mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-26 11:01:28 +00:00
Grouping with Mercenaries is considerably less buggy.
This commit is contained in:
parent
b5c6b47639
commit
c5a90adb39
186
zone/client.cpp
186
zone/client.cpp
@ -3218,6 +3218,10 @@ void Client::LinkDead()
|
||||
{
|
||||
entity_list.MessageGroup(this,true,15,"%s has gone linkdead.",GetName());
|
||||
GetGroup()->DelMember(this);
|
||||
if (GetMerc())
|
||||
{
|
||||
GetMerc()->RemoveMercFromGroup(GetMerc(), GetMerc()->GetGroup());
|
||||
}
|
||||
}
|
||||
Raid *raid = entity_list.GetRaidByClient(this);
|
||||
if(raid){
|
||||
@ -4139,6 +4143,184 @@ void Client::UpdateLFP() {
|
||||
worldserver.UpdateLFP(CharacterID(), LFPMembers);
|
||||
}
|
||||
|
||||
bool Client::GroupFollow(Client* inviter) {
|
||||
|
||||
if (inviter)
|
||||
{
|
||||
isgrouped = true;
|
||||
Raid* raid = entity_list.GetRaidByClient(inviter);
|
||||
Raid* iraid = entity_list.GetRaidByClient(this);
|
||||
|
||||
//inviter has a raid don't do group stuff instead do raid stuff!
|
||||
if (raid)
|
||||
{
|
||||
// Suspend the merc while in a raid (maybe a rule could be added for this)
|
||||
if (GetMerc())
|
||||
GetMerc()->Suspend();
|
||||
|
||||
uint32 groupToUse = 0xFFFFFFFF;
|
||||
for (int x = 0; x < MAX_RAID_MEMBERS; x++)
|
||||
{
|
||||
if (raid->members[x].member)
|
||||
{
|
||||
//this assumes the inviter is in the zone
|
||||
if (raid->members[x].member == inviter){
|
||||
groupToUse = raid->members[x].GroupNumber;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (iraid == raid)
|
||||
{
|
||||
//both in same raid
|
||||
uint32 ngid = raid->GetGroup(inviter->GetName());
|
||||
if (raid->GroupCount(ngid) < 6)
|
||||
{
|
||||
raid->MoveMember(GetName(), ngid);
|
||||
raid->SendGroupDisband(this);
|
||||
//raid->SendRaidGroupAdd(GetName(), ngid);
|
||||
//raid->SendGroupUpdate(this);
|
||||
raid->GroupUpdate(ngid); //break
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (raid->RaidCount() < MAX_RAID_MEMBERS)
|
||||
{
|
||||
if (raid->GroupCount(groupToUse) < 6)
|
||||
{
|
||||
raid->SendRaidCreate(this);
|
||||
raid->SendMakeLeaderPacketTo(raid->leadername, this);
|
||||
raid->AddMember(this, groupToUse);
|
||||
raid->SendBulkRaid(this);
|
||||
//raid->SendRaidGroupAdd(GetName(), groupToUse);
|
||||
//raid->SendGroupUpdate(this);
|
||||
raid->GroupUpdate(groupToUse); //break
|
||||
if (raid->IsLocked())
|
||||
{
|
||||
raid->SendRaidLockTo(this);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
raid->SendRaidCreate(this);
|
||||
raid->SendMakeLeaderPacketTo(raid->leadername, this);
|
||||
raid->AddMember(this);
|
||||
raid->SendBulkRaid(this);
|
||||
if (raid->IsLocked())
|
||||
{
|
||||
raid->SendRaidLockTo(this);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Group* group = entity_list.GetGroupByClient(inviter);
|
||||
|
||||
if (!group)
|
||||
{
|
||||
//Make new group
|
||||
group = new Group(inviter);
|
||||
|
||||
if (!group)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
entity_list.AddGroup(group);
|
||||
|
||||
if (group->GetID() == 0)
|
||||
{
|
||||
Message(13, "Unable to get new group id. Cannot create group.");
|
||||
inviter->Message(13, "Unable to get new group id. Cannot create group.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//now we have a group id, can set inviter's id
|
||||
database.SetGroupID(inviter->GetName(), group->GetID(), inviter->CharacterID(), false);
|
||||
database.SetGroupLeaderName(group->GetID(), inviter->GetName());
|
||||
group->UpdateGroupAAs();
|
||||
|
||||
//Invite the inviter into the group first.....dont ask
|
||||
if (inviter->GetClientVersion() < EQClientSoD)
|
||||
{
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct));
|
||||
GroupJoin_Struct* outgj = (GroupJoin_Struct*)outapp->pBuffer;
|
||||
strcpy(outgj->membername, inviter->GetName());
|
||||
strcpy(outgj->yourname, inviter->GetName());
|
||||
outgj->action = groupActInviteInitial; // 'You have formed the group'.
|
||||
group->GetGroupAAs(&outgj->leader_aas);
|
||||
inviter->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// SoD and later
|
||||
inviter->SendGroupCreatePacket();
|
||||
inviter->SendGroupLeaderChangePacket(inviter->GetName());
|
||||
inviter->SendGroupJoinAcknowledge();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!group)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove merc from old group before adding client to the new one
|
||||
if (GetMerc() && GetMerc()->HasGroup())
|
||||
{
|
||||
GetMerc()->RemoveMercFromGroup(GetMerc(), GetMerc()->GetGroup());
|
||||
}
|
||||
|
||||
if (!group->AddMember(this))
|
||||
{
|
||||
// If failed to add client to new group, regroup with merc
|
||||
if (GetMerc())
|
||||
{
|
||||
GetMerc()->MercJoinClientGroup();
|
||||
}
|
||||
else
|
||||
{
|
||||
isgrouped = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetClientVersion() >= EQClientSoD)
|
||||
{
|
||||
SendGroupJoinAcknowledge();
|
||||
}
|
||||
|
||||
// Temporary hack for SoD, as things seem to work quite differently
|
||||
if (inviter->IsClient() && inviter->GetClientVersion() >= EQClientSoD)
|
||||
{
|
||||
database.RefreshGroupFromDB(inviter);
|
||||
}
|
||||
|
||||
// Add the merc back into the new group if possible
|
||||
if (GetMerc())
|
||||
{
|
||||
GetMerc()->MercJoinClientGroup();
|
||||
}
|
||||
|
||||
if (inviter->IsLFP())
|
||||
{
|
||||
// If the player who invited us to a group is LFP, have them update world now that we have joined their group.
|
||||
inviter->UpdateLFP();
|
||||
}
|
||||
|
||||
database.RefreshGroupFromDB(this);
|
||||
group->SendHPPacketsTo(this);
|
||||
//send updates to clients out of zone...
|
||||
group->SendGroupJoinOOZ(this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16 Client::GetPrimarySkillValue()
|
||||
{
|
||||
SkillUseTypes skill = HIGHEST_SKILL; //because nullptr == 0, which is 1H Slashing, & we want it to return 0 from GetSkill
|
||||
@ -7412,13 +7594,15 @@ void Client::SendMercPersonalInfo()
|
||||
}
|
||||
if (MERC_DEBUG > 0)
|
||||
Message(7, "Mercenary Debug: SendMercPersonalInfo Send Successful");
|
||||
|
||||
SendMercMerchantResponsePacket(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MERC_DEBUG > 0)
|
||||
Message(7, "Mercenary Debug: SendMercPersonalInfo Send Failed Due to no MercData for %i", GetMercInfo().MercTemplateID);
|
||||
}
|
||||
SendMercMerchantResponsePacket(0);
|
||||
|
||||
}
|
||||
|
||||
void Client::SendClearMercInfo()
|
||||
|
||||
@ -208,7 +208,7 @@ public:
|
||||
Client(EQStreamInterface * ieqs);
|
||||
~Client();
|
||||
|
||||
//abstract virtual function implementations requird by base abstract class
|
||||
//abstract virtual function implementations required by base abstract class
|
||||
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill);
|
||||
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false);
|
||||
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false,
|
||||
@ -710,7 +710,7 @@ public:
|
||||
void UnscribeSpellAll(bool update_client = true);
|
||||
void UntrainDisc(int slot, bool update_client = true);
|
||||
void UntrainDiscAll(bool update_client = true);
|
||||
bool SpellGlobalCheck(uint16 Spell_ID, uint16 Char_ID);
|
||||
bool SpellGlobalCheck(uint16 Spell_ID, uint32 Char_ID);
|
||||
uint32 GetCharMaxLevelFromQGlobal();
|
||||
|
||||
inline bool IsSitting() const {return (playeraction == 1);}
|
||||
@ -1098,6 +1098,7 @@ void SetConsumption(int32 in_hunger, int32 in_thirst);
|
||||
void RemoveGroupXTargets();
|
||||
void RemoveAutoXTargets();
|
||||
void ShowXTargets(Client *c);
|
||||
bool GroupFollow(Client* inviter);
|
||||
|
||||
void InitializeMercInfo();
|
||||
bool CheckCanSpawnMerc(uint32 template_id);
|
||||
@ -1105,6 +1106,7 @@ void SetConsumption(int32 in_hunger, int32 in_thirst);
|
||||
bool CheckCanRetainMerc(uint32 upkeep);
|
||||
bool CheckCanUnsuspendMerc();
|
||||
bool DismissMerc(uint32 MercID);
|
||||
bool MercOnlyOrNoGroup();
|
||||
inline uint32 GetMercID() const { return mercid; }
|
||||
inline uint8 GetMercSlot() const { return mercSlot; }
|
||||
void SetMercID( uint32 newmercid) { mercid = newmercid; }
|
||||
|
||||
@ -1637,7 +1637,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
} //else, somebody from our group is already here...
|
||||
|
||||
if (!group)
|
||||
database.SetGroupID(GetName(), 0, CharacterID()); //cannot re-establish group, kill it
|
||||
database.SetGroupID(GetName(), 0, CharacterID(), false); //cannot re-establish group, kill it
|
||||
|
||||
}
|
||||
else { //no group id
|
||||
@ -6403,7 +6403,10 @@ void Client::Handle_OP_GroupCancelInvite(const EQApplicationPacket *app)
|
||||
safe_delete(pack);
|
||||
}
|
||||
|
||||
database.SetGroupID(GetName(), 0, CharacterID());
|
||||
if (!GetMerc())
|
||||
{
|
||||
database.SetGroupID(GetName(), 0, CharacterID(), false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -6433,7 +6436,8 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app)
|
||||
GroupGeneric_Struct* gd = (GroupGeneric_Struct*)app->pBuffer;
|
||||
|
||||
Raid *raid = entity_list.GetRaidByClient(this);
|
||||
if (raid){
|
||||
if (raid)
|
||||
{
|
||||
Mob* memberToDisband = nullptr;
|
||||
|
||||
if (!raid->IsGroupLeader(GetName()))
|
||||
@ -6500,93 +6504,80 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if ((group->IsLeader(this) && (GetTarget() == 0 || GetTarget() == this)) || (group->GroupCount()<3)) {
|
||||
if (group->GroupCount() < 3)
|
||||
{
|
||||
group->DisbandGroup();
|
||||
if (GetMerc() != nullptr)
|
||||
if (GetMerc())
|
||||
GetMerc()->Suspend();
|
||||
}
|
||||
else {
|
||||
else if (group->IsLeader(this) && GetTarget() == nullptr)
|
||||
{
|
||||
if (group->GroupCount() > 2 && GetMerc() && !GetMerc()->IsSuspended())
|
||||
{
|
||||
group->DisbandGroup();
|
||||
GetMerc()->MercJoinClientGroup();
|
||||
}
|
||||
else
|
||||
{
|
||||
group->DisbandGroup();
|
||||
if (GetMerc())
|
||||
GetMerc()->Suspend();
|
||||
}
|
||||
}
|
||||
else if (group->IsLeader(this) && GetTarget() == this)
|
||||
{
|
||||
LeaveGroup();
|
||||
if (GetMerc() && !GetMerc()->IsSuspended())
|
||||
{
|
||||
GetMerc()->MercJoinClientGroup();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Mob* memberToDisband = nullptr;
|
||||
memberToDisband = GetTarget();
|
||||
|
||||
if (!memberToDisband)
|
||||
memberToDisband = entity_list.GetMob(gd->name2);
|
||||
|
||||
if (memberToDisband) {
|
||||
if (group->IsLeader(this)) {
|
||||
if (memberToDisband)
|
||||
{
|
||||
if (group->IsLeader(this))
|
||||
{
|
||||
// the group leader can kick other members out of the group...
|
||||
//group->DelMember(memberToDisband,false);
|
||||
if (memberToDisband->IsClient())
|
||||
{
|
||||
group->DelMember(memberToDisband, false);
|
||||
Client* memberClient = memberToDisband->CastToClient();
|
||||
Merc* memberMerc = memberToDisband->CastToClient()->GetMerc();
|
||||
if (memberClient && memberMerc && group)
|
||||
if (memberClient && memberMerc)
|
||||
{
|
||||
if (!memberMerc->IsGrouped() && !memberClient->IsGrouped()) {
|
||||
Group *g = new Group(memberClient);
|
||||
|
||||
entity_list.AddGroup(g);
|
||||
|
||||
if (g->GetID() == 0) {
|
||||
safe_delete(g);
|
||||
return;
|
||||
}
|
||||
if (Merc::AddMercToGroup(memberMerc, g)) {
|
||||
database.SetGroupLeaderName(g->GetID(), memberClient->GetName());
|
||||
g->SaveGroupLeaderAA();
|
||||
database.SetGroupID(memberClient->GetName(), g->GetID(), memberClient->CharacterID());
|
||||
database.SetGroupID(memberMerc->GetName(), g->GetID(), memberClient->CharacterID(), true);
|
||||
database.RefreshGroupFromDB(memberClient);
|
||||
}
|
||||
}
|
||||
memberMerc->MercJoinClientGroup();
|
||||
}
|
||||
}
|
||||
else if (memberToDisband->IsMerc()) {
|
||||
else if (memberToDisband->IsMerc())
|
||||
{
|
||||
memberToDisband->CastToMerc()->Suspend();
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
// ...but other members can only remove themselves
|
||||
group->DelMember(this, false);
|
||||
|
||||
if (!IsGrouped() && GetMerc() != nullptr) {
|
||||
if (!IsGrouped()) {
|
||||
Group *g = new Group(this);
|
||||
|
||||
if (!g) {
|
||||
delete g;
|
||||
g = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
entity_list.AddGroup(g);
|
||||
|
||||
if (g->GetID() == 0) {
|
||||
safe_delete(g);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Merc::AddMercToGroup(GetMerc(), g)) {
|
||||
database.SetGroupLeaderName(g->GetID(), this->GetName());
|
||||
g->SaveGroupLeaderAA();
|
||||
database.SetGroupID(this->GetName(), g->GetID(), this->CharacterID());
|
||||
database.SetGroupID(GetMerc()->GetName(), g->GetID(), this->CharacterID(), true);
|
||||
database.RefreshGroupFromDB(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetMerc())
|
||||
GetMerc()->Depop();
|
||||
}
|
||||
}
|
||||
if (GetMerc() && !GetMerc()->IsSuspended())
|
||||
{
|
||||
GetMerc()->MercJoinClientGroup();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile->write(EQEMuLog::Error, "Failed to remove player from group. Unable to find player named %s in player group", gd->name2);
|
||||
}
|
||||
}
|
||||
if (LFP) {
|
||||
if (LFP)
|
||||
{
|
||||
// If we are looking for players, update to show we are on our own now.
|
||||
UpdateLFP();
|
||||
}
|
||||
@ -6616,157 +6607,22 @@ void Client::Handle_OP_GroupFollow2(const EQApplicationPacket *app)
|
||||
|
||||
GroupGeneric_Struct* gf = (GroupGeneric_Struct*)app->pBuffer;
|
||||
Mob* inviter = entity_list.GetClientByName(gf->name1);
|
||||
|
||||
if (inviter != nullptr && inviter->IsClient()) {
|
||||
isgrouped = true;
|
||||
strn0cpy(gf->name1, inviter->GetName(), 64);
|
||||
strn0cpy(gf->name2, this->GetName(), 64);
|
||||
|
||||
Raid* raid = entity_list.GetRaidByClient(inviter->CastToClient());
|
||||
Raid* iraid = entity_list.GetRaidByClient(this);
|
||||
|
||||
//inviter has a raid don't do group stuff instead do raid stuff!
|
||||
if (raid){
|
||||
// Suspend the merc while in a raid (maybe a rule could be added for this)
|
||||
if (GetMerc())
|
||||
GetMerc()->Suspend();
|
||||
|
||||
uint32 groupToUse = 0xFFFFFFFF;
|
||||
for (int x = 0; x < MAX_RAID_MEMBERS; x++){
|
||||
if (raid->members[x].member){ //this assumes the inviter is in the zone
|
||||
if (raid->members[x].member == inviter->CastToClient()){
|
||||
groupToUse = raid->members[x].GroupNumber;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (iraid == raid){ //both in same raid
|
||||
uint32 ngid = raid->GetGroup(inviter->GetName());
|
||||
if (raid->GroupCount(ngid) < 6){
|
||||
raid->MoveMember(GetName(), ngid);
|
||||
raid->SendGroupDisband(this);
|
||||
//raid->SendRaidGroupAdd(GetName(), ngid);
|
||||
//raid->SendGroupUpdate(this);
|
||||
raid->GroupUpdate(ngid); //break
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (raid->RaidCount() < MAX_RAID_MEMBERS){
|
||||
if (raid->GroupCount(groupToUse) < 6){
|
||||
raid->SendRaidCreate(this);
|
||||
raid->SendMakeLeaderPacketTo(raid->leadername, this);
|
||||
raid->AddMember(this, groupToUse);
|
||||
raid->SendBulkRaid(this);
|
||||
//raid->SendRaidGroupAdd(GetName(), groupToUse);
|
||||
//raid->SendGroupUpdate(this);
|
||||
raid->GroupUpdate(groupToUse); //break
|
||||
if (raid->IsLocked()) {
|
||||
raid->SendRaidLockTo(this);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else{
|
||||
raid->SendRaidCreate(this);
|
||||
raid->SendMakeLeaderPacketTo(raid->leadername, this);
|
||||
raid->AddMember(this);
|
||||
raid->SendBulkRaid(this);
|
||||
if (raid->IsLocked()) {
|
||||
raid->SendRaidLockTo(this);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Inviter and Invitee are in the same zone
|
||||
if (inviter != nullptr && inviter->IsClient())
|
||||
{
|
||||
if (GroupFollow(inviter->CastToClient()))
|
||||
{
|
||||
strn0cpy(gf->name1, inviter->GetName(), sizeof(gf->name1));
|
||||
strn0cpy(gf->name2, GetName(), sizeof(gf->name2));
|
||||
inviter->CastToClient()->QueuePacket(app);//notify inviter the client accepted
|
||||
}
|
||||
|
||||
Group* group = entity_list.GetGroupByClient(inviter->CastToClient());
|
||||
|
||||
if (!group){
|
||||
//Make new group
|
||||
group = new Group(inviter);
|
||||
if (!group)
|
||||
return;
|
||||
entity_list.AddGroup(group);
|
||||
|
||||
if (group->GetID() == 0) {
|
||||
Message(13, "Unable to get new group id. Cannot create group.");
|
||||
inviter->Message(13, "Unable to get new group id. Cannot create group.");
|
||||
return;
|
||||
}
|
||||
|
||||
//now we have a group id, can set inviter's id
|
||||
database.SetGroupID(inviter->GetName(), group->GetID(), inviter->CastToClient()->CharacterID());
|
||||
database.SetGroupLeaderName(group->GetID(), inviter->GetName());
|
||||
|
||||
group->UpdateGroupAAs();
|
||||
|
||||
//Invite the inviter into the group first.....dont ask
|
||||
if (inviter->CastToClient()->GetClientVersion() < EQClientSoD)
|
||||
{
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct));
|
||||
GroupJoin_Struct* outgj = (GroupJoin_Struct*)outapp->pBuffer;
|
||||
strcpy(outgj->membername, inviter->GetName());
|
||||
strcpy(outgj->yourname, inviter->GetName());
|
||||
outgj->action = groupActInviteInitial; // 'You have formed the group'.
|
||||
group->GetGroupAAs(&outgj->leader_aas);
|
||||
inviter->CastToClient()->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// SoD and later
|
||||
//
|
||||
inviter->CastToClient()->SendGroupCreatePacket();
|
||||
|
||||
inviter->CastToClient()->SendGroupLeaderChangePacket(inviter->GetName());
|
||||
|
||||
inviter->CastToClient()->SendGroupJoinAcknowledge();
|
||||
}
|
||||
|
||||
}
|
||||
if (!group)
|
||||
return;
|
||||
|
||||
inviter->CastToClient()->QueuePacket(app);//notify inviter the client accepted
|
||||
|
||||
if (!group->AddMember(this))
|
||||
return;
|
||||
|
||||
if (inviter->CastToClient()->IsLFP()) {
|
||||
// If the player who invited us to a group is LFP, have them update world now that we have joined
|
||||
// their group.
|
||||
inviter->CastToClient()->UpdateLFP();
|
||||
}
|
||||
|
||||
if (GetClientVersion() >= EQClientSoD)
|
||||
SendGroupJoinAcknowledge();
|
||||
|
||||
database.RefreshGroupFromDB(this);
|
||||
group->SendHPPacketsTo(this);
|
||||
|
||||
// Temporary hack for SoD, as things seem to work quite differently
|
||||
if (inviter->CastToClient()->GetClientVersion() >= EQClientSoD)
|
||||
database.RefreshGroupFromDB(inviter->CastToClient());
|
||||
|
||||
// Add the merc back into the new group
|
||||
if (GetMerc()) {
|
||||
if (Merc::AddMercToGroup(GetMerc(), group)) {
|
||||
database.SetGroupID(GetMerc()->GetName(), group->GetID(), inviter->CastToClient()->CharacterID(), true);
|
||||
database.RefreshGroupFromDB(this);
|
||||
}
|
||||
}
|
||||
|
||||
//send updates to clients out of zone...
|
||||
ServerPacket* pack = new ServerPacket(ServerOP_GroupJoin, sizeof(ServerGroupJoin_Struct));
|
||||
ServerGroupJoin_Struct* gj = (ServerGroupJoin_Struct*)pack->pBuffer;
|
||||
gj->gid = group->GetID();
|
||||
gj->zoneid = zone->GetZoneID();
|
||||
gj->instance_id = zone->GetInstanceID();
|
||||
strcpy(gj->member_name, GetName());
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
else if (inviter == nullptr)
|
||||
{
|
||||
// Inviter is in another zone - Remove merc from group now if any
|
||||
LeaveGroup();
|
||||
|
||||
ServerPacket* pack = new ServerPacket(ServerOP_GroupFollow, sizeof(ServerGroupFollow_Struct));
|
||||
ServerGroupFollow_Struct *sgfs = (ServerGroupFollow_Struct *)pack->pBuffer;
|
||||
sgfs->CharacterID = CharacterID();
|
||||
@ -6801,10 +6657,11 @@ void Client::Handle_OP_GroupInvite2(const EQApplicationPacket *app)
|
||||
return;
|
||||
}
|
||||
|
||||
if (Invitee) {
|
||||
if (Invitee->IsClient()) {
|
||||
if ((!Invitee->IsGrouped() && !Invitee->IsRaidGrouped()) ||
|
||||
(Invitee->GetGroup() && Invitee->CastToClient()->GetMerc() && Invitee->GetGroup()->GroupCount() == 2))
|
||||
if (Invitee)
|
||||
{
|
||||
if (Invitee->IsClient())
|
||||
{
|
||||
if(Invitee->CastToClient()->MercOnlyOrNoGroup() && !Invitee->IsRaidGrouped())
|
||||
{
|
||||
if (app->GetOpcode() == OP_GroupInvite2)
|
||||
{
|
||||
@ -9507,7 +9364,8 @@ void Client::Handle_OP_MercenaryCommand(const EQApplicationPacket *app)
|
||||
Merc* merc = GetMerc();
|
||||
GetMercInfo().State = option;
|
||||
|
||||
if (merc) {
|
||||
if (merc)
|
||||
{
|
||||
uint8 numStances = 0;
|
||||
|
||||
//get number of available stances for the current merc
|
||||
@ -9519,10 +9377,11 @@ void Client::Handle_OP_MercenaryCommand(const EQApplicationPacket *app)
|
||||
}
|
||||
|
||||
MercTemplate* mercTemplate = zone->GetMercTemplate(GetMerc()->GetMercTemplateID());
|
||||
if (mercTemplate) {
|
||||
|
||||
if (mercTemplate)
|
||||
{
|
||||
//check to see if selected option is a valid stance slot (option is the slot the stance is in, not the actual stance)
|
||||
if (option >= 0 && option < numStances) {
|
||||
if (option >= 0 && option < numStances)
|
||||
{
|
||||
merc->SetStance(mercTemplate->Stances[option]);
|
||||
GetMercInfo().Stance = mercTemplate->Stances[option];
|
||||
|
||||
@ -9710,7 +9569,7 @@ void Client::Handle_OP_MercenaryDismiss(const EQApplicationPacket *app)
|
||||
Message(7, "Mercenary Debug: Dismiss Request ( %i ) Received.", Command);
|
||||
|
||||
// Handle the dismiss here...
|
||||
DismissMerc(GetMercInfo().mercid); // GetMercID()
|
||||
DismissMerc(GetMercInfo().mercid);
|
||||
|
||||
}
|
||||
|
||||
@ -9744,10 +9603,12 @@ void Client::Handle_OP_MercenaryHire(const EQApplicationPacket *app)
|
||||
|
||||
MercTemplate* merc_template = zone->GetMercTemplate(merc_template_id);
|
||||
|
||||
if (merc_template) {
|
||||
if (merc_template)
|
||||
{
|
||||
|
||||
Mob* merchant = entity_list.GetNPCByID(merchant_id);
|
||||
if (!CheckCanHireMerc(merchant, merc_template_id)) {
|
||||
if (!CheckCanHireMerc(merchant, merc_template_id))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@ -9762,7 +9623,8 @@ void Client::Handle_OP_MercenaryHire(const EQApplicationPacket *app)
|
||||
SpawnMerc(merc, true);
|
||||
merc->Save();
|
||||
|
||||
if (RuleB(Mercs, ChargeMercPurchaseCost)) {
|
||||
if (RuleB(Mercs, ChargeMercPurchaseCost))
|
||||
{
|
||||
uint32 cost = Merc::CalcPurchaseCost(merc_template->MercTemplateID, GetLevel()) * 100; // Cost is in gold
|
||||
TakeMoneyFromPP(cost, true);
|
||||
}
|
||||
@ -9770,12 +9632,14 @@ void Client::Handle_OP_MercenaryHire(const EQApplicationPacket *app)
|
||||
// 0 is approved hire request
|
||||
SendMercMerchantResponsePacket(0);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
//merc failed to spawn
|
||||
SendMercMerchantResponsePacket(3);
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
//merc doesn't exist in db
|
||||
SendMercMerchantResponsePacket(2);
|
||||
}
|
||||
|
||||
@ -245,7 +245,6 @@ bool Client::Process() {
|
||||
|
||||
if(GetMercInfo().MercTemplateID != 0 && GetMercInfo().IsSuspended)
|
||||
{
|
||||
//CheckMercSuspendTimer();
|
||||
if(p_timers.Expired(&database, pTimerMercSuspend, false))
|
||||
{
|
||||
CheckMercSuspendTimer();
|
||||
@ -746,9 +745,9 @@ bool Client::Process() {
|
||||
{
|
||||
entity_list.MessageGroup(this, true, 15, "%s left the zone.", GetName());
|
||||
mygroup->MemberZoned(this);
|
||||
if (GetMerc() && GetMerc()->HasGroup() && GetMerc()->GetGroup() == mygroup)
|
||||
if (GetMerc() && GetMerc()->HasGroup())
|
||||
{
|
||||
mygroup->DelMember(GetMerc());
|
||||
GetMerc()->RemoveMercFromGroup(GetMerc(), GetMerc()->GetGroup());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
146
zone/groups.cpp
146
zone/groups.cpp
@ -203,28 +203,34 @@ void Group::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinu
|
||||
}
|
||||
}
|
||||
|
||||
bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 CharacterID)
|
||||
bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 CharacterID, bool ismerc)
|
||||
{
|
||||
bool InZone = true;
|
||||
bool ismerc = false;
|
||||
|
||||
// This method should either be passed a Mob*, if the new member is in this zone, or a nullptr Mob*
|
||||
// and the name and CharacterID of the new member, if they are out of zone.
|
||||
//
|
||||
if(!newmember && !NewMemberName)
|
||||
return false;
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(GroupCount() >= MAX_GROUP_MEMBERS) //Sanity check for merging groups together.
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!newmember)
|
||||
{
|
||||
InZone = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
NewMemberName = newmember->GetCleanName();
|
||||
|
||||
if(newmember->IsClient())
|
||||
{
|
||||
CharacterID = newmember->CastToClient()->CharacterID();
|
||||
}
|
||||
if(newmember->IsMerc())
|
||||
{
|
||||
Client* owner = newmember->CastToMerc()->GetMercOwner();
|
||||
@ -232,18 +238,20 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
|
||||
{
|
||||
CharacterID = owner->CastToClient()->CharacterID();
|
||||
NewMemberName = newmember->GetName();
|
||||
ismerc = true;
|
||||
}
|
||||
ismerc = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 i = 0;
|
||||
|
||||
// See if they are already in the group
|
||||
//
|
||||
uint32 i = 0;
|
||||
for (i = 0; i < MAX_GROUP_MEMBERS; ++i)
|
||||
{
|
||||
if(!strcasecmp(membername[i], NewMemberName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Put them in the group
|
||||
for (i = 0; i < MAX_GROUP_MEMBERS; ++i)
|
||||
@ -251,17 +259,20 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
|
||||
if (membername[i][0] == '\0')
|
||||
{
|
||||
if(InZone)
|
||||
{
|
||||
members[i] = newmember;
|
||||
|
||||
}
|
||||
strcpy(membername[i], NewMemberName);
|
||||
MemberRoles[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Is this even possible based on the above loops? Remove?
|
||||
if (i == MAX_GROUP_MEMBERS)
|
||||
{
|
||||
return false;
|
||||
|
||||
strcpy(membername[i], NewMemberName);
|
||||
MemberRoles[i] = 0;
|
||||
}
|
||||
|
||||
int x=1;
|
||||
|
||||
@ -270,11 +281,12 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
|
||||
GroupJoin_Struct* gj = (GroupJoin_Struct*) outapp->pBuffer;
|
||||
strcpy(gj->membername, NewMemberName);
|
||||
gj->action = groupActJoin;
|
||||
|
||||
gj->leader_aas = LeaderAbilities;
|
||||
|
||||
for (i = 0;i < MAX_GROUP_MEMBERS; i++) {
|
||||
if (members[i] != nullptr && members[i] != newmember) {
|
||||
for (i = 0;i < MAX_GROUP_MEMBERS; i++)
|
||||
{
|
||||
if (members[i] != nullptr && members[i] != newmember)
|
||||
{
|
||||
//fill in group join & send it
|
||||
if(members[i]->IsMerc())
|
||||
{
|
||||
@ -284,18 +296,23 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
|
||||
{
|
||||
strcpy(gj->yourname, members[i]->GetCleanName());
|
||||
}
|
||||
if(members[i]->IsClient()) {
|
||||
if(members[i]->IsClient())
|
||||
{
|
||||
members[i]->CastToClient()->QueuePacket(outapp);
|
||||
|
||||
//put new member into existing person's list
|
||||
//put new member into existing group members' list(s)
|
||||
strcpy(members[i]->CastToClient()->GetPP().groupMembers[this->GroupCount()-1], NewMemberName);
|
||||
}
|
||||
|
||||
//put this existing person into the new member's list
|
||||
if(InZone && newmember->IsClient()) {
|
||||
//put existing group member(s) into the new member's list
|
||||
if(InZone && newmember->IsClient())
|
||||
{
|
||||
if(IsLeader(members[i]))
|
||||
{
|
||||
strcpy(newmember->CastToClient()->GetPP().groupMembers[0], members[i]->GetCleanName());
|
||||
else {
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(newmember->CastToClient()->GetPP().groupMembers[x], members[i]->GetCleanName());
|
||||
x++;
|
||||
}
|
||||
@ -337,7 +354,9 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
|
||||
#endif //BOTS
|
||||
}
|
||||
else
|
||||
{
|
||||
database.SetGroupID(NewMemberName, GetID(), CharacterID, ismerc);
|
||||
}
|
||||
|
||||
safe_delete(outapp);
|
||||
|
||||
@ -512,6 +531,30 @@ void Group::MemberZoned(Mob* removemob) {
|
||||
mentoree = nullptr;
|
||||
}
|
||||
|
||||
void Group::SendGroupJoinOOZ(Mob* NewMember) {
|
||||
|
||||
if (NewMember == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!NewMember->HasGroup())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//send updates to clients out of zone...
|
||||
ServerPacket* pack = new ServerPacket(ServerOP_GroupJoin, sizeof(ServerGroupJoin_Struct));
|
||||
ServerGroupJoin_Struct* gj = (ServerGroupJoin_Struct*)pack->pBuffer;
|
||||
gj->gid = GetID();
|
||||
gj->zoneid = zone->GetZoneID();
|
||||
gj->instance_id = zone->GetInstanceID();
|
||||
strcpy(gj->member_name, NewMember->GetName());
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
|
||||
}
|
||||
|
||||
bool Group::DelMemberOOZ(const char *Name) {
|
||||
|
||||
if(!Name) return false;
|
||||
@ -619,7 +662,8 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender)
|
||||
#endif //BOTS
|
||||
}
|
||||
|
||||
if (!ignoresender) {
|
||||
if (!ignoresender)
|
||||
{
|
||||
strcpy(gu->yourname,oldmember->GetCleanName());
|
||||
strcpy(gu->membername,oldmember->GetCleanName());
|
||||
gu->action = groupActLeave;
|
||||
@ -629,7 +673,18 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender)
|
||||
}
|
||||
|
||||
if(oldmember->IsClient())
|
||||
database.SetGroupID(oldmember->GetCleanName(), 0, oldmember->CastToClient()->CharacterID());
|
||||
{
|
||||
database.SetGroupID(oldmember->GetCleanName(), 0, oldmember->CastToClient()->CharacterID(), false);
|
||||
}
|
||||
|
||||
if(oldmember->IsMerc())
|
||||
{
|
||||
Client* owner = oldmember->CastToMerc()->GetMercOwner();
|
||||
if(owner)
|
||||
{
|
||||
database.SetGroupID(oldmember->GetName(), 0, owner->CharacterID(), true);
|
||||
}
|
||||
}
|
||||
|
||||
oldmember->SetGrouped(false);
|
||||
disbandcheck = true;
|
||||
@ -819,20 +874,33 @@ void Group::DisbandGroup() {
|
||||
Client *Leader = nullptr;
|
||||
|
||||
uint32 i;
|
||||
for (i = 0; i < MAX_GROUP_MEMBERS; i++) {
|
||||
if (members[i] == nullptr) {
|
||||
for (i = 0; i < MAX_GROUP_MEMBERS; i++)
|
||||
{
|
||||
if (members[i] == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (members[i]->IsClient()) {
|
||||
if (members[i]->IsClient())
|
||||
{
|
||||
if(IsLeader(members[i]))
|
||||
{
|
||||
Leader = members[i]->CastToClient();
|
||||
}
|
||||
|
||||
strcpy(gu->yourname, members[i]->GetName());
|
||||
database.SetGroupID(members[i]->GetName(), 0, members[i]->CastToClient()->CharacterID());
|
||||
database.SetGroupID(members[i]->GetName(), 0, members[i]->CastToClient()->CharacterID(), false);
|
||||
members[i]->CastToClient()->QueuePacket(outapp);
|
||||
SendMarkedNPCsToMember(members[i]->CastToClient(), true);
|
||||
|
||||
}
|
||||
|
||||
if (members[i]->IsMerc())
|
||||
{
|
||||
Client* owner = members[i]->CastToMerc()->GetMercOwner();
|
||||
if(owner)
|
||||
{
|
||||
database.SetGroupID(members[i]->GetName(), 0, owner->CharacterID(), true);
|
||||
}
|
||||
}
|
||||
|
||||
members[i]->SetGrouped(false);
|
||||
@ -852,9 +920,12 @@ void Group::DisbandGroup() {
|
||||
|
||||
entity_list.RemoveGroup(GetID());
|
||||
if(GetID() != 0)
|
||||
{
|
||||
database.ClearGroup(GetID());
|
||||
}
|
||||
|
||||
if(Leader && (Leader->IsLFP())) {
|
||||
if(Leader && (Leader->IsLFP()))
|
||||
{
|
||||
Leader->UpdateLFP();
|
||||
}
|
||||
|
||||
@ -936,8 +1007,12 @@ uint8 Group::GroupCount() {
|
||||
uint8 MemberCount = 0;
|
||||
|
||||
for(uint8 i = 0; i < MAX_GROUP_MEMBERS; ++i)
|
||||
{
|
||||
if(membername[i][0])
|
||||
{
|
||||
++MemberCount;
|
||||
}
|
||||
}
|
||||
|
||||
return MemberCount;
|
||||
}
|
||||
@ -1071,7 +1146,14 @@ void Client::LeaveGroup() {
|
||||
|
||||
if(g)
|
||||
{
|
||||
if(g->GroupCount() < 3)
|
||||
int32 MemberCount = g->GroupCount();
|
||||
// Account for both client and merc leaving the group
|
||||
if (GetMerc() && GetMerc()->HasGroup() && GetMerc()->GetGroup() == g)
|
||||
{
|
||||
MemberCount -= 1;
|
||||
}
|
||||
|
||||
if(MemberCount < 3)
|
||||
{
|
||||
g->DisbandGroup();
|
||||
}
|
||||
@ -1080,17 +1162,17 @@ void Client::LeaveGroup() {
|
||||
g->DelMember(this);
|
||||
if (GetMerc() && GetMerc()->HasGroup() && GetMerc()->GetGroup() == g)
|
||||
{
|
||||
g->DelMember(GetMerc());
|
||||
GetMerc()->RemoveMercFromGroup(GetMerc(), GetMerc()->GetGroup());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//force things a little
|
||||
database.SetGroupID(GetName(), 0, CharacterID());
|
||||
database.SetGroupID(GetName(), 0, CharacterID(), false);
|
||||
if (GetMerc())
|
||||
{
|
||||
database.SetGroupID(GetMerc()->GetName(), 0, CharacterID());
|
||||
database.SetGroupID(GetMerc()->GetName(), 0, CharacterID(), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ public:
|
||||
Group(uint32 gid);
|
||||
~Group();
|
||||
|
||||
bool AddMember(Mob* newmember, const char* NewMemberName = nullptr, uint32 CharacterID = 0);
|
||||
bool AddMember(Mob* newmember, const char* NewMemberName = nullptr, uint32 CharacterID = 0, bool ismerc = false);
|
||||
void AddMember(const char* NewMemberName);
|
||||
void SendUpdate(uint32 type,Mob* member);
|
||||
void SendLeadershipAAUpdate();
|
||||
@ -63,6 +63,7 @@ public:
|
||||
bool IsGroupMember(const char *Name);
|
||||
bool Process();
|
||||
bool IsGroup() { return true; }
|
||||
void SendGroupJoinOOZ(Mob* NewMember);
|
||||
void CastGroupSpell(Mob* caster,uint16 spellid);
|
||||
void GroupBardPulse(Mob* caster,uint16 spellid);
|
||||
void SplitExp(uint32 exp, Mob* other);
|
||||
|
||||
238
zone/merc.cpp
238
zone/merc.cpp
@ -1287,8 +1287,8 @@ bool Merc::Process()
|
||||
|
||||
if (GetDepop())
|
||||
{
|
||||
//SetMercCharacterID(0);
|
||||
//SetOwnerID(0);
|
||||
SetMercCharacterID(0);
|
||||
SetOwnerID(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1297,7 +1297,8 @@ bool Merc::Process()
|
||||
//return false; //merc can live after client dies, not sure how long
|
||||
}
|
||||
|
||||
if(IsSuspended()) {
|
||||
if(IsSuspended())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -5368,12 +5369,14 @@ bool Client::CheckCanRetainMerc(uint32 upkeep) {
|
||||
bool Client::CheckCanSpawnMerc(uint32 template_id) {
|
||||
|
||||
// Check if mercs are enabled globally
|
||||
if(!RuleB(Mercs, AllowMercs)) {
|
||||
if(!RuleB(Mercs, AllowMercs))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if zone allows mercs
|
||||
if(!zone->AllowMercs()) {
|
||||
if(!zone->AllowMercs())
|
||||
{
|
||||
SendMercResponsePackets(3);
|
||||
return false;
|
||||
}
|
||||
@ -5381,31 +5384,36 @@ bool Client::CheckCanSpawnMerc(uint32 template_id) {
|
||||
MercTemplate* mercTemplate = zone->GetMercTemplate(template_id);
|
||||
|
||||
// Invalid merc data
|
||||
if(!mercTemplate) {
|
||||
if(!mercTemplate)
|
||||
{
|
||||
SendMercResponsePackets(11);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check client version
|
||||
if(GetClientVersion() < mercTemplate->ClientVersion) {
|
||||
if(GetClientVersion() < mercTemplate->ClientVersion)
|
||||
{
|
||||
SendMercResponsePackets(3);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for raid
|
||||
if(HasRaid()) {
|
||||
if(HasRaid())
|
||||
{
|
||||
SendMercResponsePackets(4);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check group size
|
||||
if(HasGroup() && GetGroup()->GroupCount() >= MAX_GROUP_MEMBERS) {
|
||||
if(GetGroup() && GetGroup()->GroupCount() >= MAX_GROUP_MEMBERS) // database.GroupCount(GetGroup()->GetID())
|
||||
{
|
||||
SendMercResponsePackets(8);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check in combat
|
||||
if(GetAggroCount() > 0) {
|
||||
if(GetAggroCount() > 0)
|
||||
{
|
||||
SendMercResponsePackets(9);
|
||||
return false;
|
||||
}
|
||||
@ -5584,6 +5592,10 @@ void Client::SpawnMerc(Merc* merc, bool setMaxStats) {
|
||||
|
||||
if (!merc || !CheckCanSpawnMerc(merc->GetMercTemplateID()))
|
||||
{
|
||||
if (merc)
|
||||
{
|
||||
merc->Suspend();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -5618,9 +5630,7 @@ bool Merc::Suspend() {
|
||||
mercOwner->GetMercInfo().Stance = GetStance();
|
||||
Save();
|
||||
mercOwner->GetMercTimer()->Disable();
|
||||
|
||||
mercOwner->SendMercSuspendResponsePacket(mercOwner->GetMercInfo().SuspendedTime);
|
||||
|
||||
mercOwner->SendMercTimer(this);
|
||||
|
||||
Depop();
|
||||
@ -5634,6 +5644,25 @@ bool Merc::Suspend() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Client::MercOnlyOrNoGroup() {
|
||||
|
||||
if (!GetGroup())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (GetMerc())
|
||||
{
|
||||
if (GetMerc()->HasGroup() && GetMerc()->GetGroup() == GetGroup())
|
||||
{
|
||||
if (GetGroup()->GroupCount() < 3)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Merc::Unsuspend(bool setMaxStats) {
|
||||
|
||||
Client* mercOwner = nullptr;
|
||||
@ -5657,65 +5686,15 @@ bool Merc::Unsuspend(bool setMaxStats) {
|
||||
mercOwner->SendMercenaryUnsuspendPacket(0);
|
||||
mercOwner->SendMercenaryUnknownPacket(1);
|
||||
mercOwner->GetMercInfo().SuspendedTime = 0;
|
||||
// Reset the upkeep timer
|
||||
mercOwner->GetMercInfo().MercTimerRemaining = RuleI(Mercs, UpkeepIntervalMS);
|
||||
mercOwner->GetMercTimer()->Start(RuleI(Mercs, UpkeepIntervalMS));
|
||||
mercOwner->GetMercTimer()->SetTimer(mercOwner->GetMercInfo().MercTimerRemaining);
|
||||
//mercOwner->GetMercTimer()->SetTimer(mercOwner->GetMercInfo().MercTimerRemaining);
|
||||
mercOwner->SendMercTimer(this);
|
||||
if(!mercOwner->GetPTimers().Expired(&database, pTimerMercSuspend, false))
|
||||
mercOwner->GetPTimers().Clear(&database, pTimerMercSuspend);
|
||||
|
||||
//mercOwner->SendMercPersonalInfo();
|
||||
Group* g = entity_list.GetGroupByClient(mercOwner);
|
||||
|
||||
//nobody from our group is here... start a new group
|
||||
if(!g)
|
||||
{
|
||||
g = new Group(mercOwner);
|
||||
|
||||
if(!g) {
|
||||
delete g;
|
||||
g = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
entity_list.AddGroup(g);
|
||||
|
||||
if(g->GetID() == 0) {
|
||||
delete g;
|
||||
g = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(AddMercToGroup(this, g))
|
||||
{
|
||||
entity_list.AddGroup(g, g->GetID());
|
||||
database.SetGroupLeaderName(g->GetID(), mercOwner->GetName());
|
||||
database.SetGroupID(mercOwner->GetName(), g->GetID(), mercOwner->CharacterID());
|
||||
database.SetGroupID(this->GetName(), g->GetID(), mercOwner->CharacterID(), true);
|
||||
database.RefreshGroupFromDB(mercOwner);
|
||||
g->SaveGroupLeaderAA();
|
||||
loaded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
g->DisbandGroup();
|
||||
}
|
||||
}
|
||||
else if (AddMercToGroup(this, mercOwner->GetGroup()))
|
||||
{
|
||||
// Group already exists
|
||||
database.SetGroupID(GetName(), mercOwner->GetGroup()->GetID(), mercOwner->CharacterID(), true);
|
||||
database.RefreshGroupFromDB(mercOwner);
|
||||
|
||||
loaded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(MERC_DEBUG > 0)
|
||||
mercOwner->Message(7, "Mercenary failed to join the group - Suspending");
|
||||
|
||||
Suspend();
|
||||
}
|
||||
|
||||
MercJoinClientGroup();
|
||||
|
||||
if(loaded)
|
||||
{
|
||||
@ -5788,7 +5767,7 @@ void Merc::Depop() {
|
||||
|
||||
entity_list.RemoveFromHateLists(this);
|
||||
|
||||
if(HasGroup())
|
||||
if(GetGroup())
|
||||
{
|
||||
RemoveMercFromGroup(this, GetGroup());
|
||||
}
|
||||
@ -5820,7 +5799,9 @@ bool Merc::RemoveMercFromGroup(Merc* merc, Group* group) {
|
||||
if(group->DelMember(merc, true))
|
||||
{
|
||||
if(merc->GetMercCharacterID() != 0)
|
||||
{
|
||||
database.SetGroupID(merc->GetName(), 0, merc->GetMercCharacterID(), true);
|
||||
}
|
||||
}
|
||||
|
||||
if(group->GroupCount() <= 1 && ZoneLoaded)
|
||||
@ -5830,6 +5811,17 @@ bool Merc::RemoveMercFromGroup(Merc* merc, Group* group) {
|
||||
}
|
||||
else
|
||||
{
|
||||
// A merc is group leader - Disband and re-group each member with their mercs
|
||||
for(int i = 0; i < MAX_GROUP_MEMBERS; i++)
|
||||
{
|
||||
if(!group->members[i])
|
||||
continue;
|
||||
|
||||
if(!group->members[i]->IsClient())
|
||||
continue;
|
||||
|
||||
group->members[i]->CastToClient()->LeaveGroup();
|
||||
}
|
||||
for(int i = 0; i < MAX_GROUP_MEMBERS; i++)
|
||||
{
|
||||
if(!group->members[i])
|
||||
@ -5838,15 +5830,9 @@ bool Merc::RemoveMercFromGroup(Merc* merc, Group* group) {
|
||||
if(!group->members[i]->IsMerc())
|
||||
continue;
|
||||
|
||||
Merc* groupmerc = group->members[i]->CastToMerc();
|
||||
|
||||
//groupmerc->SetOwnerID(0);
|
||||
if (!groupmerc->IsSuspended())
|
||||
{
|
||||
groupmerc->Suspend();
|
||||
database.SetGroupID(groupmerc->GetCleanName(), 0, groupmerc->GetMercCharacterID(), true);
|
||||
}
|
||||
group->members[i]->CastToMerc()->MercJoinClientGroup();
|
||||
}
|
||||
// Group should be removed by now, but just in case:
|
||||
group->DisbandGroup();
|
||||
}
|
||||
|
||||
@ -5857,16 +5843,112 @@ bool Merc::RemoveMercFromGroup(Merc* merc, Group* group) {
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool Merc::MercJoinClientGroup() {
|
||||
|
||||
Client* mercOwner = nullptr;
|
||||
|
||||
if(GetMercOwner())
|
||||
{
|
||||
mercOwner = GetMercOwner();
|
||||
}
|
||||
|
||||
if(!mercOwner)
|
||||
{
|
||||
Suspend();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(GetID())
|
||||
{
|
||||
if (HasGroup())
|
||||
{
|
||||
RemoveMercFromGroup(this, GetGroup());
|
||||
}
|
||||
|
||||
Group* g = entity_list.GetGroupByClient(mercOwner);
|
||||
|
||||
//nobody from our group is here... start a new group
|
||||
if(!g)
|
||||
{
|
||||
g = new Group(mercOwner);
|
||||
|
||||
if(!g)
|
||||
{
|
||||
delete g;
|
||||
g = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
entity_list.AddGroup(g);
|
||||
|
||||
if(g->GetID() == 0)
|
||||
{
|
||||
delete g;
|
||||
g = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(AddMercToGroup(this, g))
|
||||
{
|
||||
entity_list.AddGroup(g, g->GetID());
|
||||
database.SetGroupLeaderName(g->GetID(), mercOwner->GetName());
|
||||
database.SetGroupID(mercOwner->GetName(), g->GetID(), mercOwner->CharacterID(), false);
|
||||
database.SetGroupID(this->GetName(), g->GetID(), mercOwner->CharacterID(), true);
|
||||
database.RefreshGroupFromDB(mercOwner);
|
||||
g->SaveGroupLeaderAA();
|
||||
if(MERC_DEBUG > 0)
|
||||
mercOwner->Message(7, "Mercenary Debug: Mercenary joined new group.");
|
||||
}
|
||||
else
|
||||
{
|
||||
g->DisbandGroup();
|
||||
Suspend();
|
||||
|
||||
if(MERC_DEBUG > 0)
|
||||
mercOwner->Message(7, "Mercenary Debug: Mercenary disbanded new group.");
|
||||
}
|
||||
|
||||
}
|
||||
else if (AddMercToGroup(this, mercOwner->GetGroup()))
|
||||
{
|
||||
// Group already exists
|
||||
database.SetGroupID(GetName(), mercOwner->GetGroup()->GetID(), mercOwner->CharacterID(), true);
|
||||
database.RefreshGroupFromDB(mercOwner);
|
||||
// Update members that are out of zone
|
||||
GetGroup()->SendGroupJoinOOZ(this);
|
||||
|
||||
if(MERC_DEBUG > 0)
|
||||
mercOwner->Message(7, "Mercenary Debug: Mercenary joined existing group.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Suspend();
|
||||
|
||||
if(MERC_DEBUG > 0)
|
||||
mercOwner->Message(7, "Mercenary Debug: Mercenary failed to join the group - Suspending");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Merc::AddMercToGroup(Merc* merc, Group* group) {
|
||||
bool Result = false;
|
||||
|
||||
if(merc && group) {
|
||||
// Remove merc from current group if any
|
||||
if(merc->HasGroup()) {
|
||||
// Remove merc from current group if it's not the destination group
|
||||
if(merc->HasGroup())
|
||||
{
|
||||
if(merc->GetGroup() == group && merc->GetMercOwner())
|
||||
{
|
||||
// Merc is already in the destination group
|
||||
merc->SetFollowID(merc->GetMercOwner()->GetID());
|
||||
return true;
|
||||
}
|
||||
merc->RemoveMercFromGroup(merc, merc->GetGroup());
|
||||
}
|
||||
//Try and add the member, followed by checking if the merc owner exists.
|
||||
if(group->AddMember(merc) && merc->GetMercOwner() != nullptr)
|
||||
if(group->AddMember(merc) && merc->GetMercOwner())
|
||||
{
|
||||
merc->SetFollowID(merc->GetMercOwner()->GetID());
|
||||
Result = true;
|
||||
|
||||
@ -138,6 +138,7 @@ public:
|
||||
bool Spawn(Client *owner);
|
||||
bool Suspend();
|
||||
bool Unsuspend(bool setMaxStats);
|
||||
bool MercJoinClientGroup();
|
||||
void Zone();
|
||||
virtual void Depop();
|
||||
virtual bool Save();
|
||||
|
||||
@ -907,7 +907,7 @@ uint16 QuestManager::scribespells(uint8 max_level, uint8 min_level) {
|
||||
uint16 book_slot, count;
|
||||
uint16 curspell;
|
||||
|
||||
uint16 Char_ID = initiator->CharacterID();
|
||||
uint32 Char_ID = initiator->CharacterID();
|
||||
bool SpellGlobalRule = RuleB(Spells, EnableSpellGlobals);
|
||||
bool SpellGlobalCheckResult = 0;
|
||||
|
||||
|
||||
@ -4928,7 +4928,7 @@ int Client::FindSpellBookSlotBySpellID(uint16 spellid) {
|
||||
return -1; //default
|
||||
}
|
||||
|
||||
bool Client::SpellGlobalCheck(uint16 spell_ID, uint16 char_ID) {
|
||||
bool Client::SpellGlobalCheck(uint16 spell_ID, uint32 char_ID) {
|
||||
|
||||
std::string spell_Global_Name;
|
||||
int spell_Global_Value;
|
||||
|
||||
@ -831,12 +831,11 @@ void WorldServer::Process() {
|
||||
}
|
||||
case ServerOP_GroupInvite: {
|
||||
// A player in another zone invited a player in this zone to join their group.
|
||||
//
|
||||
GroupInvite_Struct* gis = (GroupInvite_Struct*)pack->pBuffer;
|
||||
|
||||
Mob *Invitee = entity_list.GetMob(gis->invitee_name);
|
||||
|
||||
if(Invitee && Invitee->IsClient() && !Invitee->IsGrouped() && !Invitee->IsRaidGrouped())
|
||||
if(Invitee && Invitee->IsClient() && Invitee->CastToClient()->MercOnlyOrNoGroup() && !Invitee->IsRaidGrouped())
|
||||
{
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupInvite, sizeof(GroupInvite_Struct));
|
||||
memcpy(outapp->pBuffer, gis, sizeof(GroupInvite_Struct));
|
||||
@ -848,7 +847,6 @@ void WorldServer::Process() {
|
||||
}
|
||||
case ServerOP_GroupFollow: {
|
||||
// Player in another zone accepted a group invitation from a player in this zone.
|
||||
//
|
||||
ServerGroupFollow_Struct* sgfs = (ServerGroupFollow_Struct*) pack->pBuffer;
|
||||
|
||||
Mob* Inviter = entity_list.GetClientByName(sgfs->gf.name1);
|
||||
@ -857,12 +855,15 @@ void WorldServer::Process() {
|
||||
{
|
||||
Group* group = entity_list.GetGroupByClient(Inviter->CastToClient());
|
||||
|
||||
if(!group){
|
||||
|
||||
if(!group)
|
||||
{
|
||||
//Make new group
|
||||
group = new Group(Inviter);
|
||||
|
||||
if(!group)
|
||||
if (!group)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
entity_list.AddGroup(group);
|
||||
|
||||
@ -871,10 +872,8 @@ void WorldServer::Process() {
|
||||
break;
|
||||
}
|
||||
|
||||
database.SetGroupID(Inviter->GetName(), group->GetID(), Inviter->CastToClient()->CharacterID());
|
||||
|
||||
database.SetGroupID(Inviter->GetName(), group->GetID(), Inviter->CastToClient()->CharacterID(), false);
|
||||
database.SetGroupLeaderName(group->GetID(), Inviter->GetName());
|
||||
|
||||
group->UpdateGroupAAs();
|
||||
|
||||
if(Inviter->CastToClient()->GetClientVersion() < EQClientSoD)
|
||||
@ -891,25 +890,22 @@ void WorldServer::Process() {
|
||||
else
|
||||
{
|
||||
// SoD and later
|
||||
//
|
||||
Inviter->CastToClient()->SendGroupCreatePacket();
|
||||
Inviter->CastToClient()->SendGroupLeaderChangePacket(Inviter->GetName());
|
||||
Inviter->CastToClient()->SendGroupJoinAcknowledge();
|
||||
}
|
||||
}
|
||||
|
||||
if(!group)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
EQApplicationPacket* outapp=new EQApplicationPacket(OP_GroupFollow, sizeof(GroupGeneric_Struct));
|
||||
|
||||
GroupGeneric_Struct *gg = (GroupGeneric_Struct *)outapp->pBuffer;
|
||||
|
||||
strn0cpy(gg->name1, sgfs->gf.name1, sizeof(gg->name1));
|
||||
|
||||
strn0cpy(gg->name2, sgfs->gf.name2, sizeof(gg->name2));
|
||||
|
||||
Inviter->CastToClient()->QueuePacket(outapp);
|
||||
|
||||
safe_delete(outapp);
|
||||
|
||||
if(!group->AddMember(nullptr, sgfs->gf.name2, sgfs->CharacterID))
|
||||
@ -919,46 +915,35 @@ void WorldServer::Process() {
|
||||
Inviter->CastToClient()->UpdateLFP();
|
||||
|
||||
ServerPacket* pack2 = new ServerPacket(ServerOP_GroupJoin, sizeof(ServerGroupJoin_Struct));
|
||||
|
||||
ServerGroupJoin_Struct* gj = (ServerGroupJoin_Struct*)pack2->pBuffer;
|
||||
|
||||
gj->gid = group->GetID();
|
||||
|
||||
gj->zoneid = zone->GetZoneID();
|
||||
|
||||
gj->instance_id = zone->GetInstanceID();
|
||||
|
||||
strn0cpy(gj->member_name, sgfs->gf.name2, sizeof(gj->member_name));
|
||||
|
||||
worldserver.SendPacket(pack2);
|
||||
|
||||
safe_delete(pack2);
|
||||
|
||||
|
||||
|
||||
// Send acknowledgement back to the Invitee to let them know we have added them to the group.
|
||||
//
|
||||
ServerPacket* pack3 = new ServerPacket(ServerOP_GroupFollowAck, sizeof(ServerGroupFollowAck_Struct));
|
||||
|
||||
ServerGroupFollowAck_Struct* sgfas = (ServerGroupFollowAck_Struct*)pack3->pBuffer;
|
||||
|
||||
strn0cpy(sgfas->Name, sgfs->gf.name2, sizeof(sgfas->Name));
|
||||
|
||||
worldserver.SendPacket(pack3);
|
||||
|
||||
safe_delete(pack3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_GroupFollowAck: {
|
||||
// The Inviter (in another zone) has successfully added the Invitee (in this zone) to the group.
|
||||
//
|
||||
ServerGroupFollowAck_Struct* sgfas = (ServerGroupFollowAck_Struct*)pack->pBuffer;
|
||||
|
||||
Client *c = entity_list.GetClientByName(sgfas->Name);
|
||||
Client *client = entity_list.GetClientByName(sgfas->Name);
|
||||
|
||||
if(!c)
|
||||
if(!client)
|
||||
break;
|
||||
|
||||
uint32 groupid = database.GetGroupID(c->GetName());
|
||||
uint32 groupid = database.GetGroupID(client->GetName());
|
||||
|
||||
Group* group = nullptr;
|
||||
|
||||
@ -974,26 +959,30 @@ void WorldServer::Process() {
|
||||
entity_list.AddGroup(group, groupid);
|
||||
else
|
||||
group = nullptr;
|
||||
} //else, somebody from our group is already here...
|
||||
}
|
||||
|
||||
if(group)
|
||||
group->UpdatePlayer(c);
|
||||
group->UpdatePlayer(client);
|
||||
else
|
||||
{
|
||||
if(c->GetMerc())
|
||||
database.SetGroupID(c->GetMerc()->GetCleanName(), 0, c->CharacterID(), true);
|
||||
database.SetGroupID(c->GetName(), 0, c->CharacterID()); //cannot re-establish group, kill it
|
||||
if(client->GetMerc())
|
||||
database.SetGroupID(client->GetMerc()->GetCleanName(), 0, client->CharacterID(), true);
|
||||
database.SetGroupID(client->GetName(), 0, client->CharacterID(), false); //cannot re-establish group, kill it
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(group)
|
||||
{
|
||||
database.RefreshGroupFromDB(c);
|
||||
if (client->GetMerc())
|
||||
{
|
||||
client->GetMerc()->MercJoinClientGroup();
|
||||
}
|
||||
database.RefreshGroupFromDB(client);
|
||||
|
||||
group->SendHPPacketsTo(c);
|
||||
group->SendHPPacketsTo(client);
|
||||
|
||||
// If the group leader is not set, pull the group leader infomrmation from the database.
|
||||
// If the group leader is not set, pull the group leader information from the database.
|
||||
if(!group->GetLeader())
|
||||
{
|
||||
char ln[64];
|
||||
@ -1019,6 +1008,10 @@ void WorldServer::Process() {
|
||||
|
||||
}
|
||||
}
|
||||
else if (client->GetMerc())
|
||||
{
|
||||
client->GetMerc()->MercJoinClientGroup();
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
@ -2563,18 +2563,22 @@ void ZoneDatabase::RefreshGroupFromDB(Client *client){
|
||||
std::string query = StringFormat("SELECT name FROM group_id WHERE groupid = %d", group->GetID());
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
printf("Error in group update query: %s\n", results.ErrorMessage().c_str());
|
||||
else
|
||||
{
|
||||
printf("Error in group update query: %s\n", results.ErrorMessage().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
if(index >= 6)
|
||||
continue;
|
||||
continue;
|
||||
|
||||
if(strcmp(client->GetName(), row[0]) == 0)
|
||||
continue;
|
||||
continue;
|
||||
|
||||
strcpy(gu->membername[index], row[0]);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
client->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user