#if defined( macintosh ) #include <types.h> #else #include <sys/types.h> #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "merc.h" #include "build.h" /* * Globals */ CLAN_DATA * clan_first; CLAN_DATA * clan_last; CLAN_DATA * clan_free; sh_int top_clan; char * rank_string args( ( CHAR_DATA * ch, sh_int rank ) ); #if defined(KEY) #undef KEY #endif #if defined(SKEY) #undef SKEY #endif #define KEY( literal, field, value ) \ if ( !str_cmp( word, literal ) ) \ { \ field = value; \ fMatch = TRUE; \ break; \ } #define SKEY( string, field ) \ if ( !str_cmp( word, string ) ) \ { \ free_string( field ); \ field = fread_string( fp ); \ fMatch = TRUE; \ break; \ } bool is_clan( CHAR_DATA *ch ) { if ( !IS_NPC( ch ) && ch->pcdata->clan && ch->pcdata->clan_rank > RANK_EXILED ) return TRUE; return FALSE; } /* * It is very important that this be an equivalence relation: * (1) A ~ A * (2) if A ~ B then B ~ A * (3) if A ~ B and B ~ C, then A ~ C */ bool is_same_clan( CHAR_DATA *ach, CHAR_DATA *bch ) { if ( !ach || !bch ) return FALSE; if ( is_clan( ach ) && is_clan( bch ) ) return ach->pcdata->clan == bch->pcdata->clan; else return FALSE; } /* * Get pointer to clan structure from clan name. */ CLAN_DATA *get_clan( const char *name ) { CLAN_DATA *clan; for ( clan = clan_first; clan; clan = clan->next ) if ( !str_cmp( name, clan->name ) ) return clan; return NULL; } void remove_from_clan( CHAR_DATA *ch ) { CLAN_DATA *clan; if ( !is_clan( ch ) ) return; clan = ch->pcdata->clan; switch ( ch->pcdata->clan_rank ) { default: break; case RANK_CLANSMAN: break; case RANK_CLANHERO: clan->clanheros--; break; case RANK_SUBCHIEF: clan->subchiefs--; break; case RANK_CHIEFTAIN: free_string( clan->chieftain ); break; case RANK_OVERLORD: free_string( clan->overlord ); break; } clan->members--; ch->pcdata->clan = NULL; return; } char * rank_string( CHAR_DATA *ch, sh_int rank ) { switch ( rank ) { default: case RANK_CLANSMAN: return "soldier"; case RANK_CLANHERO: return "warhero"; case RANK_SUBCHIEF: return "general"; case RANK_CHIEFTAIN: return "baron"; case RANK_OVERLORD: return "overlord"; } } void do_initiate( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; CLAN_DATA *clan; OBJ_DATA *card; OBJ_DATA *ring; char arg [ MAX_INPUT_LENGTH ]; char buf [ MAX_STRING_LENGTH ]; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Initiate whom?\n\r", ch ); return; } if ( !( victim = get_char_room( ch, arg ) ) ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( !is_clan( ch ) || ch->pcdata->clan_rank < RANK_CHIEFTAIN || victim->level > ch->level ) { send_to_char( "You don't have the power to do this.\n\r", ch ); return; } clan = ch->pcdata->clan; if ( victim == ch ) return; card = get_eq_char( victim, WEAR_HOLD ); if ( is_clan( victim ) || IS_NPC( victim ) || !card || victim->pcdata->clan_rank == RANK_EXILED || victim->level < 20 ) { act( "$N hasn't what's required to be initiated.", ch, NULL, victim, TO_CHAR ); act( "You can't be initiated to $t!", ch, clan->name, victim, TO_VICT ); return; } victim->pcdata->clan = clan; victim->pcdata->clan_rank = RANK_CLANSMAN; clan->members++; ring = create_object( get_obj_index( clan->clanobj1 ), victim->level ); if ( ring ) obj_to_char( ring, victim ); sprintf( buf, "Log %s: initiated %s to %s", ch->name, victim->name, clan->name ); log_clan( buf ); sprintf( buf, "I %s %s, hereby declare you %s a member of %s!", rank_string( ch, PC(ch,clan_rank) ), ch->name, victim->name, clan->name ); do_say( ch, buf ); sprintf( buf, "Take %s as a symbol of this union for all time.", ring ? ring->short_descr : "my handshake" ); do_say( ch, buf ); sprintf( buf, "Forever remember our motto: \"%s\"\n\r", clan->motto ); do_say( ch, buf ); act( "$N has been initiated to $t!", ch, clan->name, victim, TO_ROOM ); act( "You have initiated $N to $t!", ch, clan->name, victim, TO_CHAR ); save_char_obj( victim ); return; } /* * "exil" command is a trap to the "exile" command. */ void do_exil( CHAR_DATA *ch, char *argument ) { send_to_char( "If you want to EXILE, you have to spell it out.\n\r", ch ); return; } void do_exile( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; CLAN_DATA *clan; char arg [ MAX_INPUT_LENGTH ]; char buf [ MAX_STRING_LENGTH ]; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Exile whom?\n\r", ch ); return; } if ( !is_clan( ch ) || ch->pcdata->clan_rank != RANK_OVERLORD ) { send_to_char( "You don't have the power to do this.\n\r", ch ); return; } clan = ch->pcdata->clan; if ( !( victim = get_char_room( ch, arg ) ) ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( IS_NPC( victim ) || victim == ch ) return; if ( !is_same_clan( ch, victim ) ) { act( "$N isn't even from $t.", ch, clan->name, victim, TO_CHAR ); return; } sprintf( buf, "Log %s: exiling %s from %s", ch->name, victim->name, ch->pcdata->clan->name ); log_clan( buf ); sprintf( buf, "The grand %s of %s %s says:\n\r\n\r" "'Then so be done, you %s shall be exiled from %s!'\n\r" "You hear a thundering sound...\n\r\n\r" "A booming voice says: 'You have been exiled!n\r", rank_string( ch, PC(ch,clan_rank) ), clan->name, clan->overlord, victim->name, clan->name ); send_to_char( buf, victim ); remove_from_clan( victim ); victim->pcdata->clan_rank = RANK_EXILED; act( "You have exiled $N from $t!", ch, clan->name, victim, TO_CHAR ); save_char_obj( victim ); return; } void do_bestow( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; CLAN_DATA *clan; OBJ_DATA *obj; char arg [ MAX_INPUT_LENGTH ]; char buf [ MAX_STRING_LENGTH ]; int newrank; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Promote whom?\n\r", ch ); return; } if ( !is_clan( ch ) || ch->pcdata->clan_rank != RANK_OVERLORD ) { send_to_char( "You don't have the power to do this.\n\r", ch ); return; } clan = ch->pcdata->clan; if ( !( victim = get_char_room( ch, arg ) ) ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( IS_NPC( victim ) || victim == ch ) return; if ( !is_same_clan( ch, victim ) ) { act( "$N isn't even from $t.", ch, clan->name, victim, TO_CHAR ); return; } obj = NULL; switch ( victim->pcdata->clan_rank ) { default: return; break; case RANK_CLANSMAN: if ( clan->clanheros >= clan->members / 3 ) { send_to_char( "You may have only 1 clanhero per 3 clansmen.\n\r", ch ); return; } obj = create_object( get_obj_index( clan->clanobj2 ), victim->level ); clan->clanheros++; break; case RANK_CLANHERO: if ( clan->subchiefs >= clan->members / 6 ) { send_to_char( "You may have only 1 subchief per 6 clansmen.\n\r", ch ); return; } obj = create_object( get_obj_index( clan->clanobj3 ), victim->level ); clan->clanheros--; clan->subchiefs++; break; case RANK_SUBCHIEF: if ( clan->chieftain[0] != '\0' ) { send_to_char( "You may have only 1 chieftain.\n\r", ch ); return; } else if ( clan->members < 9 ) { send_to_char( "You need to have 9 clansmen before you can have a chieftain.\n\r", ch ); return; } clan->subchiefs--; if( clan->chieftain ) free_string( clan->chieftain ); clan->chieftain = str_dup( victim->name ); break; case RANK_CHIEFTAIN: case RANK_OVERLORD: send_to_char( "You may not promote any further that person.\n\r", ch ); return; break; } victim->pcdata->clan_rank++; newrank = victim->pcdata->clan_rank; if ( obj ) obj_to_char( obj, victim ); sprintf( buf, "Log %s: promoting %s to %s", ch->name, victim->name, ch->pcdata->clan->name ); log_clan( buf ); sprintf( buf, "The grand Overlord %s says:\n\r\n\r" "'I hereby promote you %s to %s!'\n\r" "Take %s as a prize for your superb performance.\n\r" "%s\n\r", ch->name, victim->name, rank_string( ch, newrank ), obj ? obj->short_descr : "this promotion", clan->motto ); send_to_char( buf, victim ); act( "You have promoted $N to $t.", ch, rank_string( ch, newrank ), victim, TO_CHAR ); save_char_obj( victim ); return; } void do_demote( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; CLAN_DATA *clan; char arg [ MAX_INPUT_LENGTH ]; char buf [ MAX_STRING_LENGTH ]; int newrank; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Demote whom?\n\r", ch ); return; } if ( !is_clan( ch ) || ch->pcdata->clan_rank != RANK_OVERLORD ) { send_to_char( "You don't have the power to do this.\n\r", ch ); return; } clan = ch->pcdata->clan; if ( !( victim = get_char_room( ch, arg ) ) ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( IS_NPC( victim ) || victim == ch ) return; if ( !is_same_clan( ch, victim ) ) { act( "$N isn't even from $t.", ch, clan->name, victim, TO_CHAR ); return; } switch ( victim->pcdata->clan_rank ) { default: return; break; case RANK_CLANSMAN: send_to_char( "He's as low as they can get.\n\r", ch ); return; break; case RANK_CLANHERO: clan->clanheros--; break; case RANK_SUBCHIEF: clan->clanheros++; clan->subchiefs--; break; case RANK_CHIEFTAIN: clan->subchiefs++; free_string( clan->chieftain ); break; case RANK_OVERLORD: send_to_char( "You may not demote an Overlord!?\n\r", ch ); return; break; } victim->pcdata->clan_rank--; newrank = victim->pcdata->clan_rank; sprintf( buf, "Log %s: demoting %s to %s", ch->name, victim->name, ch->pcdata->clan->name ); log_clan( buf ); sprintf( buf, "The grand Overlord %s says:\n\r\n\r" "'I hereby demote you %s to %s!!!'\n\r" "You should make more efforts to improve!", ch->name, victim->name, rank_string( ch, newrank ) ); send_to_char( buf, victim ); act( "You have demoted $N to $t.", ch, rank_string( ch, newrank ), victim, TO_CHAR ); save_char_obj( victim ); return; } void do_leave( CHAR_DATA *ch, char *argument ) { CLAN_DATA *clan; char buf [ MAX_STRING_LENGTH ]; if ( !is_clan( ch ) ) { send_to_char( "You aren't a clansman.\n\r", ch ); return; } clan = ch->pcdata->clan; if ( ch->pcdata->clan_rank == RANK_OVERLORD ) { send_to_char( "Huh? An Overlord shouldn't leave his clan!\n\r", ch ); return; } remove_from_clan( ch ); ch->pcdata->clan_rank = RANK_EXILED; sprintf( buf, "You leave %s off into exile.\n\r" "You hear a thundering sound...\n\r\n\r" "A booming voice says: 'You have been exiled!'\n\r", clan->name ); send_to_char( buf, ch ); act( "You have left clan $t.", ch, clan->name, NULL, TO_CHAR ); save_char_obj( ch ); return; } void do_overthrow( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; CLAN_DATA *pClan; char buf [ MAX_STRING_LENGTH ]; if( IS_NPC(ch) ) return; pClan = PC(ch,clan); if( !(victim = get_char_room( ch, argument ) ) ) { stc( "There is noone here by that name.\n\r", ch ); return; } if( IS_NPC(victim) ) { stc( "Not on NPC's.\n\r", ch ); return; } if( victim == ch ) { stc( "Why would you want to do that?\n\r", ch ); return; } if( PC(victim,clan) != pClan ) { ch_printf( ch, "%s is not the overlord of %s.\n\r", PERS(victim,ch), pClan->name ); return; } if( PC(victim,clan_rank) != RANK_OVERLORD ) { ch_printf( ch, "%s is not the overlord of %s.\n\r", PERS(victim,ch), pClan->name ); return; } if( victim->hit > 0 ) { ch_printf( ch, "%s must be morted.\n\r", PERS(victim,ch) ); return; } PC(victim,clan_rank) = PC(ch,clan_rank); PC(ch,clan_rank) = RANK_OVERLORD; free_string( pClan->overlord ); pClan->overlord = str_dup( ch->name ); if( PC(victim,clan_rank) == RANK_CHIEFTAIN ) { free_string( pClan->chieftain ); pClan->chieftain = str_dup( victim->name ); } sprintf( buf, "I %s, a former %s of %s\n\r", ch->name, rank_string(victim, PC(victim,clan_rank)),pClan->name ); do_say( ch, buf ); sprintf( buf, "declare that %s kingdom is now under my control.", pClan->name ); do_say( ch, buf ); save_char_obj( victim ); save_char_obj( ch ); return; } void do_clans( CHAR_DATA *ch, char *argument ) { CLAN_DATA *clan; char buf1 [ MAX_STRING_LENGTH ]; char buf [ MAX_STRING_LENGTH ]; int found; buf1[0] = '\0'; sprintf( buf, "{o{rClan Overlord Chieftain Pkills{x\n\r" ); strcat( buf1, buf ); for ( clan = clan_first, found = 0; clan; clan = clan->next ) { sprintf( buf, "{R%-16.16s %-16.16s %-16.16s %5.5d{x\n\r", clan->name, clan->overlord, clan->chieftain, clan->pkills ); strcat( buf1, buf ); found++; } if ( !found ) sprintf( buf, "{RThere are no Clans currently formed.{x\n\r" ); else sprintf( buf, "{RYou see %d clan%s in the game.{x\n\r", found, found == 1 ? "" : "s" ); strcat( buf1, buf ); send_to_char( buf1, ch ); return; } void show_clan( CHAR_DATA *ch, CLAN_DATA *clan ) { DESCRIPTOR_DATA *d; CHAR_DATA *wch; int found = 0; char temp[MAX_INPUT_LENGTH]; ch_printf( ch, "{yOrder: {b[{c%s{b] {n%s{n\n\r", clan->name, clan->who_name ); ch_printf( ch, "{gMotto{n\n\r %s{n\n\r", clan->motto ); ch_printf( ch, "{gStory\n\r{W... %s ...{n\n\r", clan->description ); ch_printf( ch, "{g%-14.14s {b[{c%s{b]{n\n\r", rank_string( ch, RANK_OVERLORD ), clan->overlord ); if( clan->chieftain && clan->chieftain[0] ) { sprintf( temp, "%ss", rank_string( ch, RANK_CHIEFTAIN ) ); ch_printf( ch, "{g%-14.14s {b[{c%s{b]{n\n\r", rank_string( ch, RANK_CHIEFTAIN ), clan->chieftain ); } sprintf( temp, "%ss", rank_string( ch, RANK_CLANHERO ) ); ch_printf( ch, "{g%-14.14s {b[{c%d{b/{c%d{b]{n\n\r", temp, clan->clanheros, clan->members / 3 ); sprintf( temp, "%ss", rank_string( ch, RANK_CLANSMAN ) ); ch_printf( ch, "{g%-14.14s {b[{c%d{b]{n\n\r", temp, clan->members ); ch_printf( ch, "{gKills {b[{c%d{b]{n\n\r", clan->pkills ); ch_printf( ch, "{gDeaths {b[{c%d{b]{n\n\r", clan->pdeaths ); ch_printf( ch, "{gRecall {b[{c%d{b]{y %s{n\n\r", IS_IMMORTAL( ch ) ? clan->recall : 0, get_room_index( clan->recall ) ? ( get_room_index( clan->recall ) )->name : "nowhere" ); for( d = descriptor_list; d; d = d->next ) { wch = CH( d ); if( wch->pcdata->clan != clan || !can_see( ch, wch ) ) continue; if( !found ) { stc( LINE_SEPERATOR, ch ); stc("{gMembers online:{n\n\r",ch ); } found++; ch_printf( ch, "{y%25.25s", wch->name ); if( found % 3 == 0 ) stc("{n\n\r", ch); } if( found % 3 != 0 ) stc("{n\n\r", ch ); if( found ) ch_printf( ch,"{gFound {c%d {gmember%s online.{n\n\r", found, ( found == 1 ) ? "" : "s" ); } void do_claninfo( CHAR_DATA *ch, char *argument ) { CLAN_DATA * clan; if ( !is_clan( ch ) ) { send_to_char( "You aren't a clansman.\n\r", ch ); return; } clan = ch->pcdata->clan; stc( LINE_SEPERATOR, ch ); show_clan( ch, clan ); stc( LINE_SEPERATOR, ch ); return; } /* * All the file and loading for clans from here on down */ /* * New code for loading clans from file. */ bool fread_clan( CLAN_DATA *clan, FILE *fp ) { char *word; bool fMatch; for ( ; ; ) { word = feof( fp ) ? "End" : fread_word( fp ); fMatch = FALSE; switch ( UPPER( word[0] ) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'C': SKEY( "Chieftain", clan->chieftain ); KEY( "ClanHeros", clan->clanheros, fread_number( fp ) ); KEY( "ClanObjOne", clan->clanobj1, fread_number( fp ) ); KEY( "ClanObjTwo", clan->clanobj2, fread_number( fp ) ); KEY( "ClanObjThree", clan->clanobj3, fread_number( fp ) ); break; case 'D': SKEY( "Desc", clan->description ); break; case 'E': if ( !str_cmp( word, "End" ) ) return TRUE; break; case 'M': KEY( "Members", clan->members, fread_number( fp ) ); SKEY( "Motto", clan->motto ); break; case 'N': SKEY( "Name", clan->name ); break; case 'O': SKEY( "Overlord", clan->overlord ); break; case 'P': KEY( "PKills", clan->pkills, fread_number( fp ) ); KEY( "PDeaths", clan->pdeaths, fread_number( fp ) ); break; case 'R': KEY( "Recall", clan->recall, fread_number( fp ) ); break; case 'S': KEY( "Subchiefs", clan->subchiefs, fread_number( fp ) ); break; case 'W': SKEY( "WhoName", clan->who_name ); break; } if ( !fMatch ) { bugf( "Load_clan_file: no match: %s", word ); fread_to_eol(fp); } } return FALSE; } bool load_clan_file( char *filename ) { CLAN_DATA *clan; FILE *fp; char buf [ MAX_STRING_LENGTH ]; sprintf( buf, "%s%s", CLAN_DIR, filename ); if ( !( fp = fopen( buf, "r" ) ) ) { perror( buf ); return FALSE; } clan = alloc_mem ( sizeof( CLAN_DATA ) ); clan->filename = str_dup( filename ); for ( ; ; ) { char *word; int letter; letter = fread_letter( fp ); if ( letter == '*' ) { fread_to_eol( fp ); continue; } if ( letter != '#' ) { bug( "Load_clan_file: # not found.", 0 ); free_mem( clan, sizeof( CLAN_DATA ) ); break; } word = fread_word( fp ); if ( !str_cmp( word, "CLAN" ) ) { fread_clan( clan, fp ); if ( !clan_first ) clan_first = clan; else clan_last->next = clan; clan->next = NULL; clan_last = clan; top_clan++; break; } else if ( !str_cmp( word, "END" ) ) break; else { bugf( "Load_clan_file: bad section: %s.", word ); free_mem( clan, sizeof( CLAN_DATA ) ); break; } } fclose( fp ); return TRUE; } /* * Load in all the clan files. */ void load_clans( void ) { FILE *fpList; char *filename; char fname [ MAX_STRING_LENGTH ]; char clanslist [ MAX_STRING_LENGTH ]; clan_first = NULL; clan_last = NULL; top_clan = 0; sprintf( clanslist, "%s%s", CLAN_DIR, CLAN_LIST ); if ( !( fpList = fopen( clanslist, "r" ) ) ) { perror( clanslist ); exit( 1 ); } for ( ; ; ) { filename = feof( fpList ) ? "$" : fread_word( fpList ); strcpy( fname, filename ); if ( fname[0] == '$' ) break; if ( !load_clan_file( fname ) ) bugf( "Cannot load clan file: %s", fname ); } fclose( fpList ); return; } void save_clan_list( void ) { FILE *fp; CLAN_DATA *clan; char clanslist [ MAX_STRING_LENGTH ]; sprintf( clanslist, "%s%s", CLAN_DIR, CLAN_LIST ); fclose( fpReserve ); if ( !( fp = fopen( clanslist, "w" ) ) ) { bug( "Save_clan_list: fopen", 0 ); perror( clanslist ); return; } for ( clan = clan_first; clan; clan = clan->next ) fprintf( fp, "%s\n", clan->filename ); fprintf( fp, "$\n" ); fclose( fp ); fpReserve = fopen( NULL_FILE, "r" ); return; } void clan_update( void ) { CLAN_DATA *clan; for ( clan = clan_first; clan; clan = clan->next ) save_clan( clan ); return; } /* * New code for writing a clan to a file. */ void save_clan( CLAN_DATA *clan ) { FILE *fp; char buf [ MAX_STRING_LENGTH ]; if ( !clan->filename ) return; sprintf( buf, "%s%s", CLAN_DIR, clan->filename ); fclose( fpReserve ); if ( !( fp = fopen( buf, "w" ) ) ) { bugf( "Cannot open: %s for writing", clan->filename ); } else { fprintf( fp, "#CLAN\n" ); fprintf( fp, "WhoName %s~\n", clan->who_name ); fprintf( fp, "Name %s~\n", clan->name ); fprintf( fp, "Motto %s~\n", clan->motto ); fprintf( fp, "Desc %s~\n", strip_cr(clan->description ) ); fprintf( fp, "Overlord %s~\n", clan->overlord ); fprintf( fp, "Chieftain %s~\n", clan->chieftain ); fprintf( fp, "PKills %d\n", clan->pkills ); fprintf( fp, "PDeaths %d\n", clan->pdeaths ); fprintf( fp, "Clanheros %d\n", clan->clanheros ); fprintf( fp, "Subchiefs %d\n", clan->subchiefs ); fprintf( fp, "Members %d\n", clan->members ); fprintf( fp, "ClanObjOne %d\n", clan->clanobj1 ); fprintf( fp, "ClanObjTwo %d\n", clan->clanobj2 ); fprintf( fp, "ClanObjThree %d\n", clan->clanobj3 ); fprintf( fp, "Recall %d\n", clan->recall ); fprintf( fp, "End\n" ); fprintf( fp, "#END\n" ); fclose( fp ); } fpReserve = fopen( NULL_FILE, "r" ); return; }