mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-17 13:53:57 -07:00
Game, Simulation, etc: Separated 'update' and 'interpolate', and made 'update' return whether it's going fast enough (so callers can decide to do more updates per render). Changed some time variables to 'double' so they have enough precision in long games. Atlas: Added "Fast" playback button. Made simulation sometimes go at real-time speed, if it's just slightly too slow at rendering. VertexBuffer: Removed some non-useful glGetError calls. Entity: Commented out redundant Tick code. Fixed syntax error in disabled code that confused the IDE. Aura: Changed string code again, to simply use ASCII instead of UTF-16. (SpiderMonkey seems to handle it just as efficiently, for small strings.) Misc: Some more minor header-file cleanup. SVN log: Added feed link. This was SVN commit r4807.
160 lines
4.4 KiB
C++
160 lines
4.4 KiB
C++
#include "precompiled.h"
|
|
|
|
#include "Aura.h"
|
|
|
|
#include "EntityManager.h"
|
|
#include "Entity.h"
|
|
|
|
#include <algorithm>
|
|
|
|
CAura::CAura( JSContext* cx, CEntity* source, CStrW& name, float radius, size_t tickRate, const CVector4D& color, JSObject* handler )
|
|
: m_cx(cx), m_source(source), m_name(name), m_radius(radius), m_handler(handler),
|
|
m_tickRate(tickRate), m_tickCyclePos(0), m_color(color)
|
|
{
|
|
JS_AddRoot( m_cx, &m_handler ); // don't GC it so we can call it later
|
|
}
|
|
|
|
CAura::~CAura()
|
|
{
|
|
JS_RemoveRoot( m_cx, &m_handler );
|
|
}
|
|
|
|
void CAura::Update( size_t timestep )
|
|
{
|
|
std::vector<CEntity*> inRange;
|
|
CVector3D pos = m_source->m_position;
|
|
g_EntityManager.GetInRange( pos.X, pos.Z, m_radius, inRange );
|
|
|
|
std::vector<CEntity*> prevInfluenced, curInfluenced, entered, exited;
|
|
|
|
prevInfluenced.reserve(m_influenced.size());
|
|
curInfluenced.reserve(m_influenced.size());
|
|
|
|
for( std::vector<HEntity>::iterator it = m_influenced.begin(); it != m_influenced.end(); it++ )
|
|
{
|
|
CEntity* ent = *it;
|
|
if( ent->m_extant )
|
|
{
|
|
prevInfluenced.push_back(ent);
|
|
}
|
|
}
|
|
|
|
m_influenced.clear();
|
|
|
|
for( std::vector<CEntity*>::iterator it = inRange.begin(); it != inRange.end(); it++ )
|
|
{
|
|
CEntity* ent = *it;
|
|
if(ent != m_source)
|
|
{
|
|
curInfluenced.push_back(ent);
|
|
m_influenced.push_back( HEntity(ent->me) );
|
|
}
|
|
}
|
|
|
|
sort( prevInfluenced.begin(), prevInfluenced.end() );
|
|
sort( curInfluenced.begin(), curInfluenced.end() );
|
|
|
|
jsval rval;
|
|
jsval argv[1];
|
|
|
|
// Call onEnter on any new unit that has entered the aura
|
|
jsval enterFunction;
|
|
if( JS_GetProperty( m_cx, m_handler, "onEnter", &enterFunction )
|
|
&& enterFunction != JSVAL_VOID)
|
|
{
|
|
std::back_insert_iterator<std::vector<CEntity*> > ins( entered );
|
|
set_difference( curInfluenced.begin(), curInfluenced.end(),
|
|
prevInfluenced.begin(), prevInfluenced.end(),
|
|
ins );
|
|
for( std::vector<CEntity*>::iterator it = entered.begin(); it != entered.end(); it++ )
|
|
{
|
|
argv[0] = OBJECT_TO_JSVAL( (*it)->GetScript() );
|
|
JS_CallFunctionValue( m_cx, m_handler, enterFunction, 1, argv, &rval );
|
|
(*it)->m_aurasInfluencingMe.insert( this );
|
|
}
|
|
}
|
|
|
|
// Call onExit on any unit that has exited the aura
|
|
jsval exitFunction;
|
|
if( JS_GetProperty( m_cx, m_handler, "onExit", &exitFunction )
|
|
&& exitFunction != JSVAL_VOID )
|
|
{
|
|
std::back_insert_iterator<std::vector<CEntity*> > ins( exited );
|
|
set_difference( prevInfluenced.begin(), prevInfluenced.end(),
|
|
curInfluenced.begin(), curInfluenced.end(),
|
|
ins );
|
|
for( std::vector<CEntity*>::iterator it = exited.begin(); it != exited.end(); it++ )
|
|
{
|
|
argv[0] = OBJECT_TO_JSVAL( (*it)->GetScript() );
|
|
JS_CallFunctionValue( m_cx, m_handler, exitFunction, 1, argv, &rval );
|
|
(*it)->m_aurasInfluencingMe.erase( this );
|
|
}
|
|
}
|
|
|
|
m_tickCyclePos += timestep;
|
|
|
|
if( m_tickRate > 0 && m_tickCyclePos > m_tickRate )
|
|
{
|
|
// It's time to tick; call OnTick on any unit that is in the aura
|
|
jsval tickFunction;
|
|
if( JS_GetProperty( m_cx, m_handler, "onTick", &tickFunction )
|
|
&& tickFunction != JSVAL_VOID )
|
|
{
|
|
for( std::vector<CEntity*>::iterator it = curInfluenced.begin(); it != curInfluenced.end(); it++ )
|
|
{
|
|
argv[0] = OBJECT_TO_JSVAL( (*it)->GetScript() );
|
|
JS_CallFunctionValue( m_cx, m_handler, tickFunction, 1, argv, &rval );
|
|
}
|
|
}
|
|
|
|
// Reset cycle pos
|
|
m_tickCyclePos %= m_tickRate;
|
|
}
|
|
}
|
|
|
|
void CAura::RemoveAll()
|
|
{
|
|
jsval rval;
|
|
jsval argv[1];
|
|
jsval exitFunction;
|
|
if( JS_GetProperty( m_cx, m_handler, "onExit", &exitFunction )
|
|
&& exitFunction != JSVAL_VOID )
|
|
{
|
|
// Call the exit function on everything in our influence
|
|
for( std::vector<HEntity>::iterator it = m_influenced.begin(); it != m_influenced.end(); it++ )
|
|
{
|
|
CEntity* ent = *it;
|
|
if( ent->m_extant )
|
|
{
|
|
argv[0] = OBJECT_TO_JSVAL( ent->GetScript() );
|
|
JS_CallFunctionValue( m_cx, m_handler, exitFunction, 1, argv, &rval );
|
|
(*it)->m_aurasInfluencingMe.erase( this );
|
|
}
|
|
}
|
|
}
|
|
m_influenced.clear();
|
|
}
|
|
|
|
void CAura::Remove( CEntity* ent )
|
|
{
|
|
jsval rval;
|
|
jsval argv[1];
|
|
jsval exitFunction;
|
|
if( JS_GetProperty( m_cx, m_handler, "onExit", &exitFunction )
|
|
&& exitFunction != JSVAL_VOID )
|
|
{
|
|
// Call the exit function on it
|
|
argv[0] = OBJECT_TO_JSVAL( ent->GetScript() );
|
|
JS_CallFunctionValue( m_cx, m_handler, exitFunction, 1, argv, &rval );
|
|
|
|
// Remove it from the m_influenced array
|
|
for( size_t i=0; i < m_influenced.size(); i++ )
|
|
{
|
|
if( ((CEntity*) m_influenced[i]) == ent )
|
|
{
|
|
m_influenced.erase( m_influenced.begin() + i );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|