1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-01-24 17:26:41 +00:00

Add a safe pointer model to ScriptInterface, additional bug/crash fixes.

This commit introduces pointer checks to various functions;
so that entity_* will no longer crash or produce weird results
if passed a Node pointer, etc.
The checks are disabled by default, but can be enabled in
ScriptInterface.cpp.

Fixed possible crashes in a few more functions due to missing NULL-checks.

There was a "feature" in the single Lua state that it would keep globals
intact until the game was quit. That made any globals from mods "leak"
into the game or other mods. Now it resets the Lua state when a mod
is loaded or closed.
This commit is contained in:
fgenesis 2012-01-03 04:38:28 +01:00
parent becd31770c
commit 4320b8296b
22 changed files with 298 additions and 103 deletions

View file

@ -28,6 +28,7 @@ Beam::Beams Beam::beams;
Beam::Beam(Vector pos, float angle) : Quad() Beam::Beam(Vector pos, float angle) : Quad()
{ {
addType(SCO_BEAM);
cull = false; cull = false;
trace(); trace();
//rotation.z = angle; //rotation.z = angle;

View file

@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
CollideEntity::CollideEntity() : Entity() CollideEntity::CollideEntity() : Entity()
{ {
addType(SCO_COLLIDE_ENTITY);
this->canBeTargetedByAvatar = true; this->canBeTargetedByAvatar = true;
weight = 0; weight = 0;
bounceAmount = 0.5f; bounceAmount = 0.5f;

View file

@ -167,6 +167,7 @@ bool Entity::canSetBoneLock()
Entity::Entity() : StateMachine(), DFSprite() Entity::Entity() : StateMachine(), DFSprite()
{ {
addType(SCO_ENTITY);
poison = 0.0f; poison = 0.0f;
calledEntityDied = false; calledEntityDied = false;
wasUnderWater = true; wasUnderWater = true;

View file

@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "../BBGE/StateMachine.h" #include "../BBGE/StateMachine.h"
#include "../ExternalLibs/tinyxml.h" #include "../ExternalLibs/tinyxml.h"
#include "../BBGE/SkeletalSprite.h" #include "../BBGE/SkeletalSprite.h"
#include "../BBGE/ScriptObject.h"
#include "DSQ.h" #include "DSQ.h"
#include "Path.h" #include "Path.h"
@ -193,7 +194,7 @@ enum BounceType
BOUNCE_REAL = 1 BOUNCE_REAL = 1
}; };
class Entity : public StateMachine, public DFSprite class Entity : public ScriptObject, public DFSprite, public StateMachine
{ {
public: public:
Entity(); Entity();

View file

@ -40,6 +40,7 @@ bool IngredientData::hasIET(IngredientEffectType iet)
Ingredient::Ingredient(const Vector &pos, IngredientData *data, int amount) Ingredient::Ingredient(const Vector &pos, IngredientData *data, int amount)
: Entity(), data(data), amount(amount), gone(false), used(false) : Entity(), data(data), amount(amount), gone(false), used(false)
{ {
addType(SCO_INGREDIENT);
entityType = ET_INGREDIENT; entityType = ET_INGREDIENT;
position = pos; position = pos;
lifeSpan = 30; lifeSpan = 30;

View file

@ -196,7 +196,8 @@ void Mod::applyStart()
core->clearGarbage(); core->clearGarbage();
recache(); recache();
dsq->continuity.reset(); dsq->continuity.reset();
dsq->scriptInterface.reset();
// load the mod-init.lua file // load the mod-init.lua file
// which is in the root of the mod's folder // which is in the root of the mod's folder
// e.g. _mods/recachetest/ // e.g. _mods/recachetest/
@ -265,6 +266,7 @@ void Mod::stop()
core->settings.runInBackground = false; core->settings.runInBackground = false;
debugMenu = false; debugMenu = false;
shuttingDown = false; shuttingDown = false;
dsq->scriptInterface.reset();
} }
void Mod::update(float dt) void Mod::update(float dt)

View file

@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Path::Path() Path::Path()
{ {
addType(SCO_PATH);
localWarpType = LOCALWARP_NONE; localWarpType = LOCALWARP_NONE;
effectOn = true; effectOn = true;
time = 0; time = 0;

View file

@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "../BBGE/Base.h" #include "../BBGE/Base.h"
#include "../BBGE/Particles.h" #include "../BBGE/Particles.h"
#include "../BBGE/ScriptObject.h"
#include "ScriptInterface.h" #include "ScriptInterface.h"
#undef PATH_MAX // May be set by a system header. #undef PATH_MAX // May be set by a system header.
@ -67,7 +68,7 @@ enum PathShape
PATHSHAPE_CIRCLE = 1 PATHSHAPE_CIRCLE = 1
}; };
class Path class Path : public ScriptObject
{ {
public: public:
Path(); Path();

View file

@ -19,6 +19,7 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#include "ScriptInterface.h" #include "ScriptInterface.h"
#include "../BBGE/ScriptObject.h"
extern "C" extern "C"
{ {
#include "lua.h" #include "lua.h"
@ -37,14 +38,22 @@ extern "C"
#include "../BBGE/MathFunctions.h" #include "../BBGE/MathFunctions.h"
// Define this to 1 to check types of pointers passed to functions,
// and warn if a type mismatch is detected. In this case,
// the pointer is treated as NULL, to avoid crashing or undefined behavior.
//#define CHECK_POINTER_TYPES 1
// If true, send all sort of script errors to errorLog instead of debugLog. // If true, send all sort of script errors to errorLog instead of debugLog.
// On win32, this pops up message boxes which help to locate errors easily, // On win32/OSX, this pops up message boxes which help to locate errors easily,
// but can be annoying for regular gameplay. // but can be annoying for regular gameplay.
const bool loudScriptErrors = false; const bool loudScriptErrors = false;
// This setting causes NULL/0 pointers passed to a function to issue
// a Lua error instead of silently ignoring it.
// Some functions expect this behavior - do not enable!.
const bool throwLuaErrors = false; const bool throwLuaErrors = false;
// Set this to true to complain (via errorLog()) whenever a script tries to // Set this to true to complain whenever a script tries to
// get or set a global variable. // get or set a global variable.
const bool complainOnGlobalVar = false; const bool complainOnGlobalVar = false;
@ -312,10 +321,75 @@ static inline void luaPushPointer(lua_State *L, void *ptr)
lua_pushnumber(L, 0); lua_pushnumber(L, 0);
} }
static std::string luaFormatStackInfo(lua_State *L)
{
lua_Debug ar;
if (lua_getstack(L, 1, &ar))
lua_getinfo(L, "Sl", &ar);
else
{
snprintf(ar.short_src, sizeof(ar.short_src), "???");
ar.currentline = 0;
}
std::ostringstream os;
os << ar.short_src << ":" << ar.currentline;
return os.str();
}
#if CHECK_POINTER_TYPES
// Not intended to be called.
// Because wild typecasting expects X::_objtype to reside at the same relative
// memory location, be sure this is the case before running into undefined behavior later.
// - The C++ standard allows offsetof() only on POD-types. Oh well, it probably works anyways.
// If it does not compile for some reason, comment it out, hope for the best, and go ahead.
void compile_time_assertions()
{
#define oo(cls) offsetof(cls, _objtype)
#define compile_assert(pred) switch(0){case 0:case (pred):;}
compile_assert(oo(Path) == oo(Entity));
compile_assert(oo(Path) == oo(Ingredient));
compile_assert(oo(Path) == oo(CollideEntity));
compile_assert(oo(Path) == oo(ScriptedEntity));
compile_assert(oo(Path) == oo(Beam));
compile_assert(oo(Path) == oo(Shot));
compile_assert(oo(Path) == oo(Web));
compile_assert(oo(Path) == oo(Bone));
compile_assert(oo(Path) == oo(PauseQuad));
compile_assert(oo(Path) == oo(Avatar));
#undef oo
#undef compile_assert
}
template <typename T>
static void ensureType(lua_State *L, T *& ptr, ScriptObjectType ty)
{
if (ptr)
{
ScriptObject *so = (ScriptObject*)(ptr);
if (!so->isType(ty))
{
std::ostringstream os;
os << "WARNING: " << luaFormatStackInfo(L)
<< ": script passed wrong pointer to function (expected type: "
<< ScriptObject::getTypeString(ty) << "; got: "
<< so->getTypeString() << ')';
scriptError(os.str());
ptr = NULL; // note that the pointer is passed by reference
}
}
}
# define ENSURE_TYPE(ptr, ty) ensureType(L, (ptr), (ty))
#else
# define ENSURE_TYPE(ptr, ty)
#endif
static inline static inline
ScriptedEntity *scriptedEntity(lua_State *L, int slot = 1) ScriptedEntity *scriptedEntity(lua_State *L, int slot = 1)
{ {
ScriptedEntity *se = (ScriptedEntity*)lua_touserdata(L, slot); ScriptedEntity *se = (ScriptedEntity*)lua_touserdata(L, slot);
ENSURE_TYPE(se, SCO_SCRIPTED_ENTITY);
if (!se) if (!se)
debugLog("ScriptedEntity invalid pointer."); debugLog("ScriptedEntity invalid pointer.");
return se; return se;
@ -325,25 +399,17 @@ static inline
CollideEntity *collideEntity(lua_State *L, int slot = 1) CollideEntity *collideEntity(lua_State *L, int slot = 1)
{ {
CollideEntity *ce = (CollideEntity*)lua_touserdata(L, slot); CollideEntity *ce = (CollideEntity*)lua_touserdata(L, slot);
ENSURE_TYPE(ce, SCO_COLLIDE_ENTITY);
if (!ce) if (!ce)
debugLog("CollideEntity invalid pointer."); debugLog("CollideEntity invalid pointer.");
return ce ; return ce ;
} }
static inline
RenderObject *object(lua_State *L, int slot = 1)
{
//RenderObject *obj = dynamic_cast<RenderObject*>((RenderObject*)(int(lua_tonumber(L, slot))));
RenderObject *obj = static_cast<RenderObject*>(lua_touserdata(L, slot));
if (!obj)
debugLog("RenderObject invalid pointer");
return obj;
}
static inline static inline
Beam *beam(lua_State *L, int slot = 1) Beam *beam(lua_State *L, int slot = 1)
{ {
Beam *b = (Beam*)lua_touserdata(L, slot); Beam *b = (Beam*)lua_touserdata(L, slot);
ENSURE_TYPE(b, SCO_BEAM);
if (!b) if (!b)
debugLog("Beam invalid pointer."); debugLog("Beam invalid pointer.");
return b; return b;
@ -364,6 +430,7 @@ static inline
Shot *getShot(lua_State *L, int slot = 1) Shot *getShot(lua_State *L, int slot = 1)
{ {
Shot *shot = (Shot*)lua_touserdata(L, slot); Shot *shot = (Shot*)lua_touserdata(L, slot);
ENSURE_TYPE(shot, SCO_SHOT);
return shot; return shot;
} }
@ -371,13 +438,16 @@ static inline
Web *getWeb(lua_State *L, int slot = 1) Web *getWeb(lua_State *L, int slot = 1)
{ {
Web *web = (Web*)lua_touserdata(L, slot); Web *web = (Web*)lua_touserdata(L, slot);
ENSURE_TYPE(web, SCO_WEB);
return web; return web;
} }
static inline static inline
Ingredient *getIng(lua_State *L, int slot = 1) Ingredient *getIng(lua_State *L, int slot = 1)
{ {
return (Ingredient*)lua_touserdata(L, slot); Ingredient *ing = (Ingredient*)lua_touserdata(L, slot);
ENSURE_TYPE(ing, SCO_INGREDIENT);
return ing;
} }
static inline static inline
@ -402,6 +472,7 @@ static inline
Entity *entity(lua_State *L, int slot = 1) Entity *entity(lua_State *L, int slot = 1)
{ {
Entity *ent = (Entity*)lua_touserdata(L, slot); Entity *ent = (Entity*)lua_touserdata(L, slot);
ENSURE_TYPE(ent, SCO_ENTITY);
if (!ent) if (!ent)
{ {
luaErrorMsg(L, "Entity Invalid Pointer"); luaErrorMsg(L, "Entity Invalid Pointer");
@ -421,6 +492,7 @@ static inline
Bone *bone(lua_State *L, int slot = 1) Bone *bone(lua_State *L, int slot = 1)
{ {
Bone *b = (Bone*)lua_touserdata(L, slot); Bone *b = (Bone*)lua_touserdata(L, slot);
ENSURE_TYPE(b, SCO_BONE);
if (!b) if (!b)
{ {
luaErrorMsg(L, "Bone Invalid Pointer"); luaErrorMsg(L, "Bone Invalid Pointer");
@ -445,6 +517,7 @@ static inline
Path *path(lua_State *L, int slot = 1) Path *path(lua_State *L, int slot = 1)
{ {
Path *p = (Path*)lua_touserdata(L, slot); Path *p = (Path*)lua_touserdata(L, slot);
ENSURE_TYPE(p, SCO_PATH);
return p; return p;
} }
@ -463,28 +536,15 @@ static RenderObject *boneToRenderObject(lua_State *L, int slot = 1)
static PauseQuad *getPauseQuad(lua_State *L, int slot = 1) static PauseQuad *getPauseQuad(lua_State *L, int slot = 1)
{ {
PauseQuad *q = (PauseQuad*)lua_touserdata(L, slot); PauseQuad *q = (PauseQuad*)lua_touserdata(L, slot);
if (q) ENSURE_TYPE(q, SCO_PAUSEQUAD);
return q; if (!q)
else
errorLog("Invalid PauseQuad/Particle"); errorLog("Invalid PauseQuad/Particle");
return 0; return q;
} }
static SkeletalSprite *getSkeletalSprite(Entity *e) static SkeletalSprite *getSkeletalSprite(Entity *e)
{ {
Avatar *a; return e ? &e->skeletalSprite : NULL;
ScriptedEntity *se;
SkeletalSprite *skel = 0;
if ((a = dynamic_cast<Avatar*>(e)) != 0)
{
//a->skeletalSprite.transitionAnimate(lua_tostring(L, 2), 0.15, lua_tointeger(L, 3));
skel = &a->skeletalSprite;
}
else if ((se = dynamic_cast<ScriptedEntity*>(e)) != 0)
{
skel = &se->skeletalSprite;
}
return skel;
} }
static bool looksLikeGlobal(const char *s) static bool looksLikeGlobal(const char *s)
@ -537,20 +597,8 @@ luaFunc(indexWarnGlobal)
if (doWarn) if (doWarn)
{ {
lua_Debug ar;
if (lua_getstack(L, 1, &ar))
{
lua_getinfo(L, "Sl", &ar);
}
else
{
snprintf(ar.short_src, sizeof(ar.short_src), "???");
ar.currentline = 0;
}
lua_getinfo(L, "Sl", &ar);
std::ostringstream os; std::ostringstream os;
os << "WARNING: " << ar.short_src << ":" << ar.currentline os << "WARNING: " << luaFormatStackInfo(L)
<< ": script tried to get/call undefined global variable " << ": script tried to get/call undefined global variable "
<< varname; << varname;
scriptError(os.str()); scriptError(os.str());
@ -577,22 +625,11 @@ luaFunc(newindexWarnGlobal)
if (doWarn) if (doWarn)
{ {
lua_Debug ar;
if (lua_getstack(L, 1, &ar))
{
lua_getinfo(L, "Sl", &ar);
}
else
{
snprintf(ar.short_src, sizeof(ar.short_src), "???");
ar.currentline = 0;
}
std::ostringstream os; std::ostringstream os;
os << "WARNING: " << ar.short_src << ":" << ar.currentline os << "WARNING: " << luaFormatStackInfo(L)
<< ": script set global " << ": script set global "
<< (lua_type(L, -2) == LUA_TFUNCTION ? "function" : "variable") << (lua_type(L, -2) == LUA_TFUNCTION ? "function" : "variable")
<< " " << lua_tostring(L, -1); << " " << varname;
scriptError(os.str()); scriptError(os.str());
} }
@ -611,18 +648,8 @@ luaFunc(indexWarnInstance)
lua_remove(L, -3); lua_remove(L, -3);
if (lua_isnil(L, -1)) if (lua_isnil(L, -1))
{ {
lua_Debug ar;
if (lua_getstack(L, 1, &ar))
{
lua_getinfo(L, "Sl", &ar);
}
else
{
snprintf(ar.short_src, sizeof(ar.short_src), "???");
ar.currentline = 0;
}
std::ostringstream os; std::ostringstream os;
os << "WARNING: " << ar.short_src << ":" << ar.currentline os << "WARNING: " << luaFormatStackInfo(L)
<< ": script tried to get/call undefined instance variable " << ": script tried to get/call undefined instance variable "
<< lua_tostring(L, -2); << lua_tostring(L, -2);
errorLog(os.str()); errorLog(os.str());
@ -1819,14 +1846,6 @@ luaFunc(loadMap)
luaFunc(entity_followPath) luaFunc(entity_followPath)
{ {
/*
std::ostringstream os2;
os2 << lua_tointeger(L, 1);
errorLog(os2.str());
std::ostringstream os;
os << "Entity: " << scriptedEntity(L)->name << " moving on Path: " << lua_tostring(L, 2);
debugLog(os.str());
*/
Entity *e = entity(L); Entity *e = entity(L);
if (e) if (e)
{ {
@ -2627,16 +2646,16 @@ luaFunc(entity_setAnimLayerTimeMult)
luaFunc(entity_animate) luaFunc(entity_animate)
{ {
SkeletalSprite *skel = getSkeletalSprite(entity(L)); SkeletalSprite *skel = getSkeletalSprite(entity(L));
float ret = 0;
// 0.15 if (skel)
// 0.2 {
float transition = lua_tonumber(L, 5); float transition = lua_tonumber(L, 5);
if (transition == -1) if (transition == -1)
transition = 0; transition = 0;
else if (transition == 0) else if (transition == 0)
transition = 0.2; transition = 0.2;
float ret = skel->transitionAnimate(lua_tostring(L, 2), transition, lua_tointeger(L, 3), lua_tointeger(L, 4)); ret = skel->transitionAnimate(lua_tostring(L, 2), transition, lua_tointeger(L, 3), lua_tointeger(L, 4));
}
luaReturnNum(ret); luaReturnNum(ret);
} }
@ -3642,13 +3661,17 @@ luaFunc(entity_rotateToVec)
luaFunc(entity_update) luaFunc(entity_update)
{ {
entity(L)->update(lua_tonumber(L, 2)); Entity *e = entity(L);
if (e)
e->update(lua_tonumber(L, 2));
luaReturnNum(0); luaReturnNum(0);
} }
luaFunc(entity_updateSkeletal) luaFunc(entity_updateSkeletal)
{ {
entity(L)->skeletalSprite.update(lua_tonumber(L, 2)); Entity *e = entity(L);
if (e)
e->skeletalSprite.update(lua_tonumber(L, 2));
luaReturnNum(0); luaReturnNum(0);
} }
@ -3667,17 +3690,21 @@ luaFunc(entity_msg)
luaFunc(entity_updateCurrents) luaFunc(entity_updateCurrents)
{ {
luaReturnBool(entity(L)->updateCurrents(lua_tonumber(L, 2))); Entity *e = entity(L);
luaReturnBool(e ? e->updateCurrents(lua_tonumber(L, 2)) : false);
} }
luaFunc(entity_updateLocalWarpAreas) luaFunc(entity_updateLocalWarpAreas)
{ {
luaReturnBool(entity(L)->updateLocalWarpAreas(getBool(L, 2))); Entity *e = entity(L);
luaReturnBool(e ? e->updateLocalWarpAreas(getBool(L, 2)) : false);
} }
luaFunc(entity_updateMovement) luaFunc(entity_updateMovement)
{ {
scriptedEntity(L)->updateMovement(lua_tonumber(L, 2)); ScriptedEntity *e = scriptedEntity(L);
if (e)
e->updateMovement(lua_tonumber(L, 2));
luaReturnNum(0); luaReturnNum(0);
} }
@ -6586,12 +6613,14 @@ luaFunc(entity_getTarget)
luaFunc(entity_getTargetPositionX) luaFunc(entity_getTargetPositionX)
{ {
luaReturnInt(int(entity(L)->getTargetEntity()->position.x)); Entity *e = entity(L);
luaReturnInt(e ? e->getTargetEntity()->position.x : 0);
} }
luaFunc(entity_getTargetPositionY) luaFunc(entity_getTargetPositionY)
{ {
luaReturnInt(int(entity(L)->getTargetEntity()->position.y)); Entity *e = entity(L);
luaReturnNum(e ? e->getTargetEntity()->position.y : 0);
} }
luaFunc(entity_isNearObstruction) luaFunc(entity_isNearObstruction)
@ -7095,7 +7124,6 @@ luaFunc(entity_setFlag)
luaFunc(entity_getFlag) luaFunc(entity_getFlag)
{ {
Entity *e = entity(L); Entity *e = entity(L);
int v = lua_tonumber(L, 2);
int ret = 0; int ret = 0;
if (e) if (e)
{ {
@ -8821,9 +8849,21 @@ static const struct {
// F U N C T I O N S // F U N C T I O N S
//============================================================================================ //============================================================================================
ScriptInterface::ScriptInterface()
: baseState(NULL)
{
}
void ScriptInterface::init() void ScriptInterface::init()
{ {
baseState = createLuaVM(); if (!baseState)
baseState = createLuaVM();
}
void ScriptInterface::reset()
{
shutdown();
init();
} }
lua_State *ScriptInterface::createLuaVM() lua_State *ScriptInterface::createLuaVM()
@ -8987,6 +9027,8 @@ void ScriptInterface::collectGarbage()
void ScriptInterface::shutdown() void ScriptInterface::shutdown()
{ {
destroyLuaVM(baseState);
baseState = NULL;
} }
Script *ScriptInterface::openScript(const std::string &file, bool ignoremissing /* = false */) Script *ScriptInterface::openScript(const std::string &file, bool ignoremissing /* = false */)

View file

@ -77,7 +77,9 @@ protected:
class ScriptInterface class ScriptInterface
{ {
public: public:
ScriptInterface();
void init(); void init();
void reset();
void collectGarbage(); void collectGarbage();
void shutdown(); void shutdown();

View file

@ -27,7 +27,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
bool ScriptedEntity::runningActivation = false; bool ScriptedEntity::runningActivation = false;
ScriptedEntity::ScriptedEntity(const std::string &scriptName, Vector position, EntityType et) : CollideEntity(), Segmented(2, 26) ScriptedEntity::ScriptedEntity(const std::string &scriptName, Vector position, EntityType et) : CollideEntity(), Segmented(2, 26)
{ {
addType(SCO_SCRIPTED_ENTITY);
crushDelay = 0; crushDelay = 0;
autoSkeletalSpriteUpdate = true; autoSkeletalSpriteUpdate = true;
script = 0; script = 0;

View file

@ -323,6 +323,7 @@ Shot::Shot(DamageType damageType, Entity *firer, Vector pos, Entity *target, std
Shot::Shot() : Quad(), Segmented(0,0) Shot::Shot() : Quad(), Segmented(0,0)
{ {
addType(SCO_SHOT);
extraDamage= 0; extraDamage= 0;
waveTimer = rand()%314; waveTimer = rand()%314;
emitter = 0; emitter = 0;

View file

@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "CollideEntity.h" #include "CollideEntity.h"
#include "Segmented.h" #include "Segmented.h"
#include "../BBGE/Particles.h" #include "../BBGE/Particles.h"
#include "../BBGE/ScriptObject.h"
struct ShotData struct ShotData
{ {
@ -69,7 +70,7 @@ struct ShotData
}; };
class Shot : public Quad, public Segmented class Shot : public ScriptObject, public Quad, public Segmented
{ {
public: public:
//Shot(DamageType damageType, Entity *firer, Vector pos, Entity *target, std::string tex="", float homingness=1000, int maxSpeed=400, int segments=10, float segMin=0.1, float segMax=5, float damage = 1, float lifeTime = 0); //Shot(DamageType damageType, Entity *firer, Vector pos, Entity *target, std::string tex="", float homingness=1000, int maxSpeed=400, int segments=10, float segMin=0.1, float segMax=5, float damage = 1, float lifeTime = 0);
@ -136,7 +137,7 @@ protected:
void onUpdate(float dt); void onUpdate(float dt);
}; };
class Beam : public Quad class Beam : public ScriptObject, public Quad
{ {
public: public:
Beam(Vector pos, float angle); Beam(Vector pos, float angle);

View file

@ -27,6 +27,7 @@ Web::Webs Web::webs;
Web::Web() : RenderObject() Web::Web() : RenderObject()
{ {
addType(SCO_WEB);
webs.push_back(this); webs.push_back(this);
cull = false; cull = false;
parentEntity = 0; parentEntity = 0;

View file

@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "../BBGE/Quad.h" #include "../BBGE/Quad.h"
#include "Entity.h" #include "Entity.h"
class Web : public RenderObject class Web : public ScriptObject, public RenderObject
{ {
public: public:
Web(); Web();

View file

@ -918,6 +918,7 @@ void Quad::onSetTexture()
PauseQuad::PauseQuad() : Quad(), pauseLevel(0) PauseQuad::PauseQuad() : Quad(), pauseLevel(0)
{ {
addType(SCO_PAUSEQUAD);
} }
void PauseQuad::onUpdate(float dt) void PauseQuad::onUpdate(float dt)

View file

@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define __quad__ #define __quad__
#include "RenderObject.h" #include "RenderObject.h"
#include "ScriptObject.h"
class QuadLight class QuadLight
{ {
@ -149,7 +150,7 @@ private:
void initQuad(); void initQuad();
}; };
class PauseQuad : public Quad class PauseQuad : public ScriptObject, public Quad
{ {
public: public:
PauseQuad(); PauseQuad();

60
BBGE/ScriptObject.cpp Normal file
View file

@ -0,0 +1,60 @@
/*
Copyright (C) 2007, 2012 - Bit-Blot
This file is part of Aquaria.
Aquaria 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; either version 2
of the License, or (at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <sstream>
#include "ScriptObject.h"
static const char *scriptObjTypeNames[] =
{
/* (1 << 0) */ "Entity",
/* (1 << 1) */ "Ingredient",
/* (1 << 2) */ "CollideEntity",
/* (1 << 3) */ "ScriptedEntity",
/* (1 << 4) */ "Beam",
/* (1 << 5) */ "Shot",
/* (1 << 6) */ "Web",
/* (1 << 7) */ "Bone",
/* (1 << 8) */ "Path/Node",
/* (1 << 9) */ "PauseQuad",
NULL
};
std::string ScriptObject::getTypeString(unsigned int ty)
{
if (ty == SCO_NONE)
return "NO TYPE";
bool more = false;
std::ostringstream os;
for (int i = 0; scriptObjTypeNames[i]; ++i)
{
if (ty & (1 << i))
{
if (more)
os << ", ";
os << scriptObjTypeNames[i];
more = true;
}
}
return os.str();
}

74
BBGE/ScriptObject.h Normal file
View file

@ -0,0 +1,74 @@
/*
Copyright (C) 2007, 2012 - Bit-Blot
This file is part of Aquaria.
Aquaria 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; either version 2
of the License, or (at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#pragma once
enum ScriptObjectType
{
SCO_NONE = 0x0000,
// If you change this enum, do not forget to adjust the string array in the cpp,
// and to add additional compile time assertions to ScriptInterface.cpp as necessary!
SCO_ENTITY = 0x0001,
SCO_INGREDIENT = 0x0002,
SCO_COLLIDE_ENTITY = 0x0004,
SCO_SCRIPTED_ENTITY = 0x0008,
SCO_BEAM = 0x0010,
SCO_SHOT = 0x0020,
SCO_WEB = 0x0040,
SCO_BONE = 0x0080,
SCO_PATH = 0x0100,
SCO_PAUSEQUAD = 0x0200,
SCO_FORCE_32BIT = 0xFFFFFFFF
};
class ScriptObject
{
public:
ScriptObject()
: _objtype(SCO_NONE)
{
}
virtual ~ScriptObject() {}
inline void addType(ScriptObjectType ty)
{
_objtype = ScriptObjectType(int(ty) | int(_objtype)); // prevent the compiler from crying
}
inline bool isType(ScriptObjectType bt) const
{
return (_objtype & bt) != 0;
}
inline std::string getTypeString() const
{
return getTypeString(_objtype);
}
static std::string getTypeString(unsigned int ty);
// public to allow the static compile check in ScriptInterface.cpp to work
ScriptObjectType _objtype;
};

View file

@ -42,6 +42,7 @@ void SkeletalKeyframe::copyAllButTime(SkeletalKeyframe *copy)
Bone::Bone() : Quad() Bone::Bone() : Quad()
{ {
addType(SCO_BONE);
fileRenderQuad = true; fileRenderQuad = true;
skeleton = 0; skeleton = 0;
generateCollisionMask = true; generateCollisionMask = true;

View file

@ -37,7 +37,7 @@ enum AnimationCommand
class ParticleEffect; class ParticleEffect;
class SkeletalSprite; class SkeletalSprite;
class Bone : public Quad class Bone : public ScriptObject, public Quad
{ {
public: public:
Bone(); Bone();

View file

@ -362,6 +362,7 @@ SET(BBGE_SRCS
${BBGEDIR}/Resource.cpp ${BBGEDIR}/Resource.cpp
${BBGEDIR}/RoundedRect.cpp ${BBGEDIR}/RoundedRect.cpp
${BBGEDIR}/ScreenTransition.cpp ${BBGEDIR}/ScreenTransition.cpp
${BBGEDIR}/ScriptObject.cpp
${BBGEDIR}/Shader.cpp ${BBGEDIR}/Shader.cpp
${BBGEDIR}/SkeletalSprite.cpp ${BBGEDIR}/SkeletalSprite.cpp
${BBGEDIR}/Slider.cpp ${BBGEDIR}/Slider.cpp