1
0
forked from 0ad/0ad

This was SVN commit r3507.

This commit is contained in:
pyrolink 2006-02-13 03:32:15 +00:00
parent b3a5c6f8af
commit 10d84599e9
6 changed files with 166 additions and 56 deletions

View File

@ -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) )

View File

@ -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();

View File

@ -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];

View File

@ -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 );
}

View File

@ -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

View File

@ -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;