uox3/source/cGuild.cpp
Xoduz a48d9ee299 UOX3 0.99.6-RC6
Removed arbitrary and hidden restrictions on refreshing list of online players shown with 'wholist command
Fixed an issue where player ghosts that get teleported would not see themselves get updated to new location
Fixed a server crash from clients disconnecting while running server in debug mode
Improved how container updates are sent to players; now only sends to clients that have actually opened the container, and who are still within range
Added more information about UO data files being loaded during server startup
Enhanced the GM 'add menu to allow clicking directly on images of items/npcs to add them, and adjusted size of menus to accommodate this
Fixed an issue with fleeing NPCs that could cause them to attempt to flee across time and space, regardless of distance to target/attacker in combat
Added NPC AI that runs away from players if they get too close (even outside combat). Applied to hind, rabbits, squirrels, ferrets and various birds by default:
	AI_ANIMAL_SCARED (aitype 12)
Fixed issues with NPCs fleeing forever, or getting stuck in flee/don't flee loop, by introducing max fleeing distance (50 tiles) and cooldown (30 sec) on fleeing
Updated onNameRequest JS Event to include third parameter with origin of name request, so script responses can be tailored appropriately:
	onNameRequest( myObj, requestedBy, requestSource )
		Potential values for requestSource:
			0 - Speech/System Messages
			1 - Guild Menus
			2 - Stat Window (self)
			3 - Stat Window (other)
			4 - Tooltip
			5 - Paperdoll Journal
			6 - Paperdoll
			7 - Single Click / All-Names
			8 - System
			9 - Secure Trade Window
Added Adaptive Performance System (APS) that dynamically adjust how often NPC AI/movement is checked based on overall shard performance. If performance drops below defined threshold, UOX3 gradually slows down checks for NPC AI/movement to prioritize player movement/speech/command responsiveness. If performance climbs back up above threshold, slowdowns are gradually removed. The following UOX.INI options have been added under [system] category to support this system:
	APSPERFTHRESHOLD=50 	// Performance threshold (measured in simulation cycles/sec) below which the APS kicks in
	APSINTERVAL=100 		// How often (in milliseconds) the APS checks performance and makes adjustments (if needed) to balance out shard performance
	APSDELAYSTEP=50 		// How much the delay timer is modified by (in milliseconds) each time APS makes adjustments
	APSDELAYMAXCAP=2000 	// Max amount of of delay APS can introduce for NPC AI/movement handling when attempting to restore shard performance
Added new JS Methods for Region objects:
	.GetOrePrefs( oreType )	// Get ore preference data for ore type found in town region. Returned as an array containing the following data:
		orePrefData -> [
			oreName,	// name of ore
			color,		// color of ore
			minskill,	// min skill to mine ore
			ingotName,	// name of ingot created from ore
			makemenu,	// makemenu entry for crafting something from ingot
			oreChance,	// default global chance of finding this ore type
			scriptID 	// script attached to mined ore
		],
		orePrefChance 	// Chance of finding this ore type in given town region
	.GetOreChance() 	// Get base chance of finding any ore in town region
Moved Mining skill plus gravedigging feature from hard code to scripts (js/skill/mining.js) to make it easier to maintain and/or customize, and removed hard coded variants
Gravedigging now relies on the ore resource system behind the scenes to restrict how often graves in a given area can be dug up
Fixed some incorrect references to .worldNumber Character property in misc scripts (should be .worldnumber)
Made some "hard-scripted" system messages in misc scripts use dictionary system instead
Added spawn region for banker NPCs in Serpent's Hold (dfndata/spawn/felucca/spawn_town_serpents_hold.dfn, dfndata/spawn/trammel/spawn_town_serpents_hold.dfn)
Fixed region definition of Ocllo to actually cover the entire town (dfndata/regions/regions.dfn)
Added numerous additional locations accessible with 'goplace # command, for key locations in Ilshenar, Malas, Tokuno Islands and Ter Mur (dfndata/location/location.dfn)
Revised travel-menu portion of GM menu (shortcut: 'travel) to include more travel options based on new locations (dfndata/items/travelmenu.dfn and travelmenu.bulk.dfn)
Fixed an issue where NPCs could attempt to attack targets in other worlds/instances
Added new JS Event that triggers for characters who are about to deal damage in combat. Complimentary to onDamage, which triggers for chars receiving damage:
	onDamageDeal( dmgDealer, dmgReceiver, damageValue, damageType )
Added new JS Event that can trigger in global script upon creation of new player chars. Note that this will trigger in place of onCreateDFN event for player characters:
	onCreatePlayer( pChar )
Added new JS Event that triggers for characters selecting a target with a spell. Complimentary to onSpellTarget, which triggers for targets selected with a spell:
	onSpellTargetSelect( caster, target, spellNum )
Updated onCombatStart and onCombatEnd JS Events to also trigger for the other party in combat
Updated onPickup JS Event to include a third parameter - the potential container item was picked up from. Event now also triggers event in scripts attached to said containers:
	onPickup( iPickedUp, pChar, iCont )
Added tracking of total playtime per individual character, and per account across all characters, and exposed these properties to JS engine:
	.totalPlayTime		// Account property, total playtime across all chars
	.playTime 			// Character property, total playtime on given character only
Added new player-accessible command ('playtime) to spit out the playtime of current character/account as a whole (js/commands/playtime.js)
Implemented first version of Young Player System:
	Replaced the UNUSED9 account flag with YOUNG, to be used by Young/New Player System
	Added new JS Account property that gets/sets whether player account is considered Young:
		.isYoung
	Added new Char timers:
		TIMER_YOUNGHEAL		// Restricts how often Young players are healed by NPC healers
		TIMER_YOUNGMESSAGE	// Restricts how often Young players are warned about dangerous looking monsters in overworld
	Updated GM commands 'get and 'set to get/set .isYoung property of player's account (js/commands/targeting/get.js and set.js)
	Added new UOX.INI setting to enable/disable Young Player System (enabled by default):
		YOUNGPLAYERSYSTEM=1
	If Young Player System is enabled, all newly created player accounts are automatically marked with Young flag
	Added new script to handle various restrictions and functions related to Young characters (js/player/young_player.js):
		Young characters will have [Young] displayed over their head
		Young characters will have their Young status checked and verified on every login + every stat/skill gain, to revoke the Young status if any of the following is true:
			Account has a total playtime of more than 40 hours
			Any character has more than 350 total (base) skill points
			Any character has more than 70 skill points in a single skill
			Any character has more than 150 total stat points
			Any character has more than 80 stat points in a single stat
		Young characters can renounce their Young status manually by saying the words "I renounce my young player status"
		Young characters get two additional items upon creation:
			a new player ticket (can be combined with any other players new player ticket for both players to get a reward)
			a sextant (shows Young players directions to nearest moongate/bank regardless of where they are, as long as outdoors)
		Young characters cannot target other player characters with hostile spells or skills
		Young characters cannot be the target of other player characters' hostile spells or skills
		Young characters can only cast beneficial spells upon themselves or other Young characters
		Young characters can only be the target of beneficial spells from other Young players
		Young players (and their pets/followers) cannot attack or harm any other players (or their pets/followers), nor themselves be attacked or harmed by any other players (or their pets/followers), whether from combat, spells, skills or items
		Young players don't lose any of their items on death, and are teleported to the nearest healer upon death with all their items intact
		Young players receive a warning upon entering dungeons that monsters there will be hostile
	Updated global script (js/server/global.js) to:
		Check/Verify Young status of players upon login
		Attach young player script on login/creation for players on Young accounts
		Give specific items to Young players upon creation
	Added new script (js/item/corpse.js) that is assigned to all freshly created corpses. This script handles restrictions related to Young players interactions with corpses, and the interactions of other players with corpses of Young players
	Updated JS Method .Carve() to return true/false depending on whether carving a corpse was successful
	Updated Healer AI in code to heal nearby injured Young players
	Updated Evil AI and Evil Caster AI in code to avoid selecting Young players as targets in combat outside of dungeons
	Added a new section to UOX.INI - [young player starting locations] - that can be used to define starting locations for Young players. If only one such location is provided, all players start there. Otherwise, it matches the same starting location setup as the regular one - with one entry per town in Britannia.
	Restricted transferring and/or friending of pets (code) and hirelings (hirelings.js) between Young and non-Young players
	Restricted Young players from recalling or gating to Felucca facet
	Young players can instantly logout from anywhere, at any time
2023-07-01 20:02:40 +08:00

2043 lines
68 KiB
C++

#include "uox3.h"
#include "cGuild.h"
#include "speech.h"
#include "ssection.h"
#include "scriptc.h"
#include "classes.h"
#include "CPacketSend.h"
#include "Dictionary.h"
#include "CJSEngine.h"
#include "StringUtility.hpp"
#include "osunique.hpp"
#ifndef va_start
#include <cstdarg>
#endif
using namespace std::string_literals;
CGuildCollection *GuildSys;
#define DEFAULTCHARTER "UOX3 Guildstone"
#define DEFAULTWEBPAGE "http://www.uox3.org/"
CGuild::CGuild() : name( "" ), gType( GT_STANDARD ), charter( "" ), webpage( "" ), stone( INVALIDSERIAL ), master( INVALIDSERIAL )
{
abbreviation[0] = 0;
recruits.resize( 0 );
members.resize( 0 );
recruitPtr = recruits.end();
memberPtr = members.end();
warPtr = relationList.end();
allyPtr = relationList.end();
}
CGuild::~CGuild()
{
JSEngine->ReleaseObject( IUE_GUILD, this );
recruits.clear();
members.clear();
relationList.clear();
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::FirstWar()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Moves to start of the relation list and returns the next
//| relation which is at war
//o------------------------------------------------------------------------------------------------o
GUILDID CGuild::FirstWar( void )
{
warPtr = relationList.begin();
return NextWar();
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::NextWar()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Moves through relation list, returning guild ID of next
//| guild at war, or -1 if no war
//o------------------------------------------------------------------------------------------------o
GUILDID CGuild::NextWar( void )
{
while( warPtr != relationList.end() )
{
if( warPtr->second == GR_WAR )
{
return warPtr->first;
}
++warPtr;
}
return -1;
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::FinishedWar()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Returns true if at end of war list, or false if not
//| Must iterate through war list if not at end of relation list
//| Moves back one if it does find something it's at war with
//| to ensure pointer integrity
//o------------------------------------------------------------------------------------------------o
bool CGuild::FinishedWar( void )
{
if( warPtr == relationList.end() )
return true;
if( NextWar() == -1 )
return true;
else if( warPtr != relationList.begin() ) // we move back if we found it, so NextWar will return a valid warring guild
{
--warPtr;
}
return false;
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::FirstAlly()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Moves to start of the relation list and returns the next
//| relation which is at ally
//o------------------------------------------------------------------------------------------------o
GUILDID CGuild::FirstAlly( void )
{
allyPtr = relationList.begin();
return NextAlly();
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::NextAlly()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Moves through relation list, returning guild ID of next
//| guild as ally, or -1 if no ally
//o------------------------------------------------------------------------------------------------o
GUILDID CGuild::NextAlly( void )
{
while( allyPtr != relationList.end() )
{
if( allyPtr->second == GR_ALLY )
{
return allyPtr->first;
}
++allyPtr;
}
return -1;
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::FinishedAlly()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Returns true if at end of ally list, or false if not
//| Must iterate through ally list if not at end of relation list
//| Moves back one if it does find something it's an ally with
//| to ensure pointer integrity
//o------------------------------------------------------------------------------------------------o
bool CGuild::FinishedAlly( void )
{
if( allyPtr == relationList.end() )
return true;
if( NextAlly() == -1 )
return true;
else if( allyPtr != relationList.begin() ) // we move back if we found it, so NextWar will return a valid warring guild
{
--allyPtr;
}
return false;
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::Name()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Gets/Sets the name of the guild.
//| Setting also updates name of guildstone, if it exists
//o------------------------------------------------------------------------------------------------o
const std::string CGuild::Name( void ) const
{
return name;
}
void CGuild::Name( std::string txt )
{
name = txt;
if( Stone() != INVALIDSERIAL ) // we have a guildstone
{
CItem *gStone = CalcItemObjFromSer( Stone() );
if( ValidateObject( gStone ))
{
gStone->SetName( txt );
}
}
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::Abbreviation()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Gets/Sets the abbreviation of the guild
//o------------------------------------------------------------------------------------------------o
auto CGuild::Abbreviation() const -> const std::string&
{
return abbreviation;
}
auto CGuild::Abbreviation( const std::string &value ) -> void
{
abbreviation = value;
if( value.size() > 4 )
{
abbreviation = value.substr( 0, 4 );
}
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::Type()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Gets/Sets the guild's type
//| GT_STANDARD = 0,
//| GT_ORDER,
//| GT_CHAOS,
//| GT_UNKNOWN,
//| GT_COUNT
//o------------------------------------------------------------------------------------------------o
GuildType CGuild::Type( void ) const
{
return gType;
}
void CGuild::Type( GuildType nType )
{
gType = nType;
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::Charter()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Gets/Sets the charter of the guild
//o------------------------------------------------------------------------------------------------o
const std::string CGuild::Charter( void ) const
{
return charter;
}
void CGuild::Charter( const std::string &txt )
{
charter = txt;
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::Webpage()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Returns the webpage of the guild
//o------------------------------------------------------------------------------------------------o
const std::string CGuild::Webpage( void ) const
{
return webpage;
}
void CGuild::Webpage( const std::string &txt )
{
webpage = txt;
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::Stone()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Gets/Sets the serial of the guild stone
//o------------------------------------------------------------------------------------------------o
SERIAL CGuild::Stone( void ) const
{
return stone;
}
void CGuild::Stone( SERIAL newStone )
{
stone = newStone;
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::Master()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Gets/Sets the serial of the guild master (if any)
//o------------------------------------------------------------------------------------------------o
SERIAL CGuild::Master( void ) const
{
return master;
}
void CGuild::Master( SERIAL newMaster )
{
master = newMaster;
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::FirstRecruit()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Returns the serial of the first recruit in the recruit list
//| If no recruits, returns INVALIDSERIAL
//o------------------------------------------------------------------------------------------------o
SERIAL CGuild::FirstRecruit( void )
{
SERIAL retVal = INVALIDSERIAL;
recruitPtr = recruits.begin();
if( !FinishedRecruits() )
{
retVal = ( *recruitPtr );
}
return retVal;
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::NextRecruit()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Returns the serial of the next recruit in the recruit list
//| If there are no more, it returns INVALIDSERIAL
//o------------------------------------------------------------------------------------------------o
SERIAL CGuild::NextRecruit()
{
SERIAL retVal = INVALIDSERIAL;
if( !FinishedRecruits() )
{
++recruitPtr;
if( !FinishedRecruits() )
{
retVal = (*recruitPtr);
}
}
return retVal;
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::FinishedRecruits()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Returns true if there are no more recruits left
//o------------------------------------------------------------------------------------------------o
bool CGuild::FinishedRecruits()
{
return ( recruitPtr == recruits.end() );
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::RecruitNumber()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Returns the serial of the recruit in slot rNum
//| If rNum is invalid, it returns INVALIDSERIAL
//o------------------------------------------------------------------------------------------------o
SERIAL CGuild::RecruitNumber( size_t rNum ) const
{
if( rNum >= recruits.size() )
{
return INVALIDSERIAL;
}
else
{
return recruits[rNum];
}
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::MemberNumber()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Returns the serial of the member in slot rNum
//| If rNum is invalid, it returns INVALIDSERIAL
//o------------------------------------------------------------------------------------------------o
SERIAL CGuild::MemberNumber( size_t rNum ) const
{
if( rNum >= members.size() )
{
return INVALIDSERIAL;
}
else
{
return members[rNum];
}
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::FirstMember()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Returns the serial of the first member of the guild
//| If no members, returns INVALIDSERIAL
//o------------------------------------------------------------------------------------------------o
SERIAL CGuild::FirstMember( void )
{
SERIAL retVal = INVALIDSERIAL;
memberPtr = members.begin();
if( !FinishedMember() )
{
retVal = ( *memberPtr );
}
return retVal;
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::NextMember()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Returns the serial of the next member of the guild, if any
//| If none, it returns INVALIDSERIAL
//o------------------------------------------------------------------------------------------------o
SERIAL CGuild::NextMember( void )
{
SERIAL retVal = INVALIDSERIAL;
if( !FinishedMember() )
{
++memberPtr; // post ++ forces a copy constructor
if( !FinishedMember() )
{
retVal = ( *memberPtr );
}
}
return retVal;
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::FinishedMember()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Returns true if there are no more members left
//o------------------------------------------------------------------------------------------------o
bool CGuild::FinishedMember( void )
{
return ( memberPtr == members.end() );
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::Stone()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Sets the guild's stone serial to the CItem newStone
//o------------------------------------------------------------------------------------------------o
void CGuild::Stone( CItem &newStone )
{
stone = newStone.GetSerial();
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::Master()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Sets the guild's master serial to CChar newMaster's serial
//o------------------------------------------------------------------------------------------------o
void CGuild::Master( CChar &newMaster )
{
master = newMaster.GetSerial();
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::NewRecruit()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Add new recruit to guild
//o------------------------------------------------------------------------------------------------o
void CGuild::NewRecruit( CChar &newRecruit )
{
NewRecruit( newRecruit.GetSerial() );
}
void CGuild::NewRecruit( SERIAL newRecruit )
{
if( IsMember( newRecruit ))
{
RemoveMember( newRecruit );
}
recruits.push_back( newRecruit );
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::NewMember()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Add new member to guild
//o------------------------------------------------------------------------------------------------o
void CGuild::NewMember( CChar &newMember )
{
NewMember( newMember.GetSerial() );
}
void CGuild::NewMember( SERIAL newMember )
{
if( IsRecruit( newMember ))
{
RemoveRecruit( newMember );
}
members.push_back( newMember );
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::RemoveRecruit()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Remove recruit from guild
//o------------------------------------------------------------------------------------------------o
void CGuild::RemoveRecruit( CChar &newRecruit )
{
RemoveRecruit( newRecruit.GetSerial() );
}
void CGuild::RemoveRecruit( SERIAL newRecruit )
{
auto iter = std::find_if( recruits.begin(), recruits.end(), [newRecruit]( SERIAL &entry )
{
return entry == newRecruit;
});
if( iter != recruits.end() )
{
recruits.erase( iter );
}
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::RemoveMember()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Remove member from guild
//o------------------------------------------------------------------------------------------------o
void CGuild::RemoveMember( CChar &newMember )
{
RemoveMember( newMember.GetSerial() );
}
void CGuild::RemoveMember( SERIAL newMember )
{
auto iter = std::find_if( members.begin(), members.end(), [newMember]( SERIAL &entry )
{
return entry == newMember;
});
if( iter != members.end() )
{
members.erase( iter );
}
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::RecruitToMember()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Change guild recruit to member
//o------------------------------------------------------------------------------------------------o
void CGuild::RecruitToMember( CChar &newMember )
{
RemoveRecruit( newMember );
NewMember( newMember );
}
void CGuild::RecruitToMember( SERIAL newMember )
{
RemoveRecruit( newMember );
NewMember( newMember );
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::IsRecruit()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Check if character can be found in list of guild recruits
//o------------------------------------------------------------------------------------------------o
bool CGuild::IsRecruit( CChar &toCheck ) const
{
return IsRecruit( toCheck.GetSerial() );
}
//============================================================================================
auto CGuild::IsRecruit( SERIAL toCheck ) const -> bool
{
auto rValue = false;
auto iter = std::find_if( recruits.begin(), recruits.end(), [toCheck]( const SERIAL &entry )
{
return toCheck == entry;
});
if( iter != recruits.end() )
{
rValue = true;
}
return rValue;
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::IsMember()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Check if character can be found in list of guild members
//o------------------------------------------------------------------------------------------------o
bool CGuild::IsMember( CChar &toCheck ) const
{
return IsMember( toCheck.GetSerial() );
}
//============================================================================================
auto CGuild::IsMember( SERIAL toCheck ) const -> bool
{
auto rValue = false;
auto iter = std::find_if( members.begin(), members.end(), [toCheck]( const SERIAL &entry )
{
return toCheck == entry;
});
if( iter != members.end() )
{
rValue = true;
}
return rValue;
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::RelatedToGuild()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Determine other guild's relation (Alliance/War) to this guild
//o------------------------------------------------------------------------------------------------o
GUILDRELATION CGuild::RelatedToGuild( GUILDID otherGuild ) const
{
GUILDREL::const_iterator toFind = relationList.find( otherGuild );
if( toFind == relationList.end() )
{
return GR_UNKNOWN;
}
else
{
return toFind->second;
}
}
bool CGuild::IsAtWar( GUILDID otherGuild ) const
{
GUILDREL::const_iterator toFind = relationList.find( otherGuild );
if( toFind == relationList.end() )
{
return false;
}
else
{
return ( toFind->second == GR_WAR );
}
}
bool CGuild::IsNeutral( GUILDID otherGuild ) const
{
GUILDREL::const_iterator toFind = relationList.find( otherGuild );
if( toFind == relationList.end() )
{
return false;
}
else
{
return ( toFind->second == GR_NEUTRAL );
}
}
bool CGuild::IsAlly( GUILDID otherGuild ) const
{
GUILDREL::const_iterator toFind = relationList.find( otherGuild );
if( toFind == relationList.end() )
{
return false;
}
else
{
return ( toFind->second == GR_ALLY );
}
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::IsAtPeace()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Determine if this guild is in a state of peace, i.e. NOT at war with anyone
//o------------------------------------------------------------------------------------------------o
bool CGuild::IsAtPeace() const
{
for( auto &relation : relationList )
{
if( relation.second == GR_WAR )
return false;
}
return true;
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::SetGuildRelation()
//| CGuild::GuildRelationList()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Gets/Sets guild's relation to another guild
//| Notes - NOTE: This is aimed ONLY at menu stuff
//o------------------------------------------------------------------------------------------------o
void CGuild::SetGuildRelation( GUILDID otherGuild, GUILDRELATION toSet )
{
relationList[otherGuild] = toSet;
}
GUILDREL *CGuild::GuildRelationList( void )
{
return &relationList;
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::Save()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Save guild data to worldfiles
//o------------------------------------------------------------------------------------------------o
void CGuild::Save( std::ofstream &toSave, GUILDID gNum )
{
toSave << "[GUILD " << gNum << ']' << '\n' << "{" << '\n';
toSave << "NAME=" << name << '\n';
toSave << "ABBREVIATION=" << abbreviation << '\n';
toSave << "TYPE=" << GTypeNames[gType] << '\n';
toSave << "CHARTER=" << charter << '\n';
toSave << "WEBPAGE=" << webpage << '\n';
toSave << "STONE=" << stone << '\n';
toSave << "MASTER=" << master << '\n';
std::for_each( recruits.begin(), recruits.end(), [&toSave] ( SERIAL entry )
{
toSave << "RECRUIT=" << entry << '\n';
});
std::for_each( members.begin(), members.end(), [&toSave] ( SERIAL entry )
{
toSave << "MEMBER=" << entry << '\n';
});
GUILDREL::const_iterator relly = relationList.begin();
while( relly != relationList.end() )
{
toSave << GRelationNames[relly->second] << " " << relly->first <<'\n';
++relly;
}
toSave << "}" << '\n' << '\n';
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::Load()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Load guilds from guilds worldfile
//o------------------------------------------------------------------------------------------------o
void CGuild::Load( CScriptSection *toRead )
{
std::string tag;
std::string data;
std::string UTag;
for( const auto &sec : toRead->collection() )
{
tag = sec->tag;
data = sec->data;
if( tag.empty() )
continue;
UTag = oldstrutil::upper( tag );
switch(( UTag.data()[0] ))
{
case '{':
case '/': break; // open section, comment, we don't really care;)
case 'A':
if( UTag == "ABBREVIATION" )
{
Abbreviation( data.c_str() );
}
else if( UTag == "ALLY" )
{
SetGuildRelation( static_cast<SI16>( std::stoi( data, nullptr, 0 )), GR_ALLY );
}
break;
case 'C':
if( UTag == "CHARTER" )
{
Charter( data );
}
break;
case 'M':
if( UTag == "MASTER" )
{
Master( static_cast<UI32>( std::stoul( data, nullptr, 0 )));
}
else if( UTag == "MEMBER" )
{
NewMember( static_cast<UI32>( std::stoul( data, nullptr, 0 )));
}
break;
case 'N':
if( UTag == "NAME" )
{
Name( data );
}
else if( UTag == "NEUTRAL" )
{
SetGuildRelation( static_cast<SI16>( std::stoi( data, nullptr, 0 )), GR_NEUTRAL );
}
break;
case 'R':
if( UTag == "RECRUIT" )
{
NewRecruit( static_cast<UI32>( std::stoul( data, nullptr, 0 )));
}
break;
case 'S':
if( UTag == "STONE" )
{
Stone( static_cast<UI32>( std::stoul( data, nullptr, 0 )));
}
break;
case 'T':
if( UTag == "TYPE" )
{
for( GuildType gt = GT_STANDARD; gt < GT_COUNT; gt = static_cast<GuildType>( gt + static_cast<GuildType>( 1 )))
{
if( data == GTypeNames[gt] )
{
Type( gt );
break;
}
}
}
break;
case 'U':
if( UTag == "UNKNOWN" )
{
SetGuildRelation( static_cast<SI16>( std::stoi( data, nullptr, 0 )), GR_UNKNOWN );
}
break;
case 'W':
if( UTag == "WEBPAGE" )
{
Webpage( data );
}
else if( UTag == "WAR" )
{
SetGuildRelation( static_cast<SI16>( std::stoi( data, nullptr, 0 )), GR_WAR );
}
break;
}
}
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::NumMembers()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Gets number of guild members
//o------------------------------------------------------------------------------------------------o
size_t CGuild::NumMembers( void ) const
{
return members.size();
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::NumRecruits()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Gets number of guild recruits
//o------------------------------------------------------------------------------------------------o
size_t CGuild::NumRecruits( void ) const
{
return recruits.size();
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::CalcMaster()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Calculate next guild master based on vote count
//o------------------------------------------------------------------------------------------------o
void CGuild::CalcMaster( void )
{
if( members.empty() )
{
Master( INVALIDSERIAL );
return;
}
std::vector<SI32> votes;
votes.resize( members.size() );
UI32 maxIndex = 0;
for( size_t counter = 0; counter < votes.size(); ++counter )
{
votes[counter] = 0; // init the count before adding
for( size_t counter2 = 0; counter2 < votes.size(); ++counter2 )
{
CChar *myChar = CalcCharObjFromSer( members[counter2] );
if( ValidateObject( myChar ) && myChar->GetGuildFealty() == members[counter] )
{
++votes[counter];
}
}
if( votes[counter] > votes[maxIndex] )
{
maxIndex = static_cast<UI32>( counter );
}
}
Master( members[maxIndex] );
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::TellMembers()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Tell all guild members a message
//o------------------------------------------------------------------------------------------------o
void CGuild::TellMembers( SI32 dictEntry, ... )
{
for( auto &member: members )
{
CChar *targetChar = CalcCharObjFromSer( member );
CSocket *targetSock = targetChar->GetSocket();
if( targetSock != nullptr )
{
std::string txt = "GUILD: ";
txt += Dictionary->GetEntry( dictEntry, targetSock->Language() );
va_list argptr;
va_start( argptr, dictEntry );
if( cwmWorldState->ServerData()->UseUnicodeMessages() )
{
std::string tempStr = oldstrutil::format( 512, txt, argptr );
CPUnicodeMessage unicodeMessage;
unicodeMessage.Message( tempStr );
unicodeMessage.Font( FNT_NORMAL );
unicodeMessage.Colour( 0x000B );
unicodeMessage.Type( SYSTEM );
unicodeMessage.Language( "ENG" );
unicodeMessage.Name( "System" );
unicodeMessage.ID( INVALIDID );
unicodeMessage.Serial( INVALIDSERIAL );
targetSock->Send( &unicodeMessage );
}
else
{
CSpeechEntry& toAdd = SpeechSys->Add();
toAdd.Speech( oldstrutil::format( 512, txt, argptr ));
toAdd.Font( FNT_NORMAL );
toAdd.Speaker( INVALIDSERIAL );
toAdd.SpokenTo( member );
toAdd.Colour( 0x000B );
toAdd.Type( SYSTEM );
toAdd.At( cwmWorldState->GetUICurrentTime() );
toAdd.TargType( SPTRG_INDIVIDUAL );
}
va_end( argptr );
}
}
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::SetGuildFaction()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Sets the guild's faction - neutral, order or chaos
//o------------------------------------------------------------------------------------------------o
void CGuild::SetGuildFaction( GuildType newFaction )
{
Type( newFaction );
if( newFaction != GT_STANDARD )
{
for( auto &member : members )
{
CChar *memberChar = CalcCharObjFromSer( member );
if( !memberChar->GetGuildToggle() )
{
memberChar->SetGuildToggle( true );
CSocket *memberSock = memberChar->GetSocket();
if( memberSock != nullptr )
{
memberSock->SysMessage( 154 ); // Let him know about the change
}
}
}
}
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuild::TypeName()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Gets guild type as a string
//o------------------------------------------------------------------------------------------------o
const std::string CGuild::TypeName( void )
{
return GTypeNames[Type()];
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuildCollection::NumGuilds()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Gets number of guilds on the server
//o------------------------------------------------------------------------------------------------o
size_t CGuildCollection::NumGuilds( void ) const
{
return gList.size();
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuildCollection::MaximumGuild()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Gets the next available guild ID
//o------------------------------------------------------------------------------------------------o
GUILDID CGuildCollection::MaximumGuild( void )
{
GUILDID maxVal = -1;
GUILDLIST::const_iterator pFind = gList.begin();
while( pFind != gList.end() )
{
if( pFind->first > maxVal )
{
maxVal = pFind->first;
}
++pFind;
}
return static_cast<GUILDID>( maxVal + 1 );
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuildCollection::NewGuild()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Create a new guild
//o------------------------------------------------------------------------------------------------o
GUILDID CGuildCollection::NewGuild( void )
{
CGuild *toAdd = new CGuild();
GUILDID gAdd = MaximumGuild();
gList[gAdd] = toAdd;
return gAdd;
}
CGuild *CGuildCollection::Guild( GUILDID num ) const
{
GUILDLIST::const_iterator pFind = gList.find( num );
if( pFind == gList.end() )
return nullptr;
return pFind->second;
}
CGuild *CGuildCollection::operator[]( GUILDID num )
{
return Guild( num );
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuildCollection::Save()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Saves guild to worldfile
//o------------------------------------------------------------------------------------------------o
void CGuildCollection::Save( void )
{
Console << "Saving guild data.... ";
std::string filename = cwmWorldState->ServerData()->Directory( CSDDP_SHARED ) + "guilds.wsc";
std::ofstream toSave( filename.c_str() );
GUILDLIST::const_iterator pMove = gList.begin();
while( pMove != gList.end() )
{
( pMove->second )->Save( toSave, pMove->first );
++pMove;
}
Console.PrintDone();
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuildCollection::Load()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Load guilds from worldfile
//o------------------------------------------------------------------------------------------------o
void CGuildCollection::Load( void )
{
std::string filename = cwmWorldState->ServerData()->Directory( CSDDP_SHARED ) + "guilds.wsc";
if( FileExists( filename ))
{
Script newScript( filename, NUM_DEFS, false );
CScriptSection *testSect = nullptr;
GUILDID guildNum = 0;
for( testSect = newScript.FirstEntry(); testSect != nullptr; testSect = newScript.NextEntry() )
{
std::string text = newScript.EntryName();
text = text.substr( 6 );
guildNum = static_cast<SI16>( std::stoi( text, nullptr, 0 ));
if( gList[guildNum] != nullptr )
{
delete gList[guildNum];
}
gList[guildNum] = new CGuild();
gList[guildNum]->Load( testSect );
}
}
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuildCollection::Compare()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Compare the guild relation between two guilds
//o------------------------------------------------------------------------------------------------o
GUILDRELATION CGuildCollection::Compare( GUILDID srcGuild, GUILDID trgGuild ) const
{
if( srcGuild == -1 || trgGuild == -1 )
return GR_UNKNOWN;
if( srcGuild == trgGuild )
return GR_SAME;
CGuild *mGuild = Guild( srcGuild );
if( mGuild == nullptr )
return GR_UNKNOWN;
return mGuild->RelatedToGuild( trgGuild );
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuildCollection::Compare()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Compare the guild relation between two characters
//o------------------------------------------------------------------------------------------------o
GUILDRELATION CGuildCollection::Compare( CChar *src, CChar *trg ) const
{
if( src == nullptr || trg == nullptr )
return GR_UNKNOWN;
auto srcGuild = src->GetGuildNumber();
auto trgGuild = trg->GetGuildNumber();
if( srcGuild == -1 || trgGuild == -1 )
return GR_UNKNOWN;
if( srcGuild == trgGuild )
return GR_SAME;
return Compare( srcGuild, trgGuild );
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuildCollection::Menu()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Send guild menu to player
//o------------------------------------------------------------------------------------------------o
void CGuildCollection::Menu( CSocket *s, SI16 menu, GUILDID trgGuild, SERIAL plId )
{
if( s == nullptr )
return;
if( trgGuild >= static_cast<SI32>( NumGuilds() ))
return;
CPSendGumpMenu toSend;
toSend.GumpId( menu );
toSend.UserId( INVALIDSERIAL );
toSend.addCommand( "page 0" );
toSend.addCommand( oldstrutil::format( "resizepic 0 0 %u 600 400", cwmWorldState->ServerData()->BackgroundPic() ));
toSend.addCommand( oldstrutil::format( "button 560 10 %u %i 1 0 1", cwmWorldState->ServerData()->ButtonCancel(), cwmWorldState->ServerData()->ButtonCancel() + 1 )); //OKAY
toSend.addCommand( oldstrutil::format( "text 120 10 %u 0", cwmWorldState->ServerData()->TitleColour() ));
toSend.addCommand( "page 1" );
SERIAL gMaster = gList[trgGuild]->Master();
CChar *mChar = s->CurrcharObj();
CChar *gMstr = CalcCharObjFromSer( gMaster );
UI16 numButtons = 0, numText = 0, numColumns = 1;
auto guildFealty = "yourself"s;
if( mChar->GetGuildFealty() != mChar->GetSerial() && mChar->GetGuildFealty() != INVALIDSERIAL )
{
CChar *fChar = CalcCharObjFromSer( mChar->GetGuildFealty() );
if( ValidateObject( fChar ))
{
guildFealty = fChar->GetNameRequest( mChar, NRS_GUILD );
}
}
else
{
mChar->SetGuildFealty( mChar->GetSerial() );
}
auto guildt = "INVALID"s;
switch( gList[trgGuild]->Type() )
{
case 0:
guildt = " Standard"s;
break;
case 1:
guildt = "n Order"s;
break;
case 2:
guildt = " Chaos"s;
break;
default:
break;
}
auto toggle = "Off"s;
if( mChar->GetGuildToggle() )
{
toggle = "On"s;
}
std::string gName = gList[trgGuild]->Name();
UI16 tCtr = 0;
SERIAL tChar = 0;
GUILDREL::iterator toCheck;
GUILDREL *ourList;
s->TempInt( trgGuild );
UnicodeTypes sLang = s->Language();
UI32 tCounter = 0;
switch( menu )
{
case -1: break;
case BasePage: break;
case BasePage + 1: numButtons = 10; // Main menu
toSend.addText( Dictionary->GetEntry( 102, sLang ));
toSend.addText( Dictionary->GetEntry( 103, sLang ));
toSend.addText( Dictionary->GetEntry( 104, sLang ));
toSend.addText( Dictionary->GetEntry( 105, sLang ));
toSend.addText( oldstrutil::format( Dictionary->GetEntry( 106, sLang ), guildFealty.c_str() ));
toSend.addText( oldstrutil::format( Dictionary->GetEntry( 107, sLang ), toggle.c_str() ));
toSend.addText( Dictionary->GetEntry( 108, sLang ));
toSend.addText( Dictionary->GetEntry( 109, sLang ));
toSend.addText( oldstrutil::format( Dictionary->GetEntry( 110, sLang ), gName.c_str() ));
toSend.addText( oldstrutil::format( Dictionary->GetEntry( 111, sLang ), gName.c_str() ));
toSend.addText( Dictionary->GetEntry( 112, sLang ));
if( mChar->GetSerial() == gMaster || mChar->IsGM() ) // Guildmaster Access?
{
++numButtons;
toSend.addText( oldstrutil::format( Dictionary->GetEntry( 113, sLang ), gMstr->GetGuildTitle().c_str() ));
}
break;
case BasePage + 2: numButtons = 16; // Guildmaster menu
toSend.addText( Dictionary->GetEntry( 114, sLang ));
toSend.addText( Dictionary->GetEntry( 115, sLang ));
toSend.addText( Dictionary->GetEntry( 116, sLang ));
toSend.addText(oldstrutil::format( Dictionary->GetEntry( 117, sLang ), guildt.c_str() ));
for( tCounter = 118; tCounter <= 130; ++tCounter )
{
toSend.addText( Dictionary->GetEntry( tCounter, sLang ));
}
break;
case BasePage + 3: numButtons = 4; // Guild type
toSend.addText( Dictionary->GetEntry( 131, sLang ));
toSend.addText( Dictionary->GetEntry( 133, sLang ));
toSend.addText( Dictionary->GetEntry( 134, sLang ));
toSend.addText( Dictionary->GetEntry( 135, sLang ));
toSend.addText( Dictionary->GetEntry( 130, sLang ));
break;
case BasePage + 4: numButtons = 3; // Set charter
toSend.addText( Dictionary->GetEntry( 136, sLang ));
toSend.addText( Dictionary->GetEntry( 138, sLang ));
toSend.addText( Dictionary->GetEntry( 139, sLang ));
toSend.addText( Dictionary->GetEntry( 130, sLang ));
break;
case BasePage + 5: numButtons = 3; // View charter
toSend.addText( Dictionary->GetEntry( 140, sLang ));
toSend.addText( gList[trgGuild]->Charter() );
toSend.addText( oldstrutil::format( Dictionary->GetEntry( 142, sLang ), gList[trgGuild]->Webpage().c_str() ));
toSend.addText( Dictionary->GetEntry( 130, sLang ));
break;
case BasePage + 6: // List of recruits
toSend.addText( Dictionary->GetEntry( 143, sLang ));
tCtr = 0;
for( tChar = gList[trgGuild]->FirstRecruit(); !gList[trgGuild]->FinishedRecruits(); tChar = gList[trgGuild]->NextRecruit() )
{
toSend.addText( CalcCharObjFromSer( tChar )->GetNameRequest( mChar, NRS_GUILD ));
++tCtr;
}
toSend.addText( Dictionary->GetEntry( 130, sLang ));
numButtons = ++tCtr;
break;
case BasePage + 7: // List of members
toSend.addText( Dictionary->GetEntry( 144, sLang ));
tCtr = 0;
for( tChar = gList[trgGuild]->FirstMember(); !gList[trgGuild]->FinishedMember(); tChar = gList[trgGuild]->NextMember() )
{
toSend.addText( CalcCharObjFromSer( tChar )->GetNameRequest( mChar, NRS_GUILD ));
++tCtr;
}
toSend.addText( Dictionary->GetEntry( 130, sLang ));
numButtons = ++tCtr;
break;
case BasePage + 8: // Member dismiss
toSend.addText( Dictionary->GetEntry( 145, sLang ));
tCtr = 0;
for( tChar = gList[trgGuild]->FirstMember(); !gList[trgGuild]->FinishedMember(); tChar = gList[trgGuild]->NextMember() )
{
toSend.addText( CalcCharObjFromSer( tChar )->GetNameRequest( mChar, NRS_GUILD ));
++tCtr;
}
toSend.addText( Dictionary->GetEntry( 130, sLang ));
numButtons = ++tCtr; break;
case BasePage + 9: // Dismiss recruit
toSend.addText( Dictionary->GetEntry( 146, sLang ));
tCtr = 0;
for( tChar = gList[trgGuild]->FirstRecruit(); !gList[trgGuild]->FinishedRecruits(); tChar = gList[trgGuild]->NextRecruit() )
{
toSend.addText( CalcCharObjFromSer( tChar )->GetNameRequest( mChar, NRS_GUILD ));
++tCtr;
}
toSend.addText( Dictionary->GetEntry( 130, sLang ));
numButtons = ++tCtr; break;
case BasePage + 10: // Accept recruit
toSend.addText( Dictionary->GetEntry( 147, sLang ));
tCtr = 0;
for( tChar = gList[trgGuild]->FirstRecruit(); !gList[trgGuild]->FinishedRecruits(); tChar = gList[trgGuild]->NextRecruit() )
{
toSend.addText( CalcCharObjFromSer( tChar )->GetNameRequest( mChar, NRS_GUILD ));
++tCtr;
}
toSend.addText( Dictionary->GetEntry( 130, sLang ));
numButtons = ++tCtr; break;
case BasePage + 11: // War list
toSend.addText( Dictionary->GetEntry( 148, sLang ));
tCtr = 0;
ourList = gList[trgGuild]->GuildRelationList();
toCheck = ourList->begin();
while( toCheck != ourList->end() )
{
if( toCheck->second == GR_WAR )
{
toSend.addText( gList[toCheck->first]->Name() );
++tCtr;
}
++toCheck;
}
toSend.addText( Dictionary->GetEntry( 130, sLang ));
numButtons = ++tCtr; break;
case BasePage + 13: // Declare war list
toSend.addText( Dictionary->GetEntry( 149, sLang ));
tCtr = 0;
ourList = gList[trgGuild]->GuildRelationList();
toCheck = ourList->begin();
while( toCheck != ourList->end() )
{
if( toCheck->second != GR_WAR )
{
toSend.addText( gList[toCheck->first]->Name() );
++tCtr;
}
++toCheck;
}
toSend.addText( Dictionary->GetEntry( 130, sLang ));
numButtons = ++tCtr; break;
case BasePage + 14: // Declare peace list
toSend.addText( Dictionary->GetEntry( 150, sLang ));
tCtr = 0;
ourList = gList[trgGuild]->GuildRelationList();
toCheck = ourList->begin();
while( toCheck != ourList->end() )
{
if( toCheck->second == GR_WAR )
{
toSend.addText( gList[toCheck->first]->Name() );
++tCtr;
}
++toCheck;
}
toSend.addText( Dictionary->GetEntry( 130, sLang ));
numButtons = ++tCtr; break;
case BasePage + 15: // List of guilds warring on us
case BasePage + 16: // Display recruit information
numButtons = 1;
toSend.addText( "Unfilled functionality" );
toSend.addText( Dictionary->GetEntry( 130, sLang ));
break;
case BasePage + 17: // Display member information
CChar *kChar;
kChar = CalcCharObjFromSer( plId );
if( ValidateObject( kChar ))
{
auto temp = kChar->GetNameRequest( mChar, NRS_GUILD );
if( kChar->IsInnocent() )
{
temp += std::string(" Innocent" );
}
else if( kChar->IsMurderer() )
{
temp += std::string(" Murderer" );
}
else
{
temp += std::string(" Criminal" );
}
toSend.addText( temp );
// To display: Name, str, dex, int, # kills, # deaths, status (criminal, murderer, innocent), top x skills
toSend.addText( "Strength" );
toSend.addText( oldstrutil::format( "%i", kChar->GetStrength() ));
toSend.addText( "Dexterity" );
toSend.addText( oldstrutil::format( "%i", kChar->GetDexterity() ));
toSend.addText( "Intelligence" );
toSend.addText( oldstrutil::format( "%i", kChar->GetIntelligence() ));
toSend.addText( "Kills" );
toSend.addText( oldstrutil::format( "%i", kChar->GetKills() ));
toSend.addText( "Deaths" );
toSend.addText( oldstrutil::format( "%u", kChar->GetDeaths() ));
numText = 10;
numColumns = 2;
numButtons = 1;
}
else
{
numButtons = 1;
toSend.addText( "Unknown player" );
}
toSend.addText( Dictionary->GetEntry( 130, sLang ));
break;
case BasePage + 18: // Ally list
toSend.addText( Dictionary->GetEntry( 151, sLang ));
tCtr = 0;
ourList = gList[trgGuild]->GuildRelationList();
toCheck = ourList->begin();
while( toCheck != ourList->end() )
{
if( toCheck->second == GR_ALLY )
{
toSend.addText( gList[toCheck->first]->Name() );
++tCtr;
}
++toCheck;
}
toSend.addText( Dictionary->GetEntry( 130, sLang ));
numButtons = ++tCtr; break;
case BasePage + 19: // Declare Ally list
toSend.addText( Dictionary->GetEntry( 152, sLang ));
tCtr = 0;
ourList = gList[trgGuild]->GuildRelationList();
toCheck = ourList->begin();
while( toCheck != ourList->end() )
{
if( toCheck->second != GR_ALLY )
{
toSend.addText( gList[toCheck->first]->Name() );
++tCtr;
}
++toCheck;
}
toSend.addText( Dictionary->GetEntry( 130, sLang ));
numButtons = ++tCtr; break;
}
for( UI16 iCtr = 0; iCtr < numButtons; ++iCtr )
{
toSend.addCommand( oldstrutil::format( "button 20 %i %i %i 1 0 %i", 30 + 20 * iCtr, cwmWorldState->ServerData()->ButtonRight(), cwmWorldState->ServerData()->ButtonRight() + 1, iCtr + 2 ));
toSend.addCommand( oldstrutil::format( "text 50 %i %i %i", 30 + 20 * iCtr, cwmWorldState->ServerData()->LeftTextColour(), iCtr + 1 ));
}
if( numText != 0 )
{
for( UI16 iCtr = 0; iCtr < numText; ++iCtr )
{
if( numColumns == 1 )
{
toSend.addCommand( oldstrutil::format( "text 50 %i %i %i", 30 + 20 * ( iCtr + numButtons ), cwmWorldState->ServerData()->LeftTextColour(), iCtr + numButtons + 1 ));
}
else
{
toSend.addCommand( oldstrutil::format( "text %i %i %i %i", 50 + ( iCtr % numColumns ) * 100, 30 + 20 * (( iCtr / 2 ) + numButtons ), cwmWorldState->ServerData()->LeftTextColour(), iCtr + numButtons + 1 ));
}
}
}
toSend.Finalize();
s->Send( &toSend );
}
void CGuildCollection::GumpInput( CPIGumpInput *gi )
{
UI08 type = gi->Type();
UI08 index = gi->Index();
std::string text = gi->Reply();
CSocket *s = gi->GetSocket();
if( text.empty() )
return;
if( type != 100 )
return;
GUILDID trgGuild = static_cast<GUILDID>( s->TempInt() );
CChar *gMaster = CalcCharObjFromSer( gList[trgGuild]->Master() );
switch( index )
{
case 1: gList[trgGuild]->Name( text ); break; // set guild name
case 2: gList[trgGuild]->Abbreviation( text.c_str() ); break; // set guild abbreviation
case 3: gMaster->SetGuildTitle( text ); break; // set guildmaster title
case 4: gList[trgGuild]->Charter( text ); break; // new charter
case 5: gList[trgGuild]->Webpage( text ); break; // new webpage
case 6: // set guild member title
auto gMember = CalcCharObjFromSer( s->TempInt2() );
if( ValidateObject( gMember ))
{
gMember->SetGuildTitle( text );
auto gSock = gMember->GetSocket();
if( gSock != nullptr )
{
gSock->SysMessage( 1686, text.c_str() ); // You have been granted a guild title of '%s'!
}
gMember->Dirty( UT_UPDATE );
}
break;
}
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuildCollection::ToggleAbbreviation()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Toggles guild abbreviation on/off - except for order/chaos, which must show
//o------------------------------------------------------------------------------------------------o
void CGuildCollection::ToggleAbbreviation( CSocket *s )
{
CChar *mChar = s->CurrcharObj();
GUILDID guildNumber = mChar->GetGuildNumber();
if( guildNumber == -1 )
return;
if( gList[guildNumber]->Type() != GT_STANDARD ) // Check for Order/Chaos
{
s->SysMessage( 153 ); // They may not toggle it off!
}
else
{
mChar->SetGuildToggle( !mChar->GetGuildToggle() );
if( mChar->GetGuildToggle() ) // If set to On then
{
s->SysMessage( 154 ); // Tell player about the change
}
else // Otherwise
{
s->SysMessage( 155 ); // And tell him also
}
mChar->Dirty( UT_UPDATE );
}
}
void CGuildCollection::TransportGuildStone( CSocket *s, GUILDID guildId )
{
CChar *mChar = s->CurrcharObj();
if( guildId == -1 )
return;
if( gList[guildId]->Stone() == INVALIDSERIAL )
return;
// Make sure this is the guild master
if( gList[guildId]->Master() == mChar->GetSerial() )
{
CItem *gTransportStone = Items->CreateItem( s, mChar, 0x1869, 1, 0, OT_ITEM, true );
if( ValidateObject( gTransportStone ))
{
gTransportStone->SetTempVar( CITV_MORE, guildId );
gTransportStone->SetNewbie( true );
gTransportStone->SetWeight( 1, true );
gTransportStone->SetType( IT_GUILDSTONE );
gTransportStone->SetName( oldstrutil::format( Dictionary->GetEntry( 101 ), gList[guildId]->Name().c_str() ));
CItem *gStone = CalcItemObjFromSer( gList[guildId]->Stone() );
gStone->Delete();
// A guildstone transporter object has been placed in your backpack. Use it to move the guildstone to a new location.
s->SysMessage( 1972 );
}
}
}
void TextEntryGump( CSocket *s, SERIAL ser, UI08 type, UI08 index, SI16 maxlength, SI32 dictEntry );
//o------------------------------------------------------------------------------------------------o
//| Function - CGuildCollection::GumpChoice()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Handles button presses in guild menus
//o------------------------------------------------------------------------------------------------o
void CGuildCollection::GumpChoice( CSocket *s )
{
UI32 realType = s->GetDWord( 7 );
UI32 button = s->GetDWord( 11 );
GUILDID trgGuild = static_cast<GUILDID>( s->TempInt() );
if( button == 1 ) // hit cancel
return;
CChar *mChar = s->CurrcharObj();
if( !ValidateObject( mChar ))
return;
SERIAL ser = mChar->GetSerial();
UI16 tCtr = 0;
GUILDREL::iterator toCheck;
GUILDREL *ourList;
size_t offCounter;
CChar *tChar = nullptr;
switch( realType )
{
case INVALIDSERIAL:
case BasePage:
case BasePage + 1: // Main menu
switch( button )
{
case 2: s->SendTargetCursor( 2, 0, 0, 156 ); break; // recruit into guild
case 3: Menu( s, BasePage + 7, trgGuild ); break;
case 4: Menu( s, BasePage + 5, trgGuild ); break;
case 5: s->SendTargetCursor( 2, 1, 0, 157 ); break; // declare fealty
case 6: ToggleAbbreviation( s ); break; // toggle abbreviation
case 7: Resign( s ); break; // Resign from guild
case 8: Menu( s, BasePage + 6, trgGuild ); break; // View candidates
case 9: Menu( s, BasePage + 11, trgGuild ); break; // View warring guilds
case 10: Menu( s, BasePage + 15, trgGuild ); break; // View guilds that declared war on us
case 11: Menu( s, BasePage + 18, trgGuild ); break; // View list of allied guilds
case 12: Menu( s, BasePage + 2, trgGuild ); break; // Access guildmaster functions
}
break;
case BasePage + 2: // Guildmaster menu
switch( button )
{
case 2: TextEntryGump( s, ser, 100, 1, 30, 158 ); break; // set guild name
case 3: TextEntryGump( s, ser, 100, 2, 4, 159 ); break; // set guild abbreviation
case 4: Menu( s, BasePage + 3, trgGuild ); break; // set guild type
case 5: Menu( s, BasePage + 4, trgGuild ); break; // set guild charter
case 6: Menu( s, BasePage + 8, trgGuild ); break; // dismiss a member
case 7: Menu( s, BasePage + 13, trgGuild ); break; // declare war from menu
case 8: s->SendTargetCursor( 2, 2, 0, 160 ); break; // declare war from target
case 9: Menu( s, BasePage + 14, trgGuild ); break; // declare peace
case 10: Menu( s, BasePage + 19, trgGuild ); break; // declare ally from menu
case 11: s->SendTargetCursor( 2, 3, 0, 161 ); break; // declare ally from target
case 12: Menu( s, BasePage + 10, trgGuild ); break; // accept candidate seeking membership
case 13: Menu( s, BasePage + 9, trgGuild ); break; // refuse candidate seeking membership
case 14: TextEntryGump( s, ser, 100, 3, 15, 162 ); break; // set guild master's title
case 15: s->SendTargetCursor( 2, 4, 0, 1685 ); break; // Select guild member to grant title to
#if defined( _MSC_VER )
#pragma note( "Move guildstone functionality goes here" )
#endif
case 16: TransportGuildStone( s, trgGuild ); break; // move guildstone
case 17: Menu( s, BasePage + 1, trgGuild ); break; // return to main menu
}
break;
case BasePage + 3: // Guild type
switch( button )
{
case 2: gList[trgGuild]->SetGuildFaction( GT_STANDARD ); break;
case 3: gList[trgGuild]->SetGuildFaction( GT_ORDER ); break;
case 4: gList[trgGuild]->SetGuildFaction( GT_CHAOS ); break;
case 5: Menu( s, BasePage + 2, trgGuild ); break;
}
break;
case BasePage + 4: // Set charter
switch( button )
{
case 2: TextEntryGump( s, ser, 100, 4, 50, 163 ); break;
case 3: TextEntryGump( s, ser, 100, 5, 50, 164 ); break;
case 4: Menu( s, BasePage + 2, trgGuild ); break;
}
break;
case BasePage + 5: // View charter
switch( button )
{
case 3: s->OpenURL( gList[trgGuild]->Webpage() ); break;
case 2:
case 4: Menu( s, BasePage + 1, trgGuild ); break;
}
break;
case BasePage + 6: // List of recruits
if( gList[trgGuild]->NumRecruits() >= ( button - 2 ))
{
Menu( s, BasePage + 1, trgGuild );
}
else
{
Menu( s, BasePage + 16, trgGuild, gList[trgGuild]->RecruitNumber( button - 2 )); // display recruit number
}
break;
case BasePage + 7: // List of members
if( gList[trgGuild]->NumMembers() >= ( button - 2 ))
{
Menu( s, BasePage + 1, trgGuild );
}
else
{
Menu( s, BasePage + 17, trgGuild, gList[trgGuild]->MemberNumber( button - 2 )); // display member number
}
break;
case BasePage + 8: // Member dismiss
if( gList[trgGuild]->NumMembers() <= ( button - 2 ))
{
Menu( s, BasePage + 2, trgGuild );
}
else
{
tChar = CalcCharObjFromSer( gList[trgGuild]->MemberNumber( button - 2 ));
if( ValidateObject( tChar ))
{
if( tChar == mChar )
{
s->SysMessage( 1691 ); // You cannot dismiss yourself from the guild!
break;
}
gList[trgGuild]->RemoveMember(( *tChar ));
tChar->SetGuildNumber( -1 );
s->SysMessage( 1689, tChar->GetName().c_str() ); // You have dismissed %s from your guild!
auto tSock = tChar->GetSocket();
if( tSock != nullptr )
{
tSock->SysMessage( 1690 ); // You have been dismissed from your guild!
}
}
}
break;
case BasePage + 9: // Dismiss recruit
if( gList[trgGuild]->NumRecruits() <= ( button - 2 ))
{
Menu( s, BasePage + 2, trgGuild );
}
else
{
gList[trgGuild]->RemoveRecruit( gList[trgGuild]->RecruitNumber( button - 2 ));
}
break;
case BasePage + 10: // Accept recruit
if( gList[trgGuild]->NumRecruits() <= ( button - 2 ))
{
Menu( s, BasePage + 2, trgGuild );
}
else
{
tChar = CalcCharObjFromSer( gList[trgGuild]->RecruitNumber( button - 2 ));
if( ValidateObject( tChar ))
{
gList[trgGuild]->RecruitToMember(( *tChar ));
tChar->SetGuildNumber( trgGuild );
if( gList[trgGuild]->Type() != GT_STANDARD )
{
tChar->SetGuildToggle( true );
}
}
}
break;
case BasePage + 11: // War list
case BasePage + 12: // Grant title
Menu( s, BasePage + 2, trgGuild );
break;
case BasePage + 13: // Declare war list
offCounter = tCtr = 0;
ourList = gList[trgGuild]->GuildRelationList();
if( ourList->size() <= ( button - 2 ))
{
Menu( s, BasePage + 2, trgGuild );
}
toCheck = ourList->begin();
while( toCheck != ourList->end() )
{
if( toCheck->second != GR_WAR )
{
if( offCounter == ( button - 2 ))
{
gList[trgGuild]->SetGuildRelation( tCtr, GR_ALLY );
gList[trgGuild]->TellMembers( 165, gList[tCtr]->Name().c_str() );
gList[tCtr]->TellMembers( 166, gList[trgGuild]->Name().c_str() );
break;
}
else
{
++offCounter;
}
}
++tCtr;
++toCheck;
}
break;
case BasePage + 14: // Declare peace list
offCounter = tCtr = 0;
ourList = gList[trgGuild]->GuildRelationList();
if( ourList->size() <= ( button - 2 ))
{
Menu( s, BasePage + 2, trgGuild );
}
toCheck = ourList->begin();
while( toCheck != ourList->end() )
{
if( toCheck->second == GR_WAR )
{
if( offCounter == ( button - 2 ))
{
gList[trgGuild]->SetGuildRelation( tCtr, GR_NEUTRAL );
gList[trgGuild]->TellMembers( 167, gList[tCtr]->Name().c_str() );
gList[tCtr]->TellMembers( 168, gList[trgGuild]->Name().c_str() );
break;
}
else
{
++offCounter;
}
}
++tCtr;
++toCheck;
}
break;
case BasePage + 15: // List of guilds warring on us
Menu( s, BasePage + 1, trgGuild );
break;
case BasePage + 16: // Display recruit information
Menu( s, BasePage + 1, trgGuild );
break;
case BasePage + 17: // Display member information
Menu( s, BasePage + 1, trgGuild );
break;
case BasePage + 18: // Ally list
Menu( s, BasePage + 1, trgGuild );
break;
case BasePage + 19: // Declare Ally list
offCounter = tCtr = 0;
ourList = gList[trgGuild]->GuildRelationList();
toCheck = ourList->begin();
while( toCheck != ourList->end() )
{
if( toCheck->second != GR_ALLY )
{
if( offCounter == ( button - 2 ))
{
gList[trgGuild]->SetGuildRelation( tCtr, GR_ALLY );
gList[trgGuild]->TellMembers( 169, gList[tCtr]->Name().c_str() );
gList[tCtr]->TellMembers( 170, gList[trgGuild]->Name().c_str() );
break;
}
else
{
++offCounter;
}
}
++tCtr;
++toCheck;
}
break;
}
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuildCollection::Resign()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Handles player resigning from guild
//o------------------------------------------------------------------------------------------------o
void CGuildCollection::Resign( CSocket *s )
{
CChar *mChar = s->CurrcharObj();
SI16 guildNumber = mChar->GetGuildNumber();
if( guildNumber == -1 )
return;
CGuild *nGuild = gList[guildNumber];
if( nGuild == nullptr )
return;
nGuild->RemoveMember( *( s->CurrcharObj() ));
s->SysMessage( 171 ); // You are no longer in that guild.
mChar->SetGuildNumber( -1 );
mChar->SetGuildTitle( "" );
if( nGuild->Master() == mChar->GetSerial() && nGuild->NumMembers() != 0 )
{
nGuild->CalcMaster();
auto newGuildMaster = CalcCharObjFromSer( nGuild->Master() );
if( ValidateObject( newGuildMaster ))
{
nGuild->TellMembers( 1692, newGuildMaster->GetName().c_str(), nGuild->Name().c_str() ); // %s is now the new Guild Master of %s!
}
}
if( nGuild->NumMembers() == 0 )
{
SERIAL stone = nGuild->Stone();
if( stone != INVALIDSERIAL )
{
CItem *gStone = CalcItemObjFromSer( stone );
if( ValidateObject( gStone ))
{
gStone->Delete();
}
}
Erase( guildNumber );
s->SysMessage( 172 ); // You have been the last member of that guild so the stone vanishes.
}
mChar->Dirty( UT_UPDATE );
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuildCollection::Erase()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Erase guild - there are no guild members left
//o------------------------------------------------------------------------------------------------o
void CGuildCollection::Erase( GUILDID toErase )
{
GUILDLIST::iterator pFind = gList.find( toErase );
if( pFind == gList.end() ) // doesn't exist
return;
CGuild *gErase = pFind->second;
if( gErase == nullptr )
{
gList.erase( pFind );
return;
}
for( size_t iCounter = 0; iCounter < gErase->NumMembers(); ++iCounter )
{
SERIAL iMember = gErase->MemberNumber( iCounter );
CChar *member = CalcCharObjFromSer( iMember );
if( ValidateObject( member ))
{
member->SetGuildNumber( -1 );
}
}
for( size_t iC = 0; iC < gErase->NumRecruits(); ++iC )
{
SERIAL iRecruit = gErase->RecruitNumber( iC );
CChar *recruit = CalcCharObjFromSer( iRecruit );
if( ValidateObject( recruit ))
{
recruit->SetGuildNumber( -1 );
}
}
delete pFind->second;
gList.erase( pFind );
}
CGuildCollection::~CGuildCollection()
{
GUILDLIST::const_iterator i = gList.begin();
while( i != gList.end() )
{
if( i->second != nullptr )
{
delete i->second;
}
++i;
}
gList.clear();
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuildCollection::PlaceStone()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Handle placement of guildstone from deed, by player
//o------------------------------------------------------------------------------------------------o
void CGuildCollection::PlaceStone( CSocket *s, CItem *deed )
{
if( s == nullptr || !ValidateObject( deed ))
return;
CChar *mChar = s->CurrcharObj();
if( !ValidateObject( mChar ))
return;
if( deed->GetId() == 0x14F0 )
{
if( mChar->GetGuildNumber() != -1 ) // in a guild
{
s->ObjMessage( 173, deed ); // You are already in a guild.
return;
}
GUILDID gNum = NewGuild();
CGuild *nGuild = Guild( gNum );
if( nGuild == nullptr )
{
s->ObjMessage( 174, deed ); // Critical error adding guildstone, please contact a GM!
Console.Error( oldstrutil::format( "Critical error adding guildstone, memory allocation failed. Attempted by player 0x%X", mChar->GetSerial() ));
return;
}
mChar->SetGuildNumber( gNum );
s->TempInt( gNum );
nGuild->NewMember(( *mChar ));
CItem *stone = Items->CreateItem( nullptr, mChar, 0x0ED5, 1, 0, OT_ITEM );
if( !ValidateObject( stone ))
{
s->ObjMessage( 176, deed ); // Critical error, unable to spawn guildstone, please contact a GM!
Console.Error( oldstrutil::format( "Critical error spawning guildstone, no stone made. Attempted by player 0x%X", mChar->GetSerial() ));
return;
}
stone->SetName( Dictionary->GetEntry( 175 )); // Guildstone for an unnamed guild
if( mChar->GetId() == 0x0191 || mChar->GetId() == 0x0193 || mChar->GetId() == 0x025E || mChar->GetId() == 0x0260 )
{
mChar->SetGuildTitle( "Guildmistress" );
}
else
{
mChar->SetGuildTitle( "Guildmaster" );
}
stone->SetLocation( mChar );
nGuild->Webpage( DEFAULTWEBPAGE );
nGuild->Charter( DEFAULTCHARTER );
stone->SetType( IT_GUILDSTONE );
stone->SetTempVar( CITV_MORE, gNum );
stone->SetWipeable( false );
stone->SetDecayable( false );
deed->Delete();
nGuild->Master(( *mChar ));
nGuild->Stone(( *stone ));
TextEntryGump( s, mChar->GetSerial(), 100, 1, 30, 158 );
}
else if( deed->GetId() == 0x1869 )
{
// Transporter stone for guildstone
if( mChar->GetGuildNumber() == -1 ) // not in a guild
{
s->ObjMessage( "You don't appear to be in a guild", deed ); // You don't appear to be in a guild
return;
}
GUILDID gNum = deed->GetTempVar( CITV_MORE );
CGuild *nGuild = Guild( gNum );
if( nGuild == nullptr )
{
s->ObjMessage( 174, deed ); // Critical error adding guildstone, please contact a GM!
Console.Error( oldstrutil::format( "Critical error adding guildstone, memory allocation failed. Attempted by player 0x%X", mChar->GetSerial() ));
return;
}
CItem *stone = Items->CreateItem( nullptr, mChar, 0x0ED5, 1, 0, OT_ITEM );
if( !ValidateObject( stone ))
{
s->ObjMessage( 176, deed ); // Critical error, unable to spawn guildstone, please contact a GM!
Console.Error( oldstrutil::format( "Critical error spawning guildstone, no stone made. Attempted by player 0x%X", mChar->GetSerial() ));
return;
}
stone->SetName( oldstrutil::format( Dictionary->GetEntry( 101 ), nGuild->Name().c_str() ));
stone->SetLocation( mChar );
stone->SetType( IT_GUILDSTONE );
stone->SetTempVar( CITV_MORE, gNum );
stone->SetWipeable( false );
stone->SetDecayable( false );
deed->Delete();
nGuild->Stone(( *stone ));
}
else
{
s->SysMessage( 177 ); // That is not a valid guildstone deed
}
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuildCollection::ResultInCriminal()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Sets/Gets whether action will result in criminal flag based on guild relation
//o------------------------------------------------------------------------------------------------o
bool CGuildCollection::ResultInCriminal( GUILDID srcGuild, GUILDID trgGuild ) const
{
GUILDRELATION gRel = Compare( srcGuild, trgGuild );
switch( gRel )
{
case GR_WAR:
case GR_SAME:
return false;
case GR_ALLY:
case GR_NEUTRAL:
case GR_UNKNOWN:
case GR_COUNT:
default:
return true;
}
}
bool CGuildCollection::ResultInCriminal( CChar *src, CChar *trg ) const
{
if( !ValidateObject( src ) || !ValidateObject( trg ))
return false;
return ResultInCriminal( src->GetGuildNumber(), trg->GetGuildNumber() );
}
//o------------------------------------------------------------------------------------------------o
//| Function - CGuildCollection::DisplayTitle()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Display guild title for player character
//o------------------------------------------------------------------------------------------------o
void CGuildCollection::DisplayTitle( CSocket *s, CChar *src ) const
{
if( !ValidateObject( src ) || s == nullptr )
return;
GUILDID sGuild = src->GetGuildNumber();
if( sGuild != -1 && src->GetGuildToggle() )
{
std::string title;
CGuild *mGuild = Guild( sGuild );
if( mGuild == nullptr )
return;
auto abbreviation = std::string( mGuild->Abbreviation() );
if( abbreviation.empty() ) // 0 length string
{
abbreviation = "none";
}
if( mGuild->Type() != GT_STANDARD )
{
auto guildtype= GTypeNames[mGuild->Type()];
if( !src->GetGuildTitle().empty() )
{
title = oldstrutil::format( "[%s, %s] [%s]", src->GetGuildTitle().c_str(), abbreviation.c_str(), guildtype.c_str() );
}
else
{
title = oldstrutil::format( "[%s] [%s]", abbreviation.c_str(), guildtype.c_str() );
}
}
else
{
if( !src->GetGuildTitle().empty() )
{
title = oldstrutil::format( "[%s, %s]", src->GetGuildTitle().c_str(), abbreviation.c_str() );
}
else
{
title = oldstrutil::format( "[%s]", abbreviation.c_str() );
}
}
s->ObjMessage( title, src );
}
}