#include "precompile.h" #include "explosion.h" #include "creature.h" #include "room.h" enum ExplosionType_e { kExplosionIndifference = 1, kExplosionEnemyAndObstacle = 2 }; void Explosion::IndifferenceAttack(Room* room, const a8::Vec2& center, float explosion_range, int explosion_effect, float dmg, long long special_damage_type) { type_ = kExplosionIndifference; room_ = room; explosion_range_ = explosion_range; explosion_effect_ = explosion_effect; dmg_ = dmg; center_ = center; special_damage_type_ = special_damage_type; InternalAttack(); } void Explosion::EnemyAndObstacleAttack(CreatureWeakPtr& sender, const a8::Vec2& center, float explosion_range, int explosion_effect, float dmg, long long special_damage_type) { if (!sender.Get()) { return; } type_ = kExplosionEnemyAndObstacle; room_ = sender.Get()->room; sender_ = sender; explosion_range_ = explosion_range; explosion_effect_ = explosion_effect; dmg_ = dmg; center_ = center; special_damage_type_ = special_damage_type; InternalAttack(); } void Explosion::InternalAttack() { if (explosion_range_ <= 0) { return; } room_->frame_event.AddExplosionEx (sender_, 0, center_, explosion_effect_); std::set grid_list; room_->grid_service->GetAllCellsByXy ( room_, center_.x, center_.y, grid_list ); std::set objects; room_->grid_service->TraverseCreatures ( room_->GetRoomIdx(), grid_list, [this, &objects] (Creature* c, bool& stop) { if (c->GetUniId() == exclude_uniid) { return; } if (!c->Attackable(room_)) { return; } if (!c->ReceiveExplosionDmg(this)) { return; } if (type_ == kExplosionEnemyAndObstacle) { if (sender_.Get()->IsProperTarget(c)) { if (center_.Distance(c->GetPos()) < explosion_range_) { objects.insert(c); } } } else { if (center_.Distance(c->GetPos()) < explosion_range_) { objects.insert(c); } } } ); room_->grid_service->TraverseAllLayerEntityList ( room_->GetRoomIdx(), grid_list, [this, &objects] (Entity* entity, bool& stop) { if (entity->GetUniId() == exclude_uniid) { return; } if (!entity->Attackable(room_)) { return; } if (!entity->ReceiveExplosionDmg(this)) { return; } if (center_.Distance(entity->GetPos()) < explosion_range_) { objects.insert(entity); } } ); for (auto& target : objects) { if (target->HasBuffEffect(kBET_BulletThrough)) { continue; } target->OnExplosionHit(this); } }