1
This commit is contained in:
parent
1a9f70be47
commit
dab0a0d303
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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_; }
|
||||
|
@ -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;
|
||||
}
|
||||
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<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
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -536,40 +536,28 @@ 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 0
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
2
third_party/a8engine
vendored
2
third_party/a8engine
vendored
@ -1 +1 @@
|
||||
Subproject commit b16f9a6176bfac30c0e7d29ec6df37e750fd1c60
|
||||
Subproject commit 8932713766a5c0289966f08a5a0153a1ae493a9d
|
Loading…
x
Reference in New Issue
Block a user