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(); 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()); gun_meta->i->explosion_effect());
OnHit(objects); OnHit(objects);
} }

View File

@ -11,6 +11,7 @@
#include "perfmonitor.h" #include "perfmonitor.h"
#include "typeconvert.h" #include "typeconvert.h"
#include "bullet.h" #include "bullet.h"
#include "explosion.h"
Car::Car():Creature() 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); passenger->RemoveBuffByEffectId(kBET_Passenger);
room->frame_event.AddCarChg(passenger->GetWeakPtrRef()); 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) void Car::GetAabbBox(AabbCollider& aabb_box)
@ -347,46 +354,6 @@ void Car::GetAabbBox(AabbCollider& aabb_box)
aabb_box._max.y = hero_meta_->i->radius(); 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) void Car::SendDebugMsg(const std::string& debug_msg)
{ {
#if 1 #if 1

View File

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

View File

@ -347,6 +347,30 @@ enum OptResult
kOptBreak = 2 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_NAME_FMT = "game%d_gameserver";
const char* const PROJ_ROOT_FMT = "/data/logs/%s"; const char* const PROJ_ROOT_FMT = "/data/logs/%s";

View File

@ -12,6 +12,7 @@ class AabbCollider;
class CircleCollider; class CircleCollider;
class Human; class Human;
class Bullet; class Bullet;
class Explosion;
class Entity class Entity
{ {
public: public:
@ -33,6 +34,7 @@ class Entity
virtual void OnPreCollision(Room* room) {}; virtual void OnPreCollision(Room* room) {};
virtual void RecalcSelfCollider() {}; virtual void RecalcSelfCollider() {};
virtual void OnBulletHit(Bullet* bullet) {}; virtual void OnBulletHit(Bullet* bullet) {};
virtual void OnExplosionHit(Explosion* explosion) {};
virtual void OnAddToTargetPartObject(Entity* target) {}; virtual void OnAddToTargetPartObject(Entity* target) {};
virtual void OnRemoveFromTargetPartObject(Entity* target) {}; virtual void OnRemoveFromTargetPartObject(Entity* target) {};
virtual bool CanSeeMe(Human* hum) { return true; }; 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 "gridservice.h"
#include "creature.h" #include "creature.h"
#include "obstacle.h" #include "obstacle.h"
#include "explosion.h"
void FragMiTask::Done() void FragMiTask::Done()
{ {
if (!sender.Get()) { a8::Vec2 center = bomb_pos;
return;
}
if (follow_target.Get()) { if (follow_target.Get()) {
bomb_pos = follow_target.Get()->GetPos(); 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; return true;
} }
if (!obstacle->IsDead(room) && if (!obstacle->IsDead(room) &&
#if 0
obstacle->Attackable(this) && obstacle->Attackable(this) &&
#endif
obstacle->meta->i->drop() != 0 && obstacle->meta->i->drop() != 0 &&
obstacle->IsTouchInteraction() && obstacle->IsTouchInteraction() &&
room->GetGasData().gas_mode != GasInactive && room->GetGasData().gas_mode != GasInactive &&

View File

@ -525,7 +525,9 @@ bool Human::IsCollisionInMapService()
return true; return true;
} }
if (!obstacle->IsDead(room) && if (!obstacle->IsDead(room) &&
#if 0
obstacle->Attackable(this) && obstacle->Attackable(this) &&
#endif
obstacle->meta->i->drop() != 0 && obstacle->meta->i->drop() != 0 &&
obstacle->IsTouchInteraction() && obstacle->IsTouchInteraction() &&
room->GetGasData().gas_mode != GasInactive && 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, void Human::SendRollMsgEx(KillInfo& info,
const char* fmt, const char* fmt,
std::initializer_list<a8::XValue> args std::initializer_list<a8::XValue> args

View File

@ -141,6 +141,7 @@ class Human : public Creature
virtual bool IsDead(Room* room) override; virtual bool IsDead(Room* room) override;
virtual long long GetDeadFrameNo(Room* room) override; virtual long long GetDeadFrameNo(Room* room) override;
virtual void OnBulletHit(Bullet* bullet) override; virtual void OnBulletHit(Bullet* bullet) override;
virtual void OnExplosionHit(Explosion* explosion) override;
void FillItemList(::google::protobuf::RepeatedPtrField<::cs::MFPair>* pb_item_list); void FillItemList(::google::protobuf::RepeatedPtrField<::cs::MFPair>* pb_item_list);
long long GetRealDeadFrameNo(Room* room); long long GetRealDeadFrameNo(Room* room);
void FillMFTeamData(cs::MFTeamData* team_data, bool is_game_over); 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); grid_service_->AddPermanentEntity(entity);
} }
{ {
#if 0
switch (thing->i->attack_type()) { switch (thing->i->attack_type()) {
case 0: case 0:
{ {
@ -377,6 +378,7 @@ Obstacle* MapInstance::InternalCreateObstacle(int id, float x, float y, int coll
} }
break; break;
} }
#endif
++obstacle_num_; ++obstacle_num_;
} }
return entity; return entity;

View File

@ -12,6 +12,7 @@
#include "perfmonitor.h" #include "perfmonitor.h"
#include "roomobstacle.h" #include "roomobstacle.h"
#include "loot.h" #include "loot.h"
#include "explosion.h"
enum ObstacleDataFlags_e enum ObstacleDataFlags_e
{ {
@ -108,7 +109,7 @@ void Obstacle::RecalcSelfCollider()
collider->tag = collider_tag; collider->tag = collider_tag;
collider->param1 = collider_param1; collider->param1 = collider_param1;
collider->param2 = collider_param2; collider->param2 = collider_param2;
if (meta->i->attack_type() == 3) { if (IsHalfWallCollider()) {
a8::SetBitFlag(collider->tag, kHalfWallTag); 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) void Obstacle::SetDoorInfo(Building* building, int door_id_x)
{ {
MetaData::Building::Door* door_meta = &building->meta->doors[door_id_x]; MetaData::Building::Door* door_meta = &building->meta->doors[door_id_x];
@ -509,35 +404,11 @@ bool Obstacle::IsPermanent()
return is_permanent; 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() bool Obstacle::Throughable()
{ {
#if 0
return meta->i->attack_type() == 2; return meta->i->attack_type() == 2;
#endif
} }
int Obstacle::GetTeamId(Room* room) int Obstacle::GetTeamId(Room* room)
@ -599,7 +470,6 @@ void Obstacle::SetMasterId(Room* room, int master_id)
void Obstacle::OnBulletHit(Bullet* bullet) void Obstacle::OnBulletHit(Bullet* bullet)
{ {
if (!IsDead(bullet->room) && if (!IsDead(bullet->room) &&
Attackable(bullet) &&
!IsTerminatorAirDropBox(bullet->room)) { !IsTerminatorAirDropBox(bullet->room)) {
if (meta->receive_special_damage_type != 0 && if (meta->receive_special_damage_type != 0 &&
((bullet->gun_meta->special_damage_type & 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 (IsDead(bullet->room)) {
if (meta->i->damage_dia() > 0.01f && if (meta->i->damage_dia() > 0.01f &&
meta->i->damage() > 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); 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) bool Obstacle::CanThroughable(Creature* c)
{ {
#if 0
if (meta->i->attack_type() == 4) { if (meta->i->attack_type() == 4) {
return true; return true;
} }
#endif
return false; return false;
} }
bool Obstacle::CanThroughable(Bullet* bullet) bool Obstacle::CanThroughable(Bullet* bullet)
{ {
#if 0
if (meta->i->attack_type() == 4) { if (meta->i->attack_type() == 4) {
return !(meta->receive_special_damage_type != 0 && return !(meta->receive_special_damage_type != 0 &&
((bullet->gun_meta->special_damage_type & meta->receive_special_damage_type) != 0)); ((bullet->gun_meta->special_damage_type & meta->receive_special_damage_type) != 0));
} }
#endif
return false; return false;
} }
@ -744,7 +662,9 @@ void Obstacle::OnCollisionTrigger(Creature* c, OptResult& opt_result)
{ {
if (c->team_id != GetTeamId(c->room)) { if (c->team_id != GetTeamId(c->room)) {
AddObstacleBuff(c); AddObstacleBuff(c);
#if 0
Explosion(); Explosion();
#endif
Die(c->room); Die(c->room);
BroadcastFullState(c->room); BroadcastFullState(c->room);
} }
@ -858,3 +778,9 @@ bool Obstacle::CanSeeMe(Human* hum)
break; 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 long long GetDeadFrameNo(Room* room) override;
virtual void OnPreCollision(Room* room) override; virtual void OnPreCollision(Room* room) override;
virtual void OnBulletHit(Bullet* bullet) override; virtual void OnBulletHit(Bullet* bullet) override;
virtual void OnExplosionHit(Explosion* explosion) override;
virtual bool IsTerminatorAirDropBox(Room* room) { return false; } virtual bool IsTerminatorAirDropBox(Room* room) { return false; }
virtual bool CanThroughable(Creature* c); virtual bool CanThroughable(Creature* c);
virtual bool CanThroughable(Bullet* bullet); virtual bool CanThroughable(Bullet* bullet);
virtual bool DoInteraction(Human* sender); virtual bool DoInteraction(Human* sender);
virtual void OnCollisionTrigger(Creature* c, OptResult& opt_result); virtual void OnCollisionTrigger(Creature* c, OptResult& opt_result);
virtual void Explosion() {};
virtual bool CanSeeMe(Human* hum); virtual bool CanSeeMe(Human* hum);
void Explosion(Bullet* bullet);
void SetDoorInfo(Building* building, int door_id_x); void SetDoorInfo(Building* building, int door_id_x);
bool IsDoor(); bool IsDoor();
DoorState_e GetDoorState(Room* room); DoorState_e GetDoorState(Room* room);
@ -67,7 +66,6 @@ class Obstacle : public Entity
int GetMasterId(Room* room); int GetMasterId(Room* room);
void SetMasterId(Room* room, int master_id); void SetMasterId(Room* room, int master_id);
bool IsPermanent(); bool IsPermanent();
bool Attackable(Entity* sender);
bool Throughable(); bool Throughable();
bool IsTouchInteraction(); bool IsTouchInteraction();
bool IsOpenInteraction(); bool IsOpenInteraction();
@ -80,6 +78,7 @@ protected:
std::tuple<long long, a8::Vec2>* GetInteractionData(Human* sender); std::tuple<long long, a8::Vec2>* GetInteractionData(Human* sender);
void AddObstacleBuff(Creature* c); void AddObstacleBuff(Creature* c);
void ClearObstacleBuff(Creature* c); void ClearObstacleBuff(Creature* c);
bool IsHalfWallCollider();
protected: protected:
CircleCollider* self_collider_ = nullptr; CircleCollider* self_collider_ = nullptr;

View File

@ -10,6 +10,7 @@
#include "bullet.h" #include "bullet.h"
#include "mapservice.h" #include "mapservice.h"
#include "roomobstacle.h" #include "roomobstacle.h"
#include "explosion.h"
RoomObstacle::RoomObstacle():Obstacle() RoomObstacle::RoomObstacle():Obstacle()
{ {
@ -94,7 +95,7 @@ void RoomObstacle::RecalcSelfCollider()
collider->tag = collider_tag; collider->tag = collider_tag;
collider->param1 = collider_param1; collider->param1 = collider_param1;
collider->param2 = collider_param2; collider->param2 = collider_param2;
if (meta->i->attack_type() == 3) { if (IsHalfWallCollider()) {
a8::SetBitFlag(collider->tag, kHalfWallTag); a8::SetBitFlag(collider->tag, kHalfWallTag);
} }
} }
@ -163,8 +164,16 @@ void RoomObstacle::UpdateTimerFunc()
} }
} }
} }
Explosion();
Die(room); Die(room);
{
Explosion explosion;
explosion.IndifferenceAttack(
room,
GetPos(),
meta->i->damage_dia(),
meta->i->damage(),
meta->i->explosion_effect());
}
BroadcastFullState(room); BroadcastFullState(room);
if (room->xtimer.GetRunningTimer()) { if (room->xtimer.GetRunningTimer()) {
room->xtimer.DeleteTimer(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() void RoomObstacle::SpecExplosion()
{ {
++explosion_times_; ++explosion_times_;
@ -284,59 +197,14 @@ void RoomObstacle::SpecExplosion()
bomb_born_offset.Rotate(a8::RandAngle()); bomb_born_offset.Rotate(a8::RandAngle());
bomb_born_offset = bomb_born_offset * a8::RandEx(1, std::max(2, meta->i->explosion_float())); bomb_born_offset = bomb_born_offset * a8::RandEx(1, std::max(2, meta->i->explosion_float()));
a8::Vec2 bomb_pos = GetPos() + bomb_born_offset; a8::Vec2 bomb_pos = GetPos() + bomb_born_offset;
std::set<Entity*> objects; Explosion explosion;
Creature* dumy_c = nullptr; explosion.IndifferenceAttack(
room->grid_service->TraverseAllLayerHumanList room,
(
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, bomb_pos,
meta->i->damage_dia(),
meta->i->damage(),
meta->i->explosion_effect()); 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;
}
}
}
if (explosion_times_ >= meta->i->explosion_times()) { if (explosion_times_ >= meta->i->explosion_times()) {
room->xtimer.DeleteTimer(room->xtimer.GetRunningTimer()); room->xtimer.DeleteTimer(room->xtimer.GetRunningTimer());
Die(room); Die(room);

View File

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

View File

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