cargotype.cpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "stdafx.h"
00013 #include "cargotype.h"
00014 #include "newgrf_cargo.h"
00015 #include "string_func.h"
00016 #include "strings_func.h"
00017 #include "core/sort_func.hpp"
00018 
00019 #include "table/sprites.h"
00020 #include "table/strings.h"
00021 #include "table/cargo_const.h"
00022 
00023 CargoSpec CargoSpec::array[NUM_CARGO];
00024 
00029 uint32 _cargo_mask;
00030 
00034 uint32 _standard_cargo_mask;
00035 
00040 void SetupCargoForClimate(LandscapeID l)
00041 {
00042   assert(l < lengthof(_default_climate_cargo));
00043 
00044   /* Reset and disable all cargo types */
00045   memset(CargoSpec::array, 0, sizeof(CargoSpec::array));
00046   for (CargoID i = 0; i < lengthof(CargoSpec::array); i++) {
00047     CargoSpec::Get(i)->bitnum = INVALID_CARGO;
00048 
00049     /* Set defaults for newer properties, which old GRFs do not know */
00050     CargoSpec::Get(i)->multiplier = 0x100;
00051   }
00052 
00053   _cargo_mask = 0;
00054 
00055   for (CargoID i = 0; i < lengthof(_default_climate_cargo[l]); i++) {
00056     CargoLabel cl = _default_climate_cargo[l][i];
00057 
00058     /* Bzzt: check if cl is just an index into the cargo table */
00059     if (cl < lengthof(_default_cargo)) {
00060       /* Copy the indexed cargo */
00061       CargoSpec *cargo = CargoSpec::Get(i);
00062       *cargo = _default_cargo[cl];
00063       if (cargo->bitnum != INVALID_CARGO) SetBit(_cargo_mask, i);
00064       continue;
00065     }
00066 
00067     /* Loop through each of the default cargo types to see if
00068      * the label matches */
00069     for (uint j = 0; j < lengthof(_default_cargo); j++) {
00070       if (_default_cargo[j].label == cl) {
00071         *CargoSpec::Get(i) = _default_cargo[j];
00072 
00073         /* Populate the available cargo mask */
00074         SetBit(_cargo_mask, i);
00075         break;
00076       }
00077     }
00078   }
00079 }
00080 
00086 CargoID GetCargoIDByLabel(CargoLabel cl)
00087 {
00088   const CargoSpec *cs;
00089   FOR_ALL_CARGOSPECS(cs) {
00090     if (cs->label == cl) return cs->Index();
00091   }
00092 
00093   /* No matching label was found, so it is invalid */
00094   return CT_INVALID;
00095 }
00096 
00097 
00103 CargoID GetCargoIDByBitnum(uint8 bitnum)
00104 {
00105   if (bitnum == INVALID_CARGO) return CT_INVALID;
00106 
00107   const CargoSpec *cs;
00108   FOR_ALL_CARGOSPECS(cs) {
00109     if (cs->bitnum == bitnum) return cs->Index();
00110   }
00111 
00112   /* No matching label was found, so it is invalid */
00113   return CT_INVALID;
00114 }
00115 
00120 SpriteID CargoSpec::GetCargoIcon() const
00121 {
00122   SpriteID sprite = this->sprite;
00123   if (sprite == 0xFFFF) {
00124     /* A value of 0xFFFF indicates we should draw a custom icon */
00125     sprite = GetCustomCargoSprite(this);
00126   }
00127 
00128   if (sprite == 0) sprite = SPR_CARGO_GOODS;
00129 
00130   return sprite;
00131 }
00132 
00133 const CargoSpec *_sorted_cargo_specs[NUM_CARGO]; 
00134 uint8 _sorted_cargo_specs_size;                  
00135 uint8 _sorted_standard_cargo_specs_size;         
00136 
00137 
00139 static int CDECL CargoSpecNameSorter(const CargoSpec * const *a, const CargoSpec * const *b)
00140 {
00141   static char a_name[64];
00142   static char b_name[64];
00143 
00144   GetString(a_name, (*a)->name, lastof(a_name));
00145   GetString(b_name, (*b)->name, lastof(b_name));
00146 
00147   int res = strnatcmp(a_name, b_name); // Sort by name (natural sorting).
00148 
00149   /* If the names are equal, sort by cargo bitnum. */
00150   return (res != 0) ? res : ((*a)->bitnum - (*b)->bitnum);
00151 }
00152 
00154 static int CDECL CargoSpecClassSorter(const CargoSpec * const *a, const CargoSpec * const *b)
00155 {
00156   int res = ((*b)->classes & CC_PASSENGERS) - ((*a)->classes & CC_PASSENGERS);
00157   if (res == 0) {
00158     res = ((*b)->classes & CC_MAIL) - ((*a)->classes & CC_MAIL);
00159     if (res == 0) {
00160       res = ((*a)->classes & CC_SPECIAL) - ((*b)->classes & CC_SPECIAL);
00161       if (res == 0) {
00162         return CargoSpecNameSorter(a, b);
00163       }
00164     }
00165   }
00166 
00167   return res;
00168 }
00169 
00171 void InitializeSortedCargoSpecs()
00172 {
00173   _sorted_cargo_specs_size = 0;
00174   const CargoSpec *cargo;
00175   /* Add each cargo spec to the list. */
00176   FOR_ALL_CARGOSPECS(cargo) {
00177     _sorted_cargo_specs[_sorted_cargo_specs_size] = cargo;
00178     _sorted_cargo_specs_size++;
00179   }
00180 
00181   /* Sort cargo specifications by cargo class and name. */
00182   QSortT(_sorted_cargo_specs, _sorted_cargo_specs_size, &CargoSpecClassSorter);
00183 
00184   _standard_cargo_mask = 0;
00185 
00186   _sorted_standard_cargo_specs_size = 0;
00187   FOR_ALL_SORTED_CARGOSPECS(cargo) {
00188     if (cargo->classes & CC_SPECIAL) break;
00189     _sorted_standard_cargo_specs_size++;
00190     SetBit(_standard_cargo_mask, cargo->Index());
00191   }
00192 }
00193