337 lines
13 KiB
C++
337 lines
13 KiB
C++
#include "game/Mobs.h"
|
|
|
|
#include <map>
|
|
#include <algorithm>
|
|
|
|
namespace td {
|
|
namespace game {
|
|
|
|
bool Mob::isImmuneTo(TowerType type) {
|
|
return std::find(getTowerImmunities().begin(), getTowerImmunities().end(), type) != getTowerImmunities().end();
|
|
}
|
|
|
|
bool Mob::isImmuneTo(EffectType type) {
|
|
return std::find(getEffectImmunities().begin(), getEffectImmunities().end(), type) != getEffectImmunities().end();
|
|
}
|
|
|
|
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)) {
|
|
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, tower });
|
|
}
|
|
}
|
|
|
|
void Mob::tick(std::uint64_t delta) {
|
|
updateEffects(delta);
|
|
}
|
|
|
|
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.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, getEffect(EffectType::Fire).tower);
|
|
}
|
|
}
|
|
if(hasEffect(EffectType::Poison)){
|
|
if(m_EffectPoisonTimer.update(delta)){
|
|
damage(3, 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.type == type;}) != m_Effects.end();
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef std::pair<MobType, std::uint8_t> MobKey;
|
|
|
|
const std::map<MobKey, MobStats> MobConstants = {
|
|
// damage speed money_cost exp_cost exp_reward max_health
|
|
{{MobType::Zombie, 1},{MobStats{1, 1.6, 15, 0, 7, 40}}},
|
|
{{MobType::Zombie, 2},{MobStats{1, 1.6, 18, 88, 9, 56}}},
|
|
{{MobType::Zombie, 3},{MobStats{1, 1.6, 22, 153, 10, 78}}},
|
|
{{MobType::Zombie, 4},{MobStats{1.5, 1.6, 26, 268, 13, 110}}},
|
|
{{MobType::Zombie, 5},{MobStats{2, 1.6, 31, 469, 15, 154}}},
|
|
|
|
{{MobType::Spider, 1},{MobStats{1, 1.6, 25, 100, 15, 80}}},
|
|
{{MobType::Spider, 2},{MobStats{1, 2, 30, 175, 16, 112}}},
|
|
{{MobType::Spider, 3},{MobStats{1.5, 2, 36, 306, 18, 157}}},
|
|
{{MobType::Spider, 4},{MobStats{2.5, 2, 43, 536, 19, 222}}},
|
|
{{MobType::Spider, 5},{MobStats{1.5, 2.5, 52, 938, 22, 307}}},
|
|
|
|
{{MobType::Skeleton, 1},{MobStats{0, 0, 0, 0, 0, 350}}},
|
|
{{MobType::Skeleton, 2},{MobStats{0, 0, 0, 0, 0, 490}}},
|
|
{{MobType::Skeleton, 3},{MobStats{0, 0, 0, 0, 0, 686}}},
|
|
{{MobType::Skeleton, 4},{MobStats{0, 0, 0, 0, 0, 960}}},
|
|
{{MobType::Skeleton, 5},{MobStats{0, 0, 0, 0, 0, 1345}}},
|
|
|
|
{{MobType::Pigman, 1},{MobStats{0, 0, 0, 0, 0, 150}}},
|
|
{{MobType::Pigman, 2},{MobStats{0, 0, 0, 0, 0, 210}}},
|
|
{{MobType::Pigman, 3},{MobStats{0, 0, 0, 0, 0, 297}}},
|
|
{{MobType::Pigman, 4},{MobStats{0, 0, 0, 0, 0, 412}}},
|
|
{{MobType::Pigman, 5},{MobStats{0, 0, 0, 0, 0, 576}}},
|
|
|
|
{{MobType::Creeper, 1},{MobStats{0, 0, 0, 0, 0, 350}}},
|
|
{{MobType::Creeper, 2},{MobStats{0, 0, 0, 0, 0, 460}}},
|
|
{{MobType::Creeper, 3},{MobStats{0, 0, 0, 0, 0, 630}}},
|
|
{{MobType::Creeper, 4},{MobStats{0, 0, 0, 0, 0, 900}}},
|
|
{{MobType::Creeper, 5},{MobStats{0, 0, 0, 0, 0, 1250}}},
|
|
|
|
{{MobType::Silverfish, 1},{MobStats{0, 0, 0, 0, 0, 120}}},
|
|
{{MobType::Silverfish, 2},{MobStats{0, 0, 0, 0, 0, 170}}},
|
|
{{MobType::Silverfish, 3},{MobStats{0, 0, 0, 0, 0, 225}}},
|
|
{{MobType::Silverfish, 4},{MobStats{0, 0, 0, 0, 0, 310}}},
|
|
{{MobType::Silverfish, 5},{MobStats{0, 0, 0, 0, 0, 390}}},
|
|
|
|
{{MobType::Blaze, 1},{MobStats{0, 0, 0, 0, 0, 410}}},
|
|
{{MobType::Blaze, 2},{MobStats{0, 0, 0, 0, 0, 574}}},
|
|
{{MobType::Blaze, 3},{MobStats{0, 0, 0, 0, 0, 804}}},
|
|
{{MobType::Blaze, 4},{MobStats{0, 0, 0, 0, 0, 1125}}},
|
|
{{MobType::Blaze, 5},{MobStats{0, 0, 0, 0, 0, 1575}}},
|
|
|
|
{{MobType::Witch, 1},{MobStats{0, 0, 0, 0, 0, 300}}},
|
|
{{MobType::Witch, 2},{MobStats{0, 0, 0, 0, 0, 405}}},
|
|
{{MobType::Witch, 3},{MobStats{0, 0, 0, 0, 0, 547}}},
|
|
{{MobType::Witch, 4},{MobStats{0, 0, 0, 0, 0, 738}}},
|
|
{{MobType::Witch, 5},{MobStats{0, 0, 0, 0, 0, 996}}},
|
|
|
|
{{MobType::Slime, 1},{MobStats{0, 0, 0, 0, 0, 800}}},
|
|
{{MobType::Slime, 2},{MobStats{0, 0, 0, 0, 0, 880}}},
|
|
{{MobType::Slime, 3},{MobStats{0, 0, 0, 0, 0, 968}}},
|
|
{{MobType::Slime, 4},{MobStats{0, 0, 0, 0, 0, 1065}}},
|
|
{{MobType::Slime, 5},{MobStats{0, 0, 0, 0, 0, 1171}}},
|
|
|
|
{{MobType::Giant, 1},{MobStats{0, 0, 0, 0, 0, 6250}}},
|
|
{{MobType::Giant, 2},{MobStats{0, 0, 0, 0, 0, 9375}}},
|
|
{{MobType::Giant, 3},{MobStats{0, 0, 0, 0, 0, 14062}}},
|
|
{{MobType::Giant, 4},{MobStats{0, 0, 0, 0, 0, 21093}}},
|
|
{{MobType::Giant, 5},{MobStats{0, 0, 0, 0, 0, 31640}}},
|
|
};
|
|
|
|
const MobStats* getMobStats(MobType type, std::uint8_t level) {
|
|
return &MobConstants.at(MobKey{ type, level });
|
|
}
|
|
|
|
const std::map<MobKey, TowerImmunities> MobsTowerImmunities = {
|
|
{{MobType::Zombie, 1},{}},
|
|
{{MobType::Zombie, 2},{}},
|
|
{{MobType::Zombie, 3},{}},
|
|
{{MobType::Zombie, 4},{}},
|
|
{{MobType::Zombie, 5},{}},
|
|
|
|
{{MobType::Spider, 1},{}},
|
|
{{MobType::Spider, 2},{}},
|
|
{{MobType::Spider, 3},{}},
|
|
{{MobType::Spider, 4},{TowerType::Archer, TowerType::Artillery, TowerType::Leach, TowerType::Necromancer, TowerType::Poison, TowerType::Quake, TowerType::Sorcerer, TowerType::Turret, TowerType::Zeus}},
|
|
{{MobType::Spider, 5},{TowerType::Archer, TowerType::Artillery, TowerType::Leach, TowerType::Necromancer, TowerType::Poison, TowerType::Quake, TowerType::Sorcerer, TowerType::Turret, TowerType::Zeus}},
|
|
|
|
{{MobType::Skeleton, 1},{}},
|
|
{{MobType::Skeleton, 2},{}},
|
|
{{MobType::Skeleton, 3},{}},
|
|
{{MobType::Skeleton, 4},{}},
|
|
{{MobType::Skeleton, 5},{}},
|
|
|
|
{{MobType::Pigman, 1},{TowerType::Zeus}},
|
|
{{MobType::Pigman, 2},{TowerType::Zeus}},
|
|
{{MobType::Pigman, 3},{TowerType::Zeus}},
|
|
{{MobType::Pigman, 4},{TowerType::Zeus}},
|
|
{{MobType::Pigman, 5},{TowerType::Zeus}},
|
|
|
|
{{MobType::Creeper, 1},{}},
|
|
{{MobType::Creeper, 2},{}},
|
|
{{MobType::Creeper, 3},{}},
|
|
{{MobType::Creeper, 4},{}},
|
|
{{MobType::Creeper, 5},{}},
|
|
|
|
{{MobType::Silverfish, 1},{}},
|
|
{{MobType::Silverfish, 2},{}},
|
|
{{MobType::Silverfish, 3},{}},
|
|
{{MobType::Silverfish, 4},{}},
|
|
{{MobType::Silverfish, 5},{}},
|
|
|
|
{{MobType::Blaze, 1},{}},
|
|
{{MobType::Blaze, 2},{}},
|
|
{{MobType::Blaze, 3},{}},
|
|
{{MobType::Blaze, 4},{}},
|
|
{{MobType::Blaze, 5},{}},
|
|
|
|
{{MobType::Witch, 1},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
|
{{MobType::Witch, 2},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
|
{{MobType::Witch, 3},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
|
{{MobType::Witch, 4},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
|
{{MobType::Witch, 5},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
|
|
|
{{MobType::Slime, 1},{}},
|
|
{{MobType::Slime, 2},{}},
|
|
{{MobType::Slime, 3},{}},
|
|
{{MobType::Slime, 4},{}},
|
|
{{MobType::Slime, 5},{}},
|
|
|
|
{{MobType::Giant, 1},{}},
|
|
{{MobType::Giant, 2},{}},
|
|
{{MobType::Giant, 3},{}},
|
|
{{MobType::Giant, 4},{}},
|
|
{{MobType::Giant, 5},{}},
|
|
};
|
|
|
|
const TowerImmunities& getMobTowerImmunities(MobType type, std::uint8_t level) {
|
|
return MobsTowerImmunities.at({ type, level });
|
|
}
|
|
|
|
const std::map<MobKey, EffectImmunities> MobsEffectImmunities = {
|
|
{{MobType::Zombie, 1},{}},
|
|
{{MobType::Zombie, 2},{}},
|
|
{{MobType::Zombie, 3},{}},
|
|
{{MobType::Zombie, 4},{}},
|
|
{{MobType::Zombie, 5},{}},
|
|
|
|
{{MobType::Spider, 1},{}},
|
|
{{MobType::Spider, 2},{}},
|
|
{{MobType::Spider, 3},{}},
|
|
{{MobType::Spider, 4},{}},
|
|
{{MobType::Spider, 5},{}},
|
|
|
|
{{MobType::Skeleton, 1},{}},
|
|
{{MobType::Skeleton, 2},{}},
|
|
{{MobType::Skeleton, 3},{EffectType::Fire}},
|
|
{{MobType::Skeleton, 4},{EffectType::Fire}},
|
|
{{MobType::Skeleton, 5},{EffectType::Fire}},
|
|
|
|
{{MobType::Pigman, 1},{EffectType::Fire}},
|
|
{{MobType::Pigman, 2},{EffectType::Fire}},
|
|
{{MobType::Pigman, 3},{EffectType::Fire}},
|
|
{{MobType::Pigman, 4},{EffectType::Fire}},
|
|
{{MobType::Pigman, 5},{EffectType::Fire}},
|
|
|
|
{{MobType::Creeper, 1},{}},
|
|
{{MobType::Creeper, 2},{}},
|
|
{{MobType::Creeper, 3},{}},
|
|
{{MobType::Creeper, 4},{}},
|
|
{{MobType::Creeper, 5},{}},
|
|
|
|
{{MobType::Silverfish, 1},{}},
|
|
{{MobType::Silverfish, 2},{}},
|
|
{{MobType::Silverfish, 3},{}},
|
|
{{MobType::Silverfish, 4},{EffectType::Fire}},
|
|
{{MobType::Silverfish, 5},{EffectType::Fire}},
|
|
|
|
{{MobType::Blaze, 1},{EffectType::Fire}},
|
|
{{MobType::Blaze, 2},{EffectType::Fire}},
|
|
{{MobType::Blaze, 3},{EffectType::Fire}},
|
|
{{MobType::Blaze, 4},{EffectType::Fire}},
|
|
{{MobType::Blaze, 5},{EffectType::Fire}},
|
|
|
|
{{MobType::Witch, 1},{}},
|
|
{{MobType::Witch, 2},{}},
|
|
{{MobType::Witch, 3},{}},
|
|
{{MobType::Witch, 4},{}},
|
|
{{MobType::Witch, 5},{}},
|
|
|
|
{{MobType::Slime, 1},{}},
|
|
{{MobType::Slime, 2},{}},
|
|
{{MobType::Slime, 3},{}},
|
|
{{MobType::Slime, 4},{EffectType::Fire}},
|
|
{{MobType::Slime, 5},{EffectType::Fire}},
|
|
|
|
{{MobType::Giant, 1},{EffectType::Stun}},
|
|
{{MobType::Giant, 2},{EffectType::Stun}},
|
|
{{MobType::Giant, 3},{EffectType::Stun}},
|
|
{{MobType::Giant, 4},{EffectType::Stun}},
|
|
{{MobType::Giant, 5},{EffectType::Stun}},
|
|
};
|
|
|
|
const EffectImmunities& getMobEffectImmunities(MobType type, std::uint8_t level) {
|
|
return MobsEffectImmunities.at({ type, level });
|
|
}
|
|
|
|
MobPtr MobFactory::createMob(MobID id, MobType type, std::uint8_t level, PlayerID sender) {
|
|
using MobCreator = std::function<std::shared_ptr<Mob>(MobID, std::uint8_t, PlayerID)>;
|
|
|
|
static std::map<MobType, MobCreator> mobFactory = {
|
|
{MobType::Zombie, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Zombie>(id, level, sender);} },
|
|
{MobType::Spider, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Spider>(id, level, sender);} },
|
|
{MobType::Skeleton, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Skeleton>(id, level, sender);} },
|
|
{MobType::Pigman, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<PigMan>(id, level, sender);} },
|
|
{MobType::Creeper, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Creeper>(id, level, sender);} },
|
|
{MobType::Silverfish, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Silverfish>(id, level, sender);} },
|
|
{MobType::Blaze, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Blaze>(id, level, sender);} },
|
|
{MobType::Witch, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Witch>(id, level, sender);} },
|
|
{MobType::Slime, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Slime>(id, level, sender);} },
|
|
{MobType::Giant, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Giant>(id, level, sender);} },
|
|
};
|
|
|
|
return mobFactory[type](id, level, sender);
|
|
}
|
|
|
|
std::string MobFactory::getMobName(MobType type){
|
|
switch(type){
|
|
case MobType::Zombie:
|
|
return "Zombie";
|
|
case MobType::Spider:
|
|
return "Spider";
|
|
case MobType::Skeleton:
|
|
return "Skeleton";
|
|
case MobType::Pigman:
|
|
return "Pigman";
|
|
case MobType::Creeper:
|
|
return "Creeper";
|
|
case MobType::Silverfish:
|
|
return "Silverfish";
|
|
case MobType::Blaze:
|
|
return "Blaze";
|
|
case MobType::Witch:
|
|
return "Witch";
|
|
case MobType::Slime:
|
|
return "Slime";
|
|
case MobType::Giant:
|
|
return "Giant";
|
|
default:
|
|
return "Unknow";
|
|
}
|
|
}
|
|
|
|
} // namespace game
|
|
} // namespace td
|