diff --git a/server/gameserver/creature.cc b/server/gameserver/creature.cc index 420e1b0..08f7231 100644 --- a/server/gameserver/creature.cc +++ b/server/gameserver/creature.cc @@ -2791,3 +2791,27 @@ bool Creature::CanFollow(Creature* follower) } return true; } + +void Creature::FollowToTarget() +{ + if (HasBuffEffect(kBET_Jump) && + follow_target.Get() && + follow_target.Get()->GetChgAttackDirTimes() > follow_target_last_chg_move_dir_times_) { +#if 1 + { +#else + if (GetPos().ManhattanDistance(follow_target.Get()->GetPos()) > 20) { +#endif + a8::Vec2 dir = a8::Vec2::UP; + dir.Rotate(a8::RandAngle()); + dir.Normalize(); + a8::Vec2 target_pos = follow_target.Get()->GetPos() + dir * (10 + (rand() % 10)); + if (GetPos().ManhattanDistance(target_pos) > 5) { + a8::Vec2 move_dir = target_pos - GetPos(); + move_dir.Normalize(); + SetMoveDir(move_dir); + } + follow_target_last_chg_move_dir_times_ = follow_target.Get()->GetChgAttackDirTimes(); + } + } +} diff --git a/server/gameserver/creature.h b/server/gameserver/creature.h index 9d8a8f3..f9fb5e4 100644 --- a/server/gameserver/creature.h +++ b/server/gameserver/creature.h @@ -239,6 +239,7 @@ class Creature : public MoveableEntity long long GetCollisionTimes() { return collision_times_; }; std::string DebugOutBuffList(); bool CanFollow(Creature* follower); + void FollowToTarget(); protected: virtual void OnBuffRemove(Buff& buff); @@ -279,6 +280,8 @@ protected: int camouflage_move_addition_ = 0; int camouflage_aiming_addition_ = 0; + long long last_follow_move_frameno_ = 0; + int follow_target_last_chg_move_dir_times_ = -1; private: CreatureWeakPtr weak_ptr_; diff --git a/server/gameserver/moveableentity.cc b/server/gameserver/moveableentity.cc index d207d91..5b43603 100644 --- a/server/gameserver/moveableentity.cc +++ b/server/gameserver/moveableentity.cc @@ -70,3 +70,15 @@ void MoveableEntity::TraverseCreatures(std::function fu GetGridList(), func); } + +void MoveableEntity::SetMoveDir(const a8::Vec2& move_dir) +{ + move_dir_ = move_dir; + ++chg_move_dir_times_; +} + +void MoveableEntity::SetAttackDir(const a8::Vec2& attack_dir) +{ + attack_dir_ = attack_dir; + ++chg_attack_dir_times_; +} diff --git a/server/gameserver/moveableentity.h b/server/gameserver/moveableentity.h index 9fd2926..00de819 100644 --- a/server/gameserver/moveableentity.h +++ b/server/gameserver/moveableentity.h @@ -24,9 +24,11 @@ class MoveableEntity : public RoomEntity ); virtual void SyncAroundPlayers(const char* file, int line, const char* func); virtual const a8::Vec2& GetMoveDir() { return move_dir_; }; - virtual void SetMoveDir(const a8::Vec2& move_dir) { move_dir_ = move_dir; }; + virtual void SetMoveDir(const a8::Vec2& move_dir); virtual const a8::Vec2& GetAttackDir() { return attack_dir_; }; - virtual void SetAttackDir(const a8::Vec2& attack_dir) { attack_dir_ = attack_dir; }; + virtual void SetAttackDir(const a8::Vec2& attack_dir); + int GetChgMoveDirTimes() { return chg_move_dir_times_; } + int GetChgAttackDirTimes() { return chg_attack_dir_times_; } protected: int updated_times_ = 0; @@ -35,4 +37,6 @@ private: a8::Vec2 move_dir_; a8::Vec2 attack_dir_; std::set grid_list_; + int chg_move_dir_times_ = 0; + int chg_attack_dir_times_ = 0; }; diff --git a/server/gameserver/player.cc b/server/gameserver/player.cc index 6be89bb..a070ed9 100644 --- a/server/gameserver/player.cc +++ b/server/gameserver/player.cc @@ -70,6 +70,11 @@ void Player::InternalUpdate(int delta_time) } else { if (HasBuffEffect(kBET_Sprint)) { moving = true; + moved_frames = 0; + } + if (HasBuffEffect(kBET_Jump) && follow_target.Get()) { + moving = true; + moved_frames = 0; } if (moving) { UpdateMove(); @@ -410,6 +415,12 @@ void Player::UpdateJump() } } room->last_player_jump_pos = GetPos(); + if (follow_target.Get()) { + follow_target.Detach(); + if (follow_target_timer_) { + room->xtimer.DeleteTimer(follow_target_timer_); + } + } } jump = false; } @@ -1235,6 +1246,9 @@ void Player::UpdateFollow() if (follow_target.Get()) { follow_target.Detach(); room->frame_event.AddPropChg(GetWeakPtrRef(), kPropFollowTarget, 0, 0, true); + if (follow_target_timer_) { + room->xtimer.DeleteTimer(follow_target_timer_); + } } } else { if (GetTeam()) { @@ -1242,9 +1256,48 @@ void Player::UpdateFollow() if (member && member->CanFollow(this)) { if (follow_target.Get()) { follow_target.Detach(); + if (follow_target_timer_) { + room->xtimer.DeleteTimer(follow_target_timer_); + } } + follow_target_last_chg_move_dir_times_ = -1; follow_target.Attach(member); room->frame_event.AddPropChg(GetWeakPtrRef(), kPropFollowTarget, 0, follow, true); + follow_target_timer_ = room->xtimer.AddRepeatTimerAndAttach + ( + FRAME_RATE_MS, + a8::XParams() + .SetSender(this), + [] (const a8::XParams& param) + { + Player* hum = (Player*)param.sender.GetUserData(); + if (!hum->follow_target.Get()) { + hum->room->xtimer.DeleteTimer(hum->room->xtimer.GetRunningTimer()); + return; + } + if (hum->room->GetGasData().gas_mode != GasInactive && + !(hum->follow_target.Get()->HasBuffEffect(kBET_Fly) || + hum->follow_target.Get()->HasBuffEffect(kBET_Jump)) + ){ + hum->follow_target.Detach(); + hum->room->xtimer.DeleteTimer(hum->room->xtimer.GetRunningTimer()); + return; + } + + if (hum->follow_target.Get()->HasBuffEffect(kBET_Jump)) { + if (hum->HasBuffEffect(kBET_Jump)) { + hum->FollowToTarget(); + } else { + hum->DoJump(); + } + } + }, + &xtimer_attacher.timer_list_, + [] (const a8::XParams& param) + { + Player* hum = (Player*)param.sender.GetUserData(); + hum->follow_target_timer_ = nullptr; + }); } } } diff --git a/server/gameserver/player.h b/server/gameserver/player.h index 64835a4..215d81a 100644 --- a/server/gameserver/player.h +++ b/server/gameserver/player.h @@ -139,6 +139,7 @@ private: std::set receved_box_hash_; long long last_cmmove_frameno_ = 0; xtimer_list* watch_war_req_timer_ = nullptr; + xtimer_list* follow_target_timer_ = nullptr; friend class EntityFactory; };