mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r24683) -Codechange: Add resolver classes for objects.
This commit is contained in:
parent
d7b62da87b
commit
a9b8b22daf
|
@ -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)
|
||||
ObjectScopeResolver::ObjectScopeResolver(ResolverObject *ro, Object *obj, TileIndex tile, uint8 view)
|
||||
: ScopeResolver(ro)
|
||||
{
|
||||
TileIndex t = object->u.object.tile;
|
||||
return IsValidTile(t) && IsTileType(t, MP_OBJECT) ? GetObjectRandomBits(t) : 0;
|
||||
this->obj = obj;
|
||||
this->tile = tile;
|
||||
this->view = view;
|
||||
}
|
||||
|
||||
static uint32 ObjectGetTriggers(const ResolverObject *object)
|
||||
/* virtual */ uint32 ObjectScopeResolver::GetRandomBits() const
|
||||
{
|
||||
return 0;
|
||||
return IsValidTile(this->tile) && IsTileType(this->tile, MP_OBJECT) ? GetObjectRandomBits(this->tile) : 0;
|
||||
}
|
||||
|
||||
static void ObjectSetTriggers(const ResolverObject *object, int triggers)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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 = {
|
||||
|
|
Loading…
Reference in New Issue