diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 976753bb2..41fc9528a 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -617,7 +617,7 @@ struct NewZone_Struct { /*0704*/ char zone_short_name2[32]; //zone file name? excludes instance number which can be in previous version. /*0736*/ char WeatherString[32]; /*0768*/ char SkyString2[32]; - /*0800*/ int32 SkyRelated2; //seen -1 + /*0800*/ int32 SkyRelated2; //seen -1 -- maybe some default sky time? /*0804*/ char WeatherString2[32]; // /*0836*/ float WeatherChangeTime; // not sure :P /*0840*/ uint32 Climate; diff --git a/common/ruletypes.h b/common/ruletypes.h index a51a224b0..529c7d239 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -563,6 +563,8 @@ RULE_INT(Range, DamageMessages, 50) RULE_INT(Range, SpellMessages, 75) RULE_INT(Range, SongMessages, 75) RULE_INT(Range, MobPositionUpdates, 600) +RULE_INT(Range, ClientPositionUpdates, 300) +RULE_INT(Range, ClientForceSpawnUpdateRange, 1000) RULE_INT(Range, CriticalDamage, 80) RULE_INT(Range, ClientNPCScan, 300) RULE_CATEGORY_END() diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index faccf9e48..e385b9f9e 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -357,7 +357,7 @@ 9101|2016_12_01_pcnpc_only.sql|SHOW COLUMNS FROM `spells_new` LIKE 'pcnpc_only_flag'|empty| 9102|2017_01_10_book_languages.sql|SHOW COLUMNS FROM `books` LIKE 'language'|empty| 9103|2017_01_30_book_languages_fix.sql|SELECT `language` from `books` WHERE `language` IS NULL|not_empty| -9104|2017_02_09_npc_spells_entries_type_update.sql|SHOW COLUMNS IN `npc_spells_entries` LIKE `type`|contains|smallint(5) unsigned +9104|2017_02_09_npc_spells_entries_type_update.sql|SHOW COLUMNS IN `npc_spells_entries` LIKE 'type'|contains|smallint(5) unsigned 9105|2017_02_15_bot_spells_entries.sql|SELECT `id` FROM `npc_spells_entries` WHERE `npc_spells_id` >= 701 AND `npc_spells_id` <= 712|not_empty| 9106|2017_02_26_npc_spells_update_for_bots.sql|SELECT * FROM `npc_spells` WHERE `id` = '701' AND `name` = 'Cleric Bot'|not_empty| 9107|2017_03_09_inventory_version.sql|SHOW TABLES LIKE 'inventory_version'|empty| diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 4406508fe..098de9eb9 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1003,6 +1003,15 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_RiposteChance: newbon->RiposteChance += base1; break; + case SE_DodgeChance: + newbon->DodgeChance += base1; + break; + case SE_ParryChance: + newbon->ParryChance += base1; + break; + case SE_IncreaseBlockChance: + newbon->IncreaseBlockChance += base1; + break; case SE_Flurry: newbon->FlurryChance += base1; break; @@ -2495,7 +2504,12 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; case SE_IncreaseBlockChance: - new_bonus->IncreaseBlockChance += effect_value; + if (AdditiveWornBonus) + new_bonus->IncreaseBlockChance += effect_value; + else if (effect_value < 0 && new_bonus->IncreaseBlockChance > effect_value) + new_bonus->IncreaseBlockChance = effect_value; + else if (new_bonus->IncreaseBlockChance < effect_value) + new_bonus->IncreaseBlockChance = effect_value; break; case SE_PersistantCasting: diff --git a/zone/client.h b/zone/client.h index a34bb8e72..58c7ad4c4 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1489,7 +1489,9 @@ private: Timer hp_self_update_throttle_timer; /* This is to prevent excessive packet sending under trains/fast combat */ Timer hp_other_update_throttle_timer; /* This is to keep clients from DOSing the server with macros that change client targets constantly */ Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */ - glm::vec3 m_Proximity; + + glm::vec3 m_Proximity; + glm::vec4 last_major_update_position; void BulkSendInventoryItems(); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 27c4d2c50..8a23b6996 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4635,7 +4635,19 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) entity_list.QueueClientsStatus(this, outapp, true, Admin(), 250); } else { - entity_list.QueueCloseClients(this, outapp, true, 300, nullptr, true); + entity_list.QueueCloseClients(this, outapp, true, RuleI(Range, ClientPositionUpdates), nullptr, true); + } + + + /* Always send position updates to group - send when beyond normal ClientPositionUpdate range */ + Group *group = this->GetGroup(); + Raid *raid = this->GetRaid(); + + if (raid) { + raid->QueueClients(this, outapp, true, true, (RuleI(Range, ClientPositionUpdates) * -1)); + } + else if (group) { + group->QueueClients(this, outapp, true, true, (RuleI(Range, ClientPositionUpdates) * -1)); } safe_delete(outapp); @@ -10932,592 +10944,614 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) return; } - RaidGeneral_Struct *ri = (RaidGeneral_Struct*)app->pBuffer; - switch (ri->action) + RaidGeneral_Struct *raid_command_packet = (RaidGeneral_Struct*)app->pBuffer; + switch (raid_command_packet->action) { - case RaidCommandInviteIntoExisting: - case RaidCommandInvite: { - Client *i = entity_list.GetClientByName(ri->player_name); - if (!i) - break; - Group *g = i->GetGroup(); - // These two messages should be generated by the client I think, just do this for now - if (i->HasRaid()) { - Message(13, "%s is already in a raid.", i->GetName()); + case RaidCommandInviteIntoExisting: + case RaidCommandInvite: { + + Client *player_to_invite = entity_list.GetClientByName(raid_command_packet->player_name); + + if (!player_to_invite) + break; + + Group *player_to_invite_group = player_to_invite->GetGroup(); + + if (player_to_invite->HasRaid()) { + Message(13, "%s is already in a raid.", player_to_invite->GetName()); + break; + } + + if (player_to_invite_group && !player_to_invite_group->IsLeader(player_to_invite)) { + Message(13, "You can only invite an ungrouped player or group leader to join your raid."); + break; + } + + /* Send out invite to the client */ + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); + RaidGeneral_Struct *raid_command = (RaidGeneral_Struct*)outapp->pBuffer; + + strn0cpy(raid_command->leader_name, raid_command_packet->leader_name, 64); + strn0cpy(raid_command->player_name, raid_command_packet->player_name, 64); + + raid_command->parameter = 0; + raid_command->action = 20; + + player_to_invite->QueuePacket(outapp); + + safe_delete(outapp); + break; } - if (g && !g->IsLeader(i)) { - Message(13, "You can only invite an ungrouped player or group leader to join your raid."); - break; - } - //This sends an "invite" to the client in question. - auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); - RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer; - strn0cpy(rg->leader_name, ri->leader_name, 64); - strn0cpy(rg->player_name, ri->player_name, 64); - - rg->parameter = 0; - rg->action = 20; - i->QueuePacket(outapp); - safe_delete(outapp); - break; - } - case RaidCommandAcceptInvite: { - Client *i = entity_list.GetClientByName(ri->player_name); - if (i) { - if (IsRaidGrouped()) { - i->Message_StringID(0, ALREADY_IN_RAID, GetName()); //group failed, must invite members not in raid... - return; - } - Raid *r = entity_list.GetRaidByClient(i); - if (r) { - r->VerifyRaid(); - Group *g = GetGroup(); - if (g) { - if (g->GroupCount() + r->RaidCount() > MAX_RAID_MEMBERS) - { - i->Message(13, "Invite failed, group invite would create a raid larger than the maximum number of members allowed."); - return; - } + case RaidCommandAcceptInvite: { + Client *player_accepting_invite = entity_list.GetClientByName(raid_command_packet->player_name); + if (player_accepting_invite) { + if (IsRaidGrouped()) { + player_accepting_invite->Message_StringID(0, ALREADY_IN_RAID, GetName()); //group failed, must invite members not in raid... + return; } - else { - if (1 + r->RaidCount() > MAX_RAID_MEMBERS) - { - i->Message(13, "Invite failed, member invite would create a raid larger than the maximum number of members allowed."); - return; - } - } - if (g) {//add us all - uint32 freeGroup = r->GetFreeGroup(); - Client *addClient = nullptr; - for (int x = 0; x < 6; x++) - { - if (g->members[x]) { - Client *c = nullptr; - if (g->members[x]->IsClient()) - c = g->members[x]->CastToClient(); - else - continue; - - if (!addClient) - { - addClient = c; - r->SetGroupLeader(addClient->GetName()); - } - - r->SendRaidCreate(c); - r->SendMakeLeaderPacketTo(r->leadername, c); - if (g->IsLeader(g->members[x])) - r->AddMember(c, freeGroup, false, true); - else - r->AddMember(c, freeGroup); - r->SendBulkRaid(c); - if (r->IsLocked()) { - r->SendRaidLockTo(c); - } + Raid *raid = entity_list.GetRaidByClient(player_accepting_invite); + if (raid) { + raid->VerifyRaid(); + Group *group = GetGroup(); + if (group) { + if (group->GroupCount() + raid->RaidCount() > MAX_RAID_MEMBERS) { + player_accepting_invite->Message(13, "Invite failed, group invite would create a raid larger than the maximum number of members allowed."); + return; } } - g->JoinRaidXTarget(r); - g->DisbandGroup(true); - r->GroupUpdate(freeGroup); - } - else { - r->SendRaidCreate(this); - r->SendMakeLeaderPacketTo(r->leadername, this); - r->AddMember(this); - r->SendBulkRaid(this); - if (r->IsLocked()) { - r->SendRaidLockTo(this); - } - } - } - else - { - Group *ig = i->GetGroup(); - Group *g = GetGroup(); - if (g) //if our target has a group - { - r = new Raid(i); - entity_list.AddRaid(r); - r->SetRaidDetails(); - - uint32 groupFree = r->GetFreeGroup(); //get a free group - if (ig) { //if we already have a group then cycle through adding us... - Client *addClientig = nullptr; - for (int x = 0; x < 6; x++) - { - if (ig->members[x]) { - if (!addClientig) { - if (ig->members[x]->IsClient()) { - addClientig = ig->members[x]->CastToClient(); - r->SetGroupLeader(addClientig->GetName()); - } - } - if (ig->IsLeader(ig->members[x])) { - Client *c = nullptr; - if (ig->members[x]->IsClient()) - c = ig->members[x]->CastToClient(); - else - continue; - r->SendRaidCreate(c); - r->SendMakeLeaderPacketTo(r->leadername, c); - r->AddMember(c, groupFree, true, true, true); - r->SendBulkRaid(c); - if (r->IsLocked()) { - r->SendRaidLockTo(c); - } - } - else { - Client *c = nullptr; - if (ig->members[x]->IsClient()) - c = ig->members[x]->CastToClient(); - else - continue; - r->SendRaidCreate(c); - r->SendMakeLeaderPacketTo(r->leadername, c); - r->AddMember(c, groupFree); - r->SendBulkRaid(c); - if (r->IsLocked()) { - r->SendRaidLockTo(c); - } - } - } + else { + if (1 + raid->RaidCount() > MAX_RAID_MEMBERS) { + player_accepting_invite->Message(13, "Invite failed, member invite would create a raid larger than the maximum number of members allowed."); + return; } - ig->JoinRaidXTarget(r, true); - ig->DisbandGroup(true); - r->GroupUpdate(groupFree); - groupFree = r->GetFreeGroup(); } - else { //else just add the inviter - r->SendRaidCreate(i); - r->AddMember(i, 0xFFFFFFFF, true, false, true); - } - - Client *addClient = nullptr; - //now add the existing group - for (int x = 0; x < 6; x++) - { - if (g->members[x]) { - if (!addClient) - { - if (g->members[x]->IsClient()) { - addClient = g->members[x]->CastToClient(); - r->SetGroupLeader(addClient->GetName()); - } - } - if (g->IsLeader(g->members[x])) - { + if (group) {//add us all + uint32 free_group_id = raid->GetFreeGroup(); + Client *addClient = nullptr; + for (int x = 0; x < 6; x++) { + if (group->members[x]) { Client *c = nullptr; - if (g->members[x]->IsClient()) - c = g->members[x]->CastToClient(); + if (group->members[x]->IsClient()) + c = group->members[x]->CastToClient(); else continue; - r->SendRaidCreate(c); - r->SendMakeLeaderPacketTo(r->leadername, c); - r->AddMember(c, groupFree, false, true); - r->SendBulkRaid(c); - if (r->IsLocked()) { - r->SendRaidLockTo(c); - } - } - else - { - Client *c = nullptr; - if (g->members[x]->IsClient()) - c = g->members[x]->CastToClient(); - else - continue; - r->SendRaidCreate(c); - r->SendMakeLeaderPacketTo(r->leadername, c); - r->AddMember(c, groupFree); - r->SendBulkRaid(c); - if (r->IsLocked()) { - r->SendRaidLockTo(c); - } - } - } - } - g->JoinRaidXTarget(r); - g->DisbandGroup(true); - r->GroupUpdate(groupFree); - } - else // target does not have a group - { - if (ig) { - r = new Raid(i); - entity_list.AddRaid(r); - r->SetRaidDetails(); - Client *addClientig = nullptr; - for (int x = 0; x < 6; x++) - { - if (ig->members[x]) - { - if (!addClientig) { - if (ig->members[x]->IsClient()) { - addClientig = ig->members[x]->CastToClient(); - r->SetGroupLeader(addClientig->GetName()); - } - } - if (ig->IsLeader(ig->members[x])) + + if (!addClient) { + addClient = c; + raid->SetGroupLeader(addClient->GetName()); + } + + raid->SendRaidCreate(c); + raid->SendMakeLeaderPacketTo(raid->leadername, c); + if (group->IsLeader(group->members[x])) + raid->AddMember(c, free_group_id, false, true); + else + raid->AddMember(c, free_group_id); + raid->SendBulkRaid(c); + if (raid->IsLocked()) { + raid->SendRaidLockTo(c); + } + } + } + group->JoinRaidXTarget(raid); + group->DisbandGroup(true); + raid->GroupUpdate(free_group_id); + } + else { + raid->SendRaidCreate(this); + raid->SendMakeLeaderPacketTo(raid->leadername, this); + raid->AddMember(this); + raid->SendBulkRaid(this); + if (raid->IsLocked()) { + raid->SendRaidLockTo(this); + } + } + } + else + { + Group *player_invited_group = player_accepting_invite->GetGroup(); + Group *group = GetGroup(); + if (group) //if our target has a group + { + raid = new Raid(player_accepting_invite); + entity_list.AddRaid(raid); + raid->SetRaidDetails(); + + uint32 raid_free_group_id = raid->GetFreeGroup(); + + /* If we already have a group then cycle through adding us... */ + if (player_invited_group) { + Client *client_to_be_leader = nullptr; + for (int x = 0; x < 6; x++) { + if (player_invited_group->members[x]) { + if (!client_to_be_leader) { + if (player_invited_group->members[x]->IsClient()) { + client_to_be_leader = player_invited_group->members[x]->CastToClient(); + raid->SetGroupLeader(client_to_be_leader->GetName()); + } + } + if (player_invited_group->IsLeader(player_invited_group->members[x])) { + Client *c = nullptr; + + if (player_invited_group->members[x]->IsClient()) + c = player_invited_group->members[x]->CastToClient(); + else + continue; + + raid->SendRaidCreate(c); + raid->SendMakeLeaderPacketTo(raid->leadername, c); + raid->AddMember(c, raid_free_group_id, true, true, true); + raid->SendBulkRaid(c); + + if (raid->IsLocked()) { + raid->SendRaidLockTo(c); + } + } + else { + Client *c = nullptr; + + if (player_invited_group->members[x]->IsClient()) + c = player_invited_group->members[x]->CastToClient(); + else + continue; + + raid->SendRaidCreate(c); + raid->SendMakeLeaderPacketTo(raid->leadername, c); + raid->AddMember(c, raid_free_group_id); + raid->SendBulkRaid(c); + + if (raid->IsLocked()) { + raid->SendRaidLockTo(c); + } + } + } + } + player_invited_group->JoinRaidXTarget(raid, true); + player_invited_group->DisbandGroup(true); + raid->GroupUpdate(raid_free_group_id); + raid_free_group_id = raid->GetFreeGroup(); + } + else { + raid->SendRaidCreate(player_accepting_invite); + raid->AddMember(player_accepting_invite, 0xFFFFFFFF, true, false, true); + } + + Client *client_to_add = nullptr; + /* Add client to an existing group */ + for (int x = 0; x < 6; x++) { + if (group->members[x]) { + if (!client_to_add) { + if (group->members[x]->IsClient()) { + client_to_add = group->members[x]->CastToClient(); + raid->SetGroupLeader(client_to_add->GetName()); + } + } + if (group->IsLeader(group->members[x])) { Client *c = nullptr; - if (ig->members[x]->IsClient()) - c = ig->members[x]->CastToClient(); + + if (group->members[x]->IsClient()) + c = group->members[x]->CastToClient(); else continue; - - r->SendRaidCreate(c); - r->SendMakeLeaderPacketTo(r->leadername, c); - r->AddMember(c, 0, true, true, true); - r->SendBulkRaid(c); - if (r->IsLocked()) { - r->SendRaidLockTo(c); + + raid->SendRaidCreate(c); + raid->SendMakeLeaderPacketTo(raid->leadername, c); + raid->AddMember(c, raid_free_group_id, false, true); + raid->SendBulkRaid(c); + + if (raid->IsLocked()) { + raid->SendRaidLockTo(c); } } else { Client *c = nullptr; - if (ig->members[x]->IsClient()) - c = ig->members[x]->CastToClient(); + + if (group->members[x]->IsClient()) + c = group->members[x]->CastToClient(); else continue; - - r->SendRaidCreate(c); - r->SendMakeLeaderPacketTo(r->leadername, c); - r->AddMember(c, 0); - r->SendBulkRaid(c); - if (r->IsLocked()) { - r->SendRaidLockTo(c); + + raid->SendRaidCreate(c); + raid->SendMakeLeaderPacketTo(raid->leadername, c); + raid->AddMember(c, raid_free_group_id); + raid->SendBulkRaid(c); + + if (raid->IsLocked()) { + raid->SendRaidLockTo(c); } } } } - r->SendRaidCreate(this); - r->SendMakeLeaderPacketTo(r->leadername, this); - r->SendBulkRaid(this); - ig->JoinRaidXTarget(r, true); - r->AddMember(this); - ig->DisbandGroup(true); - r->GroupUpdate(0); - if (r->IsLocked()) { - r->SendRaidLockTo(this); - } + group->JoinRaidXTarget(raid); + group->DisbandGroup(true); + + raid->GroupUpdate(raid_free_group_id); } - else { // neither has a group - r = new Raid(i); - entity_list.AddRaid(r); - r->SetRaidDetails(); - r->SendRaidCreate(i); - r->SendRaidCreate(this); - r->SendMakeLeaderPacketTo(r->leadername, this); - r->AddMember(i, 0xFFFFFFFF, true, false, true); - r->SendBulkRaid(this); - r->AddMember(this); - if (r->IsLocked()) { - r->SendRaidLockTo(this); + /* Target does not have a group */ + else { + if (player_invited_group) { + + raid = new Raid(player_accepting_invite); + + entity_list.AddRaid(raid); + raid->SetRaidDetails(); + Client *addClientig = nullptr; + for (int x = 0; x < 6; x++) { + if (player_invited_group->members[x]) { + if (!addClientig) { + if (player_invited_group->members[x]->IsClient()) { + addClientig = player_invited_group->members[x]->CastToClient(); + raid->SetGroupLeader(addClientig->GetName()); + } + } + if (player_invited_group->IsLeader(player_invited_group->members[x])) { + Client *c = nullptr; + + if (player_invited_group->members[x]->IsClient()) + c = player_invited_group->members[x]->CastToClient(); + else + continue; + + raid->SendRaidCreate(c); + raid->SendMakeLeaderPacketTo(raid->leadername, c); + raid->AddMember(c, 0, true, true, true); + raid->SendBulkRaid(c); + + if (raid->IsLocked()) { + raid->SendRaidLockTo(c); + } + } + else + { + Client *c = nullptr; + if (player_invited_group->members[x]->IsClient()) + c = player_invited_group->members[x]->CastToClient(); + else + continue; + + raid->SendRaidCreate(c); + raid->SendMakeLeaderPacketTo(raid->leadername, c); + raid->AddMember(c, 0); + raid->SendBulkRaid(c); + if (raid->IsLocked()) { + raid->SendRaidLockTo(c); + } + } + } + } + raid->SendRaidCreate(this); + raid->SendMakeLeaderPacketTo(raid->leadername, this); + raid->SendBulkRaid(this); + player_invited_group->JoinRaidXTarget(raid, true); + raid->AddMember(this); + player_invited_group->DisbandGroup(true); + raid->GroupUpdate(0); + if (raid->IsLocked()) { + raid->SendRaidLockTo(this); + } + } + else { // neither has a group + raid = new Raid(player_accepting_invite); + entity_list.AddRaid(raid); + raid->SetRaidDetails(); + raid->SendRaidCreate(player_accepting_invite); + raid->SendRaidCreate(this); + raid->SendMakeLeaderPacketTo(raid->leadername, this); + raid->AddMember(player_accepting_invite, 0xFFFFFFFF, true, false, true); + raid->SendBulkRaid(this); + raid->AddMember(this); + if (raid->IsLocked()) { + raid->SendRaidLockTo(this); + } } } } } + break; } - break; - } - case RaidCommandDisband: { - Raid *r = entity_list.GetRaidByClient(this); - if (r) { - //if(this == r->GetLeader()){ - uint32 grp = r->GetGroup(ri->leader_name); + case RaidCommandDisband: { + Raid *raid = entity_list.GetRaidByClient(this); + if (raid) { + uint32 group = raid->GetGroup(raid_command_packet->leader_name); - if (grp < 12) { - uint32 i = r->GetPlayerIndex(ri->leader_name); - if (r->members[i].IsGroupLeader) { //assign group leader to someone else - for (int x = 0; x < MAX_RAID_MEMBERS; x++) { - if (strlen(r->members[x].membername) > 0 && i != x) { - if (r->members[x].GroupNumber == grp) { - r->SetGroupLeader(ri->leader_name, false); - r->SetGroupLeader(r->members[x].membername); - r->UpdateGroupAAs(grp); + if (group < 12) { + uint32 i = raid->GetPlayerIndex(raid_command_packet->leader_name); + if (raid->members[i].IsGroupLeader) { //assign group leader to someone else + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + if (strlen(raid->members[x].membername) > 0 && i != x) { + if (raid->members[x].GroupNumber == group) { + raid->SetGroupLeader(raid_command_packet->leader_name, false); + raid->SetGroupLeader(raid->members[x].membername); + raid->UpdateGroupAAs(group); + break; + } + } + } + + } + if (raid->members[i].IsRaidLeader) { + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + if (strlen(raid->members[x].membername) > 0 && strcmp(raid->members[x].membername, raid->members[i].membername) != 0) + { + raid->SetRaidLeader(raid->members[i].membername, raid->members[x].membername); + raid->UpdateRaidAAs(); + raid->SendAllRaidLeadershipAA(); break; } } } - } - if (r->members[i].IsRaidLeader) { - for (int x = 0; x < MAX_RAID_MEMBERS; x++) { - if (strlen(r->members[x].membername) > 0 && strcmp(r->members[x].membername, r->members[i].membername) != 0) - { - r->SetRaidLeader(r->members[i].membername, r->members[x].membername); - r->UpdateRaidAAs(); - r->SendAllRaidLeadershipAA(); - break; - } - } - } - } - r->RemoveMember(ri->leader_name); - Client *c = entity_list.GetClientByName(ri->leader_name); - if (c) - r->SendGroupDisband(c); - else { - auto pack = - new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct* rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - rga->rid = GetID(); - rga->zoneid = zone->GetZoneID(); - rga->instance_id = zone->GetInstanceID(); - strn0cpy(rga->playername, ri->leader_name, 64); - worldserver.SendPacket(pack); - safe_delete(pack); + raid->RemoveMember(raid_command_packet->leader_name); + Client *c = entity_list.GetClientByName(raid_command_packet->leader_name); + if (c) + raid->SendGroupDisband(c); + else { + auto pack = + new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); + ServerRaidGeneralAction_Struct* rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; + rga->rid = GetID(); + rga->zoneid = zone->GetZoneID(); + rga->instance_id = zone->GetInstanceID(); + strn0cpy(rga->playername, raid_command_packet->leader_name, 64); + worldserver.SendPacket(pack); + safe_delete(pack); + } + //r->SendRaidGroupRemove(ri->leader_name, grp); + raid->GroupUpdate(group);// break + //} } - //r->SendRaidGroupRemove(ri->leader_name, grp); - r->GroupUpdate(grp);// break - //} + break; } - break; - } - case RaidCommandMoveGroup: - { - Raid *r = entity_list.GetRaidByClient(this); - if (r) + case RaidCommandMoveGroup: { - if (ri->parameter < 12) //moving to a group - { - uint8 grpcount = r->GroupCount(ri->parameter); + Raid *raid = entity_list.GetRaidByClient(this); + if (raid) { + /* Moving to group */ + if (raid_command_packet->parameter < 12) { + uint8 group_count = raid->GroupCount(raid_command_packet->parameter); - if (grpcount < 6) - { - Client *c = entity_list.GetClientByName(ri->leader_name); - uint32 oldgrp = r->GetGroup(ri->leader_name); - if (ri->parameter == oldgrp) //don't rejoin grp if we order to join same group. - break; + if (group_count < 6) { + Client *c = entity_list.GetClientByName(raid_command_packet->leader_name); + uint32 old_group = raid->GetGroup(raid_command_packet->leader_name); + if (raid_command_packet->parameter == old_group) //don't rejoin grp if we order to join same group. + break; - if (r->members[r->GetPlayerIndex(ri->leader_name)].IsGroupLeader) - { - r->SetGroupLeader(ri->leader_name, false); - if (oldgrp < 12) { //we were the leader of our old grp - for (int x = 0; x < MAX_RAID_MEMBERS; x++) //assign a new grp leader if we can - { - if (r->members[x].GroupNumber == oldgrp) - { - if (strcmp(ri->leader_name, r->members[x].membername) != 0 && strlen(ri->leader_name) > 0) - { - r->SetGroupLeader(r->members[x].membername); - r->UpdateGroupAAs(oldgrp); - Client *cgl = entity_list.GetClientByName(r->members[x].membername); - if (cgl) { - r->SendRaidRemove(r->members[x].membername, cgl); - r->SendRaidCreate(cgl); - r->SendMakeLeaderPacketTo(r->leadername, cgl); - r->SendRaidAdd(r->members[x].membername, cgl); - r->SendBulkRaid(cgl); - if (r->IsLocked()) { - r->SendRaidLockTo(cgl); + if (raid->members[raid->GetPlayerIndex(raid_command_packet->leader_name)].IsGroupLeader) { + raid->SetGroupLeader(raid_command_packet->leader_name, false); + + /* We were the leader of our old group */ + if (old_group < 12) { + /* Assign new group leader if we can */ + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + if (raid->members[x].GroupNumber == old_group) { + if (strcmp(raid_command_packet->leader_name, raid->members[x].membername) != 0 && strlen(raid_command_packet->leader_name) > 0) { + raid->SetGroupLeader(raid->members[x].membername); + raid->UpdateGroupAAs(old_group); + + Client *client_to_update = entity_list.GetClientByName(raid->members[x].membername); + if (client_to_update) { + raid->SendRaidRemove(raid->members[x].membername, client_to_update); + raid->SendRaidCreate(client_to_update); + raid->SendMakeLeaderPacketTo(raid->leadername, client_to_update); + raid->SendRaidAdd(raid->members[x].membername, client_to_update); + raid->SendBulkRaid(client_to_update); + if (raid->IsLocked()) { + raid->SendRaidLockTo(client_to_update); + } } + else { + auto pack = new ServerPacket(ServerOP_RaidChangeGroup, sizeof(ServerRaidGeneralAction_Struct)); + ServerRaidGeneralAction_Struct *raid_command_packet = (ServerRaidGeneralAction_Struct*)pack->pBuffer; + + raid_command_packet->rid = raid->GetID(); + raid_command_packet->zoneid = zone->GetZoneID(); + raid_command_packet->instance_id = zone->GetInstanceID(); + strn0cpy(raid_command_packet->playername, raid->members[x].membername, 64); + + worldserver.SendPacket(pack); + + safe_delete(pack); + } + break; } - else { - auto pack = new ServerPacket( - ServerOP_RaidChangeGroup, - sizeof( - ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - rga->rid = r->GetID(); - strn0cpy(rga->playername, r->members[x].membername, 64); - rga->zoneid = zone->GetZoneID(); - rga->instance_id = zone->GetInstanceID(); - worldserver.SendPacket(pack); - safe_delete(pack); - } - break; } } } } - } - if (grpcount == 0) { - r->SetGroupLeader(ri->leader_name); - r->UpdateGroupAAs(ri->parameter); - } + if (group_count == 0) { + raid->SetGroupLeader(raid_command_packet->leader_name); + raid->UpdateGroupAAs(raid_command_packet->parameter); + } - r->MoveMember(ri->leader_name, ri->parameter); - if (c) { - r->SendGroupDisband(c); - } - else { - auto pack = new ServerPacket(ServerOP_RaidGroupDisband, - sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct* rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - rga->rid = r->GetID(); - rga->zoneid = zone->GetZoneID(); - rga->instance_id = zone->GetInstanceID(); - strn0cpy(rga->playername, ri->leader_name, 64); - worldserver.SendPacket(pack); - safe_delete(pack); - } - //r->SendRaidGroupAdd(ri->leader_name, ri->parameter); - //r->SendRaidGroupRemove(ri->leader_name, oldgrp); - //r->SendGroupUpdate(c); - //break - r->GroupUpdate(ri->parameter); //send group update to our new group - if (oldgrp < 12) //if our old was a group send update there too - r->GroupUpdate(oldgrp); + raid->MoveMember(raid_command_packet->leader_name, raid_command_packet->parameter); + if (c) { + raid->SendGroupDisband(c); + } + else { + auto pack = new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); + ServerRaidGeneralAction_Struct* raid_command = (ServerRaidGeneralAction_Struct*)pack->pBuffer; + raid_command->rid = raid->GetID(); + raid_command->zoneid = zone->GetZoneID(); + raid_command->instance_id = zone->GetInstanceID(); + strn0cpy(raid_command->playername, raid_command_packet->leader_name, 64); + worldserver.SendPacket(pack); + safe_delete(pack); + } - //r->SendMakeGroupLeaderPacketAll(); + /* Send group update to our new group */ + raid->GroupUpdate(raid_command_packet->parameter); + + /* If our old was a group send update there too */ + if (old_group < 12) + raid->GroupUpdate(old_group); + + } } - } - else //moving to ungrouped - { - Client *c = entity_list.GetClientByName(ri->leader_name); - uint32 oldgrp = r->GetGroup(ri->leader_name); - if (r->members[r->GetPlayerIndex(ri->leader_name)].IsGroupLeader) { - r->SetGroupLeader(ri->leader_name, false); - for (int x = 0; x < MAX_RAID_MEMBERS; x++) - { - if (r->members[x].GroupNumber == oldgrp && strlen(r->members[x].membername) > 0 && strcmp(r->members[x].membername, ri->leader_name) != 0) - { - r->SetGroupLeader(r->members[x].membername); - r->UpdateGroupAAs(oldgrp); - Client *cgl = entity_list.GetClientByName(r->members[x].membername); - if (cgl) { - r->SendRaidRemove(r->members[x].membername, cgl); - r->SendRaidCreate(cgl); - r->SendMakeLeaderPacketTo(r->leadername, cgl); - r->SendRaidAdd(r->members[x].membername, cgl); - r->SendBulkRaid(cgl); - if (r->IsLocked()) { - r->SendRaidLockTo(cgl); + /* Move player to ungrouped bank */ + else { + Client *c = entity_list.GetClientByName(raid_command_packet->leader_name); + uint32 oldgrp = raid->GetGroup(raid_command_packet->leader_name); + if (raid->members[raid->GetPlayerIndex(raid_command_packet->leader_name)].IsGroupLeader) { + raid->SetGroupLeader(raid_command_packet->leader_name, false); + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + if (raid->members[x].GroupNumber == oldgrp && strlen(raid->members[x].membername) > 0 && strcmp(raid->members[x].membername, raid_command_packet->leader_name) != 0){ + + raid->SetGroupLeader(raid->members[x].membername); + raid->UpdateGroupAAs(oldgrp); + + Client *client_leaving_group = entity_list.GetClientByName(raid->members[x].membername); + if (client_leaving_group) { + raid->SendRaidRemove(raid->members[x].membername, client_leaving_group); + raid->SendRaidCreate(client_leaving_group); + raid->SendMakeLeaderPacketTo(raid->leadername, client_leaving_group); + raid->SendRaidAdd(raid->members[x].membername, client_leaving_group); + raid->SendBulkRaid(client_leaving_group); + if (raid->IsLocked()) { + raid->SendRaidLockTo(client_leaving_group); + } } + else { + auto pack = new ServerPacket( ServerOP_RaidChangeGroup, sizeof(ServerRaidGeneralAction_Struct)); + ServerRaidGeneralAction_Struct *raid_command = (ServerRaidGeneralAction_Struct*)pack->pBuffer; + + raid_command->rid = raid->GetID(); + strn0cpy(raid_command->playername, raid->members[x].membername, 64); + raid_command->zoneid = zone->GetZoneID(); + raid_command->instance_id = zone->GetInstanceID(); + + worldserver.SendPacket(pack); + safe_delete(pack); + } + break; } - else { - auto pack = new ServerPacket( - ServerOP_RaidChangeGroup, - sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - rga->rid = r->GetID(); - strn0cpy(rga->playername, r->members[x].membername, 64); - rga->zoneid = zone->GetZoneID(); - rga->instance_id = zone->GetInstanceID(); - worldserver.SendPacket(pack); - safe_delete(pack); - } - break; } } + raid->MoveMember(raid_command_packet->leader_name, 0xFFFFFFFF); + if (c) { + raid->SendGroupDisband(c); + } + else { + auto pack = new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); + ServerRaidGeneralAction_Struct* raid_command = (ServerRaidGeneralAction_Struct*)pack->pBuffer; + + raid_command->rid = raid->GetID(); + raid_command->zoneid = zone->GetZoneID(); + raid_command->instance_id = zone->GetInstanceID(); + strn0cpy(raid_command->playername, raid_command_packet->leader_name, 64); + + worldserver.SendPacket(pack); + + safe_delete(pack); + } + + raid->GroupUpdate(oldgrp); } - r->MoveMember(ri->leader_name, 0xFFFFFFFF); - if (c) { - r->SendGroupDisband(c); - } - else { - auto pack = new ServerPacket(ServerOP_RaidGroupDisband, - sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct* rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - rga->rid = r->GetID(); - rga->zoneid = zone->GetZoneID(); - rga->instance_id = zone->GetInstanceID(); - strn0cpy(rga->playername, ri->leader_name, 64); - worldserver.SendPacket(pack); - safe_delete(pack); - } - //r->SendRaidGroupRemove(ri->leader_name, oldgrp); - r->GroupUpdate(oldgrp); - //r->SendMakeGroupLeaderPacketAll(); } - } - break; - } - case RaidCommandRaidLock: - { - Raid *r = entity_list.GetRaidByClient(this); - if (r) - { - if (!r->IsLocked()) - r->LockRaid(true); - else - r->SendRaidLockTo(this); - } - break; - } - case RaidCommandRaidUnlock: - { - Raid *r = entity_list.GetRaidByClient(this); - if (r) - { - if (r->IsLocked()) - r->LockRaid(false); - else - r->SendRaidUnlockTo(this); - } - break; - } - case RaidCommandLootType2: - case RaidCommandLootType: - { - Raid *r = entity_list.GetRaidByClient(this); - if (r) - { - Message(15, "Loot type changed to: %d.", ri->parameter); - r->ChangeLootType(ri->parameter); - } - break; - } - case RaidCommandAddLooter2: - case RaidCommandAddLooter: - { - Raid *r = entity_list.GetRaidByClient(this); - if (r) - { - Message(15, "Adding %s as a raid looter.", ri->leader_name); - r->AddRaidLooter(ri->leader_name); - } - break; - } + Client *client_moved = entity_list.GetClientByName(raid_command_packet->leader_name); - case RaidCommandRemoveLooter2: - case RaidCommandRemoveLooter: - { - Raid *r = entity_list.GetRaidByClient(this); - if (r) - { - Message(15, "Removing %s as a raid looter.", ri->leader_name); - r->RemoveRaidLooter(ri->leader_name); - } - break; - } + if (client_moved) { + client_moved->GetRaid()->SendHPManaEndPacketsTo(client_moved); + client_moved->GetRaid()->SendHPManaEndPacketsFrom(client_moved); - case RaidCommandMakeLeader: - { - Raid *r = entity_list.GetRaidByClient(this); - if (r) - { - if (strcmp(r->leadername, GetName()) == 0) { - r->SetRaidLeader(GetName(), ri->leader_name); - r->UpdateRaidAAs(); - r->SendAllRaidLeadershipAA(); + Log(Logs::General, Logs::HP_Update, + "Client::Handle_OP_RaidCommand :: %s sending and recieving HP/Mana/End updates", + client_moved->GetCleanName() + ); } - } - break; - } - case RaidCommandSetMotd: - { - Raid *r = entity_list.GetRaidByClient(this); - if (!r) break; - // we don't use the RaidGeneral here! - RaidMOTD_Struct *motd = (RaidMOTD_Struct *)app->pBuffer; - r->SetRaidMOTD(std::string(motd->motd)); - r->SaveRaidMOTD(); - r->SendRaidMOTDToWorld(); - break; - } + } + case RaidCommandRaidLock: + { + Raid *raid = entity_list.GetRaidByClient(this); + if (raid) { + if (!raid->IsLocked()) + raid->LockRaid(true); + else + raid->SendRaidLockTo(this); + } + break; + } + case RaidCommandRaidUnlock: + { + Raid *raid = entity_list.GetRaidByClient(this); + if (raid) + { + if (raid->IsLocked()) + raid->LockRaid(false); + else + raid->SendRaidUnlockTo(this); + } + break; + } + case RaidCommandLootType2: + case RaidCommandLootType: + { + Raid *raid = entity_list.GetRaidByClient(this); + if (raid) { + Message(15, "Loot type changed to: %d.", raid_command_packet->parameter); + raid->ChangeLootType(raid_command_packet->parameter); + } + break; + } - default: { - Message(13, "Raid command (%d) NYI", ri->action); - break; - } + case RaidCommandAddLooter2: + case RaidCommandAddLooter: + { + Raid *raid = entity_list.GetRaidByClient(this); + if (raid) { + Message(15, "Adding %s as a raid looter.", raid_command_packet->leader_name); + raid->AddRaidLooter(raid_command_packet->leader_name); + } + break; + } + + case RaidCommandRemoveLooter2: + case RaidCommandRemoveLooter: + { + Raid *raid = entity_list.GetRaidByClient(this); + if (raid) { + Message(15, "Removing %s as a raid looter.", raid_command_packet->leader_name); + raid->RemoveRaidLooter(raid_command_packet->leader_name); + } + break; + } + + case RaidCommandMakeLeader: + { + Raid *raid = entity_list.GetRaidByClient(this); + if (raid) { + if (strcmp(raid->leadername, GetName()) == 0) { + raid->SetRaidLeader(GetName(), raid_command_packet->leader_name); + raid->UpdateRaidAAs(); + raid->SendAllRaidLeadershipAA(); + } + } + break; + } + + case RaidCommandSetMotd: + { + Raid *raid = entity_list.GetRaidByClient(this); + if (!raid) + break; + // we don't use the RaidGeneral here! + RaidMOTD_Struct *motd = (RaidMOTD_Struct *)app->pBuffer; + raid->SetRaidMOTD(std::string(motd->motd)); + raid->SaveRaidMOTD(); + raid->SendRaidMOTDToWorld(); + break; + } + + default: { + Message(13, "Raid command (%d) NYI", raid_command_packet->action); + break; + } } } @@ -13352,10 +13386,9 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app) } QueuePacket(app); - EQApplicationPacket hp_app; + GetTarget()->IsTargeted(1); - GetTarget()->CreateHPPacket(&hp_app); - QueuePacket(&hp_app, false); + SendHPUpdate(); } else { diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 032e658b0..62921f6ce 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -243,15 +243,21 @@ bool Client::Process() { /* Build a close range list of NPC's */ if (npc_close_scan_timer.Check()) { - close_mobs.clear(); - auto &mob_list = entity_list.GetMobList(); - float scan_range = (RuleI(Range, ClientNPCScan) * RuleI(Range, ClientNPCScan)); - float client_update_range = (RuleI(Range, MobPositionUpdates) * RuleI(Range, MobPositionUpdates)); + /* Force spawn updates when traveled far */ + bool force_spawn_updates = false; + float client_update_range = (RuleI(Range, ClientForceSpawnUpdateRange) * RuleI(Range, ClientForceSpawnUpdateRange)); + if (DistanceSquared(last_major_update_position, m_Position) >= client_update_range) { + last_major_update_position = m_Position; + force_spawn_updates = true; + } + float scan_range = (RuleI(Range, ClientNPCScan) * RuleI(Range, ClientNPCScan)); + auto &mob_list = entity_list.GetMobList(); for (auto itr = mob_list.begin(); itr != mob_list.end(); ++itr) { Mob* mob = itr->second; + float distance = DistanceSquared(m_Position, mob->GetPosition()); if (mob->IsNPC()) { if (distance <= scan_range) { @@ -261,6 +267,10 @@ bool Client::Process() { close_mobs.insert(std::pair(mob, distance)); } } + + if (force_spawn_updates && mob != this && distance <= client_update_range) + mob->SendPositionUpdateToClient(this); + } } diff --git a/zone/command.cpp b/zone/command.cpp index ebf70d03e..ccdf55ec5 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -3894,6 +3894,8 @@ void command_depopzone(Client *c, const Seperator *sep) void command_repop(Client *c, const Seperator *sep) { int timearg = 1; + int delay = 0; + if (sep->arg[1] && strcasecmp(sep->arg[1], "force") == 0) { timearg++; @@ -3912,13 +3914,19 @@ void command_repop(Client *c, const Seperator *sep) } if (!sep->IsNumber(timearg)) { - c->Message(0, "Zone depoped. Repoping now."); + c->Message(0, "Zone depopped - repopping now."); + zone->Repop(); + + /* Force a spawn2 timer trigger so we don't delay actually spawning the NPC's */ + zone->spawn2_timer.Trigger(); return; } c->Message(0, "Zone depoped. Repop in %i seconds", atoi(sep->arg[timearg])); - zone->Repop(atoi(sep->arg[timearg])*1000); + zone->Repop(atoi(sep->arg[timearg]) * 1000); + + zone->spawn2_timer.Trigger(); } void command_repopclose(Client *c, const Seperator *sep) diff --git a/zone/effects.cpp b/zone/effects.cpp index adc7b16b2..2741a924b 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -613,7 +613,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { //Check the disc timer pTimerType DiscTimer = pTimerDisciplineReuseStart + spell.EndurTimerIndex; - if(!p_timers.Expired(&database, DiscTimer)) { + if(!p_timers.Expired(&database, DiscTimer, false)) { // lets not set the reuse timer in case CastSpell fails (or we would have to turn off the timer, but CastSpell will set it as well) /*char val1[20]={0};*/ //unused /*char val2[20]={0};*/ //unused uint32 remain = p_timers.GetRemainingTime(DiscTimer); diff --git a/zone/embperl.cpp b/zone/embperl.cpp index 71338c05a..bc20bd4ef 100644 --- a/zone/embperl.cpp +++ b/zone/embperl.cpp @@ -119,7 +119,7 @@ void Embperl::DoInit() { perl_run(my_perl); //a little routine we use a lot. - eval_pv("sub my_eval {eval $_[0];}", TRUE); //dies on error + eval_pv("sub my_eval { eval $_[0];}", TRUE); //dies on error //ruin the perl exit and command: eval_pv("sub my_exit {}",TRUE); @@ -149,7 +149,7 @@ void Embperl::DoInit() { //make a tieable class to capture IO and pass it into EQEMuLog eval_pv( "package EQEmuIO; " - "sub TIEHANDLE { my $me = bless {}, $_[0]; $me->PRINT('Creating '.$me); return($me); } " + "sub TIEHANDLE { my $me = bless {}, $_[0]; $me->PRINT('Creating '. $me); return($me); } " "sub WRITE { } " //dunno why I need to shift off fmt here, but it dosent like without it "sub PRINTF { my $me = shift; my $fmt = shift; $me->PRINT(sprintf($fmt, @_)); } " @@ -237,6 +237,7 @@ void Embperl::init_eval_file(void) { eval_pv( "our %Cache;" + "no warnings;" "use Symbol qw(delete_package);" "sub eval_file {" "my($package, $filename) = @_;" @@ -246,8 +247,9 @@ void Embperl::init_eval_file(void) "if(defined $Cache{$package}{mtime}&&$Cache{$package}{mtime} <= $mtime && !($package eq 'plugin')){" " return;" "} else {" - //we 'my' $filename,$mtime,$package,$sub to prevent them from changing our state up here. - " eval(\"package $package; my(\\$filename,\\$mtime,\\$package,\\$sub); \\$isloaded = 1; require '$filename'; \");" + // we 'my' $filename,$mtime,$package,$sub to prevent them from changing our state up here. + " eval(\"package $package; my(\\$filename,\\$mtime,\\$package,\\$sub); \\$isloaded = 1; require './$filename'; \");" + // " print $@ if $@;" /* "local *FH;open FH, $filename or die \"open '$filename' $!\";" "local($/) = undef;my $sub = ;close FH;" "my $eval = qq{package $package; sub handler { $sub; }};" diff --git a/zone/embxs.cpp b/zone/embxs.cpp index fe4a12aee..3816850db 100644 --- a/zone/embxs.cpp +++ b/zone/embxs.cpp @@ -99,6 +99,10 @@ XS(XS_EQEmuIO_PRINT) /* Strip newlines from log message 'str' */ *std::remove(str, str + strlen(str), '\n') = '\0'; + std::string log_string = str; + if (log_string.find("did not return a true") != std::string::npos) + return;; + int i; int pos = 0; int len = 0; diff --git a/zone/entity.cpp b/zone/entity.cpp index 5a2340e41..81c857d9d 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -648,6 +648,8 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue) parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0); + npc->FixZ(); + uint16 emoteid = npc->GetEmoteID(); if (emoteid != 0) npc->DoNPCEmote(ONSPAWN, emoteid); diff --git a/zone/groups.cpp b/zone/groups.cpp index c6fa6a978..d72b71c30 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -2464,3 +2464,30 @@ bool Group::HasRole(Mob *m, uint8 Role) return false; } +void Group::QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_required /*= true*/, bool ignore_sender /*= true*/, float distance /*= 0*/) { + if (sender && sender->IsClient()) { + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { + + if (!members[i]) + continue; + + if (ignore_sender && members[i] == sender) + continue; + + /* If we don't have a distance requirement - send to all members */ + if (distance == 0) { + members[i]->CastToClient()->QueuePacket(app, ack_required); + } + else { + /* If negative distance - we check if current distance is greater than X */ + if (distance <= 0 && DistanceSquared(sender->GetPosition(), members[i]->GetPosition()) >= (distance * distance)) { + members[i]->CastToClient()->QueuePacket(app, ack_required); + } + /* If positive distance - we check if current distance is less than X */ + else if (distance >= 0 && DistanceSquared(sender->GetPosition(), members[i]->GetPosition()) <= (distance * distance)) { + members[i]->CastToClient()->QueuePacket(app, ack_required); + } + } + } + } +} \ No newline at end of file diff --git a/zone/groups.h b/zone/groups.h index 79fb0d8b6..913a6c169 100644 --- a/zone/groups.h +++ b/zone/groups.h @@ -140,6 +140,7 @@ public: inline int GetLeadershipAA(int AAID) { return LeaderAbilities.ranks[AAID]; } void ClearAllNPCMarks(); void QueueHPPacketsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app); + void QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_required = true, bool ignore_sender = true, float distance = 0); void ChangeLeader(Mob* newleader); const char *GetClientNameByIndex(uint8 index); void UpdateXTargetMarkedNPC(uint32 Number, Mob *m); diff --git a/zone/mob.cpp b/zone/mob.cpp index e2ab820d3..a0b16c76c 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1375,7 +1375,7 @@ void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= fal if(IsClient()){ Raid *raid = entity_list.GetRaidByClient(CastToClient()); if (raid) - raid->SendHPPacketsFrom(this); + raid->SendHPManaEndPacketsFrom(this); } /* Pet - Update master - group and raid if exists */ @@ -1388,7 +1388,7 @@ void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= fal Raid *raid = entity_list.GetRaidByClient(GetOwner()->CastToClient()); if(raid) - raid->SendHPPacketsFrom(this); + raid->SendHPManaEndPacketsFrom(this); } /* Send to pet */ @@ -1447,6 +1447,20 @@ void Mob::SendPosition() { safe_delete(app); } +void Mob::SendPositionUpdateToClient(Client *client) { + auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + PlayerPositionUpdateServer_Struct* spawn_update = (PlayerPositionUpdateServer_Struct*)app->pBuffer; + + if(this->IsMoving()) + MakeSpawnUpdate(spawn_update); + else + MakeSpawnUpdateNoDelta(spawn_update); + + client->QueuePacket(app, false); + + safe_delete(app); +} + /* Position updates for mobs on the move */ void Mob::SendPositionUpdate(uint8 iSendToSelf) { auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); diff --git a/zone/mob.h b/zone/mob.h index 43f1765e0..25d32a16c 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -543,6 +543,7 @@ public: virtual void GMMove(float x, float y, float z, float heading = 0.01, bool SendUpdate = true); void SetDelta(const glm::vec4& delta); void SetTargetDestSteps(uint8 target_steps) { tar_ndx = target_steps; } + void SendPositionUpdateToClient(Client *client); void SendPositionUpdate(uint8 iSendToSelf = 0); void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu); void MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 6e5fd8c8f..6da1cffbb 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -997,10 +997,9 @@ void Mob::AI_Process() { if (this->GetTarget()) { /* If we are engaged, moving and following client, let's look for best Z more often */ float target_distance = DistanceNoZ(this->GetPosition(), this->GetTarget()->GetPosition()); - if (target_distance >= 25) { - this->FixZ(); - } - else if (!this->CheckLosFN(this->GetTarget())) { + this->FixZ(); + + if (target_distance <= 15 && !this->CheckLosFN(this->GetTarget())) { Mob* target = this->GetTarget(); m_Position.x = target->GetX(); diff --git a/zone/raids.cpp b/zone/raids.cpp index 26845910c..9b33056c0 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -149,7 +149,7 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo raid_update = c->GetRaid(); if (raid_update) { raid_update->SendHPManaEndPacketsTo(c); - raid_update->SendHPPacketsFrom(c); + raid_update->SendHPManaEndPacketsFrom(c); } auto pack = new ServerPacket(ServerOP_RaidAdd, sizeof(ServerRaidGeneralAction_Struct)); @@ -1591,7 +1591,7 @@ void Raid::SendHPManaEndPacketsTo(Client *client) } } -void Raid::SendHPPacketsFrom(Mob *mob) +void Raid::SendHPManaEndPacketsFrom(Mob *mob) { if(!mob) return; @@ -1779,3 +1779,42 @@ void Raid::SetDirtyAutoHaters() } +void Raid::QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_required /*= true*/, bool ignore_sender /*= true*/, float distance /*= 0*/, bool group_only /*= true*/) { + if (sender && sender->IsClient()) { + + uint32 group_id = this->GetGroup(sender->CastToClient()); + + /* If this is a group only packet and we're not in a group -- return */ + if (!group_id == 0xFFFFFFFF && group_only) + return; + + for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++) { + if (!members[i].member) + continue; + + if (!members[i].member->IsClient()) + continue; + + if (ignore_sender && members[i].member == sender) + continue; + + if (group_only && members[i].GroupNumber != group_id) + continue; + + /* If we don't have a distance requirement - send to all members */ + if (distance == 0) { + members[i].member->CastToClient()->QueuePacket(app, ack_required); + } + else { + /* If negative distance - we check if current distance is greater than X */ + if (distance <= 0 && DistanceSquared(sender->GetPosition(), members[i].member->GetPosition()) >= (distance * distance)) { + members[i].member->CastToClient()->QueuePacket(app, ack_required); + } + /* If positive distance - we check if current distance is less than X */ + else if (distance >= 0 && DistanceSquared(sender->GetPosition(), members[i].member->GetPosition()) <= (distance * distance)) { + members[i].member->CastToClient()->QueuePacket(app, ack_required); + } + } + } + } +} \ No newline at end of file diff --git a/zone/raids.h b/zone/raids.h index df43d7755..9ed9bc11c 100644 --- a/zone/raids.h +++ b/zone/raids.h @@ -174,7 +174,7 @@ public: void VerifyRaid(); void MemberZoned(Client *c); void SendHPManaEndPacketsTo(Client *c); - void SendHPPacketsFrom(Mob *mob); + void SendHPManaEndPacketsFrom(Mob *mob); void SendManaPacketFrom(Mob *mob); void SendEndurancePacketFrom(Mob *mob); void RaidSay(const char *msg, Client *c); @@ -237,6 +237,8 @@ public: void SetDirtyAutoHaters(); inline XTargetAutoHaters *GetXTargetAutoMgr() { return &m_autohatermgr; } + void QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_required = true, bool ignore_sender = true, float distance = 0, bool group_only = true); + RaidMember members[MAX_RAID_MEMBERS]; char leadername[64]; protected: diff --git a/zone/spells.cpp b/zone/spells.cpp index 8e7d6721a..0bc897912 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1427,8 +1427,10 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo ZeroCastingVars(); // set the rapid recast timer for next time around + // Why do we have this? It mostly just causes issues when things are working correctly + // It also needs to be iterator(spawn2_list); EQEmu::InventoryProfile::CleanDirty(); + Log(Logs::Detail, Logs::Spawns, "Running Zone::Process -> Spawn2::Process"); + iterator.Reset(); while (iterator.MoreElements()) { if (iterator.GetData()->Process()) { @@ -1183,10 +1186,10 @@ bool Zone::Process() { iterator.RemoveCurrent(); } } + if(adv_data && !did_adventure_actions) - { DoAdventureActions(); - } + } if(initgrids_timer.Check()) { //delayed grid loading stuff. diff --git a/zone/zone.h b/zone/zone.h index 4f5e3b5cc..4ab717ab9 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -106,6 +106,7 @@ public: inline const uint8 GetZoneType() const { return zone_type; } inline Timer* GetInstanceTimer() { return Instance_Timer; } + Timer spawn2_timer; inline glm::vec3 GetSafePoint() { return m_SafePoint; } inline const uint32& graveyard_zoneid() { return pgraveyard_zoneid; } @@ -336,7 +337,6 @@ private: Timer autoshutdown_timer; Timer clientauth_timer; - Timer spawn2_timer; Timer qglobal_purge_timer; Timer* Weather_Timer; Timer* Instance_Timer;