/*
*
* 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 <level 1> <level 2>.", 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.
*/