(svn r9671) -Codechange: Implement NewGRF callback 36, which allows changing of various properties which were previously static. Vehicle max speed and train power/te/running costs are adjustable.
authorpeter1138
Wed, 18 Apr 2007 18:37:40 +0000
changeset 6986 168d3add1f13
parent 6985 6fd300b20503
child 6987 b0f13039bda2
(svn r9671) -Codechange: Implement NewGRF callback 36, which allows changing of various properties which were previously static. Vehicle max speed and train power/te/running costs are adjustable.
src/aircraft.h
src/aircraft_cmd.cpp
src/newgrf_callbacks.h
src/newgrf_engine.cpp
src/newgrf_engine.h
src/ship_cmd.cpp
src/train_cmd.cpp
src/vehicle.cpp
src/vehicle.h
--- a/src/aircraft.h	Wed Apr 18 18:20:31 2007 +0000
+++ b/src/aircraft.h	Wed Apr 18 18:37:40 2007 +0000
@@ -109,4 +109,10 @@
  */
 void UpdateAirplanesOnNewStation(const Station *st);
 
+/** Update cached values of an aircraft.
+ * Currently caches callback 36 max speed.
+ * @param v Vehicle
+ */
+void UpdateAircraftCache(Vehicle *v);
+
 #endif /* AIRCRAFT_H */
--- a/src/aircraft_cmd.cpp	Wed Apr 18 18:20:31 2007 +0000
+++ b/src/aircraft_cmd.cpp	Wed Apr 18 18:37:40 2007 +0000
@@ -393,6 +393,8 @@
 		v->vehicle_flags = 0;
 		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
 
+		UpdateAircraftCache(v);
+
 		VehiclePositionChanged(v);
 		VehiclePositionChanged(u);
 
@@ -862,6 +864,21 @@
 	}
 }
 
+
+void UpdateAircraftCache(Vehicle *v)
+{
+	uint max_speed = GetVehicleProperty(v, 0x0C, 0);
+	if (max_speed != 0) {
+		/* Convert from original units to (approx) km/h */
+		max_speed = (max_speed * 129) / 10;
+
+		v->u.air.cached_max_speed = max_speed;
+	} else {
+		v->u.air.cached_max_speed = 0xFFFF;
+	}
+}
+
+
 /**
  * Special velocities for aircraft
  */
@@ -885,6 +902,11 @@
 	uint spd = v->acceleration * 16;
 	byte t;
 
+	if (v->u.air.cached_max_speed < speed_limit) {
+		if (v->cur_speed < speed_limit) hard_limit = false;
+		speed_limit = v->u.air.cached_max_speed;
+	}
+
 	speed_limit = min(speed_limit, v->max_speed);
 
 	v->subspeed = (t=v->subspeed) + (byte)spd;
@@ -1856,8 +1878,10 @@
 	/* we have arrived in an important state (eg terminal, hangar, etc.) */
 	if (current->heading == v->u.air.state) {
 		byte prev_pos = v->u.air.pos; // location could be changed in state, so save it before-hand
+		byte prev_state = v->u.air.state;
 		_aircraft_state_handlers[v->u.air.state](v, apc);
 		if (v->u.air.state != FLYING) v->u.air.previous_pos = prev_pos;
+		if (v->u.air.state != prev_state) UpdateAircraftCache(v);
 		return true;
 	}
 
--- a/src/newgrf_callbacks.h	Wed Apr 18 18:20:31 2007 +0000
+++ b/src/newgrf_callbacks.h	Wed Apr 18 18:37:40 2007 +0000
@@ -133,6 +133,10 @@
 	/* Called monthly on production changes, so it can be adjusted more frequently */
 	CBID_INDUSTRY_MONTHLYPROD_CHANGE= 0x35, // not yet implemented
 
+	/* Called to modify various vehicle properties. Callback parameter 1
+	 * specifies the property index, as used in Action 0, to change. */
+	CBID_VEHICLE_MODIFY_PROPERTY    = 0x36,
+
 	/* Called to determine text to display after cargo name */
 	CBID_INDUSTRY_CARGO_SUFFIX      = 0x37, // not yet implemented
 
--- a/src/newgrf_engine.cpp	Wed Apr 18 18:20:31 2007 +0000
+++ b/src/newgrf_engine.cpp	Wed Apr 18 18:37:40 2007 +0000
@@ -935,6 +935,17 @@
 	return group->g.callback.result;
 }
 
+
+/* Callback 36 handler */
+uint GetVehicleProperty(const Vehicle *v, uint8 property, uint orig_value)
+{
+	uint16 callback = GetVehicleCallback(CBID_VEHICLE_MODIFY_PROPERTY, property, 0, v->engine_type, v);
+	if (callback != CALLBACK_FAILED) return callback;
+
+	return orig_value;
+}
+
+
 static void DoTriggerVehicle(Vehicle *v, VehicleTrigger trigger, byte base_random_bits, bool first)
 {
 	const SpriteGroup *group;
--- a/src/newgrf_engine.h	Wed Apr 18 18:20:31 2007 +0000
+++ b/src/newgrf_engine.h	Wed Apr 18 18:37:40 2007 +0000
@@ -35,6 +35,10 @@
 #define GetCustomVehicleSprite(v, direction) GetCustomEngineSprite(v->engine_type, v, direction)
 #define GetCustomVehicleIcon(et, direction) GetCustomEngineSprite(et, NULL, direction)
 
+/* Handler to Evaluate callback 36. If the callback fails (i.e. most of the
+ * time) orig_value is returned */
+uint GetVehicleProperty(const Vehicle *v, uint8 property, uint orig_value);
+
 enum VehicleTrigger {
 	VEHICLE_TRIGGER_NEW_CARGO     = 1,
 	/* Externally triggered only for the first vehicle in chain */
--- a/src/ship_cmd.cpp	Wed Apr 18 18:20:31 2007 +0000
+++ b/src/ship_cmd.cpp	Wed Apr 18 18:37:40 2007 +0000
@@ -406,7 +406,7 @@
 	uint spd;
 	byte t;
 
-	spd = min(v->cur_speed + 1, v->max_speed);
+	spd = min(v->cur_speed + 1, GetVehicleProperty(v, 0x0B, v->max_speed));
 
 	/*updates statusbar only if speed have changed to save CPU time */
 	if (spd != v->cur_speed) {
--- a/src/train_cmd.cpp	Wed Apr 18 18:20:31 2007 +0000
+++ b/src/train_cmd.cpp	Wed Apr 18 18:37:40 2007 +0000
@@ -63,7 +63,7 @@
  */
 void TrainPowerChanged(Vehicle* v)
 {
-	uint32 power = 0;
+	uint32 total_power = 0;
 	uint32 max_te = 0;
 
 	for (const Vehicle *u = v; u != NULL; u = u->next) {
@@ -76,19 +76,22 @@
 
 		const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
 
-		if (engine_has_power && rvi_u->power != 0) {
-			power += rvi_u->power;
-			/* Tractive effort in (tonnes * 1000 * 10 =) N */
-			max_te += (u->u.rail.cached_veh_weight * 10000 * rvi_u->tractive_effort) / 256;
+		if (engine_has_power) {
+			uint16 power = GetVehicleProperty(u, 0x0B, rvi_u->power);
+			if (power != 0) {
+				total_power += power;
+				/* Tractive effort in (tonnes * 1000 * 10 =) N */
+				max_te += (u->u.rail.cached_veh_weight * 10000 * GetVehicleProperty(u, 0x1F, rvi_u->tractive_effort)) / 256;
+			}
 		}
 
 		if (HASBIT(u->u.rail.flags, VRF_POWEREDWAGON) && (wagon_has_power)) {
-			power += RailVehInfo(u->u.rail.first_engine)->pow_wag_power;
+			total_power += RailVehInfo(u->u.rail.first_engine)->pow_wag_power;
 		}
 	}
 
-	if (v->u.rail.cached_power != power || v->u.rail.cached_max_te != max_te) {
-		v->u.rail.cached_power = power;
+	if (v->u.rail.cached_power != total_power || v->u.rail.cached_max_te != max_te) {
+		v->u.rail.cached_power = total_power;
 		v->u.rail.cached_max_te = max_te;
 		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
@@ -208,9 +211,10 @@
 			}
 
 			/* max speed is the minimum of the speed limits of all vehicles in the consist */
-			if ((rvi_u->railveh_type != RAILVEH_WAGON || _patches.wagon_speed_limits) &&
-				rvi_u->max_speed != 0 && !UsesWagonOverride(u))
-				max_speed = min(rvi_u->max_speed, max_speed);
+			if ((rvi_u->railveh_type != RAILVEH_WAGON || _patches.wagon_speed_limits) && !UsesWagonOverride(u)) {
+				uint16 speed = GetVehicleProperty(u, 0x09, rvi_u->max_speed);
+				if (speed != 0) max_speed = min(speed, max_speed);
+			}
 		}
 
 		/* check the vehicle length (callback) */
@@ -3473,8 +3477,11 @@
 
 	do {
 		const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
-		if (rvi->running_cost_base > 0)
-			cost += rvi->running_cost_base * _price.running_rail[rvi->running_cost_class];
+
+		byte cost_factor = GetVehicleProperty(v, 0x0D, rvi->running_cost_base);
+		if (cost_factor == 0) continue;
+
+		cost += cost_factor * _price.running_rail[rvi->running_cost_class];
 	} while ((v = GetNextVehicle(v)) != NULL);
 
 	return cost;
--- a/src/vehicle.cpp	Wed Apr 18 18:20:31 2007 +0000
+++ b/src/vehicle.cpp	Wed Apr 18 18:37:40 2007 +0000
@@ -251,6 +251,8 @@
 						Vehicle *rotor = shadow->next;
 						rotor->cur_image = GetRotorImage(v);
 					}
+
+					UpdateAircraftCache(v);
 				}
 				break;
 			default: break;
--- a/src/vehicle.h	Wed Apr 18 18:20:31 2007 +0000
+++ b/src/vehicle.h	Wed Apr 18 18:37:40 2007 +0000
@@ -166,6 +166,7 @@
 
 struct VehicleAir {
 	uint16 crashed_counter;
+	uint16 cached_max_speed;
 	byte pos;
 	byte previous_pos;
 	StationID targetairport;