explosion

This commit is contained in:
aozhiwei 2021-06-22 02:25:30 +00:00
parent 18a0c5eeb7
commit 1a9f70be47
17 changed files with 293 additions and 422 deletions

View File

@ -132,7 +132,9 @@ void Bullet::ProcBomb()
{
//榴弹炮
a8::Vec2 bomb_pos = GetPos();
room->frame_event.AddExplosionEx(sender, meta->i->id(), bomb_pos,
room->frame_event.AddExplosionEx(sender,
meta->i->id(),
bomb_pos,
gun_meta->i->explosion_effect());
OnHit(objects);
}

View File

@ -11,6 +11,7 @@
#include "perfmonitor.h"
#include "typeconvert.h"
#include "bullet.h"
#include "explosion.h"
Car::Car():Creature()
{
@ -334,7 +335,13 @@ void Car::BeKill(int killer_id, const std::string& killer_name, int weapon_id)
passenger->RemoveBuffByEffectId(kBET_Passenger);
room->frame_event.AddCarChg(passenger->GetWeakPtrRef());
}
Explosion(team_id);
Explosion explosion;
explosion.IndifferenceAttack(
room,
GetPos(),
meta->i->explosion_range(),
meta->i->atk(),
meta->i->explosion_effect());
}
void Car::GetAabbBox(AabbCollider& aabb_box)
@ -347,46 +354,6 @@ void Car::GetAabbBox(AabbCollider& aabb_box)
aabb_box._max.y = hero_meta_->i->radius();
}
void Car::Explosion(int team_id)
{
if (meta->i->explosion_range() <= 0) {
return;
}
std::set<Creature*> objects;
TraverseProperTargetsNoTeammate
(
[this, &objects, team_id] (Creature* c, bool& stop)
{
float distance = (c->GetPos() - GetPos()).Norm();
if (distance < meta->i->explosion_range()) {
objects.insert(c);
}
});
room->frame_event.AddExplosionEx(GetWeakPtrRef(),
0,
GetPos(),
meta->i->explosion_effect());
for (auto& target : objects) {
switch (target->GetEntityType()) {
case ET_Player:
{
Human* hum = (Human*)target;
if (!hum->dead) {
float dmg = meta->i->atk();
float def = hum->ability.def;
float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K);
hum->DecHP(finaly_dmg, VP_Mine, TEXT("battle_server_killer_mine", "地雷"), VW_Mine);
}
}
break;
default:
{
}
break;
}
}
}
void Car::SendDebugMsg(const std::string& debug_msg)
{
#if 1

View File

@ -47,7 +47,6 @@ class Car : public Creature
private:
int AllocSeat();
void BeKill(int killer_id, const std::string& killer_name, int weapon_id);
void Explosion(int team_id);
bool IsPassenger(Human* hum);
private:
long long born_frameno_ = 0;

View File

@ -347,6 +347,30 @@ enum OptResult
kOptBreak = 2
};
enum BulletHit_e
{
kBulletHitPass = 1,
kBulletHitAnyDmg = 2,
kBulletHitOnlySpecDmg = 3,
kBulletHitEatDmg = 4,
};
enum CollisionHit_e
{
kCollisionHitPass = 1,
kCollisionHitBlock = 2,
kCollisionHitDeadAndDrop = 3,
kCollisionHitSpecEvent = 4,
};
enum ExplosionHit_e
{
kExplosionHitPass = 1,
kExplosionHitAnyDmg = 2,
kExplosionHitOnlySpecDmg = 3,
kExplosionHitEatDmg = 4,
};
const char* const PROJ_NAME_FMT = "game%d_gameserver";
const char* const PROJ_ROOT_FMT = "/data/logs/%s";

View File

@ -12,6 +12,7 @@ class AabbCollider;
class CircleCollider;
class Human;
class Bullet;
class Explosion;
class Entity
{
public:
@ -33,6 +34,7 @@ class Entity
virtual void OnPreCollision(Room* room) {};
virtual void RecalcSelfCollider() {};
virtual void OnBulletHit(Bullet* bullet) {};
virtual void OnExplosionHit(Explosion* explosion) {};
virtual void OnAddToTargetPartObject(Entity* target) {};
virtual void OnRemoveFromTargetPartObject(Entity* target) {};
virtual bool CanSeeMe(Human* hum) { return true; };

View File

@ -0,0 +1,110 @@
#include "precompile.h"
#include "explosion.h"
void Explosion::IndifferenceAttack(Room* room,
const a8::Vec2& center,
float range,
int explosion_effect,
float dmg)
{
#if 0
if (meta->i->explosion_range() <= 0) {
return;
}
std::set<Creature*> objects;
TraverseProperTargetsNoTeammate
(
[this, &objects, team_id] (Creature* c, bool& stop)
{
float distance = (c->GetPos() - GetPos()).Norm();
if (distance < meta->i->explosion_range()) {
objects.insert(c);
}
});
room->frame_event.AddExplosionEx(GetWeakPtrRef(),
0,
GetPos(),
meta->i->explosion_effect());
for (auto& target : objects) {
switch (target->GetEntityType()) {
case ET_Player:
{
Human* hum = (Human*)target;
if (!hum->dead) {
float dmg = meta->i->atk();
float def = hum->ability.def;
float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K);
hum->DecHP(finaly_dmg, VP_Mine, TEXT("battle_server_killer_mine", "地雷"), VW_Mine);
}
}
break;
default:
{
}
break;
}
}
#endif
}
void Explosion::EnemyAndObstacleAttack(CreatureWeakPtr& sender,
const a8::Vec2& center,
float range,
int explosion_effect,
float dmg)
{
#if 0
if (!sender.Get()) {
return;
}
if (follow_target.Get()) {
bomb_pos = follow_target.Get()->GetPos();
}
room->frame_event.AddExplosionEx(sender,
meta->i->id(),
bomb_pos,
gun_meta->i->explosion_effect());
std::set<GridCell*> grid_list;
sender.Get()->room->grid_service->GetAllCellsByXy
(
sender.Get()->room,
bomb_pos.x,
bomb_pos.y,
grid_list
);
std::set<Creature*> objects;
sender.Get()->room->grid_service->TraverseCreatures
(
sender.Get()->room->GetRoomIdx(),
grid_list,
[this, &objects] (Creature* c, bool& stop)
{
if (sender.Get()->IsProperTarget(c)) {
if (bomb_pos.Distance(c->GetPos()) < meta->i->explosion_range()) {
objects.insert(c);
}
}
}
);
std::set<Entity*> entitys;
sender.Get()->room->grid_service->TraverseAllLayerEntityList
(
sender.Get()->room->GetRoomIdx(),
grid_list,
[this, &entitys] (Entity* entity, bool& stop)
{
}
);
Explosion explosion;
for (auto& target : objects) {
target->OnExplosionHit(&explosion);
}
for (auto& target : entitys) {
target->OnExplosionHit(&explosion);
}
#endif
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "weakptr.h"
class Room;
class Explosion
{
public:
void IndifferenceAttack(Room* room,
const a8::Vec2& center,
float range,
int explosion_effect,
float dmg);
void EnemyAndObstacleAttack(CreatureWeakPtr& sender,
const a8::Vec2& center,
float range,
int explosion_effect,
float dmg);
};

View File

@ -8,100 +8,19 @@
#include "gridservice.h"
#include "creature.h"
#include "obstacle.h"
#include "explosion.h"
void FragMiTask::Done()
{
if (!sender.Get()) {
return;
}
a8::Vec2 center = bomb_pos;
if (follow_target.Get()) {
bomb_pos = follow_target.Get()->GetPos();
}
room->frame_event.AddExplosionEx(sender,
meta->i->id(),
bomb_pos,
gun_meta->i->explosion_effect());
std::set<GridCell*> grid_list;
sender.Get()->room->grid_service->GetAllCellsByXy
(
sender.Get()->room,
bomb_pos.x,
bomb_pos.y,
grid_list
);
std::set<Creature*> objects;
sender.Get()->room->grid_service->TraverseCreatures
(
sender.Get()->room->GetRoomIdx(),
grid_list,
[this, &objects] (Creature* c, bool& stop)
{
if (sender.Get()->IsProperTarget(c)) {
if (bomb_pos.Distance(c->GetPos()) < meta->i->explosion_range()) {
objects.insert(c);
}
}
}
);
std::set<Entity*> entitys;
sender.Get()->room->grid_service->TraverseAllLayerEntityList
(
sender.Get()->room->GetRoomIdx(),
grid_list,
[this, &entitys] (Entity* entity, bool& stop)
{
}
);
for (auto& target : objects) {
if (target->IsInvincible()) {
continue;
}
if (sender.Get()->room->GetRoomMode() == kZombieMode &&
sender.Get()->GetRace() == target->GetRace()) {
continue;
}
if (!target->dead) {
float dmg = GetAtk() * (1 + sender.Get()->GetAttrRate(kHAT_Atk)) +
sender.Get()->GetAttrAbs(kHAT_Atk);
float def = target->ability.def * (1 + target->GetAttrRate(kHAT_Def)) +
target->GetAttrAbs(kHAT_Def);
float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K);
finaly_dmg = std::max(finaly_dmg, 0.0f);
target->DecHP(finaly_dmg,
sender.Get()->GetUniId(),
sender.Get()->GetName(),
gun_meta->i->id());
}
}
for (auto& target : entitys) {
if (target->GetEntityType() != ET_Obstacle) {
continue;
}
Obstacle* obstacle = (Obstacle*)target;
if (!obstacle->IsDead(room) &&
obstacle->Attackable(sender.Get()) &&
!obstacle->IsTerminatorAirDropBox(room)) {
float dmg = GetAtk() * (1 + sender.Get()->GetAttrRate(kHAT_Atk)) +
sender.Get()->GetAttrAbs(kHAT_Atk);
float def = 0;
float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K);
obstacle->SetHealth(room, std::max(0.0f, obstacle->GetHealth(room) - finaly_dmg));
if (obstacle->GetHealth(room) <= 0.01f) {
obstacle->Die(room);
}
if (obstacle->IsDead(room)) {
if (obstacle->meta->i->damage_dia() > 0.01f &&
obstacle->meta->i->damage() > 0.01f) {
#if 0
obstacle->Explosion(this);
#endif
}
sender.Get()->DropItems(obstacle);
}
obstacle->BroadcastFullState(room);
}
}
Explosion explosion;
explosion.EnemyAndObstacleAttack(sender,
center,
meta->i->explosion_range(),
gun_meta->i->explosion_effect(),
GetAtk());
}

View File

@ -165,7 +165,9 @@ bool Hero::IsCollisionInMapService()
return true;
}
if (!obstacle->IsDead(room) &&
#if 0
obstacle->Attackable(this) &&
#endif
obstacle->meta->i->drop() != 0 &&
obstacle->IsTouchInteraction() &&
room->GetGasData().gas_mode != GasInactive &&

View File

@ -525,7 +525,9 @@ bool Human::IsCollisionInMapService()
return true;
}
if (!obstacle->IsDead(room) &&
#if 0
obstacle->Attackable(this) &&
#endif
obstacle->meta->i->drop() != 0 &&
obstacle->IsTouchInteraction() &&
room->GetGasData().gas_mode != GasInactive &&
@ -3598,6 +3600,37 @@ void Human::OnBulletHit(Bullet* bullet)
}
}
void Human::OnExplosionHit(Explosion* explosion)
{
if (IsInvincible()) {
return;
}
if (dead) {
return;
}
#if 0
if (target->IsInvincible()) {
continue;
}
if (sender.Get()->room->GetRoomMode() == kZombieMode &&
sender.Get()->GetRace() == target->GetRace()) {
continue;
}
if (!target->dead) {
float dmg = GetAtk() * (1 + sender.Get()->GetAttrRate(kHAT_Atk)) +
sender.Get()->GetAttrAbs(kHAT_Atk);
float def = target->ability.def * (1 + target->GetAttrRate(kHAT_Def)) +
target->GetAttrAbs(kHAT_Def);
float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K);
finaly_dmg = std::max(finaly_dmg, 0.0f);
target->DecHP(finaly_dmg,
sender.Get()->GetUniId(),
sender.Get()->GetName(),
gun_meta->i->id());
}
#endif
}
void Human::SendRollMsgEx(KillInfo& info,
const char* fmt,
std::initializer_list<a8::XValue> args

View File

@ -141,6 +141,7 @@ class Human : public Creature
virtual bool IsDead(Room* room) override;
virtual long long GetDeadFrameNo(Room* room) override;
virtual void OnBulletHit(Bullet* bullet) override;
virtual void OnExplosionHit(Explosion* explosion) override;
void FillItemList(::google::protobuf::RepeatedPtrField<::cs::MFPair>* pb_item_list);
long long GetRealDeadFrameNo(Room* room);
void FillMFTeamData(cs::MFTeamData* team_data, bool is_game_over);

View File

@ -356,6 +356,7 @@ Obstacle* MapInstance::InternalCreateObstacle(int id, float x, float y, int coll
grid_service_->AddPermanentEntity(entity);
}
{
#if 0
switch (thing->i->attack_type()) {
case 0:
{
@ -377,6 +378,7 @@ Obstacle* MapInstance::InternalCreateObstacle(int id, float x, float y, int coll
}
break;
}
#endif
++obstacle_num_;
}
return entity;

View File

@ -12,6 +12,7 @@
#include "perfmonitor.h"
#include "roomobstacle.h"
#include "loot.h"
#include "explosion.h"
enum ObstacleDataFlags_e
{
@ -108,7 +109,7 @@ void Obstacle::RecalcSelfCollider()
collider->tag = collider_tag;
collider->param1 = collider_param1;
collider->param2 = collider_param2;
if (meta->i->attack_type() == 3) {
if (IsHalfWallCollider()) {
a8::SetBitFlag(collider->tag, kHalfWallTag);
}
}
@ -289,112 +290,6 @@ void Obstacle::OnPreCollision(Room* room)
}
}
void Obstacle::Explosion(Bullet* bullet)
{
Room* room = bullet->room;
float old_rad = self_collider_->rad;
if (self_collider_) {
self_collider_->rad = meta->i->damage_dia();
}
if (meta->i->damage_dia() > 0.01f &&
meta->i->damage() > 0.01f) {
std::set<Entity*> objects;
std::set<GridCell*> tmp_grids;
room->grid_service->GetAllCellsByXy(room, GetX(), GetY(), tmp_grids);
room->grid_service->TraverseAllLayerHumanList
(
room->GetRoomIdx(),
tmp_grids,
[this, room, &objects] (Human* hum, bool& stop)
{
if (TestCollision(room, hum)) {
objects.insert(hum);
}
});
room->grid_service->TraverseAllLayerEntityList
(
room->GetRoomIdx(),
tmp_grids,
[this, room, &objects] (Entity* entity, bool& stop)
{
switch (entity->GetEntityType()) {
case ET_Obstacle:
case ET_Building:
{
if (entity != this && TestCollision(room, entity)) {
objects.insert(entity);
}
}
break;
default:
{
}
break;
}
});
a8::Vec2 bomb_pos = GetPos();
#if 1
room->frame_event.AddExplosionEx(bullet->sender,
meta->i->thing_id(),
bomb_pos,
meta->i->explosion_effect());
#else
room->frame_event.AddExplosion(bullet, meta->i->thing_id(), bomb_pos);
#endif
for (auto& target : objects) {
switch (target->GetEntityType()) {
case ET_Player:
{
Human* hum = (Human*)target;
if (!hum->dead && hum->team_id != team_id_) {
float dmg = meta->i->damage();
float def = hum->ability.def;
float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K);
if (GetMasterId(bullet->room)) {
Human* master = bullet->room->GetHumanByUniId(GetMasterId(bullet->room));
if (master) {
hum->DecHP(finaly_dmg, master->GetUniId(), master->GetName(), VW_Mine);
} else {
hum->DecHP(finaly_dmg, VP_Mine, TEXT("battle_server_killer_mine", "地雷"), VW_Mine);
}
} else {
hum->DecHP(finaly_dmg, VP_Mine, TEXT("battle_server_killer_mine", "地雷"), VW_Mine);
}
}
}
break;
case ET_Obstacle:
{
Obstacle* obstacle = (Obstacle*)target;
if (!obstacle->IsDead(room) &&
obstacle->Attackable(this) &&
!obstacle->IsTerminatorAirDropBox(room)) {
float dmg = meta->i->damage();
float def = 0;
float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K);
obstacle->SetHealth(room,
std::max(0.0f, obstacle->health_ - finaly_dmg));
if (obstacle->GetHealth(room) <= 0.01f) {
obstacle->Die(room);
}
if (obstacle->IsDead(room)) {
bullet->sender.Get()->DropItems(obstacle);
}
obstacle->BroadcastFullState(room);
}
}
break;
default:
break;
}
}
}
if (self_collider_) {
self_collider_->rad = old_rad;
}
}
void Obstacle::SetDoorInfo(Building* building, int door_id_x)
{
MetaData::Building::Door* door_meta = &building->meta->doors[door_id_x];
@ -509,35 +404,11 @@ bool Obstacle::IsPermanent()
return is_permanent;
}
bool Obstacle::Attackable(Entity* sender)
{
switch (meta->i->attack_type()) {
case 1:
{
return true;
}
break;
case 4:
{
//只有特定子弹
if (sender->IsEntityType(ET_Bullet)) {
Bullet* bullet = (Bullet*)sender;
return ((bullet->gun_meta->special_damage_type & meta->receive_special_damage_type) != 0);
}
return false;
}
break;
default:
{
return false;
}
break;
}
}
bool Obstacle::Throughable()
{
#if 0
return meta->i->attack_type() == 2;
#endif
}
int Obstacle::GetTeamId(Room* room)
@ -599,7 +470,6 @@ void Obstacle::SetMasterId(Room* room, int master_id)
void Obstacle::OnBulletHit(Bullet* bullet)
{
if (!IsDead(bullet->room) &&
Attackable(bullet) &&
!IsTerminatorAirDropBox(bullet->room)) {
if (meta->receive_special_damage_type != 0 &&
((bullet->gun_meta->special_damage_type & meta->receive_special_damage_type) == 0)) {
@ -640,7 +510,13 @@ void Obstacle::OnBulletHit(Bullet* bullet)
if (IsDead(bullet->room)) {
if (meta->i->damage_dia() > 0.01f &&
meta->i->damage() > 0.01f) {
Explosion(bullet);
Explosion explosion;
explosion.IndifferenceAttack(
bullet->room,
GetPos(),
meta->i->damage_dia(),
meta->i->damage(),
meta->i->explosion_effect());
}
bullet->sender.Get()->DropItems(this);
}
@ -658,20 +534,62 @@ void Obstacle::OnBulletHit(Bullet* bullet)
}
}
void Obstacle::OnExplosionHit(Explosion* e)
{
#if 0
if (!target->IsEntityType(Obstacle)) {
continue;
}
Obstacle* obstacle = (Obstacle*)target;
if (obstacle->IsDead(room)) {
continue;
}
if (obstacle->meta->i->explosion_hit() == kExplosionHitPass ||
obstacle->meta->i->explosion_hit() == kExplosionHitEatDmg) {
continue;
}
if (obstacle->Attackable(sender.Get()) &&
!obstacle->IsTerminatorAirDropBox(room)) {
float dmg = GetAtk() * (1 + sender.Get()->GetAttrRate(kHAT_Atk)) +
sender.Get()->GetAttrAbs(kHAT_Atk);
float def = 0;
float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K);
obstacle->SetHealth(room, std::max(0.0f, obstacle->GetHealth(room) - finaly_dmg));
if (obstacle->GetHealth(room) <= 0.01f) {
obstacle->Die(room);
}
if (obstacle->IsDead(room)) {
if (obstacle->meta->i->damage_dia() > 0.01f &&
obstacle->meta->i->damage() > 0.01f) {
#if 0
obstacle->Explosion(this);
#endif
}
sender.Get()->DropItems(obstacle);
}
obstacle->BroadcastFullState(room);
}
#endif
}
bool Obstacle::CanThroughable(Creature* c)
{
#if 0
if (meta->i->attack_type() == 4) {
return true;
}
#endif
return false;
}
bool Obstacle::CanThroughable(Bullet* bullet)
{
#if 0
if (meta->i->attack_type() == 4) {
return !(meta->receive_special_damage_type != 0 &&
((bullet->gun_meta->special_damage_type & meta->receive_special_damage_type) != 0));
}
#endif
return false;
}
@ -744,7 +662,9 @@ void Obstacle::OnCollisionTrigger(Creature* c, OptResult& opt_result)
{
if (c->team_id != GetTeamId(c->room)) {
AddObstacleBuff(c);
#if 0
Explosion();
#endif
Die(c->room);
BroadcastFullState(c->room);
}
@ -858,3 +778,9 @@ bool Obstacle::CanSeeMe(Human* hum)
break;
}
}
bool Obstacle::IsHalfWallCollider()
{
return meta->i->collision_hit() == kCollisionHitPass &&
meta->i->bullet_hit() != kBulletHitPass;
}

View File

@ -42,14 +42,13 @@ class Obstacle : public Entity
virtual long long GetDeadFrameNo(Room* room) override;
virtual void OnPreCollision(Room* room) override;
virtual void OnBulletHit(Bullet* bullet) override;
virtual void OnExplosionHit(Explosion* explosion) override;
virtual bool IsTerminatorAirDropBox(Room* room) { return false; }
virtual bool CanThroughable(Creature* c);
virtual bool CanThroughable(Bullet* bullet);
virtual bool DoInteraction(Human* sender);
virtual void OnCollisionTrigger(Creature* c, OptResult& opt_result);
virtual void Explosion() {};
virtual bool CanSeeMe(Human* hum);
void Explosion(Bullet* bullet);
void SetDoorInfo(Building* building, int door_id_x);
bool IsDoor();
DoorState_e GetDoorState(Room* room);
@ -67,7 +66,6 @@ class Obstacle : public Entity
int GetMasterId(Room* room);
void SetMasterId(Room* room, int master_id);
bool IsPermanent();
bool Attackable(Entity* sender);
bool Throughable();
bool IsTouchInteraction();
bool IsOpenInteraction();
@ -80,6 +78,7 @@ protected:
std::tuple<long long, a8::Vec2>* GetInteractionData(Human* sender);
void AddObstacleBuff(Creature* c);
void ClearObstacleBuff(Creature* c);
bool IsHalfWallCollider();
protected:
CircleCollider* self_collider_ = nullptr;

View File

@ -10,6 +10,7 @@
#include "bullet.h"
#include "mapservice.h"
#include "roomobstacle.h"
#include "explosion.h"
RoomObstacle::RoomObstacle():Obstacle()
{
@ -94,7 +95,7 @@ void RoomObstacle::RecalcSelfCollider()
collider->tag = collider_tag;
collider->param1 = collider_param1;
collider->param2 = collider_param2;
if (meta->i->attack_type() == 3) {
if (IsHalfWallCollider()) {
a8::SetBitFlag(collider->tag, kHalfWallTag);
}
}
@ -163,8 +164,16 @@ void RoomObstacle::UpdateTimerFunc()
}
}
}
Explosion();
Die(room);
{
Explosion explosion;
explosion.IndifferenceAttack(
room,
GetPos(),
meta->i->damage_dia(),
meta->i->damage(),
meta->i->explosion_effect());
}
BroadcastFullState(room);
if (room->xtimer.GetRunningTimer()) {
room->xtimer.DeleteTimer(room->xtimer.GetRunningTimer());
@ -175,102 +184,6 @@ void RoomObstacle::UpdateTimerFunc()
}
}
void RoomObstacle::Explosion()
{
float old_rad = self_collider_->rad;
if (self_collider_) {
self_collider_->rad = meta->i->damage_dia();
}
if (meta->i->damage_dia() > 0.01f &&
meta->i->damage() > 0.01f) {
std::set<Entity*> objects;
room->grid_service->TraverseAllLayerHumanList
(
room->GetRoomIdx(),
*grid_list_,
[this, &objects] (Human* hum, bool& stop)
{
if (master.Get()->team_id != hum->team_id && TestCollision(room, hum)) {
objects.insert(hum);
}
});
room->grid_service->TraverseAllLayerEntityList
(
room->GetRoomIdx(),
*grid_list_,
[this, &objects] (Entity* entity, bool& stop)
{
switch (entity->GetEntityType()) {
case ET_Obstacle:
case ET_Building:
{
if (entity != this && TestCollision(room, entity)) {
objects.insert(entity);
}
}
break;
default:
{
}
break;
}
});
a8::Vec2 bomb_pos = GetPos();
room->frame_event.AddExplosionEx(master,
meta->i->thing_id(),
bomb_pos,
meta->i->explosion_effect());
for (auto& target : objects) {
switch (target->GetEntityType()) {
case ET_Player:
{
Human* hum = (Human*)target;
if (!hum->dead) {
float dmg = meta->i->damage();
float def = hum->ability.def;
float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K);
if (master.Get()) {
hum->DecHP(finaly_dmg, master.Get()->GetUniId(), master.Get()->GetName(), VW_Mine);
} else {
hum->DecHP(finaly_dmg, VP_Mine, TEXT("battle_server_killer_mine", "地雷"), VW_Mine);
}
}
}
break;
case ET_Obstacle:
{
Obstacle* obstacle = (Obstacle*)target;
if (!obstacle->IsDead(room) &&
obstacle->Attackable(this) &&
!obstacle->IsTerminatorAirDropBox(room)) {
float dmg = meta->i->damage();
float def = 0;
float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K);
obstacle->SetHealth(room,
std::max(0.0f, obstacle->GetHealth(room) - finaly_dmg));
if (obstacle->GetHealth(room) <= 0.01f) {
obstacle->Die(room);
}
if (obstacle->IsDead(room)) {
#if 0
bullet->player->DropItems(obstacle);
#endif
}
obstacle->BroadcastFullState(room);
}
}
break;
default:
break;
}
}
}
if (self_collider_) {
self_collider_->rad = old_rad;
}
}
void RoomObstacle::SpecExplosion()
{
++explosion_times_;
@ -284,58 +197,13 @@ void RoomObstacle::SpecExplosion()
bomb_born_offset.Rotate(a8::RandAngle());
bomb_born_offset = bomb_born_offset * a8::RandEx(1, std::max(2, meta->i->explosion_float()));
a8::Vec2 bomb_pos = GetPos() + bomb_born_offset;
std::set<Entity*> objects;
Creature* dumy_c = nullptr;
room->grid_service->TraverseAllLayerHumanList
(
room->GetRoomIdx(),
*grid_list_,
[this, &objects, &bomb_pos, &dumy_c] (Human* hum, bool& stop)
{
if (!dumy_c) {
dumy_c = hum;
}
float distance = (hum->GetPos() - bomb_pos).Norm();
if ((!master.Get() || master.Get()->team_id != hum->team_id) &&
distance < meta->i->damage_dia()) {
dumy_c = hum;
objects.insert(hum);
}
});
if (dumy_c) {
room->frame_event.AddExplosionEx(dumy_c->GetWeakPtrRef(),
meta->i->thing_id(),
bomb_pos,
meta->i->explosion_effect());
}
for (auto& target : objects) {
switch (target->GetEntityType()) {
case ET_Player:
{
Human* hum = (Human*)target;
if (!hum->dead) {
float dmg = meta->i->damage();
float def = hum->ability.def;
float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K);
hum->DecHP(finaly_dmg, VP_Mine, TEXT("battle_server_killer_mine", "地雷"), VW_Mine);
for (int buff_id : meta->buff_list) {
MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(buff_id);
if (buff_meta) {
hum->AddBuff(master.Get(),
buff_meta,
1);
}
}
}
}
break;
default:
{
}
break;
}
}
Explosion explosion;
explosion.IndifferenceAttack(
room,
bomb_pos,
meta->i->damage_dia(),
meta->i->damage(),
meta->i->explosion_effect());
}
if (explosion_times_ >= meta->i->explosion_times()) {
room->xtimer.DeleteTimer(room->xtimer.GetRunningTimer());

View File

@ -25,7 +25,6 @@ class RoomObstacle : public Obstacle
void Active();
void DetachFromMaster();
virtual void Die(Room* room) override;
virtual void Explosion() override;
Entity* GetRealObject(Room* room);
private:

View File

@ -52,7 +52,6 @@ message MapThing
optional float damage = 6; //
optional float damage_dia = 7; //
optional int32 drop = 8; //
optional int32 attack_type = 9; // 0: 1 2穿
optional int32 is_door = 10; //
optional int32 is_house = 11; //
optional int32 is_tree = 12; //