refactor: mob die event

This commit is contained in:
2021-12-11 19:51:45 +01:00
parent 0af4cd506c
commit a241d7691b
5 changed files with 32 additions and 27 deletions

View File

@@ -73,7 +73,7 @@ public:
struct EffectDuration { struct EffectDuration {
EffectType type; EffectType type;
float duration; // in seconds float duration; // in seconds
const Tower* tower; // the tower that gived the effect Tower* tower; // the tower that gived the effect
}; };
const MobStats* getMobStats(MobType type, std::uint8_t level); const MobStats* getMobStats(MobType type, std::uint8_t level);
@@ -129,7 +129,7 @@ public:
bool isImmuneTo(TowerType type); bool isImmuneTo(TowerType type);
bool isImmuneTo(EffectType type); bool isImmuneTo(EffectType type);
void addEffect(EffectType type, float durationSec, const Tower* tower); void addEffect(EffectType type, float durationSec, Tower* tower);
bool hasEffect(EffectType type); bool hasEffect(EffectType type);
float getTileX() { return getCenterX() - static_cast<float>(static_cast<std::int32_t>(getCenterX())); } // returns a float between 0 and 1 excluded float getTileX() { return getCenterX() - static_cast<float>(static_cast<std::int32_t>(getCenterX())); } // returns a float between 0 and 1 excluded
@@ -143,7 +143,7 @@ protected:
setSize(getStats()->getSize().x, getStats()->getSize().y); setSize(getStats()->getSize().x, getStats()->getSize().y);
} }
private: private:
void updateEffects(std::uint64_t delta); void updateEffects(std::uint64_t delta, World* world);
void attackCastle(std::uint64_t delta, World* world); void attackCastle(std::uint64_t delta, World* world);
void move(std::uint64_t delta, World* world); void move(std::uint64_t delta, World* world);
void walk(std::uint64_t delta, World* world); void walk(std::uint64_t delta, World* world);
@@ -232,10 +232,10 @@ std::string getMobName(MobType type);
class MobListener { class MobListener {
public: public:
virtual void OnMobSpawn(MobPtr mob) {} virtual void OnMobSpawn(Mob* mob) {}
virtual void OnMobDie(MobPtr mob) {} virtual void OnMobDie(Mob* mob) {}
virtual void OnMobDamage(MobPtr target, float damage, Tower* damager) {} virtual void OnMobDamage(Mob* target, float damage, Tower* damager) {}
virtual void OnMobTouchCastle(Mob* damager, TeamCastle* enemyCastle) {} virtual void OnMobTouchCastle(Mob* damager, TeamCastle* enemyCastle) {}
virtual void OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage) {} virtual void OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage) {}

View File

@@ -222,7 +222,9 @@ public:
// MobListener // MobListener
virtual void OnMobDamage(MobPtr target, float damage, Tower* source); virtual void OnMobDamage(Mob* target, float damage, Tower* source);
virtual void OnMobDie(Mob* mob);
private: private:
void tickMobs(std::uint64_t delta); void tickMobs(std::uint64_t delta);
void cleanDeadMobs(); void cleanDeadMobs();

View File

@@ -20,7 +20,7 @@ EffectDuration& Mob::getEffect(EffectType effectType) {
return *std::find_if(m_Effects.begin(), m_Effects.end(), [&effectType](EffectDuration effect) { return effect.type == 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) { void Mob::addEffect(EffectType effectType, float durationSec, Tower* tower) {
if (isImmuneTo(effectType)) if (isImmuneTo(effectType))
return; return;
if (hasEffect(effectType)) { if (hasEffect(effectType)) {
@@ -194,12 +194,12 @@ bool Mob::isTouchingCastle(const TeamCastle& enemyCastle) const {
} }
void Mob::tick(std::uint64_t delta, World* world) { void Mob::tick(std::uint64_t delta, World* world) {
updateEffects(delta); updateEffects(delta, world);
move(delta, world); move(delta, world);
attackCastle(delta, world); attackCastle(delta, world);
} }
void Mob::updateEffects(std::uint64_t delta) { void Mob::updateEffects(std::uint64_t delta, World* world) {
float deltaSec = (float)delta / 1000.0f; float deltaSec = (float)delta / 1000.0f;
for (std::size_t i = 0; i < m_Effects.size(); i++) { for (std::size_t i = 0; i < m_Effects.size(); i++) {
EffectDuration& effect = m_Effects[i]; EffectDuration& effect = m_Effects[i];
@@ -228,12 +228,12 @@ void Mob::updateEffects(std::uint64_t delta) {
} }
if (hasEffect(EffectType::Fire)) { if (hasEffect(EffectType::Fire)) {
if (m_EffectFireTimer.update(delta)) { if (m_EffectFireTimer.update(delta)) {
damage(3, getEffect(EffectType::Fire).tower); world->getMobNotifier().notifyListeners(&MobListener::OnMobDamage, this, 3.0f, getEffect(EffectType::Fire).tower);
} }
} }
if (hasEffect(EffectType::Poison)) { if (hasEffect(EffectType::Poison)) {
if (m_EffectPoisonTimer.update(delta)) { if (m_EffectPoisonTimer.update(delta)) {
damage(1, getEffect(EffectType::Poison).tower); world->getMobNotifier().notifyListeners(&MobListener::OnMobDamage, this, 1.0f, getEffect(EffectType::Poison).tower);
} }
} }
if (hasEffect(EffectType::Heal)) { if (hasEffect(EffectType::Heal)) {

View File

@@ -230,7 +230,7 @@ void IceTower::tick(std::uint64_t delta, World* world) {
if (isMobInRange(mob)) { if (isMobInRange(mob)) {
mob->addEffect(EffectType::Slowness, 1, this); // slowness for 1s every second mob->addEffect(EffectType::Slowness, 1, this); // slowness for 1s every second
if (damage > 0) if (damage > 0)
world->getMobNotifier().notifyListeners(&MobListener::OnMobDamage, mob, damage, this); world->getMobNotifier().notifyListeners(&MobListener::OnMobDamage, mob.get(), damage, this);
m_Timer.applyCooldown(); m_Timer.applyCooldown();
} }
} }
@@ -253,7 +253,7 @@ void PoisonTower::tick(std::uint64_t delta, World* world) {
for (MobPtr mob : world->getMobList()) { for (MobPtr mob : world->getMobList()) {
if (isMobInRange(mob)) { if (isMobInRange(mob)) {
if (getLevel().getPath() == TowerPath::Bottom) { if (getLevel().getPath() == TowerPath::Bottom) {
world->getMobNotifier().notifyListeners(&MobListener::OnMobDamage, mob, getStats()->getDamage(), this); world->getMobNotifier().notifyListeners(&MobListener::OnMobDamage, mob.get(), getStats()->getDamage(), this);
} else { } else {
float durationSec; float durationSec;
switch (getLevel().getLevel()) { switch (getLevel().getLevel()) {

View File

@@ -214,21 +214,24 @@ bool World::CanPlaceBigTower(const glm::vec2& worldPos, PlayerID playerID) const
return false; return false;
} }
void World::cleanDeadMobs() { void World::OnMobDie(Mob* mob) {
for (std::size_t i = 0; i < m_Mobs.size(); i++) { if (mob->OnDeath(this)) { // check if the mob is actually dead (slimes ...)
MobPtr mob = m_Mobs[i];
if (mob->isDead()) {
if (mob->OnDeath(this)) {
//reward players //reward players
Player* sender = m_Game->getPlayerById(mob->getSender()); Player* sender = m_Game->getPlayerById(mob->getSender());
sender->addExp(mob->getStats()->getExpReward()); sender->addExp(mob->getStats()->getExpReward());
Player* killer = m_Game->getPlayerById(mob->getLastDamageTower()->getBuilder()); Player* killer = m_Game->getPlayerById(mob->getLastDamageTower()->getBuilder());
killer->addGold(mob->getStats()->getMoneyCost()); killer->addGold(mob->getStats()->getMoneyCost());
m_Mobs.erase(m_Mobs.begin() + i);
} }
} }
void World::cleanDeadMobs() {
// safely remove mobs when unused
for (std::size_t i = 0; i < m_Mobs.size(); i++) {
MobPtr mob = m_Mobs[i];
if (mob->isDead()) {
m_Mobs.erase(m_Mobs.begin() + i);
}
} }
} }
@@ -266,7 +269,7 @@ void World::OnArcherTowerShot(MobPtr target, ArcherTower* shooter) {
} }
void World::OnArrowShot(MobPtr target, bool fireArrow, Tower* shooter) { void World::OnArrowShot(MobPtr target, bool fireArrow, Tower* shooter) {
getMobNotifier().notifyListeners(&MobListener::OnMobDamage, target, shooter->getStats()->getDamage(), shooter); getMobNotifier().notifyListeners(&MobListener::OnMobDamage, target.get(), shooter->getStats()->getDamage(), shooter);
if (fireArrow) { if (fireArrow) {
target->addEffect(EffectType::Fire, ArcherTower::FireDurationSec, shooter); target->addEffect(EffectType::Fire, ArcherTower::FireDurationSec, shooter);
} }
@@ -277,12 +280,12 @@ void World::OnExplosion(utils::shape::Circle explosion, float centerDamage, Towe
if (mob->isAlive() && mob->collidesWith(explosion)) { if (mob->isAlive() && mob->collidesWith(explosion)) {
// linear distance damage reduction // linear distance damage reduction
float explosionDamage = mob->distance(explosion) / explosion.getRadius() * centerDamage; float explosionDamage = mob->distance(explosion) / explosion.getRadius() * centerDamage;
getMobNotifier().notifyListeners(&MobListener::OnMobDamage, mob, explosionDamage, shooter); getMobNotifier().notifyListeners(&MobListener::OnMobDamage, mob.get(), explosionDamage, shooter);
} }
} }
} }
void World::OnMobDamage(MobPtr target, float damage, Tower* source) { void World::OnMobDamage(Mob* target, float damage, Tower* source) {
target->damage(damage, source); target->damage(damage, source);
if (target->isDead()) { if (target->isDead()) {
getMobNotifier().notifyListeners(&MobListener::OnMobDie, target); getMobNotifier().notifyListeners(&MobListener::OnMobDie, target);