Fixing some stuff related to attacks

This commit is contained in:
Vladislav Khorev 2026-07-12 16:55:23 +03:00
parent 9d03b52c2a
commit 92929118d5
7 changed files with 32 additions and 7 deletions

View File

@ -330,6 +330,7 @@ void Character::update(int64_t deltaMs, const CharacterResolver& resolver) {
state.currentState != AnimationState::DEATH_IDLE) {
state.currentState = AnimationState::ACTION_TO_DEATH;
state.resetAnim = true;
state.attackTargetIndex = CharacterState::kNoTarget;
}
} else {
if (state.battle_state == 1) {
@ -433,7 +434,7 @@ void Character::update(int64_t deltaMs, const CharacterResolver& resolver) {
(state.currentState == AnimationState::ACTION_ATTACK ||
state.currentState == AnimationState::ACTION_ATTACK_2)) {
if (attackTarget != nullptr) {
attackTarget->applyDamage(10.f, attackDirectionToTarget());
attackTarget->applyDamage(10.f, attackDirectionToTarget(), index);
if (audioPlayer) {
if (state.isPlayer)
@ -1214,12 +1215,12 @@ void Character::setupHitSparks(std::shared_ptr<Texture> sparkTexture) {
hitSparkEmitter.markConfigured();
}
void Character::applyDamage(float damageAmount, const Eigen::Vector3f& attackDirection) {
void Character::applyDamage(float damageAmount, const Eigen::Vector3f& attackDirection, int attackerIndex) {
std::cout << "Character::applyDamage" << std::endl;
state.hp -= damageAmount;
if (state.hp < 0) state.hp = 0;
if (state.onHpChanged) state.onHpChanged(state.hp, state.initialHp);
if (state.onHpChanged) state.onHpChanged(state.hp, state.initialHp, attackerIndex);
if (!hitSparkEmitter.isConfigured()) return;

View File

@ -31,6 +31,8 @@ public:
// All serializable game state (position, hp, flags, pathfinding, etc.)
CharacterState state;
int index = CharacterState::kNoTarget;
// ---- Asset loading ----
void loadAnimation(AnimationState animState, const std::string& filename, const std::string& zipFile = "");
void loadBinaryAnimation(AnimationState animState, const std::string& filename, const std::string& zipFile = "");
@ -64,7 +66,7 @@ public:
void resetPlayerAfterDeath();
// ---- Damage ----
void applyDamage(float damageAmount, const Eigen::Vector3f& attackDirection = Eigen::Vector3f::Zero());
void applyDamage(float damageAmount, const Eigen::Vector3f& attackDirection = Eigen::Vector3f::Zero(), int attackerIndex = CharacterState::kNoTarget);
// ---- Spark setup ----
void setupHitSparks(std::shared_ptr<Texture> sparkTexture);

View File

@ -27,7 +27,7 @@ void CharacterState::stopInPlace() {
void CharacterState::setHp(float newHp) {
hp = newHp;
if (hp < 0.f) hp = 0.f;
if (onHpChanged) onHpChanged(hp, initialHp);
if (onHpChanged) onHpChanged(hp, initialHp, CharacterState::kNoTarget);
}
void CharacterState::save(nlohmann::json& out) const

View File

@ -114,7 +114,7 @@ public:
// --- Non-serializable callbacks (re-wired after each load) ---
std::function<void()> onArrivedCallback;
std::function<void()> onDeathAnimComplete;
std::function<void(float, float)> onHpChanged;
std::function<void(float, float, int)> onHpChanged;
// Global Lua function name backing onArrivedCallback, if it was sourced from a
// script (see ScriptEngine::rehydrateNamedCallback). Serialized so the callback

View File

@ -744,8 +744,25 @@ namespace ZL
// Wire HP-change callbacks so all player instances update the health bar HUD.
for (auto& [name, loc] : gameState.locations) {
if (loc->player) {
loc->player->state.onHpChanged = [this](float hp, float maxHp) {
loc->player->state.onHpChanged = [this, loc](float hp, float maxHp, int attackerIndex) {
menuManager.updateHealthBar(hp, maxHp);
if (attackerIndex != CharacterState::kNoTarget) {
//Someone attacked, cancel dialogue and agro the player
if (loc->dialogueSystem.isDialogueActive()) {
loc->dialogueSystem.stopDialogue();
}
if ((loc->player->state.attackTargetIndex == CharacterState::kNoTarget ||
((loc->player->state.attackTargetIndex >= 0) &&
(loc->npcs[loc->player->state.attackTargetIndex]->state.hp <= 0)))
&&
loc->player->isMoving() == false) {
loc->player->state.attackTargetIndex = attackerIndex;
}
}
};
}
}

View File

@ -52,6 +52,7 @@ public:
void load(const nlohmann::json& in) override { loadDialogueState(in); }
bool isActive() const { return dialogueRuntime.isActive() || cutsceneRuntime.isActive(); }
bool isDialogueActive() const { return dialogueRuntime.isActive(); }
bool blocksGameplayInput() const { return isActive(); }
void setFlag(const std::string& name, int value) { dialogueRuntime.setFlag(name, value); }

View File

@ -363,6 +363,8 @@ namespace ZL {
{
std::vector<std::unique_ptr<Character>> npcs;
int index = 0;
for (const auto& npcData : loadNpcsFromJson(jsonPath, zipPath)) {
SDL_PumpEvents();
std::cout << "Loading NPC: " << npcData.name << std::endl;
@ -371,7 +373,9 @@ namespace ZL {
if (npc) {
std::cout << "Successfully loaded NPC: " << npcData.name << " at ("
<< npcData.positionX << ", " << npcData.positionY << ", " << npcData.positionZ << ")" << std::endl;
npc->index = index;
npcs.push_back(std::move(npc));
index = index + 1;
}
} catch (const std::exception& e) {
std::cerr << "GameObjectLoader: Failed to load NPC '" << npcData.name << "': " << e.what() << std::endl;