group_cmd.cpp

Go to the documentation of this file.
00001 /* $Id: group_cmd.cpp 15434 2009-02-09 21:20:05Z rubidium $ */
00002 
00005 #include "stdafx.h"
00006 #include "command_func.h"
00007 #include "group.h"
00008 #include "train.h"
00009 #include "engine_base.h"
00010 #include "vehicle_gui.h"
00011 #include "window_func.h"
00012 #include "vehicle_func.h"
00013 #include "autoreplace_base.h"
00014 #include "autoreplace_func.h"
00015 #include "string_func.h"
00016 #include "company_func.h"
00017 #include "oldpool_func.h"
00018 #include "core/alloc_func.hpp"
00019 
00020 #include "table/strings.h"
00021 
00022 GroupID _new_group_id;
00023 
00031 static inline void UpdateNumEngineGroup(EngineID i, GroupID old_g, GroupID new_g)
00032 {
00033   if (old_g != new_g) {
00034     /* Decrease the num engines of EngineID i of the old group if it's not the default one */
00035     if (!IsDefaultGroupID(old_g) && IsValidGroupID(old_g)) GetGroup(old_g)->num_engines[i]--;
00036 
00037     /* Increase the num engines of EngineID i of the new group if it's not the default one */
00038     if (!IsDefaultGroupID(new_g) && IsValidGroupID(new_g)) GetGroup(new_g)->num_engines[i]++;
00039   }
00040 }
00041 
00042 
00043 DEFINE_OLD_POOL_GENERIC(Group, Group)
00044 
00045 
00046 Group::Group(Owner owner)
00047 {
00048   this->owner = owner;
00049 
00050   if (this->IsValid()) this->num_engines = CallocT<uint16>(GetEnginePoolSize());
00051 }
00052 
00053 Group::~Group()
00054 {
00055   free(this->name);
00056   this->owner = INVALID_OWNER;
00057   free(this->num_engines);
00058 }
00059 
00060 bool Group::IsValid() const
00061 {
00062   return this->owner != INVALID_OWNER;
00063 }
00064 
00065 void InitializeGroup(void)
00066 {
00067   _Group_pool.CleanPool();
00068   _Group_pool.AddBlockToPool();
00069 }
00070 
00071 
00078 CommandCost CmdCreateGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00079 {
00080   VehicleType vt = (VehicleType)p1;
00081   if (!IsCompanyBuildableVehicleType(vt)) return CMD_ERROR;
00082 
00083   if (!Group::CanAllocateItem()) return CMD_ERROR;
00084 
00085   if (flags & DC_EXEC) {
00086     Group *g = new Group(_current_company);
00087     g->replace_protection = false;
00088     g->vehicle_type = vt;
00089 
00090     _new_group_id = g->index;
00091 
00092     InvalidateWindowData(GetWindowClassForVehicleType(vt), (vt << 11) | VLW_GROUP_LIST | _current_company);
00093   }
00094 
00095   return CommandCost();
00096 }
00097 
00098 
00106 CommandCost CmdDeleteGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00107 {
00108   if (!IsValidGroupID(p1)) return CMD_ERROR;
00109 
00110   Group *g = GetGroup(p1);
00111   if (g->owner != _current_company) return CMD_ERROR;
00112 
00113   if (flags & DC_EXEC) {
00114     Vehicle *v;
00115 
00116     /* Add all vehicles belong to the group to the default group */
00117     FOR_ALL_VEHICLES(v) {
00118       if (v->group_id == g->index && v->type == g->vehicle_type) v->group_id = DEFAULT_GROUP;
00119     }
00120 
00121     /* Update backupped orders if needed */
00122     if (_backup_orders_data.group == g->index) _backup_orders_data.group = DEFAULT_GROUP;
00123 
00124     /* If we set an autoreplace for the group we delete, remove it. */
00125     if (_current_company < MAX_COMPANIES) {
00126       Company *c;
00127       EngineRenew *er;
00128 
00129       c = GetCompany(_current_company);
00130       FOR_ALL_ENGINE_RENEWS(er) {
00131         if (er->group_id == g->index) RemoveEngineReplacementForCompany(c, er->from, g->index, flags);
00132       }
00133     }
00134 
00135     VehicleType vt = g->vehicle_type;
00136 
00137     /* Delete the Replace Vehicle Windows */
00138     DeleteWindowById(WC_REPLACE_VEHICLE, g->vehicle_type);
00139     delete g;
00140 
00141     InvalidateWindowData(GetWindowClassForVehicleType(vt), (vt << 11) | VLW_GROUP_LIST | _current_company);
00142   }
00143 
00144   return CommandCost();
00145 }
00146 
00147 static bool IsUniqueGroupName(const char *name)
00148 {
00149   const Group *g;
00150 
00151   FOR_ALL_GROUPS(g) {
00152     if (g->name != NULL && strcmp(g->name, name) == 0) return false;
00153   }
00154 
00155   return true;
00156 }
00157 
00165 CommandCost CmdRenameGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00166 {
00167   if (!IsValidGroupID(p1)) return CMD_ERROR;
00168 
00169   Group *g = GetGroup(p1);
00170   if (g->owner != _current_company) return CMD_ERROR;
00171 
00172   bool reset = StrEmpty(text);
00173 
00174   if (!reset) {
00175     if (strlen(text) >= MAX_LENGTH_GROUP_NAME_BYTES) return CMD_ERROR;
00176     if (!IsUniqueGroupName(text)) return_cmd_error(STR_NAME_MUST_BE_UNIQUE);
00177   }
00178 
00179   if (flags & DC_EXEC) {
00180     /* Delete the old name */
00181     free(g->name);
00182     /* Assign the new one */
00183     g->name = reset ? NULL : strdup(text);
00184 
00185     InvalidateWindowData(GetWindowClassForVehicleType(g->vehicle_type), (g->vehicle_type << 11) | VLW_GROUP_LIST | _current_company);
00186   }
00187 
00188   return CommandCost();
00189 }
00190 
00191 
00200 CommandCost CmdAddVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00201 {
00202   GroupID new_g = p1;
00203 
00204   if (!IsValidVehicleID(p2) || (!IsValidGroupID(new_g) && !IsDefaultGroupID(new_g))) return CMD_ERROR;
00205 
00206   Vehicle *v = GetVehicle(p2);
00207 
00208   if (IsValidGroupID(new_g)) {
00209     Group *g = GetGroup(new_g);
00210     if (g->owner != _current_company || g->vehicle_type != v->type) return CMD_ERROR;
00211   }
00212 
00213   if (v->owner != _current_company || !v->IsPrimaryVehicle()) return CMD_ERROR;
00214 
00215   if (flags & DC_EXEC) {
00216     DecreaseGroupNumVehicle(v->group_id);
00217     IncreaseGroupNumVehicle(new_g);
00218 
00219     switch (v->type) {
00220       default: NOT_REACHED();
00221       case VEH_TRAIN:
00222         SetTrainGroupID(v, new_g);
00223         break;
00224       case VEH_ROAD:
00225       case VEH_SHIP:
00226       case VEH_AIRCRAFT:
00227         if (IsEngineCountable(v)) UpdateNumEngineGroup(v->engine_type, v->group_id, new_g);
00228         v->group_id = new_g;
00229         break;
00230     }
00231 
00232     /* Update the Replace Vehicle Windows */
00233     InvalidateWindow(WC_REPLACE_VEHICLE, v->type);
00234     InvalidateWindowData(GetWindowClassForVehicleType(v->type), (v->type << 11) | VLW_GROUP_LIST | _current_company);
00235   }
00236 
00237   return CommandCost();
00238 }
00239 
00247 CommandCost CmdAddSharedVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00248 {
00249   VehicleType type = (VehicleType)p2;
00250   if (!IsValidGroupID(p1) || !IsCompanyBuildableVehicleType(type)) return CMD_ERROR;
00251 
00252   if (flags & DC_EXEC) {
00253     Vehicle *v;
00254     VehicleType type = (VehicleType)p2;
00255     GroupID id_g = p1;
00256 
00257     /* Find the first front engine which belong to the group id_g
00258      * then add all shared vehicles of this front engine to the group id_g */
00259     FOR_ALL_VEHICLES(v) {
00260       if (v->type == type && v->IsPrimaryVehicle()) {
00261         if (v->group_id != id_g) continue;
00262 
00263         /* For each shared vehicles add it to the group */
00264         for (Vehicle *v2 = v->FirstShared(); v2 != NULL; v2 = v2->NextShared()) {
00265           if (v2->group_id != id_g) CmdAddVehicleGroup(tile, flags, id_g, v2->index, text);
00266         }
00267       }
00268     }
00269 
00270     InvalidateWindowData(GetWindowClassForVehicleType(type), (type << 11) | VLW_GROUP_LIST | _current_company);
00271   }
00272 
00273   return CommandCost();
00274 }
00275 
00276 
00284 CommandCost CmdRemoveAllVehiclesGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00285 {
00286   VehicleType type = (VehicleType)p2;
00287   if (!IsValidGroupID(p1) || !IsCompanyBuildableVehicleType(type)) return CMD_ERROR;
00288 
00289   Group *g = GetGroup(p1);
00290   if (g->owner != _current_company) return CMD_ERROR;
00291 
00292   if (flags & DC_EXEC) {
00293     GroupID old_g = p1;
00294     Vehicle *v;
00295 
00296     /* Find each Vehicle that belongs to the group old_g and add it to the default group */
00297     FOR_ALL_VEHICLES(v) {
00298       if (v->type == type && v->IsPrimaryVehicle()) {
00299         if (v->group_id != old_g) continue;
00300 
00301         /* Add The Vehicle to the default group */
00302         CmdAddVehicleGroup(tile, flags, DEFAULT_GROUP, v->index, text);
00303       }
00304     }
00305 
00306     InvalidateWindowData(GetWindowClassForVehicleType(type), (type << 11) | VLW_GROUP_LIST | _current_company);
00307   }
00308 
00309   return CommandCost();
00310 }
00311 
00312 
00321 CommandCost CmdSetGroupReplaceProtection(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00322 {
00323   if (!IsValidGroupID(p1)) return CMD_ERROR;
00324 
00325   Group *g = GetGroup(p1);
00326   if (g->owner != _current_company) return CMD_ERROR;
00327 
00328   if (flags & DC_EXEC) {
00329     g->replace_protection = HasBit(p2, 0);
00330 
00331     InvalidateWindowData(GetWindowClassForVehicleType(g->vehicle_type), (g->vehicle_type << 11) | VLW_GROUP_LIST | _current_company);
00332     InvalidateWindowData(WC_REPLACE_VEHICLE, g->vehicle_type);
00333   }
00334 
00335   return CommandCost();
00336 }
00337 
00343 void RemoveVehicleFromGroup(const Vehicle *v)
00344 {
00345   if (!v->IsValid() || !v->IsPrimaryVehicle()) return;
00346 
00347   if (!IsDefaultGroupID(v->group_id)) DecreaseGroupNumVehicle(v->group_id);
00348 }
00349 
00350 
00357 void SetTrainGroupID(Vehicle *v, GroupID new_g)
00358 {
00359   if (!IsValidGroupID(new_g) && !IsDefaultGroupID(new_g)) return;
00360 
00361   assert(v->IsValid() && v->type == VEH_TRAIN && IsFrontEngine(v));
00362 
00363   for (Vehicle *u = v; u != NULL; u = u->Next()) {
00364     if (IsEngineCountable(u)) UpdateNumEngineGroup(u->engine_type, u->group_id, new_g);
00365 
00366     u->group_id = new_g;
00367   }
00368 
00369   /* Update the Replace Vehicle Windows */
00370   InvalidateWindow(WC_REPLACE_VEHICLE, VEH_TRAIN);
00371 }
00372 
00373 
00381 void UpdateTrainGroupID(Vehicle *v)
00382 {
00383   assert(v->IsValid() && v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v)));
00384 
00385   GroupID new_g = IsFrontEngine(v) ? v->group_id : (GroupID)DEFAULT_GROUP;
00386   for (Vehicle *u = v; u != NULL; u = u->Next()) {
00387     if (IsEngineCountable(u)) UpdateNumEngineGroup(u->engine_type, u->group_id, new_g);
00388 
00389     u->group_id = new_g;
00390   }
00391 
00392   /* Update the Replace Vehicle Windows */
00393   InvalidateWindow(WC_REPLACE_VEHICLE, VEH_TRAIN);
00394 }
00395 
00396 uint GetGroupNumEngines(CompanyID company, GroupID id_g, EngineID id_e)
00397 {
00398   if (IsValidGroupID(id_g)) return GetGroup(id_g)->num_engines[id_e];
00399 
00400   uint num = GetCompany(company)->num_engines[id_e];
00401   if (!IsDefaultGroupID(id_g)) return num;
00402 
00403   const Group *g;
00404   FOR_ALL_GROUPS(g) {
00405     if (g->owner == company) num -= g->num_engines[id_e];
00406   }
00407   return num;
00408 }
00409 
00410 void RemoveAllGroupsForCompany(const CompanyID company)
00411 {
00412   Group *g;
00413 
00414   FOR_ALL_GROUPS(g) {
00415     if (company == g->owner) delete g;
00416   }
00417 }

Generated on Sun Nov 15 15:40:11 2009 for OpenTTD by  doxygen 1.5.6