/**************************************************************************** * ResortMUD 4.0 Beta by Ntanel, Garinan, Badastaz, Josh, Digifuzz, Senir, * * Kratas, Scion, Shogar and Tagith. Special thanks to Thoric, Nivek, * * Altrag, Arlorn, Justice, Samson, Dace, HyperEye and Yakkov. * **************************************************************************** * Copyright (C) 1996 - 2001 Haslage Net Electronics: MudWorld * * of Lorain, Ohio - ALL RIGHTS RESERVED * * The text and pictures of this publication, or any part thereof, may not * * be reproduced or transmitted in any form or by any means, electronic or * * mechanical, includes photocopying, recording, storage in a information * * retrieval system, or otherwise, without the prior written or e-mail * * consent from the publisher. * **************************************************************************** * GREETING must mention ResortMUD programmers and the help file named * * CREDITS must remain completely intact as listed in the SMAUG license. * ****************************************************************************/ /* * ResortMUD Arena Code * Author: Scion (Scion@usa.net) * * Permission to use and distribute this code is granted provided * this header is retained and unaltered, and the distribution * package contains all the original files unmodified. * If you modify this code and use/distribute modified versions * you must give credit to the original author(s). */ #include <sys/stat.h> #include <unistd.h> #include <stdio.h> #include "mud.h" void arena_add( int number, bool money ); int arena_death( CHAR_DATA * ch, CHAR_DATA * victim ); void arena_update( void ); /* called by comm.c */ extern void save_sysdata args( ( SYSTEM_DATA sys ) ); /* act_wiz.c in ShogTag */ const int MAX_ARENA_FEE = 3000000; /* Set this to something reasonable */ const int ARENA_DEFAULT_PRIZE = 10000; int arena_players = 0; /* This keeps track of the number of players left in the arena */ int arena_total_players = 0; int arena_prize; /* This is always 500 coins, set it to be balanced on your MUD */ int arena_fee = 0; /* This is the entrance fee to get in, which can be set with arena start */ int low_level = 0; /* Lowest level allowed in arena */ int hi_level = 0; /* Highest level allowes in arena */ int arena_update_mode = 0; /* Update is called once per minute, but we don't want to do something * every minute. */ void do_arena( CHAR_DATA * ch, char *argument ) { char cmd[MAX_INPUT_LENGTH]; char cmd2[MAX_INPUT_LENGTH]; char cmd3[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; CHAR_DATA *victim; AREA_DATA *arena; int hi_vnum = 0; int lo_vnum = 0; int real_vnum; int i; argument = one_argument( argument, cmd ); set_char_color( AT_IMMORT, ch ); if( IS_IMMORTAL( ch ) ) { if( !str_cmp( cmd, "start" ) ) { if( sysdata.arena >= 1 ) { send_to_char( "There is already a battle in the arena!\r\n", ch ); return; } argument = one_argument( argument, cmd ); /* entrance fee */ argument = one_argument( argument, cmd2 ); /* low level */ argument = one_argument( argument, cmd3 ); /* high level */ arena_prize = ARENA_DEFAULT_PRIZE; if( cmd[0] == '\0' ) arena_fee = 0; else arena_fee = atoi( cmd ); if( arena_fee < 0 ) /* Free matches are, of course, allowed and encouraged! */ arena_fee = 0; if( arena_fee >= MAX_ARENA_FEE ) arena_fee = MAX_ARENA_FEE; if( cmd2[0] == '\0' ) low_level = -1; /* Ignore level settings if not specified */ else { low_level = atoi( cmd2 ); if( low_level > MAX_LEVEL ) low_level = MAX_LEVEL; if( low_level <= 0 ) low_level = -1; } if( cmd3[0] == '\0' ) hi_level = -1; /* Ignore level settings if not specified */ else { hi_level = atoi( cmd3 ); if( hi_level > MAX_LEVEL ) hi_level = MAX_LEVEL; if( hi_level <= 0 ) hi_level = -1; } if( hi_level < low_level ) { /* If they're backward, reverse them */ i = hi_level; hi_level = low_level; low_level = i; } sysdata.arena = 2; save_sysdata( sysdata ); arena_players = 0; arena_total_players = 0; /* * Display the appropriate start messages */ if( hi_level > 0 && low_level == -1 ) sprintf( buf, "%s has ^zOPENED^x the arena with a MAX level of %d!", ch->name, hi_level ); else if( low_level > 0 && hi_level == -1 ) sprintf( buf, "%s has ^zOPENED^x the arena with a MIN level of %d!", ch->name, low_level ); else if( low_level == -1 && hi_level == -1 ) sprintf( buf, "%s has ^zOPENED^x the arena!", ch->name ); else sprintf( buf, "%s has ^zOPENED^x the arena for levels %d through %d!", ch->name, low_level, hi_level ); do_info( ch, buf ); if( arena_fee ) { sprintf( buf, "The entrance fee is %d coins!", arena_fee ); do_info( ch, buf ); } do_info( ch, "Type \'arena join\' to join!" ); set_char_color( AT_IMMORT, ch ); send_to_char( "Ready.\r\n", ch ); return; } else if( !str_cmp( cmd, "end" ) ) { if( sysdata.arena == 0 ) { send_to_char( "There is not currently an arena battle to end.\r\n", ch ); return; } sprintf( buf, "%s has canceled the arena match!", ch->name ); do_info( ch, buf ); do_info( ch, "The arena is ^zCLOSED^x." ); for( victim = first_char; victim; victim = victim->next ) { if( IS_NPC( victim ) ) continue; if( victim->arena != 2 ) continue; /* * remove recent fight timer */ if( get_timer( victim, TIMER_RECENTFIGHT ) ) remove_timer( victim, TIMER_RECENTFIGHT ); /* * make everyone STANDING (for all peace, etc) */ stop_fighting( victim, TRUE ); victim->position = POS_STANDING; if( arena_fee ) { send_to_char( "Your entrance fee has been returned to you.\r\n", victim ); victim->gold += arena_fee; } act( AT_MAGIC, "$n disappears in blinding flash of light.", victim, NULL, NULL, TO_ROOM ); char_from_room( victim ); char_to_room( victim, get_room_index( victim->retran ) ); act( AT_MAGIC, "$n arrives in a blinding flash of light.", victim, NULL, NULL, TO_ROOM ); do_look( victim, "auto" ); victim->arena = 0; } sysdata.arena = 0; save_sysdata( sysdata ); set_char_color( AT_IMMORT, ch ); send_to_char( "Done.\r\n", ch ); return; } else if( !str_cmp( cmd, "who" ) ) { send_to_char( "\r\nWho is in the arena:\r\n", ch ); for( victim = first_char; victim; victim = victim->next ) { if( IS_NPC( victim ) ) continue; if( victim->arena == 0 ) continue; switch ( victim->arena ) { case 2: sprintf( cmd, "Fighting" ); break; case 3: sprintf( cmd, "Defeated" ); break; case 4: sprintf( cmd, "Spectator" ); break; default: sprintf( cmd, "Unknown" ); break; } sprintf( buf, "%15s: %s\r\n", victim->name, cmd ); send_to_char( buf, ch ); } return; } } /* if IS_IMMORTAL(ch) */ if( ( !IS_IMMORTAL( ch ) ) || ( sysdata.imm_arena == TRUE ) ) { /******* JOIN *******/ if( !str_cmp( cmd, "join" ) ) { if( ch->arena == 2 ) { send_to_char( "You are already in the arena!\r\n", ch ); return; } if( sysdata.arena == 0 ) { send_to_char( "The arena is currently closed. Ask an immortal to open it!\r\n", ch ); return; } if( ( ch->gold < arena_fee ) && !IS_IMMORTAL( ch ) ) { sprintf( buf, "You do not have the %d coins to join this arena match!\r\n", arena_fee ); send_to_char( buf, ch ); return; } if( ch->arena == 3 ) { send_to_char( "You were already defeated in this round!\r\n", ch ); return; } if( ch->arena == 4 ) { send_to_char( "You are watching a player in this round, you cannot participate.\r\n", ch ); return; } if( ch->level < low_level && low_level != -1 ) { send_to_char( "You are not of a high enough level to compete in this match!\r\n", ch ); return; } if( ch->level > hi_level && hi_level != -1 ) { send_to_char( "Leave those low level players to bicker amongst themselves.\r\n", ch ); return; } if( ch->fighting ) { send_to_char( "You had better stop fighting before entering the arena!\r\n", ch ); return; } /* * Put them in a random room inside arena.are */ for( arena = first_area; arena; arena = arena->next ) { if( !str_cmp( arena->filename, "arena.are" ) ) { lo_vnum = arena->low_r_vnum; hi_vnum = arena->hi_r_vnum; break; } else { lo_vnum = 2; hi_vnum = 2; } } if( ( lo_vnum == 2 ) && ( hi_vnum == 2 ) ) { bug( "Could not find arena.are!", 0 ); send_to_char ( "An error ocurred while moving you to the arena.\r\nThe administrators have been notified of the error.\r\n", ch ); return; } i = 0; while( !get_room_index( real_vnum = number_range( lo_vnum, hi_vnum ) ) ) { if( i++ >= 50 ) { bug( "Cannot find a room in the arena for %s!", ch->name ); send_to_char ( "An error ocurred while moving you to the arena.\r\nThe administrators have been notified of the error.\r\n", ch ); return; } } stop_fighting( ch, TRUE ); ch->position = POS_STANDING; act( AT_MAGIC, "$n disappears in a blinding flash of light.", ch, NULL, NULL, TO_ROOM ); ch->retran = ch->in_room->vnum; char_from_room( ch ); char_to_room( ch, get_room_index( real_vnum ) ); /* * Take their money and put it in the pot */ if( arena_fee ) { if( IS_IMMORTAL( ch ) ) { sprintf( buf, "Bill Gates donates %d coins for %s\'s entrance fee!", arena_fee, ch->name ); do_info( ch, buf ); } else ch->gold -= arena_fee; arena_prize += arena_fee; } act( AT_MAGIC, "$n arrives in a blinding flash of light.", ch, NULL, NULL, TO_ROOM ); do_look( ch, "auto" ); send_to_char( "You have entered the arena!\r\n", ch ); sprintf( buf, "%s has joined the arena match!", ch->name ); do_info( ch, buf ); ch->arena = 2; arena_add( 1, FALSE ); return; } /******** WIMPOUT ********/ else if( !str_cmp( cmd, "wimpout" ) ) { if( ch->arena != 2 ) { send_to_char( "You are not in the arena!\r\n", ch ); return; } if( ch->fighting ) { send_to_char( "You had better stop fighting before you do that!\r\n", ch ); return; } if( arena_fee > 0 ) send_to_char( "By wimping out, you forfeit your entrance fee!\r\n", ch ); stop_fighting( ch, TRUE ); ch->position = POS_STANDING; act( AT_MAGIC, "$n disappears in a blinding flash of light.", ch, NULL, NULL, TO_ROOM ); char_from_room( ch ); char_to_room( ch, get_room_index( ch->retran ) ); act( AT_MAGIC, "$n arrives in a blinding flash of light.", ch, NULL, NULL, TO_ROOM ); do_look( ch, "auto" ); sprintf( buf, "%s has wimped out of the arena match!", ch->name ); do_info( ch, buf ); ch->arena = 0; arena_add( -1, FALSE ); return; } /****** NO VALID COMMAND ******/ else { /* * If we got no valid arguments */ send_to_char( "Syntax:\r\n", ch ); if( !IS_IMMORTAL( ch ) || ( sysdata.imm_arena == TRUE ) ) { if( sysdata.arena > 0 ) send_to_char( "arena join\r\n", ch ); if( ch->arena == 2 ) send_to_char( "arena wimpout\r\n", ch ); } if( IS_IMMORTAL( ch ) ) { if( sysdata.arena == 0 ) { send_to_char( "\r\narena start [fee] [low] [high]\r\n", ch ); } if( sysdata.arena > 0 ) send_to_char( "arena end\r\n", ch ); send_to_char( "arena who\r\n", ch ); } switch ( sysdata.arena ) { case 0: send_to_char( "\r\nThe arena is closed.\r\n", ch ); break; case 2: sprintf( buf, "\r\nThere are %d combatants in the arena.\r\n", arena_players ); send_to_char( buf, ch ); break; } /* switch */ } /* else */ } /* if !IS_IMMORTAL(ch) */ } /* function */ void arena_update( void ) { char buf[MAX_STRING_LENGTH]; switch ( sysdata.arena ) { case 0: /* arena is off */ arena_update_mode = 0; return; break; case 2: /* arena is in free for all mode */ if( arena_fee > 0 ) sprintf( buf, "Now in the arena: levels %d to %d, entry fee only %d coins!", ( ( low_level > 0 ) ? low_level : 1 ), ( ( hi_level > 0 ) ? hi_level : MAX_LEVEL ), arena_fee ); else sprintf( buf, "Now in the arena: Free for All, levels %d to %d!", ( ( low_level > 0 ) ? low_level : 1 ), ( ( hi_level > 0 ) ? hi_level : MAX_LEVEL ) ); do_info( first_char, buf ); break; default: sysdata.arena = 0; bug( "Default case reached in arena_update!", 0 ); break; } } void arena_add( int number, bool money ) { /* * This adds "number" players to arena_players and checks win conditions. */ char buf[MAX_STRING_LENGTH]; CHAR_DATA *ch; arena_players += number; if( arena_players > arena_total_players ) arena_total_players = arena_players; if( ( sysdata.arena == 2 ) && ( arena_players <= 1 ) && ( number <= 0 ) ) { /* someone won */ for( ch = first_char; ch; ch = ch->next ) { /* if number is positive, we've just added */ if( IS_NPC( ch ) ) /* a player. How could they have just won? */ continue; switch ( ch->arena ) { case 0: /* Character's not in, and hasn't been in the arena */ continue; break; case 2: /* Character has won, being the last one left alive in arena */ if( money == TRUE ) { sprintf( buf, "%s has ^zWON^x the arena match, and ^z%d^x coins!", ch->name, arena_prize ); do_info( ch, buf ); ch->gold += arena_prize; ch->arena_wins++; adjust_hiscore( "arena_pkill", ch, ch->arena_wins ); } else do_info( ch, "The arena match has been closed without a winner." ); stop_fighting( ch, TRUE ); ch->position = POS_STANDING; act( AT_MAGIC, "$n disappears in a golden beam of light.", ch, NULL, NULL, TO_ROOM ); ch->hit = ch->max_hit; ch->mana = ch->max_mana; ch->move = ch->max_move; ch->pcdata->condition[COND_BLOODTHIRST] = ( 10 + ch->level ); update_pos( ch ); send_to_char( "You have been fully restored!\r\n", ch ); char_from_room( ch ); char_to_room( ch, get_room_index( ch->retran ) ); act( AT_MAGIC, "$n appears in a golden beam of light.", ch, NULL, NULL, TO_ROOM ); do_look( ch, "auto" ); ch->arena = 0; break; case 3: /* Character died in arena */ ch->arena = 0; break; case 4: /* Character is watching a participant */ ch->arena = 0; break; } } arena_prize = ARENA_DEFAULT_PRIZE; sysdata.arena = 0; save_sysdata( sysdata ); arena_players = 0; } } int arena_death( CHAR_DATA * ch, CHAR_DATA * victim ) { char buf[MAX_STRING_LENGTH]; /* * If they were in the arena, override death! */ if( victim->arena == 2 ) { act( AT_DEAD, "$n has been DEFEATED!!", victim, 0, 0, TO_ROOM ); act( AT_DEAD, "You have been DEFEATED!", victim, 0, 0, TO_CHAR ); sprintf( buf, "%s has been defeated by %s in the arena!", victim->name, ch->name ); do_info( victim, buf ); sprintf( buf, "%s (%d) killed by %s in arena at %d", victim->name, victim->level, ( IS_NPC( ch ) ? ch->short_descr : ch->name ), victim->in_room->vnum ); log_string( buf ); to_channel( buf, CHANNEL_MONITOR, "Monitor", LEVEL_IMMORTAL ); ch->arena_kills++; victim->arena_deaths++; /* * Now that that fiasco is over, retran and restore the victim */ stop_fighting( victim, TRUE ); victim->position = POS_STANDING; act( AT_MAGIC, "$n disappears in a beam of holy light.", victim, NULL, NULL, TO_ROOM ); victim->hit = victim->max_hit; victim->mana = victim->max_mana; victim->move = victim->max_move; victim->pcdata->condition[COND_BLOODTHIRST] = ( 10 + victim->level ); update_pos( victim ); send_to_char( "You have been fully restored!\r\n", victim ); char_from_room( victim ); char_to_room( victim, get_room_index( victim->retran ) ); act( AT_MAGIC, "$n falls delicately out of the sky.", victim, NULL, NULL, TO_ROOM ); do_look( victim, "auto" ); victim->arena = 3; /* 0==no arena, 1==betting, 2==fighting, 3==dead, 4==watching */ arena_add( -1, TRUE ); /* Reduce the player count by one */ return 0; } return 1; }