diff --git a/server/gameserver/virtualbullet.cc b/server/gameserver/virtualbullet.cc index 74570210..27a90887 100644 --- a/server/gameserver/virtualbullet.cc +++ b/server/gameserver/virtualbullet.cc @@ -1,5 +1,12 @@ #include "precompile.h" + #include "virtualbullet.h" +#include "metamgr.h" +#include "room.h" +#include "mapservice.h" +#include "gridservice.h" +#include "creature.h" +#include "collider.h" float VirtualBullet::GetStrengthenWall() { @@ -53,10 +60,218 @@ Room* VirtualBullet::GetRoom() void VirtualBullet::Update(int delta_time) { - + if (sender.Get()) { + float move_length = gun_meta->i->bullet_speed() / (float)SERVER_FRAME_RATE; + do { + float step_len = move_length - MetaMgr::Instance()->bullet_planck_step_length; + if (step_len <= 0.001f) { + if (move_length > 0.1f) { + step_len = move_length; + } else { + break; + } + } + move_length -= step_len; + SetPos(GetPos() + dir * step_len); + float distance = (GetPos() - born_pos).Norm(); + if (room->OverBorder(GetPos(), gun_meta->i->bullet_rad())) { + Check(distance); + if (!later_removed_) { + ForceRemove(); + } + } else { + #if 0 + room->grid_service->MoveBullet(this); + #endif + Check(distance); + } + } while(!later_removed_ && move_length >= 0.0001f); + } } bool VirtualBullet::IsDone() { return false; } + +void VirtualBullet::Check(float distance) +{ + int c_hit_num = 0; + int t_hit_num = 0; + int o_hit_num = 0; + std::set objects; + { + std::set colliders; + room->map_service->GetColliders(room, GetPos().x, GetPos().y, colliders); + #if 0 + 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->i->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->i->is_penetrate_thing()) { + ++t_hit_num; + ++o_hit_num; + hit_objects_.insert(collider->owner->GetUniId()); + } + } + } else if (obstacle->meta->i->thing_type() == kObstacleStrengthenWall) { + if (!strengthened_ && sender.Get() && + sender.Get()->team_id == obstacle->GetTeamId(room)) { + bool ret = Check2dRotationRectangle + (GetPos().x, + GetPos().y, + gun_meta->i->bullet_rad(), + obstacle->GetPos().x, + obstacle->GetPos().y, + obstacle->meta->i->width(), + obstacle->meta->i->height(), + obstacle->GetRotate() * 180.0f + ); + if (ret) { + strengthened_ = true; + OnStrengthen(obstacle); +#ifdef DEBUG + a8::XPrintf("命中能量墙\n", {}); +#endif + } + } + } + } + } + #endif + } + bool eat = false; + if (o_hit_num <= 0) { + #if 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->i->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()) { + //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->i->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; + } + } + } + AabbCollider aabb_box; + c->GetHitAabbBox(aabb_box); + if (c != sender.Get() && !c->dead && TestCollision(room, &aabb_box)) { + if (meta->i->_inventory_slot() == IS_C4) { + if (!c->IsHuman()) { + objects.insert(c); + if (gun_meta->i->ispenetrate()) { + ++c_hit_num; + hit_objects_.insert(c->GetUniId()); + } + } + } else { + objects.insert(c); + if (gun_meta->i->ispenetrate()) { + ++c_hit_num; + hit_objects_.insert(c->GetUniId()); + } + } + } + } + }); + #endif + } + float bullet_range = gun_meta->i->range(); + if (!objects.empty() || (!IsBomb() && distance > bullet_range) + ) { + if (IsBomb()) { + } else { + bool hited = false; + if (!eat && !objects.empty()) { + hited = true; + OnHit(objects); + } + bool need_remove = true; + if (distance < bullet_range) { + if (!gun_meta->i->is_penetrate_thing() && !gun_meta->i->ispenetrate()) { + } else { + if ((!gun_meta->i->is_penetrate_thing() && (t_hit_num > 0)) || + (!gun_meta->i->ispenetrate() && (c_hit_num > 0))) { + } else { + need_remove = false; + } + } + } + if (need_remove) { + ForceRemove(); + } + } + } +} + +void VirtualBullet::ForceRemove() +{ + +} + +void VirtualBullet::OnHit(std::set& objects) +{ + +} diff --git a/server/gameserver/virtualbullet.h b/server/gameserver/virtualbullet.h index c627ac4d..bb9a9983 100644 --- a/server/gameserver/virtualbullet.h +++ b/server/gameserver/virtualbullet.h @@ -36,4 +36,16 @@ class VirtualBullet : public IBullet, public ITask virtual void Update(int delta_time) override; virtual bool IsDone() override; + void SetPos(a8::Vec2 pos) { pos_ = pos; }; + a8::Vec2 GetPos() { return pos_; }; + + private: + void Check(float distance); + void ForceRemove(); + void OnHit(std::set& objects); + + private: + bool later_removed_ = false; + a8::Vec2 pos_; + };