1
0
forked from 0ad/0ad

Random animations.

This was SVN commit r2330.
This commit is contained in:
Ykkrosh 2005-05-21 01:40:32 +00:00
parent 0331883a86
commit 26b1cf5556
13 changed files with 158 additions and 150 deletions

View File

@ -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;i<m_Props.size();i++) {
for (uint i=0; i<m_Props.size(); i++) {
m_Props[i].m_Model->Update(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);

View File

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

View File

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

View File

@ -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<typename T, typename S> static void delete_pair_2nd(std::pair<T,S> v) { delete v.second; }
CObjectEntry::~CObjectEntry()
{
for (size_t i=0;i<m_Animations.size();i++) {
delete m_Animations[i].m_AnimData;
}
std::for_each(m_Animations.begin(), m_Animations.end(), delete_pair_2nd<CStr, CSkeletonAnim*>);
delete m_Model;
}
@ -51,7 +42,7 @@ bool CObjectEntry::BuildRandomVariant(CObjectBase::variation_key& vars, CObjectB
CStr chosenModel;
CStr chosenColor;
std::map<CStr, CObjectBase::Prop> chosenProps;
std::map<CStr, CObjectBase::Anim> chosenAnims;
std::multimap<CStr, CObjectBase::Anim> 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<CObjectBase::Prop>::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<CObjectBase::Anim>::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<CObjectBase::Anim>::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<CObjectBase::Prop> props;
for (std::map<CStr, CObjectBase::Prop>::iterator it = chosenProps.begin(); it != chosenProps.end(); ++it)
m_Props.push_back(it->second);
for (std::map<CStr, CObjectBase::Anim>::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<CStr, CObjectBase::Anim>::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;
}
}

View File

@ -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<CObjectBase::Anim> 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<CObjectBase::Prop> 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<CStr, CSkeletonAnim*> SkeletonAnimMap;
SkeletonAnimMap m_Animations;
// TODO: something more memory-efficient than storing loads of similar strings for each unit?
};

View File

@ -33,7 +33,7 @@ CObjectManager::CObjectManager() : m_SelectedThing(NULL)
m_ObjectTypes.reserve(32);
}
template<typename T, typename S> void delete_pair_2nd(std::pair<T,S> v) { delete v.second; }
template<typename T, typename S> static void delete_pair_2nd(std::pair<T,S> v) { delete v.second; }
CObjectManager::~CObjectManager()
{

View File

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

View File

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

View File

@ -30,4 +30,34 @@ void CUnit::HideAmmunition()
}
// No usual prop.
m_Model->RemoveProp( m_Object->m_AmmunitionPoint );
}
}
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);
}

View File

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

View File

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

View File

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

View File

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