forked from 0ad/0ad
This was SVN commit r3507.
This commit is contained in:
parent
b3a5c6f8af
commit
10d84599e9
@ -112,6 +112,8 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation )
|
||||
|
||||
m_frameCheck = 0;
|
||||
m_lastCombatTime = 0;
|
||||
m_currentNotification = 0;
|
||||
m_currentListener = NULL;
|
||||
|
||||
m_grouped = -1;
|
||||
|
||||
@ -623,24 +625,38 @@ void CEntity::clearOrders()
|
||||
|
||||
void CEntity::pushOrder( CEntityOrder& order )
|
||||
{
|
||||
if( acceptsOrder( order.m_type, order.m_data[0].entity ) )
|
||||
//Replace acceptsOrder because we need the notification data after the order is pushed
|
||||
CEventPrepareOrder evt( order.m_data[0].entity, order.m_type, order.m_data[1].data );
|
||||
if( DispatchEvent(&evt) )
|
||||
{
|
||||
m_orderQueue.push_back( order );
|
||||
CheckListeners( evt.m_notifyType, evt.m_notifySource );
|
||||
}
|
||||
}
|
||||
|
||||
bool CEntity::acceptsOrder( int orderType, CEntity* orderTarget )
|
||||
bool CEntity::acceptsOrder( int orderType, CEntity* orderTarget, int action )
|
||||
{
|
||||
CEventPrepareOrder evt( orderTarget, orderType );
|
||||
return( DispatchEvent( &evt ) );
|
||||
CEventPrepareOrder evt( orderTarget, orderType, action );
|
||||
return ( DispatchEvent(&evt) );
|
||||
}
|
||||
|
||||
void CEntity::DispatchNotification( CEntityOrder order, uint type )
|
||||
void CEntity::DispatchNotification( CEntityOrder order, int type )
|
||||
{
|
||||
CEventNotification evt( order, type );
|
||||
DispatchEvent( &evt );
|
||||
}
|
||||
void CEntity::DestroyListeners( CEntity* target )
|
||||
{
|
||||
if (target->m_listeners.empty())
|
||||
return;
|
||||
|
||||
for ( size_t i=0; i < target->m_listeners.size(); i++)
|
||||
{
|
||||
if ( target->m_listeners[i].m_sender == this )
|
||||
target->m_listeners.erase(target->m_listeners.begin() + i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CEntity::repath()
|
||||
{
|
||||
@ -1051,6 +1067,7 @@ void CEntity::ScriptingInit()
|
||||
AddMethod<jsval, &CEntity::ToString>( "toString", 0 );
|
||||
AddMethod<bool, &CEntity::OrderSingle>( "order", 1 );
|
||||
AddMethod<bool, &CEntity::OrderQueued>( "orderQueued", 1 );
|
||||
AddMethod<jsval, &CEntity::TerminateOrder>( "terminateOrder", 1 );
|
||||
AddMethod<bool, &CEntity::Kill>( "kill", 0 );
|
||||
AddMethod<bool, &CEntity::IsIdle>( "isIdle", 0 );
|
||||
AddMethod<bool, &CEntity::HasClass>( "hasClass", 1 );
|
||||
@ -1058,8 +1075,8 @@ void CEntity::ScriptingInit()
|
||||
AddMethod<jsval, &CEntity::AddAura>( "addAura", 3 );
|
||||
AddMethod<jsval, &CEntity::RemoveAura>( "removeAura", 1 );
|
||||
AddMethod<jsval, &CEntity::SetActionParams>( "setActionParams", 5 );
|
||||
AddMethod<jsval, &CEntity::CheckListeners>( "checkListeners", 1 );
|
||||
AddMethod<jsval, &CEntity::RequestNotification>( "requestNotification", 3 );
|
||||
AddMethod<bool, &CEntity::ForceCheckListeners>( "forceCheckListeners", 2 );
|
||||
AddMethod<bool, &CEntity::RequestNotification>( "requestNotification", 3 );
|
||||
AddMethod<jsval, &CEntity::TriggerRun>( "triggerRun", 1 );
|
||||
AddMethod<jsval, &CEntity::SetRun>( "setRun", 1 );
|
||||
AddMethod<jsval, &CEntity::GetRunState>( "getRunState", 0 );
|
||||
@ -1192,6 +1209,13 @@ bool CEntity::Order( JSContext* cx, uintN argc, jsval* argv, bool Queued )
|
||||
}
|
||||
if ( orderCode == CEntityOrder::ORDER_RUN )
|
||||
m_triggerRun = true;
|
||||
//It's not a notification order
|
||||
if ( argc == 3 )
|
||||
{
|
||||
if ( m_currentListener )
|
||||
DestroyListeners( m_currentListener );
|
||||
m_currentListener = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
case CEntityOrder::ORDER_GENERIC:
|
||||
@ -1216,6 +1240,13 @@ bool CEntity::Order( JSContext* cx, uintN argc, jsval* argv, bool Queued )
|
||||
JS_ReportError( cx, "Invalid generic order type" );
|
||||
return( false );
|
||||
}
|
||||
//It's not a notification order
|
||||
if ( argc == 3 )
|
||||
{
|
||||
if ( m_currentListener )
|
||||
DestroyListeners( m_currentListener );
|
||||
m_currentListener = NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
JS_ReportError( cx, "Invalid order type" );
|
||||
@ -1472,43 +1503,81 @@ jsval CEntity::SetActionParams( JSContext* UNUSED(cx), uintN argc, jsval* argv )
|
||||
return JSVAL_VOID;
|
||||
}
|
||||
|
||||
jsval CEntity::RequestNotification( JSContext* cx, uintN argc, jsval* argv )
|
||||
bool CEntity::RequestNotification( JSContext* cx, uintN argc, jsval* argv )
|
||||
{
|
||||
if( argc < 3 )
|
||||
{
|
||||
JS_ReportError( cx, "Too few parameters" );
|
||||
return( false );
|
||||
}
|
||||
|
||||
CEntityListener notify;
|
||||
|
||||
notify.m_sender = this;
|
||||
//(Convert from int to enum)
|
||||
CEntity *target = ToNative<CEntity>( argv[0] );
|
||||
*( (uint*) &(notify.m_type) ) = ToPrimitive<int>( argv[1] );
|
||||
|
||||
bool destroy = ToPrimitive<bool>( argv[2] );
|
||||
|
||||
std::deque<CEntityListener>::iterator it = target->m_listeners.begin();
|
||||
for ( ; it != target->m_listeners.end(); it++)
|
||||
{
|
||||
if ( destroy && it->m_sender == this )
|
||||
target->m_listeners.erase(it);
|
||||
}
|
||||
if (target == this)
|
||||
return false;
|
||||
|
||||
*( (int*) &(notify.m_type) ) = ToPrimitive<int>( argv[1] );
|
||||
|
||||
//Clean up old requests
|
||||
if ( ToPrimitive<bool>( argv[2] ) && !target->m_listeners.empty() )
|
||||
DestroyListeners( target );
|
||||
|
||||
if ( target != m_currentListener && m_currentListener )
|
||||
DestroyListeners( m_currentListener );
|
||||
|
||||
m_currentListener = target;
|
||||
|
||||
//If our target isn't stationary and it's doing something we want to follow, send notification
|
||||
int result = target->m_currentNotification & notify.m_type;
|
||||
if ( result && !target->m_orderQueue.empty() )
|
||||
{
|
||||
CEntityOrder order = target->m_orderQueue.front();
|
||||
switch( result )
|
||||
{
|
||||
case CEntityListener::NOTIFY_GOTO:
|
||||
case CEntityListener::NOTIFY_RUN:
|
||||
DispatchNotification( order, result );
|
||||
break;
|
||||
|
||||
case CEntityListener::NOTIFY_HEAL:
|
||||
case CEntityListener::NOTIFY_ATTACK:
|
||||
case CEntityListener::NOTIFY_GATHER:
|
||||
case CEntityListener::NOTIFY_DAMAGE:
|
||||
if( argc < 2 )
|
||||
{
|
||||
JS_ReportError( cx, "Too few parameters" );
|
||||
}
|
||||
|
||||
DispatchNotification( order, result );
|
||||
break;
|
||||
default:
|
||||
JS_ReportError( cx, "Invalid order type" );
|
||||
break;
|
||||
}
|
||||
target->m_listeners.push_back( notify );
|
||||
return true;
|
||||
}
|
||||
|
||||
target->m_listeners.push_back( notify );
|
||||
return JSVAL_VOID;
|
||||
return false;
|
||||
}
|
||||
jsval CEntity::CheckListeners( JSContext *cx, uintN argc, jsval* argv )
|
||||
bool CEntity::ForceCheckListeners( JSContext *cx, uintN argc, jsval* argv )
|
||||
{
|
||||
if( argc < 1 )
|
||||
if( argc < 2 )
|
||||
{
|
||||
JS_ReportError( cx, "Too few parameters" );
|
||||
return( false );
|
||||
return false;
|
||||
}
|
||||
int type = ToPrimitive<int>( argv[0] ); //notify code
|
||||
CEntityOrder order = this->m_orderQueue.front();
|
||||
CEntity* target;
|
||||
m_currentNotification = type;
|
||||
|
||||
CEntity *target = ToNative<CEntity>( argv[1] );
|
||||
if ( target->m_orderQueue.empty() )
|
||||
return false;
|
||||
|
||||
CEntityOrder order = target->m_orderQueue.front();
|
||||
for (size_t i=0; i<m_listeners.size(); i++)
|
||||
{
|
||||
int result = m_listeners[i].m_type & type;
|
||||
@ -1516,33 +1585,52 @@ jsval CEntity::CheckListeners( JSContext *cx, uintN argc, jsval* argv )
|
||||
{
|
||||
switch( result )
|
||||
{
|
||||
case CEntityListener::NOTIFY_GOTO:
|
||||
case CEntityListener::NOTIFY_RUN:
|
||||
m_listeners[i].m_sender->DispatchNotification( order, result );
|
||||
break;
|
||||
|
||||
case CEntityListener::NOTIFY_GOTO:
|
||||
case CEntityListener::NOTIFY_RUN:
|
||||
case CEntityListener::NOTIFY_HEAL:
|
||||
case CEntityListener::NOTIFY_ATTACK:
|
||||
case CEntityListener::NOTIFY_GATHER:
|
||||
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, result );
|
||||
break;
|
||||
m_listeners[i].m_sender->DispatchNotification( order, result );
|
||||
|
||||
default:
|
||||
default:
|
||||
JS_ReportError( cx, "Invalid order type" );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return JSVAL_VOID;
|
||||
return true;
|
||||
}
|
||||
void CEntity::CheckListeners( int type, CEntity *target)
|
||||
{
|
||||
m_currentNotification = type;
|
||||
|
||||
debug_assert(target);
|
||||
if ( target->m_orderQueue.empty() )
|
||||
return;
|
||||
|
||||
CEntityOrder order = target->m_orderQueue.front();
|
||||
for (size_t i=0; i<m_listeners.size(); i++)
|
||||
{
|
||||
int result = m_listeners[i].m_type & type;
|
||||
if ( result )
|
||||
{
|
||||
switch( result )
|
||||
{
|
||||
case CEntityListener::NOTIFY_GOTO:
|
||||
case CEntityListener::NOTIFY_RUN:
|
||||
case CEntityListener::NOTIFY_HEAL:
|
||||
case CEntityListener::NOTIFY_ATTACK:
|
||||
case CEntityListener::NOTIFY_GATHER:
|
||||
case CEntityListener::NOTIFY_DAMAGE:
|
||||
m_listeners[i].m_sender->DispatchNotification( order, result );
|
||||
break;
|
||||
default:
|
||||
debug_warn("Invalid notification: CheckListeners()");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jsval CEntity::TriggerRun( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
|
||||
|
@ -174,6 +174,8 @@ public:
|
||||
|
||||
std::deque<CEntityOrder> m_orderQueue;
|
||||
std::deque<CEntityListener> m_listeners;
|
||||
int m_currentNotification;
|
||||
CEntity* m_currentListener;
|
||||
|
||||
private:
|
||||
CEntity( CBaseEntity* base, CVector3D position, float orientation );
|
||||
@ -261,12 +263,13 @@ public:
|
||||
void checkExtant(); // Existence
|
||||
|
||||
// Returns whether the entity is capable of performing the given orderType on the target.
|
||||
bool acceptsOrder( int orderType, CEntity* orderTarget );
|
||||
bool acceptsOrder( int orderType, CEntity* orderTarget, int action );
|
||||
|
||||
void clearOrders();
|
||||
void pushOrder( CEntityOrder& order );
|
||||
|
||||
void DispatchNotification( CEntityOrder order,uint type );
|
||||
void DispatchNotification( CEntityOrder order, int type );
|
||||
void DestroyListeners( CEntity* target );
|
||||
|
||||
// Script constructor
|
||||
|
||||
@ -288,8 +291,10 @@ public:
|
||||
jsval IsRunning( JSContext* cx, uintN argc, jsval* argv );
|
||||
jsval GetRunState( JSContext* cx, uintN argc, jsval* argv );
|
||||
|
||||
jsval RequestNotification( JSContext* cx, uintN argc, jsval* argv );
|
||||
jsval CheckListeners( JSContext* cx, uintN argc, jsval* argv );
|
||||
bool RequestNotification( JSContext* cx, uintN argc, jsval* argv );
|
||||
//Just in case we want to explicitly check the listeners without waiting for the order to be pushed
|
||||
bool ForceCheckListeners( JSContext* cx, uintN argc, jsval* argv );
|
||||
void CheckListeners( int type, CEntity *target );
|
||||
|
||||
bool Order( JSContext* cx, uintN argc, jsval* argv, bool Queued );
|
||||
inline bool OrderSingle( JSContext* cx, uintN argc, jsval* argv )
|
||||
@ -311,6 +316,14 @@ public:
|
||||
debug_assert( argc >= 1 );
|
||||
return( m_classes.IsMember( ToPrimitive<CStrW>( cx, argv[0] ) ) );
|
||||
}
|
||||
jsval TerminateOrder( JSContext* cx, uintN argc, jsval* argv )
|
||||
{
|
||||
debug_assert( argc >= 1);
|
||||
if ( ToPrimitive<bool>( argv[0] ) )
|
||||
m_orderQueue.clear();
|
||||
else
|
||||
m_orderQueue.pop_front();
|
||||
}
|
||||
|
||||
static void ScriptingInit();
|
||||
|
||||
|
@ -85,6 +85,7 @@ public:
|
||||
ORDER_PATH_END_MARKER,
|
||||
ORDER_GENERIC,
|
||||
ORDER_GENERIC_NOPATHING,
|
||||
ORDER_NOTIFY_REQUEST,
|
||||
ORDER_LAST
|
||||
} m_type;
|
||||
SOrderData m_data[ORDER_MAX_DATA];
|
||||
|
@ -39,12 +39,16 @@ CEventTargetChanged::CEventTargetChanged( CEntity* target ) : CScriptEvent( L"ta
|
||||
AddLocalProperty( L"secondaryAction", &m_secondaryAction );
|
||||
}
|
||||
|
||||
CEventPrepareOrder::CEventPrepareOrder( CEntity* target, int orderType ) : CScriptEvent( L"prepareOrder", EVENT_PREPARE_ORDER, true )
|
||||
CEventPrepareOrder::CEventPrepareOrder( CEntity* target, int orderType, int action ) : CScriptEvent( L"prepareOrder", EVENT_PREPARE_ORDER, true )
|
||||
{
|
||||
m_target = target;
|
||||
m_orderType = orderType;
|
||||
m_action = action;
|
||||
AddLocalProperty( L"target", &m_target, true );
|
||||
AddLocalProperty( L"orderType", &m_orderType, true );
|
||||
AddLocalProperty( L"action", &m_action );
|
||||
AddLocalProperty( L"notifyType", &m_notifyType );
|
||||
AddLocalProperty( L"notifySource", &m_notifySource );
|
||||
}
|
||||
|
||||
CEventOrderTransition::CEventOrderTransition( int orderPrevious, int orderCurrent, CEntity*& target, CVector3D& worldPosition ) : CScriptEvent( L"orderTransition", EVENT_ORDER_TRANSITION, true )
|
||||
@ -58,16 +62,14 @@ 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 )
|
||||
CEventNotification::CEventNotification( CEntityOrder order, int notifyType ) : CScriptEvent( L"notification", EVENT_NOTIFICATION, true )
|
||||
{
|
||||
m_type = type;
|
||||
m_notifyType = notifyType;
|
||||
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"notifyType", &m_notifyType );
|
||||
AddLocalProperty( L"target", &m_target );
|
||||
AddLocalProperty( L"data", &m_data );
|
||||
AddLocalProperty( L"location", &m_location );
|
||||
}
|
||||
|
@ -47,7 +47,10 @@ class CEventPrepareOrder : public CScriptEvent
|
||||
CEntity* m_target;
|
||||
int m_orderType;
|
||||
public:
|
||||
CEventPrepareOrder( CEntity* target, int orderType );
|
||||
CEntity* m_notifySource;
|
||||
int m_notifyType;
|
||||
int m_action;
|
||||
CEventPrepareOrder( CEntity* target, int orderType, int action );
|
||||
};
|
||||
|
||||
class CEventOrderTransition : public CScriptEvent
|
||||
@ -63,11 +66,11 @@ 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;
|
||||
int m_action; //u64 is unsupported...will this work?
|
||||
int m_notifyType;
|
||||
CVector3D m_location; //No real use for y, but CVector2D unsupported
|
||||
public:
|
||||
CEventNotification( CEntityOrder order, uint type );
|
||||
CEventNotification( CEntityOrder order, int notifyType );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -260,6 +260,9 @@ uint CSimulation::TranslateMessage(CNetMessage* pMsg, uint clientMask, void* UNU
|
||||
case NMT_Generic:
|
||||
ENTITY_ENTITY_INT(CGeneric, ORDER_GENERIC);
|
||||
break;
|
||||
case NMT_NotifyRequest:
|
||||
ENTITY_ENTITY_INT(CNotifyRequest, ORDER_NOTIFY_REQUEST);
|
||||
break;
|
||||
}
|
||||
|
||||
return clientMask;
|
||||
|
Loading…
Reference in New Issue
Block a user