1
0
forked from 0ad/0ad

Stamina bars, run order

This was SVN commit r3364.
This commit is contained in:
pyrolink 2006-01-16 10:56:47 +00:00
parent a917ffa711
commit 1175b5cdba
9 changed files with 333 additions and 158 deletions

View File

@ -14,7 +14,7 @@ STL_HASH_SET<CStr, CStr_hash_compare> CBaseEntity::scriptsLoaded;
CBaseEntity::CBaseEntity()
{
m_base = NULL;
AddProperty( L"tag", &m_Tag, false );
AddProperty( L"parent", &m_base, false );
AddProperty( L"actions.move.speed", &m_speed );
@ -22,6 +22,8 @@ CBaseEntity::CBaseEntity()
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.move.run.regen_rate", &m_runRegenRate );
AddProperty( L"actions.move.run.decay_rate", &m_runDecayRate );
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 ) );
@ -35,8 +37,13 @@ CBaseEntity::CBaseEntity()
AddProperty( L"traits.extant", &m_extant );
AddProperty( L"traits.corpse", &m_corpse );
AddProperty( L"traits.health.curr", &m_healthCurr );
AddProperty( L"traits.health.max", &m_healthMax );
AddProperty( L"traits.health.bar_height", &m_healthBarHeight );
AddProperty( L"traits.health.max", &m_healthMax );
AddProperty( L"traits.health.bar_height", &m_healthBarHeight );
AddProperty( L"traits.health.bar_size", &m_healthBarSize );
AddProperty( L"traits.stamina.curr", &m_staminaCurr );
AddProperty( L"traits.stamina.max", &m_staminaMax );
AddProperty( L"traits.stamina.bar_height", &m_staminaBarHeight );
AddProperty( L"traits.stamina.bar_size", &m_staminaBarSize );
AddProperty( L"traits.minimap.type", &m_minimapType );
AddProperty( L"traits.minimap.red", &m_minimapR );
AddProperty( L"traits.minimap.green", &m_minimapG );

View File

@ -55,11 +55,18 @@ public:
CBoundingCircle* m_bound_circle;
CBoundingBox* m_bound_box;
CBoundingObject::EBoundingType m_bound_type;
//SP properties
float m_staminaCurr;
float m_staminaMax;
float m_staminaBarHeight;
int m_staminaBarSize;
// HP properties
float m_healthCurr;
float m_healthMax;
float m_healthBarHeight;
int m_healthBarSize;
// Minimap properties
CStrW m_minimapType;
@ -75,7 +82,9 @@ public:
bool m_permanent;
float m_speed;
float m_runRegenRate;
float m_runDecayRate;
SEntityAction m_run;
SEntityAction m_melee;
SEntityAction m_gather;

View File

@ -33,11 +33,16 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation )
m_orientation = orientation;
m_ahead.x = sin( m_orientation );
m_ahead.y = cos( m_orientation );
/* Anything added to this list MUST be added to BaseEntity.cpp (and variables used should
also be added to BaseEntity.h */
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"actions.move.run.regen_rate", &m_runRegenRate );
AddProperty( L"actions.move.run.decay_rate", &m_runDecayRate );
AddProperty( L"selected", &m_selected, false, (NotifyFn)&CEntity::checkSelection );
AddProperty( L"group", &m_grouped, false, (NotifyFn)&CEntity::checkGroup );
AddProperty( L"traits.extant", &m_extant );
@ -58,6 +63,11 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation )
AddProperty( L"traits.health.curr", &m_healthCurr );
AddProperty( L"traits.health.max", &m_healthMax );
AddProperty( L"traits.health.bar_height", &m_healthBarHeight );
AddProperty( L"traits.health.bar_size", &m_healthBarSize );
AddProperty( L"traits.stamina.curr", &m_staminaCurr );
AddProperty( L"traits.stamina.max", &m_staminaMax );
AddProperty( L"traits.stamina.bar_height", &m_staminaBarHeight );
AddProperty( L"traits.stamina.bar_size", &m_staminaBarSize );
AddProperty( L"traits.minimap.type", &m_minimapType );
AddProperty( L"traits.minimap.red", &m_minimapR );
AddProperty( L"traits.minimap.green", &m_minimapG );
@ -102,6 +112,12 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation )
m_isRunning = false;
m_shouldRun = false;
m_triggerRun = false;
m_frameCheck = 0;
m_grouped = -1;
m_player = g_Game->GetPlayer( 0 );
@ -304,8 +320,21 @@ void CEntity::update( size_t timestep )
{
m_position_previous = m_position;
m_orientation_previous = m_orientation;
// Note: aura processing is done before state processing because the state
if ( m_triggerRun )
m_frameCheck++;
CalculateRun( timestep );
if ( m_frameCheck != 0 )
{
m_shouldRun = true;
m_triggerRun = false;
m_frameCheck = 0;
}
// Note: aura processing is done before state processing because the state
// processing code is filled with all kinds of returns
PROFILE_START( "aura processing" );
@ -410,6 +439,7 @@ void CEntity::update( size_t timestep )
updateCollisionPatch();
return;
case CEntityOrder::ORDER_GOTO:
case CEntityOrder::ORDER_RUN:
if( processGoto( current, timestep ) )
break;
updateCollisionPatch();
@ -647,90 +677,13 @@ bool CEntity::acceptsOrder( int orderType, CEntity* orderTarget )
return( DispatchEvent( &evt ) );
}
jsval CEntity::RequestNotification( JSContext* cx, uintN argc, jsval* argv )
{
debug_assert( argc > 3 );
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);
}
target->m_listeners.push_back( notify );
return JSVAL_VOID;
}
void CEntity::DispatchNotification( CEntityOrder order, uint type )
{
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)
{
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;
}
void CEntity::repath()
{
CVector2D destination;
@ -855,11 +808,8 @@ void CEntity::render()
glShadeModel( GL_FLAT );
glBegin( GL_LINE_STRIP );
glVertex3f( m_position.X, m_position.Y + 0.25f, m_position.Z );
x = m_position.X;
y = m_position.Z;
@ -1047,9 +997,8 @@ void CEntity::renderHealthBar()
g_Camera.GetScreenCoordinates(above, sx, sy);
float fraction = clamp(m_healthCurr / m_healthMax, 0.0f, 1.0f);
const float SIZE = 20;
float x1 = sx - SIZE/2;
float x2 = sx + SIZE/2;
float x1 = sx - m_healthBarSize/2;
float x2 = sx + m_healthBarSize/2;
float y = g_yres - sy;
glBegin(GL_LINES);
@ -1058,19 +1007,61 @@ void CEntity::renderHealthBar()
glColor3f( 0, 1, 0 );
glVertex3f( x1, y, 0 );
glColor3f( 0, 1, 0 );
glVertex3f( x1 + SIZE*fraction, y, 0 );
glVertex3f( x1 + m_healthBarSize*fraction, y, 0 );
// red part of bar
glColor3f( 1, 0, 0 );
glVertex3f( x1 + SIZE*fraction, y, 0 );
glVertex3f( x1 + m_healthBarSize*fraction, y, 0 );
glColor3f( 1, 0, 0 );
glVertex3f( x2, y, 0 );
glEnd();
}
void CEntity::renderStaminaBar()
{
if( !m_bounds )
return;
if( m_staminaBarHeight < 0 )
return; // negative bar height means don't display health bar
CCamera *g_Camera=g_Game->GetView()->GetCamera();
float sx, sy;
CVector3D above;
above.X = m_position.X;
above.Z = m_position.Z;
above.Y = getAnchorLevel(m_position.X, m_position.Z) + m_staminaBarHeight;
g_Camera->GetScreenCoordinates(above, sx, sy);
float fraction = clamp(m_staminaCurr / m_staminaMax, 0.0f, 1.0f);
float x1 = sx - m_staminaBarSize/2;
float x2 = sx + m_staminaBarSize/2;
float y = g_yres - sy;
glBegin(GL_LINES);
// blue part of bar
glColor3f( 0, 0, 1 );
glVertex3f( x1, y, 0 );
glColor3f( 0, 0, 1 );
glVertex3f( x1 + m_staminaBarSize*fraction, y, 0 );
// red part of bar
glColor3f( 1, 0, 0 );
glVertex3f( x1 + m_staminaBarSize*fraction, y, 0 );
glColor3f( 1, 0, 0 );
glVertex3f( x2, y, 0 );
glEnd();
}
void CEntity::CalculateRun(float timestep)
{
if ( m_isRunning )
m_staminaCurr = max( 0.0f, m_staminaCurr - timestep / 1000.0f / m_runDecayRate * m_staminaMax );
else if ( m_orderQueue.empty() )
m_staminaCurr = min( m_staminaMax, m_staminaCurr + timestep / 1000.0f / m_runRegenRate * m_staminaMax );
}
/*
Scripting interface
@ -1092,6 +1083,11 @@ 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<jsval, &CEntity::TriggerRun>( "triggerRun", 1 );
AddMethod<jsval, &CEntity::SetRun>( "setRun", 1 );
AddClassProperty( L"template", (CBaseEntity* CEntity::*)&CEntity::m_base, false, (NotifyFn)&CEntity::loadBase );
AddClassProperty( L"traits.id.classes", (GetFn)&CEntity::getClassSet, (SetFn)&CEntity::setClassSet );
@ -1549,3 +1545,90 @@ jsval CEntity::SetActionParams( JSContext* UNUSED(cx), uintN argc, jsval* argv )
return JSVAL_VOID;
}
jsval 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);
}
target->m_listeners.push_back( notify );
return JSVAL_VOID;
}
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)
{
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:
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 );
break;
default:
JS_ReportError( cx, "Invalid order type" );
continue;
}
}
return JSVAL_VOID;
}
jsval CEntity::TriggerRun( JSContext* cx, uintN argc, jsval* argv )
{
m_triggerRun = true;
return JSVAL_VOID;
}
jsval CEntity::SetRun( JSContext* cx, uintN argc, jsval* argv )
{
if( argc < 1 )
{
JS_ReportError( cx, "Too few parameters" );
return( false );
}
m_isRunning = ToPrimitive<bool> ( argv[0] );
return JSVAL_VOID;
}

View File

@ -72,8 +72,9 @@ public:
float m_speed;
float m_turningRadius;
float m_trampleStart;
float m_runRegenRate;
float m_runDecayRate;
SEntityAction m_run;
SEntityAction m_melee;
SEntityAction m_gather;
@ -91,12 +92,23 @@ public:
// If this unit is still active in the gameworld - i.e. not a corpse.
bool m_extant;
bool m_isRunning;
bool m_isRunning; //is it actually running
bool m_shouldRun; //if run was issued, it will remain true until it is stopped
bool m_triggerRun; //used in SetRun, corrects 1 frame stamina imbalance
int m_frameCheck; //counts the frame
//SP properties
float m_staminaCurr;
float m_staminaMax;
float m_staminaBarHeight;
int m_staminaBarSize;
// HP properties
float m_healthCurr;
float m_healthMax;
float m_healthBarHeight;
int m_healthBarSize;
// Minimap properties
CStrW m_minimapType;
@ -237,9 +249,13 @@ public:
void render();
void renderSelectionOutline( float alpha = 1.0f );
void renderHealthBar();
void renderStaminaBar();
// After a collision, recalc the path to the next fixed waypoint.
void repath();
//Calculate stamina points
void CalculateRun(float timestep);
// Reset properties after the entity-template we use changes.
void loadBase();
@ -257,10 +273,8 @@ public:
void clearOrders();
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
static JSBool Construct( JSContext* cx, JSObject* obj, uint argc, jsval* argv, jsval* rval );
@ -277,6 +291,12 @@ public:
jsval RemoveAura( JSContext* cx, uintN argc, jsval* argv );
jsval SetActionParams( JSContext* cx, uintN argc, jsval* argv );
jsval TriggerRun( JSContext* cx, uintN argc, jsval* argv );
jsval SetRun( JSContext* cx, uintN argc, jsval* argv );
jsval IsRunning( JSContext* cx, uintN argc, jsval* argv );
jsval RequestNotification( JSContext* cx, uintN argc, jsval* argv );
jsval CheckListeners( JSContext* cx, uintN argc, jsval* argv );
bool Order( JSContext* cx, uintN argc, jsval* argv, bool Queued );
inline bool OrderSingle( JSContext* cx, uintN argc, jsval* argv )

View File

@ -53,8 +53,8 @@ public:
enum
{
NOTIFY_GOTO = 0x01,
//NOTIFY_ = 0x02, reservered for possible second goto like command
//NOTIFY_FOLLOW = 0x03, //GOTO | RUN
NOTIFY_RUN = 0x02,
NOTIFY_FOLLOW = 0x03, //GOTO | RUN
NOTIFY_ATTACK = 0x04,
NOTIFY_DAMAGE = 0x08,

View File

@ -47,7 +47,10 @@ uint CEntity::processGotoHelper( CEntityOrder* current, size_t timestep_millis,
// Here there be trig.
float scale;
if ( m_run.m_Speed > 0 && len < m_run.m_MaxRange && ( len > m_run.m_MinRange || m_isRunning ) )
//Should we run or walk
if (m_shouldRun && m_staminaCurr > 0 && len < m_run.m_MaxRange &&
( len > m_run.m_MinRange || m_isRunning ) )
{
scale = m_run.m_Speed * timestep;
if ( m_actor )
@ -57,7 +60,7 @@ uint CEntity::processGotoHelper( CEntityOrder* current, size_t timestep_millis,
CSkeletonAnim* run = m_actor->GetRandomAnimation( "run" );
if ( 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 );
m_isRunning = true;
@ -66,28 +69,29 @@ uint CEntity::processGotoHelper( CEntityOrder* current, size_t timestep_millis,
}
else
{
scale = m_speed * timestep;
scale = m_speed * timestep;
if ( m_actor )
{
//Should we update animation?
if ( !m_actor->IsPlayingAnimation( "walk" ) )
{
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 );
m_isRunning = false;
}
}
}
}
}
// Note: Easy optimization: flag somewhere that this unit
// is already pointing the right way, and don't do this
// trig every time.
// is already pointing the way, and don't do this
// trig every time.right
m_targetorientation = atan2( delta.x, delta.y );
@ -237,6 +241,7 @@ bool CEntity::processGotoNoPathing( CEntityOrder* current, size_t timestep_milli
{
m_orderQueue.pop_front();
m_isRunning = false;
m_shouldRun = false;
}
return( false );
case COLLISION_OVERLAPPING_OBJECTS:
@ -245,6 +250,7 @@ bool CEntity::processGotoNoPathing( CEntityOrder* current, size_t timestep_milli
// We're here...
m_orderQueue.pop_front();
m_isRunning = false;
m_shouldRun = false;
return( false );
case COLLISION_NEAR_DESTINATION:
@ -309,6 +315,7 @@ bool CEntity::processGotoNoPathing( CEntityOrder* current, size_t timestep_milli
// Just stop here, repath if necessary.
m_orderQueue.pop_front();
m_isRunning = false;
m_shouldRun = false;
return( false );
default:
@ -329,31 +336,41 @@ bool CEntity::processContactAction( CEntityOrder* current, size_t UNUSED(timeste
if( Distance < action->m_MaxRange )
{
(int&)current->m_type = transition;
m_isRunning = false;
m_orderQueue.push_front(*current); // Seems to be needed since we do a pop above
return( true );
}
if( m_transition && m_actor )
if ( m_actor )
{
if ( m_run.m_Speed > 0 && Distance < m_run.m_MaxRange && ( Distance > m_run.m_MinRange || m_isRunning ) )
//Should we run or walk
if (m_shouldRun && m_staminaCurr > 0 && Distance < m_run.m_MaxRange &&
( Distance > m_run.m_MinRange || m_isRunning ) )
{
CSkeletonAnim* run = m_actor->GetRandomAnimation( "run" );
if ( 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 );
m_isRunning = true;
if ( !m_actor->IsPlayingAnimation( "run" ) )
{
CSkeletonAnim* run = m_actor->GetRandomAnimation( "run" );
if ( 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 );
m_isRunning = true;
}
}
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 );
m_isRunning = false;
//Should we update animation?
if ( !m_actor->IsPlayingAnimation( "walk" ) )
{
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 );
m_isRunning = false;
}
}
}
@ -419,6 +436,7 @@ bool CEntity::processContactActionNoPathing( CEntityOrder* current, size_t times
m_orderQueue.pop_front();
m_isRunning = false;
m_shouldRun = false;
return( false );
}
@ -433,6 +451,7 @@ bool CEntity::processContactActionNoPathing( CEntityOrder* current, size_t times
{
// Too close... do nothing.
m_isRunning = false;
m_shouldRun = false;
return( false );
}
}
@ -445,28 +464,37 @@ bool CEntity::processContactActionNoPathing( CEntityOrder* current, size_t times
delta = delta.normalize() * ( adjRange - m_bounds->m_radius );
float deltaLength = delta.length();
if( m_transition && m_actor )
if ( m_actor )
{
if ( m_run.m_Speed > 0 && deltaLength < m_run.m_MaxRange && ( deltaLength > m_run.m_MinRange || m_isRunning ) )
//Should we run or walk
if (m_shouldRun && m_staminaCurr > 0 && deltaLength < m_run.m_MaxRange &&
( deltaLength > m_run.m_MinRange || m_isRunning ) )
{
CSkeletonAnim* run = m_actor->GetRandomAnimation( "run" );
if ( 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 );
m_isRunning = true;
if ( !m_actor->IsPlayingAnimation( "run" ) )
{
CSkeletonAnim* run = m_actor->GetRandomAnimation( "run" );
if ( 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 );
m_isRunning = true;
}
}
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 );
m_isRunning = false;
}
//Should we update animation?
if ( !m_actor->IsPlayingAnimation( "walk" ) )
{
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 );
m_isRunning = false;
}
}
}
current->m_data[0].location = (CVector2D)current->m_data[0].entity->m_position - delta;
@ -639,29 +667,42 @@ bool CEntity::processGoto( CEntityOrder* current, size_t UNUSED(timestep_millis)
// Let's just check we're going somewhere...
if( Distance < 0.1f )
return( false );
if( m_transition && m_actor )
{
if ( m_run.m_Speed > 0 && Distance < m_run.m_MaxRange && ( Distance > m_run.m_MinRange || m_isRunning ) )
m_isRunning = false;
m_shouldRun = false;
return( false );
}
if ( m_actor )
{
//Should we run or walk
if (m_shouldRun && m_staminaCurr > 0 && Distance < m_run.m_MaxRange &&
( Distance > m_run.m_MinRange || m_isRunning ) )
{
CSkeletonAnim* run = m_actor->GetRandomAnimation( "run" );
if ( 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 );
m_isRunning = true;
if ( !m_actor->IsPlayingAnimation( "run" ) )
{
CSkeletonAnim* run = m_actor->GetRandomAnimation( "run" );
if ( 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 );
m_isRunning = true;
}
}
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 );
m_isRunning = false;
//Should we update animation?
if ( !m_actor->IsPlayingAnimation( "walk" ) )
{
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 );
m_isRunning = false;
}
}
}

View File

@ -42,10 +42,19 @@ CEventTargetChanged::CEventTargetChanged( CEntity* target ) : CScriptEvent( L"ta
m_defaultOrder = -1;
m_defaultAction = 0;
m_defaultCursor = L"arrow-default";
m_secondaryOrder = -1;
m_secondaryAction = 0;
m_secondaryCursor = L"arrow-default";
AddLocalProperty( L"target", &m_target, true );
AddLocalProperty( L"defaultOrder", &m_defaultOrder );
AddLocalProperty( L"defaultAction", &m_defaultAction );
AddLocalProperty( L"defaultCursor", &m_defaultCursor );
AddLocalProperty( L"secondaryOrder", &m_secondaryOrder );
AddLocalProperty( L"secondaryCursor", &m_secondaryCursor );
AddLocalProperty( L"secondaryAction", &m_secondaryAction );
}
CEventPrepareOrder::CEventPrepareOrder( CEntity* target, int orderType ) : CScriptEvent( L"prepareOrder", EVENT_PREPARE_ORDER, true )

View File

@ -67,6 +67,9 @@ public:
int m_defaultOrder;
int m_defaultAction;
CStrW m_defaultCursor;
CStrW m_secondaryCursor;
int m_secondaryOrder;
int m_secondaryAction;
CEventTargetChanged( CEntity* target );
};

View File

@ -263,6 +263,9 @@ uint CSimulation::TranslateMessage(CNetMessage* pMsg, uint clientMask, void* UNU
case NMT_Goto:
ENTITY_POSITION(CGoto, ORDER_GOTO);
break;
case NMT_Run:
ENTITY_POSITION(CRun, ORDER_RUN);
break;
case NMT_Patrol:
ENTITY_POSITION(CPatrol, ORDER_PATROL);
break;