src/newgrf_commons.cpp
branchgamebalance
changeset 9911 0b8b245a2391
child 6720 35756db7e577
child 7297 1df77fb920bd
child 9626 79f2b5a0cdd7
equal deleted inserted replaced
9910:0b2aebc8283e 9911:0b8b245a2391
       
     1 /* $Id$ */
       
     2 
       
     3 /** @file newgrf_commons.cpp Implementation of the class OverrideManagerBase
       
     4  * and its descendance, present and futur
       
     5  */
       
     6 
       
     7 #include "stdafx.h"
       
     8 #include "openttd.h"
       
     9 #include "town.h"
       
    10 #include "industry.h"
       
    11 #include "newgrf.h"
       
    12 #include "newgrf_commons.h"
       
    13 
       
    14 /** Constructor of generic class
       
    15  * @param offset end of original data for this entity. i.e: houses = 110
       
    16  * @param maximum of entities this manager can deal with. i.e: houses = 512
       
    17  * @param invalid is the ID used to identify an invalid entity id
       
    18  */
       
    19 OverrideManagerBase::OverrideManagerBase(uint16 offset, uint16 maximum, uint16 invalid)
       
    20 {
       
    21 	max_offset = offset;
       
    22 	max_new_entities = maximum;
       
    23 	invalid_ID = invalid;
       
    24 
       
    25 	mapping_ID = CallocT<EntityIDMapping>(max_new_entities);
       
    26 	entity_overrides = MallocT<uint16>(max_offset);
       
    27 	memset(entity_overrides, invalid, sizeof(entity_overrides));
       
    28 }
       
    29 
       
    30 /** Destructor of the generic class.
       
    31  * Frees allocated memory of constructor
       
    32  */
       
    33 OverrideManagerBase::~OverrideManagerBase()
       
    34 {
       
    35 	free(mapping_ID);
       
    36 	free(entity_overrides);
       
    37 }
       
    38 
       
    39 /** Since the entity IDs defined by the GRF file does not necessarily correlate
       
    40  * to those used by the game, the IDs used for overriding old entities must be
       
    41  * translated when the entity spec is set.
       
    42  * @param local_id id in grf file
       
    43  * @param entity_type original entity type
       
    44  */
       
    45 void OverrideManagerBase::Add(uint8 local_id, uint entity_type)
       
    46 {
       
    47 	assert(entity_type < max_offset);
       
    48 	entity_overrides[entity_type] = local_id;
       
    49 }
       
    50 
       
    51 /** Resets the mapping, which is used while initializing game */
       
    52 void OverrideManagerBase::ResetMapping()
       
    53 {
       
    54 	memset(mapping_ID, 0, (max_new_entities - 1) * sizeof(EntityIDMapping));
       
    55 }
       
    56 
       
    57 /** Resets the override, which is used while initializing game */
       
    58 void OverrideManagerBase::ResetOverride()
       
    59 {
       
    60 	for (uint16 i = 0; i < max_offset; i++) {
       
    61 		entity_overrides[i] = invalid_ID;
       
    62 	}
       
    63 }
       
    64 
       
    65 /** Return the ID (if ever available) of a previously inserted entity.
       
    66  * @param grf_local_id ID of this enity withing the grfID
       
    67  * @param grfid ID of the grf file
       
    68  * @return the ID of the candidate, of the Invalid flag item ID
       
    69  */
       
    70 uint16 OverrideManagerBase::GetID(uint8 grf_local_id, uint32 grfid)
       
    71 {
       
    72 	const EntityIDMapping *map;
       
    73 
       
    74 	for (uint16 id = max_offset; id < max_new_entities; id++) {
       
    75 		map = &mapping_ID[id];
       
    76 		if (map->entity_id == grf_local_id && map->grfid == grfid) {
       
    77 			return id;
       
    78 		}
       
    79 	}
       
    80 	return invalid_ID;
       
    81 }
       
    82 
       
    83 /** Reserves a place in the mapping array for an entity to be installed
       
    84  * @param grf_local_id is an arbitrary id given by the grf's author.  Also known as setid
       
    85  * @param grfid is the id of the grf file itself
       
    86  * @param substitute_id is the original entity from which data is copied for the new one
       
    87  * @return the proper usable slot id, or invalid marker if none is found
       
    88  */
       
    89 uint16 OverrideManagerBase::AddEntityID(byte grf_local_id, uint32 grfid, byte substitute_id)
       
    90 {
       
    91 	uint16 id = this->GetID(grf_local_id, grfid);
       
    92 	EntityIDMapping *map;
       
    93 
       
    94 	/* Look to see if this entity has already been added. This is done
       
    95 	 * separately from the loop below in case a GRF has been deleted, and there
       
    96 	 * are any gaps in the array.
       
    97 	 */
       
    98 	if (id != invalid_ID) {
       
    99 		return id;
       
   100 	}
       
   101 
       
   102 	/* This entity hasn't been defined before, so give it an ID now. */
       
   103 	for (id = max_offset; id < max_new_entities; id++) {
       
   104 		map = &mapping_ID[id];
       
   105 
       
   106 		if (map->entity_id == 0 && map->grfid == 0) {
       
   107 			map->entity_id     = grf_local_id;
       
   108 			map->grfid         = grfid;
       
   109 			map->substitute_id = substitute_id;
       
   110 			return id;
       
   111 		}
       
   112 	}
       
   113 
       
   114 	return invalid_ID;
       
   115 }
       
   116 
       
   117 /** Gives the substitute of the entity, as specified by the grf file
       
   118  * @param entity_id of the entity being queried
       
   119  * @return mapped id
       
   120  */
       
   121 uint16 OverrideManagerBase::GetSubstituteID(byte entity_id)
       
   122 {
       
   123 	return mapping_ID[entity_id].substitute_id;
       
   124 }
       
   125 
       
   126 /** Install the specs into the HouseSpecs array
       
   127  * It will find itself the proper slot onwhich it will go
       
   128  * @param hs HouseSpec read from the grf file, ready for inclusion
       
   129  */
       
   130 void HouseOverrideManager::SetEntitySpec(const HouseSpec *hs)
       
   131 {
       
   132 	HouseID house_id = this->AddEntityID(hs->local_id, hs->grffile->grfid, hs->substitute_id);
       
   133 
       
   134 	if (house_id == invalid_ID) {
       
   135 		grfmsg(1, "House.SetEntitySpec: Too many houses allocated. Ignoring.");
       
   136 		return;
       
   137 	}
       
   138 
       
   139 	memcpy(&_house_specs[house_id], hs, sizeof(*hs));
       
   140 
       
   141 	/* Now add the overrides. */
       
   142 	for (int i = 0; i != max_offset; i++) {
       
   143 		HouseSpec *overridden_hs = GetHouseSpecs(i);
       
   144 
       
   145 		if (entity_overrides[i] != hs->local_id) continue;
       
   146 
       
   147 		overridden_hs->override = house_id;
       
   148 		entity_overrides[i] = invalid_ID;
       
   149 	}
       
   150 }