changeset 13049:adea29ba4429 draft

(svn r17547) -Feature: [NewGRF] Implement callback 145 (custom station rating)
author rubidium <rubidium@openttd.org>
date Tue, 15 Sep 2009 17:24:18 +0000
parents f9399c64435f
children 5cade6728298
files src/newgrf_callbacks.h src/station_cmd.cpp
diffstat 2 files changed, 45 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/src/newgrf_callbacks.h
+++ b/src/newgrf_callbacks.h
@@ -192,7 +192,7 @@
 	CBID_SOUNDS_AMBIENT_EFFECT           = 0x144, // 15 bit callback, not implemented
 
 	/** Called to calculate part of a station rating. */
-	CBID_CARGO_STATION_RATING_CALC       = 0x145, // 15 bit callback, not implemented
+	CBID_CARGO_STATION_RATING_CALC       = 0x145, // 15 bit callback
 
 	/** Allow signal sprites to be replaced dynamically. */
 	CBID_NEW_SIGNALS_SPRITE_DRAW         = 0x146, // 15 bit callback, not implemented
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -2727,8 +2727,9 @@
 	byte_inc_sat(&st->time_since_load);
 	byte_inc_sat(&st->time_since_unload);
 
-	GoodsEntry *ge = st->goods;
-	do {
+	const CargoSpec *cs;
+	FOR_ALL_CARGOSPECS(cs) {
+		GoodsEntry *ge = &st->goods[cs->Index()];
 		/* Slowly increase the rating back to his original level in the case we
 		 *  didn't deliver cargo yet to this station. This happens when a bribe
 		 *  failed while you didn't moved that cargo yet to a station. */
@@ -2740,25 +2741,35 @@
 		if (HasBit(ge->acceptance_pickup, GoodsEntry::PICKUP)) {
 			byte_inc_sat(&ge->days_since_pickup);
 
+			bool skip = false;
 			int rating = 0;
-
-			{
-				int b = ge->last_speed - 85;
-				if (b >= 0)
-					rating += b >> 2;
+			uint waiting = ge->cargo.Count();
+
+			if (HasBit(cs->callback_mask, CBM_CARGO_STATION_RATING_CALC)) {
+				/* Perform custom station rating. If it succeeds the speed, days in transit and
+				 * waiting cargo ratings must not be executed. */
+
+				/* NewGRFs expect last speed to be 0xFF when no vehicle has arrived yet. */
+				uint last_speed = ge->last_speed;
+				if (last_speed == 0) last_speed = 0xFF;
+
+				uint32 var18 = min(ge->days_since_pickup, 0xFF) | (min(waiting, 0xFFFF) << 8) | (min(last_speed, 0xFF) << 24);
+				/* Convert to the 'old' vehicle types */
+				uint32 var10 = (st->last_vehicle_type == VEH_INVALID) ? 0x0 : (st->last_vehicle_type + 0x10);
+				uint16 callback = GetCargoCallback(CBID_CARGO_STATION_RATING_CALC, var10, var18, cs);
+				if (callback != CALLBACK_FAILED) {
+					skip = true;
+					rating = GB(callback, 0, 14);
+
+					/* Simulate a 15 bit signed value */
+					if (HasBit(callback, 14)) rating -= 0x4000;
+				}
 			}
 
-			{
-				byte age = ge->last_age;
-				(age >= 3) ||
-				(rating += 10, age >= 2) ||
-				(rating += 10, age >= 1) ||
-				(rating += 13, true);
-			}
-
-			if (Company::IsValidID(st->owner) && HasBit(st->town->statues, st->owner)) rating += 26;
-
-			{
+			if (!skip) {
+				int b = ge->last_speed - 85;
+				if (b >= 0) rating += b >> 2;
+
 				byte days = ge->days_since_pickup;
 				if (st->last_vehicle_type == VEH_SHIP) days >>= 2;
 				(days > 21) ||
@@ -2766,15 +2777,22 @@
 				(rating += 25, days > 6) ||
 				(rating += 45, days > 3) ||
 				(rating += 35, true);
+
+				(rating -= 90, waiting > 1500) ||
+				(rating += 55, waiting > 1000) ||
+				(rating += 35, waiting > 600) ||
+				(rating += 10, waiting > 300) ||
+				(rating += 20, waiting > 100) ||
+				(rating += 10, true);
 			}
 
-			uint waiting = ge->cargo.Count();
-			(rating -= 90, waiting > 1500) ||
-			(rating += 55, waiting > 1000) ||
-			(rating += 35, waiting > 600) ||
-			(rating += 10, waiting > 300) ||
-			(rating += 20, waiting > 100) ||
-			(rating += 10, true);
+			if (Company::IsValidID(st->owner) && HasBit(st->town->statues, st->owner)) rating += 26;
+
+			byte age = ge->last_age;
+			(age >= 3) ||
+			(rating += 10, age >= 2) ||
+			(rating += 10, age >= 1) ||
+			(rating += 13, true);
 
 			{
 				int or_ = ge->rating; // old rating
@@ -2819,7 +2837,7 @@
 				if (waiting_changed) ge->cargo.Truncate(waiting);
 			}
 		}
-	} while (++ge != endof(st->goods));
+	}
 
 	StationID index = st->index;
 	if (waiting_changed) {