1
This commit is contained in:
parent
d5334732a3
commit
7ced148ff7
@ -29,6 +29,15 @@
|
|||||||
#include "mt/Hero.h"
|
#include "mt/Hero.h"
|
||||||
#include "mt/MapThing.h"
|
#include "mt/MapThing.h"
|
||||||
|
|
||||||
|
struct BulletCheckResult
|
||||||
|
{
|
||||||
|
int c_hit_num = 0;
|
||||||
|
int t_hit_num = 0;
|
||||||
|
int o_hit_num = 0;
|
||||||
|
bool eat = false;
|
||||||
|
std::set<Entity*> objects;
|
||||||
|
};
|
||||||
|
|
||||||
Bullet::Bullet():MoveableEntity()
|
Bullet::Bullet():MoveableEntity()
|
||||||
{
|
{
|
||||||
++PerfMonitor::Instance()->entity_num[ET_Bullet];
|
++PerfMonitor::Instance()->entity_num[ET_Bullet];
|
||||||
@ -253,17 +262,17 @@ void Bullet::ProcBomb()
|
|||||||
if (sender.Get() && sender.Get()->IsHuman()) {
|
if (sender.Get() && sender.Get()->IsHuman()) {
|
||||||
sender.Get()->AsHuman()->stats.IncWeaponUseTimes(gun_meta->id(), 1);
|
sender.Get()->AsHuman()->stats.IncWeaponUseTimes(gun_meta->id(), 1);
|
||||||
}
|
}
|
||||||
#if 1
|
#if 1
|
||||||
AddGunBuff();
|
AddGunBuff();
|
||||||
ProcSmokeBomb();
|
ProcSmokeBomb();
|
||||||
#else
|
#else
|
||||||
a8::Vec2 bomb_pos = GetPos();
|
a8::Vec2 bomb_pos = GetPos();
|
||||||
float time_addition = 0;
|
float time_addition = 0;
|
||||||
if (IsCurrWeapon() && sender.Get()) {
|
if (IsCurrWeapon() && sender.Get()) {
|
||||||
time_addition += sender.Get()->GetAbility()->GetAttrAbs(kHAT_WeaponExplosionContinueTime);
|
time_addition += sender.Get()->GetAbility()->GetAttrAbs(kHAT_WeaponExplosionContinueTime);
|
||||||
}
|
}
|
||||||
room->frame_event.AddSmoke(this, meta->id(), bomb_pos, time_addition);
|
room->frame_event.AddSmoke(this, meta->id(), bomb_pos, time_addition);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IS_POSION_GAS_BOMB:
|
case IS_POSION_GAS_BOMB:
|
||||||
@ -467,149 +476,13 @@ float Bullet::GetExplosionRange()
|
|||||||
|
|
||||||
void Bullet::Check(float distance)
|
void Bullet::Check(float distance)
|
||||||
{
|
{
|
||||||
int c_hit_num = 0;
|
BulletCheckResult result;
|
||||||
int t_hit_num = 0;
|
GetHitThings(result);
|
||||||
int o_hit_num = 0;
|
if (result.o_hit_num <= 0) {
|
||||||
std::set<Entity*> objects;
|
GetHitCreatures(result);
|
||||||
{
|
|
||||||
std::set<ColliderComponent*> colliders;
|
|
||||||
room->map_service->GetColliders(room, GetPos().GetX(), GetPos().GetY(), colliders);
|
|
||||||
for (ColliderComponent* collider : colliders) {
|
|
||||||
if (collider->owner->IsEntityType(ET_Dummy)) {
|
|
||||||
if (a8::HasBitFlag(collider->tag, kHalfWallTag)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (TestCollision(room, collider)) {
|
|
||||||
++o_hit_num;
|
|
||||||
objects.insert(collider->owner);
|
|
||||||
}
|
|
||||||
} else if (collider->owner->IsEntityType(ET_Obstacle)) {
|
|
||||||
Obstacle* obstacle = (Obstacle*)collider->owner;
|
|
||||||
if (gun_meta->is_penetrate_thing() &&
|
|
||||||
hit_objects_.find(obstacle->GetUniId()) != hit_objects_.end()) {
|
|
||||||
//穿物件
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!obstacle->CanThroughable(this)) {
|
|
||||||
if (TestCollision(room, collider)) {
|
|
||||||
objects.insert(collider->owner);
|
|
||||||
if (gun_meta->is_penetrate_thing()) {
|
|
||||||
++t_hit_num;
|
|
||||||
++o_hit_num;
|
|
||||||
hit_objects_.insert(collider->owner->GetUniId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (obstacle->meta->thing_type() == kObstacleStrengthenWall) {
|
|
||||||
if (!strengthened_ && sender.Get() &&
|
|
||||||
sender.Get()->team_id == obstacle->GetTeamId(room)) {
|
|
||||||
bool ret = Check2dRotationRectangle
|
|
||||||
(GetPos().x,
|
|
||||||
GetPos().y,
|
|
||||||
gun_meta->bullet_rad(),
|
|
||||||
obstacle->GetPos().x,
|
|
||||||
obstacle->GetPos().y,
|
|
||||||
obstacle->meta->width(),
|
|
||||||
obstacle->meta->height(),
|
|
||||||
obstacle->GetRotate() * 180.0f
|
|
||||||
);
|
|
||||||
if (ret) {
|
|
||||||
strengthened_ = true;
|
|
||||||
OnStrengthen(obstacle);
|
|
||||||
#ifdef DEBUG
|
|
||||||
a8::XPrintf("命中能量墙\n", {});
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool eat = false;
|
|
||||||
if (o_hit_num <= 0) {
|
|
||||||
room->grid_service->TraverseCreatures
|
|
||||||
(room->GetRoomIdx(),
|
|
||||||
GetGridList(),
|
|
||||||
[this, &objects, &c_hit_num, &eat] (Creature* c, bool& stop)
|
|
||||||
{
|
|
||||||
bool no_teammate = IsFlyHook();
|
|
||||||
if (sender.Get()->IsProperTarget(c, no_teammate)) {
|
|
||||||
if (gun_meta->ispenetrate() &&
|
|
||||||
hit_objects_.find(c->GetUniId()) != hit_objects_.end()) {
|
|
||||||
//穿人
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (c->HasBuffEffect(kBET_BulletThrough)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
Buff* hold_shield_buff = c->GetBuffByEffectId(kBET_HoldShield);
|
|
||||||
if (hold_shield_buff && !IsBomb() && !c->dead && c != sender.Get()) {
|
|
||||||
// 999
|
|
||||||
#if 0
|
|
||||||
//param2是距离 param4是宽度
|
|
||||||
a8::Vec2 shield_pos = c->GetPos() + c->GetAttackDir() * hold_shield_buff->meta->param2;
|
|
||||||
bool ret = Check2dRotationRectangle(GetPos().x,
|
|
||||||
GetPos().y,
|
|
||||||
//10,
|
|
||||||
gun_meta->bullet_rad(),
|
|
||||||
shield_pos.x,
|
|
||||||
shield_pos.y,
|
|
||||||
hold_shield_buff->meta->param4,
|
|
||||||
MetaMgr::Instance()->bullet_planck_step_length,
|
|
||||||
c->GetAttackDirRotate() * 180.0f
|
|
||||||
);
|
|
||||||
if (ret) {
|
|
||||||
float finaly_dmg = c->GetBattleContext()->CalcDmg(c, this);
|
|
||||||
c->shield_hp_ = std::max(0.0f, c->shield_hp_ - finaly_dmg);
|
|
||||||
#ifdef DEBUG
|
|
||||||
a8::XPrintf("命中盾牌 finally_dmg:%f shield_hp:%f\n",
|
|
||||||
{
|
|
||||||
finaly_dmg,
|
|
||||||
c->shield_hp_
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
room->frame_event.AddPropChg(c->GetWeakPtrRef(),
|
|
||||||
kPropShieldHp,
|
|
||||||
c->shield_max_hp_,
|
|
||||||
c->shield_hp_);
|
|
||||||
if (c->shield_hp_ <= 0) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
a8::XPrintf("shiled destory\n", {});
|
|
||||||
#endif
|
|
||||||
c->GetTrigger()->ShieldDestory();
|
|
||||||
c->RemoveBuffByUniId(hold_shield_buff->buff_uniid);
|
|
||||||
}
|
|
||||||
eat = true;
|
|
||||||
stop = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AabbCollider aabb_box;
|
|
||||||
c->GetHitAabbBox(aabb_box);
|
|
||||||
if (c != sender.Get() && !c->dead && TestCollision(room, &aabb_box)) {
|
|
||||||
if (meta->_inventory_slot() == IS_C4) {
|
|
||||||
if (!c->IsHuman()) {
|
|
||||||
objects.insert(c);
|
|
||||||
if (gun_meta->ispenetrate()) {
|
|
||||||
++c_hit_num;
|
|
||||||
hit_objects_.insert(c->GetUniId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
objects.insert(c);
|
|
||||||
if (gun_meta->ispenetrate()) {
|
|
||||||
++c_hit_num;
|
|
||||||
hit_objects_.insert(c->GetUniId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
float bullet_range = gun_meta->range();
|
float bullet_range = gun_meta->range();
|
||||||
if (!objects.empty() || (!IsBomb() && distance > bullet_range) || eat ||
|
if (!result.objects.empty() || (!IsBomb() && distance > bullet_range) || result.eat ||
|
||||||
(gun_meta->id() == 30918 && distance >= fly_distance) ||
|
(gun_meta->id() == 30918 && distance >= fly_distance) ||
|
||||||
(IsBomb() && meta->_inventory_slot() != IS_RPG && distance >= fly_distance)
|
(IsBomb() && meta->_inventory_slot() != IS_RPG && distance >= fly_distance)
|
||||||
) {
|
) {
|
||||||
@ -617,16 +490,16 @@ void Bullet::Check(float distance)
|
|||||||
ProcBomb();
|
ProcBomb();
|
||||||
} else {
|
} else {
|
||||||
bool hited = false;
|
bool hited = false;
|
||||||
if (!eat && !objects.empty()) {
|
if (!result.eat && !result.objects.empty()) {
|
||||||
hited = true;
|
hited = true;
|
||||||
OnHit(objects);
|
OnHit(result.objects);
|
||||||
}
|
}
|
||||||
bool need_remove = true;
|
bool need_remove = true;
|
||||||
if (distance < bullet_range) {
|
if (distance < bullet_range) {
|
||||||
if (!gun_meta->is_penetrate_thing() && !gun_meta->ispenetrate()) {
|
if (!gun_meta->is_penetrate_thing() && !gun_meta->ispenetrate()) {
|
||||||
} else {
|
} else {
|
||||||
if ((!gun_meta->is_penetrate_thing() && (t_hit_num > 0)) ||
|
if ((!gun_meta->is_penetrate_thing() && (result.t_hit_num > 0)) ||
|
||||||
(!gun_meta->ispenetrate() && (c_hit_num > 0))) {
|
(!gun_meta->ispenetrate() && (result.c_hit_num > 0))) {
|
||||||
} else {
|
} else {
|
||||||
need_remove = false;
|
need_remove = false;
|
||||||
}
|
}
|
||||||
@ -935,3 +808,143 @@ bool Bullet::IsFlyHook()
|
|||||||
{
|
{
|
||||||
return gun_meta->equip_subtype() == GUN_SUB_EQUIP_TYPE_FLY_HOOk;
|
return gun_meta->equip_subtype() == GUN_SUB_EQUIP_TYPE_FLY_HOOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bullet::GetHitThings(BulletCheckResult& result)
|
||||||
|
{
|
||||||
|
std::set<ColliderComponent*> colliders;
|
||||||
|
room->map_service->GetColliders(room, GetPos().GetX(), GetPos().GetY(), colliders);
|
||||||
|
for (ColliderComponent* collider : colliders) {
|
||||||
|
if (collider->owner->IsEntityType(ET_Dummy)) {
|
||||||
|
if (a8::HasBitFlag(collider->tag, kHalfWallTag)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (TestCollision(room, collider)) {
|
||||||
|
++result.o_hit_num;
|
||||||
|
result.objects.insert(collider->owner);
|
||||||
|
}
|
||||||
|
} else if (collider->owner->IsEntityType(ET_Obstacle)) {
|
||||||
|
Obstacle* obstacle = (Obstacle*)collider->owner;
|
||||||
|
if (gun_meta->is_penetrate_thing() &&
|
||||||
|
hit_objects_.find(obstacle->GetUniId()) != hit_objects_.end()) {
|
||||||
|
//穿物件
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!obstacle->CanThroughable(this)) {
|
||||||
|
if (TestCollision(room, collider)) {
|
||||||
|
result.objects.insert(collider->owner);
|
||||||
|
if (gun_meta->is_penetrate_thing()) {
|
||||||
|
++result.t_hit_num;
|
||||||
|
++result.o_hit_num;
|
||||||
|
hit_objects_.insert(collider->owner->GetUniId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (obstacle->meta->thing_type() == kObstacleStrengthenWall) {
|
||||||
|
if (!strengthened_ && sender.Get() &&
|
||||||
|
sender.Get()->team_id == obstacle->GetTeamId(room)) {
|
||||||
|
bool ret = Check2dRotationRectangle
|
||||||
|
(GetPos().x,
|
||||||
|
GetPos().y,
|
||||||
|
gun_meta->bullet_rad(),
|
||||||
|
obstacle->GetPos().x,
|
||||||
|
obstacle->GetPos().y,
|
||||||
|
obstacle->meta->width(),
|
||||||
|
obstacle->meta->height(),
|
||||||
|
obstacle->GetRotate() * 180.0f
|
||||||
|
);
|
||||||
|
if (ret) {
|
||||||
|
strengthened_ = true;
|
||||||
|
OnStrengthen(obstacle);
|
||||||
|
#ifdef DEBUG
|
||||||
|
a8::XPrintf("命中能量墙\n", {});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bullet::GetHitCreatures(BulletCheckResult& result)
|
||||||
|
{
|
||||||
|
room->grid_service->TraverseCreatures
|
||||||
|
(room->GetRoomIdx(),
|
||||||
|
GetGridList(),
|
||||||
|
[this, &result] (Creature* c, bool& stop)
|
||||||
|
{
|
||||||
|
bool no_teammate = IsFlyHook();
|
||||||
|
if (sender.Get()->IsProperTarget(c, no_teammate)) {
|
||||||
|
if (gun_meta->ispenetrate() &&
|
||||||
|
hit_objects_.find(c->GetUniId()) != hit_objects_.end()) {
|
||||||
|
//穿人
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (c->HasBuffEffect(kBET_BulletThrough)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Buff* hold_shield_buff = c->GetBuffByEffectId(kBET_HoldShield);
|
||||||
|
if (hold_shield_buff && !IsBomb() && !c->dead && c != sender.Get()) {
|
||||||
|
// 999
|
||||||
|
#if 0
|
||||||
|
//param2是距离 param4是宽度
|
||||||
|
a8::Vec2 shield_pos = c->GetPos() + c->GetAttackDir() * hold_shield_buff->meta->param2;
|
||||||
|
bool ret = Check2dRotationRectangle(GetPos().x,
|
||||||
|
GetPos().y,
|
||||||
|
//10,
|
||||||
|
gun_meta->bullet_rad(),
|
||||||
|
shield_pos.x,
|
||||||
|
shield_pos.y,
|
||||||
|
hold_shield_buff->meta->param4,
|
||||||
|
MetaMgr::Instance()->bullet_planck_step_length,
|
||||||
|
c->GetAttackDirRotate() * 180.0f
|
||||||
|
);
|
||||||
|
if (ret) {
|
||||||
|
float finaly_dmg = c->GetBattleContext()->CalcDmg(c, this);
|
||||||
|
c->shield_hp_ = std::max(0.0f, c->shield_hp_ - finaly_dmg);
|
||||||
|
#ifdef DEBUG
|
||||||
|
a8::XPrintf("命中盾牌 finally_dmg:%f shield_hp:%f\n",
|
||||||
|
{
|
||||||
|
finaly_dmg,
|
||||||
|
c->shield_hp_
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
room->frame_event.AddPropChg(c->GetWeakPtrRef(),
|
||||||
|
kPropShieldHp,
|
||||||
|
c->shield_max_hp_,
|
||||||
|
c->shield_hp_);
|
||||||
|
if (c->shield_hp_ <= 0) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
a8::XPrintf("shiled destory\n", {});
|
||||||
|
#endif
|
||||||
|
c->GetTrigger()->ShieldDestory();
|
||||||
|
c->RemoveBuffByUniId(hold_shield_buff->buff_uniid);
|
||||||
|
}
|
||||||
|
eat = true;
|
||||||
|
stop = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AabbCollider aabb_box;
|
||||||
|
c->GetHitAabbBox(aabb_box);
|
||||||
|
if (c != sender.Get() && !c->dead && TestCollision(room, &aabb_box)) {
|
||||||
|
if (meta->_inventory_slot() == IS_C4) {
|
||||||
|
if (!c->IsHuman()) {
|
||||||
|
result.objects.insert(c);
|
||||||
|
if (gun_meta->ispenetrate()) {
|
||||||
|
++result.c_hit_num;
|
||||||
|
hit_objects_.insert(c->GetUniId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.objects.insert(c);
|
||||||
|
if (gun_meta->ispenetrate()) {
|
||||||
|
++result.c_hit_num;
|
||||||
|
hit_objects_.insert(c->GetUniId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "moveableentity.h"
|
#include "moveableentity.h"
|
||||||
#include "weakptr.h"
|
#include "weakptr.h"
|
||||||
|
|
||||||
|
struct BulletCheckResult;
|
||||||
class Human;
|
class Human;
|
||||||
class Obstacle;
|
class Obstacle;
|
||||||
class Creature;
|
class Creature;
|
||||||
@ -75,6 +76,8 @@ protected:
|
|||||||
void OnKillTarget(Entity* target);
|
void OnKillTarget(Entity* target);
|
||||||
void OnStrengthen(Obstacle* ob);
|
void OnStrengthen(Obstacle* ob);
|
||||||
void ClearBuffList();
|
void ClearBuffList();
|
||||||
|
void GetHitThings(BulletCheckResult& result);
|
||||||
|
void GetHitCreatures(BulletCheckResult& result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CircleCollider* self_collider_ = nullptr;
|
CircleCollider* self_collider_ = nullptr;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user