/**************************************************************************/
// clan.cpp - Clan Class and clan related functions - Tibault & Kal
/***************************************************************************
* The Dawn of Time v1.69r (c)1997-2004 Michael Garratt *
* >> A number of people have contributed to the Dawn codebase, with the *
* majority of code written by Michael Garratt - www.dawnoftime.org *
* >> To use this source code, you must fully comply with the dawn license *
* in licenses.txt... In particular, you may not remove this copyright *
* notice. *
**************************************************************************/
#include "include.h"
#include "olc.h"
#include "clan.h"
void save_clan_db( void );
CClanType *clan_list=NULL;
/**************************************************************************/
CClanType::CClanType()
{
m_pSaveName = str_dup("");
m_pName = str_dup("");
m_pNoteName = str_dup("");
m_pWhoName = str_dup("");
m_pDescription = str_dup("");
m_pWhoCat = str_dup("");
m_pColorStr = str_dup("");
m_RecallRoom = 0;
m_BankRoom = 0;
m_pClanRankTitle[0] = str_dup( "toprank" );
m_CanAdd[0] = true;
m_CanPromote[0] = true;
m_CanRemove[0] = true;
m_CanWithdraw[0] = true;
for ( int i=1; i< MAX_RANK; i++ )
{
m_pClanRankTitle[i] = str_dup( "" );
m_CanAdd[i] = false;
m_CanPromote[i] = false;
m_CanRemove[i] = false;
m_CanWithdraw[i] = false;
}
next=NULL;
}
/**************************************************************************/
CClanType::~CClanType()
{
free_string(m_pSaveName);
free_string(m_pName);
free_string(m_pNoteName);
free_string(m_pWhoName);
free_string(m_pDescription);
free_string(m_pWhoCat);
free_string(m_pColorStr);
for ( int i=0; i< MAX_RANK; i++ )
{
free_string(m_pClanRankTitle[i]);
}
}
/**************************************************************************/
void CClanType::printDetails(char_data *ch)
{
if(IS_ADMIN(ch)){
ch->printlnf( " `#%s%-40s`& %-15s %6d %8d",
m_pColorStr, m_pName, m_pNoteName, m_RecallRoom, (int)m_BankFunds);
}else if(IS_IMMORTAL(ch)){
ch->printlnf( " `#%s%-40s`& %-15s %6d",
m_pColorStr, m_pName, m_pNoteName, m_RecallRoom );
}else{
ch->printlnf( " `#%s%-40s`& %-15s ???",
m_pColorStr, m_pName, m_pNoteName);
}
}
/**************************************************************************/
void CClanType::printRanks( char_data *ch )
{
int i;
int count=0;
for ( i=0; i< MAX_RANK; i++ )
{
if ( !IS_NULLSTR(m_pClanRankTitle[i]) ) {
ch->printlnf( "`sRank %d `s- Title %s%s",
i,
m_pColorStr,
m_pClanRankTitle[i] );
count++;
}
}
ch->printlnf("There %s a total of %d rank%s in %s",
count==1?"is":"are",
count,
count==1?"":"s",
cname());
}
/**************************************************************************/
int CClanType::minRank()
{
int lIdx;
for ( lIdx=MAX_RANK-1; lIdx>=0; lIdx-- ) {
if( !IS_NULLSTR(m_pClanRankTitle[lIdx])){
return lIdx;
}
}
return 0;
}
/**************************************************************************/
/**************************************************************************/
// GENERIC CLAN FUNCTIONS
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
// do_addclan Tibault:Sep 00
// Function for admin or headclan for setting the clan on players.
// You can also set the rank with this command. If ommited, the top rank
// will be set.
/**************************************************************************/
void do_addclan( char_data *ch, char *argument )
{
char arg1[MIL],arg2[MIL],arg3[MIL];
char_data *victim;
int rank = 0;
CClanType* pClan;
if (!IS_ADMIN(ch)
&& !IS_SET(TRUE_CH(ch)->pcdata->council, COUNCIL_HEADCLAN))
{
ch->println( "Addclan can only be used by the head of the clan council or admin." );
return;
}
argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );
argument = one_argument( argument, arg3 );
if ( arg1[0] == '\0' || arg2[0] == '\0' )
{
ch->println( "Syntax: addclan <char> <clan name> <clan rank>" );
ch->println( "Syntax: addclan <char> none (to remove them from a clan)" );
return;
}
if ( ( victim = get_whovis_player_world( ch, arg1 ) ) == NULL )
{
ch->println( "They aren't playing." );
return;
}
if (!str_prefix(arg2,"none"))
{
ch->println( "They are now clanless." );
victim->println( "You are now a member of no clan!" );
victim->clan = NULL;
victim->clanrank = 0;
return;
}
if (!IS_LETGAINED(victim)){
ch->printlnf( "%s hasn't been letgained yet.", PERS(victim, ch) );
return;
}
if ((pClan = clan_lookup(arg2)) == NULL)
{
ch->printlnf( "No such clan '%s' exists.", arg2 );
return;
}
if (IS_NULLSTR(arg3))
{
rank=pClan->minRank();
}
else
{
if ((rank = pClan->rank_lookup(arg3) ) == -1)
{
ch->printlnf( "No such rank '%s' exists in the clan '%s'.",
arg3, pClan->cname());
return;
}
}
{
ch->printlnf( "They are now a %s (%d) of clan %s.",
pClan->clan_rank_title(rank), rank, pClan->cname() );
victim->printlnf("You are now a %s of clan %s.",
pClan->clan_rank_title(rank), pClan->cname() );
}
victim->clan = pClan;
victim->clanrank = rank;
}
/**************************************************************************
do_clanlist Tibault:Sep 00
Prints the details for every clan in the global variable clan_list.
If you want to change the way these details are shown, change
the CClanType function printdetails().
**************************************************************************/
void do_clanlist(char_data *ch, char *)
{
CClanType *pClan;
if(!clan_list){
ch->println("There are currently no clans, clans can be added using clanedit create.");
return;
}
ch->print( "`#`S-`YClanname`S===================================`YNoteName`S========`YRecall`S");
if(IS_ADMIN(ch)){
ch->println("====`YFunds`S-`^");
}else{
ch->println("-`^");
}
for (pClan = clan_list; pClan; pClan = pClan->next ){
pClan->printDetails(ch);
}
}
/**************************************************************************/
// Kal, Feb 02
void clan_show_clanrank_syntax(char_data *ch)
{
if(IS_IMMORTAL(ch)){
ch->println("syntax: clanrank <clanname> - to see the ranks of a given clan.");
ch->println("syntax: clanrank <player> - to see the rank of a given player.");
}else{
ch->println("syntax: clanrank <clanmember> - to see the rank of another clan member in the same room.");
}
}
/**************************************************************************/
// Kal, Feb 02
void clan_show_ranks(char_data *ch, char_data *victim, CClanType *pClan)
{
if(pClan){
pClan->printRanks(ch);
if(victim){
ch->printlnf( "%s's rank in this clan is: `#%s%s`^",
PERS(victim, ch),
pClan->color_str(),
pClan->clan_rank_title(victim->clanrank) );
}
if ( ch->clan == pClan){
ch->printlnf( "Your rank in this clan is: `#%s%s`^",
pClan->color_str(),
pClan->clan_rank_title(ch->clanrank) );
}
}
}
/**************************************************************************/
// Kal, Feb 02
void do_clanranks(char_data *ch, char *argument)
{
char_data *victim;
// non clanned players can not use the command
if(!IS_IMMORTAL(ch) && !ch->clan){
ch->println("You are clanless, you have no use for this command.");
return;
}
// if no argument is specified, show a player/immortal
// the clan they are in
if(IS_NULLSTR(argument)){
clan_show_ranks(ch, NULL, ch->clan);
clan_show_clanrank_syntax(ch);
return;
}
// attempt to find a specified player
victim = get_whovis_player_world(ch, argument);
if(!victim){
// character not found
if(IS_IMMORTAL(ch)){ // imms can also specify the clan name
// picking a clan
CClanType* pClan= clan_lookup(argument);
if(!pClan){
ch->printlnf( "No such clan or player '%s' is currently in the game.", argument );
clan_show_clanrank_syntax(ch);
return;
}
// clan found, show the ranks
clan_show_ranks(ch, NULL, pClan);
return;
}
ch->printlnf( "No such clanmember '%s' is currently in the game.", argument );
return;
}
// victim was found, do some checks
if(IS_IMMORTAL(ch)){
if(!victim->clan){
ch->printlnf("%s is not in a clan.", PERS(victim, ch));
clan_show_clanrank_syntax(ch);
return;
}
}else{
if(!victim->clan || victim->clan!=ch->clan){
ch->printlnf("%s is not in the same clan as you.", PERS(victim, ch));
clan_show_clanrank_syntax(ch);
return;
}
if(ch->in_room!=victim->in_room){
ch->printlnf("%s is not in the same room as you.", PERS(victim, ch));
clan_show_clanrank_syntax(ch);
return;
}
}
// victim found, show the ranks
clan_show_ranks(ch, victim, victim->clan);
}
/**************************************************************************
do_add Tibault:Sep 00
Function for mortals to add members to their clan.
**************************************************************************/
void do_add( char_data *ch, char *argument )
{
char arg1[MIL];
char_data *victim;
if ( IS_OOC(ch) ) {
ch->println( "Add is an IC command, you can't use it in OOC rooms." );
return;
}
argument = one_argument( argument, arg1 );
if( ch->clan == NULL ) {
ch->println( "You are not in a clan yourself!" );
return;
}
if( ch->clan->m_CanAdd[ch->clanrank] == false ) {
ch->println( "You don't have the authority to do that." );
return;
}
if ( ( victim = get_char_world( ch, arg1 ) ) == NULL ) {
ch->println( "They aren't playing." );
return;
}
if ( victim->in_room != ch->in_room ) {
ch->println( "They aren't here." );
return;
}
if ( !IS_LETGAINED(victim) ) {
ch->printlnf( "%s hasn't been letgained yet.", PERS(victim, ch) );
return;
}
if( victim->clan ) {
ch->printlnf( "%s is already in a clan.", PERS(victim, ch) );
return;
}
if( victim->seeks != ch->clan ) {
ch->wraplnf("They are not seeking to join your clan."
"They have been told you invited them to join, and to seek your clan if interested"
"- try again shortly.");
victim->wraplnf("%s invited you to become a member of a "
"clan which goes by the name '%s'. You weren't seeking that "
"clan, type 'seek %s' if you want to join, and when they invite "
"you again... you will automatically join.",
PERS(ch, victim),
ch->clan->name(),
ch->clan->notename());
return;
}
victim->clan = ch->clan ;
victim->clanrank = ch->clan->minRank();
victim->seeks = NULL;
ch->printlnf( "They are now a %s of your clan.",
victim->clan->clan_rank_title(victim->clanrank));
victim->printlnf( "You are now a %s of clan %s.",
victim->clan->clan_rank_title(victim->clanrank),
victim->clan->name());
return;
}
/**************************************************************************
do_demote Tibault:Sep 00
Function for mortals to demote members to their clan.
**************************************************************************/
void do_demote( char_data *ch, char *argument )
{
char arg1[MIL];
char_data *victim;
if ( IS_OOC(ch) ) {
ch->println( "Demote is an IC command, you can't use it in OOC rooms." );
return;
}
if( ch->clan == NULL ) {
ch->println( "You are not in a clan yourself!" );
return;
}
if( ch->clan->m_CanPromote[ch->clanrank] == false ) {
ch->println( "You don't have the authority to do that." );
return;
}
argument = one_argument( argument, arg1 );
if ( ( victim = get_char_world( ch, arg1 ) ) == NULL ) {
ch->println( "They aren't playing." );
return;
}
if ( victim->in_room != ch->in_room ) {
ch->println( "They aren't here." );
return;
}
if( victim->clan != ch->clan ) {
ch->println( "They are not in your clan." );
return;
}
if( victim->clanrank <= ch->clanrank ) {
ch->println( "They are too high in rank for your authority." );
ch->println( "You Must ask an Immortal to remove another leader." );
return;
}
if( victim->clanrank >= victim->clan->minRank() ) {
ch->println( "They are already of the lowest rank." );
return;
}
victim->clanrank++;
ch->printlnf( "They are now a %s of your clan.",
ch->clan->clan_rank_title(victim->clanrank) );
victim->printlnf( "You are now a %s of clan %s.",
victim->clan->clan_rank_title(victim->clanrank),
victim->clan->name());
return;
}
/**************************************************************************
do_outcast Tibault:Sep 00
Function for mortals to outcast members to their clan.
**************************************************************************/
void do_outcast( char_data *ch, char *argument )
{
char arg1[MIL];
char_data *victim;
if ( IS_OOC(ch) ) {
ch->println( "Outcast is an IC command, you can't use it in OOC rooms." );
return;
}
if( ch->clan == NULL ) {
ch->println( "You are not in a clan yourself!" );
return;
}
if( ch->clan->m_CanRemove[ch->clanrank] == false ) {
ch->println( "You don't have the authority to do that." );
return;
}
argument = one_argument( argument, arg1 );
if ( (victim=get_char_world(ch, arg1)) == NULL ) {
ch->println( "They aren't playing." );
return;
}
if ( victim->in_room != ch->in_room ) {
ch->println( "They aren't here." );
return;
}
if( victim->clan != ch->clan ){
ch->println( "They are not in your clan." );
return;
}
if(ch->clanrank >= victim->clanrank ) {
ch->println( "You don't have the authority to do that." );
return;
}
ch->printlnf( "They are no longer a %s of your clan.",
victim->clan->clan_rank_title(victim->clanrank) );
victim->printlnf( "You are no longer a %s of clan %s.",
victim->clan->clan_rank_title(victim->clanrank),
victim->clan->name());
victim->println("You have been outcast!");
victim->clan = NULL;
victim->clanrank = 0;
return;
}
/**************************************************************************
do_promote Tibault:Sep 00
Function for mortals to outcast members to their clan.
**************************************************************************/
void do_promote( char_data *ch, char *argument )
{
char arg1[MIL];
char_data *victim;
if ( IS_OOC(ch) ) {
ch->println( "Promote is an IC command, you can't use it in OOC rooms." );
return;
}
if( ch->clan == NULL ) {
ch->println("You are not in a clan yourself!" );
return;
}
if( ch->clan->m_CanPromote[ch->clanrank] == false ) {
ch->println( "You don't have the authority to do that." );
return;
}
argument = one_argument( argument, arg1 );
if ( (victim = get_char_world(ch, arg1)) == NULL ) {
ch->println( "They aren't playing." );
return;
}
if ( victim->in_room != ch->in_room ) {
ch->println( "They aren't here." );
return;
}
if( victim->clan != ch->clan ) {
ch->println( "They are not in your clan." );
return;
}
if( victim->clanrank<=ch->clanrank ){
ch->println( "They are already too high in rank for your authority." );
return;
}
if(victim->clanrank==0){
ch->println( "They are already the highest rank in your clan." );
return;
}
victim->clanrank--;
ch->printlnf( "They are now a %s of your clan.",
ch->clan->clan_rank_title(victim->clanrank) );
victim->printlnf( "Congratulations, you are now a %s of clan %s.",
ch->clan->clan_rank_title(victim->clanrank),
ch->clan->name());
return;
}
/**************************************************************************
do_seek Tibault:Sep 00
Function for mortals to seek the clan they wish to join.
**************************************************************************/
void do_seek( char_data *ch, char *argument )
{
char arg1[MIL];
CClanType* pClan;
argument = one_argument(argument, arg1);
if ( !str_cmp(arg1,"none") ) {
ch->seeks = NULL;
ch->println( "You are seeking no clan." );
return;
}
if ( ch->clan ) {
ch->println( "You are already in a clan." );
return;
}
if ( (pClan = clan_lookup(arg1)) == NULL ) {
ch->println( "No such clan exists." );
return;
}
ch->seeks = pClan;
ch->printlnf( "You are seeking to join %s.",
pClan->name() );
ch->println("(type 'seek none' to stop seeking a clan.)");
return;
}
/**************************************************************************/
const char * CClanType::name()
{
if(!this){
return "";
}
return m_pName;
}
/**************************************************************************/
const char * CClanType::cname()
{
if(!this){
return "";
}
static char result[MIL];
sprintf(result, "`#%s%s`&", m_pColorStr, m_pName);
return result;
}
/**************************************************************************/
// name used to save to disk, never changes
const char * CClanType::savename()
{
if(!this){
return "";
}
return m_pSaveName;
}
/**************************************************************************/
const char * CClanType::notename()
{
if(!this){
return "";
}
return m_pNoteName;
}
/**************************************************************************/
const char * CClanType::color_str()
{
if(!this){
return "";
}
return m_pColorStr;
}
/**************************************************************************/
const char * CClanType::who_name()
{
if(!this){
return "";
}
return m_pWhoName;
}
/**************************************************************************/
const char * CClanType::cwho_name()
{
if(!this){
return "";
}
static char result[MIL];
sprintf(result, "`#%s%s`&", m_pColorStr, m_pWhoName);
return result;
}
/**************************************************************************/
const char * CClanType::who_cat()
{
if(!this){
return "";
}
return m_pWhoCat;
}
/**************************************************************************/
const char * CClanType::clan_rank_title(int rank)
{
return m_pClanRankTitle[rank];
}
/**************************************************************************/
int CClanType::recall_room()
{
return m_RecallRoom;
}
/**************************************************************************/
// Kal - Sept 2000
int CClanType::rank_lookup(const char *ranktitle)
{
int rnk;
if(this==NULL){ // clanless
return 0;
}
for (rnk = 0; rnk < MAX_RANK; rnk++)
{
if (!str_prefix(ranktitle,m_pClanRankTitle[rnk])){
return rnk;
}
}
return -1;
}
/**************************************************************************/
CClanType* clan_lookup( const char *name )
{
CClanType *pClan;
if(IS_NULLSTR(name)){
return NULL;
}
// first try an exact match
for(pClan=clan_list;pClan;pClan=pClan->next){
if(!str_cmp(name,pClan->name() )){
return pClan;
}
}
// now try a prefix match
for(pClan=clan_list;pClan;pClan=pClan->next){
if(!str_prefix(name,pClan->name())){
return pClan;
}
}
// not found
return NULL;
}
/**************************************************************************/
// lookup a clan by their note name - Kalahn oct97
CClanType* clan_nlookup( const char *name )
{
CClanType *pClan;
// first try an exact match
for(pClan=clan_list;pClan;pClan=pClan->next){
if(!str_cmp(name,pClan->notename())){
return pClan;
}
}
// now try a prefix match
for(pClan=clan_list;pClan;pClan=pClan->next){
if(!str_prefix(name,pClan->notename())){
return pClan;
}
}
// not found
return NULL;
}
/**************************************************************************/
// lookup a clan by their save name - Kalahn Sept2000
CClanType* clan_slookup( const char *savename )
{
CClanType *pClan;
// only do exact matching
for(pClan=clan_list;pClan;pClan=pClan->next){
if(!str_cmp(savename,pClan->savename())){
return pClan;
}
}
// not found
return NULL;
}
/**************************************************************************/
void clan_bank( char_data *ch, char *task, char *amount)
{
int number;
if(IS_NPC(ch)){
ch->println("clan banking by players only sorry.");
return;
}
if(!str_prefix(task,"balance") )
{
ch->printlnf( "Your clan has %ld gold in its coffers.", ch->clan->m_BankFunds );
// the clanbank transaction trail
append_datetimestring_to_file( CLANBANKING_FILE,
FORMATF("%s[%d] got a clanbank balance of %s - balance is %d`x",
TRUE_CH(ch)->name,
ch->clanrank,
ch->clan->who_name(),
(int)ch->clan->m_BankFunds));
return;
}
if(!is_number(amount))
{
ch->printlnf( "clanbank: The second argument must be a number, '%s' is not.", amount );
return;
}
number=atoi(amount);
if(number<=0)
{
ch->println( "clanbank: The second argument must be a number greater than 0." );
return;
}
if(number>1250000){
ch->println( "clanbank: Sorry, we don't deal with such large amounts!" );
return;
}
if(!str_prefix(task,"deposit"))
{
if( number+5>ch->gold )
{
if( number>ch->gold ){
ch->println( "You do not have that much money." );
}else{
ch->wrapln( "There is a 5 gold piece fee per deposit. Banking all that money will not leave you with enough to pay our deposit fee." );
}
return;
}
ch->gold -= number + 5;
ch->clan->m_BankFunds += number;
ch->printlnf( "Deposit made.\r\nYour clan now has %ld gold pieces in its coffers.",
ch->clan->m_BankFunds );
logf("[clanbank] %s deposited %d gold into clan bank account %s - balance now %d",
ch->name,
number,
ch->clan->who_name(),
(int)ch->clan->m_BankFunds);
// the clanbank transaction trail
append_datetimestring_to_file( CLANBANKING_FILE,
FORMATF("%s[%d] deposited %d gold into clan bank account %s - balance now %d`x",
TRUE_CH(ch)->name,
ch->clanrank,
number,
ch->clan->who_name(),
(int)ch->clan->m_BankFunds));
// resave the clan database
save_clan_db();
save_char_obj(ch); // resave them
WAIT_STATE(ch, PULSE_PER_SECOND*3);
return;
}
if(!str_prefix(task,"withdraw"))
{
if ( !ch->clan->m_CanWithdraw[ch->clanrank])
{
// the clanbank transaction trail
append_datetimestring_to_file( CLANBANKING_FILE,
FORMATF("%s[%d] attempted to withdraw %d gold from clan bank account %s but didn't have authority - balance is %d`x",
TRUE_CH(ch)->name,
ch->clanrank,
number,
ch->clan->who_name(),
(int)ch->clan->m_BankFunds));
ch->println( "You do not have the authority to withdraw money from your clan." );
return;
}
if( number < 6 )
{
ch->println("Due to the surcharge of 5 gold you can not withdraw that small of an amount.");
return;
}
if( number > ch->clan->m_BankFunds-5 )
{
ch->println("You do not have that much in the bank.");
return;
}
ch->gold += number;
ch->clan->m_BankFunds -= number + 5;
ch->printlnf( "Withdrawal made. There was a 5 gold piece surcharge.\r\nYour clan now has %ld gold pieces in its coffers.",
ch->clan->m_BankFunds );
logf("[clanbank] %s withdrew %d gold from clan bank account %s - balance now %d",
ch->name,
number,
ch->clan->who_name(),
(int)ch->clan->m_BankFunds);
// the clanbank transaction trail
append_datetimestring_to_file( CLANBANKING_FILE,
FORMATF("%s[%d] withdrew %d gold from clan bank account %s - balance now %d`x",
TRUE_CH(ch)->name,
ch->clanrank,
number,
ch->clan->who_name(),
(int)ch->clan->m_BankFunds));
// resave the clan database
save_clan_db();
save_char_obj(ch); // resave them
WAIT_STATE(ch, PULSE_PER_SECOND*3);
return;
}
ch->printlnf( "'%s' is not a valid clanbank transaction.", task );
return;
}
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/