1
0
forked from 0ad/0ad

Fixed up running and notifications.

This was SVN commit r3341.
This commit is contained in:
pyrolink 2006-01-08 08:25:11 +00:00
parent 8f7202f00b
commit 19b33141c1
6 changed files with 129 additions and 56 deletions

View File

@ -100,6 +100,8 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation )
m_selected = false;
m_isRunning = false;
m_grouped = -1;
m_player = g_Game->GetPlayer( 0 );
@ -408,7 +410,6 @@ void CEntity::update( size_t timestep )
updateCollisionPatch();
return;
case CEntityOrder::ORDER_GOTO:
case CEntityOrder::ORDER_RUN:
if( processGoto( current, timestep ) )
break;
updateCollisionPatch();
@ -648,35 +649,82 @@ bool CEntity::acceptsOrder( int orderType, CEntity* orderTarget )
jsval CEntity::RequestNotification( JSContext* cx, uintN argc, jsval* argv )
{
debug_assert( argc >= 3 );
debug_assert( argc > 3 );
CEntityListener notify;
notify.m_sender = this;
//(Convert from int to enum)
CEntity* target = ToPrimitive<CEntity*>( argv[0] );
CEntity *target = ToNative<CEntity>( argv[0] );
*( (uint*) &(notify.m_type) ) = ToPrimitive<int>( argv[1] );
if ( ToPrimitive<bool>( argv[2] ) )
bool destroy = ToPrimitive<bool>( argv[2] );
std::deque<CEntityListener>::iterator it = target->m_listeners.begin();
for ( ; it != target->m_listeners.end(); it++)
{
std::deque<CEntityListener>::iterator it = target->m_listeners.begin();
for ( ; it != target->m_listeners.end(); it++)
{
if ( it->m_sender == this )
target->m_listeners.erase(it);
}
if ( destroy && it->m_sender == this )
target->m_listeners.erase(it);
}
target->m_listeners.push_back( notify );
return JSVAL_VOID;
}
jsval CEntity::CheckListeners( JSContext *cx, uintN argc, jsval* argv )
void CEntity::DispatchNotification( CEntityOrder order, uint type )
{
debug_assert( argc >= 1);
int type = ToPrimitive<int>( argv[0] );
for (int i=0; i<m_listeners.size(); i++)
CEventNotification evt( order, type );
DispatchEvent( &evt );
}
jsval CEntity::CheckListeners( JSContext *cx, uintN argc, jsval* argv )
{
if( argc < 1 )
{
JS_ReportError( cx, "Too few parameters" );
return( false );
}
int type = ToPrimitive<int>( argv[0] ); //notify code
CEntityOrder order = this->m_orderQueue.front();
CEntity* target;
for (int i=0; i<m_listeners.size(); i++)
if (m_listeners[i].m_type & type)
m_listeners[i].m_sender->pushOrder( this->m_orderQueue.front() );
{
switch( type )
{
case CEntityListener::NOTIFY_GOTO:
m_listeners[i].m_sender->DispatchNotification( order, type );
break;
case CEntityListener::NOTIFY_HEAL:
case CEntityListener::NOTIFY_ATTACK:
case CEntityListener::NOTIFY_GATHER:
if( argc < 3 )
{
JS_ReportError( cx, "Too few parameters" );
continue;
}
target = ToNative<CEntity>( argv[1] );
order.m_data[1].data = ToPrimitive<int>( argv[2] ); //which action
order.m_data[0].entity = target->me;
m_listeners[i].m_sender->DispatchNotification( order, type );
break;
case CEntityListener::NOTIFY_DAMAGE:
if( argc < 2 )
{
JS_ReportError( cx, "Too few parameters" );
continue;
}
target = ToNative<CEntity>( argv[1] );
order.m_data[0].entity = target->me;
m_listeners[i].m_sender->DispatchNotification( order, type );
default:
JS_ReportError( cx, "Invalid order type" );
continue;
}
}
return JSVAL_VOID;
}

View File

@ -91,6 +91,8 @@ public:
// If this unit is still active in the gameworld - i.e. not a corpse.
bool m_extant;
bool m_isRunning;
// HP properties
float m_healthCurr;
float m_healthMax;
@ -256,6 +258,7 @@ public:
void pushOrder( CEntityOrder& order );
jsval RequestNotification( JSContext* cx, uintN argc, jsval* argv );
void DispatchNotification( CEntityOrder order,uint type );
jsval CheckListeners( JSContext* cx, uintN argc, jsval* argv );
// Script constructor

View File

@ -53,10 +53,13 @@ public:
enum
{
NOTIFY_GOTO = 0x01,
NOTIFY_RUN = 0x02,
NOTIFY_FOLLOW = 0x03, //GOTO | RUN
//NOTIFY_ = 0x02, reservered for possible second goto like command
//NOTIFY_FOLLOW = 0x03, //GOTO | RUN
NOTIFY_ATTACK = 0x04,
NOTIFY_DAMAGE = 0x08,
NOTIFY_COMBAT = 0x0C, //ATTACK | DAMAGE
NOTIFY_ESCORT = 0x0D, //GOTO | ATTACK | DAMAGE
NOTIFY_HEAL = 0x10,
NOTIFY_GATHER = 0x20

View File

@ -46,7 +46,11 @@ uint CEntity::processGotoHelper( CEntityOrder* current, size_t timestep_millis,
// Curve smoothing.
// Here there be trig.
float scale = ( m_run.m_Speed > 0 ? m_run.m_Speed : m_speed ) * timestep;
float scale;
if ( m_run.m_Speed > 0 && len < m_run.m_MaxRange && ( m_isRunning || len > m_run.m_MinRange ) )
scale = m_run.m_Speed * timestep;
else
scale = m_speed * timestep;
// Note: Easy optimization: flag somewhere that this unit
// is already pointing the right way, and don't do this
@ -290,18 +294,17 @@ bool CEntity::processContactAction( CEntityOrder* current, size_t UNUSED(timeste
if( m_transition && m_actor )
{
if (m_run.m_Speed > 0 )
{
if ( Distance > m_run.m_MinRange && Distance < m_run.m_MaxRange )
{
CSkeletonAnim* run = m_actor->GetRandomAnimation( "run" );
m_actor->GetModel()->SetAnimation( run, false, m_run.m_Speed * run->m_AnimDef->GetDuration() );
}
if ( m_run.m_Speed > 0 && Distance < m_run.m_MaxRange && ( Distance > m_run.m_MinRange || m_isRunning ) )
{
CSkeletonAnim* run = m_actor->GetRandomAnimation( "run" );
m_actor->GetModel()->SetAnimation( run, false, m_run.m_Speed * run->m_AnimDef->GetDuration() );
m_isRunning = true;
}
else
{
CSkeletonAnim* walk = m_actor->GetRandomAnimation( "walk" );
m_actor->GetModel()->SetAnimation( walk, false, m_speed * walk->m_AnimDef->GetDuration() );
m_isRunning = false;
}
// Animation desync
m_actor->GetModel()->Update( ( rand() * 1000.0f ) / 1000.0f );
@ -391,35 +394,30 @@ bool CEntity::processContactActionNoPathing( CEntityOrder* current, size_t times
// We're aiming to end up at a location just inside our maximum range
// (is this good enough?)
delta = delta.normalize() * ( adjRange - m_bounds->m_radius );
float deltaLength = delta.length();
//Determine whether to run or to walk
if ( m_run.m_Speed > 0 )
if ( m_actor )
{
float deltaLength = delta.length();
if ( m_actor && ! m_actor->IsPlayingAnimation( "run" ) )
//Can we run, are we in range, and are we already running?
if ( m_run.m_Speed > 0 && deltaLength < m_run.m_MaxRange && ( deltaLength > m_run.m_MinRange ||
m_isRunning ) && !m_actor->IsPlayingAnimation( "run ") )
{
//Are we in range?
if ( deltaLength < m_run.m_MaxRange && deltaLength > m_run.m_MinRange )
{
CSkeletonAnim* run = m_actor->GetRandomAnimation( "run" );
m_actor->GetModel()->SetAnimation( run, false, m_run.m_Speed * run->m_AnimDef->GetDuration() );
// Animation desync
m_actor->GetModel()->Update( ( rand() * 1000.0f ) / 1000.0f );
}
CSkeletonAnim* run = m_actor->GetRandomAnimation( "run" );
m_actor->GetModel()->SetAnimation( run, false, m_run.m_Speed * run->m_AnimDef->GetDuration() );
m_isRunning = true;
}
// Play walk for a bit.
else if( !m_actor->IsPlayingAnimation( "walk" ) )
{
CSkeletonAnim* walk = m_actor->GetRandomAnimation( "walk" );
m_actor->GetModel()->SetAnimation( walk, false, m_speed * walk->m_AnimDef->GetDuration() );
// Animation desync
m_actor->GetModel()->Update( ( rand() * 1000.0f ) / 1000.0f );
m_isRunning = false;
}
}
// Play walk for a bit.
else if( m_actor && ! m_actor->IsPlayingAnimation( "walk" ) )
{
CSkeletonAnim* walk = m_actor->GetRandomAnimation( "walk" );
m_actor->GetModel()->SetAnimation( walk, false, m_speed * walk->m_AnimDef->GetDuration() );
// Animation desync
m_actor->GetModel()->Update( ( rand() * 1000.0f ) / 1000.0f );
}
current->m_data[0].location = (CVector2D)current->m_data[0].entity->m_position - delta;
HEntity collide;
@ -594,13 +592,10 @@ bool CEntity::processGoto( CEntityOrder* current, size_t UNUSED(timestep_millis)
if( m_transition && m_actor )
{
if (m_run.m_Speed > 0 )
if ( m_run.m_Speed > 0 && Distance < m_run.m_MaxRange && ( Distance > m_run.m_MinRange || m_isRunning ) )
{
if ( Distance > m_run.m_MinRange && Distance < m_run.m_MaxRange )
{
CSkeletonAnim* run = m_actor->GetRandomAnimation( "run" );
m_actor->GetModel()->SetAnimation( run, false, m_run.m_Speed * run->m_AnimDef->GetDuration() );
}
CSkeletonAnim* run = m_actor->GetRandomAnimation( "run" );
m_actor->GetModel()->SetAnimation( run, false, m_run.m_Speed * run->m_AnimDef->GetDuration() );
}
else
{

View File

@ -67,3 +67,16 @@ CEventOrderTransition::CEventOrderTransition( int orderPrevious, int orderCurren
AddLocalProperty( L"target", m_target );
AddLocalProperty( L"position", m_worldPosition );
}
CEventNotification::CEventNotification( CEntityOrder order, uint type ) : CScriptEvent( L"notification", EVENT_NOTIFICATION, true )
{
m_type = type;
m_target = order.m_data[0].entity;
m_data = (uint) order.m_data[1].data;
CVector3D convert( order.m_data[0].location.x, 0.0f, order.m_data[0].location.y );
m_location = convert;
AddLocalProperty( L"type", &m_type );
AddLocalProperty( L"target", &m_target );
AddLocalProperty( L"data", &m_data );
AddLocalProperty( L"location", &m_location );
}

View File

@ -7,6 +7,7 @@
#include "scripting/DOMEvent.h"
#include "Vector3D.h"
#include "EntityOrders.h"
class CDamageType;
@ -86,5 +87,15 @@ class CEventOrderTransition : public CScriptEvent
public:
CEventOrderTransition( int orderPrevious, int orderCurrent, CEntity*& target, CVector3D& worldPosition );
};
class CEventNotification : public CScriptEvent
{
//Same as CEntityOrder data for support of all orders
CEntity* m_target;
uint m_data; //u64 is unsupported...will this work?
uint m_type;
CVector3D m_location; //No real use for y, but CVector2D unsupported
public:
CEventNotification( CEntityOrder order, uint type );
};
#endif