Skip to content

Commit 5a052da

Browse files
authored
Remove Party Member update (#1476)
* Remove party member from list (#1475) * Do not disband party when party leader disconnects (possible fix for 1358) - new party message about changing leader - CPartyDef::RemoveMember refactoring There is no solution, when party leader removes himself from the party, since the packet for disbanding and removing leader is the same.
1 parent b87d722 commit 5a052da

File tree

6 files changed

+64
-29
lines changed

6 files changed

+64
-29
lines changed

Changelog.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4056,3 +4056,6 @@ When setting a property like MORE to the a spell or skill defname, trying to rea
40564056

40574057
24-09-2025, Mulambo
40584058
- Added: ARGN3 for trigger @PersonalSpace [R/W], allowing to bypass maximum stamina requirement (default 1 = require maximum stamina) when stepping over players.
4059+
4060+
26-09-2025, Mulambo
4061+
- Changed: When the party leader gets disconnected (or deleted), new party leader is appointed, instead of disbanding the party.

src/game/chars/CChar.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ CChar::~CChar()
354354

355355
if (m_pParty)
356356
{
357-
m_pParty->RemoveMember( GetUID(), GetUID() );
357+
m_pParty->RemoveMember(GetUID(), GetUID(), false);
358358
m_pParty = nullptr;
359359
}
360360
//Guild_Resign(MEMORY_GUILD); Moved to the ClearPlayer method otherwise it will cause a server crash because the deleted player will still be found in the guild list.
@@ -493,13 +493,6 @@ void CChar::ClientDetach()
493493
if ( !IsClientActive() )
494494
return;
495495

496-
if ( m_pParty && m_pParty->IsPartyMaster( this ))
497-
{
498-
// Party must disband if the master is logged out.
499-
m_pParty->Disband(GetUID());
500-
m_pParty = nullptr;
501-
}
502-
503496
// If this char is on a IT_SHIP then we need to stop the ship !
504497
if ( m_pArea && m_pArea->IsFlag( REGION_FLAG_SHIP ))
505498
{
@@ -548,7 +541,7 @@ void CChar::SetDisconnected(CSector* pNewSector)
548541

549542
if (m_pParty)
550543
{
551-
m_pParty->RemoveMember( GetUID(), GetUID() );
544+
m_pParty->RemoveMember(GetUID(), GetUID(), false);
552545
m_pParty = nullptr;
553546
}
554547

src/game/clients/CParty.cpp

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -293,43 +293,60 @@ void CPartyDef::AcceptMember( CChar *pChar )
293293
SendAddList(nullptr);
294294
}
295295

296-
bool CPartyDef::RemoveMember( CUID uidRemove, CUID uidCommand )
296+
bool CPartyDef::RemoveMember(const CUID& uidRemove, const CUID &uidCommand, const bool fDisband)
297297
{
298298
ADDTOCALLSTACK("CPartyDef::RemoveMember");
299-
// ARGS:
300-
// uidRemove = Who is being removed.
301-
// uidCommand = who removed this person (only the master or self can remove)
302-
//
303-
// NOTE: remove of the master will cause the party to disband.
304299

305-
if ( m_Chars.GetCharCount() <= 0 )
300+
if (m_Chars.GetCharCount() <= 0)
306301
return false;
307302

308-
CUID uidMaster(GetMaster());
309-
if ( (uidRemove != uidCommand) && (uidCommand != uidMaster) )
303+
const CUID uidMaster(GetMaster());
304+
if (uidRemove != uidCommand && uidCommand != uidMaster)
310305
return false;
311306

312307
CChar *pCharRemove(uidRemove.CharFind());
313-
if ( !pCharRemove )
308+
if (!pCharRemove)
314309
return false;
315-
if ( !IsInParty(pCharRemove) )
310+
if (!IsInParty(pCharRemove))
316311
return false;
317-
if ( uidRemove == uidMaster )
312+
if (fDisband && uidRemove == uidMaster)
318313
return Disband(uidMaster);
319314

320315
CChar *pSrc = uidCommand.CharFind();
321-
if ( pSrc && IsTrigUsed(TRIGGER_PARTYREMOVE) )
316+
if (pSrc && IsTrigUsed(TRIGGER_PARTYREMOVE))
322317
{
323-
if ( pCharRemove->OnTrigger(CTRIG_PartyRemove, CScriptParserBufs::GetCScriptTriggerArgsPtr(), pSrc) == TRIGRET_RET_TRUE )
318+
if (pCharRemove->OnTrigger(CTRIG_PartyRemove, CScriptParserBufs::GetCScriptTriggerArgsPtr(), pSrc) == TRIGRET_RET_TRUE)
324319
return false;
325320
}
326-
if ( IsTrigUsed(TRIGGER_PARTYLEAVE) )
321+
if (IsTrigUsed(TRIGGER_PARTYLEAVE))
327322
{
328-
if ( pCharRemove->OnTrigger(CTRIG_PartyLeave, CScriptParserBufs::GetCScriptTriggerArgsPtr(), pCharRemove) == TRIGRET_RET_TRUE )
323+
if (pCharRemove->OnTrigger(CTRIG_PartyLeave, CScriptParserBufs::GetCScriptTriggerArgsPtr(), pCharRemove) == TRIGRET_RET_TRUE)
329324
return false;
330325
}
331326

332-
// Remove it from the party
327+
// If the party leader left, try to promote new character to be the leader.
328+
tchar *pszChangeLeader = Str_GetTemp();
329+
if (uidRemove == uidMaster)
330+
{
331+
// No valid character on second position in the party, disband it.
332+
if (!m_Chars.IsValidIndex(1))
333+
return Disband(uidMaster);
334+
335+
const CUID newMaster(m_Chars.GetChar(1));
336+
CChar *pCharNewMaster(newMaster.CharFind());
337+
338+
// Cannot find new leader's character, disband it.
339+
if (!pCharNewMaster)
340+
return Disband(uidMaster);
341+
342+
// If new master wasn't appointed, disband the party.
343+
if (!SetMaster(pCharNewMaster))
344+
return Disband(uidMaster);
345+
346+
snprintf(pszChangeLeader, Str_TempLength(), g_Cfg.GetDefaultMsg(DEFMSG_PARTY_CHANGE_LEADER), pCharNewMaster->GetName());
347+
}
348+
349+
// Remove the character from the party.
333350
SendRemoveList(pCharRemove, true);
334351
DetachChar(pCharRemove);
335352
pCharRemove->SysMessageDefault(DEFMSG_PARTY_LEAVE_2);
@@ -338,13 +355,20 @@ bool CPartyDef::RemoveMember( CUID uidRemove, CUID uidCommand )
338355
snprintf(pszMsg, Str_TempLength(), g_Cfg.GetDefaultMsg(DEFMSG_PARTY_LEAVE_1), pCharRemove->GetName());
339356
SysMessageAll(pszMsg);
340357

341-
if ( m_Chars.GetCharCount() <= 1 )
358+
// Disband the party if I'm alone.
359+
if (m_Chars.GetCharCount() <= 1)
342360
{
343-
// Disband the party
344361
SysMessageAll(g_Cfg.GetDefaultMsg(DEFMSG_PARTY_LEAVE_LAST_PERSON));
345362
return Disband(uidMaster);
346363
}
347364

365+
// Notify about change in party leadership (we need to do it here, so it doesn't get sent to the previous leader).
366+
if (uidRemove == uidMaster)
367+
SysMessageAll(pszChangeLeader);
368+
369+
// We still have a party, notify other members about removal.
370+
SendRemoveList(pCharRemove, false);
371+
348372
return true;
349373
}
350374

src/game/clients/CParty.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,20 @@ class CPartyDef : public CSObjListRec, public CScriptObj
7878

7979
// Commands
8080
bool Disband( CUID uidMaster );
81-
bool RemoveMember( CUID uidRemove, CUID uidCommand );
81+
82+
/**
83+
* Removes a member from party. If leader is removed, it tries to pass leader to another character.
84+
*
85+
* @note We need to switch characters at leader position before we remove him, because original client doesn't like removing leader and thinks, the party
86+
* was disbanded (Classic UO doesn't care though).
87+
*
88+
* @param uidRemove Character being removed.
89+
* @param uidCommand Character, who issued the removal (leader or self).
90+
* @param fDisband If set to false, we try to change leader instead of disbanding the party.
91+
*
92+
* @return True if successfully removed, false otherwise.
93+
*/
94+
bool RemoveMember(const CUID& uidRemove, const CUID &uidCommand, bool fDisband = true);
8295
void AcceptMember( CChar * pChar );
8396
void SetLootFlag( CChar * pChar, bool fSet );
8497
bool GetLootFlag( const CChar * pChar );

src/network/receive.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2655,6 +2655,7 @@ bool PacketPartyMessage::onReceive(CNetState* net)
26552655
client->addTarget( CLIMODE_TARG_PARTY_ADD, g_Cfg.GetDefaultMsg(DEFMSG_PARTY_TARG_WHO), false, false);
26562656
break;
26572657

2658+
// This doesn't happen, since disbanding the party is handled by client sending a packet to remove the party master.
26582659
case PARTYMSG_Disband:
26592660
if (character->m_pParty == nullptr)
26602661
return false;

src/tables/defmessages.tbl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,7 @@ MSG(PARTY_ADDED, "You have been added to the party.")
732732
MSG(PARTY_DECLINE_1, "%s: Does not wish to join the party.")
733733
MSG(PARTY_DECLINE_2, "You notify %s that you do not wish to join the party.")
734734
MSG(PARTY_DISBANDED, "Your party has disbanded.")
735+
MSG(PARTY_CHANGE_LEADER, "%s was appointed the new party leader.")
735736
MSG(PARTY_INVITE, "You have invited %s to join the party.")
736737
MSG(PARTY_INVITE_TARG, "%s: You are invited to join the party. Type /accept to join or /decline to decline the offer.")
737738
MSG(PARTY_JOINED, "%s: joined the party.")

0 commit comments

Comments
 (0)