mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r26596) [1.4] -Backport from trunk:
- Fix: Save/load issues on big endian machines (r26593, r26590, r26589) - Fix: Consider multiheaded trains in station refits [FS#5995] (r26586) - Fix: Game script could be changed in game by double clicking [FS#5974] (r26583)
This commit is contained in:
parent
3cd96a459b
commit
d3c41a9d0e
|
@ -853,7 +853,7 @@ struct AIConfigWindow : public Window {
|
||||||
case WID_AIC_GAMELIST: {
|
case WID_AIC_GAMELIST: {
|
||||||
this->selected_slot = OWNER_DEITY;
|
this->selected_slot = OWNER_DEITY;
|
||||||
this->InvalidateData();
|
this->InvalidateData();
|
||||||
if (click_count > 1 && this->selected_slot != INVALID_COMPANY) ShowAIListWindow((CompanyID)this->selected_slot);
|
if (click_count > 1 && this->selected_slot != INVALID_COMPANY && _game_mode != GM_NORMAL) ShowAIListWindow((CompanyID)this->selected_slot);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
182
src/economy.cpp
182
src/economy.cpp
|
@ -19,6 +19,7 @@
|
||||||
#include "network/network_func.h"
|
#include "network/network_func.h"
|
||||||
#include "ai/ai.hpp"
|
#include "ai/ai.hpp"
|
||||||
#include "aircraft.h"
|
#include "aircraft.h"
|
||||||
|
#include "train.h"
|
||||||
#include "newgrf_engine.h"
|
#include "newgrf_engine.h"
|
||||||
#include "engine_base.h"
|
#include "engine_base.h"
|
||||||
#include "ground_vehicle.hpp"
|
#include "ground_vehicle.hpp"
|
||||||
|
@ -1338,21 +1339,135 @@ static void ReserveConsist(Station *st, Vehicle *u, CargoArray *consist_capleft,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether an articulated vehicle is empty.
|
* Iterate the articulated parts of a vehicle, also considering the special cases of "normal"
|
||||||
* @param v Vehicle
|
* aircraft and double headed trains. Apply an action to each vehicle and immediately return false
|
||||||
* @return true if all parts are empty.
|
* if that action does so. Otherwise return true.
|
||||||
|
* @tparam Taction Class of action to be applied. Must implement bool operator()([const] Vehicle *).
|
||||||
|
* @param v First articulated part.
|
||||||
|
* @param action Instance of Taction.
|
||||||
|
* @return false if any of the action invocations returned false, true otherwise.
|
||||||
*/
|
*/
|
||||||
static bool IsArticulatedVehicleEmpty(Vehicle *v)
|
template<class Taction>
|
||||||
|
bool IterateVehicleParts(Vehicle *v, Taction action)
|
||||||
{
|
{
|
||||||
v = v->GetFirstEnginePart();
|
for (Vehicle *w = v; w != NULL;
|
||||||
|
w = w->HasArticulatedPart() ? w->GetNextArticulatedPart() : NULL) {
|
||||||
for (; v != NULL; v = v->HasArticulatedPart() ? v->GetNextArticulatedPart() : NULL) {
|
if (!action(w)) return false;
|
||||||
if (v->cargo.StoredCount() != 0) return false;
|
if (w->type == VEH_TRAIN) {
|
||||||
|
Train *train = Train::From(w);
|
||||||
|
if (train->IsMultiheaded() && !action(train->other_multiheaded_part)) return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (v->type == VEH_AIRCRAFT && Aircraft::From(v)->IsNormalAircraft()) return action(v->Next());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action to check if a vehicle has no stored cargo.
|
||||||
|
*/
|
||||||
|
struct IsEmptyAction
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Checks if the vehicle has stored cargo.
|
||||||
|
* @param v Vehicle to be checked.
|
||||||
|
* @return true if v is either empty or has only reserved cargo, false otherwise.
|
||||||
|
*/
|
||||||
|
bool operator()(const Vehicle *v)
|
||||||
|
{
|
||||||
|
return v->cargo.StoredCount() == 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refit preparation action.
|
||||||
|
*/
|
||||||
|
struct PrepareRefitAction
|
||||||
|
{
|
||||||
|
CargoArray &consist_capleft; ///< Capacities left in the consist.
|
||||||
|
uint32 &refit_mask; ///< Bitmask of possible refit cargoes.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a refit preparation action.
|
||||||
|
* @param consist_capleft Capacities left in consist, to be updated here.
|
||||||
|
* @param refit_mask Refit mask to be constructed from refit information of vehicles.
|
||||||
|
*/
|
||||||
|
PrepareRefitAction(CargoArray &consist_capleft, uint32 &refit_mask) :
|
||||||
|
consist_capleft(consist_capleft), refit_mask(refit_mask) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares for refitting of a vehicle, subtracting its free capacity from consist_capleft and
|
||||||
|
* adding the cargoes it can refit to to the refit mask.
|
||||||
|
* @param v The vehicle to be refitted.
|
||||||
|
* @return true.
|
||||||
|
*/
|
||||||
|
bool operator()(const Vehicle *v)
|
||||||
|
{
|
||||||
|
this->consist_capleft[v->cargo_type] -= v->cargo_cap - v->cargo.ReservedCount();
|
||||||
|
this->refit_mask |= EngInfo(v->engine_type)->refit_mask;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action for returning reserved cargo.
|
||||||
|
*/
|
||||||
|
struct ReturnCargoAction
|
||||||
|
{
|
||||||
|
Station *st; ///< Station to give the returned cargo to.
|
||||||
|
StationID next_hop; ///< Next hop the cargo should be assigned to.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a cargo return action.
|
||||||
|
* @param st Station to give the returned cargo to.
|
||||||
|
* @param next_one Next hop the cargo should be assigned to.
|
||||||
|
*/
|
||||||
|
ReturnCargoAction(Station *st, StationID next_one) : st(st), next_hop(next_one) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all reserved cargo from a vehicle.
|
||||||
|
* @param v Vehicle to return cargo from.
|
||||||
|
* @return true.
|
||||||
|
*/
|
||||||
|
bool operator()(Vehicle *v)
|
||||||
|
{
|
||||||
|
v->cargo.Return(UINT_MAX, &this->st->goods[v->cargo_type].cargo, this->next_hop);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action for finalizing a refit.
|
||||||
|
*/
|
||||||
|
struct FinalizeRefitAction
|
||||||
|
{
|
||||||
|
CargoArray &consist_capleft; ///< Capacities left in the consist.
|
||||||
|
Station *st; ///< Station to reserve cargo from.
|
||||||
|
StationIDStack &next_station; ///< Next hops to reserve cargo for.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a finalizing action.
|
||||||
|
* @param consist_capleft Capacities left in the consist.
|
||||||
|
* @param st Station to reserve cargo from.
|
||||||
|
* @param next_station Next hops to reserve cargo for.
|
||||||
|
*/
|
||||||
|
FinalizeRefitAction(CargoArray &consist_capleft, Station *st, StationIDStack &next_station) :
|
||||||
|
consist_capleft(consist_capleft), st(st), next_station(next_station) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reserve cargo from the station and update the remaining consist capacities with the
|
||||||
|
* vehicle's remaining free capacity.
|
||||||
|
* @param v Vehicle to be finalized.
|
||||||
|
* @return true.
|
||||||
|
*/
|
||||||
|
bool operator()(Vehicle *v)
|
||||||
|
{
|
||||||
|
this->st->goods[v->cargo_type].cargo.Reserve(v->cargo_cap - v->cargo.RemainingCount(),
|
||||||
|
&v->cargo, st->xy, next_station);
|
||||||
|
this->consist_capleft[v->cargo_type] += v->cargo_cap - v->cargo.RemainingCount();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refit a vehicle in a station.
|
* Refit a vehicle in a station.
|
||||||
* @param v Vehicle to be refitted.
|
* @param v Vehicle to be refitted.
|
||||||
|
@ -1363,32 +1478,15 @@ static bool IsArticulatedVehicleEmpty(Vehicle *v)
|
||||||
*/
|
*/
|
||||||
static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station *st, StationIDStack next_station, CargoID new_cid)
|
static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station *st, StationIDStack next_station, CargoID new_cid)
|
||||||
{
|
{
|
||||||
if (v->type == VEH_AIRCRAFT && (!Aircraft::From(v)->IsNormalAircraft() || v->Next()->cargo.StoredCount() > 0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_normal_aircraft = (v->type == VEH_AIRCRAFT && Aircraft::From(v)->IsNormalAircraft());
|
|
||||||
Vehicle *v_start = v->GetFirstEnginePart();
|
Vehicle *v_start = v->GetFirstEnginePart();
|
||||||
|
if (!IterateVehicleParts(v_start, IsEmptyAction())) return;
|
||||||
/* Remove old capacity from consist capacity */
|
|
||||||
consist_capleft[v_start->cargo_type] -= (v_start->cargo_cap - v_start->cargo.ReservedCount());
|
|
||||||
for (Vehicle *w = v_start; w->HasArticulatedPart(); ) {
|
|
||||||
w = w->GetNextArticulatedPart();
|
|
||||||
consist_capleft[w->cargo_type] -= (w->cargo_cap - w->cargo.ReservedCount());
|
|
||||||
}
|
|
||||||
if (is_normal_aircraft) {
|
|
||||||
consist_capleft[v->Next()->cargo_type] -= (v->Next()->cargo_cap - v->Next()->cargo.ReservedCount());
|
|
||||||
}
|
|
||||||
|
|
||||||
Backup<CompanyByte> cur_company(_current_company, v->owner, FILE_LINE);
|
Backup<CompanyByte> cur_company(_current_company, v->owner, FILE_LINE);
|
||||||
|
|
||||||
/* Check if all articulated parts are empty and collect refit mask. */
|
|
||||||
uint32 refit_mask = v->GetEngine()->info.refit_mask;
|
uint32 refit_mask = v->GetEngine()->info.refit_mask;
|
||||||
Vehicle *w = v_start;
|
|
||||||
while (w->HasArticulatedPart()) {
|
/* Remove old capacity from consist capacity and collect refit mask. */
|
||||||
w = w->GetNextArticulatedPart();
|
IterateVehicleParts(v_start, PrepareRefitAction(consist_capleft, refit_mask));
|
||||||
refit_mask |= EngInfo(w->engine_type)->refit_mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new_cid == CT_AUTO_REFIT) {
|
if (new_cid == CT_AUTO_REFIT) {
|
||||||
/* Get a refittable cargo type with waiting cargo for next_station or INVALID_STATION. */
|
/* Get a refittable cargo type with waiting cargo for next_station or INVALID_STATION. */
|
||||||
|
@ -1416,31 +1514,13 @@ static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station
|
||||||
|
|
||||||
/* Refit if given a valid cargo. */
|
/* Refit if given a valid cargo. */
|
||||||
if (new_cid < NUM_CARGO && new_cid != v_start->cargo_type) {
|
if (new_cid < NUM_CARGO && new_cid != v_start->cargo_type) {
|
||||||
StationID next_one = StationIDStack(next_station).Pop();
|
IterateVehicleParts(v_start, ReturnCargoAction(st, StationIDStack(next_station).Pop()));
|
||||||
v_start->cargo.Return(UINT_MAX, &st->goods[v_start->cargo_type].cargo, next_one);
|
|
||||||
for (w = v_start; w->HasArticulatedPart();) {
|
|
||||||
w = w->GetNextArticulatedPart();
|
|
||||||
w->cargo.Return(UINT_MAX, &st->goods[w->cargo_type].cargo, next_one);
|
|
||||||
}
|
|
||||||
if (is_normal_aircraft) {
|
|
||||||
v->Next()->cargo.Return(UINT_MAX, &st->goods[v->Next()->cargo_type].cargo, next_one);
|
|
||||||
}
|
|
||||||
CommandCost cost = DoCommand(v_start->tile, v_start->index, new_cid | 1U << 6 | 0xFF << 8 | 1U << 16, DC_EXEC, GetCmdRefitVeh(v_start)); // Auto-refit and only this vehicle including artic parts.
|
CommandCost cost = DoCommand(v_start->tile, v_start->index, new_cid | 1U << 6 | 0xFF << 8 | 1U << 16, DC_EXEC, GetCmdRefitVeh(v_start)); // Auto-refit and only this vehicle including artic parts.
|
||||||
if (cost.Succeeded()) v->First()->profit_this_year -= cost.GetCost() << 8;
|
if (cost.Succeeded()) v->First()->profit_this_year -= cost.GetCost() << 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add new capacity to consist capacity and reserve cargo */
|
/* Add new capacity to consist capacity and reserve cargo */
|
||||||
w = v_start;
|
IterateVehicleParts(v_start, FinalizeRefitAction(consist_capleft, st, next_station));
|
||||||
do {
|
|
||||||
st->goods[w->cargo_type].cargo.Reserve(w->cargo_cap - w->cargo.RemainingCount(), &w->cargo, st->xy, next_station);
|
|
||||||
consist_capleft[w->cargo_type] += w->cargo_cap - w->cargo.RemainingCount();
|
|
||||||
w = w->HasArticulatedPart() ? w->GetNextArticulatedPart() : NULL;
|
|
||||||
} while (w != NULL);
|
|
||||||
if (is_normal_aircraft) {
|
|
||||||
w = v->Next();
|
|
||||||
st->goods[w->cargo_type].cargo.Reserve(w->cargo_cap - w->cargo.RemainingCount(), &w->cargo, st->xy, next_station);
|
|
||||||
consist_capleft[w->cargo_type] += w->cargo_cap - w->cargo.RemainingCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_company.Restore();
|
cur_company.Restore();
|
||||||
}
|
}
|
||||||
|
@ -1572,7 +1652,7 @@ static void LoadUnloadVehicle(Vehicle *front)
|
||||||
if (front->current_order.GetLoadType() & OLFB_NO_LOAD || HasBit(front->vehicle_flags, VF_STOP_LOADING)) continue;
|
if (front->current_order.GetLoadType() & OLFB_NO_LOAD || HasBit(front->vehicle_flags, VF_STOP_LOADING)) continue;
|
||||||
|
|
||||||
/* This order has a refit, if this is the first vehicle part carrying cargo and the whole vehicle is empty, try refitting. */
|
/* This order has a refit, if this is the first vehicle part carrying cargo and the whole vehicle is empty, try refitting. */
|
||||||
if (front->current_order.IsRefit() && artic_part == 1 && IsArticulatedVehicleEmpty(v)) {
|
if (front->current_order.IsRefit() && artic_part == 1) {
|
||||||
HandleStationRefit(v, consist_capleft, st, next_station, front->current_order.GetRefitCargo());
|
HandleStationRefit(v, consist_capleft, st, next_station, front->current_order.GetRefitCargo());
|
||||||
ge = &st->goods[v->cargo_type];
|
ge = &st->goods[v->cargo_type];
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,7 +256,7 @@ static const SaveLoad _company_desc[] = {
|
||||||
|
|
||||||
SLE_VAR(CompanyProperties, colour, SLE_UINT8),
|
SLE_VAR(CompanyProperties, colour, SLE_UINT8),
|
||||||
SLE_VAR(CompanyProperties, money_fraction, SLE_UINT8),
|
SLE_VAR(CompanyProperties, money_fraction, SLE_UINT8),
|
||||||
SLE_CONDVAR(CompanyProperties, avail_railtypes, SLE_UINT8, 0, 57),
|
SLE_CONDVAR(CompanyProperties, avail_railtypes, SLE_VAR_I32 | SLE_FILE_I8, 0, 57),
|
||||||
SLE_VAR(CompanyProperties, block_preview, SLE_UINT8),
|
SLE_VAR(CompanyProperties, block_preview, SLE_UINT8),
|
||||||
|
|
||||||
SLE_CONDNULL(2, 0, 93), ///< cargo_types
|
SLE_CONDNULL(2, 0, 93), ///< cargo_types
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
#include "saveload.h"
|
#include "saveload.h"
|
||||||
|
|
||||||
static const SaveLoad _goals_desc[] = {
|
static const SaveLoad _goals_desc[] = {
|
||||||
SLE_VAR(Goal, company, SLE_UINT16),
|
SLE_VAR(Goal, company, SLE_FILE_U16 | SLE_VAR_U8),
|
||||||
SLE_VAR(Goal, type, SLE_UINT16),
|
SLE_VAR(Goal, type, SLE_FILE_U16 | SLE_VAR_U8),
|
||||||
SLE_VAR(Goal, dst, SLE_UINT32),
|
SLE_VAR(Goal, dst, SLE_UINT32),
|
||||||
SLE_STR(Goal, text, SLE_STR | SLF_ALLOW_CONTROL, 0),
|
SLE_STR(Goal, text, SLE_STR | SLF_ALLOW_CONTROL, 0),
|
||||||
SLE_CONDSTR(Goal, progress, SLE_STR | SLF_ALLOW_CONTROL, 0, 182, SL_MAX_VERSION),
|
SLE_CONDSTR(Goal, progress, SLE_STR | SLF_ALLOW_CONTROL, 0, 182, SL_MAX_VERSION),
|
||||||
|
|
|
@ -21,7 +21,7 @@ typedef LinkGraph::BaseEdge Edge;
|
||||||
|
|
||||||
const SettingDesc *GetSettingDescription(uint index);
|
const SettingDesc *GetSettingDescription(uint index);
|
||||||
|
|
||||||
static uint _num_nodes;
|
static uint16 _num_nodes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a SaveLoad array for a link graph.
|
* Get a SaveLoad array for a link graph.
|
||||||
|
|
|
@ -301,7 +301,7 @@ struct Airport : public TileArea {
|
||||||
uint64 flags; ///< stores which blocks on the airport are taken. was 16 bit earlier on, then 32
|
uint64 flags; ///< stores which blocks on the airport are taken. was 16 bit earlier on, then 32
|
||||||
byte type; ///< Type of this airport, @see AirportTypes
|
byte type; ///< Type of this airport, @see AirportTypes
|
||||||
byte layout; ///< Airport layout number.
|
byte layout; ///< Airport layout number.
|
||||||
Direction rotation; ///< How this airport is rotated.
|
DirectionByte rotation; ///< How this airport is rotated.
|
||||||
|
|
||||||
PersistentStorage *psa; ///< Persistent storage for NewGRF airports.
|
PersistentStorage *psa; ///< Persistent storage for NewGRF airports.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue