cargotype.cpp

Go to the documentation of this file.
00001 /* $Id: cargotype.cpp 23526 2011-12-15 21:56:00Z rubidium $ */
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 "core/bitmath_func.hpp"
00015 #include "newgrf_cargo.h"
00016 #include "string_func.h"
00017 #include "strings_func.h"
00018 #include "core/sort_func.hpp"
00019 
00020 #include "table/sprites.h"
00021 #include "table/strings.h"
00022 #include "table/cargo_const.h"
00023 
00024 CargoSpec CargoSpec::array[NUM_CARGO];
00025 
00030 uint32 _cargo_mask;
00031 
00036 void SetupCargoForClimate(LandscapeID l)
00037 {
00038   assert(l < lengthof(_default_climate_cargo));
00039 
00040   /* Reset and disable all cargo types */
00041   memset(CargoSpec::array, 0, sizeof(CargoSpec::array));
00042   for (CargoID i = 0; i < lengthof(CargoSpec::array); i++) CargoSpec::Get(i)->bitnum = INVALID_CARGO;
00043 
00044   _cargo_mask = 0;
00045 
00046   for (CargoID i = 0; i < lengthof(_default_climate_cargo[l]); i++) {
00047     CargoLabel cl = _default_climate_cargo[l][i];
00048 
00049     /* Bzzt: check if cl is just an index into the cargo table */
00050     if (cl < lengthof(_default_cargo)) {
00051       /* Copy the indexed cargo */
00052       CargoSpec *cargo = CargoSpec::Get(i);
00053       *cargo = _default_cargo[cl];
00054       if (cargo->bitnum != INVALID_CARGO) SetBit(_cargo_mask, i);
00055       continue;
00056     }
00057 
00058     /* Loop through each of the default cargo types to see if
00059      * the label matches */
00060     for (uint j = 0; j < lengthof(_default_cargo); j++) {
00061       if (_default_cargo[j].label == cl) {
00062         *CargoSpec::Get(i) = _default_cargo[j];
00063 
00064         /* Populate the available cargo mask */
00065         SetBit(_cargo_mask, i);
00066         break;
00067       }
00068     }
00069   }
00070 }
00071 
00077 CargoID GetCargoIDByLabel(CargoLabel cl)
00078 {
00079   const CargoSpec *cs;
00080   FOR_ALL_CARGOSPECS(cs) {
00081     if (cs->label == cl) return cs->Index();
00082   }
00083 
00084   /* No matching label was found, so it is invalid */
00085   return CT_INVALID;
00086 }
00087 
00088 
00094 CargoID GetCargoIDByBitnum(uint8 bitnum)
00095 {
00096   if (bitnum == INVALID_CARGO) return CT_INVALID;
00097 
00098   const CargoSpec *cs;
00099   FOR_ALL_CARGOSPECS(cs) {
00100     if (cs->bitnum == bitnum) return cs->Index();
00101   }
00102 
00103   /* No matching label was found, so it is invalid */
00104   return CT_INVALID;
00105 }
00106 
00111 SpriteID CargoSpec::GetCargoIcon() const
00112 {
00113   SpriteID sprite = this->sprite;
00114   if (sprite == 0xFFFF) {
00115     /* A value of 0xFFFF indicates we should draw a custom icon */
00116     sprite = GetCustomCargoSprite(this);
00117   }
00118 
00119   if (sprite == 0) sprite = SPR_CARGO_GOODS;
00120 
00121   return sprite;
00122 }
00123 
00124 const CargoSpec *_sorted_cargo_specs[NUM_CARGO]; 
00125 uint8 _sorted_cargo_specs_size;                  
00126 uint8 _sorted_standard_cargo_specs_size;         
00127 
00128 
00130 static int CDECL CargoSpecNameSorter(const CargoSpec * const *a, const CargoSpec * const *b)
00131 {
00132   static char a_name[64];
00133   static char b_name[64];
00134 
00135   GetString(a_name, (*a)->name, lastof(a_name));
00136   GetString(b_name, (*b)->name, lastof(b_name));
00137 
00138   int res = strnatcmp(a_name, b_name); // Sort by name (natural sorting).
00139 
00140   /* If the names are equal, sort by cargo bitnum. */
00141   return (res != 0) ? res : ((*a)->bitnum - (*b)->bitnum);
00142 }
00143 
00145 static int CDECL CargoSpecClassSorter(const CargoSpec * const *a, const CargoSpec * const *b)
00146 {
00147   int res = ((*b)->classes & CC_PASSENGERS) - ((*a)->classes & CC_PASSENGERS);
00148   if (res == 0) {
00149     res = ((*b)->classes & CC_MAIL) - ((*a)->classes & CC_MAIL);
00150     if (res == 0) {
00151       res = ((*a)->classes & CC_SPECIAL) - ((*b)->classes & CC_SPECIAL);
00152       if (res == 0) {
00153         return CargoSpecNameSorter(a, b);
00154       }
00155     }
00156   }
00157 
00158   return res;
00159 }
00160 
00162 void InitializeSortedCargoSpecs()
00163 {
00164   _sorted_cargo_specs_size = 0;
00165   const CargoSpec *cargo;
00166   /* Add each cargo spec to the list. */
00167   FOR_ALL_CARGOSPECS(cargo) {
00168     _sorted_cargo_specs[_sorted_cargo_specs_size] = cargo;
00169     _sorted_cargo_specs_size++;
00170   }
00171 
00172   /* Sort cargo specifications by cargo class and name. */
00173   QSortT(_sorted_cargo_specs, _sorted_cargo_specs_size, &CargoSpecClassSorter);
00174 
00175   _sorted_standard_cargo_specs_size = 0;
00176   FOR_ALL_SORTED_CARGOSPECS(cargo) {
00177     if (cargo->classes & CC_SPECIAL) break;
00178     _sorted_standard_cargo_specs_size++;
00179   }
00180 }
00181