/**************************************************************************** * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// * * -----------------------------------------------------------| (0...0) * * SMAUG 1.0 (C) 1994, 1995, 1996 by Derek Snider | ).:.( * * -----------------------------------------------------------| {o o} * * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ * * Scryn, Rennard, Swordbearer, Gorog, Grishnakh and Tricops |~'~.VxvxV.~'~* * ------------------------------------------------------------------------ * * 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 St{rfeldt, Tom Madsen, and Katja Nyboe. * * ------------------------------------------------------------------------ * * Player skills module * ****************************************************************************/ /*static char rcsid[] = "$Id: skills.c,v 1.64 2004/04/06 22:00:11 dotd Exp $";*/ #include <sys/types.h> #include <stdio.h> #include <string.h> #include <time.h> #include <ctype.h> #include "mud.h" #include "gsn.h" DECLARE_DO_FUN(do_steal); DECLARE_DO_FUN(do_gossip); DECLARE_DO_FUN(do_look); DECLARE_DO_FUN(do_recall); DECLARE_DO_FUN(do_shout); DECLARE_DO_FUN(do_cast); const char *att_kick_kill_ch[] = { "Your kick caves $N's chest in, killing $M instantly.", "Your kick destroys $N's arm and caves in one side of $S rib cage.", "Your kick smashes through $N's leg and into $S pelvis, killing $M.", "Your kick shatters $N's skull.", "Your kick at $N's snout shatters $S jaw, killing $M.", "You kick $N in the rump with such force that $E keels over dead.", "You kick $N in the belly, mangling several ribs and killing $M instantly.", "$N's scales cave in as your mighty kick kills $N.", "Your kick rips bark asunder and leaves fly everywhere, killing the $N.", "Bits of $N are sent flying as you kick him to pieces.", "You punt $N across the room, $E lands in a heap of broken flesh.", "You kick $N in the groin, $E dies screaming an octave higher.", "", /* GHOST */ "Feathers fly about as you blast $N to pieces with your kick.", "Your kick splits $N to pieces, rotting flesh flies everywhere.", "Your kick topples $N over, killing it.", "Your foot shatters cartilage, sending bits of $N everywhere.", "You launch a mighty kick at $N's gills, killing it.", "Your kick at $N sends $M to the grave.", "." }; const char *att_kick_kill_victim[] = { "$n crushes you beneath $s foot, killing you.", "$n destroys your arm and half your ribs. You die.", "$n neatly splits your groin in two, you collapse and die instantly.", "$n splits your head in two, killing you instantly.", "$n forces your jaw into the lower part of your brain.", "$n kicks you from behind, snapping your spine and killing you.", "$n kicks your stomach and you into the great land beyond!!", "Your scales are no defense against $n's mighty kick.", "$n rips you apart with a massive kick, you die in a flutter of leaves.", "You are torn to little pieces as $n splits you with $s kick.", "$n's kick sends you flying, you die before you land.", "Puny little $n manages to land a killing blow to your groin, OUCH!", "", /* GHOST */ "Your feathers fly about as $n pulverizes you with a massive kick.", "$n's kick rips your rotten body into shreds, and your various pieces die.", "$n kicks you so hard, you fall over and die.", "$n shatters your exoskeleton, you die.", "$n kicks you in the gills! You cannot breath..... you die!.", "$n sends you to the grave with a mighty kick.", "." }; const char *att_kick_kill_room[] = { "$n strikes $N in chest, shattering the ribs beneath it.", "$n kicks $N in the side, destroying $S arm and ribs.", "$n nails $N in the groin, the pain killing $M.", "$n shatters $N's head, reducing $M to a twitching heap!", "$n blasts $N in the snout, destroying bones and causing death.", "$n kills $N with a massive kick to the rear.", "$n sends $N to the grave with a massive blow to the stomach!", "$n ignores $N's scales and kills $M with a mighty kick.", "$n sends bark and leaves flying as $e splits $N in two.", "$n blasts $N to pieces with a ferocious kick.", "$n sends $N flying, $E lands with a LOUD THUD, making no other noise.", "$N falls to the ground and dies clutching $S crotch due to $n's kick.", "", /* GHOST */ "$N disappears into a cloud of feathers as $n kicks $M to death.", "$n blasts $N's rotten body into pieces with a powerful kick.", "$n kicks $N so hard, it falls over and dies.", "$n blasts $N's exoskeleton to little fragments.", "$n kicks $N in the gills, killing it.", "$n sends $N to the grave with a mighty kick.", "." }; const char *att_kick_miss_ch[] = { "$N steps back, and your kick misses $M.", "$N deftly blocks your kick with $S forearm.", "$N dodges, and you miss your kick at $S legs.", "$N ducks, and your foot flies a mile high.", "$N steps back and grins evilly as your foot flys by $S face.", "$N laughs at your feeble attempt to kick $M from behind.", "Your kick at $N's belly makes it laugh.", "$N chuckles as your kick bounces off $S tough scales.", "You kick $N in the side, denting your foot.", "Your sloppy kick is easily avoided by $N.", "You misjudge $N's height and kick well above $S head.", "You stub your toe against $N's shin as you try to kick $M.", "Your kick passes through $N!!", /* Ghost */ "$N nimbly flitters away from your kick.", "$N sidesteps your kick and sneers at you.", "Your kick bounces off $N's leathery hide.", "Your kick bounces off $N's tough exoskeleton.", "$N deflects your kick with a fin.", "$N avoids your paltry attempt at a kick.", "." }; const char *att_kick_miss_victim[] = { "$n misses you with $s clumsy kick at your chest.", "You block $n's feeble kick with your arm.", "You dodge $n's feeble leg sweep.", "You duck under $n's lame kick.", "You step back and grin as $n misses your face with a kick.", "$n attempts a feeble kick from behind, which you neatly avoid.", "You laugh at $n's feeble attempt to kick you in the stomach.", "$n kicks you, but your scales are much too tough for that wimp.", "You laugh as $n dents $s foot on your bark.", "You easily avoid a sloppy kick from $n.", "$n's kick parts your hair but does little else.", "$n's light kick to your shin bearly gets your attention.", "$n passes through you with $s puny kick.", "You nimbly flitter away from $n's kick.", "You sneer as you sidestep $n's kick.", "$n's kick bounces off your tough hide.", "$n tries to kick you, but your too tough.", "$n tried to kick you, but you deflected it with a fin.", "You avoid $n's feeble attempt to kick you.", "." }; const char *att_kick_miss_room[] = { "$n misses $N with a clumsy kick.", "$N blocks $n's kick with $S arm.", "$N easily dodges $n's feeble leg sweep.", "$N easily ducks under $n's lame kick.", "$N steps back and grins evilly at $n's feeble kick to $S face misses.", "$n launches a kick at $N's behind, but fails miserably.", "$N laughs at $n's attempt to kick $M in the stomach.", "$n tries to kick $N, but $s foot bounces off of $N's scales.", "$n hurts his foot trying to kick $N.", "$N avoids a lame kick launched by $n.", "$n misses a kick at $N due to $S small size.", "$n misses a kick at $N's groin, stubbing $s toe in the process.", "$n's foot goes right through $N!!!!", "$N flitters away from $n's kick.", "$N sneers at $n while sidestepping $s kick.", "$N's tough hide deflects $n's kick.", "$n hurts $s foot on $N's tough exterior.", "$n tries to kick $N, but is thwarted by a fin.", "$N avoids $n's feeble kick.", "." }; const char *att_kick_hit_ch[] = { "Your kick crashes into $N's chest.", "Your kick hits $N in the side.", "You hit $N in the thigh with a hefty sweep.", "You hit $N in the face, sending $M reeling.", "You plant your foot firmly in $N's snout, smashing it to one side.", "You nail $N from behind, sending him reeling.", "You kick $N in the stomach, winding $M.", "You find a soft spot in $N's scales and launch a solid kick there.", "Your kick hits $N, sending small branches and leaves everywhere.", "Your kick contacts with $N, dislodging little pieces of $M.", "Your kick hits $N right in the stomach, $N is rendered breathless.", "You stomp on $N's foot. After all, thats about all you can do to a giant.", "", /* GHOST */ "Your kick sends $N reeling through the air.", "You kick $N and feel rotten bones crunch from the blow.", "You smash $N with a hefty roundhouse kick.", "You kick $N, cracking it's exoskeleton.", "Your mighty kick rearranges $N's scales.", "You leap off the ground and crash into $N with a powerful kick.", "." }; const char *att_kick_hit_victim[] = { "$n's kick crashes into your chest.", "$n's kick hits you in your side.", "$n's sweep catches you in the side and you almost stumble.", "$n hits you in the face, gee, what pretty colors...", "$n kicks you in the snout, smashing it up against your face.", "$n blasts you in the rear, ouch!", "Your breath rushes from you as $n kicks you in the stomach.", "$n finds a soft spot on your scales and kicks you, ouch!", "$n kicks you hard, sending leaves flying everywhere!", "$n kicks you in the side, dislodging small parts of you.", "You suddenly see $n's foot in your chest.", "$n lands a kick hard on your foot making you jump around in pain.", "", /* GHOST */ "$n kicks you, and you go reeling through the air.", "$n kicks you and your bones crumble.", "$n hits you in the flank with a hefty roundhouse kick.", "$n ruins some of your scales with a well placed kick.", "$n leaps off of the grand and crashes into you with $s kick.", "." }; const char *att_kick_hit_room[] = { "$n hits $N with a mighty kick to $S chest.", "$n whacks $N in the side with a sound kick.", "$n almost sweeps $N off of $S feet with a well placed leg sweep.", "$N's eyes roll as $n plants a foot in $S face.", "$N's snout is smashed as $n relocates it with $s foot.", "$n hits $N with an impressive kick from behind.", "$N gasps as $n kick $N in the stomach.", "$n finds a soft spot in $N's scales and launches a solid kick there.", "$n kicks $N. Leaves fly everywhere!!", "$n hits $N with a mighty kick, $N loses parts of $Mself.", "$n kicks $N in the stomach, $N is rendered breathless.", "$n kicks $N in the foot, $N hops around in pain.", "", /* GHOST */ "$n sends $N reeling through the air with a mighty kick.", "$n kicks $N causing parts of $N to cave in!", "$n kicks $N in the side with a hefty roundhouse kick.", "$n kicks $N, cracking exo-skelelton.", "$n kicks $N hard, sending scales flying!", "$n leaps up and nails $N with a mighty kick.", "." }; char * const spell_flag[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "water", "earth", "air", "astral", "area", "distant", "reverse", "save_half_dam", "save_negates", "accumulative", "recastable", "noscribe", "nobrew", "group", "object", "character", "secretskill", "pksensitive", "stoponfail", "verbalize_skill", "requires_forge" }; char * const spell_save[] = { "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_ch_class[] = { "none", "lunar", "solar", "travel", "summon", "life", "death", "illusion", "curse" }; char * const target_type[] = { "ignore", "offensive", "defensive", "self", "objinv", "objroom"}; void show_char_to_char( CHAR_DATA *list, CHAR_DATA *ch ); int ris_save( CHAR_DATA *ch, int chance, int ris ); bool check_illegal_psteal( CHAR_DATA *ch, CHAR_DATA *victim ); /* from magic.c */ void failed_casting( SKILLTYPE *skill, CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA *obj ); /* * Dummy function */ void skill_notfound( CHAR_DATA *ch, char *argument ) { send_to_char( "Huh?\n\r", ch ); return; } int get_starget( char *name ) { unsigned int x; for ( x = 0; x < sizeof(target_type) / sizeof(target_type[0]); x++ ) if ( !str_cmp( name, target_type[x] ) ) return x; return -1; } int get_sflag( char *name ) { unsigned int x; for ( x = 0; x < sizeof(spell_flag) / sizeof(spell_flag[0]); x++ ) if ( !str_cmp( name, spell_flag[x] ) ) return x; return -1; } int get_sdamage( char *name ) { unsigned int x; for ( x = 0; x < sizeof(spell_damage) / sizeof(spell_damage[0]); x++ ) if ( !str_cmp( name, spell_damage[x] ) ) return x; return -1; } int get_saction( char *name ) { unsigned int x; for ( x = 0; x < sizeof(spell_action) / sizeof(spell_action[0]); x++ ) if ( !str_cmp( name, spell_action[x] ) ) return x; return -1; } int get_spower( char *name ) { unsigned int x; for ( x = 0; x < sizeof(spell_power) / sizeof(spell_power[0]); x++ ) if ( !str_cmp( name, spell_power[x] ) ) return x; return -1; } int get_ssave( char *name ) { unsigned int x; for ( x = 0; x < sizeof(spell_save) / sizeof(spell_save[0]); x++ ) if ( !str_cmp( name, spell_save[x] ) ) return x; return -1; } int get_sch_class( char *name ) { unsigned int x; for ( x = 0; x < sizeof(spell_ch_class) / sizeof(spell_ch_class[0]); x++ ) if ( !str_cmp( name, spell_ch_class[x] ) ) return x; return -1; } bool is_legal_kill(CHAR_DATA *ch, CHAR_DATA *vch) { if ( IS_NPC(ch) || IS_NPC(vch) ) return TRUE; if ( !IS_PKILL(ch) || !IS_PKILL(vch) ) return FALSE; if ( ch->pcdata->clan && ch->pcdata->clan == vch->pcdata->clan ) 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( CHAR_DATA *ch, char *command, char *argument ) { int sn; int max=0; sh_int cl; int first = gsn_first_skill; int top = GSN_LAST_SKILL; int mana, blood; struct timeval time_used; char tempstr[MAX_INPUT_LENGTH]; /* bsearch for the skill */ for (;;) { sn = (first + top) >> 1; if ( LOWER(command[0]) == LOWER(skill_table[sn]->name[0]) && !str_prefix(command, skill_table[sn]->name) && (skill_table[sn]->skill_fun || skill_table[sn]->spell_fun != spell_null) && ((IS_NPC(ch) && !IS_SET(ch->act, ACT_POLYMORPHED)) || (LEARNED(ch, sn) > 0 && CanUseSkill(ch, sn))) ) break; if (first >= top) return FALSE; if (strcmp( command, skill_table[sn]->name) < 1) top = sn - 1; else first = sn + 1; } if ( !check_pos( ch, skill_table[sn]->minimum_position ) ) return TRUE; if ( IS_NPC(ch) && (IS_AFFECTED( ch, AFF_CHARM ) || IS_AFFECTED( ch, AFF_POSSESS )) ) { send_to_char( "For some reason, you seem unable to perform that...\n\r", ch ); act( AT_GREY,"$n wanders around aimlessly.", ch, NULL, NULL, TO_ROOM ); return TRUE; } /* check if mana is required */ if ( skill_table[sn]->min_mana ) { mana = IS_NPC(ch) ? 0 : UMAX(skill_table[sn]->min_mana, 100 / (UMAX(2,(2 + ch->levels[LowSkCl(ch, sn)]) - LowSkLv(ch, sn)) ) ); blood = UMAX(1, (mana+4) / 8); /* NPCs don't have PCDatas. -- Altrag */ if ( IS_VAMPIRE(ch) ) { if (GET_COND(ch, COND_BLOODTHIRST) < blood) { send_to_char( "You don't have enough blood power.\n\r", ch ); return TRUE; } } else if ( !IS_NPC(ch) && GET_MANA(ch) < mana ) { send_to_char( "You don't have enough mana.\n\r", ch ); return TRUE; } } else { mana = 0; blood = 0; } /* * Is this a real do-fun, or a really a spell? */ if ( !skill_table[sn]->skill_fun ) { ch_ret retcode = rNONE; void *vo = NULL; CHAR_DATA *victim = NULL; OBJ_DATA *obj = NULL; target_name = ""; switch ( skill_table[sn]->target ) { default: bug( "Check_skill: bad target for sn %d.", sn ); send_to_char( "Something went wrong...\n\r", ch ); return TRUE; case TAR_IGNORE: vo = NULL; if ( argument[0] == '\0' ) { if ( (victim=who_fighting(ch)) != NULL ) target_name = victim->name; } else target_name = argument; break; case TAR_CHAR_OFFENSIVE: if ( argument[0] == '\0' && (victim=who_fighting(ch)) == NULL ) { ch_printf( ch, "%s who?\n\r", capitalize( skill_table[sn]->name ) ); return TRUE; } else if ( argument[0] != '\0' && (victim=get_char_room(ch, argument)) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return TRUE; } if ( is_safe( ch, victim ) ) return TRUE; vo = (void *) victim; break; case TAR_CHAR_DEFENSIVE: if ( argument[0] != '\0' && (victim=get_char_room(ch, argument)) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return TRUE; } if ( !victim ) victim = ch; vo = (void *) victim; break; case TAR_CHAR_SELF: if ( !victim ) victim = ch; vo = (void *) ch; break; case TAR_OBJ_INV: if ( (obj=get_obj_carry(ch, argument)) == NULL ) { send_to_char( "You can't find that.\n\r", ch ); return TRUE; } vo = (void *) obj; break; } /* waitstate */ spell_lag(ch, sn); /* check for failure */ /* check for anti eq and give penalty must like cast does */ for (cl = FIRST_CLASS; cl < MAX_CLASS; cl++) { if (!IS_ACTIVE(ch, cl)) continue; switch (cl) { case CLASS_NONE: case LAST_CLASS: break; case CLASS_MAGE: case CLASS_SORCERER: if (EqWBits(ch, ITEM_ANTI_MAGE)) max += 5; break; case CLASS_NECROMANCER: if (EqWBits2(ch, ITEM2_ANTI_NECROMANCER)) max += 5; break; case CLASS_CLERIC: if (EqWBits(ch, ITEM_ANTI_CLERIC)) max += 5; break; case CLASS_DRUID: if (EqWBits(ch, ITEM_ANTI_DRUID)) max += 5; break; case CLASS_PALADIN: if (EqWBits2(ch, ITEM2_ANTI_PALADIN)) max += 10; break; case CLASS_ANTIPALADIN: if (EqWBits2(ch, ITEM2_ANTI_APALADIN)) max += 10; break; case CLASS_PSIONIST: if (EqWBits2(ch, ITEM2_ANTI_PSI)) max += 10; break; case CLASS_RANGER: if (EqWBits2(ch, ITEM2_ANTI_RANGER)) max += 10; break; case CLASS_VAMPIRE: if (EqWBits(ch, ITEM_ANTI_VAMPIRE)) max += 5; break; case CLASS_ARTIFICER: if (EqWBits2(ch, ITEM2_ANTI_ARTIFICER)) max += 5; break; case CLASS_MONK: if (EqWBits2(ch, ITEM2_ANTI_MONK)) max += 10; break; case CLASS_THIEF: if (EqWBits(ch, ITEM_ANTI_THIEF)) max += 10; break; case CLASS_AMAZON: if (EqWBits2(ch, ITEM2_ANTI_AMAZON)) max += 10; break; case CLASS_WARRIOR: if (EqWBits(ch, ITEM_ANTI_WARRIOR)) max += 10; break; case CLASS_BARBARIAN: if (EqWBits2(ch, ITEM2_ANTI_BARBARIAN)) max += 10; break; } } if (max > 0 && GetMaxLevel(ch)<5) send_to_char("Note: You are wearing anti-class eq, removing it will improve your skill ability.\n\r(This message will self-destruct when you reach level 5)\n\r", ch); max += skill_table[sn]->difficulty * 5; if (!IS_NPC(ch)) log_printf_plus(LOG_DEBUG, LEVEL_IMMORTAL, SEV_DEBUG, "check_skill: %s skillfail: %d sn: %d", GET_NAME(ch), max, sn); if ( (number_percent( ) + max) > LEARNED(ch, sn) ) { failed_casting( skill_table[sn], ch, victim, obj ); learn_from_failure( ch, sn ); if ( mana ) { if ( IS_VAMPIRE(ch) ) gain_condition( ch, COND_BLOODTHIRST, - blood ); else GET_MANA(ch) -= mana; } return TRUE; } if ( mana ) { if ( IS_VAMPIRE(ch) ) gain_condition( ch, COND_BLOODTHIRST, - (blood >> 1) ); else GET_MANA(ch) -= (mana >> 1); } start_timer(&time_used); retcode = (*skill_table[sn]->spell_fun) ( sn, ch->levels[BestSkCl(ch, sn)], ch, vo ); end_timer(&time_used); update_userec(&time_used, &skill_table[sn]->userec); 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 ( skill_table[sn]->target == TAR_CHAR_OFFENSIVE && victim != ch && !char_died(victim) ) { CHAR_DATA *vch; CHAR_DATA *vch_next; for ( vch = ch->in_room->first_person; vch; vch = vch_next ) { vch_next = vch->next_in_room; if ( victim == vch && !victim->fighting && victim->master != ch ) { retcode = multi_hit( victim, ch, TYPE_UNDEFINED ); break; } } } return TRUE; } if ( mana ) { if ( IS_VAMPIRE(ch) ) gain_condition( ch, COND_BLOODTHIRST, - (blood >> 1) ); else GET_MANA(ch) -= (mana >> 1); } ch->prev_cmd = ch->last_cmd; /* haus, for automapping */ ch->last_cmd = skill_table[sn]->skill_fun; start_timer(&time_used); if (skill_table[sn]->skill_fun!=do_smaug_skill) (*skill_table[sn]->skill_fun) ( ch, argument ); else { sprintf(tempstr, "%s %s", skill_table[sn]->name, argument); (*skill_table[sn]->skill_fun) ( ch, tempstr ); } end_timer(&time_used); update_userec(&time_used, &skill_table[sn]->userec); tail_chain( ); return TRUE; } /* * Lookup a skills information * High god command */ void do_slookup( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; char arg[MAX_INPUT_LENGTH]; int sn; int iClass; int type; SKILLTYPE *skill = NULL; char s1[16], s2[16], s3[16], s4[16]; buf[0] = '\0'; arg[0] = '\0'; strcpy(arg, argument); if ( arg[0] == '\0' ) { send_to_char( "Slookup what?\n\r" " slookup all\n\r slookup null\n\r slookup smaug\n\r" " slookup herbs\n\r slookup lore\n\r slookup tongue\n\r" " slookup <class>\n\r slookup slots\n\r", ch ); return; } sprintf(s1, "%s", color_str(AT_SCORE, ch)); sprintf(s2, "%s", color_str(AT_SCORE2, ch)); sprintf(s3, "%s", color_str(AT_SCORE3, ch)); sprintf(s4, "%s", color_str(AT_SCORE4, ch)); if ( !str_cmp( arg, "all" ) ) { for ( sn = 0; sn < top_sn && skill_table[sn] && skill_table[sn]->name; sn++ ) pager_printf( ch, "Sn: %3d Slot: %3d Name: '%-24s' Damtype: %s\n\r", sn, skill_table[sn]->slot, skill_table[sn]->name, spell_damage[SPELL_DAMAGE( skill_table[sn] )] ); } else if ( !str_cmp( arg, "null" ) ) { int num=0; for ( sn = 0; sn < top_sn && skill_table[sn] && skill_table[sn]->name; sn++ ) if ((skill_table[sn]->skill_fun==skill_notfound || skill_table[sn]->skill_fun==NULL) && (skill_table[sn]->spell_fun==spell_notfound || skill_table[sn]->spell_fun==spell_null) && skill_table[sn]->type != SKILL_LORE && skill_table[sn]->type != SKILL_TONGUE) { pager_printf( ch, "Sn: %3d Slot: %3d Name: '%-24s' Damtype: %s\n\r", sn, skill_table[sn]->slot, skill_table[sn]->name, spell_damage[SPELL_DAMAGE( skill_table[sn] )] ); num++; } pager_printf(ch, "%d matches found.\n\r", num); } else if ( (type = get_skill_tname(arg)) ) { int num=0; for ( sn = 0; sn < top_sn && skill_table[sn] && skill_table[sn]->name; sn++ ) if (skill_table[sn]->type == type) { pager_printf( ch, "Sn: %3d Slot: %3d Name: '%-24s'\n\r", sn, skill_table[sn]->slot, skill_table[sn]->name ); num++; } pager_printf(ch, "%d matches found.\n\r", num); } else if ( (iClass = get_classtype(arg)) != CLASS_NONE ) { int num=0; for ( sn = 0; sn < top_sn && skill_table[sn] && skill_table[sn]->name; sn++ ) if (skill_table[sn]->skill_level[iClass] < LEVEL_IMMORTAL) { pager_printf( ch, "Sn: %3d Slot: %3d Name: '%-24s' Damtype: %s\n\r", sn, skill_table[sn]->slot, skill_table[sn]->name, spell_damage[SPELL_DAMAGE( skill_table[sn] )] ); num++; } pager_printf(ch, "%d matches found for %s.\n\r", num, pc_class[iClass]); } else if ( !str_cmp( arg, "smaug" ) ) { int num=0; for ( sn = 0; sn < top_sn && skill_table[sn] && skill_table[sn]->name; sn++ ) if (skill_table[sn]->skill_fun==do_smaug_skill || skill_table[sn]->spell_fun==spell_smaug) { pager_printf( ch, "Sn: %3d Slot: %3d Name: '%-24s' Damtype: %s\n\r", sn, skill_table[sn]->slot, skill_table[sn]->name, spell_damage[SPELL_DAMAGE( skill_table[sn] )] ); num++; } pager_printf(ch, "%d matches found.\n\r", num); } else if ( !str_cmp( arg, "herbs" ) ) { for ( sn = 0; sn < top_herb && herb_table[sn] && herb_table[sn]->name; sn++ ) pager_printf( ch, "%d) %s\n\r", sn, herb_table[sn]->name ); } else if ( !str_cmp( arg, "slots" ) ) { int maxslot=0, x; for ( sn = 0; sn < top_sn && skill_table[sn]; sn++ ) maxslot = UMAX(maxslot, skill_table[sn]->slot); for ( x = 0; x <= maxslot; x++ ) { if ( (sn = slot_lookup(x)) < 1 ) continue; pager_printf( ch, "Slot: %3d Sn: %3d Name: '%-24s' Damtype: %s\n\r", skill_table[sn]->slot, sn, skill_table[sn]->name, spell_damage[SPELL_DAMAGE( skill_table[sn] )] ); } return; } else { SMAUG_AFF *aff; int cnt = 0; if ( arg[0] == 'h' && is_number(arg+1) ) { sn = atoi(arg+1); if ( !IS_VALID_HERB(sn) ) { send_to_char( "Invalid herb.\n\r", ch ); return; } skill = herb_table[sn]; } else if ( is_number(arg) ) { sn = atoi(arg); if ( (skill=get_skilltype(sn)) == NULL ) { send_to_char( "Invalid sn.\n\r", ch ); return; } sn %= 1000; } else if ( ( sn = skill_lookup( arg ) ) >= 0 ) skill = skill_table[sn]; else if ( ( sn = herb_lookup( arg ) ) >= 0 ) skill = herb_table[sn]; else { send_to_char( "No such skill, spell, proficiency or tongue.\n\r", ch ); return; } if ( !skill ) { send_to_char( "Not created yet.\n\r", ch ); return; } set_char_color(AT_SCORE,ch); ch_printf( ch, "%sSn: %s%4d%s Slot: %s%4d%s %s: '%s%-20s%s'\n\r", s1, s2, sn, s1, s2, skill->slot, s1, skill_tname[skill->type], s3, skill->name, s1 ); if ( skill->flags ) { ch_printf( ch, "%sDamtype: %s%s%s Acttype: %s%s%s Classtype: %s%s%s Powertype: %s%s\n\r", s1, s3, spell_damage[SPELL_DAMAGE( skill )], s1, s3, spell_action[SPELL_ACTION( skill )], s1, s3, spell_ch_class[SPELL_CLASS( skill )], s1, s3, spell_power[SPELL_POWER( skill )] ); ch_printf( ch, "%sFlags: %s%s\n\r", s1, s3, flag_string(skill->flags, spell_flag)); } ch_printf( ch, "%sSaves: %s%s\n\r", s1, s3, spell_save[SPELL_SAVE(skill)] ); if ( skill->difficulty != '\0' ) ch_printf( ch, "%sDifficulty: %s%d%s\n\r", s1, s2, (int) skill->difficulty, s1 ); ch_printf( ch, "%sType: %s%s%s Target: %s%s%s Minpos: %s%s%s Mana: %s%d%s Beats: %s%d%s\n\r", s1, s3, skill_tname[skill->type], s1, s3, target_type[URANGE(TAR_IGNORE, skill->target, TAR_OBJ_ROOM)], s1, s3, position_types[skill->minimum_position], s1, s2, skill->min_mana, s1, s2, skill->beats, s1 ); ch_printf( ch, "Flags: %s%d%s Guild: %s%d%s Code: %s%s%s\n\r", s2, skill->flags, s1, s2, skill->guild, s1, s3, skill->skill_fun ? skill_name(skill->skill_fun) : spell_name(skill->spell_fun), s1); if ( skill->noun_damage ) ch_printf( ch, "Dammsg: %s%s%s\n\r", s3, skill->noun_damage, s1 ); if ( skill->msg_off && skill->msg_off[0] != '\0' ) ch_printf( ch, "Wearoff: %s%s%s\n\r", s3, skill->msg_off, s1 ); if ( skill->msg_off_room && skill->msg_off_room[0] != '\0' ) ch_printf(ch, "Wearoffroom: %s%s%s\n\r", s3, skill->msg_off_room, s1); if ( skill->msg_off_soon && skill->msg_off_soon[0] != '\0' ) ch_printf( ch, "Wearoffsoon: %s%s%s\n\r", s3, skill->msg_off_soon, s1); if ( skill->msg_off_soon_room && skill->msg_off_soon_room[0] != '\0' ) ch_printf(ch, "Wearoffsoonroom: %s%s%s\n\r", s3, skill->msg_off_soon_room, s1 ); if ( skill->dice && skill->dice[0] != '\0' ) ch_printf( ch, "Dice: %s%s%s\n\r", s3, skill->dice, s1 ); if ( skill->teachers && skill->teachers[0] != '\0' ) ch_printf( ch, "Teachers: %s%s%s\n\r", s3, skill->teachers, s1 ); if ( skill->components && skill->components[0] != '\0' ) ch_printf( ch, "Components: %s%s%s\n\r", s3, skill->components, s1 ); if ( skill->participants ) ch_printf( ch, "Participants : %s%d%s\n\r", s2, (int) skill->participants, s1 ); if ( skill->part_start_char && skill->part_start_char[0] != '\0' ) ch_printf( ch, "PartStartChar: %s%s%s\n\r", s3, skill->part_start_char, s1 ); if ( skill->part_start_room && skill->part_start_room[0] != '\0' ) ch_printf( ch, "PartStartRoom: %s%s%s\n\r", s3, skill->part_start_room, s1 ); if ( skill->part_end_char && skill->part_end_char[0] != '\0' ) ch_printf( ch, "PartEndChar : %s%s%s\n\r", s3, skill->part_end_char, s1 ); if ( skill->part_end_vict && skill->part_end_vict[0] != '\0' ) ch_printf( ch, "PartEndVict : %s%s%s\n\r", s3, skill->part_end_vict, s1 ); if ( skill->part_end_room && skill->part_end_room[0] != '\0' ) ch_printf( ch, "PartEndRoom : %s%s%s\n\r", s3, skill->part_end_room, s1 ); if ( skill->part_end_caster && skill->part_end_caster[0] != '\0' ) ch_printf( ch, "PartEndCaster: %s%s%s\n\r", s3, skill->part_end_caster, s1 ); if ( skill->part_miss_char && skill->part_miss_char[0] != '\0' ) ch_printf( ch, "PartMissChar : %s%s%s\n\r", s3, skill->part_miss_char, s1 ); if ( skill->part_miss_room && skill->part_miss_room[0] != '\0' ) ch_printf( ch, "PartMissRoom : %s%s%s\n\r", s3, skill->part_miss_room, s1 ); if ( skill->part_abort_char && skill->part_abort_char[0] != '\0' ) ch_printf( ch, "PartAbortChar: %s%s%s\n\r", s3, skill->part_abort_char, s1 ); if ( skill->userec.num_uses ) send_timer(&skill->userec, ch); for ( aff = skill->affects; aff; aff = aff->next ) { if ( aff == skill->affects ) send_to_char( "\n\r", ch ); sprintf( buf, "Affect %s%d%s", s2, ++cnt, s1 ); if ( aff->location ) { strcat( buf, " modifies " ); strcat( buf, s3 ); if (aff->location > REVERSE_APPLY) strcat(buf, "!"); strcat( buf, a_types[aff->location % REVERSE_APPLY] ); strcat( buf, s1 ); strcat( buf, " by '" ); strcat( buf, s3 ); strcat( buf, aff->modifier ); strcat( buf, s1 ); if ( aff->bitvector ) strcat( buf, "' and" ); else strcat( buf, "'" ); strcat( buf, s1 ); } if ( aff->bitvector ) { int x; strcat( buf, " applies" ); strcat( buf, s3 ); for ( x = 0; x < 32; x++ ) if ( IS_SET(aff->bitvector, 1 << x) ) { strcat( buf, " " ); strcat( buf, a_flags[x] ); } strcat( buf, s1 ); } if ( aff->duration[0] != '\0' && aff->duration[0] != '0' ) { strcat( buf, " for '" ); strcat( buf, s3 ); strcat( buf, aff->duration ); strcat( buf, s1 ); strcat( buf, "' rounds" ); } if ( aff->location >= REVERSE_APPLY ) strcat( buf, " (affects caster only)" ); strcat( buf, "\n\r" ); send_to_char( buf, ch ); if ( !aff->next ) send_to_char( "\n\r", ch ); } if ( skill->hit_char && skill->hit_char[0] != '\0' ) ch_printf( ch, "Hitchar : %s%s%s\n\r", s3, skill->hit_char, s1 ); if ( skill->hit_vict && skill->hit_vict[0] != '\0' ) ch_printf( ch, "Hitvict : %s%s%s\n\r", s3, skill->hit_vict, s1 ); if ( skill->hit_room && skill->hit_room[0] != '\0' ) ch_printf( ch, "Hitroom : %s%s%s\n\r", s3, skill->hit_room, s1 ); if ( skill->miss_char && skill->miss_char[0] != '\0' ) ch_printf( ch, "Misschar: %s%s%s\n\r", s3, skill->miss_char, s1 ); if ( skill->miss_vict && skill->miss_vict[0] != '\0' ) ch_printf( ch, "Missvict: %s%s%s\n\r", s3, skill->miss_vict, s1 ); if ( skill->miss_room && skill->miss_room[0] != '\0' ) ch_printf( ch, "Missroom: %s%s%s\n\r", s3, skill->miss_room, s1 ); if ( skill->die_char && skill->die_char[0] != '\0' ) ch_printf( ch, "Diechar : %s%s%s\n\r", s3, skill->die_char, s1 ); if ( skill->die_vict && skill->die_vict[0] != '\0' ) ch_printf( ch, "Dievict : %s%s%s\n\r", s3, skill->die_vict, s1 ); if ( skill->die_room && skill->die_room[0] != '\0' ) ch_printf( ch, "Dieroom : %s%s%s\n\r", s3, skill->die_room, s1 ); if ( skill->imm_char && skill->imm_char[0] != '\0' ) ch_printf( ch, "Immchar : %s%s%s\n\r", s3, skill->imm_char, s1 ); if ( skill->imm_vict && skill->imm_vict[0] != '\0' ) ch_printf( ch, "Immvict : %s%s%s\n\r", s3, skill->imm_vict, s1 ); if ( skill->imm_room && skill->imm_room[0] != '\0' ) ch_printf( ch, "Immroom : %s%s%s\n\r", s3, skill->imm_room, s1 ); if ( skill->abs_char && skill->abs_char[0] != '\0' ) ch_printf( ch, "Abschar : %s%s%s\n\r", s3, skill->abs_char, s1 ); if ( skill->abs_vict && skill->abs_vict[0] != '\0' ) ch_printf( ch, "Absvict : %s%s%s\n\r", s3, skill->abs_vict, s1 ); if ( skill->abs_room && skill->abs_room[0] != '\0' ) ch_printf( ch, "Absroom : %s%s%s\n\r", s3, skill->abs_room, s1 ); if ( skill->corpse_string && skill->corpse_string[0] != '\0' ) { ch_printf( ch, "Corpse : %s%s%s\n\r", s3, skill->corpse_string, s1 ); ch_printf( ch, "DecayLev: %s%d%s\n\r", s3, skill->corpse_stage, s1 ); } if ( skill->type != SKILL_HERB ) { for ( iClass = 0; iClass < MAX_CLASS; iClass++ ) { if ( skill->skill_level[iClass] != LEVEL_IMMORTAL ) sprintf(buf, "%s%3.3s%s) lvl: %s%2d%s max: %s%2d%s%% mana: %s%2d%s bts: %s%2d%s", s3, class_table[iClass]->who_name, s1, s2, skill->skill_level[iClass], s1, s4, skill->skill_adept[iClass], s1, s2, skill->class_mana[iClass], s1, s4, skill->class_beats[iClass], s1); else sprintf(buf, "%3.3s) lvl: %2d max: %2d%% mana: %2d bts: %2d", class_table[iClass]->who_name, skill->skill_level[iClass], skill->skill_adept[iClass], skill->class_mana[iClass], skill->class_beats[iClass]); if ( iClass < MAX_CLASS ) { if ( iClass % 2 == 1 ) strcat(buf, "\n\r" ); else strcat(buf, " " ); } send_to_char( buf, ch ); } } send_to_char( "\n\r", ch ); } return; } /* * 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( CHAR_DATA *ch, char *argument ) { char arg1 [MAX_INPUT_LENGTH]; char arg2 [MAX_INPUT_LENGTH]; CHAR_DATA *victim; int value; int sn; bool fAll; argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); if (!str_cmp(arg1, "list")) { int x; if (!str_prefix(arg2, "affecttypes")) { send_to_char("Spell affect types:\n\r", ch); for (x=0;x<MAX_APPLY_TYPE;x++) { ch_printf(ch, "%-15s", a_types[x]); if (x%5==4) send_to_char("\n\r", ch); } send_to_char("\n\r", ch); return; } if (!str_prefix(arg2, "affectedby")) { send_to_char("Affectedby bits:\n\r", ch); for (x=0;x<32;x++) { ch_printf(ch, "%-15s", a_flags[x]); if (x%5==4) send_to_char("\n\r", ch); } send_to_char("\n\r", ch); return; } if (!str_cmp(arg2, "spellflags")) { send_to_char("Spell flags:\n\r", ch); for ( x = 0; x < sizeof(spell_flag) / sizeof(spell_flag[0]); x++ ) { ch_printf(ch, "%-15s", spell_flag[x]); if (x%5==4) send_to_char("\n\r", ch); } send_to_char("\n\r", ch); return; } do_sset(ch, ""); return; } if ( arg1[0] == '\0' || arg2[0] == '\0' || argument[0] == '\0' ) { send_to_char( "Syntax: sset <victim> <skill> <value>\n\r", ch ); send_to_char( "or: sset <victim> all <value>\n\r", ch ); if ( get_trust(ch) > LEVEL_GOD ) { send_to_char( "or: sset save skill table\n\r", ch ); send_to_char( "or: sset save herb table\n\r", ch ); send_to_char( "or: sset create skill 'new skill'\n\r", ch ); send_to_char( "or: sset copy skill <sn> 'new skill'\n\r", ch ); send_to_char( "or: sset create herb 'new herb'\n\r", ch ); } if ( get_trust(ch) > LEVEL_GOD ) { send_to_char( "or: sset <sn> <field> <value>\n\r", ch ); send_to_char( "or: sset list affecttypes\n\r", ch ); send_to_char( "or: sset list affectedby\n\r", ch ); send_to_char( "or: sset list spellflags\n\r", ch ); send_to_char( "\n\rField being one of:\n\r", ch ); send_to_char( " name code target minpos slot mana beats dammsg wearoff guild minlevel\n\r", ch ); send_to_char( " type damtype acttype classtype powertype flags dice value difficulty affect\n\r", ch ); send_to_char( " rmaffect level adept hit miss die imm (char/vict/room) corpse decay\n\r", ch ); send_to_char( " components teachers wearoffroom wearoffsoon wearoffsoonroom\n\r", ch ); send_to_char( " partstartchar partstartroom partendchar partendvict partendroom\n\r", ch); send_to_char( " partendcaster partmisschar partmissroom partabortchar\n\r", ch); send_to_char( " cmana cbeats amana abeats\n\r", ch); send_to_char( "Affect having the fields: <location> <modfifier> [duration] [bitvector]\n\r", ch ); send_to_char( "(See AFFECTTYPES for location, and AFFECTEDBY for bitvector)\n\r", ch ); } send_to_char( "Skill being any skill or spell.\n\r", ch ); return; } if ( get_trust(ch) > LEVEL_GOD ) { if (!str_cmp( arg1, "save" ) && !str_cmp( argument, "table" ) ) { if ( !str_cmp( arg2, "skill" ) ) { send_to_char( "Saving skill table...\n\r", ch ); save_skill_table(); save_classes(); return; } if ( !str_cmp( arg2, "herb" ) ) { send_to_char( "Saving herb table...\n\r", ch ); save_herb_table(); return; } } if ( (!str_cmp( arg1, "create" ) || !str_cmp( arg1, "copy" )) && (!str_cmp( arg2, "skill" ) || !str_cmp( arg2, "herb" )) ) { SKILLTYPE *skill; sh_int type = SKILL_UNKNOWN; if ( !str_cmp( arg2, "herb" ) ) { type = SKILL_HERB; if ( top_herb >= MAX_HERB ) { ch_printf( ch, "The current top herb is %d, which is the maximum. " "To add more herbs,\n\rMAX_HERB will have to be " "raised in mud.h, and the mud recompiled.\n\r", top_sn ); return; } } else if ( top_sn >= MAX_SKILL ) { ch_printf( ch, "The current top sn is %d, which is the maximum. " "To add more skills,\n\rMAX_SKILL will have to be " "raised in mud.h, and the mud recompiled.\n\r", top_sn ); return; } CREATE( skill, SKILLTYPE, 1 ); if ( !str_cmp( arg1, "copy" ) ) { char arg3 [MAX_INPUT_LENGTH]; argument = one_argument( argument, arg3 ); if ( arg3[0] == 'h' ) sn = atoi( arg3+1 ); else sn = atoi( arg3 ); if (!IS_VALID_SN(sn)) { send_to_char("That is not a valid sn.\n\r", ch); return; } /* copy it here */ } else { int x; skill->noun_damage = str_dup( "" ); skill->msg_off = str_dup( "" ); skill->msg_off_room = str_dup( "" ); skill->msg_off_soon = str_dup( "" ); skill->msg_off_soon_room = str_dup( "" ); skill->spell_fun = spell_smaug; skill->type = type; for (x = 0; x < MAX_CLASS; x++) { skill->skill_level[x] = LEVEL_IMMORTAL; skill->skill_adept[x] = 95; } } skill->name = str_dup( argument ); if ( type == SKILL_HERB ) { int max, x; herb_table[top_herb++] = skill; for ( max = x = 0; x < top_herb-1; x++ ) if ( herb_table[x] && herb_table[x]->slot > max ) max = herb_table[x]->slot; skill->slot = max+1; } else skill_table[top_sn++] = skill; ch_printf(ch, "Done, spell is sn %d.\n\r", top_sn-1); return; } } if ( arg1[0] == 'h' ) sn = atoi( arg1+1 ); else sn = atoi( arg1 ); if (!IS_VALID_SN(sn)) { send_to_char("That is not a valid sn.\n\r", ch); return; } if ( get_trust(ch) > LEVEL_GOD && ((arg1[0] == 'h' && is_number(arg1+1) && (sn=atoi(arg1+1))>=0) || (is_number(arg1) && (sn=atoi(arg1)) >= 0)) ) { SKILLTYPE *skill; if ( arg1[0] == 'h' ) { if ( sn >= top_herb ) { send_to_char( "Herb number out of range.\n\r", ch ); return; } skill = herb_table[sn]; } else { if ( (skill=get_skilltype(sn)) == NULL ) { send_to_char( "Skill number out of range.\n\r", ch ); return; } sn %= 1000; } if ( !str_cmp( arg2, "difficulty" ) ) { skill->difficulty = atoi( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "participants" ) ) { skill->participants = atoi( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "damtype" ) ) { int x = get_sdamage( argument ); if ( x == -1 ) send_to_char( "Not a spell damage type.\n\r", ch ); else { SET_SDAM( skill, x ); send_to_char( "Ok.\n\r", ch ); } return; } if ( !str_cmp( arg2, "acttype" ) ) { int x = get_saction( argument ); if ( x == -1 ) send_to_char( "Not a spell action type.\n\r", ch ); else { SET_SACT( skill, x ); send_to_char( "Ok.\n\r", ch ); } return; } if ( !str_cmp( arg2, "classtype" ) ) { int x = get_sch_class( argument ); if ( x == -1 ) send_to_char( "Not a spell class type.\n\r", ch ); else { SET_SCLA( skill, x ); send_to_char( "Ok.\n\r", ch ); } return; } if ( !str_cmp( arg2, "powertype" ) ) { int x = get_spower( argument ); if ( x == -1 ) send_to_char( "Not a spell power type.\n\r", ch ); else { SET_SPOW( skill, x ); send_to_char( "Ok.\n\r", ch ); } return; } if ( !str_cmp( arg2, "savetype" ) ) { int x = get_ssave( argument ); if ( x == -1 ) send_to_char( "Not a spell save type.\n\r", ch ); else { SET_SSAV( skill, x ); send_to_char( "Ok.\n\r", ch ); } return; } if ( !str_cmp( arg2, "flags" ) ) { int x = get_sflag( argument ); if ( x == -1 ) send_to_char( "Not a spell flag.\n\r", ch ); else { TOGGLE_BIT( skill->flags, 1 << x ); send_to_char( "Ok.\n\r", ch ); } return; } if ( !str_cmp( arg2, "code" ) ) { SPELL_FUN *spellfun; DO_FUN *dofun; if ( (spellfun=spell_function(argument)) != spell_notfound ) { skill->spell_fun = spellfun; skill->skill_fun = NULL; } else if ( (dofun=skill_function(argument)) != skill_notfound ) { skill->skill_fun = dofun; skill->spell_fun = NULL; } else { send_to_char( "Not a spell or skill.\n\r", ch ); return; } send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "target" ) ) { int x = get_starget( argument ); if ( x == -1 ) send_to_char( "Not a valid target type.\n\r", ch ); else { skill->target = x; send_to_char( "Ok.\n\r", ch ); } return; } if ( !str_cmp( arg2, "minpos" ) ) { skill->minimum_position = URANGE( POS_DEAD, get_postype( argument ), POS_DRAG ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "minlevel" ) ) { skill->min_level = URANGE( 1, atoi( argument ), MAX_LEVEL ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "slot" ) ) { skill->slot = URANGE( 0, atoi( argument ), 30000 ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "mana" ) ) { skill->min_mana = URANGE( 0, atoi( argument ), 2000 ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "amana" ) ) { sh_int cl; for (cl = FIRST_CLASS; cl < MAX_CLASS; cl++) skill->class_mana[cl] = URANGE( 0, atoi( argument ), 2000 ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "beats" ) ) { skill->beats = URANGE( 0, atoi( argument ), 288 ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "abeats" ) ) { sh_int cl; for (cl = FIRST_CLASS; cl < MAX_CLASS; cl++) skill->class_beats[cl] = URANGE( 0, atoi( argument ), 288 ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "guild" ) ) { skill->guild = atoi( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "value" ) ) { skill->value = atoi( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "decay" ) ) { skill->corpse_stage = atoi( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "type" ) ) { skill->type = get_skill_tname( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "rmaffect" ) ) { SMAUG_AFF *aff = skill->affects; SMAUG_AFF *aff_next; int num = atoi( argument ); int cnt = 1; if ( !aff ) { send_to_char( "This spell has no special affects to remove.\n\r", ch ); return; } if ( num == 1 ) { skill->affects = aff->next; DISPOSE( aff->duration ); DISPOSE( aff->modifier ); DISPOSE( aff ); send_to_char( "Removed.\n\r", ch ); return; } for ( ; aff; aff = aff->next ) { if ( ++cnt == num && (aff_next=aff->next) != NULL ) { aff->next = aff_next->next; DISPOSE( aff_next->duration ); DISPOSE( aff_next->modifier ); DISPOSE( aff_next ); send_to_char( "Removed.\n\r", ch ); return; } } send_to_char( "Not found.\n\r", ch ); 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]; char bitvector[MAX_INPUT_LENGTH]; int loc, bit, tmpbit; SMAUG_AFF *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 ) { send_to_char( "Unknown affect location. See AFFECTTYPES.\n\r", ch ); return; } bit = 0; while ( argument[0] != 0 ) { argument = one_argument( argument, bitvector ); if ( (tmpbit=get_aflag( bitvector )) == -1 ) ch_printf( ch, "Unknown bitvector: %s. See AFFECTEDBY\n\r", bitvector ); else bit |= (1 << tmpbit); } CREATE( aff, SMAUG_AFF, 1 ); 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->next = skill->affects; skill->affects = aff; send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "level" ) ) { char arg3[MAX_INPUT_LENGTH]; int ch_class; argument = one_argument( argument, arg3 ); ch_class = get_classtype( arg3 ); if ( ch_class >= MAX_CLASS || ch_class < 0 ) send_to_char( "Not a valid class.\n\r", ch ); else skill->skill_level[ch_class] = URANGE(0, atoi(argument), MAX_LEVEL); return; } if ( !str_cmp( arg2, "adept" ) ) { char arg3[MAX_INPUT_LENGTH]; int ch_class; argument = one_argument( argument, arg3 ); ch_class = get_classtype( arg3 ); if ( ch_class >= MAX_CLASS || ch_class < 0 ) send_to_char( "Not a valid class.\n\r", ch ); else skill->skill_adept[ch_class] = URANGE(0, atoi(argument), 100); return; } if ( !str_cmp( arg2, "cmana" ) ) { char arg3[MAX_INPUT_LENGTH]; int ch_class; argument = one_argument( argument, arg3 ); ch_class = get_classtype( arg3 ); if ( ch_class >= MAX_CLASS || ch_class < 0 ) send_to_char( "Not a valid class.\n\r", ch ); else skill->class_mana[ch_class] = URANGE(0, atoi(argument), 2000); return; } if ( !str_cmp( arg2, "cbeats" ) ) { char arg3[MAX_INPUT_LENGTH]; int ch_class; argument = one_argument( argument, arg3 ); ch_class = get_classtype( arg3 ); if ( ch_class >= MAX_CLASS || ch_class < 0 ) send_to_char( "Not a valid class.\n\r", ch ); else skill->class_beats[ch_class] = URANGE(0, atoi(argument), 288); return; } if ( !str_cmp( arg2, "name" ) ) { DISPOSE(skill->name); skill->name = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "dammsg" ) ) { DISPOSE(skill->noun_damage); if ( !str_cmp( argument, "clear" ) ) skill->noun_damage = str_dup( "" ); else skill->noun_damage = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "wearoff" ) ) { DISPOSE(skill->msg_off); if ( str_cmp( argument, "clear" ) ) skill->msg_off = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "wearoffroom" ) ) { DISPOSE(skill->msg_off_room); if ( str_cmp( argument, "clear" ) ) skill->msg_off_room = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "wearoffsoon" ) ) { DISPOSE(skill->msg_off_soon); if ( str_cmp( argument, "clear" ) ) skill->msg_off_soon = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "wearoffsoonroom" ) ) { DISPOSE(skill->msg_off_soon_room); if ( str_cmp( argument, "clear" ) ) skill->msg_off_soon_room = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "hitchar" ) ) { if ( skill->hit_char ) DISPOSE(skill->hit_char); if ( str_cmp( argument, "clear" ) ) skill->hit_char = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "hitvict" ) ) { if ( skill->hit_vict ) DISPOSE(skill->hit_vict); if ( str_cmp( argument, "clear" ) ) skill->hit_vict = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "hitroom" ) ) { if ( skill->hit_room ) DISPOSE(skill->hit_room); if ( str_cmp( argument, "clear" ) ) skill->hit_room = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "misschar" ) ) { if ( skill->miss_char ) DISPOSE(skill->miss_char); if ( str_cmp( argument, "clear" ) ) skill->miss_char = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "missvict" ) ) { if ( skill->miss_vict ) DISPOSE(skill->miss_vict); if ( str_cmp( argument, "clear" ) ) skill->miss_vict = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "missroom" ) ) { if ( skill->miss_room ) DISPOSE(skill->miss_room); if ( str_cmp( argument, "clear" ) ) skill->miss_room = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "diechar" ) ) { if ( skill->die_char ) DISPOSE(skill->die_char); if ( str_cmp( argument, "clear" ) ) skill->die_char = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "dievict" ) ) { if ( skill->die_vict ) DISPOSE(skill->die_vict); if ( str_cmp( argument, "clear" ) ) skill->die_vict = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "dieroom" ) ) { if ( skill->die_room ) DISPOSE(skill->die_room); if ( str_cmp( argument, "clear" ) ) skill->die_room = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "immchar" ) ) { if ( skill->imm_char ) DISPOSE(skill->imm_char); if ( str_cmp( argument, "clear" ) ) skill->imm_char = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "immvict" ) ) { if ( skill->imm_vict ) DISPOSE(skill->imm_vict); if ( str_cmp( argument, "clear" ) ) skill->imm_vict = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "immroom" ) ) { if ( skill->imm_room ) DISPOSE(skill->imm_room); if ( str_cmp( argument, "clear" ) ) skill->imm_room = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "abschar" ) ) { if ( skill->abs_char ) DISPOSE(skill->abs_char); if ( str_cmp( argument, "clear" ) ) skill->abs_char = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "absvict" ) ) { if ( skill->abs_vict ) DISPOSE(skill->abs_vict); if ( str_cmp( argument, "clear" ) ) skill->abs_vict = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "absroom" ) ) { if ( skill->abs_room ) DISPOSE(skill->abs_room); if ( str_cmp( argument, "clear" ) ) skill->abs_room = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "corpse" ) ) { if ( skill->corpse_string ) DISPOSE(skill->corpse_string); if ( str_cmp( argument, "clear" ) ) skill->corpse_string = str_dup( argument ); skill->corpse_stage = 0; send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "dice" ) ) { if ( skill->dice ) DISPOSE(skill->dice); if ( str_cmp( argument, "clear" ) ) skill->dice = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "components" ) ) { if ( skill->components ) DISPOSE(skill->components); if ( str_cmp( argument, "clear" ) ) skill->components = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "teachers" ) ) { if ( skill->teachers ) DISPOSE(skill->teachers); if ( str_cmp( argument, "clear" ) ) skill->teachers = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "partstartchar" ) ) { if ( skill->part_start_char ) DISPOSE(skill->part_start_char); if ( str_cmp( argument, "clear" ) ) skill->part_start_char = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "partstartroom" ) ) { if ( skill->part_start_room ) DISPOSE(skill->part_start_room); if ( str_cmp( argument, "clear" ) ) skill->part_start_room = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "partendchar" ) ) { if ( skill->part_end_char ) DISPOSE(skill->part_end_char); if ( str_cmp( argument, "clear" ) ) skill->part_end_char = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "partendvict" ) ) { if ( skill->part_end_vict ) DISPOSE(skill->part_end_vict); if ( str_cmp( argument, "clear" ) ) skill->part_end_vict = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "partendroom" ) ) { if ( skill->part_end_room ) DISPOSE(skill->part_end_room); if ( str_cmp( argument, "clear" ) ) skill->part_end_room = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "partendcaster" ) ) { if ( skill->part_end_caster ) DISPOSE(skill->part_end_caster); if ( str_cmp( argument, "clear" ) ) skill->part_end_caster = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "partmisschar" ) ) { if ( skill->part_miss_char ) DISPOSE(skill->part_miss_char); if ( str_cmp( argument, "clear" ) ) skill->part_miss_char = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "partmissroom" ) ) { if ( skill->part_miss_room ) DISPOSE(skill->part_miss_room); if ( str_cmp( argument, "clear" ) ) skill->part_miss_room = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg2, "partabortchar" ) ) { if ( skill->part_abort_char ) DISPOSE(skill->part_abort_char); if ( str_cmp( argument, "clear" ) ) skill->part_abort_char = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } do_sset( ch, "" ); return; } if ( ( victim = get_char_world( ch, arg1 ) ) == NULL ) { if ( (sn = skill_lookup(arg1)) >= 0 ) { sprintf(arg1, "%d %s %s", sn, arg2, argument); do_sset(ch, arg1); } else send_to_char( "They aren't here.\n\r", ch ); return; } if ( IS_NPC(victim) ) { send_to_char( "Not on NPC's.\n\r", ch ); return; } fAll = !str_cmp( arg2, "all" ); sn = 0; if ( !fAll && ( sn = skill_lookup( arg2 ) ) < 0 ) { send_to_char( "No such skill or spell.\n\r", ch ); return; } /* * Snarf the value. */ if ( !is_number( argument ) ) { send_to_char( "Value must be numeric.\n\r", ch ); return; } value = atoi( argument ); if ( value < 0 || value > 100 ) { send_to_char( "Value range is 0 to 100.\n\r", ch ); return; } if ( fAll ) { for ( sn = 0; sn < top_sn; sn++ ) { /* Fix by Narn to prevent ssetting skills the player shouldn't have. */ if ( skill_table[sn]->name && ( CanUseSkill(victim, sn) || value == 0 ) ) victim->pcdata->learned[sn] = value; } } else victim->pcdata->learned[sn] = value; return; } void learn_from_success( CHAR_DATA *ch, int sn ) { #if 0 int adept, /*gain,*/ sklvl, learn, percent, chance; if ( IS_NPC(ch) || LEARNED(ch, sn) == 0 ) return; adept = GET_ADEPT(ch,sn); sklvl = skill_table[sn]->skill_level[BestSkCl(ch, sn)]; if ( sklvl == 0 ) sklvl = GetMaxLevel(ch); if ( LEARNED(ch, sn) < adept ) { chance = LEARNED(ch, sn) + (5 * skill_table[sn]->difficulty); percent = number_percent(); if ( percent >= chance ) learn = 2; else if ( chance - percent > 25 ) return; else learn = 1; ch->pcdata->learned[sn] = UMIN( adept, LEARNED(ch, sn) + learn ); ch_printf( ch, "You learn from your success.\n\r" ); if ( LEARNED(ch, sn) == adept ) /* fully learned! */ { gain = 1000 * sklvl; if (IS_ACTIVE(ch, CLASS_MAGE)) gain = gain *5; /* h, mage upgrade */ set_char_color( AT_WHITE, ch ); ch_printf( ch, "You are now an adept of %s! You gain %d bonus experience!\n\r", skill_table[sn]->name, gain ); } else { gain = 20 * sklvl; if (IS_ACTIVE(ch, CLASS_MAGE)) gain = gain *6; /* h, mage upgrade */ if ( !ch->fighting && sn != gsn_hide && sn != gsn_sneak ) { set_char_color( AT_WHITE, ch ); ch_printf( ch, "You gain %d experience points from your success!\n\r", gain ); } } gain_exp( ch, gain ); } #endif } void learn_from_failure(CHAR_DATA *ch, int sn) { int adept, chance; if (IS_NPC(ch) || sn<0 || LEARNED(ch, sn) == 0) return; chance = LEARNED(ch, sn) + (5 * skill_table[sn]->difficulty); if (number_percent() < (chance/2)) return; adept = GET_ADEPT(ch, sn); if (LEARNED(ch, sn) == adept) return; ch->pcdata->learned[sn] = UMIN( adept, LEARNED(ch, sn) + 1); if (LEARNED(ch, sn) == adept) send_to_char("You are now learned in this skill!\n\r", ch); else if (LEARNED(ch, sn) < adept && sn != gsn_drinking) send_to_char("You learn from your mistake.\n\r",ch); } void do_gouge( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; AFFECT_DATA af; sh_int dam; int percent; if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } if ( !IS_NPC(ch) && !LEARNED(ch, gsn_gouge) ) { send_to_char("You do not yet know of this skill.\n\r", ch ); return; } if ( ch->mount ) { send_to_char( "You can't get close enough while mounted.\n\r", ch ); return; } if ( ( victim = who_fighting( ch ) ) == NULL ) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } percent = number_percent( ) - (get_curr_lck(ch) - 13); if ( IS_NPC(ch) || percent < LEARNED(ch, gsn_gouge) ) { dam = number_range( 1, ch->levels[BestSkCl(ch, gsn_gouge)] ); global_retcode = damage( ch, victim, dam, gsn_gouge ); if ( global_retcode == rNONE ) { if ( !IS_AFFECTED( victim, AFF_BLIND ) ) { af.type = gsn_blindness; af.location = APPLY_HITROLL; af.modifier = -6; af.duration = 3 + (ch->levels[BestSkCl(ch, gsn_gouge)] / 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 ); 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. */ } 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 { spell_lag(ch, gsn_gouge); global_retcode = damage( ch, victim, 0, gsn_gouge ); learn_from_failure( ch, gsn_gouge ); } return; } void do_detrap( CHAR_DATA *ch, char *argument ) { char arg [MAX_INPUT_LENGTH]; OBJ_DATA *obj; OBJ_DATA *trap; int percent; bool found = FALSE; switch( ch->substate ) { default: if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } argument = one_argument( argument, arg ); if ( !IS_NPC(ch) && !LEARNED(ch, gsn_detrap) ) { send_to_char("You do not yet know of this skill.\n\r", ch ); return; } if ( arg[0] == '\0' ) { send_to_char( "Detrap what?\n\r", ch ); return; } if ( ms_find_obj(ch) ) return; found = FALSE; if ( ch->mount ) { send_to_char( "You can't do that while mounted.\n\r", ch ); return; } if ( !ch->in_room->first_content ) { send_to_char( "You can't find that here.\n\r", ch ); return; } for ( obj = ch->in_room->first_content; obj; obj = obj->next_content ) { if ( can_see_obj( ch, obj ) && nifty_is_name( arg, obj->name ) ) { found = TRUE; break; } } if ( !found ) { send_to_char( "You can't find that here.\n\r", ch ); 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->dest_buf = str_dup( obj->name ); add_timer( ch, TIMER_DO_FUN, UMAX(skill_table[gsn_detrap]->beats/SPELL_BEATS_PER_ROUND, 1), do_detrap, 1 ); return; case 1: if ( !ch->dest_buf ) { send_to_char( "Your detrapping was interrupted!\n\r", ch ); bug( "do_detrap: ch->dest_buf NULL!" ); return; } strcpy( arg, (const char *)ch->dest_buf ); DISPOSE( ch->dest_buf ); ch->dest_buf = NULL; ch->substate = SUB_NONE; break; case SUB_TIMER_DO_ABORT: DISPOSE(ch->dest_buf); ch->substate = SUB_NONE; send_to_char( "You carefully stop what you were doing.\n\r", ch ); return; } for ( obj = ch->in_room->first_content; obj; obj = obj->next_content ) { if ( can_see_obj( ch, obj ) && nifty_is_name( arg, obj->name ) ) { found = TRUE; break; } } if ( !found ) { send_to_char( "You can't find that here.\n\r", ch ); return; } if ( (trap = get_trap( obj )) == NULL ) { send_to_char( "You find no trap on that.\n\r", ch ); return; } percent = number_percent( ) - ( ch->levels[BestSkCl(ch, gsn_detrap)] / 15 ) - (get_curr_lck(ch) - 16); separate_obj(obj); if ( !IS_NPC(ch) || percent > LEARNED(ch, gsn_detrap) ) { send_to_char( "Ooops!\n\r", ch ); spring_trap( ch, trap ); learn_from_failure( ch, gsn_detrap ); return; } extract_obj( trap ); send_to_char( "You successfully remove a trap.\n\r", ch ); learn_from_success( ch, gsn_detrap ); return; } void do_dig( CHAR_DATA *ch, char *argument ) { char arg [MAX_INPUT_LENGTH]; OBJ_DATA *obj; OBJ_DATA *startobj; bool found, shovel; EXIT_DATA *pexit; switch( ch->substate ) { default: if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } if ( ch->mount ) { send_to_char( "You can't do that while mounted.\n\r", ch ); return; } one_argument( argument, arg ); if ( arg[0] != '\0' ) { if ( ( pexit = find_door( ch, arg, TRUE ) ) == NULL && get_dir(arg) == -1 ) { send_to_char( "What direction is that?\n\r", ch ); return; } if ( pexit ) { if ( !IS_SET(pexit->exit_info, EX_DIG) && !IS_SET(pexit->exit_info, EX_CLOSED) ) { send_to_char( "There is no need to dig out that exit.\n\r", ch ); return; } } } else { switch( ch->in_room->sector_type ) { case SECT_CITY: case SECT_INSIDE: send_to_char( "The floor is too hard to dig through.\n\r", ch ); return; case SECT_WATER_SWIM: case SECT_WATER_NOSWIM: case SECT_UNDERWATER: send_to_char( "You cannot dig here.\n\r", ch ); return; case SECT_AIR: send_to_char( "What? In the air?!\n\r", ch ); return; } } add_timer( ch, TIMER_DO_FUN, UMAX(skill_table[gsn_dig]->beats/SPELL_BEATS_PER_ROUND, 1), do_dig, 1); ch->dest_buf = str_dup( arg ); send_to_char( "You begin digging...\n\r", ch ); act( AT_SKILL, "$n begins digging...", ch, NULL, NULL, TO_ROOM ); return; case 1: if ( !ch->dest_buf ) { send_to_char( "Your digging was interrupted!\n\r", ch ); act( AT_SKILL, "$n's digging was interrupted!", ch, NULL, NULL, TO_ROOM ); bug( "do_dig: dest_buf NULL" ); return; } strcpy( arg, (const char *)ch->dest_buf ); DISPOSE( ch->dest_buf ); break; case SUB_TIMER_DO_ABORT: DISPOSE( ch->dest_buf ); ch->substate = SUB_NONE; send_to_char( "You stop digging...\n\r", ch ); act( AT_SKILL, "$n stops digging...", ch, NULL, NULL, TO_ROOM ); return; } ch->substate = SUB_NONE; /* not having a shovel makes it harder to succeed */ shovel = FALSE; for ( obj = ch->first_carrying; obj; obj = obj->next_content ) if ( obj->item_type == ITEM_SHOVEL ) { shovel = TRUE; break; } /* dig out an EX_DIG exit... */ if ( arg[0] != '\0' ) { if ( ( pexit = find_door( ch, arg, TRUE ) ) != NULL && IS_SET( pexit->exit_info, EX_DIG ) && IS_SET( pexit->exit_info, EX_CLOSED ) ) { /* 4 times harder to dig open a passage without a shovel */ if ( (number_percent() * (shovel ? 1 : 4)) < (IS_NPC(ch) ? 80 : LEARNED(ch, gsn_dig)) ) { REMOVE_BIT( pexit->exit_info, EX_CLOSED ); send_to_char( "You dig open a passageway!\n\r", ch ); act( AT_SKILL, "$n digs open a passageway!", ch, NULL, NULL, TO_ROOM ); learn_from_success( ch, gsn_dig ); return; } } learn_from_failure( ch, gsn_dig ); send_to_char( "Your dig did not discover any exit...\n\r", ch ); act( AT_SKILL, "$n's dig did not discover any exit...", ch, NULL, NULL, TO_ROOM ); return; } startobj = ch->in_room->first_content; found = FALSE; for ( obj = startobj; obj; obj = obj->next_content ) { /* twice as hard to find something without a shovel */ if ( IS_OBJ_STAT( obj, ITEM_BURRIED ) && (number_percent() * (shovel ? 1 : 2)) < (IS_NPC(ch) ? 80 : LEARNED(ch, gsn_dig)) ) { found = TRUE; break; } } if ( !found ) { send_to_char( "Your dig uncovered nothing.\n\r", ch ); act( AT_SKILL, "$n's dig uncovered nothing.", ch, NULL, NULL, TO_ROOM ); learn_from_failure( ch, gsn_dig ); return; } separate_obj(obj); REMOVE_BIT( obj->extra_flags, ITEM_BURRIED ); 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 ); return; } void do_search( CHAR_DATA *ch, char *argument ) { char arg [MAX_INPUT_LENGTH]; OBJ_DATA *obj = NULL; OBJ_DATA *container; OBJ_DATA *startobj; int percent, door; bool found, room; door = -1; switch( ch->substate ) { default: if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } if ( ch->mount ) { send_to_char( "You can't do that while mounted.\n\r", ch ); return; } argument = one_argument( argument, arg ); if ( arg[0] != '\0' && (door = get_door( arg )) == -1 ) { container = get_obj_here( ch, arg ); if ( !container ) { send_to_char( "You can't find that here.\n\r", ch ); return; } if ( container->item_type != ITEM_CONTAINER ) { send_to_char( "You can't search in that!\n\r", ch ); return; } if ( IS_SET(container->value[1], CONT_CLOSED) ) { send_to_char( "It is closed.\n\r", ch ); return; } } add_timer( ch, TIMER_DO_FUN, UMAX(skill_table[gsn_search]->beats/SPELL_BEATS_PER_ROUND, 1), do_search, 1 ); send_to_char( "You begin your search...\n\r", ch ); ch->dest_buf = str_dup( arg ); return; case 1: if ( !ch->dest_buf ) { send_to_char( "Your search was interrupted!\n\r", ch ); bug( "do_search: dest_buf NULL" ); return; } strcpy( arg, (const char *)ch->dest_buf ); DISPOSE( ch->dest_buf ); break; case SUB_TIMER_DO_ABORT: DISPOSE( ch->dest_buf ); ch->substate = SUB_NONE; send_to_char( "You stop your search...\n\r", ch ); return; } ch->substate = SUB_NONE; if ( arg[0] == '\0' ) { room = TRUE; startobj = ch->in_room->first_content; } else { if ( (door = get_door( arg )) != -1 ) startobj = NULL; else { container = get_obj_here( ch, arg ); if ( !container ) { send_to_char( "You can't find that here.\n\r", ch ); return; } startobj = container->first_content; } } found = FALSE; if ( (!startobj && door == -1) || IS_NPC(ch) ) { send_to_char( "You find nothing.\n\r", ch ); learn_from_failure( ch, gsn_search ); return; } percent = number_percent( ) + number_percent( ) - ( ch->levels[BestSkCl(ch, gsn_search)] / 10 ); if ( door != -1 ) { EXIT_DATA *pexit; if ( (pexit = get_exit( ch->in_room, door )) != NULL && IS_SET( pexit->exit_info, EX_SECRET ) && IS_SET( pexit->exit_info, EX_xSEARCHABLE ) && percent < (IS_NPC(ch) ? 80 : LEARNED(ch, 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 ); REMOVE_BIT( pexit->exit_info, EX_SECRET ); learn_from_success( ch, gsn_search ); return; } } else for ( obj = startobj; obj; obj = obj->next_content ) { if ( IS_OBJ_STAT( obj, ITEM_HIDDEN ) && percent < LEARNED(ch, gsn_search) ) { found = TRUE; break; } } if ( !found ) { send_to_char( "You find nothing.\n\r", ch ); learn_from_failure( ch, gsn_search ); return; } separate_obj(obj); REMOVE_BIT( obj->extra_flags, ITEM_HIDDEN ); 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; } void do_steal( CHAR_DATA *ch, char *argument ) { char buf [MAX_STRING_LENGTH]; char arg1 [MAX_INPUT_LENGTH]; char arg2 [MAX_INPUT_LENGTH]; CHAR_DATA *victim, *mst; OBJ_DATA *obj; int percent; argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); if ( ch->mount ) { send_to_char( "You can't do that while mounted.\n\r", ch ); return; } if ( arg1[0] == '\0' || arg2[0] == '\0' ) { send_to_char( "Steal what from whom?\n\r", ch ); return; } if ( ms_find_obj(ch) ) return; if ( ( victim = get_char_room( ch, arg2 ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( victim == ch ) { send_to_char( "That's pointless.\n\r", ch ); return; } if ( IS_SET( ch->in_room->room_flags, ROOM_SAFE ) && !IS_IMMORTAL(ch) ) { set_char_color( AT_MAGIC, ch ); send_to_char( "A magical force interrupts you.\n\r", ch ); 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 ) ) { send_to_char( "You can't steal from that player.\n\r", ch ); return; } */ if ( !IS_IMMORTAL( ch ) && !IS_NPC( ch ) && !IS_NPC( victim ) ) { set_char_color( AT_IMMORT, ch ); send_to_char( "The gods forbid theft between players.\n\r", ch ); return; } spell_lag(ch, gsn_steal); percent = number_percent( ) + ( IS_AWAKE(victim) ? 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( GetMaxLevel(ch) + 10 < GetMaxLevel(victim) ) { send_to_char( "You really don't want to try that!\n\r", ch ); return; } if ( victim->position == POS_FIGHTING || percent > ( IS_NPC(ch) ? 90 : LEARNED(ch, gsn_steal) ) ) { /* * Failure. */ send_to_char( "Oops...\n\r", ch ); 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->name ); do_gossip( victim, buf ); learn_from_failure( ch, gsn_steal ); if ( !IS_NPC(ch) ) { if ( legal_loot( ch, victim ) ) { global_retcode = multi_hit( victim, ch, TYPE_UNDEFINED ); } else { /* log_string( buf ); */ if ( IS_NPC( ch ) ) { if ( (mst = ch->master) == NULL ) return; } else mst = ch; if ( IS_NPC( mst ) ) return; if ( !IS_SET(mst->act, PLR_THIEF) ) { SET_BIT(mst->act, PLR_THIEF); set_char_color( AT_WHITE, ch ); send_to_char( "A strange feeling grows deep inside you, and a tingle goes up your spine...\n\r", ch ); set_char_color( AT_IMMORT, ch ); send_to_char( "A deep voice booms inside your head, 'Thou shall now be known as a lowly thief!'\n\r", ch ); set_char_color( AT_WHITE, ch ); send_to_char( "You feel as if your soul has been revealed for all to see.\n\r", ch ); save_char_obj( mst ); } } } return; } if ( !str_cmp( arg1, "coin" ) || !str_cmp( arg1, "coins" ) ) { int amount, type=CURR_GOLD; for (amount=FIRST_CURR;amount<=LAST_CURR;amount++) { type = number_range(FIRST_CURR, LAST_CURR); if (GET_MONEY(victim,type)) break; } amount = (int) (GET_MONEY(victim,type) * number_range(1, 10) / 100); if ( amount <= 0 ) { send_to_char( "You couldn't get any money.\n\r", ch ); learn_from_failure( ch, gsn_steal ); return; } GET_MONEY(ch,type) += amount; GET_MONEY(victim,type) -= amount; ch_printf( ch, "Aha! You got %d %s coins.\n\r", amount, curr_types[type] ); learn_from_success( ch, gsn_steal ); return; } if ( ( obj = get_obj_carry( victim, arg1 ) ) == NULL ) { send_to_char( "You can't seem to find it.\n\r", ch ); learn_from_failure( ch, gsn_steal ); return; } if ( !can_drop_obj( ch, obj ) || IS_OBJ_STAT(obj, ITEM_INVENTORY) || IS_OBJ_STAT(obj, ITEM_PROTOTYPE) || item_ego(obj) > char_ego(ch) ) { send_to_char( "You can't manage to pry it away.\n\r", ch ); learn_from_failure( ch, gsn_steal ); return; } if ( carry_n(ch) + (get_obj_number(obj)/obj->count) > can_carry_n( ch ) ) { send_to_char( "You have your hands full.\n\r", ch ); learn_from_failure( ch, gsn_steal ); return; } if ( carry_w(ch) + (get_obj_weight(obj)/obj->count) > can_carry_w( ch ) ) { send_to_char( "You can't carry that much weight.\n\r", ch ); learn_from_failure( ch, gsn_steal ); return; } separate_obj( obj ); obj_from_char( obj ); obj_to_char( obj, ch ); send_to_char( "Ok.\n\r", ch ); learn_from_success( ch, gsn_steal ); adjust_favor( ch, 9, 1 ); return; } void do_backstab( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; OBJ_DATA *obj; int percent; if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't do that right now.\n\r", ch ); return; } one_argument( argument, arg ); if ( ch->mount ) { send_to_char( "You can't get close enough while mounted.\n\r", ch ); return; } if ( arg[0] == '\0' ) { send_to_char( "Backstab whom?\n\r", ch ); return; } if ( ( victim = get_char_room( ch, arg ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( victim == ch ) { send_to_char( "How can you sneak up on yourself?\n\r", ch ); return; } if ( is_safe( ch, victim ) ) return; /* Added stabbing weapon. -Narn */ if ( ( obj = get_eq_char( ch, WEAR_WIELD ) ) == NULL || ( obj->value[3] != DAM_STAB && obj->value[3] != DAM_PIERCE && obj->value[3] != DAM_STING) ) { send_to_char( "You need to wield a piercing or stabbing weapon.\n\r", ch ); return; } percent = number_percent() - (get_curr_lck(victim) - 14) + (get_curr_lck(ch) - 13); if ( !IS_NPC(victim) && CanUseSkill(victim, gsn_avoid_back_attack) && percent < LEARNED(victim, gsn_avoid_back_attack) ) { act( AT_DANGER, "You avoid a back attack from $N!", victim, NULL, ch, TO_CHAR); act( AT_DANGER, "$n avoided your attack!", victim, NULL, ch, TO_VICT); learn_from_success( victim, gsn_avoid_back_attack ); return; } percent = number_percent( ) - (get_curr_lck(ch) - 14) + (get_curr_lck(victim) - 13); check_attacker( ch, victim ); check_illegal_pk( ch, victim ); spell_lag(ch, gsn_backstab); if ( !IS_AWAKE(victim) || IS_NPC(ch) || percent < LEARNED(ch, gsn_backstab) ) { global_retcode = multi_hit( ch, victim, gsn_backstab ); adjust_favor( ch, 10, 1 ); } else { learn_from_failure( ch, gsn_backstab ); global_retcode = damage( ch, victim, 0, gsn_backstab ); } return; } void do_meditate( CHAR_DATA *ch, char *argument ) { if (is_affected(ch, gsn_mindwipe) || is_affected(ch, gsn_mindwipe)) { send_to_char("Der, what is that?\n\r", ch); return; } if ( ch->mount ) { send_to_char( "I doubt your mount would hold still enough.\n\r", ch ); return; } if ( !IS_AWAKE(ch) ) { send_to_char( "You seem too tired.\n\r", ch ); return; } spell_lag(ch, gsn_meditate); if ( IS_NPC(ch) || number_percent() < LEARNED(ch, gsn_meditate) ) { send_to_char("You sit down and begin humming.\n\r", ch); if (GET_LEVEL(ch, CLASS_PSIONIST)<10) send_to_char("(Remember: to visit the psionist guild, type psitrain when meditating)\n\r", ch); GET_POS(ch) = POS_MEDITATING; } else learn_from_failure( ch, gsn_meditate ); return; } void do_rescue( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; CHAR_DATA *fch; int percent; if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Rescue whom?\n\r", ch ); return; } if ( ( victim = get_char_room( ch, arg ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( victim == ch ) { send_to_char( "How about fleeing instead?\n\r", ch ); return; } if ( ch->mount ) { send_to_char( "You can't do that while mounted.\n\r", ch ); return; } if ( !IS_NPC(ch) && IS_NPC(victim) ) { send_to_char( "Doesn't need your help!\n\r", ch ); return; } if ( !ch->fighting ) { send_to_char( "Too late...\n\r", ch ); return; } if ( ( fch = who_fighting( victim) ) == NULL ) { send_to_char( "They are not fighting right now.\n\r", ch ); return; } percent = number_percent( ) - (get_curr_lck(ch) - 14) - (get_curr_lck(victim) - 16); spell_lag(ch, gsn_rescue); if ( !IS_NPC(ch) && percent > LEARNED(ch, gsn_rescue) ) { send_to_char( "You fail the rescue.\n\r", ch ); 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->fighting ) stop_fighting( ch, FALSE ); /* check_killer( ch, fch ); */ set_fighting( ch, fch ); set_fighting( fch, ch ); return; } void kick_messages(CHAR_DATA *ch, CHAR_DATA *victim, int hard_damage) { int i, soft_damage; soft_damage = hard_damage; if (IS_RESIS(victim, RIS_BLUNT)) soft_damage /= 2; if (IS_AFFECTED(victim, AFF_SANCTUARY)) soft_damage /= 2; if (IS_IMMUNE(victim, RIS_BLUNT)) soft_damage = 0; switch(GET_RACE(victim)) { case RACE_HUMAN: case RACE_ELVEN: case RACE_DWARF: case RACE_DROW: case RACE_ORC: case RACE_LYCANTH: case RACE_TROLL: case RACE_DEMON: case RACE_DEVIL: case RACE_MFLAYER: case RACE_ASTRAL: case RACE_PATRYN: case RACE_SARTAN: case RACE_DRAAGDIM: case RACE_GOLEM: case RACE_TROGMAN: case RACE_LIZARDMAN: case RACE_HALF_ELVEN: case RACE_HALF_OGRE: case RACE_HALF_ORC: case RACE_HALF_GIANT: i=number_range(0,3); break; case RACE_PREDATOR: case RACE_HERBIV: case RACE_LABRAT: i=number_range(4,6); break; case RACE_REPTILE: case RACE_DRAGON: case RACE_DRAGON_RED : case RACE_DRAGON_BLACK : case RACE_DRAGON_GREEN : case RACE_DRAGON_WHITE : case RACE_DRAGON_BLUE : case RACE_DRAGON_SILVER : case RACE_DRAGON_GOLD : case RACE_DRAGON_BRONZE : case RACE_DRAGON_COPPER : case RACE_DRAGON_BRASS : i=number_range(4,7); break; case RACE_TREE: i=8; break; case RACE_PARASITE: case RACE_SLIME: case RACE_VEGGIE: case RACE_VEGMAN: i=9; break; case RACE_ROO: case RACE_GNOME: case RACE_HALFLING: case RACE_GOBLIN: case RACE_SMURF: case RACE_ENFAN: i=10; break; case RACE_GIANT: case RACE_GIANT_HILL : case RACE_GIANT_FROST : case RACE_GIANT_FIRE : case RACE_GIANT_CLOUD : case RACE_GIANT_STORM : case RACE_GIANT_STONE : case RACE_TYTAN: case RACE_GOD: i=11; break; case RACE_GHOST: i=12; break; case RACE_BIRD: case RACE_SKEXIE: i=13; break; case RACE_UNDEAD: case RACE_UNDEAD_VAMPIRE : case RACE_UNDEAD_LICH : case RACE_UNDEAD_WIGHT : case RACE_UNDEAD_GHAST : case RACE_UNDEAD_SPECTRE : case RACE_UNDEAD_ZOMBIE : case RACE_UNDEAD_SKELETON : case RACE_UNDEAD_GHOUL : i=14; break; case RACE_DINOSAUR: i=15; break; case RACE_INSECT: case RACE_ARACHNID: i=16; break; case RACE_FISH: i=17; break; default: i=18; }; if(!soft_damage){ act(AT_GREY, att_kick_miss_ch[i], ch, NULL, victim, TO_CHAR); act(AT_GREY, att_kick_miss_victim[i], ch, NULL, victim, TO_VICT); act(AT_GREY, att_kick_miss_room[i], ch, NULL, victim, TO_NOTVICT); } else if(soft_damage > GET_HIT(victim)) { act(AT_GREY, att_kick_kill_ch[i], ch, NULL, victim, TO_CHAR); act(AT_GREY, att_kick_kill_victim[i], ch, NULL, victim, TO_VICT); act(AT_GREY, att_kick_kill_room[i], ch, NULL, victim, TO_NOTVICT); } else { act(AT_GREY, att_kick_hit_ch[i], ch, NULL, victim, TO_CHAR); act(AT_GREY, att_kick_hit_victim[i], ch, NULL, victim, TO_VICT); act(AT_GREY, att_kick_hit_room[i],ch, NULL, victim, TO_NOTVICT); } } void do_kick( CHAR_DATA *ch, char *argument ) { int dam; CHAR_DATA *victim; if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } if ( !IS_NPC(ch) && !CanUseSkill(ch, gsn_kick) ) { send_to_char( "You better leave the martial arts to fighters.\n\r", ch ); return; } if ( !(victim = who_fighting(ch)) ) if ( !(victim = get_char_room(ch, argument)) ) { send_to_char("They aren't here.\n\r", ch ); return; } if ( !is_legal_kill(ch, victim) || is_safe(ch, victim) ) { send_to_char("You can't do that!\n\r", ch); return; } dam = IS_ACTIVE(ch, CLASS_MONK)? GetMaxLevel(ch):(GetMaxLevel(ch)/2); spell_lag(ch, gsn_kick); if ( (IS_NPC(ch) || number_percent( ) < LEARNED(ch, gsn_kick) ) && GET_RACE(victim)!=RACE_GHOST) { learn_from_success( ch, gsn_kick ); kick_messages(ch, victim, dam); global_retcode = damage( ch, victim, dam, gsn_kick); } else { learn_from_failure( ch, gsn_kick ); kick_messages(ch, victim, 0); global_retcode = damage( ch, victim, 0, gsn_kick ); } return; } void do_punch( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } if ( !IS_NPC(ch) && !CanUseSkill(ch, gsn_punch) ) { send_to_char( "You better leave the martial arts to fighters.\n\r", ch ); return; } if ( ( victim = who_fighting( ch ) ) == NULL ) if ( !(victim = get_char_room(ch, argument)) ) { send_to_char("They aren't here.\n\r", ch ); return; } if (ch == victim) { send_to_char("You try to punch yourself, but fail!\n\r", ch); return; } spell_lag(ch, gsn_punch); if ( IS_NPC(ch) || number_percent( ) < LEARNED(ch, gsn_punch) ) { learn_from_success( ch, gsn_punch ); global_retcode = damage( ch, victim, number_range( 1, GetMaxLevel(ch)), gsn_punch ); } else { learn_from_failure( ch, gsn_punch ); global_retcode = damage( ch, victim, 0, gsn_punch ); } return; } void do_bite( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } if ( !IS_NPC(ch) && !CanUseSkill(ch, gsn_bite) ) { send_to_char( "That isn't quite one of your natural skills.\n\r", ch ); return; } if ( ( victim = who_fighting( ch ) ) == NULL ) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } spell_lag(ch, gsn_bite); if ( IS_NPC(ch) || number_percent( ) < LEARNED(ch, gsn_bite) ) { learn_from_success( ch, gsn_bite ); global_retcode = damage( ch, victim, number_range( 1, GetMaxLevel(ch) ), gsn_bite ); } else { learn_from_failure( ch, gsn_bite ); global_retcode = damage( ch, victim, 0, gsn_bite ); } return; } void do_claw( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; if ( !IS_NPC(ch) && !CanUseSkill(ch, gsn_claw) ) { send_to_char( "That isn't quite one of your natural skills.\n\r", ch ); return; } if ( ( victim = who_fighting( ch ) ) == NULL ) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } spell_lag(ch, gsn_claw); if ( IS_NPC(ch) || number_percent( ) < LEARNED(ch, gsn_claw) ) { learn_from_success( ch, gsn_claw ); global_retcode = damage( ch, victim, number_range( 1, GetMaxLevel(ch) ), gsn_claw ); } else { learn_from_failure( ch, gsn_claw ); global_retcode = damage( ch, victim, 0, gsn_claw ); } return; } void do_sting( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } if ( !IS_NPC(ch) && !CanUseSkill(ch, gsn_sting) ) { send_to_char( "That isn't quite one of your natural skills.\n\r", ch ); return; } if ( ( victim = who_fighting( ch ) ) == NULL ) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } spell_lag(ch, gsn_sting); if ( IS_NPC(ch) || number_percent( ) < LEARNED(ch, gsn_sting) ) { learn_from_success( ch, gsn_sting ); global_retcode = damage( ch, victim, number_range( 1, GetMaxLevel(ch) ), gsn_sting ); } else { learn_from_failure( ch, gsn_sting ); global_retcode = damage( ch, victim, 0, gsn_sting ); } return; } void do_tail( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } if ( !IS_NPC(ch) && !CanUseSkill(ch, gsn_tail) ) { send_to_char( "That isn't quite one of your natural skills.\n\r", ch ); return; } if ( ( victim = who_fighting( ch ) ) == NULL ) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } spell_lag(ch, gsn_tail); if ( IS_NPC(ch) || number_percent( ) < LEARNED(ch, gsn_tail) ) { learn_from_success( ch, gsn_tail ); global_retcode = damage( ch, victim, number_range( 1, GetMaxLevel(ch) ), gsn_tail ); } else { learn_from_failure( ch, gsn_tail ); global_retcode = damage( ch, victim, 0, gsn_tail ); } return; } void do_bash( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; int chance; if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } if ( !IS_NPC(ch) && !CanUseSkill(ch, gsn_bash) ) { send_to_char("You better leave the martial arts to fighters.\n\r", ch ); return; } if ( ( victim = who_fighting( ch ) ) == NULL ) if ( !(victim = get_char_room(ch, argument)) ) { send_to_char("They aren't here.\n\r", ch ); return; } if (ch == victim) { send_to_char("You try to bash yourself, but fail!\n\r", ch); return; } if ((IS_NPC(victim) && IS_SET(victim->act, ACT_HUGE)) || IS_SET(victim->affected_by2, AFF2_GROWTH) ) if (!IsGiant(ch) && !IS_SET(ch->affected_by2, AFF2_GROWTH)) { ch_printf(ch, "%s is MUCH too large to bash!\n\r", PERS(victim, ch)); return; } chance = ( (get_curr_dex(victim) + get_curr_str(victim) + GetMaxLevel(victim)) - (get_curr_dex(ch) + get_curr_str(ch) + GetMaxLevel(ch)) ); if ( victim->fighting && victim->fighting->who != ch ) chance += 25; spell_lag(ch, gsn_bash); if ( IS_NPC(ch) || (number_percent( ) + chance) < LEARNED(ch, gsn_bash) ) { WAIT_STATE( ch, 2 * PULSE_VIOLENCE ); WAIT_STATE( victim, 2 * PULSE_VIOLENCE ); victim->position = POS_SITTING; global_retcode = damage( ch, victim, number_range( 1, 2 ), gsn_bash ); } else { WAIT_STATE( ch, 2 * PULSE_VIOLENCE ); learn_from_failure( ch, gsn_bash ); ch->position = POS_SITTING; global_retcode = damage( ch, victim, 0, gsn_bash ); } } void do_stun( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; AFFECT_DATA af; int chance; bool fail; if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } if ( !IS_NPC(ch) && !CanUseSkill(ch, gsn_stun) ) { send_to_char( "You better leave the martial arts to fighters.\n\r", ch ); return; } if ( ( victim = who_fighting( ch ) ) == NULL ) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } if ( GET_MOVE(ch) < 16 ) { set_char_color( AT_SKILL, ch ); send_to_char( "You are far too tired to do that.\n\r", ch ); return; /* missing return fixed March 11/96 */ } spell_lag(ch, gsn_stun); fail = FALSE; chance = ris_save( victim, ch->levels[BestSkCl(ch, gsn_stun)], RIS_PARALYSIS ); if ( chance == 1000 ) fail = TRUE; else fail = saves_para_petri( chance, victim ); chance = (((get_curr_dex(victim) + get_curr_str(victim)) - (get_curr_dex(ch) + get_curr_str(ch))) * 10) + 10; /* harder for player to stun another player */ if ( !IS_NPC(ch) && !IS_NPC(victim) ) chance += sysdata.stun_plr_vs_plr; else chance += sysdata.stun_regular; if ( !fail && ( IS_NPC(ch) || (number_percent( ) + chance) < LEARNED(ch, gsn_stun) ) ) { learn_from_success( ch, gsn_stun ); /* DO *NOT* CHANGE! -Thoric */ GET_MOVE(ch) -= 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 ( !IS_AFFECTED( victim, AFF_PARALYSIS ) ) { 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 ); GET_MOVE(ch) -= 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 ); } return; } void do_feed( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; sh_int dam; if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } if ( !IS_NPC(ch) && !IS_VAMPIRE(ch) ) { send_to_char( "It is not of your nature to feed on living creatures.\n\r", ch ); return; } if ( !IS_NPC(ch) && !LEARNED(ch, gsn_feed) ) { send_to_char( "You have not yet practiced your new teeth.\n\r", ch ); return; } if ( ( victim = who_fighting( ch ) ) == NULL ) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } if ( ch->mount ) { send_to_char( "You can't do that while mounted.\n\r", ch ); return; } spell_lag(ch, gsn_feed); if ( IS_NPC(ch) || number_percent( ) < LEARNED(ch, gsn_feed) ) { dam = number_range( 1, ch->levels[CLASS_VAMPIRE] ); global_retcode = damage( ch, victim, dam, gsn_feed ); if ( global_retcode == rNONE && !IS_NPC(ch) && dam && ch->fighting && GET_COND(ch, COND_BLOODTHIRST) < (GET_MAX_BLOOD(ch)) ) { gain_condition( ch, COND_BLOODTHIRST, UMIN( number_range(1, (ch->levels[CLASS_VAMPIRE]+ GetMaxLevel(victim) / 20) + 3 ), GET_MAX_BLOOD(ch) - GET_COND(ch, 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 && !IS_NPC(ch) && ch->fighting && GET_COND(ch, COND_BLOODTHIRST) < (GET_MAX_BLOOD(ch)) ) { 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( CHAR_DATA *ch, CHAR_DATA *victim ) { OBJ_DATA *obj, *tmpobj; if ( ( obj = get_eq_char( victim, WEAR_WIELD ) ) == NULL ) return; if ( ( tmpobj = get_eq_char( victim, WEAR_DUAL_WIELD ) ) != NULL && 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 ( IS_NPC( ch ) && !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 ( IS_NPC(victim) || ( IS_OBJ_STAT(obj, ITEM_LOYAL) && IS_PKILL(victim) ) ) obj_to_char( obj, victim ); else obj_to_room( obj, victim->in_room ); return; } void do_disarm( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; OBJ_DATA *obj; int percent; if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } if ( !IS_NPC(ch) && !CanUseSkill(ch, gsn_disarm) ) { send_to_char( "You don't know how to disarm opponents.\n\r", ch ); return; } if ( get_eq_char( ch, WEAR_WIELD ) == NULL ) { send_to_char( "You must wield a weapon to disarm.\n\r", ch ); return; } if ( ( victim = who_fighting( ch ) ) == NULL ) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } if ( ( obj = get_eq_char( victim, WEAR_WIELD ) ) == NULL ) { send_to_char( "Your opponent is not wielding a weapon.\n\r", ch ); return; } spell_lag(ch, gsn_disarm); percent = number_percent( ) + GetMaxLevel(victim) - ch->levels[BestSkCl(ch, gsn_disarm)] - (get_curr_lck(ch) - 15) + (get_curr_lck(victim) - 15); if ( !can_see_obj( ch, obj ) ) percent += 10; if ( IS_NPC(ch) || percent < LEARNED(ch, gsn_disarm) * 2 / 3 ) disarm( ch, victim ); else { send_to_char( "You failed.\n\r", ch ); learn_from_failure( ch, gsn_disarm ); } return; } /* * Trip a creature. * Caller must check for successful attack. */ void trip( CHAR_DATA *ch, CHAR_DATA *victim ) { if (GET_POS(victim) == POS_SITTING) { send_to_char("They are already on the ground.\n\r", ch); return; } if ( IS_AFFECTED( victim, AFF_FLYING ) || IS_AFFECTED( victim, AFF_FLOATING ) ) { act( AT_SKILL, "$n trys to trip you, buy you nimbly float away!", ch, NULL, victim, TO_VICT ); act( AT_SKILL, "$N nimbly floats away from your well placed trip!", ch, NULL, victim, TO_CHAR ); act( AT_SKILL, "$N nimbly floats away from $n's well placed trip!", ch, NULL, victim, TO_NOTVICT ); return; } if ( victim->mount ) { if ( IS_AFFECTED( victim->mount, AFF_FLYING ) || IS_AFFECTED( victim->mount, AFF_FLOATING ) ) 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 ); REMOVE_BIT( victim->mount->act, ACT_MOUNTED ); victim->mount = NULL; WAIT_STATE( ch, 2 * PULSE_VIOLENCE ); WAIT_STATE( victim, 2 * PULSE_VIOLENCE ); victim->position = POS_SITTING; return; } else { 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->position = POS_SITTING; } return; } void do_legsweep( CHAR_DATA *ch, char *argument ) { int gsn_legsweep = skill_lookup("legsweep"); CHAR_DATA *victim; int fl = 0; if (!ch) return; if ( ( victim = who_fighting( ch ) ) == NULL ) if ( !(victim = get_char_room(ch, argument)) ) { send_to_char("They aren't here.\n\r", ch ); return; } if (ch == victim) { send_to_char("You try to legsweep yourself, but fail!\n\r", ch); return; } if (HAS_BODYPART(victim, PART_FORELEGS)) fl = 20; if (!CanUseSkill(ch, gsn_legsweep)) { send_to_char("Leave the martial arts to fighters!\n\r", ch); return; } if ((number_percent()+fl) > (IS_NPC(ch)? 80:LEARNED(ch, gsn_legsweep)) ) { send_to_char("You fail and fall down!\n\r", ch); ch->position = POS_SITTING; learn_from_failure(ch, gsn_legsweep); return; } if (!HAS_BODYPART(victim, PART_LEGS) && !HAS_BODYPART(victim, PART_FORELEGS)) { send_to_char("How can you legsweep something with no legs?\n\r", ch); return; } trip(ch, victim); } void do_pick( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *gch; OBJ_DATA *obj; EXIT_DATA *pexit; if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Pick what?\n\r", ch ); return; } if ( ms_find_obj(ch) ) return; if ( ch->mount ) { send_to_char( "You can't do that while mounted.\n\r", ch ); return; } spell_lag(ch, gsn_pick_lock); /* look for guards */ for ( gch = ch->in_room->first_person; gch; gch = gch->next_in_room ) { if ( IS_NPC(gch) && IS_AWAKE(gch) && GetMaxLevel(ch) + 5 < GetMaxLevel(gch) ) { act( AT_SKILL, "$N is standing too close to the lock.", ch, NULL, gch, TO_CHAR ); return; } } if ( !IS_NPC(ch) && number_percent( ) > LEARNED(ch, gsn_pick_lock) ) { send_to_char( "You failed.\n\r", ch); learn_from_failure( ch, gsn_pick_lock ); return; } if ( ( pexit = find_door( ch, arg, TRUE ) ) != NULL ) { /* 'pick door' */ /* ROOM_INDEX_DATA *to_room; */ /* Unused */ EXIT_DATA *pexit_rev; if ( !IS_SET(pexit->exit_info, EX_CLOSED) ) { send_to_char( "It's not closed.\n\r", ch ); return; } if ( pexit->key < 0 ) { send_to_char( "It can't be picked.\n\r", ch ); return; } if ( !IS_SET(pexit->exit_info, EX_LOCKED) ) { send_to_char( "It's already unlocked.\n\r", ch ); return; } if ( IS_SET(pexit->exit_info, EX_PICKPROOF) ) { send_to_char( "You failed.\n\r", ch ); learn_from_failure( ch, gsn_pick_lock ); check_room_for_traps( ch, TRAP_PICK | trap_door[pexit->vdir] ); return; } REMOVE_BIT(pexit->exit_info, EX_LOCKED); send_to_char( "*Click*\n\r", ch ); 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->to_room == ch->in_room ) { REMOVE_BIT( pexit_rev->exit_info, EX_LOCKED ); } 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 ) { send_to_char( "That's not a container.\n\r", ch ); return; } if ( !IS_SET(obj->value[1], CONT_CLOSED) ) { send_to_char( "It's not closed.\n\r", ch ); return; } if ( obj->value[2] < 0 ) { send_to_char( "It can't be unlocked.\n\r", ch ); return; } if ( !IS_SET(obj->value[1], CONT_LOCKED) ) { send_to_char( "It's already unlocked.\n\r", ch ); return; } if ( IS_SET(obj->value[1], CONT_PICKPROOF) ) { send_to_char( "You failed.\n\r", ch ); 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); send_to_char( "*Click*\n\r", ch ); 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_printf( ch, "You see no %s here.\n\r", arg ); return; } void do_sneak( CHAR_DATA *ch, char *argument ) { AFFECT_DATA af; if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } if ( ch->mount ) { send_to_char( "You can't do that while mounted.\n\r", ch ); return; } send_to_char( "You attempt to move silently.\n\r", ch ); affect_strip( ch, gsn_sneak ); if ( IS_NPC(ch) || number_percent( ) < LEARNED(ch, gsn_sneak) ) { af.type = gsn_sneak; af.duration = (int)((float)ch->levels[BestSkCl(ch, gsn_sneak)] * 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( CHAR_DATA *ch, char *argument ) { if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } if ( ch->mount ) { send_to_char( "You can't do that while mounted.\n\r", ch ); return; } send_to_char( "You attempt to hide.\n\r", ch ); if ( IS_AFFECTED(ch, AFF_HIDE) ) REMOVE_BIT(ch->affected_by, AFF_HIDE); if ( IS_NPC(ch) || number_percent( ) < LEARNED(ch, gsn_hide) ) { SET_BIT(ch->affected_by, AFF_HIDE); learn_from_success( ch, gsn_hide ); } else learn_from_failure( ch, gsn_hide ); return; } /* * Contributed by Alander. */ void do_visible( CHAR_DATA *ch, char *argument ) { affect_strip ( ch, gsn_invis ); affect_strip ( ch, gsn_group_invis ); affect_strip ( ch, gsn_sneak ); REMOVE_BIT ( ch->affected_by, AFF_HIDE ); REMOVE_BIT ( ch->affected_by, AFF_INVISIBLE ); if (ch->race != RACE_HALFLING) /* Halfling has perm sneak SB */ REMOVE_BIT ( ch->affected_by, AFF_SNEAK ); if (!IS_NPC(ch)) ch->pcdata->wizinvis = 0; if (IS_NPC(ch)) ch->mobinvis = 0; send_to_char( "Ok.\n\r", ch ); return; } void do_recall( CHAR_DATA *ch, char *argument ) { if ( IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL) ) { send_to_char( "For some strange reason... nothing happens.\n\r", ch ); return; } if ( who_fighting( ch ) ) { send_to_char("You cannot recall while fighting.\n\r",ch); return; } act( AT_ACTION, "$n disappears in a swirl of smoke.", ch, NULL, NULL, TO_ROOM ); recall_char( ch ); if ( ch->mount ) { char_from_room( ch->mount ); char_to_room( ch->mount, ch->in_room ); } act( AT_ACTION, "$n appears in the room.", ch, NULL, NULL, TO_ROOM ); do_look( ch, "auto" ); return; } void do_aid( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; int percent; if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't concentrate enough for that.\n\r", ch ); return; } one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Aid whom?\n\r", ch ); return; } if ( ( victim = get_char_room( ch, arg ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( ch->mount ) { send_to_char( "You can't do that while mounted.\n\r", ch ); return; } if ( victim == ch ) { send_to_char( "Aid yourself?\n\r", ch ); return; } if ( victim->position > POS_STUNNED ) { act( AT_SKILL, "$N doesn't need your help.", ch, NULL, victim, TO_CHAR); return; } if ( GET_HIT(victim) <= -6 ) { act( AT_SKILL, "$N's condition is beyond your aiding ability.", ch, NULL, victim, TO_CHAR); return; } percent = number_percent( ) - (get_curr_lck(ch) - 13); spell_lag(ch, gsn_aid); if ( !IS_NPC(ch) && percent > LEARNED(ch, gsn_aid) ) { send_to_char( "You fail.\n\r", ch ); 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 ( GET_HIT(victim) < 1 ) GET_HIT(victim) = 1; update_pos( victim ); act( AT_SKILL, "$n aids you!", ch, NULL, victim, TO_VICT ); return; } int mount_ego_check(CHAR_DATA *ch, CHAR_DATA *horse) { int ride_ego, drag_ego, align, check; if (IsDragon(horse)) { drag_ego = GetMaxLevel(horse)*2; if (IS_ACT_FLAG(horse, ACT_AGGRESSIVE) || IS_ACT_FLAG(horse, ACT_META_AGGR)) { drag_ego += GetMaxLevel(horse); } ride_ego = LEARNED(ch, gsn_mount)/10 + GetMaxLevel(ch)/2; if (is_affected(ch, gsn_dragon_ride)) { ride_ego += ((get_curr_int(ch) + get_curr_wis(ch))/2); } align = GET_ALIGN(ch) - GET_ALIGN(horse); if (align < 0) align = -align; align/=100; align -= 5; drag_ego += align; if (GET_HIT(horse) > 0) drag_ego -= GET_MAX_HIT(horse)/GET_HIT(horse); else drag_ego = 0; if (GET_HIT(ch) > 0) ride_ego -= GET_MAX_HIT(ch)/GET_HIT(ch); else ride_ego = 0; check = drag_ego+number_range(1,10)-(ride_ego+number_range(1,10)); return(check); } else { drag_ego = GetMaxLevel(horse); if (drag_ego > 15) drag_ego *= 2; ride_ego = LEARNED(ch, gsn_mount)/10 + GetMaxLevel(ch); if (is_affected(ch, gsn_dragon_ride)) { ride_ego += (get_curr_int(ch) + get_curr_wis(ch)); } check = drag_ego+number_range(1,5)-(ride_ego+number_range(1,10)); return(check); } } void do_mount( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; sh_int learned; int check; if ( !IS_NPC(ch) && !CanUseSkill(ch, gsn_mount) ) { send_to_char( "I don't think that would be a good idea...\n\r", ch ); return; } if ( ch->mount ) { send_to_char( "You're already mounted!\n\r", ch ); return; } if ( ( victim = get_char_room( ch, argument ) ) == NULL ) { send_to_char( "You can't find that here.\n\r", ch ); return; } if (!IS_NPC(victim) || (!IS_SET(victim->act, ACT_MOUNTABLE) && GET_RACE(victim) != RACE_HORSE && !IsDragon(victim))) { send_to_char( "You can't mount that!\n\r", ch ); return; } if ( IS_SET(victim->act, ACT_MOUNTED ) ) { send_to_char( "That mount already has a rider.\n\r", ch ); return; } if ( victim->position < POS_STANDING ) { send_to_char( "Your mount must be standing.\n\r", ch ); return; } if ( victim->position == POS_FIGHTING || victim->fighting ) { send_to_char( "Your mount is moving around too much.\n\r", ch ); return; } spell_lag(ch, gsn_mount); check = mount_ego_check(ch, victim); if (check > 5) { act(AT_SKILL, "$N snarls and attacks!", ch, NULL, victim, TO_CHAR); act(AT_SKILL, "As $n tries to mount $N, $N attacks $n!", ch, NULL, victim, TO_NOTVICT); one_hit(ch, victim, gsn_mount); return; } else if (check > -1) { act(AT_SKILL, "$N moves out of the way and you fall on your butt.", ch, NULL, victim, TO_CHAR); act(AT_SKILL, "as $n tries to mount $N, $N moves out of the way", ch, NULL, victim, TO_NOTVICT); GET_POS(ch) = POS_SITTING; return; } learned = LEARNED(ch, gsn_mount); if (is_affected(ch, gsn_dragon_ride)) learned += GET_LEVEL(ch, BestMagicClass(ch)); if ( IS_NPC(ch) || number_percent( ) < learned ) { SET_BIT( victim->act, 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 ); GET_POS(ch) = 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( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; if ( (victim = ch->mount) == NULL ) { send_to_char( "You're not mounted.\n\r", ch ); return; } spell_lag(ch, gsn_mount); if ( IS_NPC(ch) || number_percent( ) < LEARNED(ch, 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 ); REMOVE_BIT( victim->act, ACT_MOUNTED ); ch->mount = NULL; ch->position = 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 ); REMOVE_BIT( victim->act, ACT_MOUNTED ); ch->mount = NULL; ch->position = POS_SITTING; global_retcode = damage( ch, ch, 1, gsn_mount ); } return; } /**************************************************************************/ /* * Check for parry. */ int check_parry( CHAR_DATA *ch, CHAR_DATA *victim, int dam ) { int chances; if ( !IS_AWAKE(victim) ) return dam; if ( IS_NPC(victim) && !IS_SET(victim->defenses, DFND_PARRY) ) return dam; if (!LEARNED(ch, gsn_parry)) return dam; if ( IS_NPC(victim) ) { /* Tuan was here. :) */ /* Heath was here bigger, badder, AND more recently! */ chances = UMIN( 60, 2 * GetMaxLevel(victim) ); } else { if ( get_eq_char( victim, WEAR_WIELD ) == NULL ) return dam; chances = (int) (LEARNED(victim, gsn_parry) / 2); } /* Put in the call to chance() to allow penalties for misaligned clannies. */ if ( !chance( victim, chances + GetMaxLevel(victim) - GetMaxLevel(ch) ) ) { learn_from_failure( victim, gsn_parry ); return dam; } if ( dam == 0 ) { if ( !IS_NPC(victim) && !IS_SET( victim->pcdata->flags, PCFLAG_GAG) ) act( AT_SKILL, "You parry $n's attack.", ch, NULL, victim, TO_VICT ); if ( !IS_NPC(ch) && !IS_SET( ch->pcdata->flags, PCFLAG_GAG) ) act( AT_SKILL, "$N parries your attack.", ch, NULL, victim, TO_CHAR ); } learn_from_success( victim, gsn_parry ); return dam; } /* * Check for dodge. */ int check_dodge( CHAR_DATA *ch, CHAR_DATA *victim, int dam ) { int chances; if ( !IS_AWAKE(victim) ) return dam; if ( IS_NPC(victim) && !IS_SET(victim->defenses, DFND_DODGE) ) return dam; if ( !IS_NPC(victim) && !LEARNED(victim, gsn_dodge)) return dam; if ( IS_NPC(victim) ) chances = UMIN( 60, 2 * GetMaxLevel(victim) ); else chances = (int) (LEARNED(victim, gsn_dodge) / 2); /* Consider luck as a factor */ if ( !chance( victim, chances + GetMaxLevel(victim) - GetMaxLevel(ch)) ) { learn_from_failure( victim, gsn_dodge ); return dam; } learn_from_success( victim, gsn_dodge ); dam -= number_range(1,3); if (!IS_NPC(victim) && IS_ACTIVE(victim,CLASS_MONK) && number_range(1,20000)<LEARNED(victim, gsn_dodge)*GET_LEVEL(ch,CLASS_MONK)) dam = 0; else dam -= (GET_LEVEL(ch,CLASS_MONK)/10); if ( dam == 0 ) { if ( !IS_NPC(victim) && !IS_SET( victim->pcdata->flags, PCFLAG_GAG) ) act( AT_SKILL, "You dodge $n's attack.", ch, NULL, victim, TO_VICT ); if ( !IS_NPC(ch) && !IS_SET( ch->pcdata->flags, PCFLAG_GAG) ) act( AT_SKILL, "$N dodges your attack.", ch, NULL, victim, TO_CHAR ); } return dam; } void do_poison_weapon( CHAR_DATA *ch, char *argument ) { OBJ_DATA *obj; OBJ_DATA *pobj; OBJ_DATA *wobj; char arg [ MAX_INPUT_LENGTH ]; int percent; if ( !IS_NPC( ch ) && !CanUseSkill(ch, gsn_poison_weapon) ) { send_to_char( "What do you think you are, a thief?\n\r", ch ); return; } one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "What are you trying to poison?\n\r", ch ); return; } if ( ch->fighting ) { send_to_char( "While you're fighting? Nice try.\n\r", ch ); return; } if ( ms_find_obj(ch) ) return; if ( !( obj = get_obj_carry( ch, arg ) ) ) { send_to_char( "You do not have that weapon.\n\r", ch ); return; } if ( obj->item_type != ITEM_WEAPON ) { send_to_char( "That item is not a weapon.\n\r", ch ); return; } if ( IS_OBJ_STAT( obj, ITEM_POISONED ) ) { send_to_char( "That weapon is already poisoned.\n\r", ch ); return; } /* Now we have a valid weapon...check to see if we have the powder. */ for ( pobj = ch->first_carrying; pobj; pobj = pobj->next_content ) { if ( pobj->vnum == OBJ_VNUM_BLACK_POWDER ) break; } if ( !pobj ) { send_to_char( "You do not have the black poison powder.\n\r", ch ); return; } /* Okay, we have the powder...do we have water? */ for ( wobj = ch->first_carrying; wobj; wobj = wobj->next_content ) { if ( wobj->item_type == ITEM_DRINK_CON && wobj->value[1] > 0 && wobj->value[2] == 0 ) break; } if ( !wobj ) { send_to_char( "You have no water to mix with the powder.\n\r", ch ); return; } /* Great, we have the ingredients...but is the thief smart enough? */ if ( !IS_NPC( ch ) && get_curr_wis( ch ) < 16 ) { send_to_char( "You can't quite remember what to do...\n\r", ch ); return; } /* And does the thief have steady enough hands? */ if ( !IS_NPC( ch ) && ( (get_curr_dex( ch ) < 17) || GET_COND(ch, COND_DRUNK) > 0 ) ) { send_to_char("Your hands aren't steady enough to properly mix the poison.\n\r", ch ); return; } spell_lag(ch, gsn_poison_weapon); percent = (number_percent( ) - get_curr_lck(ch) - 14); /* Check the skill percentage */ separate_obj( pobj ); separate_obj( wobj ); if ( !IS_NPC( ch ) && percent > LEARNED(ch, gsn_poison_weapon) ) { set_char_color( AT_RED, ch ); send_to_char( "You failed and spill some on yourself. Ouch!\n\r", ch ); set_char_color( AT_GREY, ch ); damage( ch, ch, BestSkLv(ch, gsn_poison_weapon), 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 ); SET_BIT( obj->extra_flags, ITEM_POISONED ); obj->cost *= BestSkLv(ch, gsn_poison_weapon); /* Set an object timer. Don't want proliferation of poisoned weapons */ obj->timer = 10 + BestSkLv(ch, gsn_poison_weapon); if ( IS_OBJ_STAT( obj, ITEM_BLESS ) ) obj->timer *= 2; if ( IS_OBJ_STAT( obj, ITEM_MAGIC ) ) 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( CHAR_DATA *ch, char *argument ) { OBJ_DATA *scroll; int sn; char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char buf3[MAX_STRING_LENGTH]; int mana; if ( IS_NPC(ch) ) return; if ( !IS_NPC(ch) && !CanUseSkill(ch, gsn_scribe) ) { send_to_char( "A skill such as this requires more magical ability than that of your class.\n\r", ch ); return; } if ( argument[0] == '\0' || !str_cmp(argument, "") ) { send_to_char( "Scribe what?\n\r", ch ); return; } if ( ms_find_obj(ch) ) return; if ( (sn = find_spell( ch, argument, TRUE )) < 0 ) { send_to_char( "You have not learned that spell.\n\r", ch ); return; } if ( skill_table[sn]->spell_fun == spell_null ) { send_to_char( "That's not a spell!\n\r", ch ); return; } if ( SPELL_FLAG(skill_table[sn], SF_NOSCRIBE) ) { send_to_char( "You cannot scribe that spell.\n\r", ch ); return; } mana = IS_NPC(ch) ? 0 : UMAX(skill_table[sn]->min_mana, 100 / ( 2 + BestSkLv(ch, sn) - LowSkLv(ch, sn) ) ); mana *=5; if ( !IS_NPC(ch) && GET_MANA(ch) < mana ) { send_to_char( "You don't have enough mana.\n\r", ch ); return; } if ( ( scroll = get_eq_char( ch, WEAR_HOLD ) ) == NULL ) { send_to_char( "You must be holding a blank scroll to scribe it.\n\r", ch ); return; } if( scroll->vnum != OBJ_VNUM_SCROLL_SCRIBING ) { send_to_char( "You must be holding a blank scroll to scribe it.\n\r", ch ); return; } if ( ( scroll->value[1] != -1 ) && ( scroll->vnum == OBJ_VNUM_SCROLL_SCRIBING ) ) { send_to_char( "That scroll has already been inscribed.\n\r", ch); return; } if ( !process_spell_components( ch, sn ) ) { learn_from_failure( ch, gsn_scribe ); GET_MANA(ch) -= (mana / 2); return; } if ( !IS_NPC(ch) && number_percent( ) > LEARNED(ch, gsn_scribe) ) { set_char_color ( AT_MAGIC, ch ); send_to_char("You failed.\n\r", ch); learn_from_failure( ch, gsn_scribe ); GET_MANA(ch) -= (mana / 2); return; } scroll->value[1] = sn; scroll->value[0] = BestSkLv(ch, gsn_scribe); sprintf(buf1, "%s scroll", skill_table[sn]->name); STRFREE(scroll->short_descr); scroll->short_descr = STRALLOC( aoran(buf1) ); sprintf(buf2, "A glowing scroll inscribed '%s' lies in the dust.", skill_table[sn]->name); STRFREE(scroll->description); scroll->description = STRALLOC(buf2); sprintf(buf3, "scroll scribing %s", skill_table[sn]->name); STRFREE(scroll->name); scroll->name = STRALLOC(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 ); GET_MANA(ch) -= mana; } void do_brew( CHAR_DATA *ch, char *argument ) { OBJ_DATA *potion; OBJ_DATA *fire; int sn; char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char buf3[MAX_STRING_LENGTH]; int mana; bool found; if ( IS_NPC(ch) ) return; if ( !IS_NPC(ch) && !CanUseSkill(ch, gsn_brew) ) { send_to_char( "A skill such as this requires more magical ability than that of your ch_class.\n\r", ch ); return; } if ( argument[0] == '\0' || !str_cmp(argument, "") ) { send_to_char( "Brew what?\n\r", ch ); return; } if ( ms_find_obj(ch) ) return; if ( (sn = find_spell( ch, argument, TRUE )) < 0 ) { send_to_char( "You have not learned that spell.\n\r", ch ); return; } if ( skill_table[sn]->spell_fun == spell_null ) { send_to_char( "That's not a spell!\n\r", ch ); return; } if ( SPELL_FLAG(skill_table[sn], SF_NOBREW) ) { send_to_char( "You cannot brew that spell.\n\r", ch ); return; } mana = IS_NPC(ch) ? 0 : UMAX(skill_table[sn]->min_mana, 100 / ( 2 + BestSkLv(ch, gsn_brew) - LowSkLv(ch, sn))); mana *=4; if ( !IS_NPC(ch) && GET_MANA(ch) < mana ) { send_to_char( "You don't have enough mana.\n\r", ch ); return; } found = FALSE; for ( fire = ch->in_room->first_content; fire; fire = fire->next_content ) { if( fire->item_type == ITEM_FIRE) { found = TRUE; break; } } if ( !found ) { send_to_char( "There must be a fire in the room to brew a potion.\n\r", ch ); return; } if ( ( potion = get_eq_char( ch, WEAR_HOLD ) ) == NULL ) { send_to_char( "You must be holding an empty flask to brew a potion.\n\r", ch ); return; } if( potion->vnum != OBJ_VNUM_FLASK_BREWING ) { send_to_char( "You must be holding an empty flask to brew a potion.\n\r", ch ); return; } if ( ( potion->value[1] != -1 ) && ( potion->vnum == OBJ_VNUM_FLASK_BREWING ) ) { send_to_char( "That's not an empty flask.\n\r", ch); return; } if ( !process_spell_components( ch, sn ) ) { learn_from_failure( ch, gsn_brew ); GET_MANA(ch) -= (mana / 2); return; } if ( !IS_NPC(ch) && number_percent( ) > LEARNED(ch, gsn_brew) ) { set_char_color ( AT_MAGIC, ch ); send_to_char("You failed.\n\r", ch); learn_from_failure( ch, gsn_brew ); GET_MANA(ch) -= (mana / 2); return; } potion->value[1] = sn; potion->value[0] = BestSkLv(ch, gsn_brew); sprintf(buf1, "%s potion", skill_table[sn]->name); STRFREE(potion->short_descr); potion->short_descr = STRALLOC( aoran(buf1) ); sprintf(buf2, "A strange potion labelled '%s' sizzles in a glass flask.", skill_table[sn]->name); STRFREE(potion->description); potion->description = STRALLOC(buf2); sprintf(buf3, "flask potion %s", skill_table[sn]->name); STRFREE(potion->name); potion->name = STRALLOC(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 ); GET_MANA(ch) -= mana; } bool check_grip( CHAR_DATA *ch, CHAR_DATA *victim ) { int chance; if ( !IS_AWAKE(victim) ) return FALSE; if ( IS_NPC(victim) && !IS_SET(victim->defenses, DFND_GRIP) ) return FALSE; if ( IS_NPC(victim) ) chance = UMIN( 60, 2 * GetMaxLevel(victim) ); else chance = (int) (LEARNED(victim, gsn_grip) / 2); /* Consider luck as a factor */ chance += (2 * (get_curr_lck(victim) - 13 ) ); if ( number_percent( ) >= chance + GetMaxLevel(victim) - GetMaxLevel(ch) ) { 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 base_berserk(CHAR_DATA *ch) { AFFECT_DATA af; 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(GetMaxLevel(ch)/5, GetMaxLevel(ch)*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); send_to_char( "You start to lose control..\n\r", ch ); } /* Berserk and HitAll. -- Altrag */ void do_berserk( CHAR_DATA *ch, char *argument ) { sh_int percent; if ( !ch->fighting ) { send_to_char( "But you aren't fighting!\n\r", ch ); return; } if ( IS_AFFECTED(ch, AFF_BERSERK) ) { send_to_char( "Your rage is already at its peak!\n\r", ch ); return; } percent = IS_NPC(ch) ? 80 : LEARNED(ch, gsn_berserk); spell_lag(ch, gsn_berserk); if ( !chance(ch, percent) ) { send_to_char( "You couldn't build up enough rage.\n\r", ch); learn_from_failure(ch, gsn_berserk); return; } base_berserk(ch); learn_from_success(ch, gsn_berserk); return; } bool check_illegal_psteal( CHAR_DATA *ch, CHAR_DATA *victim ) { if (!IS_NPC (victim) && !IS_NPC(ch)) { if ( ( !IS_SET( victim->pcdata->flags, PCFLAG_DEADLY ) || GetMaxLevel(ch) - GetMaxLevel(victim) > 10 || !IS_SET( ch->pcdata->flags, PCFLAG_DEADLY ) ) && ( ch->in_room->vnum < 29 || ch->in_room->vnum > 43 ) && ch != victim ) { /* sprintf( log_buf, "%s illegally stealing from %s at %d", (IS_NPC(ch) ? ch->short_descr : ch->name), victim->name, victim->in_room->vnum ); log_string_plus( log_buf,LOG_MONITOR,LEVEL_IMMORTAL); */ return TRUE; } } return FALSE; } static char *dir_desc[] = { "to the north", "to the east", "to the south", "to the west", "upwards", "downwards", "to the northeast", "to the northwest", "to the southeast", "to the southwest", "through the portal" }; static char *rng_desc[] = { "right here", "immediately", "nearby", "a ways", "a good ways", "far", "far off", "very far", "very far off", "in the distance" }; static void scanroom(CHAR_DATA *ch, ROOM_INDEX_DATA *room, int dir, int maxdist, int dist) { CHAR_DATA *tch; EXIT_DATA *ex; for (tch=room->first_person;tch;tch=tch->next_in_room) { if (can_see(ch,tch)) ch_printf(ch, "%-30s : %s %s\n\r", PERS(tch,ch), rng_desc[dist], dist==0?"":dir_desc[dir]); } for (ex=room->first_exit;ex;ex=ex->next) if (ex->vdir==dir) break; if (!ex || ex->vdir!=dir || ex->vdir>=MAX_REXITS || maxdist-1==0 || IS_SET(ex->exit_info, EX_CLOSED) || IS_SET(ex->exit_info, EX_DIG)) return; if (ex->vdir == DIR_SOMEWHERE) return; scanroom(ch,ex->to_room,dir,maxdist-1,dist+1); } void do_scan(CHAR_DATA *ch, char *argument) { int maxdist=1; EXIT_DATA *ex; if (number_percent() > LEARNED(ch, gsn_spot) ) { send_to_char("You fail at trying to spot the rooms around you!\n\r", ch); learn_from_failure(ch, gsn_spot); return; } if (IS_NPC(ch)) maxdist=GetMaxLevel(ch)/10; else maxdist=LEARNED(ch, gsn_spot)/20; maxdist=UMAX(maxdist,9); scanroom(ch,ch->in_room,-1,1,0); if ((ex = find_door(ch, argument, TRUE))) scanroom(ch,ex->to_room,ex->vdir,maxdist,1); else for (ex=ch->in_room->first_exit;ex;ex=ex->next) { if (IS_SET(ex->exit_info, EX_DIG) || IS_SET(ex->exit_info, EX_CLOSED)) continue; if (ex->vdir>=MAX_REXITS) return; if (ex->vdir == DIR_SOMEWHERE && !IS_IMMORTAL(ch)) continue; scanroom(ch,ex->to_room,ex->vdir,maxdist,1); } } /* * Basically the same guts as do_scan() from above (please keep them in * sync) used to find the victim we're firing at. -Thoric */ CHAR_DATA *scan_for_victim( CHAR_DATA *ch, EXIT_DATA *pexit, char *name ) { CHAR_DATA *victim; ROOM_INDEX_DATA *was_in_room; sh_int dist, dir; sh_int max_dist = 8; if ( IS_AFFECTED(ch, AFF_BLIND) || !pexit ) return NULL; was_in_room = ch->in_room; if ( IS_VAMPIRE(ch) && time_info.hour < 21 && time_info.hour > 5 ) max_dist = 1; if ( GetMaxLevel(ch) < 50 ) --max_dist; if ( GetMaxLevel(ch) < 40 ) --max_dist; if ( GetMaxLevel(ch) < 30 ) --max_dist; for ( dist = 1; dist <= max_dist; ) { if ( IS_SET(pexit->exit_info, EX_CLOSED) ) break; if ( room_is_private( pexit->to_room ) && GetMaxLevel(ch) < LEVEL_GREATER ) break; char_from_room( ch ); char_to_room( ch, pexit->to_room ); if ( (victim=get_char_room(ch, name)) != NULL ) { char_from_room(ch); char_to_room(ch, was_in_room); return victim; } switch( ch->in_room->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->in_room, dir)) == NULL ) break; } char_from_room(ch); char_to_room(ch, was_in_room); return NULL; } /* * Search inventory for an appropriate projectile to fire. * Also search open quivers. -Thoric */ OBJ_DATA *find_projectile( CHAR_DATA *ch, int type ) { OBJ_DATA *obj, *obj2; for ( obj = ch->last_carrying; obj; obj = obj->prev_content ) { if ( can_see_obj(ch, obj) ) { if ( obj->item_type == ITEM_QUIVER && !IS_SET(obj->value[1], CONT_CLOSED) ) { for ( obj2 = obj->last_content; obj2; obj2 = obj2->prev_content ) { if ( obj2->item_type == ITEM_PROJECTILE && obj2->value[2] == type ) return obj2; } } if ( obj->item_type == ITEM_PROJECTILE && obj->value[2] == type ) return obj; } } return NULL; } ch_ret spell_attack( int, int, CHAR_DATA *, void * ); /* * Perform the actual attack on a victim -Thoric */ ch_ret ranged_got_target( CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA *weapon, OBJ_DATA *projectile, sh_int dist, sh_int dt, char *stxt, sh_int color ) { if ( IS_SET(ch->in_room->room_flags, ROOM_SAFE) ) { /* safe room, bubye projectile */ if ( projectile ) { ch_printf(ch, "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_printf(ch, "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 ( IS_NPC(victim) && IS_SET(victim->act, ACT_SENTINEL) && ch->in_room != victim->in_room ) { /* * 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_archery ); /* 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->in_room); } } return damage( ch, victim, 0, dt ); } if ( number_percent() > 50 || (projectile && weapon && CanUseSkill(ch, gsn_archery)) ) { if ( projectile ) global_retcode = projectile_hit(ch, victim, weapon, projectile, dist ); else global_retcode = spell_attack( dt, GetMaxLevel(ch), ch, victim ); } else { learn_from_failure( ch, gsn_archery ); 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->in_room); } } } return global_retcode; } /* * Generic use ranged attack function -Thoric & Tricops */ ch_ret ranged_attack( CHAR_DATA *ch, char *argument, OBJ_DATA *weapon, OBJ_DATA *projectile, sh_int dt, sh_int range ) { CHAR_DATA *victim, *vch; EXIT_DATA *pexit; ROOM_INDEX_DATA *was_in_room; char arg[MAX_INPUT_LENGTH]; char arg1[MAX_INPUT_LENGTH]; char temp[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; SKILLTYPE *skill = NULL; sh_int 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' ) { send_to_char( "Where? At who?\n\r", ch ); 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 ) { send_to_char( "Aim in what direction?\n\r", ch ); return rNONE; } else { if ( who_fighting(ch) == victim ) { send_to_char( "They are too close to release that type of attack!\n\r", ch ); return rNONE; } if ( !IS_NPC(ch) && !IS_NPC(victim) ) { send_to_char("Pkill like a real pkiller.\n\r", ch ); return rNONE; } } } else dir = pexit->vdir; /* check for ranged attacks from private rooms, etc */ if ( !victim ) { if ( IS_SET(ch->in_room->room_flags, ROOM_PRIVATE) || IS_SET(ch->in_room->room_flags, ROOM_SOLITARY) ) { send_to_char( "You cannot perform a ranged attack from a private room.\n\r", ch ); return rNONE; } if ( ch->in_room->tunnel > 0 ) { count = 0; for ( vch = ch->in_room->first_person; vch; vch = vch->next_in_room ) ++count; if ( count >= ch->in_room->tunnel ) { send_to_char( "This room is too cramped to perform such an attack.\n\r", ch ); return rNONE; } } } if ( IS_VALID_SN(dt) ) skill = skill_table[dt]; if ( pexit && !pexit->to_room ) { send_to_char( "Are you expecting to fire through a wall!?\n\r", ch ); return rNONE; } /* Check for obstruction */ if ( pexit && IS_SET(pexit->exit_info, EX_CLOSED) ) { if ( IS_SET(pexit->exit_info, EX_SECRET) || IS_SET(pexit->exit_info, EX_DIG) ) send_to_char( "Are you expecting to fire through a wall!?\n\r", ch ); else send_to_char( "Are you expecting to fire through a door!?\n\r", ch ); return rNONE; } vch = NULL; if ( pexit && arg1[0] != '\0' ) { if ( (vch=scan_for_victim(ch, pexit, arg1)) == NULL ) { send_to_char( "You cannot see your target.\n\r", ch ); return rNONE; } /* don't allow attacks on mobs stuck in another area? if ( IS_NPC(vch) && xIS_SET(vch->act, ACT_STAY_AREA) && ch->in_room->area != vch->in_room->area) ) { } */ /*don't allow attacks on mobs that are in a no-missile room --Shaddai */ if ( IS_SET(vch->in_room->room_flags, ROOM_NOMISSILE) ) { send_to_char( "You can't get a clean shot off.\n\r", ch ); return rNONE; } if ( !IS_NPC(ch) && !IS_NPC(vch) ) { send_to_char("Pkill like a real pkiller.\n\r", ch ); return rNONE; } /* can't properly target someone heavily in battle */ if ( vch->num_fighting > max_fight(vch) ) { send_to_char( "There is too much activity there for you to get a clear shot.\n\r", ch ); return rNONE; } } if ( vch ) { if ( !IS_NPC( vch ) && !IS_NPC( ch ) && IS_SET(ch->act, PLR_NICE ) ) { send_to_char( "Your too nice to do that!\n\r", ch ); return rNONE; } if ( vch && is_safe(ch, vch) ) return rNONE; } was_in_room = ch->in_room; 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 ( skill ) { if ( skill->noun_damage && skill->noun_damage[0] != '\0' ) stxt = skill->noun_damage; else stxt = skill->name; /* a plain "spell" flying around seems boring */ if ( !str_cmp(stxt, "spell") ) stxt = "magical burst of energy"; if ( skill->type == 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 = dir_name(pexit->rdir); while ( dist <= range ) { char_from_room(ch); char_to_room(ch, pexit->to_room); if ( IS_SET(pexit->exit_info, EX_CLOSED) ) { /* 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 ) { for ( vch = ch->in_room->first_person; vch; vch = vch->next_in_room ) { if ( ((IS_NPC(ch) && !IS_NPC(vch)) || (!IS_NPC(ch) && IS_NPC(vch))) && number_bits(1) == 0 ) { victim = vch; break; } } if ( victim && is_safe(ch, victim) ) { char_from_room(ch); char_to_room(ch, was_in_room); return rNONE; } } /* In the same room as our victim? */ if ( victim && ch->in_room == victim->in_room ) { 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 */ char_from_room(ch); char_to_room(ch, was_in_room); 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->in_room); } 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->in_room, 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->in_room); } 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++; } char_from_room( ch ); char_to_room( ch, was_in_room ); 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( CHAR_DATA *ch, char *argument ) { OBJ_DATA *arrow; OBJ_DATA *bow; sh_int max_dist; if ( argument[0] == '\0' || !str_cmp(argument, " ") ) { send_to_char( "Fire where at who?\n\r", ch ); return; } if ( !IS_IMMORTAL(ch) && IS_SET( ch->in_room->room_flags, ROOM_SAFE ) ) { set_char_color( AT_MAGIC, ch ); send_to_char( "A magical force prevents you from attacking.\n\r", ch ); return; } /* * Find the projectile weapon */ if ( (bow=get_eq_char(ch, WEAR_WIELD)) != NULL ) if ( !(bow->item_type == ITEM_MISSILE_WEAPON) ) bow = NULL; if ( !bow ) { send_to_char( "You are not wielding a missile weapon.\n\r", ch ); return; } if ( (arrow=get_eq_char(ch, WEAR_MISSILE_WIELD)) != NULL ) if ( !(arrow->item_type == ITEM_PROJECTILE) ) arrow = NULL; if ( !arrow ) { send_to_char( "You do not have the proper ammunition loaded.\n\r", ch ); return; } /* modify maximum distance based on bow-type and ch's class/str/etc */ max_dist = URANGE( 1, bow->value[2], 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; } send_to_char( msg, ch ); return; }*/ /* handle the ranged attack */ ranged_attack( ch, argument, bow, arrow, TYPE_HIT + arrow->value[2], max_dist ); return; } /* * Attempt to fire at a victim. * Returns FALSE if no attempt was made */ bool mob_fire( CHAR_DATA *ch, char *name ) { OBJ_DATA *arrow; OBJ_DATA *bow; sh_int max_dist; if ( IS_SET( ch->in_room->room_flags, ROOM_SAFE ) ) return FALSE; if ( (bow=get_eq_char(ch, WEAR_MISSILE_WIELD)) != NULL ) 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[2], 10 ); if ( (arrow=find_projectile(ch, bow->value[3])) == NULL ) return FALSE; ranged_attack( ch, name, bow, arrow, TYPE_HIT + arrow->value[2], max_dist ); return TRUE; } /* -- 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( CHAR_DATA *ch, char *argument ) { ROOM_INDEX_DATA *was_in_room; CHAR_DATA *victim; OBJ_DATA *throw_obj; EXIT_DATA *pexit; sh_int dir; sh_int dist; sh_int 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 ( can_see_obj( ch, throw_obj ) && nifty_is_name( arg, throw_obj->name ) break; } if ( !throw_obj ) { send_to_char( "You aren't holding or wielding anything like that.\n\r", ch ); return; } ---- if ( ( throw_obj->item_type != ITEM_WEAPON) { send_to_char("You can only throw weapons.\n\r", ch ); return; } ---- if (get_obj_weight( throw_obj ) - ( 3 * (get_curr_str(ch) - 15) ) > 0) { send_to_char("That is too heavy for you to throw.\n\r", ch); if (!number_range(0,10)) learn_from_failure( ch, gsn_throw ); return; } if ( ch->fighting ) victim = ch->fighting; 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; } } }*/ /* * * void do_release( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; OBJ_INDEX_DATA *arrow; OBJ_DATA *quiver; OBJ_DATA *bow; EXIT_DATA *pexit; ROOM_INDEX_DATA *was_in_room; char arg[MAX_INPUT_LENGTH]; char arg1[MAX_INPUT_LENGTH]; sh_int dir; sh_int dist; sh_int 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 ) { send_to_char( "You are not wielding a bow.\n\r", ch ); 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->prev ) { if ( can_see_obj( ch, quiver ) && ( quiver->item_type == ITEM_QUIVER ) ) break; } for ( arrow = ch->last_carrying; arrow; arrow = arrow->prev ) { if ( can_see_obj( ch, arrow ) && ( arrow->item_type == ITEM_PROJECTILE ) ) break; } if ( ( dir = get_door( arg ) ) == -1 ) { send_to_char( "Aim in what direction?\n\r", ch ); return; } if ( ( pexit = get_exit( ch->in_room, dir ) ) == NULL ) { send_to_char( "Are you expecting to fire through a wall!?\n\r", ch ); return; } if ( IS_SET( pexit->exit_info, EX_CLOSED ) ) { send_to_char( "Are you expecting to fire through a door!?\n\r", ch ); return; } was_in_room = ch->in_room; 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; } char_from_room( ch ); char_to_room( ch, pexit->to_room ); if ( ( victim = get_char_room( ch, arg1 ) ) != NULL ) { } if ( dist == max_dist ) break; if ( ( pexit = get_exit( ch->in_room, dir ) ) == NULL ) { } } char_from_room( ch ); char_to_room( ch, 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( CHAR_DATA *ch, char *argument ) { ROOM_INDEX_DATA *was_in_room; CHAR_DATA *victim; OBJ_DATA *throw_obj; EXIT_DATA *pexit; sh_int dir; sh_int dist; sh_int 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 ) { send_to_char( "You aren't holding or wielding anything like that.\n\r", ch ); return; } if ( ( throw_obj->item_type != ITEM_WEAPON) { send_to_char("You can only throw weapons.\n\r", ch ); return; } if (get_obj_weight( throw_obj ) - ( 3 * (get_curr_str(ch) - 15) ) > 0) { send_to_char("That is too heavy for you to throw.\n\r", ch); learn_from_failure( ch, gsn_throw ); return; } if ( ch->fighting ) victim = ch->fighting; 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; } } }*/ void do_slice( CHAR_DATA *ch, char *argument ) { OBJ_DATA *corpse; OBJ_DATA *obj; OBJ_DATA *slice; bool found; MOB_INDEX_DATA *pMobIndex; char buf[MAX_STRING_LENGTH]; char buf1[MAX_STRING_LENGTH]; found = FALSE; if ( !IS_NPC(ch) && !IS_IMMORTAL(ch) && !CanUseSkill(ch, gsn_slice) ) { send_to_char("You are not learned in this skill.\n\r", ch ); return; } if ( argument[0] == '\0' ) { send_to_char("From what do you wish to slice meat?\n\r", ch); 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) ) { send_to_char( "You need to wield a sharp weapon.\n\r", ch); return; } if ( (corpse = get_obj_here( ch, argument )) == NULL) { send_to_char("You can't find that here.\n\r", ch); return; } if (corpse->item_type != ITEM_CORPSE_NPC || corpse->value[2] < 6) { send_to_char("That is not a suitable source of meat.\n\r", ch); return; } if ( (pMobIndex = get_mob_index((sh_int) (0 - corpse->cost) )) == NULL ) { bug("Can not find mob vnum of corpse, do_slice"); return; } if ( !obj_exists_index(OBJ_VNUM_SLICE) ) { bug("Vnum %d not found for do_slice!", OBJ_VNUM_SLICE); return; } if ( !IS_NPC(ch) && !IS_IMMORTAL(ch) && number_percent() > LEARNED(ch, gsn_slice) ) { send_to_char("You fail to slice the meat properly.\n\r", ch); learn_from_failure(ch, gsn_slice); /* Just in case they die :> */ if ( number_percent() + (get_curr_dex(ch) - 13) < 10) { act(AT_BLOOD, "You cut yourself!", ch, NULL, NULL, TO_CHAR); damage(ch, ch, BestSkLv(ch, gsn_slice), gsn_slice); } return; } slice = create_object( OBJ_VNUM_SLICE ); sprintf(buf, "meat fresh slice %s", pMobIndex->player_name); STRFREE(slice->name); slice->name = STRALLOC(buf); sprintf(buf, "a slice of raw meat from %s", pMobIndex->short_descr); STRFREE(slice->short_descr); slice->short_descr = STRALLOC(buf); sprintf(buf1, "A slice of raw meat from %s lies on the ground.", pMobIndex->short_descr); STRFREE(slice->description); slice->description = STRALLOC(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; } extern int pAbort; void *locate_targets( CHAR_DATA *ch, char *arg, int sn, CHAR_DATA **victim, OBJ_DATA **obj ); void do_smaug_skill( CHAR_DATA *ch, char *argument ) { #if 1 char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; static char staticbuf[MAX_INPUT_LENGTH]; CHAR_DATA *victim; OBJ_DATA *obj; void *vo = NULL; int mana; int blood; int sn; ch_ret retcode; bool dont_wait = FALSE; SKILLTYPE *skill = NULL; struct timeval time_used; retcode = rNONE; switch( ch->substate ) { default: /* no ordering charmed mobs to cast spells */ if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) ) { send_to_char( "You can't seem to do that right now...\n\r", ch ); return; } target_name = one_argument( argument, arg1 ); one_argument( target_name, arg2 ); if ( get_trust(ch) < LEVEL_GOD ) { if ( ( sn = find_skill( ch, arg1, TRUE ) ) < 0 || ( !IS_NPC(ch) && !CanUseSkill(ch, sn) ) ) { send_to_char( "You can't do that.\n\r", ch ); bug("You can't do that in do_smaug_skill"); return; } if ( (skill=get_skilltype(sn)) == NULL ) { send_to_char( "You can't do that right now...\n\r", ch ); return; } } else { if ( (sn=skill_lookup(arg1)) < 0 ) { send_to_char( "We didn't create that yet...\n\r", ch ); return; } if ( sn >= MAX_SKILL ) { send_to_char( "Hmm... that might hurt.\n\r", ch ); return; } if ( (skill=get_skilltype(sn)) == NULL ) { send_to_char( "Somethis is severely wrong with that one...\n\r", ch ); return; } if ( skill->type != SKILL_SKILL ) { send_to_char( "That isn't a skill.\n\r", ch ); return; } if ( !skill->skill_fun ) { send_to_char( "We didn't finish that one yet...\n\r", ch ); return; } } /* * Something else removed by Merc -Thoric */ if ( ch->position < skill->minimum_position ) { switch( ch->position ) { default: send_to_char( "You can't concentrate enough.\n\r", ch ); break; case POS_SITTING: case POS_MEDITATING: send_to_char( "You can't seem to do this sitting down.\n\r", ch ); break; case POS_RESTING: send_to_char( "You're too relaxed to do that.\n\r", ch ); break; case POS_FIGHTING: send_to_char( "You can't concentrate enough while fighting!\n\r", ch ); break; case POS_SLEEPING: send_to_char( "In your dreams?\n\r", ch ); break; } return; } if ( !skill->skill_fun ) { send_to_char( "You cannot cast that... yet.\n\r", ch ); return; } if ( !IS_NPC(ch) /* fixed by Thoric */ && !IS_IMMORTAL(ch) && skill->guild != CLASS_NONE && (!ch->pcdata->clan || skill->guild != ch->pcdata->clan->cl) ) { send_to_char( "That is only available to members of a certain guild.\n\r", ch); return; } mana = IS_NPC(ch) ? 0 : skill->min_mana; /* * Locate targets. */ vo = locate_targets( ch, arg2, sn, &victim, &obj ); if ( vo == &pAbort ) return; if ( !IS_NPC( ch ) && victim && !IS_NPC( victim ) && CAN_PKILL( victim ) && !CAN_PKILL( ch ) && !in_arena( ch ) && !in_arena( victim ) ) { set_char_color( AT_GREY, ch ); send_to_char( "The gods will not permit you to do that.\n\r", ch ); return; } /* * Vampire spell casting -Thoric */ blood = UMAX(1, (mana+4) / 8); /* NPCs don't have PCDatas. -- Altrag */ if ( IS_VAMPIRE(ch) ) { if (GET_COND(ch, COND_BLOODTHIRST) < blood) { send_to_char( "You don't have enough blood power.\n\r", ch ); return; } } else if ( !IS_NPC(ch) && GET_MANA(ch) < mana ) { send_to_char( "You don't have enough mana.\n\r", ch ); return; } if ( skill->participants <= 1 ) break; /* multi-participant spells -Thoric */ add_timer( ch, TIMER_DO_FUN, UMAX(skill->beats/SPELL_BEATS_PER_ROUND, 1), do_cast, 1 ); if (skill->part_start_char && *skill->part_start_char) act( AT_MAGIC, skill->part_start_char, ch, NULL, NULL, TO_CHAR ); else act( AT_MAGIC, "You begin to chant...", ch, NULL, NULL, TO_CHAR ); if (skill->part_start_room && *skill->part_start_room) act( AT_MAGIC, skill->part_start_room, ch, NULL, NULL, TO_ROOM ); else act( AT_MAGIC, "$n begins to chant...", ch, NULL, NULL, TO_ROOM ); sprintf( staticbuf, "'%s' %s", arg2, target_name ); ch->dest_buf = str_dup( staticbuf ); ch->tempnum = sn; return; case SUB_TIMER_DO_ABORT: DISPOSE( ch->dest_buf ); if ( IS_VALID_SN((sn = ch->tempnum)) ) { if ( (skill=get_skilltype(sn)) == NULL ) { send_to_char( "Something went wrong...\n\r", ch ); bug( "do_cast: SUB_TIMER_DO_ABORT: bad sn %d", sn ); return; } mana = IS_NPC(ch) ? 0 : skill->min_mana; blood = UMAX(1, (mana+4) / 8); if ( IS_VAMPIRE(ch) ) gain_condition( ch, COND_BLOODTHIRST, - UMAX(1, blood / 3) ); else if (GetMaxLevel(ch) < LEVEL_IMMORTAL) /* so imms dont lose mana */ GET_MANA(ch) -= mana / 3; } if (skill->part_abort_char && *skill->part_abort_char) act( AT_GREY, skill->part_abort_char, ch, NULL, NULL, TO_CHAR ); else act( AT_GREY, "You stop chanting...", ch, NULL, NULL, TO_CHAR ); /* should add chance of backfire here */ return; case 1: sn = ch->tempnum; if ( (skill=get_skilltype(sn)) == NULL ) { send_to_char( "Something went wrong...\n\r", ch ); bug( "do_smaug_skill: substate 1: bad sn %d", sn ); return; } if ( !ch->dest_buf || !IS_VALID_SN(sn) || skill->type != SKILL_SPELL ) { send_to_char( "Something cancels out the spell!\n\r", ch ); bug( "do_smaug_skill: ch->dest_buf NULL or bad sn (%d)", sn ); return; } mana = IS_NPC(ch) ? 0 : skill->min_mana; blood = UMAX(1, (mana+4) / 8); strcpy( staticbuf, (const char *)ch->dest_buf ); target_name = one_argument(staticbuf, arg2); DISPOSE( ch->dest_buf ); ch->substate = SUB_NONE; if ( skill->participants > 1 ) { int cnt = 1; CHAR_DATA *tmp; TIMER *t; for ( tmp = ch->in_room->first_person; tmp; tmp = tmp->next_in_room ) if ( tmp != ch && (t = get_timerptr( tmp, TIMER_DO_FUN )) != NULL && t->count >= 1 && t->do_fun == do_cast && tmp->tempnum == sn && tmp->dest_buf && !str_cmp( (const char *)tmp->dest_buf, staticbuf ) ) ++cnt; if ( cnt >= skill->participants ) { for ( tmp = ch->in_room->first_person; tmp; tmp = tmp->next_in_room ) if ( tmp != ch && (t = get_timerptr( tmp, TIMER_DO_FUN )) != NULL && t->count >= 1 && t->do_fun == do_cast && tmp->tempnum == sn && tmp->dest_buf && !str_cmp( (const char *)tmp->dest_buf, staticbuf ) ) { extract_timer( tmp, t ); if (skill->part_end_vict && *skill->part_end_vict) act( AT_GREY, skill->part_end_vict, ch, NULL, tmp, TO_VICT ); else act( AT_GREY, "You channel your energy into $n!", ch, NULL, tmp, TO_VICT ); if (skill->part_end_char && *skill->part_end_char) act( AT_GREY, skill->part_end_char, ch, NULL, tmp, TO_CHAR ); else act( AT_GREY, "$N channels $S energy into you!", ch, NULL, tmp, TO_CHAR ); if (skill->part_end_room && *skill->part_end_room) act( AT_GREY, skill->part_end_room, ch, NULL, tmp, TO_NOTVICT ); else act( AT_GREY, "$N channels $S energy into $n!", ch, NULL, tmp, TO_NOTVICT ); learn_from_success( tmp, sn ); if ( IS_VAMPIRE(ch) ) gain_condition( tmp, COND_BLOODTHIRST, - blood ); else if (!IS_IMMORTAL(tmp)) GET_MANA(tmp) -= mana; tmp->substate = SUB_NONE; tmp->tempnum = -1; DISPOSE( tmp->dest_buf ); } dont_wait = TRUE; if (skill->part_end_caster && *skill->part_end_caster) act( AT_GREY, skill->part_end_caster, ch, NULL, NULL, TO_CHAR ); else act( AT_GREY, "You concentrate all the energy into a single burst!", ch, NULL, NULL, TO_CHAR ); vo = locate_targets( ch, arg2, sn, &victim, &obj ); if ( vo == &pAbort ) return; } else { if (skill->part_miss_char && *skill->part_miss_char) act( AT_GREY, skill->part_miss_char, ch, NULL, NULL, TO_CHAR ); else act( AT_GREY, "There was not enough power for success...", ch, NULL, NULL, TO_CHAR ); if (skill->part_miss_room && *skill->part_miss_room) act( AT_GREY, skill->part_miss_room, ch, NULL, NULL, TO_ROOM ); if ( IS_VAMPIRE(ch) ) gain_condition( ch, COND_BLOODTHIRST, - UMAX(1, blood / 2) ); else if (GetMaxLevel(ch) < LEVEL_IMMORTAL) /* so imms dont lose mana */ GET_MANA(ch) -= mana / 2; learn_from_failure( ch, sn ); return; } } } if ( !dont_wait ) /*if (!IS_NPC(ch))*/ spell_lag(ch, sn); /* * Getting ready to cast... check for spell components -Thoric */ if ( !process_spell_components( ch, sn ) ) { if ( IS_VAMPIRE(ch) ) gain_condition( ch, COND_BLOODTHIRST, - UMAX(1, blood / 2) ); else if (GetMaxLevel(ch) < LEVEL_IMMORTAL) /* so imms dont lose mana */ GET_MANA(ch) -= mana / 2; learn_from_failure( ch, sn ); return; } if ( !IS_NPC(ch) && (number_percent( ) + skill->difficulty * 5) > LEARNED(ch, sn) ) { /* Some more interesting loss of concentration messages -Thoric */ switch( number_bits(2) ) { case 0: /* too busy */ if ( ch->fighting ) send_to_char( "This round of battle is too hectic to concentrate properly.\n\r", ch ); else send_to_char( "You lost your concentration.\n\r", ch ); break; case 1: /* irritation */ if ( number_bits(2) == 0 ) { switch( number_bits(2) ) { case 0: send_to_char( "A tickle in your nose prevents you from keeping your concentration.\n\r", ch ); break; case 1: send_to_char( "An itch on your leg keeps you from properly finishing.\n\r", ch ); break; case 2: send_to_char( "Something prevents you from doing that task.\n\r", ch ); break; case 3: send_to_char( "A twitch in your eye disrupts your concentration for a moment.\n\r", ch ); break; } } else send_to_char( "Something distracts you, and you lose your concentration.\n\r", ch ); break; case 2: /* not enough time */ if ( ch->fighting ) send_to_char( "There wasn't enough time this round to complete what you were doing.\n\r", ch ); else send_to_char( "You lost your concentration.\n\r", ch ); break; case 3: send_to_char( "You get a mental block mid-way through what you were doing.\n\r", ch ); break; } if ( IS_VAMPIRE(ch) ) gain_condition( ch, COND_BLOODTHIRST, - UMAX(1, blood / 2) ); else if (GetMaxLevel(ch) < LEVEL_IMMORTAL) /* so imms dont lose mana */ GET_MANA(ch) -= mana / 2; learn_from_failure( ch, sn ); return; } else { if ( IS_VAMPIRE(ch) ) gain_condition( ch, COND_BLOODTHIRST, - blood ); else GET_MANA(ch) -= mana; start_timer(&time_used); if ( SPELL_FLAG(skill, SF_VERBALIZE_SKILL) ) { sprintf(buf, "%s!", skill->name); buf[0] = toupper(buf[0]); do_shout( ch, buf); } retcode = spell_smaug ( sn, BestSkLv(ch, sn), ch, vo ); end_timer(&time_used); update_userec(&time_used, &skill->userec); } if ( retcode == rCHAR_DIED || retcode == rERROR || char_died(ch) ) return; if ( retcode != rSPELL_FAILED ) learn_from_success( ch, sn ); else learn_from_failure( ch, sn ); /* * Fixed up a weird mess here, and added double safeguards -Thoric */ if ( skill->target == TAR_CHAR_OFFENSIVE && victim && !char_died(victim) && victim != ch ) { CHAR_DATA *vch, *vch_next; for ( vch = ch->in_room->first_person; vch; vch = vch_next ) { vch_next = vch->next_in_room; if ( vch == victim ) { if ( victim->master != ch && !victim->fighting ) retcode = multi_hit( victim, ch, TYPE_UNDEFINED ); break; } } } return; #endif } /* * Cook was coded by Blackmane and heavily modified by Shaddai */ void do_cook ( CHAR_DATA *ch, char *argument ) { OBJ_DATA *food, *fire; char arg[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; one_argument( argument, arg ); if ( IS_NPC(ch) || !CanUseSkill(ch, gsn_cook)) { send_to_char("That skill is beyond your understanding.\n\r", ch ); return; } if ( arg[0] == '\0' ) { send_to_char("Cook what?\n\r", ch ); return; } if ( ms_find_obj(ch) ) return; if ( ( food = get_obj_carry( ch, arg ) ) == NULL ) { send_to_char("You do not have that item.\n\r", ch ); return; } if ( food->item_type != ITEM_COOK ) { send_to_char("How can you cook that?\n\r", ch ); return; } if ( food->value[2] > 2 ) { send_to_char("That is already burnt to a crisp.\n\r", ch ); return; } for ( fire = ch->in_room->first_content; fire; fire = fire->next_content ) { if ( fire->item_type == ITEM_FIRE ) break; } if ( !fire ) { send_to_char("There is no fire here!\n\r", ch ); return; } if ( number_percent() > LEARNED(ch, gsn_cook) ) { food->timer = food->timer/2; food->value[0] = 0; food->value[2] = 3; act( AT_MAGIC, "$p catches on fire burning it to a crisp!\n\r", ch, food, NULL, TO_CHAR ); act( AT_MAGIC, "$n catches $p on fire burning it to a crisp.", ch, food, NULL, TO_ROOM); sprintf( buf, "a burnt %s", food->pIndexData->name ); STRFREE(food->short_descr); food->short_descr = STRALLOC(buf); sprintf( buf, "A burnt %s.", food->pIndexData->name); STRFREE(food->description); food->description = STRALLOC(buf); return; } if ( number_percent() > 85 ) { food->timer = food->timer*3; food->value[2]+=2; act( AT_MAGIC, "$n overcooks a $p.",ch, food, NULL, TO_ROOM); act( AT_MAGIC, "You overcook a $p.",ch, food, NULL, TO_CHAR); sprintf( buf, "an overcooked %s", food->pIndexData->name ); STRFREE(food->short_descr); food->short_descr = STRALLOC(buf); sprintf( buf, "An overcooked %s.", food->pIndexData->name); STRFREE(food->description); food->description = STRALLOC(buf); } else { food->timer = food->timer*4; food->value[0] *= 2; act( AT_MAGIC, "$n roasts a $p.",ch, food, NULL, TO_ROOM); act( AT_MAGIC, "You roast a $p.",ch, food, NULL, TO_CHAR); sprintf( buf, "a roasted %s", food->pIndexData->name ); STRFREE(food->short_descr); food->short_descr = STRALLOC(buf); sprintf( buf, "A roasted %s.", food->pIndexData->name); STRFREE(food->description); food->description = STRALLOC(buf); food->value[2]++; } learn_from_success(ch, gsn_cook); } void do_forge(CHAR_DATA *ch, char *argument ) { OBJ_DATA *forge = NULL; OBJ_DATA *material = NULL; OBJ_DATA *newitem = NULL; AFFECT_DATA *paf = NULL, *paf2 = NULL, *paf3 = NULL; char itemname[MAX_INPUT_LENGTH], itemtype[MAX_INPUT_LENGTH], sdesc[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; int percent=0, quality = 0; int gsn_forge, hplus = 0, dplus = 0; if ( (gsn_forge = skill_lookup("forge")) == -1 ) return; if (IS_NPC(ch) && !IS_ACT_FLAG(ch, ACT_POLYMORPHED)) return; if (ch->mount) { send_to_char("Not from this mount you cannot!\n\r",ch); return; } if (!CanUseSkill(ch, gsn_forge)) { send_to_char("What do you think you are, an artificer?\n\r",ch); return; } argument = one_argument(argument, itemname); argument = one_argument(argument, itemtype); if (!*itemname) { send_to_char("Forge what?\n\r",ch); return; } if (!*itemtype) { send_to_char("I see that, but what do you wanna make?\n\r",ch); return; } if (!(forge = get_obj_here(ch, "forge"))) { send_to_char("You need a forge to complete the process.\n\r",ch); return; } else if (forge->item_type != ITEM_FORGE) { send_to_char("This forge is inoperable!\n\r",ch); return; } if (!(material = get_obj_carry(ch, itemname))) { send_to_char("Where did those materials go?\n\r",ch); return; } if (material->item_type != ITEM_MATERIAL) { send_to_char("These materials are improper for the task at hand.\n\r", ch); return; } if (MTYPE(material) == MAT_WORTHLESS || MGRADE(material) == QUAL_WORTHLESS) { send_to_char("These materials are just scraps, not enough for an attmpt.\n\r", ch); return; } percent = number_percent(); if (percent > LEARNED(ch, gsn_forge)) { if (material->value[1] > 0) material->value[1]--; sprintf(buf,"You pound at %s but accomplish nothing.\n\r", material->short_descr); send_to_char(buf,ch); sprintf(buf,"$n tries to forge %s into a %s, but fails.", material->short_descr, itemtype); act(AT_SKILL, buf, ch, NULL, NULL, TO_ROOM); learn_from_failure(ch, gsn_tan); WAIT_STATE(ch, PULSE_VIOLENCE*5); return; } quality = (int)((GetClassLevel(ch, CLASS_ARTIFICER) / 10) + MGRADE(material) - 2); quality = URANGE(0, quality, 10); switch(quality) { case 0: sprintf(sdesc," worthless"); dplus = -1; break; case 1: case 2: sprintf(sdesc," poor"); break; case 3: case 4: case 5: sprintf(sdesc,"n average"); break; case 6: case 7: sprintf(sdesc," well crafted"); break; case 8: case 9: sprintf(sdesc,"n excelently crafted"); hplus = 1; break; case 10: sprintf(sdesc," masterfully crafted"); hplus = 1; dplus = 1; break; } if (!str_cmp(itemtype,"dagger") && (ARTLEV(ch) >= 1)) { newitem = create_object(45002); strcat(sdesc," dagger"); } else if (!str_cmp(itemtype,"sword") && (ARTLEV(ch) >= 2)) { newitem = create_object(45003); strcat(sdesc," sword"); } else if (!str_cmp(itemtype,"longsword") && (ARTLEV(ch) >= 5)) { newitem = create_object(45004); strcat(sdesc," long sword"); } else if (!str_cmp(itemtype,"twohander") && (ARTLEV(ch) >= 10)) { newitem = create_object(45005); strcat(sdesc," two handed sword"); } else if (!str_cmp(itemtype,"broadsword") && (ARTLEV(ch) >= 15)) { newitem = create_object(45006); strcat(sdesc," broad sword"); } else if (!str_cmp(itemtype,"halberd") && (ARTLEV(ch) >= 20)) { newitem = create_object(45007); strcat(sdesc," halberd"); } else if (!str_cmp(itemtype,"spear") && (ARTLEV(ch) >= 20)) { newitem = create_object(45008); strcat(sdesc," spear"); } else if (!str_cmp(itemtype,"axe") && (ARTLEV(ch) >= 7)) { newitem = create_object(45009); strcat(sdesc," axe"); } else if (!str_cmp(itemtype,"battleaxe") && (ARTLEV(ch) >= 18)) { newitem = create_object(45010); strcat(sdesc," battle axe"); } else if (!str_cmp(itemtype,"warhammer") && (ARTLEV(ch) >= 30)) { newitem = create_object(45011); strcat(sdesc," warhammer"); } else if (!str_cmp(itemtype,"hammer") && (ARTLEV(ch) >= 1)) { newitem = create_object(45012); strcat(sdesc," smith's hammer"); } else { send_to_char("You have not learned how to make that yet!\n\r",ch); return; } if (!newitem) { bug("forge objects missing."); send_to_char("You messed up the hide and it's useless.\n\r", ch); return; } obj_to_char(newitem, ch); sprintf( buf, "a%s", sdesc ); STRFREE(newitem->short_descr); newitem->short_descr = STRALLOC(buf); sprintf( buf, "A%s lies here.", sdesc ); STRFREE(newitem->description); newitem->description = STRALLOC(buf); newitem->cost = (int)((material->cost / 100 * mat_costmul[MTYPE(material)]) + (quality * quality * 10)); hplus += mat_hitplus[MTYPE(material)]; dplus += mat_damplus[MTYPE(material)]; if (hplus != 0) { CREATE(paf, AFFECT_DATA, 1); paf->type = -1; paf->duration = -1; paf->location = APPLY_HITROLL; paf->modifier = hplus; paf->bitvector = 0; paf->next = NULL; LINK(paf, newitem->first_affect, newitem->last_affect, next, prev); } if (dplus != 0) { CREATE(paf2, AFFECT_DATA, 1); paf2->type = -1; paf2->duration = -1; paf2->location = APPLY_DAMROLL; paf2->modifier = dplus; paf2->bitvector = 0; paf2->next = NULL; LINK(paf2, newitem->first_affect, newitem->last_affect, next, prev); } if (MTYPE(material) == MAT_SILVER) { CREATE(paf3, AFFECT_DATA, 1); paf3->type = -1; paf3->duration = -1; paf3->location = APPLY_RACE_SLAYER; paf3->modifier = RACE_LYCANTH; paf3->bitvector = 0; paf3->next = NULL; LINK(paf2, newitem->first_affect, newitem->last_affect, next, prev); } else if (MTYPE(material) == MAT_LEAD) { SET_BIT(newitem->extra_flags, ITEM_POISONED); } sprintf(buf,"You pound at the %s and finally forge %s.\n\r", material->short_descr, newitem->short_descr); send_to_char(buf,ch); sprintf(buf,"$n manages to forge %s.", newitem->short_descr); act(AT_SKILL, buf, ch, NULL, NULL, TO_ROOM); MGRADE(material) = 0; sprintf(buf, "All that remains of %s is scraps.\n\r", material->short_descr); send_to_char(buf, ch); WAIT_STATE(ch, PULSE_VIOLENCE*5); return; } void do_probability_travel(CHAR_DATA *ch, char *argument ) { CHAR_DATA *gch, *gch_next; ROOM_INDEX_DATA *astral; astral = get_room_index( ROOM_VNUM_ASTRAL_ENTRANCE ); if ( IS_SET (ch->in_room->room_flags, ROOM_NO_ASTRAL) || IS_SET (ch->in_room->area->flags, AFLAG_ARENA) || IS_SET (ch->in_room->area->flags, AFLAG_NOPKILL) || IS_SET (ch->in_room->room_flags, ROOM_SAFE) ) { send_to_char("You can't access the astral plane from here.\n", ch); return; } for ( gch = ch->in_room->first_person; gch; gch = gch = gch_next ) { gch_next = gch->next_in_room; if ( IS_NPC(gch) && IS_SET (gch->act, ACT_PROTOTYPE) ) continue; if ( is_same_group(ch, gch) && gch->position != POS_FIGHTING ) { act( AT_MAGIC, "$n wavers, fades and dissappears.", gch, NULL, NULL, TO_ROOM ); char_from_room(gch); char_to_room(gch, astral); act( AT_MAGIC, "$n wavers into existence.", gch, NULL, NULL, TO_ROOM ); do_look( gch, "auto" ); } } }