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
 
@@ -156,97 +156,101 @@ static uint32 GetCountAndDistanceOfClose
 
		case 0xFFFFFFFF: // current grf
 
			GrfID = GetIndustrySpec(current->type)->grf_prop.grffile->grfid;
 
			/* Fall through */
 

	
 
		default: //use the grfid specified in register 100h
 
			SetBit(param_setID, 7); // bit 7 means it is not an old type
 
			ind_index = MapNewGRFIndustryType(param_setID, GrfID);
 
			break;
 
	}
 

	
 
	if (layout_filter == 0) {
 
		/* If the filter is 0, it could be because none was specified as well as being really a 0.
 
		 * In either case, just do the regular var67 */
 
		closest_dist = GetClosestIndustry(current->xy, ind_index, current);
 
		count = GetIndustryTypeCount(ind_index);
 
	} else {
 
		/* Count only those who match the same industry type and layout filter
 
		 * Unfortunately, we have to do it manually */
 
		const Industry *i;
 
		FOR_ALL_INDUSTRIES(i) {
 
			if (i->type == ind_index && i != current && i->selected_layout == layout_filter) {
 
				closest_dist = min(closest_dist, DistanceManhattan(current->xy, i->xy));
 
				count++;
 
			}
 
		}
 
	}
 

	
 
	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);
 
			}
 

	
 
			return industry->founder | (is_ai ? 0x10000 : 0) | (colours << 24);
 
		}
 

	
 
		/* Get industry ID at offset param */
 
		case 0x60: return GetIndustryIDAtOffset(GetNearbyTile(parameter, industry->xy), industry);
 

	
 
		/* Get random tile bits at offset param */
 
		case 0x61:
 
			tile = GetNearbyTile(parameter, tile);
 
			return (IsTileType(tile, MP_INDUSTRY) && GetIndustryByTile(tile) == industry) ? GetIndustryRandomBits(tile) : 0;
 

	
 
		/* Land info of nearby tiles */
 
		case 0x62: return GetNearbyIndustryTileInformation(parameter, tile, INVALID_INDUSTRY);
 

	
 
		/* Animation stage of nearby tiles */
 
		case 0x63:
 
			tile = GetNearbyTile(parameter, tile);
 
			if (IsTileType(tile, MP_INDUSTRY) && GetIndustryByTile(tile) == industry) {
 
				return GetIndustryAnimationState(tile);
 
			}
 
			return 0xFFFFFFFF;
 

	
 
@@ -460,88 +464,90 @@ bool CheckIfCallBackAllowsCreation(TileI
 
	 * the building of the industry, as that's how it's done in TTDP. */
 
	if (group == NULL || group->type != SGT_CALLBACK) return true;
 

	
 
	/* Copy some parameters from the registers to the error message text ref. stack */
 
	SwitchToErrorRefStack();
 
	PrepareTextRefStackUsage(4);
 
	SwitchToNormalRefStack();
 

	
 
	switch (group->g.callback.result) {
 
		case 0x400: return true;
 
		case 0x401: _error_message = STR_0239_SITE_UNSUITABLE; break;
 
		case 0x402: _error_message = STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST; break;
 
		case 0x403: _error_message = STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT; break;
 
		default: _error_message = GetGRFStringID(indspec->grf_prop.grffile->grfid, 0xD000 + group->g.callback.result); break;
 
	}
 

	
 
	return false;
 
}
 

	
 
bool CheckIfCallBackAllowsAvailability(IndustryType type, IndustryAvailabilityCallType creation_type)
 
{
 
	const IndustrySpec *indspec = GetIndustrySpec(type);
 

	
 
	if (HasBit(indspec->callback_flags, CBM_IND_AVAILABLE)) {
 
		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;
 
	ind->random |= new_random_bits & object.reseed;
 
}
0 comments (0 inline, 0 general)