This commit is contained in:
aozhiwei 2021-06-22 09:40:19 +00:00
parent 1a9f70be47
commit dab0a0d303
8 changed files with 197 additions and 107 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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_; }

View File

@ -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<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
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;
}
if (follow_target.Get()) {
bomb_pos = follow_target.Get()->GetPos();
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();
}
room->frame_event.AddExplosionEx(sender,
meta->i->id(),
bomb_pos,
gun_meta->i->explosion_effect());
void Explosion::InternalAttack()
{
if (explosion_range_ <= 0) {
return;
}
sender_.Get()->room->frame_event.AddExplosionEx
(sender_,
0,
center_,
explosion_effect_);
std::set<GridCell*> 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<Creature*> objects;
sender.Get()->room->grid_service->TraverseCreatures
std::set<Entity*> 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<Entity*> 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
}

View File

@ -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;
};

View File

@ -536,41 +536,29 @@ void Obstacle::OnBulletHit(Bullet* bullet)
void Obstacle::OnExplosionHit(Explosion* e)
{
#if 0
if (!target->IsEntityType(Obstacle)) {
continue;
if (meta->i->explosion_hit() == kExplosionHitEatDmg) {
return;
}
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 dmg = e->GetDmg();
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);
SetHealth(e->GetRoom(), std::max(0.0f, GetHealth(e->GetRoom()) - finaly_dmg));
if (GetHealth(e->GetRoom()) <= 0.01f) {
Die(e->GetRoom());
}
if (obstacle->IsDead(room)) {
if (obstacle->meta->i->damage_dia() > 0.01f &&
obstacle->meta->i->damage() > 0.01f) {
if (IsDead(e->GetRoom())) {
if (meta->i->damage_dia() > 0.01f &&
meta->i->damage() > 0.01f) {
#if 0
obstacle->Explosion(this);
#endif
}
#if 0
sender.Get()->DropItems(obstacle);
}
obstacle->BroadcastFullState(room);
}
#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;
}

View File

@ -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);

@ -1 +1 @@
Subproject commit b16f9a6176bfac30c0e7d29ec6df37e750fd1c60
Subproject commit 8932713766a5c0289966f08a5a0153a1ae493a9d