diff --git a/source/WorldServer/Player.cpp b/source/WorldServer/Player.cpp index d203c53..feb52b8 100644 --- a/source/WorldServer/Player.cpp +++ b/source/WorldServer/Player.cpp @@ -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 Player::GetQuestIDs(){ diff --git a/source/WorldServer/Player.h b/source/WorldServer/Player.h index 4a1d03f..cb1a499 100644 --- a/source/WorldServer/Player.h +++ b/source/WorldServer/Player.h @@ -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; diff --git a/source/WorldServer/Rules/Rules.cpp b/source/WorldServer/Rules/Rules.cpp index 16ccbc2..3e7298c 100644 --- a/source/WorldServer/Rules/Rules.cpp +++ b/source/WorldServer/Rules/Rules.cpp @@ -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"); diff --git a/source/WorldServer/Rules/Rules.h b/source/WorldServer/Rules/Rules.h index abb1c40..bc1a1f9 100644 --- a/source/WorldServer/Rules/Rules.h +++ b/source/WorldServer/Rules/Rules.h @@ -101,6 +101,7 @@ enum RuleType { MaxTargetCommandDistance, MinSkillMultiplierValue, HarvestSkillUpMultiplier, + MiniDingPercentage, /* PVP */ AllowPVP, diff --git a/source/WorldServer/client.cpp b/source/WorldServer/client.cpp index 4c3a9c8..4453faa 100644 --- a/source/WorldServer/client.cpp +++ b/source/WorldServer/client.cpp @@ -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* results = GetCurrentZone()->GetRevivePoints(this); vector::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) @@ -542,13 +547,19 @@ void Client::DisplayDeadWindow() QueuePacket(packet->serialize()); safe_delete(packet); } - + + 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()) @@ -1934,6 +1942,9 @@ bool Client::HandlePacket(EQApplicationPacket* app) { if (zone_script && lua_interface) { 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; diff --git a/source/WorldServer/client.h b/source/WorldServer/client.h index 3f0b948..7752663 100644 --- a/source/WorldServer/client.h +++ b/source/WorldServer/client.h @@ -782,6 +782,11 @@ private: bool connected; std::atomic ready_for_spawns; std::atomic ready_for_updates; + std::atomic dead_window_sent; + float dead_x; + float dead_y; + float dead_z; + float dead_h; bool seencharsel; bool connected_to_zone;