/************************************************************************ Realms of Aurealis James Rhone aka Vall of RoA arena.c Arena code. Player killing in settable zones/areas without penalty. Other various minor games for players besides just PK. ******** 100% completely original code ******** *** BE AWARE OF ALL RIGHTS AND RESERVATIONS *** ******** 100% completely original code ******** All rights reserved henceforth. Please note that no guarantees are associated with any code from Realms of Aurealis. All code which has been released to the general public has been done so with an 'as is' pretense. RoA is based on both Diku and CircleMUD and ALL licenses from both *MUST* be adhered to as well as the RoA license. *** Read, Learn, Understand, Improve *** *************************************************************************/ #include "conf.h" #include "sysdep.h" #include "structures.h" #include "utils.h" #include "comm.h" #include "interpreter.h" #include "acmd.h" #include "handler.h" #include "db.h" #include "mudlimits.h" #include "fight.h" #include "lists.h" #include "global.h" /* external vars */ extern struct arena_data arena_info; // external functions extern void send_to_arena(char *messg); /* ARENA setting of ANY zone by a certain level of immortal sets zone flag ARENA or checks on current ARENA zones Another RoA innovation... James Rhone */ void default_arena(void) { arena_info.in_progress = FALSE; arena_info.locked = TRUE; arena_info.maxlevel = 70; arena_info.minlevel = 1; arena_info.official = FALSE; arena_info.ticks_to_start = -1; arena_info.ticks_since_kill = -1; arena_info.mortal_initiated = FALSE; } /* check to see if any arena participants left */ /* if award, then last participant is victor */ int check_arena_state(BOOL award) { chdata *player, *winner = NULL; dsdata *pt; int count; for (player = character_list, count = 0; player; player = player->next) if (IS_PC(player) && IN_ARENA(player)) { winner = player; count++; } if (award && count == 1 && winner) { sprintf(buf, "%%B%%5%s is the final ARENA combatant!%%0",GET_NAME(winner)); for (pt = descriptor_list; pt; pt = pt->next) if (D_CHECK(pt) && pt->character != winner && SEND_OK(pt->character) && !PRF2_FLAGGED(pt->character, PRF2_NOARENA)) act(buf, FALSE, pt->character, 0, 0, TO_CHAR); GET_MANA(winner) = GET_MAX_MANA(winner); GET_HIT(winner) = GET_MAX_HIT(winner); GET_MOVE(winner) = GET_MAX_MOVE(winner); if (FIGHTING(winner)) stop_fighting(winner); GET_POS(winner) = POS_STANDING; char_from_room(winner); char_to_room(winner, real_room(GET_LOADROOM(winner))); do_look_at_room(winner, 0, 0); send_to_char("You have won the ARENA!!\n\r",winner); if (arena_info.official) winner->pc_specials->saved.arena_wins++; REMOVE_BIT(PRF_FLAGS(winner), PRF_AREN_CH); REMOVE_BIT(PLR_FLAGS(winner), PLR_ARENA); default_arena(); return 0; } else if (award && !count) { default_arena(); mudlog("Arena cancelled, no combatants.", NRM, LEV_IMM, FALSE); return 0; } return count; } // remove an arena player, also let us know if last one is winner void remove_arena_player(chdata *vict, BOOL award) { if (IN_ARENA(vict)) { char_from_room(vict); if (vict->pc_specials->preroom > 0 && vict->pc_specials->preroom < top_of_world) char_to_room(vict, vict->pc_specials->preroom); else char_to_room(vict, real_room(GET_LOADROOM(vict))); do_look_at_room(vict, 0, 0); // restore old hit/move/mana only if they were less than now GET_HIT(vict) = vict->pc_specials->prehit; GET_MANA(vict) = vict->pc_specials->premana; GET_MOVE(vict) = vict->pc_specials->premove; vict->pc_specials->prehit = 1; vict->pc_specials->premana = 1; vict->pc_specials->premove = 1; update_pos(vict); act("You have been removed from the %BArena%0.", FALSE, vict, 0, 0,TO_CHAR); REMOVE_BIT(PLR_FLAGS(vict), PLR_ARENA); REMOVE_BIT(PRF_FLAGS(vict), PRF_AREN_CH); check_arena_state(award); } } // add somebody to the arena void add_arena_player(chdata *vict) { int i; BOOL found; for (i = 0, found = FALSE; i < top_of_world; i++) if (ZONE_FLAGGED(world[i].zone, Z_ARENA) && world[i].max_contains != 0 && !world[i].people && !ROOM_FLAGGED(i, FLY_DEATH) && !ROOM_FLAGGED(i, DEATH) && !ROOM_FLAGGED(i, GODROOM) && !ROOM_FLAGGED(i, PRIVATE) && world[i].terrain_type != TERRAIN_AIR && world[i].terrain_type != TERRAIN_UWATER) { found = TRUE; act("A %B%6streaming%0 array of %Blight%0 encompasses $n and $e disappears.", TRUE, vict,0,0,TO_ROOM); vict->pc_specials->preroom = vict->in_room; vict->pc_specials->prehit = GET_HIT(vict); vict->pc_specials->premana = GET_MANA(vict); vict->pc_specials->premove = GET_MOVE(vict); char_from_room(vict); char_to_room(vict, i); do_look_at_room(vict, 0, 0); break; } if (found) { SET_BIT(PRF_FLAGS(vict), PRF_AREN_CH); SET_BIT(PLR_FLAGS(vict), PLR_ARENA); strcpy(buf,"You are now entered in an ARENA contest!\n\r"); strcat(buf,"Always remember to keep an eye over your shoulder,\n\r"); strcat(buf,"because at ANY time another ARENA combatant may choose you as\n\r"); strcat(buf,"their next target. Be wary...and Enjoy.\n\r"); act(buf, FALSE, vict, 0, 0, TO_CHAR); } else send_to_char("A powerful force interfered with your attempt. Try Again.\n\r",vict); } // called once per tick from comm.c, checks mortally ran arenas // updates ticks_to_start, etc etc -roa void do_arena_update(void) { chdata *ch; int count; // first, take care of arena if its mortally ran if (arena_info.in_progress && arena_info.mortal_initiated) { // combat hasnt started yet if (!arena_info.locked) { arena_info.ticks_to_start--; sprintf(buf, "The arena begins in %%B%%6%d%%0 hour%s.\n\r", arena_info.ticks_to_start, (arena_info.ticks_to_start > 1) ? "s" : ""); if (arena_info.ticks_to_start > 0) // still have to wait { send_to_arena(buf); return; } else // start it, only if combatants > 1 { if ((count = check_arena_state(FALSE)) <= 1) { default_arena(); send_to_arena("%B%4Arena cancelled, not enough participants%0.\n\r"); for (ch = character_list; ch; ch=ch->next) if (IN_ARENA(ch)) remove_arena_player(ch, FALSE); return; } else arena_info.official = (count >= minforarenawin); send_to_arena("%B%6Arena combatants... BEGIN!%0\n\r"); arena_info.mortal_initiated = TRUE; arena_info.locked = TRUE; arena_info.ticks_since_kill = 0; } // end of start it } // end of !locked else // bump up ticks since last kill by 1, check for too idle { arena_info.ticks_since_kill++; if (arena_info.ticks_since_kill >= 15) // wax the arena { default_arena(); send_to_arena("%B%4Arena cancelled, kill time limit reached%0.\n\r"); for (ch = character_list; ch; ch=ch->next) if (IN_ARENA(ch)) remove_arena_player(ch, FALSE); return; } } } // end if in_progress and mortal_initiated } // just an arena channel toggle ACMD(do_arena_flag) { TOGGLE_BIT(PRF2_FLAGS(ch), PRF2_NOARENA); if (!PRF2_FLAGGED(ch, PRF2_NOARENA)) send_to_char("You will now hear arena messages.\n\r",ch); else send_to_char("You will no longer hear arena messages.\n\r",ch); } /* lets a player join an arena if arena is running and not in hold state */ ACMD(do_arjoin) { if (IS_NPC(ch)) return; if (!arena_info.in_progress) { send_to_char("There is no Arena in progress. Ask a God+ to set one up.\n\r",ch); return; } if (GET_LEVEL(ch) < arena_info.minlevel || GET_LEVEL(ch) > arena_info.maxlevel) { sprintf(buf, "You must be between levels %d and %d to join.\n\r", arena_info.minlevel, arena_info.maxlevel); S2C(); return; } if (arena_info.locked) { send_to_char("You cannot join the Arena right now.\n\r",ch); return; } if (IN_ARENA(ch)) { send_to_char("You are already in the Arena.\n\r",ch); return; } if (ROOM_FLAGGED(ch->in_room, NO_RECALL) || ROOM_FLAGGED(ch->in_room, NO_TELEPORT)) { send_to_char("Forces beyond your comprehension prevent you from joining.\n\r",ch); return; } add_arena_player(ch); } /* give em a channel */ ACMD(do_arena_say) { dsdata *d; char *argu = argument; if (IS_NPC(ch)) return; if (!IN_ARENA(ch) && !IS_IMMORTAL(ch)) { send_to_char("You are not in an arena contest!\n\r",ch); return; } if (!*argu) { send_to_char("What do you wish to arena-say??\n\r",ch); return; } skip_spaces(&argu); if (*argu == '+') { SET_BIT(PRF_FLAGS(ch), PRF_AREN_CH); send_to_char("You join the arena channel. ( - to turn off)\n\r",ch); return; } else if (*argu == '-') { REMOVE_BIT(PRF_FLAGS(ch), PRF_AREN_CH); send_to_char("You turn the arena channel off.\n\r",ch); return; } if (!PRF_FLAGGED(ch, PRF_AREN_CH)) { send_to_char("You are not on the arena channel! ( + to turn on)\n\r",ch); return; } if (*argu == '?') { sprintf(buf, "%%BArena combatants online and on channel%%0:\n\r"); for (d = descriptor_list; d; d = d->next) if (D_CHECK(d) && IS_PC(d->character) && IN_ARENA(d->character) && PRF_FLAGGED(d->character, PRF_AREN_CH) && GET_LEVEL(ch) >= GET_INVIS_LEV(d->character)) { sprintf(buf2, " %s\n\r",GET_NAME(d->character)); strcat(buf, buf2); } page_string(ch->desc, buf, 1); return; } sprintf(buf, "You arena-say '%s'\n\r",argu); S2C(); for (d = descriptor_list; d; d = d->next) if (D_CHECK(d) && d != ch->desc && IS_PC(d->character) && IN_ARENA(d->character) && SEND_OK(d->character) && PRF_FLAGGED(d->character, PRF_AREN_CH)) { sprintf(buf, "[%%6Arena%%0] %s: %s\n\r",GET_NAME(ch),argu); send_to_char(buf, d->character); } } /* various command for morts and immorts to view and set up arena stats */ ACMD(do_arwho) { int level, count; chdata *player; dsdata *pt; char *argu = argument; if (IS_NPC(ch)) return; if (strlen(argument) > MAX_CLAN_LENGTH) return; skip_spaces(&argu); if (!*argu) { sprintf(buf, "Current %%BArena%%0 statistics:\n\r"); S2C(); sprintf(buf, " Arena in progress? %s\n\r", (arena_info.in_progress)?"Yes":"No."); S2C(); if (!arena_info.in_progress && !IS_IMMORTAL(ch)) return; sprintf(buf, " Levels %d - %d.\n\r",arena_info.minlevel, arena_info.maxlevel); S2C(); sprintf(buf,"\n\r%%BCurrent Arena combatants%%0:\n\r"); for (count = 0,player = character_list; player; player = player->next) if (IS_PC(player) && IN_ARENA(player)) { sprintf(buf, "%s %10.10s (%%5Arena Victories%%0: %d)\n\r", buf, GET_NAME(player), player->pc_specials->saved.arena_wins); count++; } if (count) { sprintf(buf+strlen(buf), "\n\r%%6%d%%0 combatants.\n\r",count); page_string(ch->desc, buf, 1); } else send_to_char("There are currently no Arena combatants.\n\r",ch); if (!IN_ARENA(ch) && GET_LEVEL(ch) >= arena_info.minlevel && GET_LEVEL(ch) <= arena_info.maxlevel && arena_info.in_progress && !arena_info.locked) send_to_char("You qualify for this Arena, type %Barjoin%0 to enter!\n\r",ch); return; } if (!IS_IMMORTAL(ch) && !str_cmp(argu, "init")) { if (arena_info.in_progress) { send_to_char("There is already an arena in progress.\n\r",ch); return; } // no no no... if (ROOM_FLAGGED(ch->in_room, NO_RECALL) || ROOM_FLAGGED(ch->in_room, NO_TELEPORT)) { send_to_char("Forces beyond your comprehension prevent you from joining.\n\r",ch); return; } arena_info.mortal_initiated = TRUE; arena_info.ticks_to_start = 3; arena_info.ticks_since_kill = 0; arena_info.in_progress = TRUE; arena_info.locked = FALSE; sprintf(buf, "An %%BArena%%0 has been initiated.\n\r%%6Levels %d - %d.\n\r", arena_info.minlevel,arena_info.maxlevel); strcat(buf, "Type: %Barjoin%0 to join the arena."); for (pt = descriptor_list; pt; pt = pt->next) if (D_CHECK(pt) && SEND_OK(pt->character) && !PRF2_FLAGGED(pt->character, PRF2_NOARENA)) act(buf, FALSE, pt->character, 0, 0, TO_CHAR); // make initters join on init now do_arjoin(ch, "", 0, 0); return; } if (GET_LEVEL(ch) < LEV_GOD) { send_to_char("Only God+ may use this command to set arena states.\n\r",ch); return; } half_chop(argu, arg, buf1); if (!str_cmp(arg, "init")) { if (arena_info.in_progress) { send_to_char("There is an arena in progress already.\n\r",ch); return; } arena_info.official = TRUE; arena_info.mortal_initiated = FALSE; arena_info.in_progress = TRUE; arena_info.locked = FALSE; sprintf(buf, "An %%BArena%%0 has been initiated.\n\r%%6Levels %d - %d.\n\r", arena_info.minlevel,arena_info.maxlevel); strcat(buf, "Type: %Barjoin%0 to join the arena."); for (pt = descriptor_list; pt; pt = pt->next) if (D_CHECK(pt) && SEND_OK(pt->character) && !PRF2_FLAGGED(pt->character, PRF2_NOARENA)) act(buf, FALSE, pt->character, 0, 0, TO_CHAR); return; } else if (!str_cmp(arg, "finish")) { if (!arena_info.in_progress) { send_to_char("What arena?\n\r",ch); return; } if (check_arena_state(FALSE) > 0) { send_to_char("The arena has combatants in it. Remove them first.\n\r",ch); return; } arena_info.official = FALSE; arena_info.in_progress = FALSE; arena_info.locked = TRUE; send_to_char("Ok. Arena has been cancelled.\n\r",ch); return; } else if (!str_cmp(arg, "max")) { if (!is_number(buf1)) { send_to_char("Usage: arwho < init || < max <num> || min <num>>>.\n\r",ch); return; } level = atoi(buf1); if (level < arena_info.minlevel || level >= LEV_IMM) { sprintf(buf, "Valid max levels are %d - %d.\n\r",arena_info.minlevel, LEV_IMM-1); S2C(); return; } sprintf(buf, "Arena max level set to: %%B%d%%0.\n\r",level); S2C(); arena_info.maxlevel = level; return; } else if (!str_cmp(arg, "min")) { if (!is_number(buf1)) { send_to_char("Usage: arwho < init || < max <num> || min <num>>>.\n\r",ch); return; } level = atoi(buf1); if (level > arena_info.maxlevel || level < 1) { sprintf(buf, "Valid min levels are 1 - %d.\n\r",arena_info.maxlevel); S2C(); return; } sprintf(buf, "Arena min level set to: %%B%d%%0.\n\r",level); S2C(); arena_info.minlevel = level; return; } else if (!str_cmp(arg, "lock")) { if (arena_info.locked) { send_to_char("Arena already locked.\n\r",ch); return; } if (check_arena_state(FALSE) < 2) { send_to_char("The arena needs more combatants.\n\r",ch); return; } arena_info.locked = TRUE; send_to_char("The arena is now locked.\n\r",ch); return; } else if (!str_cmp(arg, "unlock")) { if (!arena_info.locked) { send_to_char("Arena already unlocked.\n\r",ch); return; } arena_info.locked = FALSE; send_to_char("The arena is now unlocked.\n\r",ch); return; } else if (IS_IMMORTAL(ch)) send_to_char("Usage: arwho < init || < max <num> || min <num>> || lock || unlock >.\n\r",ch); } ACMD(do_zarena) { char zstr[MAX_INPUT_LENGTH]; int zone; chdata *player; int count = 0; extern int is_empty(int zone); if (IS_NPC(ch)) return; if (strlen(argument) > MAX_CLAN_LENGTH) return; if (!*argument || !IS_IMMORTAL(ch)) { if (IS_IMMORTAL(ch)) { send_to_char("Current zones flagged ARENA:\n\r",ch); for(zone = 1; zone < NUM_ZONES; zone++) if(REAL_ZONE(zone) && ZONE_FLAGGED(zone, Z_ARENA)) { sprintf(buf,"(%d) %s\n\r", zone_table[zone].number, zone_table[zone].name); S2C(); } } sprintf(buf,"\n\r%%BCurrent Arena combatants%%0:\n\r"); for (player = character_list; player; player = player->next) if (IS_PC(player) && IN_ARENA(player)) { sprintf(buf, "%s %10.10s (%%5Arena Victories%%0: %d)\n\r", buf, GET_NAME(player), player->pc_specials->saved.arena_wins); count++; } if (count) page_string(ch->desc, buf, 1); else send_to_char("There are currently no Arena combatants.\n\r",ch); return; } half_chop(argument, zstr, buf); if (!is_number(zstr)) { send_to_char("Usage: Zarena <zone_num> < 'on' || 'off' >.\n\r",ch); return; } zone = atoi(zstr); if (!REAL_ZONE(zone) || ZONE_FLAGGED(zone, Z_CLOSED)) { send_to_char("Zone doesn't exist or it's closed.\n\r",ch); return; } if (str_cmp(buf, "on") && str_cmp(buf, "off")) { send_to_char("Usage: Zarena <zone_num> < 'on' || 'off' >.\n\r",ch); return; } if (GET_LEVEL(ch) < LEV_GOD) { send_to_char("Only GOD+ may designate an Arena.\n\r",ch); return; } if (GET_LEVEL(ch) < LEV_IMPL) if (zone < ch->pc_specials->saved.olc_min_zone || zone > ch->pc_specials->saved.olc_max_zone) { send_to_char("You don't have privs to that zone.\n\r",ch); return; } if (!is_empty(zone)) { send_to_char("There are players in that zone.\n\r",ch); return; } if (!str_cmp(buf, "on")) { SET_BIT(ZONE_FLAGS(zone), Z_ARENA); send_to_char("Ok. That zone is now flagged ARENA.\n\r",ch); return; } else { REMOVE_BIT(ZONE_FLAGS(zone), Z_ARENA); send_to_char("Ok. That zone is no longer flagged ARENA.\n\r",ch); return; } } /* following code is for TAG games jtrhone RoA */ ACMD(do_tag) { chdata *plr; BOOL found = FALSE; char *argu = argument; if (IS_NPC(ch)) return; skip_spaces(&argu); if (!*argu) { sprintf(buf, "The following players are playing %%BTAG%%0:\n\r"); for (plr = character_list; plr; plr = plr->next) if (IS_PC(plr) && PLR_FLAGGED(plr, PLR_INTAG)) { sprintf(buf+strlen(buf), "%-20.20s %s\n\r",GET_NAME(plr), PLR_FLAGGED(plr, PLR_TAGGED)?"%B%6IT%0":""); found = TRUE; } if (found) page_string(ch->desc, buf, TRUE); else send_to_char("There is nobody playing tag right now.\n\r",ch); return; } else if (!str_cmp(argu, "join")) { if (PLR_FLAGGED(ch, PLR_INTAG)) { send_to_char("You are already in the tag game!\n\r",ch); return; } /* if no people playin, first joiner is IT :) */ for (plr = character_list; plr; plr = plr->next) if (PLR_FLAGGED(plr, PLR_INTAG)) { found = TRUE; break; } if (!found) { send_to_char("You %Bstart%0 a %B%6TAG%0 game!! You are %BIT%0!!!\n\r",ch); SET_BIT(PLR_FLAGS(ch), PLR_TAGGED); } else send_to_char("Ok. You join the %B%6TAG%0 game!!\n\r",ch); SET_BIT(PLR_FLAGS(ch), PLR_INTAG); return; } else if (!str_cmp(argu, "quit")) { if (!PLR_FLAGGED(ch, PLR_INTAG)) { send_to_char("You aren't playing tag anyways.\n\r",ch); return; } else if (PLR_FLAGGED(ch, PLR_TAGGED)) { send_to_char("You are %B%6IT%0!! You can't quit!\n\r",ch); return; } else { send_to_char("Ok. You chicken out and quit the tag game.\n\r",ch); REMOVE_BIT(PLR_FLAGS(ch), PLR_INTAG); return; } } else if (!PLR_FLAGGED(ch, PLR_INTAG)) { send_to_char("You are not playing tag! (To join, type: %Btag join%0)\n\r",ch); return; } else if (!PLR_FLAGGED(ch, PLR_TAGGED)) { send_to_char("You are not it!\n\r",ch); return; } else if (!(plr = get_char_room_vis(ch, argu))) { send_to_char("Tag who?\n\r",ch); return; } /* now we have a victim, and we are playing */ if (plr == ch) { send_to_char("You some kinda wierdo? Alllllllll Riiiiigggghhhtttyyy theennn.\n\r",ch); return; } if (!PLR_FLAGGED(plr, PLR_INTAG)) { act("$N is not playing %B%6TAG%0!", FALSE, ch, 0, plr, TO_CHAR); return; } /* ok, all set lets tag the victim and untag the tagger */ REMOVE_BIT(PLR_FLAGS(ch), PLR_TAGGED); SET_BIT(PLR_FLAGS(plr), PLR_TAGGED); act("$n %B%6TAGS%0 $N... and $N is now %BIT%0!!",FALSE, ch, 0, plr, TO_ROOM); act("$n %B%6TAGS%0 you!!! You are %BIT%0!!", FALSE, ch, 0, plr, TO_VICT); act("You %B%6TAG%0 $N!!! You are not %BIT%0 anymore!!",FALSE, ch, 0, plr, TO_CHAR); } /* give em a channel */ ACMD(do_tag_say) { dsdata *d; char *argu = argument; if (IS_NPC(ch)) return; if (!PLR_FLAGGED(ch, PLR_INTAG)) { send_to_char("You are not playing tag!\n\r",ch); return; } if (!*argu) { send_to_char("What do you wish to tag-say??\n\r",ch); return; } skip_spaces(&argu); sprintf(buf, "You tag-say '%s'\n\r",argu); S2C(); for (d = descriptor_list; d; d = d->next) if (D_CHECK(d) && d != ch->desc && IS_PC(d->character) && SEND_OK(d->character) && PLR_FLAGGED(d->character, PLR_INTAG)) { sprintf(buf, "[%%6Tag%%0] %s: %s\n\r",GET_NAME(ch),argu); send_to_char(buf, d->character); } }