tron@3319: /* $Id$ */ tron@3319: belugas@3432: /** @file town_map.h Accessors for towns */ belugas@3432: celestar@3426: #ifndef TOWN_MAP_H celestar@3426: #define TOWN_MAP_H celestar@3426: tron@3319: #include "town.h" KUDr@6303: #include "date.h" tron@3319: KUDr@6303: /** KUDr@6303: * Get the index of which town this house/street is attached to. KUDr@6303: * @param t the tile KUDr@6303: * @pre IsTileType(t, MP_HOUSE) or IsTileType(t, MP_STREET) KUDr@6303: * @return TownID KUDr@6303: */ belugas@3432: static inline TownID GetTownIndex(TileIndex t) tron@3319: { tron@3369: assert(IsTileType(t, MP_HOUSE) || IsTileType(t, MP_STREET)); // XXX incomplete tron@3319: return _m[t].m2; tron@3319: } tron@3319: belugas@3432: /** tron@3983: * Set the town index for a road or house tile. KUDr@6303: * @param t the tile KUDr@6303: * @pre IsTileType(t, MP_HOUSE) or IsTileType(t, MP_STREET) belugas@3432: * @param index the index of the town rubidium@6220: * @pre IsTileType(t, MP_STREET) || IsTileType(t, MP_HOUSE) belugas@3432: */ belugas@3432: static inline void SetTownIndex(TileIndex t, TownID index) belugas@3432: { KUDr@6303: assert(IsTileType(t, MP_HOUSE) || IsTileType(t, MP_STREET)); belugas@3432: _m[t].m2 = index; belugas@3432: } belugas@3432: rubidium@6220: /** rubidium@6220: * Gets the town associated with the house or road tile rubidium@6220: * @param t the tile to get the town of rubidium@6220: * @return the town rubidium@6220: */ rubidium@6220: static inline Town* GetTownByTile(TileIndex t) rubidium@6220: { rubidium@6220: return GetTown(GetTownIndex(t)); rubidium@6220: } rubidium@6220: KUDr@6303: /** KUDr@6303: * Get the type of this house, which is an index into the house spec array KUDr@6303: * Since m4 is only a byte and we want to support 512 houses, we use the bit 6 KUDr@6303: * of m3 as an additional bit to house type. KUDr@6303: * @param t the tile KUDr@6303: * @pre IsTileType(t, MP_HOUSE) KUDr@6303: * @return house type KUDr@6303: */ KUDr@6303: static inline HouseID GetHouseType(TileIndex t) rubidium@6220: { rubidium@6220: assert(IsTileType(t, MP_HOUSE)); KUDr@6303: return _m[t].m4 | (GB(_m[t].m3, 6, 1) << 8); celestar@3426: } celestar@3426: KUDr@6303: /** KUDr@6303: * Set the house type. KUDr@6303: * @param t the tile KUDr@6303: * @param house_id the new house type KUDr@6303: * @pre IsTileType(t, MP_HOUSE) KUDr@6303: */ KUDr@6303: static inline void SetHouseType(TileIndex t, HouseID house_id) celestar@3426: { KUDr@6303: assert(IsTileType(t, MP_HOUSE)); KUDr@6303: _m[t].m4 = GB(house_id, 0, 8); KUDr@6303: SB(_m[t].m3, 6, 1, GB(house_id, 8, 1)); celestar@3426: } celestar@3426: KUDr@6303: /** KUDr@6303: * Check if the lift of this animated house has a destination KUDr@6303: * @param t the tile KUDr@6303: * @return has destination KUDr@6303: */ KUDr@6303: static inline bool LiftHasDestination(TileIndex t) celestar@3426: { KUDr@6303: return HASBIT(_me[t].m7, 0); celestar@3426: } celestar@3426: KUDr@6303: /** KUDr@6303: * Set the new destination of the lift for this animated house, and activate KUDr@6303: * the LiftHasDestination bit. KUDr@6303: * @param t the tile KUDr@6303: * @param dest new destination KUDr@6303: */ KUDr@6303: static inline void SetLiftDestination(TileIndex t, byte dest) KUDr@6303: { KUDr@6303: SETBIT(_me[t].m7, 0); KUDr@6303: SB(_me[t].m7, 1, 3, dest); KUDr@6303: } KUDr@6303: KUDr@6303: /** KUDr@6303: * Get the current destination for this lift KUDr@6303: * @param t the tile KUDr@6303: * @return destination KUDr@6303: */ KUDr@6303: static inline byte GetLiftDestination(TileIndex t) KUDr@6303: { KUDr@6303: return GB(_me[t].m7, 1, 3); KUDr@6303: } KUDr@6303: KUDr@6303: /** KUDr@6303: * Stop the lift of this animated house from moving. KUDr@6303: * Clears the first 4 bits of m7 at once, clearing the LiftHasDestination bit KUDr@6303: * and the destination. KUDr@6303: * @param t the tile KUDr@6303: */ celestar@3426: static inline void HaltLift(TileIndex t) celestar@3426: { KUDr@6303: SB(_me[t].m7, 0, 4, 0); celestar@3426: DeleteAnimatedTile(t); celestar@3426: } celestar@3426: KUDr@6303: /** KUDr@6303: * Get the position of the lift on this animated house KUDr@6303: * @param t the tile KUDr@6303: * @return position, from 0 to 36 KUDr@6303: */ celestar@3426: static inline byte GetLiftPosition(TileIndex t) celestar@3426: { KUDr@6303: return GB(_m[t].m6, 2, 6); celestar@3426: } celestar@3426: KUDr@6303: /** KUDr@6303: * Set the position of the lift on this animated house KUDr@6303: * @param t the tile KUDr@6303: * @param pos, from 0 to 36 KUDr@6303: */ celestar@3426: static inline void SetLiftPosition(TileIndex t, byte pos) celestar@3426: { KUDr@6303: SB(_m[t].m6, 2, 6, pos); celestar@3426: } celestar@3426: KUDr@6303: /** KUDr@6303: * Get the current animation frame for this house KUDr@6303: * @param t the tile KUDr@6303: * @pre IsTileType(t, MP_HOUSE) KUDr@6303: * @return frame number KUDr@6303: */ KUDr@6303: static inline byte GetHouseAnimationFrame(TileIndex t) KUDr@6303: { KUDr@6303: assert(IsTileType(t, MP_HOUSE)); KUDr@6303: return GB(_m[t].m6, 3, 5); KUDr@6303: } KUDr@6303: KUDr@6303: /** KUDr@6303: * Set a new animation frame for this house KUDr@6303: * @param t the tile KUDr@6303: * @param frame the new frame number KUDr@6303: * @pre IsTileType(t, MP_HOUSE) KUDr@6303: */ KUDr@6303: static inline void SetHouseAnimationFrame(TileIndex t, byte frame) KUDr@6303: { KUDr@6303: assert(IsTileType(t, MP_HOUSE)); KUDr@6303: SB(_m[t].m6, 3, 5, frame); KUDr@6303: } KUDr@6303: KUDr@6303: /** KUDr@6303: * Get the completion of this house KUDr@6303: * @param t the tile KUDr@6303: * @return true if it is, false if it is not KUDr@6303: */ KUDr@6303: static inline bool IsHouseCompleted(TileIndex t) KUDr@6303: { KUDr@6303: assert(IsTileType(t, MP_HOUSE)); KUDr@6303: return HASBIT(_m[t].m3, 7); KUDr@6303: } KUDr@6303: KUDr@6303: /** KUDr@6303: * Mark this house as been completed KUDr@6303: * @param t the tile KUDr@6303: * @param status KUDr@6303: */ KUDr@6303: static inline void SetHouseCompleted(TileIndex t, bool status) KUDr@6303: { KUDr@6303: assert(IsTileType(t, MP_HOUSE)); KUDr@6303: SB(_m[t].m3, 7, 1, !!status); KUDr@6303: } KUDr@6303: KUDr@6303: /** KUDr@6303: * Make the tile a house. KUDr@6303: * @param t tile index KUDr@6303: * @param tid Town index KUDr@6303: * @param counter of construction step KUDr@6303: * @param stage of construction (used for drawing) KUDr@6303: * @param type of house. Index into house specs array KUDr@6303: * @param random_bits required for newgrf houses KUDr@6303: * @pre IsTileType(t, MP_CLEAR) KUDr@6303: */ KUDr@6303: static inline void MakeHouseTile(TileIndex t, TownID tid, byte counter, byte stage, HouseID type, byte random_bits) celestar@3382: { celestar@3382: assert(IsTileType(t, MP_CLEAR)); celestar@3382: celestar@3382: SetTileType(t, MP_HOUSE); KUDr@6303: _m[t].m1 = random_bits; celestar@3382: _m[t].m2 = tid; KUDr@6303: _m[t].m3 = 0; KUDr@6303: SetHouseType(t, type); KUDr@6303: SetHouseCompleted(t, stage == TOWN_HOUSE_COMPLETED); KUDr@6303: _m[t].m5 = IsHouseCompleted(t) ? 0 : (stage << 3 | counter); KUDr@6303: SetHouseAnimationFrame(t, 0); KUDr@6303: _me[t].m7 = GetHouseSpecs(type)->processing_time; celestar@3382: KUDr@6303: if (GetHouseSpecs(type)->building_flags & BUILDING_IS_ANIMATED) AddAnimatedTile(t); celestar@3382: MarkTileDirtyByTile(t); celestar@3382: } celestar@3382: KUDr@6303: /** KUDr@6303: * Helper function for MakeHouseTile. KUDr@6303: * It is called for each tile of a multi-tile house. KUDr@6303: * Parametes are the same. KUDr@6303: * @param t tile index KUDr@6303: * @param tid Town index KUDr@6303: * @param counter of construction step KUDr@6303: * @param stage of construction (used for drawing) KUDr@6303: * @param type of house. Index into house specs array KUDr@6303: * @param random_bits required for newgrf houses KUDr@6303: */ KUDr@6303: static inline void MakeTownHouse(TileIndex t, TownID tid, byte counter, byte stage, HouseID type, byte random_bits) celestar@3382: { KUDr@6303: BuildingFlags size = GetHouseSpecs(type)->building_flags; KUDr@6303: MakeHouseTile(t, tid, counter, stage, type, random_bits); KUDr@6303: if (size & BUILDING_2_TILES_Y) MakeHouseTile(t + TileDiffXY(0, 1), tid, counter, stage, ++type, random_bits); KUDr@6303: if (size & BUILDING_2_TILES_X) MakeHouseTile(t + TileDiffXY(1, 0), tid, counter, stage, ++type, random_bits); KUDr@6303: if (size & BUILDING_HAS_4_TILES) MakeHouseTile(t + TileDiffXY(1, 1), tid, counter, stage, ++type, random_bits); celestar@3382: } belugas@3432: belugas@3432: /** belugas@3432: * House Construction Scheme. belugas@3432: * Construction counter, for buildings under construction. Incremented on every belugas@3432: * periodic tile processing. belugas@3432: * On wraparound, the stage of building in is increased. KUDr@6303: * GetHouseBuildingStage is taking care of the real stages, belugas@3432: * (as the sprite for the next phase of house building) KUDr@6303: * (Get|Inc)HouseConstructionTick is simply a tick counter between the belugas@3432: * different stages belugas@3432: */ belugas@3432: belugas@3432: /** belugas@3432: * Gets the building stage of a house KUDr@6303: * Since the stage is used for determining what sprite to use, KUDr@6303: * if the house is complete (and that stage no longuer is available), KUDr@6303: * fool the system by returning the TOWN_HOUSE_COMPLETE (3), KUDr@6303: * thus showing a beautiful complete house. KUDr@6303: * @param t the tile of the house to get the building stage of belugas@3432: * @pre IsTileType(t, MP_HOUSE) belugas@3432: * @return the building stage of the house belugas@3432: */ belugas@3432: static inline byte GetHouseBuildingStage(TileIndex t) belugas@3432: { belugas@3432: assert(IsTileType(t, MP_HOUSE)); KUDr@6303: return IsHouseCompleted(t) ? (byte)TOWN_HOUSE_COMPLETED : GB(_m[t].m5, 3, 2); belugas@3432: } belugas@3432: belugas@3432: /** belugas@3432: * Gets the construction stage of a house KUDr@6303: * @param t the tile of the house to get the construction stage of belugas@3432: * @pre IsTileType(t, MP_HOUSE) belugas@3432: * @return the construction stage of the house belugas@3432: */ belugas@3432: static inline byte GetHouseConstructionTick(TileIndex t) belugas@3432: { belugas@3432: assert(IsTileType(t, MP_HOUSE)); KUDr@6303: return IsHouseCompleted(t) ? 0 : GB(_m[t].m5, 0, 3); belugas@3432: } belugas@3432: belugas@3432: /** belugas@3432: * Sets the increment stage of a house KUDr@6303: * It is working with the whole counter + stage 5 bits, making it KUDr@6303: * easier to work: the wraparound is automatic. KUDr@6303: * @param t the tile of the house to increment the construction stage of belugas@3432: * @pre IsTileType(t, MP_HOUSE) belugas@3432: */ belugas@3432: static inline void IncHouseConstructionTick(TileIndex t) belugas@3432: { belugas@3432: assert(IsTileType(t, MP_HOUSE)); KUDr@6303: AB(_m[t].m5, 0, 5, 1); KUDr@6303: KUDr@6303: if (GB(_m[t].m5, 3, 2) == TOWN_HOUSE_COMPLETED) { KUDr@6303: /* House is now completed. KUDr@6303: * Store the year of construction as well, for newgrf house purpose */ KUDr@6303: SetHouseCompleted(t, true); KUDr@6303: _m[t].m5 = clamp(_cur_year - ORIGINAL_BASE_YEAR, 0, 0xFF); KUDr@6303: } belugas@3432: } belugas@3432: KUDr@6303: /** KUDr@6303: * Get the year that this house was constructed (between 1920 and 2175). KUDr@6303: * @param t the tile of this house KUDr@6303: * @pre IsTileType(t, MP_HOUSE) KUDr@6303: * @return year KUDr@6303: */ KUDr@6303: static inline Year GetHouseConstructionYear(TileIndex t) KUDr@6303: { KUDr@6303: assert(IsTileType(t, MP_HOUSE)); KUDr@6303: return IsHouseCompleted(t) ? _m[t].m5 + ORIGINAL_BASE_YEAR : 0; KUDr@6303: } KUDr@6303: KUDr@6303: /** KUDr@6303: * Get the random bits for this house. KUDr@6303: * This is required for newgrf house KUDr@6303: * @param t the tile of this house KUDr@6303: * @pre IsTileType(t, MP_HOUSE) KUDr@6303: * @return random bits KUDr@6303: */ KUDr@6303: static inline byte GetHouseRandomBits(TileIndex t) KUDr@6303: { KUDr@6303: assert(IsTileType(t, MP_HOUSE)); KUDr@6303: return _m[t].m1; KUDr@6303: } KUDr@6303: KUDr@6303: /** KUDr@6303: * Set the activated triggers bits for this house. KUDr@6303: * This is required for newgrf house KUDr@6303: * @param t the tile of this house KUDr@6303: * @pre IsTileType(t, MP_HOUSE) KUDr@6303: */ KUDr@6303: static inline void SetHouseTriggers(TileIndex t, byte triggers) KUDr@6303: { KUDr@6303: assert(IsTileType(t, MP_HOUSE)); KUDr@6303: SB(_m[t].m3, 0, 5, triggers); KUDr@6303: } KUDr@6303: KUDr@6303: /** KUDr@6303: * Get the already activated triggers bits for this house. KUDr@6303: * This is required for newgrf house KUDr@6303: * @param t the tile of this house KUDr@6303: * @pre IsTileType(t, MP_HOUSE) KUDr@6303: * @return triggers KUDr@6303: */ KUDr@6303: static inline byte GetHouseTriggers(TileIndex t) KUDr@6303: { KUDr@6303: assert(IsTileType(t, MP_HOUSE)); KUDr@6303: return GB(_m[t].m3, 0, 5); KUDr@6303: } KUDr@6303: KUDr@6303: /** KUDr@6303: * Get the amount of time remaining before the tile loop processes this tile. KUDr@6303: * @param t the house tile KUDr@6303: * @pre IsTileType(t, MP_HOUSE) KUDr@6303: * @return time remaining KUDr@6303: */ KUDr@6303: static inline byte GetHouseProcessingTime(TileIndex t) KUDr@6303: { KUDr@6303: assert(IsTileType(t, MP_HOUSE)); KUDr@6303: return _me[t].m7; KUDr@6303: } KUDr@6303: KUDr@6303: /** KUDr@6303: * Set the amount of time remaining before the tile loop processes this tile. KUDr@6303: * @param t the house tile KUDr@6303: * @param time the time to be set KUDr@6303: * @pre IsTileType(t, MP_HOUSE) KUDr@6303: */ KUDr@6303: static inline void SetHouseProcessingTime(TileIndex t, byte time) KUDr@6303: { KUDr@6303: assert(IsTileType(t, MP_HOUSE)); KUDr@6303: _me[t].m7 = time; KUDr@6303: } KUDr@6303: KUDr@6303: /** KUDr@6303: * Decrease the amount of time remaining before the tile loop processes this tile. KUDr@6303: * @param t the house tile KUDr@6303: * @pre IsTileType(t, MP_HOUSE) KUDr@6303: */ KUDr@6303: static inline void DecHouseProcessingTime(TileIndex t) KUDr@6303: { KUDr@6303: assert(IsTileType(t, MP_HOUSE)); KUDr@6303: _me[t].m7--; KUDr@6303: } belugas@3432: belugas@3432: #endif /* TOWN_MAP_H */