Changeset - r7958:7816b05b15ac
[Not reviewed]
master
0 1 0
rubidium - 17 years ago 2007-11-24 14:03:47
rubidium@openttd.org
(svn r11514) -Change: implement the automatic multiplier handler for NewGRF industries.
1 file changed with 9 insertions and 3 deletions:
0 comments (0 inline, 0 general)
src/newgrf_industries.cpp
Show inline comments
 
@@ -180,49 +180,53 @@ static uint32 GetCountAndDistanceOfClose
 
		}
 
	}
 

	
 
	return count << 16 | GB(closest_dist, 0, 16);
 
}
 

	
 
/** This function implements the industries variables that newGRF defines.
 
 * @param variable that is queried
 
 * @param parameter unused
 
 * @param available will return false if ever the variable asked for does not exist
 
 * @param ind is of course the industry we are inquiring
 
 * @return the value stored in the corresponding variable*/
 
uint32 IndustryGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available)
 
{
 
	const Industry *industry = object->u.industry.ind;
 
	TileIndex tile = object->u.industry.tile;
 
	const IndustrySpec *indspec = GetIndustrySpec(industry->type);
 

	
 
	switch (variable) {
 
		case 0x40:
 
		case 0x41:
 
		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 min(industry->incoming_cargo_waiting[variable - 0x40], (uint16)0xFFFF);
 
				if ((indspec->behaviour & INDUSTRYBEH_PROD_MULTI_HNDLING) != 0) {
 
					return min(industry->incoming_cargo_waiting[variable - 0x40] / industry->prod_level, (uint16)0xFFFF);
 
				} else {
 
					return min(industry->incoming_cargo_waiting[variable - 0x40], (uint16)0xFFFF);
 
				}
 
			} else {
 
				return 0;
 
			}
 
		}
 

	
 
		/* Manhattan distance of closes dry/water tile */
 
		case 0x43: return GetClosestWaterDistance(tile, (indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) == 0);
 

	
 
		/* Layout number */
 
		case 0x44: return industry->selected_layout;
 

	
 
		/* player info */
 
		case 0x45: {
 
			byte colours;
 
			bool is_ai = false;
 

	
 
			if (IsValidPlayer(industry->founder)) {
 
				const Player *p = GetPlayer(industry->founder);
 
				const Livery *l = &p->livery[LS_DEFAULT];
 

	
 
				is_ai = p->is_ai;
 
				colours = l->colour1 + l->colour2 * 16;
 
			} else {
 
				colours = GB(Random(), 0, 8);
 
@@ -484,62 +488,64 @@ bool CheckIfCallBackAllowsAvailability(I
 
		uint16 res = GetIndustryCallback(CBID_INDUSTRY_AVAILABLE, 0, creation_type, NULL, type, INVALID_TILE);
 
		if (res != CALLBACK_FAILED) {
 
			return (res == 0);
 
		}
 
	}
 
	return true;
 
}
 

	
 
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)
 
{
 
	const IndustrySpec *spec = GetIndustrySpec(ind->type);
 
	ResolverObject object;
 
	NewIndustryResolver(&object, ind->xy, ind);
 
	if ((spec->behaviour & INDUSTRYBEH_PRODCALLBACK_RANDOM) != 0) object.callback_param1 = Random();
 
	int multiplier = 1;
 
	if ((spec->behaviour & INDUSTRYBEH_PROD_MULTI_HNDLING) != 0) multiplier = ind->prod_level;
 
	object.callback_param2 = reason;
 

	
 
	for (uint loop = 0;; loop++) {
 
		SB(object.callback_param2, 8, 16, loop);
 
		const SpriteGroup *group = Resolve(spec->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);
 
			ind->incoming_cargo_waiting[i] = Clamp(ind->incoming_cargo_waiting[i] - DerefIndProd(group->g.indprod.substract_input[i], deref) * multiplier, 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);
 
			ind->produced_cargo_waiting[i] = Clamp(ind->produced_cargo_waiting[i] + max(DerefIndProd(group->g.indprod.add_output[i], deref), 0) * multiplier, 0, 0xFFFF);
 
		}
 

	
 
		int32 again = DerefIndProd(group->g.indprod.again, deref);
 
		if (again == 0) break;
 

	
 
		SB(object.callback_param2, 24, 8, again);
 
	}
 

	
 
	InvalidateWindow(WC_INDUSTRY_VIEW, ind->index);
 
}
 

	
 
void DoTriggerIndustry(Industry *ind, IndustryTileTrigger trigger)
 
{
 
	ResolverObject object;
 

	
 
	NewIndustryResolver(&object, ind->xy, ind);
 
	object.callback = CBID_RANDOM_TRIGGER;
 
	object.trigger = trigger;
 

	
 
	const SpriteGroup *group = Resolve(GetIndustrySpec(ind->type)->grf_prop.spritegroup, &object);
 
	if (group == NULL) return;
 

	
 
	byte new_random_bits = Random();
 
	ind->random &= ~object.reseed;
0 comments (0 inline, 0 general)