1
0

Fix #19 Position updates ignored when dead, new rule MiniDing, fix

Fix #19 - ignore position updates when dead
New rule R_Player MiniDingPercentage
Fixed ordering of locks in RemoveSpawn
ResetSpawnPackets function created to test resetting the spawn packet to a spawn (testing purposes only not live code)
This commit is contained in:
Emagi 2025-05-30 21:47:57 -04:00
parent 6d52f19108
commit 97d1393627
6 changed files with 67 additions and 18 deletions

View File

@ -999,7 +999,7 @@ EQ2Packet* PlayerInfo::serialize(int16 version, int16 modifyPos, int32 modifyVal
if (version <= 561) {
packet->setDataByName("exp_yellow", info_struct->get_xp_yellow() / 10);
packet->setDataByName("exp_blue", info_struct->get_xp_blue()/10);
packet->setDataByName("exp_blue", info_struct->get_xp_blue()/100);
}
else {
packet->setDataByName("exp_yellow", info_struct->get_xp_yellow());
@ -3577,9 +3577,9 @@ void Player::RemoveSpellEffect(LuaSpell* spell){
GetSpellEffectMutex()->releasewritelock(__FUNCTION__, __LINE__);
}
void Player::PrepareIncomingMovementPacket(int32 len, uchar* data, int16 version)
void Player::PrepareIncomingMovementPacket(int32 len, uchar* data, int16 version, bool dead_window_sent)
{
if(GetClient() && GetClient()->IsReloadingZone())
if((GetClient() && GetClient()->IsReloadingZone()) || dead_window_sent)
return;
LogWrite(PLAYER__DEBUG, 7, "Player", "Enter: %s", __FUNCTION__); // trace
@ -4503,7 +4503,14 @@ bool Player::AddXP(int32 xp_amount){
int32 prev_level = GetLevel();
float current_xp_percent = ((float)GetXP()/(float)GetNeededXP())*100;
float miniding_min_percent = ((int)(current_xp_percent/10)+1)*10;
int32 mini_ding_pct = rule_manager.GetGlobalRule(R_Player, MiniDingPercentage)->GetInt32();
float miniding_min_percent = 0.0f;
if(mini_ding_pct < 10 || mini_ding_pct > 50) {
mini_ding_pct = 0;
}
else {
miniding_min_percent = ((int)(current_xp_percent/mini_ding_pct)+1)*mini_ding_pct;
}
while((xp_amount + GetXP()) >= GetNeededXP()){
if (!CheckLevelStatus(GetLevel() + 1)) {
if(GetClient()) {
@ -4518,7 +4525,7 @@ bool Player::AddXP(int32 xp_amount){
SetXP(GetXP() + xp_amount);
GetPlayerInfo()->CalculateXPPercentages();
current_xp_percent = ((float)GetXP()/(float)GetNeededXP())*100;
if(current_xp_percent >= miniding_min_percent){
if(miniding_min_percent > 0.0f && current_xp_percent >= miniding_min_percent){
if(GetClient() && rule_manager.GetGlobalRule(R_Spells, UseClassicSpellLevel)->GetInt8())
GetClient()->SendNewAdventureSpells(); // mini ding involves checking spells again in classic level settings
SetHP(GetTotalHP());
@ -4632,6 +4639,27 @@ bool Player::WasSpawnRemoved(Spawn* spawn){
return wasRemoved;
}
void Player::ResetSpawnPackets(int32 id) {
info_mutex.writelock(__FUNCTION__, __LINE__);
vis_mutex.writelock(__FUNCTION__, __LINE__);
pos_mutex.writelock(__FUNCTION__, __LINE__);
index_mutex.writelock(__FUNCTION__, __LINE__);
if (spawn_info_packet_list.count(id))
spawn_info_packet_list.erase(id);
if (spawn_pos_packet_list.count(id))
spawn_pos_packet_list.erase(id);
if (spawn_vis_packet_list.count(id))
spawn_vis_packet_list.erase(id);
index_mutex.releasewritelock(__FUNCTION__, __LINE__);
vis_mutex.releasewritelock(__FUNCTION__, __LINE__);
pos_mutex.releasewritelock(__FUNCTION__, __LINE__);
info_mutex.releasewritelock(__FUNCTION__, __LINE__);
}
void Player::RemoveSpawn(Spawn* spawn, bool delete_spawn)
{
LogWrite(PLAYER__DEBUG, 3, "Player", "Remove Spawn '%s' (%u)", spawn->GetName(), spawn->GetID());
@ -4664,10 +4692,9 @@ void Player::RemoveSpawn(Spawn* spawn, bool delete_spawn)
spawn_vis_packet_list.erase(id);
index_mutex.releasewritelock(__FUNCTION__, __LINE__);
info_mutex.releasewritelock(__FUNCTION__, __LINE__);
pos_mutex.releasewritelock(__FUNCTION__, __LINE__);
vis_mutex.releasewritelock(__FUNCTION__, __LINE__);
info_mutex.releasewritelock(__FUNCTION__, __LINE__);
}
vector<int32> Player::GetQuestIDs(){

View File

@ -624,7 +624,7 @@ public:
float CalculateTSXP(int8 level);
void CalculateOfflineDebtRecovery(int32 unix_timestamp);
void InCombat(bool val, bool range = false);
void PrepareIncomingMovementPacket(int32 len, uchar* data, int16 version);
void PrepareIncomingMovementPacket(int32 len, uchar* data, int16 version, bool dead_window_sent = false);
uchar* GetMovementPacketData(){
return movement_packet;
}
@ -655,6 +655,7 @@ public:
Spawn* GetSpawnByIndex(int16 index);
int16 GetIndexForSpawn(Spawn* spawn);
bool WasSpawnRemoved(Spawn* spawn);
void ResetSpawnPackets(int32 id);
void RemoveSpawn(Spawn* spawn, bool delete_spawn = true);
bool ShouldSendSpawn(Spawn* spawn);
Client* client = 0;

View File

@ -243,6 +243,10 @@ void RuleManager::Init()
RULE_INIT(R_Player, HarvestSkillUpMultiplier, "2.0"); /* multiplier for node to take the "min skill" max and use a multiplier to offset the max skill allowed to skill up on node.
** Eg. 50 min skill on node, 50*1.5=75, no one with higher than 75 skill gets a skill up
*/
RULE_INIT(R_Player, MiniDingPercentage, "10"); /* Mini ding percentage for EverQuest 2, eg. default is every 10% (triggers at 10%, 20%, 30%, 40%, 50%, .. so on). setting 20% (triggers at 20%, 40%, 60%, 80%)
** Setting to less than 10 or greater than 50 will disable completely
** Range supported is 10 - 50%.
**/
/* PVP */
RULE_INIT(R_PVP, AllowPVP, "0");
RULE_INIT(R_PVP, LevelRange, "4");

View File

@ -101,6 +101,7 @@ enum RuleType {
MaxTargetCommandDistance,
MinSkillMultiplierValue,
HarvestSkillUpMultiplier,
MiniDingPercentage,
/* PVP */
AllowPVP,

View File

@ -184,6 +184,11 @@ Client::Client(EQStream* ieqs) : underworld_cooldown_timer(5000), pos_update(125
lua_debug = false;
ready_for_spawns = false;
ready_for_updates = false;
dead_window_sent = false;
dead_x = 0.0f;
dead_y = 0.0f;
dead_z = 0.0f;
dead_h = 0.0f;
lua_debug_timer.Disable();
transport_spawn = 0;
MBuyBack.SetName("Client::MBuyBack");
@ -478,7 +483,7 @@ void Client::SendPlayerDeathWindow()
vector<RevivePoint*>* results = GetCurrentZone()->GetRevivePoints(this);
vector<RevivePoint*>::iterator itr;
if (results && results->size() > 0)
if (results && results->size() > 0) // we always populate a safe point if there is no revive point
{
PacketStruct* packet = configReader.getStruct("WS_DeathWindow", GetVersion());
if (packet)
@ -543,12 +548,18 @@ void Client::DisplayDeadWindow()
safe_delete(packet);
}
SendPlayerDeathWindow();
dead_x = player->GetX();
dead_y = player->GetY();
dead_z = player->GetZ();
dead_window_sent = true;
SendPlayerDeathWindow();
}
void Client::HandlePlayerRevive(int32 point_id)
{
dead_window_sent = false;
if (GetVersion() <= 561) {
ClientPacketFunctions::SendServerControlFlagsClassic(this, 8, 0);
ClientPacketFunctions::SendServerControlFlagsClassic(this, 16, 0);
@ -845,9 +856,6 @@ void Client::SendCharInfo() {
safe_delete(items);
if (!player->Alive())
DisplayDeadWindow();
ClientPacketFunctions::SendLocalizedTextMessage(this);
if (GetCurrentZone()->GetInstanceID())
@ -1935,6 +1943,9 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
lua_interface->RunZoneScript(zone_script, "enter_location", GetPlayer()->GetZone(), GetPlayer(), GetPlayer()->GetLocation());
}
if (!GetPlayer()->Alive())
DisplayDeadWindow();
if (GetPlayer()->GetHP() < GetPlayer()->GetTotalHP() || GetPlayer()->GetPower() < GetPlayer()->GetTotalPower())
GetCurrentZone()->AddDamagedSpawn(GetPlayer());
}
@ -2089,13 +2100,13 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
float x = player->GetX();
float y = player->GetY();
float z = player->GetZ();
player->PrepareIncomingMovementPacket(app->size - offset, app->pBuffer + offset, version);
player->PrepareIncomingMovementPacket(app->size - offset, app->pBuffer + offset, version, dead_window_sent);
distance = player->GetDistance(x, y, z, false);
if (distance > .5)
current_zone->Interrupted(player, 0, SPELL_ERROR_INTERRUPTED, false, true);
}
else
player->PrepareIncomingMovementPacket(app->size - offset, app->pBuffer + offset, version);
player->PrepareIncomingMovementPacket(app->size - offset, app->pBuffer + offset, version, dead_window_sent);
player_pos_changed = true;
GetPlayer()->changed = true;
@ -2144,13 +2155,13 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
float x = player->GetX();
float y = player->GetY();
float z = player->GetZ();
player->PrepareIncomingMovementPacket(app->size - offset, app->pBuffer + offset, version);
player->PrepareIncomingMovementPacket(app->size - offset, app->pBuffer + offset, version, dead_window_sent);
distance = player->GetDistance(x, y, z, false);
if (distance > .5)
current_zone->Interrupted(player, 0, SPELL_ERROR_INTERRUPTED, false, true);
}
else
player->PrepareIncomingMovementPacket(app->size - offset, app->pBuffer + offset, version);
player->PrepareIncomingMovementPacket(app->size - offset, app->pBuffer + offset, version, dead_window_sent);
player_pos_changed = true;
GetPlayer()->changed = true;

View File

@ -782,6 +782,11 @@ private:
bool connected;
std::atomic<bool> ready_for_spawns;
std::atomic<bool> ready_for_updates;
std::atomic<bool> dead_window_sent;
float dead_x;
float dead_y;
float dead_z;
float dead_h;
bool seencharsel;
bool connected_to_zone;