[Feature] Update raid features (#3443)

* [RAID] Add Raid Features

[RAID] Add Raid Features

- Add delegate main assist
- Add delegate main marker
- Add target ring for main assisters.  Uses MA1, then MA2, then MA3
- Add /assist raid respecting /assist on and /assist off
- Add Raid Notes.  Functions across zones
- Add Raid XTarget functional
- Raid Leader can mark without being delegated Main Marker.  Must have the appropriate AA

* Update to new db routines

* Updated several formatting issues based on review

* Update to pp->tribute_time_remaining to avoid edge case.  Unrelated to raid updates.

* Updates to resolve comments/review.
Added a few edge case updates as well.

* Refactored to use database repositories for raid_details and raid_members.  Other updates as noted in review.

* Updated database manifest and fixed potential leak within Client::Handle_OP_AssistGroup

* Update for remaining review items

* Refactor SendAssistTarget to use struct/vector loop

* Have IsAssister use range based for loop and return bool

* General cleanup

* Simplify SendRaidAssistTarget to use struct / vector

* Formatting in Handle_OP_RaidDelegateAbility

* Format SendRemoveRaidXTargets and clean up error statements

* Format SendRemoveAllRaidXTargets

* Formatting

* Default return FindNextRaidDelegateSlot to -1

* Change fields to marked_npc_1/2/3 (missing last underscore)

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
Mitch Freeman
2023-07-13 00:04:50 -03:00
committed by GitHub
parent 50ce99ce3e
commit b01486d767
24 changed files with 1322 additions and 88 deletions
+212 -10
View File
@@ -328,6 +328,8 @@ void MapOpcodes()
ConnectedOpcodes[OP_PVPLeaderBoardRequest] = &Client::Handle_OP_PVPLeaderBoardRequest;
ConnectedOpcodes[OP_QueryUCSServerStatus] = &Client::Handle_OP_QueryUCSServerStatus;
ConnectedOpcodes[OP_RaidInvite] = &Client::Handle_OP_RaidCommand;
ConnectedOpcodes[OP_RaidDelegateAbility] = &Client::Handle_OP_RaidDelegateAbility;
ConnectedOpcodes[OP_RaidClearNPCMarks] = &Client::Handle_OP_RaidClearNPCMarks;
ConnectedOpcodes[OP_RandomReq] = &Client::Handle_OP_RandomReq;
ConnectedOpcodes[OP_ReadBook] = &Client::Handle_OP_ReadBook;
ConnectedOpcodes[OP_RecipeAutoCombine] = &Client::Handle_OP_RecipeAutoCombine;
@@ -607,7 +609,6 @@ void Client::CompleteConnect()
but not important for now.
*/
raid->SendRaidCreate(this);
raid->SendMakeLeaderPacketTo(raid->leadername, this);
raid->SendRaidAdd(GetName(), this);
raid->SendBulkRaid(this);
raid->SendGroupUpdate(this);
@@ -616,6 +617,7 @@ void Client::CompleteConnect()
raid->UpdateRaidAAs();
raid->SendAllRaidLeadershipAA();
}
raid->SendMakeLeaderPacketTo(raid->leadername, this);
uint32 grpID = raid->GetGroup(GetName());
if (grpID < 12) {
raid->SendRaidGroupRemove(GetName(), grpID);
@@ -636,6 +638,8 @@ void Client::CompleteConnect()
raid->SendRaidLockTo(this);
raid->SendHPManaEndPacketsTo(this);
raid->SendAssistTarget(this);
raid->SendMarkTargets(this);
}
}
else {
@@ -3043,8 +3047,22 @@ void Client::Handle_OP_AssistGroup(const EQApplicationPacket *app)
LogDebug("Size mismatch in OP_AssistGroup expected [{}] got [{}]", sizeof(EntityId_Struct), app->size);
return;
}
QueuePacket(app);
return;
EntityId_Struct* eid = (EntityId_Struct*)app->pBuffer;
Entity* entity = entity_list.GetID(eid->entity_id);
if (entity && entity->IsMob()) {
Mob* new_target = entity->CastToMob();
if (new_target && (GetGM() ||
Distance(m_Position, new_target->GetPosition()) <= TARGETING_RANGE)) {
cheat_manager.SetExemptStatus(Assist, true);
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Assist, sizeof(EntityId_Struct));
eid = (EntityId_Struct*)outapp->pBuffer;
eid->entity_id = new_target->GetID();
FastQueuePacket(&outapp);
safe_delete(outapp);
}
}
}
void Client::Handle_OP_AugmentInfo(const EQApplicationPacket *app)
@@ -5850,6 +5868,31 @@ void Client::Handle_OP_DoGroupLeadershipAbility(const EQApplicationPacket *app)
break;
}
case RaidLeadershipAbility_MainAssist:
{
//This is not needed as it executes from opcode 0x2b33 which is sent
//with this opcode.
//if (GetTarget())
//{
// Raid* r = GetRaid();
// if (r)
// {
// r->DelegateAbility(GetTarget()->CastToClient()->GetName());
// }
//}
break;
}
case RaidLeadershipAbility_MarkNPC:
{
if (GetTarget() && GetTarget()->IsMob()) {
Raid* r = GetRaid();
if (r) {
r->RaidMarkNPC(this, dglas->Parameter);
}
}
break;
}
default:
LogDebug("Got unhandled OP_DoGroupLeadershipAbility Ability: [{}] Parameter: [{}]", dglas->Ability, dglas->Parameter);
break;
@@ -11934,6 +11977,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
if (raid->IsLocked()) {
raid->SendRaidLockTo(c);
}
raid->SendAssistTarget(c);
raid->SendMarkTargets(c);
}
}
group->JoinRaidXTarget(raid);
@@ -11948,6 +11993,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
if (raid->IsLocked()) {
raid->SendRaidLockTo(this);
}
raid->SendAssistTarget(this);
raid->SendMarkTargets(this);
}
}
else
@@ -11988,6 +12035,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
if (raid->IsLocked()) {
raid->SendRaidLockTo(c);
}
raid->SendAssistTarget(c);
raid->SendMarkTargets(c);
}
else {
Client* c = nullptr;
@@ -12004,6 +12053,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
if (raid->IsLocked()) {
raid->SendRaidLockTo(c);
}
raid->SendAssistTarget(c);
raid->SendMarkTargets(c);
}
}
}
@@ -12043,6 +12094,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
if (raid->IsLocked()) {
raid->SendRaidLockTo(c);
}
raid->SendAssistTarget(c);
raid->SendMarkTargets(c);
}
else
{
@@ -12060,6 +12113,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
if (raid->IsLocked()) {
raid->SendRaidLockTo(c);
}
raid->SendAssistTarget(c);
raid->SendMarkTargets(c);
}
}
}
@@ -12100,6 +12155,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
if (raid->IsLocked()) {
raid->SendRaidLockTo(c);
}
raid->SendAssistTarget(c);
raid->SendMarkTargets(c);
}
else
{
@@ -12116,6 +12173,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
if (raid->IsLocked()) {
raid->SendRaidLockTo(c);
}
raid->SendAssistTarget(c);
raid->SendMarkTargets(c);
}
}
}
@@ -12129,6 +12188,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
if (raid->IsLocked()) {
raid->SendRaidLockTo(this);
}
raid->SendAssistTarget(this);
raid->SendMarkTargets(this);
}
else { // neither has a group
raid = new Raid(player_sending_invite);
@@ -12143,6 +12204,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
if (raid->IsLocked()) {
raid->SendRaidLockTo(this);
}
raid->SendAssistTarget(this);
raid->SendMarkTargets(this);
}
}
}
@@ -12165,6 +12228,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
//Does not camp the Bots, just removes from the raid
if (c_to_disband) {
uint32 i = raid->GetPlayerIndex(raid_command_packet->leader_name);
raid->RemoveRaidDelegates(raid_command_packet->leader_name);
raid->SendRemoveAllRaidXTargets(raid_command_packet->leader_name);
raid->SetNewRaidLeader(i);
raid->HandleBotGroupDisband(c_to_disband->CharacterID());
raid->HandleOfflineBots(c_to_disband->CharacterID());
@@ -12180,11 +12245,13 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
if (gid < 12 && (raid->IsGroupLeader(b_to_disband->GetName()) || raid->GroupCount(gid) < 2)) {
uint32 owner_id = b_to_disband->CastToBot()->GetOwner()->CastToClient()->CharacterID();
raid->RemoveRaidDelegates(raid_command_packet->leader_name);
raid->UpdateRaidXTargets();
raid->HandleBotGroupDisband(owner_id, gid);
} else if (b_to_disband && raid->IsRaidMember(b_to_disband->GetName())) {
raid->RemoveRaidDelegates(raid_command_packet->leader_name);
raid->UpdateRaidXTargets();
Bot::RemoveBotFromRaid(b_to_disband);
} else if (gid < 12 && raid->GetGroupLeader(gid) && raid->GetGroupLeader(gid)->IsBot()) {
c_doing_disband->Message(
Chat::Yellow,
@@ -12215,6 +12282,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
}
}
raid->SetNewRaidLeader(i);
raid->RemoveRaidDelegates(raid_command_packet->leader_name);
raid->UpdateRaidXTargets();
raid->RemoveMember(raid_command_packet->leader_name);
Client* c = entity_list.GetClientByName(raid_command_packet->leader_name);
if (c) {
@@ -12268,9 +12337,9 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
if (client_to_update) {
raid->SendRaidRemove(raid->members[x].member_name, client_to_update);
raid->SendRaidCreate(client_to_update);
raid->SendMakeLeaderPacketTo(raid->leadername, client_to_update);
raid->SendRaidAdd(raid->members[x].member_name, client_to_update);
raid->SendBulkRaid(client_to_update);
raid->SendMakeLeaderPacketTo(raid->leadername, client_to_update);
if (raid->IsLocked()) {
raid->SendRaidLockTo(client_to_update);
}
@@ -12318,9 +12387,9 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
raid->GroupUpdate(raid_command_packet->parameter);
/* If our old was a group send update there too */
if (old_group < 12)
if (old_group < 12) {
raid->GroupUpdate(old_group);
}
}
}
/* Move player to ungrouped bank */
@@ -12381,7 +12450,7 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
}
raid->GroupUpdate(oldgrp);
}
}
}
Client* client_moved = entity_list.GetClientByName(raid_command_packet->leader_name);
@@ -12479,7 +12548,18 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
raid->SendRaidMOTDToWorld();
break;
}
case RaidCommandSetNote:
{
Raid* raid = entity_list.GetRaidByClient(this);
if (!raid) {
break;
}
raid->SaveRaidNote(raid_command_packet->leader_name, raid_command_packet->note);
raid->SendRaidNotesToWorld();
break;
}
default: {
Message(Chat::Red, "Raid command (%d) NYI", raid_command_packet->action);
break;
@@ -15799,14 +15879,87 @@ void Client::Handle_OP_XTargetRequest(const EQApplicationPacket *app)
case RaidAssist1:
case RaidAssist2:
case RaidAssist3:
{
struct AssistType {
XTargetType type;
int32 assist_slot;
};
std::vector<AssistType> assist_types = {
{ RaidAssist1, MAIN_ASSIST_1_SLOT },
{ RaidAssist2, MAIN_ASSIST_2_SLOT },
{ RaidAssist3, MAIN_ASSIST_3_SLOT }
};
for (auto& t : assist_types) {
if (t.type == Type) {
Raid* r = GetRaid();
if (r) {
Client* ma = entity_list.GetClientByName(r->main_assister_pcs[t.assist_slot]);
if (ma) {
UpdateXTargetType(t.type, ma, ma->GetName());
}
}
}
}
break;
}
case RaidAssist1Target:
case RaidAssist2Target:
case RaidAssist3Target:
{
struct AssistType {
XTargetType type;
int32 assist_slot;
};
std::vector<AssistType> assist_types = {
{ RaidAssist1Target, MAIN_ASSIST_1_SLOT },
{ RaidAssist2Target, MAIN_ASSIST_2_SLOT },
{ RaidAssist3Target, MAIN_ASSIST_3_SLOT }
};
for (auto& t : assist_types) {
if (t.type == Type) {
Raid* r = GetRaid();
if (r) {
Client* ma = entity_list.GetClientByName(r->main_assister_pcs[t.assist_slot]);
if (ma && ma->GetTarget()) {
UpdateXTargetType(t.type, ma->GetTarget(), ma->GetTarget()->GetName());
}
}
}
}
break;
}
case RaidMarkTarget1:
case RaidMarkTarget2:
case RaidMarkTarget3:
{
// Not implemented yet.
struct AssistType {
XTargetType type;
int32 assist_slot;
};
std::vector<AssistType> assist_types = {
{ RaidMarkTarget1, MAIN_MARKER_1_SLOT },
{ RaidMarkTarget2, MAIN_MARKER_2_SLOT },
{ RaidMarkTarget3, MAIN_MARKER_3_SLOT }
};
for (auto& t : assist_types) {
if (t.type == Type) {
Raid* r = GetRaid();
if (r) {
auto mm = entity_list.GetNPCByID(r->marked_npcs[t.assist_slot]);
if (mm) {
UpdateXTargetType(t.type, mm->CastToMob(), mm->CastToMob()->GetName());
}
}
}
}
break;
}
@@ -16190,3 +16343,52 @@ void Client::RecordKilledNPCEvent(NPC *n)
}
}
}
void Client::Handle_OP_RaidDelegateAbility(const EQApplicationPacket *app)
{
if (app->size != sizeof(DelegateAbility_Struct)) {
LogDebug(
"Size mismatch in OP_RaidDelegateAbility expected [{}] got [{}]",
sizeof(DelegateAbility_Struct),
app->size
);
DumpPacket(app);
return;
}
DelegateAbility_Struct *das = (DelegateAbility_Struct *) app->pBuffer;
switch (das->DelegateAbility) {
case RaidDelegateMainAssist: {
auto r = GetRaid();
if (r) {
r->DelegateAbilityAssist(this, das->Name);
}
break;
}
case RaidDelegateMainMarker: {
auto r = GetRaid();
if (r) {
r->DelegateAbilityMark(this, das->Name);
}
break;
}
default:
LogDebug("RaidDelegateAbility default case");
break;
}
}
void Client::Handle_OP_RaidClearNPCMarks(const EQApplicationPacket* app)
{
if (app->size != 0) {
LogDebug("Size mismatch in OP_RaidClearNPCMark expected [{}] got [{}]", 0, app->size);
DumpPacket(app);
return;
}
auto r = GetRaid();
if (r) {
r->RaidClearNPCMarks(this);
}
}