/**************************************************************************** * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | * * -----------------------------------------------------------| \\._.// * * SmaugWiz (C) 1998 by Russ Pillsbury (Windows NT version) | (0...0) * * -----------------------------------------------------------| ).:.( * * SMAUG (C) 1994, 1995, 1996 by Derek Snider | {o o} * * -----------------------------------------------------------| / ' ' \ * * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, |~'~.VxvxV.~'~* * Scryn, Swordbearer, Rennard, Tricops, and Gorog. | * * ------------------------------------------------------------------------ * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik Staerfeldt, Tom Madsen, and Katja Nyboe. * * ------------------------------------------------------------------------ * * Player skills module * ****************************************************************************/ #include "stdafx.h" #include "smaug.h" #include "SysData.h" #include "area.h" #include "skill.h" #include "mobiles.h" #include "objects.h" #include "rooms.h" #include "deity.h" #include "races.h" #include "class.h" #include "Exits.h" #include "character.h" #include "SmaugWizDoc.h" char * const spell_flag[] = { "water", "earth", "air", "astral", "area", "distant", "reverse", "noself", "_unused2_", "accumulative", "recastable", "noscribe", "nobrew", "group", "object", "character", "secretskill", "pksensitive", "stoponfail", "nofight", "nodispel", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" }; char * const spell_saves[] = { "none", "poison_death", "wands", "para_petri", "breath", "spell_staff" }; char * const spell_damage[] = { "none", "fire", "cold", "electricity", "energy", "acid", "poison", "drain" }; char * const spell_action[] = { "none", "create", "destroy", "resist", "suscept", "divinate", "obscure", "change" }; char * const spell_power[] = { "none", "minor", "greater", "major" }; char * const spell_class[] = { "none", "lunar", "solar", "travel", "summon", "life", "death", "illusion" }; char * const target_type[] = { "ignore", "offensive", "defensive", "self", "objinv" }; int ris_save (CCharacter *ch, int chance, int ris); BOOL check_illegal_psteal (CCharacter *ch, CCharacter *victim); BOOL can_use_skill (CCharacter* ch, int percent, int gsn); char *myobj (CObjData *obj); void SkillHelp (CCharacter* ch); ch_ret ranged_got_target (CCharacter *ch, CCharacter *victim, CObjData *weapon, CObjData *projectile, short dist, short dt, char *stxt, short color); CObjData *find_projectile (CCharacter* ch, int type); // Dummy function void skill_notfound (CCharacter *ch, char *argument) { ch->SendText ("Huh?\n\r"); return; } int get_ssave (char *name) { int x; for (x = 0; x < DIM (spell_saves); x++) if (!str_cmp (name, spell_saves[x])) return x; return -1; } int get_starget (char *name) { int x; for (x = 0; x < DIM (target_type); x++) if (!str_cmp (name, target_type[x])) return x; return -1; } int get_sflag (char *name) { int x; for (x = 0; x < DIM (spell_flag); x++) if (!str_cmp (name, spell_flag[x])) return x; return -1; } int get_sdamage (char *name) { int x; for (x = 0; x < DIM (spell_damage); x++) if (!str_cmp (name, spell_damage[x])) return x; return -1; } int get_saction (char *name) { int x; for (x = 0; x < DIM (spell_action); x++) if (!str_cmp (name, spell_action[x])) return x; return -1; } int get_spower (char *name) { int x; for (x = 0; x < DIM (spell_power); x++) if (!str_cmp (name, spell_power[x])) return x; return -1; } int get_sclass (char *name) { int x; for (x = 0; x < DIM (spell_class); x++) if (!str_cmp (name, spell_class[x])) return x; return -1; } BOOL is_legal_kill (CCharacter *ch, CCharacter *vch) { if (ch->IsNpc () || vch->IsNpc ()) return TRUE; if (!ch->IsPkiller () || !vch->IsPkiller ()) return FALSE; if (ch->GetPcData ()->GetClan () && ch->GetPcData ()->GetClan () == vch->GetPcData ()->GetClan ()) return FALSE; return TRUE; } extern char *target_name; /* from magic.c */ // Perform a binary search on a section of the skill table // Each different section of the skill table is sorted alphabetically // Only match skills player knows -Thoric BOOL check_skill (CCharacter *ch, char *command, char *argument) { int sn; int first = gsn_first_skill; int top = gsn_first_weapon-1; int mana, blood; struct timeval time_used; // bsearch for the skill for (;;) { sn = (first + top) >> 1; if (LOWER (command[0]) == LOWER (SkillTable.GetName (sn)[0]) && !str_prefix (command, SkillTable.GetName (sn)) && (SkillTable.GetSkillFunction (sn) || SkillTable.GetSpellFunction (sn) != spell_null) && (can_use_skill (ch, 0, sn))) break; if (first >= top) return FALSE; if (strcmp (command, SkillTable.GetName (sn)) < 1) top = sn - 1; else first = sn + 1; } if (! check_pos (ch, SkillTable.GetMinimumPosition (sn))) return TRUE; if (ch->IsNpc () && (ch->IsCharmed () || ch->IsPossessed ())) { ch->SendText ("For some reason, you seem unable to perform that...\n\r"); act (AT_GREY,"$n wanders around aimlessly.", ch, NULL, NULL, TO_ROOM); return TRUE; } // check if mana is required if (SkillTable.GetMinMana (sn)) { mana = ch->IsNpc () ? 0 : UMAX (SkillTable.GetMinMana (sn), 100 / (2 + ch->GetLevel () - SkillTable.GetClassLevel (sn, ch->GetClass ()))); blood = UMAX (1, (mana+4) / 8); // NPCs don't have PCDatas. -- Altrag if (ch->IsVampire ()) { if (ch->GetPcData ()->condition [COND_BLOODTHIRST] < blood) { ch->SendText ("You don't have enough blood power.\n\r"); return TRUE; } } else if (! ch->IsNpc () && ch->GetMana () < mana) { ch->SendText ("You don't have enough mana.\n\r"); return TRUE; } } else { mana = 0; blood = 0; } // Is this a real do-fun, or a really a spell? if (! SkillTable.GetSkillFunction (sn)) { ch_ret retcode = rNONE; void *vo = NULL; CCharacter *victim = NULL; CObjData *obj = NULL; target_name = ""; switch (SkillTable.GetTarget (sn)) { default: bug ("Check_skill: bad target for sn %d.", sn); ch->SendText ("Something went wrong...\n\r"); return TRUE; case TAR_IGNORE: vo = NULL; if (argument [0] == '\0') { if (victim = ch->GetFightWho ()) target_name = NCCP victim->GetName (); } else target_name = argument; break; case TAR_CHAR_OFFENSIVE: if (argument [0] == '\0' && (victim = ch->GetFightWho ()) == NULL) { ch->SendTextf ("%s who?\n\r", capitalize (SkillTable.GetName (sn))); return TRUE; } else if (argument[0] != '\0' && (victim=get_char_room (ch, argument)) == NULL) { ch->SendText ("They aren't here.\n\r"); return TRUE; } if (is_safe (ch, victim)) return TRUE; vo = victim; break; case TAR_CHAR_DEFENSIVE: if (argument [0] != '\0' && (victim=get_char_room (ch, argument)) == NULL) { ch->SendText ("They aren't here.\n\r"); return TRUE; } if (! victim) victim = ch; vo = victim; break; case TAR_CHAR_SELF: vo = ch; break; case TAR_OBJ_INV: if ((obj = get_obj_carry (ch, argument)) == NULL) { ch->SendText ("You can't find that.\n\r"); return TRUE; } vo = obj; break; } // waitstate WAIT_STATE (ch, SkillTable.GetBeats (sn)); // check for failure if ((number_percent () + SkillTable.GetDifficulty (sn) * 5) > (ch->IsNpc () ? 75 : ch->GetPcData ()->learned [sn])) { failed_casting (SkillTable.GetSkill (sn), ch, (CCharacter*) vo, obj); learn_from_failure (ch, sn); if (mana) { if (ch->IsVampire ()) gain_condition (ch, COND_BLOODTHIRST, - blood/2); else ch->AddMana (-mana/2); } return TRUE; } if (mana) { if (ch->IsVampire ()) gain_condition (ch, COND_BLOODTHIRST, - blood); else ch->AddMana (-mana); } start_timer (&time_used); retcode = (*SkillTable.GetSpellFunction (sn)) (sn, ch->GetLevel (),ch,vo); end_timer (&time_used); update_userec (&time_used, &SkillTable.GetUseRec (sn)); if (retcode == rCHAR_DIED || retcode == rERROR) return TRUE; if (char_died (ch)) return TRUE; if (retcode == rSPELL_FAILED) { learn_from_failure (ch, sn); retcode = rNONE; } else learn_from_success (ch, sn); if (SkillTable.GetTarget (sn) == TAR_CHAR_OFFENSIVE && victim != ch && ! char_died (victim)) { CCharacter *vch; CCharacter *vch_next; for (vch = ch->GetInRoom ()->first_person; vch; vch = vch_next) { vch_next = vch->GetNextInRoom (); if (victim == vch && ! victim->GetFightData () && victim->GetMaster () != ch) { retcode = multi_hit (victim, ch, TYPE_UNDEFINED); break; } } } return TRUE; } if (mana) { if (ch->IsVampire ()) gain_condition (ch, COND_BLOODTHIRST, - blood); else ch->AddMana (-mana); } ch->prev_cmd = ch->last_cmd; // haus, for automapping ch->last_cmd = SkillTable.GetSkillFunction (sn); start_timer (&time_used); (*SkillTable.GetSkillFunction (sn)) (ch, argument); end_timer (&time_used); update_userec (&time_used, &SkillTable.GetUseRec (sn)); return TRUE; } // Lookup a skills information // High god command void do_slookup (CCharacter *ch, char *argument) { char buf [MAX_STRING_LENGTH]; char arg [MAX_INPUT_LENGTH]; int sn; int iClass; CSkill *pSkill = NULL; one_argument (argument, arg); if (arg [0] == '\0') { ch->SendText ("Slookup what?\n\r"); return; } if (! str_cmp (arg, "all")) { for (sn=0; sn < SkillTable.GetCount (); ++sn) { if (pSkill = SkillTable.GetSkill (sn)) pager_printf (ch, "Sn: %4d Slot: %4d Skill/spell: '%-20s' Damtype: %s\n\r", sn, pSkill->GetSlot (), pSkill->GetName (), spell_damage [pSkill->GetSpellDamage ()]); } } else if (! str_cmp (arg, "herbs")) { for (sn=0; sn < HerbTable.GetCount (); ++sn) { pSkill = HerbTable.GetSkill (sn); pager_printf (ch, "%d) %s\n\r", sn, pSkill->GetName ()); } } else { pSkill = NULL; CSmaugAffect *aff; int cnt = 0; if (arg [0] == 'h' && is_number (arg+1)) { sn = atoi (arg+1); if (! HerbTable.IsValid (sn)) { ch->SendText ("Invalid herb.\n\r"); return; } pSkill = HerbTable.GetSkill (sn); } else if (is_number (arg)) { sn = atoi (arg); if ((pSkill = SkillTable.GetValidSkill (sn)) == NULL) { ch->SendText ("Invalid sn.\n\r"); return; } sn %= 1000; } else if ((sn = SkillTable.Lookup (arg)) >= 0) pSkill = SkillTable.GetSkill (sn); else if ((sn = HerbTable.Lookup (arg)) >= 0) pSkill = HerbTable.GetSkill (sn); else { ch->SendText ("No such skill, spell, proficiency or tongue.\n\r"); return; } if (! pSkill) { ch->SendText ("Not created yet.\n\r"); return; } ch->SendTextf ("Sn: %4d Slot: %4d %s: '%-20s'\n\r", sn, pSkill->GetSlot (), skill_tname [pSkill->GetType ()], pSkill->GetName ()); if (pSkill->GetInfo ()) ch->SendTextf ("Damtype: %s Acttype: %s Classtype: %s" " Powertype: %s\n\r", spell_damage [pSkill->GetSpellDamage ()], spell_action [pSkill->GetSpellAction ()], spell_class [pSkill->GetSpellClass ()], spell_power [pSkill->GetSpellPower ()]); if (pSkill->GetFlags ()) { strcpy (buf, "Flags:"); for (int x = 0; x < 32; x++) if (pSkill->HasSpell (1 << x)) { strcat (buf, " "); strcat (buf, spell_flag [x]); } strcat (buf, "\n\r"); ch->SendText (buf); } ch->SendTextf ("Saves: %s SaveEffect: %s\n\r", pSkill->GetSaveName (), pSkill->GetSaveEffectName ()); if (pSkill->GetDifficulty () != '\0') ch->SendTextf ("Difficulty: %d\n\r", pSkill->GetDifficulty ()); ch->SendTextf ("Type: %s Target: %s Minpos: %d Mana: %d " "Beats: %d Range: %d\n\r", skill_tname [pSkill->GetType ()], target_type [URANGE (TAR_IGNORE, pSkill->GetTarget (), TAR_OBJ_INV)], pSkill->GetMinimumPosition (), pSkill->GetMinMana (), pSkill->GetBeats (), pSkill->GetRange ()); ch->SendTextf ( "Flags: %d Guild: %d Value: %d Info: %d Code: %s\n\r", pSkill->GetFlags (), pSkill->GetGuild (), pSkill->GetValue (), pSkill->GetInfo (), pSkill->GetSkillFunction () ? skill_name (pSkill->GetSkillFunction ()) : spell_name (pSkill->GetSpellFunction ())); ch->SendTextf ("Dammsg: %s\n\rWearoff: %s\n", pSkill->GetDamageMsg (), pSkill->GetOffMsg () ? pSkill->GetOffMsg () : "(none set)"); if (pSkill->GetDiceRoll () && pSkill->GetDiceRoll ()[0] != '\0') ch->SendTextf ("Dice: %s\n\r", pSkill->GetDiceRoll ()); if (pSkill->GetTeachers () && pSkill->GetTeachers ()[0] != '\0') ch->SendTextf ("Teachers: %s\n\r", pSkill->GetTeachers ()); if (pSkill->GetComponents () && pSkill->GetComponents ()[0] != '\0') ch->SendTextf ("Components: %s\n\r", pSkill->GetComponents ()); if (pSkill->GetParticipants ()) ch->SendTextf ("Participants: %d\n\r", pSkill->GetParticipants ()); if (pSkill->GetUseRec ().num_uses) send_timer (&pSkill->GetUseRec (), ch); for (aff = pSkill->GetAffects (); aff; aff = aff->GetNext ()) { if (aff == pSkill->GetAffects ()) ch->SendText ("\n\r"); sprintf (buf, "Affect %d", ++cnt); if (aff->location) { strcat (buf, " modifies "); strcat (buf, a_types [aff->location % REVERSE_APPLY]); strcat (buf, " by '"); strcat (buf, aff->modifier); strcat (buf, (aff->bitvector >= 0) ? "' and" : "'"); } if (aff->bitvector >= 0) { strcat (buf, " applies "); strcat (buf, CAffectFlags::GetName (aff->bitvector)); } if (aff->duration [0] != '\0' && aff->duration [0] != '0') { strcat (buf, " for '"); strcat (buf, aff->duration); strcat (buf, "' rounds"); } if (aff->location >= REVERSE_APPLY) strcat (buf, " (affects caster only)"); strcat (buf, "\n\r"); ch->SendText (buf); if (! aff->GetNext ()) ch->SendText ("\n\r"); } if (pSkill->ValidHitCharMsg ()) ch->SendTextf ("Hitchar : %s\n\r", pSkill->GetHitCharMsg ()); if (pSkill->ValidHitVictMsg ()) ch->SendTextf ("Hitvict : %s\n\r", pSkill->GetHitVictMsg ()); if (pSkill->ValidHitRoomMsg ()) ch->SendTextf ("Hitroom : %s\n\r", pSkill->GetHitRoomMsg ()); if (pSkill->ValidHitDest ()) ch->SendTextf ("Hitdest : %s\n\r", pSkill->GetHitDest ()); if (pSkill->ValidMissCharMsg ()) ch->SendTextf ("Misschar : %s\n\r", pSkill->GetMissCharMsg ()); if (pSkill->ValidMissVictMsg ()) ch->SendTextf ("Missvict : %s\n\r", pSkill->GetMissVictMsg ()); if (pSkill->ValidMissRoomMsg ()) ch->SendTextf ("Missroom : %s\n\r", pSkill->GetMissRoomMsg ()); if (pSkill->ValidDieCharMsg ()) ch->SendTextf ("Diechar : %s\n\r", pSkill->GetDieCharMsg ()); if (pSkill->ValidDieVictMsg ()) ch->SendTextf ("Dievict : %s\n\r", pSkill->GetDieVictMsg ()); if (pSkill->ValidDieRoomMsg ()) ch->SendTextf ("Dieroom : %s\n\r", pSkill->GetDieRoomMsg ()); if (pSkill->ValidImmuneCharMsg ()) ch->SendTextf ("Immchar : %s\n\r", pSkill->GetImmuneCharMsg ()); if (pSkill->ValidImmuneVictMsg ()) ch->SendTextf ("Immvict : %s\n\r", pSkill->GetImmuneVictMsg ()); if (pSkill->ValidImmuneRoomMsg ()) ch->SendTextf ("Immroom : %s\n\r", pSkill->GetImmuneRoomMsg ()); if (pSkill->GetType () != SKILL_HERB) { if (pSkill->GetType () != SKILL_RACIAL) { ch->SendText ("--------------------------[CLASS USE]-----" "---------------------\n\r"); for (iClass = 0; iClass < ClassTable.GetCount (); ++iClass) { strcpy (buf, ClassTable.GetName (iClass)); sprintf (buf+3, ") lvl: %3d max: %2d%%", pSkill->GetClassLevel (iClass), pSkill->GetClassAdept (iClass)); if (iClass % 3 == 2) strcat (buf, "\n\r"); else strcat (buf, " "); ch->SendText (buf); } } else { ch->SendText ("\n\r--------------------------[RACE USE]---" "-----------------------\n\r"); for (int ra=0; ra < RaceTable.GetCount (); ++ra) { sprintf (buf, "%8.8s) lvl: %3d max: %2d%%", RaceTable.GetName (ra), pSkill->GetRaceLevel (ra), pSkill->GetRaceAdept (ra)); if (ra % 3 == 2) strcat (buf, "\n\r"); else strcat (buf, " "); ch->SendText (buf); } } } ch->SendText ("\n\r"); } } // Set a skill's attributes or what skills a player has. // High god command, with support for creating skills/spells/herbs/etc void do_sset (CCharacter *ch, char *argument) { char arg1 [MAX_INPUT_LENGTH]; char arg2 [MAX_INPUT_LENGTH]; CCharacter *victim; int value; int sn; int i; BOOL fAll; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); if (arg1 [0] == '\0' || arg2 [0] == '\0') { SkillHelp (ch); return; } if (ch->GetTrustLevel () > LEVEL_SUB_IMPLEM && ! str_cmp (arg1, "save")) { if (! str_cmp (arg2, "skills")) { ch->SendText ("Saving skill table...\n\r"); save_skill_table (); return; } if (! str_cmp (arg2, "classes")) { ch->SendText ("Saving classes...\n\r"); ClassTable.Save (); return; } if (! str_cmp (arg2, "races")) { ch->SendText ("Saving races...\n\r"); RaceTable.Save (); return; } if (! str_cmp (arg2, "herbs")) { ch->SendText ("Saving herb table...\n\r"); save_herb_table (); return; } } if (argument [0] == '\0') { SkillHelp (ch); return; } if (ch->GetTrustLevel () > LEVEL_SUB_IMPLEM && !str_cmp (arg1, "create") && (!str_cmp (arg2, "skill") || !str_cmp (arg2, "herb") || !str_cmp (arg2, "ability"))) { CSkill *skill; short type = SKILL_UNKNOWN; if (! str_cmp (arg2, "herb")) { type = SKILL_HERB; if (HerbTable.GetCount () >= MAX_HERB) { ch->SendTextf ("The current top herb is %d, which is the " "maximum. To add more herbs,\n\rMAX_HERB will have to be " "raised in smaug.h, and the mud recompiled.\n\r", HerbTable.GetCount ()); return; } } else if (SkillTable.GetCount () >= MAX_SKILL) { ch->SendTextf ("The current top sn is %d, which is the maximum. " "To add more skills,\n\rMAX_SKILL will have to be " "raised in smaug.h, and the mud recompiled.\n\r", SkillTable.GetCount ()); return; } skill = new CSkill; if (type == SKILL_HERB) HerbTable.Add (skill); else SkillTable.Add (skill); skill->SetName (str_dup (argument)); skill->SetDamageMsg (str_dup ("")); skill->SetOffMsg (str_dup ("")); skill->SetSpellFunction (spell_smaug); skill->SetType (type); skill->SetGuild (CLASS_NONE); if (! str_cmp (arg2, "ability")) skill->SetType (SKILL_RACIAL); for (i=0; i < ClassTable.GetCount (); ++i) { skill->SetClassLevel (i, LEVEL_IMMORTAL); skill->SetClassAdept (i, 95); } for (i=0; i < RaceTable.GetCount (); ++i) { skill->SetRaceLevel (i, LEVEL_IMMORTAL); skill->SetRaceAdept (i, 95); } ch->SendText ("Done.\n\r"); return; } if (arg1 [0] == 'h') sn = atoi (arg1+1); else sn = atoi (arg1); if (ch->GetTrustLevel () > LEVEL_GREATER && ((arg1[0] == 'h' && is_number (arg1+1) && (sn=atoi (arg1+1))>=0) || (is_number (arg1) && (sn=atoi (arg1)) >= 0))) { CSkill *skill; if (arg1 [0] == 'h') { if (sn >= HerbTable.GetCount ()) { ch->SendText ("Herb number out of range.\n\r"); return; } skill = HerbTable.GetSkill (sn); } else { if ((skill=SkillTable.GetValidSkill (sn)) == NULL) { ch->SendText ("Skill number out of range.\n\r"); return; } sn %= 1000; } if (! str_cmp (arg2, "difficulty")) { skill->SetDifficulty (atoi (argument)); ch->SendText ("Ok.\n\r"); return; } if (! str_cmp (arg2, "participants")) { skill->SetParticipants (atoi (argument)); ch->SendText ("Ok.\n\r"); return; } if (! str_cmp (arg2, "damtype")) { int x = get_sdamage (argument); if (x == -1) ch->SendText ("Not a spell damage type.\n\r"); else { SET_SDAM (skill, x); ch->SendText ("Ok.\n\r"); } return; } if (! str_cmp (arg2, "acttype")) { int x = get_saction (argument); if (x == -1) ch->SendText ("Not a spell action type.\n\r"); else { SET_SACT (skill, x); ch->SendText ("Ok.\n\r"); } return; } if (! str_cmp (arg2, "classtype")) { int x = get_sclass (argument); if (x == -1) ch->SendText ("Not a spell class type.\n\r"); else { SET_SCLA (skill, x); ch->SendText ("Ok.\n\r"); } return; } if (! str_cmp (arg2, "powertype")) { int x = get_spower (argument); if (x == -1) ch->SendText ("Not a spell power type.\n\r"); else { SET_SPOW (skill, x); ch->SendText ("Ok.\n\r"); } return; } if (! str_cmp (arg2, "seffect")) { int x = SkillTable.GetSaveEffectFromName (argument); if (x == -1) ch->SendText ("Not a spell save effect type.\n\r"); else { skill->SetSaveEffect (x); ch->SendText ("Ok.\n\r"); } return; } if (! str_cmp (arg2, "flag")) { int x = get_sflag (argument); if (x == -1) ch->SendText ("Not a spell flag.\n\r"); else { int flgs = skill->GetFlags (); TOGGLE_BIT (flgs, 1 << (x)); skill->SetFlags (flgs); ch->SendText ("Ok.\n\r"); } return; } if (! str_cmp (arg2, "saves")) { int x = get_ssave (argument); if (x == -1) ch->SendText ("Not a saving type.\n\r"); else { skill->SetSaves (x); ch->SendText ("Ok.\n\r"); } return; } if (! str_cmp (arg2, "code")) { SPELL_FUN *spellfun; DO_FUN *dofun; if ((spellfun=spell_function (argument)) != spell_notfound) { skill->SetSpellFunction (spellfun); skill->SetSkillFunction (NULL); } else if ((dofun=skill_function (argument)) != skill_notfound) { skill->SetSkillFunction (dofun); skill->SetSpellFunction (NULL); } else { ch->SendText ("Not a spell or skill.\n\r"); return; } ch->SendText ("Ok.\n\r"); return; } if (! str_cmp (arg2, "target")) { int x = get_starget (argument); if (x == -1) ch->SendText ("Not a valid target type.\n\r"); else { skill->SetTarget (x); ch->SendText ("Ok.\n\r"); } return; } if (! str_cmp (arg2, "minpos")) { skill->SetMinimumPosition (URANGE (POS_DEAD, atoi (argument), POS_DRAG)); ch->SendText ("Ok.\n\r"); return; } if (! str_cmp (arg2, "minlevel")) { skill->SetMinLevel (URANGE (1, atoi (argument), MAX_LEVEL)); ch->SendText ("Ok.\n\r"); return; } if (! str_cmp (arg2, "slot")) { skill->SetSlot (URANGE (0, atoi (argument), 30000)); ch->SendText ("Ok.\n\r"); return; } if (! str_cmp (arg2, "mana")) { skill->SetMinMana (URANGE (0, atoi (argument), 2000)); ch->SendText ("Ok.\n\r"); return; } if (! str_cmp (arg2, "beats")) { skill->SetBeats (URANGE (0, atoi (argument), 120)); ch->SendText ("Ok.\n\r"); return; } if (! str_cmp (arg2, "range")) { skill->SetRange (URANGE (0, atoi (argument), 20)); ch->SendText ("Ok.\n\r"); return; } if (! str_cmp (arg2, "guild")) { skill->SetGuild (atoi (argument)); ch->SendText ("Ok.\n\r"); return; } if (! str_cmp (arg2, "value")) { skill->SetValue (atoi (argument)); ch->SendText ("Ok.\n\r"); return; } if (! str_cmp (arg2, "type")) { skill->SetType (get_skill (argument)); ch->SendText ("Ok.\n\r"); return; } if (! str_cmp (arg2, "rmaffect")) { CSmaugAffect *aff = skill->GetAffects (); CSmaugAffect *aff_next; int num = atoi (argument); int cnt = 1; if (! aff) { ch->SendText ("This spell has no special affects to remove.\n\r"); return; } if (num == 1) { skill->SetAffects (aff->GetNext ()); delete aff; ch->SendText ("Removed.\n\r"); return; } for (; aff; aff = aff->GetNext ()) { if (++cnt == num && (aff_next=aff->GetNext ()) != NULL) { aff->SetNext (aff_next->GetNext ()); delete aff_next; ch->SendText ("Removed.\n\r"); return; } } ch->SendText ("Not found.\n\r"); return; } // affect <location> <modifier> <duration> <bitvector> if (! str_cmp (arg2, "affect")) { char location [MAX_INPUT_LENGTH]; char modifier [MAX_INPUT_LENGTH]; char duration [MAX_INPUT_LENGTH]; int loc, bit, tmpbit; CSmaugAffect *aff; argument = one_argument (argument, location); argument = one_argument (argument, modifier); argument = one_argument (argument, duration); if (location [0] == '!') loc = get_atype (location+1) + REVERSE_APPLY; else loc = get_atype (location); if ((loc % REVERSE_APPLY) < 0 || (loc % REVERSE_APPLY) >= MAX_APPLY_TYPE) { ch->SendText ("Unknown affect location. See AFFECTTYPES.\n\r"); return; } bit = -1; if (argument [0] != 0) { if ((tmpbit = get_aflag (argument)) == -1) ch->SendTextf ("Unknown bitvector: %s. See " "AFFECTED_BY\n\r", argument); else bit = tmpbit; } aff = new CSmaugAffect; if (! str_cmp (duration, "0")) duration [0] = '\0'; if (! str_cmp (modifier, "0")) modifier [0] = '\0'; aff->duration = str_dup (duration); aff->location = loc; aff->modifier = str_dup (modifier); aff->bitvector = bit; aff->SetNext (skill->GetAffects ()); skill->SetAffects (aff); ch->SendText ("Ok.\n\r"); return; } if (! str_cmp (arg2, "level")) { char arg3 [MAX_INPUT_LENGTH]; int Class; argument = one_argument (argument, arg3); Class = ClassTable.GetClass (arg3); if (Class == CLASS_NONE) ch->SendText ("Not a valid class.\n\r"); else skill->SetClassLevel (Class, URANGE (0, atoi (argument), MAX_LEVEL)); return; } if (! str_cmp (arg2, "racelevel")) { char arg3 [MAX_INPUT_LENGTH]; int race; argument = one_argument (argument, arg3); race = RaceTable.GetRace (arg3); if (race == RACE_NONE) ch->SendText ("Not a valid race.\n\r"); else skill->SetRaceLevel (race, URANGE (0, atoi (argument), MAX_LEVEL)); return; } if (! str_cmp (arg2, "adept")) { char arg3 [MAX_INPUT_LENGTH]; int Class; argument = one_argument (argument, arg3); Class = ClassTable.GetClass (arg3); if (Class == CLASS_NONE) ch->SendText ("Not a valid class.\n\r"); else skill->SetClassAdept (Class, URANGE (0, atoi (argument), 100)); return; } if (! str_cmp (arg2, "raceadept")) { char arg3 [MAX_INPUT_LENGTH]; int race; argument = one_argument (argument, arg3); race = RaceTable.GetRace (arg3); if (race == RACE_NONE) ch->SendText ("Not a valid race.\n\r"); else skill->SetRaceAdept (race, URANGE (0, atoi (argument), 100)); return; } if (! str_cmp (arg2, "name")) { delete skill->GetName (); skill->SetName (str_dup (argument)); ch->SendText ("Ok.\n\r"); return; } #define REP(msg) skill->msg (stricmp (argument, "clear") ? \ str_dup (argument) : NULL); \ ch->SendText ("Ok.\n\r") // if (! str_cmp (argument, "clear")) // skill->SetDamageMsg (NULL); // else // skill->SetDamageMsg (str_dup (argument)); // ch->SendText ("Ok.\n\r"); if (! str_cmp (arg2, "dammsg")) { delete skill->GetDamageMsg (); REP (SetDamageMsg); return; } if (! str_cmp (arg2, "wearoff")) { delete skill->GetOffMsg (); REP (SetOffMsg); return; } if (! str_cmp (arg2, "hitchar")) { delete skill->GetHitCharMsg (); REP (SetHitCharMsg); return; } if (! str_cmp (arg2, "hitvict")) { delete skill->GetHitVictMsg (); REP (SetHitVictMsg); return; } if (! str_cmp (arg2, "hitroom")) { delete skill->GetHitRoomMsg (); REP (SetHitRoomMsg); return; } if (! str_cmp (arg2, "hitdest")) { delete skill->GetHitDest (); REP (SetHitDest); return; } if (! str_cmp (arg2, "misschar")) { delete skill->GetMissCharMsg (); REP (SetMissCharMsg); return; } if (! str_cmp (arg2, "missvict")) { delete skill->GetMissVictMsg (); REP (SetMissVictMsg); return; } if (! str_cmp (arg2, "missroom")) { delete skill->GetMissRoomMsg (); REP (SetMissRoomMsg); return; } if (! str_cmp (arg2, "diechar")) { delete skill->GetDieCharMsg (); REP (SetDieCharMsg); return; } if (! str_cmp (arg2, "dievict")) { delete skill->GetDieVictMsg (); REP (SetDieVictMsg); return; } if (! str_cmp (arg2, "dieroom")) { delete skill->GetDieRoomMsg (); REP (SetDieRoomMsg); return; } if (! str_cmp (arg2, "immchar")) { delete skill->GetImmuneCharMsg (); REP (SetImmuneCharMsg); return; } if (! str_cmp (arg2, "immvict")) { delete skill->GetImmuneVictMsg (); REP (SetImmuneVictMsg); return; } if (! str_cmp (arg2, "immroom")) { delete skill->GetImmuneRoomMsg (); REP (SetImmuneRoomMsg); return; } if (! str_cmp (arg2, "dice")) { delete skill->GetDiceRoll (); REP (SetDiceRoll); return; } if (! str_cmp (arg2, "components")) { delete skill->GetComponents (); REP (SetComponents); return; } if (! str_cmp (arg2, "teachers")) { delete skill->GetTeachers (); REP (SetTeachers); return; } do_sset (ch, ""); return; } if ((victim = get_char_world (ch, arg1)) == NULL) { if ((sn = SkillTable.Lookup (arg1)) >= 0) { sprintf (arg1, "%d %s %s", sn, arg2, argument); do_sset (ch, arg1); } else ch->SendText ("They aren't here.\n\r"); return; } if (victim->IsNpc ()) { ch->SendText ("Not on NPC's.\n\r"); return; } fAll = ! str_cmp (arg2, "all"); sn = 0; if (! fAll && (sn = SkillTable.Lookup (arg2)) < 0) { ch->SendText ("No such skill or spell.\n\r"); return; } // Snarf the value. if (! is_number (argument)) { ch->SendText ("Value must be numeric.\n\r"); return; } value = atoi (argument); if (value < 0 || value > 100) { ch->SendText ("Value range is 0 to 100.\n\r"); return; } if (fAll) { for (sn = 0; sn < SkillTable.GetCount (); sn++) { // Fix by Narn to prevent ssetting skills // the player shouldn't have. if (SkillTable.GetName (sn) && (victim->GetLevel () >= SkillTable.GetClassLevel (sn, victim->GetClass ()) || value == 0)) victim->GetPcData ()->learned [sn] = value; } } else victim->GetPcData ()->learned [sn] = value; } void SkillHelp (CCharacter* ch) { ch->SendText ("Syntax: sset <victim> <skill> <value>\n\r"); ch->SendText ("or: sset <victim> all <value>\n\r"); if (ch->GetTrustLevel () > LEVEL_SUB_IMPLEM) { ch->SendText ("or: sset save skills\n\r"); ch->SendText ("or: sset save herbs\n\r"); ch->SendText ("or: sset save classes\n\r"); ch->SendText ("or: sset save races\n\r"); ch->SendText ("or: sset create skill 'new skill'\n\r"); ch->SendText ("or: sset create herb 'new herb'\n\r"); ch->SendText ("or: sset create ability 'new ability'\n\r"); } if (ch->GetTrustLevel () > LEVEL_GREATER) { ch->SendText ("or: sset <sn> <field> <value>\n\r"); ch->SendText ("\n\rField being one of:\n\r"); ch->SendText (" name code target minpos slot mana beats dammsg wearoff guild minlevel\n\r"); ch->SendText (" type damtype acttype classtype powertype seffect flag dice value difficulty affect\n\r"); ch->SendText (" affect rmaffect level adept hit miss die imm (char/vict/room)\n\r"); ch->SendText (" components teachers racelevel raceadept\n\r"); ch->SendText ("Affect having the fields: <location> <modfifier> [duration] [bitvector]\n\r"); ch->SendText ("(See AFFECTTYPES for location, and AFFECTED_BY for bitvector)\n\r"); } ch->SendText ("Skill being any skill or spell.\n\r"); } void learn_from_success (CCharacter *ch, int sn) { int adept, gain, sklvl, learn, percent, chance; if (ch->IsNpc () || ch->GetPcData ()->learned [sn] == 0) return; short &learned = ch->GetPcData ()->learned [sn]; adept = SkillTable.GetClassAdept (sn, ch->GetClass ()); if (learned >= adept) return; // already knows it all sklvl = SkillTable.GetClassLevel (sn, ch->GetClass ()); if (sklvl == 0) sklvl = ch->GetLevel (); chance = learned + (5 * SkillTable.GetDifficulty (sn)); percent = number_percent (); if (percent >= chance) learn = 2; else if (chance - percent > 25) return; else learn = 1; learned = UMIN (adept, learned + learn); int Mage = ClassTable.GetClass ("Mage"); if (learned == adept) { // now fully learned! gain = 1000 * sklvl; if (ch->GetClass () == Mage) gain *= 5; // h, mage upgrade set_char_color (AT_WHITE, ch); ch->SendTextf ("You are now an adept of %s! You gain %d bonus" " experience!\n\r", SkillTable.GetName (sn), gain); } else { gain = 20 * sklvl; if (ch->GetClass () == Mage) gain *= 6; // h, mage upgrade if (! ch->GetFightData () && sn != gsn_hide && sn != gsn_sneak) { set_char_color (AT_WHITE, ch); ch->SendTextf ( "You gain %d experience points from your success!\n\r", gain); } } gain_exp (ch, gain); } void learn_from_failure (CCharacter *ch, int sn) { int adept, chance; short &learned = ch->GetPcData ()->learned [sn]; if (ch->IsNpc () || learned == 0) return; chance = learned + (5 * SkillTable.GetDifficulty (sn)); if (chance - number_percent () > 25) return; adept = SkillTable.GetClassAdept (sn, ch->GetClass ()); if (learned < (adept-1)) ++learned; } void do_gouge (CCharacter *ch, char *argument) { CCharacter *victim; CAffectData af; short dam; int chance; if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } if (! can_use_skill (ch, 0, gsn_gouge)) { ch->SendText ("You do not yet know of this skill.\n\r"); return; } if (ch->mount) { ch->SendText ("You can't get close enough while mounted.\n\r"); return; } if ((victim = ch->GetFightWho ()) == NULL) { ch->SendText ("You aren't fighting anyone.\n\r"); return; } chance = ((victim->GetDexterity () - ch->GetDexterity ()) * 10) + 10; // 1.4add // if (! ch->IsNpc () && ! victim->IsNpc ()) // chance += sysdata.gouge_plr_vs_plr; // // if (victim->fighting && victim->fighting->who != ch) // chance += sysdata.gouge_nontank; if (can_use_skill (ch, (number_percent () + chance), gsn_gouge)) { dam = number_range (5, ch->GetLevel ()); global_retcode = damage (ch, victim, dam, gsn_gouge); if (global_retcode == rNONE) { if (! victim->IsBlind ()) { af.type = gsn_blindness; af.location = APPLY_HITROLL; af.modifier = -6; if (! victim->IsNpc () && ! ch->IsNpc ()) af.duration = (ch->GetLevel () + 10) / victim->GetConstitution (); else af.duration = 3 + (ch->GetLevel () / 15); af.bitvector = AFF_BLIND; affect_to_char (victim, &af); act (AT_SKILL, "You can't see a thing!", victim, NULL, NULL, TO_CHAR); } WAIT_STATE (ch, PULSE_VIOLENCE); if (! ch->IsNpc () && ! victim->IsNpc ()) { if (number_bits (1) == 0) { ch->SendTextf ("%s looks momentarily dazed.\n\r", victim->GetName ()); victim->SendText ("You are momentarily dazed ...\n\r"); WAIT_STATE (victim, PULSE_VIOLENCE); } } else WAIT_STATE (victim, PULSE_VIOLENCE); // Taken out by request - put back in by Thoric // This is how it was designed. You'd be a tad stunned // if someone gouged you in the eye. // Mildly modified by Blodkai, Feb 1998 at request of // of pkill Conclave (peaceful use remains the same) } else if (global_retcode == rVICT_DIED) { act (AT_BLOOD, "Your fingers plunge into your victim's brain, " "causing immediate death!", ch, NULL, NULL, TO_CHAR); } if (global_retcode != rCHAR_DIED && global_retcode != rBOTH_DIED) learn_from_success (ch, gsn_gouge); } else { WAIT_STATE (victim, PULSE_VIOLENCE); WAIT_STATE (ch, SkillTable.GetBeats (gsn_gouge)); global_retcode = damage (ch, victim, 0, gsn_gouge); learn_from_failure (ch, gsn_gouge); } } void do_detrap (CCharacter *ch, char *argument) { char arg [MAX_INPUT_LENGTH]; CObjData *trap; CObjData *obj; int percent; BOOL bFound = FALSE; POSITION Cpos; switch (ch->GetSubstate ()) { default: if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } argument = one_argument (argument, arg); if (! can_use_skill (ch, 0, gsn_detrap)) { ch->SendText ("You do not yet know of this skill.\n\r"); return; } if (arg [0] == '\0') { ch->SendText ("Detrap what?\n\r"); return; } if (ms_find_obj (ch)) return; if (ch->mount) { ch->SendText ("You can't do that while mounted.\n\r"); return; } if (ch->GetInRoom ()->IsEmpty ()) { ch->SendText ("You can't find that here.\n\r"); return; } Cpos = ch->GetInRoom ()->GetHeadContentPos (); while (obj = ch->GetInRoom ()->GetNextContent (Cpos)) { if (can_see_obj (ch, *obj) && nifty_is_name (arg, obj->GetName ())) { bFound = TRUE; break; } } if (! bFound) { ch->SendText ("You can't find that here.\n\r"); return; } act (AT_ACTION, "You carefully begin your attempt to remove a trap from $p...", ch, obj, NULL, TO_CHAR); act (AT_ACTION, "$n carefully attempts to remove a trap from $p...", ch, obj, NULL, TO_ROOM); ch->alloc_ptr = str_dup (obj->GetName ()); add_timer (ch, TIMER_DO_FUN, 3, do_detrap, 1); /* WAIT_STATE (ch, skill_table[gsn_detrap]->beats); */ return; case 1: if (! ch->alloc_ptr) { ch->SendText ("Your detrapping was interrupted!\n\r"); bug ("do_detrap: ch->dest_buf NULL!"); return; } strcpy (arg, (char*) ch->alloc_ptr); delete ch->alloc_ptr; ch->alloc_ptr = NULL; ch->SetSubstate (SUB_NONE); break; case SUB_TIMER_DO_ABORT: delete ch->alloc_ptr; ch->alloc_ptr = NULL; ch->SetSubstate (SUB_NONE); ch->SendText ("You carefully stop what you were doing.\n\r"); return; } if (ch->GetInRoom ()->IsEmpty ()) { ch->SendText ("You can't find that here.\n\r"); return; } Cpos = ch->GetInRoom ()->GetHeadContentPos (); while (obj = ch->GetInRoom ()->GetNextContent (Cpos)) { if (can_see_obj (ch, *obj) && nifty_is_name (arg, obj->GetName ())) { bFound = TRUE; break; } } if (! bFound) { ch->SendText ("You can't find that here.\n\r"); return; } if ((trap = get_trap (obj)) == NULL) { ch->SendText ("You find no trap on that.\n\r"); return; } percent = number_percent () - (ch->GetLevel () / 15) - (get_curr_lck (ch) - 16); separate_obj (obj); if (can_use_skill (ch, percent, gsn_detrap)) { ch->SendText ("Ooops!\n\r"); spring_trap (ch, trap); learn_from_failure (ch, gsn_detrap); return; } extract_obj (trap); ch->SendText ("You successfully remove a trap.\n\r"); learn_from_success (ch, gsn_detrap); } void do_dig (CCharacter *ch, char *argument) { char arg [MAX_INPUT_LENGTH]; CObjData *obj; BOOL bFound; BOOL bShovel; CExitData *pexit; switch (ch->GetSubstate ()) { default: if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } if (ch->mount) { ch->SendText ("You can't do that while mounted.\n\r"); return; } one_argument (argument, arg); if (arg [0] != '\0') { if ((pexit = find_door (ch, arg, TRUE)) == NULL && get_dir (arg) == -1) { ch->SendText ("What direction is that?\n\r"); return; } if (pexit) { if (! pexit->IsDig () && ! pexit->IsClosed ()) { ch->SendText ("There is no need to dig out that exit.\n\r"); return; } } } else { switch (ch->GetInRoom ()->sector_type) { case SECT_CITY: case SECT_INSIDE: ch->SendText ("The floor is too hard to dig through.\n\r"); return; case SECT_WATER_SWIM: case SECT_WATER_NOSWIM: case SECT_UNDERWATER: ch->SendText ("You cannot dig here.\n\r"); return; case SECT_AIR: ch->SendText ("What? In the air?!\n\r"); return; } } add_timer (ch, TIMER_DO_FUN, UMIN (SkillTable.GetBeats (gsn_dig) / 10, 3), do_dig, 1); ch->alloc_ptr = str_dup (arg); ch->SendText ("You begin digging...\n\r"); act (AT_PLAIN, "$n begins digging...", ch, NULL, NULL, TO_ROOM); return; case 1: if (! ch->alloc_ptr) { ch->SendText ("Your digging was interrupted!\n\r"); act (AT_PLAIN, "$n's digging was interrupted!", ch, NULL, NULL, TO_ROOM); bug ("do_dig: dest_buf NULL"); return; } strcpy (arg, (char*) ch->alloc_ptr); delete ch->alloc_ptr; ch->alloc_ptr = NULL; break; case SUB_TIMER_DO_ABORT: delete ch->alloc_ptr; ch->alloc_ptr = NULL; ch->SetSubstate (SUB_NONE); ch->SendText ("You stop digging...\n\r"); act (AT_PLAIN, "$n stops digging...", ch, NULL, NULL, TO_ROOM); return; } ch->SetSubstate (SUB_NONE); // not having a shovel makes it harder to succeed bShovel = FALSE; POSITION pos = ch->GetHeadCarryPos (); while (pos) if (ch->GetNextCarrying (pos)->item_type == ITEM_SHOVEL) { bShovel = TRUE; break; } // dig out an EX_DIG exit... if (arg [0] != '\0') { if ((pexit = find_door (ch, arg, TRUE)) != NULL && pexit->IsDig () && pexit->IsClosed ()) { // 4 times harder to dig open a passage without a shovel if (can_use_skill (ch, (number_percent () * (bShovel ? 1 : 4)), gsn_dig)) { pexit->ClrClosed (); ch->SendText ("You dig open a passageway!\n\r"); act (AT_PLAIN, "$n digs open a passageway!", ch, NULL, NULL, TO_ROOM); learn_from_success (ch, gsn_dig); return; } } learn_from_failure (ch, gsn_dig); ch->SendText ("Your dig did not discover any exit...\n\r"); act (AT_PLAIN, "$n's dig did not discover any exit...", ch, NULL, NULL, TO_ROOM); return; } bFound = FALSE; pos = ch->GetInRoom ()->GetHeadContentPos (); while (obj = ch->GetInRoom ()->GetNextContent (pos)) { // twice as hard to find something without a shovel if (obj->IsBuried () && (can_use_skill (ch, (number_percent () * (bShovel ? 1 : 2)), gsn_dig))) { bFound = TRUE; break; } } if (! bFound) { ch->SendText ("Your dig uncovered nothing.\n\r"); act (AT_PLAIN, "$n's dig uncovered nothing.", ch, NULL, NULL, TO_ROOM); learn_from_failure (ch, gsn_dig); return; } separate_obj (obj); obj->ClrBuried (); act (AT_SKILL, "Your dig uncovered $p!", ch, obj, NULL, TO_CHAR); act (AT_SKILL, "$n's dig uncovered $p!", ch, obj, NULL, TO_ROOM); learn_from_success (ch, gsn_dig); if (obj->item_type == ITEM_CORPSE_PC || obj->item_type == ITEM_CORPSE_NPC) adjust_favor (ch, 14, 1); } void do_search (CCharacter *ch, char *argument) { char arg [MAX_INPUT_LENGTH]; CObjData *obj; CObjData *container; int percent; int door = -1; switch (ch->GetSubstate ()) { default: if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } if (ch->mount) { ch->SendText ("You can't do that while mounted.\n\r"); return; } argument = one_argument (argument, arg); if (arg [0] != '\0' && (door = get_door (arg)) == -1) { container = get_obj_here (ch, arg); if (! container) { ch->SendText ("You can't find that here.\n\r"); return; } if (container->item_type != ITEM_CONTAINER) { ch->SendText ("You can't search in that!\n\r"); return; } if (IS_SET (container->value [1], CONT_CLOSED)) { ch->SendText ("It is closed.\n\r"); return; } } add_timer (ch, TIMER_DO_FUN, UMIN (SkillTable.GetBeats (gsn_search) / 10, 3), do_search, 1); ch->SendText ("You begin your search...\n\r"); ch->alloc_ptr = str_dup (arg); return; case 1: if (! ch->alloc_ptr) { ch->SendText ("Your search was interrupted!\n\r"); bug ("do_search: dest_buf NULL"); return; } strcpy (arg, (char*) ch->alloc_ptr); delete ch->alloc_ptr; ch->alloc_ptr = NULL; break; case SUB_TIMER_DO_ABORT: delete ch->alloc_ptr; ch->alloc_ptr = NULL; ch->SetSubstate (SUB_NONE); ch->SendText ("You stop your search...\n\r"); return; } ch->SetSubstate (SUB_NONE); CObjectList *pList = NULL; if (arg [0] == '\0') pList = &ch->GetInRoom ()->GetContentList (); else { if ((door = get_door (arg)) == -1) { container = get_obj_here (ch, arg); if (! container) { ch->SendText ("You can't find that here.\n\r"); return; } pList = &container->GetContentList (); } } if ((! pList && door == -1) || ch->IsNpc ()) { ch->SendText ("You find nothing.\n\r"); learn_from_failure (ch, gsn_search); return; } percent = number_percent () + number_percent () - (ch->GetLevel () / 10); if (door != -1) { CExitData *pexit; if ((pexit = get_exit (ch->GetInRoom (), door)) != NULL && pexit->IsSecret () && pexit->CanSearch () && can_use_skill (ch, percent, gsn_search)) { act (AT_SKILL, "Your search reveals the $d!", ch, NULL, pexit->keyword, TO_CHAR); act (AT_SKILL, "$n finds the $d!", ch, NULL, pexit->keyword, TO_ROOM); pexit->ClrSecret (); learn_from_success (ch, gsn_search); return; } } else { POSITION pos = pList->GetHeadPosition (); while (obj = pList->GetNext (pos)) { if (obj->IsHidden () && can_use_skill (ch, percent, gsn_search)) { separate_obj (obj); obj->ClrHidden (); act (AT_SKILL, "Your search reveals $p!", ch, obj,NULL,TO_CHAR); act (AT_SKILL, "$n finds $p!", ch, obj, NULL, TO_ROOM ); learn_from_success (ch, gsn_search); return; } } } ch->SendText ("You find nothing.\n\r"); learn_from_failure (ch, gsn_search); } void do_steal (CCharacter *ch, char *argument) { char buf [MAX_STRING_LENGTH]; char arg1 [MAX_INPUT_LENGTH]; char arg2 [MAX_INPUT_LENGTH]; CCharacter *victim, *mst; CObjData *obj; int percent; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); if (ch->mount) { ch->SendText ("You can't do that while mounted.\n\r"); return; } if (arg1[0] == '\0' || arg2[0] == '\0') { ch->SendText ("Steal what from whom?\n\r"); return; } if (ms_find_obj (ch)) return; if ((victim = get_char_room (ch, arg2)) == NULL) { ch->SendText ("They aren't here.\n\r"); return; } if (victim == ch) { ch->SendText ("That's pointless.\n\r"); return; } if (ch->GetInRoom ()->IsSafe ()) { set_char_color (AT_MAGIC, ch); ch->SendText ("A magical force interrupts you.\n\r"); return; } /* Disabled stealing among players because of complaints naked avatars were running around stealing eq from equipped pkillers. -- Narn */ /* if (check_illegal_psteal (ch, victim)) { ch->SendText ("You can't steal from that player.\n\r"); return; } */ if (!ch->IsNpc () && !victim->IsNpc ()) { set_char_color (AT_IMMORT, ch); ch->SendText ("The gods forbid theft between players.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_steal)); percent = number_percent () + (victim->IsAwake () ? 10 : -50) - (get_curr_lck (ch) - 15) + (get_curr_lck (victim) - 13); /* Changed the level check, made it 10 levels instead of five and made the victim not attack in the case of a too high level difference. This is to allow mobprogs where the mob steals eq without having to put level checks into the progs. Also gave the mobs a 10% chance of failure. */ if (ch->GetLevel () + 10 < victim->GetLevel ()) { ch->SendText ("You really don't want to try that!\n\r"); return; } if (victim->GetPosition () == POS_FIGHTING || ! can_use_skill (ch, percent, gsn_steal)) { /* * Failure. */ ch->SendText ("Oops...\n\r"); act (AT_ACTION, "$n tried to steal from you!\n\r", ch, NULL, victim, TO_VICT ); act (AT_ACTION, "$n tried to steal from $N.\n\r", ch, NULL, victim, TO_NOTVICT); sprintf (buf, "%s is a bloody thief!", ch->GetName ()); do_yell (victim, buf); learn_from_failure (ch, gsn_steal); if (!ch->IsNpc ()) { if (legal_loot (ch, victim)) { global_retcode = multi_hit (victim, ch, TYPE_UNDEFINED); } else { /* gpDoc->LogString (buf); */ if (ch->IsNpc ()) { if ((mst = ch->GetMaster ()) == NULL) return; } else mst = ch; if (mst->IsNpc ()) return; if (! mst->IsThief ()) { mst->SetThief (); set_char_color (AT_WHITE, ch); ch->SendText ("A strange feeling grows deep inside you, and a tingle goes up your spine...\n\r"); set_char_color (AT_IMMORT, ch); ch->SendText ("A deep voice booms inside your head, 'Thou shall now be known as a lowly thief!'\n\r"); set_char_color (AT_WHITE, ch); ch->SendText ("You feel as if your soul has been revealed for all to see.\n\r"); save_char_obj (mst); } } } return; } if (!str_cmp (arg1, "coin" ) || !str_cmp (arg1, "coins") || !str_cmp (arg1, "gold" )) { int amount; amount = (int) (victim->GetGold () * number_range (1, 10) / 100); if (amount <= 0) { ch->SendText ("You couldn't get any gold.\n\r"); learn_from_failure (ch, gsn_steal); return; } ch->AddGold (amount); victim->AddGold (-amount); ch->SendTextf ("Aha! You got %d gold coins.\n\r", amount); learn_from_success (ch, gsn_steal); return; } if ((obj = get_obj_carry (victim, arg1)) == NULL) { ch->SendText ("You can't seem to find it.\n\r"); learn_from_failure (ch, gsn_steal); return; } if (!can_drop_obj (ch, obj) || obj->IsInventory () || obj->IsPrototype () || obj->level > ch->GetLevel ()) { ch->SendText ("You can't manage to pry it away.\n\r"); learn_from_failure (ch, gsn_steal); return; } if (ch->carry_number + (get_obj_number (obj)/obj->count) > ch->GetMaxItems ()) { ch->SendText ("You have your hands full.\n\r"); learn_from_failure (ch, gsn_steal); return; } if (ch->GetCarryWeight () + (get_obj_weight (obj)/obj->count) > can_carry_w (ch)) { ch->SendText ("You can't carry that much weight.\n\r"); learn_from_failure (ch, gsn_steal); return; } separate_obj (obj); obj_from_char (obj); obj_to_char (obj, ch); ch->SendText ("Ok.\n\r"); learn_from_success (ch, gsn_steal); adjust_favor (ch, 9, 1); return; } void do_backstab (CCharacter *ch, char *argument) { char arg[MAX_INPUT_LENGTH]; CCharacter *victim; CObjData *obj; int percent; if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't do that right now.\n\r"); return; } one_argument (argument, arg); if (ch->mount) { ch->SendText ("You can't get close enough while mounted.\n\r"); return; } if (arg[0] == '\0') { ch->SendText ("Backstab whom?\n\r"); return; } if ((victim = get_char_room (ch, arg)) == NULL) { ch->SendText ("They aren't here.\n\r"); return; } if (victim == ch) { ch->SendText ("How can you sneak up on yourself?\n\r"); return; } if (is_safe (ch, victim)) return; /* Added stabbing weapon. -Narn */ if ((obj = get_eq_char (ch, WEAR_WIELD)) == NULL || (obj->value[3] != 11 && obj->value[3] != 2)) { ch->SendText ("You need to wield a piercing or stabbing weapon.\n\r"); return; } if (victim->GetFightData ()) { ch->SendText ("You can't backstab someone who is in combat.\n\r"); return; } /* Can backstab a char even if it's hurt as long as it's sleeping. -Narn */ if (victim->GetHp () < victim->GetMaxHp () && victim->IsAwake ()) { act (AT_PLAIN, "$N is hurt and suspicious ... you can't sneak up.", ch, NULL, victim, TO_CHAR); return; } percent = number_percent () - (get_curr_lck (ch) - 14) + (get_curr_lck (victim) - 13); check_attacker (ch, victim); WAIT_STATE (ch, SkillTable.GetBeats (gsn_backstab)); if (!victim->IsAwake () || ch->IsNpc () || can_use_skill( ch, percent, gsn_backstab)) { learn_from_success (ch, gsn_backstab); global_retcode = multi_hit (ch, victim, gsn_backstab); adjust_favor (ch, 10, 1); check_illegal_pk (ch, victim); } else { learn_from_failure (ch, gsn_backstab); global_retcode = damage (ch, victim, 0, gsn_backstab); } return; } void do_rescue (CCharacter *ch, char *argument) { char arg[MAX_INPUT_LENGTH]; CCharacter *victim; CCharacter *fch; int percent; if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } one_argument (argument, arg); if (arg[0] == '\0') { ch->SendText ("Rescue whom?\n\r"); return; } if ((victim = get_char_room (ch, arg)) == NULL) { ch->SendText ("They aren't here.\n\r"); return; } if (victim == ch) { ch->SendText ("How about fleeing instead?\n\r"); return; } if (ch->mount) { ch->SendText ("You can't do that while mounted.\n\r"); return; } if (!ch->IsNpc () && victim->IsNpc ()) { ch->SendText ("Doesn't need your help!\n\r"); return; } if (!ch->GetFightData ()) { ch->SendText ("Too late...\n\r"); return; } if ((fch = victim->GetFightWho ()) == NULL) { ch->SendText ("They are not fighting right now.\n\r"); return; } percent = number_percent () - (get_curr_lck (ch) - 14) - (get_curr_lck (victim) - 16); WAIT_STATE (ch, SkillTable.GetBeats (gsn_rescue)); if (! can_use_skill( ch, percent, gsn_rescue)) { ch->SendText ("You fail the rescue.\n\r"); act (AT_SKILL, "$n tries to rescue you!", ch, NULL, victim, TO_VICT ); act (AT_SKILL, "$n tries to rescue $N!", ch, NULL, victim, TO_NOTVICT); learn_from_failure (ch, gsn_rescue); return; } act (AT_SKILL, "You rescue $N!", ch, NULL, victim, TO_CHAR ); act (AT_SKILL, "$n rescues you!", ch, NULL, victim, TO_VICT ); act (AT_SKILL, "$n moves in front of $N!", ch, NULL, victim, TO_NOTVICT); learn_from_success (ch, gsn_rescue); adjust_favor (ch, 8, 1); stop_fighting (fch, FALSE); stop_fighting (victim, FALSE); if (ch->GetFightData ()) stop_fighting (ch, FALSE); /* check_killer (ch, fch); */ set_fighting (ch, fch); set_fighting (fch, ch); return; } void do_kick (CCharacter *ch, char *argument) { CCharacter *victim; if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } if (!ch->IsNpc () && ch->GetLevel () < SkillTable.GetClassLevel (gsn_kick, ch->GetClass ())) { ch->SendText ( "You better leave the martial arts to fighters.\n\r"); return; } if ((victim = ch->GetFightWho ()) == NULL) { ch->SendText ("You aren't fighting anyone.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_kick)); if (ch->IsNpc () || number_percent () < ch->GetPcData ()->learned[gsn_kick]) { learn_from_success (ch, gsn_kick); global_retcode = damage (ch, victim, number_range (1, ch->GetLevel ()), gsn_kick); } else { learn_from_failure (ch, gsn_kick); global_retcode = damage (ch, victim, 0, gsn_kick); } return; } void do_punch (CCharacter *ch, char *argument) { CCharacter *victim; if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } if (!ch->IsNpc () && ch->GetLevel () < SkillTable.GetClassLevel (gsn_punch, ch->GetClass ())) { ch->SendText ( "You better leave the martial arts to fighters.\n\r"); return; } if ((victim = ch->GetFightWho ()) == NULL) { ch->SendText ("You aren't fighting anyone.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_punch)); if (can_use_skill (ch, number_percent (), gsn_kick)) { learn_from_success (ch, gsn_punch); global_retcode = damage (ch, victim, number_range (1, ch->GetLevel ()), gsn_punch); } else { learn_from_failure (ch, gsn_punch); global_retcode = damage (ch, victim, 0, gsn_punch); } return; } void do_bite (CCharacter *ch, char *argument) { CCharacter *victim; if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } if (! ch->IsNpc () && ch->GetLevel () < SkillTable.GetClassLevel (gsn_bite, ch->GetClass ())) { ch->SendText ("That isn't quite one of your natural skills.\n\r"); return; } if ((victim = ch->GetFightWho ()) == NULL) { ch->SendText ("You aren't fighting anyone.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_bite)); if (can_use_skill (ch, number_percent (), gsn_bite)) { learn_from_success (ch, gsn_bite); global_retcode = damage (ch, victim, number_range (1, ch->GetLevel ()), gsn_bite); } else { learn_from_failure (ch, gsn_bite); global_retcode = damage (ch, victim, 0, gsn_bite); } } void do_claw (CCharacter *ch, char *argument) { CCharacter *victim; if (! ch->IsNpc () && ch->GetLevel () < SkillTable.GetClassLevel (gsn_claw, ch->GetClass ())) { ch->SendText ("That isn't quite one of your natural skills.\n\r"); return; } if ((victim = ch->GetFightWho ()) == NULL) { ch->SendText ("You aren't fighting anyone.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_claw)); if (can_use_skill (ch, number_percent (), gsn_claw)) { learn_from_success (ch, gsn_claw); global_retcode = damage (ch, victim, number_range (1, ch->GetLevel ()), gsn_claw); } else { learn_from_failure (ch, gsn_claw); global_retcode = damage (ch, victim, 0, gsn_claw); } } void do_sting (CCharacter *ch, char *argument) { CCharacter *victim; if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } if (! ch->IsNpc () && ch->GetLevel () < SkillTable.GetClassLevel (gsn_sting, ch->GetClass ())) { ch->SendText ("That isn't quite one of your natural skills.\n\r"); return; } if ((victim = ch->GetFightWho ()) == NULL) { ch->SendText ("You aren't fighting anyone.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_sting)); if (can_use_skill (ch, number_percent (), gsn_sting)) { learn_from_success (ch, gsn_sting); global_retcode = damage (ch, victim, number_range (1, ch->GetLevel ()), gsn_sting); } else { learn_from_failure (ch, gsn_sting); global_retcode = damage (ch, victim, 0, gsn_sting); } } void do_tail (CCharacter *ch, char *argument) { CCharacter *victim; if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } if (! ch->IsNpc () && ch->GetLevel () < SkillTable.GetClassLevel (gsn_tail, ch->GetClass ())) { ch->SendText ("That isn't quite one of your natural skills.\n\r"); return; } if ((victim = ch->GetFightWho ()) == NULL) { ch->SendText ("You aren't fighting anyone.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_tail)); if (can_use_skill (ch, number_percent (), gsn_tail)) { learn_from_success (ch, gsn_tail); global_retcode = damage (ch, victim, number_range (1, ch->GetLevel ()), gsn_tail); } else { learn_from_failure (ch, gsn_tail); global_retcode = damage (ch, victim, 0, gsn_tail); } } void do_bash (CCharacter *ch, char *argument) { CCharacter *victim; if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } if (! ch->IsNpc () && ch->GetLevel () < SkillTable.GetClassLevel (gsn_bash, ch->GetClass ())) { ch->SendText ("You better leave the martial arts to fighters.\n\r"); return; } if ((victim = ch->GetFightWho ()) == NULL) { ch->SendText ("You aren't fighting anyone.\n\r"); return; } int chance = (((victim->GetDexterity () + victim->GetCurrentStrength ()) - (ch->GetDexterity () + ch->GetCurrentStrength ())) * 10) + 10; if (! ch->IsNpc () && !victim->IsNpc ()) chance += 25; if (victim->GetFightData () && victim->GetFightData ()->who != ch) chance += 19; WAIT_STATE (ch, SkillTable.GetBeats (gsn_bash)); if (can_use_skill (ch, (number_percent () + chance), gsn_bash)) { learn_from_success (ch, gsn_bash); // do not change anything here! -Thoric WAIT_STATE (ch, 2 * PULSE_VIOLENCE); WAIT_STATE (victim, 2 * PULSE_VIOLENCE); victim->SetPosition (POS_SITTING); global_retcode = damage (ch, victim, number_range (1, ch->GetLevel ()), gsn_bash); } else { WAIT_STATE (ch, 2 * PULSE_VIOLENCE); learn_from_failure (ch, gsn_bash); global_retcode = damage (ch, victim, 0, gsn_bash); } } void do_stun (CCharacter *ch, char *argument) { CCharacter *victim; CAffectData af; if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } if (! ch->IsNpc () && ch->GetLevel () < SkillTable.GetClassLevel (gsn_stun, ch->GetClass ())) { ch->SendText ("You better leave the martial arts to fighters.\n\r"); return; } if ((victim = ch->GetFightWho ()) == NULL) { ch->SendText ("You aren't fighting anyone.\n\r"); return; } if (ch->GetMove () < 16) { set_char_color (AT_SKILL, ch); ch->SendText ("You are far too tired to do that.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_stun)); BOOL fail = FALSE; int chance = ris_save (victim, ch->GetLevel (), RIS_PARALYSIS); if (chance == 1000) fail = TRUE; else fail = saves_para_petri (chance, victim); chance = (((victim->GetDexterity () + victim->GetCurrentStrength ()) - (ch->GetDexterity () + ch->GetCurrentStrength ())) * 10) + 10; // harder for player to stun another player if (!ch->IsNpc () && !victim->IsNpc ()) chance += SysData.StunPlayerLev; else chance += SysData.StunRegularLev; if (!fail && can_use_skill (ch, (number_percent () + chance), gsn_stun)) { learn_from_success (ch, gsn_stun); // DO *NOT* CHANGE! -Thoric ch->AddMove (-15); WAIT_STATE (ch, 2 * PULSE_VIOLENCE); WAIT_STATE (victim, PULSE_VIOLENCE); act (AT_SKILL, "$N smashes into you, leaving you stunned!", victim, NULL, ch, TO_CHAR); act (AT_SKILL, "You smash into $N, leaving $M stunned!", ch, NULL, victim, TO_CHAR); act (AT_SKILL, "$n smashes into $N, leaving $M stunned!", ch, NULL, victim, TO_NOTVICT); if (! victim->IsParalysed ()) { af.type = gsn_stun; af.location = APPLY_AC; af.modifier = 20; af.duration = 3; af.bitvector = AFF_PARALYSIS; affect_to_char (victim, &af); update_pos (victim); } } else { WAIT_STATE (ch, 2 * PULSE_VIOLENCE); ch->AddMove (-5); learn_from_failure (ch, gsn_stun); act (AT_SKILL, "$N charges at you screaming, but you dodge out " "of the way.", victim, NULL, ch, TO_CHAR); act (AT_SKILL, "You try to stun $N, but $E dodges out of the way.", ch, NULL, victim, TO_CHAR); act (AT_SKILL, "$n charges screaming at $N, but keeps going right " "on past.", ch, NULL, victim, TO_NOTVICT); } } void do_bloodlet (CCharacter *ch, char *argument) { CObjData *obj; if (ch->IsNpc () || ! ch->IsVampire ()) return; if (ch->GetFightWho ()) { ch->SendText ("You're too busy fighting...\n\r"); return; } if (ch->GetPcData ()->condition [COND_BLOODTHIRST] < 10) { ch->SendText ("You are too drained to offer any blood...\n\r"); return; } WAIT_STATE (ch, PULSE_VIOLENCE); if (can_use_skill (ch, number_percent (), gsn_bloodlet)) { gain_condition (ch, COND_BLOODTHIRST, -7); act (AT_BLOOD, "Tracing a sharp nail over your skin, you let your " "blood spill.", ch, NULL, NULL, TO_CHAR); act (AT_BLOOD, "$n traces a sharp nail over $s skin, spilling a " "quantity of blood to the ground.", ch, NULL, NULL, TO_ROOM); learn_from_success (ch, gsn_bloodlet); obj = create_object (OIdxTable.GetObj (OBJ_VNUM_BLOODLET), 0); obj->timer = 1; obj->value [1] = 6; obj_to_room (obj, ch->GetInRoom ()); } else { act (AT_BLOOD, "You cannot manage to draw much blood...", ch, NULL, NULL, TO_CHAR); act (AT_BLOOD, "$n slices open $s skin, but no blood is spilled...", ch, NULL, NULL, TO_ROOM); learn_from_failure (ch, gsn_bloodlet); } } void do_feed (CCharacter *ch, char *argument) { CCharacter *victim; short dam; if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } if (!ch->IsNpc () && !ch->IsVampire ()) { ch->SendText ("It is not of your nature to feed on living creatures.\n\r"); return; } if (! can_use_skill (ch, 0, gsn_feed)) { ch->SendText ("You have not yet practiced your new teeth.\n\r"); return; } if ((victim = ch->GetFightWho ()) == NULL) { ch->SendText ("You aren't fighting anyone.\n\r"); return; } if (ch->mount) { ch->SendText ("You can't do that while mounted.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_feed)); if (can_use_skill (ch, number_percent (), gsn_feed)) { dam = number_range (1, ch->GetLevel ()); global_retcode = damage (ch, victim, dam, gsn_feed); if (global_retcode == rNONE && !ch->IsNpc () && dam && ch->GetFightData () && ch->GetPcData ()->condition[COND_BLOODTHIRST] < (10 + ch->GetLevel ())) { gain_condition (ch, COND_BLOODTHIRST, UMIN (number_range (1, (ch->GetLevel ()+victim->GetLevel () / 20) + 3), (10 + ch->GetLevel ()) - ch->GetPcData ()->condition[COND_BLOODTHIRST])); gain_condition (ch, COND_FULL, 2); gain_condition (ch, COND_THIRST, 2); act (AT_BLOOD, "You manage to suck a little life out of $N.", ch, NULL, victim, TO_CHAR); act (AT_BLOOD, "$n sucks some of your blood!", ch, NULL, victim, TO_VICT); learn_from_success (ch, gsn_feed); } } else { global_retcode = damage (ch, victim, 0, gsn_feed); if (global_retcode == rNONE && !ch->IsNpc () && ch->GetFightData () && ch->GetPcData ()->condition[COND_BLOODTHIRST] < (10 + ch->GetLevel ())) { act (AT_BLOOD, "The smell of $N's blood is driving you insane!", ch, NULL, victim, TO_CHAR); act (AT_BLOOD, "$n is lusting after your blood!", ch, NULL, victim, TO_VICT); learn_from_failure (ch, gsn_feed); } } return; } // Disarm a creature. // Caller must check for successful attack. // Check for loyalty flag (weapon disarms to inventory) for pkillers -Blodkai void disarm (CCharacter *ch, CCharacter *victim) { CObjData *obj, *tmpobj; if ((obj = get_eq_char (victim, WEAR_WIELD)) == NULL) return; if ((tmpobj = get_eq_char (victim, WEAR_DUAL_WIELD)) && number_bits (1) == 0) obj = tmpobj; if (get_eq_char (ch, WEAR_WIELD) == NULL && number_bits (1) == 0) { learn_from_failure (ch, gsn_disarm); return; } if (ch->IsNpc () && !can_see_obj (ch, *obj) && number_bits (1) == 0) { learn_from_failure (ch, gsn_disarm); return; } if (check_grip (ch, victim)) { learn_from_failure (ch, gsn_disarm); return; } act (AT_SKILL, "$n DISARMS you!", ch, NULL, victim, TO_VICT); act (AT_SKILL, "You disarm $N!", ch, NULL, victim, TO_CHAR); act (AT_SKILL, "$n disarms $N!", ch, NULL, victim, TO_NOTVICT); learn_from_success (ch, gsn_disarm); if (obj == get_eq_char (victim, WEAR_WIELD) && (tmpobj = get_eq_char (victim, WEAR_DUAL_WIELD)) != NULL) tmpobj->wear_loc = WEAR_WIELD; obj_from_char (obj); if (victim->IsNpc () || (obj->IsLoyal () && victim->IsPkiller ())) obj_to_char (obj, victim); else obj_to_room (obj, victim->GetInRoom ()); } void do_disarm (CCharacter *ch, char *argument) { CCharacter *victim; CObjData *obj; int percent; if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } if (! ch->IsNpc () && ch->GetLevel () < SkillTable.GetClassLevel (gsn_disarm, ch->GetClass ())) { ch->SendText ("You don't know how to disarm opponents.\n\r"); return; } if (get_eq_char (ch, WEAR_WIELD) == NULL) { ch->SendText ("You must wield a weapon to disarm.\n\r"); return; } if ((victim = ch->GetFightWho ()) == NULL) { ch->SendText ("You aren't fighting anyone.\n\r"); return; } if ((obj = get_eq_char (victim, WEAR_WIELD)) == NULL) { ch->SendText ("Your opponent is not wielding a weapon.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_disarm)); percent = number_percent () + victim->GetLevel () - ch->GetLevel () - (get_curr_lck (ch) - 15) + (get_curr_lck (victim) - 15); if (! can_see_obj (ch, *obj)) percent += 10; if (can_use_skill (ch, (percent*3/2), gsn_disarm)) disarm (ch, victim); else { ch->SendText ("You failed.\n\r"); learn_from_failure (ch, gsn_disarm); } } // Trip a creature. // Caller must check for successful attack. void trip (CCharacter *ch, CCharacter *victim) { if (victim->IsFlying () || victim->IsFloating ()) return; if (victim->mount) { if (victim->mount->IsFlying () || victim->mount->IsFloating ()) return; act (AT_SKILL, "$n trips your mount and you fall off!", ch, NULL, victim, TO_VICT ); act (AT_SKILL, "You trip $N's mount and $N falls off!", ch, NULL, victim, TO_CHAR ); act (AT_SKILL, "$n trips $N's mount and $N falls off!", ch, NULL, victim, TO_NOTVICT); victim->mount->ClrActBit (ACT_MOUNTED); victim->mount = NULL; WAIT_STATE (ch, 2 * PULSE_VIOLENCE); WAIT_STATE (victim, 2 * PULSE_VIOLENCE); victim->SetPosition (POS_RESTING); return; } if (victim->GetWait () == 0) { act (AT_SKILL, "$n trips you and you go down!", ch, NULL, victim, TO_VICT ); act (AT_SKILL, "You trip $N and $N goes down!", ch, NULL, victim, TO_CHAR ); act (AT_SKILL, "$n trips $N and $N goes down!", ch, NULL, victim, TO_NOTVICT); WAIT_STATE (ch, 2 * PULSE_VIOLENCE); WAIT_STATE (victim, 2 * PULSE_VIOLENCE); victim->SetPosition (POS_RESTING); } return; } // Converted to function well as a skill for vampires -- Blodkai void do_mistwalk (CCharacter *ch, char *argument) { char arg [MAX_INPUT_LENGTH]; CCharacter *victim; bool allowday; set_char_color (AT_DGREEN, ch); if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't do that right now.\n\r"); return; } if (ch->mount) { ch->SendText ("And scare your mount to death?\n\r"); return; } one_argument (argument, arg); if (arg [0] == '\0') { ch->SendText ("Who will be your victim?\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_mistwalk)); if ((victim = get_char_world (ch, arg)) == NULL || victim == ch) { ch->SendText ("You are unable to sense your victim.\n\r"); return; } allowday = (ch->IsPkiller () && ch->GetPcData ()->condition [COND_BLOODTHIRST] > 22); CRoomIndexData *pRoom = victim->GetInRoom (); if ((time_info.hour < 21 && time_info.hour > 5 && !allowday) || ! pRoom || pRoom->IsPrivate () || pRoom->IsSolitary () || pRoom->IsNoAstral () || pRoom->IsDeathRoom () || pRoom->IsPrototype () || pRoom->IsNoRecall () || victim->GetLevel () >= ch->GetLevel () + 15 || (victim->IsNpc () && victim->IsPrototype ()) || (victim->IsNpc () && saves_spell_staff (ch->GetLevel (), victim)) || (victim->CanPkill () && ! ch->IsNpc () && ! ch->CanPkill ()) || ! in_hard_range (ch, pRoom->GetArea ()) || (pRoom->GetArea ()->IsNoPkill () && ch->IsPkiller ())) { ch->SendText ("You are unable to sense your victim.\n\r"); learn_from_failure (ch, gsn_mistwalk); return; } // Subtract 22 extra bp for mist walk from 0500 to 2100 SB if (time_info.hour < 21 && time_info.hour > 5 && ! ch->IsNpc ()) gain_condition (ch, COND_BLOODTHIRST, - 22); act (AT_DGREEN, "Your surroundings blur as you assume a form of " "churning mist!", ch, NULL, NULL, TO_CHAR); act (AT_DGREEN, "$n dissolves into a cloud of glowing mist, then " "vanishes!", ch, NULL, NULL, TO_ROOM); learn_from_success (ch, gsn_mistwalk); ch->RemoveFromRoom (); ch->SendToRoom (pRoom); act (AT_DGREEN, "A cloud of glowing mist engulfs you, then withdraws " "to unveil $n!", ch, NULL, NULL, TO_ROOM); do_look (ch, "auto"); } void do_broach (CCharacter *ch, char *argument) { char arg [MAX_INPUT_LENGTH]; CExitData *pexit; set_char_color (AT_DGREEN, ch); if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } one_argument (argument, arg); if (arg [0] == '\0') { ch->SendText ("Attempt this in which direction?\n\r"); return; } if (ch->mount) { ch->SendText ("You should really dismount first.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_broach)); if (pexit = find_door (ch, arg, TRUE)) { CExitData *pexit_rev; if (! pexit->IsClosed () || ! pexit->IsLocked () || pexit->IsPickProof () || can_use_skill (ch, number_percent (), gsn_broach)) { ch->SendText ("Your attempt fails.\n\r"); learn_from_failure (ch, gsn_broach); check_room_for_traps (ch, TRAP_PICK | trap_door[pexit->vdir]); return; } pexit->ClrLocked (); ch->SendText ("You successfully broach the exit...\n\r"); learn_from_success (ch, gsn_broach); adjust_favor (ch, 9, 1); if ((pexit_rev = pexit->rexit) != NULL && pexit_rev->GetToRoom () == ch->GetInRoom ()) pexit_rev->ClrLocked (); check_room_for_traps (ch, TRAP_PICK | trap_door [pexit->vdir]); return; } ch->SendText ("Your attempt fails.\n\r"); } void do_pick (CCharacter *ch, char *argument) { char arg [MAX_INPUT_LENGTH]; CCharacter *gch; CObjData *obj; CExitData *pexit; if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } one_argument (argument, arg); if (arg [0] == '\0') { ch->SendText ("Pick what?\n\r"); return; } if (ms_find_obj (ch)) return; if (ch->mount) { ch->SendText ("You can't do that while mounted.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_pick_lock)); // look for guards gch = ch->GetInRoom ()->first_person; for ( ; gch; gch = gch->GetNextInRoom ()) { if (gch->IsNpc () && gch->IsAwake () && ch->GetLevel () + 5 < gch->GetLevel ()) { act (AT_PLAIN, "$N is standing too close to the lock.", ch, NULL, gch, TO_CHAR); return; } } if (! can_use_skill (ch, number_percent (), gsn_pick_lock)) { ch->SendText ("You failed.\n\r"); learn_from_failure (ch, gsn_pick_lock); return; } if ((pexit = find_door (ch, arg, TRUE)) != NULL) { // 'pick door' CExitData *pexit_rev; if (! pexit->IsClosed ()) { ch->SendText ("It's not closed.\n\r"); return; } if (pexit->key < 0) { ch->SendText ("It can't be picked.\n\r"); return; } if (! pexit->IsLocked ()) { ch->SendText ("It's already unlocked.\n\r"); return; } if (pexit->IsPickProof ()) { ch->SendText ("You failed.\n\r"); learn_from_failure (ch, gsn_pick_lock); check_room_for_traps (ch, TRAP_PICK | trap_door[pexit->vdir]); return; } pexit->ClrLocked (); ch->SendText ("*Click*\n\r"); act (AT_ACTION, "$n picks the $d.", ch, NULL, pexit->keyword, TO_ROOM); learn_from_success (ch, gsn_pick_lock); adjust_favor (ch, 9, 1); // pick the other side if ((pexit_rev = pexit->rexit) != NULL && pexit_rev->GetToRoom () == ch->GetInRoom ()) { pexit_rev->ClrLocked (); } check_room_for_traps (ch, TRAP_PICK | trap_door[pexit->vdir]); return; } if ((obj = get_obj_here (ch, arg)) != NULL) { // 'pick object' if (obj->item_type != ITEM_CONTAINER) { ch->SendText ("That's not a container.\n\r"); return; } if (! IS_SET (obj->value[1], CONT_CLOSED)) { ch->SendText ("It's not closed.\n\r"); return; } if (obj->value [2] < 0) { ch->SendText ("It can't be unlocked.\n\r"); return; } if (! IS_SET (obj->value [1], CONT_LOCKED)) { ch->SendText ("It's already unlocked.\n\r"); return; } if (IS_SET (obj->value [1], CONT_PICKPROOF)) { ch->SendText ("You failed.\n\r"); learn_from_failure (ch, gsn_pick_lock); check_for_trap (ch, obj, TRAP_PICK); return; } separate_obj (obj); REMOVE_BIT (obj->value [1], CONT_LOCKED); ch->SendText ("*Click*\n\r"); act (AT_ACTION, "$n picks $p.", ch, obj, NULL, TO_ROOM); learn_from_success (ch, gsn_pick_lock); adjust_favor (ch, 9, 1); check_for_trap (ch, obj, TRAP_PICK); return; } ch->SendTextf ("You see no %s here.\n\r", arg); } void do_sneak (CCharacter *ch, char *argument) { CAffectData af; if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } if (ch->mount) { ch->SendText ("You can't do that while mounted.\n\r"); return; } ch->SendText ("You attempt to move silently.\n\r"); affect_strip (ch, gsn_sneak); if (can_use_skill (ch, number_percent (), gsn_sneak)) { af.type = gsn_sneak; af.duration = (short) (ch->GetLevel () * DUR_CONV); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_SNEAK; affect_to_char (ch, &af); learn_from_success (ch, gsn_sneak); } else learn_from_failure (ch, gsn_sneak); return; } void do_hide (CCharacter *ch, char *argument) { if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } if (ch->mount) { ch->SendText ("You can't do that while mounted.\n\r"); return; } ch->SendText ("You attempt to hide.\n\r"); if (ch->IsHidden ()) ch->ClrHide (); if (can_use_skill (ch, number_percent (), gsn_hide)) { ch->SetHide (); learn_from_success (ch, gsn_hide); } else learn_from_failure (ch, gsn_hide); return; } // Contributed by Alander. void do_visible (CCharacter *ch, char *argument) { affect_strip (ch, gsn_invis); affect_strip (ch, gsn_mass_invis); affect_strip (ch, gsn_sneak); ch->ClrHide (); ch->ClrInvis (); if (! RaceTable.IsAffected (ch->GetRace (), AFF_SNEAK)) ch->ClrSneak (); ch->SendText ("Ok.\n\r"); } void do_recall (CCharacter *ch, char *argument) { CRoomIndexData *location; CCharacter *opponent; location = NULL; if (!ch->IsNpc () && ch->GetPcData ()->GetClan ()) location = RoomTable.GetRoom (ch->GetPcData ()->GetClan ()->recall); if (! location) // 1998-01-02, h location = RoomTable.GetRoom (RaceTable.GetRaceRecall (ch->GetRace ())); if (! location) location = RoomTable.GetRoom (SysData.m_RoomTemple); if (! location) { ch->SendText ("You are completely lost.\n\r"); return; } if (ch->GetInRoom () == location) return; if (ch->GetInRoom ()->IsNoRecall ()) { ch->SendText ("For some strange reason... nothing happens.\n\r"); return; } if (ch->IsCursed ()) { ch->SendText ("You are cursed and cannot recall!\n\r"); return; } if (opponent = ch->GetFightWho ()) { int lose; if (number_bits (1) == 0 || (!opponent->IsNpc () && number_bits (3) > 1)) { WAIT_STATE (ch, 4); lose = (int) ((exp_level (ch, ch->GetLevel ()+1) - exp_level (ch, ch->GetLevel ())) * 0.1); if (ch->GetDesc ()) lose /= 2; gain_exp (ch, 0 - lose); ch->SendTextf ("You failed! You lose %d exps.\n\r", lose); return; } lose = (int) ((exp_level (ch, ch->GetLevel ()+1) - exp_level (ch, ch->GetLevel ())) * 0.2); if (ch->GetDesc ()) lose /= 2; gain_exp (ch, 0 - lose); ch->SendTextf ("You recall from combat! You lose %d exps.\n\r",lose); stop_fighting (ch, TRUE); } act (AT_ACTION, "$n disappears in a swirl of smoke.", ch, NULL, NULL, TO_ROOM); ch->RemoveFromRoom (); ch->SendToRoom (location); if (ch->mount) { ch->mount->RemoveFromRoom (); ch->mount->SendToRoom (location); } act (AT_ACTION, "$n appears in the room.", ch, NULL, NULL, TO_ROOM); do_look (ch, "auto"); } void do_aid (CCharacter *ch, char *argument) { char arg[MAX_INPUT_LENGTH]; CCharacter *victim; int percent; if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } one_argument (argument, arg); if (arg[0] == '\0') { ch->SendText ("Aid whom?\n\r"); return; } if ((victim = get_char_room (ch, arg)) == NULL) { ch->SendText ("They aren't here.\n\r"); return; } if (ch->mount) { ch->SendText ("You can't do that while mounted.\n\r"); return; } if (victim == ch) { ch->SendText ("Aid yourself?\n\r"); return; } if (victim->GetPosition () > POS_STUNNED) { act (AT_PLAIN, "$N doesn't need your help.", ch, NULL, victim, TO_CHAR); return; } if (victim->GetHp () <= -6) { act (AT_PLAIN, "$N's condition is beyond your aiding ability.", ch, NULL, victim, TO_CHAR); return; } percent = number_percent () - (get_curr_lck (ch) - 13); WAIT_STATE (ch, SkillTable.GetBeats (gsn_aid)); if (! can_use_skill (ch, percent, gsn_aid)) { ch->SendText ("You fail.\n\r"); learn_from_failure (ch, gsn_aid); return; } act (AT_SKILL, "You aid $N!", ch, NULL, victim, TO_CHAR ); act (AT_SKILL, "$n aids $N!", ch, NULL, victim, TO_NOTVICT); learn_from_success (ch, gsn_aid); adjust_favor (ch, 8, 1); if (victim->GetHp () < 1) victim->SetHp (1); update_pos (victim); act (AT_SKILL, "$n aids you!", ch, NULL, victim, TO_VICT ); return; } void do_mount (CCharacter *ch, char *argument) { CCharacter *victim; if (!ch->IsNpc () && ch->GetLevel () < SkillTable.GetClassLevel (gsn_mount, ch->GetClass ())) { ch->SendText ( "I don't think that would be a good idea...\n\r"); return; } if (ch->mount) { ch->SendText ("You're already mounted!\n\r"); return; } if ((victim = get_char_room (ch, argument)) == NULL) { ch->SendText ("You can't find that here.\n\r"); return; } if (!victim->IsNpc () || ! victim->IsAction (ACT_MOUNTABLE)) { ch->SendText ("You can't mount that!\n\r"); return; } if (victim->IsAction (ACT_MOUNTED)) { ch->SendText ("That mount already has a rider.\n\r"); return; } if (victim->GetPosition () < POS_STANDING) { ch->SendText ("Your mount must be standing.\n\r"); return; } if (victim->GetPosition () == POS_FIGHTING || victim->GetFightData ()) { ch->SendText ("Your mount is moving around too much.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_mount)); if (can_use_skill (ch, number_percent (), gsn_mount)) { victim->SetActBit (ACT_MOUNTED); ch->mount = victim; act (AT_SKILL, "You mount $N.", ch, NULL, victim, TO_CHAR); act (AT_SKILL, "$n skillfully mounts $N.", ch, NULL, victim, TO_NOTVICT); act (AT_SKILL, "$n mounts you.", ch, NULL, victim, TO_VICT); learn_from_success (ch, gsn_mount); ch->SetPosition (POS_MOUNTED); } else { act (AT_SKILL, "You unsuccessfully try to mount $N.", ch, NULL, victim, TO_CHAR); act (AT_SKILL, "$n unsuccessfully attempts to mount $N.", ch, NULL, victim, TO_NOTVICT); act (AT_SKILL, "$n tries to mount you.", ch, NULL, victim, TO_VICT); learn_from_failure (ch, gsn_mount); } return; } void do_dismount (CCharacter *ch, char *argument) { CCharacter *victim; if ((victim = ch->mount) == NULL) { ch->SendText ("You're not mounted.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_mount)); if (can_use_skill (ch, number_percent (), gsn_mount)) { act (AT_SKILL, "You dismount $N.", ch, NULL, victim, TO_CHAR); act (AT_SKILL, "$n skillfully dismounts $N.", ch, NULL, victim, TO_NOTVICT); act (AT_SKILL, "$n dismounts you. Whew!", ch, NULL, victim, TO_VICT); victim->ClrActBit (ACT_MOUNTED); ch->mount = NULL; ch->SetPosition (POS_STANDING); learn_from_success (ch, gsn_mount); } else { act (AT_SKILL, "You fall off while dismounting $N. Ouch!", ch, NULL, victim, TO_CHAR); act (AT_SKILL, "$n falls off of $N while dismounting.", ch, NULL, victim, TO_NOTVICT); act (AT_SKILL, "$n falls off your back.", ch, NULL, victim, TO_VICT); learn_from_failure (ch, gsn_mount); victim->ClrActBit (ACT_MOUNTED); ch->mount = NULL; ch->SetPosition (POS_SITTING); global_retcode = damage (ch, ch, 1, TYPE_UNDEFINED); } return; } /**************************************************************************/ // Check for parry. BOOL check_parry (CCharacter *ch, CCharacter *victim) { int chances; if (! victim->IsAwake ()) return FALSE; if (victim->IsNpc () && ! victim->CanParry ()) return FALSE; if (victim->IsNpc ()) { // Tuan was here. :) chances = UMIN (60, 2 * victim->GetLevel ()); } else { if (get_eq_char (victim, WEAR_WIELD) == NULL) return FALSE; chances = (int) (victim->GetPcData ()->learned [gsn_parry] / 2); } // Put in the call to chance () to allow penalties for misaligned // clannies. if (! chance (victim, chances + victim->GetLevel () - ch->GetLevel ())) { learn_from_failure (victim, gsn_parry); return FALSE; } if (! victim->IsNpc () && ! victim->IsGagged ()) // SB act (AT_SKILL, "You parry $n's attack.", ch, NULL, victim, TO_VICT); if (! ch->IsNpc () && ! ch->IsGagged ()) // SB act (AT_SKILL, "$N parries your attack.", ch, NULL, victim, TO_CHAR); learn_from_success (victim, gsn_parry); return TRUE; } // Check for dodge. BOOL check_dodge (CCharacter *ch, CCharacter *victim) { int chances; if (! victim->IsAwake ()) return FALSE; if (victim->IsNpc () && ! victim->CanDodge ()) return FALSE; if (victim->IsNpc ()) chances = UMIN (60, 2 * victim->GetLevel ()); else chances = (int) (victim->GetPcData ()->learned [gsn_dodge] / 2); // Consider luck as a factor if (! chance (victim, chances + victim->GetLevel () - ch->GetLevel ())) { learn_from_failure (victim, gsn_dodge); return FALSE; } if (! victim->IsNpc () && ! victim->IsGagged ()) act (AT_SKILL, "You dodge $n's attack.", ch, NULL, victim, TO_VICT); if (! ch->IsNpc () && ! ch->IsGagged ()) act (AT_SKILL, "$N dodges your attack.", ch, NULL, victim, TO_CHAR); learn_from_success (victim, gsn_dodge); return TRUE; } void do_poison_weapon (CCharacter *ch, char *argument) { CObjData *obj; CObjData *pobj; CObjData *wobj; char arg [ MAX_INPUT_LENGTH ]; int percent; if (!ch->IsNpc () && ch->GetLevel () < SkillTable.GetClassLevel (gsn_poison_weapon, ch->GetClass ())) { ch->SendText ("What do you think you are, a thief?\n\r"); return; } one_argument (argument, arg); if (arg[0] == '\0') { ch->SendText ("What are you trying to poison?\n\r"); return; } if (ch->GetFightData ()) { ch->SendText ("While you're fighting? Nice try.\n\r"); return; } if (ms_find_obj (ch)) return; if (! (obj = get_obj_carry (ch, arg))) { ch->SendText ("You do not have that weapon.\n\r"); return; } if (obj->item_type != ITEM_WEAPON) { ch->SendText ("That item is not a weapon.\n\r"); return; } if (obj->IsPoisoned ()) { ch->SendText ("That weapon is already poisoned.\n\r"); return; } // Now we have a valid weapon...check to see if we have the powder. POSITION Cpos = ch->GetHeadCarryPos (); while (pobj = ch->GetNextCarrying (Cpos)) { if (pobj->pIndexData->vnum == OBJ_VNUM_BLACK_POWDER) break; } if (! pobj) { ch->SendText ("You do not have the black poison powder.\n\r"); return; } // Okay, we have the powder...do we have water? Cpos = ch->GetHeadCarryPos (); while (wobj = ch->GetNextCarrying (Cpos)) { if (wobj->item_type == ITEM_DRINK_CON && wobj->value [1] > 0 && wobj->value [2] == 0) break; } if (! wobj) { ch->SendText ("You have no water to mix with the powder.\n\r"); return; } /* Great, we have the ingredients...but is the thief smart enough? */ if (!ch->IsNpc () && ch->GetWisdom () < 16) { ch->SendText ("You can't quite remember what to do...\n\r"); return; } /* And does the thief have steady enough hands? */ if (!ch->IsNpc () && ((ch->GetDexterity () < 17) || ch->GetPcData ()->condition[COND_DRUNK] > 0)) { ch->SendText ("Your hands aren't steady enough to properly mix the poison.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_poison_weapon)); percent = (number_percent () - get_curr_lck (ch) - 14); /* Check the skill percentage */ separate_obj (pobj); separate_obj (wobj); if (! can_use_skill (ch, percent, gsn_poison_weapon)) { set_char_color (AT_RED, ch); ch->SendText ("You failed and spill some on yourself. Ouch!\n\r"); set_char_color (AT_GREY, ch); damage (ch, ch, ch->GetLevel (), gsn_poison_weapon); act (AT_RED, "$n spills the poison all over!", ch, NULL, NULL, TO_ROOM); extract_obj (pobj); extract_obj (wobj); learn_from_failure (ch, gsn_poison_weapon); return; } separate_obj (obj); /* Well, I'm tired of waiting. Are you? */ act (AT_RED, "You mix $p in $P, creating a deadly poison!", ch, pobj, wobj, TO_CHAR); act (AT_RED, "$n mixes $p in $P, creating a deadly poison!",ch, pobj, wobj, TO_ROOM); act (AT_GREEN, "You pour the poison over $p, which glistens wickedly!",ch, obj, NULL, TO_CHAR ); act (AT_GREEN, "$n pours the poison over $p, which glistens wickedly!",ch, obj, NULL, TO_ROOM ); obj->SetPoisoned (); obj->cost *= ch->GetLevel (); /* Set an object timer. Don't want proliferation of poisoned weapons */ obj->timer = 10 + ch->GetLevel (); if (obj->IsBlessed ()) obj->timer *= 2; if (obj->IsMagic ()) obj->timer *= 2; /* WHAT? All of that, just for that one bit? How lame. ;) */ act (AT_BLUE, "The remainder of the poison eats through $p.", ch, wobj, NULL, TO_CHAR); act (AT_BLUE, "The remainder of the poison eats through $p.", ch, wobj, NULL, TO_ROOM); extract_obj (pobj); extract_obj (wobj); learn_from_success (ch, gsn_poison_weapon); return; } void do_scribe (CCharacter *ch, char *argument) { CObjData *scroll; int sn; char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char buf3[MAX_STRING_LENGTH]; int mana; if (ch->IsNpc ()) return; if (!ch->IsNpc () && ch->GetLevel () < SkillTable.GetClassLevel (gsn_scribe, ch->GetClass ())) { ch->SendText ("A skill such as this requires more magical ability than that of your class.\n\r"); return; } if (argument[0] == '\0' || !str_cmp (argument, "")) { ch->SendText ("Scribe what?\n\r"); return; } if (ms_find_obj (ch)) return; if ((sn = find_spell (ch, argument, TRUE)) < 0) { ch->SendText ("You have not learned that spell.\n\r"); return; } if (SkillTable.GetSpellFunction (sn) == spell_null) { ch->SendText ("That's not a spell!\n\r"); return; } if (SkillTable.GetSkill (sn)->IsNoScribe ()) { ch->SendText ("You cannot scribe that spell.\n\r"); return; } mana = ch->IsNpc () ? 0 : UMAX (SkillTable.GetMinMana (sn), 100 / (2 + ch->GetLevel () - SkillTable.GetClassLevel (sn, ch->GetClass ()))); mana *=5; if (!ch->IsNpc () && ch->GetMana () < mana) { ch->SendText ("You don't have enough mana.\n\r"); return; } if ((scroll = get_eq_char (ch, WEAR_HOLD)) == NULL) { ch->SendText ("You must be holding a blank scroll to scribe it.\n\r"); return; } if (scroll->pIndexData->vnum != OBJ_VNUM_SCROLL_SCRIBING) { ch->SendText ("You must be holding a blank scroll to scribe it.\n\r"); return; } if ((scroll->value[1] != -1) && (scroll->pIndexData->vnum == OBJ_VNUM_SCROLL_SCRIBING)) { ch->SendText ("That scroll has already been inscribed.\n\r"); return; } if (!process_spell_components (ch, sn)) { learn_from_failure (ch, gsn_scribe); ch->AddMana (-mana / 2); return; } if (! can_use_skill (ch, number_percent (), gsn_scribe)) { set_char_color (AT_MAGIC, ch); ch->SendText ("You failed.\n\r"); learn_from_failure (ch, gsn_scribe); ch->AddMana (-mana / 2); return; } scroll->value[1] = sn; scroll->value[0] = ch->GetLevel (); sprintf (buf1, "%s scroll", SkillTable.GetName (sn)); scroll->SetShortDescr (aoran (buf1)); sprintf (buf2, "A glowing scroll inscribed '%s' lies in the dust.", SkillTable.GetName (sn)); scroll->SetDescription (buf2); sprintf (buf3, "scroll scribing %s", SkillTable.GetName (sn)); scroll->SetName (buf3); act (AT_MAGIC, "$n magically scribes $p.", ch,scroll, NULL, TO_ROOM); act (AT_MAGIC, "You magically scribe $p.", ch,scroll, NULL, TO_CHAR); learn_from_success (ch, gsn_scribe); ch->AddMana (-mana); } void do_brew (CCharacter *ch, char *argument) { CObjData *potion; CObjData *fire; int sn; char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char buf3[MAX_STRING_LENGTH]; int mana; BOOL found; if (ch->IsNpc ()) return; if (!ch->IsNpc () && ch->GetLevel () < SkillTable.GetClassLevel (gsn_brew, ch->GetClass ())) { ch->SendText ("A skill such as this requires more magical ability than that of your class.\n\r"); return; } if (argument[0] == '\0' || !str_cmp (argument, "")) { ch->SendText ("Brew what?\n\r"); return; } if (ms_find_obj (ch)) return; if ((sn = find_spell (ch, argument, TRUE)) < 0) { ch->SendText ("You have not learned that spell.\n\r"); return; } if (SkillTable.GetSpellFunction (sn) == spell_null) { ch->SendText ("That's not a spell!\n\r"); return; } if (SkillTable.GetSkill (sn)->IsNoBrew ()) { ch->SendText ("You cannot brew that spell.\n\r"); return; } mana = ch->IsNpc () ? 0 : UMAX (SkillTable.GetMinMana (sn), 100 / (2 + ch->GetLevel () - SkillTable.GetClassLevel (sn, ch->GetClass ()))); mana *=4; if (!ch->IsNpc () && ch->GetMana () < mana) { ch->SendText ("You don't have enough mana.\n\r"); return; } found = FALSE; POSITION pos = ch->GetInRoom ()->GetHeadContentPos (); while (fire = ch->GetInRoom ()->GetNextContent (pos)) { if (fire->item_type == ITEM_FIRE) { found = TRUE; break; } } if (! found) { ch->SendText ( "There must be a fire in the room to brew a potion.\n\r"); return; } if ((potion = get_eq_char (ch, WEAR_HOLD)) == NULL) { ch->SendText ( "You must be holding an empty flask to brew a potion.\n\r"); return; } if (potion->pIndexData->vnum != OBJ_VNUM_FLASK_BREWING) { ch->SendText ("You must be holding an empty flask to brew a potion.\n\r"); return; } if ((potion->value[1] != -1) && (potion->pIndexData->vnum == OBJ_VNUM_FLASK_BREWING)) { ch->SendText ("That's not an empty flask.\n\r"); return; } if (!process_spell_components (ch, sn)) { learn_from_failure (ch, gsn_brew); ch->AddMana (-mana / 2); return; } if (! can_use_skill (ch, number_percent (), gsn_brew)) { set_char_color (AT_MAGIC, ch); ch->SendText ("You failed.\n\r"); learn_from_failure (ch, gsn_brew); ch->AddMana (-mana / 2); return; } potion->value[1] = sn; potion->value[0] = ch->GetLevel (); sprintf (buf1, "%s potion", SkillTable.GetName (sn)); potion->SetShortDescr (aoran (buf1)); sprintf (buf2, "A strange potion labelled '%s' sizzles in a glass flask.", SkillTable.GetName (sn)); potion->SetDescription (buf2); sprintf (buf3, "flask potion %s", SkillTable.GetName (sn)); potion->SetName (buf3); act (AT_MAGIC, "$n brews up $p.", ch,potion, NULL, TO_ROOM); act (AT_MAGIC, "You brew up $p.", ch,potion, NULL, TO_CHAR); learn_from_success (ch, gsn_brew); ch->AddMana (-mana); } BOOL check_grip (CCharacter *ch, CCharacter *victim) { int chance; if (! victim->IsAwake ()) return FALSE; if (victim->IsNpc () && ! victim->CanGrip ()) return FALSE; if (victim->IsNpc ()) chance = UMIN (60, 2 * victim->GetLevel ()); else chance = victim->GetLearnedPercent (gsn_grip) / 2; // Consider luck as a factor chance += (2 * (get_curr_lck (victim) - 13)); if (number_percent () >= chance + victim->GetLevel () - ch->GetLevel ()) { learn_from_failure (victim, gsn_grip); return FALSE; } act (AT_SKILL, "You evade $n's attempt to disarm you.", ch, NULL, victim, TO_VICT ); act (AT_SKILL, "$N holds $S weapon strongly, and is not disarmed.", ch, NULL, victim, TO_CHAR); learn_from_success (victim, gsn_grip); return TRUE; } void do_circle (CCharacter *ch, char *argument) { char arg [MAX_INPUT_LENGTH]; CCharacter *victim; CObjData *obj; int percent; if (ch->IsNpc () && ch->IsCharmed ()) { ch->SendText ("You can't concentrate enough for that.\n\r"); return; } one_argument (argument, arg); if (ch->mount) { ch->SendText ("You can't circle while mounted.\n\r"); return; } if (arg [0] == '\0') { ch->SendText ("Circle around whom?\n\r"); return; } if ((victim = get_char_room (ch, arg)) == NULL) { ch->SendText ("They aren't here.\n\r"); return; } if (victim == ch) { ch->SendText ("How can you sneak up on yourself?\n\r"); return; } if (is_safe (ch, victim)) return; if ((obj = get_eq_char (ch, WEAR_WIELD)) == NULL || (obj->value [3] != 11 && obj->value [3] != 2)) { ch->SendText ("You need to wield a piercing or stabbing weapon.\n\r"); return; } if (! ch->GetFightData ()) { ch->SendText ("You can't circle when you aren't fighting.\n\r"); return; } if (! victim->GetFightData ()) { ch->SendText ("You can't circle around a person who is not fighting.\n\r"); return; } if (victim->num_fighting < 2) { act (AT_PLAIN, "You can't circle around them without a distraction.", ch, NULL, victim, TO_CHAR); return; } percent = number_percent () - (get_curr_lck (ch) - 16) + (get_curr_lck (victim) - 13); check_attacker (ch, victim); WAIT_STATE (ch, SkillTable.GetBeats (gsn_circle)); if (can_use_skill (ch, percent, gsn_circle)) { learn_from_success (ch, gsn_circle); WAIT_STATE (ch, 2 * PULSE_VIOLENCE); global_retcode = multi_hit (ch, victim, gsn_circle); adjust_favor (ch, 10, 1); check_illegal_pk (ch, victim); } else { learn_from_failure (ch, gsn_circle); WAIT_STATE (ch, 2 * PULSE_VIOLENCE); global_retcode = damage (ch, victim, 0, gsn_circle); } } // Berserk and HitAll. -- Altrag void do_berserk (CCharacter *ch, char *argument) { short percent; CAffectData af; if (!ch->GetFightData ()) { ch->SendText ("But you aren't fighting!\n\r"); return; } if (ch->IsBeserk ()) { ch->SendText ("Your rage is already at its peak!\n\r"); return; } percent = ch->IsNpc () ? 80 : ch->GetPcData ()->learned[gsn_berserk]; WAIT_STATE (ch, SkillTable.GetBeats (gsn_berserk)); if (!chance (ch, percent)) { ch->SendText ("You couldn't build up enough rage.\n\r"); learn_from_failure (ch, gsn_berserk); return; } af.type = gsn_berserk; /* Hmmm.. 10-20 combat rounds at level 50.. good enough for most mobs, and if not they can always go berserk again.. shrug.. maybe even too high. -- Altrag */ af.duration = number_range (ch->GetLevel ()/5, ch->GetLevel ()*2/5); /* Hmm.. you get stronger when yer really enraged.. mind over matter type thing.. */ af.location = APPLY_STR; af.modifier = 1; af.bitvector = AFF_BERSERK; affect_to_char (ch, &af); ch->SendText ("You start to lose control..\n\r"); learn_from_success (ch, gsn_berserk); return; } // External from fight.c ch_ret one_hit (CCharacter *ch, CCharacter *victim, int dt); void do_hitall (CCharacter *ch, char *argument) { CCharacter *vch; CCharacter *vch_next; short nvict = 0; short nhit = 0; short percent; if (ch->GetInRoom ()->IsSafe ()) { ch->SendText ("You cannot do that here.\n\r"); return; } if (!ch->GetInRoom ()->first_person) { ch->SendText ("There's no one here!\n\r"); return; } percent = ch->IsNpc () ? 80 : ch->GetPcData ()->learned[gsn_hitall]; for (vch = ch->GetInRoom ()->first_person; vch; vch = vch_next) { vch_next = vch->GetNextInRoom (); if (is_same_group (ch, vch) || !is_legal_kill (ch, vch) || !can_see (ch, vch) || is_safe (ch, vch)) continue; if (++nvict > ch->GetLevel () / 5) break; check_illegal_pk (ch, vch); if (chance (ch, percent)) { nhit++; global_retcode = one_hit (ch, vch, TYPE_UNDEFINED); } else global_retcode = damage (ch, vch, 0, TYPE_UNDEFINED); // Fireshield, etc. could kill ch too.. :>.. -- Altrag if (global_retcode == rCHAR_DIED || global_retcode == rBOTH_DIED || char_died (ch)) return; } if (!nvict) { ch->SendText ("There's no one here!\n\r"); return; } ch->SetMove (UMAX (0, ch->GetMove ()-nvict*3+nhit)); if (nhit) learn_from_success (ch, gsn_hitall); else learn_from_failure (ch, gsn_hitall); } BOOL check_illegal_psteal (CCharacter *ch, CCharacter *victim) { if (!victim->IsNpc () && ! ch->IsNpc ()) { if ((! victim->IsPkiller () || ch->GetLevel () - victim->GetLevel () > 10 || ! ch->IsPkiller ()) && (ch->GetInRoom ()->vnum < 29 || ch->GetInRoom ()->vnum > 43) && ch != victim) { //sprintf (log_buf, "%s illegally stealing from %s at %d", // (ch->IsNpc () ? ch->short_descr : ch->GetName ()), // victim->GetName (), victim->GetInRoom ()->vnum); //gpDoc->LogString (log_buf); //to_channel (log_buf, CHANNEL_MONITOR, "Monitor", LEVEL_IMMORTAL); return TRUE; } } return FALSE; } void do_scan (CCharacter *ch, char *argument) { CRoomIndexData *was_in_room; CExitData *pExit; short dir = -1; short dist; short max_dist = 5; if (argument [0] == '\0') { ch->SendText ("Scan in a direction...\n\r"); return; } if ((dir = get_door (argument)) == -1) { ch->SendText ("Scan in WHAT direction?\n\r"); return; } was_in_room = ch->GetInRoom (); act (AT_GREY, "Scanning $t...", ch, dir_name [dir], NULL, TO_CHAR); act (AT_GREY, "$n scans $t.", ch, dir_name [dir], NULL, TO_ROOM); if (! can_use_skill (ch, number_percent (), gsn_scan)) { act (AT_GREY, "You stop scanning $t as your vision blurs.", ch, dir_name [dir], NULL, TO_CHAR); learn_from_failure (ch, gsn_scan); return; } if (ch->IsVampire ()) { if (time_info.hour < 21 && time_info.hour > 5) { ch->SendText ("You have trouble seeing clearly through all the " "light.\n\r"); max_dist = 1; } } if ((pExit = get_exit (ch->GetInRoom (), dir)) == NULL) { act (AT_GREY, "You can't see $t.", ch, dir_name[dir], NULL, TO_CHAR); return; } if (ch->GetLevel () < 50) --max_dist; if (ch->GetLevel () < 40) --max_dist; for (dist = 1; dist <= max_dist; ) { if (pExit->IsClosed ()) { if (pExit->IsSecret ()) act (AT_GREY, "Your view $t is blocked by a wall.", ch, dir_name [dir], NULL, TO_CHAR); else act (AT_GREY, "Your view $t is blocked by a door.", ch, dir_name [dir], NULL, TO_CHAR); break; } if (room_is_private (pExit->GetToRoom ()) && ch->GetLevel () < LEVEL_GREATER) { act (AT_GREY, "Your view $t is blocked by a private room.", ch, dir_name [dir], NULL, TO_CHAR); break; } ch->RemoveFromRoom (); ch->SendToRoom (pExit->GetToRoom ()); set_char_color (AT_RMNAME, ch); ch->SendText (ch->GetInRoom ()->GetName ()); ch->SendText ("\n\r"); ShowListToChar (ch->GetInRoom ()->GetContentList (), ch, FALSE, FALSE); show_char_to_char (ch->GetInRoom ()->first_person, ch); switch (ch->GetInRoom ()->sector_type) { default: dist++; break; case SECT_AIR: if (number_percent () < 80) dist++; break; case SECT_INSIDE: case SECT_FIELD: case SECT_UNDERGROUND: dist++; break; case SECT_FOREST: case SECT_CITY: case SECT_DESERT: case SECT_HILLS: dist += 2; break; case SECT_WATER_SWIM: case SECT_WATER_NOSWIM: dist += 3; break; case SECT_MOUNTAIN: case SECT_UNDERWATER: case SECT_OCEANFLOOR: dist += 4; break; } if (dist >= max_dist) { act (AT_GREY, "Your vision blurs with distance and you see no " "farther $t.", ch, dir_name [dir], NULL, TO_CHAR); break; } if ((pExit = get_exit (ch->GetInRoom (), dir)) == NULL) { act (AT_GREY, "Your view $t is blocked by a wall.", ch, dir_name [dir], NULL, TO_CHAR); break; } } ch->RemoveFromRoom (); ch->SendToRoom (was_in_room); learn_from_success (ch, gsn_scan); } // Basically the same guts as do_scan() from above (please keep them in // sync) used to find the victim we're firing at. -Thoric CCharacter *scan_for_victim (CCharacter *ch, CExitData *pexit, char *name) { CCharacter *victim; short dist, dir; short max_dist = 8; if (ch->IsBlind () || ! pexit) return NULL; CRoomIndexData *pWasInRoom = ch->GetInRoom (); if (ch->IsVampire () && time_info.hour < 21 && time_info.hour > 5) max_dist = 1; if (ch->GetLevel () < 50) --max_dist; if (ch->GetLevel () < 40) --max_dist; if (ch->GetLevel () < 30) --max_dist; for (dist = 1; dist <= max_dist; ) { if (pexit->IsClosed ()) break; if (room_is_private (pexit->GetToRoom ()) && ch->GetLevel () < LEVEL_GREATER) break; ch->RemoveFromRoom (); ch->SendToRoom (pexit->GetToRoom ()); if ((victim = get_char_room (ch, name)) != NULL) { ch->RemoveFromRoom (); ch->SendToRoom (pWasInRoom); return victim; } switch (ch->GetInRoom ()->sector_type) { default: ++dist; break; case SECT_AIR: if (number_percent () < 80) ++dist; break; case SECT_INSIDE: case SECT_FIELD: case SECT_UNDERGROUND: ++dist; break; case SECT_FOREST: case SECT_CITY: case SECT_DESERT: case SECT_HILLS: dist += 2; break; case SECT_WATER_SWIM: case SECT_WATER_NOSWIM: dist += 3; break; case SECT_MOUNTAIN: case SECT_UNDERWATER: case SECT_OCEANFLOOR: dist += 4; break; } if (dist >= max_dist) break; dir = pexit->vdir; if ((pexit = get_exit (ch->GetInRoom (), dir)) == NULL) break; } ch->RemoveFromRoom (); ch->SendToRoom (pWasInRoom); return NULL; } // Perform the actual attack on a victim -Thoric ch_ret ranged_got_target (CCharacter *ch, CCharacter *victim, CObjData *weapon, CObjData *projectile, short dist, short dt, char *stxt, short color) { if (ch->GetInRoom ()->IsSafe ()) { // safe room, bubye projectile if (projectile) { ch->SendTextf ("Your %s is blasted from existance by a godly " "presense.", myobj (projectile)); act (color, "A godly presence smites $p!", ch, projectile, NULL, TO_ROOM); extract_obj (projectile); } else { ch->SendTextf ("Your %s is blasted from existance by a godly " "presense.", stxt); act (color, "A godly presence smites $t!", ch, aoran (stxt), NULL, TO_ROOM); } return rNONE; } if (victim->IsNpc () && victim->IsAction (ACT_SENTINEL) && ch->GetInRoom () != victim->GetInRoom ()) { // letsee, if they're high enough.. attack back with fireballs // long distance or maybe some minions... go herne! heh.. // // For now, just always miss if not in same room -Thoric if (projectile) { learn_from_failure (ch, gsn_missile_weapons); // 50% chance of projectile getting lost if (number_percent () < 50) extract_obj (projectile); else { if (projectile->in_obj) obj_from_obj (projectile); if (projectile->carried_by) obj_from_char (projectile); obj_to_room (projectile, victim->GetInRoom ()); } } return damage (ch, victim, 0, dt); } if (number_percent () > 50 || (projectile && weapon && can_use_skill (ch, number_percent (), gsn_missile_weapons))) { if (projectile) global_retcode = projectile_hit (ch, victim, weapon, projectile, dist); else global_retcode = spell_attack (dt, ch->GetLevel (), ch, victim); } else { learn_from_failure (ch, gsn_missile_weapons); global_retcode = damage (ch, victim, 0, dt); if (projectile) { // 50% chance of getting lost if (number_percent() < 50) extract_obj (projectile); else { if (projectile->in_obj) obj_from_obj (projectile); if (projectile->carried_by) obj_from_char (projectile); obj_to_room (projectile, victim->GetInRoom ()); } } } return global_retcode; } // Generic use ranged attack function -Thoric & Tricops ch_ret ranged_attack (CCharacter *ch, char *argument, CObjData *weapon, CObjData *projectile, short dt, short range) { CCharacter *victim, *vch; CExitData *pexit; char arg [MAX_INPUT_LENGTH]; char arg1 [MAX_INPUT_LENGTH]; char temp [MAX_INPUT_LENGTH]; char buf [MAX_STRING_LENGTH]; short dir = -1, dist = 0, color = AT_GREY; char *dtxt = "somewhere"; char *stxt = "burst of energy"; int count; if (argument && argument [0] != '\0' && argument [0] == '\'') { one_argument (argument, temp); argument = temp; } argument = one_argument (argument, arg); argument = one_argument (argument, arg1); if (arg [0] == '\0') { ch->SendText ("Where? At who?\n\r"); return rNONE; } victim = NULL; // get an exit or a victim if ((pexit = find_door (ch, arg, TRUE)) == NULL) { if ((victim = get_char_room (ch, arg)) == NULL) { ch->SendText ("Aim in what direction?\n\r"); return rNONE; } else { if (ch->GetFightWho () == victim) { ch->SendText ("They are too close to release that type of " "attack!\n\r"); return rNONE; } if (! ch->IsNpc () && ! victim->IsNpc ()) { ch->SendText ("Pkill like a real pkiller.\n\r"); return rNONE; } } } else dir = pexit->vdir; // check for ranged attacks from private rooms, etc CRoomIndexData &ChRoom = *ch->GetInRoom (); if (! victim) { if (ChRoom.IsPrivate () || ChRoom.IsSolitary ()) { ch->SendText ("You cannot perform a ranged attack from a " "private room.\n\r"); return rNONE; } if (ChRoom.tunnel > 0) { count = 0; for (vch = ChRoom.first_person; vch; vch = vch->GetNextInRoom ()) ++count; if (count >= ChRoom.tunnel) { ch->SendText ("This room is too cramped to perform such " "an attack.\n\r"); return rNONE; } } } CSkill *pSkill = SkillTable.GetSkill (dt); if (pexit && ! pexit->GetToRoom ()) { ch->SendText ("Are you expecting to fire through a wall!?\n\r"); return rNONE; } // Check for obstruction if (pexit && pexit->IsClosed ()) { if (pexit->IsSecret () || pexit->IsDig ()) ch->SendText ("Are you expecting to fire through a wall!?\n\r"); else ch->SendText ("Are you expecting to fire through a door!?\n\r"); return rNONE; } vch = NULL; if (pexit && arg1 [0] != '\0') { if ((vch = scan_for_victim (ch, pexit, arg1)) == NULL) { ch->SendText ("You cannot see your target.\n\r"); return rNONE; } // don't allow attacks on mobs stuck in another area? // if (vch->IsNpc () && vch->IsAction (ACT_STAY_AREA) // && ch->GetInRoom ()->area != vch->GetInRoom ()->area) {} // don't allow attacks on mobs that are in a no-missile room if (vch->GetInRoom ()->IsNoMissile ()) { ch->SendText ("You can't get a clean shot off.\n\r"); return rNONE; } if (! ch->IsNpc () && ! vch->IsNpc ()) { ch->SendText ("Pkill like a real pkiller.\n\r"); return rNONE; } // can't properly target someone heavily in battle if (vch->num_fighting > max_fight (vch)) { ch->SendText ("There is too much activity there for you to " "get a clear shot.\n\r"); return rNONE; } } if (vch) { if (! vch->IsNpc () && ! ch->IsNpc () && ch->IsNice ()) { ch->SendText ("Your too nice to do that!\n\r"); return rNONE; } if (vch && is_safe (ch, vch)) return rNONE; } CRoomIndexData *pWasInRoom = ch->GetInRoom (); if (projectile) { separate_obj (projectile); if (pexit) { if (weapon) { act (AT_GREY, "You fire $p $T.", ch, projectile, dir_name [dir], TO_CHAR); act (AT_GREY, "$n fires $p $T.", ch, projectile, dir_name [dir], TO_ROOM); } else { act (AT_GREY, "You throw $p $T.", ch, projectile, dir_name [dir], TO_CHAR); act (AT_GREY, "$n throw $p $T.", ch, projectile, dir_name [dir], TO_ROOM); } } else { if (weapon) { act (AT_GREY, "You fire $p at $N.", ch, projectile, victim, TO_CHAR); act (AT_GREY, "$n fires $p at $N.", ch, projectile, victim, TO_NOTVICT); act (AT_GREY, "$n fires $p at you!", ch, projectile, victim, TO_VICT); } else { act (AT_GREY, "You throw $p at $N.", ch, projectile, victim, TO_CHAR); act (AT_GREY, "$n throws $p at $N.", ch, projectile, victim, TO_NOTVICT); act (AT_GREY, "$n throws $p at you!", ch, projectile, victim, TO_VICT); } } } else if (pSkill) { if (pSkill->ValidDamageMsg ()) stxt = pSkill->GetDamageMsg (); else stxt = pSkill->GetName (); // a plain "spell" flying around seems boring if (! str_cmp (stxt, "spell")) stxt = "magical burst of energy"; if (pSkill->GetType () == SKILL_SPELL) { color = AT_MAGIC; if (pexit) { act (AT_MAGIC, "You release $t $T.", ch, aoran (stxt), dir_name [dir], TO_CHAR); act (AT_MAGIC, "$n releases $s $t $T.", ch, stxt, dir_name [dir], TO_ROOM); } else { act (AT_MAGIC, "You release $t at $N.", ch, aoran (stxt), victim, TO_CHAR); act (AT_MAGIC, "$n releases $s $t at $N.", ch, stxt, victim, TO_NOTVICT); act (AT_MAGIC, "$n releases $s $t at you!", ch, stxt, victim, TO_VICT); } } } else { bug ("Ranged_attack: no projectile, no skill dt %d", dt); return rNONE; } // victim in same room if (victim) { check_illegal_pk (ch, victim); check_attacker (ch, victim); return ranged_got_target (ch, victim, weapon, projectile, 0, dt, stxt, color); } // assign scanned victim victim = vch; // reverse direction text from move_char dtxt = ReverseExit (pexit->vdir); while (dist <= range) { ch->RemoveFromRoom (); ch->SendToRoom (pexit->GetToRoom ()); if (pexit->IsClosed ()) { // whadoyahknow, the door's closed if (projectile) sprintf (buf, "You see your %s pierce a door in the distance to the %s.", myobj (projectile), dir_name [dir]); else sprintf (buf, "You see your %s hit a door in the distance to the %s.", stxt, dir_name [dir]); act (color, buf, ch, NULL, NULL, TO_CHAR); if (projectile) { sprintf (buf, "$p flies in from %s and implants itself " "solidly in the %sern door.", dtxt, dir_name [dir]); act (color, buf, ch, projectile, NULL, TO_ROOM); } else { sprintf (buf, "%s flies in from %s and implants itself " "solidly in the %sern door.", aoran (stxt), dtxt, dir_name [dir]); buf [0] = UPPER (buf [0]); act (color, buf, ch, NULL, NULL, TO_ROOM); } break; } // no victim? pick a random one if (! victim) { vch = ch->GetInRoom ()->first_person; for ( ; vch; vch = vch->GetNextInRoom ()) { if (((ch->IsNpc () && ! vch->IsNpc ()) || (! ch->IsNpc () && vch->IsNpc ())) && number_bits (1) == 0) { victim = vch; break; } } if (victim && is_safe (ch, victim)) { ch->RemoveFromRoom (); ch->SendToRoom (pWasInRoom); return rNONE; } } // In the same room as our victim? if (victim && ch->GetInRoom () == victim->GetInRoom ()) { if (projectile) act (color, "$p flies in from $T.", ch, projectile, dtxt, TO_ROOM); else act (color, "$t flies in from $T.", ch, aoran (stxt), dtxt, TO_ROOM); // get back before the action starts ch->RemoveFromRoom (); ch->SendToRoom (pWasInRoom); check_illegal_pk (ch, victim); check_attacker (ch, victim); return ranged_got_target (ch, victim, weapon, projectile, dist, dt, stxt, color); } if (dist == range) { if (projectile) { act (color, "Your $t falls harmlessly to the ground to the $T.", ch, myobj (projectile), dir_name [dir], TO_CHAR); act (color, "$p flies in from $T and falls harmlessly to " "the ground here.", ch, projectile, dtxt, TO_ROOM); if (projectile->in_obj) obj_from_obj (projectile); if (projectile->carried_by) obj_from_char (projectile); obj_to_room (projectile, ch->GetInRoom ()); } else { act (color, "Your $t fizzles out harmlessly to the $T.", ch, stxt, dir_name [dir], TO_CHAR); act (color, "$t flies in from $T and fizzles out harmlessly.", ch, aoran (stxt), dtxt, TO_ROOM); } break; } if ((pexit = get_exit (ch->GetInRoom (), dir)) == NULL) { if (projectile) { act (color, "Your $t hits a wall and bounces harmlessly " "to the ground to the $T.", ch, myobj (projectile), dir_name [dir], TO_CHAR); act (color, "$p strikes the $Tsern wall and falls harmlessly" " to the ground.", ch, projectile, dir_name [dir], TO_ROOM); if (projectile->in_obj) obj_from_obj (projectile); if (projectile->carried_by) obj_from_char (projectile); obj_to_room (projectile, ch->GetInRoom ()); } else { act (color, "Your $t harmlessly hits a wall to the $T.", ch, stxt, dir_name [dir], TO_CHAR); act (color, "$t strikes the $Tsern wall and falls harmlessly" " to the ground.", ch, aoran (stxt), dir_name [dir], TO_ROOM); } break; } if (projectile) act (color, "$p flies in from $T.", ch, projectile, dtxt, TO_ROOM); else act (color, "$t flies in from $T.", ch, aoran (stxt), dtxt, TO_ROOM); ++dist; } ch->RemoveFromRoom (); ch->SendToRoom (pWasInRoom); return rNONE; } // Fire <direction> <target> // // Fire a projectile from a missile weapon (bow, crossbow, etc) // // Design by Thoric, coding by Thoric and Tricops. // // Support code (see projectile_hit(), quiver support, other changes to // fight.c, etc by Thoric. void do_fire (CCharacter* ch, char* argument) { CObjData *arrow; CObjData *bow; short max_dist; if (argument [0] == '\0' || !str_cmp (argument, " ")) { ch->SendText ("Fire where at who?\n\r"); return; } if (ch->GetInRoom ()->IsSafe ()) { set_char_color (AT_MAGIC, ch); ch->SendText ("A magical force prevents you from attacking.\n\r"); return; } // Find the projectile weapon if (bow = get_eq_char (ch, WEAR_MISSILE_WIELD)) if (bow->item_type != ITEM_MISSILE_WEAPON) bow = NULL; if (! bow) { ch->SendText ("You are not wielding a missile weapon.\n\r"); return; } // modify maximum distance based on bow-type and ch's class/str/etc max_dist = URANGE (1, bow->value [4], 10); if ((arrow = find_projectile (ch, bow->value [3])) == NULL) { char *msg = "You have nothing to fire...\n\r"; switch (bow->value [3]) { case DAM_BOLT: msg = "You have no bolts...\n\r"; break; case DAM_ARROW: msg = "You have no arrows...\n\r"; break; case DAM_DART: msg = "You have no darts...\n\r"; break; case DAM_STONE: msg = "You have no slingstones...\n\r"; break; case DAM_PEA: msg = "You have no peas...\n\r"; break; } ch->SendText (msg); return; } // handle the ranged attack ranged_attack (ch, argument, bow, arrow, TYPE_HIT + arrow->value [3], max_dist); } // Attempt to fire at a victim. // Returns FALSE if no attempt was made BOOL mob_fire (CCharacter* ch, char* name) { CObjData *arrow; CObjData *bow; short max_dist; if (ch->GetInRoom ()->IsSafe ()) return FALSE; if (bow = get_eq_char (ch, WEAR_MISSILE_WIELD)) if (bow->item_type != ITEM_MISSILE_WEAPON) bow = NULL; if (! bow) return FALSE; // modify maximum distance based on bow-type and ch's class/str/etc max_dist = URANGE (1, bow->value [4], 10); if ((arrow = find_projectile (ch, bow->value [3])) == NULL) return FALSE; ranged_attack (ch, name, bow, arrow, TYPE_HIT + arrow->value [3], max_dist); return TRUE; } /* * * void do_release (CCharacter *ch, char *argument) { CCharacter *victim; OBJ_INDEX_DATA *arrow; CObjData *quiver; CObjData *bow; CExitData *pexit; CRoomIndexData *was_in_room; char arg[MAX_INPUT_LENGTH]; char arg1[MAX_INPUT_LENGTH]; short dir; short dist; short max_dist = 3; for (bow = ch->last_carrying; bow; bow = bow->prev_content) { if (can_see_obj (ch, bow) && (bow->wear_loc == WEAR_WIELDED || bow->wear_loc == WEAR_DUAL_WIELDED) && ((bow->item_type == ITEM_SHORT_BOW) || (bow->item_type == ITEM_LONG_BOW) || (bow->item_type == ITEM_CROSS_BOW))) break; } if (!bow) { ch->SendText ("You are not wielding a bow.\n\r"); return; } switch (bow->item_type) { case ITEM_SHORT_BOW: max_dist = 4; break; case ITEM_LONG_BOW: max_dist = 5; break; case ITEM_CROSS_BOW: max_dist = 6; break; } for (quiver = ch->last_carrying; quiver; quiver = quiver->GetPrev ()) { if (can_see_obj (ch, quiver) && (quiver->item_type == ITEM_QUIVER)) break; } for (arrow = ch->last_carrying; arrow; arrow = arrow->GetPrev ()) { if (can_see_obj (ch, arrow) && (arrow->item_type == ITEM_PROJECTILE)) break; } if ((dir = get_door (arg)) == -1) { ch->SendText ("Aim in what direction?\n\r"); return; } if ((pexit = get_exit (ch->GetInRoom (), dir)) == NULL) { ch->SendText ("Are you expecting to fire through a wall!?\n\r"); return; } if (IS_SET (pexit->exit_info, EX_CLOSED)) { ch->SendText ("Are you expecting to fire through a door!?\n\r"); return; } was_in_room = ch->GetInRoom (); act (AT_GREY, "You release an arrow $t.", ch, dir_name[dir], NULL, TO_CHAR); act (AT_GREY, "$n releases an arrow $t.", ch, dir_name[dir], NULL, TO_ROOM); for (dist = 0; dist <= max_dist;) { if (IS_SET (pexit->exit_info, EX_CLOSED)) { act (AT_GREY, "You see your arrow pierce a door in the distance.", ch, NULL, NULL, TO_CHAR); break; } ch->RemoveFromRoom (); ch->SendToRoom (pexit->to_room); if ((victim = get_char_room (ch, arg1)) != NULL) { } if (dist == max_dist) break; if ((pexit = get_exit (ch->GetInRoom (), dir)) == NULL) { } } ch->RemoveFromRoom (); ch->SendToRoom (was_in_room); return; } */ /* -- working on -- * Syntaxes: throw object (assumed already fighting) * throw object direction target (all needed args for distance * throwing) * throw object (assumed same room throw) void do_throw (CCharacter *ch, char *argument) { CRoomIndexData *was_in_room; CCharacter *victim; CObjData *throw_obj; CExitData *pexit; short dir; short dist; short max_dist = 3; char arg[MAX_INPUT_LENGTH]; char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; argument = one_argument (argument, arg); argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); for (throw_obj = ch->last_carrying; throw_obj; throw_obj = throw_obj=>prev_content) { if (can_see_obj (ch, throw_obj) && (throw_obj->wear_loc == WEAR_HELD || throw_obj->wear_loc == WEAR_WIELDED || throw_obj->wear_loc == WEAR_DUAL_WIELDED) && nifty_is_name (arg, throw_obj->name)) break; } if (!throw_obj) { ch->SendText ("You aren't holding or wielding anything like that.\n\r", ch); return; } if ((throw_obj->item_type != ITEM_WEAPON) { ch->SendText ("You can only throw weapons.\n\r"); return; } if (get_obj_weight (throw_obj) - (3 * (ch->GetCurrentStrength () - 15)) > 0) { ch->SendText ("That is too heavy for you to throw.\n\r"); learn_from_failure (ch, gsn_throw); return; } if (ch->GetFightData ()) victim = ch->GetFightData (); else { if (( (victim = get_char_room (ch, arg1)) == NULL) && (arg2[0] == '\0')) { act (AT_GREY, "Throw $t at whom?", ch, obj->short_descr, NULL, TO_CHAR); return; } } }*/ // Search inventory for an appropriate projectile to fire. // Also search open quivers. -Thoric CObjData *find_projectile (CCharacter* ch, int type) { CObjData *obj, *obj2; POSITION pos = ch->GetHeadCarryPos (); while (obj = ch->GetNextCarrying (pos)) { if (can_see_obj (ch, *obj)) { if (obj->item_type == ITEM_QUIVER && !IS_SET (obj->value [1], CONT_CLOSED)) { POSITION pos = obj->GetTailContentPos (); while (obj2 = obj->GetPreviousContent (pos)) { if (obj2->item_type == ITEM_PROJECTILE && obj2->value [3] == type) return obj2; } } if (obj->item_type == ITEM_PROJECTILE && obj->value [3] == type) return obj; } } return NULL; } void do_slice (CCharacter *ch, char *argument) { CObjData *corpse; CObjData *obj; CObjData *slice; BOOL found; CMobIndexData *pMobIndex; char buf[MAX_STRING_LENGTH]; char buf1[MAX_STRING_LENGTH]; found = FALSE; if (!ch->IsNpc () && ch->IsMortal () && ch->GetLevel () < SkillTable.GetClassLevel (gsn_slice, ch->GetClass ())) { ch->SendText ("You are not learned in this skill.\n\r"); return; } if (argument[0] == '\0') { ch->SendText ("From what do you wish to slice meat?\n\r"); return; } if ((obj = get_eq_char (ch, WEAR_WIELD)) == NULL || (obj->value[3] != 1 && obj->value[3] != 2 && obj->value[3] != 3 && obj->value[3] != 11)) { ch->SendText ("You need to wield a sharp weapon.\n\r"); return; } if ((corpse = get_obj_here (ch, argument)) == NULL) { ch->SendText ("You can't find that here.\n\r"); return; } if (corpse->item_type != ITEM_CORPSE_NPC || corpse->value[3] < 75) { ch->SendText ("That is not a suitable source of meat.\n\r"); return; } if ((pMobIndex = MobTable.GetMob ((short) - (corpse->value[2]))) == NULL) { bug ("Can not find mob for value[2] of corpse, do_slice", 0); return; } if (OIdxTable.GetObj (OBJ_VNUM_SLICE) == NULL) { bug ("Vnum 24 not found for do_slice!", 0); return; } if (! can_use_skill (ch, number_percent (), gsn_slice) && ch->IsMortal ()) { ch->SendText ("You fail to slice the meat properly.\n\r"); learn_from_failure (ch, gsn_slice); /* Just in case they die :> */ if (number_percent () + (ch->GetDexterity () - 13) < 10) { act (AT_BLOOD, "You cut yourself!", ch, NULL, NULL, TO_CHAR); damage (ch, ch, ch->GetLevel (), gsn_slice); } return; } slice = create_object (OIdxTable.GetObj (OBJ_VNUM_SLICE), 0); sprintf (buf, "meat fresh slice %s", pMobIndex->GetPlayerName ()); slice->SetName (buf); sprintf (buf, "a slice of raw meat from %s", pMobIndex->GetShortDescr ()); slice->SetShortDescr (buf); sprintf (buf1, "A slice of raw meat from %s lies on the ground.", pMobIndex->GetShortDescr ()); slice->SetDescription (buf1); act (AT_BLOOD, "$n cuts a slice of meat from $p.", ch, corpse, NULL, TO_ROOM); act (AT_BLOOD, "You cut a slice of meat from $p.", ch, corpse, NULL, TO_CHAR); obj_to_char (slice, ch); corpse->value[3] -= 25; learn_from_success (ch, gsn_slice); return; } // Fighting Styles - haus void do_style (CCharacter* ch, char* argument) { char arg [MAX_INPUT_LENGTH]; if (ch->IsNpc ()) return; int style = ch->GetStyle (); one_argument (argument, arg); if (arg [0] == '\0') { ch->SendColorf ("&wAdopt which fighting style? (current: %s&w)\n\r", style == STYLE_BERSERK ? "&Rberserk" : style == STYLE_AGGRESSIVE ? "&Raggressive" : style == STYLE_DEFENSIVE ? "&Ydefensive" : style == STYLE_EVASIVE ? "&Yevasive" : "standard"); return; } if (! str_prefix (arg, "evasive")) { if (ch->GetLevel () < SkillTable.GetClassLevel (gsn_style_evasive, ch->GetClass ())) { ch->SendText ("You have not yet learned enough to fight evasively.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_style_evasive)); if (number_percent () < ch->GetLearnedPercent (gsn_style_evasive)) { // success if (ch->GetFightData ()) { ch->SetPosition (POS_EVASIVE); learn_from_success (ch, gsn_style_evasive); if (ch->IsPkiller ()) act (AT_ACTION, "$n falls back into an evasive stance.", ch, NULL, NULL, TO_ROOM); } ch->SetStyle (STYLE_EVASIVE); ch->SendText ("You adopt an evasive fighting style.\n\r"); return; } else { // failure ch->SendText ("You nearly trip in a lame attempt to adopt " "an evasive fighting style.\n\r"); return; } } else if (! str_prefix (arg, "defensive")) { if (ch->GetLevel () < SkillTable.GetClassLevel (gsn_style_defensive, ch->GetClass())) { ch->SendText ("You have not yet learned enough to fight " "defensively.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_style_defensive)); if (number_percent () < ch->GetLearnedPercent (gsn_style_defensive)){ // success if (ch->GetFightData ()) { ch->SetPosition (POS_DEFENSIVE); learn_from_success (ch, gsn_style_defensive); if (ch->IsPkiller ()) act (AT_ACTION, "$n moves into a defensive posture.", ch, NULL, NULL, TO_ROOM ); } ch->SetStyle (STYLE_DEFENSIVE); ch->SendText ("You adopt a defensive fighting style.\n\r"); return; } else { // failure ch->SendText ("You nearly trip in a lame attempt to adopt " "a defensive fighting style.\n\r"); return; } } else if (! str_prefix (arg, "standard")) { if (ch->GetLevel () < SkillTable.GetClassLevel (gsn_style_standard, ch->GetClass ())) { ch->SendText ("You have not yet learned enough to fight in " "the standard style.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_style_standard)); if (number_percent () < ch->GetLearnedPercent (gsn_style_standard)) { // success if (ch->GetFightData ()) { ch->SetPosition (POS_FIGHTING); learn_from_success (ch, gsn_style_standard); if (ch->IsPkiller ()) act (AT_ACTION, "$n switches to a standard fighting " "style.", ch, NULL, NULL, TO_ROOM); } ch->SetStyle (STYLE_FIGHTING); ch->SendText ("You adopt a standard fighting style.\n\r"); return; } else { // failure ch->SendText ("You nearly trip in a lame attempt to adopt a " "standard fighting style.\n\r"); return; } } else if (! str_prefix (arg, "aggressive")) { if (ch->GetLevel () < SkillTable.GetClassLevel (gsn_style_aggressive, ch->GetClass ())) { ch->SendText ("You have not yet learned enough to fight " "aggressively.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_style_aggressive)); if (number_percent () < ch->GetLearnedPercent (gsn_style_aggressive)){ // success if (ch->GetFightData ()) { ch->SetPosition (POS_AGGRESSIVE); learn_from_success (ch, gsn_style_aggressive); if (ch->IsPkiller ()) act (AT_ACTION, "$n assumes an aggressive stance.", ch, NULL, NULL, TO_ROOM); } ch->SetStyle (STYLE_AGGRESSIVE); ch->SendText ("You adopt an aggressive fighting style.\n\r"); return; } else { // failure ch->SendText ("You nearly trip in a lame attempt to adopt an " "aggressive fighting style.\n\r"); return; } } else if (! str_prefix (arg, "berserk")) { if (ch->GetLevel () < SkillTable.GetClassLevel (gsn_style_berserk, ch->GetClass ())) { ch->SendText ("You have not yet learned enough to fight as a " "berserker.\n\r"); return; } WAIT_STATE (ch, SkillTable.GetBeats (gsn_style_berserk)); if (number_percent () < ch->GetLearnedPercent (gsn_style_berserk)) { // success if (ch->GetFightData ()) { ch->SetPosition (POS_BERSERK); learn_from_success (ch, gsn_style_berserk); if (ch->IsPkiller ()) act (AT_ACTION, "$n enters a wildly aggressive style.", ch, NULL, NULL, TO_ROOM); } ch->SetStyle (STYLE_BERSERK); ch->SendText ("You adopt a berserk fighting style.\n\r"); return; } else { // failure ch->SendText ("You nearly trip in a lame attempt to adopt a " "berserk fighting style.\n\r"); return; } } ch->SendText ("Adopt which fighting style?\n\r"); } // Function used by qsort to sort skills int skill_comp (CSkill **sk1, CSkill **sk2) { CSkill *skill1 = *sk1; CSkill *skill2 = *sk2; if (!skill1 && skill2) return 1; if (skill1 && !skill2) return -1; if (!skill1 && !skill2) return 0; if (skill1->GetType () < skill2->GetType ()) return -1; if (skill1->GetType () > skill2->GetType ()) return 1; return strcmp (skill1->GetName (), skill2->GetName ()); } BOOL CSkillTable::Read (FILE* fp) { BOOL bHerb = this == &HerbTable; int max = bHerb ? MAX_HERB : MAX_SKILL; if (m_Top >= max) { bug ("CSkillTable::Read: Too many Skills for table. Max=%d.", max); fclose (fp); return FALSE; } m_sk [m_Top] = new CSkill; m_sk [m_Top++]->Read (fp); if (bHerb) { if (m_sk [m_Top-1]->m_Slot == 0) then m_sk [m_Top-1]->m_Slot = m_Top-1; } return TRUE; } void CSkillTable::Add (CSkill* skill) { BOOL bHerb = this == &HerbTable; int max = bHerb ? MAX_HERB : MAX_SKILL; ASSERT (m_Top < max); m_sk [m_Top++] = skill; if (bHerb) { int max, x; for (max = x = 0; x < m_Top-1; ++x) if (m_sk [x] && m_sk [x]->m_Slot > max) max = m_sk [x]->m_Slot; skill->m_Slot = max+1; } } // Sort the skill table with qsort void CSkillTable::Sort () { gpDoc->LogString ("Sorting skill table...", LOG_BOOT); qsort (&m_sk [1], m_Top-1, sizeof (CSkill*), (int (*) (const void *, const void *)) skill_comp); } //Lookup a skill by name. int CSkillTable::Lookup (const char *name) { int sn; BOOL bHerb = this == &HerbTable; if (! bHerb) { // do skills if ((sn = BsearchExact (name, gsn_first_spell, gsn_first_skill-1)) == -1) if ((sn = BsearchExact (name, gsn_first_skill, gsn_first_weapon-1)) == -1) if ((sn = BsearchExact (name, gsn_first_weapon, gsn_first_tongue-1)) == -1) if ((sn = BsearchExact (name, gsn_first_tongue, gsn_top_sn-1)) == -1) if ((sn = Bsearch (name, gsn_first_spell, gsn_first_skill-1)) == -1) if ((sn = Bsearch (name, gsn_first_skill, gsn_first_weapon-1)) == -1) if ((sn = Bsearch (name, gsn_first_weapon, gsn_first_tongue-1)) == -1) if ((sn = Bsearch (name, gsn_first_tongue, gsn_top_sn-1)) == -1 && gsn_top_sn < m_Top) { for (sn = gsn_top_sn; sn < m_Top; ++sn) { if (GetSkill (sn) == NULL || GetName (sn) == NULL) return -1; if (LOWER (name[0]) == LOWER (GetName (sn)[0]) && !str_prefix (name, GetName (sn))) return sn; } return -1; } return sn; } else { // else do herbs for (sn = 0; sn < m_Top; sn++) { if (! GetSkill (sn) || ! GetName (sn)) return -1; if (LOWER (name[0]) == LOWER (GetName (sn)[0]) && !str_prefix (name, GetName (sn))) return sn; } return -1; } return sn; // should never get here } // Return a skilltype pointer from either table based on sn -Thoric // Returns NULL if bad, unused or personal sn. CSkill *CSkillTable::GetValidSkill (int sn) { if (sn >= TYPE_PERSONAL) return NULL; if (sn >= TYPE_HERB) return HerbTable.IsValid (sn - TYPE_HERB) ? HerbTable.GetSkill (sn - TYPE_HERB) : NULL; if (sn >= TYPE_HIT) return NULL; return SkillTable.IsValid (sn) ? SkillTable.GetSkill (sn) : NULL; } // Perform a binary search on a section of the skill table -Thoric // Each different section of the skill table is sorted alphabetically int CSkillTable::Bsearch (const char *name, int first, int top) { int sn; for (;;) { sn = (first + top) >> 1; if (LOWER (name[0]) == LOWER (GetName (sn)[0]) && !str_prefix (name, GetName (sn))) return sn; if (first >= top) return -1; if (strcmp (name, GetName (sn)) < 1) top = sn - 1; else first = sn + 1; } return -1; } // Perform a binary search on a section of the skill table -Thoric // Each different section of the skill table is sorted alphabetically // Check for exact matches only int CSkillTable::BsearchExact (const char *name, int first, int top) { int sn; for (;;) { sn = (first + top) >> 1; if (!str_prefix (name, GetName (sn))) return sn; if (first >= top) return -1; if (strcmp (name, GetName (sn)) < 1) top = sn - 1; else first = sn + 1; } return -1; } // Perform a binary search on a section of the skill table // Each different section of the skill table is sorted alphabetically // Only match skills player knows -Thoric int CSkillTable::ChBsearch (CCharacter *ch, const char *name, int first, int top) { int sn; for (;;) { sn = (first + top) >> 1; if (LOWER (name[0]) == LOWER (GetName (sn)[0]) && !str_prefix (name, GetName (sn)) && ch->GetPcData ()->learned [sn] > 0 && ch->GetLevel () >= GetClassLevel (sn, ch->GetClass ())) return sn; if (first >= top) return -1; if (strcmp (name, GetName (sn)) < 1) top = sn - 1; else first = sn + 1; } return -1; } #define KEY2(literal,field,value) \ if (!str_cmp (word, literal)) { \ field (value); \ fMatch = TRUE; \ break; \ } void CSkill::Read (FILE *fp) { char *word, *pLine; BOOL fMatch; SetGuild (-1); for (;;) { fMatch = FALSE; if (! feof (fp)) { pLine = fread_line (fp); word = ParseWord (pLine); } else word = "End"; switch (UPPER (word [0])) { case '*': fMatch = TRUE; break; case 'A': if (! str_cmp (word, "Affect")) { CSmaugAffect *aff = new CSmaugAffect; aff->duration = str_dup (ParseWord (pLine)); aff->location = ParseNumber (pLine); aff->modifier = str_dup (ParseWord (pLine)); aff->bitvector = ParseNumber (pLine); aff->SetNext (GetAffects ()); SetAffects (aff); fMatch = TRUE; break; } break; case 'C': if (! str_cmp (word, "Class")) { // Class not used in skill.dat fMatch = TRUE; break; } if (! str_cmp (word, "Code")) { SPELL_FUN *spellfun = NULL; DO_FUN *dofun = NULL; char *w = ParseWord (pLine); fMatch = TRUE; spellfun = spell_function (w); if (spellfun != spell_notfound) { SetSpellFunction (spellfun); break; } dofun = skill_function (w); if (dofun != skill_notfound) { SetSkillFunction (dofun); break; } bug ("CSkill::Read: unknown skill/spell %s (%s)", w, GetName ()); SetSpellFunction (spell_null); break; } KEY2("Code", SetSpellFunction, spell_function (ParseWord (pLine))); KEY2("Components", SetComponents, ParseStringNohash (pLine, fp)); break; case 'D': KEY2("Dammsg", SetDamageMsg, ParseStringNohash (pLine, fp)); KEY2("Dice", SetDiceRoll, ParseStringNohash (pLine, fp)); KEY2("Diechar", SetDieCharMsg, ParseStringNohash (pLine, fp)); KEY2("Dieroom", SetDieRoomMsg, ParseStringNohash (pLine, fp)); KEY2("Dievict", SetDieVictMsg, ParseStringNohash (pLine, fp)); KEY2("Difficulty", SetDifficulty, ParseNumber (pLine)); break; case 'E': if (! str_cmp (word, "End")) return; break; case 'F': KEY2("Flags", SetFlags, ParseNumber (pLine)); break; case 'G': KEY2("Guild", SetGuild, ParseNumber (pLine)); break; case 'H': KEY2("Hitchar", SetHitCharMsg, ParseStringNohash (pLine, fp)); KEY2("Hitdest", SetHitDest, ParseStringNohash (pLine, fp)); KEY2("Hitroom", SetHitRoomMsg, ParseStringNohash (pLine, fp)); KEY2("Hitvict", SetHitVictMsg, ParseStringNohash (pLine, fp)); break; case 'I': KEY2("Immchar", SetImmuneCharMsg, ParseStringNohash (pLine, fp)); KEY2("Immroom", SetImmuneRoomMsg, ParseStringNohash (pLine, fp)); KEY2("Immvict", SetImmuneVictMsg, ParseStringNohash (pLine, fp)); KEY2("Info", SetInfo, ParseNumber (pLine)); break; case 'M': KEY2("Mana", SetMinMana, ParseNumber (pLine)); if (! str_cmp (word, "Minlevel")) { fMatch = TRUE; break; } KEY2("Minpos", SetMinimumPosition, ParseNumber (pLine)); KEY2("Misschar", SetMissCharMsg, ParseStringNohash (pLine, fp)); KEY2("Missroom", SetMissRoomMsg, ParseStringNohash (pLine, fp)); KEY2("Missvict", SetMissVictMsg, ParseStringNohash (pLine, fp)); break; case 'N': KEY2("Name", SetName, ParseStringNohash (pLine, fp)); break; case 'P': KEY2("Participants", SetParticipants, ParseNumber (pLine)); break; case 'R': KEY2("Range", SetRange, ParseNumber (pLine)); KEY2("Rounds", SetBeats, ParseNumber (pLine)); break; case 'S': KEY2("Slot", SetSlot, ParseNumber (pLine)); KEY2("Saves", SetSaves, ParseNumber (pLine)); break; case 'T': KEY2("Target", SetTarget, ParseNumber (pLine)); KEY2("Teachers", SetTeachers, ParseStringNohash (pLine, fp)); KEY2("Type", SetType, get_skill (ParseWord (pLine))); break; case 'V': KEY2("Value", SetValue, ParseNumber (pLine)); break; case 'W': KEY2("Wearoff", SetOffMsg, ParseStringNohash (pLine, fp)); break; } if (!fMatch) bug ("CSkill::Read: no match: %s", word); } } // Write skill data to a file void CSkill::Write (FILE *fp) { CSmaugAffect *aff; fprintf (fp, "Name %s~\n", GetName ()); fprintf (fp, "Type %s\n", skill_tname [GetType ()]); if (GetInfo ()) fprintf (fp, "Info %d\n", GetInfo ()); fprintf (fp, "Flags %d\n", GetFlags ()); if (GetTarget ()) fprintf (fp, "Target %d\n", GetTarget ()); if (GetMinimumPosition ()) fprintf (fp, "Minpos %d\n", GetMinimumPosition ()); if (GetSaves ()) fprintf (fp, "Saves %d\n", GetSaves ()); if (GetSlot ()) fprintf (fp, "Slot %d\n", GetSlot ()); if (GetMinMana ()) fprintf (fp, "Mana %d\n", GetMinMana ()); if (GetBeats ()) fprintf (fp, "Rounds %d\n", GetBeats ()); if (GetGuild () != -1) fprintf (fp, "Guild %d\n", GetGuild ()); if (GetSkillFunction ()) fprintf (fp, "Code %s\n", skill_name (GetSkillFunction ())); else if (GetSpellFunction ()) fprintf (fp, "Code %s\n", spell_name (GetSpellFunction ())); if (ValidDamageMsg ()) fprintf (fp, "Dammsg %s~\n", GetDamageMsg ()); if (ValidOffMsg ()) fprintf (fp, "Wearoff %s~\n", GetOffMsg ()); if (ValidHitCharMsg ()) fprintf (fp, "Hitchar %s~\n", GetHitCharMsg ()); if (ValidHitVictMsg ()) fprintf (fp, "Hitvict %s~\n", GetHitVictMsg ()); if (ValidHitRoomMsg ()) fprintf (fp, "Hitroom %s~\n", GetHitRoomMsg ()); if (ValidHitDest ()) fprintf (fp, "Hitdest %s~\n", GetHitDest ()); if (ValidMissCharMsg ()) fprintf (fp, "Misschar %s~\n", GetMissCharMsg ()); if (ValidMissVictMsg ()) fprintf (fp, "Missvict %s~\n", GetMissVictMsg ()); if (ValidMissRoomMsg ()) fprintf (fp, "Missroom %s~\n", GetMissRoomMsg ()); if (ValidDieCharMsg ()) fprintf (fp, "Diechar %s~\n", GetDieCharMsg ()); if (ValidDieVictMsg ()) fprintf (fp, "Dievict %s~\n", GetDieVictMsg ()); if (ValidDieRoomMsg ()) fprintf (fp, "Dieroom %s~\n", GetDieRoomMsg ()); if (ValidImmuneCharMsg ()) fprintf (fp, "Immchar %s~\n", GetImmuneCharMsg ()); if (ValidImmuneVictMsg ()) fprintf (fp, "Immvict %s~\n", GetImmuneVictMsg ()); if (ValidImmuneRoomMsg ()) fprintf (fp, "Immroom %s~\n", GetImmuneRoomMsg ()); if (HasTeachers ()) fprintf (fp, "Teachers %s~\n", GetTeachers ()); if (GetDiceRoll () && GetDiceRoll ()[0] != '\0') fprintf (fp, "Dice %s~\n", GetDiceRoll ()); if (GetValue ()) fprintf (fp, "Value %d\n", GetValue ()); if (GetDifficulty ()) fprintf (fp, "Difficulty %d\n", GetDifficulty ()); if (GetParticipants ()) fprintf (fp, "Participants %d\n", GetParticipants ()); if (GetComponents () && GetComponents ()[0] != '\0') fprintf (fp, "Components %s~\n", GetComponents ()); for (aff = GetAffects (); aff; aff = aff->GetNext ()) { fprintf (fp, "Affect '%s' %d ", aff->duration, aff->location); int iMod = atoi (aff->modifier); if ((aff->location == APPLY_WEAPONSPELL || aff->location == APPLY_WEARSPELL || aff->location == APPLY_REMOVESPELL || aff->location == APPLY_STRIPSN || aff->location == APPLY_RECURRINGSPELL) && SkillTable.IsValid (iMod)) fprintf (fp, "'%d' ", SkillTable.GetSlot (iMod)); else fprintf (fp, "'%s' ", aff->modifier); fprintf (fp, "%d\n", aff->bitvector); } if (GetType () != SKILL_HERB) { int y; int min = 1000; for (y = 0; y < ClassTable.GetCount (); y++) if (GetClassLevel (y) < min) min = GetClassLevel (y); fprintf (fp, "Minlevel %d\n", min); } fprintf (fp, "End\n\n"); } void CSkillTable::RemoveAll () { for (int skill=0; skill < m_Top; ++skill) { delete m_sk [skill]; m_sk [skill] = NULL; } m_Top = 0; } CSkill::~CSkill () { delete m_pName; delete m_pDamMsg; delete m_OffMsg; delete m_HitChar; delete m_HitVict; delete m_HitRoom; delete m_MissChar; delete m_MissVict; delete m_MissRoom; delete m_DieChar; delete m_DieVict; delete m_DieRoom; delete m_pDice; delete m_ImmChar; delete m_ImmVict; delete m_ImmRoom; delete m_pComponents; delete m_pTeachers; CSmaugAffect *pNext, *pAff = m_pAffects; while (pAff) { pNext = pAff->GetNext (); delete pAff; pAff = pNext; } m_ClassLevel.RemoveAll (); m_ClassAdept.RemoveAll (); m_RaceLevel.RemoveAll (); m_RaceAdept.RemoveAll (); } DO_FUN *skill_function (char *name) { switch (name[3]) { case 'a': if (!str_cmp (name, "do_aassign")) return do_aassign; if (!str_cmp (name, "do_advance")) return do_advance; if (!str_cmp (name, "do_affected")) return do_affected; if (!str_cmp (name, "do_afk")) return do_afk; if (!str_cmp (name, "do_aid")) return do_aid; if (!str_cmp (name, "do_allow")) return do_allow; if (!str_cmp (name, "do_ansi")) return do_ansi; if (!str_cmp (name, "do_answer")) return do_answer; if (!str_cmp (name, "do_apply")) return do_apply; if (!str_cmp (name, "do_appraise")) return do_appraise; if (!str_cmp (name, "do_areas")) return do_areas; if (!str_cmp (name, "do_aset")) return do_aset; if (!str_cmp (name, "do_ask")) return do_ask; if (!str_cmp (name, "do_astat")) return do_astat; if (!str_cmp (name, "do_at")) return do_at; if (!str_cmp (name, "do_atmob")) return do_atmob; if (!str_cmp (name, "do_atobj")) return do_atobj; if (!str_cmp (name, "do_auction")) return do_auction; if (!str_cmp (name, "do_authorize")) return do_authorize; if (!str_cmp (name, "do_avtalk")) return do_avtalk; break; case 'b': if (!str_cmp (name, "do_backstab")) return do_backstab; if (!str_cmp (name, "do_balzhur")) return do_balzhur; if (!str_cmp (name, "do_bamfin")) return do_bamfin; if (!str_cmp (name, "do_bamfout")) return do_bamfout; if (!str_cmp (name, "do_ban")) return do_ban; if (!str_cmp (name, "do_bash")) return do_bash; if (!str_cmp (name, "do_bashdoor")) return do_bashdoor; if (!str_cmp (name, "do_berserk")) return do_berserk; if (!str_cmp (name, "do_bestow")) return do_bestow; if (!str_cmp (name, "do_bestowarea")) return do_bestowarea; if (!str_cmp (name, "do_bio")) return do_bio; if (!str_cmp( name, "do_bite" )) return do_bite; if (!str_cmp( name, "do_bloodlet")) return do_bloodlet; if (!str_cmp (name, "do_boards")) return do_boards; if (!str_cmp (name, "do_bodybag")) return do_bodybag; if (!str_cmp (name, "do_brandish")) return do_brandish; if (!str_cmp (name, "do_brew")) return do_brew; if (!str_cmp (name, "do_broach")) return do_broach; if (!str_cmp (name, "do_bset")) return do_bset; if (!str_cmp (name, "do_bstat")) return do_bstat; if (!str_cmp (name, "do_bug")) return do_bug; if (!str_cmp (name, "do_bury")) return do_bury; if (!str_cmp (name, "do_buy")) return do_buy; break; case 'c': if (!str_cmp (name, "do_cast")) return do_cast; if (!str_cmp (name, "do_cedit")) return do_cedit; if (!str_cmp (name, "do_channels")) return do_channels; if (!str_cmp (name, "do_chat")) return do_chat; if (!str_cmp (name, "do_check_vnums")) return do_check_vnums; if (!str_cmp (name, "do_circle")) return do_circle; if (!str_cmp (name, "do_clans")) return do_clans; if (!str_cmp (name, "do_clantalk")) return do_clantalk; if (!str_cmp (name, "do_climb")) return do_climb; if (!str_cmp (name, "do_close")) return do_close; if (!str_cmp (name, "do_cmdtable")) return do_cmdtable; if (!str_cmp (name, "do_cmenu")) return do_cmenu; if (!str_cmp (name, "do_commands")) return do_commands; if (!str_cmp (name, "do_comment")) return do_comment; if (!str_cmp (name, "do_compare")) return do_compare; if (!str_cmp (name, "do_config")) return do_config; if (!str_cmp (name, "do_consider")) return do_consider; if (!str_cmp( name, "do_cook")) return do_cook; if (!str_cmp (name, "do_council_induct")) return do_council_induct; if (!str_cmp (name, "do_council_outcast")) return do_council_outcast; if (!str_cmp (name, "do_councils")) return do_councils; if (!str_cmp (name, "do_counciltalk")) return do_counciltalk; if (!str_cmp (name, "do_credits")) return do_credits; if (!str_cmp (name, "do_cset")) return do_cset; break; case 'd': if (!str_cmp (name, "do_deities")) return do_deities; if (!str_cmp (name, "do_deny")) return do_deny; if (!str_cmp (name, "do_description")) return do_description; if (!str_cmp (name, "do_destro")) return do_destro; if (!str_cmp (name, "do_destroy")) return do_destroy; if (!str_cmp (name, "do_detrap")) return do_detrap; if (!str_cmp (name, "do_devote")) return do_devote; if (!str_cmp (name, "do_dig")) return do_dig; if (!str_cmp (name, "do_disarm")) return do_disarm; if (!str_cmp (name, "do_disconnect")) return do_disconnect; if (!str_cmp (name, "do_dismiss")) return do_dismiss; if (!str_cmp (name, "do_dismount")) return do_dismount; if (!str_cmp (name, "do_dmesg")) return do_dmesg; if (!str_cmp (name, "do_down")) return do_down; if (!str_cmp (name, "do_drag")) return do_drag; if (!str_cmp (name, "do_drink")) return do_drink; if (!str_cmp (name, "do_drop")) return do_drop; if (!str_cmp (name, "do_diagnose")) return do_diagnose; break; case 'e': if (!str_cmp (name, "do_east")) return do_east; if (!str_cmp (name, "do_eat")) return do_eat; if (!str_cmp (name, "do_echo")) return do_echo; if (!str_cmp (name, "do_elevate")) return do_elevate; if (!str_cmp (name, "do_emote")) return do_emote; if (!str_cmp (name, "do_empty")) return do_empty; if (!str_cmp (name, "do_enter")) return do_enter; if (!str_cmp (name, "do_equipment")) return do_equipment; if (!str_cmp (name, "do_examine")) return do_examine; if (!str_cmp (name, "do_exits")) return do_exits; break; case 'f': if (!str_cmp (name, "do_feed")) return do_feed; if (!str_cmp (name, "do_fill")) return do_fill; if (!str_cmp (name, "do_fire")) return do_fire; if (!str_cmp (name, "do_fixchar")) return do_fixchar; if (!str_cmp (name, "do_flee")) return do_flee; if (!str_cmp (name, "do_foldarea")) return do_foldarea; if (!str_cmp (name, "do_follow")) return do_follow; if (!str_cmp (name, "do_for")) return do_for; if (!str_cmp (name, "do_force")) return do_force; if (!str_cmp (name, "do_forceclose")) return do_forceclose; if (!str_cmp (name, "do_form_password")) return do_form_password; if (!str_cmp (name, "do_fprompt")) return do_fprompt; if (!str_cmp (name, "do_fquit")) return do_fquit; if (!str_cmp (name, "do_freeze")) return do_freeze; break; case 'g': if (!str_cmp (name, "do_get")) return do_get; if (!str_cmp (name, "do_gfighting")) return do_gfighting; if (!str_cmp (name, "do_give")) return do_give; if (!str_cmp (name, "do_glance")) return do_glance; if (!str_cmp (name, "do_gold")) return do_gold; if (!str_cmp (name, "do_goto")) return do_goto; if (!str_cmp (name, "do_gouge")) return do_gouge; if (!str_cmp (name, "do_group")) return do_group; if (!str_cmp (name, "do_grub")) return do_grub; if (!str_cmp (name, "do_gtell")) return do_gtell; if (!str_cmp (name, "do_guilds")) return do_guilds; if (!str_cmp (name, "do_guildtalk")) return do_guildtalk; if (!str_cmp (name, "do_gwhere")) return do_gwhere; break; case 'h': if (!str_cmp (name, "do_hedit")) return do_hedit; if (!str_cmp (name, "do_hell")) return do_hell; if (!str_cmp (name, "do_help")) return do_help; if (!str_cmp (name, "do_hide")) return do_hide; if (!str_cmp (name, "do_hitall")) return do_hitall; if (!str_cmp (name, "do_hlist")) return do_hlist; if (!str_cmp (name, "do_holylight")) return do_holylight; if (!str_cmp (name, "do_homepage")) return do_homepage; if (!str_cmp (name, "do_hset")) return do_hset; break; case 'i': if (!str_cmp (name, "do_ide")) return do_ide; if (!str_cmp (name, "do_idea")) return do_idea; if (!str_cmp (name, "do_ignore")) return do_ignore; if (!str_cmp (name, "do_immortalize")) return do_immortalize; if (!str_cmp (name, "do_immtalk")) return do_immtalk; if (!str_cmp (name, "do_induct")) return do_induct; if (!str_cmp (name, "do_installarea")) return do_installarea; if (!str_cmp (name, "do_instaroom")) return do_instaroom; if (!str_cmp (name, "do_instazone")) return do_instazone; if (!str_cmp (name, "do_inventory")) return do_inventory; if (!str_cmp (name, "do_invis")) return do_invis; break; case 'k': if (!str_cmp (name, "do_kick")) return do_kick; if (!str_cmp (name, "do_kill")) return do_kill; break; case 'l': if (!str_cmp (name, "do_languages")) return do_languages; if (!str_cmp (name, "do_last")) return do_last; if (!str_cmp (name, "do_leave")) return do_leave; if (!str_cmp (name, "do_level")) return do_level; if (!str_cmp (name, "do_light")) return do_light; if (!str_cmp (name, "do_list")) return do_list; if (!str_cmp (name, "do_litterbug")) return do_litterbug; if (!str_cmp (name, "do_loadarea")) return do_loadarea; if (!str_cmp (name, "do_loadup")) return do_loadup; if (!str_cmp (name, "do_lock")) return do_lock; if (!str_cmp (name, "do_log")) return do_log; if (!str_cmp (name, "do_look")) return do_look; if (!str_cmp (name, "do_low_purge")) return do_low_purge; break; case 'm': if (!str_cmp (name, "do_mailroom")) return do_mailroom; if (!str_cmp (name, "do_make")) return do_make; if (!str_cmp (name, "do_makeboard")) return do_makeboard; if (!str_cmp (name, "do_makeclan")) return do_makeclan; if (!str_cmp (name, "do_makecouncil")) return do_makecouncil; if (!str_cmp (name, "do_makedeity")) return do_makedeity; if (!str_cmp (name, "do_makeguild")) return do_makeguild; if (!str_cmp (name, "do_makeorder")) return do_makeorder; if (!str_cmp (name, "do_makerepair")) return do_makerepair; if (!str_cmp (name, "do_makeshop")) return do_makeshop; if (!str_cmp (name, "do_makewizlist")) return do_makewizlist; if (!str_cmp (name, "do_massign")) return do_massign; if (!str_cmp (name, "do_mcreate")) return do_mcreate; if (!str_cmp (name, "do_mdelete")) return do_mdelete; if (!str_cmp (name, "do_memory")) return do_memory; if (!str_cmp (name, "do_mfind")) return do_mfind; if (!str_cmp (name, "do_minvoke")) return do_minvoke; if (!str_cmp (name, "do_mistwalk")) return do_mistwalk; if (!str_cmp (name, "do_mlist")) return do_mlist; if (!str_cmp (name, "do_mmenu")) return do_mmenu; if (!str_cmp (name, "do_mount")) return do_mount; if (!str_cmp (name, "do_mp_close_passage")) return do_mp_close_passage; if (!str_cmp (name, "do_mp_damage")) return do_mp_damage; if (!str_cmp (name, "do_mp_deposit")) return do_mp_deposit; if (!str_cmp (name, "do_mp_open_passage")) return do_mp_open_passage; if (!str_cmp (name, "do_mp_practice")) return do_mp_practice; if (!str_cmp (name, "do_mp_restore")) return do_mp_restore; if (!str_cmp (name, "do_mp_slay")) return do_mp_slay; if (!str_cmp (name, "do_mp_withdraw")) return do_mp_withdraw; if (!str_cmp (name, "do_mpadvance")) return do_mpadvance; if (!str_cmp (name, "do_mpapply")) return do_mpapply; if (!str_cmp (name, "do_mpapplyb")) return do_mpapplyb; if (!str_cmp (name, "do_mpasound")) return do_mpasound; if (!str_cmp (name, "do_mpasupress")) return do_mpasupress; if (!str_cmp (name, "do_mpat")) return do_mpat; if (!str_cmp (name, "do_mpbodybag")) return do_mpbodybag; if (!str_cmp (name, "do_mpdream")) return do_mpdream; if (!str_cmp (name, "do_mpecho")) return do_mpecho; if (!str_cmp (name, "do_mpechoaround")) return do_mpechoaround; if (!str_cmp (name, "do_mpechoat")) return do_mpechoat; if (!str_cmp (name, "do_mpedit")) return do_mpedit; if (!str_cmp (name, "do_mpfavor")) return do_mpfavor; if (!str_cmp (name, "do_mpforce")) return do_mpforce; if (!str_cmp (name, "do_mpgoto")) return do_mpgoto; if (!str_cmp (name, "do_mpinvis")) return do_mpinvis; if (!str_cmp (name, "do_mpjunk")) return do_mpjunk; if (!str_cmp (name, "do_mpkill")) return do_mpkill; if (!str_cmp (name, "do_mpmload")) return do_mpmload; if (!str_cmp (name, "do_mpmset")) return do_mpmset; if (!str_cmp (name, "do_mpnothing")) return do_mpnothing; if (!str_cmp (name, "do_mpoload")) return do_mpoload; if (!str_cmp (name, "do_mposet")) return do_mposet; if (!str_cmp (name, "do_mppardon")) return do_mppardon; if (!str_cmp (name, "do_mppkset")) return do_mppkset; if (!str_cmp (name, "do_mppurge")) return do_mppurge; if (!str_cmp (name, "do_mpstat")) return do_mpstat; if (!str_cmp (name, "do_mptransfer")) return do_mptransfer; if (!str_cmp (name, "do_mrange")) return do_mrange; if (!str_cmp (name, "do_mset")) return do_mset; if (!str_cmp (name, "do_mstat")) return do_mstat; if (!str_cmp (name, "do_murde")) return do_murde; if (!str_cmp (name, "do_murder")) return do_murder; if (!str_cmp (name, "do_muse")) return do_muse; if (!str_cmp (name, "do_music")) return do_music; if (!str_cmp (name, "do_mwhere")) return do_mwhere; break; case 'n': if (!str_cmp (name, "do_name")) return do_name; if (!str_cmp (name, "do_newbiechat")) return do_newbiechat; if (!str_cmp (name, "do_newbieset")) return do_newbieset; if (!str_cmp (name, "do_newzones")) return do_newzones; if (!str_cmp (name, "do_noemote")) return do_noemote; if (!str_cmp (name, "do_noresolve")) return do_noresolve; if (!str_cmp (name, "do_north")) return do_north; if (!str_cmp (name, "do_northeast")) return do_northeast; if (!str_cmp (name, "do_northwest")) return do_northwest; if (!str_cmp (name, "do_notell")) return do_notell; if (!str_cmp (name, "do_notitle")) return do_notitle; if (!str_cmp (name, "do_noteroom")) return do_noteroom; break; case 'o': if (!str_cmp (name, "do_oassign")) return do_oassign; if (!str_cmp (name, "do_ocreate")) return do_ocreate; if (!str_cmp (name, "do_odelete")) return do_odelete; if (!str_cmp (name, "do_ofind")) return do_ofind; if (!str_cmp (name, "do_ogrub")) return do_ogrub; if (!str_cmp (name, "do_oinvoke")) return do_oinvoke; if (!str_cmp (name, "do_oldscore")) return do_oldscore; if (!str_cmp (name, "do_olist")) return do_olist; if (!str_cmp (name, "do_omenu")) return do_omenu; if (!str_cmp (name, "do_opedit")) return do_opedit; if (!str_cmp (name, "do_open")) return do_open; /* if (!str_cmp (name, "do_opentourney")) return do_opentourney; */ if (!str_cmp (name, "do_opstat")) return do_opstat; if (!str_cmp (name, "do_orange")) return do_orange; if (!str_cmp (name, "do_order")) return do_order; if (!str_cmp (name, "do_orders")) return do_orders; if (!str_cmp (name, "do_ordertalk")) return do_ordertalk; if (!str_cmp (name, "do_oset")) return do_oset; if (!str_cmp (name, "do_ostat")) return do_ostat; if (!str_cmp (name, "do_outcast")) return do_outcast; if (!str_cmp (name, "do_owhere")) return do_owhere; break; case 'p': if (!str_cmp (name, "do_pager")) return do_pager; if (!str_cmp (name, "do_pagelen")) return do_pagelen; if (!str_cmp (name, "do_pardon")) return do_pardon; if (!str_cmp (name, "do_password")) return do_password; if (!str_cmp (name, "do_pcrename")) return do_pcrename; if (!str_cmp (name, "do_peace")) return do_peace; if (!str_cmp (name, "do_pick")) return do_pick; if (!str_cmp (name, "do_pmenu")) return do_pmenu; if (!str_cmp (name, "do_poison_weapon")) return do_poison_weapon; if (!str_cmp (name, "do_practice")) return do_practice; if (!str_cmp (name, "do_prompt")) return do_prompt; if (!str_cmp (name, "do_pull")) return do_pull; if (!str_cmp (name, "do_punch")) return do_punch; if (!str_cmp (name, "do_purge")) return do_purge; if (!str_cmp (name, "do_push")) return do_push; if (!str_cmp (name, "do_put")) return do_put; break; case 'q': if (!str_cmp (name, "do_qpset")) return do_qpset; if (!str_cmp (name, "do_quaff")) return do_quaff; if (!str_cmp (name, "do_quest")) return do_quest; if (!str_cmp (name, "do_qui")) return do_qui; if (!str_cmp (name, "do_quit")) return do_quit; break; case 'r': if (!str_cmp (name, "do_racetalk")) return do_racetalk; if (!str_cmp (name, "do_rank")) return do_rank; if (!str_cmp (name, "do_rap")) return do_rap; if (!str_cmp (name, "do_rassign")) return do_rassign; if (!str_cmp (name, "do_rat")) return do_rat; if (!str_cmp (name, "do_rdelete")) return do_rdelete; if (!str_cmp (name, "do_reboo")) return do_reboo; if (!str_cmp (name, "do_reboot")) return do_reboot; if (!str_cmp (name, "do_recho")) return do_recho; if (!str_cmp (name, "do_recite")) return do_recite; if (!str_cmp (name, "do_redit")) return do_redit; if (!str_cmp (name, "do_regoto")) return do_regoto; if (!str_cmp (name, "do_remains")) return do_remains; if (!str_cmp (name, "do_remove")) return do_remove; if (!str_cmp (name, "do_rent")) return do_rent; if (!str_cmp (name, "do_repair")) return do_repair; if (!str_cmp (name, "do_repairset")) return do_repairset; if (!str_cmp (name, "do_repairshops")) return do_repairshops; if (!str_cmp (name, "do_repairstat")) return do_repairstat; if (!str_cmp (name, "do_reply")) return do_reply; if (!str_cmp (name, "do_report")) return do_report; if (!str_cmp (name, "do_rescue")) return do_rescue; if (!str_cmp (name, "do_reset")) return do_reset; if (!str_cmp (name, "do_reserve")) return do_reserve; if (!str_cmp (name, "do_rest")) return do_rest; if (!str_cmp (name, "do_restore")) return do_restore; if (!str_cmp (name, "do_restoretime")) return do_restoretime; if (!str_cmp (name, "do_restrict")) return do_restrict; if (!str_cmp (name, "do_retire")) return do_retire; if (!str_cmp (name, "do_retran")) return do_retran; if (!str_cmp (name, "do_return")) return do_return; if (!str_cmp (name, "do_revert")) return do_revert; if (!str_cmp (name, "do_rip")) return do_rip; if (!str_cmp (name, "do_rlist")) return do_rlist; if (!str_cmp (name, "do_rmenu")) return do_rmenu; if (!str_cmp (name, "do_rpedit")) return do_rpedit; if (!str_cmp (name, "do_rpstat")) return do_rpstat; if (!str_cmp (name, "do_rreset")) return do_rreset; if (!str_cmp (name, "do_rset")) return do_rset; if (!str_cmp (name, "do_rstat")) return do_rstat; break; case 's': if (!str_cmp (name, "do_sacrifice")) return do_sacrifice; if (!str_cmp (name, "do_save")) return do_save; if (!str_cmp (name, "do_savearea")) return do_savearea; if (!str_cmp (name, "do_say")) return do_say; if (!str_cmp (name, "do_scan")) return do_scan; if (!str_cmp (name, "do_score")) return do_score; if (!str_cmp (name, "do_scribe")) return do_scribe; if (!str_cmp (name, "do_search")) return do_search; if (!str_cmp (name, "do_sedit")) return do_sedit; if (!str_cmp (name, "do_sell")) return do_sell; if (!str_cmp (name, "do_set_boot_time")) return do_set_boot_time; if (!str_cmp (name, "do_setclan")) return do_setclan; if (!str_cmp (name, "do_setclass")) return do_setclass; if (!str_cmp (name, "do_setcouncil")) return do_setcouncil; if (!str_cmp (name, "do_setdeity")) return do_setdeity; if (!str_cmp (name, "do_setguild")) return do_setguild; if (!str_cmp (name, "do_setorder")) return do_setorder; if (!str_cmp (name, "do_setrace")) return do_setrace; if (!str_cmp (name, "do_shops")) return do_shops; if (!str_cmp (name, "do_shopset")) return do_shopset; if (!str_cmp (name, "do_shopstat")) return do_shopstat; if (!str_cmp (name, "do_shout")) return do_shout; if (!str_cmp (name, "do_shove")) return do_shove; if (!str_cmp (name, "do_showclan")) return do_showclan; if (!str_cmp (name, "do_showclass")) return do_showclass; if (!str_cmp (name, "do_showcouncil")) return do_showcouncil; if (!str_cmp (name, "do_showdeity")) return do_showdeity; if (!str_cmp (name, "do_showguild")) return do_showguild; if (!str_cmp (name, "do_showorder")) return do_showorder; if (!str_cmp (name, "do_showrace")) return do_showrace; if (!str_cmp (name, "do_showbytes")) return do_showbytes; if (!str_cmp (name, "do_shutdow")) return do_shutdow; if (!str_cmp (name, "do_shutdown")) return do_shutdown; if (!str_cmp (name, "do_silence")) return do_silence; if (!str_cmp (name, "do_sit")) return do_sit; if (!str_cmp (name, "do_sla")) return do_sla; if (!str_cmp (name, "do_slay")) return do_slay; if (!str_cmp (name, "do_sleep")) return do_sleep; if (!str_cmp (name, "do_slice")) return do_slice; if (!str_cmp (name, "do_slist")) return do_slist; if (!str_cmp (name, "do_slookup")) return do_slookup; if (!str_cmp (name, "do_smoke")) return do_smoke; if (!str_cmp (name, "do_snoop")) return do_snoop; if (!str_cmp (name, "do_sober")) return do_sober; if (!str_cmp (name, "do_socials")) return do_socials; if (!str_cmp (name, "do_south")) return do_south; if (!str_cmp (name, "do_southeast")) return do_southeast; if (!str_cmp (name, "do_southwest")) return do_southwest; if (!str_cmp (name, "do_speak")) return do_speak; if (!str_cmp (name, "do_split")) return do_split; if (!str_cmp (name, "do_sset")) return do_sset; if (!str_cmp (name, "do_stand")) return do_stand; if (!str_cmp (name, "do_stat")) return do_stat; if (!str_cmp (name, "do_statreport")) return do_statreport; if (!str_cmp (name, "do_steal")) return do_steal; if (!str_cmp (name, "do_stun")) return do_stun; if (!str_cmp (name, "do_style")) return do_style; if (!str_cmp (name, "do_supplicate")) return do_supplicate; if (!str_cmp (name, "do_switch")) return do_switch; break; case 't': if (!str_cmp (name, "do_tamp")) return do_tamp; if (!str_cmp (name, "do_tell")) return do_tell; if (!str_cmp (name, "do_think")) return do_think; if (!str_cmp (name, "do_time")) return do_time; if (!str_cmp (name, "do_timecmd")) return do_timecmd; if (!str_cmp (name, "do_title")) return do_title; if (!str_cmp (name, "do_track")) return do_track; if (!str_cmp (name, "do_transfer")) return do_transfer; if (!str_cmp (name, "do_trust")) return do_trust; if (!str_cmp (name, "do_typo")) return do_typo; break; case 'u': if (!str_cmp (name, "do_unfoldarea")) return do_unfoldarea; if (!str_cmp (name, "do_unhell")) return do_unhell; if (!str_cmp (name, "do_unlock")) return do_unlock; if (!str_cmp (name, "do_unsilence")) return do_unsilence; if (!str_cmp (name, "do_up")) return do_up; if (!str_cmp (name, "do_users")) return do_users; break; case 'v': if (!str_cmp (name, "do_value")) return do_value; if (!str_cmp (name, "do_versio")) return do_versio; if (!str_cmp (name, "do_version")) return do_version; if (!str_cmp (name, "do_visible")) return do_visible; if (!str_cmp (name, "do_vnums")) return do_vnums; if (!str_cmp (name, "do_vsearch")) return do_vsearch; break; case 'w': if (!str_cmp (name, "do_wake")) return do_wake; if (!str_cmp (name, "do_wartalk")) return do_wartalk; if (!str_cmp (name, "do_wear")) return do_wear; if (!str_cmp (name, "do_weather")) return do_weather; if (!str_cmp (name, "do_west")) return do_west; if (!str_cmp (name, "do_where")) return do_where; if (!str_cmp (name, "do_who")) return do_who; if (!str_cmp (name, "do_whois")) return do_whois; if (!str_cmp (name, "do_wimpy")) return do_wimpy; if (!str_cmp (name, "do_wizhelp")) return do_wizhelp; if (!str_cmp (name, "do_wizlist")) return do_wizlist; if (!str_cmp (name, "do_wizlock")) return do_wizlock; break; case 'y': if (!str_cmp (name, "do_yell")) return do_yell; break; case 'z': if (!str_cmp (name, "do_zap")) return do_zap; if (!str_cmp (name, "do_zones")) return do_zones; } return skill_notfound; } char *skill_name (DO_FUN *skill) { if (skill == do_aassign) return "do_aassign"; if (skill == do_advance) return "do_advance"; if (skill == do_affected) return "do_affected"; if (skill == do_afk) return "do_afk"; if (skill == do_aid) return "do_aid"; if (skill == do_allow) return "do_allow"; if (skill == do_ansi) return "do_ansi"; if (skill == do_answer) return "do_answer"; if (skill == do_apply) return "do_apply"; if (skill == do_appraise) return "do_appraise"; if (skill == do_areas) return "do_areas"; if (skill == do_aset) return "do_aset"; if (skill == do_ask) return "do_ask"; if (skill == do_astat) return "do_astat"; if (skill == do_at) return "do_at"; if (skill == do_atmob) return "do_atmob"; if (skill == do_atobj) return "do_atobj"; if (skill == do_auction) return "do_auction"; if (skill == do_authorize) return "do_authorize"; if (skill == do_avtalk) return "do_avtalk"; if (skill == do_backstab) return "do_backstab"; if (skill == do_balzhur) return "do_balzhur"; if (skill == do_bamfin) return "do_bamfin"; if (skill == do_bamfout) return "do_bamfout"; if (skill == do_ban) return "do_ban"; if (skill == do_bash) return "do_bash"; if (skill == do_bashdoor) return "do_bashdoor"; if (skill == do_berserk) return "do_berserk"; if (skill == do_bestow) return "do_bestow"; if (skill == do_bestowarea) return "do_bestowarea"; if (skill == do_bio) return "do_bio"; if (skill == do_bite) return "do_bite"; if (skill == do_bloodlet) return "do_bloodlet"; if (skill == do_boards) return "do_boards"; if (skill == do_bodybag) return "do_bodybag"; if (skill == do_brandish) return "do_brandish"; if (skill == do_brew) return "do_brew"; if (skill == do_broach) return "do_broach"; if (skill == do_bset) return "do_bset"; if (skill == do_bstat) return "do_bstat"; if (skill == do_bug) return "do_bug"; if (skill == do_bury) return "do_bury"; if (skill == do_buy) return "do_buy"; if (skill == do_cast) return "do_cast"; if (skill == do_cedit) return "do_cedit"; if (skill == do_channels) return "do_channels"; if (skill == do_chat) return "do_chat"; if (skill == do_check_vnums) return "do_check_vnums"; if (skill == do_circle) return "do_circle"; if (skill == do_clans) return "do_clans"; if (skill == do_clantalk) return "do_clantalk"; if (skill == do_climb) return "do_climb"; if (skill == do_close) return "do_close"; if (skill == do_cmdtable) return "do_cmdtable"; if (skill == do_cmenu) return "do_cmenu"; if (skill == do_commands) return "do_commands"; if (skill == do_comment) return "do_comment"; if (skill == do_compare) return "do_compare"; if (skill == do_config) return "do_config"; if (skill == do_consider) return "do_consider"; if (skill == do_cook) return "do_cook"; if (skill == do_council_induct) return "do_council_induct"; if (skill == do_council_outcast) return "do_council_outcast"; if (skill == do_councils) return "do_councils"; if (skill == do_counciltalk) return "do_counciltalk"; if (skill == do_credits) return "do_credits"; if (skill == do_cset) return "do_cset"; if (skill == do_deities) return "do_deities"; if (skill == do_deny) return "do_deny"; if (skill == do_description) return "do_description"; if (skill == do_destro) return "do_destro"; if (skill == do_destroy) return "do_destroy"; if (skill == do_detrap) return "do_detrap"; if (skill == do_devote) return "do_devote"; if (skill == do_dig) return "do_dig"; if (skill == do_disarm) return "do_disarm"; if (skill == do_disconnect) return "do_disconnect"; if (skill == do_dismiss) return "do_dismiss"; if (skill == do_dismount) return "do_dismount"; if (skill == do_dmesg) return "do_dmesg"; if (skill == do_down) return "do_down"; if (skill == do_drag) return "do_drag"; if (skill == do_drink) return "do_drink"; if (skill == do_drop) return "do_drop"; if (skill == do_diagnose) return "do_diagnose"; if (skill == do_east) return "do_east"; if (skill == do_eat) return "do_eat"; if (skill == do_echo) return "do_echo"; if (skill == do_elevate) return "do_elevate"; if (skill == do_emote) return "do_emote"; if (skill == do_empty) return "do_empty"; if (skill == do_enter) return "do_enter"; if (skill == do_equipment) return "do_equipment"; if (skill == do_examine) return "do_examine"; if (skill == do_exits) return "do_exits"; if (skill == do_feed) return "do_feed"; if (skill == do_fill) return "do_fill"; if (skill == do_fire) return "do_fire"; if (skill == do_fixchar) return "do_fixchar"; if (skill == do_flee) return "do_flee"; if (skill == do_foldarea) return "do_foldarea"; if (skill == do_follow) return "do_follow"; if (skill == do_for) return "do_for"; if (skill == do_force) return "do_force"; if (skill == do_forceclose) return "do_forceclose"; if (skill == do_form_password) return "do_form_password"; if (skill == do_fprompt) return "do_fprompt"; if (skill == do_fquit) return "do_fquit"; if (skill == do_freeze) return "do_freeze"; if (skill == do_gfighting) return "do_gfighting"; if (skill == do_get) return "do_get"; if (skill == do_give) return "do_give"; if (skill == do_glance) return "do_glance"; if (skill == do_gold) return "do_gold"; if (skill == do_goto) return "do_goto"; if (skill == do_gouge) return "do_gouge"; if (skill == do_group) return "do_group"; if (skill == do_grub) return "do_grub"; if (skill == do_gtell) return "do_gtell"; if (skill == do_guilds) return "do_guilds"; if (skill == do_guildtalk) return "do_guildtalk"; if (skill == do_gwhere) return "do_gwhere"; if (skill == do_hedit) return "do_hedit"; if (skill == do_hell) return "do_hell"; if (skill == do_help) return "do_help"; if (skill == do_hide) return "do_hide"; if (skill == do_hitall) return "do_hitall"; if (skill == do_hlist) return "do_hlist"; if (skill == do_holylight) return "do_holylight"; if (skill == do_homepage) return "do_homepage"; if (skill == do_hset) return "do_hset"; if (skill == do_ide) return "do_ide"; if (skill == do_idea) return "do_idea"; if (skill == do_ignore) return "do_ignore"; if (skill == do_immortalize) return "do_immortalize"; if (skill == do_immtalk) return "do_immtalk"; if (skill == do_induct) return "do_induct"; if (skill == do_installarea) return "do_installarea"; if (skill == do_instaroom) return "do_instaroom"; if (skill == do_instazone) return "do_instazone"; if (skill == do_inventory) return "do_inventory"; if (skill == do_invis) return "do_invis"; if (skill == do_kick) return "do_kick"; if (skill == do_kill) return "do_kill"; if (skill == do_languages) return "do_languages"; if (skill == do_last) return "do_last"; if (skill == do_leave) return "do_leave"; if (skill == do_level) return "do_level"; if (skill == do_light) return "do_light"; if (skill == do_list) return "do_list"; if (skill == do_litterbug) return "do_litterbug"; if (skill == do_loadarea) return "do_loadarea"; if (skill == do_loadup) return "do_loadup"; if (skill == do_lock) return "do_lock"; if (skill == do_log) return "do_log"; if (skill == do_look) return "do_look"; if (skill == do_low_purge) return "do_low_purge"; if (skill == do_mailroom) return "do_mailroom"; if (skill == do_make) return "do_make"; if (skill == do_makeboard) return "do_makeboard"; if (skill == do_makeclan) return "do_makeclan"; if (skill == do_makecouncil) return "do_makecouncil"; if (skill == do_makedeity) return "do_makedeity"; if (skill == do_makeguild) return "do_makeguild"; if (skill == do_makeorder) return "do_makeorder"; if (skill == do_makerepair) return "do_makerepair"; if (skill == do_makeshop) return "do_makeshop"; if (skill == do_makewizlist) return "do_makewizlist"; if (skill == do_massign) return "do_massign"; if (skill == do_mcreate) return "do_mcreate"; if (skill == do_mdelete) return "do_mdelete"; if (skill == do_memory) return "do_memory"; if (skill == do_mfind) return "do_mfind"; if (skill == do_minvoke) return "do_minvoke"; if (skill == do_mistwalk) return "do_mistwalk"; if (skill == do_mlist) return "do_mlist"; if (skill == do_mmenu) return "do_mmenu"; if (skill == do_mount) return "do_mount"; if (skill == do_mp_close_passage) return "do_mp_close_passage"; if (skill == do_mp_damage) return "do_mp_damage"; if (skill == do_mp_deposit) return "do_mp_deposit"; if (skill == do_mp_open_passage) return "do_mp_open_passage"; if (skill == do_mp_practice) return "do_mp_practice"; if (skill == do_mp_restore) return "do_mp_restore"; if (skill == do_mp_slay) return "do_mp_slay"; if (skill == do_mp_withdraw) return "do_mp_withdraw"; if (skill == do_mpadvance) return "do_mpadvance"; if (skill == do_mpapply) return "do_mpapply"; if (skill == do_mpapplyb) return "do_mpapplyb"; if (skill == do_mpasound) return "do_mpasound"; if (skill == do_mpasupress) return "do_mpasupress"; if (skill == do_mpat) return "do_mpat"; if (skill == do_mpbodybag) return "do_mpbodybag"; if (skill == do_mpdream) return "do_mpdream"; if (skill == do_mpecho) return "do_mpecho"; if (skill == do_mpechoaround) return "do_mpechoaround"; if (skill == do_mpechoat) return "do_mpechoat"; if (skill == do_mpedit) return "do_mpedit"; if (skill == do_mpfavor) return "do_mpfavor"; if (skill == do_mpforce) return "do_mpforce"; if (skill == do_mpgoto) return "do_mpgoto"; if (skill == do_mpinvis) return "do_mpinvis"; if (skill == do_mpjunk) return "do_mpjunk"; if (skill == do_mpkill) return "do_mpkill"; if (skill == do_mpmload) return "do_mpmload"; if (skill == do_mpmset) return "do_mpmset"; if (skill == do_mpnothing) return "do_mpnothing"; if (skill == do_mpoload) return "do_mpoload"; if (skill == do_mposet) return "do_mposet"; if (skill == do_mppardon) return "do_mppardon"; if (skill == do_mppkset) return "do_mppkset"; if (skill == do_mppurge) return "do_mppurge"; if (skill == do_mpstat) return "do_mpstat"; if (skill == do_mptransfer) return "do_mptransfer"; if (skill == do_mrange) return "do_mrange"; if (skill == do_mset) return "do_mset"; if (skill == do_mstat) return "do_mstat"; if (skill == do_murde) return "do_murde"; if (skill == do_murder) return "do_murder"; if (skill == do_muse) return "do_muse"; if (skill == do_music) return "do_music"; if (skill == do_mwhere) return "do_mwhere"; if (skill == do_name) return "do_name"; if (skill == do_newbiechat) return "do_newbiechat"; if (skill == do_newbieset) return "do_newbieset"; if (skill == do_newzones) return "do_newzones"; if (skill == do_noemote) return "do_noemote"; if (skill == do_noresolve) return "do_noresolve"; if (skill == do_north) return "do_north"; if (skill == do_northeast) return "do_northeast"; if (skill == do_northwest) return "do_northwest"; if (skill == do_notell) return "do_notell"; if (skill == do_notitle) return "do_notitle"; if (skill == do_noteroom) return "do_noteroom"; if (skill == do_oassign) return "do_oassign"; if (skill == do_ocreate) return "do_ocreate"; if (skill == do_odelete) return "do_odelete"; if (skill == do_ofind) return "do_ofind"; if (skill == do_ogrub) return "do_ogrub"; if (skill == do_oinvoke) return "do_oinvoke"; if (skill == do_oldscore) return "do_oldscore"; if (skill == do_olist) return "do_olist"; if (skill == do_omenu) return "do_omenu"; if (skill == do_opedit) return "do_opedit"; if (skill == do_open) return "do_open"; /* if (skill == do_opentourney) return "do_opentourney"; */ if (skill == do_opstat) return "do_opstat"; if (skill == do_orange) return "do_orange"; if (skill == do_order) return "do_order"; if (skill == do_orders) return "do_orders"; if (skill == do_ordertalk) return "do_ordertalk"; if (skill == do_oset) return "do_oset"; if (skill == do_ostat) return "do_ostat"; if (skill == do_outcast) return "do_outcast"; if (skill == do_owhere) return "do_owhere"; if (skill == do_pagelen) return "do_pagelen"; if (skill == do_pager) return "do_pager"; if (skill == do_pardon) return "do_pardon"; if (skill == do_password) return "do_password"; if (skill == do_pcrename) return "do_pcrename"; if (skill == do_peace) return "do_peace"; if (skill == do_pick) return "do_pick"; if (skill == do_pmenu) return "do_pmenu"; if (skill == do_poison_weapon) return "do_poison_weapon"; if (skill == do_practice) return "do_practice"; if (skill == do_prompt) return "do_prompt"; if (skill == do_pull) return "do_pull"; if (skill == do_punch) return "do_punch"; if (skill == do_purge) return "do_purge"; if (skill == do_push) return "do_push"; if (skill == do_put) return "do_put"; if (skill == do_qpset) return "do_qpset"; if (skill == do_quaff) return "do_quaff"; if (skill == do_quest) return "do_quest"; if (skill == do_qui) return "do_qui"; if (skill == do_quit) return "do_quit"; if (skill == do_racetalk) return "do_racetalk"; if (skill == do_rank) return "do_rank"; if (skill == do_rap) return "do_rap"; if (skill == do_rassign) return "do_rassign"; if (skill == do_rat) return "do_rat"; if (skill == do_rdelete) return "do_rdelete"; if (skill == do_reboo) return "do_reboo"; if (skill == do_reboot) return "do_reboot"; if (skill == do_recho) return "do_recho"; if (skill == do_recite) return "do_recite"; if (skill == do_redit) return "do_redit"; if (skill == do_regoto) return "do_regoto"; if (skill == do_remains) return "do_remains"; if (skill == do_remove) return "do_remove"; if (skill == do_rent) return "do_rent"; if (skill == do_repair) return "do_repair"; if (skill == do_repairset) return "do_repairset"; if (skill == do_repairshops) return "do_repairshops"; if (skill == do_repairstat) return "do_repairstat"; if (skill == do_reply) return "do_reply"; if (skill == do_report) return "do_report"; if (skill == do_rescue) return "do_rescue"; if (skill == do_reserve) return "do_reserve"; if (skill == do_reset) return "do_reset"; if (skill == do_rest) return "do_rest"; if (skill == do_restore) return "do_restore"; if (skill == do_restoretime) return "do_restoretime"; if (skill == do_restrict) return "do_restrict"; if (skill == do_retire) return "do_retire"; if (skill == do_retran) return "do_retran"; if (skill == do_return) return "do_return"; if (skill == do_revert) return "do_revert"; if (skill == do_rip) return "do_rip"; if (skill == do_rlist) return "do_rlist"; if (skill == do_rmenu) return "do_rmenu"; if (skill == do_rpedit) return "do_rpedit"; if (skill == do_rpstat) return "do_rpstat"; if (skill == do_rreset) return "do_rreset"; if (skill == do_rset) return "do_rset"; if (skill == do_rstat) return "do_rstat"; if (skill == do_sacrifice) return "do_sacrifice"; if (skill == do_save) return "do_save"; if (skill == do_savearea) return "do_savearea"; if (skill == do_say) return "do_say"; if (skill == do_scan) return "do_scan"; if (skill == do_score) return "do_score"; if (skill == do_scribe) return "do_scribe"; if (skill == do_search) return "do_search"; if (skill == do_sedit) return "do_sedit"; if (skill == do_sell) return "do_sell"; if (skill == do_set_boot_time) return "do_set_boot_time"; if (skill == do_setclan) return "do_setclan"; if (skill == do_setclass) return "do_setclass"; if (skill == do_setcouncil) return "do_setcouncil"; if (skill == do_setdeity) return "do_setdeity"; if (skill == do_setguild) return "do_setguild"; if (skill == do_setorder) return "do_setorder"; if (skill == do_setrace) return "do_setrace"; if (skill == do_shops) return "do_shops"; if (skill == do_shopset) return "do_shopset"; if (skill == do_shopstat) return "do_shopstat"; if (skill == do_shout) return "do_shout"; if (skill == do_shove) return "do_shove"; if (skill == do_showclan) return "do_showclan"; if (skill == do_showclass) return "do_showclass"; if (skill == do_showcouncil) return "do_showcouncil"; if (skill == do_showdeity) return "do_showdeity"; if (skill == do_showguild) return "do_showguild"; if (skill == do_showorder) return "do_showorder"; if (skill == do_showrace) return "do_showrace"; if (skill == do_showbytes) return "do_showbytes"; if (skill == do_shutdow) return "do_shutdow"; if (skill == do_shutdown) return "do_shutdown"; if (skill == do_silence) return "do_silence"; if (skill == do_sit) return "do_sit"; if (skill == do_sla) return "do_sla"; if (skill == do_slay) return "do_slay"; if (skill == do_sleep) return "do_sleep"; if (skill == do_slice) return "do_slice"; if (skill == do_slist) return "do_slist"; if (skill == do_slookup) return "do_slookup"; if (skill == do_smoke) return "do_smoke"; if (skill == do_snoop) return "do_snoop"; if (skill == do_sober) return "do_sober"; if (skill == do_socials) return "do_socials"; if (skill == do_south) return "do_south"; if (skill == do_southeast) return "do_southeast"; if (skill == do_southwest) return "do_southwest"; if (skill == do_speak) return "do_speak"; if (skill == do_split) return "do_split"; if (skill == do_sset) return "do_sset"; if (skill == do_stand) return "do_stand"; if (skill == do_stat) return "do_stat"; if (skill == do_statreport) return "do_statreport"; if (skill == do_steal) return "do_steal"; if (skill == do_stun) return "do_stun"; if (skill == do_style) return "do_style"; if (skill == do_supplicate) return "do_supplicate"; if (skill == do_switch) return "do_switch"; if (skill == do_tamp) return "do_tamp"; if (skill == do_tell) return "do_tell"; if (skill == do_think) return "do_think"; if (skill == do_time) return "do_time"; if (skill == do_timecmd) return "do_timecmd"; if (skill == do_title) return "do_title"; if (skill == do_track) return "do_track"; if (skill == do_transfer) return "do_transfer"; if (skill == do_trust) return "do_trust"; if (skill == do_typo) return "do_typo"; if (skill == do_unfoldarea) return "do_unfoldarea"; if (skill == do_unhell) return "do_unhell"; if (skill == do_unlock) return "do_unlock"; if (skill == do_unsilence) return "do_unsilence"; if (skill == do_up) return "do_up"; if (skill == do_users) return "do_users"; if (skill == do_value) return "do_value"; if (skill == do_versio) return "do_versio"; if (skill == do_version) return "do_version"; if (skill == do_visible) return "do_visible"; if (skill == do_vnums) return "do_vnums"; if (skill == do_vsearch) return "do_vsearch"; if (skill == do_wake) return "do_wake"; if (skill == do_wartalk) return "do_wartalk"; if (skill == do_wear) return "do_wear"; if (skill == do_weather) return "do_weather"; if (skill == do_west) return "do_west"; if (skill == do_where) return "do_where"; if (skill == do_who) return "do_who"; if (skill == do_whois) return "do_whois"; if (skill == do_wimpy) return "do_wimpy"; if (skill == do_wizhelp) return "do_wizhelp"; if (skill == do_wizlist) return "do_wizlist"; if (skill == do_wizlock) return "do_wizlock"; if (skill == do_yell) return "do_yell"; if (skill == do_zap) return "do_zap"; if (skill == do_zones) return "do_zones"; return "reserved"; } int CSkillTable::GetSaveEffectFromName (const char* n) { for (int i=0; i < DIM (SpellSaveEffectNames); ++i) if (! str_cmp (n, SpellSaveEffectNames [i])) return i; return -1; } // New check to see if you can use skills to support morphs --Shaddai BOOL can_use_skill (CCharacter* ch, int percent, int gsn) { if (ch->IsNpc () && percent < 85) return TRUE; if (! ch->IsNpc () && percent < ch->GetLearnedPercent (gsn)) return TRUE; // 1.4add // if (ch->morph && ch->morph->morph && ch->morph->morph->skills && // ch->morph->morph->skills [0] != '\0' && // is_name (SkillTable.GetName (gsn), ch->morph->morph->skills) && // percent < 85) // return TRUE; // // if (! (ch->morph && ch->morph->morph && ch->morph->morph->no_skills && // ch->morph->morph->no_skills [0] != '\0' && // is_name (skillTable.GetName (gsn), ch->morph->morph->no_skills))) // return TRUE; return FALSE; } // Cook was coded by Blackmane and heavily modified by Shaddai void do_cook (CCharacter* ch, char* argument) { char arg [MAX_INPUT_LENGTH]; char buf [MAX_STRING_LENGTH]; one_argument (argument, arg); if (ch->IsNpc () || ch->GetLevel () < SkillTable.GetClassLevel (gsn_cook, ch->GetClass ())) { ch->SendText ("That skill is beyond your understanding.\n\r"); return; } if (arg [0] == '\0') { ch->SendText ("Cook what?\n\r"); return; } if (ms_find_obj (ch)) return; CObjData *pFood = get_obj_carry (ch, arg); if (! pFood) { ch->SendText ("You do not have that item.\n\r"); return; } if (pFood->item_type != ITEM_COOK) { ch->SendText ("How can you cook that?\n\r"); return; } if (pFood->value [2] > 2) { ch->SendText ("That is already burnt to a crisp.\n\r"); return; } CObjData *pFire = NULL; POSITION pos = ch->GetInRoom ()->GetHeadContentPos (); while (pFire = ch->GetInRoom ()->GetNextContent (pos)) if (pFire->item_type == ITEM_FIRE) break; if (! pFire ) { ch->SendText ("There is no fire here!\n\r"); return; } if (number_percent () > ch->GetPcData ()->learned [gsn_cook]) { pFood->timer /= 2; pFood->value [0] = 0; pFood->value [2] = 3; act (AT_MAGIC, "$p catches on fire burning it to a crisp!\n\r", ch, pFood, NULL, TO_CHAR); act (AT_MAGIC, "$n catches $p on fire burning it to a crisp.", ch, pFood, NULL, TO_ROOM); sprintf (buf, "a burnt %s", pFood->pIndexData->GetName ()); pFood->SetShortDescr (buf); sprintf (buf, "A burnt %s.", pFood->pIndexData->GetName ()); pFood->SetDescription (buf); return; } if (number_percent() > 85) { pFood->timer *= 3; pFood->value [2] += 2; act (AT_MAGIC, "$n overcooks a $p.", ch, pFood, NULL, TO_ROOM); act (AT_MAGIC, "You overcook a $p.", ch, pFood, NULL, TO_CHAR); sprintf (buf, "an overcooked %s", pFood->pIndexData->GetName ()); pFood->SetShortDescr (buf); sprintf (buf, "An overcooked %s.", pFood->pIndexData->GetName ()); pFood->SetDescription (buf); } else { pFood->timer *= 4; pFood->value [0] *= 2; act (AT_MAGIC, "$n roasts a $p.", ch, pFood, NULL, TO_ROOM); act (AT_MAGIC, "You roast a $p.", ch, pFood, NULL, TO_CHAR); sprintf (buf, "a roasted %s", pFood->pIndexData->GetName ()); pFood->SetShortDescr (buf); sprintf (buf, "A roasted %s.", pFood->pIndexData->GetName ()); pFood->SetDescription (buf); ++pFood->value [2]; } learn_from_success (ch, gsn_cook); } // Function to strip off the "a" or "an" or "the" or "some" from an object's // short description for the purpose of using it in a sentence sent to // the owner of the object. (Ie: an object with the short description // "a long dark blade" would return "long dark blade" for use in a sentence // like "Your long dark blade". The object name isn't always appropriate // since it contains keywords that may not look proper. -Thoric char *myobj (CObjData *obj) { int offset = 0; if (! str_prefix ("a ", obj->GetShortDescr ())) offset = 2; else if (! str_prefix ("an ", obj->GetShortDescr ())) offset = 3; else if (! str_prefix ("the ", obj->GetShortDescr ())) offset = 4; else if (! str_prefix ("some ", obj->GetShortDescr ())) offset = 5; return NCCP (obj->GetShortDescr () + offset); }