diff --git a/server/gameserver/creature.cc b/server/gameserver/creature.cc index 26019d6..adb21be 100644 --- a/server/gameserver/creature.cc +++ b/server/gameserver/creature.cc @@ -2047,3 +2047,31 @@ void Creature::FindLocation() FindLocationWithTarget(target); } } + +bool Creature::Attackable(Room* room) +{ + if (dead) { + return false; + } + if (a8::HasBitFlag(status, CS_Disable)) { + return false; + } + if (IsInvincible()) { + return false; + } + if (HasBuffEffect(kBET_Hide)) { + return false; + } + if (HasBuffEffect(kBET_Driver)) { + return false; + } + if (HasBuffEffect(kBET_Passenger)) { + return false; + } + return true; +} + +bool Creature::ReceiveExplosionDmg(Explosion* explosion) +{ + return true; +} diff --git a/server/gameserver/creature.h b/server/gameserver/creature.h index 2dcfa67..9733280 100644 --- a/server/gameserver/creature.h +++ b/server/gameserver/creature.h @@ -84,6 +84,8 @@ class Creature : public MoveableEntity virtual void RemoveObjects(Entity* entity) {}; virtual void AddOutObjects(Entity* entity) {}; virtual void RemoveOutObjects(Entity* entity) {}; + virtual bool Attackable(Room* room) override; + virtual bool ReceiveExplosionDmg(Explosion* explosion) override; bool HasBuffEffect(int buff_effect_id); Buff* GetBuffByEffectId(int effect_id); Buff* GetBuffById(int buff_id); diff --git a/server/gameserver/entity.h b/server/gameserver/entity.h index 1494a16..e4e0d77 100644 --- a/server/gameserver/entity.h +++ b/server/gameserver/entity.h @@ -38,6 +38,8 @@ class Entity virtual void OnAddToTargetPartObject(Entity* target) {}; virtual void OnRemoveFromTargetPartObject(Entity* target) {}; virtual bool CanSeeMe(Human* hum) { return true; }; + virtual bool Attackable(Room* room) { return false; }; + virtual bool ReceiveExplosionDmg(Explosion* explosion) { return false; }; int GetUniId() const { return uniid_; } EntityType_e GetEntityType() const { return entity_type_; } EntitySubType_e GetEntitySubType() const { return entity_subtype_; } diff --git a/server/gameserver/explosion.cc b/server/gameserver/explosion.cc index 4fe45cf..0f567e8 100644 --- a/server/gameserver/explosion.cc +++ b/server/gameserver/explosion.cc @@ -1,110 +1,115 @@ #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 range, + float explosion_range, int explosion_effect, - float dmg) + float dmg, + long long special_damage_type) { -#if 0 - if (meta->i->explosion_range() <= 0) { - return; - } - std::set 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 + 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 range, + float explosion_range, int explosion_effect, - float dmg) + float dmg, + long long special_damage_type) { - #if 0 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(); +} - if (follow_target.Get()) { - bomb_pos = follow_target.Get()->GetPos(); +void Explosion::InternalAttack() +{ + if (explosion_range_ <= 0) { + return; } - room->frame_event.AddExplosionEx(sender, - meta->i->id(), - bomb_pos, - gun_meta->i->explosion_effect()); + sender_.Get()->room->frame_event.AddExplosionEx + (sender_, + 0, + center_, + explosion_effect_); std::set grid_list; - sender.Get()->room->grid_service->GetAllCellsByXy + sender_.Get()->room->grid_service->GetAllCellsByXy ( - sender.Get()->room, - bomb_pos.x, - bomb_pos.y, + room_, + center_.x, + center_.y, grid_list ); - std::set objects; - sender.Get()->room->grid_service->TraverseCreatures + std::set objects; + room_->grid_service->TraverseCreatures ( - sender.Get()->room->GetRoomIdx(), + 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()) { + 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); } } } ); - std::set entitys; - sender.Get()->room->grid_service->TraverseAllLayerEntityList + room_->grid_service->TraverseAllLayerEntityList ( - sender.Get()->room->GetRoomIdx(), + room_->GetRoomIdx(), grid_list, - [this, &entitys] (Entity* entity, bool& stop) + [this, &objects] (Entity* entity, bool& stop) { + if (!entity->Attackable(room_)) { + return; + } + if (!entity->ReceiveExplosionDmg(this)) { + return; + } + if (center_.Distance(entity->GetPos()) < explosion_range_) { + objects.insert(entity); + } } ); - - Explosion explosion; for (auto& target : objects) { - target->OnExplosionHit(&explosion); + target->OnExplosionHit(this); } - - for (auto& target : entitys) { - target->OnExplosionHit(&explosion); - } - #endif } diff --git a/server/gameserver/explosion.h b/server/gameserver/explosion.h index 414697e..92b3966 100644 --- a/server/gameserver/explosion.h +++ b/server/gameserver/explosion.h @@ -6,14 +6,34 @@ class Room; class Explosion { public: + + Room* GetRoom() { return room_; }; + CreatureWeakPtr GetSender() { return sender_; }; + float GetDmg() { return dmg_; }; + long long GetSpecialDamageType() { return special_damage_type_; }; + void IndifferenceAttack(Room* room, const a8::Vec2& center, - float range, + float explosion_range, int explosion_effect, - float dmg); + float dmg, + long long special_damage_type = 0); void EnemyAndObstacleAttack(CreatureWeakPtr& sender, const a8::Vec2& center, - float range, + float explosion_range, int explosion_effect, - float dmg); + float dmg, + long long special_damage_type = 0); + private: + void InternalAttack(); + + private: + int type_ = 0; + Room* room_ = nullptr; + CreatureWeakPtr sender_; + float explosion_range_ = 0; + int explosion_effect_ = 0; + float dmg_ = 0; + a8::Vec2 center_; + long long special_damage_type_ = 0; }; diff --git a/server/gameserver/obstacle.cc b/server/gameserver/obstacle.cc index 6297a3e..0543db4 100644 --- a/server/gameserver/obstacle.cc +++ b/server/gameserver/obstacle.cc @@ -536,40 +536,28 @@ void Obstacle::OnBulletHit(Bullet* bullet) void Obstacle::OnExplosionHit(Explosion* e) { + if (meta->i->explosion_hit() == kExplosionHitEatDmg) { + return; + } + float dmg = e->GetDmg(); + float def = 0; + float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K); + SetHealth(e->GetRoom(), std::max(0.0f, GetHealth(e->GetRoom()) - finaly_dmg)); + if (GetHealth(e->GetRoom()) <= 0.01f) { + Die(e->GetRoom()); + } + if (IsDead(e->GetRoom())) { + if (meta->i->damage_dia() > 0.01f && + meta->i->damage() > 0.01f) { #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); - } + obstacle->Explosion(this); #endif + } + #if 0 + sender.Get()->DropItems(obstacle); + #endif + } + BroadcastFullState(e->GetRoom()); } bool Obstacle::CanThroughable(Creature* c) @@ -784,3 +772,46 @@ bool Obstacle::IsHalfWallCollider() return meta->i->collision_hit() == kCollisionHitPass && meta->i->bullet_hit() != kBulletHitPass; } + +bool Obstacle::Attackable(Room* room) +{ + if (IsDead(room)) { + return false; + } + return true; +} + +bool Obstacle::ReceiveExplosionDmg(Explosion* explosion) +{ + switch (meta->i->explosion_hit()) { + case kExplosionHitPass: + { + return false; + } + break; + case kExplosionHitAnyDmg: + { + return true; + } + break; + case kExplosionHitOnlySpecDmg: + { + if (meta->receive_special_damage_type == 0) { + return true; + } + return (meta->receive_special_damage_type & explosion->GetSpecialDamageType()) != 0; + } + break; + case kExplosionHitEatDmg: + { + return false; + } + break; + default: + { + return false; + } + break; + } + return false; +} diff --git a/server/gameserver/obstacle.h b/server/gameserver/obstacle.h index 2f4288a..c5474f2 100644 --- a/server/gameserver/obstacle.h +++ b/server/gameserver/obstacle.h @@ -43,12 +43,14 @@ class Obstacle : public Entity virtual void OnPreCollision(Room* room) override; virtual void OnBulletHit(Bullet* bullet) override; virtual void OnExplosionHit(Explosion* explosion) override; + virtual bool Attackable(Room* room) 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 bool CanSeeMe(Human* hum); + virtual bool ReceiveExplosionDmg(Explosion* explosion) override; void SetDoorInfo(Building* building, int door_id_x); bool IsDoor(); DoorState_e GetDoorState(Room* room); diff --git a/third_party/a8engine b/third_party/a8engine index b16f9a6..8932713 160000 --- a/third_party/a8engine +++ b/third_party/a8engine @@ -1 +1 @@ -Subproject commit b16f9a6176bfac30c0e7d29ec6df37e750fd1c60 +Subproject commit 8932713766a5c0289966f08a5a0153a1ae493a9d