game2005/server/gameserver/explosion.cc
2021-07-19 11:18:59 +00:00

125 lines
3.5 KiB
C++

#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<GridCell*> grid_list;
room_->grid_service->GetAllCellsByXy
(
room_,
center_.x,
center_.y,
grid_list
);
std::set<Entity*> 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);
}
}