From 00aca63b48e18e4bf3644964457c7d81c1a10573 Mon Sep 17 00:00:00 2001 From: frosch Date: Wed, 28 Oct 2009 21:09:37 +0000 Subject: (svn r17899) -Codechange: Deduplicate code for refitting vehicles. --- src/aircraft_cmd.cpp | 31 +++---------------- src/roadveh_cmd.cpp | 49 ++++------------------------- src/ship_cmd.cpp | 27 ++-------------- src/train_cmd.cpp | 49 ++++------------------------- src/vehicle.cpp | 46 --------------------------- src/vehicle_cmd.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/vehicle_func.h | 3 +- 7 files changed, 106 insertions(+), 186 deletions(-) (limited to 'src') diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index c5a422c8e..65c3f6ff1 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -500,40 +500,17 @@ CommandCost CmdRefitAircraft(TileIndex tile, DoCommandFlag flags, uint32 p1, uin /* Check cargo */ CargoID new_cid = GB(p2, 0, 8); - if (new_cid >= NUM_CARGO || !CanRefitTo(v->engine_type, new_cid)) return CMD_ERROR; + if (new_cid >= NUM_CARGO) return CMD_ERROR; - const Engine *e = Engine::Get(v->engine_type); - v->InvalidateNewGRFCacheOfChain(); - - /* Back up the existing cargo type */ - CargoID temp_cid = v->cargo_type; - byte temp_subtype = v->cargo_subtype; - v->cargo_type = new_cid; - v->cargo_subtype = new_subtype; - - uint pass = GetVehicleCapacity(v); - - /* Restore the cargo type */ - v->cargo_type = temp_cid; - v->cargo_subtype = temp_subtype; - - _returned_refit_capacity = pass; - - CommandCost cost; - if (new_cid != v->cargo_type) { - cost = GetRefitCost(v->engine_type); - } + CommandCost cost = RefitVehicle(v, true, new_cid, new_subtype, flags); if (flags & DC_EXEC) { - v->cargo_cap = pass; - + const Engine *e = Engine::Get(v->engine_type); Vehicle *u = v->Next(); uint mail = IsCargoInClass(new_cid, CC_PASSENGERS) ? e->u.air.mail_capacity : 0; u->cargo_cap = mail; - v->cargo.Truncate(v->cargo_type == new_cid ? pass : 0); u->cargo.Truncate(v->cargo_type == new_cid ? mail : 0); - v->cargo_type = new_cid; - v->cargo_subtype = new_subtype; + v->colourmap = PAL_NONE; // invalidate vehicle colour map SetWindowDirty(WC_VEHICLE_DETAILS, v->index); SetWindowDirty(WC_VEHICLE_DEPOT, v->tile); diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index bbdbb874b..f482c0ebb 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -2003,11 +2003,9 @@ Trackdir RoadVehicle::GetVehicleTrackdir() const */ CommandCost CmdRefitRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - CommandCost cost(EXPENSES_ROADVEH_RUN); CargoID new_cid = GB(p2, 0, 8); byte new_subtype = GB(p2, 8, 8); bool only_this = HasBit(p2, 16); - uint total_capacity = 0; RoadVehicle *v = RoadVehicle::GetIfValid(p1); @@ -2017,52 +2015,17 @@ CommandCost CmdRefitRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint if (new_cid >= NUM_CARGO) return CMD_ERROR; - v->InvalidateNewGRFCacheOfChain(); - for (; v != NULL; v = (only_this ? NULL : v->Next())) { - /* XXX: We refit all the attached wagons en-masse if they can be - * refitted. This is how TTDPatch does it. TODO: Have some nice - * [Refit] button near each wagon. */ - if (!CanRefitTo(v->engine_type, new_cid)) continue; - - const Engine *e = Engine::Get(v->engine_type); - if (!e->CanCarryCargo()) continue; - - /* Back up the cargo type */ - CargoID temp_cid = v->cargo_type; - byte temp_subtype = v->cargo_subtype; - v->cargo_type = new_cid; - v->cargo_subtype = new_subtype; - - uint capacity = GetVehicleCapacity(v); - - /* Restore the original cargo type */ - v->cargo_type = temp_cid; - v->cargo_subtype = temp_subtype; - - total_capacity += capacity; - - if (new_cid != v->cargo_type) { - cost.AddCost(GetRefitCost(v->engine_type)); - } - - if (flags & DC_EXEC) { - v->cargo_cap = capacity; - v->cargo.Truncate((v->cargo_type == new_cid) ? capacity : 0); - v->cargo_type = new_cid; - v->cargo_subtype = new_subtype; - SetWindowDirty(WC_VEHICLE_DETAILS, v->index); - SetWindowDirty(WC_VEHICLE_DEPOT, v->tile); - InvalidateWindowClassesData(WC_ROADVEH_LIST, 0); - } - } + CommandCost cost = RefitVehicle(v, only_this, new_cid, new_subtype, flags); if (flags & DC_EXEC) { - RoadVehUpdateCache(RoadVehicle::Get(p1)->First()); + RoadVehicle *front = v->First(); + RoadVehUpdateCache(front); + SetWindowDirty(WC_VEHICLE_DETAILS, front->index); + SetWindowDirty(WC_VEHICLE_DEPOT, front->tile); + InvalidateWindowClassesData(WC_ROADVEH_LIST, 0); } else { v->InvalidateNewGRFCacheOfChain(); // always invalidate; querycost might have filled it } - _returned_refit_capacity = total_capacity; - return cost; } diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 7c64e4ee5..c56f2dcf3 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -909,7 +909,6 @@ CommandCost CmdSendShipToDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, u */ CommandCost CmdRefitShip(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - CommandCost cost(EXPENSES_SHIP_RUN); CargoID new_cid = GB(p2, 0, 8); // gets the cargo number byte new_subtype = GB(p2, 8, 8); @@ -920,33 +919,11 @@ CommandCost CmdRefitShip(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 if (v->vehstatus & VS_CRASHED) return_cmd_error(STR_ERROR_CAN_T_REFIT_DESTROYED_VEHICLE); /* Check cargo */ - if (new_cid >= NUM_CARGO || !CanRefitTo(v->engine_type, new_cid)) return CMD_ERROR; + if (new_cid >= NUM_CARGO) return CMD_ERROR; - v->InvalidateNewGRFCacheOfChain(); - - /* Back up the existing cargo type */ - CargoID temp_cid = v->cargo_type; - byte temp_subtype = v->cargo_subtype; - v->cargo_type = new_cid; - v->cargo_subtype = new_subtype; - - uint capacity = GetVehicleCapacity(v); - - /* Restore the cargo type */ - v->cargo_type = temp_cid; - v->cargo_subtype = temp_subtype; - - _returned_refit_capacity = capacity; - - if (new_cid != v->cargo_type) { - cost = GetRefitCost(v->engine_type); - } + CommandCost cost = RefitVehicle(v, true, new_cid, new_subtype, flags); if (flags & DC_EXEC) { - v->cargo_cap = capacity; - v->cargo.Truncate((v->cargo_type == new_cid) ? capacity : 0); - v->cargo_type = new_cid; - v->cargo_subtype = new_subtype; v->colourmap = PAL_NONE; // invalidate vehicle colour map SetWindowDirty(WC_VEHICLE_DETAILS, v->index); SetWindowDirty(WC_VEHICLE_DEPOT, v->tile); diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index be4c66f3e..2cb2541c0 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -2113,52 +2113,15 @@ CommandCost CmdRefitRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, /* Check cargo */ if (new_cid >= NUM_CARGO) return CMD_ERROR; - CommandCost cost(EXPENSES_TRAIN_RUN); - uint num = 0; - - v->InvalidateNewGRFCacheOfChain(); - do { - /* XXX: We also refit all the attached wagons en-masse if they - * can be refitted. This is how TTDPatch does it. TODO: Have - * some nice [Refit] button near each wagon. --pasky */ - if (!CanRefitTo(v->engine_type, new_cid)) continue; - - const Engine *e = Engine::Get(v->engine_type); - if (!e->CanCarryCargo()) continue; - - /* Back up the vehicle's cargo type */ - CargoID temp_cid = v->cargo_type; - byte temp_subtype = v->cargo_subtype; - v->cargo_type = new_cid; - v->cargo_subtype = new_subtype; - - uint amount = GetVehicleCapacity(v); - - /* Restore the original cargo type */ - v->cargo_type = temp_cid; - v->cargo_subtype = temp_subtype; - - if (new_cid != v->cargo_type) { - cost.AddCost(GetRefitCost(v->engine_type)); - } - - num += amount; - if (flags & DC_EXEC) { - v->cargo.Truncate((v->cargo_type == new_cid) ? amount : 0); - v->cargo_type = new_cid; - v->cargo_cap = amount; - v->cargo_subtype = new_subtype; - SetWindowDirty(WC_VEHICLE_DETAILS, v->index); - SetWindowDirty(WC_VEHICLE_DEPOT, v->tile); - InvalidateWindowClassesData(WC_TRAINS_LIST, 0); - } - } while ((v = v->Next()) != NULL && !only_this); - - _returned_refit_capacity = num; + CommandCost cost = RefitVehicle(v, only_this, new_cid, new_subtype, flags); /* Update the train's cached variables */ if (flags & DC_EXEC) { - TrainConsistChanged(Train::Get(p1)->First(), false); + Train *front = v->First(); + TrainConsistChanged(front, false); + SetWindowDirty(WC_VEHICLE_DETAILS, front->index); + SetWindowDirty(WC_VEHICLE_DEPOT, front->tile); + InvalidateWindowClassesData(WC_TRAINS_LIST, 0); } else { v->InvalidateNewGRFCacheOfChain(); // always invalidate; querycost might have filled it } diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 2fbc9a6ac..174cc6aa0 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -683,52 +683,6 @@ void CallVehicleTicks() _current_company = OWNER_NONE; } -/** Check if a given engine type can be refitted to a given cargo - * @param engine_type Engine type to check - * @param cid_to check refit to this cargo-type - * @return true if it is possible, false otherwise - */ -bool CanRefitTo(EngineID engine_type, CargoID cid_to) -{ - return HasBit(EngInfo(engine_type)->refit_mask, cid_to); -} - -/** Learn the price of refitting a certain engine - * @param engine_type Which engine to refit - * @return Price for refitting - */ -CommandCost GetRefitCost(EngineID engine_type) -{ - Money base_cost; - ExpensesType expense_type; - const Engine *e = Engine::Get(engine_type); - switch (e->type) { - case VEH_SHIP: - base_cost = _price.ship_base; - expense_type = EXPENSES_SHIP_RUN; - break; - - case VEH_ROAD: - base_cost = _price.roadveh_base; - expense_type = EXPENSES_ROADVEH_RUN; - break; - - case VEH_AIRCRAFT: - base_cost = _price.aircraft_base; - expense_type = EXPENSES_AIRCRAFT_RUN; - break; - - case VEH_TRAIN: - base_cost = 2 * ((e->u.rail.railveh_type == RAILVEH_WAGON) ? - _price.build_railwagon : _price.build_railvehicle); - expense_type = EXPENSES_TRAIN_RUN; - break; - - default: NOT_REACHED(); - } - return CommandCost(expense_type, (e->info.refit_cost * base_cost) >> 10); -} - static void DoDrawVehicle(const Vehicle *v) { SpriteID image = v->cur_image; diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index e8567abc4..58d8dabc2 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -256,6 +256,93 @@ CommandCost CmdDepotMassAutoReplace(TileIndex tile, DoCommandFlag flags, uint32 return cost; } +/** Learn the price of refitting a certain engine + * @param engine_type Which engine to refit + * @return Price for refitting + */ +static CommandCost GetRefitCost(EngineID engine_type) +{ + Money base_cost; + ExpensesType expense_type; + const Engine *e = Engine::Get(engine_type); + switch (e->type) { + case VEH_SHIP: + base_cost = _price.ship_base; + expense_type = EXPENSES_SHIP_RUN; + break; + + case VEH_ROAD: + base_cost = _price.roadveh_base; + expense_type = EXPENSES_ROADVEH_RUN; + break; + + case VEH_AIRCRAFT: + base_cost = _price.aircraft_base; + expense_type = EXPENSES_AIRCRAFT_RUN; + break; + + case VEH_TRAIN: + base_cost = 2 * ((e->u.rail.railveh_type == RAILVEH_WAGON) ? + _price.build_railwagon : _price.build_railvehicle); + expense_type = EXPENSES_TRAIN_RUN; + break; + + default: NOT_REACHED(); + } + return CommandCost(expense_type, (e->info.refit_cost * base_cost) >> 10); +} + +/** + * Refits a vehicle (chain). + * This is the vehicle-type independent part of the CmdRefitXXX functions. + * @param v The vehicle to refit. + * @param only_this Whether to only refit this vehicle, or the whole chain. + * @param new_cid Cargotype to refit to + * @param new_subtype Cargo subtype to refit to + * @param flags Command flags + * @return refit cost; or CMD_ERROR if no vehicle was actually refitable to the cargo + */ +CommandCost RefitVehicle(Vehicle *v, bool only_this, CargoID new_cid, byte new_subtype, DoCommandFlag flags) +{ + CommandCost cost(v->GetExpenseType(false)); + uint total_capacity = 0; + bool success = false; + + v->InvalidateNewGRFCacheOfChain(); + for (; v != NULL; v = (only_this ? NULL : v->Next())) { + const Engine *e = Engine::Get(v->engine_type); + if (!e->CanCarryCargo() || !HasBit(e->info.refit_mask, new_cid)) continue; + success = true; + + /* Back up the vehicle's cargo type */ + CargoID temp_cid = v->cargo_type; + byte temp_subtype = v->cargo_subtype; + v->cargo_type = new_cid; + v->cargo_subtype = new_subtype; + + uint amount = GetVehicleCapacity(v); + total_capacity += amount; + + /* Restore the original cargo type */ + v->cargo_type = temp_cid; + v->cargo_subtype = temp_subtype; + + if (new_cid != v->cargo_type) { + cost.AddCost(GetRefitCost(v->engine_type)); + } + + if (flags & DC_EXEC) { + v->cargo.Truncate((v->cargo_type == new_cid) ? amount : 0); + v->cargo_type = new_cid; + v->cargo_cap = amount; + v->cargo_subtype = new_subtype; + } + } + + _returned_refit_capacity = total_capacity; + return success ? cost : CMD_ERROR; +} + /** Test if a name is unique among vehicle names. * @param name Name to test. * @return True ifffffff the name is unique. diff --git a/src/vehicle_func.h b/src/vehicle_func.h index 718feb426..1d46abd45 100644 --- a/src/vehicle_func.h +++ b/src/vehicle_func.h @@ -42,8 +42,7 @@ byte VehicleRandomBits(); void ResetVehiclePosHash(); void ResetVehicleColourMap(); -bool CanRefitTo(EngineID engine_type, CargoID cid_to); -CommandCost GetRefitCost(EngineID engine_type); +CommandCost RefitVehicle(Vehicle *v, bool only_this, CargoID new_cid, byte new_subtype, DoCommandFlag flags); void ViewportAddVehicles(DrawPixelInfo *dpi); -- cgit v1.2.3-54-g00ecf