diff --git a/server/gameserver/human.cc b/server/gameserver/human.cc index 1677d3b..f00b1d0 100644 --- a/server/gameserver/human.cc +++ b/server/gameserver/human.cc @@ -84,6 +84,28 @@ void Human::FillMFObjectFull(cs::MFObjectFull* full_data) #endif p->set_vip(vip); p->set_sdmg(sdmg); + if (pain_killer_timer) { + int passed_time = (room->frame_no - pain_killer_frameno) * FRAME_RATE_MS; + int left_time = std::max(0, pain_killer_lastingtime * 1000 - passed_time); + int anodyne_max_time = MetaMgr::Instance()->GetSysParamAsInt("anodyne_max_time"); + left_time = std::min(left_time, anodyne_max_time * 1000); + + cs::MFBodyState* state = p->add_states(); + state->set_state_type(1); + state->set_left_time(left_time); + state->set_lasting_time(anodyne_max_time * 1000); + } + if (a8::HasBitFlag(status, HS_Fly)) { + cs::MFBodyState* state = p->add_states(); + state->set_state_type(2); + } + if (a8::HasBitFlag(status, HS_Jump)) { + int passed_time = (room->frame_no - jump_frameno) * FRAME_RATE_MS; + cs::MFBodyState* state = p->add_states(); + state->set_state_type(3); + state->set_left_time(std::max(0, MetaMgr::Instance()->jump_time - passed_time)); + state->set_lasting_time(MetaMgr::Instance()->jump_time); + } } void Human::FillMFPlayerStats(cs::MFPlayerStats* stats_pb) @@ -275,6 +297,10 @@ bool Human::IsCollision() } } + if (a8::HasBitFlag(status, HS_Jump)) { + return false; + } + int detection_flags = 0; a8::SetBitFlag(detection_flags, ET_Obstacle); a8::SetBitFlag(detection_flags, ET_Building); @@ -375,9 +401,10 @@ void Human::UpdatePoisoning() void Human::SyncAroundPlayers() { room->TouchHumanList(a8::XParams(), - [this] (Human* hum, a8::XParams& param) + [this] (Human* hum, a8::XParams& param) -> bool { hum->new_objects.insert(this); + return true; }); } @@ -440,9 +467,10 @@ void Human::FillSMGameOver(cs::SMGameOver& msg) { std::vector human_list; room->TouchHumanList(a8::XParams(), - [&human_list] (Human* hum, a8::XParams& param) + [&human_list] (Human* hum, a8::XParams& param) -> bool { human_list.push_back(hum); + return true; }); std::sort(human_list.begin(), human_list.end(), [] (Human* a, Human* b ) @@ -582,3 +610,28 @@ bool Human::HasLiveTeammate() } return false; } + +void Human::Land() +{ + a8::UnSetBitFlag(status, HS_Jump); + SyncAroundPlayers(); +} + +void Human::DoJump() +{ + if (a8::HasBitFlag(status, HS_Fly)) { + a8::UnSetBitFlag(status, HS_Fly); + a8::SetBitFlag(status, HS_Jump); + jump_frameno = room->frame_no; + SyncAroundPlayers(); + room->xtimer.AddDeadLineTimerAndAttach(MetaMgr::Instance()->jump_time, + a8::XParams() + .SetSender(this), + [] (const a8::XParams& param) + { + Human* hum = (Human*)param.sender.GetUserData(); + hum->Land(); + }, + &xtimer_attacher.timer_list_); + } +} diff --git a/server/gameserver/human.h b/server/gameserver/human.h index b23d800..22626e1 100644 --- a/server/gameserver/human.h +++ b/server/gameserver/human.h @@ -83,6 +83,8 @@ class Human : public Entity std::set* team_members = nullptr; + long long jump_frameno = 0; + Human(); virtual ~Human() override; virtual void Initialize() override; @@ -115,6 +117,10 @@ class Human : public Entity void RemoveNewObjects(Entity* entity); void RemovePartObjects(Entity* entity); bool HasLiveTeammate(); + void Land(); + void DoJump(); + +protected: protected: long long last_shot_frameno_ = 0; diff --git a/server/gameserver/metamgr.cc b/server/gameserver/metamgr.cc index 2b0b40d..8ebec58 100755 --- a/server/gameserver/metamgr.cc +++ b/server/gameserver/metamgr.cc @@ -68,6 +68,7 @@ public: { MetaMgr::Instance()->gas_inactive_time = MetaMgr::Instance()->GetSysParamAsInt("gas_inactive_time"); MetaMgr::Instance()->plane_speed = MetaMgr::Instance()->GetSysParamAsFloat("plane_speed") / SERVER_FRAME_RATE; + MetaMgr::Instance()->jump_time = MetaMgr::Instance()->GetSysParamAsFloat("jump_time"); } #endif } diff --git a/server/gameserver/metamgr.h b/server/gameserver/metamgr.h index 0dcf27e..da3971c 100755 --- a/server/gameserver/metamgr.h +++ b/server/gameserver/metamgr.h @@ -32,6 +32,7 @@ class MetaMgr : public a8::Singleton int gas_inactive_time = 10; float plane_speed = 5.0f; + int jump_time = 10; private: MetaDataLoader* loader_ = nullptr; diff --git a/server/gameserver/player.cc b/server/gameserver/player.cc index 04fb35a..ce5d962 100644 --- a/server/gameserver/player.cc +++ b/server/gameserver/player.cc @@ -77,6 +77,9 @@ void Player::Update(int delta_time) if (emote) { UpdateEmote(); } + if (jump) { + UpdateJump(); + } } } @@ -116,7 +119,8 @@ void Player::UpdateMove() void Player::UpdateShot() { - if (a8::HasBitFlag(status, HS_Fly)) { + if (a8::HasBitFlag(status, HS_Fly) || + a8::HasBitFlag(status, HS_Jump) ) { shot_start = false; shot_hold = false; series_shot_frames = 0; @@ -391,6 +395,32 @@ void Player::UpdateEmote() emote_id = 0; } +void Player::UpdateJump() +{ + if (a8::HasBitFlag(status, HS_Fly)) { + DoJump(); + room->xtimer.AddDeadLineTimerAndAttach(SERVER_FRAME_RATE * 3, + a8::XParams(), + [] (const a8::XParams& param) + { + Human* hum = (Human*)param.sender.GetUserData(); + hum->room->TouchHumanList( + a8::XParams() + .SetSender(hum), + [] (Human* hum, a8::XParams& param) -> bool + { + if (a8::HasBitFlag(hum->status, HS_Fly)) { + hum->DoJump(); + return false; + } + return true; + }); + }, + &xtimer_attacher.timer_list_); + } + jump = false; +} + void Player::Shot() { if (!curr_weapon->meta) { @@ -554,7 +584,7 @@ void Player::ObstacleInteraction(Obstacle* entity) } entity->RecalcSelfCollider(); room->TouchHumanList(a8::XParams(), - [entity] (Human* hum, a8::XParams& param) + [entity] (Human* hum, a8::XParams& param) -> bool { hum->AddToNewObjects(entity); if (entity->TestCollision(hum)) { @@ -562,6 +592,7 @@ void Player::ObstacleInteraction(Obstacle* entity) } else if (hum->last_collision_door == entity) { hum->last_collision_door = nullptr; } + return true; }); } else { } @@ -809,6 +840,9 @@ void Player::_CMMove(f8::MsgHdr& hdr, const cs::CMMove& msg) emote = true; emote_id = msg.emote(); } + if (msg.has_jump()) { + jump = true; + } } void Player::UpdateDropWeapon() @@ -979,6 +1013,8 @@ void Player::FillMFGasData(cs::MFGasData* gas_data) long long duration = MetaMgr::Instance()->gas_inactive_time * SERVER_FRAME_RATE - (room->frame_no - room->gas_data.gas_start_frameno); gas_data->set_duration(std::max(duration * 50, (long long)1000) / 1000); + } else if (room->gas_data.gas_mode == GasJump) { + gas_data->set_duration(0); } else { if (room->gas_data.old_area_meta->i->wait_time() <= 0) { gas_data->set_duration(0); diff --git a/server/gameserver/player.h b/server/gameserver/player.h index 36a7057..b496d39 100644 --- a/server/gameserver/player.h +++ b/server/gameserver/player.h @@ -58,6 +58,8 @@ class Player : public Human bool emote = false; int emote_id = 0; + bool jump = false; + ::google::protobuf::RepeatedField< ::google::protobuf::int32 > interaction_objids; template @@ -82,6 +84,7 @@ class Player : public Human void UpdateSpectate(); void UpdateGameOver(); void UpdateEmote(); + void UpdateJump(); void Shot(); void ProcInteraction(); void ObstacleInteraction(Obstacle* entity); diff --git a/server/gameserver/room.cc b/server/gameserver/room.cc index 06966c8..83a19e4 100644 --- a/server/gameserver/room.cc +++ b/server/gameserver/room.cc @@ -705,14 +705,16 @@ void Room::TouchPlayerList(a8::XParams param, } void Room::TouchHumanList(a8::XParams param, - std::function func) + std::function func) { if (!func) { return; } for (auto& pair : human_hash_) { if (pair.second) { - func(pair.second, param); + if (!func(pair.second, param)) { + break; + } } } } @@ -769,6 +771,15 @@ void Room::UpdateGas() Vector2D len_vec = plane.dir * (frame_no - gas_data.gas_start_frameno)*MetaMgr::Instance()->plane_speed; plane.curr_pos = plane.start_point + len_vec; if ((plane.end_point - plane.start_point).Norm() <= len_vec.Norm()) { + TouchHumanList( + a8::XParams(), + [] (Human* hum, a8::XParams& param) -> bool + { + if (a8::HasBitFlag(hum->status, HS_Fly)) { + hum->DoJump(); + } + return true; + }); gas_data.gas_mode = GasWaiting; gas_data.old_area_meta = MetaMgr::Instance()->GetSafeArea(30001); gas_data.new_area_meta = MetaMgr::Instance()->GetSafeArea(30002); @@ -1040,9 +1051,24 @@ void Room::AirDrop(int appear_time, int box_id) void Room::ShuaPlane() { + plane.start_point = Vector2D(100, 100); + plane.end_point = Vector2D(7500, 7500); + plane.dir = plane.end_point - plane.start_point; + plane.curr_pos = plane.start_point; + + std::vector humans; for (auto& pair : human_hash_) { a8::SetBitFlag(pair.second->status, HS_Fly); pair.second->pos = plane.curr_pos; pair.second->attack_dir = plane.dir; + pair.second->move_dir = plane.dir; + humans.push_back(pair.second); } + for (auto& hum : humans) { + for (auto& pair : human_hash_) { + hum->AddToNewObjects(pair.second); + hum->AddToPartObjects(pair.second); + } + } + } diff --git a/server/gameserver/room.h b/server/gameserver/room.h index 1ee525a..8b47d16 100644 --- a/server/gameserver/room.h +++ b/server/gameserver/room.h @@ -62,7 +62,7 @@ public: void TouchPlayerList(a8::XParams param, std::function func); void TouchHumanList(a8::XParams param, - std::function func); + std::function func); void ScatterDrop(Vector2D center, int drop_id); void DropItem(Vector2D pos, int item_id, int item_count);