/* * * Battle code to allow players * to fight one another without * the loss of experience or items. * Origianlly coded for Age of Infinity MUD * by Theodryck. C 1999. * * You may use and distribute this code * freely as long you leave unaltered * the documention within. * */ /* In merc.h we need to make the declarations */ /* Add this after PLR_PAGER */ #define PLR_BATTLE BV30 /* Add this in the channel declarations part of merc.h */ #define CHANNEL_BATTLE BV10 /* In the DECLARE_DO_FUN section add the following: */ /*Battle stuff by Theodryck*/ DECLARE_DO_FUN( do_battle ); DECLARE_DO_FUN( do_bopen ); DECLARE_DO_FUN( do_bclose ); DECLARE_DO_FUN( do_bstop ); DECLARE_DO_FUN( do_bchat ); DECLARE_DO_FUN( do_badd ); DECLARE_DO_FUN( do_bremove ); /* * Set up all the parts used */ typedef struct battle_data BATTLE_DATA; /*battle struct*/ extern BATTLE_DATA * battle; /*Here's the main battle struct */ struct battle_data { int level1; int level2; bool open; bool running; }; void talk_battle args( (char *argument) ); void do_battle args( (CHAR_DATA *ch, char * argument ) ); void do_bopen args( (CHAR_DATA *ch, char * argument ) ); void do_bclose args( (CHAR_DATA *ch, char * argument ) ); void do_bstop args( (CHAR_DATA *ch, char * argument ) ); void do_bchat args( (CHAR_DATA *ch, char * argument ) ); /* In act_wiz.c we add the actual functions for the immortal commands */ void do_bopen(CHAR_DATA *ch, char* argument ) { int upper; int lower; char buf[MAX_STRING_LENGTH]; int number; // battle = (BATTLE_DATA *) malloc (sizeof(BATTLE_DATA)); if(IS_NPC( ch ) ) /*mobs can't open battles */ return; lower = 0; upper = 0; number = 0; for ( ;; ) { char arg[MAX_STRING_LENGTH]; argument = one_argument(argument, arg); if(arg[0] == '\0') break; if (is_number( arg ) ) { switch (++number) { case 1: lower = atoi( arg ) ; break; case 2: upper = atoi( arg ) ; break; default : send_to_char("Only two level numbers please.", ch ); return; } } else { send_to_char ("Syntax is: bopen .", ch ); return; } } battle->open = TRUE; battle->level1 = lower; battle->level2 = upper; sprintf( buf,"{o{wNow open for levels {m<{r%d - %d{m>{w!{x\n\r",lower,upper); talk_battle( buf ); return; } /*Now that we've opened a battle , we need a way to close it */ void do_bclose (CHAR_DATA *ch, char *argument) { char buf[MAX_STRING_LENGTH]; ROOM_INDEX_DATA *location; int place; if(IS_NPC( ch ) ) /*Since mobs can't open battles, let's not let them close battles*/ return; /*actual closing of battle and scattering of players */ battle->open = FALSE; sprintf(buf,"Is now closed!\n\r"); talk_battle( buf ); for(ch = char_list; ch; ch = ch->next) { if (IS_SET( ch->act, PLR_BATTLE ) ) { place = number_range(24001, 24048); location = get_room_index( place ); char_from_room( ch ); /*Randomly drop players about*/ char_to_room( ch, location ); /*the battle field, the numbers*/ } /*can be changed to suit your*/ } /*battle area.*/ battle->running = TRUE; return; } /*Just in case we need it*/ void do_bstop(CHAR_DATA *ch, char * argument) { char buf[MAX_STRING_LENGTH]; ROOM_INDEX_DATA *location; int place; if(IS_NPC( ch ) ) return; place = 3001; location = get_room_index( place ); if( !battle->running && !battle->open ) { send_to_char( "There is no battle going on that you can stop", ch ); return; } sprintf( buf,"{o{wHas been stopped!{x\n\r" ); talk_battle( buf ); for(ch = char_list; ch; ch = ch->next ) { if(IS_SET( ch->act, PLR_BATTLE ) ) { /* Ahapin - added this check to stop fights in progress */ if ( ch->fighting ) stop_fighting( ch, TRUE ); REMOVE_BIT( ch->act, PLR_BATTLE ); char_from_room( ch ); char_to_room( ch, location ); } } battle->running = FALSE; battle->open = FALSE; return; } /*Here's a little tidbit just for fun *Add players to battle regardless of level */ void do_badd( CHAR_DATA * ch, char * argument ) { CHAR_DATA *victim; CHAR_DATA *rch; ROOM_INDEX_DATA *location; int place; char arg1[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; argument = one_argument(argument, arg1 ); rch = get_char( ch ); if ( !authorized( rch, "badd" ) ) return; if(!battle->running && !battle->open ) { send_to_char( "There is no battle going on at the moment", ch ); return; } if (arg1[0] == '\0') { send_to_char( "Add who to the battle?", ch ); return; } if ( !( victim = get_char_world( ch, arg1 ) ) ) { send_to_char( "They aren't here.\n\r", ch ); return; } place = ROOM_VNUM_PREP; location = get_room_index( place ); if ( IS_NPC( victim ) ) { send_to_char( "Not on mobs.\n\r", ch ); return; } else { act( "$n has gone to seek glory on the battlefield.", victim, NULL, NULL, TO_ROOM ); char_from_room( victim ); char_to_room( victim, location ); act( "$n has arrived on the battlefield.", victim, NULL, NULL, TO_ROOM ); do_look( victim, "auto" ); SET_BIT ( victim->act, PLR_BATTLE ); victim->battles++; sprintf( buf,"{o{w%s {rhas joined the battle!.{x\n\r",victim->name ); talk_battle( buf ); victim->mana = victim->max_mana; victim->hit = victim->max_hit; victim->move = victim->max_move; sprintf( buf, "%s added to the battle.\n\r", victim->name ); send_to_char( buf, ch ); } return; } /*Since we can add players...let's be able to remove them as well. */ void do_bremove( CHAR_DATA * ch, char * argument ) { CHAR_DATA *victim; CHAR_DATA *rch; ROOM_INDEX_DATA *location; int place; char buf[MAX_STRING_LENGTH]; char arg1[MAX_STRING_LENGTH]; argument = one_argument( argument, arg1 ); rch = get_char( ch ); if ( !authorized( rch, "bremove" ) ) return; if(!battle->running && !battle->open ) { send_to_char( "There is no battle going on at the moment", ch ); return; } if (arg1[0] == '\0') { send_to_char( "Remove who from the battle?", ch ); return; } if ( !( victim = get_char_world( ch, arg1 ) ) ) { send_to_char( "They aren't here.\n\r", ch ); return; } if (IS_NPC( victim ) ) { send_to_char( "Not on mobs.\n\r", ch ); return; } else { REMOVE_BIT( victim->act, PLR_BATTLE ); place = victim->pcdata->temple; location = get_room_index( place ); sprintf( buf, "%s has removed you from battle.\n\r", ch->name ); send_to_char( buf, victim ); char_from_room( victim ); char_to_room( victim, location ); do_look( victim, "auto" ); sprintf( buf, "%s has been removed from battle.\n\r", victim->name ); send_to_char( buf, ch ); } return; } /* * In act_move.c we add the function that allows * players to actually join the battles */ /*Battle code stuff by Theodryck */ void do_battle (CHAR_DATA *ch, char * argument) { ROOM_INDEX_DATA *location; char buf[MAX_STRING_LENGTH]; int place; /*can't let mobs in battles :P*/ if (IS_NPC( ch ) ) return; /*There's no battle going on dummy */ if(!battle->open) { send_to_char("There is no battle currently open",ch ); return; } if( IS_SET( ch->act, PLR_BATTLE ) ) return; place = ROOM_VNUM_PREP; location = get_room_index( place ); /* *Here we check to see if the player is in the *proper level range */ if(battle->open && (ch->level >= battle->level1 && ch->level <= battle->level2) ) { act( "$n has gone to seek glory on the battlefield.", ch, NULL, NULL, TO_ROOM ); char_from_room( ch); char_to_room( ch, location ); act( "$n has arrived on the battlefield.", ch, NULL, NULL, TO_ROOM ); do_look(ch, "auto" ); SET_BIT (ch->act, PLR_BATTLE ); ch->battles++; sprintf(buf,"{o{w%s {rhas joined the battle!.{x\n\r",ch->name); talk_battle( buf ); ch->mana = ch->max_mana; ch->hit = ch->max_hit; ch->move = ch->max_move; } else { send_to_char("You are not in the correct level range", ch); return; } return; } /* in db.c we add the following */ /*In the globals section */ BATTLE_DATA * battle; bool check_battle; /* Add this after the weather initialization in boot_db */ battle = (BATTLE_DATA *) malloc (sizeof(BATTLE_DATA)); /* DOH!!! */ if (battle == NULL) { bug ("malloc'ing BATTLE_DATA didn't give %d bytes",sizeof(BATTLE_DATA)); exit (1); } battle->open = FALSE; battle->running = FALSE; /* In fight.c we need to add this */ /*Add this in one_hit, right after the declarations are made */ if ( IS_SET( ch->act, PLR_BATTLE ) && !IS_NPC( victim ) && !IS_SET( victim->act, PLR_BATTLE ) ) return; /*A little further down we need to change the check for immortals so that it looks like this */ if ( !IS_NPC( victim ) && victim->level >= LEVEL_IMMORTAL add this--->&& !IS_SET( ch->act, PLR_BATTLE ) && victim->hit < 1 ) victim->hit = 1; /* In damage() we need to add this in case POS_DEAD */ if ( !IS_NPC( victim ) && IS_SET( victim->act, PLR_BATTLE ) ) { sprintf( buf, "{o{m %s{r has been slain by{w %s!{x\n\r",victim->name, ( IS_NPC( ch ) ? ch->short_descr : ch->name ) ); talk_battle( buf ); break; } /* * Make sure to add && !IS_SET( victim->act, PLR_BATTLE ) * to the if statement just before the call to gain_exp () * */ /* In is_safe() add this */ if ( !IS_NPC( victim ) && IS_SET( victim->act, PLR_BATTLE ) ) return FALSE; /*change the statment just after to look like this */ if ( !IS_NPC( victim ) && !IS_NPC( ch ) && victim != ch && !IS_SET( victim->act, PLR_BATTLE ) && !IS_SET( ch->act, PLR_BATTLE ) ) return TRUE; /* Also be sure to add a check for PLR_BATTLE in check_killer() */ /* * In raw_kill * change the call to make corpse to look like this */ if ( !IS_SET( victim->act, PLR_BATTLE ) ) make_corpse( victim ); /* Just before the call to extract_char in raw_kill add the following */ if (!IS_NPC( victim ) && IS_SET(victim->act, PLR_BATTLE) ) { ROOM_INDEX_DATA *location; int place; place = victim->pcdata->temple; location = get_room_index( place); REMOVE_BIT( victim->act, PLR_BATTLE ); do_recall(victim, ""); do_look(victim, "auto"); victim->position = POS_RESTING; victim->hit = victim->max_hit; victim->mana = victim->max_mana; victim->move = victim->max_move; return; } /* In group_gain add this right after the declarations */ if ( victim == ch || IS_SET(victim->act, PLR_BATTLE ) ) return; /* A little further down, after the check for in_arena( victim ) */ if( IS_SET( ch->act, PLR_BATTLE ) ) continue; /*In do_kill change the following if statement to look like this */ if ( !IS_NPC( victim ) ) { if ( !IS_SET( victim->act, PLR_KILLER ) && !IS_SET( victim->act, PLR_THIEF ) add this--->&& !IS_SET(ch->act, PLR_BATTLE) ) { send_to_char( "You can not kill another player.\n\r", ch ); return; } } else { if ( IS_AFFECTED( victim, AFF_CHARM ) && victim->master ) { send_to_char( "You must MURDER a charmed creature.\n\r", ch ); return; } /* In do_flee add an if check for PLR_BATTLE to prevent loss of exp */ /* In interp.c we need to add this to the command table */ /*In the immortal commands section add this:*/ { "battle", do_battle, POS_DEAD, 0, LOG_NORMAL, 1 }, { "bonus", do_bonus, POS_DEAD, L_ARC, LOG_NORMAL, 1 }, { "bopen", do_bopen, POS_DEAD, L_HER, LOG_NORMAL, 1 }, { "bclose", do_bclose, POS_DEAD, L_HER, LOG_NORMAL, 1 }, { "bstop", do_bstop, POS_DEAD, L_HER, LOG_NORMAL, 1 }, { "bchat", do_bchat, POS_DEAD, L_HER, LOG_NORMAL, 1 }, { "badd", do_badd, POS_DEAD, L_HER, LOG_NORMAL, 1 }, { "bremove", do_bremove, POS_DEAD, L_HER, LOG_NORMAL, 1 }, /* In update.c add this */ /*add this after weather_update*/ void battle_update ( void ) { CHAR_DATA * ch; CHAR_DATA * winner; ROOM_INDEX_DATA *location; int place; int count; char buf[MAX_STRING_LENGTH]; count = 0; if( battle->running == FALSE || battle->open == TRUE ) return; place = 3001; location = get_room_index( place ); for(ch = char_list; ch; ch = ch->next) { if(IS_SET( ch->act, PLR_BATTLE ) ) { ++count; winner = ch; } } if( count == 1 ) { sprintf( buf,"{o{w%s {rhas won the battle!{x\n\r",winner->name); talk_battle( buf ); winner->bwins++; REMOVE_BIT(winner->act, PLR_BATTLE); winner->hit = winner->max_hit; winner->mana = winner->max_mana; winner->move = winner->max_move; char_from_room( winner ); char_to_room( winner, location ); do_look( winner, "auto" ); battle->running = FALSE; } battle->running = TRUE; return; } /* Add this right after the call to violence_update() */ if ( battle->running == TRUE && battle->open == FALSE ) battle_update ( ); /* And lastly we need to set up the channels in act_comm.c */ /* In the first part of chanoff add this */ SET_BIT( ch->deaf, CHANNEL_BATTLE ); /* Add this to do_quit */ if( IS_SET( ch->act, PLR_BATTLE ) ) { send_to_char( "But your in a battle!", ch ); return; } /*In act_comm.c we need to set up a channel for battle */ void talk_battle (char *argument) { DESCRIPTOR_DATA *d; char buf[MAX_STRING_LENGTH]; CHAR_DATA *original; sprintf (buf,"{o{rBATTLE: %s{x\n\r", argument); for (d = descriptor_list; d != NULL; d = d->next) { original = d->original ? d->original : d->character; /* if switched */ if ( (d->connected == CON_PLAYING) ) //act (buf, original , NULL, NULL, TO_CHAR); send_to_char( buf , original ); } } /*Now we need a way to let imms talk on it */ void do_bchat( CHAR_DATA *ch, char *argument ) { talk_battle( argument ); return; } /* * And that should be it. If you have any troubles implementing this code or * have any comments on it email me at theo@envy.com. */