Allow simulation to set the actor variant selection, and use it for the garrison flag. Fixes #3952 Refs #2679, #3983

This was SVN commit r18266.
This commit is contained in:
sanderd17 2016-05-30 14:07:48 +00:00
parent df971c3885
commit 83af69286d
9 changed files with 64 additions and 53 deletions

View File

@ -17,12 +17,15 @@
</variant>
</group>
<group>
<variant frequency="100" name="Idle"/>
<variant frequency="1" name="ungarrisoned"/>
<variant name="garrisoned">
<props>
<prop actor="props/special/common/waypoint_flag_0ad.xml" attachpoint="garrisoned"/>
</props>
</variant>
</group>
<group>
<variant frequency="1" name="alive"/>
<variant name="death">
<props>
<prop attachpoint="garrisoned"/>

View File

@ -1,6 +1,6 @@
<variant name="gather_fruit">
<animations>
<animation file="infantry/general/forage.psa" name="gather_fruit" speed="125"/>
<animation file="infantry/general/forage.psa" frequency="1" speed="125"/>
</animations>
<props>
<prop actor="props/units/tools/basket.xml" attachpoint="l_leg"/>

View File

@ -566,16 +566,11 @@ GarrisonHolder.prototype.HealTimeout = function(data)
GarrisonHolder.prototype.UpdateGarrisonFlag = function()
{
var cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
let cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
if (!cmpVisual)
return;
cmpVisual.SelectAnimation("garrisoned", true, 0, "");
// TODO: ought to extend ICmpVisual to let us just select variant
// keywords without changing the animation too
if (this.entities.length)
cmpVisual.SelectAnimation("garrisoned", false, 1.0, "");
else
cmpVisual.SelectAnimation("idle", false, 1.0, "");
let selection = this.entities.length ? "garrisoned" : "ungarrisoned";
cmpVisual.SetVariant("garrison", selection);
};
/**

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2013 Wildfire Games.
/* Copyright (C) 2016 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -77,17 +77,21 @@ void CUnit::SetID(entity_id_t id)
m_Animation->SetEntityID(id);
}
void CUnit::SetEntitySelection(const CStr& selection)
void CUnit::SetEntitySelection(const CStr& key, const CStr& selection)
{
CStr selection_lc = selection.LowerCase();
// If we've already selected this, don't do anything
if (m_EntitySelections.find(selection_lc) != m_EntitySelections.end())
if (m_EntitySelections[key] == selection_lc)
return;
m_EntitySelections[key] = selection_lc;
// Just allow one selection at a time
m_EntitySelections.clear();
m_EntitySelections.insert(selection_lc);
ReloadObject();
}
void CUnit::SetEntitySelection(const std::map<CStr, CStr>& selections)
{
for (const std::pair<CStr, CStr>& s : selections)
m_EntitySelections[s.first] = s.second.LowerCase();
ReloadObject();
}
@ -100,9 +104,11 @@ void CUnit::SetActorSelections(const std::set<CStr>& selections)
void CUnit::ReloadObject()
{
std::set<CStr> entitySelections;
for (const std::pair<CStr, CStr>& selection : m_EntitySelections)
entitySelections.insert(selection.second);
std::vector<std::set<CStr> > selections;
// TODO: push world selections (seasons, etc) (and reload whenever they're changed)
selections.push_back(m_EntitySelections);
selections.push_back(entitySelections);
selections.push_back(m_ActorSelections);
// randomly select any remain selections necessary to completely identify a variation (e.g., the new selection

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2013 Wildfire Games.
/* Copyright (C) 2016 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -64,8 +64,9 @@ public:
void UpdateModel(float frameTime);
// Sets the entity-selection, and updates the unit to use the new
// actor variation.
void SetEntitySelection(const CStr& selection);
// actor variation. Either set one key at a time, or a complete map.
void SetEntitySelection(const CStr& key, const CStr& selection);
void SetEntitySelection(const std::map<CStr, CStr>& selections);
// Most units have a hopefully-unique ID number, so they can be referred to
// persistently despite saving/loading maps. Default for new units is -1; should
@ -95,7 +96,7 @@ private:
// actor-level selections for this unit
std::set<CStr> m_ActorSelections;
// entity-level selections for this unit
std::set<CStr> m_EntitySelections;
std::map<CStr, CStr> m_EntitySelections;
// object manager which looks after this unit's objectentry
CObjectManager& m_ObjectManager;

View File

@ -556,7 +556,7 @@ void CCmpRallyPointRenderer::UpdateMarkers()
CmpPtr<ICmpVisual> cmpVisualActor(GetSimContext(), m_MarkerEntityIds[i]);
if (cmpVisualActor)
cmpVisualActor->SetUnitEntitySelection(CStrW(cmpPlayer->GetCiv()).ToUTF8());
cmpVisualActor->SetVariant("civ", CStrW(cmpPlayer->GetCiv()).ToUTF8());
}
m_LastMarkerCount = m_RallyPoints.size() - 1;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2014 Wildfire Games.
/* Copyright (C) 2016 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -32,6 +32,8 @@
#include "ICmpValueModificationManager.h"
#include "ICmpVisibility.h"
#include "simulation2/serialization/SerializeTemplates.h"
#include "graphics/Decal.h"
#include "graphics/Frustum.h"
#include "graphics/Model.h"
@ -80,6 +82,8 @@ private:
fixed m_AnimDesync;
fixed m_AnimSyncRepeatTime; // 0.0 if not synced
std::map<CStr, CStr> m_VariantSelections;
u32 m_Seed; // seed used for random variations
bool m_ConstructionPreview;
@ -229,8 +233,9 @@ public:
serialize.NumberFixed_Unbounded("anim desync", m_AnimDesync);
serialize.NumberFixed_Unbounded("anim sync repeat time", m_AnimSyncRepeatTime);
SerializeMap<SerializeString, SerializeString>()(serialize, "variation", m_VariantSelections);
serialize.NumberU32_Unbounded("seed", m_Seed);
// TODO: variation/selection strings
serialize.String("actor", m_ActorName, 0, 256);
// TODO: store actor variables?
@ -259,6 +264,8 @@ public:
// If we serialized a different seed or different actor, reload actor
if (oldSeed != GetActorSeed() || m_BaseActorName != m_ActorName)
ReloadActor();
else
m_Unit->SetEntitySelection(m_VariantSelections);
fixed repeattime = m_AnimSyncRepeatTime; // save because SelectAnimation overwrites it
@ -410,6 +417,14 @@ public:
return CVector3D();
}
virtual void SetVariant(const CStr& key, const CStr& selection)
{
m_VariantSelections[key] = selection;
if (!m_Unit)
return;
m_Unit->SetEntitySelection(key, selection);
}
virtual void SelectAnimation(const std::string& name, bool once, fixed speed, const std::wstring& soundgroup)
{
m_AnimRunThreshold = fixed::Zero();
@ -422,7 +437,7 @@ public:
if (m_Unit)
{
m_Unit->SetEntitySelection(m_AnimName);
SetVariant("animation", m_AnimName);
if (m_Unit->GetAnimation())
m_Unit->GetAnimation()->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed.ToFloat(), m_AnimDesync.ToFloat(), m_SoundGroup.c_str());
}
@ -440,21 +455,13 @@ public:
m_AnimOverride.erase(name);
}
virtual void SetUnitEntitySelection(const CStr& selection)
{
if (m_Unit)
{
m_Unit->SetEntitySelection(selection);
}
}
virtual void SelectMovementAnimation(fixed runThreshold)
{
m_AnimRunThreshold = runThreshold;
if (m_Unit)
{
m_Unit->SetEntitySelection("walk");
SetVariant("animation", "walk");
if (m_Unit->GetAnimation())
m_Unit->GetAnimation()->SetAnimationState("walk", false, 1.f, 0.f, L"");
}
@ -713,7 +720,8 @@ void CCmpVisualActor::ReloadActor()
InitModel(node->GetChild("VisualActor"));
m_Unit->SetEntitySelection(m_AnimName);
m_Unit->SetEntitySelection(m_VariantSelections);
if (m_Unit->GetAnimation())
m_Unit->GetAnimation()->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed.ToFloat(), m_AnimDesync.ToFloat(), m_SoundGroup.c_str());
@ -763,17 +771,12 @@ void CCmpVisualActor::Update(fixed UNUSED(turnLength))
if (it != m_AnimOverride.end())
name = it->second;
m_Unit->SetEntitySelection(name);
if (speed == 0.0f)
SetVariant("animation", name);
if (m_Unit->GetAnimation())
{
m_Unit->SetEntitySelection(name);
if (m_Unit->GetAnimation())
if (speed == 0.0f)
m_Unit->GetAnimation()->SetAnimationState(name, false, 1.f, 0.f, L"");
}
else
{
m_Unit->SetEntitySelection(name);
if (m_Unit->GetAnimation())
else
m_Unit->GetAnimation()->SetAnimationState(name, false, speed, 0.f, L"");
}
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2013 Wildfire Games.
/* Copyright (C) 2016 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -22,6 +22,7 @@
#include "simulation2/system/InterfaceScripted.h"
BEGIN_INTERFACE_WRAPPER(Visual)
DEFINE_INTERFACE_METHOD_2("SetVariant", void, ICmpVisual, SetVariant, CStr, CStr)
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)

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2013 Wildfire Games.
/* Copyright (C) 2016 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -79,6 +79,13 @@ public:
*/
virtual CUnit* GetUnit() = 0;
/**
* Set the variant selection of the actor for a certain key.
* This overrides a previous selection on that key, so every component
* should use unique keys.
*/
virtual void SetVariant(const CStr& key, const CStr& selection) = 0;
/**
* Start playing the given animation. If there are multiple possible animations then it will
* pick one at random (not network-synchronised).
@ -106,11 +113,6 @@ public:
*/
virtual void ResetMoveAnimation(const std::string& name) = 0;
/**
* Sets the specified entity selection on the underlying unit.
*/
virtual void SetUnitEntitySelection(const CStr& selection) = 0;
/**
* Start playing the walk/run animations, scaled to the unit's movement speed.
* @param runThreshold movement speed at which to switch to the run animation