Added run order (if applicable, the unit will use the run animation and speed for movement, otherwise walk is used). If the unit's run speed is more than 0 and the target is within the run action's range, it will run instead of walk.
Notifications - called from javascript. You request orders with a target entity, order type, and whether the previous listeners you have requested for this entity should be destroyed. When the target entity processes an order that was requested, that order is pushed onto the queue of the requester. This is useful for things such as follow that require the actual order to perform the action. This was SVN commit r3329.
This commit is contained in:
parent
763eb9311d
commit
2d8f45fd94
@ -19,6 +19,9 @@ CBaseEntity::CBaseEntity()
|
||||
AddProperty( L"parent", &m_base, false );
|
||||
AddProperty( L"actions.move.speed", &m_speed );
|
||||
AddProperty( L"actions.move.turningradius", &m_turningRadius );
|
||||
AddProperty( L"actions.move.run.speed", &( m_run.m_Speed ) );
|
||||
AddProperty( L"actions.move.run.rangemin", &( m_run.m_MinRange ) );
|
||||
AddProperty( L"actions.move.run.range", &( m_run.m_MaxRange ) );
|
||||
AddProperty( L"actions.attack.range", &( m_melee.m_MaxRange ) );
|
||||
AddProperty( L"actions.attack.rangemin", &( m_melee.m_MinRange ) );
|
||||
AddProperty( L"actions.attack.speed", &( m_melee.m_Speed ) );
|
||||
|
@ -75,7 +75,8 @@ public:
|
||||
bool m_permanent;
|
||||
|
||||
float m_speed;
|
||||
|
||||
|
||||
SEntityAction m_run;
|
||||
SEntityAction m_melee;
|
||||
SEntityAction m_gather;
|
||||
SEntityAction m_heal;
|
||||
|
@ -34,6 +34,9 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation )
|
||||
m_ahead.y = cos( m_orientation );
|
||||
|
||||
AddProperty( L"actions.move.speed", &m_speed );
|
||||
AddProperty( L"actions.move.run.speed", &( m_run.m_Speed ) );
|
||||
AddProperty( L"actions.move.run.rangemin", &( m_run.m_MinRange ) );
|
||||
AddProperty( L"actions.move.run.range", &( m_run.m_MaxRange ) );
|
||||
AddProperty( L"selected", &m_selected, false, (NotifyFn)&CEntity::checkSelection );
|
||||
AddProperty( L"group", &m_grouped, false, (NotifyFn)&CEntity::checkGroup );
|
||||
AddProperty( L"traits.extant", &m_extant );
|
||||
@ -404,6 +407,7 @@ void CEntity::update( size_t timestep )
|
||||
updateCollisionPatch();
|
||||
return;
|
||||
case CEntityOrder::ORDER_GOTO:
|
||||
case CEntityOrder::ORDER_RUN:
|
||||
if( processGoto( current, timestep ) )
|
||||
break;
|
||||
updateCollisionPatch();
|
||||
@ -641,28 +645,43 @@ bool CEntity::acceptsOrder( int orderType, CEntity* orderTarget )
|
||||
return( DispatchEvent( &evt ) );
|
||||
}
|
||||
|
||||
/*void CEntity::RequestNotification( CEntity* target, unsigned long orderType )
|
||||
jsval CEntity::RequestNotification( JSContext* cx, uintN argc, jsval* argv )
|
||||
{
|
||||
debug_assert( argc >= 3 );
|
||||
CEntityListener notify;
|
||||
|
||||
notify.m_sender = this;
|
||||
notify.m_type = orderType;
|
||||
//(Convert from int to enum)
|
||||
CEntity* target = ToPrimitive<CEntity*>( argv[0] );
|
||||
*( (uint*) &(notify.m_type) ) = ToPrimitive<int>( argv[1] );
|
||||
|
||||
if ( ToPrimitive<bool>( argv[2] ) )
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
target->m_listeners.push_back( notify );
|
||||
return JSVAL_VOID;
|
||||
}
|
||||
void CEntity::SendNotification( CEntity* target, unsigned long orderType )
|
||||
jsval CEntity::CheckListeners( JSContext *cx, uintN argc, jsval* argv )
|
||||
{
|
||||
CEntityListener notify;
|
||||
notify.m_sender = this;
|
||||
notify.m_type = orderType;
|
||||
target->m_notifications.push_back( notify );
|
||||
debug_assert( argc >= 1);
|
||||
|
||||
int type = ToPrimitive<int>( argv[0] );
|
||||
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() );
|
||||
}
|
||||
return JSVAL_VOID;
|
||||
}
|
||||
|
||||
void CEntity::DispatchNotification( CEntityListener notify )
|
||||
{
|
||||
CEventNotification evt( notify );
|
||||
DispatchEvent( &evt );
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void CEntity::repath()
|
||||
{
|
||||
CVector2D destination;
|
||||
|
@ -72,7 +72,9 @@ public:
|
||||
|
||||
float m_speed;
|
||||
float m_turningRadius;
|
||||
|
||||
float m_trampleStart;
|
||||
|
||||
SEntityAction m_run;
|
||||
SEntityAction m_melee;
|
||||
SEntityAction m_gather;
|
||||
SEntityAction m_heal;
|
||||
@ -153,8 +155,7 @@ public:
|
||||
size_t m_fsm_anipos2; // for when there are two animation-related events we need to take care of.
|
||||
|
||||
std::deque<CEntityOrder> m_orderQueue;
|
||||
//std::deque<CEntityListener> m_notifications;
|
||||
//std::deque<CEntityListener> m_listeners;
|
||||
std::deque<CEntityListener> m_listeners;
|
||||
|
||||
private:
|
||||
CEntity( CBaseEntity* base, CVector3D position, float orientation );
|
||||
@ -253,10 +254,9 @@ public:
|
||||
|
||||
void clearOrders();
|
||||
void pushOrder( CEntityOrder& order );
|
||||
|
||||
//void RequestNotification( CEntity* target, unsigned long orderType );
|
||||
//void SendNotification( CEntity* target, unsigned long orderType );
|
||||
//void DispatchNotification( CEntityListener notify );
|
||||
|
||||
jsval RequestNotification( JSContext* cx, uintN argc, jsval* argv );
|
||||
jsval CheckListeners( JSContext* cx, uintN argc, jsval* argv );
|
||||
|
||||
// Script constructor
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
|
||||
#include "EntityHandles.h"
|
||||
#include "Vector2D.h"
|
||||
#include "scripting/DOMEvent.h"
|
||||
|
||||
struct SOrderData
|
||||
{
|
||||
@ -46,6 +47,27 @@ struct SOrderData
|
||||
HEntity entity;
|
||||
};
|
||||
|
||||
class CEntityListener
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
NOTIFY_GOTO = 0x01,
|
||||
NOTIFY_RUN = 0x02,
|
||||
NOTIFY_FOLLOW = 0x03, //GOTO | RUN
|
||||
NOTIFY_ATTACK = 0x04,
|
||||
NOTIFY_DAMAGE = 0x08,
|
||||
NOTIFY_ESCORT = 0x0D, //GOTO | ATTACK | DAMAGE
|
||||
NOTIFY_HEAL = 0x10,
|
||||
NOTIFY_GATHER = 0x20
|
||||
|
||||
} m_type;
|
||||
|
||||
CEntity* m_sender;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CEntityOrder
|
||||
{
|
||||
public:
|
||||
@ -53,8 +75,9 @@ public:
|
||||
{
|
||||
ORDER_GOTO_NOPATHING,
|
||||
ORDER_GOTO_SMOOTHED,
|
||||
ORDER_GOTO_COLLISION,
|
||||
ORDER_GOTO_COLLISION,
|
||||
ORDER_GOTO,
|
||||
ORDER_RUN,
|
||||
ORDER_PATROL,
|
||||
ORDER_ATTACK_MELEE,
|
||||
ORDER_ATTACK_MELEE_NOPATHING,
|
||||
|
@ -46,7 +46,7 @@ uint CEntity::processGotoHelper( CEntityOrder* current, size_t timestep_millis,
|
||||
// Curve smoothing.
|
||||
// Here there be trig.
|
||||
|
||||
float scale = m_speed * timestep;
|
||||
float scale = ( m_run.m_Speed > 0 ? m_run.m_Speed : m_speed ) * timestep;
|
||||
|
||||
// Note: Easy optimization: flag somewhere that this unit
|
||||
// is already pointing the right way, and don't do this
|
||||
@ -278,10 +278,10 @@ bool CEntity::processContactAction( CEntityOrder* current, size_t UNUSED(timeste
|
||||
|
||||
if( !current->m_data[0].entity || !current->m_data[0].entity->m_extant )
|
||||
return( false );
|
||||
|
||||
current->m_data[0].location = current->m_data[0].entity->m_position;
|
||||
|
||||
if( ( current->m_data[0].location - m_position ).length() < action->m_MaxRange )
|
||||
float Distance = (current->m_data[0].location - m_position).length();
|
||||
|
||||
if( Distance < action->m_MaxRange )
|
||||
{
|
||||
(int&)current->m_type = transition;
|
||||
m_orderQueue.push_front(*current); // Seems to be needed since we do a pop above
|
||||
@ -290,8 +290,19 @@ bool CEntity::processContactAction( CEntityOrder* current, size_t UNUSED(timeste
|
||||
|
||||
if( m_transition && m_actor )
|
||||
{
|
||||
CSkeletonAnim* walk = m_actor->GetRandomAnimation( "walk" );
|
||||
m_actor->GetModel()->SetAnimation( walk, false, m_speed * walk->m_AnimDef->GetDuration() );
|
||||
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() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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 );
|
||||
}
|
||||
@ -353,6 +364,9 @@ bool CEntity::processContactActionNoPathing( CEntityOrder* current, size_t times
|
||||
// Target's dead (or exhausted)? Then our work here is done.
|
||||
if( !current->m_data[0].entity || !current->m_data[0].entity->m_extant )
|
||||
{
|
||||
//TODO: eventually when stances/formations are implemented, if applicable (e.g. not
|
||||
//heal or if defensive stance), the unit should expand and continue the order.
|
||||
|
||||
m_orderQueue.pop_front();
|
||||
return( false );
|
||||
}
|
||||
@ -376,9 +390,27 @@ bool CEntity::processContactActionNoPathing( CEntityOrder* current, size_t times
|
||||
// Too far away at the moment, chase after the target...
|
||||
// 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 );
|
||||
|
||||
//Determine whether to run or to walk
|
||||
if ( m_run.m_Speed > 0 )
|
||||
{
|
||||
float deltaLength = delta.length();
|
||||
if ( m_actor && ! 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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Play walk for a bit.
|
||||
if( m_actor && ! m_actor->IsPlayingAnimation( "walk" ) )
|
||||
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() );
|
||||
@ -386,7 +418,7 @@ bool CEntity::processContactActionNoPathing( CEntityOrder* current, size_t times
|
||||
m_actor->GetModel()->Update( ( rand() * 1000.0f ) / 1000.0f );
|
||||
}
|
||||
|
||||
delta = delta.normalize() * ( adjRange - m_bounds->m_radius );
|
||||
|
||||
|
||||
current->m_data[0].location = (CVector2D)current->m_data[0].entity->m_position - delta;
|
||||
|
||||
@ -554,19 +586,30 @@ bool CEntity::processGoto( CEntityOrder* current, size_t UNUSED(timestep_millis)
|
||||
CVector2D pos( m_position.X, m_position.Z );
|
||||
CVector2D path_to = current->m_data[0].location;
|
||||
m_orderQueue.pop_front();
|
||||
|
||||
float Distance = ( path_to - pos ).length();
|
||||
|
||||
// Let's just check we're going somewhere...
|
||||
if( ( path_to - pos ).length() < 0.1f )
|
||||
if( Distance < 0.1f )
|
||||
return( false );
|
||||
|
||||
if( m_transition && m_actor )
|
||||
{
|
||||
|
||||
CSkeletonAnim* walk = m_actor->GetRandomAnimation( "walk" );
|
||||
if( walk )
|
||||
m_actor->GetModel()->SetAnimation( walk, false, m_speed * walk->m_AnimDef->GetDuration() );
|
||||
// Animation desync
|
||||
m_actor->GetModel()->Update( ( rand() * 1000.0f ) / 1000.0f );
|
||||
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() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CSkeletonAnim* walk = m_actor->GetRandomAnimation( "walk" );
|
||||
if( walk )
|
||||
m_actor->GetModel()->SetAnimation( walk, false, m_speed * walk->m_AnimDef->GetDuration() );
|
||||
// Animation desync
|
||||
m_actor->GetModel()->Update( ( rand() * 1000.0f ) / 1000.0f );
|
||||
}
|
||||
}
|
||||
|
||||
// The pathfinder will push its result back into this unit's queue.
|
||||
|
Loading…
Reference in New Issue
Block a user