Fix units not being able to play sounds when walking and running

This currently disabled by variants, and will be reenabled when sounds
have been chosen.
Reviewed by: Vladislav,
Comments by: Itms, elexis
Differential Revision: ​https://code.wildfiregames.com/1257
This was SVN commit r21359.
This commit is contained in:
Stan 2018-02-24 18:13:03 +00:00
parent 976ab3d395
commit af2abb8cbf
17 changed files with 137 additions and 88 deletions

View File

@ -246,7 +246,7 @@ Foundation.prototype.Build = function(builderEnt, work)
// Switch foundation to scaffold variant
var cmpFoundationVisual = Engine.QueryInterface(this.entity, IID_Visual);
if (cmpFoundationVisual)
cmpFoundationVisual.SelectAnimation("scaffold", false, 1.0, "");
cmpFoundationVisual.SelectAnimation("scaffold", false, 1.0);
// Create preview entity and copy various parameters from the foundation
if (cmpFoundationVisual && cmpFoundationVisual.HasConstructionPreview())

View File

@ -199,7 +199,7 @@ Gate.prototype.OpenGate = function()
PlaySound("gate_opening", this.entity);
var cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
if (cmpVisual)
cmpVisual.SelectAnimation("gate_opening", true, 1.0, "");
cmpVisual.SelectAnimation("gate_opening", true, 1.0);
};
/**
@ -238,7 +238,7 @@ Gate.prototype.CloseGate = function()
PlaySound("gate_closing", this.entity);
var cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
if (cmpVisual)
cmpVisual.SelectAnimation("gate_closing", true, 1.0, "");
cmpVisual.SelectAnimation("gate_closing", true, 1.0);
};
Engine.RegisterComponentType(IID_Gate, "Gate", Gate);

View File

@ -317,7 +317,7 @@ Health.prototype.CreateCorpse = function(leaveResources)
cmpCorpseVisual.SetActorSeed(cmpVisual.GetActorSeed());
// Make it fall over
cmpCorpseVisual.SelectAnimation("death", true, 1.0, "");
cmpCorpseVisual.SelectAnimation("death", true, 1.0);
return corpse;
};

View File

@ -76,7 +76,7 @@ Pack.prototype.Unpack = function()
let cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
if (cmpVisual)
cmpVisual.SelectAnimation("unpacking", true, 1.0, "unpacking");
cmpVisual.SelectAnimation("unpacking", true, 1.0);
};
Pack.prototype.CancelPack = function()
@ -91,7 +91,7 @@ Pack.prototype.CancelPack = function()
// Clear animation
let cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
if (cmpVisual)
cmpVisual.SelectAnimation("idle", false, 1.0, "");
cmpVisual.SelectAnimation("idle", false, 1.0);
};
Pack.prototype.GetPackTime = function()

View File

@ -1896,7 +1896,7 @@ UnitAI.prototype.UnitFsmSpec = {
animationName = cmpFormation.GetFormationAnimation(this.entity, animationName);
}
this.SetAnimationVariant("combat");
this.SelectAnimation(animationName, false, 1.0, animationName);
this.SelectAnimation(animationName);
this.SetAnimationSync(prepare, this.attackTimers.repeat);
this.StartTimer(prepare, this.attackTimers.repeat);
// TODO: we should probably only bother syncing projectile attacks, not melee
@ -2308,7 +2308,7 @@ UnitAI.prototype.UnitFsmSpec = {
{
this.SetDefaultAnimationVariant();
var typename = "gather_" + this.order.data.type.specific;
this.SelectAnimation(typename, false, 1.0, typename);
this.SelectAnimation(typename);
}
return false;
},
@ -2512,7 +2512,7 @@ UnitAI.prototype.UnitFsmSpec = {
prepare = Math.max(prepare, repeatLeft);
}
this.SelectAnimation("heal", false, 1.0, "heal");
this.SelectAnimation("heal");
this.SetAnimationSync(prepare, this.healTimers.repeat);
this.StartTimer(prepare, this.healTimers.repeat);
@ -2735,7 +2735,7 @@ UnitAI.prototype.UnitFsmSpec = {
if (cmpBuilderList)
cmpBuilderList.AddBuilder(this.entity);
this.SelectAnimation("build", false, 1.0, "build");
this.SelectAnimation("build");
this.StartTimer(1000, 1000);
return false;
},
@ -4226,9 +4226,9 @@ UnitAI.prototype.SetDefaultAnimationVariant = function()
this.SetAnimationVariant("");
};
UnitAI.prototype.SelectAnimation = function(name, once, speed, sound)
UnitAI.prototype.SelectAnimation = function(name, once = false, speed = 1.0)
{
var cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
let cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
if (!cmpVisual)
return;
@ -4237,29 +4237,11 @@ UnitAI.prototype.SelectAnimation = function(name, once, speed, sound)
if (name == "move")
{
// Speed to switch from walking to running animations
var runThreshold = (this.GetWalkSpeed() + this.GetRunSpeed()) / 2;
cmpVisual.SelectMovementAnimation(runThreshold);
cmpVisual.SelectMovementAnimation((this.GetWalkSpeed() + this.GetRunSpeed()) / 2);
return;
}
var soundgroup;
if (sound)
{
var cmpSound = Engine.QueryInterface(this.entity, IID_Sound);
if (cmpSound)
soundgroup = cmpSound.GetSoundGroup(sound);
}
// Set default values if unspecified
if (once === undefined)
once = false;
if (speed === undefined)
speed = 1.0;
if (soundgroup === undefined)
soundgroup = "";
cmpVisual.SelectAnimation(name, once, speed, soundgroup);
cmpVisual.SelectAnimation(name, once, speed);
};
UnitAI.prototype.SetAnimationSync = function(actiontime, repeattime)

View File

@ -1 +0,0 @@
Engine.RegisterInterface("Sound");

View File

@ -193,7 +193,7 @@ testFoundation([foundationEnt, IID_Visual, {
TS_ASSERT_EQUALS(key, "numbuilders");
TS_ASSERT(num == 1 || num == 2);
},
"SelectAnimation": () => {},
"SelectAnimation": (name, once, speed) => name
"HasConstructionPreview": () => true,
}]);

View File

@ -22,7 +22,7 @@ const PACKING_INTERVAL = 250;
let timerActivated = false;
AddMock(ent, IID_Visual, {
"SelectAnimation": (name, once, speed, soundgroup) => name
"SelectAnimation": (name, once, speed) => name
});
AddMock(ent, IID_Ownership, {

View File

@ -162,6 +162,9 @@ COMPONENT(Selectable)
INTERFACE(Settlement)
COMPONENT(SettlementScripted)
INTERFACE(Sound)
COMPONENT(SoundScripted)
INTERFACE(SoundManager)
COMPONENT(SoundManager)

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2017 Wildfire Games.
/* Copyright (C) 2018 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -62,27 +62,26 @@ public:
virtual void PlaySoundGroup(const std::wstring& name, entity_id_t source)
{
if ( ! g_SoundManager || (source == INVALID_ENTITY) )
if (!g_SoundManager || (source == INVALID_ENTITY))
return;
CmpPtr<ICmpRangeManager> cmpRangeManager(GetSystemEntity());
int currentPlayer = GetSimContext().GetCurrentDisplayedPlayer();
if ( !cmpRangeManager ||
( cmpRangeManager->GetLosVisibility(source, currentPlayer) != ICmpRangeManager::VIS_VISIBLE ) )
CmpPtr<ICmpRangeManager> cmpRangeManager(GetSystemEntity());
if (!cmpRangeManager || (cmpRangeManager->GetLosVisibility(source, currentPlayer) != ICmpRangeManager::VIS_VISIBLE))
return;
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), source);
if (cmpPosition && cmpPosition->IsInWorld())
{
bool playerOwned = false;
CmpPtr<ICmpOwnership> cmpOwnership( GetSimContext(), source);
if (cmpOwnership)
playerOwned = cmpOwnership->GetOwner() == currentPlayer;
if (!cmpPosition || !cmpPosition->IsInWorld())
return;
CVector3D sourcePos = CVector3D(cmpPosition->GetPosition());
g_SoundManager->PlayAsGroup(name, sourcePos, source, playerOwned);
}
bool playerOwned = false;
CmpPtr<ICmpOwnership> cmpOwnership(GetSimContext(), source);
if (cmpOwnership)
playerOwned = cmpOwnership->GetOwner() == currentPlayer;
CVector3D sourcePos = CVector3D(cmpPosition->GetPosition());
g_SoundManager->PlayAsGroup(name, sourcePos, source, playerOwned);
}
virtual void PlaySoundGroupAtPosition(const std::wstring& name, const CFixedVector3D& sourcePos)

View File

@ -31,6 +31,7 @@
#include "ICmpUnitMotion.h"
#include "ICmpValueModificationManager.h"
#include "ICmpVisibility.h"
#include "ICmpSound.h"
#include "simulation2/serialization/SerializeTemplates.h"
@ -206,7 +207,7 @@ public:
InitModel(paramNode);
SelectAnimation("idle", false, fixed::FromInt(1), L"");
SelectAnimation("idle");
}
virtual void Deinit()
@ -436,16 +437,20 @@ public:
return m_AnimName;
}
virtual void SelectAnimation(const std::string& name, bool once, fixed speed, const std::wstring& soundgroup)
virtual void SelectAnimation(const std::string& name, bool once = false, fixed speed = fixed::FromInt(1))
{
m_AnimRunThreshold = fixed::Zero();
m_AnimName = name;
m_AnimOnce = once;
m_AnimSpeed = speed;
m_SoundGroup = soundgroup;
m_SoundGroup = L"";
m_AnimDesync = fixed::FromInt(1)/20; // TODO: make this an argument
m_AnimSyncRepeatTime = fixed::Zero();
m_AnimSyncOffsetTime = fixed::Zero();
CmpPtr<ICmpSound> cmpSound(GetSimContext(), m_Unit->GetID());
if(cmpSound)
m_SoundGroup = cmpSound->GetSoundGroup(wstring_from_utf8(m_AnimName));
SetVariant("animation", m_AnimName);
@ -467,7 +472,6 @@ public:
virtual void SelectMovementAnimation(fixed runThreshold)
{
SelectAnimation("walk", false, fixed::FromFloat(1.f), L"");
m_AnimRunThreshold = runThreshold;
}
@ -795,6 +799,6 @@ void CCmpVisualActor::Update(fixed UNUSED(turnLength))
// Selecting the animation is going to reset the anim run threshold, so save it
fixed runThreshold = m_AnimRunThreshold;
SelectAnimation(name, false, speed, L"");
SelectAnimation(name, false, speed);
m_AnimRunThreshold = runThreshold;
}

View File

@ -0,0 +1,39 @@
/* Copyright (C) 2018 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "ICmpSound.h"
#include "simulation2/scripting/ScriptComponent.h"
#include "simulation2/system/InterfaceScripted.h"
BEGIN_INTERFACE_WRAPPER(Sound)
END_INTERFACE_WRAPPER(Sound)
class CCmpSoundScripted : public ICmpSound
{
public:
DEFAULT_SCRIPT_WRAPPER(SoundScripted)
virtual std::wstring GetSoundGroup(const std::wstring& soundName) const
{
return m_Script.Call<std::wstring>("GetSoundGroup", soundName);
}
};
REGISTER_COMPONENT_SCRIPT_WRAPPER(SoundScripted)

View File

@ -0,0 +1,36 @@
/* Copyright (C) 2018 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_ICMPSOUND
#define INCLUDED_ICMPSOUND
#include "simulation2/system/Interface.h"
/**
* Sound data.
* (This interface includes functions needed by native code for loading soundgroups.
* Most of the sound interaction is handled by scripts instead).
*/
class ICmpSound : public IComponent
{
public:
virtual std::wstring GetSoundGroup(const std::wstring& soundName) const = 0;
DECLARE_INTERFACE_TYPE(Sound)
};
#endif // INCLUDED_ICMPSOUND

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2017 Wildfire Games.
/* Copyright (C) 2018 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -26,7 +26,7 @@ DEFINE_INTERFACE_METHOD_2("SetVariant", void, ICmpVisual, SetVariant, CStr, CStr
DEFINE_INTERFACE_METHOD_CONST_0("GetAnimationName", std::string, ICmpVisual, GetAnimationName)
DEFINE_INTERFACE_METHOD_CONST_0("GetProjectileActor", std::wstring, ICmpVisual, GetProjectileActor)
DEFINE_INTERFACE_METHOD_CONST_0("GetProjectileLaunchPoint", CFixedVector3D, ICmpVisual, GetProjectileLaunchPoint)
DEFINE_INTERFACE_METHOD_4("SelectAnimation", void, ICmpVisual, SelectAnimation, std::string, bool, fixed, std::wstring)
DEFINE_INTERFACE_METHOD_3("SelectAnimation", void, ICmpVisual, SelectAnimation, std::string, bool, fixed)
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)

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2017 Wildfire Games.
/* Copyright (C) 2018 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -103,7 +103,7 @@ public:
* @param speed animation speed multiplier (typically 1.0 for the default speed)
* @param soundgroup VFS path of sound group .xml, relative to audio/, or empty string for none
*/
virtual void SelectAnimation(const std::string& name, bool once, fixed speed, const std::wstring& soundgroup) = 0;
virtual void SelectAnimation(const std::string& name, bool once, fixed speed) = 0;
/**
* Replaces a specified animation with another. Only affects the special speed-based

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2015 Wildfire Games.
/* Copyright (C) 2018 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -156,50 +156,46 @@ float CSoundGroup::RadiansOffCenter(const CVector3D& position, bool& onScreen, f
void CSoundGroup::UploadPropertiesAndPlay(size_t theIndex, const CVector3D& position, entity_id_t source)
{
#if CONFIG2_AUDIO
if ( !g_SoundManager )
if (!g_SoundManager)
return;
bool isOnscreen = false;
ALfloat initialRolllOff = 0.1f;
ALfloat itemRollOff = initialRolllOff;
float offSet = RadiansOffCenter(position, isOnscreen, itemRollOff);
bool shouldBePlayed = isOnscreen || TestFlag(eDistanceless) || TestFlag(eOmnipresent);
if ( !shouldBePlayed )
ALfloat itemRollOff = 0.1f;
float offset = RadiansOffCenter(position, isOnscreen, itemRollOff);
if (!isOnscreen && !TestFlag(eDistanceless) && !TestFlag(eOmnipresent))
return;
if (snd_group.size() == 0)
Reload();
if ( snd_group.size() <= theIndex )
if (snd_group.size() <= theIndex)
return;
CSoundData* sndData = snd_group[theIndex];
if ( sndData == NULL )
if (sndData == nullptr)
return;
ISoundItem* hSound = ((CSoundManager*)g_SoundManager)->ItemForEntity( source, sndData);
if ( hSound == NULL )
ISoundItem* hSound = static_cast<CSoundManager*>(g_SoundManager)->ItemForEntity(source, sndData);
if (hSound == nullptr)
return;
if (!TestFlag(eOmnipresent))
{
CVector3D origin = g_Game->GetView()->GetCamera()->GetOrientation().GetTranslation();
float sndDist = origin.Y;
float itemDist = ( position - origin ).Length();
float itemDist = (position - origin).Length();
if ( (sndDist * 2) < itemDist )
if ((sndDist * 2) < itemDist)
sndDist = itemDist;
if (TestFlag(eDistanceless))
itemRollOff = 0;
if ( sndData->IsStereo() )
if (sndData->IsStereo())
LOGWARNING("OpenAL: stereo sounds can't be positioned: %s", sndData->GetFileName().string8());
hSound->SetLocation(CVector3D((sndDist * sin(offSet)), 0, - sndDist * cos(offSet)));
hSound->SetLocation(CVector3D((sndDist * sin(offset)), 0, -sndDist * cos(offset)));
hSound->SetRollOff(itemRollOff);
}
@ -208,12 +204,11 @@ void CSoundGroup::UploadPropertiesAndPlay(size_t theIndex, const CVector3D& posi
else
hSound->SetPitch(m_Pitch);
ALfloat theGain = m_Gain;
if (TestFlag(eRandGain))
theGain = RandFloat(m_GainLower, m_GainUpper);
m_Gain = RandFloat(m_GainLower, m_GainUpper);
hSound->SetCone(m_ConeInnerAngle, m_ConeOuterAngle, m_ConeOuterGain);
((CSoundManager*)g_SoundManager)->PlayGroupItem(hSound, theGain);
static_cast<CSoundManager*>(g_SoundManager)->PlayGroupItem(hSound, m_Gain);
#else // !CONFIG2_AUDIO
UNUSED2(theIndex);

View File

@ -425,19 +425,11 @@ void ActorViewer::SetActor(const CStrW& name, const CStrW& animation, player_id_
else if (anim.Find("gather_") == 0)
sound = anim;
std::wstring soundgroup;
if (!sound.empty())
{
CStr code = "var cmp = Engine.QueryInterface("+CStr::FromUInt(m.Entity)+", IID_Sound); " +
"if (cmp) cmp.GetSoundGroup('"+sound+"'); else '';";
m.Simulation2.GetScriptInterface().Eval(code.c_str(), soundgroup);
}
CmpPtr<ICmpVisual> cmpVisual(m.Simulation2, m.Entity);
if (cmpVisual)
{
// TODO: SetEntitySelection(anim)
cmpVisual->SelectAnimation(anim, false, fixed::FromFloat(speed), soundgroup);
cmpVisual->SelectAnimation(anim, false, fixed::FromFloat(speed));
if (repeattime)
cmpVisual->SetAnimationSyncRepeat(fixed::FromFloat(repeattime));
}