refactor: mob die event
This commit is contained in:
@@ -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) {}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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)) {
|
||||||
|
|||||||
@@ -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()) {
|
||||||
|
|||||||
@@ -214,20 +214,23 @@ 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);
|
||||||
|
|||||||
Reference in New Issue
Block a user