diff --git a/server/gameserver/buff.cc b/server/gameserver/buff.cc index 3cf120f..7c65309 100644 --- a/server/gameserver/buff.cc +++ b/server/gameserver/buff.cc @@ -743,3 +743,52 @@ void Buff::CalcPassengerShotOffset() } } } + +void Buff::ProcDive() +{ + if (owner->IsHuman()) { + owner->AsHuman()->SetOxygen(MetaMgr::Instance()->dive_oxygen_total); + owner->AsHuman()->room->frame_event.AddPropChg + (owner->AsHuman()->GetWeakPtrRef(), + kPropDive, + MetaMgr::Instance()->dive_oxygen_total, + owner->AsHuman()->GetOxygen(), + true); + } + owner->room->xtimer.AddRepeatTimerAndAttach + ( + SERVER_FRAME_RATE, + a8::XParams() + .SetSender(this), + [] (const a8::XParams& param) + { + Buff* buff = (Buff*)param.sender.GetUserData(); + if (buff->owner->dead || !buff->owner->IsHuman()) { + buff->owner->RemoveBuffByUniId(buff->buff_uniid); + return; + } + Human* hum = buff->owner->AsHuman(); + if (hum->GetOxygen() > 0) { + hum->DecOxygen(MetaMgr::Instance()->dive_oxygen_consume); + hum->room->frame_event.AddPropChg(hum->GetWeakPtrRef(), + kPropDive, + MetaMgr::Instance()->dive_oxygen_total, + hum->GetOxygen(), + true); + return; + } + hum->DecHP(MetaMgr::Instance()->dive_hp_consume, + VP_Water, + "水", + 0); + }, + &xtimer_attacher.timer_list_ + ); +} + +void Buff::ProcRemoveDive() +{ + if (owner->IsHuman()) { + owner->AsHuman()->SetOxygen(0); + } +} diff --git a/server/gameserver/buff.h b/server/gameserver/buff.h index 0b50c81..a67b4e2 100644 --- a/server/gameserver/buff.h +++ b/server/gameserver/buff.h @@ -73,6 +73,8 @@ class Buff void ProcAutoShot(); void ProcBeatBack(); void ProcDisperse(); + void ProcDive(); + void ProcRemoveDive(); void CalcPassengerShotOffset(); diff --git a/server/gameserver/constant.h b/server/gameserver/constant.h index 83759c1..e31c151 100644 --- a/server/gameserver/constant.h +++ b/server/gameserver/constant.h @@ -219,6 +219,7 @@ enum VirtualPlayer_e VP_Gas = 9000000, VP_Buff = 9000001, VP_Explosion = 9000002, + VP_Water = 9000003, }; enum EquipType_e @@ -264,6 +265,7 @@ enum PropertyType_e kPropSkillMaxTimes = 26, kPropCarOil = 27, kPropFollowTarget = 30, + kPropDive = 31, }; enum MapObjectType_e diff --git a/server/gameserver/constant_export.h b/server/gameserver/constant_export.h index a248bf5..8acb644 100644 --- a/server/gameserver/constant_export.h +++ b/server/gameserver/constant_export.h @@ -18,6 +18,7 @@ const int kRescueBuffId = 7017; const int kVertigoBuffId = 7018; const int kPeaceModeBuffId = 7019; const int kPullToWalkableBuffId = 8003; +const int kDiveBuffId = 8054; enum BuffEffectType_e { @@ -94,6 +95,7 @@ enum BuffEffectType_e kBET_PeaceMode = 69, //和平模式 kBET_ClientUse1 = 70, // kBET_ClientUse2 = 71, // + kBET_Dive = 72, //下潜模式 kBET_End }; diff --git a/server/gameserver/creature.cc b/server/gameserver/creature.cc index cee317d..65bb6e2 100644 --- a/server/gameserver/creature.cc +++ b/server/gameserver/creature.cc @@ -1386,6 +1386,11 @@ void Creature::ProcBuffEffect(Creature* caster, Buff* buff) { } break; + case kBET_Dive: + { + buff->ProcDive(); + } + break; default: { } diff --git a/server/gameserver/human.cc b/server/gameserver/human.cc index a8e1659..3e12dfa 100644 --- a/server/gameserver/human.cc +++ b/server/gameserver/human.cc @@ -1187,6 +1187,10 @@ void Human::FillMFActivePlayerData(cs::MFActivePlayerData* player_data) player_data->set_max_health(GetMaxHP()); player_data->set_cur_weapon_idx(GetCurrWeapon()->weapon_idx); player_data->set_cur_scope(curr_scope_idx); + if (HasBuffEffect(kBET_Dive)) { + player_data->set_dive_oxygen_max(MetaMgr::Instance()->dive_oxygen_total); + player_data->set_dive_oxygen_curr(oxygen_); + } for (auto& weapon : weapons) { auto p = player_data->add_weapons(); weapon.ToPB(p); @@ -2878,6 +2882,11 @@ void Human::OnBuffRemove(Buff& buff) buff.ProcRemovePassenger(); } break; + case kBET_Dive: + { + buff.ProcRemoveDive(); + } + break; case kBET_AddInventory: { for (int slot : buff.meta->param2_int_list) { @@ -3804,6 +3813,20 @@ void Human::DoFollow(int target_id) IncFollowTimes(); } +void Human::DoDive() +{ + if (!HasBuffEffect(kBET_InWater)) { + return; + } + if (HasBuffEffect(kBET_Dive)) { + return; + } + if (HasBuffEffect(kBET_Camouflage) ) { + RemoveBuffByEffectId(kBET_Camouflage); + } + MustBeAddBuff(this, kDiveBuffId); +} + void Human::OnWatcherDie(Human* watcher) { if (follow_target_ == watcher) { @@ -3827,3 +3850,9 @@ void Human::TraverseObservers(std::function func) } } } + +void Human::DecOxygen(int val) +{ + oxygen_ -= val; + oxygen_ = std::max(0, oxygen_); +} diff --git a/server/gameserver/human.h b/server/gameserver/human.h index 375f2b4..0b7db39 100644 --- a/server/gameserver/human.h +++ b/server/gameserver/human.h @@ -264,8 +264,12 @@ class Human : public Creature void ProcUseItem(int item_id); void StartRefreshViewTimer(); void DoFollow(int target_id); + void DoDive(); void OnWatcherDie(Human* watcher); FrameData& GetFrameData() { return framedata_; }; + int GetOxygen() { return oxygen_; }; + void SetOxygen(int oxygen) { oxygen_ = oxygen; }; + void DecOxygen(int val); protected: void _InternalUpdateMove(float speed); @@ -325,6 +329,7 @@ protected: long long last_sync_teamdata_frameno_ = 0; bool leave_ = false; long long leave_frameno_ = 0; + int oxygen_ = 0; std::array volume_ = {}; Human* follow_target_ = nullptr; diff --git a/server/gameserver/killmgr.cc b/server/gameserver/killmgr.cc index eb29048..d380979 100644 --- a/server/gameserver/killmgr.cc +++ b/server/gameserver/killmgr.cc @@ -112,7 +112,14 @@ void KillMgr::FillHintInfo(Human* dead_hum, KillInfo* info, RollMsgHintInfo& hin } } break; - default: + case VP_Water: + { + hint_info.killer_name = ""; + hint_info.hint_template = MetaMgr::Instance()->GetTextElements + ("battle_server_dead_text_drown"); + } + break; + default: { Entity* killer = dead_hum->room->GetEntityByUniId(info->killer_id); if (killer) { diff --git a/server/gameserver/metamgr.cc b/server/gameserver/metamgr.cc index 8777e8a..c728b76 100644 --- a/server/gameserver/metamgr.cc +++ b/server/gameserver/metamgr.cc @@ -514,6 +514,10 @@ public: METAMGR_READ(level1room_robot_autodie_distance, 500); METAMGR_READ_STR(level1room_born_point, ""); + METAMGR_READ(dive_oxygen_total, 200); + METAMGR_READ(dive_oxygen_consume, 20); + METAMGR_READ(dive_hp_consume, 20); + METAMGR_READ(dive_explosion_dmg_switch, 0); } if (MetaMgr::Instance()->K < 0.01f) { abort(); diff --git a/server/gameserver/metamgr.h b/server/gameserver/metamgr.h index 10e8b6f..5347679 100644 --- a/server/gameserver/metamgr.h +++ b/server/gameserver/metamgr.h @@ -183,6 +183,11 @@ class MetaMgr : public a8::Singleton int match_choose_time = 0; int match_lock_time = 0; + int dive_oxygen_total = 0; + int dive_oxygen_consume = 0; + int dive_hp_consume = 0; + int dive_explosion_dmg_switch = 0; + private: MetaDataLoader* loader_ = nullptr; diff --git a/server/gameserver/player.cc b/server/gameserver/player.cc index ce74dc5..a146380 100644 --- a/server/gameserver/player.cc +++ b/server/gameserver/player.cc @@ -122,6 +122,9 @@ void Player::InternalUpdate(int delta_time) if (follow != -1) { UpdateFollow(); } + if (dive) { + UpdateDive(); + } if (shot_start || shot_hold) { UpdateShot(); } @@ -797,6 +800,9 @@ void Player::_CMMove(f8::MsgHdr& hdr, const cs::CMMove& msg) if (msg.has_follow()) { follow = msg.follow(); } + if (msg.has_dive()) { + dive = msg.dive(); + } if (msg.has_use_skill()) { use_skill = msg.use_skill(); use_skill_id = msg.skill_id(); @@ -1321,6 +1327,12 @@ void Player::UpdateFollow() follow = -1; } +void Player::UpdateDive() +{ + DoDive(); + dive = 0; +} + void Player::CheckShotHoldState(Weapon* weapon) { if (weapon->meta->buff_meta && weapon->meta->buff_meta->i->trigger_type() == kBTT_SeriesShot) { diff --git a/server/gameserver/player.h b/server/gameserver/player.h index 47fa30b..74990ef 100644 --- a/server/gameserver/player.h +++ b/server/gameserver/player.h @@ -69,6 +69,7 @@ class Player : public Human int switch_seat = 0; int follow = -1; + int dive = 0; ::google::protobuf::RepeatedField< ::google::protobuf::int32 > interaction_objids; @@ -93,6 +94,7 @@ class Player : public Human void UpdateUseSkill(); void UpdateAiming(); void UpdateFollow(); + void UpdateDive(); void Shot(); void ProcInteraction(); void ObstacleInteraction(Obstacle* entity); diff --git a/server/tools/protobuild/cs_proto.proto b/server/tools/protobuild/cs_proto.proto index e285e87..8238adb 100755 --- a/server/tools/protobuild/cs_proto.proto +++ b/server/tools/protobuild/cs_proto.proto @@ -143,6 +143,9 @@ message MFVec2 valule: 百分比绝对值 property_type: 30 跟随目标id valule: 目标id + property_type: 31 下潜后氧气 + property_subtype: 总量 + valule: 当前量 */ message MFPropertyChg { @@ -595,6 +598,9 @@ message MFActivePlayerData optional float shoot_offset_x = 50 [default = 0]; //射击偏移量-x optional float shoot_offset_y = 51 [default = 0]; //射击偏移量-y + + optional int32 dive_oxygen_max = 63; //下潜时氧气总量 + optional int32 dive_oxygen_curr = 64; //下潜时氧气当前量 } //毒圈数据 @@ -1016,6 +1022,8 @@ message CMMove optional int32 switch_seat = 37; //切换座位 optional int32 follow = 38; //跟随0:取消跟随 其他:玩家uniid + + optional int32 dive = 39; //下潜 } //执行GM指令