src/newgrf_house.cpp
branchgamebalance
changeset 9911 0b8b245a2391
parent 9908 0fa543611bbe
child 9912 1ac8aac92385
equal deleted inserted replaced
9910:0b2aebc8283e 9911:0b8b245a2391
    22 #include "newgrf_house.h"
    22 #include "newgrf_house.h"
    23 #include "newgrf_spritegroup.h"
    23 #include "newgrf_spritegroup.h"
    24 #include "newgrf_callbacks.h"
    24 #include "newgrf_callbacks.h"
    25 #include "newgrf_town.h"
    25 #include "newgrf_town.h"
    26 #include "newgrf_sound.h"
    26 #include "newgrf_sound.h"
       
    27 #include "newgrf_commons.h"
    27 
    28 
    28 static BuildingCounts    _building_counts;
    29 static BuildingCounts    _building_counts;
    29 static HouseClassMapping _class_mapping[HOUSE_CLASS_MAX];
    30 static HouseClassMapping _class_mapping[HOUSE_CLASS_MAX];
    30 HouseIDMapping _house_id_mapping[HOUSE_MAX];
    31 
    31 
    32 HouseOverrideManager _house_mngr(NEW_HOUSE_OFFSET, HOUSE_MAX, INVALID_HOUSE_ID);
    32 /* Since the house IDs defined by the GRF file don't necessarily correlate
       
    33  * to those used by the game, the IDs used for overriding old houses must be
       
    34  * translated when the house spec is set. */
       
    35 static uint16 _house_overrides[NEW_HOUSE_OFFSET];
       
    36 
       
    37 void AddHouseOverride(uint8 local_id, uint house_type)
       
    38 {
       
    39 	assert(house_type < NEW_HOUSE_OFFSET);
       
    40 	_house_overrides[house_type] = local_id;
       
    41 }
       
    42 
       
    43 void ResetHouseOverrides()
       
    44 {
       
    45 	for (int i = 0; i != lengthof(_house_overrides); i++) {
       
    46 		_house_overrides[i] = INVALID_HOUSE_ID;
       
    47 	}
       
    48 }
       
    49 
       
    50 static HouseID GetHouseID(byte grf_local_id, uint32 grfid)
       
    51 {
       
    52 	const HouseIDMapping *map;
       
    53 
       
    54 	for (HouseID house_id = NEW_HOUSE_OFFSET; house_id != lengthof(_house_id_mapping); house_id++) {
       
    55 		map = &_house_id_mapping[house_id];
       
    56 		if (map->house_id == grf_local_id && map->grfid == grfid) return house_id;
       
    57 	}
       
    58 	return INVALID_HOUSE_ID;
       
    59 }
       
    60 
       
    61 static HouseID AddHouseID(byte grf_local_id, uint32 grfid, byte substitute_id)
       
    62 {
       
    63 	HouseID house_id;
       
    64 	HouseIDMapping *map;
       
    65 
       
    66 	/* Look to see if this house has already been added. This is done
       
    67 	 * separately from the loop below in case a GRF has been deleted, and there
       
    68 	 * are any gaps in the array. */
       
    69 	house_id = GetHouseID(grf_local_id, grfid);
       
    70 	if (house_id != INVALID_HOUSE_ID) return house_id;
       
    71 
       
    72 	/* This house hasn't been defined before, so give it an ID now. */
       
    73 	for (house_id = NEW_HOUSE_OFFSET; house_id != lengthof(_house_id_mapping); house_id++) {
       
    74 		map = &_house_id_mapping[house_id];
       
    75 
       
    76 		if (map->house_id == 0 && map->grfid == 0) {
       
    77 			map->house_id      = grf_local_id;
       
    78 			map->grfid         = grfid;
       
    79 			map->substitute_id = substitute_id;
       
    80 			return house_id;
       
    81 		}
       
    82 	}
       
    83 
       
    84 	return INVALID_HOUSE_ID;
       
    85 }
       
    86 
       
    87 void SetHouseSpec(const HouseSpec *hs)
       
    88 {
       
    89 	HouseID house_id = AddHouseID(hs->local_id, hs->grffile->grfid, hs->substitute_id);
       
    90 
       
    91 	if (house_id == INVALID_HOUSE_ID) {
       
    92 		grfmsg(1, "SetHouseSpec: Too many houses allocated. Ignoring.");
       
    93 		return;
       
    94 	}
       
    95 
       
    96 	memcpy(&_house_specs[house_id], hs, sizeof(*hs));
       
    97 
       
    98 	/* Now add the overrides. */
       
    99 	for (int i = 0; i != lengthof(_house_overrides); i++) {
       
   100 		HouseSpec *overridden_hs = GetHouseSpecs(i);
       
   101 
       
   102 		if (_house_overrides[i] != hs->local_id) continue;
       
   103 
       
   104 		overridden_hs->override = house_id;
       
   105 		_house_overrides[i] = INVALID_HOUSE_ID;
       
   106 	}
       
   107 }
       
   108 
       
   109 void ResetHouseIDMapping()
       
   110 {
       
   111 	memset(&_house_id_mapping, 0, sizeof(_house_id_mapping));
       
   112 }
       
   113 
    33 
   114 void CheckHouseIDs()
    34 void CheckHouseIDs()
   115 {
    35 {
   116 	for (TileIndex t = 0; t < MapSize(); t++) {
    36 	for (TileIndex t = 0; t < MapSize(); t++) {
   117 		HouseID house_id;
    37 		HouseID house_id;
   120 
    40 
   121 		house_id = GetHouseType(t);
    41 		house_id = GetHouseType(t);
   122 		if (!GetHouseSpecs(house_id)->enabled && house_id >= NEW_HOUSE_OFFSET) {
    42 		if (!GetHouseSpecs(house_id)->enabled && house_id >= NEW_HOUSE_OFFSET) {
   123 			/* The specs for this type of house are not available any more, so
    43 			/* The specs for this type of house are not available any more, so
   124 			 * replace it with the substitute original house type. */
    44 			 * replace it with the substitute original house type. */
   125 			SetHouseType(t, _house_id_mapping[house_id].substitute_id);
    45 			SetHouseType(t, _house_mngr.GetSubstituteID(house_id));
   126 		}
    46 		}
   127 	}
    47 	}
   128 
    48 
   129 	InitializeBuildingCounts();
    49 	InitializeBuildingCounts();
   130 	AfterLoadCountBuildings();
    50 	AfterLoadCountBuildings();
   311 		/* Building counts for new houses with id = parameter. */
   231 		/* Building counts for new houses with id = parameter. */
   312 		case 0x61: {
   232 		case 0x61: {
   313 			const HouseSpec *hs = GetHouseSpecs(house_id);
   233 			const HouseSpec *hs = GetHouseSpecs(house_id);
   314 			if (hs->grffile == NULL) return 0;
   234 			if (hs->grffile == NULL) return 0;
   315 
   235 
   316 			HouseID new_house = GetHouseID(parameter, hs->grffile->grfid);
   236 			HouseID new_house = _house_mngr.GetID(parameter, hs->grffile->grfid);
   317 			return new_house == INVALID_HOUSE_ID ? 0 : GetNumHouses(new_house, town);
   237 			return new_house == INVALID_HOUSE_ID ? 0 : GetNumHouses(new_house, town);
   318 		}
   238 		}
   319 
   239 
   320 		/* Land info for nearby tiles. */
   240 		/* Land info for nearby tiles. */
   321 		case 0x62: {
   241 		case 0x62: {
   372 	res->last_value      = 0;
   292 	res->last_value      = 0;
   373 	res->trigger         = 0;
   293 	res->trigger         = 0;
   374 	res->reseed          = 0;
   294 	res->reseed          = 0;
   375 }
   295 }
   376 
   296 
   377 uint16 GetHouseCallback(uint16 callback, uint32 param1, HouseID house_id, Town *town, TileIndex tile)
   297 uint16 GetHouseCallback(uint16 callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile)
   378 {
   298 {
   379 	ResolverObject object;
   299 	ResolverObject object;
   380 	const SpriteGroup *group;
   300 	const SpriteGroup *group;
   381 
   301 
   382 	NewHouseResolver(&object, house_id, tile, town);
   302 	NewHouseResolver(&object, house_id, tile, town);
   383 	object.callback = callback;
   303 	object.callback = callback;
   384 	object.callback_param1 = param1;
   304 	object.callback_param1 = param1;
   385 	object.callback_param2 = 0;
   305 	object.callback_param2 = param2;
   386 
   306 
   387 	group = Resolve(GetHouseSpecs(house_id)->spritegroup, &object);
   307 	group = Resolve(GetHouseSpecs(house_id)->spritegroup, &object);
   388 	if (group == NULL || group->type != SGT_CALLBACK) return CALLBACK_FAILED;
   308 	if (group == NULL || group->type != SGT_CALLBACK) return CALLBACK_FAILED;
   389 
   309 
   390 	return group->g.callback.result;
   310 	return group->g.callback.result;
   411 			pal = PALETTE_TO_TRANSPARENT;
   331 			pal = PALETTE_TO_TRANSPARENT;
   412 		} else if (HASBIT(image, PALETTE_MODIFIER_COLOR)) {
   332 		} else if (HASBIT(image, PALETTE_MODIFIER_COLOR)) {
   413 			if (pal == 0) {
   333 			if (pal == 0) {
   414 				const HouseSpec *hs = GetHouseSpecs(house_id);
   334 				const HouseSpec *hs = GetHouseSpecs(house_id);
   415 				if (HASBIT(hs->callback_mask, CBM_BUILDING_COLOUR)) {
   335 				if (HASBIT(hs->callback_mask, CBM_BUILDING_COLOUR)) {
   416 					uint16 callback = GetHouseCallback(CBID_BUILDING_COLOUR, 0, house_id, GetTownByTile(ti->tile), ti->tile);
   336 					uint16 callback = GetHouseCallback(CBID_BUILDING_COLOUR, 0, 0, house_id, GetTownByTile(ti->tile), ti->tile);
   417 					if (callback != CALLBACK_FAILED) {
   337 					if (callback != CALLBACK_FAILED) {
   418 						/* If bit 14 is set, we should use a 2cc colour map, else use the callback value. */
   338 						/* If bit 14 is set, we should use a 2cc colour map, else use the callback value. */
   419 						pal = HASBIT(callback, 14) ? GB(callback, 0, 8) + SPR_2CCMAP_BASE : callback;
   339 						pal = HASBIT(callback, 14) ? GB(callback, 0, 8) + SPR_2CCMAP_BASE : callback;
   420 					}
   340 					}
   421 				} else {
   341 				} else {
   466 	const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
   386 	const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
   467 	byte animation_speed = hs->animation_speed;
   387 	byte animation_speed = hs->animation_speed;
   468 	bool frame_set_by_callback = false;
   388 	bool frame_set_by_callback = false;
   469 
   389 
   470 	if (HASBIT(hs->callback_mask, CBM_ANIMATION_SPEED)) {
   390 	if (HASBIT(hs->callback_mask, CBM_ANIMATION_SPEED)) {
   471 		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_SPEED, 0, GetHouseType(tile), GetTownByTile(tile), tile);
   391 		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_SPEED, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile);
   472 		if (callback_res != CALLBACK_FAILED) animation_speed = clamp(callback_res & 0xFF, 2, 16);
   392 		if (callback_res != CALLBACK_FAILED) animation_speed = clamp(callback_res & 0xFF, 2, 16);
   473 	}
   393 	}
   474 
   394 
   475 	/* An animation speed of 2 means the animation frame changes 4 ticks, and
   395 	/* An animation speed of 2 means the animation frame changes 4 ticks, and
   476 	 * increasing this value by one doubles the wait. 2 is the minimum value
   396 	 * increasing this value by one doubles the wait. 2 is the minimum value
   481 	byte frame      = GetHouseAnimationFrame(tile);
   401 	byte frame      = GetHouseAnimationFrame(tile);
   482 	byte num_frames = GB(hs->animation_frames, 0, 7);
   402 	byte num_frames = GB(hs->animation_frames, 0, 7);
   483 
   403 
   484 	if (HASBIT(hs->callback_mask, CBM_ANIMATION_NEXT_FRAME)) {
   404 	if (HASBIT(hs->callback_mask, CBM_ANIMATION_NEXT_FRAME)) {
   485 		uint32 param = (hs->extra_flags & CALLBACK_1A_RANDOM_BITS) ? Random() : 0;
   405 		uint32 param = (hs->extra_flags & CALLBACK_1A_RANDOM_BITS) ? Random() : 0;
   486 		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_NEXT_FRAME, param, GetHouseType(tile), GetTownByTile(tile), tile);
   406 		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_NEXT_FRAME, param, 0, GetHouseType(tile), GetTownByTile(tile), tile);
   487 
   407 
   488 		if (callback_res != CALLBACK_FAILED) {
   408 		if (callback_res != CALLBACK_FAILED) {
   489 			frame_set_by_callback = true;
   409 			frame_set_by_callback = true;
   490 
   410 
   491 			switch (callback_res & 0xFF) {
   411 			switch (callback_res & 0xFF) {
   547 	 * anyone using the scenario editor. */
   467 	 * anyone using the scenario editor. */
   548 	if ((IsValidPlayer(_current_player) && IsHumanPlayer(_current_player))
   468 	if ((IsValidPlayer(_current_player) && IsHumanPlayer(_current_player))
   549 			|| _current_player == OWNER_WATER || _current_player == OWNER_NONE) return true;
   469 			|| _current_player == OWNER_WATER || _current_player == OWNER_NONE) return true;
   550 
   470 
   551 	if (HASBIT(hs->callback_mask, CBM_HOUSE_DENY_DESTRUCTION)) {
   471 	if (HASBIT(hs->callback_mask, CBM_HOUSE_DENY_DESTRUCTION)) {
   552 		uint16 callback_res = GetHouseCallback(CBID_HOUSE_DENY_DESTRUCTION, 0, GetHouseType(tile), GetTownByTile(tile), tile);
   472 		uint16 callback_res = GetHouseCallback(CBID_HOUSE_DENY_DESTRUCTION, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile);
   553 		return (callback_res == CALLBACK_FAILED || callback_res == 0);
   473 		return (callback_res == CALLBACK_FAILED || callback_res == 0);
   554 	} else {
   474 	} else {
   555 		return !(hs->extra_flags & BUILDING_IS_PROTECTED);
   475 		return !(hs->extra_flags & BUILDING_IS_PROTECTED);
   556 	}
   476 	}
   557 }
   477 }
   560 {
   480 {
   561 	const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
   481 	const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
   562 
   482 
   563 	if (HASBIT(hs->callback_mask, CBM_ANIMATION_START_STOP)) {
   483 	if (HASBIT(hs->callback_mask, CBM_ANIMATION_START_STOP)) {
   564 		uint32 param = (hs->extra_flags & SYNCHRONISED_CALLBACK_1B) ? (GB(Random(), 0, 16) | random_bits << 16) : Random();
   484 		uint32 param = (hs->extra_flags & SYNCHRONISED_CALLBACK_1B) ? (GB(Random(), 0, 16) | random_bits << 16) : Random();
   565 		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_START_STOP, param, GetHouseType(tile), GetTownByTile(tile), tile);
   485 		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_START_STOP, param, 0, GetHouseType(tile), GetTownByTile(tile), tile);
   566 
   486 
   567 		if (callback_res != CALLBACK_FAILED) ChangeHouseAnimationFrame(tile, callback_res);
   487 		if (callback_res != CALLBACK_FAILED) ChangeHouseAnimationFrame(tile, callback_res);
   568 	}
   488 	}
   569 }
   489 }
   570 
   490 
   575 	if (GetHouseProcessingTime(tile) > 0) {
   495 	if (GetHouseProcessingTime(tile) > 0) {
   576 		DecHouseProcessingTime(tile);
   496 		DecHouseProcessingTime(tile);
   577 		return true;
   497 		return true;
   578 	}
   498 	}
   579 
   499 
   580 	/* @todo: Magic with triggers goes here.  Got to implement that, one day. .. */
   500 	/* @todo: Magic with triggers goes here.  Got to implement that, one day. ..
       
   501 	 * Process randomizing of tiles following specs.
       
   502 	 * Once done, redraw the house
       
   503 	 * MarkTileDirtyByTile(tile);
       
   504 	 */
   581 
   505 
   582 	if (HASBIT(hs->callback_mask, CBM_ANIMATION_START_STOP)) {
   506 	if (HASBIT(hs->callback_mask, CBM_ANIMATION_START_STOP)) {
   583 		/* If this house is marked as having a synchronised callback, all the
   507 		/* If this house is marked as having a synchronised callback, all the
   584 		 * tiles will have the callback called at once, rather than when the
   508 		 * tiles will have the callback called at once, rather than when the
   585 		 * tile loop reaches them. This should only be enabled for the northern
   509 		 * tile loop reaches them. This should only be enabled for the northern
   596 		}
   520 		}
   597 	}
   521 	}
   598 
   522 
   599 	/* Check callback 21, which determines if a house should be destroyed. */
   523 	/* Check callback 21, which determines if a house should be destroyed. */
   600 	if (HASBIT(hs->callback_mask, CBM_HOUSE_DESTRUCTION)) {
   524 	if (HASBIT(hs->callback_mask, CBM_HOUSE_DESTRUCTION)) {
   601 		uint16 callback_res = GetHouseCallback(CBID_HOUSE_DESTRUCTION, 0, GetHouseType(tile), GetTownByTile(tile), tile);
   525 		uint16 callback_res = GetHouseCallback(CBID_HOUSE_DESTRUCTION, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile);
   602 		if (callback_res != CALLBACK_FAILED && callback_res > 0) {
   526 		if (callback_res != CALLBACK_FAILED && callback_res > 0) {
   603 			ClearTownHouse(GetTownByTile(tile), tile);
   527 			ClearTownHouse(GetTownByTile(tile), tile);
   604 			return false;
   528 			return false;
   605 		}
   529 		}
   606 	}
   530 	}