changeset 7168:f0216e74951d draft

(svn r10442) -Codechange: implement the industry production callback.
author rubidium <rubidium@openttd.org>
date Thu, 05 Jul 2007 05:41:56 +0000
parents 8cb30c91ffd4
children bb0d45d67816
files src/economy.cpp src/industry_cmd.cpp src/newgrf.cpp src/newgrf_industries.cpp src/newgrf_industries.h src/newgrf_spritegroup.cpp src/newgrf_spritegroup.h
diffstat 7 files changed, 96 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/economy.cpp
+++ b/src/economy.cpp
@@ -35,6 +35,7 @@
 #include "newgrf_engine.h"
 #include "newgrf_sound.h"
 #include "newgrf_callbacks.h"
+#include "newgrf_industries.h"
 #include "unmovable.h"
 #include "date.h"
 #include "cargotype.h"
@@ -1239,7 +1240,7 @@
 
 		if (HASBIT(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HASBIT(callback, CBM_IND_PRODUCTION_256_TICKS)) {
 			best->incoming_cargo_waiting[accepted_cargo_index] = min(num_pieces + best->incoming_cargo_waiting[accepted_cargo_index], 0xFFFF);
-			if (HASBIT(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) {} ///< @todo Perform some magic
+			if (HASBIT(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) IndustryProductionCallback(ind, 0);
 		} else {
 			best->produced_cargo_waiting[0] = min(best->produced_cargo_waiting[0] + (num_pieces * indspec->input_cargo_multiplier[accepted_cargo_index][0] / 256), 0xFFFF);
 			best->produced_cargo_waiting[1] = min(best->produced_cargo_waiting[1] + (num_pieces * indspec->input_cargo_multiplier[accepted_cargo_index][1] / 256), 0xFFFF);
--- a/src/industry_cmd.cpp
+++ b/src/industry_cmd.cpp
@@ -30,6 +30,7 @@
 #include "water_map.h"
 #include "tree_map.h"
 #include "cargotype.h"
+#include "newgrf_industries.h"
 #include "newgrf_industrytiles.h"
 #include "newgrf_callbacks.h"
 
@@ -965,6 +966,8 @@
 
 	/* produce some cargo */
 	if ((i->counter & 0xFF) == 0) {
+		if (HASBIT(indsp->callback_flags, CBM_IND_PRODUCTION_256_TICKS)) IndustryProductionCallback(i, 1);
+
 		IndustyBehaviour indbehav = indsp->behaviour;
 		i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + i->production_rate[0]);
 		i->produced_cargo_waiting[1] = min(0xffff, i->produced_cargo_waiting[1] + i->production_rate[1]);
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -2287,6 +2287,35 @@
 					break;
 				}
 
+				case GSF_INDUSTRIES: {
+					if (type > 1) {
+						grfmsg(1, "NewSpriteGroup: Unsupported industry production version %d, skipping", type);
+						break;
+					}
+
+					group = AllocateSpriteGroup();
+					group->type = SGT_INDUSTRY_PRODUCTION;
+					group->g.indprod.version = type;
+					if (type == 0) {
+						for (uint i = 0; i < 3; i++) {
+							group->g.indprod.substract_input[i] = grf_load_word(&buf);
+						}
+						for (uint i = 0; i < 2; i++) {
+							group->g.indprod.add_output[i] = grf_load_word(&buf);
+						}
+						group->g.indprod.again = grf_load_byte(&buf);
+					} else {
+						for (uint i = 0; i < 3; i++) {
+							group->g.indprod.substract_input[i] = grf_load_byte(&buf);
+						}
+						for (uint i = 0; i < 2; i++) {
+							group->g.indprod.add_output[i] = grf_load_byte(&buf);
+						}
+						group->g.indprod.again = grf_load_byte(&buf);
+					}
+					break;
+				}
+
 				/* Loading of Tile Layout and Production Callback groups would happen here */
 				default: grfmsg(1, "NewSpriteGroup: Unsupported feature %d, skipping", feature);
 			}
--- a/src/newgrf_industries.cpp
+++ b/src/newgrf_industries.cpp
@@ -124,7 +124,7 @@
 		case 0x42: { // waiting cargo, but only if those two callback flags are set
 			uint16 callback = indspec->callback_flags;
 			if (HASBIT(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HASBIT(callback, CBM_IND_PRODUCTION_256_TICKS)) {
-				return max(industry->incoming_cargo_waiting[variable - 0x40], (uint16)0x7FFF);
+				return max(industry->incoming_cargo_waiting[variable - 0x40], (uint16)0xFFFF);
 			} else {
 				return 0;
 			}
@@ -263,3 +263,40 @@
 
 	return group->g.callback.result;
 }
+
+static int32 DerefIndProd(uint field, bool use_register)
+{
+	return use_register ? (int32)GetRegister(field) : field;
+}
+
+/**
+ * Get the industry production callback and apply it to the industry.
+ * @param ind    the industry this callback has to be called for
+ * @param reason the reason it is called (0 = incoming cargo, 1 = periodic tick callback)
+ */
+void IndustryProductionCallback(Industry *ind, int reason)
+{
+	ResolverObject object;
+	NewIndustryResolver(&object, INVALID_TILE, ind);
+	object.callback_param2 = reason;
+
+	for (uint loop = 0;; loop++) {
+		SB(object.callback_param2, 8, 16, loop);
+		const SpriteGroup *group = Resolve(GetIndustrySpec(ind->type)->grf_prop.spritegroup, &object);
+		if (group == NULL || group->type != SGT_INDUSTRY_PRODUCTION) break;
+
+		bool deref = (group->g.indprod.version == 1);
+
+		for (uint i = 0; i < 3; i++) {
+			ind->incoming_cargo_waiting[i] = clamp(ind->incoming_cargo_waiting[i] - DerefIndProd(group->g.indprod.substract_input[i], deref), 0, 0xFFFF);
+		}
+		for (uint i = 0; i < 2; i++) {
+			ind->produced_cargo_waiting[i] = clamp(ind->produced_cargo_waiting[i] + DerefIndProd(group->g.indprod.add_output[i], deref), 0, 0xFFFF);
+		}
+
+		int32 again = DerefIndProd(group->g.indprod.again, deref);
+		if (again == 0) break;
+
+		SB(object.callback_param2, 24, 8, again);
+	}
+}
--- a/src/newgrf_industries.h
+++ b/src/newgrf_industries.h
@@ -12,6 +12,7 @@
 uint32 IndustryGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available);
 uint16 GetIndustryCallback(uint16 callback, uint32 param1, uint32 param2, Industry *industry, IndustryType type, TileIndex tile);
 uint32 GetIndustryIDAtOffset(TileIndex new_tile, TileIndex old_tile, const Industry *i);
+void IndustryProductionCallback(Industry *ind, int reason);
 
 /* in newgrf_industrytiles.cpp*/
 uint32 IndustryTileGetRandomBits(const ResolverObject *object);
--- a/src/newgrf_spritegroup.cpp
+++ b/src/newgrf_spritegroup.cpp
@@ -76,7 +76,7 @@
 	_spritegroup_count = 0;
 }
 
-static uint32 _temp_store[0x110];
+uint32 _temp_store[0x110];
 
 
 static inline uint32 GetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available)
--- a/src/newgrf_spritegroup.h
+++ b/src/newgrf_spritegroup.h
@@ -8,6 +8,19 @@
 #include "town.h"
 #include "industry.h"
 
+/**
+ * Gets the value of a so-called newgrf "register".
+ * @param i index of the register
+ * @pre i < 0x110
+ * @return the value of the register
+ */
+static inline uint32 GetRegister(uint i)
+{
+	assert(i < 0x110);
+	extern uint32 _temp_store[0x110];
+	return _temp_store[i];
+}
+
 struct SpriteGroup;
 
 
@@ -135,6 +148,13 @@
 	struct DrawTileSprites *dts;
 };
 
+struct IndustryProductionSpriteGroup {
+	uint8 version;
+	uint16 substract_input[3];
+	uint16 add_output[2];
+	uint8 again;
+};
+
 /* List of different sprite group types */
 enum SpriteGroupType {
 	SGT_INVALID,
@@ -144,6 +164,7 @@
 	SGT_CALLBACK,
 	SGT_RESULT,
 	SGT_TILELAYOUT,
+	SGT_INDUSTRY_PRODUCTION,
 };
 
 /* Common wrapper for all the different sprite group types */
@@ -157,6 +178,7 @@
 		CallbackResultSpriteGroup callback;
 		ResultSpriteGroup result;
 		TileLayoutSpriteGroup layout;
+		IndustryProductionSpriteGroup indprod;
 	} g;
 };