1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2024-12-26 14:45:48 +00:00

Shot Lua API update + related internal changes.

With this change, shots are no longer stored in a std::list.
In the current code, the global shot store may be modified while iterating,
this did not cause problems with the list implementation,
but would easily crash if a shot is removed while iterating.
To fix this, a 2nd vector stores shots to be deleted from the global store
and does so when no iteration is in progress and modifying the vector is
safe.

Added functions:

getFirstShot -- for iterating over all shots on the map
getNextShot
shot_setFirer
shot_setExtraDamage
shot_getExtraDamage
shot_getDamage
shot_getDamageType
shot_getName
This commit is contained in:
fgenesis 2013-03-06 02:06:52 +01:00
parent eef2289fb2
commit 0784d1b9df
7 changed files with 134 additions and 38 deletions

View file

@ -2921,7 +2921,7 @@ void Avatar::formAbility(int ability)
for (i = Shot::shots.begin(); i != Shot::shots.end(); i++)
{
Shot *s = (*i);
if (s->shotData && !s->shotData->invisible)
if (s->isActive() && s->shotData && !s->shotData->invisible)
{
if (!s->firer || s->firer->getEntityType()==ET_ENEMY)
{
@ -4935,23 +4935,23 @@ void Avatar::updateAura(float dt)
*/
for (Shot::Shots::iterator i = Shot::shots.begin(); i != Shot::shots.end(); ++i)
{
//&& (*i)->life > 0.2f
if ((*i) && dsq->game->isDamageTypeEnemy((*i)->getDamageType()) && (*i)->firer != this
&& (!(*i)->shotData || !(*i)->shotData->ignoreShield))
Shot *s = *i;
if (s->isActive() && dsq->game->isDamageTypeEnemy(s->getDamageType()) && s->firer != this
&& (!s->shotData || !s->shotData->ignoreShield))
{
Vector diff = (*i)->position - shieldPosition;
Vector diff = s->position - shieldPosition;
if (diff.getSquaredLength2D() < sqr(AURA_SHIELD_RADIUS))
{
shieldPoints -= (*i)->getDamage();
shieldPoints -= s->getDamage();
auraHitEmitter.start();
dsq->spawnParticleEffect("ReflectShot", (*i)->position);
dsq->spawnParticleEffect("ReflectShot", s->position);
core->sound->playSfx("Shield-Hit");
(*i)->position += diff;
//(*i)->target = 0;
diff.setLength2D((*i)->maxSpeed);
(*i)->velocity = diff;
(*i)->reflectFromEntity(this);
s->position += diff;
//s->target = 0;
diff.setLength2D(s->maxSpeed);
s->velocity = diff;
s->reflectFromEntity(this);
}
}
}

View file

@ -4665,6 +4665,8 @@ void DSQ::onUpdate(float dt)
lockMouse();
Network::update();
Shot::clearShotGarbage();
}
void DSQ::lockMouse()

View file

@ -2912,7 +2912,7 @@ void Entity::doSpellAvoidance(float dt, int range, float mod)
{
Shot *s = (Shot*)(*i);
if ((s->position - this->position).getSquaredLength2D() < sqr(range))
if (s->isActive() && (s->position - this->position).getSquaredLength2D() < sqr(range))
{
for (int j = 0; j < ignoreShotDamageTypes.size(); j++)
{

View file

@ -6253,6 +6253,7 @@ void Game::applyState()
//core->afterEffectManager->addEffect(new RippleEffect());
}
Shot::shots.clear();
Shot::deleteShots.clear();
backdropQuad = 0;
clearObsRows();
inGameMenu = false;
@ -8491,7 +8492,7 @@ void Game::handleShotCollisions(Entity *e, bool hasShield)
for (Shot::Shots::iterator i = Shot::shots.begin(); i != Shot::shots.end(); i++)
{
Shot *shot = *i;
if (isEntityCollideWithShot(e, shot) && (!hasShield || (!shot->shotData || !shot->shotData->ignoreShield)))
if (shot->isActive() && isEntityCollideWithShot(e, shot) && (!hasShield || (!shot->shotData || !shot->shotData->ignoreShield)))
{
Vector collidePoint = e->position+e->offset;
if (e->getNumTargetPoints()>0)
@ -8523,7 +8524,7 @@ void Game::handleShotCollisionsSkeletal(Entity *e)
for (Shot::Shots::iterator i = Shot::shots.begin(); i != Shot::shots.end(); i++)
{
Shot *shot = *i;
if (isEntityCollideWithShot(e, shot))
if (shot->isActive() && isEntityCollideWithShot(e, shot))
{
Bone *b = collideSkeletalVsCircle(e, shot->position, shot->collideRadius);
if (b)
@ -8540,7 +8541,7 @@ void Game::handleShotCollisionsHair(Entity *e, int num)
for (Shot::Shots::iterator i = Shot::shots.begin(); i != Shot::shots.end(); i++)
{
Shot *shot = *i;
if (isEntityCollideWithShot(e, shot))
if (shot->isActive() && isEntityCollideWithShot(e, shot))
{
bool b = collideHairVsCircle(e, num, shot->position, 8);
if (b)
@ -10886,6 +10887,7 @@ void Game::removeState()
debugLog("killAllShots");
Shot::killAllShots();
Shot::clearShotGarbage();
debugLog("killAllBeams");
Beam::killAllBeams();
debugLog("killAllWebs");

View file

@ -1811,6 +1811,22 @@ luaFunc(web_getNumPoints)
luaReturnInt(num);
}
luaFunc(getFirstShot)
{
luaReturnPtr(Shot::getFirstShot());
}
luaFunc(getNextShot)
{
luaReturnPtr(Shot::getNextShot());
}
luaFunc(shot_getName)
{
Shot *s = getShot(L);
luaReturnStr(s ? s->getName() : "");
}
luaFunc(shot_setOut)
{
Shot *shot = getShot(L);
@ -1859,11 +1875,26 @@ luaFunc(shot_getFirer)
luaReturnPtr(shot ? shot->firer : NULL);
}
luaFunc(shot_setFirer)
{
Shot *shot = getShot(L);
if(shot)
{
Entity *e = lua_isuserdata(L, 2) ? entity(L, 2) : NULL;
shot->firer = e;
}
luaReturnNil();
}
luaFunc(shot_setTarget)
{
Shot *shot = getShot(L);
if(shot)
shot->setTarget(entity(L, 2));
{
Entity *e = lua_isuserdata(L, 2) ? entity(L, 2) : NULL;
shot->setTarget(e);
}
luaReturnNil();
}
@ -1873,6 +1904,32 @@ luaFunc(shot_getTarget)
luaReturnPtr(shot ? shot->target : NULL);
}
luaFunc(shot_setExtraDamage)
{
Shot *shot = getShot(L);
if(shot)
shot->extraDamage = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(shot_getExtraDamage)
{
Shot *shot = getShot(L);
luaReturnNum(shot ? shot->extraDamage : 0.0f);
}
luaFunc(shot_getDamage)
{
Shot *shot = getShot(L);
luaReturnNum(shot ? shot->getDamage() : 0.0f);
}
luaFunc(shot_getDamageType)
{
Shot *shot = getShot(L);
luaReturnNum(shot ? shot->getDamageType() : DT_NONE);
}
luaFunc(entity_setVel)
{
Entity *e = entity(L);
@ -5275,7 +5332,10 @@ luaFunc(entity_getRandomTargetPoint)
luaFunc(playVisualEffect)
{
dsq->playVisualEffect(lua_tonumber(L, 1), Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)));
Entity *target = NULL;
if(lua_isuserdata(L, 4))
target = entity(L, 4);
dsq->playVisualEffect(lua_tonumber(L, 1), Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)), target);
luaReturnNil();
}
@ -7959,13 +8019,21 @@ static const struct {
luaRegister(createSpore),
luaRegister(getFirstShot),
luaRegister(getNextShot),
luaRegister(shot_setAimVector),
luaRegister(shot_setOut),
luaRegister(shot_getEffectTime),
luaRegister(shot_isIgnoreShield),
luaRegister(shot_setFirer),
luaRegister(shot_getFirer),
luaRegister(shot_setTarget),
luaRegister(shot_getTarget),
luaRegister(shot_setExtraDamage),
luaRegister(shot_getExtraDamage),
luaRegister(shot_getDamage),
luaRegister(shot_getDamageType),
luaRegister(shot_getName),
luaRegister(entity_pathBurst),
luaRegister(entity_handleShotCollisions),
luaRegister(entity_handleShotCollisionsSkeletal),

View file

@ -26,7 +26,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "../BBGE/MathFunctions.h"
Shot::Shots Shot::shots;
Shot::Shots Shot::deleteShots;
Shot::ShotBank Shot::shotBank;
unsigned int Shot::shotsIter = 0;
std::string Shot::shotBankPath = "";
@ -92,6 +94,9 @@ void ShotData::bankLoad(const std::string &file, const std::string &path)
checkDamageTarget = true;
}
this->name = file;
stringToLower(this->name);
debugLog(usef);
char *data = readFile(core->adjustFilenameCase(usef).c_str());
if (!data)
@ -335,6 +340,7 @@ Shot::Shot() : Quad(), Segmented(0,0)
fired = false;
target = 0;
dead = false;
shotIdx = shots.size();
shots.push_back(this);
}
@ -479,7 +485,9 @@ void Shot::setLifeTime(float l)
void Shot::onEndOfLife()
{
destroySegments(0.2);
shots.remove(this);
deleteShots.push_back(this);
dead = true;
if (emitter)
{
emitter->killParticleEffect();
@ -531,24 +539,31 @@ void Shot::onHitWall()
void Shot::killAllShots()
{
std::queue<Shot*>shotDeleteQueue;
for (Shots::iterator i = shots.begin(); i != shots.end(); i++)
{
shotDeleteQueue.push(*i);
}
Shot *s = 0;
while (!shotDeleteQueue.empty())
{
s = shotDeleteQueue.front();
if (s)
{
s->safeKill();
}
shotDeleteQueue.pop();
}
shots.clear();
for (Shots::iterator i = shots.begin(); i != shots.end(); ++i)
(*i)->safeKill();
}
void Shot::clearShotGarbage()
{
for(size_t i = 0; i < deleteShots.size(); ++i)
{
Shot *s = deleteShots[i];
const unsigned int idx = s->shotIdx;
// move last shot to deleted one and shorten vector
if(idx < shots.size() && shots[idx] == s)
{
Shot *lastshot = shots.back();
shots[idx] = lastshot;
lastshot->shotIdx = idx;
shots.pop_back();
}
else
errorLog("Shot::clearShotGarbage(): wrong index in shot vector");
}
deleteShots.clear();
}
void Shot::reflectFromEntity(Entity *e)
{
Entity *oldFirer = firer;

View file

@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
struct ShotData
{
ShotData();
std::string texture;
std::string texture, name;
std::string hitSfx, bounceSfx, fireSfx;
std::string hitPrt, trailPrt, firePrt, bouncePrt;
std::string spawnEntity;
@ -79,11 +79,15 @@ public:
//void destroy();
void reflectFromEntity(Entity *e);
void setParticleEffect(const std::string &particleEffect);
typedef std::list<Shot*> Shots;
static Shots shots;
typedef std::vector<Shot*> Shots;
static Shots shots, deleteShots;
static unsigned int shotsIter; // for script
static Shot *getFirstShot() { shotsIter = 0; return getNextShot(); }
static Shot *getNextShot() { return shotsIter < shots.size() ? shots[shotsIter++] : NULL; }
static std::string shotBankPath;
static void targetDied(Entity *t);
static void killAllShots();
static void clearShotGarbage();
Entity *target, *firer;
int maxSpeed, targetPt;
@ -117,6 +121,8 @@ public:
void updatePosition();
bool isHitEnts() const;
bool isObstructed(float dt) const;
inline bool isActive() const { return !dead; }
inline const char *getName() const { return shotData ? shotData->name.c_str() : ""; }
float extraDamage;
protected:
@ -136,6 +142,9 @@ protected:
bool dead;
void onUpdate(float dt);
private:
unsigned int shotIdx;
};
class Beam : public Quad