/* ************************************************************************ * File: interpreter.c EmpireMUD AD 1.0 * * Usage: parse user commands, search for specials, call ACMD functions * * * * All rights reserved. See license.doc for complete information. * * * * Code base by Paul Clarke. EmpireMUD Project, a tbgMUD Production. * * Based upon CircleMUD 3.0, beta patch level 17, by Jeremy Elson. * * * * Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University * * CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. * ************************************************************************ */ #include "conf.h" #include "sysdep.h" #include "structs.h" #include "comm.h" #include "interpreter.h" #include "db.h" #include "utils.h" #include "handler.h" #include "mail.h" #include "utils.h" #include "empire.h" #include "olc.h" #include "skills.h" extern struct player_index_element *player_table; extern int top_of_p_table; extern int max_bad_pws; /* external functions */ void echo_on(Descr d); void echo_off(Descr d); void do_start(Creature ch); int isbanned(char *hostname); int Valid_Name(char *newname); /* prototypes for all do_x functions, sorted by letter */ /* A Block */ ACMD(do_advance); ACMD(do_autowiz); ACMD(do_attach); ACMD(do_abandon); ACMD(do_authorize); ACMD(do_afk); ACMD(do_affects); ACMD(do_alias); ACMD(do_assist); ACMD(do_assemble); ACMD(do_at); /* B Block */ ACMD(do_board); ACMD(do_blow); ACMD(do_bathe); ACMD(do_boost); ACMD(do_bite); ACMD(do_balance); ACMD(do_bake); ACMD(do_build); ACMD(do_ban); ACMD(do_bash); /* C Block */ ACMD(do_chgleader); ACMD(do_chip); ACMD(do_catapult); ACMD(do_create); ACMD(do_cede); ACMD(do_confirm); ACMD(do_claim); ACMD(do_craft); ACMD(do_chop); ACMD(do_commands); ACMD(do_credits); /* D Block */ ACMD(do_date); ACMD(do_discipline); ACMD(do_draw); ACMD(do_disembark); ACMD(do_deposit); ACMD(do_douse); ACMD(do_designate); ACMD(do_defect); ACMD(do_demote); ACMD(do_dismantle); ACMD(do_dismount); ACMD(do_dig); ACMD(do_dc); ACMD(do_diagnose); ACMD(do_display); ACMD(do_drink); ACMD(do_drop); ACMD(do_diplomacy); /* E Block */ ACMD(do_eat); ACMD(do_extract); ACMD(do_experience); ACMD(do_excavate); ACMD(do_embrace); ACMD(do_execute); ACMD(do_esay); ACMD(do_edelete); ACMD(do_empires); ACMD(do_expell); ACMD(do_enroll); ACMD(do_echo); ACMD(do_equipment); ACMD(do_examine); ACMD(do_exit); ACMD(do_exits); /* F Block */ ACMD(do_flee); ACMD(do_feed); ACMD(do_file); ACMD(do_forge); ACMD(do_fire); ACMD(do_fullsave); ACMD(do_follow); ACMD(do_force); ACMD(do_form); ACMD(do_fish); /* G Block */ ACMD(do_gecho); ACMD(do_gather); ACMD(do_gen_door); ACMD(do_gen_ps); ACMD(do_gen_tog); ACMD(do_gen_write); ACMD(do_get); ACMD(do_give); ACMD(do_goto); ACMD(do_grab); /* H Block */ ACMD(do_help); ACMD(do_harness); ACMD(do_herd); ACMD(do_history); ACMD(do_harvest); ACMD(do_hide); ACMD(do_hit); /* I Block */ ACMD(do_info); ACMD(do_infiltrate); ACMD(do_insult); ACMD(do_inventory); ACMD(do_invis); /* K Block */ ACMD(do_kick); /* L Block */ ACMD(do_last); ACMD(do_light); ACMD(do_lead); ACMD(do_lay); ACMD(do_load); ACMD(do_load_boat); ACMD(do_look); /* M Block */ ACMD(do_move); ACMD(do_milk); ACMD(do_melt); ACMD(do_mill); ACMD(do_mold); ACMD(do_mine); ACMD(do_mount); ACMD(do_messages); ACMD(do_mail); ACMD(do_manufacture); /* O Block */ ACMD(do_olc); ACMD(do_offer); ACMD(do_order); /* P Block */ ACMD(do_page); ACMD(do_path); ACMD(do_play); ACMD(do_pick); ACMD(do_pan); ACMD(do_purgevnum); ACMD(do_purgeobjs); ACMD(do_party); ACMD(do_promote); ACMD(do_plant); ACMD(do_psay); ACMD(do_pledge); ACMD(do_purgemobs); ACMD(do_pub_comm); ACMD(do_prompt); ACMD(do_poofset); ACMD(do_pour); ACMD(do_purge); ACMD(do_put); ACMD(do_publicize); /* Q Block */ ACMD(do_quit); /* R Block */ ACMD(do_reload); ACMD(do_rise); ACMD(do_reward); ACMD(do_retrieve); ACMD(do_roster); ACMD(do_read); ACMD(do_respond); ACMD(do_random); ACMD(do_remove); ACMD(do_reply); ACMD(do_report); ACMD(do_rescue); ACMD(do_reboot); ACMD(do_rest); ACMD(do_restore); ACMD(do_return); /* S Block */ ACMD(do_save); ACMD(do_sap); ACMD(do_shift); ACMD(do_scrape); ACMD(do_stake); ACMD(do_speak); ACMD(do_slit); ACMD(do_seal); ACMD(do_search); ACMD(do_swap); ACMD(do_sheath); ACMD(do_shoot); ACMD(do_sail); ACMD(do_sacrifice); ACMD(do_sew); ACMD(do_slay); ACMD(do_spawn); ACMD(do_socials); ACMD(do_skin); ACMD(do_say); ACMD(do_score); ACMD(do_send); ACMD(do_set); ACMD(do_show); ACMD(do_sit); ACMD(do_sleep); ACMD(do_sneak); ACMD(do_snoop); ACMD(do_spec_comm); ACMD(do_split); ACMD(do_stand); ACMD(do_store); ACMD(do_struggle); ACMD(do_stat); ACMD(do_steal); ACMD(do_switch); /* T Block */ ACMD(do_teleport); ACMD(do_teach); ACMD(do_tie); ACMD(do_transport); ACMD(do_throw); ACMD(do_tedit); ACMD(do_tell); ACMD(do_time); ACMD(do_title); ACMD(do_track); ACMD(do_trans); /* U Block */ ACMD(do_unban); ACMD(do_unload_boat); ACMD(do_unpublicize); ACMD(do_upgrade); ACMD(do_unparty); ACMD(do_users); /* V Block */ ACMD(do_visible); ACMD(do_vc); ACMD(do_vcsay); ACMD(do_vampire_heal); ACMD(do_vnum); ACMD(do_vstat); /* W Block */ ACMD(do_wake); ACMD(do_withdraw); ACMD(do_wear); ACMD(do_weather); ACMD(do_where); ACMD(do_who); ACMD(do_whois); ACMD(do_wield); ACMD(do_wizlock); ACMD(do_wizutil); ACMD(do_write); /* This is the Master Command List(tm). * You can put new commands in, take commands out, change the order * they appear in, etc. You can adjust the "priority" of commands * simply by changing the order they appear in the command list. * (For example, if you want "as" to mean "assist" instead of "ask", * just put "assist" above "ask" in the Master Command List(tm). * * In general, utility commands such as "at" should have high priority; * infrequently used and dangerously destructive commands should have low * priority. */ cpp_extern const struct command_info cmd_info[] = { { "RESERVED", 0, 0, 0, 0, 0, 0 }, /* this must be first -- for specprocs */ /* directions come before other commands to preserve abbrevs */ { "north" , POS_STANDING , do_move , 0 , NORTH , CTYPE_MOVE , 0 }, { "east" , POS_STANDING , do_move , 0 , EAST , CTYPE_MOVE , 0 }, { "south" , POS_STANDING , do_move , 0 , SOUTH , CTYPE_MOVE , 0 }, { "west" , POS_STANDING , do_move , 0 , WEST , CTYPE_MOVE , 0 }, { "northeast" , POS_STANDING , do_move , 0 , NORTHEAST , CTYPE_MOVE , 0 }, { "northwest" , POS_STANDING , do_move , 0 , NORTHWEST , CTYPE_MOVE , 0 }, { "southeast" , POS_STANDING , do_move , 0 , SOUTHEAST , CTYPE_MOVE , 0 }, { "southwest" , POS_STANDING , do_move , 0 , SOUTHWEST , CTYPE_MOVE , 0 }, { "ne" , POS_STANDING , do_move , 0 , NORTHEAST , CTYPE_MOVE , 0 }, { "nw" , POS_STANDING , do_move , 0 , NORTHWEST , CTYPE_MOVE , 0 }, { "se" , POS_STANDING , do_move , 0 , SOUTHEAST , CTYPE_MOVE , 0 }, { "sw" , POS_STANDING , do_move , 0 , SOUTHWEST , CTYPE_MOVE , 0 }, { "up" , POS_STANDING , do_move , 0 , UP , CTYPE_MOVE , 0 }, { "down" , POS_STANDING , do_move , 0 , DOWN , CTYPE_MOVE , 0 }, /* now, the main list */ { "at" , POS_DEAD , do_at , LVL_START_IMM , 0 , CTYPE_IMMORTAL, 0 }, { "advance" , POS_DEAD , do_advance , LVL_TOP , 0 , CTYPE_IMMORTAL, 0 }, { "alias" , POS_DEAD , do_alias , 0 , 0 , CTYPE_UTIL , 0 }, { "abandon" , POS_DEAD , do_abandon , LVL_APPROVED , 0 , CTYPE_EMPIRE , 0 }, { "affects" , POS_DEAD , do_affects , 0 , 0 , CTYPE_UTIL , 0 }, { "afk" , POS_DEAD , do_afk , 0 , 0 , CTYPE_COMM , 0 }, { "assemble" , POS_STANDING , do_assemble , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "assist" , POS_FIGHTING , do_assist , 0 , 0 , CTYPE_COMBAT , 0 }, { "ask" , POS_RESTING , do_spec_comm , 0 , SCMD_ASK , CTYPE_COMM , 0 }, { "attach" , POS_SITTING , do_attach , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "authorize" , POS_DEAD , do_authorize , LVL_TOP , 0 , CTYPE_IMMORTAL, 0 }, { "autoexecute" , POS_DEAD , do_gen_tog , 0 , SCMD_AUTOKILL , CTYPE_COMBAT , 0 }, { "autokill" , POS_DEAD , do_gen_tog , 0 , SCMD_AUTOKILL , CTYPE_COMBAT , 0 }, { "autowiz" , POS_DEAD , do_autowiz , LVL_CIMPL , 0 , CTYPE_IMMORTAL, 0 }, { "build" , POS_STANDING , do_build , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "bake" , POS_STANDING , do_bake , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "ban" , POS_DEAD , do_ban , LVL_TOP , 0 , CTYPE_IMMORTAL, 0 }, { "bash" , POS_FIGHTING , do_bash , 0 , 0 , CTYPE_COMBAT , 0 }, { "bathe" , POS_STANDING , do_bathe , 0 , 0 , CTYPE_MOVE , 0 }, { "bite" , POS_STANDING , do_bite , 0 , 0 , CTYPE_COMBAT , CMD_VAMPIRE_ONLY }, { "blow" , POS_STANDING , do_blow , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "board" , POS_STANDING , do_board , 0 , 0 , CTYPE_MOVE , 0 }, { "boatload" , POS_STANDING , do_load_boat , 0 , 0 , CTYPE_MOVE , 0 }, { "boost" , POS_RESTING , do_boost , 0 , 0 , CTYPE_UTIL , CMD_VAMPIRE_ONLY | CMD_GHOUL_ONLY }, { "boatunload" , POS_STANDING , do_unload_boat, 0 , 0 , CTYPE_MOVE , 0 }, { "brief" , POS_DEAD , do_gen_tog , 0 , SCMD_BRIEF , CTYPE_UTIL , 0 }, { "bug" , POS_DEAD , do_gen_write , 0 , SCMD_BUG , CTYPE_COMM , 0 }, { "chop" , POS_STANDING , do_chop , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "catapult" , POS_STANDING , do_catapult , LVL_APPROVED , 0 , CTYPE_COMBAT , 0 }, { "cede" , POS_DEAD , do_cede , LVL_APPROVED , 0 , CTYPE_EMPIRE , 0 }, { "chgleader" , POS_DEAD , do_chgleader , LVL_APPROVED , 0 , CTYPE_EMPIRE , 0 }, { "chip" , POS_STANDING , do_chip , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "claim" , POS_DEAD , do_claim , LVL_APPROVED , 0 , CTYPE_EMPIRE , 0 }, { "clear" , POS_DEAD , do_gen_ps , 0 , SCMD_CLEAR , CTYPE_UTIL , 0 }, { "close" , POS_SITTING , do_gen_door , 0 , SCMD_CLOSE , CTYPE_MOVE , 0 }, { "cls" , POS_DEAD , do_gen_ps , 0 , SCMD_CLEAR , CTYPE_UTIL , 0 }, { "color" , POS_DEAD , do_gen_tog , 0 , SCMD_COLOR , CTYPE_UTIL , 0 }, { "commands" , POS_DEAD , do_commands , 0 , SCMD_COMMANDS , CTYPE_UTIL , 0 }, { "compact" , POS_DEAD , do_gen_tog , 0 , SCMD_COMPACT , CTYPE_UTIL , 0 }, { "confirm" , POS_SLEEPING , do_confirm , 0 , 0 , CTYPE_UTIL , 0 }, { "craft" , POS_STANDING , do_craft , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "credits" , POS_DEAD , do_gen_ps , 0 , SCMD_CREDITS , CTYPE_UTIL , 0 }, { "create" , POS_STANDING , do_create , LVL_GOD , 0 , CTYPE_IMMORTAL, 0 }, { "date" , POS_DEAD , do_date , LVL_START_IMM , SCMD_DATE , CTYPE_IMMORTAL, 0 }, { "dc" , POS_DEAD , do_dc , LVL_ASST , 0 , CTYPE_IMMORTAL, 0 }, { "drink" , POS_RESTING , do_drink , 0 , SCMD_DRINK , CTYPE_MOVE , 0 }, { "demote" , POS_DEAD , do_demote , LVL_APPROVED , 0 , CTYPE_EMPIRE , 0 }, { "defect" , POS_DEAD , do_defect , LVL_APPROVED , 0 , CTYPE_EMPIRE , 0 }, { "designate" , POS_STANDING , do_designate , LVL_APPROVED , FALSE , CTYPE_BUILD , 0 }, { "discipline" , POS_DEAD , do_discipline , 0 , 0 , CTYPE_MOVE , CMD_VAMPIRE_ONLY | CMD_GHOUL_ONLY }, { "diagnose" , POS_RESTING , do_diagnose , 0 , 0 , CTYPE_UTIL , 0 }, { "diplomacy" , POS_SLEEPING , do_diplomacy , LVL_APPROVED , 0 , CTYPE_EMPIRE , 0 }, { "dismount" , POS_FIGHTING , do_dismount , 0 , 0 , CTYPE_MOVE , 0 }, { "dismantle" , POS_STANDING , do_dismantle , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "disembark" , POS_STANDING , do_disembark , 0 , 0 , CTYPE_MOVE , 0 }, { "dig" , POS_STANDING , do_dig , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "douse" , POS_STANDING , do_douse , 0 , 0 , CTYPE_BUILD , 0 }, { "drop" , POS_RESTING , do_drop , 0 , SCMD_DROP , CTYPE_MOVE , 0 }, { "draw" , POS_RESTING , do_draw , 0 , 0 , CTYPE_COMBAT , 0 }, { "eat" , POS_RESTING , do_eat , 0 , SCMD_EAT , CTYPE_MOVE , 0 }, { "echo" , POS_SLEEPING , do_echo , LVL_GOD , SCMD_ECHO , CTYPE_IMMORTAL, 0 }, { "empires" , POS_DEAD , do_empires , 0 , 0 , CTYPE_EMPIRE , 0 }, { "embrace" , POS_STANDING , do_embrace , 0 , 0 , CTYPE_COMBAT , CMD_VAMPIRE_ONLY }, { "emote" , POS_RESTING , do_echo , 0 , SCMD_EMOTE , CTYPE_COMM , 0 }, { ":" , POS_RESTING , do_echo , 0 , SCMD_EMOTE , CTYPE_COMM , 0 }, { "enroll" , POS_SLEEPING , do_enroll , LVL_APPROVED , 0 , CTYPE_EMPIRE , 0 }, { "equipment" , POS_RESTING , do_equipment , 0 , 0 , CTYPE_MOVE , 0 }, { "esay" , POS_STUNNED , do_esay , LVL_APPROVED , 0 , CTYPE_EMPIRE , CMD_NOT_RP }, { "etalk" , POS_STUNNED , do_esay , LVL_APPROVED , 0 , CTYPE_EMPIRE , CMD_NOT_RP }, { "examine" , POS_SITTING , do_examine , 0 , 0 , CTYPE_UTIL , 0 }, { "excavate" , POS_STANDING , do_excavate , LVL_APPROVED , 0 , CTYPE_MOVE , 0 }, { "execute" , POS_STANDING , do_execute , 0 , 0 , CTYPE_COMBAT , 0 }, { "exits" , POS_RESTING , do_exits , 0 , NOWHERE , CTYPE_MOVE , 0 }, { "experience" , POS_SLEEPING , do_experience , LVL_APPROVED , 0 , CTYPE_UTIL , CMD_NOT_RP }, { "expell" , POS_SLEEPING , do_expell , LVL_APPROVED , 0 , CTYPE_EMPIRE , 0 }, { "extract" , POS_SLEEPING , do_extract , 0 , 0 , CTYPE_BUILD , 0 }, { "edelete" , POS_DEAD , do_edelete , LVL_TOP , 0 , CTYPE_EMPIRE , 0 }, { "force" , POS_SLEEPING , do_force , LVL_CIMPL , 0 , CTYPE_IMMORTAL, 0 }, { "fill" , POS_STANDING , do_pour , 0 , SCMD_FILL , CTYPE_MOVE , 0 }, { "feed" , POS_STANDING , do_feed , 0 , 0 , CTYPE_MOVE , CMD_VAMPIRE_ONLY }, { "file" , POS_DEAD , do_file , LVL_START_IMM , 0 , CTYPE_IMMORTAL, 0 }, { "forge" , POS_STANDING , do_forge , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "form" , POS_DEAD , do_form , 0 , 0 , CTYPE_UTIL , CMD_WEREWOLF_ONLY }, { "fire" , POS_STANDING , do_fire , LVL_APPROVED , 0 , CTYPE_COMBAT , 0 }, { "fish" , POS_STANDING , do_fish , 0 , 0 , CTYPE_COMBAT , 0 }, { "flee" , POS_FIGHTING , do_flee , 0 , 0 , CTYPE_COMBAT , 0 }, { "follow" , POS_RESTING , do_follow , 0 , 0 , CTYPE_MOVE , 0 }, { "fullsave" , POS_DEAD , do_fullsave , LVL_TOP , 0 , CTYPE_IMMORTAL, 0 }, { "freeze" , POS_DEAD , do_wizutil , LVL_FREEZE , SCMD_FREEZE , CTYPE_IMMORTAL, 0 }, { "get" , POS_RESTING , do_get , 0 , 0 , CTYPE_MOVE , 0 }, { "gather" , POS_STANDING , do_gather , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "gecho" , POS_DEAD , do_gecho , LVL_GOD , 0 , CTYPE_IMMORTAL, 0 }, { "give" , POS_RESTING , do_give , 0 , 0 , CTYPE_MOVE , 0 }, { "goto" , POS_SLEEPING , do_goto , LVL_START_IMM , SCMD_GOTO , CTYPE_IMMORTAL, 0 }, { "godnet" , POS_DEAD , do_pub_comm , LVL_GOD , SCMD_GODNET , CTYPE_IMMORTAL, 0 }, { "/" , POS_DEAD , do_pub_comm , LVL_GOD , SCMD_GODNET , CTYPE_IMMORTAL, 0 }, { "godlist" , POS_DEAD , do_gen_ps , 0 , SCMD_GODLIST , CTYPE_UTIL , 0 }, { "gossip" , POS_SLEEPING , do_pub_comm , 0 , SCMD_GOSSIP , CTYPE_UTIL , 0 }, { "grab" , POS_RESTING , do_grab , 0 , 0 , CTYPE_MOVE , 0 }, { "help" , POS_DEAD , do_help , 0 , 0 , CTYPE_UTIL , 0 }, { "harness" , POS_STANDING , do_harness , 0 , FALSE , CTYPE_MOVE , 0 }, { "harvest" , POS_STANDING , do_harvest , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "handbook" , POS_DEAD , do_gen_ps , LVL_START_IMM , SCMD_HANDBOOK , CTYPE_IMMORTAL, 0 }, { "heal" , POS_DEAD , do_vampire_heal,0 , 0 , CTYPE_MOVE , CMD_VAMPIRE_ONLY | CMD_GHOUL_ONLY }, { "herd" , POS_STANDING , do_herd , 0 , 0 , CTYPE_MOVE , 0 }, { "hide" , POS_RESTING , do_hide , 0 , 0 , CTYPE_MOVE , CMD_HUMAN_ONLY }, { "history" , POS_DEAD , do_history , 0 , 0 , CTYPE_COMM , CMD_NOT_RP }, //hide email moved to prevent errors, check end of list { "hit" , POS_FIGHTING , do_hit , 0 , SCMD_HIT , CTYPE_COMBAT , 0 }, { "hold" , POS_RESTING , do_grab , 0 , 0 , CTYPE_MOVE , 0 }, { "holylight" , POS_DEAD , do_gen_tog , LVL_GOD , SCMD_HOLYLIGHT, CTYPE_IMMORTAL, 0 }, { "inventory" , POS_RESTING , do_inventory , 0 , 0 , CTYPE_MOVE , 0 }, { "idea" , POS_DEAD , do_gen_write , 0 , SCMD_IDEA , CTYPE_COMM , 0 }, { "imotd" , POS_DEAD , do_gen_ps , LVL_START_IMM , SCMD_IMOTD , CTYPE_IMMORTAL, 0 }, { "infiltrate" , POS_STANDING , do_infiltrate , LVL_APPROVED , 0 , CTYPE_EMPIRE , 0 }, { "info" , POS_SLEEPING , do_gen_ps , 0 , SCMD_INFO , CTYPE_UTIL , 0 }, { "insult" , POS_RESTING , do_insult , 0 , 0 , CTYPE_COMM , 0 }, { "invis" , POS_DEAD , do_invis , LVL_GOD , 0 , CTYPE_IMMORTAL, 0 }, { "junk" , POS_RESTING , do_drop , 0 , SCMD_JUNK , CTYPE_UTIL , 0 }, { "kill" , POS_FIGHTING , do_hit , 0 , 0 , CTYPE_COMBAT , 0 }, { "kick" , POS_FIGHTING , do_kick , 0 , 0 , CTYPE_COMBAT , 0 }, { "look" , POS_RESTING , do_look , 0 , SCMD_LOOK , CTYPE_MOVE , 0 }, { "ls" , POS_RESTING , do_look , 0 , SCMD_LOOK , CTYPE_MOVE , 0 }, { "lay" , POS_STANDING , do_lay , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "last" , POS_DEAD , do_last , LVL_START_IMM , 0 , CTYPE_IMMORTAL, 0 }, { "lead" , POS_STANDING , do_lead , 0 , 0 , CTYPE_MOVE , 0 }, { "light" , POS_SITTING , do_light , 0 , 0 , CTYPE_MOVE , 0 }, { "load" , POS_DEAD , do_load , LVL_START_IMM , 0 , CTYPE_IMMORTAL, 0 }, { "load" , POS_STANDING , do_load_boat , 0 , 0 , CTYPE_MOVE , 0 }, { "messages" , POS_DEAD , do_messages , 0 , 0 , CTYPE_COMM , CMD_NOT_RP }, { "mappc" , POS_DEAD , do_gen_tog , 0 , SCMD_MAPPC , CTYPE_UTIL , 0 }, { "mapcolor" , POS_DEAD , do_gen_tog , 0 , SCMD_NOMAPCOL , CTYPE_UTIL , 0 }, { "manufacture" , POS_STANDING , do_manufacture, LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "melt" , POS_STANDING , do_melt , LVL_APPROVED , 0 , CTYPE_EMPIRE , 0 }, { "mine" , POS_STANDING , do_mine , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "mill" , POS_STANDING , do_mill , LVL_APPROVED , 0 , CTYPE_MOVE , 0 }, { "milk" , POS_STANDING , do_milk , LVL_APPROVED , 0 , CTYPE_MOVE , 0 }, { "mortlog" , POS_DEAD , do_gen_tog , 0 , SCMD_MORTLOG , CTYPE_UTIL , 0 }, { "motd" , POS_DEAD , do_gen_ps , 0 , SCMD_MOTD , CTYPE_UTIL , 0 }, { "mount" , POS_STANDING , do_mount , 0 , 0 , CTYPE_MOVE , 0 }, { "mail" , POS_STANDING , do_mail , 0 , 0 , CTYPE_UTIL , 0 }, { "mold" , POS_STANDING , do_mold , LVL_APPROVED , 0 , CTYPE_MOVE , 0 }, { "mute" , POS_DEAD , do_wizutil , LVL_MUTE , SCMD_MUTE , CTYPE_IMMORTAL, 0 }, { "noclear" , POS_DEAD , do_gen_tog , 0 , SCMD_NOCLEAR , CTYPE_UTIL , 0 }, { "nobite" , POS_DEAD , do_gen_tog , 0 , SCMD_NOBITE , CTYPE_UTIL , 0 }, { "nofeed" , POS_DEAD , do_gen_tog , 0 , SCMD_NOFEED , CTYPE_UTIL , 0 }, { "nogossip" , POS_DEAD , do_gen_tog , 0 , SCMD_NOGOSSIP , CTYPE_UTIL , 0 }, { "noooc" , POS_DEAD , do_gen_tog , 0 , SCMD_NOOOC , CTYPE_UTIL , 0 }, { "norepeat" , POS_DEAD , do_gen_tog , 0 , SCMD_NOREPEAT , CTYPE_UTIL , 0 }, { "noshout" , POS_SLEEPING , do_gen_tog , 0 , SCMD_DEAF , CTYPE_UTIL , 0 }, { "notell" , POS_DEAD , do_gen_tog , 0 , SCMD_NOTELL , CTYPE_UTIL , 0 }, { "noteach" , POS_DEAD , do_gen_tog , 0 , SCMD_NOTEACH , CTYPE_UTIL , 0 }, { "notitle" , POS_DEAD , do_wizutil , LVL_ASST , SCMD_NOTITLE , CTYPE_IMMORTAL, 0 }, { "nowiz" , POS_DEAD , do_gen_tog , LVL_GOD , SCMD_NOWIZ , CTYPE_IMMORTAL, 0 }, { "ooc" , POS_DEAD , do_pub_comm , 0 , SCMD_OOC , CTYPE_COMM , CMD_NOT_RP }, { "oocsay" , POS_RESTING , do_say , 0 , SCMD_OOCSAY , CTYPE_COMM , 0 }, { "\"" , POS_RESTING , do_say , 0 , SCMD_OOCSAY , CTYPE_COMM , 0 }, { "order" , POS_RESTING , do_order , 0 , 0 , CTYPE_MOVE , 0 }, { "open" , POS_SITTING , do_gen_door , 0 , SCMD_OPEN , CTYPE_MOVE , 0 }, { "put" , POS_RESTING , do_put , 0 , 0 , CTYPE_MOVE , 0 }, { "path" , POS_DEAD , do_path , 0 , 0 , CTYPE_MOVE , CMD_VAMPIRE_ONLY | CMD_GHOUL_ONLY }, { "page" , POS_DEAD , do_page , LVL_START_IMM , 0 , CTYPE_IMMORTAL, 0 }, { "pan" , POS_STANDING , do_pan , LVL_APPROVED , 0 , CTYPE_MOVE , 0 }, { "party" , POS_RESTING , do_party , 0 , 0 , CTYPE_MOVE , 0 }, { "pick" , POS_STANDING , do_pick , 0 , 0 , CTYPE_MOVE , 0 }, { "play" , POS_STANDING , do_play , 0 , 0 , CTYPE_MOVE , 0 }, { "plant" , POS_STANDING , do_plant , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "pledge" , POS_SLEEPING , do_pledge , LVL_APPROVED , 0 , CTYPE_EMPIRE , 0 }, { "political" , POS_DEAD , do_gen_tog , 0 , SCMD_POLITICAL, CTYPE_EMPIRE , 0 }, { "policy" , POS_DEAD , do_gen_ps , 0 , SCMD_POLICIES , CTYPE_UTIL , 0 }, { "poofin" , POS_DEAD , do_poofset , LVL_GOD , SCMD_POOFIN , CTYPE_IMMORTAL, 0 }, { "poofout" , POS_DEAD , do_poofset , LVL_GOD , SCMD_POOFOUT , CTYPE_IMMORTAL, 0 }, { "pour" , POS_STANDING , do_pour , 0 , SCMD_POUR , CTYPE_MOVE , 0 }, { "promote" , POS_DEAD , do_promote , LVL_APPROVED , 0 , CTYPE_EMPIRE , 0 }, { "prompt" , POS_DEAD , do_prompt , 0 , 0 , CTYPE_UTIL , 0 }, { "publicize" , POS_RESTING , do_publicize , LVL_APPROVED , 0 , CTYPE_EMPIRE , 0 }, { "purge" , POS_DEAD , do_purge , LVL_ASST , 0 , CTYPE_IMMORTAL, 0 }, { "purgemobs" , POS_DEAD , do_purgemobs , LVL_TOP , 0 , CTYPE_IMMORTAL, 0 }, { "purgeobjs" , POS_DEAD , do_purgeobjs , LVL_TOP , 0 , CTYPE_COMM , 0 }, { "psay" , POS_SLEEPING , do_psay , 0 , 0 , CTYPE_COMM , CMD_NOT_RP }, { "ptell" , POS_SLEEPING , do_psay , 0 , 0 , CTYPE_COMM , CMD_NOT_RP }, { "purgevnum" , POS_STANDING , do_purgevnum , LVL_TOP , 0 , CTYPE_IMMORTAL, 0 }, { "qui" , POS_DEAD , do_quit , 0 , 0 , CTYPE_UTIL , CMD_NOT_RP }, { "quit" , POS_DEAD , do_quit , 0 , SCMD_QUIT , CTYPE_UTIL , CMD_NOT_RP }, { "reply" , POS_DEAD , do_reply , 0 , 0 , CTYPE_COMM , CMD_NOT_RP }, { "redesignate" , POS_STANDING , do_designate , LVL_APPROVED , TRUE , CTYPE_BUILD , 0 }, { "respond" , POS_RESTING , do_respond , 0 , 0 , CTYPE_COMM , 0 }, { "reboo" , POS_DEAD , do_reboot , LVL_CIMPL , SCMD_REBOOT_DUMMY , CTYPE_IMMORTAL, 0 }, { "reboot" , POS_DEAD , do_reboot , LVL_CIMPL , SCMD_REBOOT , CTYPE_IMMORTAL, 0 }, { "reload" , POS_DEAD , do_reload , LVL_TOP , 0 , CTYPE_IMMORTAL, 0 }, { "reward" , POS_DEAD , do_reward , LVL_START_IMM , 0 , CTYPE_IMMORTAL, 0 }, { "random" , POS_SLEEPING , do_random , LVL_TOP , 0 , CTYPE_IMMORTAL, 0 }, { "read" , POS_RESTING , do_read , 0 , 0 , CTYPE_COMM , 0 }, { "redit" , POS_DEAD , do_olc , LVL_BUILDER , SCMD_REDIT , CTYPE_OLC , 0 }, { "remove" , POS_RESTING , do_remove , 0 , 0 , CTYPE_COMM , 0 }, { "report" , POS_RESTING , do_report , 0 , 0 , CTYPE_COMM , 0 }, { "rescue" , POS_FIGHTING , do_rescue , 0 , 0 , CTYPE_COMBAT , 0 }, { "rest" , POS_RESTING , do_rest , 0 , 0 , CTYPE_MOVE , 0 }, { "restore" , POS_DEAD , do_restore , LVL_CIMPL , 0 , CTYPE_IMMORTAL, 0 }, { "retrieve" , POS_STANDING , do_retrieve , LVL_APPROVED , 0 , CTYPE_MOVE , 0 }, { "return" , POS_DEAD , do_return , 0 , 0 , CTYPE_IMMORTAL, 0 }, { "rise" , POS_STUNNED , do_rise , 0 , 0 , CTYPE_MOVE , 0 }, { "roster" , POS_DEAD , do_roster , 0 , 0 , CTYPE_EMPIRE , 0 }, { "rp" , POS_DEAD , do_gen_tog , 0 , SCMD_RP , CTYPE_UTIL , 0 }, { "say" , POS_RESTING , do_say , 0 , SCMD_SAY , CTYPE_COMM , 0 }, { "'" , POS_RESTING , do_say , 0 , SCMD_SAY , CTYPE_COMM , 0 }, { "sail" , POS_STANDING , do_sail , 0 , 0 , CTYPE_MOVE , 0 }, { "sap" , POS_STANDING , do_sap , 0 , 0 , CTYPE_BUILD , 0 }, { "save" , POS_STUNNED , do_save , 0 , 0 , CTYPE_UTIL , 0 }, { "sacrifice" , POS_STANDING , do_sacrifice , 0 , 0 , CTYPE_MOVE , 0 }, { "score" , POS_DEAD , do_score , 0 , 0 , CTYPE_UTIL , 0 }, { "scrape" , POS_STANDING , do_scrape , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "scrolling" , POS_DEAD , do_gen_tog , 0 , SCMD_SCROLLING, CTYPE_UTIL , 0 }, { "seal" , POS_RESTING , do_seal , 0 , 0 , CTYPE_MOVE , CMD_VAMPIRE_ONLY }, { "search" , POS_STANDING , do_search , 0 , 0 , CTYPE_MOVE , 0 }, { "send" , POS_SLEEPING , do_send , LVL_START_IMM , 0 , CTYPE_IMMORTAL, 0 }, { "set" , POS_DEAD , do_set , LVL_ASST , 0 , CTYPE_IMMORTAL, 0 }, { "sew" , POS_STANDING , do_sew , LVL_APPROVED , 0 , CTYPE_MOVE , 0 }, { "sheath" , POS_RESTING , do_sheath , 0 , 0 , CTYPE_COMBAT , 0 }, { "shift" , POS_FIGHTING , do_shift , LVL_APPROVED , 0 , CTYPE_MOVE , CMD_WEREWOLF_ONLY }, { "shoot" , POS_STANDING , do_shoot , 0 , 0 , CTYPE_COMBAT , 0 }, { "shout" , POS_RESTING , do_pub_comm , 0 , SCMD_SHOUT , CTYPE_COMM , 0 }, { "show" , POS_DEAD , do_show , LVL_START_IMM , 0 , CTYPE_IMMORTAL, 0 }, { "shutdow" , POS_DEAD , do_reboot , LVL_TOP , SCMD_REBOOT_DUMMY , CTYPE_IMMORTAL, 0 }, { "shutdown" , POS_DEAD , do_reboot , LVL_TOP , SCMD_SHUTDOWN , CTYPE_IMMORTAL, 0 }, { "sip" , POS_RESTING , do_drink , 0 , SCMD_SIP , CTYPE_MOVE , 0 }, { "sit" , POS_RESTING , do_sit , 0 , 0 , CTYPE_MOVE , 0 }, { "skin" , POS_STANDING , do_skin , LVL_APPROVED , 0 , CTYPE_MOVE , 0 }, { "sleep" , POS_SLEEPING , do_sleep , 0 , 0 , CTYPE_MOVE , 0 }, { "slay" , POS_RESTING , do_slay , LVL_IMPL , 0 , CTYPE_IMMORTAL, 0 }, { "slit" , POS_RESTING , do_slit , 0 , 0 , CTYPE_MOVE , CMD_VAMPIRE_ONLY }, { "sneak" , POS_STANDING , do_sneak , 0 , 0 , CTYPE_MOVE , CMD_HUMAN_ONLY | CMD_STAY_HIDDEN }, { "snoop" , POS_DEAD , do_snoop , LVL_ASST , 0 , CTYPE_IMMORTAL, 0 }, { "socials" , POS_DEAD , do_socials , 0 , 0 , CTYPE_UTIL , 0 }, { "speak" , POS_DEAD , do_speak , 0 , 0 , CTYPE_COMM , 0 }, { "stand" , POS_RESTING , do_stand , 0 , 0 , CTYPE_MOVE , 0 }, { "stake" , POS_FIGHTING , do_stake , 0 , FALSE , CTYPE_COMBAT , 0 }, { "stat" , POS_DEAD , do_stat , LVL_START_IMM , 0 , CTYPE_IMMORTAL, 0 }, { "steal" , POS_STANDING , do_steal , LVL_APPROVED , 0 , CTYPE_MOVE , 0 }, { "store" , POS_STANDING , do_store , LVL_APPROVED , 0 , CTYPE_MOVE , 0 }, { "struggle" , POS_SLEEPING , do_struggle , 0 , 0 , CTYPE_COMBAT , 0 }, { "swap" , POS_RESTING , do_swap , 0 , 0 , CTYPE_MOVE , 0 }, { "switch" , POS_DEAD , do_switch , LVL_CIMPL , 0 , CTYPE_IMMORTAL, 0 }, { "spawn" , POS_DEAD , do_spawn , LVL_TOP , 0 , CTYPE_IMMORTAL, 0 }, { "tell" , POS_DEAD , do_tell , 0 , 0 , CTYPE_COMM , CMD_NOT_RP }, { "take" , POS_RESTING , do_get , 0 , 0 , CTYPE_MOVE , 0 }, { "taste" , POS_RESTING , do_eat , 0 , SCMD_TASTE , CTYPE_MOVE , 0 }, { "teach" , POS_STANDING , do_teach , LVL_APPROVED , 0 , CTYPE_UTIL , CMD_VAMPIRE_ONLY }, { "tedit" , POS_DEAD , do_tedit , LVL_CIMPL , 0 , CTYPE_IMMORTAL, 0 }, { "teleport" , POS_STANDING , do_goto , LVL_GOD , SCMD_TELEPORT , CTYPE_IMMORTAL, 0 }, { "throw" , POS_FIGHTING , do_throw , LVL_APPROVED , 0 , CTYPE_COMBAT , 0 }, { "thaw" , POS_DEAD , do_wizutil , LVL_FREEZE , SCMD_THAW , CTYPE_IMMORTAL, 0 }, { "tie" , POS_STANDING , do_tie , 0 , FALSE , CTYPE_COMBAT , 0 }, { "title" , POS_DEAD , do_title , 0 , 0 , CTYPE_UTIL , 0 }, { "time" , POS_DEAD , do_time , 0 , 0 , CTYPE_UTIL , 0 }, { "track" , POS_STANDING , do_track , 0 , 0 , CTYPE_MOVE , 0 }, { "transfer" , POS_SLEEPING , do_trans , LVL_ASST , 0 , CTYPE_IMMORTAL, 0 }, { "transport" , POS_STANDING , do_transport , 0 , 0 , CTYPE_MOVE , 0 }, { "typo" , POS_DEAD , do_gen_write , 0 , SCMD_TYPO , CTYPE_COMM , 0 }, { "unparty" , POS_DEAD , do_unparty , 0 , 0 , CTYPE_MOVE , 0 }, { "unharness" , POS_STANDING , do_harness , 0 , TRUE , CTYPE_MOVE , 0 }, { "unload" , POS_STANDING , do_unload_boat, 0 , 0 , CTYPE_MOVE , 0 }, { "unstake" , POS_STANDING , do_stake , 0 , TRUE , CTYPE_COMBAT , 0 }, { "untie" , POS_STANDING , do_tie , 0 , TRUE , CTYPE_COMBAT , 0 }, { "unban" , POS_DEAD , do_unban , LVL_TOP , 0 , CTYPE_IMMORTAL, 0 }, { "unpublicize" , POS_DEAD , do_unpublicize, LVL_APPROVED , 0 , CTYPE_EMPIRE , 0 }, { "uptime" , POS_DEAD , do_date , LVL_START_IMM , SCMD_UPTIME , CTYPE_IMMORTAL, 0 }, { "upgrade" , POS_STANDING , do_upgrade , LVL_APPROVED , 0 , CTYPE_BUILD , 0 }, { "users" , POS_DEAD , do_users , LVL_START_IMM , 0 , CTYPE_IMMORTAL, 0 }, { "vc" , POS_DEAD , do_vc , 0 , 0 , CTYPE_COMM , CMD_NOT_RP }, { "vcsay" , POS_DEAD , do_vcsay , 0 , 0 , CTYPE_COMM , CMD_NOT_RP }, { "." , POS_DEAD , do_vcsay , 0 , 0 , CTYPE_COMM , CMD_NOT_RP }, { "version" , POS_DEAD , do_gen_ps , 0 , SCMD_VERSION , CTYPE_UTIL , 0 }, { "visible" , POS_RESTING , do_visible , 0 , 0 , CTYPE_UTIL , 0 }, { "vnum" , POS_DEAD , do_vnum , LVL_START_IMM , 0 , CTYPE_IMMORTAL, 0 }, { "vstat" , POS_DEAD , do_vstat , LVL_START_IMM , 0 , CTYPE_IMMORTAL, 0 }, { "wake" , POS_SLEEPING , do_wake , 0 , 0 , CTYPE_MOVE , 0 }, { "wear" , POS_RESTING , do_wear , 0 , 0 , CTYPE_MOVE , 0 }, { "weather" , POS_RESTING , do_weather , 0 , 0 , CTYPE_UTIL , 0 }, { "who" , POS_DEAD , do_who , 0 , 0 , CTYPE_COMM , CMD_STAY_HIDDEN }, { "whois" , POS_DEAD , do_whois , 0 , 0 , CTYPE_COMM , CMD_STAY_HIDDEN }, { "where" , POS_RESTING , do_where , 0 , 0 , CTYPE_COMM , 0 }, { "whisper" , POS_RESTING , do_spec_comm , 0 , SCMD_WHISPER , CTYPE_COMM , 0 }, { "wield" , POS_RESTING , do_wield , 0 , 0 , CTYPE_MOVE , 0 }, { "wiznet" , POS_DEAD , do_pub_comm , LVL_START_IMM , SCMD_WIZNET , CTYPE_IMMORTAL, 0 }, { ";" , POS_DEAD , do_pub_comm , LVL_START_IMM , SCMD_WIZNET , CTYPE_IMMORTAL, 0 }, { "wizhelp" , POS_SLEEPING , do_commands , LVL_GOD , SCMD_WIZHELP , CTYPE_IMMORTAL, 0 }, { "wizlist" , POS_DEAD , do_gen_ps , 0 , SCMD_WIZLIST , CTYPE_UTIL , 0 }, { "wizlock" , POS_DEAD , do_wizlock , LVL_CIMPL , 0 , CTYPE_IMMORTAL, 0 }, { "write" , POS_STANDING , do_write , 0 , 0 , CTYPE_COMM , 0 }, //moved to help prevent glitch of "hide" executing "hideemail" { "hideemail" , POS_DEAD , do_gen_tog , LVL_APPROVED , SCMD_HIDEEMAIL, CTYPE_UTIL , 0 }, { "\n", 0, 0, 0, 0, 0, 0 } }; /* this must be last */ const char *fill[] = { "in", "from", "with", "the", "on", "at", "to", "\n" }; const char *reserved[] = { "a", "an", "some", "self", "me", "all", "room", "someone", "something", "\n" }; /* * This is the actual command interpreter called from game_loop() in comm.c * It makes sure you are the proper level and position to execute the command, * then calls the appropriate function. */ void command_interpreter(Creature ch, char *argument) { extern int check_social(Creature ch, char *string); int cmd, length; char *line; /* just drop to next line for hitting CR */ skip_spaces(&argument); if (!*argument) return; /* * special case to handle one-character, non-alphanumeric commands; * requested by many people so "'hi" or ";godnet test" is possible. * Patch sent by Eric Green and Stefan Wasilewski. */ if (!isalpha(*argument)) { arg[0] = argument[0]; arg[1] = '\0'; line = argument + 1; } else line = any_one_arg(argument, arg); /* otherwise, find the command */ for (length = strlen(arg), cmd = 0; *cmd_info[cmd].command != '\n'; cmd++) if (!strncmp(cmd_info[cmd].command, arg, length)) if (GET_LEVEL(ch) >= cmd_info[cmd].minimum_level) { if ((IS_SET(cmd_info[cmd].flags, CMD_VAMPIRE_ONLY) && IS_VAMPIRE(ch)) || (IS_SET(cmd_info[cmd].flags, CMD_WEREWOLF_ONLY) && IS_WEREWOLF(ch)) || (IS_SET(cmd_info[cmd].flags, CMD_GHOUL_ONLY) && IS_GHOUL(ch)) || (IS_SET(cmd_info[cmd].flags, CMD_HUMAN_ONLY) && IS_HUMAN(ch))) break; else if (!IS_SET(cmd_info[cmd].flags, CMD_VAMPIRE_ONLY | CMD_WEREWOLF_ONLY | CMD_GHOUL_ONLY | CMD_HUMAN_ONLY)) break; } if (!IS_SET(cmd_info[cmd].flags, CMD_STAY_HIDDEN | CMD_UNHIDE_AFTER)) REMOVE_BIT(AFF_FLAGS(ch), AFF_HIDE); if (*cmd_info[cmd].command == '\n' && check_social(ch, argument)) return; else if (*cmd_info[cmd].command == '\n') send_to_char(HUH, ch); else if (!IS_NPC(ch) && PLR_FLAGGED(ch, PLR_FROZEN)) send_to_char("You try, but the mind-numbing cold prevents you...\r\n", ch); else if (!IS_NPC(ch) && !IS_GOD(ch) && !IS_IMMORTAL(ch) && PRF_FLAGGED(ch, PRF_RP) && IS_SET(cmd_info[cmd].flags, CMD_NOT_RP)) msg_to_char(ch, "You can't do that while role-playing!\r\n"); else if (IS_INJURED(ch, INJ_STAKED)) msg_to_char(ch, "You can't do that while staked!\r\n"); else if (IS_INJURED(ch, INJ_TORPOR) && cmd_info[cmd].minimum_position >= POS_SLEEPING) msg_to_char(ch, "You can't do that while in torpor!\r\n"); else if (DSC_FLAGGED(ch, DSC_EARTHMELD) && cmd_info[cmd].minimum_position >= POS_SLEEPING) msg_to_char(ch, "You can't do that while interred in the earth. Use 'rise' first.\r\n"); else if (DSC_FLAGGED(ch, DSC_BITUMENOUS_FLESH) && cmd_info[cmd].minimum_position >= POS_SLEEPING) msg_to_char(ch, "You can't do that while mummified.\r\n"); else if (DSC_FLAGGED(ch, DSC_DEATHS_WHISPER) && cmd_info[cmd].minimum_position >= POS_SLEEPING) msg_to_char(ch, "You can't do that while under the influence of death's whisper!\r\n"); else if (GET_FED_ON_BY(ch) && cmd_info[cmd].minimum_position >= POS_SLEEPING) msg_to_char(ch, "The ecstasy of the fangs in your flesh is too enchanting to do that...\r\n"); else if (GET_FEEDING_FROM(ch) && cmd_info[cmd].minimum_position >= POS_SLEEPING && cmd_info[cmd].command_pointer != do_bite) msg_to_char(ch, "You can't do that while feeding!\r\n"); else if (cmd_info[cmd].command_pointer == NULL) send_to_char("Sorry, that command hasn't been implemented yet.\r\n", ch); else if (IS_NPC(ch) && cmd_info[cmd].minimum_level >= LVL_GOD) send_to_char("You can't use immortal commands while switched.\r\n", ch); else if (IS_INJURED(ch, INJ_TIED) && cmd_info[cmd].minimum_position > POS_SLEEPING) msg_to_char(ch, "You're tied up!\r\n"); else if (GET_POS(ch) < cmd_info[cmd].minimum_position) switch (GET_POS(ch)) { case POS_DEAD: send_to_char("Lie still; you are DEAD!!! :-(\r\n", ch); break; case POS_INCAP: case POS_MORTALLYW: send_to_char("You are in a pretty bad shape, unable to do anything!\r\n", ch); break; case POS_STUNNED: send_to_char("All you can do right now is think about the stars!\r\n", ch); break; case POS_SLEEPING: send_to_char("In your dreams, or what?\r\n", ch); break; case POS_RESTING: send_to_char("Nah... You feel too relaxed to do that..\r\n", ch); break; case POS_SITTING: send_to_char("Maybe you should get on your feet first?\r\n", ch); break; case POS_FIGHTING: send_to_char("No way! You're fighting for your life!\r\n", ch); break; } else ((*cmd_info[cmd].command_pointer) (ch, line, cmd, cmd_info[cmd].subcmd)); /* Unhide after ? */ if (ch && IS_SET(cmd_info[cmd].flags, CMD_UNHIDE_AFTER)) REMOVE_BIT(AFF_FLAGS(ch), AFF_HIDE); } /************************************************************************** * Routines to handle aliasing * **************************************************************************/ struct alias_data *find_alias(struct alias_data *alias_list, char *str) { while (alias_list != NULL) { if (*str == *alias_list->alias) /* hey, every little bit counts :-) */ if (!strcmp(str, alias_list->alias)) return (alias_list); alias_list = alias_list->next; } return (NULL); } void free_alias(struct alias_data *a) { if (a->alias) free(a->alias); if (a->replacement) free(a->replacement); free(a); } /* The interface to the outside world: do_alias */ ACMD(do_alias) { char *repl; struct alias_data *a, *temp; if (IS_NPC(ch)) return; repl = any_one_arg(argument, arg); if (!*arg) { /* no argument specified -- list currently defined aliases */ send_to_char("Currently defined aliases:\r\n", ch); if ((a = GET_ALIASES(ch)) == NULL) send_to_char(" None.\r\n", ch); else { while (a != NULL) { sprintf(buf, "%-15s %s\r\n", a->alias, a->replacement); send_to_char(buf, ch); a = a->next; } } } else { /* otherwise, add or remove aliases */ /* is this an alias we've already defined? */ if ((a = find_alias(GET_ALIASES(ch), arg)) != NULL) { REMOVE_FROM_LIST(a, GET_ALIASES(ch), next); free_alias(a); } /* if no replacement string is specified, assume we want to delete */ if (!*repl) { if (a == NULL) send_to_char("No such alias.\r\n", ch); else send_to_char("Alias deleted.\r\n", ch); } else { /* otherwise, either add or redefine an alias */ if (!str_cmp(arg, "alias")) { send_to_char("You can't alias 'alias'.\r\n", ch); return; } CREATE(a, struct alias_data, 1); a->alias = str_dup(arg); delete_doubledollar(repl); a->replacement = str_dup(repl); if (strchr(repl, ALIAS_SEP_CHAR) || strchr(repl, ALIAS_VAR_CHAR)) a->type = ALIAS_COMPLEX; else a->type = ALIAS_SIMPLE; a->next = GET_ALIASES(ch); GET_ALIASES(ch) = a; send_to_char("Alias added.\r\n", ch); } } } /* * Valid numeric replacements are only $1 .. $9 (makes parsing a little * easier, and it's not that much of a limitation anyway.) Also valid * is "$*", which stands for the entire original line after the alias. * ";" is used to delimit commands. */ #define NUM_TOKENS 9 void perform_complex_alias(struct txt_q *input_q, char *orig, struct alias_data *a) { struct txt_q temp_queue; char *tokens[NUM_TOKENS], *temp, *write_point; int num_of_tokens = 0, num; skip_spaces(&orig); /* First, parse the original string */ temp = strtok(strcpy(buf2, orig), " "); while (temp != NULL && num_of_tokens < NUM_TOKENS) { tokens[num_of_tokens++] = temp; temp = strtok(NULL, " "); } /* initialize */ write_point = buf; temp_queue.head = temp_queue.tail = NULL; /* now parse the alias */ for (temp = a->replacement; *temp; temp++) { if (*temp == ALIAS_SEP_CHAR) { *write_point = '\0'; buf[MAX_INPUT_LENGTH - 1] = '\0'; write_to_q(buf, &temp_queue, 1); write_point = buf; } else if (*temp == ALIAS_VAR_CHAR) { temp++; if ((num = *temp - '1') < num_of_tokens && num >= 0) { strcpy(write_point, tokens[num]); write_point += strlen(tokens[num]); } else if (*temp == ALIAS_GLOB_CHAR) { strcpy(write_point, orig); write_point += strlen(orig); } else if ((*(write_point++) = *temp) == '$') /* redouble $ for act safety */ *(write_point++) = '$'; } else *(write_point++) = *temp; } *write_point = '\0'; buf[MAX_INPUT_LENGTH - 1] = '\0'; write_to_q(buf, &temp_queue, 1); /* push our temp_queue on to the _front_ of the input queue */ if (input_q->head == NULL) *input_q = temp_queue; else { temp_queue.tail->next = input_q->head; input_q->head = temp_queue.head; } } /* * Given a character and a string, perform alias replacement on it. * * Return values: * 0: String was modified in place; call command_interpreter immediately. * 1: String was _not_ modified in place; rather, the expanded aliases * have been placed at the front of the character's input queue. */ int perform_alias(Descr d, char *orig) { char first_arg[MAX_INPUT_LENGTH], *ptr; struct alias_data *a, *tmp; /* Mobs don't have alaises. */ if (IS_NPC(d->character)) return (0); /* bail out immediately if the guy doesn't have any aliases */ if ((tmp = GET_ALIASES(d->character)) == NULL) return (0); /* find the alias we're supposed to match */ ptr = any_one_arg(orig, first_arg); /* bail out if it's null */ if (!*first_arg) return (0); /* if the first arg is not an alias, return without doing anything */ if ((a = find_alias(tmp, first_arg)) == NULL) return (0); if (a->type == ALIAS_SIMPLE) { strcpy(orig, a->replacement); return (0); } else { perform_complex_alias(&d->input, ptr, a); return (1); } } /*************************************************************************** * Various other parsing utilities * **************************************************************************/ int enter_player_game(Descr d, int dolog) { void read_aliases(Creature ch); void read_lore(Creature ch); extern struct time_info_data time_info; extern room_rnum find_haven(Creature ch); extern room_rnum create_haven(Creature ch); extern room_rnum find_load_room(Creature ch); extern long get_ptable_by_name(char *name); extern long top_idnum; room_rnum load_room; int load_result, i; Creature ch = d->character; reset_char(ch); read_aliases(ch); read_lore(ch); if (GET_IDNUM(ch) == 0) if ((i = get_ptable_by_name(GET_NAME(ch))) != -1) player_table[i].id = GET_IDNUM(ch) = ++top_idnum; if (GET_IMM_LEV(ch) > -1) GET_LEVEL(ch) = LVL_TOP - GET_IMM_LEV(ch); if (PLR_FLAGGED(ch, PLR_INVSTART)) GET_INVIS_LEV(ch) = GET_LEVEL(ch); if (real_empire(GET_LOYALTY(ch)) == -1) GET_LOYALTY(ch) = 0; /* * We have to place the character in a room before equipping them * or equip_char() will gripe about the person in NOWHERE. */ if ((load_room = GET_LOADROOM(ch)) != NOWHERE) load_room = real_room(load_room); /* If that failed, check for a haven */ if (load_room == NOWHERE) load_room = find_haven(d->character); /* If char was saved with NOWHERE, or real_room above failed... */ if (load_room == NOWHERE) { if (IS_VAMPIRE(d->character)) load_room = create_haven(d->character); else load_room = find_load_room(d->character); } /* Temporary provision */ if (SECT(load_room) == SECT_OCEAN) load_room = find_load_room(d->character); /* No toasting! Place them in a haven or kick them back out! */ if (SECT(load_room) != SECT_INSIDE && ((SECT(load_room) != SECT_BUILDING && SECT(load_room) != SECT_MULTI) || !IS_COMPLETE(load_room)) && IS_VAMPIRE(d->character) && weather_info.sunlight != SUN_DARK && !DSC_FLAGGED(ch, DSC_EARTHMELD) && !ROOM_AFF_FLAGGED(load_room, ROOM_AFF_DARK) && (load_room = find_haven(d->character)) == NOWHERE) { sprintf(buf, "Current game time: %d o'clock %s\r\n", ((time_info.hours % 12 == 0) ? 12 : ((time_info.hours) % 12)), ((time_info.hours >= 12) ? "pm" : "am")); SEND_TO_Q("\r\nThe area where you would enter the game is lit by the sun. You are denied entry at this time because your character would probably be killed very quickly.\r\n", d); SEND_TO_Q(buf, d); SEND_TO_Q("\r\n*** Press ENTER: ", d); /* We aren't always sent here by CON_MENU */ STATE(d) = CON_MENU; return -2; } /* fail-safe */ if (IS_VAMPIRE(ch) && GET_APPARENT_AGE(ch) <= 0) GET_APPARENT_AGE(ch) = 25; /* position must be reset */ if (DSC_FLAGGED(ch, DSC_EARTHMELD | DSC_BITUMENOUS_FLESH) || IS_INJURED(ch, INJ_TORPOR)) if (GET_DAMAGE(ch) < 7) GET_POS(ch) = POS_SLEEPING; ch->next = character_list; character_list = ch; char_to_room(ch, load_room); load_result = Crash_load(ch, dolog); affect_total(ch); SAVE_CHAR(ch); return load_result; } /* * searches an array of strings for a target string. "exact" can be * 0 or non-0, depending on whether or not the match must be exact for * it to be returned. Returns -1 if not found; 0..n otherwise. Array * must be terminated with a '\n' so it knows to stop searching. */ int search_block(char *arg, const char **list, int exact) { register int i, l; /* Make into lower case, and get length of string */ for (l = 0; *(arg + l); l++) *(arg + l) = LOWER(*(arg + l)); if (exact) { for (i = 0; **(list + i) != '\n'; i++) if (!strcmp(arg, *(list + i))) return (i); } else { if (!l) l = 1; /* Avoid "" to match the first available string */ for (i = 0; **(list + i) != '\n'; i++) if (!strncmp(arg, *(list + i), l)) return (i); } return (-1); } int is_number(const char *str) { while (*str) if (!isdigit(*(str++))) return (0); return (1); } /* * Function to skip over the leading spaces of a string. */ void skip_spaces(char **string) { for (; **string && isspace(**string); (*string)++); } /* * Given a string, change all instances of double dollar signs ($$) to * single dollar signs ($). When strings come in, all $'s are changed * to $$'s to avoid having users be able to crash the system if the * inputted string is eventually sent to act(). If you are using user * input to produce screen output AND YOU ARE SURE IT WILL NOT BE SENT * THROUGH THE act() FUNCTION (i.e., do_gecho, do_title, but NOT do_say), * you can call delete_doubledollar() to make the output look correct. * * Modifies the string in-place. */ char *delete_doubledollar(char *string) { char *read, *write; /* If the string has no dollar signs, return immediately */ if ((write = strchr(string, '$')) == NULL) return (string); /* Start from the location of the first dollar sign */ read = write; while (*read) /* Until we reach the end of the string... */ if ((*(write++) = *(read++)) == '$') /* copy one char */ if (*read == '$') read++; /* skip if we saw 2 $'s in a row */ *write = '\0'; return (string); } int fill_word(char *argument) { return (search_block(argument, fill, TRUE) >= 0); } int reserved_word(char *argument) { return (search_block(argument, reserved, TRUE) >= 0); } /* * copy the first non-fill-word, space-delimited argument of 'argument' * to 'first_arg'; return a pointer to the remainder of the string. */ char *one_argument(char *argument, char *first_arg) { char *begin = first_arg; if (!argument) { log("SYSERR: one_argument received a NULL pointer!"); *first_arg = '\0'; return (NULL); } do { skip_spaces(&argument); first_arg = begin; while (*argument && !isspace(*argument)) { *(first_arg++) = LOWER(*argument); argument++; } *first_arg = '\0'; } while (fill_word(begin)); return (argument); } /* * one_word is like one_argument, except that words in quotes ("") are * considered one word. */ char *one_word(char *argument, char *first_arg) { char *begin = first_arg; do { skip_spaces(&argument); first_arg = begin; if (*argument == '\"') { argument++; while (*argument && *argument != '\"') { *(first_arg++) = LOWER(*argument); argument++; } argument++; } else { while (*argument && !isspace(*argument)) { *(first_arg++) = LOWER(*argument); argument++; } } *first_arg = '\0'; } while (fill_word(begin)); return (argument); } /* same as one_argument except that it doesn't ignore fill words */ char *any_one_arg(char *argument, char *first_arg) { skip_spaces(&argument); while (*argument && !isspace(*argument)) { *(first_arg++) = LOWER(*argument); argument++; } *first_arg = '\0'; return (argument); } /* * Same as one_argument except that it takes two args and returns the rest; * ignores fill words */ char *two_arguments(char *argument, char *first_arg, char *second_arg) { return (one_argument(one_argument(argument, first_arg), second_arg)); } /* * determine if a given string is an abbreviation of another * (now works symmetrically -- JE 7/25/94) * * that was dumb. it shouldn't be symmetrical. JE 5/1/95 * * returnss 1 if arg1 is an abbreviation of arg2 */ int is_abbrev(const char *arg1, const char *arg2) { if (!*arg1) return (0); for (; *arg1 && *arg2; arg1++, arg2++) if (LOWER(*arg1) != LOWER(*arg2)) return (0); if (!*arg1) return (1); else return (0); } /* return first space-delimited token in arg1; remainder of string in arg2 */ void half_chop(char *string, char *arg1, char *arg2) { char *temp; temp = any_one_arg(string, arg1); skip_spaces(&temp); strcpy(arg2, temp); } /* Used in specprocs, mostly. (Exactly) matches "command" to cmd number */ int find_command(const char *command) { int cmd; for (cmd = 0; *cmd_info[cmd].command != '\n'; cmd++) if (!strcmp(cmd_info[cmd].command, command)) return (cmd); return (-1); } /* ************************************************************************* * Stuff for controlling the non-playing sockets (get name, pwd etc) * ************************************************************************* */ /* locate entry in p_table with entry->name == name. -1 mrks failed search */ int find_name(char *name) { int i; for (i = 0; i <= top_of_p_table; i++) { if (!str_cmp((player_table + i)->name, name)) return (i); } return (-1); } int _parse_name(char *arg, char *name) { int i; /* skip whitespaces */ for (; isspace(*arg); arg++); for (i = 0; (*name = *arg); arg++, i++, name++) if (!isalpha(*arg) && *arg != '\'' && *arg != '-') return (1); if (!i) return (1); return (0); } #define RECON 1 #define USURP 2 #define UNSWITCH 3 /* * XXX: Make immortals 'return' instead of being disconnected when switched * into person returns. This function seems a bit over-extended too. */ int perform_dupe_check(Descr d) { Descr k, next_k; Creature target = NULL, ch, next_ch; int mode = 0; int id = GET_IDNUM(d->character); /* * Now that this descriptor has successfully logged in, disconnect all * other descriptors controlling a character with the same ID number. */ for (k = descriptor_list; k; k = next_k) { next_k = k->next; if (k == d) continue; if (k->original && (GET_IDNUM(k->original) == id)) { /* switched char */ SEND_TO_Q("\r\nMultiple login detected -- disconnecting.\r\n", k); STATE(k) = CON_CLOSE; if (!target) { target = k->original; mode = UNSWITCH; } if (k->character) k->character->desc = NULL; k->character = NULL; k->original = NULL; } else if (k->character && (GET_IDNUM(k->character) == id)) { if (!target && STATE(k) == CON_PLAYING) { SEND_TO_Q("\r\nThis body has been usurped!\r\n", k); target = k->character; mode = USURP; } k->character->desc = NULL; k->character = NULL; k->original = NULL; SEND_TO_Q("\r\nMultiple login detected -- disconnecting.\r\n", k); STATE(k) = CON_CLOSE; } } /* * now, go through the character list, deleting all characters that * are not already marked for deletion from the above step (i.e., in the * CON_HANGUP state), and have not already been selected as a target for * switching into. In addition, if we haven't already found a target, * choose one if one is available (while still deleting the other * duplicates, though theoretically none should be able to exist). */ for (ch = character_list; ch; ch = next_ch) { next_ch = ch->next; if (IS_NPC(ch)) continue; if (GET_IDNUM(ch) != id) continue; /* ignore chars with descriptors (already handled by above step) */ if (ch->desc) continue; /* don't extract the target char we've found one already */ if (ch == target) continue; /* we don't already have a target and found a candidate for switching */ if (!target) { target = ch; mode = RECON; continue; } /* we've found a duplicate - blow him away. */ if (ch->in_room != NOWHERE) char_from_room(ch); char_to_room(ch, 0); extract_char(ch); } /* no target for swicthing into was found - allow login to continue */ if (!target) return (0); /* Okay, we've found a target. Connect d to target. */ free_char(d->character); /* get rid of the old char */ d->character = target; d->character->desc = d; d->original = NULL; d->character->char_specials.timer = 0; REMOVE_BIT(PLR_FLAGS(d->character), PLR_MAILING | PLR_WRITING); REMOVE_BIT(AFF_FLAGS(d->character), AFF_PARTY); STATE(d) = CON_PLAYING; if (PLR_FLAGGED(d->character, PLR_IPMASK)) strcpy(d->host, "masked"); switch (mode) { case RECON: SEND_TO_Q("Reconnecting.\r\n", d); act("$n has reconnected.", TRUE, d->character, 0, 0, TO_ROOM); syslog(GET_INVIS_LEV(d->character), TRUE, "%s [%s] has reconnected.", GET_NAME(d->character), d->host); break; case USURP: SEND_TO_Q("You take over your own body, already in use!\r\n", d); act("$n suddenly keels over in pain, surrounded by a white aura...\r\n" "$n's body has been taken over by a new spirit!", TRUE, d->character, 0, 0, TO_ROOM); syslog(GET_INVIS_LEV(d->character), TRUE, "%s has re-logged in ... disconnecting old socket.", GET_NAME(d->character)); break; case UNSWITCH: SEND_TO_Q("Reconnecting to unswitched char.", d); syslog(GET_INVIS_LEV(d->character), TRUE, "%s [%s] has reconnected.", GET_NAME(d->character), d->host); break; } return (1); } void send_motd(Descr d) { extern char *motd; extern char *imotd; extern char *CREDIT_MESSG; int i; if (!PRF_FLAGGED(d->character, PRF_NOCLEAR)) SEND_TO_Q("[H[J", d); SEND_TO_Q(CREDIT_MESSG, d); SEND_TO_Q(" ", d); for (i = 0; i < 79; i++) SEND_TO_Q("=", d); SEND_TO_Q("\r\n\r\n", d); if (GET_LEVEL(d->character) >= LVL_START_IMM) SEND_TO_Q(imotd, d); else SEND_TO_Q(motd, d); SEND_TO_Q("\r\n ", d); for (i = 0; i < 79; i++) SEND_TO_Q("=", d); SEND_TO_Q("\r\n", d); } struct sort_struct { int sort_pos; byte is_social; } *cmd_sort_info = NULL; int num_of_cmds; void sort_commands(void) { int a, b, tmp; num_of_cmds = 0; /* * first, count commands (num_of_commands is actually one greater than the * number of commands; it inclues the '\n'. */ while (*cmd_info[num_of_cmds].command != '\n') num_of_cmds++; /* create data array */ CREATE(cmd_sort_info, struct sort_struct, num_of_cmds); /* initialize it */ for (a = 1; a < num_of_cmds; a++) { cmd_sort_info[a].sort_pos = a; cmd_sort_info[a].is_social = 0; } /* Sort. 'a' starts at 1, not 0, to remove 'RESERVED' */ for (a = 1; a < num_of_cmds - 1; a++) for (b = a + 1; b < num_of_cmds; b++) if (strcmp(cmd_info[cmd_sort_info[a].sort_pos].command, cmd_info[cmd_sort_info[b].sort_pos].command) > 0) { tmp = cmd_sort_info[a].sort_pos; cmd_sort_info[a].sort_pos = cmd_sort_info[b].sort_pos; cmd_sort_info[b].sort_pos = tmp; } } ACMD(do_commands) { int no, i, cmd_num; int wizhelp = 0; Creature vict; one_argument(argument, arg); if (*arg) { if (!(vict = get_char_vis(ch, arg, FIND_CHAR_WORLD)) || IS_NPC(vict)) { send_to_char("Who is that?\r\n", ch); return; } if (GET_LEVEL(ch) < GET_LEVEL(vict)) { send_to_char("You can't see the commands of people above your level.\r\n", ch); return; } } else vict = ch; if (subcmd == SCMD_WIZHELP) wizhelp = 1; sprintf(buf, "The following %s%s are available to %s:\r\n", wizhelp ? "privileged " : "", "commands", vict == ch ? "you" : PERS(vict, ch, 1)); /* cmd_num starts at 1, not 0, to remove 'RESERVED' */ for (no = 1, cmd_num = 1; cmd_num < num_of_cmds; cmd_num++) { i = cmd_sort_info[cmd_num].sort_pos; if (cmd_info[i].minimum_level >= 0 && GET_LEVEL(vict) >= cmd_info[i].minimum_level && (cmd_info[i].minimum_level >= LVL_GOD) == wizhelp) { sprintf(buf + strlen(buf), "%-11s", cmd_info[i].command); if (!(no % 7)) strcat(buf, "\r\n"); no++; } } strcat(buf, "\r\n"); send_to_char(buf, ch); } /* Determine if a person is multiplaying */ bool check_multiplaying(Descr d) { Descr c; bool ok = TRUE; if (GET_LEVEL(d->character) >= LVL_START_IMM) return TRUE; if (PLR_FLAGGED(d->character, PLR_MULTIOK | PLR_IPMASK)) return TRUE; /* Check for connected players with identical hosts */ for (c = descriptor_list; c; c = c->next) if (c != d && STATE(c) == CON_PLAYING && GET_LEVEL(c->character) >= LVL_APPROVED && !str_cmp(c->host, d->host) && !PLR_FLAGGED(c->character, PLR_MULTIOK) && GET_IDNUM(c->character) != GET_IDNUM(d->character)) ok = FALSE; return ok; } /* * Determine if a player can be autoauthorized * if idnum != -1 then we ignore the person with that idnum */ bool validate_autoauthorize(Descr d, char *arg, long idnum) { extern struct time_info_data *real_time_passed(time_t t2, time_t t1); extern struct player_index_element *player_table; extern int top_of_p_table; struct char_file_u vbuf; Descr c; int j; bool ok = TRUE; /* Process the e-mail address into buf */ one_argument(arg, buf); /* Check for connected players with identical hosts */ for (c = descriptor_list; c; c = c->next) if (c != d && c->character && GET_LEVEL(c->character) >= LVL_APPROVED && !str_cmp(c->host, d->host)) if (!PLR_FLAGGED(c->character, PLR_IPMASK | PLR_MULTIOK)) ok = FALSE; /* Check common email addresses and hosts - done here to help reduce lag */ if (ok) { for (j = 0; j <= top_of_p_table; j++) { load_char((player_table + j)->name, &vbuf); if (!IS_SET(vbuf.char_specials_saved.act, PLR_DELETED | PLR_SLAIN) && vbuf.level >= LVL_APPROVED) if (!str_cmp(vbuf.email, buf) || ((*real_time_passed(vbuf.last_logon, 0)).day < 14 && !str_cmp(vbuf.host, d->host))) if (!IS_SET(vbuf.char_specials_saved.act, PLR_IPMASK)) if (vbuf.char_specials_saved.idnum != idnum) ok = FALSE; } } if (ok) { syslog(0, TRUE, "Autoauthorization approved for %s: %s [%s]", GET_PC_NAME(d->character), buf, d->host); if (GET_EMAIL(d->character)) free(GET_EMAIL(d->character)); d->character->player.email = str_dup(buf); GET_LEVEL(d->character) = LVL_APPROVED; return TRUE; } syslog(0, TRUE, "Autoauthorization denied for %s [%s]", GET_PC_NAME(d->character), d->host); GET_LEVEL(d->character) = 1; return FALSE; } /* Protocol for adjusting Attributes */ #define Attribute_Modify(text, store, attribute, not1, not2) { \ if (*buf1 && is_abbrev(buf1, text)) { \ if (add) { \ if (store >= 5) \ SEND_TO_Q("\r\nYou may not begin with any Attribute greater than 5.\r\n", d); \ else if (attribute >= 10) \ SEND_TO_Q("\r\nYou can't raise any this Attribute group any more.\r\n", d); \ else if ((not1 > 8 || not2 > 8) && attribute >= 8) \ SEND_TO_Q("\r\nYou may not increase this Attribute group any more.\r\n", d); \ else if (((not1 > 6 && not2 > 6) || (not2 > 6 && not1 > 6)) && attribute >= 6) \ SEND_TO_Q("\r\nYou may not increase this Attribute group any more.\r\n", d); \ else { \ store += 1; \ d->character->player_specials->create_points -= 1; \ } \ } \ else if (subtract) { \ if (store <= 1) \ SEND_TO_Q("\r\nYou may not lower an Attribute below 1.\r\n", d); \ else { \ store -= 1; \ d->character->player_specials->create_points += 1; \ } \ } \ } \ } /* Protocol for adjusting Abilities */ #define Ability_Modify(text, store, ability, not1, not2) { \ if (*buf1 && is_abbrev(buf1, text)) { \ if (add) { \ if (store >= 3) \ SEND_TO_Q("\r\nYou may not begin with any Ability greater than 3.\r\n", d); \ else if (ability >= 13) \ SEND_TO_Q("\r\nYou can't raise any this Ability group any more.\r\n", d); \ else if ((not1 > 9 || not2 > 9) && ability >= 9) \ SEND_TO_Q("\r\nYou may not increase this Ability group any more.\r\n", d); \ else if (((not1 > 5 && not2 > 5) || (not2 > 5 && not1 > 5)) && ability >= 5) \ SEND_TO_Q("\r\nYou may not increase this Ability group any more.\r\n", d); \ else { \ store += 1; \ d->character->player_specials->create_points -= 1; \ } \ } \ else if (subtract) { \ if (store <= 0) \ SEND_TO_Q("\r\nYou may not lower an Ability below 0.\r\n", d); \ else { \ store -= 1; \ d->character->player_specials->create_points += 1; \ } \ } \ } \ } void assign_werewolf_advantages(Descr d) { /* Gnosis: by breed */ switch (GET_BREED(d->character)) { case BREED_HOMID: GET_MAX_GNOSIS(d->character) = 1; break; case BREED_METIS: GET_MAX_GNOSIS(d->character) = 3; break; case BREED_LUPUS: GET_MAX_GNOSIS(d->character) = 5; break; } /* Rage: by auspice */ GET_MAX_RAGE(d->character) = GET_AUSPICE(d->character) + 1; /* Willpower: by tribe */ switch (GET_TRIBE(d->character)) { case TRIBE_BLACK_FURIES: case TRIBE_FENRIR: case TRIBE_FIANNA: case TRIBE_RED_TALONS: case TRIBE_SHADOW_LORDS: case TRIBE_SILENT_STRIDERS: case TRIBE_WARDERS: GET_MAX_WILLPOWER(d->character) = 3; break; case TRIBE_BONE_GNAWERS: case TRIBE_CHILDREN_OF_GAIA: case TRIBE_SILVER_FANGS: GET_MAX_WILLPOWER(d->character) = 4; break; } } /* deal with newcomers and other non-playing sockets */ void nanny(Descr d, char *arg) { extern struct discipline_data path[]; extern const char *hardcore_slain_msg; extern struct new_eq_set_data new_eq[]; extern char *background; extern char *MENU; extern char *WELC_MESSG; extern char *START_MESSG; extern const char *AUTH_MESSG; extern int wizlock_level; extern char *wizlock_message; extern const char *langs[]; extern struct tribe_data tribe[]; extern const char *skin_colors[]; extern const char *hair_colors[]; extern const char *eye_colors[]; void parse_empire_edit(Descr d, char *arg); void display_statistics_to_char(Creature ch); void display_attributes(Creature ch, Creature to, bool real); void display_abilities(Creature ch, Creature to); struct time_info_data *real_time_passed(time_t t2, time_t t1); void delete_empire(int rnum); extern struct empire_edit_data *create_empire_editor(int emp); void send_empire_edit_menu(Descr d); int emp; char buf[128]; int player_i, load_result, i, j; char tmp_name[MAX_INPUT_LENGTH]; struct char_file_u tmp_store; struct time_info_data playing_time; bool add = FALSE, subtract = FALSE; byte physical, social, mental; byte talents, skills, knowledges; skip_spaces(&arg); switch (STATE(d)) { case CON_EMPIRE_EDIT: parse_empire_edit(d, arg); break; case CON_GET_NAME: /* wait for input of name */ if (d->character == NULL) { CREATE(d->character, struct char_data, 1); clear_char(d->character); CREATE(d->character->player_specials, struct player_special_data, 1); d->character->desc = d; } if (!*arg) STATE(d) = CON_CLOSE; else { if ((_parse_name(arg, tmp_name)) || strlen(tmp_name) < 2 || strlen(tmp_name) > MAX_NAME_LENGTH || !Valid_Name(tmp_name) || fill_word(strcpy(buf, tmp_name)) || reserved_word(buf)) { SEND_TO_Q("Invalid name, please try another.\r\nName: ", d); return; } if ((player_i = load_char(tmp_name, &tmp_store)) > -1) { store_to_char(&tmp_store, d->character); GET_PFILEPOS(d->character) = player_i; if (PLR_FLAGGED(d->character, PLR_DELETED)) { /* We get a false positive from the original deleted character. */ free_char(d->character); /* Check for multiple creations... */ if (!Valid_Name(tmp_name)) { SEND_TO_Q("Invalid name, please try another.\r\nName: ", d); return; } CREATE(d->character, struct char_data, 1); clear_char(d->character); CREATE(d->character->player_specials, struct player_special_data, 1); d->character->desc = d; CREATE(d->character->player.name, char, strlen(tmp_name) + 1); strcpy(d->character->player.name, CAP(tmp_name)); GET_PFILEPOS(d->character) = player_i; sprintf(buf, "Did I get that right, %s (Y/N)? ", tmp_name); SEND_TO_Q(buf, d); STATE(d) = CON_NAME_CNFRM; } else { /* undo it just in case they are set */ REMOVE_BIT(PLR_FLAGS(d->character), PLR_WRITING | PLR_MAILING); REMOVE_BIT(AFF_FLAGS(d->character), AFF_PARTY); SEND_TO_Q("Password: ", d); echo_off(d); d->idle_tics = 0; STATE(d) = CON_PASSWORD; } } else { /* player unknown -- make new character */ /* Check for multiple creations of a character. */ if (!Valid_Name(tmp_name)) { SEND_TO_Q("Invalid name, please try another.\r\nName: ", d); return; } CREATE(d->character->player.name, char, strlen(tmp_name) + 1); strcpy(d->character->player.name, CAP(tmp_name)); sprintf(buf, "Did I get that right, %s (Y/N)? ", tmp_name); SEND_TO_Q(buf, d); STATE(d) = CON_NAME_CNFRM; } } break; case CON_NAME_CNFRM: /* wait for conf. of new name */ if (UPPER(*arg) == 'Y') { if (isbanned(d->host) >= BAN_NEW) { syslog(0, TRUE, "Request for new char %s denied from [%s] (siteban)", GET_PC_NAME(d->character), d->host); SEND_TO_Q("Sorry, new characters are not allowed from your site!\r\n", d); STATE(d) = CON_CLOSE; return; } if (wizlock_level) { if (!wizlock_message) SEND_TO_Q("Sorry, new players can't be created at the moment.\r\n", d); else SEND_TO_Q(wizlock_message, d); syslog(0, TRUE, "Request for new char %s denied from [%s] (wizlock)", GET_PC_NAME(d->character), d->host); STATE(d) = CON_CLOSE; return; } SEND_TO_Q("New character.\r\n\r\n", d); sprintf(buf, "Give me a password for %s: ", GET_PC_NAME(d->character)); SEND_TO_Q(buf, d); echo_off(d); STATE(d) = CON_NEWPASSWD; } else if (*arg == 'n' || *arg == 'N') { SEND_TO_Q("Okay, what IS it, then? ", d); free(d->character->player.name); d->character->player.name = NULL; STATE(d) = CON_GET_NAME; } else { SEND_TO_Q("Please type Yes or No: ", d); } break; case CON_PASSWORD: /* get pwd for known player */ /* * To really prevent duping correctly, the player's record should * be reloaded from disk at this point (after the password has been * typed). However I'm afraid that trying to load a character over * an already loaded character is going to cause some problem down the * road that I can't see at the moment. So to compensate, I'm going to * (1) add a 15 or 20-second time limit for entering a password, and (2) * re-add the code to cut off duplicates when a player quits. JE 6 Feb 96 */ /* turn echo back on */ echo_on(d); /* New echo_on() eats the return on telnet. Extra space better than none. */ SEND_TO_Q("\r\n", d); if (!*arg) STATE(d) = CON_CLOSE; else { if (strncmp(CRYPT(arg, GET_PASSWD(d->character)), GET_PASSWD(d->character), MAX_PWD_LENGTH)) { syslog(0, TRUE, "BAD PW: %s [%s]", GET_NAME(d->character), d->host); GET_BAD_PWS(d->character)++; SAVE_CHAR(d->character); if (++(d->bad_pws) >= max_bad_pws) { /* 3 strikes and you're out. */ SEND_TO_Q("Wrong password... disconnecting.\r\n", d); STATE(d) = CON_CLOSE; } else { SEND_TO_Q("Wrong password.\r\nPassword: ", d); echo_off(d); } return; } /* Password was correct. */ load_result = GET_BAD_PWS(d->character); GET_BAD_PWS(d->character) = 0; d->bad_pws = 0; if (isbanned(d->host) == BAN_SELECT && !PLR_FLAGGED(d->character, PLR_SITEOK)) { SEND_TO_Q("Sorry, this character has not been cleared for login from your site!\r\n", d); STATE(d) = CON_CLOSE; syslog(0, TRUE, "Connection attempt for %s denied from %s", GET_NAME(d->character), d->host); return; } if (GET_LEVEL(d->character) < wizlock_level) { if (wizlock_message) SEND_TO_Q(wizlock_message, d); else SEND_TO_Q("The game is temporarily restricted.. try again later.\r\n", d); STATE(d) = CON_CLOSE; syslog(0, TRUE, "Request for login denied for %s [%s] (wizlock)", GET_NAME(d->character), d->host); return; } /* check and make sure no other copies of this player are logged in */ if (!check_multiplaying(d)) { SEND_TO_Q("\r\n\033[31mAccess Denied: Multiplaying detected\033[0m\r\n", d); SEND_TO_Q("There is already someone logged in from the same IP address as you. If you\r\n", d); SEND_TO_Q("are controlling that character, you must remove it from the game before this\r\n", d); SEND_TO_Q("character can enter. Rarely, computers may share IP addresses. If this is\r\n", d); SEND_TO_Q("the case, exceptions may be granted. You will need to petition the staff\r\n", d); SEND_TO_Q("member in charge of authorization. When you are able to log into the mud,\r\n", d); SEND_TO_Q("type HELP AUTHORIZATION for the appropriate e-mail address, or contact the\r\n", d); SEND_TO_Q("staff member via the game.\r\n", d); SEND_TO_Q("\r\nPress ENTER to contine: ", d); syslog(0, TRUE, "Login denied: Multiplaying detected for %s [%s]", GET_NAME(d->character), d->host); STATE(d) = CON_GOODBYE; return; } if (perform_dupe_check(d)) return; send_motd(d); if (!PLR_FLAGGED(d->character, PLR_INVSTART)) syslog(GET_INVIS_LEV(d->character), TRUE, "%s [%s] has connected.", GET_NAME(d->character), PLR_FLAGGED(d->character, PLR_IPMASK) ? "masked" : d->host); /* Check bad passwords */ if (load_result) { sprintf(buf, "\r\n\r\n\007\007\007&1%d LOGIN FAILURE%s SINCE LAST SUCCESSFUL LOGIN.&0\r\n", load_result, (load_result > 1) ? "S" : ""); SEND_TO_Q(buf, d); GET_BAD_PWS(d->character) = 0; } /* Check previous logon */ if (d->character->prev_host) { sprintf(buf, "Your last%s login was on %6.10s from %s.\r\n", load_result ? " attempted" : "", ctime(&d->character->prev_logon), d->character->prev_host); SEND_TO_Q(buf, d); } SEND_TO_Q("\r\n*** Press ENTER: ", d); STATE(d) = CON_RMOTD; } break; case CON_NEWPASSWD: case CON_CHPWD_GETNEW: if (!*arg || strlen(arg) > MAX_PWD_LENGTH || strlen(arg) < 3 || !str_cmp(arg, GET_PC_NAME(d->character))) { SEND_TO_Q("\r\nIllegal password.\r\n", d); SEND_TO_Q("Password: ", d); return; } strncpy(GET_PASSWD(d->character), CRYPT(arg, GET_PC_NAME(d->character)), MAX_PWD_LENGTH); *(GET_PASSWD(d->character) + MAX_PWD_LENGTH) = '\0'; SEND_TO_Q("\r\nPlease retype password: ", d); if (STATE(d) == CON_NEWPASSWD) STATE(d) = CON_CNFPASSWD; else STATE(d) = CON_CHPWD_VRFY; break; case CON_CNFPASSWD: case CON_CHPWD_VRFY: if (strncmp(CRYPT(arg, GET_PASSWD(d->character)), GET_PASSWD(d->character), MAX_PWD_LENGTH)) { SEND_TO_Q("\r\nPasswords don't match... start over.\r\n", d); SEND_TO_Q("Password: ", d); if (STATE(d) == CON_CNFPASSWD) STATE(d) = CON_NEWPASSWD; else STATE(d) = CON_CHPWD_GETNEW; return; } echo_on(d); if (STATE(d) == CON_CNFPASSWD) { SEND_TO_Q("\r\nWould you like a last name (y/N)? ", d); STATE(d) = CON_QLAST_NAME; } else { SAVE_CHAR(d->character); echo_on(d); SEND_TO_Q("\r\nDone.\r\n", d); if (GET_LEVEL(d->character) < LVL_APPROVED) SEND_TO_Q(AUTH_MESSG, d); display_statistics_to_char(d->character); SEND_TO_Q(MENU, d); STATE(d) = CON_MENU; } break; case CON_QLAST_NAME: /* Want a last name? */ if (UPPER(*arg) == 'Y') { SEND_TO_Q("\r\nEnter your last name: ", d); STATE(d) = CON_SLAST_NAME; } else if (UPPER(*arg) == 'N') { GET_LASTNAME(d->character) = NULL; SEND_TO_Q("\r\nWhat is your sex (M/F)? ", d); STATE(d) = CON_QSEX; /* Please crash_delete here */ break; } else SEND_TO_Q("\r\nPlease type Yes or No: ", d); break; case CON_SLAST_NAME: /* What's yer last name? */ if (!*arg) { SEND_TO_Q("\r\nEnter a last name: ", d); return; } else { if ((_parse_name(arg, tmp_name)) || !Valid_Name(tmp_name) || strlen(tmp_name) < 2 || strlen(tmp_name) > MAX_NAME_LENGTH || fill_word(strcpy(buf, tmp_name)) || reserved_word(buf)) { SEND_TO_Q("\r\nInvalid last name, please try another.\r\n" "Enter a last name: ", d); return; } if (GET_LASTNAME(d->character)) free(d->character->player.lastname); GET_LASTNAME(d->character) = str_dup(tmp_name); sprintf(buf, "\r\nDid I get that right, %s %s (Y/N)? ", d->character->player.name, tmp_name); SEND_TO_Q(buf, d); STATE(d) = CON_CLAST_NAME; } break; case CON_CLAST_NAME: /* Wait for conf. of last name */ if (UPPER(*arg) == 'Y') { SEND_TO_Q("\r\nWhat is your sex (M/F)? ", d); STATE(d) = CON_QSEX; } else if (UPPER(*arg) == 'N') { SEND_TO_Q("Okay, what IS it, then? ", d); free(d->character->player.lastname); d->character->player.lastname = NULL; STATE(d) = CON_SLAST_NAME; } else SEND_TO_Q("Please type Yes or No: ", d); break; case CON_QSEX: /* query sex of new user */ switch (LOWER(*arg)) { case 'm': d->character->player.sex = SEX_MALE; break; case 'f': d->character->player.sex = SEX_FEMALE; break; default: SEND_TO_Q("That is not a sex..\r\nWhat IS your sex? ", d); return; } SEND_TO_Q("\r\nDo you want color on? ", d); STATE(d) = CON_QCOLOR; break; case CON_QCOLOR: switch (LOWER(*arg)) { case 'y': SET_BIT(PRF_FLAGS(d->character), PRF_COLOR); break; case 'n': break; default: SEND_TO_Q("Please type YES or NO: ", d); return; } /* We set all Attributes to 1 now because the "races" diverge in creation */ d->character->real_abils.strength = 1; d->character->real_abils.dexterity = 1; d->character->real_abils.stamina = 1; d->character->real_abils.charisma = 1; d->character->real_abils.manipulation = 1; d->character->real_abils.appearance = 1; d->character->real_abils.perception = 1; d->character->real_abils.intelligence = 1; d->character->real_abils.wits = 1; SEND_TO_Q("\r\nHardcore Character:\r\n", d); SEND_TO_Q(" - Permanent death\r\n", d); SEND_TO_Q(" - More powerful abilities\r\n", d); SEND_TO_Q(" - More clan choices\r\n", d); SEND_TO_Q(" - More disciplines\r\n", d); SEND_TO_Q("Please consider this carefully! You can't change your mind if you choose yes.\r\n", d); SEND_TO_Q("Do you want your character to be hardcore? ", d); STATE(d) = CON_QHARDCORE; break; case CON_QPREV_HARDCORE: switch (LOWER(*arg)) { case 'y': SEND_TO_Q("\r\nPlease type the name of your former hardcore character: ", d); STATE(d) = CON_LOAD_HARDCORE_NAME; return; case 'n': SEND_TO_Q("\r\nPress ENTER to choose status.", d); STATE(d) = CON_PROMPT_STATUS; return; default: SEND_TO_Q("Please type YES or NO: ", d); return; } break; case CON_LOAD_HARDCORE_NAME: if (!*arg) { SEND_TO_Q("\r\nEnter a name: ", d); return; } if (!(d->temp_char)) { CREATE(d->temp_char, struct char_data, 1); clear_char(d->temp_char); } if ((player_i = load_char(arg, &tmp_store)) > NOBODY) store_to_char(&tmp_store, d->temp_char); else { free(d->temp_char); SEND_TO_Q("\r\nThere is no such character.\r\n", d); SEND_TO_Q("\r\nPress ENTER to choose status.", d); STATE(d) = CON_PROMPT_STATUS; return; } if (!PLR_FLAGGED(d->temp_char, PLR_SLAIN) || PLR_FLAGGED(d->temp_char, PLR_DELETED)) { SEND_TO_Q("Unable to load valid hardcore character.\r\n", d); SEND_TO_Q("\r\nPress ENTER to choose status.", d); STATE(d) = CON_PROMPT_STATUS; return; } SEND_TO_Q("\r\nCharacter loaded. Password: ", d); echo_off(d); STATE(d) = CON_LOAD_HARDCORE_PWORD; break; case CON_LOAD_HARDCORE_PWORD: if (!*arg) { SEND_TO_Q("\r\nEnter password: ", d); return; } echo_on(d); if (strncmp(CRYPT(arg, GET_PASSWD(d->temp_char)), GET_PASSWD(d->temp_char), MAX_PWD_LENGTH)) { SEND_TO_Q("\r\nInvalid password. Hardcore character not loaded.\r\n", d); SEND_TO_Q("\r\nPress ENTER to choose status.", d); free(d->temp_char); STATE(d) = CON_PROMPT_STATUS; return; } if (!validate_autoauthorize(d, GET_EMAIL(d->temp_char), GET_IDNUM(d->temp_char))) { SEND_TO_Q("\r\nThe hardcore system was unable to auto-authorize you or verify your hardcore status.\r\n", d); SEND_TO_Q("Hardcore character not loaded.\r\n", d); SEND_TO_Q("\r\nPress ENTER to choose status.", d); free(d->temp_char); STATE(d) = CON_PROMPT_STATUS; return; } playing_time = *real_time_passed(d->temp_char->player.time.played, 0); i = (playing_time.day * 2) + (playing_time.hours >= 12 ? 2 : 0); i += GET_EXPERIENCE(d->temp_char); i = MAX(0, MIN(EXP_CAP, i)); d->character->points.experience = i; GET_LEVEL(d->character) = LVL_APPROVED; GET_EMAIL(d->character) = str_dup(GET_EMAIL(d->temp_char)); SET_BIT(PLR_FLAGS(d->temp_char), PLR_DELETED); save_char(d->temp_char, NOWHERE); free_char(d->temp_char); //remove the one xp granted to new chars d->character->points.experience -= 1; sprintf(buf, "%d experience granted.\r\n", i); SEND_TO_Q(buf, d); SEND_TO_Q("Previous hardcore character deleted.\r\n", d); SEND_TO_Q("\r\nPress ENTER to choose status.", d); STATE(d) = CON_PROMPT_STATUS; break; case CON_QHARDCORE: /* Decide about being a hardcore player */ switch (LOWER(*arg)) { case 'y': SET_BIT(PLR_FLAGS(d->character), PLR_HARDCORE); SEND_TO_Q("\r\nDo you have a previously slain hardcore character? ", d); STATE(d) = CON_QPREV_HARDCORE; return; case 'n': SEND_TO_Q("Please type YES: ", d); return; default: SEND_TO_Q("Please type YES: ", d); return; } /* This BREAK is left out intentionally */ case CON_PROMPT_STATUS: SEND_TO_Q("\r\nCharacter Status:\r\n", d); SEND_TO_Q(" 1. Human - A focus on skills and abilities; humans are a challenge\r\n", d); SEND_TO_Q(" to play but are well-rewarded with skills.\r\n", d); SEND_TO_Q(" 2. Vampire - Undead and scorned by the sun, vampires are split into\r\n", d); SEND_TO_Q(" clans with unique powers and ablities. Each vampire begins\r\n", d); SEND_TO_Q(" with a haven, a home free of sunlight.\r\n", d); SEND_TO_Q(" You may become a vampire later in the game if you choose Human.\r\n", d); SEND_TO_Q(" 3. Werewolf - Gifted by Luna, the Garou are far stronger and fiercer than any\r\n", d); SEND_TO_Q(" of nature's creations! They are thus hardcore-only.\r\n", d); SEND_TO_Q("\r\n", d); SEND_TO_Q("Choose a number: ", d); STATE(d) = CON_CHOOSE_STATUS; break; case CON_CHOOSE_STATUS: /* Choose Human/Vampire */ switch (*arg) { case '1': break; case '2': SET_BIT(PLR_FLAGS(d->character), PLR_VAMPIRE); SEND_TO_Q("\r\nChoose a clan:\r\n", d); for (i = 0; i < NUM_CLANS; i++) if (clan[i].can_pick) { sprintf(buf, " %s%2d. %-15.15s %s", clan[i].hardcore ? "*" : " ", i+1, clan[i].name, !((i+1)%2) ? "\r\n" : ""); SEND_TO_Q(buf, d); } SEND_TO_Q("\r\n* Hardcore character only\r\n", d); SEND_TO_Q("Please see our web site for information on each clan.\r\n", d); SEND_TO_Q("> ", d); STATE(d) = CON_QCLAN; return; case '3': if (!IS_HARDCORE(d->character)) { SEND_TO_Q("\r\nYou must be hardcore to be a werewolf!\r\n> ", d); return; } SET_BIT(PLR_FLAGS(d->character), PLR_WEREWOLF); SEND_TO_Q("\r\nChoose a Breed (birth form):\r\n", d); SEND_TO_Q(" 1. Homid\r\n", d); SEND_TO_Q(" 2. Metis\r\n", d); SEND_TO_Q(" 3. Lupus\r\n", d); SEND_TO_Q("> ", d); STATE(d) = CON_BREED_FORM; return; default: SEND_TO_Q("Please choose a number: ", d); return; } STATE(d) = CON_CUSTOMIZE; SEND_TO_Q("Would you like to customize your Attributes and Abilities (y/n)? ", d); break; case CON_BREED_FORM: if ((i = atoi(arg)) < 1 || i > 3) { SEND_TO_Q("\r\nInvalid choice.\r\n> ", d); return; } GET_BREED(d->character) = i - 1; SEND_TO_Q("\r\nChoose an Auspice (phase of the moon under which you were born):\r\n", d); SEND_TO_Q(" 1. Ragabash (new moon)\r\n", d); SEND_TO_Q(" 2. Theurge (crescent moon)\r\n", d); SEND_TO_Q(" 3. Philodox (half moon)\r\n", d); SEND_TO_Q(" 4. Galliard (gibbous moon)\r\n", d); SEND_TO_Q(" 5. Ahroun (full moon)\r\n", d); SEND_TO_Q("> ", d); STATE(d) = CON_AUSPICE; break; case CON_AUSPICE: if ((i = atoi(arg)) < 1 || i > 5) { SEND_TO_Q("\r\nInvalid choice.\r\n> ", d); return; } GET_AUSPICE(d->character) = i - 1; SEND_TO_Q("\r\nChoose a Tribe:\r\n", d); for (i = 0; i < NUM_TRIBES; i++) { sprintf(buf, " %2d. %s\r\n", i + 1, tribe[i].name); SEND_TO_Q(buf, d); } SEND_TO_Q("> ", d); STATE(d) = CON_TRIBE; break; case CON_TRIBE: if ((i = atoi(arg) - 1) < 0 || i >= NUM_TRIBES) { SEND_TO_Q("Invalid choice.\r\n> ", d); return; } GET_REAL_TRIBE(d->character) = i; STATE(d) = CON_CUSTOMIZE; SEND_TO_Q("Would you like to customize your Attributes and Abilities (y/n)? ", d); break; case CON_CUSTOMIZE: switch (LOWER(*arg)) { case 'y': STATE(d) = CON_CHOOSE_ATTRIBUTES; d->character->player_specials->create_points = 15; SEND_TO_Q("Press ENTER to choose Attributes: ", d); break; case 'n': d->character->real_abils.strength = 3; d->character->real_abils.dexterity = 3; d->character->real_abils.stamina = 2; /* Clan Weakness: Nosferatu */ if (GET_CLAN(d->character) == CLAN_NOSFERATU) { d->character->real_abils.charisma = 3; d->character->real_abils.manipulation = 4; d->character->real_abils.appearance = 0; } else { d->character->real_abils.charisma = 3; d->character->real_abils.manipulation = 3; d->character->real_abils.appearance = 2; } d->character->real_abils.perception = 3; d->character->real_abils.intelligence = 3; d->character->real_abils.wits = 2; d->character->player_specials->saved.talents[TALENT_ACTING] = 0; d->character->player_specials->saved.talents[TALENT_ALERTNESS] = 1; d->character->player_specials->saved.talents[TALENT_ATHLETICS] = 1; d->character->player_specials->saved.talents[TALENT_BRAWL] = 1; d->character->player_specials->saved.talents[TALENT_DODGE] = 1; d->character->player_specials->saved.talents[TALENT_EMPATHY] = 1; d->character->player_specials->saved.talents[TALENT_INTIMIDATION] = 1; d->character->player_specials->saved.talents[TALENT_LARCENY] = 1; d->character->player_specials->saved.talents[TALENT_LEADERSHIP] = 1; if (IS_WEREWOLF(d->character)) d->character->player_specials->saved.talents[TALENT_PRIMAL_URGE] = 2; d->character->player_specials->saved.talents[TALENT_SUBTERFUGE] = 0; d->character->player_specials->saved.skills[SKILL_ANIMAL_KEN] = 1; d->character->player_specials->saved.skills[SKILL_ARCHERY] = 1; d->character->player_specials->saved.skills[SKILL_CRAFTS] = 2; d->character->player_specials->saved.skills[SKILL_ETIQUETTE] = 1; d->character->player_specials->saved.skills[SKILL_HERBALISM] = 1; d->character->player_specials->saved.skills[SKILL_MELEE] = 1; d->character->player_specials->saved.skills[SKILL_MUSIC] = 1; d->character->player_specials->saved.skills[SKILL_PERFORMANCE] = 0; d->character->player_specials->saved.skills[SKILL_RIDE] = 1; d->character->player_specials->saved.skills[SKILL_STEALTH] = 1; d->character->player_specials->saved.skills[SKILL_SURVIVAL] = 0; d->character->player_specials->saved.knowledges[KNOWLEDGE_ACADEMICS] = 1; if (IS_WEREWOLF(d->character)) d->character->player_specials->saved.knowledges[KNOWLEDGE_ENIGMAS] = 2; d->character->player_specials->saved.knowledges[KNOWLEDGE_HEARTH_WISDOM] = 1; d->character->player_specials->saved.knowledges[KNOWLEDGE_INVESTIGATION] = 1; d->character->player_specials->saved.knowledges[KNOWLEDGE_LAW] = 0; d->character->player_specials->saved.knowledges[KNOWLEDGE_LINGUISTICS] = 1; d->character->player_specials->saved.knowledges[KNOWLEDGE_MEDICINE] = 1; d->character->player_specials->saved.knowledges[KNOWLEDGE_OCCULT] = 1; d->character->player_specials->saved.knowledges[KNOWLEDGE_POLITICS] = 1; d->character->player_specials->saved.knowledges[KNOWLEDGE_SCIENCE] = 2; d->character->player_specials->saved.knowledges[KNOWLEDGE_SENESCHAL] = 0; /* See also: CON_CHOOSE_ABILITIES */ if (IS_VAMPIRE(d->character)) { STATE(d) = CON_CHOOSE_VIRTUES; d->character->player_specials->create_points = 7; d->character->points.conscience = 1; d->character->points.self_control = 1; d->character->points.courage = 1; SEND_TO_Q("\r\nPress ENTER to choose Virtues: ", d); break; } else if (IS_WEREWOLF(d->character)) { STATE(d) = CON_ADVANTAGES_W; d->character->points.humanity = 10; assign_werewolf_advantages(d); d->character->player_specials->create_points = 7; SEND_TO_Q("\r\nPress ENTER to choose Advantages: ", d); break; } else /* is_human */ { d->character->points.max_willpower = number(2, 5); d->character->points.humanity = 10; STATE(d) = CON_APPEARANCE; SEND_TO_Q("\r\nPress ENTER to finish character creation: ", d); break; } break; default: SEND_TO_Q("Please type YES or NO: ", d); return; } break; case CON_QCLAN: if ((i = atoi(arg) - 1) < 0 || i >= NUM_CLANS) { SEND_TO_Q("Invalid choice.\r\n> ", d); return; } if (!clan[i].can_pick) { SEND_TO_Q("You can't pick that clan!\r\n", d); return; } if (clan[i].hardcore && !IS_HARDCORE(d->character)) { SEND_TO_Q("You must be a Hardcore character to choose that clan!\r\n> ", d); return; } GET_REAL_CLAN(d->character) = i; /* Clan Weakness: Nosferatu */ if (GET_CLAN(d->character) == CLAN_NOSFERATU) d->character->real_abils.appearance = 0; STATE(d) = CON_CUSTOMIZE; SEND_TO_Q("Would you like to customize your Attributes and Abilities (y/n)? ", d); break; case CON_QHEIGHT: if ((i = atoi(arg)) < 1 || i > 5) { SEND_TO_Q("Invalid choice.\r\n> ", d); return; } switch (i) { case 1: if (d->character->player.sex == SEX_MALE) d->character->player.height = number(60, 64); else d->character->player.height = number(53, 56); break; case 2: if (d->character->player.sex == SEX_MALE) d->character->player.height = number(64, 66); else d->character->player.height = number(56, 59); break; case 3: if (d->character->player.sex == SEX_MALE) d->character->player.height = number(66, 70); else d->character->player.height = number(59, 62); break; case 4: if (d->character->player.sex == SEX_MALE) d->character->player.height = number(70, 74); else d->character->player.height = number(62, 64); break; case 5: if (d->character->player.sex == SEX_MALE) d->character->player.height = number(74, 78); else d->character->player.height = number(64, 66); break; default: SEND_TO_Q("Invalid choice.\r\n> ", d); return; } SEND_TO_Q("\r\nHow would you describe your weight:\r\n", d); SEND_TO_Q(" 1. Anorexic\r\n", d); SEND_TO_Q(" 2. Scrawny\r\n", d); SEND_TO_Q(" 3. Healthy\r\n", d); SEND_TO_Q(" 4. Well-fed\r\n", d); SEND_TO_Q(" 5. Obese\r\n", d); SEND_TO_Q("> ", d); STATE(d) = CON_QWEIGHT; break; case CON_QWEIGHT: i = atoi(arg); switch (i) { case 1: if (d->character->player.sex == SEX_MALE) d->character->player.weight = number(90, 100); else d->character->player.weight = number(80, 90); break; case 2: if (d->character->player.sex == SEX_MALE) d->character->player.weight = number(100, 120); else d->character->player.weight = number(90, 105); break; case 3: if (d->character->player.sex == SEX_MALE) d->character->player.weight = number(120, 160); else d->character->player.weight = number(105, 130); break; case 4: if (d->character->player.sex == SEX_MALE) d->character->player.weight = number(160, 200); else d->character->player.weight = number(130, 175); break; case 5: if (d->character->player.sex == SEX_MALE) d->character->player.weight = number(200, 240); else d->character->player.weight = number(175, 200); break; default: SEND_TO_Q("Invalid choice.\r\n> ", d); return; } SEND_TO_Q("\r\nDescribe your complexions:\r\n", d); for (i = 0; i < NUM_SKINS; i++) { sprintf(buf, "%2d. %s\r\n", i+1, skin_colors[i]); SEND_TO_Q(buf, d); } SEND_TO_Q("> ", d); STATE(d) = CON_QSKIN; break; case CON_QSKIN: if ((i = atoi(arg)) < 1 || i > NUM_SKINS) { SEND_TO_Q("Invalid choice.\r\n> ", d); return; } GET_SKIN(d->character) = i - 1; SEND_TO_Q("\r\nWhat color is your hair:\r\n", d); for (i = 0; i < NUM_HAIRS; i++) { sprintf(buf, "%2d. %s\r\n", i+1, hair_colors[i]); SEND_TO_Q(buf, d); } SEND_TO_Q("> ", d); STATE(d) = CON_QHAIR; break; case CON_QHAIR: if ((i = atoi(arg)) < 1 || i > NUM_HAIRS) { SEND_TO_Q("Invalid choice.\r\n> ", d); return; } GET_HAIR(d->character) = i - 1; SEND_TO_Q("\r\nWhat color are your eyes:\r\n", d); for (i = 0; i < NUM_EYES; i++) { sprintf(buf, "%2d. %s\r\n", i+1, eye_colors[i]); SEND_TO_Q(buf, d); } SEND_TO_Q("> ", d); STATE(d) = CON_QEYES; break; case CON_QEYES: if ((i = atoi(arg)) < 1 || i > NUM_EYES) { SEND_TO_Q("Invalid choice.\r\n> ", d); return; } GET_EYES(d->character) = i - 1; d->character->player_specials->create_points = GET_LINGUISTICS(d->character) + 1; if (d->character->player_specials->create_points > 0) { sprintf(buf, "\r\nSelect %d Languages (by number):\r\n", d->character->player_specials->create_points); SEND_TO_Q(buf, d); *buf = '\0'; for (i = 0; i < NUM_LANGS; i++) if (i != LANG_LATIN && i != LANG_FERAL_SPEECH && i != LANG_HIGH_TONGUE) sprintf(buf + strlen(buf), " %d. %s\r\n", i + 1, langs[i]); SEND_TO_Q(buf, d); SEND_TO_Q("> ", d); } else SEND_TO_Q("\r\n*** Press ENTER: ", d); STATE(d) = CON_LANGUAGE; break; case CON_LANGUAGE: case CON_LANGUAGE_MENU: if (d->character->player_specials->create_points > 0) { if ((i = atoi(arg)) < 1 || i > NUM_LANGS || (i - 1) == LANG_LATIN || (i - 1) == LANG_FERAL_SPEECH || (i - 1) == LANG_HIGH_TONGUE) { SEND_TO_Q("Invalid choice.\r\n> ", d); return; } if (IS_SET(GET_LANGUAGES(d->character), LANGUAGE_BIT(i-1))) { if (STATE(d) == CON_LANGUAGE_MENU) SEND_TO_Q("You can't remove a language!\r\n", d); else { REMOVE_BIT(GET_LANGUAGES(d->character), LANGUAGE_BIT(i - 1)); d->character->player_specials->create_points += 1; sprintf(buf, "Language %s removed.\r\n", langs[i - 1]); SEND_TO_Q(buf, d); } } else { /* Speaking always defaults to the first language chosen */ if (!GET_LANGUAGES(d->character)) SET_SPEAKING(d->character) = i - 1; SET_BIT(GET_LANGUAGES(d->character), LANGUAGE_BIT(i - 1)); d->character->player_specials->create_points -= 1; sprintf(buf, "Language %s added.\r\n", langs[i - 1]); SEND_TO_Q(buf, d); } if (d->character->player_specials->create_points > 0) { SEND_TO_Q("> ", d); return; } } if (STATE(d) == CON_LANGUAGE_MENU) { display_statistics_to_char(d->character); SEND_TO_Q(MENU, d); STATE(d) = CON_MENU; break; } /* Check for autoauth */ if (LVL_APPROVED > 1 && GET_LEVEL(d->character) < LVL_APPROVED) { SEND_TO_Q("\r\n", d); SEND_TO_Q(" AUTHORIZATION\r\n", d); SEND_TO_Q("EmpireMUD requires characters to be authorized to utilize all of its features.\r\n", d); SEND_TO_Q("This helps promote fair play and equal opportunity for all players. So that\r\n", d); SEND_TO_Q("our players are not inconvenienced, we have a system for automatically\r\n", d); SEND_TO_Q("authorizing people. Only one authorized character is allowed per person.\r\n", d); SEND_TO_Q(" To be authorized, you need:\r\n", d); SEND_TO_Q(" * a valid e-mail address\r\n", d); SEND_TO_Q(" * to be able to reply to an e-mail within a few days\r\n", d); SEND_TO_Q(" Please make sure:\r\n", d); SEND_TO_Q(" * if you already have an authorized character, it must be deleted first -\r\n", d); SEND_TO_Q(" you may do that now, while waiting at this menu\r\n", d); SEND_TO_Q(" * if you're on a friend's computer and your friend has an authorized\r\n", d); SEND_TO_Q(" character, auto-authorization will probably fail\r\n", d); SEND_TO_Q("\r\nDo you want to autoauthorize (y/n): ", d); STATE(d) = CON_AUTOAUTH; } else { SEND_TO_Q("\r\n*** Press ENTER: ", d); STATE(d) = CON_FINISH_CREATION; } break; case CON_QEMAIL: if (!*arg || !strstr(arg, "@")) { SEND_TO_Q("You must supply a valid e-mail address, containing an @.\r\n> ", d); return; } if (!validate_autoauthorize(d, arg, -1)) { SEND_TO_Q("\r\n AUTO-AUTHORIZATION FAILED\r\n", d); SEND_TO_Q("EmpireMUD failed to automatically authorize you for one of the reasons listed\r\n", d); SEND_TO_Q("below. You will need to send an e-mail to the administration requesting that\r\n", d); SEND_TO_Q("your character be authorized. The current address is listed when you type\r\n", d); SEND_TO_Q("HELP AUTORIZATION from within the mud.\r\n", d); SEND_TO_Q("Reasons for autoauthorize to fail:\r\n", d); SEND_TO_Q(" * another character from the same IP is currently logged in\r\n", d); SEND_TO_Q(" * another character has an identical e-mail address\r\n", d); } else { SEND_TO_Q("\r\n AUTO-AUTHORIZATION SUCCESSFUL\r\n", d); SEND_TO_Q("You will be sent an e-mail within the next few days. You MUST respond to this\r\n", d); SEND_TO_Q("e-mail or your character will be unauthorized. If the e-mail cannot be\r\n", d); SEND_TO_Q("delivered, even if it's because of an error in your mail system, you will be\r\n", d); SEND_TO_Q("unauthorized. If this happens, you will be notified via mudmail. You may\r\n", d); SEND_TO_Q("also type HELP AUTHORIZATION from within the mud to obtain the e-mail address\r\n", d); SEND_TO_Q("for the administration if you need to contact them.\r\n", d); SEND_TO_Q(" * You may only have 1 authorized character\r\n", d); } SEND_TO_Q("\r\n*** Press ENTER: ", d); STATE(d) = CON_FINISH_CREATION; break; case CON_AUTOAUTH: switch (LOWER(*arg)) { case 'y': SEND_TO_Q("\r\nEnter your full e-mail address: ", d); STATE(d) = CON_QEMAIL; return; case 'n': break; default: SEND_TO_Q("Please type YES or NO: ", d); return; } /* there is no break here because autoauth links back to here */ case CON_FINISH_CREATION: if (GET_PFILEPOS(d->character) < 0) GET_PFILEPOS(d->character) = create_entry(GET_PC_NAME(d->character)); /* Now GET_NAME() will work properly. */ if (GET_LEVEL(d->character) == 0) GET_LEVEL(d->character) = 1; init_char(d->character); SAVE_CHAR(d->character); send_motd(d); SEND_TO_Q("\r\n*** Press ENTER: ", d); STATE(d) = CON_RMOTD; syslog(0, TRUE, "NEW: %s [%s]", GET_NAME(d->character), d->host); break; case CON_CHOOSE_ATTRIBUTES: /* * This is very simple: if buf1 is nothing, it simply repeats the * output. Otherwise, it makes the change requested and displays * the statistics. */ if (*arg) { two_arguments(arg, buf, buf1); if (is_abbrev(buf, "add")) { if (d->character->player_specials->create_points <= 0) { SEND_TO_Q("\r\nYou have no more Attribute points.\r\n", d); *buf1 = '\0'; } else add = TRUE; } else if (is_abbrev(buf, "subtract")) subtract = TRUE; else if (is_abbrev(buf, "help")) { SEND_TO_Q("\r\nAttributes:\r\n", d); SEND_TO_Q(" Strength - Amount you can carry, Damage with melee weapons\r\n", d); SEND_TO_Q(" Dexterity - Ability to attack/dodge\r\n", d); SEND_TO_Q(" Stamina - Ability to absorb damage\r\n", d); SEND_TO_Q(" Charisma - Social interactions and abilities\r\n", d); SEND_TO_Q(" Manipulation - Forcing tasks upon others\r\n", d); SEND_TO_Q(" Appearance - Looks, Visual abilities\r\n", d); SEND_TO_Q(" Perception - Noticing things, Seeing through abilities\r\n", d); SEND_TO_Q(" Intelligence - Calling upon knowledge\r\n", d); SEND_TO_Q(" Wits - Fast thinking\r\n", d); SEND_TO_Q("\r\nPress ENTER to contine: ", d); break; } else if (is_abbrev(buf, "done")) { if (d->character->player_specials->create_points > 0) SEND_TO_Q("\r\nYou still have points left to assign.\r\n", d); else { STATE(d) = CON_CHOOSE_ABILITIES; d->character->player_specials->create_points = 27; SEND_TO_Q("\r\nPress ENTER to choose Abilities: ", d); break; } } else *buf1 = '\0'; } else *buf1 = '\0'; /* * Determine current Attributes * Clan Weakness: Nosferatu * There is a special clause for Appearance which states that it * counts it as 1 at a minimum, this is merely for catalog purposes * as the Appearance Trait MAY be zero. */ physical = d->character->real_abils.strength + d->character->real_abils.dexterity + d->character->real_abils.stamina; social = d->character->real_abils.charisma + d->character->real_abils.manipulation + MAX(1, d->character->real_abils.appearance); mental = d->character->real_abils.perception + d->character->real_abils.intelligence + d->character->real_abils.wits; /* Modify Attributes: add or subtract */ Attribute_Modify("strength", d->character->real_abils.strength, physical, social, mental); Attribute_Modify("dexterity", d->character->real_abils.dexterity, physical, social, mental); Attribute_Modify("stamina", d->character->real_abils.stamina, physical, social, mental); Attribute_Modify("charisma", d->character->real_abils.charisma, social, physical, mental); Attribute_Modify("manipulation", d->character->real_abils.manipulation, social, physical, mental); /* Clan Weakness: Nosferatu */ if (GET_CLAN(d->character) != CLAN_NOSFERATU) Attribute_Modify("appearance", d->character->real_abils.appearance, social, physical, mental); Attribute_Modify("perception", d->character->real_abils.perception, mental, physical, social); Attribute_Modify("intelligence", d->character->real_abils.intelligence, mental, physical, social); Attribute_Modify("wits", d->character->real_abils.wits, mental, physical, social); SEND_TO_Q("\r\nAttributes:\r\n", d); display_attributes(d->character, d->character, TRUE); SEND_TO_Q("\r\n", d); sprintf(buf, " Points remaining: %d\r\n", d->character->player_specials->create_points); SEND_TO_Q(buf, d); SEND_TO_Q(" You must assign 7 points to one column, 5 to another, and 3 to the last.\r\n", d); SEND_TO_Q(" One initial point is given for free in all Attributes.\r\n", d); /* Clan Weakness: Nosferatu */ if (GET_CLAN(d->character) == CLAN_NOSFERATU) SEND_TO_Q(" * You may not raise your Appearance.\r\n", d); SEND_TO_Q("Commands: add <attribute> - Adds a point to any Attribute\r\n", d); SEND_TO_Q(" sub <attribute> - Removes a point from any Attribute\r\n", d); SEND_TO_Q(" help - Quick reference to Attributes\r\n", d); SEND_TO_Q(" done - Finish Attribute assigments\r\n", d); SEND_TO_Q("> ", d); break; case CON_CHOOSE_ABILITIES: /* * This is very simple: if buf1 is nothing, it simply repeats the * output. Otherwise, it makes the change requested and displays * the skills. */ if (*arg) { two_arguments(arg, buf, buf1); if (is_abbrev(buf, "add")) { if (d->character->player_specials->create_points <= 0) { SEND_TO_Q("\r\nYou have no more Ability points.\r\n", d); *buf1 = '\0'; } else add = TRUE; } else if (is_abbrev(buf, "subtract")) subtract = TRUE; else if (is_abbrev(buf, "help")) { SEND_TO_Q("\r\nAbilities:\r\n", d); SEND_TO_Q(" Acting - Putting on a show\r\n", d); SEND_TO_Q(" Alertness - Aware of surroundings\r\n", d); SEND_TO_Q(" Athletics - Grand feats, Throwing\r\n", d); SEND_TO_Q(" Brawl - Fighting barehanded or with claws\r\n", d); SEND_TO_Q(" Dodge - Avoiding hits\r\n", d); SEND_TO_Q(" Empathy - Sensing emotions/truths in others\r\n", d); SEND_TO_Q(" Intimidation - Controlling/threatening others\r\n", d); SEND_TO_Q(" Larceny - Stealing, Breaking and entering\r\n", d); SEND_TO_Q(" Leadership - Controlling/leading others\r\n", d); SEND_TO_Q(" Primal-Urge - Link to the wolves\r\n", d); SEND_TO_Q(" Subterfuge - Lying, Cheating\r\n", d); SEND_TO_Q(" Animal Ken - Animal-related tasks\r\n", d); SEND_TO_Q(" Archery - Ranged combat\r\n", d); SEND_TO_Q(" Crafts - Building, Forging\r\n", d); SEND_TO_Q(" Etiquette - General politeness\r\n", d); SEND_TO_Q(" Herbalism - Finding herbs\r\n", d); SEND_TO_Q(" Melee - Hand-to-hand combat\r\n", d); SEND_TO_Q(" Music - Singing\r\n", d); SEND_TO_Q(" Performance - Performing\r\n", d); SEND_TO_Q(" Ride - Riding an animal\r\n", d); SEND_TO_Q(" Stealth - Moving quietly\r\n", d); SEND_TO_Q(" Survival - Stealth in the wilderness\r\n", d); SEND_TO_Q(" Academics - Schooling, Reading\r\n", d); SEND_TO_Q(" Enigmas - Solving riddles\r\n", d); SEND_TO_Q(" Hearth Wisdom - General Knowledge\r\n", d); SEND_TO_Q(" Investigation - Finding things/information\r\n", d); SEND_TO_Q(" Law - Knowledge of the laws\r\n", d); SEND_TO_Q(" Linguistics - Knowledge of languages\r\n", d); SEND_TO_Q(" Medicine - Ability to heal using herbs\r\n", d); SEND_TO_Q(" Occult - Knowledge of the supernatural\r\n", d); SEND_TO_Q(" Politics - Ability to run an empire\r\n", d); SEND_TO_Q(" Science - Ability to use herbs\r\n", d); SEND_TO_Q(" Seneschal - Ability to run a manor\r\n", d); SEND_TO_Q("\r\nPress ENTER to contine: ", d); break; } else if (is_abbrev(buf, "done")) { if (d->character->player_specials->create_points > 0) SEND_TO_Q("\r\nYou still have points left to assign.\r\n", d); else { if (IS_VAMPIRE(d->character)) { STATE(d) = CON_CHOOSE_VIRTUES; d->character->player_specials->create_points = 7; d->character->points.conscience = 1; d->character->points.self_control = 1; d->character->points.courage = 1; SEND_TO_Q("\r\nPress ENTER to choose Virtues: ", d); break; } else if (IS_WEREWOLF(d->character)) { STATE(d) = CON_ADVANTAGES_W; d->character->points.humanity = 10; assign_werewolf_advantages(d); d->character->player_specials->create_points = 7; SEND_TO_Q("\r\nPress ENTER to choose Advantages: ", d); break; } else /* is_human */ { d->character->points.max_willpower = number(2, 5); d->character->points.humanity = 10; STATE(d) = CON_APPEARANCE; SEND_TO_Q("\r\nPress ENTER to finish character creation: ", d); break; } break; } } else *buf1 = '\0'; } else *buf1 = '\0'; /* Determine current Abilities */ for (i = 0, talents = 0; i < NUM_ABILITIES; i++) talents += d->character->player_specials->saved.talents[i]; for (i = 0, skills = 0; i < NUM_ABILITIES; i++) skills += d->character->player_specials->saved.skills[i]; for (i = 0, knowledges = 0; i < NUM_ABILITIES; i++) knowledges += d->character->player_specials->saved.knowledges[i]; /* Modify Abilities: add or subtract */ /* Talents */ Ability_Modify("acting", d->character->player_specials->saved.talents[TALENT_ACTING], talents, skills, knowledges); Ability_Modify("alertness", d->character->player_specials->saved.talents[TALENT_ALERTNESS], talents, skills, knowledges); Ability_Modify("athletics", d->character->player_specials->saved.talents[TALENT_ATHLETICS], talents, skills, knowledges); Ability_Modify("brawl", d->character->player_specials->saved.talents[TALENT_BRAWL], talents, skills, knowledges); Ability_Modify("dodge", d->character->player_specials->saved.talents[TALENT_DODGE], talents, skills, knowledges); Ability_Modify("empathy", d->character->player_specials->saved.talents[TALENT_EMPATHY], talents, skills, knowledges); Ability_Modify("intimidation", d->character->player_specials->saved.talents[TALENT_INTIMIDATION], talents, skills, knowledges); Ability_Modify("larceny", d->character->player_specials->saved.talents[TALENT_LARCENY], talents, skills, knowledges); Ability_Modify("leadership", d->character->player_specials->saved.talents[TALENT_LEADERSHIP], talents, skills, knowledges); Ability_Modify("primal-urge", d->character->player_specials->saved.talents[TALENT_PRIMAL_URGE], talents, skills, knowledges); Ability_Modify("subterfuge", d->character->player_specials->saved.talents[TALENT_SUBTERFUGE], talents, skills, knowledges); Ability_Modify("animal ken", d->character->player_specials->saved.skills[SKILL_ANIMAL_KEN], skills, talents, knowledges); Ability_Modify("archery", d->character->player_specials->saved.skills[SKILL_ARCHERY], skills, talents, knowledges); Ability_Modify("crafts", d->character->player_specials->saved.skills[SKILL_CRAFTS], skills, talents, knowledges); Ability_Modify("etiquette", d->character->player_specials->saved.skills[SKILL_ETIQUETTE], skills, talents, knowledges); Ability_Modify("herbalism", d->character->player_specials->saved.skills[SKILL_HERBALISM], skills, talents, knowledges); Ability_Modify("melee", d->character->player_specials->saved.skills[SKILL_MELEE], skills, talents, knowledges); Ability_Modify("music", d->character->player_specials->saved.skills[SKILL_MUSIC], skills, talents, knowledges); Ability_Modify("performance", d->character->player_specials->saved.skills[SKILL_PERFORMANCE], skills, talents, knowledges); Ability_Modify("ride", d->character->player_specials->saved.skills[SKILL_RIDE], skills, talents, knowledges); Ability_Modify("stealth", d->character->player_specials->saved.skills[SKILL_STEALTH], skills, talents, knowledges); Ability_Modify("survival", d->character->player_specials->saved.skills[SKILL_SURVIVAL], skills, talents, knowledges); Ability_Modify("academics", d->character->player_specials->saved.knowledges[KNOWLEDGE_ACADEMICS], knowledges, talents, skills); Ability_Modify("enigmas", d->character->player_specials->saved.knowledges[KNOWLEDGE_ENIGMAS], knowledges, talents, skills); Ability_Modify("hearth wisdom", d->character->player_specials->saved.knowledges[KNOWLEDGE_HEARTH_WISDOM], knowledges, talents, skills); Ability_Modify("investigation", d->character->player_specials->saved.knowledges[KNOWLEDGE_INVESTIGATION], knowledges, talents, skills); Ability_Modify("law", d->character->player_specials->saved.knowledges[KNOWLEDGE_LAW], knowledges, talents, skills); Ability_Modify("linguistics", d->character->player_specials->saved.knowledges[KNOWLEDGE_LINGUISTICS], knowledges, talents, skills); Ability_Modify("medicine", d->character->player_specials->saved.knowledges[KNOWLEDGE_MEDICINE], knowledges, talents, skills); Ability_Modify("occult", d->character->player_specials->saved.knowledges[KNOWLEDGE_OCCULT], knowledges, talents, skills); Ability_Modify("politics", d->character->player_specials->saved.knowledges[KNOWLEDGE_POLITICS], knowledges, talents, skills); Ability_Modify("science", d->character->player_specials->saved.knowledges[KNOWLEDGE_SCIENCE], knowledges, talents, skills); Ability_Modify("seneschal", d->character->player_specials->saved.knowledges[KNOWLEDGE_SENESCHAL], knowledges, talents, skills); SEND_TO_Q("\r\nAbilities:\r\n", d); display_abilities(d->character, d->character); SEND_TO_Q("\r\n", d); sprintf(buf, " Points remaining: %d\r\n", d->character->player_specials->create_points); SEND_TO_Q(buf, d); SEND_TO_Q(" You must assign 13 points to one column, 9 to another, and 5 to the last.\r\n", d); SEND_TO_Q("Commands: add <ability> - Adds a point to any Ability\r\n", d); SEND_TO_Q(" sub <ability> - Removes a point from any Ability\r\n", d); SEND_TO_Q(" help - Quick reference to Abilities\r\n", d); SEND_TO_Q(" done - Finish Ability assigments\r\n", d); SEND_TO_Q("> ", d); break; case CON_CHOOSE_VIRTUES: /* * This is very simple: if buf1 is nothing, it simply repeats the * output. Otherwise, it makes the change requested and displays * the virtues. */ if (*arg) { two_arguments(arg, buf, buf1); if (is_abbrev(buf, "add")) { if (d->character->player_specials->create_points <= 0) { SEND_TO_Q("\r\nYou have no more Virtue points.\r\n", d); *buf1 = '\0'; } else add = TRUE; } else if (is_abbrev(buf, "subtract")) subtract = TRUE; else if (is_abbrev(buf, "help")) { SEND_TO_Q("\r\nVirtues:\r\n", d); SEND_TO_Q(" Conscience - A moral sense of right and wrong.\r\n", d); SEND_TO_Q(" Self-Control - One's control over the Beast within.\r\n", d); SEND_TO_Q(" Courage - The ability to face one's fears.\r\n", d); SEND_TO_Q("\r\nPress ENTER to contine: ", d); break; } else if (is_abbrev(buf, "done")) { if (d->character->player_specials->create_points > 0) SEND_TO_Q("\r\nYou still have points left to assign.\r\n", d); else { GET_MAX_WILLPOWER(d->character) = GET_COURAGE(d->character); GET_HUMANITY(d->character) = GET_CONSCIENCE(d->character) + GET_SELF_CONTROL(d->character); STATE(d) = CON_CHOOSE_DISCIPLINES; d->character->player_specials->create_points = 4; SEND_TO_Q("\r\nPress ENTER to choose Disciplines: ", d); break; } } else *buf1 = '\0'; } else *buf1 = '\0'; if (*buf1 && is_abbrev(buf1, "conscience")) { if (add) { if (d->character->points.conscience >= 5) SEND_TO_Q("\r\nYou may not begin with any Virtue greater than 5.\r\n", d); else { d->character->points.conscience += 1; d->character->player_specials->create_points -= 1; } } else if (subtract) { if (d->character->points.conscience <= 1) SEND_TO_Q("\r\nYou may not lower an Virtue below 1.\r\n", d); else { d->character->points.conscience -= 1; d->character->player_specials->create_points += 1; } } } else if (*buf1 && is_abbrev(buf1, "self-control")) { if (add) { if (d->character->points.self_control >= 5) SEND_TO_Q("\r\nYou may not begin with any Virtue greater than 5.\r\n", d); else { d->character->points.self_control += 1; d->character->player_specials->create_points -= 1; } } else if (subtract) { if (d->character->points.self_control <= 1) SEND_TO_Q("\r\nYou may not lower an Virtue below 1.\r\n", d); else { d->character->points.self_control -= 1; d->character->player_specials->create_points += 1; } } } else if (*buf1 && is_abbrev(buf1, "courage")) { if (add) { if (d->character->points.courage >= 5) SEND_TO_Q("\r\nYou may not begin with any Virtue greater than 5.\r\n", d); else { d->character->points.courage += 1; d->character->player_specials->create_points -= 1; } } else if (subtract) { if (d->character->points.courage <= 1) SEND_TO_Q("\r\nYou may not lower an Virtue below 1.\r\n", d); else { d->character->points.courage -= 1; d->character->player_specials->create_points += 1; } } } SEND_TO_Q("\r\nVirtues:\r\n", d); *buf = '\0'; strcat(buf, "Conscience: "); for (i = 0; i < d->character->points.conscience; i++) strcat(buf, "*"); strcat(buf, "\r\n"); strcat(buf, "Self-Control: "); for (i = 0; i < d->character->points.self_control; i++) strcat(buf, "*"); strcat(buf, "\r\n"); strcat(buf, "Courage: "); for (i = 0; i < d->character->points.courage; i++) strcat(buf, "*"); strcat(buf, "\r\n"); SEND_TO_Q(strcat(buf, "\r\n"), d); sprintf(buf, " Points remaining: %d\r\n", d->character->player_specials->create_points); SEND_TO_Q(buf, d); SEND_TO_Q("Commands: add <virtue> - Adds a point to any Virtue\r\n", d); SEND_TO_Q(" sub <virtue> - Removes a point from any Virtue\r\n", d); SEND_TO_Q(" help - Quick reference to Virtues\r\n", d); SEND_TO_Q(" done - Finish Virtue assigments\r\n", d); SEND_TO_Q("> ", d); break; case CON_CHOOSE_DISCIPLINES: /* * This is very simple: if arg is nothing, it simply repeats the * output. Otherwise, it makes the change requested and displays * the virtues. */ if (*arg) { /* Find if they chose a discipline */ for (i = 0; i < NUM_DISCS; i++) if ((clan[GET_CLAN(d->character)].disc[0] == i || clan[GET_CLAN(d->character)].disc[1] == i || clan[GET_CLAN(d->character)].disc[2] == i) && is_abbrev(arg, disc[i].name)) break; /* Parse the input */ if (is_abbrev(arg, "done")) { if (d->character->player_specials->create_points > 0) SEND_TO_Q("\r\nYou still have points left to assign.\r\n", d); else { if (GET_THAUMATURGY(d->character)) { STATE(d) = CON_PATH; SEND_TO_Q("\r\nPress ENTER to choose a Path: ", d); } else { STATE(d) = CON_ADVANTAGES_V; GET_GENERATION(d->character) = 12; d->character->player_specials->create_points = 7; SEND_TO_Q("\r\nPress ENTER to choose Advantages: ", d); } break; } } else if (is_abbrev(arg, "help")) { SEND_TO_Q("\r\nDisciplines:\r\n", d); SEND_TO_Q(" Animalism - Control over animals.\r\n", d); SEND_TO_Q(" Auspex - Heightened senses and awareness.\r\n", d); SEND_TO_Q(" Celerity - Improved dexterity and speed.\r\n", d); SEND_TO_Q(" Chimerstry - Mastery over illusions.\r\n", d); SEND_TO_Q(" Dementation - Control over the sanity of others.\r\n", d); SEND_TO_Q(" Dominate - Command over fragile minds.\r\n", d); SEND_TO_Q(" Fortitude - Supernatural defense.\r\n", d); SEND_TO_Q(" Mortis - Mastery over the dead.\r\n", d); SEND_TO_Q(" Obfuscate - Clouding the minds of others.\r\n", d); SEND_TO_Q(" Obtenebration - Commanding the darkness.\r\n", d); SEND_TO_Q(" Potence - Supernatural strength.\r\n", d); SEND_TO_Q(" Presence - Enticing the minds of others.\r\n", d); SEND_TO_Q(" Protean - Powerful form-changing.\r\n", d); SEND_TO_Q(" Quietus - The art of combat and assassination.\r\n", d); SEND_TO_Q(" Serpentis - Mastery and power of the serpent.\r\n", d); SEND_TO_Q(" Thaumaturgy - Blood-fueled magic.\r\n", d); SEND_TO_Q(" Vicissitude - Mastery over flesh and bone.\r\n", d); SEND_TO_Q("\r\nPress ENTER to contine: ", d); break; } else if (is_abbrev(arg, "reset")) { for (i = 0; i < NUM_DISCS; i++) GET_REAL_DISC(d->character, i) = 0; d->character->player_specials->create_points = 4; } else if (i == NUM_DISCS) { SEND_TO_Q("\r\nInvalid Discipline.\r\n", d); } else if (d->character->player_specials->create_points <= 0) SEND_TO_Q("\r\nYou don't have any points left.\r\n", d); else { GET_REAL_DISC(d->character, i) += 1; d->character->player_specials->create_points -= 1; } } SEND_TO_Q("\r\nDisciplines:\r\n", d); *buf = '\0'; sprintf(buf + strlen(buf), "%13.13s - ", disc[(int) clan[(int) GET_CLAN(d->character)].disc[0]].name); for (i = 0; i < 10; i++) if (GET_DISC(d->character, (int) clan[(int) GET_CLAN(d->character)].disc[0]) > i) strcat(buf, "*"); strcat(buf, "\r\n"); sprintf(buf + strlen(buf), "%13.13s - ", disc[(int) clan[(int) GET_CLAN(d->character)].disc[1]].name); for (i = 0; i < 10; i++) if (GET_DISC(d->character, (int) clan[(int) GET_CLAN(d->character)].disc[1]) > i) strcat(buf, "*"); strcat(buf, "\r\n"); sprintf(buf + strlen(buf), "%13.13s - ", disc[(int) clan[(int) GET_CLAN(d->character)].disc[2]].name); for (i = 0; i < 10; i++) if (GET_DISC(d->character, (int) clan[(int) GET_CLAN(d->character)].disc[2]) > i) strcat(buf, "*"); strcat(buf, "\r\n"); SEND_TO_Q(strcat(buf, "\r\n"), d); sprintf(buf, " Points remaining: %d\r\n", d->character->player_specials->create_points); SEND_TO_Q(buf, d); SEND_TO_Q("Commands: <discipline> - Adds a point to any Discipline listed\r\n", d); SEND_TO_Q(" reset - Resets the Disciplines and points\r\n", d); SEND_TO_Q(" help - Quick reference to Disciplines\r\n", d); SEND_TO_Q(" done - Finish Discipline assigments\r\n", d); SEND_TO_Q("> ", d); break; case CON_PATH: if (*arg) { /* Find if they chose a path */ for (i = 0; i < NUM_PATHS; i++) if (is_abbrev(arg, path[i].name)) break; if (i < NUM_PATHS) { GET_PRIMARY_PATH(d->character) = i; GET_REAL_PATH(d->character, (int) GET_REAL_PRIMARY_PATH(d->character)) = GET_THAUMATURGY(d->character); STATE(d) = CON_ADVANTAGES_V; GET_GENERATION(d->character) = 12; d->character->player_specials->create_points = 7; SEND_TO_Q("\r\nPress ENTER to choose Advantages: ", d); break; } else SEND_TO_Q("\r\nInvalid choice.\r\n>", d); } SEND_TO_Q("\r\nChoose your Primary Path:\r\n", d); SEND_TO_Q(" Rego Vitae - The Path of Blood\r\n", d); SEND_TO_Q(" Creo Ignem - The Path of Fire\r\n", d); SEND_TO_Q(" Rego Motus - The Path of Movement\r\n", d); SEND_TO_Q(" Rego Tempestas - The Path of Storms\r\n", d); SEND_TO_Q(" Rego Aquam - The Path of Water\r\n", d); SEND_TO_Q(" Rego Elementum - The Path of Elements\r\n", d); SEND_TO_Q(" Way of Levinbolt\r\n", d); SEND_TO_Q(" Path of Warding\r\n", d); SEND_TO_Q("> ", d); break; case CON_CHOOSE_AGE: if ((i = atoi(arg)) < 16 || i > 80) { SEND_TO_Q("\r\nYou must choose an age between 16 and 80: ", d); return; } GET_APPARENT_AGE(d->character) = i; STATE(d) = CON_APPEARANCE; SEND_TO_Q("\r\nPress ENTER to finish character creation: ", d); break; case CON_ADVANTAGES_V: /* * This is very simple: if arg is nothing, it simply repeats the * output. Otherwise, it makes the change requested and displays * the virtues. */ if (*arg) { /* Parse the input */ if (is_abbrev(arg, "done")) { if (d->character->player_specials->create_points > 0) SEND_TO_Q("\r\nYou still have points left to assign.\r\n", d); else { STATE(d) = CON_CHOOSE_AGE; SEND_TO_Q("\r\nHow old does your character appear (16 to 80): ", d); break; } } else if (is_abbrev(arg, "help")) { SEND_TO_Q("\r\nAdvantages:\r\n", d); SEND_TO_Q(" Humanity - Remnants of the mortal self and freedom from the Beast within.\r\n", d); SEND_TO_Q(" Humanity is based upon Conscience and Self-Control.\r\n", d); SEND_TO_Q(" Willpower - Mental stability and resistance to Delirium and Dominate.\r\n", d); SEND_TO_Q(" Willpower is based upon Courage.\r\n", d); SEND_TO_Q(" Generation - The thinning of one's blood marked by distance from Caine.\r\n", d); SEND_TO_Q(" Vampires start at Generation 12 unless points are spent here.\r\n", d); SEND_TO_Q("\r\nPress ENTER to contine: ", d); break; } else if (is_abbrev(arg, "reset")) { GET_MAX_WILLPOWER(d->character) = GET_COURAGE(d->character); GET_HUMANITY(d->character) = GET_CONSCIENCE(d->character) + GET_SELF_CONTROL(d->character); GET_GENERATION(d->character) = 12; d->character->player_specials->create_points = 7; } else if (d->character->player_specials->create_points <= 0) SEND_TO_Q("\r\nYou don't have any points left.\r\n", d); else if (is_abbrev(arg, "add humanity")) { if (GET_HUMANITY(d->character) >= 10) SEND_TO_Q("You may not have more than ten Humanity.\r\n", d); else { GET_HUMANITY(d->character) += 1; d->character->player_specials->create_points -= 1; } } else if (is_abbrev(arg, "add willpower")) { if (GET_MAX_WILLPOWER(d->character) >= 10) SEND_TO_Q("You may not have more than ten Willpower.\r\n", d); else { GET_MAX_WILLPOWER(d->character) += 1; d->character->player_specials->create_points -= 1; } } else if (is_abbrev(arg, "add generation")) { if (GET_GENERATION(d->character) <= 7) SEND_TO_Q("You may not begin lower than seventh generation.\r\n", d); else { GET_GENERATION(d->character) -= 1; d->character->player_specials->create_points -= 1; } } } SEND_TO_Q("\r\nAdvantages:\r\n", d); *buf = '\0'; strcat(buf, " Humanity: "); for (i = 0; i < GET_HUMANITY(d->character); i++) strcat(buf, "*"); strcat(buf, "\r\n"); strcat(buf, " Willpower: "); for (i = 0; i < GET_MAX_WILLPOWER(d->character); i++) strcat(buf, "*"); strcat(buf, "\r\n"); sprintf(buf + strlen(buf), " Generation: %dth\r\n", GET_GENERATION(d->character)); SEND_TO_Q(strcat(buf, "\r\n"), d); sprintf(buf, " Points remaining: %d\r\n", d->character->player_specials->create_points); SEND_TO_Q(buf, d); SEND_TO_Q("Commands: add <advantage> - Adds a point to any Advantage\r\n", d); SEND_TO_Q(" reset - Resets the Advantages and points\r\n", d); SEND_TO_Q(" help - Quick reference to Advantages\r\n", d); SEND_TO_Q(" done - Finish Advantage assigments\r\n", d); SEND_TO_Q("> ", d); break; case CON_ADVANTAGES_W: /* * This is very simple: if arg is nothing, it simply repeats the * output. Otherwise, it makes the change requested and displays * the advantages. */ if (*arg) { /* Parse the input */ if (is_abbrev(arg, "done")) { if (d->character->player_specials->create_points > 0) SEND_TO_Q("\r\nYou still have points left to assign.\r\n", d); else { GET_GNOSIS(d->character) = GET_MAX_GNOSIS(d->character); GET_RAGE(d->character) = GET_MAX_RAGE(d->character); GET_WILLPOWER(d->character) = GET_MAX_WILLPOWER(d->character); STATE(d) = CON_APPEARANCE; SEND_TO_Q("\r\nPress ENTER to finish character creation: ", d); break; } } else if (is_abbrev(arg, "reset")) { assign_werewolf_advantages(d); d->character->player_specials->create_points = 7; } else if (is_abbrev(arg, "help")) { SEND_TO_Q("\r\nAdvantages:\r\n", d); SEND_TO_Q(" Gnosis - Gnosis is the focus of one's spiritual energy, the opposite\r\n", d); SEND_TO_Q(" of Rage, but equally important.\r\n", d); SEND_TO_Q(" Rage - Rage is the focus of all the anger within a person. It has\r\n", d); SEND_TO_Q(" both positive and negative affects on one's being, as well as\r\n", d); SEND_TO_Q(" the things shredded around him.\r\n", d); SEND_TO_Q(" Willpower - Mental stability and resistance to Dominate.\r\n", d); SEND_TO_Q("\r\nPress ENTER to contine: ", d); break; } else if (d->character->player_specials->create_points <= 0) SEND_TO_Q("\r\nYou don't have any points left.\r\n", d); else if (is_abbrev(arg, "add gnosis")) { if (GET_MAX_GNOSIS(d->character) >= 10) SEND_TO_Q("You may not have more than ten Gnosis.\r\n", d); else { GET_MAX_GNOSIS(d->character) += 1; d->character->player_specials->create_points -= 1; } } else if (is_abbrev(arg, "add willpower")) { if (GET_MAX_WILLPOWER(d->character) >= 10) SEND_TO_Q("You may not have more than ten Willpower.\r\n", d); else { GET_MAX_WILLPOWER(d->character) += 1; d->character->player_specials->create_points -= 1; } } else if (is_abbrev(arg, "add rage")) { if (GET_MAX_RAGE(d->character) >= 10) SEND_TO_Q("You may not have more than ten Rage.\r\n", d); else { GET_MAX_RAGE(d->character) += 1; d->character->player_specials->create_points -= 1; } } } SEND_TO_Q("\r\nAdvantages:\r\n", d); *buf = '\0'; strcat(buf, " Gnosis: "); for (i = 0; i < GET_MAX_GNOSIS(d->character); i++) strcat(buf, "*"); strcat(buf, "\r\n"); strcat(buf, " Rage: "); for (i = 0; i < GET_MAX_RAGE(d->character); i++) strcat(buf, "*"); strcat(buf, "\r\n"); strcat(buf, " Willpower: "); for (i = 0; i < GET_MAX_WILLPOWER(d->character); i++) strcat(buf, "*"); strcat(buf, "\r\n"); SEND_TO_Q(strcat(buf, "\r\n"), d); sprintf(buf, " Points remaining: %d\r\n", d->character->player_specials->create_points); SEND_TO_Q(buf, d); SEND_TO_Q("Commands: add <advantage> - Adds a point to any Advantage\r\n", d); SEND_TO_Q(" reset - Resets the Advantages and points\r\n", d); SEND_TO_Q(" help - Quick reference to Advantages\r\n", d); SEND_TO_Q(" done - Finish Advantage assigments\r\n", d); SEND_TO_Q("> ", d); break; case CON_APPEARANCE: SEND_TO_Q("\r\nChoose a starting equipment set:\r\n", d); for (i = 1, j = 0; str_cmp(new_eq[i].name, "\n"); i++) { sprintf(buf, " %2d. %-15.15s %s", i, new_eq[i].name, !(++j % 3) ? "\r\n" : ""); SEND_TO_Q(buf, d); } SEND_TO_Q("\r\n> ", d); STATE(d) = CON_QEQUIPMENT; break; case CON_QEQUIPMENT: i = atoi(arg); /* Determine top choice # */ for (j = 1; str_cmp(new_eq[j].name, "\n"); j++); if (i < 1 || i >= j) { SEND_TO_Q("\r\nInvalid choice.\r\n> ", d); return; } GET_NEW_EQ_SET(d->character) = i; SEND_TO_Q("\r\nHow tall are you:\r\n", d); SEND_TO_Q(" 1. Short\r\n", d); SEND_TO_Q(" 2. Below Average\r\n", d); SEND_TO_Q(" 3. Average\r\n", d); SEND_TO_Q(" 4. Above Average\r\n", d); SEND_TO_Q(" 5. Tall\r\n", d); SEND_TO_Q("> ", d); STATE(d) = CON_QHEIGHT; break; case CON_RMOTD: /* read CR after printing motd */ if (PLR_FLAGGED(d->character, PLR_IPMASK)) strcpy(d->host, "masked"); if (GET_LEVEL(d->character) < LVL_APPROVED) SEND_TO_Q(AUTH_MESSG, d); display_statistics_to_char(d->character); SEND_TO_Q(MENU, d); STATE(d) = CON_MENU; break; case CON_MENU: /* get selection from main menu */ switch (LOWER(*arg)) { case 'l': SEND_TO_Q("Goodbye.\r\n", d); STATE(d) = CON_CLOSE; break; case 'e': if (PLR_FLAGGED(d->character, PLR_SLAIN)) { SEND_TO_Q(hardcore_slain_msg, d); SEND_TO_Q("\r\n", d); return; } if (!check_multiplaying(d)) { SEND_TO_Q("\r\n\033[31mAccess Denied: Multiplaying detected\033[0m\r\n", d); SEND_TO_Q("There is already someone logged in from the same IP address as you. If you\r\n", d); SEND_TO_Q("are controlling that character, you must remove it from the game before this\r\n", d); SEND_TO_Q("character can enter. Rarely, computers may share IP addresses. If this is\r\n", d); SEND_TO_Q("the case, exceptions may be granted. You will need to petition the staff\r\n", d); SEND_TO_Q("member in charge of authorization. When you are able to log into the mud,\r\n", d); SEND_TO_Q("type HELP AUTHORIZATION for the appropriate e-mail address, or contact the\r\n", d); SEND_TO_Q("staff member via the game.\r\n", d); SEND_TO_Q("\r\nPress ENTER to contine: ", d); syslog(0, TRUE, "Login denied: Multiplaying detected for %s [%s]", GET_NAME(d->character), d->host); STATE(d) = CON_GOODBYE; return; } /* This will make sure vampires are safe */ if ((load_result = enter_player_game(d, 1)) != -2) { send_to_char(WELC_MESSG, d->character); act("$n has entered the game.", TRUE, d->character, 0, 0, TO_ROOM); STATE(d) = CON_PLAYING; /* We can see who's new because they have a new EQ set */ if (GET_NEW_EQ_SET(d->character) != 0) { do_start(d->character); send_to_char(START_MESSG, d->character); } look_at_room(d->character); if (has_mail(GET_IDNUM(d->character))) send_to_char("&1You have mail waiting.&0\r\n", d->character); d->has_prompt = 0; } else return; break; case 'b': page_string(d, background, 0); STATE(d) = CON_RMOTD; break; case 'c': SEND_TO_Q("\r\nEnter your old password: ", d); echo_off(d); STATE(d) = CON_CHPWD_GETOLD; break; case 'd': SEND_TO_Q("\r\nEnter your password for verification: ", d); echo_off(d); STATE(d) = CON_DELCNF1; break; case 'n': if (GET_LINGUISTICS(d->character) >= att_max(d->character)) SEND_TO_Q("Your Linguistics is already at maximum.\r\n", d); else if (GET_LINGUISTICS(d->character) == 0 && GET_EXPERIENCE(d->character) < ABILITY_COST_NEW) SEND_TO_Q("You don't have enough experience to buy a point of Linguistics.\r\n", d); else if (GET_LINGUISTICS(d->character) > 0 && GET_EXPERIENCE(d->character) < ABILITY_COST * (GET_LINGUISTICS(d->character) + 1)) SEND_TO_Q("You don't have enough experience to buy a point of Linguistics.\r\n", d); else { if (GET_LINGUISTICS(d->character) == 0) GET_EXPERIENCE(d->character) -= ABILITY_COST_NEW; else GET_EXPERIENCE(d->character) -= ABILITY_COST * (GET_LINGUISTICS(d->character) + 1); d->character->player_specials->saved.knowledges[KNOWLEDGE_LINGUISTICS] += 1; SEND_TO_Q("\r\nSelect a Language (by number):\r\n", d); *buf = '\0'; for (i = 0; i < NUM_LANGS; i++) if (i != LANG_LATIN && i != LANG_FERAL_SPEECH && i != LANG_HIGH_TONGUE && !IS_SET(GET_LANGUAGES(d->character), LANGUAGE_BIT(i))) sprintf(buf + strlen(buf), " %d. %s\r\n", i + 1, langs[i]); SEND_TO_Q(buf, d); SEND_TO_Q("> ", d); d->character->player_specials->create_points = 1; STATE(d) = CON_LANGUAGE_MENU; break; } break; case 'm': if (GET_LOYALTY(d->character) == 0 || real_empire(GET_LOYALTY(d->character)) < 0) { SEND_TO_Q("\r\nYou are not a member of an empire!\r\n> ", d); return; } if (GET_LOYALTY(d->character) != GET_IDNUM(d->character)) { SEND_TO_Q("\r\nYou are not the leader of the empire!\r\n> ", d); return; } d->empire = create_empire_editor(real_empire(GET_LOYALTY(d->character))); STATE(d) = CON_EMPIRE_EDIT; send_empire_edit_menu(d); break; default: SEND_TO_Q("\r\nThat's not a menu choice!\r\n", d); if (GET_LEVEL(d->character) < LVL_APPROVED) SEND_TO_Q(AUTH_MESSG, d); display_statistics_to_char(d->character); SEND_TO_Q(MENU, d); break; } break; case CON_CHPWD_GETOLD: if (strncmp(CRYPT(arg, GET_PASSWD(d->character)), GET_PASSWD(d->character), MAX_PWD_LENGTH)) { echo_on(d); SEND_TO_Q("\r\nIncorrect password.\r\n", d); if (GET_LEVEL(d->character) < LVL_APPROVED) SEND_TO_Q(AUTH_MESSG, d); display_statistics_to_char(d->character); SEND_TO_Q(MENU, d); STATE(d) = CON_MENU; } else { SEND_TO_Q("\r\nEnter a new password: ", d); STATE(d) = CON_CHPWD_GETNEW; } return; case CON_DELCNF1: echo_on(d); if (strncmp(CRYPT(arg, GET_PASSWD(d->character)), GET_PASSWD(d->character), MAX_PWD_LENGTH)) { SEND_TO_Q("\r\nIncorrect password.\r\n", d); if (GET_LEVEL(d->character) < LVL_APPROVED) SEND_TO_Q(AUTH_MESSG, d); display_statistics_to_char(d->character); SEND_TO_Q(MENU, d); STATE(d) = CON_MENU; } else { SEND_TO_Q("\r\nYOU ARE ABOUT TO DELETE THIS CHARACTER PERMANENTLY.\r\nARE YOU ABSOLUTELY SURE?\r\n\r\nPlease type \"yes\" to confirm: ", d); STATE(d) = CON_DELCNF2; } break; case CON_DELCNF2: if (!str_cmp(arg, "yes")) { if (PLR_FLAGGED(d->character, PLR_FROZEN)) { SEND_TO_Q("You try to kill yourself, but the ice stops you.\r\n", d); SEND_TO_Q("Character not deleted.\r\n\r\n", d); STATE(d) = CON_CLOSE; return; } if (GET_LEVEL(d->character) < LVL_TOP) SET_BIT(PLR_FLAGS(d->character), PLR_DELETED); /* Check that empire */ if ((emp = real_empire(GET_LOYALTY(d->character))) != -1) { GET_LOYALTY(d->character) = 0; GET_RANK(d->character) = 0; empire[emp].members--; if (empire[emp].members == 0) delete_empire(emp); } SAVE_CHAR(d->character); Crash_delete_file(GET_NAME(d->character)); sprintf(buf, "Character '%s' deleted!\r\nGoodbye.\r\n", GET_NAME(d->character)); SEND_TO_Q(buf, d); syslog(0, TRUE, "DEL: %s (lev %d) has self-deleted.", GET_NAME(d->character), GET_LEVEL(d->character)); STATE(d) = CON_CLOSE; return; } else { SEND_TO_Q("\r\nCharacter not deleted.\r\n", d); if (GET_LEVEL(d->character) < LVL_APPROVED) SEND_TO_Q(AUTH_MESSG, d); display_statistics_to_char(d->character); SEND_TO_Q(MENU, d); STATE(d) = CON_MENU; } break; case CON_GOODBYE: /* take an ENTER and then quit */ SEND_TO_Q("Goodbye.\r\n", d); STATE(d) = CON_CLOSE; break; /* * It's possible, if enough pulses are missed, to kick someone off * while they are at the password prompt. We'll just defer to let * the game_loop() axe them. */ case CON_CLOSE: break; default: log("SYSERR: Nanny: illegal state of con'ness (%d) for '%s'; closing connection.", STATE(d), d->character ? GET_NAME(d->character) : "<unknown>"); STATE(d) = CON_DISCONNECT; /* Safest to do. */ break; } }