Implement get*Target combat routines
This commit is contained in:
parent
581984f7c0
commit
8a7885e19e
9 changed files with 131 additions and 13 deletions
|
@ -630,6 +630,7 @@ set(GAME_SOURCES
|
|||
src/game/script/routines.cpp
|
||||
src/game/script/routines_actions.cpp
|
||||
src/game/script/routines_ai.cpp
|
||||
src/game/script/routines_combat.cpp
|
||||
src/game/script/routines_common.cpp
|
||||
src/game/script/routines_effects.cpp
|
||||
src/game/script/routines_enginetypes.cpp
|
||||
|
|
|
@ -185,15 +185,15 @@ void ActionExecutor::executeStartConversation(const shared_ptr<Object> &actor, S
|
|||
}
|
||||
|
||||
void ActionExecutor::executeAttack(const shared_ptr<Object> &actor, AttackAction &action, float dt) {
|
||||
auto target = action.target();
|
||||
shared_ptr<SpatialObject> target(action.target());
|
||||
if (target->isDead()) {
|
||||
action.complete();
|
||||
return;
|
||||
}
|
||||
glm::vec3 dest(target->position());
|
||||
auto creatureActor = static_pointer_cast<Creature>(actor);
|
||||
|
||||
navigateCreature(creatureActor, dest, true, action.range(), dt);
|
||||
if (navigateCreature(creatureActor, target->position(), true, action.range(), dt)) {
|
||||
// TODO: start a combat round
|
||||
}
|
||||
}
|
||||
|
||||
bool ActionExecutor::navigateCreature(const shared_ptr<Creature> &creature, const glm::vec3 &dest, bool run, float distance, float dt) {
|
||||
|
|
|
@ -57,6 +57,13 @@ static constexpr int kStrRefRemains = 38151;
|
|||
static string g_headHookNode("headhook");
|
||||
static string g_talkDummyNode("talkdummy");
|
||||
|
||||
void Creature::Combat::reset() {
|
||||
attackTarget.reset();
|
||||
attemptedAttackTarget.reset();
|
||||
spellTarget.reset();
|
||||
attemptedSpellTarget.reset();
|
||||
}
|
||||
|
||||
Creature::Creature(
|
||||
uint32_t id,
|
||||
ObjectFactory *objectFactory,
|
||||
|
|
|
@ -90,6 +90,15 @@ public:
|
|||
std::shared_ptr<SpatialObject> lastPerceived;
|
||||
};
|
||||
|
||||
struct Combat {
|
||||
std::shared_ptr<SpatialObject> attackTarget;
|
||||
std::shared_ptr<SpatialObject> attemptedAttackTarget;
|
||||
std::shared_ptr<SpatialObject> spellTarget;
|
||||
std::shared_ptr<SpatialObject> attemptedSpellTarget;
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
Creature(
|
||||
uint32_t id,
|
||||
ObjectFactory *objectFactory,
|
||||
|
@ -130,6 +139,7 @@ public:
|
|||
int xp() const { return _xp; }
|
||||
RacialType racialType() const { return _racialType; }
|
||||
NPCAIStyle aiStyle() const { return _aiStyle; }
|
||||
Combat &combat() { return _combat; }
|
||||
|
||||
void setMovementType(MovementType type);
|
||||
void setFaction(Faction faction);
|
||||
|
@ -217,6 +227,7 @@ private:
|
|||
Perception _perception;
|
||||
RacialType _racialType { RacialType::Unknown };
|
||||
NPCAIStyle _aiStyle { NPCAIStyle::MeleeAttack };
|
||||
Combat _combat;
|
||||
|
||||
// Animation
|
||||
|
||||
|
|
|
@ -505,6 +505,15 @@ private:
|
|||
|
||||
// END Perception
|
||||
|
||||
// Combat
|
||||
|
||||
script::Variable getAttackTarget(const VariablesList &args, script::ExecutionContext &ctx);
|
||||
script::Variable getAttemptedAttackTarget(const VariablesList &args, script::ExecutionContext &ctx);
|
||||
script::Variable getSpellTarget(const VariablesList &args, script::ExecutionContext &ctx);
|
||||
script::Variable getAttemptedSpellTarget(const VariablesList &args, script::ExecutionContext &ctx);
|
||||
|
||||
// END Combat
|
||||
|
||||
// AI
|
||||
|
||||
script::Variable getNPCAIStyle(const VariablesList &args, script::ExecutionContext &ctx);
|
||||
|
|
|
@ -338,7 +338,7 @@ Variable Routines::actionAttack(const VariablesList &args, ExecutionContext &ctx
|
|||
warn("Script: actionAttack: attackee is invalid");
|
||||
return Variable();
|
||||
}
|
||||
auto action = make_unique<AttackAction>(attackee);
|
||||
auto action = make_unique<AttackAction>(attackee, caller->getAttackRange());
|
||||
caller->actionQueue().add(move(action));
|
||||
|
||||
return Variable();
|
||||
|
|
90
src/game/script/routines_combat.cpp
Normal file
90
src/game/script/routines_combat.cpp
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2021 The reone project contributors
|
||||
*
|
||||
* This program 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "routines.h"
|
||||
|
||||
#include "../../common/log.h"
|
||||
|
||||
#include "../object/creature.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
using namespace reone::script;
|
||||
|
||||
namespace reone {
|
||||
|
||||
namespace game {
|
||||
|
||||
Variable Routines::getAttackTarget(const VariablesList &args, ExecutionContext &ctx) {
|
||||
Variable result;
|
||||
result.type = VariableType::Object;
|
||||
|
||||
auto creature = getCreatureOrCaller(args, 0, ctx);
|
||||
if (creature) {
|
||||
result.object = creature->combat().attackTarget;
|
||||
} else {
|
||||
warn("Script: getAttackTarget: creature is invalid");
|
||||
}
|
||||
|
||||
return move(result);
|
||||
}
|
||||
|
||||
Variable Routines::getAttemptedAttackTarget(const VariablesList &args, ExecutionContext &ctx) {
|
||||
Variable result;
|
||||
result.type = VariableType::Object;
|
||||
|
||||
auto caller = getCallerAsCreature(ctx);
|
||||
if (caller) {
|
||||
result.object = caller->combat().attemptedAttackTarget;
|
||||
} else {
|
||||
warn("Script: getAttemptedAttackTarget: caller is invalid");
|
||||
}
|
||||
|
||||
return move(result);
|
||||
}
|
||||
|
||||
Variable Routines::getSpellTarget(const VariablesList &args, ExecutionContext &ctx) {
|
||||
Variable result;
|
||||
result.type = VariableType::Object;
|
||||
|
||||
auto creature = getCreatureOrCaller(args, 0, ctx);
|
||||
if (creature) {
|
||||
result.object = creature->combat().spellTarget;
|
||||
} else {
|
||||
warn("Script: getSpellTarget: creature is invalid");
|
||||
}
|
||||
|
||||
return move(result);
|
||||
}
|
||||
|
||||
Variable Routines::getAttemptedSpellTarget(const VariablesList &args, ExecutionContext &ctx) {
|
||||
Variable result;
|
||||
result.type = VariableType::Object;
|
||||
|
||||
auto caller = getCallerAsCreature(ctx);
|
||||
if (caller) {
|
||||
result.object = caller->combat().attemptedSpellTarget;
|
||||
} else {
|
||||
warn("Script: getAttemptedSpellTarget: caller is invalid");
|
||||
}
|
||||
|
||||
return move(result);
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
||||
} // namespace reone
|
|
@ -354,7 +354,7 @@ void Routines::addKotorRoutines() {
|
|||
add("JumpToLocation", Void, { Location }, &Routines::jumpToLocation);
|
||||
add("EffectTemporaryHitpoints", Effect, { Int }, &Routines::effectTemporaryHitpoints);
|
||||
add("GetSkillRank", Int, { Int, Object }, &Routines::getSkillRank);
|
||||
add("GetAttackTarget", Object, { Object });
|
||||
add("GetAttackTarget", Object, { Object }, &Routines::getAttackTarget);
|
||||
add("GetLastAttackType", Int, { Object });
|
||||
add("GetLastAttackMode", Int, { Object });
|
||||
add("GetDistanceBetween2D", Float, { Object, Object }, &Routines::getDistanceBetween2D);
|
||||
|
@ -399,7 +399,7 @@ void Routines::addKotorRoutines() {
|
|||
add("GetGender", Int, { Object }, &Routines::getGender);
|
||||
add("GetIsTalentValid", Int, { Talent });
|
||||
add("ActionMoveAwayFromLocation", Void, { Location, Int, Float }, &Routines::actionMoveAwayFromLocation);
|
||||
add("GetAttemptedAttackTarget", Object, { });
|
||||
add("GetAttemptedAttackTarget", Object, { }, &Routines::getAttemptedAttackTarget);
|
||||
add("GetTypeFromTalent", Int, { Talent });
|
||||
add("GetIdFromTalent", Int, { Talent });
|
||||
add("PlayPazaak", Void, { Int, String, Int, Int, Object });
|
||||
|
@ -413,7 +413,7 @@ void Routines::addKotorRoutines() {
|
|||
add("EffectDamageForcePoints", Effect, { Int }, &Routines::effectDamageForcePoints);
|
||||
add("EffectHealForcePoints", Effect, { Int }, &Routines::effectHealForcePoints);
|
||||
add("SendMessageToPC", Void, { Object, String });
|
||||
add("GetAttemptedSpellTarget", Object, { });
|
||||
add("GetAttemptedSpellTarget", Object, { }, &Routines::getAttemptedSpellTarget);
|
||||
add("GetLastOpenedBy", Object, { }, &Routines::getLastOpenedBy);
|
||||
add("GetHasSpell", Int, { Int, Object });
|
||||
add("OpenStore", Void, { Object, Object, Int, Int });
|
||||
|
@ -800,7 +800,7 @@ void Routines::addKotorRoutines() {
|
|||
add("ResetDialogState", Void, { });
|
||||
add("SetGoodEvilValue", Void, { Object, Int });
|
||||
add("GetIsPoisoned", Int, { Object });
|
||||
add("GetSpellTarget", Object, { Object });
|
||||
add("GetSpellTarget", Object, { Object }, &Routines::getSpellTarget);
|
||||
add("SetSoloMode", Void, { Int });
|
||||
add("EffectCutSceneHorrified", Effect, { }, &Routines::effectCutSceneHorrified);
|
||||
add("EffectCutSceneParalyze", Effect, { }, &Routines::effectCutSceneParalyze);
|
||||
|
|
|
@ -355,7 +355,7 @@ void Routines::addTslRoutines() {
|
|||
add("JumpToLocation", Void, { Location }, &Routines::jumpToLocation);
|
||||
add("EffectTemporaryHitpoints", Effect, { Int }, &Routines::effectTemporaryHitpoints);
|
||||
add("GetSkillRank", Int, { Int, Object }, &Routines::getSkillRank);
|
||||
add("GetAttackTarget", Object, { Object });
|
||||
add("GetAttackTarget", Object, { Object }, &Routines::getAttackTarget);
|
||||
add("GetLastAttackType", Int, { Object });
|
||||
add("GetLastAttackMode", Int, { Object });
|
||||
add("GetDistanceBetween2D", Float, { Object, Object }, &Routines::getDistanceBetween2D);
|
||||
|
@ -400,7 +400,7 @@ void Routines::addTslRoutines() {
|
|||
add("GetGender", Int, { Object }, &Routines::getGender);
|
||||
add("GetIsTalentValid", Int, { Talent });
|
||||
add("ActionMoveAwayFromLocation", Void, { Location, Int, Float }, &Routines::actionMoveAwayFromLocation);
|
||||
add("GetAttemptedAttackTarget", Object, { });
|
||||
add("GetAttemptedAttackTarget", Object, { }, &Routines::getAttemptedAttackTarget);
|
||||
add("GetTypeFromTalent", Int, { Talent });
|
||||
add("GetIdFromTalent", Int, { Talent });
|
||||
add("PlayPazaak", Void, { Int, String, Int, Int, Object });
|
||||
|
@ -414,7 +414,7 @@ void Routines::addTslRoutines() {
|
|||
add("EffectDamageForcePoints", Effect, { Int }, &Routines::effectDamageForcePoints);
|
||||
add("EffectHealForcePoints", Effect, { Int }, &Routines::effectHealForcePoints);
|
||||
add("SendMessageToPC", Void, { Object, String });
|
||||
add("GetAttemptedSpellTarget", Object, { });
|
||||
add("GetAttemptedSpellTarget", Object, { }, &Routines::getAttemptedSpellTarget);
|
||||
add("GetLastOpenedBy", Object, { }, &Routines::getLastOpenedBy);
|
||||
add("GetHasSpell", Int, { Int, Object });
|
||||
add("OpenStore", Void, { Object, Object, Int, Int });
|
||||
|
@ -799,7 +799,7 @@ void Routines::addTslRoutines() {
|
|||
add("ResetDialogState", Void, { });
|
||||
add("SetGoodEvilValue", Void, { Object, Int });
|
||||
add("GetIsPoisoned", Int, { Object });
|
||||
add("GetSpellTarget", Object, { Object });
|
||||
add("GetSpellTarget", Object, { Object }, &Routines::getSpellTarget);
|
||||
add("SetSoloMode", Void, { Int });
|
||||
add("EffectCutSceneHorrified", Effect, { }, &Routines::effectCutSceneHorrified);
|
||||
add("EffectCutSceneParalyze", Effect, { }, &Routines::effectCutSceneParalyze);
|
||||
|
|
Loading…
Reference in a new issue