mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-15 04:11:30 +00:00
Merge pull request #937 from noudess/master
Fix for client position while on boat
This commit is contained in:
commit
08b8deaa4b
@ -3838,8 +3838,9 @@ void Client::Handle_OP_BoardBoat(const EQApplicationPacket *app)
|
|||||||
boatname[63] = '\0';
|
boatname[63] = '\0';
|
||||||
|
|
||||||
Mob* boat = entity_list.GetMob(boatname);
|
Mob* boat = entity_list.GetMob(boatname);
|
||||||
if (!boat || (boat->GetRace() != CONTROLLED_BOAT && boat->GetRace() != 502))
|
if (!boat || !boat->IsControllableBoat()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
controlling_boat_id = boat->GetID(); // set the client's BoatID to show that it's on this boat
|
controlling_boat_id = boat->GetID(); // set the client's BoatID to show that it's on this boat
|
||||||
|
|
||||||
Message(0, "Board boat: %s", boatname);
|
Message(0, "Board boat: %s", boatname);
|
||||||
@ -4404,7 +4405,36 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At this point, all that's left is a client update.
|
||||||
|
// Pure boat updates, and client contolled mob updates are complete.
|
||||||
|
// This can still be tricky. If ppu->vehicle_id is set, then the client
|
||||||
|
// position is actually an offset from the boat he is inside.
|
||||||
|
|
||||||
|
bool on_boat = (ppu->vehicle_id != 0);
|
||||||
|
|
||||||
|
// From this point forward, we need to use a new set of variables for client
|
||||||
|
// position. If the client is in a boat, we need to add the boat pos and
|
||||||
|
// the client offset together.
|
||||||
|
|
||||||
|
float cx = ppu->x_pos;
|
||||||
|
float cy = ppu->y_pos;
|
||||||
|
float cz = ppu->z_pos;
|
||||||
|
float new_heading = EQ12toFloat(ppu->heading);
|
||||||
|
|
||||||
|
if (on_boat) {
|
||||||
|
Mob *boat = entity_list.GetMob(ppu->vehicle_id);
|
||||||
|
if (boat == 0) {
|
||||||
|
LogError("Can't find boat for client position offset.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cx += boat->GetX();
|
||||||
|
cy += boat->GetY();
|
||||||
|
cz += boat->GetZ();
|
||||||
|
new_heading += boat->GetHeading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (IsDraggingCorpse())
|
if (IsDraggingCorpse())
|
||||||
DragCorpses();
|
DragCorpses();
|
||||||
|
|
||||||
@ -4412,9 +4442,9 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
float rewind_x_diff = 0;
|
float rewind_x_diff = 0;
|
||||||
float rewind_y_diff = 0;
|
float rewind_y_diff = 0;
|
||||||
|
|
||||||
rewind_x_diff = ppu->x_pos - m_RewindLocation.x;
|
rewind_x_diff = cx - m_RewindLocation.x;
|
||||||
rewind_x_diff *= rewind_x_diff;
|
rewind_x_diff *= rewind_x_diff;
|
||||||
rewind_y_diff = ppu->y_pos - m_RewindLocation.y;
|
rewind_y_diff = cy - m_RewindLocation.y;
|
||||||
rewind_y_diff *= rewind_y_diff;
|
rewind_y_diff *= rewind_y_diff;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4432,26 +4462,26 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if ((rewind_x_diff > 5000) || (rewind_y_diff > 5000))
|
if ((rewind_x_diff > 5000) || (rewind_y_diff > 5000))
|
||||||
m_RewindLocation = glm::vec3(ppu->x_pos, ppu->y_pos, ppu->z_pos);
|
m_RewindLocation = glm::vec3(cx, cy, cz);
|
||||||
|
|
||||||
if (proximity_timer.Check()) {
|
if (proximity_timer.Check()) {
|
||||||
entity_list.ProcessMove(this, glm::vec3(ppu->x_pos, ppu->y_pos, ppu->z_pos));
|
entity_list.ProcessMove(this, glm::vec3(cx, cy, cz));
|
||||||
if (RuleB(TaskSystem, EnableTaskSystem) && RuleB(TaskSystem, EnableTaskProximity))
|
if (RuleB(TaskSystem, EnableTaskSystem) && RuleB(TaskSystem, EnableTaskProximity))
|
||||||
ProcessTaskProximities(ppu->x_pos, ppu->y_pos, ppu->z_pos);
|
ProcessTaskProximities(cx, cy, cz);
|
||||||
|
|
||||||
m_Proximity = glm::vec3(ppu->x_pos, ppu->y_pos, ppu->z_pos);
|
m_Proximity = glm::vec3(cx, cy, cz);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update internal state */
|
/* Update internal state */
|
||||||
m_Delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, EQ10toFloat(ppu->delta_heading));
|
m_Delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, EQ10toFloat(ppu->delta_heading));
|
||||||
|
|
||||||
if (IsTracking() && ((m_Position.x != ppu->x_pos) || (m_Position.y != ppu->y_pos))) {
|
if (IsTracking() && ((m_Position.x != cx) || (m_Position.y != cy))) {
|
||||||
if (zone->random.Real(0, 100) < 70)//should be good
|
if (zone->random.Real(0, 100) < 70)//should be good
|
||||||
CheckIncreaseSkill(EQEmu::skills::SkillTracking, nullptr, -20);
|
CheckIncreaseSkill(EQEmu::skills::SkillTracking, nullptr, -20);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Break Hide if moving without sneaking and set rewind timer if moved */
|
/* Break Hide if moving without sneaking and set rewind timer if moved */
|
||||||
if (ppu->y_pos != m_Position.y || ppu->x_pos != m_Position.x) {
|
if (cy != m_Position.y || cx != m_Position.x) {
|
||||||
if ((hidden || improved_hidden) && !sneaking) {
|
if ((hidden || improved_hidden) && !sneaking) {
|
||||||
hidden = false;
|
hidden = false;
|
||||||
improved_hidden = false;
|
improved_hidden = false;
|
||||||
@ -4470,7 +4500,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Handle client aggro scanning timers NPCs */
|
/* Handle client aggro scanning timers NPCs */
|
||||||
is_client_moving = (ppu->y_pos == m_Position.y && ppu->x_pos == m_Position.x) ? false : true;
|
is_client_moving = (cy == m_Position.y && cx == m_Position.x) ? false : true;
|
||||||
|
|
||||||
if (is_client_moving) {
|
if (is_client_moving) {
|
||||||
LogDebug("ClientUpdate: Client is moving - scan timer is: [{}]", client_scan_npc_aggro_timer.GetDuration());
|
LogDebug("ClientUpdate: Client is moving - scan timer is: [{}]", client_scan_npc_aggro_timer.GetDuration());
|
||||||
@ -4531,17 +4561,16 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
SetLastPositionBeforeBulkUpdate(GetPosition());
|
SetLastPositionBeforeBulkUpdate(GetPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
float new_heading = EQ12toFloat(ppu->heading);
|
|
||||||
int32 new_animation = ppu->animation;
|
int32 new_animation = ppu->animation;
|
||||||
|
|
||||||
/* Update internal server position from what the client has sent */
|
/* Update internal server position from what the client has sent */
|
||||||
m_Position.x = ppu->x_pos;
|
m_Position.x = cx;
|
||||||
m_Position.y = ppu->y_pos;
|
m_Position.y = cy;
|
||||||
m_Position.z = ppu->z_pos;
|
m_Position.z = cz;
|
||||||
|
|
||||||
/* Visual Debugging */
|
/* Visual Debugging */
|
||||||
if (RuleB(Character, OPClientUpdateVisualDebug)) {
|
if (RuleB(Character, OPClientUpdateVisualDebug)) {
|
||||||
LogDebug("ClientUpdate: ppu x: [{}] y: [{}] z: [{}] h: [{}]", ppu->x_pos, ppu->y_pos, ppu->z_pos, ppu->heading);
|
LogDebug("ClientUpdate: ppu x: [{}] y: [{}] z: [{}] h: [{}]", cx, cy, cz, new_heading);
|
||||||
this->SendAppearanceEffect(78, 0, 0, 0, 0);
|
this->SendAppearanceEffect(78, 0, 0, 0, 0);
|
||||||
this->SendAppearanceEffect(41, 0, 0, 0, 0);
|
this->SendAppearanceEffect(41, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
@ -4550,7 +4579,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
if (is_client_moving || new_heading != m_Position.w || new_animation != animation) {
|
if (is_client_moving || new_heading != m_Position.w || new_animation != animation) {
|
||||||
|
|
||||||
animation = ppu->animation;
|
animation = ppu->animation;
|
||||||
m_Position.w = EQ12toFloat(ppu->heading);
|
m_Position.w = new_heading;
|
||||||
|
|
||||||
/* Broadcast update to other clients */
|
/* Broadcast update to other clients */
|
||||||
auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
||||||
@ -4913,12 +4942,16 @@ void Client::Handle_OP_ControlBoat(const EQApplicationPacket *app)
|
|||||||
LogError("Wrong size: OP_ControlBoat, size=[{}], expected [{}]", app->size, sizeof(ControlBoat_Struct));
|
LogError("Wrong size: OP_ControlBoat, size=[{}], expected [{}]", app->size, sizeof(ControlBoat_Struct));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ControlBoat_Struct* cbs = (ControlBoat_Struct*)app->pBuffer;
|
ControlBoat_Struct* cbs = (ControlBoat_Struct*)app->pBuffer;
|
||||||
Mob* boat = entity_list.GetMob(cbs->boatId);
|
Mob* boat = entity_list.GetMob(cbs->boatId);
|
||||||
if (boat == 0)
|
if (!boat) {
|
||||||
return; // do nothing if the boat isn't valid
|
|
||||||
|
|
||||||
if (!boat->IsNPC() || (boat->GetRace() != CONTROLLED_BOAT && boat->GetRace() != 502))
|
LogError("Player tried to take control of non-existent boat (char_id: %u, boat_eid: %u)", CharacterID(), cbs->boatId);
|
||||||
|
return; // do nothing if the boat isn't valid
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!boat->IsNPC() || !boat->IsControllableBoat())
|
||||||
{
|
{
|
||||||
char *hacked_string = nullptr;
|
char *hacked_string = nullptr;
|
||||||
MakeAnyLenString(&hacked_string, "OP_Control Boat was sent against %s which is of race %u", boat->GetName(), boat->GetRace());
|
MakeAnyLenString(&hacked_string, "OP_Control Boat was sent against %s which is of race %u", boat->GetName(), boat->GetRace());
|
||||||
@ -4929,20 +4962,24 @@ void Client::Handle_OP_ControlBoat(const EQApplicationPacket *app)
|
|||||||
|
|
||||||
if (cbs->TakeControl) {
|
if (cbs->TakeControl) {
|
||||||
// this uses the boat's target to indicate who has control of it. It has to check hate to make sure the boat isn't actually attacking anyone.
|
// this uses the boat's target to indicate who has control of it. It has to check hate to make sure the boat isn't actually attacking anyone.
|
||||||
if ((boat->GetTarget() == 0) || (boat->GetTarget() == this && boat->GetHateAmount(this) == 0)) {
|
if (!boat->GetTarget() || (boat->GetTarget() == this && boat->GetHateAmount(this) == 0)) {
|
||||||
boat->SetTarget(this);
|
boat->SetTarget(this);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
this->MessageString(Chat::Red, IN_USE);
|
this->MessageString(Chat::Red, IN_USE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
boat->SetTarget(0);
|
if (boat->GetTarget() == this) {
|
||||||
|
boat->SetTarget(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// client responds better to a packet echo than an empty op
|
||||||
|
QueuePacket(app);
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(OP_ControlBoat, 0);
|
|
||||||
FastQueuePacket(&outapp);
|
|
||||||
safe_delete(outapp);
|
|
||||||
// have the boat signal itself, so quests can be triggered by boat use
|
// have the boat signal itself, so quests can be triggered by boat use
|
||||||
boat->CastToNPC()->SignalNPC(0);
|
boat->CastToNPC()->SignalNPC(0);
|
||||||
}
|
}
|
||||||
@ -8912,10 +8949,13 @@ void Client::Handle_OP_LeaveBoat(const EQApplicationPacket *app)
|
|||||||
{
|
{
|
||||||
Mob* boat = entity_list.GetMob(this->controlling_boat_id); // find the mob corresponding to the boat id
|
Mob* boat = entity_list.GetMob(this->controlling_boat_id); // find the mob corresponding to the boat id
|
||||||
if (boat) {
|
if (boat) {
|
||||||
if ((boat->GetTarget() == this) && boat->GetHateAmount(this) == 0) // if the client somehow left while still controlling the boat (and the boat isn't attacking them)
|
if ((boat->GetTarget() == this) && boat->GetHateAmount(this) == 0) { // if the client somehow left while still controlling the boat (and the boat isn't attacking them)
|
||||||
boat->SetTarget(0); // fix it to stop later problems
|
boat->SetTarget(nullptr); // fix it to stop later problems
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->controlling_boat_id = 0;
|
this->controlling_boat_id = 0;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
20
zone/mob.cpp
20
zone/mob.cpp
@ -128,6 +128,7 @@ Mob::Mob(
|
|||||||
SetMoving(false);
|
SetMoving(false);
|
||||||
moved = false;
|
moved = false;
|
||||||
m_RewindLocation = glm::vec3();
|
m_RewindLocation = glm::vec3();
|
||||||
|
m_RelativePosition = glm::vec4();
|
||||||
|
|
||||||
name[0] = 0;
|
name[0] = 0;
|
||||||
orig_name[0] = 0;
|
orig_name[0] = 0;
|
||||||
@ -4829,7 +4830,24 @@ void Mob::RemoveNimbusEffect(int effectid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Mob::IsBoat() const {
|
bool Mob::IsBoat() const {
|
||||||
return (race == 72 || race == 73 || race == 114 || race == 404 || race == 550 || race == 551 || race == 552);
|
|
||||||
|
return (
|
||||||
|
race == RACE_SHIP_72 ||
|
||||||
|
race == RACE_LAUNCH_73 ||
|
||||||
|
race == RACE_GHOST_SHIP_114 ||
|
||||||
|
race == RACE_SHIP_404 ||
|
||||||
|
race == RACE_MERCHANT_SHIP_550 ||
|
||||||
|
race == RACE_PIRATE_SHIP_551 ||
|
||||||
|
race == RACE_GHOST_SHIP_552
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mob::IsControllableBoat() const {
|
||||||
|
|
||||||
|
return (
|
||||||
|
race == RACE_BOAT_141 ||
|
||||||
|
race == RACE_ROWBOAT_502
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::SetBodyType(bodyType new_body, bool overwrite_orig) {
|
void Mob::SetBodyType(bodyType new_body, bool overwrite_orig) {
|
||||||
|
|||||||
@ -562,10 +562,17 @@ public:
|
|||||||
inline const float GetY() const { return m_Position.y; }
|
inline const float GetY() const { return m_Position.y; }
|
||||||
inline const float GetZ() const { return m_Position.z; }
|
inline const float GetZ() const { return m_Position.z; }
|
||||||
inline const float GetHeading() const { return m_Position.w; }
|
inline const float GetHeading() const { return m_Position.w; }
|
||||||
|
inline const glm::vec4& GetRelativePosition() const { return m_RelativePosition; }
|
||||||
|
inline void SetRelativePosition(const float x, const float y, const float z) { m_RelativePosition.x = x; m_RelativePosition.y = y; m_RelativePosition.z = z; }
|
||||||
|
inline const float GetRelativeX() const { return m_RelativePosition.x; }
|
||||||
|
inline const float GetRelativeY() const { return m_RelativePosition.y; }
|
||||||
|
inline const float GetRelativeZ() const { return m_RelativePosition.z; }
|
||||||
|
inline const float GetRelativeHeading() const { return m_RelativePosition.w; }
|
||||||
inline const float GetSize() const { return size; }
|
inline const float GetSize() const { return size; }
|
||||||
inline const float GetBaseSize() const { return base_size; }
|
inline const float GetBaseSize() const { return base_size; }
|
||||||
inline const GravityBehavior GetFlyMode() const { return flymode; }
|
inline const GravityBehavior GetFlyMode() const { return flymode; }
|
||||||
bool IsBoat() const;
|
bool IsBoat() const;
|
||||||
|
bool IsControllableBoat() const;
|
||||||
|
|
||||||
//Group
|
//Group
|
||||||
virtual bool HasRaid() = 0;
|
virtual bool HasRaid() = 0;
|
||||||
@ -1298,6 +1305,7 @@ protected:
|
|||||||
uint32 npctype_id;
|
uint32 npctype_id;
|
||||||
|
|
||||||
glm::vec4 m_Position;
|
glm::vec4 m_Position;
|
||||||
|
glm::vec4 m_RelativePosition;
|
||||||
int animation; // this is really what MQ2 calls SpeedRun just packed like (int)(SpeedRun * 40.0f)
|
int animation; // this is really what MQ2 calls SpeedRun just packed like (int)(SpeedRun * 40.0f)
|
||||||
float base_size;
|
float base_size;
|
||||||
float size;
|
float size;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user