Add animation override to VisualActor to fix carrying resource animations. Patch by Deiz. Fixes #1260, #1741.
This was SVN commit r12949.
This commit is contained in:
parent
d18b9dd2dc
commit
8c931bfa52
@ -1159,11 +1159,17 @@ var UnitFsmSpec = {
|
||||
|
||||
"APPROACHING": {
|
||||
"enter": function () {
|
||||
// Show weapons rather than carried resources.
|
||||
this.SetGathererAnimationOverride(true);
|
||||
|
||||
this.SelectAnimation("move");
|
||||
this.StartTimer(1000, 1000);
|
||||
},
|
||||
|
||||
"leave": function() {
|
||||
// Show carried resources when walking.
|
||||
this.SetGathererAnimationOverride();
|
||||
|
||||
this.StopTimer();
|
||||
},
|
||||
|
||||
@ -1330,11 +1336,17 @@ var UnitFsmSpec = {
|
||||
|
||||
"CHASING": {
|
||||
"enter": function () {
|
||||
// Show weapons rather than carried resources.
|
||||
this.SetGathererAnimationOverride(true);
|
||||
|
||||
this.SelectAnimation("move");
|
||||
this.StartTimer(1000, 1000);
|
||||
},
|
||||
|
||||
"leave": function() {
|
||||
// Show carried resources when walking.
|
||||
this.SetGathererAnimationOverride();
|
||||
|
||||
this.StopTimer();
|
||||
},
|
||||
|
||||
@ -1485,6 +1497,9 @@ var UnitFsmSpec = {
|
||||
|
||||
"leave": function() {
|
||||
this.StopTimer();
|
||||
|
||||
// Show the carried resource, if we've gathered anything.
|
||||
this.SetGathererAnimationOverride();
|
||||
},
|
||||
|
||||
"Timer": function(msg) {
|
||||
@ -1739,24 +1754,7 @@ var UnitFsmSpec = {
|
||||
"RETURNRESOURCE": {
|
||||
"APPROACHING": {
|
||||
"enter": function () {
|
||||
// Work out what we're carrying, in order to select an appropriate animation
|
||||
var cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
|
||||
var type = cmpResourceGatherer.GetLastCarriedType();
|
||||
if (type)
|
||||
{
|
||||
var typename = "carry_" + type.generic;
|
||||
|
||||
// Special case for meat
|
||||
if (type.specific == "meat")
|
||||
typename = "carry_" + type.specific;
|
||||
|
||||
this.SelectAnimation(typename, false, this.GetWalkSpeed());
|
||||
}
|
||||
else
|
||||
{
|
||||
// We're returning empty-handed
|
||||
this.SelectAnimation("move");
|
||||
}
|
||||
},
|
||||
|
||||
"MoveCompleted": function() {
|
||||
@ -1777,6 +1775,9 @@ var UnitFsmSpec = {
|
||||
var cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
|
||||
cmpResourceGatherer.CommitResources(dropsiteTypes);
|
||||
|
||||
// Stop showing the carried resource animation.
|
||||
this.SetGathererAnimationOverride();
|
||||
|
||||
// Our next order should always be a Gather,
|
||||
// so just switch back to that order
|
||||
this.FinishOrder();
|
||||
@ -1960,7 +1961,7 @@ var UnitFsmSpec = {
|
||||
"GARRISON": {
|
||||
"APPROACHING": {
|
||||
"enter": function() {
|
||||
this.SelectAnimation("walk", false, this.GetWalkSpeed());
|
||||
this.SelectAnimation("move");
|
||||
},
|
||||
|
||||
"MoveCompleted": function() {
|
||||
@ -2920,6 +2921,39 @@ UnitAI.prototype.PlaySound = function(name)
|
||||
}
|
||||
};
|
||||
|
||||
UnitAI.prototype.SetGathererAnimationOverride = function(disable)
|
||||
{
|
||||
var cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
|
||||
if (!cmpResourceGatherer)
|
||||
return;
|
||||
|
||||
var cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
|
||||
if (!cmpVisual)
|
||||
return;
|
||||
|
||||
// Remove the animation override, so that weapons are shown again.
|
||||
if (disable)
|
||||
{
|
||||
cmpVisual.ResetMoveAnimation("walk");
|
||||
return;
|
||||
}
|
||||
|
||||
// Work out what we're carrying, in order to select an appropriate animation
|
||||
var type = cmpResourceGatherer.GetLastCarriedType();
|
||||
if (type)
|
||||
{
|
||||
var typename = "carry_" + type.generic;
|
||||
|
||||
// Special case for meat
|
||||
if (type.specific == "meat")
|
||||
typename = "carry_" + type.specific;
|
||||
|
||||
cmpVisual.ReplaceMoveAnimation("walk", typename);
|
||||
}
|
||||
else
|
||||
cmpVisual.ResetMoveAnimation("walk");
|
||||
}
|
||||
|
||||
UnitAI.prototype.SelectAnimation = function(name, once, speed, sound)
|
||||
{
|
||||
var cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
|
||||
|
@ -228,6 +228,9 @@ public:
|
||||
|
||||
fixed m_Speed;
|
||||
|
||||
// Current mean speed (over the last turn).
|
||||
fixed m_CurSpeed;
|
||||
|
||||
// Currently active paths (storing waypoints in reverse order).
|
||||
// The last item in each path is the point we're currently heading towards.
|
||||
ICmpPathfinder::Path m_LongPath;
|
||||
@ -280,6 +283,7 @@ public:
|
||||
m_Moving = false;
|
||||
m_WalkSpeed = paramNode.GetChild("WalkSpeed").ToFixed();
|
||||
m_Speed = m_WalkSpeed;
|
||||
m_CurSpeed = fixed::Zero();
|
||||
|
||||
if (paramNode.GetChild("Run").IsOk())
|
||||
{
|
||||
@ -414,6 +418,11 @@ public:
|
||||
return m_PassClass;
|
||||
}
|
||||
|
||||
virtual fixed GetCurrentSpeed()
|
||||
{
|
||||
return m_CurSpeed;
|
||||
}
|
||||
|
||||
virtual void SetSpeed(fixed speed)
|
||||
{
|
||||
m_Speed = speed;
|
||||
@ -497,6 +506,9 @@ private:
|
||||
if (cmpObstruction)
|
||||
cmpObstruction->SetMovingFlag(false);
|
||||
|
||||
// No longer moving, so speed is 0.
|
||||
m_CurSpeed = fixed::Zero();
|
||||
|
||||
CMessageMotionChanged msg(false, false);
|
||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg);
|
||||
}
|
||||
@ -886,6 +898,9 @@ void CCmpUnitMotion::Move(fixed dt)
|
||||
if (pos != initialPos)
|
||||
cmpPosition->MoveTo(pos.X, pos.Y);
|
||||
|
||||
// Calculate the mean speed over this past turn.
|
||||
m_CurSpeed = cmpPosition->GetDistanceTravelled() / dt;
|
||||
|
||||
if (wasObstructed)
|
||||
{
|
||||
// Oops, we hit something (very likely another unit).
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "ICmpOwnership.h"
|
||||
#include "ICmpPosition.h"
|
||||
#include "ICmpRangeManager.h"
|
||||
#include "ICmpUnitMotion.h"
|
||||
#include "ICmpVision.h"
|
||||
#include "simulation2/MessageTypes.h"
|
||||
#include "simulation2/components/ICmpFootprint.h"
|
||||
@ -59,6 +60,8 @@ public:
|
||||
|
||||
fixed m_R, m_G, m_B; // shading colour
|
||||
|
||||
std::map<std::string, std::string> m_AnimOverride;
|
||||
|
||||
ICmpRangeManager::ELosVisibility m_Visibility; // only valid between Interpolate and RenderSubmit
|
||||
|
||||
// Current animation state
|
||||
@ -372,6 +375,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ReplaceMoveAnimation(std::string name, std::string replace)
|
||||
{
|
||||
m_AnimOverride[name] = replace;
|
||||
}
|
||||
|
||||
virtual void ResetMoveAnimation(std::string name)
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator it = m_AnimOverride.find(name);
|
||||
if (it != m_AnimOverride.end())
|
||||
m_AnimOverride.erase(name);
|
||||
}
|
||||
|
||||
virtual void SetUnitEntitySelection(const CStr& selection)
|
||||
{
|
||||
if (m_Unit)
|
||||
@ -566,7 +581,7 @@ void CCmpVisualActor::InitSelectionShapeDescriptor(CModelAbstract& model, const
|
||||
model.SetCustomSelectionShape(shapeDescriptor);
|
||||
}
|
||||
|
||||
void CCmpVisualActor::Update(fixed turnLength)
|
||||
void CCmpVisualActor::Update(fixed UNUSED(turnLength))
|
||||
{
|
||||
if (m_Unit == NULL)
|
||||
return;
|
||||
@ -580,25 +595,34 @@ void CCmpVisualActor::Update(fixed turnLength)
|
||||
if (!cmpPosition || !cmpPosition->IsInWorld())
|
||||
return;
|
||||
|
||||
float speed = cmpPosition->GetDistanceTravelled().ToFloat() / turnLength.ToFloat();
|
||||
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), GetEntityId());
|
||||
if (!cmpUnitMotion)
|
||||
return;
|
||||
|
||||
float speed = cmpUnitMotion->GetCurrentSpeed().ToFloat();
|
||||
|
||||
std::string name;
|
||||
if (speed == 0.0f)
|
||||
name = "idle";
|
||||
else
|
||||
name = (speed < m_AnimRunThreshold.ToFloat()) ? "walk" : "run";
|
||||
|
||||
std::map<std::string, std::string>::const_iterator it = m_AnimOverride.find(name);
|
||||
if (it != m_AnimOverride.end())
|
||||
name = it->second;
|
||||
|
||||
m_Unit->SetEntitySelection(name);
|
||||
if (speed == 0.0f)
|
||||
{
|
||||
m_Unit->SetEntitySelection("idle");
|
||||
m_Unit->SetEntitySelection(name);
|
||||
if (m_Unit->GetAnimation())
|
||||
m_Unit->GetAnimation()->SetAnimationState("idle", false, 1.f, 0.f, L"");
|
||||
}
|
||||
else if (speed < m_AnimRunThreshold.ToFloat())
|
||||
{
|
||||
m_Unit->SetEntitySelection("walk");
|
||||
if (m_Unit->GetAnimation())
|
||||
m_Unit->GetAnimation()->SetAnimationState("walk", false, speed, 0.f, L"");
|
||||
m_Unit->GetAnimation()->SetAnimationState(name, false, 1.f, 0.f, L"");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Unit->SetEntitySelection("run");
|
||||
m_Unit->SetEntitySelection(name);
|
||||
if (m_Unit->GetAnimation())
|
||||
m_Unit->GetAnimation()->SetAnimationState("run", false, speed, 0.f, L"");
|
||||
m_Unit->GetAnimation()->SetAnimationState(name, false, speed, 0.f, L"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ DEFINE_INTERFACE_METHOD_3("MoveToTargetRange", bool, ICmpUnitMotion, MoveToTarge
|
||||
DEFINE_INTERFACE_METHOD_3("MoveToFormationOffset", void, ICmpUnitMotion, MoveToFormationOffset, entity_id_t, entity_pos_t, entity_pos_t)
|
||||
DEFINE_INTERFACE_METHOD_2("FaceTowardsPoint", void, ICmpUnitMotion, FaceTowardsPoint, entity_pos_t, entity_pos_t)
|
||||
DEFINE_INTERFACE_METHOD_0("StopMoving", void, ICmpUnitMotion, StopMoving)
|
||||
DEFINE_INTERFACE_METHOD_0("GetCurrentSpeed", fixed, ICmpUnitMotion, GetCurrentSpeed)
|
||||
DEFINE_INTERFACE_METHOD_1("SetSpeed", void, ICmpUnitMotion, SetSpeed, fixed)
|
||||
DEFINE_INTERFACE_METHOD_0("IsMoving", bool, ICmpUnitMotion, IsMoving)
|
||||
DEFINE_INTERFACE_METHOD_0("GetWalkSpeed", fixed, ICmpUnitMotion, GetWalkSpeed)
|
||||
@ -78,6 +79,11 @@ public:
|
||||
m_Script.CallVoid("StopMoving");
|
||||
}
|
||||
|
||||
virtual fixed GetCurrentSpeed()
|
||||
{
|
||||
return m_Script.Call<fixed>("GetCurrentSpeed");
|
||||
}
|
||||
|
||||
virtual void SetSpeed(fixed speed)
|
||||
{
|
||||
m_Script.CallVoid("SetSpeed", speed);
|
||||
|
@ -84,6 +84,11 @@ public:
|
||||
*/
|
||||
virtual void StopMoving() = 0;
|
||||
|
||||
/**
|
||||
* Get the current movement speed.
|
||||
*/
|
||||
virtual fixed GetCurrentSpeed() = 0;
|
||||
|
||||
/**
|
||||
* Set the current movement speed.
|
||||
*/
|
||||
|
@ -24,6 +24,8 @@
|
||||
BEGIN_INTERFACE_WRAPPER(Visual)
|
||||
DEFINE_INTERFACE_METHOD_4("SelectAnimation", void, ICmpVisual, SelectAnimation, std::string, bool, fixed, std::wstring)
|
||||
DEFINE_INTERFACE_METHOD_1("SelectMovementAnimation", void, ICmpVisual, SelectMovementAnimation, fixed)
|
||||
DEFINE_INTERFACE_METHOD_1("ResetMoveAnimation", void, ICmpVisual, ResetMoveAnimation, std::string)
|
||||
DEFINE_INTERFACE_METHOD_2("ReplaceMoveAnimation", void, ICmpVisual, ReplaceMoveAnimation, std::string, std::string)
|
||||
DEFINE_INTERFACE_METHOD_1("SetAnimationSyncRepeat", void, ICmpVisual, SetAnimationSyncRepeat, fixed)
|
||||
DEFINE_INTERFACE_METHOD_1("SetAnimationSyncOffset", void, ICmpVisual, SetAnimationSyncOffset, fixed)
|
||||
DEFINE_INTERFACE_METHOD_4("SetShadingColour", void, ICmpVisual, SetShadingColour, fixed, fixed, fixed, fixed)
|
||||
|
@ -91,6 +91,21 @@ public:
|
||||
*/
|
||||
virtual void SelectAnimation(std::string name, bool once, fixed speed, std::wstring soundgroup) = 0;
|
||||
|
||||
/**
|
||||
* Replaces a specified animation with another. Only affects the special speed-based
|
||||
* animation determination behaviour.
|
||||
* @param name Animation to match.
|
||||
* @param replace Animation that should replace the matched animation.
|
||||
*/
|
||||
virtual void ReplaceMoveAnimation(std::string name, std::string replace) = 0;
|
||||
|
||||
/**
|
||||
* Ensures that the given animation will be used when it normally would be,
|
||||
* removing reference to any animation that might replace it.
|
||||
* @param name Animation name to remove from the replacement map.
|
||||
*/
|
||||
virtual void ResetMoveAnimation(std::string name) = 0;
|
||||
|
||||
/**
|
||||
* Sets the specified entity selection on the underlying unit.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user