diff --git a/server/gameserver/buff.cc b/server/gameserver/buff.cc index 037395e..ba69330 100644 --- a/server/gameserver/buff.cc +++ b/server/gameserver/buff.cc @@ -78,7 +78,9 @@ void Buff::ProcIntervalAddBuff() void Buff::ProcBatchAddBuff() { std::shared_ptr old_context_ability = owner->context_ability; + a8::Vec2 old_context_dir = owner->context_dir; a8::Vec2 old_context_pos = owner->context_pos; + owner->context_dir = owner->GetAttackDir(); owner->context_pos = owner->GetPos(); for (auto& tuple : meta->batch_add_list) { @@ -112,6 +114,7 @@ void Buff::ProcBatchAddBuff() } } + owner->context_dir = old_context_dir; owner->context_pos = old_context_pos; owner->context_ability = old_context_ability; } @@ -128,7 +131,9 @@ void Buff::InternalTimerAddBuff() SkillCasterState* caster_state = (SkillCasterState*)param.param1.GetUserData(); if (caster_state->caster.Get()) { std::shared_ptr old_context_ability = receiver->context_ability; + a8::Vec2 old_context_dir = receiver->context_dir; a8::Vec2 old_context_pos = receiver->context_pos; + receiver->context_dir = receiver->GetAttackDir(); receiver->context_pos = receiver->GetPos(); int buff_id = param.param2; @@ -142,6 +147,7 @@ void Buff::InternalTimerAddBuff() caster_state->caster.Get()->RecoverSkillCasterState(&old_caster_state); } + receiver->context_dir = old_context_dir; receiver->context_pos = old_context_pos; receiver->context_ability = old_context_ability; } @@ -458,20 +464,60 @@ void Buff::ProcTurnOver() a8::Vec2 old_pos = owner->GetPos(); float distance = owner->HasBuffEffect(kBET_Car) ? phase->param1.GetDouble() * 1.5 : phase->param1.GetDouble(); - if (meta->int_param1 == 1) { - //穿墙 - } else { - owner->_UpdateMove(distance); + owner->_UpdateMove(distance); + int moved_distance = (int)owner->GetPos().Distance(old_pos); + moved_distance = std::min(moved_distance, 200); + if (!meta->param1_int_list.empty() && moved_distance > 2) { + std::set target_list; + owner->TraverseCreatures + ( + [this, &target_list] (Creature* c, bool& stop) + { + if (owner->IsProperTarget(c) && owner->GetPos().Distance(c->GetPos()) < 300) { + target_list.insert(c); + } + }); + + a8::Vec2 curr_pos = owner->GetPos(); + a8::Vec2 dir = owner->GetPos() - old_pos; + dir.Normalize(); + for (int i = 5; i < moved_distance; i += 5) { + owner->SetPos(old_pos + dir * i); + std::list hit_objects; + for (auto& target : target_list) { + if (owner->TestCollision(owner->room, target)) { + hit_objects.push_back(target); + } + } + for (auto& target : hit_objects) { + target_list.erase(target); + target->room->xtimer.AddDeadLineTimerAndAttach + ( + meta->int_param4 / FRAME_RATE_MS * (i / moved_distance), + a8::XParams() + .SetSender(target) + .SetParam1(meta) + .SetParam2(owner->GetUniId()), + [] (const a8::XParams& param) + { + Creature* c = (Creature*)param.sender.GetUserData(); + MetaData::Buff* buff_meta = (MetaData::Buff*)param.param1.GetUserData(); + Entity* caster = c->room->GetEntityByUniId(param.param2); + if (caster && caster->IsCreature(c->room)) { + for (int buff_id : buff_meta->param1_int_list) { + c->TryAddBuff((Creature*)caster, buff_id); + } + } + }, + &target->xtimer_attacher.timer_list_); + } + } + owner->SetPos(curr_pos); } if (!meta->param2_int_list.empty()) { - int time = 0; - float moved_distance = owner->GetPos().Distance(old_pos); - if (std::abs(moved_distance) > 0.01f) { - time = ((moved_distance / distance) * meta->param3) / FRAME_RATE_MS; - } owner->room->xtimer.AddDeadLineTimerAndAttach ( - time, + meta->int_param4 / FRAME_RATE_MS, a8::XParams() .SetSender(owner) .SetParam1(meta), @@ -479,9 +525,16 @@ void Buff::ProcTurnOver() { Creature* c = (Creature*)param.sender.GetUserData(); MetaData::Buff* buff_meta = (MetaData::Buff*)param.param1.GetUserData(); - for (int buff_id : buff_meta->param2_int_list) { - c->TryAddBuff(c, buff_id); - } + c->TraverseCreatures + ( + [c, buff_meta] (Creature* target, bool& stop) + { + if (c->GetPos().Distance(target->GetPos()) < buff_meta->int_param3) { + for (int buff_id : buff_meta->param2_int_list) { + target->TryAddBuffWithTarget(c, buff_id); + } + } + }); }, &owner->xtimer_attacher.timer_list_ ); @@ -529,3 +582,74 @@ void Buff::ProcOnceChgAttr() { } + +void Buff::ProcAutoShot() +{ + owner->room->xtimer.AddRepeatTimerAndAttach + ( + 1, + a8::XParams() + .SetSender(this), + [] (const a8::XParams& param) + { + Buff* buff = (Buff*)param.sender.GetUserData(); + if (buff->owner->IsHuman()) { + #if 0 + buff->owner->AsHuman()->shot_start = true; + #endif + buff->owner->AsHuman()->shot_hold = true; + buff->owner->AsHuman()->series_shot_frames = 0; + } + }, + &xtimer_attacher.timer_list_, + [] (const a8::XParams& param) + { + Buff* buff = (Buff*)param.sender.GetUserData(); + if (buff->owner->IsHuman()) { + #if 0 + buff->owner->AsHuman()->shot_start = false; + #endif + buff->owner->AsHuman()->shot_hold = false; + buff->owner->AsHuman()->series_shot_frames = 0; + } + }); +} + +void Buff::ProcBeatBack() +{ + if (caster_.Get()) { + if (std::abs(caster_.Get()->context_dir.x) > FLT_EPSILON || + std::abs(caster_.Get()->context_dir.x) > FLT_EPSILON) { + if (std::abs(meta->int_param1) > 0) { + a8::Vec2 old_move_dir = owner->GetMoveDir(); + owner->SetMoveDir(caster_.Get()->context_dir); + owner->_UpdateMove(meta->param1); + owner->SetMoveDir(old_move_dir); + } + } + } +} + +void Buff::ProcDisperse() +{ + std::vector del_buffs; + owner->TraverseBuff + ( + [this, &del_buffs] (Buff* buff, bool& stop) + { + for (int tag : meta->param1_int_set) { + if (buff->meta->tags.find(tag) != buff->meta->tags.end()) { + del_buffs.push_back(buff->buff_uniid); + break; + } + } + }); + for (int buff_uniid : del_buffs) { + owner->RemoveBuffByUniId(buff_uniid); + } +} + +void Buff::ProcAISeting() +{ + +} diff --git a/server/gameserver/buff.h b/server/gameserver/buff.h index 0f5cac0..99e5dcf 100644 --- a/server/gameserver/buff.h +++ b/server/gameserver/buff.h @@ -69,6 +69,10 @@ class Buff void ProcSeletTargetWithSelfPos(); void ProcTurnOver(); void ProcPullToWalkable(); + void ProcAutoShot(); + void ProcBeatBack(); + void ProcDisperse(); + void ProcAISeting(); private: void InternalTimerAddBuff(); diff --git a/server/gameserver/bullet.cc b/server/gameserver/bullet.cc index dde4f86..d34b722 100644 --- a/server/gameserver/bullet.cc +++ b/server/gameserver/bullet.cc @@ -54,9 +54,19 @@ void Bullet::RecalcSelfCollider() void Bullet::OnHit(std::set& objects) { + std::shared_ptr old_context_ability = sender.Get()->context_ability; + a8::Vec2 old_context_dir = sender.Get()->context_dir; + a8::Vec2 old_context_pos = sender.Get()->context_pos; + sender.Get()->context_dir = dir; + sender.Get()->context_pos = GetPos(); + for (auto& target : objects) { target->OnBulletHit(this); } + + sender.Get()->context_dir = old_context_dir; + sender.Get()->context_pos = old_context_pos; + sender.Get()->context_ability = old_context_ability; } void Bullet::ProcBomb() @@ -357,6 +367,9 @@ void Bullet::Check(float distance) //穿人 return; } + if (c->HasBuffEffect(kBET_BulletThrough)) { + return; + } AabbCollider aabb_box; c->GetHitAabbBox(aabb_box); if (c != sender.Get() && !c->dead && TestCollision(room, &aabb_box)) { @@ -528,7 +541,9 @@ void Bullet::AddGunBuff() { if (sender.Get()) { std::shared_ptr old_context_ability = sender.Get()->context_ability; + a8::Vec2 old_context_dir = sender.Get()->context_dir; a8::Vec2 old_context_pos = sender.Get()->context_pos; + sender.Get()->context_dir = dir; sender.Get()->context_pos = GetPos(); if (IsCurrWeapon()) { sender.Get()->context_ability = ability_; @@ -542,6 +557,7 @@ void Bullet::AddGunBuff() 1 ); } + sender.Get()->context_dir = old_context_dir; sender.Get()->context_pos = old_context_pos; sender.Get()->context_ability = old_context_ability; } diff --git a/server/gameserver/car.cc b/server/gameserver/car.cc index faa46dc..11e7e2a 100644 --- a/server/gameserver/car.cc +++ b/server/gameserver/car.cc @@ -275,6 +275,9 @@ void Car::OnBulletHit(Bullet* bullet) GetAbility()->GetAttrAbs(kHAT_Def); float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K); finaly_dmg = std::max(finaly_dmg, 0.0f); + if (bullet->meta->buff_meta) { + MustBeAddBuff(bullet->sender.Get(), bullet->meta->i->buffid()); + } DecHP(finaly_dmg, bullet->sender.Get()->GetUniId(), bullet->sender.Get()->GetName(), diff --git a/server/gameserver/constant.h b/server/gameserver/constant.h index 62b8e04..ab74d22 100644 --- a/server/gameserver/constant.h +++ b/server/gameserver/constant.h @@ -359,6 +359,7 @@ enum ObstacleType_e kObstacleGully = 7, kObstacleAirDropBox = 8, kObstacleOilBucket = 9, + kObstacleKeepRangeBuff = 10, }; enum BulletHit_e diff --git a/server/gameserver/constant_export.h b/server/gameserver/constant_export.h index 24beb56..5914235 100644 --- a/server/gameserver/constant_export.h +++ b/server/gameserver/constant_export.h @@ -67,6 +67,7 @@ enum BuffEffectType_e kBET_Rescue = 45, //救援 kBET_AddCarBuff = 46, //给载具加buff kBET_RemoveCarBuff = 47, //移除载具身上的buff + kBET_BulletThrough = 48, //穿透 kBET_FollowMaster = 49, //跟随主人 kBET_ThroughWall = 50, //穿墙 @@ -85,6 +86,10 @@ enum BuffEffectType_e kBET_MountainTop = 63, //在山顶 kBET_UseSkill = 64, //使用技能 kBET_CamouflageAddition = 65, //对抗伪装 + kBET_AutoShot = 66, //自动射击 + kBET_BeatBack = 67, //击退 + kBET_Disperse = 68, //驱散 + kBET_AiSeting = 69, //设置ai参数 kBET_End }; diff --git a/server/gameserver/creature.cc b/server/gameserver/creature.cc index c7f12fd..8f31105 100644 --- a/server/gameserver/creature.cc +++ b/server/gameserver/creature.cc @@ -102,7 +102,9 @@ void InternalShot(Creature* c, { if (weapon_meta->i->_inventory_slot() == IS_TRAP || weapon_meta->i->_inventory_slot() == IS_MINE) { + a8::Vec2 old_context_dir = c->context_dir; a8::Vec2 old_context_pos = c->context_pos; + c->context_dir =c->GetAttackDir(); c->context_pos = c->GetPos() + c->GetAttackDir() * fly_distance; MetaData::Buff * buff_meta = MetaMgr::Instance()->GetBuff(bullet_meta->i->buffid()); if (buff_meta) { @@ -111,6 +113,7 @@ void InternalShot(Creature* c, 1 ); } + c->context_dir = old_context_dir; c->context_pos = old_context_pos; return; } @@ -363,7 +366,6 @@ int Creature::AddBuff(Creature* caster, } } } - return new_buff_uniid; #ifdef DEBUG SendDebugMsg(a8::Format("添加buff_id:%d effect:%d %s params:%d,%d,%d,%d,%d", { @@ -377,6 +379,7 @@ int Creature::AddBuff(Creature* caster, buff_meta->int_param5, })); #endif + return new_buff_uniid; } bool Creature::IsImmuneBuffEffect(int buff_effect) @@ -407,12 +410,60 @@ int Creature::TryAddBuff(Creature* caster, int buff_id) return -1; } +int Creature::TryAddBuffWithTarget(Creature* caster, int buff_id) +{ + MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(buff_id); + if (buff_meta) { + bool be_add = false; + switch (buff_meta->i->buff_target()) { + case kBuffTargetSelf: + { + be_add = caster == this; + } + break; + case kBuffTargetFriendly: + { + team_id == caster->team_id; + } + break; + case kBuffTargetEnemy: + { + team_id != caster->team_id; + } + break; + default: + { + } + break; + } + return TryAddBuff(caster, buff_id); + } + return -1; +} + void Creature::RemoveBuffById(int buff_id) { - std::vector> removed_buffs; + int buff_uniid = 0; for (auto itr = buff_list_.begin(); itr != buff_list_.end(); ++itr) { Buff& buff = *itr; if (buff.meta->i->buff_id() == buff_id) { + buff_uniid = buff.buff_uniid; + break; + } + } + if (buff_uniid != 0) { + RemoveBuffByUniId(buff_uniid); + } +} + +void Creature::RemoveBuffByUniId(int buff_uniid) +{ + int buff_id = 0; + std::vector> removed_buffs; + for (auto itr = buff_list_.begin(); itr != buff_list_.end(); ++itr) { + Buff& buff = *itr; + if (buff.buff_uniid == buff_uniid) { + buff_id = buff.meta->i->buff_id(); removed_buffs.push_back(std::make_tuple(buff.meta, buff.GetCaster().Get())); OnBuffRemove(buff); buff.UnInit(); @@ -472,7 +523,7 @@ void Creature::RemoveBuffById(int buff_id) SendDebugMsg(a8::Format("移除buff_id:%d", { buff_id - })); + })); #endif } @@ -730,6 +781,7 @@ void Creature::DoSkill(int skill_id, skill_distance_ = skill_distance; curr_skill_ = skill; playing_skill = true; + context_dir = skill_dir_; context_pos = GetPos() + skill_dir_ * skill_distance_; CurrentSkill()->last_use_frameno = room->GetFrameNo(); if (CurrentSkill()->meta->i->skill_target() == kST_Self @@ -912,6 +964,7 @@ Skill* Creature::CurrentSkill() void Creature::ProcBuffEffect(Creature* caster, Buff* buff) { + MetaData::Buff* buff_meta = buff->meta; switch (buff->meta->i->buff_effect()) { case kBET_ChgAttr: case kBET_Car: @@ -1209,6 +1262,26 @@ void Creature::ProcBuffEffect(Creature* caster, Buff* buff) } } break; + case kBET_AutoShot: + { + buff->ProcAutoShot(); + } + break; + case kBET_BeatBack: + { + buff->ProcBeatBack(); + } + break; + case kBET_Disperse: + { + buff->ProcDisperse(); + } + break; + case kBET_AiSeting: + { + buff->ProcAISeting(); + } + break; default: { } @@ -1830,6 +1903,9 @@ void Creature::SummonObstacle(Buff* buff, int id, const a8::Vec2& pos) obstacle->Active(); obstacle->context_ability = context_ability; slave_things_.push_back(std::make_tuple(buff->meta->i->buff_id(), obstacle)); +#ifdef DEBUG + SendDebugMsg(a8::Format("召唤物件 buff_id:%d thing_id:%d", {buff->meta->i->buff_id(), id})); +#endif } else { abort(); } @@ -2418,3 +2494,14 @@ void Creature::ProcOnceChgAttrBuff(MetaData::Buff* buff_meta) break; } } + +void Creature::TraverseBuff(std::function func) +{ + bool stop = false; + for (auto& buff : buff_list_) { + func(&buff, stop); + if (stop) { + return; + } + } +} diff --git a/server/gameserver/creature.h b/server/gameserver/creature.h index 50046ae..0ff67ab 100644 --- a/server/gameserver/creature.h +++ b/server/gameserver/creature.h @@ -69,6 +69,7 @@ class Creature : public MoveableEntity Weapon second_weapon; a8::Vec2 context_pos; + a8::Vec2 context_dir; std::shared_ptr context_ability; bool need_sync_active_player = false; @@ -89,6 +90,7 @@ class Creature : public MoveableEntity virtual void RemoveOutObjects(Entity* entity) {}; virtual bool Attackable(Room* room) override; virtual bool ReceiveExplosionDmg(Explosion* explosion) override; + virtual bool IsCreature(Room* room) override { return true;}; bool HasBuffEffect(int buff_effect_id); Buff* GetBuffByEffectId(int effect_id); Buff* GetBuffById(int buff_id); @@ -101,7 +103,9 @@ class Creature : public MoveableEntity bool IsImmuneBuffEffect(int buff_effect); int MustBeAddBuff(Creature* caster, int buff_id); int TryAddBuff(Creature* caster, int buff_id); + int TryAddBuffWithTarget(Creature* caster, int buff_id); void RemoveBuffById(int buff_id); + void RemoveBuffByUniId(int buff_uniid); void ClearBuffById(int buff_id); void RecalcBuffAttr(); void RemoveBuffByEffectId(int buff_effect_id); @@ -206,6 +210,7 @@ class Creature : public MoveableEntity Trigger* GetTrigger() { return trigger_; }; std::shared_ptr& GetAbility() { return ability_; }; void RefreshHP(); + void TraverseBuff(std::function func); protected: diff --git a/server/gameserver/dummyentity.cc b/server/gameserver/dummyentity.cc index 11bc9fc..a4be227 100644 --- a/server/gameserver/dummyentity.cc +++ b/server/gameserver/dummyentity.cc @@ -14,6 +14,19 @@ void DummyEntity::Initialize() for (auto& obj : *blocks) { switch (obj.shape()) { case 1: + { + CircleCollider* collider = new CircleCollider(); + collider->owner = this; + collider->pos = a8::Vec2(obj.x(), obj.y()); + collider->rad = obj.rad(); + if (obj.bullet_penetrate()) { + a8::SetBitFlag(collider->tag, kHalfWallTag); + } + AddEntityCollider(collider); + permanent_map_service->AddCollider(collider); + } + break; + case 2: { AabbCollider* collider = new AabbCollider(); collider->owner = this; @@ -21,21 +34,14 @@ void DummyEntity::Initialize() obj.y() - obj.height()/2.0); collider->_max = a8::Vec2(obj.x() + obj.width()/2.0, obj.y() + obj.height()/2.0); + if (obj.bullet_penetrate()) { + a8::SetBitFlag(collider->tag, kHalfWallTag); + } AddEntityCollider(collider); collider_list.push_back(collider); permanent_map_service->AddCollider(collider); } break; - case 2: - { - CircleCollider* collider = new CircleCollider(); - collider->owner = this; - collider->pos = a8::Vec2(obj.x(), obj.y()); - collider->rad = obj.rad(); - AddEntityCollider(collider); - permanent_map_service->AddCollider(collider); - } - break; default: { } diff --git a/server/gameserver/entity.h b/server/gameserver/entity.h index 2b16784..afcc601 100644 --- a/server/gameserver/entity.h +++ b/server/gameserver/entity.h @@ -30,6 +30,7 @@ class Entity virtual float GetHitRadius() { return GetRadius();}; virtual void GetCircleBox(CircleCollider& circle_box); virtual bool IsDead(Room* room) { return false;}; + virtual bool IsCreature(Room* room) { return false;}; virtual long long GetDeadFrameNo(Room* room) { return 0;}; virtual void OnPreCollision(Room* room) {}; virtual void RecalcSelfCollider() {}; diff --git a/server/gameserver/explosion.cc b/server/gameserver/explosion.cc index 68b16e5..7f181c0 100644 --- a/server/gameserver/explosion.cc +++ b/server/gameserver/explosion.cc @@ -116,6 +116,9 @@ void Explosion::InternalAttack() } ); for (auto& target : objects) { + if (target->IsCreature(room_) && ((Creature*)target)->HasBuffEffect(kBET_BulletThrough)) { + continue; + } target->OnExplosionHit(this); } } diff --git a/server/gameserver/hero.cc b/server/gameserver/hero.cc index 8c0ce10..418b2c1 100644 --- a/server/gameserver/hero.cc +++ b/server/gameserver/hero.cc @@ -91,7 +91,7 @@ void Hero::OnBulletHit(Bullet* bullet) sender->stats.damage_amount_out += finaly_dmg; #endif if (bullet->meta->buff_meta) { - MustBeAddBuff(this, bullet->meta->i->buffid()); + MustBeAddBuff(bullet->sender.Get(), bullet->meta->i->buffid()); } DecHP(finaly_dmg, bullet->sender.Get()->GetUniId(), diff --git a/server/gameserver/human.cc b/server/gameserver/human.cc index d72562b..f1b1176 100644 --- a/server/gameserver/human.cc +++ b/server/gameserver/human.cc @@ -1141,6 +1141,7 @@ void Human::RefreshView() case ET_Building: case ET_Obstacle: case ET_Loot: + case ET_MapBlock: { AddToNewObjects(entity); } @@ -2715,6 +2716,7 @@ void Human::GetViewObjects(std::set& view_objects) case ET_Building: case ET_Obstacle: case ET_Loot: + case ET_MapBlock: { view_objects.insert(entity); } @@ -2799,6 +2801,7 @@ void Human::ProcIncGridList(std::set& old_grids, case ET_Building: case ET_Obstacle: case ET_Loot: + case ET_MapBlock: { AddToNewObjects(entity); RemoveOutObjects(entity); @@ -2847,6 +2850,7 @@ void Human::ProcDecGridList(std::set& old_grids, case ET_Building: case ET_Obstacle: case ET_Loot: + case ET_MapBlock: { AddOutObjects(entity); } @@ -3541,7 +3545,7 @@ void Human::OnBulletHit(Bullet* bullet) sender->stats.damage_amount_out += finaly_dmg; #endif if (bullet->meta->buff_meta) { - MustBeAddBuff(this, bullet->meta->i->buffid()); + MustBeAddBuff(bullet->sender.Get(), bullet->meta->i->buffid()); } if (bullet->sender.Get() && bullet->sender.Get()->IsCar() && bullet->passenger.Get()) { DecHP(finaly_dmg, diff --git a/server/gameserver/mapblock.cc b/server/gameserver/mapblock.cc index bfa9ead..90ae1a9 100644 --- a/server/gameserver/mapblock.cc +++ b/server/gameserver/mapblock.cc @@ -1,6 +1,10 @@ #include "precompile.h" #include "mapblock.h" +#include "collider.h" +#include "cs_proto.pb.h" +#include "typeconvert.h" +#include "metamgr.h" MapBlock::MapBlock() { @@ -24,22 +28,67 @@ void MapBlock::RecalcSelfCollider() void MapBlock::FillMFObjectPart(Room* room, Human* hum, cs::MFObjectPart* part_data) { - + part_data->set_object_type(ET_Obstacle); + cs::MFObstaclePart* p = part_data->mutable_union_obj_2(); + p->set_obj_uniid(GetUniId()); + TypeConvert::ToPb(GetPos(), p->mutable_pos()); + p->set_scale(1.0f); } void MapBlock::FillMFObjectFull(Room* room, Human* hum, cs::MFObjectFull* full_data) { + full_data->set_object_type(ET_Obstacle); + if (IsClientCached(hum)) { + int object_flags = 0; + a8::SetBitFlag(object_flags, kOfReadCache); + full_data->set_obj_uniid(GetUniId()); + full_data->set_object_flags(object_flags); + return; + } + cs::MFObstacleFull* p = full_data->mutable_union_obj_2(); + if (CanClientCache(hum)) { + int object_flags = 0; + a8::SetBitFlag(object_flags, kOfWriteCache); + #if 0 + full_data->set_obj_uniid(GetUniId()); + #endif + full_data->set_object_flags(object_flags); + AddClientCache(hum); + } + p->set_obj_uniid(GetUniId()); + TypeConvert::ToPb(GetPos(), p->mutable_pos()); + p->set_scale(1.0f); + + p->set_obstacle_id(meta->i->thing_id()); + p->set_health(0); + p->set_dead(false); + p->set_dead_at_thisframe(false); + + p->set_is_door(false); + { + cs::MFCollider* collider = full_data->mutable_union_obj_2()->mutable_collider(); + collider->set_shape(shape); + if (shape == 1) { + collider->set_width(rad); + collider->set_height(rad); + } else { + collider->set_width(width); + collider->set_height(height); + } + } } void MapBlock::GetAabbBox(AabbCollider& aabb_box) { - + aabb_box.active = false; + aabb_box.owner = this; } void MapBlock::GetCircleBox(CircleCollider& circle_box) { - + circle_box.active = false; + circle_box.owner = this; } bool MapBlock::IsDead(Room* room) diff --git a/server/gameserver/mapblock.h b/server/gameserver/mapblock.h index 357ccef..86a07be 100644 --- a/server/gameserver/mapblock.h +++ b/server/gameserver/mapblock.h @@ -45,8 +45,6 @@ protected: MapBlock(); protected: - CircleCollider* self_collider_ = nullptr; - AabbCollider* self_collider2_ = nullptr; friend class EntityFactory; }; diff --git a/server/gameserver/mapinstance.cc b/server/gameserver/mapinstance.cc index 640ff9e..ef062b7 100644 --- a/server/gameserver/mapinstance.cc +++ b/server/gameserver/mapinstance.cc @@ -280,11 +280,27 @@ void MapInstance::CreateBlock() for (auto& obj : *blocks) { switch (obj.shape()) { case 1: - { - } - break; case 2: { + if (!obj.bullet_penetrate()) { + MapBlock* block = EntityFactory::Instance()->MakeBlock(++current_map_block_uniid_); + block->meta = MetaMgr::Instance()->GetMapThing + (obj.bullet_penetrate() ? 40002 : 40001); + block->shape = obj.shape(); + block->width = obj.width(); + block->height = obj.height(); + block->rad = obj.rad(); + block->permanent_map_service = map_service_; + block->SetPos(a8::Vec2(obj.x(), obj.y())); + block->Initialize(); + uniid_hash_[block->GetUniId()] = block; + grid_service_->AddPermanentEntity(block); + if (!block->meta) { + abort(); + } + } else { + int i = 0; + } } break; default: diff --git a/server/gameserver/metadata.cc b/server/gameserver/metadata.cc index b78103c..485869f 100644 --- a/server/gameserver/metadata.cc +++ b/server/gameserver/metadata.cc @@ -822,6 +822,7 @@ namespace MetaData a8::Split(i->buff_param1(), strings, '|'); for (auto& str : strings) { param1_int_list.push_back(a8::XValue(str).GetInt()); + param1_int_set.insert(a8::XValue(str).GetInt()); } } { @@ -849,6 +850,13 @@ namespace MetaData param4_int_list.push_back(a8::XValue(str).GetInt()); } } + { + std::vector strings; + a8::Split(i->tag(), strings, '|'); + for (auto& str : strings) { + tags.insert(a8::XValue(str).GetInt()); + } + } { std::vector strings; a8::Split(i->post_remove_action(), strings, '|'); diff --git a/server/gameserver/metadata.h b/server/gameserver/metadata.h index 4a7ed6e..105d277 100644 --- a/server/gameserver/metadata.h +++ b/server/gameserver/metadata.h @@ -213,6 +213,7 @@ namespace MetaData int int_param5 = 0; std::vector param1_int_list; std::vector param2_int_list; + std::set param1_int_set; std::set param2_int_set; std::vector param3_int_list; std::vector param4_int_list; @@ -220,6 +221,7 @@ namespace MetaData std::vector>> post_remove_action; std::set immune_buffeffect; std::vector> hero_infos; + std::set tags; std::vector child_buff_list; }; diff --git a/server/gameserver/obstacle.cc b/server/gameserver/obstacle.cc index 9bde65f..b27e8af 100644 --- a/server/gameserver/obstacle.cc +++ b/server/gameserver/obstacle.cc @@ -764,12 +764,15 @@ std::tuple* Obstacle::GetInteractionData(Human* sender) void Obstacle::AddObstacleBuff(Creature* c) { + a8::Vec2 old_context_dir = c->context_dir; a8::Vec2 old_context_pos = c->context_pos; + c->context_dir = c->GetAttackDir(); c->context_pos = c->GetPos(); for (int buff_id : meta->buff_list) { c->TryAddBuff(c, buff_id); } c->context_pos = old_context_pos; + c->context_dir = old_context_dir; } void Obstacle::ClearObstacleBuff(Creature* c) diff --git a/server/gameserver/player.cc b/server/gameserver/player.cc index 4ccbf2a..3a67735 100644 --- a/server/gameserver/player.cc +++ b/server/gameserver/player.cc @@ -210,7 +210,7 @@ void Player::UpdateShot() series_shot_frames = 0; return; } - if (HasBuffEffect(kBET_Vertigo)) { + if (HasBuffEffect(kBET_Vertigo) && !HasBuffEffect(kBET_AutoShot)) { return; } if (GetCar()) { @@ -1056,8 +1056,19 @@ void Player::_CMMove(f8::MsgHdr& hdr, const cs::CMMove& msg) std::abs(msg.attack_dir().y()) > 0.00001f ) ){ - if (!HasBuffEffect(kBET_Vertigo) && - !(GetCar() && (GetCar()->HasBuffEffect(kBET_Vertigo) || !GetCar()->HasOil()))) { + bool can_set = true; + if (HasBuffEffect(kBET_Vertigo)) { + can_set = HasBuffEffect(kBET_AutoShot); + } else if (GetCar()) { + if (GetCar()->HasOil()) { + if (GetCar()->HasBuffEffect(kBET_Vertigo)) { + can_set = GetCar()->HasBuffEffect(kBET_AutoShot); + } + } else { + can_set = false; + } + } + if (can_set) { a8::Vec2 attack_dir; TypeConvert::FromPb(attack_dir, &msg.attack_dir()); attack_dir.Normalize(); @@ -1065,8 +1076,6 @@ void Player::_CMMove(f8::MsgHdr& hdr, const cs::CMMove& msg) if (GetCar() && GetCar()->IsDriver(this)) { GetCar()->SetAttackDir(GetAttackDir()); } - } else { - int i = 0; } } } else { @@ -1084,8 +1093,10 @@ void Player::_CMMove(f8::MsgHdr& hdr, const cs::CMMove& msg) if (shot_start && !shot_hold) { } else { - shot_start = msg.shot_start(); - shot_hold = msg.shot_hold(); + if (!HasBuffEffect(kBET_AutoShot)) { + shot_start = msg.shot_start(); + shot_hold = msg.shot_hold(); + } } fly_distance = std::min(200.0f, msg.fly_distance()); if (!shot_hold) { diff --git a/server/gameserver/roomobstacle.cc b/server/gameserver/roomobstacle.cc index eeeb644..633649f 100644 --- a/server/gameserver/roomobstacle.cc +++ b/server/gameserver/roomobstacle.cc @@ -41,6 +41,9 @@ RoomObstacle::~RoomObstacle() if (!grid_list_) { A8_SAFE_DELETE(grid_list_); } + if (!hit_objects_) { + A8_SAFE_DELETE(hit_objects_); + } } void RoomObstacle::Initialize() @@ -277,6 +280,11 @@ void RoomObstacle::Active() ActiveAirDrop(); } break; + case kObstacleKeepRangeBuff: + { + ActiveKeepRangeBuff(); + } + break; default: { } @@ -465,3 +473,79 @@ Entity* RoomObstacle::GetRealObject(Room* room) { return room->GetEntityByUniId(real_object_uniid); } + +void RoomObstacle::ActiveKeepRangeBuff() +{ + auto check_cb = + [] (const a8::XParams& param) + { + RoomObstacle* obstacle = (RoomObstacle*)param.sender.GetUserData(); + obstacle->ProcKeepRangeBuff(); + }; + room->xtimer.AddRepeatTimerAndAttach + ( + 1, + a8::XParams() + .SetSender(this), + check_cb, + &xtimer_attacher.timer_list_ + ); + room->xtimer.AddDeadLineTimerAndAttach + ( + meta->i->time() / FRAME_RATE_MS, + a8::XParams() + .SetSender(this), + [] (const a8::XParams& param) + { + RoomObstacle* obstacle = (RoomObstacle*)param.sender.GetUserData(); + obstacle->DetachFromMaster(); + }, + &xtimer_attacher.timer_list_ + ); +} + +void RoomObstacle::ProcKeepRangeBuff() +{ + if (!grid_list_) { + grid_list_ = new std::set(); + room->grid_service->GetAllCellsByXy(room, GetPos().x, GetPos().y, *grid_list_); + } + if (!hit_objects_) { + hit_objects_ = new std::map(); + } + if (grid_list_ && master.Get() && !IsDead(room)) { + std::set target_list; + room->grid_service->TraverseCreatures + (room->GetRoomIdx(), + *grid_list_, + [this, &target_list] (Creature* hum, bool& stop) + { + if (master.Get()->team_id != hum->team_id && TestCollision(room, hum)) { + target_list.insert(hum); + } + } + ); + for (Creature* hum : target_list) { + for (int buff_id : meta->buff_list) { + MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(buff_id); + if (buff_meta && hum->GetBuffById(buff_id)) { + hum->AddBuff(master.Get(), + buff_meta, + 1); + } + } + if (hit_objects_->find(hum->GetUniId()) == hit_objects_->end()) { + (*hit_objects_)[hum->GetUniId()] = hum->GetWeakPtrRef(); + } + } + for (auto& pair : *hit_objects_) { + for (int buff_id : meta->buff_list) { + if (pair.second.Get() && target_list.find(pair.second.Get()) == target_list.end()) { + pair.second.Get()->RemoveBuffById(buff_id); + } + } + } + } else { + room->xtimer.DeleteTimer(room->xtimer.GetRunningTimer()); + } +} diff --git a/server/gameserver/roomobstacle.h b/server/gameserver/roomobstacle.h index 90bdbff..b10596c 100644 --- a/server/gameserver/roomobstacle.h +++ b/server/gameserver/roomobstacle.h @@ -38,13 +38,16 @@ private: void ActiveHideHouse(); void ActiveGully(); void ActiveAirDrop(); + void ActiveKeepRangeBuff(); void SummonAirDropBox(int box_id); + void ProcKeepRangeBuff(); protected: std::set* grid_list_ = nullptr; int explosion_times_ = 0; bool detached_ = false; + std::map* hit_objects_ = nullptr; RoomObstacle(); diff --git a/server/gameserver/trigger.cc b/server/gameserver/trigger.cc index 5c7de55..96f9e42 100644 --- a/server/gameserver/trigger.cc +++ b/server/gameserver/trigger.cc @@ -219,7 +219,9 @@ void Trigger::TraverseCondBuffs(int cond, std::function fun void Trigger::TriggeCondBuffAll(int cond) { std::shared_ptr old_context_ability = owner_->context_ability; + a8::Vec2 old_context_dir = owner_->context_dir; a8::Vec2 old_context_pos = owner_->context_pos; + owner_->context_dir = owner_->GetAttackDir(); owner_->context_pos = owner_->GetPos(); TraverseCondBuffs (cond, @@ -227,6 +229,7 @@ void Trigger::TriggeCondBuffAll(int cond) { AddBuffs(cond, buff->meta->param4_int_list); }); + owner_->context_dir = old_context_dir; owner_->context_pos = old_context_pos; owner_->context_ability = old_context_ability; } diff --git a/server/tools/protobuild/cs_proto.proto b/server/tools/protobuild/cs_proto.proto index 399f0c9..0d6faaa 100755 --- a/server/tools/protobuild/cs_proto.proto +++ b/server/tools/protobuild/cs_proto.proto @@ -154,7 +154,7 @@ message MFPropertyChg //碰撞体 message MFCollider { - optional int32 shape = 1; //形状 1:矩形 2:圆形(当是圆形的时候width=eight) + optional int32 shape = 1; //形状 1:矩形 2:圆形(当是圆形的时候width=height) optional int32 width = 2; //宽度 optional int32 height = 3; //高度 } diff --git a/server/tools/protobuild/metatable.proto b/server/tools/protobuild/metatable.proto index 2b18247..664b90f 100755 --- a/server/tools/protobuild/metatable.proto +++ b/server/tools/protobuild/metatable.proto @@ -258,6 +258,7 @@ message Buff optional int32 coexist_num = 18; optional int32 dead_valid = 23; optional int32 buff_interval = 24; + optional string tag = 25; } message Drop @@ -448,4 +449,5 @@ message MapBlockJson optional float height = 7; optional float width = 8; optional float rad = 9; + optional int32 bullet_penetrate = 10; }