(svn r1283) -Add: AutoRenew is now a client-side patch instead of a game-side patch
authortruelight
Mon, 27 Dec 2004 18:18:44 +0000
changeset 812 79c99885ad00
parent 811 d79a6b72783b
child 813 90d6adb8d4ad
(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.
aircraft_cmd.c
command.c
command.h
roadveh_cmd.c
settings.c
settings_gui.c
ship_cmd.c
train_cmd.c
vehicle.c
vehicle.h
--- a/aircraft_cmd.c	Mon Dec 27 13:40:30 2004 +0000
+++ b/aircraft_cmd.c	Mon Dec 27 18:18:44 2004 +0000
@@ -100,7 +100,7 @@
 	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 @@
 
 	ServiceAircraft(v);
 
-	MaybeRenewVehicle(v, EstimateAircraftCost(v->engine_type));
+	MaybeRenewVehicle(v);
 
 	TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
 
--- a/command.c	Mon Dec 27 13:40:30 2004 +0000
+++ b/command.c	Mon Dec 27 18:18:44 2004 +0000
@@ -167,6 +167,8 @@
 
 DEF_COMMAND(CmdBuildManySignals);
 
+DEF_COMMAND(CmdRenewVehicle);
+
 /* The master command table */
 static CommandProc * const _command_proc_table[] = {
 	CmdBuildRailroadTrack,				/* 0  */
@@ -307,6 +309,7 @@
 	CmdDestroyCompanyHQ,					/* 111 */
 	CmdGiveMoney,									/* 112 */
 	CmdChangePatchSetting,				/* 113 */
+	CmdRenewVehicle,							/* 114 */
 };
 
 int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
--- a/command.h	Mon Dec 27 13:40:30 2004 +0000
+++ b/command.h	Mon Dec 27 18:18:44 2004 +0000
@@ -148,6 +148,8 @@
 	CMD_DESTROY_COMPANY_HQ = 111,
 	CMD_GIVE_MONEY = 112,
 	CMD_CHANGE_PATCH_SETTING = 113,
+
+	CMD_RENEW_VEHICLE = 114,
 };
 
 enum {
--- a/roadveh_cmd.c	Mon Dec 27 13:40:30 2004 +0000
+++ b/roadveh_cmd.c	Mon Dec 27 18:18:44 2004 +0000
@@ -100,7 +100,7 @@
 	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 @@
 
 	InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
-	MaybeRenewVehicle(v, EstimateRoadVehCost(v->engine_type));
+	MaybeRenewVehicle(v);
 
 	VehicleServiceInDepot(v);
 
--- a/settings.c	Mon Dec 27 13:40:30 2004 +0000
+++ b/settings.c	Mon Dec 27 18:18:44 2004 +0000
@@ -822,6 +822,10 @@
 
 	{"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 @@
 	{"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},
--- a/settings_gui.c	Mon Dec 27 13:40:30 2004 +0000
+++ b/settings_gui.c	Mon Dec 27 18:18:44 2004 +0000
@@ -624,9 +624,9 @@
 	{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 @@
 	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 @@
 									*(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 @@
 								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 @@
 				}
 			break;
 		}
-		
+
 		if(edittext) {
 			WP(w,def_d).data_2 = line;
 			ShowQueryString(
@@ -1412,7 +1405,7 @@
 			w->window_number);
 			if (str !=  STR_CONFIG_PATCHES_INT32) DeleteName(str);
 		}
-		
+
 		w->flags4 |= 5 << WF_TIMEOUT_SHL;
 		SetWindowDirty(w);
 	} break;
@@ -1444,8 +1437,8 @@
 				break;
 			}
 		MarkWholeScreenDirty();
-			
-		
+
+
 	} break;
 
 	case WE_TIMEOUT:
--- a/ship_cmd.c	Mon Dec 27 13:40:30 2004 +0000
+++ b/ship_cmd.c	Mon Dec 27 18:18:44 2004 +0000
@@ -387,7 +387,7 @@
 }
 
 
-static int32 EstimateShipCost(uint16 engine_type);
+int32 EstimateShipCost(uint16 engine_type);
 
 static void ShipEnterDepot(Vehicle *v)
 {
@@ -400,7 +400,7 @@
 
 	InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
-	MaybeRenewVehicle(v, EstimateShipCost(v->engine_type));
+	MaybeRenewVehicle(v);
 
 	TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
 
@@ -680,7 +680,7 @@
 
 					/* 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 @@
 	}
 }
 
-static int32 EstimateShipCost(uint16 engine_type)
+int32 EstimateShipCost(uint16 engine_type)
 {
 	return ShipVehInfo(engine_type)->base_cost * (_price.ship_base>>3)>>5;
 }
--- a/train_cmd.c	Mon Dec 27 13:40:30 2004 +0000
+++ b/train_cmd.c	Mon Dec 27 18:18:44 2004 +0000
@@ -364,7 +364,7 @@
 };
 
 
-static int32 EstimateTrainCost(const RailVehicleInfo *rvi)
+int32 EstimateTrainCost(const RailVehicleInfo *rvi)
 {
 	return (rvi->base_cost * (_price.build_railvehicle >> 3)) >> 5;
 }
@@ -2618,7 +2618,7 @@
 	v->load_unload_time_rem = 0;
 	v->cur_speed = 0;
 
-	MaybeRenewVehicle(v, EstimateTrainCost(RailVehInfo(v->engine_type)));
+	MaybeRenewVehicle(v);
 
 	TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
 
--- a/vehicle.c	Mon Dec 27 13:40:30 2004 +0000
+++ b/vehicle.c	Mon Dec 27 18:18:44 2004 +0000
@@ -25,8 +25,8 @@
 
 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 @@
 {
 	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 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 @@
 	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);
 }
 
 
--- a/vehicle.h	Mon Dec 27 13:40:30 2004 +0000
+++ b/vehicle.h	Mon Dec 27 18:18:44 2004 +0000
@@ -361,7 +361,7 @@
 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);