mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-06 06:15:04 +00:00
(svn r20482) -Codechange: move some object related information off the map and unify the relation objects have to towns
This commit is contained in:
parent
c5ec910980
commit
89b2b9370a
@ -1568,8 +1568,8 @@
|
||||
<ul>
|
||||
<li>m1 bits 6..5 : Water class (sea, canal, river or land)
|
||||
<li>m1 bits 4..0: <a href="#OwnershipInfo">owner</a> of the object (for lighthouses and transmitters normally <tt>10</tt>)</li>
|
||||
<li>m2: see company statue
|
||||
<li>m3: offset to northern most tile
|
||||
<li>m2: index into the array of objects
|
||||
<li>m3: animation counter
|
||||
<li>m5: tile type:
|
||||
<table>
|
||||
<tr>
|
||||
@ -1585,10 +1585,6 @@
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>02</tt> </td>
|
||||
<td align=left>company statue
|
||||
<ul>
|
||||
<li>m2: TownID on which the statue is built in</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
@ -1603,7 +1599,6 @@
|
||||
</table>
|
||||
</li>
|
||||
<li>m6 bits 7..6 : Possibility of a bridge above, in the <a href="#bridge_direction">direction specified</a></li>
|
||||
<li>m6 bits 2..5 : Animation counter</li>
|
||||
<li>m6 bits 1..0 : <a href="#tropic_zone">Tropic zone definition</a></li>
|
||||
</ul>
|
||||
</td>
|
||||
|
@ -330,24 +330,13 @@ the array so you can quickly see what is used and what is not.
|
||||
<td class="caption">objects</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">O</span>XXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOO</span>X XXXX</td>
|
||||
<td class="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">company statue</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
@ -505,6 +505,7 @@
|
||||
<ClInclude Include="..\src\sound\null_s.h" />
|
||||
<ClInclude Include="..\src\video\null_v.h" />
|
||||
<ClInclude Include="..\src\object.h" />
|
||||
<ClInclude Include="..\src\object_base.h" />
|
||||
<ClInclude Include="..\src\object_type.h" />
|
||||
<ClInclude Include="..\src\openttd.h" />
|
||||
<ClInclude Include="..\src\order_base.h" />
|
||||
@ -725,6 +726,7 @@
|
||||
<ClCompile Include="..\src\saveload\misc_sl.cpp" />
|
||||
<ClCompile Include="..\src\saveload\newgrf_sl.cpp" />
|
||||
<ClInclude Include="..\src\saveload\newgrf_sl.h" />
|
||||
<ClCompile Include="..\src\saveload\object_sl.cpp" />
|
||||
<ClCompile Include="..\src\saveload\oldloader.cpp" />
|
||||
<ClInclude Include="..\src\saveload\oldloader.h" />
|
||||
<ClCompile Include="..\src\saveload\oldloader_sl.cpp" />
|
||||
|
@ -718,6 +718,9 @@
|
||||
<ClInclude Include="..\src\object.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\object_base.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\object_type.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -1378,6 +1381,9 @@
|
||||
<ClInclude Include="..\src\saveload\newgrf_sl.h">
|
||||
<Filter>Save/Load handlers</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\src\saveload\object_sl.cpp">
|
||||
<Filter>Save/Load handlers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\saveload\oldloader.cpp">
|
||||
<Filter>Save/Load handlers</Filter>
|
||||
</ClCompile>
|
||||
|
@ -1287,6 +1287,10 @@
|
||||
RelativePath=".\..\src\object.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\..\src\object_base.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\..\src\object_type.h"
|
||||
>
|
||||
@ -2187,6 +2191,10 @@
|
||||
RelativePath=".\..\src\saveload\newgrf_sl.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\..\src\saveload\object_sl.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\..\src\saveload\oldloader.cpp"
|
||||
>
|
||||
|
@ -1284,6 +1284,10 @@
|
||||
RelativePath=".\..\src\object.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\..\src\object_base.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\..\src\object_type.h"
|
||||
>
|
||||
@ -2184,6 +2188,10 @@
|
||||
RelativePath=".\..\src\saveload\newgrf_sl.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\..\src\saveload\object_sl.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\..\src\saveload\oldloader.cpp"
|
||||
>
|
||||
|
@ -231,6 +231,7 @@ music/null_m.h
|
||||
sound/null_s.h
|
||||
video/null_v.h
|
||||
object.h
|
||||
object_base.h
|
||||
object_type.h
|
||||
openttd.h
|
||||
order_base.h
|
||||
@ -476,6 +477,7 @@ saveload/map_sl.cpp
|
||||
saveload/misc_sl.cpp
|
||||
saveload/newgrf_sl.cpp
|
||||
saveload/newgrf_sl.h
|
||||
saveload/object_sl.cpp
|
||||
saveload/oldloader.cpp
|
||||
saveload/oldloader.h
|
||||
saveload/oldloader_sl.cpp
|
||||
|
@ -3630,6 +3630,7 @@ STR_ERROR_TUNNEL_THROUGH_MAP_BORDER :{WHITE}Tunnel w
|
||||
STR_ERROR_UNABLE_TO_EXCAVATE_LAND :{WHITE}Unable to excavate land for other end of tunnel
|
||||
|
||||
# Object related errors
|
||||
STR_ERROR_TOO_MANY_OBJECTS :{WHITE}... too many objects
|
||||
STR_ERROR_CAN_T_BUILD_OBJECT :{WHITE}Can't build object...
|
||||
STR_ERROR_OBJECT_IN_THE_WAY :{WHITE}Object in the way
|
||||
STR_ERROR_COMPANY_HEADQUARTERS_IN :{WHITE}... company headquarters in the way
|
||||
|
@ -42,6 +42,7 @@ void InitializeRoadGui();
|
||||
void InitializeAirportGui();
|
||||
void InitializeDockGui();
|
||||
void InitializeIndustries();
|
||||
void InitializeObjects();
|
||||
void InitializeTowns();
|
||||
void InitializeSubsidies();
|
||||
void InitializeTrees();
|
||||
@ -100,6 +101,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin
|
||||
InitializeRoadStops();
|
||||
InitializeCargoPackets();
|
||||
InitializeIndustries();
|
||||
InitializeObjects();
|
||||
InitializeBuildingCounts();
|
||||
|
||||
InitializeNPF();
|
||||
|
44
src/object_base.h
Normal file
44
src/object_base.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file object_base.h Base for all objects. */
|
||||
|
||||
#ifndef OBJECT_BASE_H
|
||||
#define OBJECT_BASE_H
|
||||
|
||||
#include "core/pool_type.hpp"
|
||||
#include "object_type.h"
|
||||
#include "tilearea_type.h"
|
||||
#include "town_type.h"
|
||||
#include "date_type.h"
|
||||
|
||||
typedef Pool<Object, ObjectID, 64, 64000> ObjectPool;
|
||||
extern ObjectPool _object_pool;
|
||||
|
||||
/** An object, such as transmitter, on the map. */
|
||||
struct Object : ObjectPool::PoolItem<&_object_pool> {
|
||||
Town *town; ///< Town the object is built in
|
||||
TileArea location; ///< Location of the object
|
||||
Date build_date; ///< Date of construction
|
||||
|
||||
/** Make sure the object isn't zeroed. */
|
||||
Object() {}
|
||||
|
||||
/**
|
||||
* Get the object associated with a tile.
|
||||
* @param tile The tile to fetch the object for.
|
||||
* @return The object.
|
||||
*/
|
||||
static Object *GetByTile(TileIndex tile);
|
||||
};
|
||||
|
||||
#define FOR_ALL_OBJECTS_FROM(var, start) FOR_ALL_ITEMS_FROM(Object, object_index, var, start)
|
||||
#define FOR_ALL_OBJECTS(var) FOR_ALL_OBJECTS_FROM(var, 0)
|
||||
|
||||
#endif /* OBJECT_BASE_H */
|
@ -29,12 +29,29 @@
|
||||
#include "cargopacket.h"
|
||||
#include "sprite.h"
|
||||
#include "core/random_func.hpp"
|
||||
#include "core/pool_func.hpp"
|
||||
#include "object_map.h"
|
||||
#include "object_base.h"
|
||||
#include "date_func.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "table/sprites.h"
|
||||
#include "table/object_land.h"
|
||||
|
||||
ObjectPool _object_pool("Object");
|
||||
INSTANTIATE_POOL_METHODS(Object)
|
||||
|
||||
/* static */ Object *Object::GetByTile(TileIndex tile)
|
||||
{
|
||||
return Object::Get(GetObjectIndex(tile));
|
||||
}
|
||||
|
||||
/** Initialize/reset the objects. */
|
||||
void InitializeObjects()
|
||||
{
|
||||
_object_pool.CleanPool();
|
||||
}
|
||||
|
||||
/* static */ const ObjectSpec *ObjectSpec::Get(ObjectType index)
|
||||
{
|
||||
assert(index < OBJECT_MAX);
|
||||
@ -51,24 +68,26 @@ void BuildObject(ObjectType type, TileIndex tile, CompanyID owner, Town *town)
|
||||
const ObjectSpec *spec = ObjectSpec::Get(type);
|
||||
|
||||
TileArea ta(tile, GB(spec->size, 0, 4), GB(spec->size, 4, 4));
|
||||
Object *o = new Object();
|
||||
o->location = ta;
|
||||
o->town = town == NULL ? CalcClosestTownFromTile(tile) : town;
|
||||
o->build_date = _date;
|
||||
|
||||
assert(o->town != NULL);
|
||||
|
||||
TILE_AREA_LOOP(t, ta) {
|
||||
TileIndex offset = t - tile;
|
||||
MakeObject(t, type, owner, TileY(offset) << 4 | TileX(offset), town == NULL ? 0 : town->index, WATER_CLASS_INVALID);
|
||||
MakeObject(t, type, owner, o->index, WATER_CLASS_INVALID);
|
||||
MarkTileDirtyByTile(t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the animation stage of a whole structure.
|
||||
* @param northern The northern tile of the structure.
|
||||
* @pre GetObjectOffset(northern) == 0
|
||||
* @param tile The tile of the structure.
|
||||
*/
|
||||
void IncreaseAnimationStage(TileIndex northern)
|
||||
static void IncreaseAnimationStage(TileIndex tile)
|
||||
{
|
||||
assert(GetObjectOffset(northern) == 0);
|
||||
const ObjectSpec *spec = ObjectSpec::GetByTile(northern);
|
||||
|
||||
TileArea ta(northern, GB(spec->size, 0, 4), GB(spec->size, 4, 4));
|
||||
TileArea ta = Object::GetByTile(tile)->location;
|
||||
TILE_AREA_LOOP(t, ta) {
|
||||
SetObjectAnimationStage(t, GetObjectAnimationStage(t) + 1);
|
||||
MarkTileDirtyByTile(t);
|
||||
@ -119,6 +138,9 @@ CommandCost CmdBuildObject(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
||||
if (spec->flags & OBJECT_FLAG_ONLY_IN_SCENEDIT && (_game_mode != GM_EDITOR || _current_company != OWNER_NONE)) return CMD_ERROR;
|
||||
if (spec->flags & OBJECT_FLAG_ONLY_IN_GAME && (_game_mode != GM_NORMAL || _current_company > MAX_COMPANIES)) return CMD_ERROR;
|
||||
|
||||
if (!Object::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_OBJECTS);
|
||||
if (Town::GetNumItems() == 0) return_cmd_error(STR_ERROR_MUST_FOUND_TOWN_FIRST);
|
||||
|
||||
int size_x = GB(spec->size, 0, 4);
|
||||
int size_y = GB(spec->size, 4, 4);
|
||||
TileArea ta(tile, size_x, size_y);
|
||||
@ -195,8 +217,8 @@ static void DrawTile_Object(TileInfo *ti)
|
||||
PaletteID palette = to == OWNER_NONE ? PAL_NONE : COMPANY_SPRITE_COLOUR(to);
|
||||
|
||||
if (type == OBJECT_HQ) {
|
||||
uint8 offset = GetObjectOffset(ti->tile);
|
||||
dts = &_object_hq[GetCompanyHQSize(ti->tile) << 2 | GB(offset, 4, 1) << 1 | GB(offset, 0, 1)];
|
||||
TileIndex diff = ti->tile - Object::GetByTile(ti->tile)->location.tile;
|
||||
dts = &_object_hq[GetCompanyHQSize(ti->tile) << 2 | TileY(diff) << 1 | TileX(diff)];
|
||||
} else {
|
||||
dts = &_objects[type];
|
||||
}
|
||||
@ -254,8 +276,8 @@ static CommandCost ClearTile_Object(TileIndex tile, DoCommandFlag flags)
|
||||
const ObjectSpec *spec = ObjectSpec::Get(type);
|
||||
|
||||
/* Get to the northern most tile. */
|
||||
byte tile_offset = GetObjectOffset(tile);
|
||||
tile -= TileXY(GB(tile_offset, 0, 4), GB(tile_offset, 4, 4));
|
||||
Object *o = Object::GetByTile(tile);
|
||||
TileArea ta = o->location;
|
||||
|
||||
/* Water can remove everything! */
|
||||
if (_current_company != OWNER_WATER) {
|
||||
@ -276,11 +298,7 @@ static CommandCost ClearTile_Object(TileIndex tile, DoCommandFlag flags)
|
||||
}
|
||||
}
|
||||
|
||||
int size_x = GB(spec->size, 0, 4);
|
||||
int size_y = GB(spec->size, 4, 4);
|
||||
TileArea ta(tile, size_x, size_y);
|
||||
|
||||
CommandCost cost(EXPENSES_CONSTRUCTION, spec->GetClearCost() * size_x * size_y);
|
||||
CommandCost cost(EXPENSES_CONSTRUCTION, spec->GetClearCost() * ta.w * ta.h);
|
||||
if (spec->flags & OBJECT_FLAG_CLEAR_INCOME) cost.MultiplyCost(-1); // They get an income!
|
||||
|
||||
switch (type) {
|
||||
@ -299,9 +317,9 @@ static CommandCost ClearTile_Object(TileIndex tile, DoCommandFlag flags)
|
||||
|
||||
case OBJECT_STATUE:
|
||||
if (flags & DC_EXEC) {
|
||||
Town *t = Town::Get(GetStatueTownID(tile));
|
||||
ClrBit(t->statues, GetTileOwner(tile));
|
||||
SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
|
||||
Town *town = o->town;
|
||||
ClrBit(town->statues, GetTileOwner(tile));
|
||||
SetWindowDirty(WC_TOWN_AUTHORITY, town->index);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -311,6 +329,7 @@ static CommandCost ClearTile_Object(TileIndex tile, DoCommandFlag flags)
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
TILE_AREA_LOOP(tile_cur, ta) DoClearSquare(tile_cur);
|
||||
delete o;
|
||||
}
|
||||
|
||||
return cost;
|
||||
@ -344,6 +363,7 @@ static void GetTileDesc_Object(TileIndex tile, TileDesc *td)
|
||||
{
|
||||
td->str = ObjectSpec::GetByTile(tile)->name;
|
||||
td->owner[0] = GetTileOwner(tile);
|
||||
td->build_date = Object::GetByTile(tile)->build_date;
|
||||
}
|
||||
|
||||
static void TileLoop_Object(TileIndex tile)
|
||||
@ -492,7 +512,7 @@ static void ChangeTileOwner_Object(TileIndex tile, Owner old_owner, Owner new_ow
|
||||
if (IsOwnedLand(tile) && new_owner != INVALID_OWNER) {
|
||||
SetTileOwner(tile, new_owner);
|
||||
} else if (IsStatueTile(tile)) {
|
||||
Town *t = Town::Get(GetStatueTownID(tile));
|
||||
Town *t = Object::GetByTile(tile)->town;
|
||||
ClrBit(t->statues, old_owner);
|
||||
if (new_owner != INVALID_OWNER && !HasBit(t->statues, new_owner)) {
|
||||
/* Transfer ownership to the new company */
|
||||
|
@ -28,6 +28,18 @@ static inline ObjectType GetObjectType(TileIndex t)
|
||||
return (ObjectType)_m[t].m5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of which object this tile is attached to.
|
||||
* @param t the tile
|
||||
* @pre IsTileType(t, MP_OBJECT)
|
||||
* @return The ObjectID of the object.
|
||||
*/
|
||||
static inline ObjectID GetObjectIndex(TileIndex t)
|
||||
{
|
||||
assert(IsTileType(t, MP_OBJECT));
|
||||
return _m[t].m2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the given tile have a transmitter?
|
||||
* @param t the tile to inspect.
|
||||
@ -94,18 +106,6 @@ static inline bool IsStatueTile(TileIndex t)
|
||||
return IsTileType(t, MP_OBJECT) && IsStatue(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the town of the given statue tile.
|
||||
* @param t the tile of the statue.
|
||||
* @pre IsStatueTile(t)
|
||||
* @return the town the given statue is in.
|
||||
*/
|
||||
static inline TownID GetStatueTownID(TileIndex t)
|
||||
{
|
||||
assert(IsStatueTile(t));
|
||||
return _m[t].m2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get animation stage/counter of this tile.
|
||||
* @param t The tile to query.
|
||||
@ -115,7 +115,7 @@ static inline TownID GetStatueTownID(TileIndex t)
|
||||
static inline byte GetObjectAnimationStage(TileIndex t)
|
||||
{
|
||||
assert(IsTileType(t, MP_OBJECT));
|
||||
return GB(_m[t].m6, 2, 4);
|
||||
return _m[t].m3;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -127,31 +127,7 @@ static inline byte GetObjectAnimationStage(TileIndex t)
|
||||
static inline void SetObjectAnimationStage(TileIndex t, uint8 stage)
|
||||
{
|
||||
assert(IsTileType(t, MP_OBJECT));
|
||||
SB(_m[t].m6, 2, 4, stage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get offset to the northern most tile.
|
||||
* @param t The tile to get the offset from.
|
||||
* @return The offset to the northern most tile of this structure.
|
||||
* @pre IsTileType(t, MP_OBJECT)
|
||||
*/
|
||||
static inline byte GetObjectOffset(TileIndex t)
|
||||
{
|
||||
assert(IsTileType(t, MP_OBJECT));
|
||||
return _m[t].m3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set offset to the northern most tile.
|
||||
* @param t The tile to set the offset of.
|
||||
* @param offset The offset to the northern most tile of this structure.
|
||||
* @pre IsTileType(t, MP_OBJECT)
|
||||
*/
|
||||
static inline void SetObjectOffset(TileIndex t, uint8 offset)
|
||||
{
|
||||
assert(IsTileType(t, MP_OBJECT));
|
||||
_m[t].m3 = offset;
|
||||
_m[t].m3 = stage;
|
||||
}
|
||||
|
||||
|
||||
@ -161,17 +137,16 @@ static inline void SetObjectOffset(TileIndex t, uint8 offset)
|
||||
* @param t The tile to make and object tile.
|
||||
* @param u The object type of the tile.
|
||||
* @param o The new owner of the tile.
|
||||
* @param offset The offset to the northern tile of this object.
|
||||
* @param index Generic index associated with the object type.
|
||||
* @param index Index to the object.
|
||||
* @param wc Water class for this obect.
|
||||
*/
|
||||
static inline void MakeObject(TileIndex t, ObjectType u, Owner o, uint8 offset, uint index, WaterClass wc)
|
||||
static inline void MakeObject(TileIndex t, ObjectType u, Owner o, ObjectID index, WaterClass wc)
|
||||
{
|
||||
SetTileType(t, MP_OBJECT);
|
||||
SetTileOwner(t, o);
|
||||
SetWaterClass(t, wc);
|
||||
_m[t].m2 = index;
|
||||
_m[t].m3 = offset;
|
||||
_m[t].m3 = 0;
|
||||
_m[t].m4 = 0;
|
||||
_m[t].m5 = u;
|
||||
SB(_m[t].m6, 2, 4, 0);
|
||||
|
@ -22,6 +22,10 @@ enum ObjectType {
|
||||
OBJECT_MAX,
|
||||
};
|
||||
|
||||
/** Unique identifier for an object. */
|
||||
typedef uint16 ObjectID;
|
||||
|
||||
struct Object;
|
||||
struct ObjectSpec;
|
||||
|
||||
#endif /* OBJECT_TYPE_H */
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "../signs_func.h"
|
||||
#include "../aircraft.h"
|
||||
#include "../object_map.h"
|
||||
#include "../object_base.h"
|
||||
#include "../tree_map.h"
|
||||
#include "../company_func.h"
|
||||
#include "../road_cmd.h"
|
||||
@ -1838,8 +1839,8 @@ bool AfterLoadGame()
|
||||
|
||||
/* Reordering/generalisation of the object bits. */
|
||||
ObjectType type = GetObjectType(t);
|
||||
SetObjectAnimationStage(t, type == OBJECT_HQ ? GB(_m[t].m3, 2, 3) : 0);
|
||||
SetObjectOffset(t, type == OBJECT_HQ ? GB(_m[t].m3, 1, 1) | GB(_m[t].m3, 0, 1) << 4 : 0);
|
||||
SB(_m[t].m6, 2, 4, type == OBJECT_HQ ? GB(_m[t].m3, 2, 3) : 0);
|
||||
_m[t].m3 = type == OBJECT_HQ ? GB(_m[t].m3, 1, 1) | GB(_m[t].m3, 0, 1) << 4 : 0;
|
||||
|
||||
/* Make sure those bits are clear as well! */
|
||||
_m[t].m4 = 0;
|
||||
@ -1847,6 +1848,43 @@ bool AfterLoadGame()
|
||||
}
|
||||
}
|
||||
|
||||
if (CheckSavegameVersion(147) && Object::GetNumItems() == 0) {
|
||||
/* Make real objects for object tiles. */
|
||||
for (TileIndex t = 0; t < map_size; t++) {
|
||||
if (!IsTileType(t, MP_OBJECT)) continue;
|
||||
|
||||
if (Town::GetNumItems() == 0) {
|
||||
/* No towns, so remove all objects! */
|
||||
DoClearSquare(t);
|
||||
} else {
|
||||
uint offset = _m[t].m3;
|
||||
|
||||
/* Also move the animation state. */
|
||||
_m[t].m3 = GB(_m[t].m6, 2, 4);
|
||||
SB(_m[t].m6, 2, 4, 0);
|
||||
|
||||
if (offset == 0) {
|
||||
/* No offset, so make the object. */
|
||||
ObjectType type = GetObjectType(t);
|
||||
int size = type == OBJECT_HQ ? 2 : 1;
|
||||
|
||||
Object *o = new Object();
|
||||
o->location.tile = t;
|
||||
o->location.w = size;
|
||||
o->location.h = size;
|
||||
o->build_date = _date;
|
||||
o->town = type == OBJECT_STATUE ? Town::Get(_m[t].m2) : CalcClosestTownFromTile(t, UINT_MAX);
|
||||
_m[t].m2 = o->index;
|
||||
} else {
|
||||
/* We're at an offset, so get the ID from our "root". */
|
||||
TileIndex northern_tile = t - TileXY(GB(offset, 0, 4), GB(offset, 4, 4));
|
||||
assert(IsTileType(northern_tile, MP_OBJECT));
|
||||
_m[t].m2 = _m[northern_tile].m2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CheckSavegameVersion(113)) {
|
||||
/* allow_town_roads is added, set it if town_layout wasn't TL_NO_ROADS */
|
||||
if (_settings_game.economy.town_layout == 0) { // was TL_NO_ROADS
|
||||
|
57
src/saveload/object_sl.cpp
Normal file
57
src/saveload/object_sl.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file object_sl.cpp Code handling saving and loading of objects */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../object_base.h"
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
static const SaveLoad _object_desc[] = {
|
||||
SLE_VAR(Object, location.tile, SLE_UINT32),
|
||||
SLE_VAR(Object, location.w, SLE_FILE_U8 | SLE_VAR_U16),
|
||||
SLE_VAR(Object, location.h, SLE_FILE_U8 | SLE_VAR_U16),
|
||||
SLE_REF(Object, town, REF_TOWN),
|
||||
SLE_VAR(Object, build_date, SLE_UINT32),
|
||||
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
static void Save_OBJS()
|
||||
{
|
||||
Object *o;
|
||||
|
||||
/* Write the objects */
|
||||
FOR_ALL_OBJECTS(o) {
|
||||
SlSetArrayIndex(o->index);
|
||||
SlObject(o, _object_desc);
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_OBJS()
|
||||
{
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Object *o = new (index) Object();
|
||||
SlObject(o, _object_desc);
|
||||
}
|
||||
}
|
||||
|
||||
static void Ptrs_OBJS()
|
||||
{
|
||||
Object *o;
|
||||
FOR_ALL_OBJECTS(o) {
|
||||
SlObject(o, _object_desc);
|
||||
}
|
||||
}
|
||||
|
||||
extern const ChunkHandler _object_chunk_handlers[] = {
|
||||
{ 'OBJS', Save_OBJS, Load_OBJS, Ptrs_OBJS, NULL, CH_ARRAY | CH_LAST},
|
||||
};
|
@ -296,6 +296,7 @@ extern const ChunkHandler _cargopacket_chunk_handlers[];
|
||||
extern const ChunkHandler _autoreplace_chunk_handlers[];
|
||||
extern const ChunkHandler _labelmaps_chunk_handlers[];
|
||||
extern const ChunkHandler _airport_chunk_handlers[];
|
||||
extern const ChunkHandler _object_chunk_handlers[];
|
||||
|
||||
static const ChunkHandler * const _chunk_handlers[] = {
|
||||
_gamelog_chunk_handlers,
|
||||
@ -324,6 +325,7 @@ static const ChunkHandler * const _chunk_handlers[] = {
|
||||
_autoreplace_chunk_handlers,
|
||||
_labelmaps_chunk_handlers,
|
||||
_airport_chunk_handlers,
|
||||
_object_chunk_handlers,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "core/backup_type.hpp"
|
||||
#include "depot_base.h"
|
||||
#include "object_map.h"
|
||||
#include "object_base.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "table/town_land.h"
|
||||
@ -71,9 +72,13 @@ Town::~Town()
|
||||
DeleteWindowById(WC_TOWN_VIEW, this->index);
|
||||
|
||||
/* Check no industry is related to us. */
|
||||
Industry *i;
|
||||
const Industry *i;
|
||||
FOR_ALL_INDUSTRIES(i) assert(i->town != this);
|
||||
|
||||
/* ... and no object is related to us. */
|
||||
const Object *o;
|
||||
FOR_ALL_OBJECTS(o) assert(o->town != this);
|
||||
|
||||
/* Check no tile is related to us. */
|
||||
for (TileIndex tile = 0; tile < MapSize(); ++tile) {
|
||||
switch (GetTileType(tile)) {
|
||||
@ -89,10 +94,6 @@ Town::~Town()
|
||||
assert(!IsTileOwner(tile, OWNER_TOWN) || ClosestTownFromTile(tile, UINT_MAX) != this);
|
||||
break;
|
||||
|
||||
case MP_OBJECT:
|
||||
assert(GetObjectType(tile) != OBJECT_STATUE || GetStatueTownID(tile) != this->index);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -114,6 +115,12 @@ void Town::PostDestructor(size_t index)
|
||||
{
|
||||
InvalidateWindowData(WC_TOWN_DIRECTORY, 0, 0);
|
||||
UpdateNearestTownForRoadTiles(false);
|
||||
|
||||
/* Give objects a new home! */
|
||||
Object *o;
|
||||
FOR_ALL_OBJECTS(o) {
|
||||
if (o->town == NULL) o->town = CalcClosestTownFromTile(o->location.tile, UINT_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2403,7 +2410,21 @@ CommandCost CmdDeleteTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
||||
break;
|
||||
|
||||
case MP_OBJECT:
|
||||
try_clear = GetObjectType(tile) == OBJECT_STATUE && GetStatueTownID(tile) == t->index;
|
||||
if (Town::GetNumItems() == 1) {
|
||||
/* No towns will be left, remove it! */
|
||||
try_clear = true;
|
||||
} else {
|
||||
Object *o = Object::GetByTile(tile);
|
||||
if (o->town == t) {
|
||||
if (GetObjectType(tile) == OBJECT_STATUE) {
|
||||
/* Statue... always remove. */
|
||||
try_clear = true;
|
||||
} else {
|
||||
/* Tell to find a new town. */
|
||||
o->town = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user