1
0
forked from 0ad/0ad

Add a C++ interface for CCmpAttack.

This allows Atlas not to rely on eval() to get access to the attack
component.
Add a quick test for the added method.
This fixes the animation speed matching that of the actor instead of the
template.
Remove some dead code after af2abb8cbf
Fixes: #5129
Reviewed by: @Angen
Comments by: @elexis
Differential Revision: https://code.wildfiregames.com/D2464
This was SVN commit r23592.
This commit is contained in:
Stan 2020-04-21 21:44:05 +00:00
parent 2c1f1ebe31
commit 0ad79096bd
8 changed files with 121 additions and 42 deletions

View File

@ -403,15 +403,22 @@ Attack.prototype.CompareEntitiesByPreference = function(a, b)
return aPreference - bPreference; return aPreference - bPreference;
}; };
Attack.prototype.GetRepeatTime = function(type)
{
let repeatTime = 1000;
if (this.template[type] && this.template[type].RepeatTime)
repeatTime = +this.template[type].RepeatTime;
return ApplyValueModificationsToEntity("Attack/" + type + "/RepeatTime", repeatTime, this.entity);
};
Attack.prototype.GetTimers = function(type) Attack.prototype.GetTimers = function(type)
{ {
let prepare = +(this.template[type].PrepareTime || 0); return {
prepare = ApplyValueModificationsToEntity("Attack/" + type + "/PrepareTime", prepare, this.entity); "prepare": ApplyValueModificationsToEntity("Attack/" + type + "/PrepareTime", +(this.template[type].PrepareTime || 0), this.entity),
"repeat": this.GetRepeatTime(type)
let repeat = +(this.template[type].RepeatTime || 1000); };
repeat = ApplyValueModificationsToEntity("Attack/" + type + "/RepeatTime", repeat, this.entity);
return { "prepare": prepare, "repeat": repeat };
}; };
Attack.prototype.GetSplashData = function(type) Attack.prototype.GetSplashData = function(type)

View File

@ -1,5 +1,3 @@
Engine.RegisterInterface("Attack");
/** /**
* Message of the form { "attacker": number, "target": number, "type": string, "damage": number, "attackerOwner": number } * Message of the form { "attacker": number, "target": number, "type": string, "damage": number, "attackerOwner": number }
* sent from Attack component and by Damage component to the target entity, each time the target is attacked or damaged. * sent from Attack component and by Damage component to the target entity, each time the target is attacked or damaged.

View File

@ -180,11 +180,16 @@ attackComponentTest(undefined, true, (attacker, cmpAttack, defender) => {
"repeat": 500 "repeat": 500
}); });
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetRepeatTime("Ranged"), 500);
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetTimers("Capture"), { TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetTimers("Capture"), {
"prepare": 0, "prepare": 0,
"repeat": 1000 "repeat": 1000
}); });
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetRepeatTime("Capture"), 1000);
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetSplashData("Ranged"), { TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetSplashData("Ranged"), {
"attackData": { "attackData": {
"Damage": { "Damage": {

View File

@ -79,6 +79,9 @@ COMPONENT(AIInterfaceScripted)
INTERFACE(AIManager) INTERFACE(AIManager)
COMPONENT(AIManager) COMPONENT(AIManager)
INTERFACE(Attack)
COMPONENT(AttackScripted)
INTERFACE(CinemaManager) INTERFACE(CinemaManager)
COMPONENT(CinemaManager) COMPONENT(CinemaManager)

View File

@ -0,0 +1,40 @@
/* Copyright (C) 2020 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 "ICmpAttack.h"
#include "simulation2/system/InterfaceScripted.h"
#include "simulation2/scripting/ScriptComponent.h"
BEGIN_INTERFACE_WRAPPER(Attack)
END_INTERFACE_WRAPPER(Attack)
class CCmpAttackScripted : public ICmpAttack
{
public:
DEFAULT_SCRIPT_WRAPPER(AttackScripted)
virtual float GetRepeatTime(const std::string& type) const
{
return m_Script.Call<float, const std::string&>("GetRepeatTime", type);
}
};
REGISTER_COMPONENT_SCRIPT_WRAPPER(AttackScripted)

View File

@ -0,0 +1,30 @@
/* Copyright (C) 2020 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_ICMPATTACK
#define INCLUDED_ICMPATTACK
#include "simulation2/system/Interface.h"
class ICmpAttack : public IComponent
{
public:
virtual float GetRepeatTime(const std::string& type) const = 0;
DECLARE_INTERFACE_TYPE(Attack)
};
#endif // INCLUDED_ICMPATTACK

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2019 Wildfire Games. /* Copyright (C) 2020 Wildfire Games.
* This file is part of 0 A.D. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@ -48,6 +48,7 @@
#include "renderer/WaterManager.h" #include "renderer/WaterManager.h"
#include "scriptinterface/ScriptInterface.h" #include "scriptinterface/ScriptInterface.h"
#include "simulation2/Simulation2.h" #include "simulation2/Simulation2.h"
#include "simulation2/components/ICmpAttack.h"
#include "simulation2/components/ICmpOwnership.h" #include "simulation2/components/ICmpOwnership.h"
#include "simulation2/components/ICmpPosition.h" #include "simulation2/components/ICmpPosition.h"
#include "simulation2/components/ICmpRangeManager.h" #include "simulation2/components/ICmpRangeManager.h"
@ -377,19 +378,19 @@ void ActorViewer::SetActor(const CStrW& name, const CStr& animation, player_id_t
if (needsAnimReload) if (needsAnimReload)
{ {
// Emulate the typical simulation animation behaviour.
CStr anim = animation.LowerCase(); CStr anim = animation.LowerCase();
float speed = 1.0f;
// Emulate the typical simulation animation behaviour // Speed will be ignored if we have a repeat time.
float speed; float repeattime = 0.0f;
float repeattime = 0.f; m.CurrentSpeed = 0.0f;
if (anim == "walk") if (anim == "walk")
{ {
CmpPtr<ICmpUnitMotion> cmpUnitMotion(m.Simulation2, m.Entity); CmpPtr<ICmpUnitMotion> cmpUnitMotion(m.Simulation2, m.Entity);
if (cmpUnitMotion) if (cmpUnitMotion)
speed = cmpUnitMotion->GetWalkSpeed().ToFloat(); speed = cmpUnitMotion->GetWalkSpeed().ToFloat();
else else
speed = 7.f; // typical unit speed speed = 7.f; // Typical unit walk speed.
m.CurrentSpeed = speed; m.CurrentSpeed = speed;
} }
else if (anim == "run") else if (anim == "run")
@ -398,33 +399,18 @@ void ActorViewer::SetActor(const CStrW& name, const CStr& animation, player_id_t
if (cmpUnitMotion) if (cmpUnitMotion)
speed = cmpUnitMotion->GetWalkSpeed().ToFloat() * cmpUnitMotion->GetRunMultiplier().ToFloat(); speed = cmpUnitMotion->GetWalkSpeed().ToFloat() * cmpUnitMotion->GetRunMultiplier().ToFloat();
else else
speed = 12.f; // typical unit speed speed = 12.f; // Typical unit run speed.
m.CurrentSpeed = speed; m.CurrentSpeed = speed;
} }
else if (anim == "melee") else if (anim == "attack_melee")
{ repeattime = GetRepeatTimeByAttackType("Melee");
speed = 1.f; // speed will be ignored if we have a repeattime else if (anim == "attack_ranged")
m.CurrentSpeed = 0.f; repeattime = GetRepeatTimeByAttackType("Ranged");
else if (anim == "attack_slaughter")
CStr code = "var cmp = Engine.QueryInterface("+CStr::FromUInt(m.Entity)+", IID_Attack); " + repeattime = GetRepeatTimeByAttackType("Slaughter");
"if (cmp) cmp.GetTimers(cmp.GetBestAttack()).repeat; else 0;"; else if (anim == "attack_capture")
m.Simulation2.GetScriptInterface().Eval(code.c_str(), repeattime); repeattime = GetRepeatTimeByAttackType("Capture");
}
else
{
// Play the animation at normal speed, but movement speed is zero
speed = 1.f;
m.CurrentSpeed = 0.f;
}
CStr sound;
if (anim == "melee")
sound = "attack";
else if (anim == "build")
sound = "build";
else if (anim.Find("gather_") == 0)
sound = anim;
CmpPtr<ICmpVisual> cmpVisual(m.Simulation2, m.Entity); CmpPtr<ICmpVisual> cmpVisual(m.Simulation2, m.Entity);
if (cmpVisual) if (cmpVisual)
@ -496,6 +482,15 @@ void ActorViewer::SetStatsEnabled(bool enabled)
g_ProfileViewer.ShowTable(""); g_ProfileViewer.ShowTable("");
} }
float ActorViewer::GetRepeatTimeByAttackType(const std::string& type) const
{
CmpPtr<ICmpAttack> cmpAttack(m.Simulation2, m.Entity);
if (cmpAttack)
return cmpAttack->GetRepeatTime(type);
return 0.0f;
}
void ActorViewer::Render() void ActorViewer::Render()
{ {
m.Terrain.MakeDirty(RENDERDATA_UPDATE_COLOR); m.Terrain.MakeDirty(RENDERDATA_UPDATE_COLOR);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2019 Wildfire Games. /* Copyright (C) 2020 Wildfire Games.
* This file is part of 0 A.D. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@ -52,6 +52,7 @@ public:
private: private:
ActorViewerImpl& m; ActorViewerImpl& m;
float GetRepeatTimeByAttackType(const std::string& type) const;
}; };
#endif // INCLUDED_ACTORVIEWER #endif // INCLUDED_ACTORVIEWER