From 29d8c5bb5056dc8efa6c953595056697fc876760 Mon Sep 17 00:00:00 2001 From: bjarni Date: Sun, 2 Jan 2005 17:23:04 +0000 Subject: (svn r1323) Adding autoreplace feature This feature works much like autorenew, but it will get you a new engine type instead of a new one of the same type. Once ordered, it will automatically replace the engines while they visits a depot. The GUI for setting this up have been added on the vehicle overview windows Note: autorenew is now autoreplace, but to the same engine type Nice new features, that was added to make this possible - windows can now have two independant vertical scrollbars - CMD_SHOW_NO_ERROR have been added as a flag for DoCommandP. It will make it do the action instead of showing the red box with estimated costs even if shift is pressed - fixed problem where enginetypes where not initialized when loading a game. It's now done in InitializeGame() --- vehicle.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 153 insertions(+), 27 deletions(-) (limited to 'vehicle.c') diff --git a/vehicle.c b/vehicle.c index e029c985a..0680581e8 100644 --- a/vehicle.c +++ b/vehicle.c @@ -4,7 +4,6 @@ #include "map.h" #include "vehicle.h" #include "gfx.h" -//#include "station.h" #include "viewport.h" #include "news.h" #include "command.h" @@ -1394,35 +1393,45 @@ extern int32 EstimateTrainCost(const RailVehicleInfo *rvi); extern int32 EstimateRoadVehCost(byte engine_type); extern int32 EstimateShipCost(uint16 engine_type); extern int32 EstimateAircraftCost(uint16 engine_type); +extern int32 CmdRefitRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2); +extern int32 CmdRefitShip(int x, int y, uint32 flags, uint32 p1, uint32 p2); +extern int32 CmdRefitAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2); -/* Renews a vehicle +/* Replaces a vehicle (used to be called autorenew) p1 - Index of vehicle p2 - Type of new engine */ -int32 CmdRenewVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) -{ - byte new_engine_type = p2; +int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + /* makesvariables to inform about how much money the player wants to have left after replacing + and which engine to replace with out of p2. + the first 16 bit is the money. The last 5 digits (all 0) were removed when sent, so we add them again. + This way the max is 6553 millions and it is more than the 32 bit that is stored in _patches + This is a nice way to send 32 bit and only use 16 bit + the last 8 bit is the engine. The 8 bits in front of the engine is free so it have room for 16 bit engine entries */ + uint16 new_engine_type = (uint16)(p2 & 0xFFFF); + uint32 autorefit_money = (p2 >> 16) * 100000; Vehicle *v = DEREF_VEHICLE(p1); int cost, build_cost; - - SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); + + if (v->type != _engines[new_engine_type].type) return CMD_ERROR; switch (v->type) { - case VEH_Train: build_cost = EstimateTrainCost(RailVehInfo(v->engine_type)); break; - case VEH_Road: build_cost = EstimateRoadVehCost(new_engine_type); break; - case VEH_Ship: build_cost = EstimateShipCost(v->engine_type); break; - case VEH_Aircraft: build_cost = EstimateAircraftCost(new_engine_type); break; + case VEH_Train: build_cost = EstimateTrainCost(RailVehInfo(new_engine_type)); break; + case VEH_Road: build_cost = EstimateRoadVehCost(new_engine_type); break; + case VEH_Ship: build_cost = EstimateShipCost(new_engine_type); break; + case VEH_Aircraft: build_cost = EstimateAircraftCost(new_engine_type); break; default: return CMD_ERROR; } /* In a rare situation, when 2 clients are connected to 1 company and have the same settings, a vehicle can be replaced twice.. check if this is the situation here */ - if (v->age == 0) + if (v->engine_type == new_engine_type && v->age == 0) return CMD_ERROR; /* Check if there is money for the upgrade.. if not, give a nice news-item (that is needed, because this CMD is called automaticly) */ - if (DEREF_PLAYER(v->owner)->money64 < _patches.autorenew_money + build_cost - v->value) { - if (_local_player == v->owner) { + if ( DEREF_PLAYER(v->owner)->money64 < (int32)(autorefit_money + build_cost - v->value)) { + if (( _local_player == v->owner ) && ( v->unitnumber != 0 )) { //v->unitnumber = 0 for train cars int message; SetDParam(0, v->unitnumber); switch (v->type) { @@ -1439,21 +1448,106 @@ int32 CmdRenewVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) return CMD_ERROR; } - cost = build_cost - v->value; - if (flags & DC_QUERY_COST) - return cost; if (flags & DC_EXEC) { Engine *e; + e = &_engines[new_engine_type]; + + // TODO make it check if refit is possible before actually doing it /* We do not really buy a new vehicle, we upgrade the old one */ if (v->engine_type != new_engine_type) { - /* XXX - We need to do some more stuff here, when we are going to upgrade - to a new engine! */ + byte cargo_type = v->cargo_type; + v->engine_type = new_engine_type; + v->max_age = e->lifelength * 366; + + /* Update limits of the vehicle (for when upgraded) */ + switch (v->type) { + case VEH_Train: + // using if (true) to declare the const + { + const RailVehicleInfo *rvi = RailVehInfo(new_engine_type); + byte capacity = rvi->capacity; + + v->spritenum = rvi->image_index; + v->cargo_type = rvi->cargo_type; + v->cargo_cap = rvi->capacity; + v->max_speed = rvi->max_speed; + + v->u.rail.railtype = e->railtype; + + // 0x0100 means that we skip the check for being stopped inside the depot + // since we do not stop it for autorefitting + if (v->cargo_type != cargo_type && capacity) { + // BUG: somehow v->index is not transfered properly + //CmdRefitRailVehicle(v->x_pos, v->y_pos, DC_EXEC, v->index , cargo_type + 0x0100 ); + v->cargo_type = cargo_type; // workaround, but it do not check the refit table + } else { + v->cargo_type = rvi->cargo_type; + } + break; + } + case VEH_Road: + // using if (true) to declare the const + if (true) { + const RoadVehicleInfo *rvi = RoadVehInfo(new_engine_type); + + v->spritenum = rvi->image_index; + v->cargo_type = rvi->cargo_type; + v->cargo_cap = rvi->capacity; + v->max_speed = rvi->max_speed; + break; + } + case VEH_Ship: + // using if (true) to declare the const + if (true) { + const ShipVehicleInfo *svi = ShipVehInfo(new_engine_type); + + v->spritenum = svi->image_index; + v->cargo_type = svi->cargo_type; + v->cargo_cap = svi->capacity; + v->max_speed = svi->max_speed; + + // 0x0100 means that we skip the check for being stopped inside the depot + // since we do not stop it for autorefitting + if (v->cargo_type != cargo_type) + CmdRefitShip(v->x_pos, v->y_pos, DC_EXEC, v->index , cargo_type + 0x0100 ); + break; + } + case VEH_Aircraft: + // using if (true) to declare the const + if (true) { + const AircraftVehicleInfo *avi = AircraftVehInfo(new_engine_type); + Vehicle *u; + + v->max_speed = avi->max_speed; + v->acceleration = avi->acceleration; + v->spritenum = avi->image_index; + + if ( cargo_type == CT_PASSENGERS ) { + v->cargo_cap = avi->passanger_capacity; + u = v->next; + u->cargo_cap = avi->mail_capacity; + } else { + // 0x0100 means that we skip the check for being stopped inside the hangar + // since we do not stop it for autorefitting + CmdRefitAircraft(v->x_pos, v->y_pos, DC_EXEC, v->index , cargo_type + 0x0100 ); + } + break; + } + default: return CMD_ERROR; + } + // makes sure that the cargo is still valid compared to new capacity + if (v->cargo_count != 0) { + if ( v->cargo_type != cargo_type ) + v->cargo_count = 0; + else if ( v->cargo_count > v->cargo_cap ) + v->cargo_count = v->cargo_cap; + } } - e = &_engines[new_engine_type]; + v->reliability = e->reliability; v->reliability_spd_dec = e->reliability_spd_dec; v->age = 0; @@ -1465,26 +1559,58 @@ int32 CmdRenewVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) InvalidateWindow(WC_VEHICLE_DETAILS, v->index); } + //needs to be down here because refitting will change SET_EXPENSES_TYPE if called + SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); return cost; } -void MaybeRenewVehicle(Vehicle *v) +void MaybeReplaceVehicle(Vehicle *v) { + uint32 new_engine_and_autoreplace_money; + if (v->owner != _local_player) return; + // uncomment next line if you want to see what engine type just entered a depot + //printf("engine type: %d\n", v->engine_type); // A vehicle is autorenewed when it it gets the amount of months // give by _patches.autorenew_months away for his max age. // Standard is -6, meaning 6 months before his max age // It can be any value between -12 and 12. - if (!_patches.autorenew || v->age - v->max_age < (_patches.autorenew_months * 30)) - return; - + // Here it also checks if the vehicles is listed for replacement + if (!_patches.autorenew || v->age - v->max_age < (_patches.autorenew_months * 30)) { //replace if engine is too old + if (_autoreplace_array[v->engine_type] == v->engine_type && v->type != VEH_Train) //updates to a new model + return; + } + /* Now replace the vehicle */ _current_player = v->owner; - - /* Now renew the vehicle */ - DoCommandP(v->tile, v->index, v->engine_type, NULL, CMD_RENEW_VEHICLE); + + /* makes the variable to inform about how much money the player wants to have left after replacing + and which engine to replace with + the first 16 bit is the money. Since we know the last 5 digits is 0, they are thrown away. + This way the max is 6553 millions and it is more than the 32 bit that is stored in _patches + This is a nice way to send 32 bit and only use 16 bit + the last 8 bit is the engine. The 8 bits in front of the engine is free so it have room for 16 bit engine entries */ + new_engine_and_autoreplace_money = (((_patches.autorenew_money / 100000) & 0xFFFF) << 16) + + _autoreplace_array[v->engine_type]; + + assert(v->type == _engines[ _autoreplace_array[v->engine_type] ].type); + + if ( v->type != VEH_Train ) { + DoCommandP(v->tile, v->index, new_engine_and_autoreplace_money, NULL, CMD_REPLACE_VEHICLE | CMD_SHOW_NO_ERROR); + } else { + // checks if the front engine is outdated + if (v->engine_type != _autoreplace_array[v->engine_type] ) + DoCommandP(v->tile, v->index, new_engine_and_autoreplace_money, NULL, CMD_REPLACE_VEHICLE | CMD_SHOW_NO_ERROR); + //we will check all the cars and engines if they should be replaced + while (v->next != NULL){ + v = v->next; + if (v->engine_type != _autoreplace_array[v->engine_type] || v->age - v->max_age < (_patches.autorenew_months * 30)) + DoCommandP(v->tile, v->index, new_engine_and_autoreplace_money , NULL, CMD_REPLACE_VEHICLE | CMD_SHOW_NO_ERROR); + } + } + _current_player = OWNER_NONE; } -- cgit v1.2.3-70-g09d2