mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-01-22 07:06:01 +00:00
(svn r1283) -Add: AutoRenew is now a client-side patch instead of a game-side patch
Note: this is the first commit that breaks compatibility with 0.3.5! -Fix: Bufferoverflow with autorenew_money. It is now a 32-bit integer.
This commit is contained in:
parent
96b36ec01e
commit
8dcbf2675b
@ -100,7 +100,7 @@ static bool AllocateVehicles(Vehicle **vl, int num)
|
||||
return success;
|
||||
}
|
||||
|
||||
static int32 EstimateAircraftCost(uint16 engine_type)
|
||||
int32 EstimateAircraftCost(uint16 engine_type)
|
||||
{
|
||||
return AircraftVehInfo(engine_type)->base_cost * (_price.aircraft_base>>3)>>5;
|
||||
}
|
||||
@ -1157,7 +1157,7 @@ static void AircraftEnterHangar(Vehicle *v)
|
||||
|
||||
ServiceAircraft(v);
|
||||
|
||||
MaybeRenewVehicle(v, EstimateAircraftCost(v->engine_type));
|
||||
MaybeRenewVehicle(v);
|
||||
|
||||
TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
|
||||
|
||||
|
@ -167,6 +167,8 @@ DEF_COMMAND(CmdStartScenario);
|
||||
|
||||
DEF_COMMAND(CmdBuildManySignals);
|
||||
|
||||
DEF_COMMAND(CmdRenewVehicle);
|
||||
|
||||
/* The master command table */
|
||||
static CommandProc * const _command_proc_table[] = {
|
||||
CmdBuildRailroadTrack, /* 0 */
|
||||
@ -307,6 +309,7 @@ static CommandProc * const _command_proc_table[] = {
|
||||
CmdDestroyCompanyHQ, /* 111 */
|
||||
CmdGiveMoney, /* 112 */
|
||||
CmdChangePatchSetting, /* 113 */
|
||||
CmdRenewVehicle, /* 114 */
|
||||
};
|
||||
|
||||
int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
|
||||
|
@ -148,6 +148,8 @@ enum {
|
||||
CMD_DESTROY_COMPANY_HQ = 111,
|
||||
CMD_GIVE_MONEY = 112,
|
||||
CMD_CHANGE_PATCH_SETTING = 113,
|
||||
|
||||
CMD_RENEW_VEHICLE = 114,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -100,7 +100,7 @@ void DrawRoadVehEngineInfo(int engine, int x, int y, int maxw)
|
||||
DrawStringMultiCenter(x, y, STR_902A_COST_SPEED_RUNNING_COST, maxw);
|
||||
}
|
||||
|
||||
static int32 EstimateRoadVehCost(byte engine_type)
|
||||
int32 EstimateRoadVehCost(byte engine_type)
|
||||
{
|
||||
return ((_price.roadveh_base >> 3) * RoadVehInfo(engine_type)->base_cost) >> 5;
|
||||
}
|
||||
@ -1379,7 +1379,7 @@ void RoadVehEnterDepot(Vehicle *v)
|
||||
|
||||
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
|
||||
|
||||
MaybeRenewVehicle(v, EstimateRoadVehCost(v->engine_type));
|
||||
MaybeRenewVehicle(v);
|
||||
|
||||
VehicleServiceInDepot(v);
|
||||
|
||||
|
@ -822,6 +822,10 @@ static const SettingDesc patch_player_settings[] = {
|
||||
|
||||
{"window_snap_radius", SDT_UINT8, (void*)10, &_patches.window_snap_radius, NULL},
|
||||
|
||||
{"autorenew", SDT_BOOL, (void*)false, &_patches.autorenew, NULL},
|
||||
{"autorenew_months", SDT_INT16, (void*)-6, &_patches.autorenew_months, NULL},
|
||||
{"autorenew_money", SDT_INT32, (void*)100000,&_patches.autorenew_money, NULL},
|
||||
|
||||
{NULL, 0, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
@ -870,10 +874,6 @@ const SettingDesc patch_settings[] = {
|
||||
{"servint_ships", SDT_UINT16, (void*)360, &_patches.servint_ships, NULL},
|
||||
{"servint_aircraft", SDT_UINT16, (void*)100, &_patches.servint_aircraft, NULL},
|
||||
|
||||
{"autorenew", SDT_BOOL, (void*)false, &_patches.autorenew, NULL},
|
||||
{"autorenew_months", SDT_INT16, (void*)-6, &_patches.autorenew_months, NULL},
|
||||
{"autorenew_money", SDT_INT32, (void*)100000,&_patches.autorenew_money, NULL},
|
||||
|
||||
{"new_pathfinding", SDT_BOOL, (void*)true, &_patches.new_pathfinding, NULL},
|
||||
{"pf_maxlength", SDT_UINT16, (void*)512, &_patches.pf_maxlength, NULL},
|
||||
{"pf_maxdepth", SDT_UINT8, (void*)16, &_patches.pf_maxdepth, NULL},
|
||||
|
@ -624,9 +624,9 @@ static const PatchEntry _patches_vehicles[] = {
|
||||
{PE_BOOL, 0, STR_CONFIG_PATCHES_NEVER_EXPIRE_VEHICLES, "never_expire_vehicles", &_patches.never_expire_vehicles,0,0,0, NULL},
|
||||
|
||||
{PE_UINT16, PF_0ISDIS | PF_PLAYERBASED, STR_CONFIG_PATCHES_LOST_TRAIN_DAYS, "lost_train_days", &_patches.lost_train_days, 180,720, 60, NULL},
|
||||
{PE_BOOL, 0, STR_CONFIG_PATCHES_AUTORENEW_VEHICLE,"autorenew", &_patches.autorenew, 0, 0, 0, NULL},
|
||||
{PE_INT16, 0, STR_CONFIG_PATCHES_AUTORENEW_MONTHS, "autorenew_months", &_patches.autorenew_months, -12, 12, 1, NULL},
|
||||
{PE_CURRENCY, 0, STR_CONFIG_PATCHES_AUTORENEW_MONEY,"autorenew_money", &_patches.autorenew_money, 0, 2000000, 100000, NULL},
|
||||
{PE_BOOL, PF_PLAYERBASED, STR_CONFIG_PATCHES_AUTORENEW_VEHICLE,"autorenew", &_patches.autorenew, 0, 0, 0, NULL},
|
||||
{PE_INT16, PF_PLAYERBASED, STR_CONFIG_PATCHES_AUTORENEW_MONTHS, "autorenew_months", &_patches.autorenew_months, -12, 12, 1, NULL},
|
||||
{PE_CURRENCY, PF_PLAYERBASED, STR_CONFIG_PATCHES_AUTORENEW_MONEY,"autorenew_money", &_patches.autorenew_money, 0, 2000000, 100000, NULL},
|
||||
|
||||
{PE_UINT8, 0, STR_CONFIG_PATCHES_MAX_TRAINS, "max_trains", &_patches.max_trains, 0,240, 10, NULL},
|
||||
{PE_UINT8, 0, STR_CONFIG_PATCHES_MAX_ROADVEH, "max_roadveh", &_patches.max_roadveh, 0,240, 10, NULL},
|
||||
@ -700,7 +700,7 @@ static int32 ReadPE(const PatchEntry*pe)
|
||||
case PE_INT16: return *(int16*)pe->variable;
|
||||
case PE_UINT16: return *(uint16*)pe->variable;
|
||||
case PE_INT32: return *(int32*)pe->variable;
|
||||
case PE_CURRENCY: return (*(int64*)pe->variable) * GetCurrentCurrencyRate();
|
||||
case PE_CURRENCY: return (*(int32*)pe->variable) * GetCurrentCurrencyRate();
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
@ -744,6 +744,7 @@ static void WritePE(const PatchEntry *pe, int32 val)
|
||||
*(uint16*)pe->variable = (uint16)val;
|
||||
break;
|
||||
|
||||
case PE_CURRENCY:
|
||||
case PE_INT32: if ((int32)val > (int32)pe->max)
|
||||
*(int32*)pe->variable = (int32)pe->max;
|
||||
else if ((int32)val < (int32)pe->min)
|
||||
@ -751,14 +752,6 @@ static void WritePE(const PatchEntry *pe, int32 val)
|
||||
else
|
||||
*(int32*)pe->variable = val;
|
||||
break;
|
||||
|
||||
case PE_CURRENCY: if ((int64)val > (int64)pe->max)
|
||||
*(int64*)pe->variable = (int64)pe->max;
|
||||
else if ((int64)val < (int64)pe->min)
|
||||
*(int64*)pe->variable = (int64)pe->min;
|
||||
else
|
||||
*(int64*)pe->variable = val;
|
||||
break;
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
@ -1400,7 +1393,7 @@ static void CustCurrencyWndProc(Window *w, WindowEvent *e)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(edittext) {
|
||||
WP(w,def_d).data_2 = line;
|
||||
ShowQueryString(
|
||||
@ -1412,7 +1405,7 @@ static void CustCurrencyWndProc(Window *w, WindowEvent *e)
|
||||
w->window_number);
|
||||
if (str != STR_CONFIG_PATCHES_INT32) DeleteName(str);
|
||||
}
|
||||
|
||||
|
||||
w->flags4 |= 5 << WF_TIMEOUT_SHL;
|
||||
SetWindowDirty(w);
|
||||
} break;
|
||||
@ -1444,8 +1437,8 @@ static void CustCurrencyWndProc(Window *w, WindowEvent *e)
|
||||
break;
|
||||
}
|
||||
MarkWholeScreenDirty();
|
||||
|
||||
|
||||
|
||||
|
||||
} break;
|
||||
|
||||
case WE_TIMEOUT:
|
||||
|
@ -387,7 +387,7 @@ static bool ShipAccelerate(Vehicle *v)
|
||||
}
|
||||
|
||||
|
||||
static int32 EstimateShipCost(uint16 engine_type);
|
||||
int32 EstimateShipCost(uint16 engine_type);
|
||||
|
||||
static void ShipEnterDepot(Vehicle *v)
|
||||
{
|
||||
@ -400,7 +400,7 @@ static void ShipEnterDepot(Vehicle *v)
|
||||
|
||||
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
|
||||
|
||||
MaybeRenewVehicle(v, EstimateShipCost(v->engine_type));
|
||||
MaybeRenewVehicle(v);
|
||||
|
||||
TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
|
||||
|
||||
@ -680,7 +680,7 @@ static void ShipController(Vehicle *v)
|
||||
|
||||
/* Process station in the schedule. Don't do that for buoys (HVOT_BUOY) */
|
||||
st = DEREF_STATION(v->current_order.station);
|
||||
if (!(st->had_vehicle_of_type & HVOT_BUOY)
|
||||
if (!(st->had_vehicle_of_type & HVOT_BUOY)
|
||||
&& (st->facilities & FACIL_DOCK)) { /* ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations */
|
||||
v->current_order.type = OT_LOADING;
|
||||
v->current_order.flags &= OF_FULL_LOAD | OF_UNLOAD;
|
||||
@ -796,7 +796,7 @@ void ShipsYearlyLoop()
|
||||
}
|
||||
}
|
||||
|
||||
static int32 EstimateShipCost(uint16 engine_type)
|
||||
int32 EstimateShipCost(uint16 engine_type)
|
||||
{
|
||||
return ShipVehInfo(engine_type)->base_cost * (_price.ship_base>>3)>>5;
|
||||
}
|
||||
|
@ -364,7 +364,7 @@ static const byte _railveh_score[] = {
|
||||
};
|
||||
|
||||
|
||||
static int32 EstimateTrainCost(const RailVehicleInfo *rvi)
|
||||
int32 EstimateTrainCost(const RailVehicleInfo *rvi)
|
||||
{
|
||||
return (rvi->base_cost * (_price.build_railvehicle >> 3)) >> 5;
|
||||
}
|
||||
@ -2618,7 +2618,7 @@ void TrainEnterDepot(Vehicle *v, uint tile)
|
||||
v->load_unload_time_rem = 0;
|
||||
v->cur_speed = 0;
|
||||
|
||||
MaybeRenewVehicle(v, EstimateTrainCost(RailVehInfo(v->engine_type)));
|
||||
MaybeRenewVehicle(v);
|
||||
|
||||
TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
|
||||
|
||||
|
127
vehicle.c
127
vehicle.c
@ -25,8 +25,8 @@ void VehicleServiceInDepot(Vehicle *v)
|
||||
|
||||
bool VehicleNeedsService(const Vehicle *v)
|
||||
{
|
||||
return _patches.servint_ispercent ?
|
||||
(v->reliability < _engines[v->engine_type].reliability * (100 - v->service_interval) / 100) :
|
||||
return _patches.servint_ispercent ?
|
||||
(v->reliability < _engines[v->engine_type].reliability * (100 - v->service_interval) / 100) :
|
||||
(v->date_of_last_service + v->service_interval < _date);
|
||||
}
|
||||
|
||||
@ -1358,6 +1358,7 @@ static void ShowVehicleGettingOld(Vehicle *v, StringID msg)
|
||||
{
|
||||
if (v->owner != _local_player)
|
||||
return;
|
||||
|
||||
// Do not show getting-old message if autorenew is active
|
||||
if (_patches.autorenew)
|
||||
return;
|
||||
@ -1389,9 +1390,89 @@ void AgeVehicle(Vehicle *v)
|
||||
}
|
||||
}
|
||||
|
||||
void MaybeRenewVehicle(Vehicle *v, int32 build_cost)
|
||||
extern int32 EstimateTrainCost(const RailVehicleInfo *rvi);
|
||||
extern int32 EstimateRoadVehCost(byte engine_type);
|
||||
extern int32 EstimateShipCost(uint16 engine_type);
|
||||
extern int32 EstimateAircraftCost(uint16 engine_type);
|
||||
|
||||
/* Renews a vehicle
|
||||
p1 - Index of vehicle
|
||||
p2 - Type of new engine */
|
||||
int32 CmdRenewVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
Engine *e;
|
||||
byte new_engine_type = p2;
|
||||
Vehicle *v = DEREF_VEHICLE(p1);
|
||||
int cost, build_cost;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
|
||||
|
||||
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;
|
||||
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)
|
||||
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) {
|
||||
int message;
|
||||
SetDParam(0, v->unitnumber);
|
||||
switch (v->type) {
|
||||
case VEH_Train: message = STR_TRAIN_AUTORENEW_FAILED; break;
|
||||
case VEH_Road: message = STR_ROADVEHICLE_AUTORENEW_FAILED; break;
|
||||
case VEH_Ship: message = STR_SHIP_AUTORENEW_FAILED; break;
|
||||
case VEH_Aircraft: message = STR_AIRCRAFT_AUTORENEW_FAILED; break;
|
||||
// This should never happen
|
||||
default: message = 0; break;
|
||||
}
|
||||
|
||||
AddNewsItem(message, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), v->index, 0);
|
||||
}
|
||||
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
cost = build_cost - v->value;
|
||||
|
||||
if (flags & DC_QUERY_COST)
|
||||
return cost;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
Engine *e;
|
||||
|
||||
/* 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! */
|
||||
}
|
||||
e = &_engines[new_engine_type];
|
||||
v->reliability = e->reliability;
|
||||
v->reliability_spd_dec = e->reliability_spd_dec;
|
||||
v->age = 0;
|
||||
|
||||
v->date_of_last_service = _date;
|
||||
v->build_year = _cur_year;
|
||||
|
||||
v->value = build_cost;
|
||||
|
||||
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
|
||||
}
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
void MaybeRenewVehicle(Vehicle *v)
|
||||
{
|
||||
if (v->owner != _local_player)
|
||||
return;
|
||||
|
||||
// A vehicle is autorenewed when it it gets the amount of months
|
||||
// give by _patches.autorenew_months away for his max age.
|
||||
@ -1400,42 +1481,8 @@ void MaybeRenewVehicle(Vehicle *v, int32 build_cost)
|
||||
if (!_patches.autorenew || v->age - v->max_age < (_patches.autorenew_months * 30))
|
||||
return;
|
||||
|
||||
if (DEREF_PLAYER(v->owner)->money64 < _patches.autorenew_money + build_cost - v->value) {
|
||||
if (v->owner == _local_player) {
|
||||
int message;
|
||||
SetDParam(0, v->unitnumber);
|
||||
switch (v->type) {
|
||||
case VEH_Train: message = STR_TRAIN_AUTORENEW_FAILED; break;
|
||||
case VEH_Road: message = STR_ROADVEHICLE_AUTORENEW_FAILED; break;
|
||||
case VEH_Ship: message = STR_SHIP_AUTORENEW_FAILED; break;
|
||||
case VEH_Aircraft: message = STR_AIRCRAFT_AUTORENEW_FAILED; break;
|
||||
// This should never happen
|
||||
default: message = 0; break;
|
||||
}
|
||||
|
||||
AddNewsItem(message, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), v->index, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Withdraw the money from the right player ;)
|
||||
_current_player = v->owner;
|
||||
|
||||
e = &_engines[v->engine_type];
|
||||
v->reliability = e->reliability;
|
||||
v->reliability_spd_dec = e->reliability_spd_dec;
|
||||
v->age = 0;
|
||||
|
||||
v->date_of_last_service = _date;
|
||||
v->build_year = _cur_year;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
|
||||
SubtractMoneyFromPlayer(build_cost - v->value);
|
||||
v->value = build_cost;
|
||||
|
||||
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
|
||||
|
||||
_current_player = OWNER_NONE;
|
||||
/* Now renew the vehicle */
|
||||
DoCommandP(v->tile, v->index, v->engine_type, NULL, CMD_RENEW_VEHICLE);
|
||||
}
|
||||
|
||||
|
||||
|
@ -361,7 +361,7 @@ Vehicle *CheckClickOnVehicle(ViewPort *vp, int x, int y);
|
||||
void DecreaseVehicleValue(Vehicle *v);
|
||||
void CheckVehicleBreakdown(Vehicle *v);
|
||||
void AgeVehicle(Vehicle *v);
|
||||
void MaybeRenewVehicle(Vehicle *v, int32 build_cost);
|
||||
void MaybeRenewVehicle(Vehicle *v);
|
||||
|
||||
void DeleteCommandFromVehicleSchedule(Order cmd);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user