summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/newgrf_object.cpp160
-rw-r--r--src/newgrf_object.h44
-rw-r--r--src/newgrf_spritegroup.h5
-rw-r--r--src/table/newgrf_debug_data.h7
4 files changed, 111 insertions, 105 deletions
diff --git a/src/newgrf_object.cpp b/src/newgrf_object.cpp
index ab4ac147e..f09e94b3b 100644
--- a/src/newgrf_object.cpp
+++ b/src/newgrf_object.cpp
@@ -16,8 +16,6 @@
#include "newgrf_class_func.h"
#include "newgrf_object.h"
#include "newgrf_sound.h"
-#include "newgrf_spritegroup.h"
-#include "newgrf_town.h"
#include "object_base.h"
#include "object_map.h"
#include "tile_cmd.h"
@@ -118,23 +116,19 @@ bool NewGRFClass<Tspec, Tid, Tmax>::IsUIAvailable(uint index) const
INSTANTIATE_NEWGRF_CLASS_METHODS(ObjectClass, ObjectSpec, ObjectClassID, OBJECT_CLASS_MAX)
-
-static uint32 ObjectGetRandomBits(const ResolverObject *object)
-{
- TileIndex t = object->u.object.tile;
- return IsValidTile(t) && IsTileType(t, MP_OBJECT) ? GetObjectRandomBits(t) : 0;
-}
-
-static uint32 ObjectGetTriggers(const ResolverObject *object)
+ObjectScopeResolver::ObjectScopeResolver(ResolverObject *ro, Object *obj, TileIndex tile, uint8 view)
+ : ScopeResolver(ro)
{
- return 0;
+ this->obj = obj;
+ this->tile = tile;
+ this->view = view;
}
-static void ObjectSetTriggers(const ResolverObject *object, int triggers)
+/* virtual */ uint32 ObjectScopeResolver::GetRandomBits() const
{
+ return IsValidTile(this->tile) && IsTileType(this->tile, MP_OBJECT) ? GetObjectRandomBits(this->tile) : 0;
}
-
/**
* Make an analysis of a tile and get the object type.
* @param tile TileIndex of the tile to query
@@ -232,21 +226,13 @@ static uint32 GetCountAndDistanceOfClosestInstance(byte local_id, uint32 grfid,
}
/** Used by the resolver to get values for feature 0F deterministic spritegroups. */
-static uint32 ObjectGetVariable(const ResolverObject *object, byte variable, uint32 parameter, bool *available)
+/* virtual */ uint32 ObjectScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const
{
- const Object *o = object->u.object.o;
- TileIndex tile = object->u.object.tile;
-
- if (object->scope == VSG_SCOPE_PARENT) {
- /* Pass the request on to the town of the object */
- return TownGetVariable(variable, parameter, available, (o == NULL) ? ClosestTownFromTile(tile, UINT_MAX) : o->town, object->grffile);
- }
-
/* We get the town from the object, or we calculate the closest
* town if we need to when there's no object. */
const Town *t = NULL;
- if (o == NULL) {
+ if (this->obj == NULL) {
switch (variable) {
/* Allow these when there's no object. */
case 0x41:
@@ -259,8 +245,8 @@ static uint32 ObjectGetVariable(const ResolverObject *object, byte variable, uin
/* Allow these, but find the closest town. */
case 0x45:
case 0x46:
- if (!IsValidTile(tile)) goto unhandled;
- t = ClosestTownFromTile(tile, UINT_MAX);
+ if (!IsValidTile(this->tile)) goto unhandled;
+ t = ClosestTownFromTile(this->tile, UINT_MAX);
break;
/* Construction date */
@@ -270,7 +256,7 @@ static uint32 ObjectGetVariable(const ResolverObject *object, byte variable, uin
case 0x44: return _current_company;
/* Object view */
- case 0x48: return object->u.object.view;
+ case 0x48: return this->view;
/*
* Disallow the rest:
@@ -284,62 +270,64 @@ static uint32 ObjectGetVariable(const ResolverObject *object, byte variable, uin
}
/* If there's an invalid tile, then we don't have enough information at all. */
- if (!IsValidTile(tile)) goto unhandled;
+ if (!IsValidTile(this->tile)) goto unhandled;
} else {
- t = o->town;
+ t = this->obj->town;
}
switch (variable) {
/* Relative position. */
case 0x40: {
- uint offset = tile - o->location.tile;
+ uint offset = this->tile - this->obj->location.tile;
uint offset_x = TileX(offset);
uint offset_y = TileY(offset);
return offset_y << 20 | offset_x << 16 | offset_y << 8 | offset_x;
}
/* Tile information. */
- case 0x41: return GetTileSlope(tile) << 8 | GetTerrainType(tile);
+ case 0x41: return GetTileSlope(this->tile) << 8 | GetTerrainType(this->tile);
/* Construction date */
- case 0x42: return o->build_date;
+ case 0x42: return this->obj->build_date;
/* Animation counter */
- case 0x43: return GetAnimationFrame(tile);
+ case 0x43: return GetAnimationFrame(this->tile);
/* Object founder information */
- case 0x44: return GetTileOwner(tile);
+ case 0x44: return GetTileOwner(this->tile);
/* Get town zone and Manhattan distance of closest town */
- case 0x45: return GetTownRadiusGroup(t, tile) << 16 | min(DistanceManhattan(tile, t->xy), 0xFFFF);
+ case 0x45: return GetTownRadiusGroup(t, this->tile) << 16 | min(DistanceManhattan(this->tile, t->xy), 0xFFFF);
/* Get square of Euclidian distance of closes town */
- case 0x46: return GetTownRadiusGroup(t, tile) << 16 | min(DistanceSquare(tile, t->xy), 0xFFFF);
+ case 0x46: return GetTownRadiusGroup(t, this->tile) << 16 | min(DistanceSquare(this->tile, t->xy), 0xFFFF);
/* Object colour */
- case 0x47: return o->colour;
+ case 0x47: return this->obj->colour;
/* Object view */
- case 0x48: return o->view;
+ case 0x48: return this->obj->view;
/* Get object ID at offset param */
- case 0x60: return GetObjectIDAtOffset(GetNearbyTile(parameter, tile), object->grffile->grfid);
+ case 0x60: return GetObjectIDAtOffset(GetNearbyTile(parameter, this->tile), this->ro->grffile->grfid);
/* Get random tile bits at offset param */
- case 0x61:
- tile = GetNearbyTile(parameter, tile);
- return (IsTileType(tile, MP_OBJECT) && Object::GetByTile(tile) == o) ? GetObjectRandomBits(tile) : 0;
+ case 0x61: {
+ TileIndex tile = GetNearbyTile(parameter, this->tile);
+ return (IsTileType(tile, MP_OBJECT) && Object::GetByTile(tile) == this->obj) ? GetObjectRandomBits(tile) : 0;
+ }
/* Land info of nearby tiles */
- case 0x62: return GetNearbyObjectTileInformation(parameter, tile, o == NULL ? INVALID_OBJECT : o->index, object->grffile->grf_version >= 8);
+ case 0x62: return GetNearbyObjectTileInformation(parameter, this->tile, this->obj == NULL ? INVALID_OBJECT : this->obj->index, this->ro->grffile->grf_version >= 8);
/* Animation counter of nearby tile */
- case 0x63:
- tile = GetNearbyTile(parameter, tile);
- return (IsTileType(tile, MP_OBJECT) && Object::GetByTile(tile) == o) ? GetAnimationFrame(tile) : 0;
+ case 0x63: {
+ TileIndex tile = GetNearbyTile(parameter, this->tile);
+ return (IsTileType(tile, MP_OBJECT) && Object::GetByTile(tile) == this->obj) ? GetAnimationFrame(tile) : 0;
+ }
/* Count of object, distance of closest instance */
- case 0x64: return GetCountAndDistanceOfClosestInstance(parameter, object->grffile->grfid, tile, o);
+ case 0x64: return GetCountAndDistanceOfClosestInstance(parameter, this->ro->grffile->grfid, this->tile, this->obj);
}
unhandled:
@@ -349,7 +337,7 @@ unhandled:
return UINT_MAX;
}
-static const SpriteGroup *ObjectResolveReal(const ResolverObject *object, const RealSpriteGroup *group)
+/* virtual */ const SpriteGroup *ObjectResolverObject::ResolveReal(const RealSpriteGroup *group) const
{
/* Objects do not have 'real' groups */
return NULL;
@@ -373,44 +361,36 @@ static const SpriteGroup *GetObjectSpriteGroup(const ObjectSpec *spec, const Obj
}
-/**
- * Store a value into the persistent storage of the object's parent.
- * @param object Object that we want to query.
- * @param pos Position in the persistent storage to use.
- * @param value Value to store.
- */
-void ObjectStorePSA(ResolverObject *object, uint pos, int32 value)
+ObjectResolverObject::ObjectResolverObject(const ObjectSpec *spec, Object *obj, TileIndex tile, uint8 view,
+ CallbackID callback, uint32 param1, uint32 param2)
+ : ResolverObject(spec->grf_prop.grffile, callback, param1, param2), object_scope(this, obj, tile, view)
{
- /* Objects have no persistent storage. */
- Object *o = object->u.object.o;
- if (object->scope != VSG_SCOPE_PARENT || o == NULL) return;
+ this->town_scope = NULL;
+}
- /* Pass the request on to the town of the object */
- TownStorePSA(o->town, object->grffile, pos, value);
+ObjectResolverObject::~ObjectResolverObject()
+{
+ delete this->town_scope;
}
/**
- * Returns a resolver object to be used with feature 0F spritegroups.
+ * Get the town resolver scope that belongs to this object resolver.
+ * On the first call, the town scope is created (if possible).
+ * @return Town scope, if available.
*/
-static void NewObjectResolver(ResolverObject *res, const ObjectSpec *spec, Object *o, TileIndex tile, uint8 view = 0)
+TownScopeResolver *ObjectResolverObject::GetTown()
{
- res->GetRandomBits = ObjectGetRandomBits;
- res->GetTriggers = ObjectGetTriggers;
- res->SetTriggers = ObjectSetTriggers;
- res->GetVariable = ObjectGetVariable;
- res->ResolveRealMethod = ObjectResolveReal;
- res->StorePSA = ObjectStorePSA;
-
- res->u.object.o = o;
- res->u.object.tile = tile;
- res->u.object.view = view;
-
- res->callback = CBID_NO_CALLBACK;
- res->callback_param1 = 0;
- res->callback_param2 = 0;
- res->ResetState();
-
- res->grffile = spec->grf_prop.grffile;
+ if (this->town_scope == NULL) {
+ Town *t;
+ if (this->object_scope.obj != NULL) {
+ t = this->object_scope.obj->town;
+ } else {
+ t = ClosestTownFromTile(this->object_scope.tile, UINT_MAX);
+ }
+ if (t == NULL) return NULL;
+ this->town_scope = new TownScopeResolver(this, t, this->object_scope.obj == NULL);
+ }
+ return this->town_scope;
}
/**
@@ -426,12 +406,7 @@ static void NewObjectResolver(ResolverObject *res, const ObjectSpec *spec, Objec
*/
uint16 GetObjectCallback(CallbackID callback, uint32 param1, uint32 param2, const ObjectSpec *spec, Object *o, TileIndex tile, uint8 view)
{
- ResolverObject object;
- NewObjectResolver(&object, spec, o, tile, view);
- object.callback = callback;
- object.callback_param1 = param1;
- object.callback_param2 = param2;
-
+ ObjectResolverObject object(spec, o, tile, view, callback, param1, param2);
const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, o), &object);
if (group == NULL) return CALLBACK_FAILED;
@@ -472,9 +447,8 @@ static void DrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *grou
*/
void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec)
{
- ResolverObject object;
Object *o = Object::GetByTile(ti->tile);
- NewObjectResolver(&object, spec, o, ti->tile);
+ ObjectResolverObject object(spec, o, ti->tile);
const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, o), &object);
if (group == NULL || group->type != SGT_TILELAYOUT) return;
@@ -491,9 +465,7 @@ void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec)
*/
void DrawNewObjectTileInGUI(int x, int y, const ObjectSpec *spec, uint8 view)
{
- ResolverObject object;
- NewObjectResolver(&object, spec, NULL, INVALID_TILE, view);
-
+ ObjectResolverObject object(spec, NULL, INVALID_TILE, view);
const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, NULL), &object);
if (group == NULL || group->type != SGT_TILELAYOUT) return;
@@ -588,13 +560,3 @@ void TriggerObjectAnimation(Object *o, ObjectAnimationTrigger trigger, const Obj
TriggerObjectTileAnimation(o, tile, trigger, spec);
}
}
-
-/**
- * Resolve an object's spec and such so we can get a variable.
- * @param ro The resolver object to fill.
- * @param index The object tile to get the data from.
- */
-void GetObjectResolver(ResolverObject *ro, uint index)
-{
- NewObjectResolver(ro, ObjectSpec::GetByTile(index), Object::GetByTile(index), index);
-}
diff --git a/src/newgrf_object.h b/src/newgrf_object.h
index bc2f64f3c..c1b79959d 100644
--- a/src/newgrf_object.h
+++ b/src/newgrf_object.h
@@ -13,6 +13,8 @@
#define NEWGRF_OBJECT_H
#include "newgrf_callbacks.h"
+#include "newgrf_spritegroup.h"
+#include "newgrf_town.h"
#include "economy_func.h"
#include "date_type.h"
#include "object_type.h"
@@ -90,6 +92,48 @@ struct ObjectSpec {
static const ObjectSpec *GetByTile(TileIndex tile);
};
+struct ObjectScopeResolver : public ScopeResolver {
+ struct Object *obj; ///< The object the callback is ran for.
+ TileIndex tile; ///< The tile related to the object.
+ uint8 view; ///< The view of the object.
+
+ ObjectScopeResolver(ResolverObject *ro, Object *obj, TileIndex tile, uint8 view = 0);
+
+ /* virtual */ uint32 GetRandomBits() const;
+ /* virtual */ uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
+};
+
+/** A resolver object to be used with feature 0F spritegroups. */
+struct ObjectResolverObject : public ResolverObject {
+ ObjectScopeResolver object_scope;
+ TownScopeResolver *town_scope;
+
+ ObjectResolverObject(const ObjectSpec *spec, Object *o, TileIndex tile, uint8 view = 0,
+ CallbackID callback = CBID_NO_CALLBACK, uint32 param1 = 0, uint32 param2 = 0);
+ ~ObjectResolverObject();
+
+ /* virtual */ ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0)
+ {
+ switch (scope) {
+ case VSG_SCOPE_SELF:
+ return &this->object_scope;
+
+ case VSG_SCOPE_PARENT: {
+ TownScopeResolver *tsr = this->GetTown();
+ if (tsr != NULL) return tsr;
+ /* FALL-THROUGH */
+ }
+
+ default: return &this->default_scope; // XXX return &ResolverObject::GetScope(scope, relative);
+ }
+ }
+
+ const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const;
+
+private:
+ TownScopeResolver *GetTown();
+};
+
/** Struct containing information relating to station classes. */
typedef NewGRFClass<ObjectSpec, ObjectClassID, OBJECT_CLASS_MAX> ObjectClass;
diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h
index 41a6c2e25..d68f2e316 100644
--- a/src/newgrf_spritegroup.h
+++ b/src/newgrf_spritegroup.h
@@ -390,11 +390,6 @@ struct ResolverObject {
byte layout; ///< Layout of the airport to build.
TileIndex tile; ///< Tile for the callback, only valid for airporttile callbacks.
} airport;
- struct {
- struct Object *o; ///< The object the callback is ran for.
- TileIndex tile; ///< The tile related to the object.
- uint8 view; ///< The view of the object.
- } object;
} u;
uint32 (*GetRandomBits)(const struct ResolverObject*);
diff --git a/src/table/newgrf_debug_data.h b/src/table/newgrf_debug_data.h
index c7f936587..8a669fee5 100644
--- a/src/table/newgrf_debug_data.h
+++ b/src/table/newgrf_debug_data.h
@@ -361,7 +361,12 @@ class NIHObject : public NIHelper {
const void *GetSpec(uint index) const { return ObjectSpec::GetByTile(index); }
void SetStringParameters(uint index) const { this->SetObjectAtStringParameters(STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT_OBJECT, INVALID_STRING_ID, index); }
uint32 GetGRFID(uint index) const { return (this->IsInspectable(index)) ? ObjectSpec::GetByTile(index)->grf_prop.grffile->grfid : 0; }
- void Resolve(ResolverObject *ro, uint32 index) const { extern void GetObjectResolver(ResolverObject *ro, uint index); GetObjectResolver(ro, index); }
+
+ /* virtual */ uint Resolve(uint index, uint var, uint param, bool *avail) const
+ {
+ ObjectResolverObject ro(ObjectSpec::GetByTile(index), Object::GetByTile(index), index);
+ return ro.GetScope(ro.scope)->GetVariable(var, param, avail);
+ }
};
static const NIFeature _nif_object = {