Skip to content

Commit

Permalink
KOTORBASE: Implement combat rounds with minimal attack damage
Browse files Browse the repository at this point in the history
  • Loading branch information
vkremianskii authored and DrMcCoy committed Sep 21, 2019
1 parent 1f7fa2c commit 55265df
Show file tree
Hide file tree
Showing 12 changed files with 227 additions and 22 deletions.
2 changes: 1 addition & 1 deletion src/engines/kotorbase/actionexecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ void ActionExecutor::executeAttackObject(const Action &action, const ExecutionCo
return;

ctx.creature->popAction();
ctx.creature->playAttackAnimation();
ctx.creature->startCombat(action.object, ctx.area->_module->getNextCombatRound());
}

bool ActionExecutor::isLocationReached(const glm::vec2 &location, float range, const ExecutionContext &ctx) {
Expand Down
4 changes: 4 additions & 0 deletions src/engines/kotorbase/area.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,10 @@ Creature *Area::getNearestCreature(const Object *target, int UNUSED(nth), const
return result;
}

const std::vector<Creature *> &Area::getCreatures() const {
return _creatures;
}

void Area::processCreaturesActions(float dt) {
ActionExecutor::ExecutionContext ctx;
ctx.area = this;
Expand Down
1 change: 1 addition & 0 deletions src/engines/kotorbase/area.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ class Area : public Object, public Events::Notifyable {

Object *getObjectByTag(const Common::UString &tag);
Creature *getNearestCreature(const Object *target, int nth, const CreatureSearchCriteria &criteria) const;
const std::vector<Creature *> &getCreatures() const;

void addCreature(Creature *creature);
void addToObjectMap(Object *object);
Expand Down
74 changes: 74 additions & 0 deletions src/engines/kotorbase/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,15 @@ void Creature::playAttackAnimation() {
_model->playAnimation("g8a1");
}

void Creature::playDodgeAnimation() {
if (!_model)
return;

int number = getWeaponAnimationNumber();
if (number != -1)
_model->playAnimation(Common::UString::format("g%dg1", number));
}

void Creature::playAnimation(const Common::UString &anim, bool restart, float length, float speed) {
if (_model)
_model->playAnimation(anim, restart, length, speed);
Expand Down Expand Up @@ -791,6 +800,36 @@ void Creature::updatePerception(Creature &object) {
}
}

bool Creature::isInCombat() const {
return _inCombat;
}

Object *Creature::getAttackTarget() const {
return _attackTarget;
}

int Creature::getAttackRound() const {
return _attackRound;
}

Object *Creature::getAttemptedAttackTarget() const {
return _attemptedAttackTarget;
}

void Creature::setAttemptedAttackTarget(Object *target) {
_attemptedAttackTarget = target;
}

void Creature::startCombat(Object *target, int round) {
_inCombat = true;
_attackTarget = target;
_attackRound = round;
}

void Creature::cancelCombat() {
_inCombat = false;
}

void Creature::handleObjectSeen(Object &object) {
bool inserted = _seenObjects.insert(&object).second;
if (inserted)
Expand Down Expand Up @@ -878,6 +917,41 @@ bool Creature::addItemToEquipment(const Common::UString &tag, InventorySlot slot
}
}

int Creature::getWeaponAnimationNumber() const {
const Item *rightWeapon = getEquipedItem(kInventorySlotRightWeapon);
const Item *leftWeapon = getEquipedItem(kInventorySlotLeftWeapon);

if (rightWeapon && !leftWeapon) {
switch (rightWeapon->getWeaponWield()) {
case kWeaponWieldBaton:
return 1;
case kWeaponWieldSword:
return 2;
case kWeaponWieldStaff:
return 3;
case kWeaponWieldPistol:
return 5;
case kWeaponWieldRifle:
return 7;
default:
return -1;
}
}

if (rightWeapon && leftWeapon) {
switch (rightWeapon->getWeaponWield()) {
case kWeaponWieldSword:
return 4;
case kWeaponWieldPistol:
return 6;
default:
return -1;
}
}

return 8;
}

} // End of namespace KotORBase

} // End of namespace Engines
22 changes: 22 additions & 0 deletions src/engines/kotorbase/creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ class Creature : public Object {
void playDefaultHeadAnimation();
void playDrawWeaponAnimation();
void playAttackAnimation();
void playDodgeAnimation();

void playAnimation(const Common::UString &anim,
bool restart = true,
Expand Down Expand Up @@ -189,6 +190,18 @@ class Creature : public Object {

void updatePerception(Creature &object);

// Combat

bool isInCombat() const;
Object *getAttackTarget() const;
int getAttackRound() const;
Object *getAttemptedAttackTarget() const;

void setAttemptedAttackTarget(Object *target);

void startCombat(Object *target, int round);
void cancelCombat();

protected:
// Parts of a creature's body.
struct PartModels {
Expand All @@ -214,6 +227,13 @@ class Creature : public Object {
std::set<Object *> _seenObjects;
std::set<Object *> _heardObjects;

// Combat

bool _inCombat { false };
Object *_attackTarget { nullptr };
int _attackRound { 0 };
Object *_attemptedAttackTarget { nullptr };


bool _isPC; ///< Is the creature a PC?

Expand Down Expand Up @@ -269,6 +289,8 @@ class Creature : public Object {

void reloadEquipment();
bool addItemToEquipment(const Common::UString &tag, InventorySlot slot);

int getWeaponAnimationNumber() const;
};

} // End of namespace KotORBase
Expand Down
59 changes: 56 additions & 3 deletions src/engines/kotorbase/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "src/common/filepath.h"
#include "src/common/filelist.h"
#include "src/common/configman.h"
#include "src/common/debug.h"

#include "src/aurora/types.h"
#include "src/aurora/rimfile.h"
Expand Down Expand Up @@ -94,12 +95,12 @@ Module::Module(::Engines::Console &console) :
_partyLeaderController(this),
_partyController(this),
_cameraController(this),
_roundController(this),
_prevTimestamp(0),
_frameTime(0),
_inDialog(false),
_runScriptVar(-1),
_soloMode(false),
_round(this) {
_soloMode(false) {

loadSurfaceTypes();
}
Expand Down Expand Up @@ -570,7 +571,7 @@ void Module::processEventQueue() {
handleEvents();
handleActions();

_round.update();
_roundController.update();

GfxMan.lockFrame();

Expand Down Expand Up @@ -719,6 +720,54 @@ void Module::openContainer(Placeable *placeable) {
updateFrameTimestamp();
}

void Module::notifyCombatRoundBegan(int round) {
for (auto c : _area->getCreatures()) {
if (!c->isInCombat() || c->getAttackRound() != round)
continue;

Object *target = c->getAttackTarget();
if (!target || c->getDistanceTo(target) > c->getMaxAttackRange())
continue;

c->setAttemptedAttackTarget(target);
c->makeLookAt(target);
c->playAttackAnimation();

Creature *targetCreature = ObjectContainer::toCreature(target);
if (targetCreature) {
targetCreature->makeLookAt(c);
targetCreature->playDodgeAnimation();
}
}
}

void Module::notifyCombatRoundEnded(int round) {
for (auto c : _area->getCreatures()) {
if (!c->isInCombat())
continue;

Object *target = c->getAttemptedAttackTarget();
if (!target)
continue;

int hp = target->getCurrentHitPoints() - 1;
int minHp = target->getMinOneHitPoints() ? 1 : 0;

if (hp <= minHp) {
hp = minHp;
c->cancelCombat();
}

target->setCurrentHitPoints(hp);

debugC(Common::kDebugEngineLogic, 1,
"Object \"%s\" was hit by \"%s\" during combat round %d, has %d HP",
target->getName().c_str(), c->getName().c_str(), round, hp);

c->setAttemptedAttackTarget(nullptr);
}
}

void Module::handleActions() {
uint32 now = EventMan.getTimestamp();

Expand Down Expand Up @@ -999,6 +1048,10 @@ void Module::toggleTriggers() {
_area->toggleTriggers();
}

int Module::getNextCombatRound() const {
return _roundController.getNextCombatRound();
}

void Module::loadSavedGame(SavedGame *save) {
try {
Common::ScopedPtr<CharacterGenerationInfo> info(save->createCharGenInfo());
Expand Down
8 changes: 6 additions & 2 deletions src/engines/kotorbase/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ class Module : public Object, public ObjectContainer {
void toggleFlyCamera();
void toggleWalkmesh();
void toggleTriggers();
int getNextCombatRound() const;

protected:
Common::ScopedPtr<IngameGUI> _ingame; ///< The ingame GUI.
Expand Down Expand Up @@ -340,13 +341,13 @@ class Module : public Object, public ObjectContainer {
PartyLeaderController _partyLeaderController;
PartyController _partyController;
CameraController _cameraController;
RoundController _roundController;

uint32 _prevTimestamp;
float _frameTime;
bool _inDialog;
int _runScriptVar;
bool _soloMode;
Round _round;

// Unloading

Expand Down Expand Up @@ -413,8 +414,11 @@ class Module : public Object, public ObjectContainer {
void handleDelayedInteractions();
void openContainer(Placeable *placeable);

void notifyCombatRoundBegan(int round);
void notifyCombatRoundEnded(int round);

friend class Round;

friend class RoundController;
};

} // End of namespace KotORBase
Expand Down
8 changes: 8 additions & 0 deletions src/engines/kotorbase/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
* Object within an area in KotOR games.
*/

#include "external/glm/geometric.hpp"

#include "src/common/uuid.h"
#include "src/common/util.h"
#include "src/common/maths.h"
Expand Down Expand Up @@ -176,6 +178,12 @@ Location Object::getLocation() const {
return location;
}

float Object::getDistanceTo(const Object *other) const {
glm::vec2 origin(_position[0], _position[1]);
glm::vec2 target(other->_position[0], other->_position[1]);
return glm::length(target - origin);
}

int Object::getMaxHitPoints() {
return _maxHitPoints;
}
Expand Down
2 changes: 2 additions & 0 deletions src/engines/kotorbase/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ class Object : public Aurora::NWScript::Object, public ScriptContainer {
/** Create a Location out of the object's area, position and orientation. */
Location getLocation() const;

float getDistanceTo(const Object *other) const;

// Hit points

/** Get the maximum hit points for the objects. */
Expand Down
1 change: 1 addition & 0 deletions src/engines/kotorbase/partyleader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ bool PartyLeaderController::processMovement(float frameTime) {
}

partyLeader->clearActions();
partyLeader->cancelCombat();

float x, y, _;
partyLeader->getPosition(x, y, _);
Expand Down

0 comments on commit 55265df

Please sign in to comment.