group_cmd.cpp

Go to the documentation of this file.
00001 /* $Id: group_cmd.cpp 18494 2009-12-13 22:17:12Z 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 "command_func.h"
00014 #include "group.h"
00015 #include "train.h"
00016 #include "engine_base.h"
00017 #include "vehicle_gui.h"
00018 #include "window_func.h"
00019 #include "vehicle_func.h"
00020 #include "autoreplace_base.h"
00021 #include "autoreplace_func.h"
00022 #include "string_func.h"
00023 #include "company_func.h"
00024 #include "core/pool_func.hpp"
00025 
00026 #include "table/strings.h"
00027 
00028 GroupID _new_group_id;
00029 
00030 GroupPool _group_pool("Group");
00031 INSTANTIATE_POOL_METHODS(Group)
00032 
00033 
00040 static inline void UpdateNumEngineGroup(EngineID i, GroupID old_g, GroupID new_g)
00041 {
00042   if (old_g != new_g) {
00043     /* Decrease the num engines of EngineID i of the old group if it's not the default one */
00044     if (!IsDefaultGroupID(old_g) && Group::IsValidID(old_g)) Group::Get(old_g)->num_engines[i]--;
00045 
00046     /* Increase the num engines of EngineID i of the new group if it's not the default one */
00047     if (!IsDefaultGroupID(new_g) && Group::IsValidID(new_g)) Group::Get(new_g)->num_engines[i]++;
00048   }
00049 }
00050 
00051 
00052 
00053 Group::Group(Owner owner)
00054 {
00055   this->owner = owner;
00056 
00057   if (!Company::IsValidID(owner)) return;
00058 
00059   this->num_engines = CallocT<uint16>(Engine::GetPoolSize());
00060 }
00061 
00062 Group::~Group()
00063 {
00064   free(this->name);
00065   free(this->num_engines);
00066 }
00067 
00068 void InitializeGroup()
00069 {
00070   _group_pool.CleanPool();
00071 }
00072 
00073 
00083 CommandCost CmdCreateGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00084 {
00085   VehicleType vt = (VehicleType)p1;
00086   if (!IsCompanyBuildableVehicleType(vt)) return CMD_ERROR;
00087 
00088   if (!Group::CanAllocateItem()) return CMD_ERROR;
00089 
00090   if (flags & DC_EXEC) {
00091     Group *g = new Group(_current_company);
00092     g->replace_protection = false;
00093     g->vehicle_type = vt;
00094 
00095     _new_group_id = g->index;
00096 
00097     InvalidateWindowData(GetWindowClassForVehicleType(vt), (vt << 11) | VLW_GROUP_LIST | _current_company);
00098   }
00099 
00100   return CommandCost();
00101 }
00102 
00103 
00114 CommandCost CmdDeleteGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00115 {
00116   Group *g = Group::GetIfValid(p1);
00117   if (g == NULL || g->owner != _current_company) return CMD_ERROR;
00118 
00119   if (flags & DC_EXEC) {
00120     Vehicle *v;
00121 
00122     /* Add all vehicles belong to the group to the default group */
00123     FOR_ALL_VEHICLES(v) {
00124       if (v->group_id == g->index && v->type == g->vehicle_type) v->group_id = DEFAULT_GROUP;
00125     }
00126 
00127     /* Update backupped orders if needed */
00128     if (_backup_orders_data.group == g->index) _backup_orders_data.group = DEFAULT_GROUP;
00129 
00130     /* If we set an autoreplace for the group we delete, remove it. */
00131     if (_current_company < MAX_COMPANIES) {
00132       Company *c;
00133       EngineRenew *er;
00134 
00135       c = Company::Get(_current_company);
00136       FOR_ALL_ENGINE_RENEWS(er) {
00137         if (er->group_id == g->index) RemoveEngineReplacementForCompany(c, er->from, g->index, flags);
00138       }
00139     }
00140 
00141     VehicleType vt = g->vehicle_type;
00142 
00143     /* Delete the Replace Vehicle Windows */
00144     DeleteWindowById(WC_REPLACE_VEHICLE, g->vehicle_type);
00145     delete g;
00146 
00147     InvalidateWindowData(GetWindowClassForVehicleType(vt), (vt << 11) | VLW_GROUP_LIST | _current_company);
00148   }
00149 
00150   return CommandCost();
00151 }
00152 
00153 static bool IsUniqueGroupName(const char *name)
00154 {
00155   const Group *g;
00156 
00157   FOR_ALL_GROUPS(g) {
00158     if (g->name != NULL && strcmp(g->name, name) == 0) return false;
00159   }
00160 
00161   return true;
00162 }
00163 
00174 CommandCost CmdRenameGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00175 {
00176   Group *g = Group::GetIfValid(p1);
00177   if (g == NULL || g->owner != _current_company) return CMD_ERROR;
00178 
00179   bool reset = StrEmpty(text);
00180 
00181   if (!reset) {
00182     if (strlen(text) >= MAX_LENGTH_GROUP_NAME_BYTES) return CMD_ERROR;
00183     if (!IsUniqueGroupName(text)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
00184   }
00185 
00186   if (flags & DC_EXEC) {
00187     /* Delete the old name */
00188     free(g->name);
00189     /* Assign the new one */
00190     g->name = reset ? NULL : strdup(text);
00191 
00192     InvalidateWindowData(GetWindowClassForVehicleType(g->vehicle_type), (g->vehicle_type << 11) | VLW_GROUP_LIST | _current_company);
00193   }
00194 
00195   return CommandCost();
00196 }
00197 
00198 
00210 CommandCost CmdAddVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00211 {
00212   Vehicle *v = Vehicle::GetIfValid(p2);
00213   GroupID new_g = p1;
00214 
00215   if (v == NULL || (!Group::IsValidID(new_g) && !IsDefaultGroupID(new_g))) return CMD_ERROR;
00216 
00217   if (Group::IsValidID(new_g)) {
00218     Group *g = Group::Get(new_g);
00219     if (g->owner != _current_company || g->vehicle_type != v->type) return CMD_ERROR;
00220   }
00221 
00222   if (v->owner != _current_company || !v->IsPrimaryVehicle()) return CMD_ERROR;
00223 
00224   if (flags & DC_EXEC) {
00225     DecreaseGroupNumVehicle(v->group_id);
00226     IncreaseGroupNumVehicle(new_g);
00227 
00228     switch (v->type) {
00229       default: NOT_REACHED();
00230       case VEH_TRAIN:
00231         SetTrainGroupID(Train::From(v), new_g);
00232         break;
00233       case VEH_ROAD:
00234       case VEH_SHIP:
00235       case VEH_AIRCRAFT:
00236         if (v->IsEngineCountable()) UpdateNumEngineGroup(v->engine_type, v->group_id, new_g);
00237         v->group_id = new_g;
00238         break;
00239     }
00240 
00241     /* Update the Replace Vehicle Windows */
00242     SetWindowDirty(WC_REPLACE_VEHICLE, v->type);
00243     InvalidateWindowData(GetWindowClassForVehicleType(v->type), (v->type << 11) | VLW_GROUP_LIST | _current_company);
00244   }
00245 
00246   return CommandCost();
00247 }
00248 
00259 CommandCost CmdAddSharedVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00260 {
00261   VehicleType type = (VehicleType)p2;
00262   if (!Group::IsValidID(p1) || !IsCompanyBuildableVehicleType(type)) return CMD_ERROR;
00263 
00264   if (flags & DC_EXEC) {
00265     Vehicle *v;
00266     VehicleType type = (VehicleType)p2;
00267     GroupID id_g = p1;
00268 
00269     /* Find the first front engine which belong to the group id_g
00270      * then add all shared vehicles of this front engine to the group id_g */
00271     FOR_ALL_VEHICLES(v) {
00272       if (v->type == type && v->IsPrimaryVehicle()) {
00273         if (v->group_id != id_g) continue;
00274 
00275         /* For each shared vehicles add it to the group */
00276         for (Vehicle *v2 = v->FirstShared(); v2 != NULL; v2 = v2->NextShared()) {
00277           if (v2->group_id != id_g) CmdAddVehicleGroup(tile, flags, id_g, v2->index, text);
00278         }
00279       }
00280     }
00281 
00282     InvalidateWindowData(GetWindowClassForVehicleType(type), (type << 11) | VLW_GROUP_LIST | _current_company);
00283   }
00284 
00285   return CommandCost();
00286 }
00287 
00288 
00299 CommandCost CmdRemoveAllVehiclesGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00300 {
00301   Group *g = Group::GetIfValid(p1);
00302   VehicleType type = (VehicleType)p2;
00303 
00304   if (g == NULL || g->owner != _current_company || !IsCompanyBuildableVehicleType(type)) return CMD_ERROR;
00305 
00306   if (flags & DC_EXEC) {
00307     GroupID old_g = p1;
00308     Vehicle *v;
00309 
00310     /* Find each Vehicle that belongs to the group old_g and add it to the default group */
00311     FOR_ALL_VEHICLES(v) {
00312       if (v->type == type && v->IsPrimaryVehicle()) {
00313         if (v->group_id != old_g) continue;
00314 
00315         /* Add The Vehicle to the default group */
00316         CmdAddVehicleGroup(tile, flags, DEFAULT_GROUP, v->index, text);
00317       }
00318     }
00319 
00320     InvalidateWindowData(GetWindowClassForVehicleType(type), (type << 11) | VLW_GROUP_LIST | _current_company);
00321   }
00322 
00323   return CommandCost();
00324 }
00325 
00326 
00338 CommandCost CmdSetGroupReplaceProtection(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00339 {
00340   Group *g = Group::GetIfValid(p1);
00341   if (g == NULL || g->owner != _current_company) return CMD_ERROR;
00342 
00343   if (flags & DC_EXEC) {
00344     g->replace_protection = HasBit(p2, 0);
00345 
00346     InvalidateWindowData(GetWindowClassForVehicleType(g->vehicle_type), (g->vehicle_type << 11) | VLW_GROUP_LIST | _current_company);
00347     InvalidateWindowData(WC_REPLACE_VEHICLE, g->vehicle_type);
00348   }
00349 
00350   return CommandCost();
00351 }
00352 
00358 void RemoveVehicleFromGroup(const Vehicle *v)
00359 {
00360   if (!v->IsPrimaryVehicle()) return;
00361 
00362   if (!IsDefaultGroupID(v->group_id)) DecreaseGroupNumVehicle(v->group_id);
00363 }
00364 
00365 
00372 void SetTrainGroupID(Train *v, GroupID new_g)
00373 {
00374   if (!Group::IsValidID(new_g) && !IsDefaultGroupID(new_g)) return;
00375 
00376   assert(v->IsFrontEngine() || IsDefaultGroupID(new_g));
00377 
00378   for (Vehicle *u = v; u != NULL; u = u->Next()) {
00379     if (u->IsEngineCountable()) UpdateNumEngineGroup(u->engine_type, u->group_id, new_g);
00380 
00381     u->group_id = new_g;
00382   }
00383 
00384   /* Update the Replace Vehicle Windows */
00385   SetWindowDirty(WC_REPLACE_VEHICLE, VEH_TRAIN);
00386 }
00387 
00388 
00396 void UpdateTrainGroupID(Train *v)
00397 {
00398   assert(v->IsFrontEngine() || v->IsFreeWagon());
00399 
00400   GroupID new_g = v->IsFrontEngine() ? v->group_id : (GroupID)DEFAULT_GROUP;
00401   for (Vehicle *u = v; u != NULL; u = u->Next()) {
00402     if (u->IsEngineCountable()) UpdateNumEngineGroup(u->engine_type, u->group_id, new_g);
00403 
00404     u->group_id = new_g;
00405   }
00406 
00407   /* Update the Replace Vehicle Windows */
00408   SetWindowDirty(WC_REPLACE_VEHICLE, VEH_TRAIN);
00409 }
00410 
00411 uint GetGroupNumEngines(CompanyID company, GroupID id_g, EngineID id_e)
00412 {
00413   if (Group::IsValidID(id_g)) return Group::Get(id_g)->num_engines[id_e];
00414 
00415   uint num = Company::Get(company)->num_engines[id_e];
00416   if (!IsDefaultGroupID(id_g)) return num;
00417 
00418   const Group *g;
00419   FOR_ALL_GROUPS(g) {
00420     if (g->owner == company) num -= g->num_engines[id_e];
00421   }
00422   return num;
00423 }
00424 
00425 void RemoveAllGroupsForCompany(const CompanyID company)
00426 {
00427   Group *g;
00428 
00429   FOR_ALL_GROUPS(g) {
00430     if (company == g->owner) delete g;
00431   }
00432 }

Generated on Tue Jan 5 21:02:54 2010 for OpenTTD by  doxygen 1.5.6