1
0
forked from 0ad/0ad

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:
leper 2012-12-06 19:46:13 +00:00
parent d18b9dd2dc
commit 8c931bfa52
7 changed files with 132 additions and 31 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -84,6 +84,11 @@ public:
*/
virtual void StopMoving() = 0;
/**
* Get the current movement speed.
*/
virtual fixed GetCurrentSpeed() = 0;
/**
* Set the current movement speed.
*/

View File

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

View File

@ -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.
*/