From 26b1cf55568f9e97e50970094fc28b0ab7bf0790 Mon Sep 17 00:00:00 2001 From: Ykkrosh Date: Sat, 21 May 2005 01:40:32 +0000 Subject: [PATCH] Random animations. This was SVN commit r2330. --- source/graphics/Model.cpp | 46 ++++---- source/graphics/Model.h | 2 +- source/graphics/ObjectBase.h | 4 +- source/graphics/ObjectEntry.cpp | 124 ++++++++------------ source/graphics/ObjectEntry.h | 26 ++-- source/graphics/ObjectManager.cpp | 2 +- source/graphics/SkeletonAnim.h | 2 + source/graphics/SkeletonAnimDef.h | 10 +- source/graphics/Unit.cpp | 32 ++++- source/graphics/Unit.h | 18 ++- source/simulation/Entity.cpp | 7 +- source/simulation/Entity.h | 2 +- source/simulation/EntityStateProcessing.cpp | 33 ++---- 13 files changed, 158 insertions(+), 150 deletions(-) diff --git a/source/graphics/Model.cpp b/source/graphics/Model.cpp index 5bd665b587..db24e440f1 100755 --- a/source/graphics/Model.cpp +++ b/source/graphics/Model.cpp @@ -206,16 +206,17 @@ void CModel::CalcAnimatedObjectBound(CSkeletonAnimDef* anim,CBound& result) ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // BuildAnimation: load raw animation frame animation from given file, and build a // animation specific to this model -CSkeletonAnim* CModel::BuildAnimation(const char* filename,float speed,double actionpos,double actionpos2) +CSkeletonAnim* CModel::BuildAnimation(const char* filename, const char* name, float speed, double actionpos, double actionpos2) { CSkeletonAnimDef* def=g_SkelAnimMan.GetAnimation(filename); - if (!def) return 0; + if (!def) return NULL; - CSkeletonAnim* anim=new CSkeletonAnim; - anim->m_AnimDef=def; - anim->m_Speed=speed; - anim->m_ActionPos=(size_t)( actionpos * anim->m_AnimDef->GetDuration() / speed ); - anim->m_ActionPos2=(size_t)( actionpos2 * anim->m_AnimDef->GetDuration() / speed ); + CSkeletonAnim* anim = new CSkeletonAnim; + anim->m_Name = name; + anim->m_AnimDef = def; + anim->m_Speed = speed; + anim->m_ActionPos = (size_t)(actionpos * anim->m_AnimDef->GetDuration() / speed); + anim->m_ActionPos2 = (size_t)(actionpos2 * anim->m_AnimDef->GetDuration() / speed); anim->m_ObjectBounds.SetEmpty(); InvalidateBounds(); @@ -228,30 +229,30 @@ void CModel::Update(float time) { if (m_Anim && m_BoneMatrices) { // convert to ms and adjust for animation speed - float animtime=time*1000*m_Anim->m_Speed; + float animtime = time*1000*m_Anim->m_Speed; // update animation time, but don't calculate bone matrices - do that (lazily) when // something requests them; that saves some calculation work for offscreen models, // and also assures the world space, inverted bone matrices (required for normal // skinning) are up to date with respect to m_Transform - m_AnimTime+=animtime; + m_AnimTime += animtime; - float duration=m_Anim->m_AnimDef->GetDuration(); - if (m_AnimTime>duration) { - if( m_Flags & MODELFLAG_NOLOOPANIMATION ) - SetAnimation( NULL ); - m_AnimTime=(float) fmod(m_AnimTime,duration); + float duration = m_Anim->m_AnimDef->GetDuration(); + if (m_AnimTime > duration) { + if (m_Flags & MODELFLAG_NOLOOPANIMATION) + SetAnimation(NULL); + m_AnimTime = fmod(m_AnimTime, duration); } // mark vertices as dirty SetDirty(RENDERDATA_UPDATE_VERTICES); // mark matrices as dirty - m_BoneMatricesValid=false; + m_BoneMatricesValid = false; } // update props - for (uint i=0;iUpdate(time); } } @@ -303,7 +304,7 @@ bool CModel::SetAnimation(CSkeletonAnim* anim, bool once) if (anim) { m_Flags &= ~MODELFLAG_NOLOOPANIMATION; - if( once ) + if (once) m_Flags |= MODELFLAG_NOLOOPANIMATION; if (!m_BoneMatrices) { @@ -311,7 +312,7 @@ bool CModel::SetAnimation(CSkeletonAnim* anim, bool once) return false; } - if (anim->m_AnimDef->GetNumKeys()!=m_pModelDef->GetNumBones()) { + if (anim->m_AnimDef->GetNumKeys() != m_pModelDef->GetNumBones()) { // mismatch between model's skeleton and animation's skeleton LOG(ERROR, LOG_CATEGORY, "Mismatch between model's skeleton and animation's skeleton (%d model bones != %d animation keys)", m_pModelDef->GetNumBones(), anim->m_AnimDef->GetNumKeys()); @@ -333,7 +334,7 @@ bool CModel::SetAnimation(CSkeletonAnim* anim, bool once) ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // AddProp: add a prop to the model on the given point -void CModel::AddProp(SPropPoint* point,CModel* model) +void CModel::AddProp(SPropPoint* point, CModel* model) { // position model according to prop point position model->SetTransform(point->m_Transform); @@ -375,11 +376,12 @@ void CModel::RemoveProp(SPropPoint* point) // Clone: return a clone of this model CModel* CModel::Clone() const { - CModel* clone=new CModel; - clone->m_ObjectBounds=m_ObjectBounds; + CModel* clone = new CModel; + clone->m_ObjectBounds = m_ObjectBounds; clone->InitModel(m_pModelDef); clone->SetTexture(m_Texture); - if (m_Texture.GetHandle()) h_add_ref(m_Texture.GetHandle()); + if (m_Texture.GetHandle()) + h_add_ref(m_Texture.GetHandle()); clone->SetMaterial(m_Material); clone->SetAnimation(m_Anim); clone->SetFlags(m_Flags); diff --git a/source/graphics/Model.h b/source/graphics/Model.h index 79b27b90b5..8459856748 100755 --- a/source/graphics/Model.h +++ b/source/graphics/Model.h @@ -102,7 +102,7 @@ public: // load raw animation frame animation from given file, and build a // animation specific to this model - CSkeletonAnim* BuildAnimation(const char* filename,float speed,double actionpos,double actionpos2); + CSkeletonAnim* BuildAnimation(const char* filename, const char* name, float speed, double actionpos, double actionpos2); // add a prop to the model on the given point void AddProp(SPropPoint* point,CModel* model); diff --git a/source/graphics/ObjectBase.h b/source/graphics/ObjectBase.h index a3de09cedc..2707fe050f 100644 --- a/source/graphics/ObjectBase.h +++ b/source/graphics/ObjectBase.h @@ -14,7 +14,7 @@ public: struct Anim { // constructor - Anim() : m_Speed(1), m_ActionPos( 0.0 ), m_ActionPos2( 0.0 ), m_AnimData(0) {} + Anim() : m_Speed(1), m_ActionPos(0.0), m_ActionPos2(0.0) {} // name of the animation - "Idle", "Run", etc CStr m_AnimName; @@ -27,8 +27,6 @@ public: // data is loaded) double m_ActionPos; double m_ActionPos2; - // the animation data, specific to the this model - CSkeletonAnim* m_AnimData; }; struct Prop { diff --git a/source/graphics/ObjectEntry.cpp b/source/graphics/ObjectEntry.cpp index e7fd4cce65..bdb53fdb6d 100755 --- a/source/graphics/ObjectEntry.cpp +++ b/source/graphics/ObjectEntry.cpp @@ -22,25 +22,16 @@ #define LOG_CATEGORY "graphics" CObjectEntry::CObjectEntry(int type, CObjectBase* base) -: m_Model(0), m_Type(type), m_Base(base), m_Color(1.0f, 1.0f, 1.0f, 1.0f) +: m_Model(NULL), m_Type(type), m_Base(base), m_Color(1.0f, 1.0f, 1.0f, 1.0f), + m_ProjectileModel(NULL), m_AmmunitionPoint(NULL), m_AmmunitionModel(NULL) { - m_IdleAnim=0; - m_WalkAnim=0; - m_DeathAnim=0; - m_CorpseAnim=0; - m_MeleeAnim=0; - m_GatherAnim=0; - m_RangedAnim=0; - m_ProjectileModel=0; - m_AmmunitionPoint=0; - m_AmmunitionModel=0; } +template static void delete_pair_2nd(std::pair v) { delete v.second; } + CObjectEntry::~CObjectEntry() { - for (size_t i=0;i); delete m_Model; } @@ -51,7 +42,7 @@ bool CObjectEntry::BuildRandomVariant(CObjectBase::variation_key& vars, CObjectB CStr chosenModel; CStr chosenColor; std::map chosenProps; - std::map chosenAnims; + std::multimap chosenAnims; // For each group in m_Base->m_Variants, take whichever variant is specified // by 'vars', and then store its data into the 'chosen' variables. If data @@ -90,8 +81,16 @@ bool CObjectEntry::BuildRandomVariant(CObjectBase::variation_key& vars, CObjectB for (std::vector::iterator it = var.m_Props.begin(); it != var.m_Props.end(); ++it) chosenProps[it->m_PropPointName] = *it; + // If one variant defines one animation called e.g. "attack", and this + // variant defines two different animations with the same name, the one + // original should be erased, and replaced by the two new ones. + // + // So, erase all existing animations which are overridden by this variant: for (std::vector::iterator it = var.m_Anims.begin(); it != var.m_Anims.end(); ++it) - chosenAnims[it->m_AnimName] = *it; + chosenAnims.erase(chosenAnims.lower_bound(it->m_AnimName), chosenAnims.upper_bound(it->m_AnimName)); + // and this insert the new ones: + for (std::vector::iterator it = var.m_Anims.begin(); it != var.m_Anims.end(); ++it) + chosenAnims.insert(make_pair(it->m_AnimName, *it)); } // Copy the chosen data onto this model: @@ -110,12 +109,10 @@ bool CObjectEntry::BuildRandomVariant(CObjectBase::variation_key& vars, CObjectB m_Color = CColor(r/255.0f, g/255.0f, b/255.0f, 1.0f); } + std::vector props; + for (std::map::iterator it = chosenProps.begin(); it != chosenProps.end(); ++it) - m_Props.push_back(it->second); - - for (std::map::iterator it = chosenAnims.begin(); it != chosenAnims.end(); ++it) - m_Animations.push_back(it->second); - + props.push_back(it->second); // Build the model: @@ -148,51 +145,31 @@ bool CObjectEntry::BuildRandomVariant(CObjectBase::variation_key& vars, CObjectB // calculate initial object space bounds, based on vertex positions m_Model->CalcObjectBounds(); - // load animations - for (size_t t = 0; t < m_Animations.size(); t++) + // load the animations + for (std::multimap::iterator it = chosenAnims.begin(); it != chosenAnims.end(); ++it) { - if (m_Animations[t].m_FileName.Length() > 0) - { - const char* animfilename = m_Animations[t].m_FileName; - m_Animations[t].m_AnimData = m_Model->BuildAnimation(animfilename, m_Animations[t].m_Speed, m_Animations[t].m_ActionPos, m_Animations[t].m_ActionPos2); + CStr name = it->first.LowerCase(); - CStr AnimNameLC = m_Animations[t].m_AnimName.LowerCase(); + // TODO: Use consistent names everywhere, then remove this translation section. + // (It's just mapping the names used in actors onto the names used by code.) + if (name == "attack") name = "melee"; + else if (name == "chop") name = "gather"; + else if (name == "decay") name = "corpse"; - if (AnimNameLC == "idle") - m_IdleAnim = m_Animations[t].m_AnimData; - else - if (AnimNameLC == "walk") - m_WalkAnim = m_Animations[t].m_AnimData; - else - if (AnimNameLC == "attack") - m_MeleeAnim = m_Animations[t].m_AnimData; - else - if (AnimNameLC == "chop") - m_GatherAnim = m_Animations[t].m_AnimData; - else - if (AnimNameLC == "death") - m_DeathAnim = m_Animations[t].m_AnimData; - else - if (AnimNameLC == "decay") - m_CorpseAnim = m_Animations[t].m_AnimData; - //else - // debug_printf("Invalid animation name '%s'\n", (const char*)AnimNameLC); - } - else - { - // FIXME, RC - don't store invalid animations (possible?) - m_Animations[t].m_AnimData = NULL; - } + CSkeletonAnim* anim = m_Model->BuildAnimation(it->second.m_FileName, name, it->second.m_Speed, it->second.m_ActionPos, it->second.m_ActionPos2); + if (anim) + m_Animations.insert(std::make_pair(name, anim)); } + // start up idling - if (! m_Model->SetAnimation(m_IdleAnim)) + if (! m_Model->SetAnimation(GetRandomAnimation("idle"))) LOG(ERROR, LOG_CATEGORY, "Failed to set idle animation in model \"%s\"", modelfilename); // build props - TODO, RC - need to fix up bounds here // TODO: Make sure random variations get handled correctly when a prop fails - for (size_t p = 0; p < m_Props.size(); p++) + for (size_t p = 0; p < props.size(); p++) { - const CObjectBase::Prop& prop = m_Props[p]; + const CObjectBase::Prop& prop = props[p]; CObjectEntry* oe = g_ObjMan.FindObjectVariation(prop.m_ModelName, vars, vars_it); if (!oe) @@ -222,8 +199,7 @@ bool CObjectEntry::BuildRandomVariant(CObjectBase::variation_key& vars, CObjectB { CModel* propmodel = oe->m_Model->Clone(); m_Model->AddProp(proppoint, propmodel); - if (oe->m_IdleAnim) - propmodel->SetAnimation(oe->m_IdleAnim); + propmodel->SetAnimation(oe->GetRandomAnimation("idle")); } else LOG(ERROR, LOG_CATEGORY, "Failed to find matching prop point called \"%s\" in model \"%s\" on actor \"%s\"", (const char*)prop.m_PropPointName, modelfilename, (const char*)prop.m_ModelName); @@ -275,21 +251,21 @@ bool CObjectEntry::BuildRandomVariant(CObjectBase::variation_key& vars, CObjectB } -CSkeletonAnim* CObjectEntry::GetNamedAnimation(CStr animationName) +CSkeletonAnim* CObjectEntry::GetRandomAnimation(const CStr& animationName) { - for (size_t t = 0; t < m_Animations.size(); t++) - if (m_Animations[t].m_AnimName == animationName) - return m_Animations[t].m_AnimData; - - return NULL; -} - - -CObjectBase::Prop* CObjectEntry::FindProp(const char* proppointname) -{ - for (size_t i = 0; i < m_Props.size(); i++) - if (strcmp(proppointname, m_Props[i].m_PropPointName) == 0) - return &m_Props[i]; - - return NULL; + SkeletonAnimMap::iterator lower = m_Animations.lower_bound(animationName); + SkeletonAnimMap::iterator upper = m_Animations.upper_bound(animationName); + size_t count = std::distance(lower, upper); + if (count == 0) + { +// LOG(WARNING, LOG_CATEGORY, "Failed to find animation '%s' for actor '%s'", animationName.c_str(), m_ModelName.c_str()); + return NULL; + } + else + { + // TODO: Do we care about network synchronisation of random animations? + int id = rand() % (int)count; + std::advance(lower, id); + return lower->second; + } } diff --git a/source/graphics/ObjectEntry.h b/source/graphics/ObjectEntry.h index b8a19f6104..1270ec8baa 100755 --- a/source/graphics/ObjectEntry.h +++ b/source/graphics/ObjectEntry.h @@ -22,35 +22,33 @@ public: // different variations of the actor. CObjectBase* m_Base; - CObjectBase::Prop* FindProp(const char* proppointname); - // texture name CStr m_TextureName; // model name CStr m_ModelName; // colour (used when doing alpha-channel colouring, but not doing player-colour) CColor m_Color; - // list of valid animations for this object - std::vector m_Animations; - CSkeletonAnim* m_IdleAnim; - CSkeletonAnim* m_WalkAnim; - CSkeletonAnim* m_DeathAnim; - CSkeletonAnim* m_MeleeAnim; - CSkeletonAnim* m_GatherAnim; - CSkeletonAnim* m_RangedAnim; - CSkeletonAnim* m_CorpseAnim; + // (probable TODO: make colour a per-model thing, rather than per-objectEntry, + // so we can have lots of colour variations without wasting memory on + // lots of objectEntries) CModel* m_ProjectileModel; CModel* m_AmmunitionModel; SPropPoint* m_AmmunitionPoint; - CSkeletonAnim* GetNamedAnimation( CStr animationName ); - // list of props attached to object - std::vector m_Props; + // Returns a randomly-chosen animation matching the given name. + // If none is found, returns NULL. + CSkeletonAnim* GetRandomAnimation(const CStr& animationName); + // corresponding model CModel* m_Model; // type of object; index into object managers types array int m_Type; + +private: + typedef std::multimap SkeletonAnimMap; + SkeletonAnimMap m_Animations; + // TODO: something more memory-efficient than storing loads of similar strings for each unit? }; diff --git a/source/graphics/ObjectManager.cpp b/source/graphics/ObjectManager.cpp index b62b068db4..0444792a5a 100755 --- a/source/graphics/ObjectManager.cpp +++ b/source/graphics/ObjectManager.cpp @@ -33,7 +33,7 @@ CObjectManager::CObjectManager() : m_SelectedThing(NULL) m_ObjectTypes.reserve(32); } -template void delete_pair_2nd(std::pair v) { delete v.second; } +template static void delete_pair_2nd(std::pair v) { delete v.second; } CObjectManager::~CObjectManager() { diff --git a/source/graphics/SkeletonAnim.h b/source/graphics/SkeletonAnim.h index 83fa511270..d61e3a47de 100755 --- a/source/graphics/SkeletonAnim.h +++ b/source/graphics/SkeletonAnim.h @@ -19,6 +19,8 @@ class CSkeletonAnimDef; class CSkeletonAnim { public: + // the name of the action which uses this animation (e.g. "idle") + CStr m_Name; // the raw animation frame data CSkeletonAnimDef* m_AnimDef; // speed at which this animation runs diff --git a/source/graphics/SkeletonAnimDef.h b/source/graphics/SkeletonAnimDef.h index 0d1fc200fd..c11e78d2d7 100755 --- a/source/graphics/SkeletonAnimDef.h +++ b/source/graphics/SkeletonAnimDef.h @@ -50,8 +50,8 @@ public: u32 GetNumKeys() const { return m_NumKeys; } // accessors: get a key for given bone at given time - Key& GetKey(u32 frame,u32 bone) { return m_Keys[frame*m_NumKeys+bone]; } - const Key& GetKey(u32 frame,u32 bone) const { return m_Keys[frame*m_NumKeys+bone]; } + Key& GetKey(u32 frame, u32 bone) { return m_Keys[frame*m_NumKeys+bone]; } + const Key& GetKey(u32 frame, u32 bone) const { return m_Keys[frame*m_NumKeys+bone]; } // get duration of this anim, in ms float GetDuration() const { return m_NumFrames*m_FrameTime; } @@ -62,15 +62,15 @@ public: u32 GetNumFrames() const { return m_NumFrames; } // build matrices for all bones at the given time (in MS) in this animation - void BuildBoneMatrices(float time,CMatrix3D* matrices) const; + void BuildBoneMatrices(float time, CMatrix3D* matrices) const; // anim I/O functions static CSkeletonAnimDef* Load(const char* filename); - static void Save(const char* filename,const CSkeletonAnimDef* anim); + static void Save(const char* filename, const CSkeletonAnimDef* anim); public: // name of the animation - CStr m_Name; + CStr m_Name; // TODO: this doesn't seem to be used, so it's just a waste of memory... // frame time - time between successive frames, in ms float m_FrameTime; // number of keys in each frame - should match number of bones in the skeleton diff --git a/source/graphics/Unit.cpp b/source/graphics/Unit.cpp index 5c2786857b..7b184d4430 100644 --- a/source/graphics/Unit.cpp +++ b/source/graphics/Unit.cpp @@ -30,4 +30,34 @@ void CUnit::HideAmmunition() } // No usual prop. m_Model->RemoveProp( m_Object->m_AmmunitionPoint ); -} \ No newline at end of file +} + +bool CUnit::SetRandomAnimation(const CStr& name, bool once) +{ + CSkeletonAnim* anim = GetRandomAnimation(name); + if (anim) + { + m_Model->SetAnimation(anim, once); + return true; + } + else + { + // TODO - report an error? + return false; + } +} + +CSkeletonAnim* CUnit::GetRandomAnimation(const CStr& name) +{ + CSkeletonAnim* anim = m_Object->GetRandomAnimation(name); + // Fall back to 'idle', if no matching animation is found + if (anim == NULL && name != "idle") + anim = m_Object->GetRandomAnimation("idle"); + + return anim; +} + +bool CUnit::IsPlayingAnimation(const CStr& name) +{ + return (m_Model->GetAnimation()->m_Name == name); +} diff --git a/source/graphics/Unit.h b/source/graphics/Unit.h index 36cecb25f2..d075add603 100755 --- a/source/graphics/Unit.h +++ b/source/graphics/Unit.h @@ -6,6 +6,8 @@ class CModel; class CObjectEntry; class CEntity; +class CSkeletonAnim; +class CStr8; ///////////////////////////////////////////////////////////////////////////////////////////// // CUnit: simple "actor" definition - defines a sole object within the world @@ -13,10 +15,10 @@ class CUnit { public: // constructor - unit invalid without a model and object - CUnit(CObjectEntry* object,CModel* model) : m_Object(object), m_Model(model), m_Entity(NULL) { + CUnit(CObjectEntry* object, CModel* model) : m_Object(object), m_Model(model), m_Entity(NULL) { assert(object && model); } - CUnit(CObjectEntry* object,CModel* model, CEntity* entity) : m_Object(object), m_Model(model), m_Entity(entity) { + CUnit(CObjectEntry* object, CModel* model, CEntity* entity) : m_Object(object), m_Model(model), m_Entity(entity) { assert(object && model); } @@ -35,6 +37,18 @@ public: void ShowAmmunition(); void HideAmmunition(); + // Sets the animation a random one matching 'name'. If none is found, + // sets to idle instead. + bool SetRandomAnimation(const CStr8& name, bool once = false); + + // Returns the animation a random one matching 'name'. If none is found, + // returns idle instead. + CSkeletonAnim* GetRandomAnimation(const CStr8& name); + + // Returns whether the currently active animation is one of the ones + // matchin 'name'. + bool IsPlayingAnimation(const CStr8& name); + private: // object from which unit was created CObjectEntry* m_Object; diff --git a/source/simulation/Entity.cpp b/source/simulation/Entity.cpp index 0a466ccb8f..886d11501b 100755 --- a/source/simulation/Entity.cpp +++ b/source/simulation/Entity.cpp @@ -331,10 +331,11 @@ void CEntity::update( size_t timestep ) if( m_extant ) { if( ( m_lastState != -1 ) || !m_actor->GetModel()->GetAnimation() ) - m_actor->GetModel()->SetAnimation( m_actor->GetObject()->m_IdleAnim ); + m_actor->SetRandomAnimation( "idle" ); + } else if( !m_actor->GetModel()->GetAnimation() ) - m_actor->GetModel()->SetAnimation( m_actor->GetObject()->m_CorpseAnim ); + m_actor->SetRandomAnimation( "corpse" ); } if( m_lastState != -1 ) @@ -860,7 +861,7 @@ bool CEntity::Kill( JSContext* cx, uintN argc, jsval* argv ) clearOrders(); if( m_actor ) - m_actor->GetModel()->SetAnimation( m_actor->GetObject()->m_DeathAnim, true ); + m_actor->SetRandomAnimation( "death", true ); return( true ); } diff --git a/source/simulation/Entity.h b/source/simulation/Entity.h index 2f28737b0c..f04d5113e5 100755 --- a/source/simulation/Entity.h +++ b/source/simulation/Entity.h @@ -120,7 +120,7 @@ private: uint processGotoHelper( CEntityOrder* current, size_t timestep_milli, HEntity& collide ); bool processContactAction( CEntityOrder* current, size_t timestep_millis, int transition, SEntityAction* action ); - bool processContactActionNoPathing( CEntityOrder* current, size_t timestep_millis, CSkeletonAnim* animation, CScriptEvent* contactEvent, SEntityAction* action ); + bool processContactActionNoPathing( CEntityOrder* current, size_t timestep_millis, const CStr& animation, CScriptEvent* contactEvent, SEntityAction* action ); bool processAttackMelee( CEntityOrder* current, size_t timestep_milli ); bool processAttackMeleeNoPathing( CEntityOrder* current, size_t timestep_milli ); diff --git a/source/simulation/EntityStateProcessing.cpp b/source/simulation/EntityStateProcessing.cpp index bff0a8220b..71dc0c222f 100755 --- a/source/simulation/EntityStateProcessing.cpp +++ b/source/simulation/EntityStateProcessing.cpp @@ -287,7 +287,7 @@ bool CEntity::processContactAction( CEntityOrder* current, size_t timestep_milli if( m_transition && m_actor ) { - m_actor->GetModel()->SetAnimation( m_actor->GetObject()->m_WalkAnim ); + m_actor->SetRandomAnimation( "walk" ); // Animation desync m_actor->GetModel()->Update( ( rand() * 1000.0f ) / 1000.0f ); } @@ -298,7 +298,7 @@ bool CEntity::processContactAction( CEntityOrder* current, size_t timestep_milli return( true ); } -bool CEntity::processContactActionNoPathing( CEntityOrder* current, size_t timestep_millis, CSkeletonAnim* animation, CScriptEvent* contactEvent, SEntityAction* action ) +bool CEntity::processContactActionNoPathing( CEntityOrder* current, size_t timestep_millis, const CStr& animation, CScriptEvent* contactEvent, SEntityAction* action ) { if( m_fsm_cyclepos != NOT_IN_CYCLE ) { @@ -373,9 +373,9 @@ bool CEntity::processContactActionNoPathing( CEntityOrder* current, size_t times // (is this good enough?) // Play walk for a bit. - if( m_actor && ( m_actor->GetModel()->GetAnimation() != m_actor->GetObject()->m_WalkAnim ) ) + if( m_actor && ! m_actor->IsPlayingAnimation( "walk" ) ) { - m_actor->GetModel()->SetAnimation( m_actor->GetObject()->m_WalkAnim ); + m_actor->SetRandomAnimation( "walk" ); // Animation desync m_actor->GetModel()->Update( ( rand() * 1000.0f ) / 1000.0f ); } @@ -440,8 +440,8 @@ bool CEntity::processContactActionNoPathing( CEntityOrder* current, size_t times } // Pick our animation, calculate the time to play it, and start the timer. - m_fsm_animation = animation; // <- Replace with a call that gets one randomly, probably pass in a CSkeletonAnim* (void) fn for this purpose - + m_fsm_animation = m_actor->GetRandomAnimation( animation ); + // Here's the idea - we want to be at that animation's event point // when the timer reaches action->m_Speed. The timer increments by 2 every millisecond. // animation->m_actionpos is the time offset into that animation that event @@ -461,7 +461,7 @@ bool CEntity::processContactActionNoPathing( CEntityOrder* current, size_t times // If we've just transitioned, play idle. Otherwise, let the previous animation complete, if it // hasn't already. if( m_transition ) - m_actor->GetModel()->SetAnimation( m_actor->GetObject()->m_IdleAnim ); + m_actor->SetRandomAnimation( "idle" ); } // Load time needs to be animation->m_ActionPos2 ms after the start of the animation. @@ -486,14 +486,7 @@ bool CEntity::processAttackMeleeNoPathing( CEntityOrder* current, size_t timeste { CEventAttack evt( current->m_data[0].entity ); if( !m_actor ) return( false ); - CSkeletonAnim* animation = m_actor->GetObject()->m_MeleeAnim; - if( !animation ) animation = m_actor->GetObject()->m_IdleAnim; - if( !animation ) return( false ); // Should probably tell people why this is failing - // (didn't specify an actor or animation) but that - // would probably involve including CLogger.h, which - // conflicts. - - return( processContactActionNoPathing( current, timestep_milli, animation, &evt, &m_melee ) ); + return( processContactActionNoPathing( current, timestep_milli, "melee", &evt, &m_melee ) ); } bool CEntity::processGather( CEntityOrder* current, size_t timestep_millis ) { @@ -504,13 +497,7 @@ bool CEntity::processGatherNoPathing( CEntityOrder* current, size_t timestep_mil { CEventGather evt( current->m_data[0].entity ); if( !m_actor ) return( false ); - CSkeletonAnim* animation = m_actor->GetObject()->m_GatherAnim; - if( !animation ) animation = m_actor->GetObject()->m_IdleAnim; - if( !animation ) return( false ); // Should probably tell people why this is failing - // (didn't specify an actor or animation) but that - // would probably involve including CLogger.h, which - // conflicts. - return( processContactActionNoPathing( current, timestep_millis, animation, &evt, &m_gather ) ); + return( processContactActionNoPathing( current, timestep_millis, "gather", &evt, &m_gather ) ); } bool CEntity::processGoto( CEntityOrder* current, size_t timestep_millis ) @@ -527,7 +514,7 @@ bool CEntity::processGoto( CEntityOrder* current, size_t timestep_millis ) if( m_transition && m_actor ) { - m_actor->GetModel()->SetAnimation( m_actor->GetObject()->m_WalkAnim ); + m_actor->SetRandomAnimation( "walk" ); // Animation desync m_actor->GetModel()->Update( ( rand() * 1000.0f ) / 1000.0f ); }