From 524af9ad5fdad8f3610368036adeb422d9ccef2f Mon Sep 17 00:00:00 2001 From: Persson-dev Date: Fri, 5 Nov 2021 13:10:42 +0100 Subject: [PATCH] feat: add kill reward + effect damages --- include/game/Mobs.h | 23 +++++++++++++--- include/game/Player.h | 12 ++++++--- include/game/Towers.h | 1 + src/game/Mobs.cpp | 61 ++++++++++++++++++++++++++++++++++++------- src/game/Towers.cpp | 4 +-- src/game/World.cpp | 11 ++++++++ 6 files changed, 94 insertions(+), 18 deletions(-) diff --git a/include/game/Mobs.h b/include/game/Mobs.h index 721e025..3be75b2 100644 --- a/include/game/Mobs.h +++ b/include/game/Mobs.h @@ -36,7 +36,6 @@ typedef std::uint32_t MobID; typedef std::uint8_t MobLevel; typedef std::vector TowerImmunities; typedef std::vector EffectImmunities; -typedef std::pair EffectDuration; class MobStats { private: @@ -62,6 +61,12 @@ public: std::uint16_t getMaxLife() const { return m_MaxLife; } }; +struct EffectDuration{ + EffectType type; + float duration; // in seconds + const Tower* tower; // the tower that gived the effect +}; + const MobStats* getMobStats(MobType type, std::uint8_t level); const TowerImmunities& getMobTowerImmunities(MobType type, std::uint8_t level); const EffectImmunities& getMobEffectImmunities(MobType type, std::uint8_t level); @@ -75,10 +80,16 @@ private: MobLevel m_Level; Direction m_Direction; std::vector m_Effects; + const Tower* m_KillTower; // the tower that killed the mob + + utils::Timer m_EffectFireTimer; + utils::Timer m_EffectPoisonTimer; + utils::Timer m_EffectHealTimer; float m_X = 0, m_Y = 0; public: - Mob(MobID id, MobLevel level, PlayerID sender) : m_Sender(sender), m_Level(level) { + Mob(MobID id, MobLevel level, PlayerID sender) : m_Sender(sender), m_Level(level), + m_EffectFireTimer(1000), m_EffectPoisonTimer(1000), m_EffectHealTimer(1000) { } @@ -86,13 +97,18 @@ public: virtual void tick(std::uint64_t delta); + virtual void OnDeath(World* world){} + const TowerImmunities& getTowerImmunities() const { return getMobTowerImmunities(getType(), m_Level); } const EffectImmunities& getEffectImmunities() const { return getMobEffectImmunities(getType(), m_Level); } PlayerID getSender() const { return m_Sender; } MobLevel getLevel() const { return m_Level; } const MobStats* getStats() const { return getMobStats(getType(), m_Level); } float getHealth() const { return m_Health; } + bool isDead() const { return m_Health <= 0; } bool isAlive() const { return m_Health > 0; } + const Tower* getKillTower() { return m_KillTower; } + void setKillTower(const Tower* killTower) { m_KillTower = killTower; } void damage(float dmg) { m_Health -= dmg; } void heal(float heal) { m_Health = std::min((float)getStats()->getMaxLife(), m_Health + heal); } @@ -106,7 +122,7 @@ public: bool isImmuneTo(TowerType type); bool isImmuneTo(EffectType type); - void addEffect(EffectType type, float durationSec); + void addEffect(EffectType type, float durationSec, const Tower* tower); bool hasEffect(EffectType type); @@ -116,6 +132,7 @@ protected: void initHealth() { m_Health = (float)getStats()->getMaxLife(); } private: void updateEffects(std::uint64_t delta); + EffectDuration& getEffect(EffectType type); }; typedef std::shared_ptr MobPtr; diff --git a/include/game/Player.h b/include/game/Player.h index 619d516..d17c687 100644 --- a/include/game/Player.h +++ b/include/game/Player.h @@ -12,14 +12,14 @@ class Player { private: game::TeamColor m_TeamColor; - std::uint32_t m_Gold = 0; - std::uint32_t m_EXP = 0; + std::uint32_t m_Gold; + std::uint32_t m_EXP; std::string m_Name; std::uint8_t m_ID; - std::uint8_t m_GoldPerSecond = 5; + std::uint8_t m_GoldPerSecond; public: - Player(std::uint8_t id = 0) : m_TeamColor(game::TeamColor::None), m_ID(id) {} + Player(std::uint8_t id = 0) : m_TeamColor(game::TeamColor::None), m_Gold(0), m_EXP(0), m_ID(id), m_GoldPerSecond(5) {} const std::string& getName() const { return m_Name; } void setName(const std::string& name) { m_Name = name; } @@ -32,9 +32,13 @@ public: std::uint32_t getGold() const { return m_Gold; } void setGold(std::uint32_t gold) { m_Gold = gold; } + void addGold(std::uint32_t gold) { m_Gold += gold; } + void removeGold(std::uint32_t gold) { m_Gold -= gold; } std::uint32_t getEXP() const { return m_EXP; } void setEXP(std::uint32_t exp) { m_EXP = exp; } + void addEXP(std::uint32_t exp) { m_EXP += exp; } + void removeEXP(std::uint32_t exp) { m_EXP -= exp; } std::uint8_t getID() const { return m_ID; } }; diff --git a/include/game/Towers.h b/include/game/Towers.h index a9b283e..a5e1483 100644 --- a/include/game/Towers.h +++ b/include/game/Towers.h @@ -115,6 +115,7 @@ public: std::uint16_t getY() const { return m_Y; } const TowerLevel& getLevel() const { return m_Level; } const TowerStats* getStats() const { return getTowerStats(m_Type, m_Level); } + PlayerID getBuilder() const { return m_Builder; } bool isMobInRange(MobPtr mob); }; diff --git a/src/game/Mobs.cpp b/src/game/Mobs.cpp index f38d981..01c211a 100644 --- a/src/game/Mobs.cpp +++ b/src/game/Mobs.cpp @@ -14,16 +14,19 @@ bool Mob::isImmuneTo(EffectType type) { return std::find(getEffectImmunities().begin(), getEffectImmunities().end(), type) != getEffectImmunities().end(); } -void Mob::addEffect(EffectType effectType, float durationSec) { +EffectDuration& Mob::getEffect(EffectType effectType){ + return *std::find_if(m_Effects.begin(), m_Effects.end(), [&effectType](EffectDuration effect) { return effect.type == effectType;}); +} + +void Mob::addEffect(EffectType effectType, float durationSec, const Tower* tower) { if (isImmuneTo(effectType)) return; if (hasEffect(effectType)) { - auto it = std::find_if(m_Effects.begin(), m_Effects.end(), [&effectType](EffectDuration effect) { return effect.first == effectType;}); - EffectDuration& effect = *it; - if (effect.second < durationSec) - effect.second = durationSec; // setting new duration if it's greater then the actual + EffectDuration& effect = getEffect(effectType); + if (effect.duration < durationSec) + effect.duration = durationSec; // setting new duration if it's greater then the actual } else { - m_Effects.push_back({ effectType, durationSec }); + m_Effects.push_back({ effectType, durationSec, tower }); } } @@ -35,14 +38,54 @@ void Mob::updateEffects(std::uint64_t delta) { float deltaSec = (float)delta / 1000.0f; for (std::size_t i = 0; i < m_Effects.size(); i++) { EffectDuration& effect = m_Effects[i]; - effect.second -= deltaSec; - if (effect.second < 0) // effect has gone + effect.duration -= deltaSec; + if (effect.duration < 0){ // effect has gone m_Effects.erase(m_Effects.begin() + i); + switch(effect.type){ + case EffectType::Fire:{ + m_EffectFireTimer.reset(); + break; + } + + case EffectType::Poison:{ + m_EffectPoisonTimer.reset(); + break; + } + + case EffectType::Heal:{ + m_EffectHealTimer.reset(); + } + + default: + break; + } + } + } + if(hasEffect(EffectType::Fire)){ + if(m_EffectFireTimer.update(delta)){ + damage(3); + if(isDead()){ + setKillTower(getEffect(EffectType::Fire).tower); + } + } + } + if(hasEffect(EffectType::Poison)){ + if(m_EffectPoisonTimer.update(delta)){ + damage(1); + if(isDead()){ + setKillTower(getEffect(EffectType::Poison).tower); + } + } + } + if(hasEffect(EffectType::Heal)){ + if(m_EffectFireTimer.update(delta)){ + heal(10); + } } } bool Mob::hasEffect(EffectType type) { - return std::find_if(m_Effects.begin(), m_Effects.end(), [&type](EffectDuration effect) { return effect.first == type;}) != m_Effects.end(); + return std::find_if(m_Effects.begin(), m_Effects.end(), [&type](EffectDuration effect) { return effect.type == type;}) != m_Effects.end(); } diff --git a/src/game/Towers.cpp b/src/game/Towers.cpp index e62b545..c393c78 100644 --- a/src/game/Towers.cpp +++ b/src/game/Towers.cpp @@ -192,7 +192,7 @@ void IceTower::tick(std::uint64_t delta, World* world) { bool wasTowerActive = false; for (MobPtr mob : world->getMobList()) { if (isMobInRange(mob)) { - mob->addEffect(EffectType::Slowness, 1); // slowness for 1s every second + mob->addEffect(EffectType::Slowness, 1, this); // slowness for 1s every second mob->damage(damage); wasTowerActive = true; } @@ -207,7 +207,7 @@ void MageTower::tick(std::uint64_t delta, World* world) { bool wasTowerActive = false; for (MobPtr mob : world->getMobList()) { if (isMobInRange(mob)) { - mob->addEffect(EffectType::Fire, getLevel().getLevel()); // slowness for 1s every second + mob->addEffect(EffectType::Fire, getLevel().getLevel() * 5, this); wasTowerActive = true; } } diff --git a/src/game/World.cpp b/src/game/World.cpp index 6e0ce06..4967c77 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -243,6 +243,15 @@ void World::cleanDeadMobs() { for (std::size_t i = 0; i < m_Mobs.size(); i++) { MobPtr mob = m_Mobs[i]; if (!mob->isAlive()) { + mob->OnDeath(this); + + //reward players + Player& sender = m_Game->getPlayerById(mob->getSender()); + sender.addEXP(mob->getStats()->getExpReward()); + + Player& killer = m_Game->getPlayerById(mob->getKillTower()->getBuilder()); + killer.addGold(mob->getStats()->getMoneyCost()); + m_Mobs.erase(m_Mobs.begin() + i); } } @@ -271,6 +280,8 @@ void World::OnArrowShot(MobPtr target, Tower* shooter) { // aoe damage } else { target->damage(shooter->getStats()->getDamage()); + if(target->isDead()) + target->setKillTower(shooter); } }