/* * The unique portions SunderMud code as well as the integration efforts * for code from other sources is based on the efforts of: * * Lotherius (elfren@aros.net) * * This code can only be used under the terms of the DikuMud, Merc, * and ROM licenses. The same requirements apply to the changes that * have been made. * * All other copyrights remain in place and in force. */ /* * act_clan.c - added by Zeran to support clans. * All functions related to clans belong in this file * for easy reference and modification. */ #include "everything.h" /*command functions needed*/ DECLARE_DO_FUN (do_who); /*Globals*/ struct clan_proto *clans[MAX_CLANS]; /*clan command functions*/ void clan_review (CHAR_DATA *ch); void clan_list (CHAR_DATA *ch); void clan_accept (CHAR_DATA *ch, char *arg); void clan_promote (CHAR_DATA *ch, char *arg); void clan_donate (CHAR_DATA *ch, char *arg); void clan_demote (CHAR_DATA *ch, char *arg); void clan_quit (CHAR_DATA *ch); void do_clan_tell (CHAR_DATA *ch, char *argument); /*local functions*/ void do_clan_tell (CHAR_DATA *ch, char *argument) /*sloppy code format stolen from do_auction*/ { char buf[MAX_STRING_LENGTH]; DESCRIPTOR_DATA *d; if (ch->pcdata->clan_num == -1) { send_to_char ("You do not belong to any clan.\n\r",ch); send_to_char ("Once you join a clan, you can use 'clan tell'\n\r",ch); return; } if (argument[0] == '\0' ) { if (IS_SET(ch->comm,COMM_NOCLANTELL)) { send_to_char("Clan channel is now ON.\n\r",ch); REMOVE_BIT(ch->comm,COMM_NOCLANTELL); } else { send_to_char("Clan channel is now OFF.\n\r",ch); SET_BIT(ch->comm,COMM_NOCLANTELL); } } else { if (IS_SET(ch->comm,COMM_QUIET)) { send_to_char("You must turn off quiet mode first.\n\r",ch); return; } if (IS_SET(ch->comm,COMM_NOCHANNELS)) { send_to_char("The gods have revoked your channel priviliges.\n\r",ch); return; } sprintf( buf, "{RYou tell your clan '%s'{x\n\r", argument ); send_to_char( buf, ch ); for ( d = descriptor_list; d != NULL; d = d->next ) { CHAR_DATA *victim; victim = d->original ? d->original : d->character; if ( d->connected == CON_PLAYING && d->character != ch && !IS_SET(victim->comm,COMM_NOCLANTELL) && !IS_SET(victim->comm,COMM_QUIET) && d->character->pcdata->clan_num == ch->pcdata->clan_num) { act_new("{R$n tells the clan '$t'{x", ch,argument,d->character,TO_VICT,POS_DEAD); } } } } /* Big clan function parser */ void do_clan (CHAR_DATA *ch, char *argument) { char message[MAX_INPUT_LENGTH]; char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; argument=one_argument(argument, arg1); sprintf(message, argument); argument=one_argument(argument, arg2); if (arg1[0]=='\0') /*no argument, kick out list of clan commands*/ { send_to_char ("\n\rClan commands:\n\r",ch); send_to_char ("---- --------\n\r",ch); send_to_char ("clan review\n\r",ch); send_to_char ("clan quit\n\r",ch); send_to_char ("clan accept [player]\n\r",ch); send_to_char ("clan promote [player]\n\r",ch); send_to_char ("clan demote [player]\n\r",ch); send_to_char ("clan list\n\r",ch); send_to_char ("clan donate [integer]\n\r",ch); send_to_char ("clan tell [message string]\n\r",ch); return; } if (!str_cmp(arg1, "review")) clan_review(ch); else if (!str_cmp(arg1, "list" )) clan_list(ch); else if (!str_cmp(arg1, "quit" )) clan_quit(ch); else if (!str_cmp(arg1, "accept")) clan_accept(ch,arg2); else if (!str_cmp(arg1, "promote")) clan_promote(ch, arg2); else if (!str_cmp(arg1, "demote")) clan_demote(ch, arg2); else if (!str_cmp(arg1, "donate")) clan_donate(ch,arg2); else if (!str_cmp(arg1, "tell")) do_clan_tell(ch,message); else if (!str_cmp(arg1, "who")) do_who(ch, "clan"); else send_to_char ("No such clan command...\n\r",ch); return; } void clan_review (CHAR_DATA *ch) /*Only clan members get a review*/ /*In the future, nonmembers will get*/ /* an abbreviated review */ { char buf[80]; int cnum; struct leader *tmp; buf[0]='\0'; cnum=ch->pcdata->clan_num; if (cnum==-1) { send_to_char ("You do not belong to any clan.\n\r",ch); return; } else if (!valid_clan(cnum)) { sprintf (buf, "%s's clan_num [%d] is invalid.\n\r", ch->name, cnum); log_string(buf); send_to_char ("Your clan number is invalid, inform the IMP asap.\n\r",ch); return; } send_to_char ("\n\r{gCLAN REVIEW:{x\n\r", ch); send_to_char ("____ ______\n\r", ch); sprintf(buf, "Clan {Y%s{x\n\r", clans[cnum]->name); send_to_char (buf, ch); send_to_char ("Clan rulers are: \n\r",ch); tmp=clans[cnum]->chiefs; if (tmp==NULL) { send_to_char ("None\n\r", ch); } else for (;tmp!=NULL;tmp=tmp->next) { sprintf(buf, "{c%s{x\n\r", tmp->name); send_to_char (buf, ch); } sprintf (buf, "Membership: {r%d{x players.\n\r", clans[cnum]->num_members); send_to_char (buf, ch); sprintf (buf, "Bank funds: {Y%d{x gold coins.\n\r", clans[cnum]->bank); send_to_char (buf, ch); return; } void clan_list (CHAR_DATA *ch) /*All players get list*/ { int count=0; char buf[80]; send_to_char("\n\r{YClan listing{W:\n\r", ch); send_to_char("{B____ _______\n\r",ch); while (clans[count]!=NULL) { sprintf(buf, "{W[{Y%d{W] %s{x\n\r",count,clans[count]->name); send_to_char(buf, ch); count++; } } void clan_accept (CHAR_DATA *ch, char *arg) { CHAR_DATA *victim; char messbuf[128]; int num=-1; if (ch->pcdata->clan_num==-1) { send_to_char ("You do not belong to a clan.\n\r",ch); return; } if (ch->pcdata->clan_rank < MIN_ACCEPT_RANK) { send_to_char ("You cannot accept new members, your clan rank is too low.\n\r",ch); return; } if (arg[0]=='\0') { send_to_char ("Accept whom?\n\r",ch); return; } if (((victim = get_char_world (ch, arg)) == NULL) || (victim->in_room != ch->in_room) || IS_NPC(victim)) { send_to_char ("That player isn't here.\n\r",ch); return; } /*ok, checks done, accept new member!*/ send_to_char ("Done. *cheer*, your clan is growing!\n\r",ch); sprintf (messbuf, "%s has accepted you into clan %s !\n\r",ch->name, ch->pcdata->clan->name); send_to_char (messbuf, victim); /* Zeran - notify message */ notify_message (victim, NOTIFY_CLANACCEPT, TO_CLAN, ch->pcdata->clan->name); /*set victims clan info*/ num = ch->pcdata->clan_num; victim->pcdata->clan_num = num; /*clan number*/ strcpy (victim->pcdata->clan_name, clans[num]->name); /*clan_name*/ victim->pcdata->clan = clans[num]; /*pointer to clan*/ victim->pcdata->clan_rank=1; /*minimum member rank*/ ch->pcdata->clan->num_members++; /*increment member count*/ fwrite_clans(); return; } void clan_promote (CHAR_DATA *ch, char *arg) { CHAR_DATA *victim; int num=-1; if (ch->pcdata->clan_num==-1) { send_to_char ("You do not belong to a clan.\n\r",ch); return; } if (ch->pcdata->clan_rank < MIN_ADVANCE_RANK) { send_to_char ("You cannot promote members, your clan rank is too low.\n\r",ch); return; } if (arg[0]=='\0') { send_to_char ("Promote whom?\n\r",ch); return; } if (((victim = get_char_world (ch, arg)) == NULL) || (victim->in_room != ch->in_room) || IS_NPC(victim)) { send_to_char ("That player isn't here.\n\r",ch); return; } num=victim->pcdata->clan_num; if (num != ch->pcdata->clan_num) { send_to_char ("That player is not a member of your clan.\n\r",ch); return; } if (victim->pcdata->clan_rank >= ch->pcdata->clan_rank) { send_to_char ("You can not promote that player any higher.\n\r",ch); return; } if (((++victim->pcdata->clan_rank) == MAX_RANK) && (victim->pcdata->clan->num_leaders == MAX_LEADER)) { send_to_char ("Promoting that player will exceed the maximum number\n\r",ch); send_to_char ("of leaders allowed in your clan...promotion cancelled.\n\r",ch); victim->pcdata->clan_rank--; return; } /*checks done, advance rank*/ send_to_char ("{cCongratulations{x, you have been promoted to a higher clan rank!\n\r",victim); send_to_char ("Done.\n\r",ch); /* Zeran - notify message */ { char rankbuf[24]; clan_rank_name(victim, rankbuf); notify_message (victim, NOTIFY_CLANPROMOTE, TO_CLAN, rankbuf); } /*check to see if new leader added, if so, update clan struct info*/ if (victim->pcdata->clan_rank == MAX_RANK) { struct leader *tmp; victim->pcdata->clan->num_leaders++; /*increment leader count*/ tmp=clans[num]->chiefs; /*assumption: one leader exists already*/ for (;tmp->next!=NULL;tmp=tmp->next); /*find end of leaders list*/ tmp->next=(struct leader *)alloc_perm(sizeof(struct leader)); strcpy (tmp->next->name, victim->name); tmp->next->next=NULL; fwrite_clans(); } } void clan_demote (CHAR_DATA *ch, char *arg) { CHAR_DATA *victim; int num=-1; if (ch->pcdata->clan_num==-1) { send_to_char ("You do not belong to a clan.\n\r",ch); return; } if (ch->pcdata->clan_rank < MAX_RANK) { send_to_char ("Only clan rulers can demote a clan member.\n\r",ch); return; } if (arg[0]=='\0') { send_to_char ("Demote whom?\n\r",ch); return; } if (((victim = get_char_world (ch, arg)) == NULL) || (victim->in_room != ch->in_room) || IS_NPC(victim)) { send_to_char ("That player isn't here.\n\r",ch); return; } num=victim->pcdata->clan_num; if (num != ch->pcdata->clan_num) { send_to_char ("That player is not a member of your clan.\n\r",ch); return; } if (victim->pcdata->clan_rank == MAX_RANK) { send_to_char ("Clan rulers cannot be demoted except by the IMP.\n\r",ch); return; } if (victim->pcdata->clan_rank == 1) { send_to_char ("That player is already at the lowest clan rank.\n\r",ch); return; } /*checks done, reduce rank*/ send_to_char ("Oh no, you have been demoted to a lower clan rank!\n\r",victim); send_to_char ("Done.\n\r",ch); victim->pcdata->clan_rank--; } void clan_donate (CHAR_DATA *ch, char *arg) { int amount; if (ch->pcdata->clan_num == -1) /*not in clan*/ { send_to_char ("You are not a member of a clan.\n\r",ch); return; } if (arg[0]=='\0') { send_to_char ("You must specify an amount of gold.\n\r",ch); return; } amount=atoi(arg); if (amount < 1) { send_to_char ("You must donate a positive number of gold coins.\n\r",ch); return; } if (amount > ch->gold) { send_to_char ("You do not have that much gold to donate.\n\r",ch); return; } if (amount >= (0.75*ch->gold)) /*very generous*/ { send_to_char ("Your clan greatly appreciates your large donation.\n\r",ch); if ((amount >= 10000) && (number_percent() <= 10)) { int bonus; char messybuf[80]; bonus = 25 + number_percent()*75/100; sprintf (messybuf, "Role playing bonus for clan involvement: %d xp.\n\r", bonus); send_to_char (messybuf, ch); ch->exp += bonus; } } else { send_to_char ("You make a donation to your clan.\n\r",ch); } ch->gold -= amount; ch->pcdata->clan->bank += amount; return; fwrite_clans(); } void clan_quit (CHAR_DATA *ch) { if (ch->pcdata->clan_num == -1) { send_to_char ("You are not a member of any clan.\n\r",ch); return; } if (ch->pcdata->clan_rank == MAX_RANK) /*rulers can't quit!*/ { send_to_char ("Clan rulers cannot simply do 'clan quit', please talk to the IMP.\n\r",ch); return; } if (!ch->pcdata->clan_quit) { send_to_char ("Are you sure you want to quit your clan?\n\r",ch); send_to_char ("Do 'clan quit' again to verify and quit your clan.\n\r",ch); ch->pcdata->clan_quit=TRUE; return; } send_to_char ("'clan quit' verified and complete.\n\r",ch); /* Zeran - notify message */ notify_message (ch, NOTIFY_CLANQUIT, TO_CLAN, ch->pcdata->clan->name); /*reset player's clan fields*/ ch->pcdata->clan_num = -1; ch->pcdata->clan_rank = -1; ch->pcdata->clan = NULL; ch->pcdata->clan_quit = FALSE; sprintf (ch->pcdata->clan_name, "none"); fwrite_clans(); } void boot_clans (void) { FILE *clan_file; int count=0; bool done=FALSE; if ( ( clan_file = fopen( CLAN_FILE, "r" ) ) == NULL ) { perror (CLAN_FILE); exit(1); } while ((!done) && (count<MAX_CLANS)) { char *word; if (fread_letter(clan_file) != '#') { bug ("boot_clan: Missing #.", 0); exit (1); } word = fread_word( clan_file ); if ( word[0] == '$' ) { done = TRUE; /* log_string ("clan: Got ending $"); */ } else if ( !str_cmp( word, "NAME" ) ) { word = fread_string( clan_file ); if (strlen(word) > 40) { bug ("boot_clan: Clan name too long.", 0); exit (1); } clans[count]=(struct clan_proto *)alloc_perm(sizeof(struct clan_proto)); clans[count]->chiefs=NULL; clans[count]->number=count; strcpy (clans[count]->name, word); /* log_string (clans[count]->name); */ } else if ( !str_cmp( word, "LEADER" ) ) { struct leader *tmp; /* log_string ("clan: getting leaders");*/ clans[count]->num_leaders=0; for (;;) { word = fread_string (clan_file); /* log_string (word); */ if (word[0]=='@') break; if (strlen(word) > 40) { bug ("boot_clan: Leader name too long.", 0); exit (1); } tmp = clans[count]->chiefs; if (clans[count]->chiefs==NULL) { clans[count]->chiefs=(struct leader *)alloc_perm(sizeof(struct leader)); tmp=clans[count]->chiefs; } else /*goto end of chief list*/ { tmp = clans[count]->chiefs; for (;(tmp->next!=NULL);tmp=tmp->next); tmp->next = (struct leader *)alloc_perm(sizeof(struct leader)); tmp=tmp->next; } strcpy (tmp->name, word); clans[count]->num_leaders++; tmp->next=NULL; } tmp=clans[count]->chiefs; for (;(tmp!=NULL);tmp=tmp->next) { /* log_string(tmp->name); */ } } else if ( !str_cmp( word, "MEMCOUNT" ) ) { int number; number = fread_number (clan_file); /* log_string ("clan: getting MEMCOUNT number"); */ if (number <=0) { bug ("boot_clan: Bad MEMCOUNT number.", 0); exit (1); } clans[count]->num_members=number; } else if ( !str_cmp( word, "BANK" ) ) { int number; number = fread_number(clan_file); /* log_string ("clan: getting BANK number"); */ if (number < 0) { bug ("boot_clan: Bad BANK number.", 0); exit (1); } clans[count]->bank=number; count++; /*increment clan counter*/ clans[count]=NULL; /*signify end of clans*/ } else { bug ("boot_clan: Bad header after #.", 0); exit (1); } } /*end while*/ log_string ("Finished Booting Clans"); fclose( clan_file ); } /*end reading of clans*/ /* Zeran: set_clan_pointer was originally only meant to set a character's clan pointer, but it has blown up to include initializations of some other clan related fields inside each character. */ void set_clan_pointer (CHAR_DATA *ch) { char buf[80]; int count=0; bool match=FALSE; ch->pcdata->clan_quit=FALSE; /*hasn't tried to quit their clan yet*/ while ((clans[count]!=NULL) && (count<MAX_CLANS)) { if (!str_cmp(clans[count]->name, ch->pcdata->clan_name)) { ch->pcdata->clan_num=count; match=TRUE; break; } /* sprintf (buf, "%d", count); log_string(buf); */ count++; } if (!match) { sprintf (buf, "%s's clan name %s is invalid.",ch->name, ch->pcdata->clan_name); log_string (buf); ch->pcdata->clan_num=-1; /*no clan*/ return; } ch->pcdata->clan=clans[count]; if (ch->pcdata->clan_rank==-1) { log_string ("Bad rank number, resetting to rank 1"); ch->pcdata->clan_rank=1; } /* log_string ("end of set_clan_pointer"); log_string (ch->pcdata->clan->name); */ return; } bool valid_clan (int number) { if ( (number < MAX_CLANS) && (number > -1) && (clans[number] != NULL) ) return TRUE; else return FALSE; } #define OUTFILE "../clan/clans.txt" /* * Zeran: Write out the clan file */ void fwrite_clans (void) { FILE *outfile; int count=0; bool done=FALSE; struct leader *tmp; if ((outfile=fopen(OUTFILE, "w+")) == NULL) { bug ("Failed to open clan output file.",0); return; } while ((!done) && (count<MAX_CLANS)) { fprintf(outfile, "#NAME\n"); fprintf(outfile, "%s~\n", clans[count]->name); fprintf(outfile, "#LEADER\n"); tmp=clans[count]->chiefs; for(;tmp!=NULL;tmp=tmp->next) { fprintf(outfile, "%s~\n", tmp->name); } fprintf(outfile, "@~\n"); fprintf(outfile, "#MEMCOUNT\n"); fprintf(outfile, "%d\n", clans[count]->num_members); fprintf(outfile, "#BANK\n"); fprintf(outfile, "%d\n", clans[count]->bank); count++; if (clans[count]==NULL) done=TRUE; } fprintf(outfile, "#$\n"); fclose (outfile); } void clan_rank_name (CHAR_DATA *ch, char *buf) { int rank=ch->pcdata->clan_rank; if (rank==1) sprintf(buf, "Follower"); else if (rank==2) sprintf(buf, "Disciple"); else if (rank==3) sprintf(buf, "Advocate"); else if (rank==4) sprintf(buf, "OverSeer"); else if (rank==5) sprintf(buf, "Ruler"); else sprintf(buf, "none"); } /* Zeran - get_clan_by_name returns a clan pointer by a clan name lookup. If the name isn't found, NULL is returned. */ struct clan_proto *get_clan_by_num (int num) { if (valid_clan(num)) return clans[num]; else return NULL; }