src/newgrf_engine.cpp
branchNewGRF_ports
changeset 6719 4cc327ad39d5
parent 6715 ce1614834bc3
child 6720 35756db7e577
--- a/src/newgrf_engine.cpp	Tue Mar 27 23:27:27 2007 +0000
+++ b/src/newgrf_engine.cpp	Sat Jun 02 19:59:29 2007 +0000
@@ -64,22 +64,22 @@
 	memcpy(wo->train_id, train_id, trains);
 }
 
-static const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, byte overriding_engine)
+const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, byte overriding_engine)
 {
 	const WagonOverrides *wos = &_engine_wagon_overrides[engine];
-	int i;
 
 	/* XXX: This could turn out to be a timesink on profiles. We could
 	 * always just dedicate 65535 bytes for an [engine][train] trampoline
 	 * for O(1). Or O(logMlogN) and searching binary tree or smt. like
 	 * that. --pasky */
 
-	for (i = 0; i < wos->overrides_count; i++) {
+	for (int i = 0; i < wos->overrides_count; i++) {
 		const WagonOverride *wo = &wos->overrides[i];
-		int j;
 
-		for (j = 0; j < wo->trains; j++) {
-			if (wo->train_id[j] == overriding_engine && (wo->cargo == cargo || wo->cargo == CT_DEFAULT)) return wo->group;
+		if (wo->cargo != cargo && wo->cargo != CT_DEFAULT) continue;
+
+		for (int j = 0; j < wo->trains; j++) {
+			if (wo->train_id[j] == overriding_engine) return wo->group;
 		}
 	}
 	return NULL;
@@ -247,7 +247,7 @@
 {
 	const Station *st = GetStation(v->u.air.targetairport);
 	const AirportFTAClass *afc = st->Airport();
-	byte amdflag = afc->MovingData(v->u.air.pos)->flag;
+	uint16 amdflag = afc->MovingData(v->u.air.pos)->flag;
 
 	switch (v->u.air.state) {
 		case HANGAR:
@@ -318,7 +318,7 @@
 			}
 
 		case FLYING:
-			return AMS_TTDP_FLIGHT_TO_TOWER;
+			return amdflag & AMED_HOLD ? AMS_TTDP_FLIGHT_APPROACH : AMS_TTDP_FLIGHT_TO_TOWER;
 
 		case LANDING: // Descent
 			return AMS_TTDP_FLIGHT_DESCENT;
@@ -477,6 +477,22 @@
 }
 
 
+static uint8 LiveryHelper(EngineID engine, const Vehicle *v)
+{
+	const Livery *l;
+
+	if (v == NULL) {
+		l = GetEngineLivery(engine, _current_player, INVALID_ENGINE, NULL);
+	} else if (v->type == VEH_TRAIN) {
+		l = GetEngineLivery((v->u.rail.first_engine != INVALID_ENGINE && (IsArticulatedPart(v) || UsesWagonOverride(v))) ? v->u.rail.first_engine : v->engine_type, v->owner, v->u.rail.first_engine, v);
+	} else {
+		l = GetEngineLivery(v->engine_type, v->owner, INVALID_ENGINE, v);
+	}
+
+	return l->colour1 + l->colour2 * 16;
+}
+
+
 static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available)
 {
 	const Vehicle *v = GRV(object);
@@ -484,7 +500,7 @@
 	if (v == NULL) {
 		/* Vehicle does not exist, so we're in a purchase list */
 		switch (variable) {
-			case 0x43: return _current_player; // Owner information
+			case 0x43: return _current_player | (LiveryHelper(object->u.vehicle.self_type, NULL) << 24); // Owner information
 			case 0x46: return 0;               // Motion counter
 			case 0x48: return GetEngine(object->u.vehicle.self_type)->flags; // Vehicle Type Info
 			case 0xC4: return clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; // Build year
@@ -553,7 +569,7 @@
 		}
 
 		case 0x43: // Player information
-			return v->owner;
+			return v->owner | (GetPlayer(v->owner)->is_ai ? 0x10000 : 0) | (LiveryHelper(v->engine_type, v) << 24);
 
 		case 0x44: // Aircraft information
 			if (v->type != VEH_AIRCRAFT) return UINT_MAX;
@@ -582,6 +598,25 @@
 				return (altitude << 8) | airporttype;
 			}
 
+		case 0x45: { // Curvature info
+			/* Format: xxxTxBxF
+			 * F - previous wagon to current wagon, 0 if vehicle is first
+			 * B - current wagon to next wagon, 0 if wagon is last
+			 * T - previous wagon to next wagon, 0 in an S-bend
+			 */
+			if (v->type != VEH_TRAIN) return 0;
+
+			const Vehicle *u_p = GetPrevVehicleInChain(v);
+			const Vehicle *u_n = v->next;
+			DirDiff f = (u_p == NULL) ?  DIRDIFF_SAME : DirDifference(u_p->direction, v->direction);
+			DirDiff b = (u_n == NULL) ?  DIRDIFF_SAME : DirDifference(v->direction, u_n->direction);
+			DirDiff t = ChangeDirDiff(f, b);
+
+			return ((t > DIRDIFF_REVERSE ? t | 8 : t) << 16) |
+			       ((b > DIRDIFF_REVERSE ? b | 8 : b) <<  8) |
+			       ( f > DIRDIFF_REVERSE ? f | 8 : f);
+		}
+
 		case 0x46: // Motion counter
 			return v->motion_counter;
 
@@ -744,6 +779,8 @@
 				case 0x66: return MapAircraftMovementAction(v); // Current movement action
 			}
 			break;
+
+		default: break;
 	}
 
 	DEBUG(grf, 1, "Unhandled vehicle property 0x%X, type 0x%X", variable, v->type);
@@ -824,8 +861,7 @@
 		cargo = v->cargo_type;
 
 		if (v->type == VEH_TRAIN) {
-			group = GetWagonOverrideSpriteSet(engine, cargo, v->u.rail.first_engine);
-
+			group = v->u.rail.cached_override;
 			if (group != NULL) return group;
 		}
 	}
@@ -886,7 +922,7 @@
 bool UsesWagonOverride(const Vehicle* v)
 {
 	assert(v->type == VEH_TRAIN);
-	return GetWagonOverrideSpriteSet(v->engine_type, v->cargo_type, v->u.rail.first_engine) != NULL;
+	return v->u.rail.cached_override != NULL;
 }
 
 /**
@@ -895,7 +931,7 @@
  * @param param1   First parameter of the callback
  * @param param2   Second parameter of the callback
  * @param engine   Engine type of the vehicle to evaluate the callback for
- * @param vehicle  The vehicle to evaluate the callback for, or NULL if it doesnt exist yet
+ * @param v        The vehicle to evaluate the callback for, or NULL if it doesnt exist yet
  * @return The value the callback returned, or CALLBACK_FAILED if it failed
  */
 uint16 GetVehicleCallback(uint16 callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v)
@@ -944,6 +980,26 @@
 	return group->g.callback.result;
 }
 
+
+/* Callback 36 handlers */
+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;
+}
+
+
+uint GetEngineProperty(EngineID engine, uint8 property, uint orig_value)
+{
+	uint16 callback = GetVehicleCallback(CBID_VEHICLE_MODIFY_PROPERTY, property, 0, engine, NULL);
+	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;