/**************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ /*************************************************************************** * ROM 2.4 is copyright 1993-1996 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@pacinfo.com) * * Gabrielle Taylor (gtaylor@pacinfo.com) * * Brian Moore (rom@rom.efn.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Tartarus/doc/rom.license * ***************************************************************************/ /*************************************************************************** * Tartarus code is copyright (C) 1997-1998 by Daniel Graham * * In using this code you agree to comply with the Tartarus license * * found in the file /Tartarus/doc/tartarus.doc * ***************************************************************************/ #include "include.h" #define HITS (dt==gsn_kick||dt==gsn_lunge||dt==gsn_downstrike||dt==gsn_throw||dt==gsn_crush||dt==gsn_bash||dt==gsn_restrike) /* * Local functions. */ void check_downstrike args( ( CHAR_DATA *ch, CHAR_DATA *victim) ); void check_assist args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void affect_join_obj args( (OBJ_DATA *obj, AFFECT_DATA *af) ); bool check_dodge args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) ); bool check_questdodge args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) ); bool check_fam args( ( CHAR_DATA *ch, char *attack ) ); bool check_block args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) ); void check_killer args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); bool check_parry args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) ); bool check_spin args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) ); bool check_displacement args( ( CHAR_DATA *ch, CHAR_DATA *victim) ); bool check_shield_block args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) ); void dam_message args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam,int dt, bool immune, char *dnoun, bool isPlural, bool showCharName) ); void death_cry args( ( CHAR_DATA *ch ) ); void group_gain args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); long quest_credit_compute args( ( CHAR_DATA *ch, CHAR_DATA *victim, int group_amount ) ); int xp_compute args( ( CHAR_DATA *gch, CHAR_DATA *victim,int group_amount, int glevel ) ); bool is_safe args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void make_corpse args( ( CHAR_DATA *killer, CHAR_DATA *ch ) ); void one_hit args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt )); void mob_hit args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) ); void raw_kill args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void raw_kill_new args( ( CHAR_DATA *ch, CHAR_DATA *victim, bool deathCry, bool fLook ) ); void set_fighting args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void disarm args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void check_ground_control args( ( CHAR_DATA *ch,CHAR_DATA *victim,int chance,int dam) ); void check_follow_through args( ( CHAR_DATA *ch, CHAR_DATA *victim,int dam) ); bool check_roll args( ( CHAR_DATA *ch,CHAR_DATA *victim,int dt) ); void do_strap args( ( CHAR_DATA *victim,OBJ_DATA *strap)); bool check_unholy_bless args( ( CHAR_DATA *ch, CHAR_DATA *victim)); void check_cheap_shot args( ( CHAR_DATA *ch, CHAR_DATA *victim)); void check_parting_blow args( ( CHAR_DATA *ch, CHAR_DATA *victim)); bool arena; bool check_distance args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt )); bool check_ironhands args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt )); bool check_unarmed_defense args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt )); char *get_dam_message args( ( CHAR_DATA *ch, int dt)); char * get_attack_noun args( ( CHAR_DATA *ch, int dt)); int get_attack_number args( ( CHAR_DATA *ch, int dt)); bool check_dispel ( int dis_level, CHAR_DATA *victim, int sn); bool check_cutoff ( CHAR_DATA *ch, CHAR_DATA *victim); void do_arena_echo ( const char *txt); int check_imperial_training ( CHAR_DATA *ch); bool check_wall_thorns args( ( CHAR_DATA *ch)); void one_hit_new args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt, bool specials, bool blockable, int addition, int multiplier, char *dnoun)); bool damage_new args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt, int dam_type, bool show, bool blockable, int addition, int multiplier, char *dnoun)); char * weapon_name_lookup args( ( int type) ); int con_multiplier args( (int con, int dam) ); //Customizable dnoun, isPlural for singular or plural dverbs, showCharName (i.e. Zornath's blah or The blah), dealtByAffect for DoTs, keep_invisible to avoid revealing the ch bool damage_newer args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt, int dam_type, bool show, bool blockable, int addition, int multiplier, char *dnoun, bool isPlural, bool showCharName, AFFECT_DATA *dealtByAffect, bool keep_invisible ) ); int damage_calculate args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt, int dam_type, bool show, bool blockable, int addition, int multiplier) ); bool check_blademaster args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) ); void check_restrike args( ( CHAR_DATA *ch, CHAR_DATA *victim)); bool check_ward_diminution args( (CHAR_DATA *mage, CHAR_DATA *attacker, int dam, int type, int dt) ); bool check_unholy_new args( (CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA *obj) ); bool is_affected_obj args( (OBJ_DATA *obj, int sn) ); void check_paladin_combo args( (CHAR_DATA *ch, CHAR_DATA *victim) ); float hitroll_multiplier args( (CHAR_DATA *ch, CHAR_DATA *victim, float max_multiplier) ); bool check_shield_magnetism args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt )); /* * Control the fights going on. * Called periodically by update_handler. */ void violence_update( void ) { CHAR_DATA *ch; CHAR_DATA *ch_next; CHAR_DATA *victim; int regen, to_heal; OBJ_DATA *obj; for ( ch = char_list; ch != NULL; ch = ch_next ) { ch_next = ch->next; /* regen */ if (!IS_NPC(ch)) { regen = get_skill(ch,gsn_regeneration); to_heal = (ch->max_hit - ch->hit); if (number_percent() <= ch->level*2) { if ((ch->hit < ch->max_hit) && ch->noregen_dam < to_heal && number_percent() < regen) { if (number_percent() < 3) check_improve(ch,gsn_regeneration,TRUE,4); ch->hit += number_range(1,3); } } } //////// Begin Lich Quaff Potion Time Interval Messages //////// if (is_affected(ch,skill_lookup("lich elixir affect"))) { AFFECT_DATA *lichAffect = affect_find(ch->affected,skill_lookup("lich elixir affect")); char buf[MSL]; if (lichAffect->level == 59) { if (lichAffect->modifier == 8) { act("{BYou feel the elixir eating at your internal organs.{x",ch,0,0,TO_CHAR); lichAffect->modifier--; } else if (lichAffect->modifier == 6) { act("{BThin stripes of blackened energy play around you.{x",ch,0,0,TO_CHAR); lichAffect->modifier--; } else if (lichAffect->modifier == 4) { act("{BYour limbs, muscles, and bones seem to grow, the pain of transformation crippling you.{x",ch,0,0,TO_CHAR); lichAffect->modifier--; } else if (lichAffect->modifier == 2) { act("{BChunks of skin fall from your body, and suddenly the pain is gone.",ch,0,0,TO_CHAR); affect_strip(ch,skill_lookup("lich elixir affect")); ch->pcdata->learned[skill_lookup("minion tactics")] = 1; ch->pcdata->learned[skill_lookup("minion sanc")] =1; ch->pcdata->learned[skill_lookup("minion flight")] =1; ch->pcdata->learned[skill_lookup("minion sneak")] =1; ch->pcdata->learned[skill_lookup("minion recall")] =1; ch->pcdata->learned[skill_lookup("minion haste")] =1; ch->pcdata->learned[skill_lookup("minion trans")] =1; ch->pcdata->learned[skill_lookup("ritual of abominations")] = 1; ch->pcdata->learned[skill_lookup("vampiric touch")] = 1; ch->race = race_lookup("lich"); ch->perm_stat[STAT_STR]=pc_race_table[ch->race].max_stats[STAT_STR]; ch->perm_stat[STAT_INT]=pc_race_table[ch->race].max_stats[STAT_INT]; ch->perm_stat[STAT_WIS]=pc_race_table[ch->race].max_stats[STAT_WIS]; ch->perm_stat[STAT_DEX]=pc_race_table[ch->race].max_stats[STAT_DEX]; ch->perm_stat[STAT_CON]=pc_race_table[ch->race].max_stats[STAT_CON]; ch->mod_stat[STAT_STR]=0; ch->mod_stat[STAT_INT]=0; ch->mod_stat[STAT_WIS]=0; ch->mod_stat[STAT_DEX]=0; ch->mod_stat[STAT_CON]=0; sprintf(buf, "{RThe power of the undead courses through your veins as your soul becomes one with the Prime Negative Plane.{x\n\r"); send_to_char(buf,ch); ch->ghost += 10; } else lichAffect->modifier--; } else if (lichAffect->level == 60) { if (lichAffect->modifier == 8) { act("{BYou feel the elixir eating at your internal organs.{x",ch,0,0,TO_CHAR); lichAffect->modifier--; } else if (lichAffect->modifier == 6) { act("{BThin stripes of blackened energy play around you.{x",ch,0,0,TO_CHAR); lichAffect->modifier--; } else if (lichAffect->modifier == 4) { act("{BYour limbs, muscles, and bones seem to grow, the pain of transformation crippling you.{x",ch,0,0,TO_CHAR); lichAffect->modifier--; } else if (lichAffect->modifier == 2) { act("{RJust as quickly, your body falls to the ground, the power leaving you.{x",ch,0,0,TO_CHAR); affect_strip(ch,skill_lookup("lich elixir affect")); if (!IS_IMMORTAL(ch)) age_death(ch); } else lichAffect->modifier--; } } //////// End Lich Quaff Potion Time Interval Messages //////// if (ch->regen_rate != 0) { if (ch->regen_rate > 0) regen = number_range(1,ch->regen_rate); else regen = number_range(ch->regen_rate, -1); if (ch->regen_rate > 0) { ch->hit = UMIN(ch->hit + regen,ch->max_hit); ch->mana = UMIN(ch->mana + regen / 2, ch->max_mana); ch->move = UMIN(ch->move + regen / 2, ch->max_move); } else { ch->hit = UMAX(ch->hit + regen,0); ch->mana = UMAX(ch->mana + regen / 2, 0); ch->move = UMAX(ch->move + regen / 2, 0); } } if ( ( victim = ch->fighting ) == NULL || ch->in_room == NULL ) continue; if (IS_NPC(ch) && (!IS_NPC(ch->fighting)) && !IS_SET(ch->act,ACT_NO_TRACK) && !IS_AFFECTED(ch,AFF_CHARM) && !IS_SET(ch->act,ACT_IS_HEALER) && !IS_SET(ch->act,ACT_BANKER)) ch->last_fought = ch->fighting; update_pc_last_fight(ch,ch->fighting); if ( IS_AWAKE(ch) && ch->in_room == victim->in_room ) { multi_hit( ch, victim, TYPE_UNDEFINED ); } else { stop_fighting( ch, FALSE ); } if ( ( victim = ch->fighting ) == NULL ) continue; for (obj = ch->carrying;obj != NULL; obj = obj->next_content) if (IS_SET(obj->progtypes,IPROG_FIGHT)) (obj->pIndexData->iprogs->fight_prog) (obj,ch); if (IS_SET(ch->progtypes,MPROG_FIGHT) && (ch->wait <= 0)) (ch->pIndexData->mprogs->fight_prog) (ch,victim); /* * Fun for the whole family! */ check_assist(ch,victim); } return; } /* for auto assisting */ void check_assist(CHAR_DATA *ch,CHAR_DATA *victim) { CHAR_DATA *rch, *rch_next; for (rch = ch->in_room->people; rch != NULL; rch = rch_next) { rch_next = rch->next_in_room; if (!IS_NPC(rch) && rch->ghost > 0) continue; if (IS_AWAKE(rch) && rch->fighting == NULL) { if (IS_NPC(rch) && (IS_AFFECTED(rch,AFF_CHARM)) && is_same_group(rch,ch) ) { multi_hit(rch,victim,TYPE_UNDEFINED); continue; } /* quick check for ASSIST_PLAYER */ if (!IS_NPC(ch) && IS_NPC(rch) && IS_SET(rch->off_flags,ASSIST_PLAYERS) && rch->level + 6 > victim->level) { do_emote(rch,"screams and attacks!"); multi_hit(rch,victim,TYPE_UNDEFINED); continue; } /* PCs next */ if ( !IS_NPC(ch) || IS_AFFECTED(ch,AFF_CHARM)) { if ( ( (!IS_NPC(rch) && IS_SET(rch->act,PLR_AUTOASSIST)) || IS_AFFECTED(rch,AFF_CHARM)) && is_same_group(ch,rch) && !is_safe(rch, victim)) multi_hit (rch,victim,TYPE_UNDEFINED); continue; } /* now check the NPC cases */ if (IS_NPC(ch) && !IS_AFFECTED(ch,AFF_CHARM)) { if ( (IS_NPC(rch) && IS_SET(rch->off_flags,ASSIST_ALL) ) || (IS_NPC(rch) && rch->group && rch->group == ch->group) || (IS_NPC(rch) && rch->race == ch->race && IS_SET(rch->off_flags,ASSIST_RACE)) || (IS_NPC(rch) && IS_SET(rch->off_flags,ASSIST_ALIGN) && ((IS_GOOD(rch) && IS_GOOD(ch)) || (IS_EVIL(rch) && IS_EVIL(ch)) || (IS_NEUTRAL(rch) && IS_NEUTRAL(ch)))) || (rch->pIndexData == ch->pIndexData && IS_SET(rch->off_flags,ASSIST_VNUM))) { CHAR_DATA *vch; CHAR_DATA *target; int number; if (number_bits(1) == 0) continue; target = NULL; number = 0; for (vch = ch->in_room->people; vch; vch = vch->next) { if (can_see(rch,vch) && is_same_group(vch,victim) && number_range(0,number) == 0) { target = vch; number++; } } if (target != NULL) { do_emote(rch,"screams and attacks!"); multi_hit(rch,target,TYPE_UNDEFINED); } } } } } } /* * Do one group of attacks. */ void multi_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { int chance, dual_chance; char buf[MAX_STRING_LENGTH]; if (is_affected(ch,gsn_timestop)) { if (ch->fighting != NULL) ch->fighting = NULL; return; } if (ch->desc == NULL) ch->wait = UMAX(0,ch->wait - PULSE_VIOLENCE); if (ch->desc == NULL) ch->daze = UMAX(0,ch->daze - PULSE_VIOLENCE); if (ch->level == MAX_LEVEL) ch->daze = 0; if(ch->in_room!=victim->in_room) { ch->fighting = NULL; victim->fighting = NULL; ch->position = POS_STANDING; victim->position = POS_STANDING; update_pos(ch); update_pos(victim); return; } if(is_affected(victim,gsn_snare) && number_percent()<80 && victim->fighting!=NULL) { act("In the chaos of combat, the snare holding $n comes loose.",victim,0,0,TO_ROOM); act("In the chaos of combat, the snare holding you comes loose.",victim,0,0,TO_CHAR); affect_strip(victim,gsn_snare); } if (ch->position < POS_RESTING) return; if (IS_NPC(ch)) { mob_hit(ch,victim,dt); return; } if (IS_NPC(victim) && IS_CABAL_GUARD(victim) && !IS_NPC(ch) && (ch->pcdata->newbie==TRUE || ch->ghost > 0)) { int attempt, door; for ( attempt = 0; attempt < 6; attempt++ ) { EXIT_DATA *pexit; ROOM_INDEX_DATA *was_in; door = number_door( ); was_in = ch->in_room; if ( ( pexit = was_in->exit[door] ) == 0 || pexit->u1.to_room == NULL || pexit->u1.to_room->cabal>0) continue; act("$N growls with rage and throws you out of the room!",ch,0,victim,TO_CHAR); act("$N growls with rage and throws $n out of the room!",ch,0,victim,TO_ROOM); char_from_room(ch); char_to_room(ch, pexit->u1.to_room); do_look(ch,"auto"); ch->ghost = 1; stop_fighting( victim, TRUE ); return; } } if (IS_NPC(victim) && IS_CABAL_GUARD(victim) && !IS_NPC(ch) && ch->cabal==victim->cabal) { sprintf(buf,"How DARE you attack me, %s!",ch->name); do_cb(victim,buf); } // First hit. one_hit( ch, victim, dt ); if (ch->fighting != victim) return; if ( ch->fighting != victim || dt == gsn_backstab || (dt == gsn_ambush)) return; if (IS_AFFECTED(ch,AFF_HASTE) && (IS_NPC(ch) || get_skill(ch,gsn_third_attack)>5)) one_hit(ch,victim,dt); chance = get_skill(ch,gsn_second_attack)/2 + GET_HITROLL(ch) / 5; dual_chance = get_skill(ch,gsn_dual_wield)/2 + GET_HITROLL(ch) / 5; if (is_affected(ch,gsn_maehslin) && number_percent() < 20) { act("The amber aura around $n intenses and their movements become more fluid!",ch,0,victim,TO_VICT); act("$n's amber aura intenses and their movements become more fluid!" ,ch,0,0,TO_NOTVICT); act("Your amber aura intenses and your movements become more fluid!",ch,0,0,TO_CHAR); one_hit_new(ch,victim,dt,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,NULL); } //////////////////////////// Begin Critical Strike Check ///////////////////////////////// if (number_percent() < ch->pcdata->learned[skill_lookup("critical strike")] / 6) { if (is_wielded(ch,WEAPON_SWORD,WIELD_PRIMARY) || is_wielded(ch,WEAPON_AXE,WIELD_PRIMARY) || is_wielded(ch,WEAPON_DAGGER,WIELD_PRIMARY) || is_wielded(ch,WEAPON_SPEAR,WIELD_PRIMARY) || is_wielded(ch,WEAPON_POLEARM,WIELD_PRIMARY) || is_wielded(ch,WEAPON_EXOTIC,WIELD_PRIMARY)) { act("You deliver a critical strike!",ch,0,0,TO_CHAR); act("$n delivers a critical strike!",ch,0,0,TO_ROOM); one_hit_new(ch,victim,dt,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,175,"critical strike"); if (!is_affected(victim,skill_lookup("critical strike"))) { act("$n's critical strike tears open an immense gash in your body!",ch,0,victim,TO_VICT); act("$n's critical strike tears open an immense gash in $N's body!",ch,0,victim,TO_NOTVICT); act("Your critical strike tears open an immense gash in $N's body!",ch,0,victim,TO_CHAR); AFFECT_DATA bleeding; init_affect(&bleeding); bleeding.aftype = AFT_SKILL; bleeding.type = skill_lookup("critical strike"); bleeding.affect_list_msg = str_dup("induces major bleeding"); bleeding.owner_name = str_dup(ch->original_name); bleeding.duration = 3; if (is_wielded(ch,WEAPON_SWORD,WIELD_PRIMARY)) bleeding.level = 3; else if (is_wielded(ch,WEAPON_AXE,WIELD_PRIMARY)) bleeding.level = 4; else if (is_wielded(ch,WEAPON_DAGGER,WIELD_PRIMARY)) bleeding.level = 2; else if (is_wielded(ch,WEAPON_POLEARM,WIELD_PRIMARY)) bleeding.level = 5; else if (is_wielded(ch,WEAPON_SPEAR,WIELD_PRIMARY)) bleeding.level = 6; else bleeding.level = 10; affect_to_char(victim,&bleeding); } } else if (is_wielded(ch,WEAPON_FLAIL,WIELD_PRIMARY) || is_wielded(ch,WEAPON_MACE,WIELD_PRIMARY) || is_wielded(ch,WEAPON_STAFF,WIELD_PRIMARY) || is_wielded(ch,WEAPON_WHIP,WIELD_PRIMARY)) { act("You deliver a critical strike!",ch,0,0,TO_CHAR); act("$n delivers a critical strike!",ch,0,0,TO_ROOM); one_hit_new(ch,victim,dt,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,175,"critical strike"); if (!is_affected(victim,skill_lookup("critical strike"))) { act("You feel your bones shatter under the force of $n's critical strike!",ch,0,victim,TO_VICT); act("$n's critical strike shatters $N's bones!",ch,0,victim,TO_NOTVICT); act("Your critical strike shatters $N's bones!",ch,0,victim,TO_CHAR); AFFECT_DATA boneshatter; init_affect(&boneshatter); boneshatter.aftype = AFT_SKILL; boneshatter.type = skill_lookup("critical strike"); boneshatter.duration = 3; boneshatter.level = 1; boneshatter.owner_name = str_dup(ch->original_name); boneshatter.location = APPLY_STR; if (is_wielded(ch,WEAPON_FLAIL,WIELD_PRIMARY)) boneshatter.modifier = -3; else if (is_wielded(ch,WEAPON_MACE,WIELD_PRIMARY)) boneshatter.modifier = -4; else if (is_wielded(ch,WEAPON_STAFF,WIELD_PRIMARY)) boneshatter.modifier = -3; else if (is_wielded(ch,WEAPON_WHIP,WIELD_PRIMARY)) boneshatter.modifier = -2; else boneshatter.modifier = -1; affect_to_char(victim,&boneshatter); boneshatter.location = APPLY_DEX; if (is_wielded(ch,WEAPON_FLAIL,WIELD_PRIMARY)) boneshatter.modifier = -3; else if (is_wielded(ch,WEAPON_MACE,WIELD_PRIMARY)) boneshatter.modifier = -4; else if (is_wielded(ch,WEAPON_STAFF,WIELD_PRIMARY)) boneshatter.modifier = -3; else if (is_wielded(ch,WEAPON_WHIP,WIELD_PRIMARY)) boneshatter.modifier = -2; else boneshatter.modifier = -1; affect_to_char(victim,&boneshatter); } } } //////////////////////////// End Critical Strike Check ///////////////////////////////// //////////////////////////// Begin Anaconda Stance Fight Check ///////////////////////////////// AFFECT_DATA *anacondaCheck = affect_find(ch->affected,gsn_stance), *poisonCheck = affect_find(victim->affected,gsn_poison), anacondaPoison; int poisonLevel = 51, poisonDuration = 3, strLoss = -1; if (anacondaCheck != NULL) { if (anacondaCheck->level == 5) { if (number_percent() < 15) { act("$n strikes forward suddenly, piercing through your defenses!",ch,0,victim,TO_VICT); act("$n strikes forward suddenly, piercing through $N's defenses!",ch,0,victim,TO_NOTVICT); act("With the speed of an Anaconda, you penetrate $N's defenses!",ch,0,victim,TO_CHAR); one_hit_new(ch,victim,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,150,"serpent strike"); if (poisonCheck != NULL) { if (!str_cmp(poisonCheck->name,"anaconda venom")) { poisonLevel = poisonCheck->level + 2; if (poisonCheck->duration < 20) poisonDuration = poisonCheck->duration + 3; else poisonDuration = poisonCheck->duration; strLoss = poisonCheck->modifier - 1; if (poisonLevel > 100) poisonLevel = 100; if (poisonDuration > 100) poisonDuration = 100; if (strLoss > 100) strLoss = 100; act("You feel your body tingle as poison seeps into your veins.",ch,0,victim,TO_VICT); act("$N looks very sick.",ch,0,victim,TO_NOTVICT); act("You release poison into $N's veins!",ch,0,victim,TO_CHAR); affect_remove(victim,poisonCheck); init_affect(&anacondaPoison); anacondaPoison.where = TO_AFFECTS; anacondaPoison.aftype = AFT_SKILL; anacondaPoison.type = gsn_poison; anacondaPoison.level = poisonLevel; anacondaPoison.duration = poisonDuration; anacondaPoison.name = str_dup("anaconda venom"); anacondaPoison.location = APPLY_STR; anacondaPoison.modifier = strLoss; anacondaPoison.owner_name = str_dup(ch->original_name); anacondaPoison.bitvector = AFF_POISON; affect_to_char(victim,&anacondaPoison); } } else if (poisonCheck == NULL) { act("You feel your body tingle as poison seeps into your veins.",ch,0,victim,TO_VICT); act("$N looks very sick.",ch,0,victim,TO_ROOM); act("You release poison into $N's veins!",ch,0,victim,TO_CHAR); init_affect(&anacondaPoison); anacondaPoison.where = TO_AFFECTS; anacondaPoison.aftype = AFT_SKILL; anacondaPoison.type = gsn_poison; anacondaPoison.level = poisonLevel; anacondaPoison.duration = poisonDuration; anacondaPoison.name = str_dup("anaconda venom"); anacondaPoison.modifier = strLoss; anacondaPoison.owner_name = str_dup(ch->original_name); affect_to_char(victim,&anacondaPoison); } } } } //////////////////////////// End Anaconda Stance Fight Check ///////////////////////////////// if (check_darkshout(ch) == DARKSHOUT_MEPHISTOPHELES && number_percent() < 40) { damage_new(ch, victim, 250, TYPE_UNDEFINED, DAM_FIRE, TRUE, HIT_UNBLOCKABLE, HIT_NOADD, HIT_NOMULT, "infernal wrath"); } if (is_affected(ch,gsn_shield_of_truth) && get_eq_char(ch,WEAR_SHIELD) != NULL) { int healingCheck = number_percent(); if (healingCheck <= 65) { act("The power of your god flows through your body, revitalizing you.",ch,0,0,TO_CHAR); act("$n looks more at peace as his wounds seem to heal.",ch,0,0,TO_ROOM); } if (healingCheck < 45) (*skill_table[skill_lookup("cure serious")].spell_fun) (skill_lookup("cure serious"), 51, ch, ch, TAR_CHAR_DEFENSIVE); if (healingCheck >= 45 && healingCheck < 57) (*skill_table[skill_lookup("cure critical")].spell_fun) (skill_lookup("cure serious"), 51, ch, ch, TAR_CHAR_DEFENSIVE); if (healingCheck >= 57 && healingCheck <= 65) (*skill_table[skill_lookup("heal")].spell_fun) (skill_lookup("heal"), 51, ch, ch, TAR_CHAR_DEFENSIVE); } if (IS_AFFECTED(ch,AFF_HASTE)) { chance*=1.25; dual_chance*=1.25; } if (IS_AFFECTED(ch,AFF_SLOW)) { chance /= 2; dual_chance /= 2; } if (check_imperial_training(ch) == IMPERIAL_DEFENSE) { chance /= 2.5; dual_chance /= 2.5; } if ( number_percent( ) < chance ) { one_hit( ch, victim, dt ); check_improve(ch,gsn_second_attack,TRUE,5); if ( ch->fighting != victim ) return; } if (get_eq_char(ch,WEAR_DUAL_WIELD) != NULL && ch->pcdata->learned[gsn_second_attack] > 10) { if (number_percent( ) < dual_chance) { one_hit(ch,victim,gsn_dual_wield); check_improve(ch,gsn_dual_wield,TRUE,3); if (ch->fighting != victim) return; } else { check_improve(ch,gsn_dual_wield,FALSE,3); } } chance = get_skill(ch,gsn_third_attack)/4 + GET_HITROLL(ch) / 10; if (IS_AFFECTED(ch,AFF_SLOW)) chance = 0; if (IS_AFFECTED(ch,AFF_HASTE)) chance*=1.3; if ( number_percent( ) < chance ) { one_hit( ch, victim, dt ); check_improve(ch,gsn_third_attack,TRUE,6); if ( ch->fighting != victim ) return; } dual_chance = get_skill(ch,gsn_dual_wield)/4 + GET_HITROLL(ch) / 10; if (IS_AFFECTED(ch,AFF_HASTE)) dual_chance*=1.2; if (get_eq_char(ch,WEAR_DUAL_WIELD) != NULL && ch->pcdata->learned[gsn_third_attack] > 10) { if (number_percent( ) < dual_chance) { one_hit(ch,victim,gsn_dual_wield); check_improve(ch,gsn_dual_wield,TRUE,3); if (ch->fighting != victim) return; } else { check_improve(ch,gsn_dual_wield,FALSE,3); } } chance = get_skill(ch,gsn_fourth_attack)/5 + GET_HITROLL(ch) / 15; if (IS_AFFECTED(ch,AFF_SLOW)) chance /= 2; if (IS_AFFECTED(ch,AFF_HASTE)) chance*=1.3; if ( number_percent() < chance ) { one_hit( ch, victim, dt ); check_improve(ch,gsn_fourth_attack,TRUE,6); if (ch->fighting != victim ) return; } dual_chance = get_skill(ch,gsn_dual_wield)/4 + GET_HITROLL(ch) / 15; if (IS_AFFECTED(ch,AFF_HASTE)) dual_chance*=1.2; if (get_eq_char(ch,WEAR_DUAL_WIELD) != NULL && ch->pcdata->learned[gsn_fourth_attack] > 10) { if (number_percent( ) < dual_chance) { one_hit(ch,victim,gsn_dual_wield); check_improve(ch,gsn_dual_wield,TRUE,6); if (ch->fighting != victim) return; } else { check_improve(ch,gsn_dual_wield,FALSE,5); } } int off_chance = 3 * get_skill(ch,skill_lookup("unarmed offense")) / 4; if (IS_AFFECTED(ch,AFF_HASTE)) off_chance = 3 * off_chance / 2; if (check_imperial_training(ch) == IMPERIAL_OFFENSE) off_chance = 5 * off_chance / 4; if (get_eq_char(ch,WEAR_WIELD) == NULL && get_eq_char(ch,WEAR_DUAL_WIELD) == NULL && ch->pcdata->learned[skill_lookup("unarmed offense")] > 10) { if (number_percent() < off_chance) { one_hit(ch,victim,dt); check_improve(ch,skill_lookup("unarmed offense"),TRUE,3); if (number_percent() < off_chance / 2) { one_hit(ch,victim,dt); check_improve(ch,skill_lookup("unarmed offense"),TRUE,5); } } else check_improve(ch,skill_lookup("unarmed offense"),FALSE,3); } if (is_affected(victim,gsn_blackjack)) { affect_strip(victim,gsn_blackjack); return; } /* imperial training */ if (check_imperial_training(ch) == IMPERIAL_OFFENSE && get_skill(ch,gsn_third_attack)>80) one_hit(ch, victim, dt); int extraAttacks; if(ch->numAttacks > 0) for (extraAttacks = 1;extraAttacks<=ch->numAttacks;extraAttacks++) if (extraAttacks <= 20) one_hit(ch,victim,dt); return; } /* procedure for all mobile attacks */ void mob_hit (CHAR_DATA *ch, CHAR_DATA *victim, int dt) { int chance,number; int dual_chance; CHAR_DATA *vch, *vch_next; one_hit(ch,victim,dt); if (ch->fighting != victim) return; /* Area attack -- BALLS nasty! */ if (IS_SET(ch->off_flags,OFF_AREA_ATTACK)) { for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next; if ((vch != victim && vch->fighting == ch)) one_hit(ch,vch,dt); } } if (IS_AFFECTED(ch,AFF_HASTE) || (IS_SET(ch->off_flags,OFF_FAST) && !IS_AFFECTED(ch,AFF_SLOW))) one_hit(ch,victim,dt); if (ch->fighting != victim || dt == gsn_backstab) return; chance = get_skill(ch,gsn_second_attack)/2; dual_chance = ch->level*2/3; if (IS_AFFECTED(ch,AFF_SLOW) && !IS_SET(ch->off_flags,OFF_FAST)) { dual_chance /= 2; chance /= 2; } if (number_percent() < chance) { one_hit(ch,victim,dt); if (ch->fighting != victim) return; } if (IS_AFFECTED(ch,AFF_HASTE)) dual_chance *= 6/4; if (number_percent() < dual_chance && get_eq_char(ch,WEAR_DUAL_WIELD) != NULL) { one_hit(ch,victim,gsn_dual_wield); if (ch->fighting != victim) return; } chance = get_skill(ch,gsn_third_attack)/4; dual_chance *= 2/3; if (IS_AFFECTED(ch,AFF_SLOW) && !IS_SET(ch->off_flags,OFF_FAST)) { dual_chance = 0; chance = 0; } if (IS_AFFECTED(ch,AFF_HASTE)) dual_chance *= 3/2; if (number_percent() < chance) { one_hit(ch,victim,dt); if (ch->fighting != victim) return; } if (number_percent() < dual_chance && get_eq_char(ch,WEAR_DUAL_WIELD) != NULL) { one_hit(ch,victim,gsn_dual_wield); if (ch->fighting != victim) return; } if (ch->pIndexData->vnum >= 28000 && ch->pIndexData->vnum <= 28011) { int hits=number_range(1,2); int x; for (x=0; x<hits; x++) { one_hit(ch,victim,dt); if (ch->fighting != victim) return; } } if (ch->wait > 0) return; /* now for the skills */ number = number_range(0,9); switch(number) { case (0) : if (IS_SET(ch->off_flags,OFF_BASH)) do_bash(ch,""); else if (IS_SET(ch->off_flags,OFF_TAIL)) do_tail(ch,""); break; case (1) : if (IS_SET(ch->off_flags,OFF_BERSERK) && !IS_AFFECTED(ch,AFF_BERSERK)) do_berserk(ch,""); break; case (2) : if (IS_SET(ch->off_flags,OFF_DISARM) || (get_weapon_sn(ch) != gsn_hand_to_hand && (IS_SET(ch->act,ACT_WARRIOR) || IS_SET(ch->act,ACT_THIEF)))) do_disarm(ch,""); break; case (3) : if (IS_SET(ch->off_flags,OFF_KICK)) do_kick(ch,""); break; case (4) : if (IS_SET(ch->off_flags,OFF_KICK_DIRT)) do_dirt(ch,""); break; case (5) : if (IS_SET(ch->off_flags,OFF_TAIL)) { do_tail(ch,""); } break; case (6) : if (IS_SET(ch->off_flags,OFF_TRIP)) do_trip(ch,""); break; case (7) : if (IS_SET(ch->off_flags,OFF_CRUSH)) { do_crush(ch,"") ; } break; case (8) : if (IS_SET(ch->off_flags,OFF_BACKSTAB)) { do_backstab(ch,""); } else if (IS_SET(ch->off_flags,OFF_UNDEAD_DRAIN)) do_undead_drain(ch,""); break; case (9) : if ( IS_SET(ch->off_flags,OFF_UNDEAD_DRAIN)) { do_undead_drain(ch,""); } break; } int extraAttacks; if(ch->numAttacks > 0) for (extraAttacks = 1;extraAttacks<=ch->numAttacks;extraAttacks++) if(extraAttacks <= 20) one_hit(ch,victim,dt); } /* * Hit one guy once. */ void one_hit(CHAR_DATA *ch, CHAR_DATA *victim, int dt) { one_hit_new(ch,victim,dt,HIT_SPECIALS,HIT_BLOCKABLE,HIT_NOADD,HIT_NOMULT,NULL); } void one_hit_new( CHAR_DATA *ch, CHAR_DATA *victim, int dt, bool specials, bool blockable, int addition, int multiplier, char *dnoun) { OBJ_DATA *wield; int dam, mdam, fchance, tchance, diceroll, diceroll2 = 0, sn, skill, dam_type, tmp_dt, tdt=dt; bool result, truestrike = FALSE, exeresult; const char *attack; char buf1[MAX_STRING_LENGTH], buf2[MAX_STRING_LENGTH], buf3[MAX_STRING_LENGTH]; /* just in case */ if (victim == ch || ch == NULL || victim == NULL) return; if(dt == TYPE_TRUESTRIKE) { truestrike = TRUE; dt = TYPE_UNDEFINED; } if ( victim->position == POS_DEAD || (ch->in_room != victim->in_room)) return; if (is_safe(ch,victim)) return; /* * Figure out the type of damage message. */ wield = get_eq_char( ch, WEAR_WIELD ); if ( dt == TYPE_UNDEFINED ) { dt = TYPE_HIT; if ( wield != NULL && wield->item_type == ITEM_WEAPON ) dt += wield->value[3]; else dt += ch->dam_type; } if(is_affected(ch,gsn_executioner) && number_percent()<5 && specials==TRUE && tdt==TYPE_UNDEFINED) { act("$n darts forward and gracefully strikes you!",ch,0,victim,TO_VICT); act("$n darts forward and gracefully strikes $N!",ch,0,victim,TO_NOTVICT); act("Moving fluidly, you dart forward and gracefully strike $N!",ch,0,victim,TO_CHAR); one_hit_new( ch, victim, TYPE_UNDEFINED, HIT_NOSPECIALS, HIT_UNBLOCKABLE, HIT_NOADD, HIT_NOMULT, NULL); return; } if(is_affected(victim,gsn_executioner) && number_percent()<7 && dt!=gsn_flurry && dt!=gsn_drum && specials==TRUE) { act("$n smoothly redirects $N's attack, unleashing a deadly riposte!",victim,0,ch,TO_NOTVICT); act("You smoothly redirect $N's attack, and unleash a deadly riposte!",victim,0,ch,TO_CHAR); act("$n smoothly redirects your attack, unleashing a deadly riposte!",victim,0,ch,TO_VICT); one_hit_new( victim, ch, TYPE_UNDEFINED, HIT_NOSPECIALS, HIT_UNBLOCKABLE, HIT_NOADD, HIT_NOMULT, NULL); return; } if (IS_NPC(ch) && ch->pIndexData->vnum == 3011) truestrike = TRUE; if(get_skill(victim,gsn_backfist) !=0 && specials==TRUE) { if (number_percent() < (get_skill(victim,gsn_backfist)/4) && count_hands(ch) < 2) { act("$n steps in quickly to strike $N with a quick backfist!",victim,0,ch,TO_NOTVICT); act("You step in quickly to strike $N with a quick backfist!",victim,0,ch,TO_CHAR); act("$n steps in quickly to strike you with a quick backfist!",victim,0,ch,TO_VICT); exeresult = damage( victim, ch, GET_DAMROLL(victim), gsn_backfist, DAM_BASH, TRUE ); check_improve(victim,gsn_backfist,TRUE,2); } else { check_improve(victim,gsn_backfist,FALSE,5); } } if(is_affected(victim,gsn_shield_of_redemption) && get_eq_char(victim,WEAR_SHIELD) != NULL && number_percent() > 40) damage_new(victim, ch, number_range(20,30), TYPE_UNDEFINED, DAM_HOLY, TRUE, HIT_UNBLOCKABLE, HIT_NOADD, HIT_NOMULT, "shield of redemption"); if (wield != NULL) dam_type = attack_table[wield->value[3]].damage; else dam_type = attack_table[ch->dam_type].damage; if (dam_type == -1) dam_type = DAM_BASH; /* get the weapon skill */ sn = get_weapon_sn(ch); skill = 20 + get_weapon_skill(ch,sn); if (dt == gsn_dual_wield) { wield = get_eq_char( ch, WEAR_DUAL_WIELD ); tmp_dt = TYPE_HIT; if ( wield != NULL && wield->item_type == ITEM_WEAPON ) tmp_dt += wield->value[3]; else tmp_dt += ch->dam_type; if (tmp_dt < TYPE_HIT) { if (wield != NULL) dam_type = attack_table[wield->value[3]].damage; else dam_type = attack_table[ch->dam_type].damage; } else { dam_type = attack_table[dt - TYPE_HIT].damage; } if (dam_type == -1) dam_type = DAM_BASH; if (wield == NULL) sn = -1; else switch (wield->value[0]) { default: sn = -1; break; case (WEAPON_SWORD): sn = gsn_sword; break; case (WEAPON_DAGGER): sn = gsn_dagger; break; case (WEAPON_SPEAR): sn = gsn_spear; break; case (WEAPON_MACE): sn = gsn_mace; break; case (WEAPON_AXE): sn = gsn_axe; break; case (WEAPON_FLAIL): sn = gsn_flail; break; case (WEAPON_WHIP): sn = gsn_whip; break; case (WEAPON_POLEARM): sn = gsn_polearm; break; } skill = 10 + get_weapon_skill(ch,sn); } if(truestrike) dam_type = DAM_TRUESTRIKE; if(victim->cabal==CABAL_KNIGHT && get_skill(victim,skill_lookup("blademaster"))>0 && specials==TRUE) { tchance=3+((get_skill(victim,skill_lookup("blademaster"))-75)/3); if(is_affected(victim,AFF_HASTE)) tchance+=2; if(is_affected(victim,AFF_SLOW)) tchance-=5; if(number_percent()<tchance) { attack = get_attack_noun(ch,dt); if(cabal_down_new(victim,CABAL_KNIGHT,FALSE)) return; sprintf(buf1,"$n parries $N's %s, and skillfully unleashes an attack of $s own!",attack); act(buf1,victim,0,ch,TO_NOTVICT); sprintf(buf2,"You parry $N's %s and skillfully unleash an attack of your own!",attack); act(buf2,victim,0,ch,TO_CHAR); sprintf(buf3,"$n parries your %s and skillfully unleashes an attack of $s own!",attack); act(buf3,victim,0,ch,TO_VICT); attack = get_attack_noun(victim,dt); one_hit_new( victim, ch, dt, HIT_NOSPECIALS, HIT_UNBLOCKABLE, HIT_NOADD, HIT_NOMULT, str_dup(attack)); check_improve(victim, skill_lookup("blademaster"),TRUE,5); return; } } if((IS_NPC(victim) && IS_SET(victim->off_flags,OFF_FADE)) || is_affected(victim,gsn_displacement)) { fchance = 25 + (victim->level - ch->level); if(IS_AFFECTED(ch,AFF_HASTE)) fchance-=8; if(IS_AFFECTED(victim,AFF_HASTE)) fchance+=5; if(number_percent()<fchance) { attack = get_attack_noun(ch,dt); sprintf(buf1,"$N's %s lands on empty air near $n.",attack); act(buf1,victim,0,ch,TO_NOTVICT); sprintf(buf2,"$N's %s lands on empty air near you.",attack); act(buf2,victim,0,ch,TO_CHAR); sprintf(buf3,"Your %s lands on empty air near $n.",attack); act(buf3,victim,0,ch,TO_VICT); if(!ch->fighting && !victim->fighting) set_fighting(ch,victim); return; } } /* * Hit. * Calc damage. */ if ( IS_NPC(ch) && (!ch->pIndexData->new_format || wield == NULL)) { if (!ch->pIndexData->new_format) { dam = number_range( ( ch->level + ch->drain_level) / 2, (ch->drain_level + ch->level) * 3 / 2 ); if ( wield != NULL ) dam += dam / 2; } else dam = dice(ch->damage[DICE_NUMBER],ch->damage[DICE_TYPE]); } else { if (sn != -1) check_improve(ch,sn,TRUE,5); if ( wield != NULL ) { if (wield->pIndexData->new_format) dam = dice(wield->value[1],wield->value[2]) * skill/100; else dam = number_range( wield->value[1] * skill/100, wield->value[2] * skill/100); if (get_eq_char(ch,WEAR_SHIELD) == NULL) /* no shield = more */ dam = dam * 11/10; if (wield->level - (ch->drain_level + ch->level) >= 35) dam = (dam*6)/10; else if (wield->level - (ch->drain_level + ch->level) >= 25) dam = (dam*7)/10; else if (wield->level - (ch->drain_level + ch->level) >= 15) dam = (dam*8)/10; else if (wield->level - (ch->drain_level + ch->level) >= 5) dam = (dam*9)/10; /* sharpness! */ if (IS_WEAPON_STAT(wield,WEAPON_SHARP)) { int percent; if ((percent = number_percent()) <= (skill / 8)) dam *= 1.2; } } else dam = number_range( 1 + GET_DAMROLL(ch) / 12 + 7 * skill/100, (ch->level - 5) * skill/100); } /* * Bonuses. */ dam += (ch->drain_level + ch->level)/8; if ( get_skill(ch,gsn_enhanced_damage) > 0 ) { diceroll = number_percent(); if (get_skill(ch,gsn_enhanced_damage_two) > 0) { diceroll2 = number_percent(); if (diceroll2 < get_skill(ch,gsn_enhanced_damage_two) && diceroll2 < get_skill(ch,gsn_enhanced_damage) ) { check_improve(ch,gsn_enhanced_damage_two,TRUE,5); diceroll2 = diceroll2 + 5; diceroll = diceroll2; } } if (get_skill(ch,gsn_enhanced_damage_three) > 0) { check_improve(ch,gsn_enhanced_damage_three,TRUE,3); diceroll += get_skill(ch,gsn_enhanced_damage_three)/3; } if (diceroll <= get_skill(ch,gsn_enhanced_damage)) { check_improve(ch,gsn_enhanced_damage,TRUE,6); dam += (dam * diceroll/125); } } else { dam *= 7; dam /= 10; } if ( !IS_AWAKE(victim) ) dam *= 2; else if (victim->position < POS_FIGHTING) dam = dam * 3 / 2; if ( dt == gsn_backstab && wield != NULL) { if ( wield->value[0] != 2 ) dam *= 2 + ((ch->level + ch->drain_level) / 10) ; else dam *= 2 + ((ch->drain_level + ch->level) / 8); } if ( dt == gsn_ambush ) dam *= 5/2 + ((ch->drain_level + ch->level) / 6 ); mdam = GET_DAMROLL(ch); dam += mdam * UMIN(100,skill) /100; if (wield != NULL && IS_WEAPON_STAT(wield,WEAPON_VORPAL) && number_percent() < 20) { act("$p emits a fierce red glow as it lashes violently at $N!",ch,wield,victim,TO_CHAR); act("$p emits a fierce red glow as it lashes violently at You!",ch,wield,victim,TO_VICT); act("$p emits a fierce red glow as it lashes violently at $N!",ch,wield,victim,TO_NOTVICT); dam *= 1.2; } if (wield != NULL && wield->pIndexData->vnum == OBJ_VNUM_AVENGER) { if (IS_WEAPON_STAT(wield,WEAPON_SHADOWBANE) && number_percent() < 7) { act("$p flares and sears $N!",ch,wield,victim,TO_CHAR); act("$p flares and sears you!",ch,wield,victim,TO_VICT); act("$p flares and sears $N!",ch,wield,victim,TO_NOTVICT); dam *= 1.5; } if (IS_WEAPON_STAT(wield,WEAPON_LIGHTBRINGER) && number_percent() < 10) { act("$p flares and sears $N!",ch,wield,victim,TO_CHAR); act("$p flares and sears you!",ch,wield,victim,TO_VICT); act("$p flares and sears $N!",ch,wield,victim,TO_NOTVICT); dam *= 1.7; } } if(!IS_NPC(ch) && ch->cabal == CABAL_RAGER && !cabal_down_new(ch,CABAL_RAGER,FALSE) && number_percent()<=5 && specials==TRUE) { send_to_char("You land an especially devastating blow!\n\r",ch); act("$n lands an especially devastating blow!",ch,0,0,TO_ROOM); dam *= 3.5; } // Same as above, except for rager mobs. if (IS_NPC(ch) && ch->cabal == CABAL_RAGER && number_percent() < 15 && specials == TRUE && (IS_CABAL_OUTER_GUARD(ch) || IS_CABAL_GUARD(ch))) { send_to_char("You land an especially devastating blow!\n\r",ch); act("$n lands an especially devastating blow!",ch,0,0,TO_ROOM); dam *= 3; } if ( dam <= 0 ) dam = 1; //Bulwark of blades damage reflection -- Zornath if(is_affected(victim,skill_lookup("bulwark of blades"))) { int chance; AFFECT_DATA bulwark_bleed; if (get_skill(victim,skill_lookup("blade mastery")) < 1) chance = 30; else chance = 50; if (number_percent() < chance) { act("The blade barrier around $N dices your flesh as your strike $M!",ch,0,victim,TO_CHAR); act("The blade barrier around $N dices into $n's flesh!",ch,0,victim,TO_NOTVICT); act("The blade barrier around you dices into $n's flesh as $e strikes you!",ch,0,victim,TO_VICT); if (get_skill(victim,skill_lookup("blade mastery")) < 1) damage_newer(victim,ch,dam / 6,TYPE_UNDEFINED,DAM_SLASH,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"the dicing blades",SINGULAR,DAM_NOT_POSSESSIVE,NULL,FALSE); else { damage_newer(victim,ch,dam / 3,TYPE_UNDEFINED,DAM_SLASH,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"the dicing blades",SINGULAR,DAM_NOT_POSSESSIVE,NULL,FALSE); //10% chance to add a bleed effect if (number_percent() < 10 && !is_affected(ch,skill_lookup("dicing wounds"))) { act("The blades dig deep into $n's flesh, unleashing a mist of blood!",ch,0,victim,TO_VICT); act("The blades dig deep into $n's flesh, unleashing a mist of blood!",ch,0,victim,TO_NOTVICT); act("The blades dig deep into your flesh, unleashing a spray of blood!",ch,0,victim,TO_CHAR); init_affect(&bulwark_bleed); bulwark_bleed.aftype = TO_AFFECTS; bulwark_bleed.type = skill_lookup("dicing wounds"); bulwark_bleed.duration = 3; bulwark_bleed.level = victim->level; bulwark_bleed.owner_name = str_dup(victim->original_name); bulwark_bleed.affect_list_msg = str_dup("bleeding uncontrollably"); affect_to_char(ch,&bulwark_bleed); } } } } if(ch->cabal==CABAL_KNIGHT && get_skill(ch,skill_lookup("truestrike")) && number_percent()<((get_skill(ch,skill_lookup("truestrike"))-40)/5)-3 && !cabal_down_new(ch,CABAL_KNIGHT,FALSE) && specials==TRUE) { act("$n unleashes a blow of true accuracy, striking through your defenses!",ch,0,victim,TO_VICT); act("$n unleashes a blow of true accuracy, striking through $N's defenses!",ch,0,victim,TO_NOTVICT); act("You unleash a blow of true accuracy, striking through $N's defenses!",ch,0,victim,TO_CHAR); dam*=1.5; result = damage_new( ch, victim, dam, dt, DAM_TRUESTRIKE, TRUE, blockable, addition, multiplier,NULL); check_improve(ch,skill_lookup("truestrike"),TRUE,1); } else result = damage_new( ch, victim, dam, dt, dam_type, TRUE, blockable, addition, multiplier,dnoun); /* but do we have a funky weapon? */ if (result && wield != NULL) { int dam; if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_POISON)) { int level = 10; AFFECT_DATA *poison, af; if ((poison = affect_find(wield->affected,gsn_poison)) == NULL) level = wield->level; else level = poison->level; if (!saves_spell(level / 2,victim,DAM_POISON) && !IS_AFFECTED(victim,AFF_POISON)) { send_to_char("You feel poison coursing through your veins.\n\r", victim); act("$n is poisoned by the venom on $p.", victim,wield,NULL,TO_ROOM); init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_MALADY; af.type = gsn_poison; af.level = level * 3/4; af.duration = level / 10; af.location = APPLY_STR; af.modifier = -6; af.bitvector = AFF_POISON; af.owner_name = str_dup(ch->original_name); affect_join( victim, &af ); } /* weaken the poison if it's temporary */ if (poison != NULL) { poison->level = UMAX(0,poison->level - 2); poison->duration = UMAX(0,poison->duration - 1); if (poison->duration < 0) act("The poison on $p has worn off.",ch,wield,NULL,TO_CHAR); } } if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_VAMPIRIC) && number_percent() < 8) { dam = number_range(wield->level/2, wield->level); act("$p draws life from $n.",victim,wield,NULL,TO_ROOM); act("You feel $p drawing your life away.", victim,wield,NULL,TO_CHAR); damage_old(ch,victim,dam,dt,DAM_NEGATIVE,FALSE); ch->hit = UMIN(ch->hit + dam, ch->max_hit); } if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_FLAMING) && number_percent() < 15) { dam = number_range(1,wield->level / 4 + 1); act("$n is burned by $p.",victim,wield,NULL,TO_ROOM); act("$p sears your flesh.",victim,wield,NULL,TO_CHAR); fire_effect( (void *) victim,wield->level/2,dam,TARGET_CHAR); damage(ch,victim,dam,dt,DAM_FIRE,FALSE); } if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_FROST) && number_percent() < 15) { dam = number_range(1,wield->level / 6 + 2); act("$p freezes $n.",victim,wield,NULL,TO_ROOM); act("The cold touch of $p surrounds you with ice.", victim,wield,NULL,TO_CHAR); cold_effect(victim,wield->level/2,dam,TARGET_CHAR); damage(ch,victim,dam,dt,DAM_COLD,FALSE); } if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_SHOCKING) && number_percent() < 15) { dam = number_range(1,wield->level/5 + 2); act("$n is struck by lightning from $p.",victim,wield,NULL,TO_ROOM); act("You are shocked by $p.",victim,wield,NULL,TO_CHAR); shock_effect(victim,wield->level/2,dam,TARGET_CHAR); damage(ch,victim,dam,dt,DAM_LIGHTNING,FALSE); } } // End special weapon flag if. tail_chain( ); return; } int avenger_multiplier(CHAR_DATA *ch,OBJ_DATA *wield) { int avenge; avenge = 1; if (IS_EVIL(ch->fighting) && wield != NULL) { if (number_percent() < 7 && IS_WEAPON_STAT(wield,WEAPON_SHADOWBANE)) avenge = 2; if (number_percent() < 7 && IS_WEAPON_STAT(wield,WEAPON_LIGHTBRINGER)) avenge = 3/2; } return avenge; } /* * Inflict damage from a hit. */ bool damage(CHAR_DATA *ch,CHAR_DATA *victim,int dam,int dt,int dam_type, bool show) { return damage_new(ch, victim, dam, dt, dam_type, show, HIT_BLOCKABLE, HIT_NOADD, HIT_NOMULT, NULL); } bool damage_old( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt, int dam_type, bool show ) { return damage_new(ch, victim, dam, dt, dam_type, show, HIT_BLOCKABLE, HIT_NOADD, HIT_NOMULT, NULL); } int con_multiplier(int con, int dam) { float damage = dam; switch(con) { case 25: damage *= 0.955; break; case 24: damage *= 0.96; break; case 23: damage *= 0.965; break; case 22: damage *= 0.97; break; case 21: damage *= 0.975; break; case 20: damage *= 0.98; break; case 19: damage *= 0.985; break; case 18: damage *= 0.99; break; case 17: damage *= 0.995; break; case 16: damage *= 1; break; case 15: damage *= 1.02; break; case 14: damage *= 1.04; break; case 13: damage *= 1.06; break; case 12: damage *= 1.08; break; case 11: damage *= 1.1; break; case 10: damage *= 1.12; break; case 9: damage *= 1.14; break; case 8: damage *= 1.16; break; case 7: damage *= 1.18; break; case 6: damage *= 1.2; break; case 5: damage *= 1.22; break; case 4: damage *= 1.24; break; case 3: damage *= 1.26; break; case 2: damage *= 1.35; break; case 1: damage *= 1.45; break; default: damage *= 2; break; } return (int)damage; } float calculate_ac_redux(int ac) { float ac_mod = 0; //If <75% reduction if (ac > AC_PER_ONE_PERCENT_DECREASE_DAMAGE * 75) //Damage modifier is AC divided by some predefined constant that can be tweaked to increase or decrease the effectiveness of AC. Zornath ac_mod = ((float)ac / (float)AC_PER_ONE_PERCENT_DECREASE_DAMAGE) / (float)100; //Otherwise asymptotically approach 100% else { //Finding a widening factor for (-1/x) + 100, so that redux asymptotically approaches 100 long widening_factor = -1 * AC_PER_ONE_PERCENT_DECREASE_DAMAGE * 75 * 25; long asymp_mod = widening_factor / ac + 100; ac_mod = (float)asymp_mod / (float)100; } return ac_mod; } bool damage_newer(CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt, int dam_type, bool show, bool blockable, int addition, int multiplier, char *dnoun, bool isPlural, bool showCharName, AFFECT_DATA *dealtByAffect, bool keep_invisible) { OBJ_DATA *corpse; OBJ_DATA *obj; OBJ_DATA *wield; bool immune; int originaldam; CHAR_DATA *owner = NULL; bool nosafe = FALSE; int ac; dam = con_multiplier(get_curr_stat(victim,STAT_CON),dam); //Armor class affects damage taken now. Zornath switch(dt) { case DAM_PIERCE: ac = GET_AC(victim,AC_PIERCE); break; case DAM_SLASH: ac = GET_AC(victim,AC_SLASH); break; case DAM_BASH: ac = GET_AC(victim,AC_BASH); break; default: ac = GET_AC(victim,AC_EXOTIC); break; } dam -= dam * calculate_ac_redux(ac); //For damage dealt by affects such as poison, plague, etc., lookup the owner by name if (dealtByAffect) { owner = find_char_by_name(dealtByAffect->owner_name); ch = victim; } if ( victim->position == POS_DEAD ) return FALSE; if (IS_NPC(ch) && spellbaned(ch,victim,dt)) return FALSE; if (is_affected(ch,skill_lookup("valiant wrath"))) { dnoun = str_dup("valiant wrath"); dt += DAM_SOUND; } if (get_skill(ch,skill_lookup("elemental affinity")) > 75) { dam = (23 * dam) / 20; } if (!dnoun && !nosafe && is_safe(ch,victim)) return FALSE; originaldam=dam; /* * Stop up any residual loopholes. */ if ( dam > 3000 && dt >= TYPE_HIT) { dam = 3000; } dam+=addition; if (multiplier != HIT_NOMULT) { dam *= multiplier/100.1; } if (!IS_NPC(ch) && IS_SET(ch->act,PLR_MORON)) dam *= .50; if ( victim != ch && ch->in_room == victim->in_room) { /* * Certain attacks are forbidden. * Most other attacks are returned. */ check_killer( ch, victim ); if ( victim->position > POS_STUNNED && victim != ch && !((is_same_group(ch,victim) || is_safe(ch,victim)) && dnoun && dnoun[strlen(dnoun)-1] == '*')) { if ( victim->fighting == NULL ) set_fighting( victim, ch ); if (victim->timer <= 4) victim->position = POS_FIGHTING; } if ( victim->position > POS_STUNNED && victim != ch) { if ( ch->fighting == NULL && !((is_same_group(ch,victim) || is_safe(ch,victim)) && dnoun && dnoun[strlen(dnoun)-1] == '*')) set_fighting( ch, victim ); } /* * More charm stuff. */ if ( victim->master == ch && !(dnoun && dnoun[strlen(dnoun)-1] == '*')) stop_follower( victim ); } if ( (dt >= TYPE_HIT || dt == gsn_dual_wield) && ch != victim && blockable==HIT_BLOCKABLE && ch->in_room == victim->in_room && dam>0) { if (check_shield_magnetism(ch, victim, dt)) return FALSE; if (check_parry(ch,victim,dt)) { (check_restrike(ch,victim)); return FALSE; } if (check_dodge(ch,victim,dt)) return FALSE; if (check_spin(ch,victim, dt)) return FALSE; if (check_distance(ch,victim,dt)) return FALSE; if (check_unarmed_defense(ch,victim,dt)) return FALSE; if (check_shield_block(ch,victim,dt)) return FALSE; if (check_questdodge(ch,victim,dt)) return FALSE; if (check_ironhands(ch,victim,dt)) return FALSE; } if (ch->enhancedDamMod >= 0) { dam *= (ch->enhancedDamMod / 100); } if (is_affected(victim,gsn_static_charge)) { affect_strip(victim,gsn_static_charge); damage_old(victim,ch,victim->level * number_range(6,8),gsn_static_charge,DAM_LIGHTNING,TRUE); } /* damage reduction */ if (dam > 85) { dam = (dam - 85); dam *= 8; dam /= 10; dam += 85; } if (is_affected(victim,gsn_soul_channel) && dam_type != DAM_TRUESTRIKE) { AFFECT_DATA *af; int start, level = 0; af = affect_find(victim->affected,gsn_soul_channel); for (start = 1; start <= level; start++) { dam *= .8; } } if (is_affected(victim,gsn_stoneskin) && dam_type!=DAM_TRUESTRIKE) dam *= .8; if (is_affected(victim,gsn_shield) && dam_type!=DAM_TRUESTRIKE) dam *= .95; if (is_affected(victim,gsn_barrier) && dam_type!=DAM_TRUESTRIKE) dam *= .5; if (is_affected(victim,skill_lookup("aura")) && dam_type != DAM_TRUESTRIKE) dam *= 0.7; if (is_affected(ch,gsn_rage) && dam_type!=DAM_TRUESTRIKE) dam *= 1.25; if ( dam > 1 && ((IS_AFFECTED(victim, AFF_PROTECT_EVIL) && IS_EVIL(ch) ) || (IS_AFFECTED(victim, AFF_PROTECT_GOOD) && IS_GOOD(ch) )) && dam_type!=DAM_TRUESTRIKE) dam -= dam / 4; // Dragonplate obj = get_eq_char(ch,WEAR_BODY); if (obj != NULL && obj->pIndexData->vnum == OBJ_VNUM_DRAGONPLATE) { if(!IS_AFFECTED(victim, AFF_SANCTUARY) && dam_type!=DAM_TRUESTRIKE) { dam *= .75; } } // Armored carapace obj = get_eq_char(victim,WEAR_ABOUT); if (obj!=NULL && obj->pIndexData->vnum==28015) dam *= .6; // Aura of Darkness obj = get_eq_char(victim,WEAR_BODY); if (obj!=NULL && obj->pIndexData->vnum==28017 && (dam_type==DAM_HOLY || dam_type==DAM_NEGATIVE)) dam *= .4; /* Check for fire demon belt immunity */ obj = get_eq_char(victim,WEAR_WAIST); if (obj!=NULL && obj->pIndexData->vnum==28016 && dam_type==DAM_FIRE) dam *= .4; if (victim->dam_mod < 20) dam *= 0.2; else dam *= (victim->dam_mod / 100.01); if (check_ward_diminution(victim, ch, dam, dam_type, dt)) dam = 1; if (!keep_invisible) { un_camouflage( ch, NULL); un_earthfade(ch, NULL); un_hide(ch, NULL); un_invis(ch, NULL); un_sneak(ch, NULL); un_duo(ch, NULL); } /* * Damage modifiers. */ if ( dam > 1 && IS_AFFECTED(victim, AFF_SANCTUARY) && dam_type!=DAM_TRUESTRIKE) { if (!is_affected(victim,skill_lookup("shroud"))) dam /= 2; else dam *= 0.4; } immune = FALSE; /* Check for absorb */ if (check_absorb(ch,victim,dt)) return FALSE; /* * Check for parry, and dodge. */ switch(check_immune(victim,dam_type)) { case(IS_IMMUNE): immune = TRUE; dam = 0; break; case(IS_RESISTANT): dam -= dam/3; break; case(IS_VULNERABLE): dam += dam/4; break; } //ObsidianPalace if(IS_NPC(victim) && victim->pIndexData->vnum>28003 && victim->pIndexData->vnum<28012 && !IS_AFFECTED(victim,AFF_SANCTUARY)) dam/=2; if(IS_NPC(victim) && victim->pIndexData->vnum==28006 && dam>10 && dam_type!=DAM_MENTAL) dam=number_range(5,25); if (dt == gsn_dual_wield) wield = get_eq_char(ch,WEAR_DUAL_WIELD); else wield = get_eq_char(ch,WEAR_WIELD); if(wield && IS_SET(victim->vuln_flags, VULN_IRON) && !str_cmp(wield->material->name,"iron")) dam += dam / 3; if(wield && IS_SET(victim->vuln_flags, VULN_SILVER) && !str_cmp(wield->material->name,"silver")) dam += dam / 3; if (is_affected(victim,skill_lookup("divine transferrer"))) { AFFECT_DATA *af; CHAR_DATA *transferree; af = affect_find(victim->affected,skill_lookup("divine transferrer")); if ((transferree = find_char_by_name(af->owner_name)) != NULL) { if (transferree->in_room == ch->in_room) { if (is_affected(transferree,skill_lookup("divine transferree"))) { damage_newer(ch,transferree,dam/2,dt,dam_type,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"the divine transferrance",PLURAL,DAM_NOT_POSSESSIVE,NULL,FALSE); dam /= 2; } } } } if (showCharName) { if (show && isPlural) dam_message( ch, victim, dam, dt, immune, dnoun, PLURAL, DAM_POSSESSIVE ); else if (show && !isPlural) dam_message( ch, victim, dam, dt, immune, dnoun, SINGULAR, DAM_POSSESSIVE ); } else { if (show && isPlural) dam_message( ch, victim, dam, dt, immune, dnoun, PLURAL, DAM_NOT_POSSESSIVE ); else if (show && !isPlural) dam_message( ch, victim, dam, dt, immune, dnoun, SINGULAR, DAM_NOT_POSSESSIVE ); } if ( (dt >= TYPE_HIT || dt == gsn_dual_wield) && ch != victim) { if (is_affected(victim,gsn_self_immolation) && dam>0) { act("$N is burned by the flames engulfing $n!",victim,NULL,ch,TO_NOTVICT); act("$N is burned by the flames engulfing you!",victim,NULL,ch,TO_CHAR); act("You are burned by the flames engulfing $n!",victim,NULL,ch,TO_VICT); damage_old(victim,ch,number_range(20,60),gsn_flames,DAM_FIRE, TRUE); } } if (dam <= 0) return FALSE; /* * Hurt the victim. * Inform the victim of his new state. */ if (is_affected(victim,skill_lookup("mana shield")) && victim->mana > dam) { victim->mana -= dam; } else if (is_affected(victim,skill_lookup("mana shield")) && victim->mana <= dam) { act("{rYour mana shield cannot withstand the force of $n's attack and shatters!{x",ch,0,victim,TO_VICT); act("{rThe mana shield around $N crumbles under your attack!{x",ch,0,victim,TO_CHAR); act("The mana shield around $N crumbles under $n's attack!",ch,0,victim,TO_NOTVICT); victim->hit -= (dam - victim->mana); victim->mana = 0; affect_strip(victim,skill_lookup("mana shield")); AFFECT_DATA shield_timer; init_affect(&shield_timer); shield_timer.aftype = AFT_MALADY; shield_timer.type = skill_lookup("mental exhaustion"); shield_timer.duration = (ch->level / 5); shield_timer.affect_list_msg = str_dup("prevents usage of mana shield"); affect_to_char(victim,&shield_timer); } else victim->hit -= dam; if (dam_type == DAM_FIRE || dam_type == DAM_ACID) victim->noregen_dam += dam; if (victim->noregen_dam > victim->max_hit) victim->noregen_dam = victim->max_hit; if ( !IS_NPC(victim) && victim->level >= LEVEL_IMMORTAL && victim->hit < 1 && !arena) victim->hit = 1; update_pos( victim ); switch( victim->position ) { case POS_MORTAL: act( "$n is mortally wounded, and will die soon, if not aided.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You are mortally wounded, and will die soon, if not aided.\n\r", victim ); break; case POS_INCAP: act( "$n is incapacitated and will slowly die, if not aided.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You are incapacitated and will slowly die, if not aided.\n\r", victim ); break; case POS_STUNNED: act( "$n is stunned, but will probably recover.", victim, NULL, NULL, TO_ROOM ); send_to_char("You are stunned, but will probably recover.\n\r", victim ); break; case POS_DEAD: act( "$n is DEAD!!", victim, 0, 0, TO_ROOM ); send_to_char( "You have been KILLED!!\n\r\n\r", victim ); break; default: if ( dam > victim->max_hit / 4 ) send_to_char( "That really did HURT!\n\r", victim ); if ( victim->hit < victim->max_hit / 4 ) send_to_char( "You sure are BLEEDING!\n\r", victim ); break; } /* * Sleep spells and extremely wounded folks. */ if ( !IS_AWAKE(victim) && ch != victim) stop_fighting( victim, FALSE ); /* * Payoff for killing things. */ if ( victim->position == POS_DEAD ) { if (owner) group_gain( owner, victim ); else group_gain( ch, victim ); if ( !IS_NPC(victim) ) { sprintf( log_buf, "%s killed by %s at %ld", victim->name, (IS_NPC(ch) ? ch->short_descr : owner ? owner->name : ch->name), victim->in_room->vnum ); log_string( log_buf ); } /* * Dying penalty: */ if (owner) raw_kill(owner, victim); else raw_kill(ch, victim); /* * Death trigger */ if (!IS_NPC(ch) && (corpse = get_obj_list(ch,"corpse",ch->in_room->contents)) != NULL && corpse->item_type == ITEM_CORPSE_NPC && can_see_obj(ch,corpse)) { OBJ_DATA *coins; corpse = get_obj_list( ch, "corpse", ch->in_room->contents ); if ( IS_SET(ch->act, PLR_AUTOLOOT) && corpse && corpse->contains) /* exists and not empty */ do_get( ch, "all corpse" ); if (IS_SET(ch->act,PLR_AUTOGOLD) && corpse && corpse->contains && /* exists and not empty */ !IS_SET(ch->act,PLR_AUTOLOOT)) if ((coins = get_obj_list(ch,"gcash",corpse->contains)) != NULL) do_get(ch, "all.gcash corpse"); if ( IS_SET(ch->act, PLR_AUTOSAC) ) { if ( IS_SET(ch->act,PLR_AUTOLOOT) && corpse && corpse->contains) return TRUE; /* leave if corpse has treasure */ else do_sacrifice( ch, "corpse" ); } } return TRUE; } if ( victim == ch ) return TRUE; /* * Take care of link dead people. if ( !IS_NPC(victim) && victim->desc == NULL ) { if ( number_range( 0, victim->wait ) == 0 ) { do_recall( victim, "" ); return TRUE; } } */ /* * Wimp out? */ if(ch->in_room != victim->in_room || dt == gsn_parting_blow) return TRUE; if ( IS_NPC(victim) && dam > 0 && victim->wait < PULSE_VIOLENCE / 2) { if ( ( IS_SET(victim->act, ACT_WIMPY) && number_bits( 2 ) == 0 && victim->hit < victim->max_hit / 5) || ( IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL && victim->master->in_room != victim->in_room && !is_centurion(victim) && dt != gsn_parting_blow && dt != gsn_cutoff)) do_flee( victim, "" ); } if ( !IS_NPC(victim) && victim->hit > 0 && victim->hit <= victim->wimpy && victim->wait < PULSE_VIOLENCE / 2 && dt != gsn_parting_blow) do_flee( victim, "" ); tail_chain( ); return TRUE; } bool damage_new(CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt, int dam_type, bool show, bool blockable, int addition, int multiplier, char *dnoun) { return damage_newer(ch,victim,dam,dt,dam_type,show,blockable,addition,multiplier,dnoun,TRUE,TRUE, NULL, FALSE); } int damage_calculate(CHAR_DATA *ch, CHAR_DATA *victim, int dt, int dam_type, bool show, bool blockable, int addition, int multiplier) { OBJ_DATA *obj; OBJ_DATA *wield; int diceroll, diceroll2 = 0; int sn, skill; int dam, mdam; bool immune; int originaldam; wield = get_eq_char( ch, WEAR_WIELD ); sn = get_weapon_sn(ch); skill = 20 + get_weapon_skill(ch,sn); if ( IS_NPC(ch) && (!ch->pIndexData->new_format || wield == NULL)) { if (!ch->pIndexData->new_format) { dam = number_range( ( ch->level + ch->drain_level) / 2, (ch->drain_level + ch->level) * 3 / 2 ); if ( wield != NULL ) dam += dam / 2; } else dam = dice(ch->damage[DICE_NUMBER],ch->damage[DICE_TYPE]); } else { if (sn != -1) check_improve(ch,sn,TRUE,5); if ( wield != NULL ) { if (wield->pIndexData->new_format) dam = dice(wield->value[1],wield->value[2]) * skill/100; else dam = number_range( wield->value[1] * skill/100, wield->value[2] * skill/100); if (get_eq_char(ch,WEAR_SHIELD) == NULL) /* no shield = more */ dam = dam * 11/10; if (wield->level - (ch->drain_level + ch->level) >= 35) dam = (dam*6)/10; else if (wield->level - (ch->drain_level + ch->level) >= 25) dam = (dam*7)/10; else if (wield->level - (ch->drain_level + ch->level) >= 15) dam = (dam*8)/10; else if (wield->level - (ch->drain_level + ch->level) >= 5) dam = (dam*9)/10; /* sharpness! */ if (IS_WEAPON_STAT(wield,WEAPON_SHARP)) { int percent; if ((percent = number_percent()) <= (skill / 8)) dam *= 1.2; } } else { dam = number_range( 1 + 7 * skill/100, (ch->level - 5) * skill/100); dam += GET_DAMROLL(ch) / 15; } } dam += (ch->drain_level + ch->level)/8; if ( get_skill(ch,gsn_enhanced_damage) > 0 ) { diceroll = number_percent(); if (get_skill(ch,gsn_enhanced_damage_two) > 0) { diceroll2 = number_percent(); if (diceroll2 < get_skill(ch,gsn_enhanced_damage_two) && diceroll2 < get_skill(ch,gsn_enhanced_damage) ) { check_improve(ch,gsn_enhanced_damage_two,TRUE,5); diceroll2 = diceroll2 + 5; diceroll = diceroll2; } } if (get_skill(ch,gsn_enhanced_damage_three) > 0) { check_improve(ch,gsn_enhanced_damage_three,TRUE,3); diceroll += get_skill(ch,gsn_enhanced_damage_three)/3; } if (diceroll <= get_skill(ch,gsn_enhanced_damage)) { check_improve(ch,gsn_enhanced_damage,TRUE,6); dam += (dam * diceroll/125); } } else { dam *= 7; dam /= 10; } mdam = GET_DAMROLL(ch); dam += mdam * UMIN(100,skill) /100; originaldam=dam; if ( dam > 3000 && dt >= TYPE_HIT) { dam = 3000; } dam+=addition; if (multiplier != HIT_NOMULT) { dam *= multiplier/100.1; } if (!IS_NPC(ch) && IS_SET(ch->act,PLR_MORON)) dam *= .50; if ( (dt >= TYPE_HIT || dt == gsn_dual_wield) && ch != victim && blockable==HIT_BLOCKABLE && ch->in_room == victim->in_room && dam>0) { } if (ch->enhancedDamMod >= 0) { dam *= (ch->enhancedDamMod / 100); } /* damage reduction */ if (dam > 85) { dam = (dam - 85); dam *= 8; dam /= 10; dam += 85; } if (is_affected(victim,gsn_stoneskin) && dam_type!=DAM_TRUESTRIKE) dam *= .8; if (is_affected(victim,gsn_shield) && dam_type!=DAM_TRUESTRIKE) dam *= .95; if (is_affected(victim,gsn_barrier) && dam_type!=DAM_TRUESTRIKE) dam *= .5; if (is_affected(ch,gsn_rage) && dam_type!=DAM_TRUESTRIKE) dam *= 1.25; if ( dam > 1 && ((IS_AFFECTED(victim, AFF_PROTECT_EVIL) && IS_EVIL(ch) ) || (IS_AFFECTED(victim, AFF_PROTECT_GOOD) && IS_GOOD(ch) )) && dam_type!=DAM_TRUESTRIKE) dam -= dam / 4; // Dragonplate obj = get_eq_char(ch,WEAR_BODY); if (obj != NULL && obj->pIndexData->vnum == OBJ_VNUM_DRAGONPLATE) { if(!IS_AFFECTED(victim, AFF_SANCTUARY) && dam_type!=DAM_TRUESTRIKE) { dam *= .75; } } // Armored carapace obj = get_eq_char(victim,WEAR_ABOUT); if (obj!=NULL && obj->pIndexData->vnum==28015) dam *= .6; // Aura of Darkness obj = get_eq_char(victim,WEAR_BODY); if (obj!=NULL && obj->pIndexData->vnum==28017 && (dam_type==DAM_HOLY || dam_type==DAM_NEGATIVE)) dam *= .4; /* Check for fire demon belt immunity */ obj = get_eq_char(victim,WEAR_WAIST); if (obj!=NULL && obj->pIndexData->vnum==28016 && dam_type==DAM_FIRE) dam *= .4; if (dam_type!=DAM_TRUESTRIKE) dam *= (victim->dam_mod / 100.01); if (check_ward_diminution(victim, ch, dam, dam_type, dt)) dam = 1; /* * Damage modifiers. */ if ( dam > 1 && IS_AFFECTED(victim, AFF_SANCTUARY) && dam_type!=DAM_TRUESTRIKE) dam /= 2; immune = FALSE; //ObsidianPalace if(IS_NPC(victim) && victim->pIndexData->vnum>28003 && victim->pIndexData->vnum<28012 && !IS_AFFECTED(victim,AFF_SANCTUARY)) dam/=2; if(IS_NPC(victim) && victim->pIndexData->vnum==28006 && dam>10 && dam_type!=DAM_MENTAL) dam=number_range(5,25); if (dt == gsn_dual_wield) wield = get_eq_char(ch,WEAR_DUAL_WIELD); else wield = get_eq_char(ch,WEAR_WIELD); if(wield && IS_SET(victim->vuln_flags, VULN_IRON) && !str_cmp(wield->material->name,"iron")) dam -= dam / 3; if(wield && IS_SET(victim->vuln_flags, VULN_SILVER) && !str_cmp(wield->material->name,"silver")) dam -= dam / 3; return dam; } bool is_area_safe(CHAR_DATA *ch, CHAR_DATA *victim) { if (victim->in_room == NULL || ch->in_room == NULL) return TRUE; if (victim == ch ) return TRUE; if (victim->fighting == ch) return FALSE; if (IS_NPC(ch) && IS_GOOD(ch) && IS_GOOD(victim)) return FALSE; if (IS_IMMORTAL(victim) && victim->invis_level > 2) return TRUE; if (IS_IMMORTAL(ch) && IS_IMMORTAL(victim) && victim->level > LEVEL_IMMORTAL && !is_same_group(ch,victim)) return FALSE; if (IS_IMMORTAL(ch) && victim->level < ch->level && !is_same_group(ch,victim)) return FALSE; /* killing mobiles */ if (IS_NPC(victim)) { if (IS_SET(victim->in_room->room_flags,ROOM_SAFE)) { send_to_char("Not in this room.\n\r",ch); return TRUE; } if (is_same_group(ch,victim)) return TRUE; } /* killing players */ else { if (IS_SET(victim->in_room->room_flags,ROOM_SAFE)) { send_to_char("Not in this room.\n\r",ch); return TRUE; } if (IS_NPC(ch) && ch->master != NULL && !IS_NPC(ch->master)) return TRUE; if (IS_NPC(ch)) return FALSE; if (is_same_group(ch,victim)) return TRUE; } if (!IS_NPC(ch)) ch->ghost = (time_t)NULL; return FALSE; } bool is_safe(CHAR_DATA *ch, CHAR_DATA *victim) { if (victim->in_room == NULL || ch->in_room == NULL) return TRUE; if (IS_NPC(ch) && victim->invis_level >= LEVEL_HERO) return TRUE; if (!IS_NPC(ch)) { if (ch->pcdata->death_status == HAS_DIED) return TRUE; } if (!IS_NPC(victim)) { if (victim->pcdata->death_status == HAS_DIED) return TRUE; } if(IS_NPC(ch) && IS_NPC(victim) && !IS_AFFECTED(ch,AFF_CHARM) && !IS_AFFECTED(victim,AFF_CHARM) && !ch->desc && !ch->hunting && !victim->hunting && victim!=ch && !ch->desc && !victim->desc) return TRUE; /* Handle Link dead players , only saves from PKS, not mobs -Ceran */ if (!IS_NPC(victim) && victim->desc == NULL && !IS_NPC(ch) && victim->fighting != ch && ch->fighting != victim) { act("The gods protect $N from $n.",ch,0,victim,TO_NOTVICT); act("The gods protect $N from you.",ch,0,victim,TO_CHAR); return TRUE; } if (!IS_NPC(victim) && victim->pcdata->newbie==TRUE && !IS_NPC(ch)) { act("$N is too young for $n to harm.",ch,0,victim,TO_NOTVICT); act("$N is too young for you to harm.",ch,0,victim,TO_CHAR); act("You are too young for $n to harm.",ch,0,victim,TO_VICT); return TRUE; } if (!IS_NPC(ch) && ch->pcdata->newbie==TRUE && !IS_NPC(victim)) { act("$n is too young to harm $N.",ch,0,victim,TO_NOTVICT); act("You are too young to harm $N. Type newbie to change this.",ch,0,victim,TO_CHAR); act("$n is too young to harm you.",ch,0,victim,TO_VICT); return TRUE; } if (is_affected(victim,gsn_timestop)) { act("$n is stuck in time and the gods protect $m.",victim,0,0,TO_ROOM); act("$N tries to do something but you are stuck in time and unaffected.",victim,0,ch,TO_CHAR); if (victim->fighting != NULL) victim->fighting = NULL; return TRUE; } if (victim->fighting == ch || victim == ch) return FALSE; if (IS_NPC(ch) && ch->last_fought == victim) return FALSE; if (victim->ghost > 0) { act("The gods protect $N from $n.",ch,0,victim,TO_NOTVICT); act("The gods protect you from $n.",ch,0,victim,TO_VICT); act("The gods protect $N from you.",ch,0,victim,TO_CHAR); return TRUE; } if (ch->ghost > 0) { if (!IS_NPC(victim)) { act("The gods protect $N from $n.",ch,0,victim,TO_NOTVICT); act("The gods protect you from $n.",ch,0,victim,TO_VICT); act("The gods protect $N from you.",ch,0,victim,TO_CHAR); return TRUE; } if (IS_AFFECTED(victim,AFF_CHARM) && victim->master != NULL && !IS_NPC(victim->master)) { act("The gods protect $N from $n.",ch,0,victim,TO_NOTVICT); act("The gods protect you from $n.",ch,0,victim,TO_VICT); act("The gods protect $N from you.",ch,0,victim,TO_CHAR); return TRUE; } } if (IS_IMMORTAL(ch) && is_affected(ch,gsn_riot) && !IS_NPC(victim)) { send_to_char("You can't riot on mortals.\n\r",ch); return TRUE; } if (IS_IMMORTAL(ch) && ch->level > LEVEL_IMMORTAL) return FALSE; if (IS_SET(victim->act,PLR_CRIMINAL)) { if (IS_NPC(ch) && ch->pIndexData->vnum == MOB_VNUM_ENFORCER) return FALSE; } if(IS_NPC(victim)&&victim->pIndexData->vnum==MOB_VNUM_ENFORCER) return FALSE; /* killing mobiles */ if (IS_NPC(victim)) { if (!IS_NPC(ch)) { /* no charmed creatures unless in pk of master */ if (IS_AFFECTED(victim,AFF_CHARM) && !can_pk(ch,victim->master) && !is_centurion(victim)) { act("The gods protect $N from $n.",ch,0,victim,TO_NOTVICT); act("The gods protect you from $n.",ch,0,victim,TO_VICT); act("The gods protect $N from you.",ch,0,victim,TO_CHAR); return TRUE; } } else { if (IS_AFFECTED(ch,AFF_CHARM) && IS_AFFECTED(victim,AFF_CHARM) && !can_pk(ch->master,victim->master)) return TRUE; } } /* killing players */ else { /* NPC doing the killing */ if (IS_NPC(ch)) { /* charmed mobs and pets cannot attack players while owned */ if (IS_AFFECTED(ch,AFF_CHARM) && ch->master != NULL && ch->master->fighting != victim && !is_centurion(ch)) { send_to_char("Players are your friends!\n\r",ch); return TRUE; } } /* player doing the killing */ else { if (!can_pk(ch, victim)) { if (!IS_IMMORTAL(victim)) { act("The gods protect $N from $n.",ch,0,victim,TO_NOTVICT); act("The gods protect you from $n.",ch,0,victim,TO_VICT); act("The gods protect $N from you.",ch,0,victim,TO_CHAR); } return TRUE; } } } return FALSE; } bool is_safe_spell(CHAR_DATA *ch, CHAR_DATA *victim, bool area ) { if (victim->in_room == NULL || ch->in_room == NULL) return TRUE; if (victim == ch && area) return TRUE; if (victim->fighting == ch || victim == ch) return FALSE; if (IS_IMMORTAL(ch) && ch->level > LEVEL_IMMORTAL && !area) return FALSE; if (!IS_NPC(victim) && victim->pcdata->newbie==TRUE && !IS_NPC(ch)) return TRUE; /* killing mobiles */ if (IS_NPC(victim)) { /* safe room? */ if (IS_SET(victim->in_room->room_flags,ROOM_SAFE)) return TRUE; if (victim->pIndexData->pShop != NULL) return TRUE; /* no killing healers, trainers, etc */ if (IS_SET(victim->act,ACT_TRAIN) || IS_SET(victim->act,ACT_PRACTICE) || IS_SET(victim->act,ACT_IS_HEALER) || IS_SET(victim->act,ACT_IS_CHANGER)) return TRUE; if (!IS_NPC(ch)) { /* no pets */ if (IS_SET(victim->act,ACT_PET)) return TRUE; /* no charmed creatures unless owner */ if (IS_AFFECTED(victim,AFF_CHARM) && (area || ch != victim->master)) return TRUE; /* legal kill? -- cannot hit mob fighting non-group member */ if (victim->fighting != NULL && !is_same_group(ch,victim->fighting)) return TRUE; } else { /* area effect spells do not hit other mobs */ if (area && !is_same_group(victim,ch->fighting)) return TRUE; } } /* killing players */ else { if (area && IS_IMMORTAL(victim) && victim->level > LEVEL_IMMORTAL) return TRUE; /* NPC doing the killing */ if (IS_NPC(ch)) { /* charmed mobs and pets cannot attack players while owned */ if (IS_AFFECTED(ch,AFF_CHARM) && ch->master != NULL && ch->master->fighting != victim) return TRUE; /* safe room? */ if (IS_SET(victim->in_room->room_flags,ROOM_SAFE)) return TRUE; /* legal kill? -- mobs only hit players grouped with opponent*/ if (ch->fighting != NULL && !is_same_group(ch->fighting,victim)) return TRUE; } /* player doing the killing */ else { if (!is_cabal(ch)) return TRUE; if (IS_SET(victim->act,PLR_KILLER) || IS_SET(victim->act,PLR_THIEF)) return FALSE; if (!is_cabal(victim)) return TRUE; if (ch->level > victim->level + 8) return TRUE; } } return FALSE; } /* * See if an attack justifies a KILLER flag. */ void check_killer( CHAR_DATA *ch, CHAR_DATA *victim ) { /* * Follow charm thread to responsible character. * Attacking someone's charmed char is hostile! */ while ( IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL ) victim = victim->master; /* * NPC's are fair game. * So are killers and thieves. */ if ( IS_NPC(victim) || IS_SET(victim->act, PLR_KILLER) || IS_SET(victim->act, PLR_THIEF)) return; /* * NPC's are cool of course (as long as not charmed). * Hitting yourself is cool too (bleeding). * So is being immortal (Alander's idea). * And current killers stay as they are. */ if ( IS_NPC(ch) || ch == victim || ch->level >= LEVEL_IMMORTAL || !is_cabal(ch) || IS_SET(ch->act, PLR_KILLER) || ch->fighting == victim) return; save_char_obj( ch ); return; } bool check_blademaster( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { int chance; int tsn; char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char *attack; if ( !IS_AWAKE(victim) ) return FALSE; tsn=skill_lookup("blademaster"); chance = get_skill(victim,tsn) / 3; if(chance==0) return FALSE; if ( get_eq_char( victim, WEAR_WIELD ) == NULL ) { if (IS_NPC(victim)) chance /= 2; else return FALSE; } if (IS_AFFECTED(victim,AFF_SLOW)) chance*=.5; if (IS_AFFECTED(victim,AFF_HASTE)) chance+=8; if (check_imperial_training(ch) == IMPERIAL_OFFENSE) chance -= 20; if (check_imperial_training(ch) == IMPERIAL_DEFENSE) chance += 20; chance+=(get_curr_stat(victim,STAT_DEX))*.6; if(chance>50) chance=50; if ( number_percent( ) >= chance) return FALSE; attack=get_dam_message(ch,dt); sprintf(buf1,"You block $n's %s with an agile cross parry.",attack); sprintf(buf2,"$N blocks your %s with an agile cross parry.",attack); act(buf1,ch,0,victim,TO_VICT); act(buf2,ch,0,victim,TO_CHAR); check_improve(victim,tsn,TRUE,1); return TRUE; } //Hitroll vs hitroll check that returns the ratio between two characters' hitrolls, up to a predefined max_multiplier. float hitroll_multiplier(CHAR_DATA *ch, CHAR_DATA *victim, float max_multiplier) { int ch_hitroll = GET_HITROLL(ch); int victim_hitroll = GET_HITROLL(victim); float hit_ratio; //Hitroll vs hitroll multiplier based on ratio if (victim_hitroll >= ch_hitroll) { hit_ratio = ch_hitroll == 0 ? ch_hitroll = 1 : ch_hitroll > 0 ? victim_hitroll / ch_hitroll : ch_hitroll / victim_hitroll; if (hit_ratio > max_multiplier) return max_multiplier; else return hit_ratio; } return 1; } bool check_displacement(CHAR_DATA *ch, CHAR_DATA *victim) { float chance, hit_ratio; int ch_hitroll, victim_hitroll; if (!(is_affected(victim, gsn_displacement))) return FALSE; chance = get_skill(victim,gsn_displacement); chance /= 1.5; ch_hitroll = GET_HITROLL(ch); victim_hitroll = GET_HITROLL(victim); //For simplicity... if (victim_hitroll <= 0) victim_hitroll = 1; if (ch_hitroll <= 0) ch_hitroll = 1; if (victim_hitroll < ch_hitroll) { hit_ratio = (float)ch_hitroll / (float)victim_hitroll; if (hit_ratio > 1.5) chance *= 1.5; else chance *= hit_ratio; } if (!can_see(victim,ch)) chance /=2; if (number_percent() > chance + victim->level - ch->level) return FALSE; act("$n's attack passes harmlessly through $N.",ch,NULL,victim,TO_NOTVICT); act("$n's attack misses you completely.",ch,NULL,victim,TO_VICT); act("Your attack passes harmlessly through $N.",ch,NULL,victim,TO_CHAR); return TRUE; } /* * Check for parry. */ bool check_parry( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { OBJ_DATA *wield, *victimwield; char *attack, buf1[MSL], buf2[MSL]; int flourintine=0, ch_hitroll, victim_hitroll, roll; float chance, hit_ratio; if ( !IS_AWAKE(victim) ) return FALSE; chance = get_skill(victim,gsn_parry) / 2; ch_hitroll = GET_HITROLL(ch); victim_hitroll = GET_HITROLL(victim); //For simplicity... if (victim_hitroll <= 0) victim_hitroll = 1; if (ch_hitroll <= 0) ch_hitroll = 1; if (victim_hitroll < ch_hitroll) { hit_ratio = (float)ch_hitroll / (float)victim_hitroll; if (hit_ratio > 1.25) chance *= 1.25; else chance *= hit_ratio; } if ( get_eq_char( victim, WEAR_WIELD ) == NULL ) { if (IS_NPC(victim)) chance /= 2; else return FALSE; } if (IS_AFFECTED(victim,AFF_BLIND)) chance *= .75; if (IS_AFFECTED(victim,AFF_HASTE)) chance+=20; if (IS_AFFECTED(ch,AFF_HASTE)) chance-=15; chance-=5*abs((ch->size-victim->size)); if (dt == gsn_dual_wield) wield = get_eq_char(ch,WEAR_DUAL_WIELD); else wield = get_eq_char(ch,WEAR_WIELD); if (wield != NULL) { switch (wield->value[0]) { case (WEAPON_SWORD): chance+=5; break; case (WEAPON_DAGGER): chance-=5; break; case (WEAPON_SPEAR): chance+=0; break; case (WEAPON_STAFF): chance+=0; break; case (WEAPON_MACE): chance-=5; break; case (WEAPON_AXE): chance-=5; break; case (WEAPON_FLAIL): chance+=10; break; case (WEAPON_WHIP): chance+=10; break; case (WEAPON_POLEARM): chance-=5; break; default: break; } } if((victimwield=get_eq_char(victim,WEAR_WIELD)) != NULL) { switch (victimwield->value[0]) { case (WEAPON_SWORD): chance+=10; flourintine++; break; case (WEAPON_DAGGER): chance-=20; break; case (WEAPON_SPEAR): chance+=15; break; case (WEAPON_STAFF): chance+=15; break; case (WEAPON_MACE): chance-=5; break; case (WEAPON_AXE): chance-=5; break; case (WEAPON_FLAIL): chance-=10; break; case (WEAPON_WHIP): chance-=10; break; case (WEAPON_POLEARM): chance+=10; break; default: break; } } if ((get_skill(victim,gsn_flourintine) > 0) && flourintine == 1) { check_improve(victim,gsn_flourintine,TRUE,1); chance += get_skill(victim,gsn_flourintine) / 7; } /* imperial training */ if (check_imperial_training(ch) == IMPERIAL_OFFENSE) chance -= 20; if (check_imperial_training(victim) == IMPERIAL_DEFENSE) chance += 20; if (check_imperial_training(victim) == IMPERIAL_OFFENSE) chance -= 20; if (check_imperial_training(ch) == IMPERIAL_DEFENSE) chance += 20; if (!IS_NPC(victim) && IS_SET(victim->act,PLR_MORON)) chance /= 2; switch(get_curr_stat(victim,STAT_STR)) { case 25: chance += 10; break; case 24: chance += 8; break; case 23: chance += 6; break; case 22: chance += 4; break; case 21: chance += 3; break; case 20: chance += 2; break; case 19: chance += 1; break; default: chance += 0; break; } chance+=attack_table[get_attack_number(ch,dt)].modifier; if (chance > 95) chance = 95; attack = get_dam_message(ch,dt); roll = number_percent(); if ( roll >= chance) return FALSE; if (chance - roll >= 40) { sprintf(buf1,"You masterfully deflect $n's %s with your %s.",attack, victimwield ? weapon_name_lookup(victimwield->value[0]) : "hands"); sprintf(buf2,"$N masterfully deflects your %s with $S %s.",attack, victimwield ? weapon_name_lookup(victimwield->value[0]) : "hands"); } else if (chance - roll >= 30) { sprintf(buf1,"You gracefully parry $n's %s with your %s.",attack, victimwield ? weapon_name_lookup(victimwield->value[0]) : "hands"); sprintf(buf2,"$N gracefully parries your %s with $S %s.",attack, victimwield ? weapon_name_lookup(victimwield->value[0]) : "hands"); } else if (chance - roll >= 20) { sprintf(buf1,"You parry $n's %s with your %s.",attack, victimwield ? weapon_name_lookup(victimwield->value[0]) : "hands"); sprintf(buf2,"$N parries your %s with $S %s.",attack, victimwield ? weapon_name_lookup(victimwield->value[0]) : "hands"); } else if (chance - roll >= 10) { sprintf(buf1,"You manage to parry $n's %s with your %s.",attack, victimwield ? weapon_name_lookup(victimwield->value[0]) : "hands"); sprintf(buf2,"$N manages to parry your %s with $S %s.",attack, victimwield ? weapon_name_lookup(victimwield->value[0]) : "hands"); } else { sprintf(buf1,"You barely manage to parry $n's %s with your %s.",attack, victimwield ? weapon_name_lookup(victimwield->value[0]) : "hands"); sprintf(buf2,"$N barely manages to parry your %s with $S %s.",attack, victimwield ? weapon_name_lookup(victimwield->value[0]) : "hands"); } act(buf1,ch,0,victim,TO_VICT); act(buf2,ch,0,victim,TO_CHAR); check_improve(victim,gsn_parry,TRUE,2); return TRUE; } bool check_block( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { float chance, hit_ratio; int tmp_dt, ch_hitroll, victim_hitroll, roll; OBJ_DATA *wield; char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char *attack; if ( !IS_AWAKE(victim) ) return FALSE; if (IS_NPC(victim)) return FALSE; chance = get_skill(victim,gsn_block); if ( victim->level <skill_table[gsn_block].skill_level[victim->class]) return FALSE; chance /= 2.25; ch_hitroll = GET_HITROLL(ch); victim_hitroll = GET_HITROLL(victim); //For simplicity... if (victim_hitroll <= 0) victim_hitroll = 1; if (ch_hitroll <= 0) ch_hitroll = 1; if (victim_hitroll < ch_hitroll) { hit_ratio = (float)ch_hitroll / (float)victim_hitroll; if (hit_ratio > 1.25) chance *= 1.25; else chance *= hit_ratio; } if (get_eq_char(victim,WEAR_WIELD) != NULL) return FALSE; if (!can_see(ch,victim)) chance /= 2; if (is_affected(victim,gsn_rage)) chance *= .75; if ( number_percent( ) >= chance + (victim->drain_level + victim->level) - (ch->drain_level + ch->level) ) { check_improve(victim,gsn_block,FALSE,5); return FALSE; } /* The rest is all new dual wield stuff, with dam types displayed for clarity when dual wielding - Ceran */ tmp_dt = TYPE_HIT; if (dt == gsn_dual_wield) wield = get_eq_char(ch,WEAR_DUAL_WIELD); else wield = get_eq_char(ch,WEAR_WIELD); if (wield != NULL) tmp_dt += wield->value[3]; else tmp_dt += ch->dam_type; if (tmp_dt > TYPE_HIT && tmp_dt < TYPE_HIT + MAX_DAMAGE_MESSAGE) attack = attack_table[tmp_dt - TYPE_HIT].noun; else { bug("In check_block, bad dam message: dt %d.",tmp_dt); attack = attack_table[0].name; } if (chance - roll >= 40) { sprintf(buf1,"You masterfully deflect $n's %s with your hands.",attack); sprintf(buf2,"$N masterfully deflects your %s with $S hands.",attack); } else if (chance - roll >= 30) { sprintf(buf1,"You gracefully block $n's %s with your hands.",attack); sprintf(buf2,"$N gracefully blocks your %s with $S hands.",attack); } else if (chance - roll >= 20) { sprintf(buf1,"You block $n's %s with your hands.",attack); sprintf(buf2,"$N blocks your %s with $S hands.",attack); } else if (chance - roll >= 10) { sprintf(buf1,"You manage to block $n's %s with your hands.",attack); sprintf(buf2,"$N manages to block your %s with $S hands.",attack); } else { sprintf(buf1,"You barely manage to block $n's %s with your hands.",attack); sprintf(buf2,"$N barely manages to block your %s with $S hands.",attack); } act(buf1,ch,0,victim,TO_VICT); act(buf2,ch,0,victim,TO_CHAR); check_improve(victim,gsn_block,TRUE,6); return TRUE; } /* * Check for shield block. */ bool check_shield_block( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { float chance, hit_ratio; int ch_hitroll, victim_hitroll, roll; char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char *attack; if ( !IS_AWAKE(victim) ) return FALSE; if(victim->level < skill_table[gsn_shield_block].skill_level[victim->class]) return FALSE; chance = (( get_skill(victim,gsn_shield_block) / 4) + 15); ch_hitroll = GET_HITROLL(ch); victim_hitroll = GET_HITROLL(victim); //For simplicity... if (victim_hitroll <= 0) victim_hitroll = 1; if (ch_hitroll <= 0) ch_hitroll = 1; if (victim_hitroll < ch_hitroll) { hit_ratio = (float)ch_hitroll / (float)victim_hitroll; if (hit_ratio > 1.35) chance *= 1.35; else chance *= hit_ratio; } /* imperial training */ if (check_imperial_training(ch) == IMPERIAL_OFFENSE) chance -= 10; if (check_imperial_training(victim) == IMPERIAL_DEFENSE) chance += 10; if (check_imperial_training(victim) == IMPERIAL_OFFENSE) chance -= 20; if (check_imperial_training(ch) == IMPERIAL_DEFENSE) chance += 20; if (is_affected(victim,gsn_shield_of_purity) && get_eq_char(victim,WEAR_SHIELD) != NULL) chance += 30; if (is_affected(victim,gsn_shield_of_justice) && get_eq_char(victim,WEAR_SHIELD) != NULL) chance -= 30; switch(get_curr_stat(victim,STAT_STR)) { case 25: chance += 13; break; case 24: chance += 10; break; case 23: chance += 9; break; case 22: chance += 7; break; case 20: chance += 4; break; case 19: chance += 2; break; default: chance += 0; break; } switch(get_curr_stat(victim,STAT_DEX)) { case 25: chance += 8; break; case 24: chance += 7; break; case 23: chance += 6; break; case 22: chance += 5; break; case 20: chance += 4; break; case 19: chance += 3; break; default: chance += 0; break; } if ( get_eq_char( victim, WEAR_SHIELD ) == NULL ) return FALSE; roll = number_percent(); if ( roll >= chance ) return FALSE; attack=get_dam_message(ch,dt); if (!is_affected(victim,gsn_shield_of_purity) && !is_affected(victim,gsn_shield_of_justice)) { sprintf(buf1,"You block $n's %s with your shield.",attack); sprintf(buf2,"$N shield blocks your %s.",attack); } else if (is_affected(victim,gsn_shield_of_purity) && get_eq_char(victim,WEAR_SHIELD) != NULL) { sprintf(buf1,"Your god guides your shield into the path of $n's %s.",attack); sprintf(buf2,"$N gracefully deflects your %s with his divine shield.",attack); } else if (is_affected(victim,gsn_shield_of_justice) && get_eq_char(victim,WEAR_SHIELD) != NULL) { sprintf(buf1,"Blocking $n's %s with your divine shield, you execute a powerful counterattack!",attack); sprintf(buf2,"Blocking your %s with his divine shield, $N executes a powerful counterattack!",attack); } else { if (chance - roll >= 40) { sprintf(buf1,"You masterfully block $n's %s with your shield.",attack); sprintf(buf2,"$N masterfully blocks your %s with $S shield.",attack); } else if (chance - roll >= 30) { sprintf(buf1,"You gracefully block $n's %s with your shield.",attack); sprintf(buf2,"$N gracefully blocks your %s with $S shield.",attack); } else if (chance - roll >= 20) { sprintf(buf1,"You block $n's %s with your shield.",attack); sprintf(buf2,"$N blocks your %s with $S shield.",attack); } else if (chance - roll >= 10) { sprintf(buf1,"You manage to block $n's %s with your shield.",attack); sprintf(buf2,"$N manages to block your %s with $S shield.",attack); } else { sprintf(buf1,"You barely manage to block $n's %s with your shield.",attack); sprintf(buf2,"$N barely manages to block your %s with $S shield.",attack); } } act(buf1,ch,0,victim,TO_VICT); act(buf2,ch,0,victim,TO_CHAR); if (is_affected(victim, gsn_shield_of_justice) && get_eq_char(victim,WEAR_SHIELD) != NULL) one_hit_new(victim,ch,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,200,"strike of justice"); check_improve(victim,gsn_shield_block,TRUE,4); return TRUE; } /* * Check for dodge. */ bool check_dodge( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { char buf1[MSL], buf2[MSL], *attack; int dex, dexa, fam, ch_hitroll, victim_hitroll, roll; float hit_ratio, chance; if ( !IS_AWAKE(victim) ) return FALSE; chance = ( 3 * get_skill(victim,gsn_dodge) / 10); dex = get_curr_stat(victim,STAT_DEX); dexa= get_curr_stat(ch,STAT_DEX); ch_hitroll = GET_HITROLL(ch); victim_hitroll = GET_HITROLL(victim); //For simplicity... if (victim_hitroll <= 0) victim_hitroll = 1; if (ch_hitroll <= 0) ch_hitroll = 1; //Only increase the chance if the victim has more hitroll than the opponent. This is to prevent mage //classes from getting gibbed since they don't stack hitroll right now. Dodge will stay the same for //mages but increase for melee classes that utilize hitroll up to 1.5x the base chance, which can be at //most 30%. Zornath if (victim_hitroll < ch_hitroll) { hit_ratio = (float)ch_hitroll / (float)victim_hitroll; if (hit_ratio > 1.5) chance *= 1.5; else chance *= hit_ratio; } if (dex <= 5) chance += 0; else if (dex <= 10) chance += dex/2; else if (dex <=15) chance += (2*dex/3); else if (dex <= 20) chance += dex; else chance += 3*dex/2; chance+=dex-dexa; chance+=(ch->size-victim->size)*5; if((fam = get_skill(ch,gsn_wilderness_fam) > 0) && isInWilderness(ch)) chance += fam/2; /* imperial training */ if (check_imperial_training(ch) == IMPERIAL_OFFENSE) chance -= 20; if (check_imperial_training(ch) == IMPERIAL_DEFENSE) chance += 20; if (check_imperial_training(victim) == IMPERIAL_OFFENSE) chance -= 20; if (check_imperial_training(victim) == IMPERIAL_DEFENSE) chance += 20; if (!can_see(victim,ch)) chance /= 2; if (!IS_NPC(victim) && IS_SET(victim->act,PLR_MORON)) chance /= 2; // haste/slow if (IS_AFFECTED(victim,AFF_HASTE)) chance += 20; if (IS_AFFECTED(victim,AFF_SLOW)) chance -= 20; if (IS_AFFECTED(ch,AFF_HASTE)) chance -= 20; if (IS_AFFECTED(ch,AFF_SLOW)) chance += 20; if (chance > 95) chance = 95; roll = number_percent(); if ( roll >= chance) return FALSE; attack=get_dam_message(ch,dt); if (chance - roll >= 40) { sprintf(buf1,"You deftly dodge $n's %s.",attack); sprintf(buf2,"$N deftly dodges your %s.",attack); } else if (chance - roll >= 30) { sprintf(buf1,"You gracefully sidestep $n's %s.",attack); sprintf(buf2,"$N gracefully sidesteps your %s.",attack); } else if (chance - roll >= 20) { sprintf(buf1,"You dodge $n's %s.",attack); sprintf(buf2,"$N dodges your %s.",attack); } else if (chance - roll >= 10) { sprintf(buf1,"You manage to avoid $n's %s.",attack); sprintf(buf2,"$N manages to avoid your %s.",attack); } else { sprintf(buf1,"You barely escape $n's %s.",attack); sprintf(buf2,"$N barely escapes your %s.",attack); } if(isInWilderness(ch) && check_fam(ch,attack)) return TRUE; act(buf1,ch,0,victim,TO_VICT); act(buf2,ch,0,victim,TO_CHAR); check_improve(victim,gsn_dodge,TRUE,5); return TRUE; } /* * Check for quest dodge. */ bool check_questdodge( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { float chance, hit_ratio; char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char *attack; int dex, dexa, ch_hitroll, victim_hitroll, roll; if ( !IS_AWAKE(victim) ) return FALSE; if (get_skill(victim,gsn_questdodge) == 0) return FALSE; chance = ( 3 * get_skill(victim,gsn_questdodge) / 7); ch_hitroll = GET_HITROLL(ch); victim_hitroll = GET_HITROLL(victim); //For simplicity... if (victim_hitroll <= 0) victim_hitroll = 1; if (ch_hitroll <= 0) ch_hitroll = 1; if (victim_hitroll < ch_hitroll) { hit_ratio = (float)ch_hitroll / (float)victim_hitroll; if (hit_ratio > 1.3) chance *= 1.3; else chance *= hit_ratio; } dex = get_curr_stat(victim,STAT_DEX); dexa= get_curr_stat(ch,STAT_DEX); if (dex <= 5) chance += 0; else if (dex <= 10) chance += dex/2; else if (dex <=15) chance += (2*dex/3); else if (dex <= 20) chance += (8*dex/10); else chance += dex; chance+=dex-dexa; chance+=(ch->size-victim->size)*5; if (is_affected(ch,gsn_executioner)) chance+=30; roll = number_percent(); if ( roll >= chance) return FALSE; attack=get_dam_message(ch,dt); if (chance - roll >= 40) { sprintf(buf1,"You deftly evade $n's %s.",attack); sprintf(buf2,"$N deftly evades your %s.",attack); } else if (chance - roll >= 30) { sprintf(buf1,"You gracefully dart around $n's %s.",attack); sprintf(buf2,"$N gracefully darts around your %s.",attack); } else if (chance - roll >= 20) { sprintf(buf1,"You evade $n's %s.",attack); sprintf(buf2,"$N evades your %s.",attack); } else if (chance - roll >= 10) { sprintf(buf1,"You manage to evade $n's %s.",attack); sprintf(buf2,"$N manages to evade your %s.",attack); } else { sprintf(buf1,"You barely evade $n's %s.",attack); sprintf(buf2,"$N barely evades your %s.",attack); } act(buf1,ch,0,victim,TO_VICT); act(buf2,ch,0,victim,TO_CHAR); check_improve(victim,gsn_questdodge,TRUE,5); return TRUE; } /* * Check for defensive spin. */ bool check_spin( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { float chance, hit_ratio; int tmp_dt, victim_hitroll, ch_hitroll, roll; OBJ_DATA *wield; char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char *attack; if ((chance = get_skill(victim,gsn_spin) / 2) == 0) { return FALSE; } ch_hitroll = GET_HITROLL(ch); victim_hitroll = GET_HITROLL(victim); //For simplicity... if (victim_hitroll <= 0) victim_hitroll = 1; if (ch_hitroll <= 0) ch_hitroll = 1; if (victim_hitroll < ch_hitroll) { hit_ratio = (float)ch_hitroll / (float)victim_hitroll; if (hit_ratio > 1.25) chance *= 1.25; else chance *= hit_ratio; } wield = get_eq_char(victim,WEAR_WIELD); if (wield == NULL) { return FALSE; } if (wield != NULL) { switch (wield->value[0]) { case (WEAPON_STAFF): chance+= get_skill(victim,gsn_staff) / 10; break; case (WEAPON_SPEAR): chance+= get_skill(victim,gsn_spear) / 10; break; default: return FALSE; break; } } if ( !IS_AWAKE(victim) ) return FALSE; if ( get_eq_char( victim, WEAR_WIELD ) == NULL ) { if (IS_NPC(victim)) chance /= 2; else return FALSE; } if (IS_AFFECTED(victim,AFF_BLIND)) chance *= .75; if (IS_AFFECTED(victim,AFF_HASTE)) chance+=20; if (IS_AFFECTED(ch,AFF_HASTE)) chance-=15; switch(get_curr_stat(victim,STAT_STR)) { case 25: chance += 13; break; case 24: chance += 10; break; case 23: chance += 9; break; case 22: chance += 7; break; case 20: chance += 4; break; case 19: chance += 2; break; default: chance += 0; break; } switch(get_curr_stat(victim,STAT_DEX)) { case 25: chance += 6; break; case 24: chance += 5; break; case 23: chance += 4; break; case 22: chance += 3; break; case 20: chance += 2; break; case 19: chance += 1; break; default: chance += 0; break; } tmp_dt = TYPE_HIT; roll = number_percent(); if ( roll >= chance) { check_improve(victim,gsn_spin,FALSE,2); return FALSE; } attack=get_dam_message(ch,dt); if (chance - roll >= 40) { sprintf(buf1,"You masterfully spin your %s, blocking $n's %s.", wield ? weapon_name_lookup(wield->value[0]) : "hands", attack); sprintf(buf2,"$N masterfully spins $S %s, blocking your %s.",wield ? weapon_name_lookup(wield->value[0]) : "hands",attack); } else if (chance - roll >= 30) { sprintf(buf1,"You gracefully deflect $n's %s with a defensive spin.",attack); sprintf(buf2,"$N gracefully deflects your %s with a defensive spin.",attack); } else if (chance - roll >= 20) { sprintf(buf1,"You spin your %s and fend off $n's %s.",wield ? weapon_name_lookup(wield->value[0]) : "hands",attack); sprintf(buf2,"$N spins $S %s, fending off your %s.",wield ? weapon_name_lookup(wield->value[0]) : "hands",attack); } else if (chance - roll >= 10) { sprintf(buf1,"You manage to spin and deflect $n's %s.",attack); sprintf(buf2,"$N manages to spin and deflect your %s.",attack); } else { sprintf(buf1,"You barely deflect $n's %s with a defensive spin.",attack); sprintf(buf2,"$N barely deflects your %s with a defensive spin.",attack); } act(buf1,ch,0,victim,TO_VICT); act(buf2,ch,0,victim,TO_CHAR); check_improve(victim,gsn_spin,TRUE,2); return TRUE; } bool check_distance( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { int sn = skill_lookup("distance"), ch_hitroll, victim_hitroll; float chance, hit_ratio; OBJ_DATA *wield; char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char *attack; if ( !IS_AWAKE(victim) ) return FALSE; if(get_skill(victim,sn)<5) return FALSE; chance = (( get_skill(victim,sn) / 4) + 15); ch_hitroll = GET_HITROLL(ch); victim_hitroll = GET_HITROLL(victim); //For simplicity... if (victim_hitroll <= 0) victim_hitroll = 1; if (ch_hitroll <= 0) ch_hitroll = 1; if (victim_hitroll < ch_hitroll) { hit_ratio = (float)ch_hitroll / (float)victim_hitroll; if (hit_ratio > 1.35) chance *= 1.35; else chance *= hit_ratio; } /* imperial training */ if (check_imperial_training(ch) == IMPERIAL_OFFENSE) chance -= 10; if (check_imperial_training(victim) == IMPERIAL_DEFENSE) chance += 10; if (check_imperial_training(victim) == IMPERIAL_OFFENSE) chance -= 20; if (check_imperial_training(ch) == IMPERIAL_DEFENSE) chance += 20; chance+=20*(victim->size-ch->size); chance+=10*(get_curr_stat(victim,STAT_STR)-get_curr_stat(ch,STAT_STR)); if(IS_AFFECTED(victim,AFF_HASTE)) chance+=15; if(IS_AFFECTED(ch,AFF_HASTE)) chance-=15; if(((wield=get_eq_char(victim,WEAR_WIELD)) == NULL || wield->value[0]!=WEAPON_POLEARM)) return FALSE; chance += (victim->drain_level + victim->level - (ch->drain_level + ch->level)); chance=URANGE(5,chance,65); if ( number_percent( ) >= chance ) return FALSE; attack=get_dam_message(ch,dt); if(number_percent()<(chance/4)) { sprintf(buf1,"You keep $n at bay with your $p, knocking $m off balance with a counter strike."); sprintf(buf2,"$N keeps you at bay with $S $p, knocking you off balance with a counter strike."); act(buf1,ch,wield,victim,TO_VICT); act(buf2,ch,wield,victim,TO_CHAR); sprintf(buf1,"$N keeps $n at bay with $S $p, knocking $m off balance with a counter strike."); act(buf1,ch,wield,victim,TO_NOTVICT); one_hit_new(victim,ch,sn,HIT_SPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,75,NULL); WAIT_STATE(ch,PULSE_VIOLENCE*1.5); return TRUE; } sprintf(buf1,"You keep $n's %s at bay with your polearm.",attack); sprintf(buf2,"$N keeps your %s at bay with $s polearm.",attack); if(IS_SET(victim->wiznet,WIZ_PERCENT)) sprintf(buf1,"You keep $n's %s at bay with your polearm. (%.0f%%)",attack,chance); if(IS_SET(ch->wiznet,WIZ_PERCENT)) sprintf(buf2,"$N keeps your %s at bay with $S polearm. (%.0f%%)",attack,chance); act(buf1,ch,0,victim,TO_VICT); act(buf2,ch,0,victim,TO_CHAR); check_improve(victim,sn,TRUE,2); return TRUE; } /* * Set position of a victim. */ void update_pos( CHAR_DATA *victim ) { if ( victim->hit > 0 ) { if ( victim->position <= POS_STUNNED ) victim->position = POS_STANDING; return; } if ( IS_NPC(victim) && victim->hit < 1 ) { victim->position = POS_DEAD; return; } if ( victim->hit <= -11 ) { victim->position = POS_DEAD; return; } if ( victim->hit <= -6 ) victim->position = POS_MORTAL; else if ( victim->hit <= -3 ) victim->position = POS_INCAP; else victim->position = POS_STUNNED; return; } /* * Start fights. */ void set_fighting( CHAR_DATA *ch, CHAR_DATA *victim ) { char buf[MAX_STRING_LENGTH]; if ( ch->fighting != NULL ) return; if (ch == victim) return; if ( IS_AFFECTED(ch, AFF_SLEEP) ) affect_strip( ch, gsn_sleep ); if ( is_affected(victim, skill_lookup("resurrect"))) { send_to_char("{RYou lose your focus and the resurrection fails!{x\n\r",victim ); affect_strip(victim,skill_lookup("resurrect")); } if ( is_affected(ch, skill_lookup("resurrect"))) { send_to_char("{RYou lose your focus and the resurrection fails!{x\n\r",ch ); affect_strip(ch,skill_lookup("resurrect")); } if (is_affected(victim,gsn_trip_wire)) { send_to_char("You lost your trip wire in the frey.\n\r",victim); affect_strip(victim,gsn_trip_wire); } if (is_affected(ch,gsn_trip_wire)) { send_to_char("You lost your trip wire in the frey.\n\r",ch); affect_strip(ch,gsn_trip_wire); } ch->fighting = victim; ch->position = POS_FIGHTING; ch->pause = UMAX(ch->pause, 10); victim->pause = UMAX(victim->pause, 10); if (is_centurion(victim)) { sprintf(buf,"empire Help! %s is attacking me at %s!",PERS(ch,victim), victim->in_room->name); do_ccb(victim,buf); } if (IS_SET(victim->progtypes,MPROG_ATTACK)) (victim->pIndexData->mprogs->attack_prog) (victim,ch); return; } /* * Stop fights. */ void stop_fighting( CHAR_DATA *ch, bool fBoth ) { CHAR_DATA *fch; for ( fch = char_list; fch != NULL; fch = fch->next ) { if ( fch == ch || ( fBoth && fch->fighting == ch ) ) { fch->fighting = NULL; fch->position = IS_NPC(fch) ? fch->default_pos : POS_STANDING; update_pos( fch ); } } return; } /* * Make a corpse out of a character. */ void make_corpse( CHAR_DATA *killer,CHAR_DATA *ch ) { char buf[MAX_STRING_LENGTH]; OBJ_DATA *corpse; OBJ_DATA *obj; OBJ_DATA *obj_next; OBJ_DATA *head; char *name, wizbuf[MAX_STRING_LENGTH], *objown; MOB_INDEX_DATA *pMobIndex; objown = NULL; if (IS_NPC(ch) && ch->pIndexData->vnum == 13724) { act("One of $n's massive heads falls decapitated onto the ground.",ch,0,0,TO_ROOM); head = create_object(get_obj_index(OBJ_VNUM_HYDRA_HEAD),0); if (head != NULL) obj_to_room(head,ch->in_room); } if ( IS_NPC(ch) ) { name = str_dup(ch->short_descr); corpse = create_object(get_obj_index(OBJ_VNUM_CORPSE_NPC), 0); corpse->corpse_of = str_dup(ch->short_descr); corpse->timer = number_range( 5, 8 ); free_string(corpse->talked); if (IS_NPC(killer)) corpse->talked = str_dup(killer->short_descr); else corpse->talked = str_dup(killer->name); pMobIndex = ch->pIndexData; // Begin gold calculation float gold = 0; //presumably single kills if (ch->level < 30) gold = 10 * (ch->level) + number_range(1,10); else if (ch->level <= 53) { gold = 52.1*(ch->level-30) + number_range(275,300); gold -= pMobIndex->killed * 10; } else if (ch->level <= 60) { gold = 214.2 *(ch->level-53) + number_range(1300,1500); gold -= pMobIndex->killed * 30; } else if (ch->level <= 70) { gold = 500*(ch->level-60) + number_range(2700,3000); gold -= pMobIndex->killed * 100; } //now we're getting to possibly high-level group kills, so the gold scales much faster to compensate else if (ch->level <= 75) { gold = 1200*(ch->level-70) + number_range(7500,8000); gold -= pMobIndex->killed * 250; } else if (ch->level <= 80) { gold = 16000*(ch->level-75) + number_range(13300,14000); gold -= pMobIndex->killed * 450; } else { gold = 20000*(ch->level-80) + number_range(90000,94000); gold -= pMobIndex->killed * 1000; } // End gold calculation obj_to_obj( create_money((int)gold), corpse ); corpse->cost = 0; } else { name = str_dup(ch->name); corpse = create_object(get_obj_index(OBJ_VNUM_CORPSE_PC), 0); corpse->corpse_of = str_dup(ch->name); corpse->timer = number_range( 20, 35 ); if(ch->in_room && IS_EXPLORE(ch->in_room)) corpse->timer = number_range(6,9); corpse->value[4] = ch->hometown; REMOVE_BIT(ch->act,PLR_CANLOOT); free_string(corpse->talked); if (IS_NPC(killer)) corpse->talked = str_dup(killer->short_descr); else corpse->talked = str_dup(killer->name); corpse->owner = str_dup(ch->original_name); if (ch->gold > 1) { obj_to_obj(create_money(ch->gold), corpse); ch->gold = 0; } corpse->cost = 0; } corpse->level = ch->level; corpse->owner_class = ch->class; if (IS_SET(ch->act,ACT_UNDEAD) || IS_SET(ch->form,FORM_UNDEAD)) set_bit(&corpse->extra_flags,CORPSE_NO_ANIMATE); sprintf( buf, corpse->short_descr, name ); free_string( corpse->short_descr ); corpse->short_descr = str_dup( buf ); sprintf( buf, corpse->description, name ); free_string( corpse->description ); corpse->description = str_dup( buf ); corpse->ohp = ch->max_hit; for ( obj = ch->carrying; obj != NULL; obj = obj_next ) { bool takeItem = TRUE; bool putInCorpse = TRUE; obj_next = obj->next_content; if(!IS_NPC(ch)) objown = str_dup(obj->carried_by->original_name); if (obj->wear_loc == WEAR_BRAND) takeItem = FALSE; if (obj->owner != NULL) { if (!str_cmp(obj->owner,ch->original_name)) { act("$p flashes brightly and returns to $n!",ch,obj,NULL,TO_ROOM); act("$p pulses brightly beside you as you collapse, following you through death itself.",ch,obj,NULL,TO_CHAR); takeItem = FALSE; } } if (takeItem) obj_from_char( obj ); if (obj->item_type == ITEM_POTION) obj->timer = number_range(500,1000); if (obj->item_type == ITEM_SCROLL) obj->timer = number_range(1000,2500); if (is_set(&obj->extra_flags,ITEM_ROT_DEATH)) { obj->timer = 2; remove_bit(&obj->extra_flags,ITEM_ROT_DEATH); } remove_bit(&obj->extra_flags,ITEM_VIS_DEATH); if (obj->pIndexData->limcount > obj->pIndexData->limtotal && obj->pIndexData->limtotal > 0) { act("$p flashes brightly and vaporizes.",ch,obj,NULL,TO_ROOM); extract_obj( obj ); putInCorpse = FALSE; } if (obj->wear_loc == WEAR_BRAND) putInCorpse = FALSE; if (obj->owner != NULL) if (!str_cmp(obj->owner,ch->original_name)) putInCorpse = FALSE; if (putInCorpse) { obj_to_obj( obj, corpse ); if(!IS_NPC(ch)) { free_string(wizbuf); free_string(objown); } } } obj_to_room( corpse, ch->in_room ); return; } /* * Improved Death_cry contributed by Diavolo. */ void death_cry( CHAR_DATA *ch ) { ROOM_INDEX_DATA *was_in_room; char *msg; int door; long vnum; vnum = 0; msg = "You hear $n's death cry."; switch ( number_bits(4)) { case 0: msg = "$n hits the ground ... DEAD."; break; case 1: if (ch->material == 0) { msg = "$n splatters blood on your armor."; break; } case 2: if (IS_SET(ch->parts,PART_GUTS)) { msg = "$n spills $s guts all over the floor."; vnum = OBJ_VNUM_GUTS; } break; case 3: if (IS_SET(ch->parts,PART_HEAD)) { msg = "$n's severed head plops on the ground."; vnum = OBJ_VNUM_SEVERED_HEAD; } break; case 4: if (IS_SET(ch->parts,PART_HEART)) { msg = "$n's heart is torn from $s chest."; vnum = OBJ_VNUM_TORN_HEART; } break; case 5: if (IS_SET(ch->parts,PART_ARMS)) { msg = "$n's arm is sliced from $s dead body."; vnum = OBJ_VNUM_SLICED_ARM; } break; case 6: if (IS_SET(ch->parts,PART_LEGS)) { msg = "$n's leg is sliced from $s dead body."; vnum = OBJ_VNUM_SLICED_LEG; } break; case 7: if (IS_SET(ch->parts,PART_BRAINS)) { msg = "$n's head is shattered, and $s brains splash all over you."; vnum = OBJ_VNUM_BRAINS; } } if (IS_SET(ch->parts,PART_HEAD) && is_affected(ch,gsn_decapitate)) { msg = "$n's severed head plops on the ground."; vnum = OBJ_VNUM_SEVERED_HEAD; } act( msg, ch, NULL, NULL, TO_ROOM ); if ( vnum != 0 ) { char buf[MAX_STRING_LENGTH]; OBJ_DATA *obj; char *name; name = IS_NPC(ch) ? ch->short_descr : ch->name; obj = create_object( get_obj_index( vnum ), 0 ); obj->timer = number_range( 4, 7 ); sprintf( buf, obj->short_descr, name ); free_string( obj->short_descr ); obj->short_descr = str_dup( buf ); sprintf( buf, obj->description, name ); free_string( obj->description ); obj->description = str_dup( buf ); if (obj->item_type == ITEM_FOOD) { if (IS_SET(ch->form,FORM_POISON)) obj->value[3] = 1; else if (!IS_SET(ch->form,FORM_EDIBLE)) obj->item_type = ITEM_TRASH; } obj_to_room( obj, ch->in_room ); } if ( IS_NPC(ch) ) msg = "You hear something's death cry."; else msg = "You hear someone's death cry."; was_in_room = ch->in_room; for ( door = 0; door <= 5; door++ ) { EXIT_DATA *pexit; if ( ( pexit = was_in_room->exit[door] ) != NULL && pexit->u1.to_room != NULL && pexit->u1.to_room != was_in_room ) { ch->in_room = pexit->u1.to_room; act( msg, ch, NULL, NULL, TO_ROOM ); } } ch->in_room = was_in_room; return; } void raw_kill_new( CHAR_DATA *ch,CHAR_DATA *victim, bool deathCry, bool fLook) { int i, cloak=0; ROOM_INDEX_DATA *location; AFFECT_DATA af; AFFECT_DATA *paf, *paf_next; CHAR_DATA *gch, *gch_next, *zombie; OBJ_DATA *trophy, *obj, *strap, *duelcorpse; ROOM_INDEX_DATA *arena_room, *old_room; char buf[MAX_STRING_LENGTH], *cname; char wizbuf[MAX_STRING_LENGTH]; bool unholy=0; bool credit_timer=0; stop_fighting( victim, TRUE ); if (check_darkshout(ch) == DARKSHOUT_NECRUVIAN) { if (IS_GOOD(victim)) { printf_to_char(ch, "You invoke your bond with The Lich Necruvian and siphon life from the lifeless body of %s.\n\r", victim->name); ch->hit = UMIN( ch->hit + number_fuzzy(victim->level), ch->max_hit ); } } if (is_affected(victim,gsn_cloak_form)) do_cloak(victim,"auto"); if (IS_NPC(victim) && victim->pIndexData->vnum == 3059) // PRACTICE DUMMY { act("$n's skull glows brightly and $n rises from $s ashes!",victim,0,0,TO_ROOM); return; } if (IS_NPC(victim) && victim->pIndexData->vnum == MOB_VNUM_DECOY) { death_cry(victim); act("$n vanishes in a poof of smoke!",victim,0,0,TO_ROOM); } else { if (deathCry) death_cry( victim ); if (!IS_NPC(victim) && IS_IMMORTAL(victim)) { if (victim->pcdata->imm_death) { act("$t.",victim,NULL,NULL,TO_ROOM); act("$t.",victim,NULL,NULL,TO_CHAR); } else { act("$n's skull glows brightly and $n rises from $s ashes!",victim,0,0,TO_ROOM); send_to_char("Your skull glows brightly and you rise from your ashes!\n\r",victim); } return; } for (obj = victim->carrying;obj != NULL;obj = obj->next_content) { if (IS_SET(obj->progtypes,IPROG_DEATH)) if ((obj->pIndexData->iprogs->death_prog) (obj,victim)) { victim->position = POS_STANDING; return; } } if ( IS_SET(victim->progtypes,MPROG_DEATH)) { if ((victim->pIndexData->mprogs->death_prog) (victim,ch)) { victim->position = POS_STANDING; return; } } if(IS_NPC(ch) && IS_AFFECTED(ch,AFF_CHARM) && ch->master && ch->master->in_room && ch->master->in_room == ch->in_room) ch = ch->master; // If bard phantom kills, killer becomes phantom->owner if(IS_NPC(ch) && ch->pIndexData->vnum == MOB_VNUM_PHANTOM && ch->owner) ch = ch->owner; if (!IS_NPC(victim)) { if (arena) { /* MAIN STUFF */ sprintf(buf,"%s is killed by %s!",victim->name,ch->original_name); do_arena_echo(buf); char_from_room(victim); location = get_room_index(26000); char_to_room(victim,location); victim->ghost = 1; affect_strip(victim,gsn_plague); affect_strip(victim,gsn_poison); affect_strip(victim,gsn_blindness); affect_strip(victim,gsn_sleep); affect_strip(victim,gsn_curse); affect_strip(victim,gsn_decapitate); affect_strip(victim,gsn_shackles); affect_strip(victim,gsn_boneshatter); affect_strip(victim,gsn_gouge); affect_strip(victim,skill_lookup("hex")); affect_strip(victim,skill_lookup("weaken")); affect_strip(victim,skill_lookup("impale")); affect_strip(victim,skill_lookup("crossslice")); affect_strip(victim,skill_lookup("insectswarm")); victim->hit = victim->max_hit; victim->mana = victim->max_mana; victim->move = victim->max_move; update_pos( victim); send_to_char("You have died and turned into an invincible ghost a few seconds.\n\r",victim); act("$n suddenly appears as a ghost.",victim,0,0,TO_ROOM); /* TROPHY CODE */ trophy = create_object(get_obj_index(OBJ_VNUM_ARENA_TROPHY),0); sprintf( buf, trophy->short_descr, victim->original_name); free_string( trophy->short_descr ); trophy->short_descr = str_dup( buf ); sprintf( buf, trophy->description, victim->original_name); free_string( trophy->description ); trophy->description = str_dup( buf ); obj_to_char(trophy,ch); act("You receive $p.",ch,trophy,0,TO_CHAR); act("$n receives $p.",ch,trophy,0,TO_ROOM); return; } // End arena } // End npc check for arena temp_death_log(ch,victim); /* AP unholy bless check --Dioxide */ if (check_unholy_new(ch,victim,get_eq_char(ch,WEAR_WIELD)) || check_unholy_new(ch,victim,get_eq_char(ch,WEAR_DUAL_WIELD))) { unholy = TRUE; } else { unholy = FALSE; } if (is_affected(victim,gsn_unholy_timer)) { unholy = TRUE; } if (is_affected(victim,gsn_credit_timer)) { credit_timer = TRUE; } strap = get_eq_char(victim, WEAR_STRAPPED); if (strap != NULL) { do_strap(victim,strap); } make_corpse( ch,victim ); } // End npc/pc decoy check. if(!IS_NPC(ch) && !IS_NPC(victim) && victim!=ch) pay_bounty(ch, victim); if (ch && victim) { sprintf( wizbuf, "%s died to %s at %s [room %ld]", (IS_NPC(victim) ? victim->short_descr : victim->original_name), (IS_NPC(ch) ? ch->short_descr : ch->original_name), victim->in_room->name, victim->in_room->vnum); if (IS_NPC(victim)) wiznet(wizbuf,NULL,NULL,WIZ_MOBDEATHS,0,0); else wiznet(wizbuf,NULL,NULL,WIZ_DEATHS,0,0); free_string(wizbuf); } for (gch = char_list; gch != NULL; gch = gch_next) { gch_next = gch->next; if (IS_NPC(gch) && gch->master == victim) extract_char(gch,TRUE); } if ( IS_NPC(victim) ) { victim->pIndexData->killed++; kill_table[URANGE(0, victim->level, MAX_LEVEL-1)].killed++; extract_char( victim, TRUE ); return; } for (paf=victim->affected; paf!=NULL; paf=paf_next) { paf_next=paf->next; if (paf->type == gsn_unholy_bless && (IS_NPC(ch) || arena)) continue; if (!paf->dispel_at_death) continue; affect_remove( victim, paf ); } extract_char( victim, FALSE ); if(is_affected(victim,gsn_cloak_form)) cloak=1; for (paf=victim->affected; paf!=NULL; paf=paf_next) { paf_next=paf->next; if (paf->type == gsn_unholy_bless && (IS_NPC(ch) || arena)) continue; if (paf->dispel_at_death == FALSE) continue; affect_remove( victim, paf ); } victim->affected_by = race_table[victim->race].aff; for (i = 0; i < 4; i++) victim->armor[i]= 100; victim->position = POS_RESTING; victim->hit = victim->pcdata->perm_hit/2; victim->mana = victim->pcdata->perm_mana/2; victim->move = victim->pcdata->perm_move/2; victim->pcdata->condition[COND_HUNGER] = 48; victim->pcdata->condition[COND_THIRST] = 48; victim->pcdata->condition[COND_DRUNK] = 0; victim->pcdata->condition[COND_FULL] = 0; victim->pcdata->condition[COND_DEHYDRATED] = 0; victim->pcdata->condition[COND_STARVING] = 0; REMOVE_BIT(victim->act,PLR_CRIMINAL); victim->ghost = 8; send_to_char("You have died and turned into an invincible ghost for a few minutes.\n\r",victim); if (victim->hometown) location = get_room_index(hometown_table[victim->hometown].recall); else location = get_room_index(ROOM_VNUM_TEMPLE); char_from_room(victim); char_to_room(victim,location); init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_SKILL; af.type = skill_lookup("infravision"); af.name = str_dup("ghost"); af.duration = 20; af.location = 0; af.bitvector = AFF_INFRARED|AFF_PASS_DOOR|AFF_FLYING; af.modifier = 0; char msg_buf[MSL]; sprintf(msg_buf,"turned into a ghostly spirit"); af.affect_list_msg = str_dup(msg_buf); af.level = victim->level; affect_to_char(victim,&af); if (unholy) { if (!is_affected(victim, skill_lookup("unholy guard"))) { init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_SPELL; af.type = skill_lookup("unholy guard"); af.duration = 18; af.location = 0; af.modifier = 0; char msg_buf[MSL]; sprintf(msg_buf,"protects your soul from unholy bless"); af.affect_list_msg = str_dup(msg_buf); af.level = victim->level; af.dispel_at_death = FALSE; affect_to_char(victim,&af); } } if (!credit_timer) { if (!IS_NPC(victim) && !IS_NPC(ch)) { char quest_buf[MSL]; sprintf(quest_buf,"As $N collapses, you find yourself holding %d quest credits!",QUEST_CREDITS_PER_PK); act(quest_buf,ch,0,victim,TO_CHAR); gain_quest_credits(ch,QUEST_CREDITS_PER_PK); init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_SKILL; af.type = gsn_credit_timer; af.duration = 30; af.location = 0; af.modifier = 0; af.name = str_dup("quest guard"); af.affect_list_msg = str_dup("cannot be harvested for quest credits"); af.level = victim->level; af.dispel_at_death = FALSE; affect_to_char(victim,&af); } } victim->last_fight_name = NULL; victim->last_fight_time = 0; // con death if (!IS_NPC(victim)) { if (ch->race == race_lookup("lich")) victim->pcdata->death_count=4; else victim->pcdata->death_count++; if ( (victim->pcdata->death_count >= 4) && !IS_IMMORTAL(victim) && !(victim->perm_stat[STAT_CON] < 3)) { victim->perm_stat[STAT_CON] -= 1; victim->pcdata->death_count = 0; send_to_char("With this death you feel your vitality draining away from you.\n\r",victim); } if (victim->perm_stat[STAT_CON] < CON_DIE_BOUND) { SET_BIT(victim->act, PLR_DENY); perm_death_log(victim,2); send_to_char("You gasp your final breaths. Your vitality has faded.\n\r",victim); wiznet("$N dies of constitution loss.",victim,NULL,0,0,0); stop_fighting(victim,TRUE); victim->pause = 0; save_char_obj(victim); cname = str_dup(victim->original_name); do_quit_new(victim,"",TRUE); delete_char(cname, TRUE); return; } if (victim->perm_stat[STAT_CON] < 5) send_to_char("The banshee wails as you feel closer to a permanent death.\n\r",victim); } // End con death if(!IS_NPC(ch) && ch->in_room->vnum==ROOM_FORCE_DUEL) { init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_POWER; af.type = gsn_honorable_combat; af.duration = 50; af.location = 0; af.modifier = 0; af.bitvector = 0; char msg_buf[MSL]; sprintf(msg_buf,"safe from honorable combat"); af.affect_list_msg = str_dup(msg_buf); af.level = ch->level; affect_to_char(victim,&af); char_from_room(ch); old_room=get_room_index(ch->pcdata->old_room); arena_room=get_room_index(ROOM_FORCE_DUEL); char_to_room(ch,old_room); act("$n arrives in a blaze of white light, having triumphed honorably over $N!\n\r",ch,0,victim,TO_ROOM); for (duelcorpse = arena_room->contents; duelcorpse != NULL; duelcorpse = duelcorpse->next) { if(duelcorpse->in_room==arena_room) { obj_from_room(duelcorpse); obj_to_room(duelcorpse,old_room); } } for (zombie = arena_room->people; zombie != NULL; zombie = zombie->next_in_room) { if (zombie!=NULL && IS_NPC(zombie) && IS_AFFECTED(zombie,AFF_CHARM) && zombie->pIndexData->vnum==MOB_VNUM_ZOMBIE) { char_from_room(zombie); char_to_room(zombie,old_room); } } } // End force duel if (fLook) do_look(victim,"auto"); return; } void raw_kill( CHAR_DATA *ch,CHAR_DATA *victim ) { raw_kill_new( ch, victim, TRUE, TRUE ); } void group_gain( CHAR_DATA *ch, CHAR_DATA *victim ) { char buf[MAX_STRING_LENGTH]; CHAR_DATA *gch; CHAR_DATA *lch; int xp; int members; int group_levels; long quest_credit_gain; /* * Monsters don't get kill xp's or alignment changes. * P-killing doesn't help either. * Dying of mortal wounds or poison doesn't give xp to anyone! */ if ( victim == ch ) return; members = 0; group_levels = 0; for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room ) { if ( is_same_group( gch, ch ) ) { if(!IS_NPC(gch)) members++; group_levels+=gch->level; if(IS_NPC(gch)) group_levels+=gch->level; } } if ( members == 0 ) { members = 1; } lch = (ch->leader != NULL) ? ch->leader : ch; for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room ) { OBJ_DATA *obj; OBJ_DATA *obj_next; bool owner = FALSE; if ( !is_same_group( gch, ch ) || IS_NPC(gch)) continue; if ( gch->level - lch->level > 8 ) { send_to_char( "You are too high for this group.\n\r", gch ); continue; } if ( gch->level - lch->level < -8 ) { send_to_char( "You are too low for this group.\n\r", gch ); continue; } xp = xp_compute( gch, victim, members, group_levels ); quest_credit_gain = quest_credit_compute( gch, victim, members ); if (IS_NPC(victim)) { if(victim->quest_credits <= 0) { sprintf( buf, "You receive %d experience points.\n\r", xp ); send_to_char( buf, gch ); } else { sprintf( buf, "You receive %d experience points.\n\r", xp); send_to_char( buf, gch ); sprintf( buf, "{RAs %s collapses, you suddenly feel an unusually large weight of precious quest credits burden you.{x\n\r", victim->short_descr); send_to_char( buf, gch ); sprintf( buf, "You find an extra %ld quest credits in your possession!\n\r", quest_credit_gain ); send_to_char( buf, gch ); gain_quest_credits( gch, quest_credit_gain ); } } gain_exp( gch, xp ); for ( obj = ch->carrying; obj != NULL; obj = obj_next ) { obj_next = obj->next_content; if ( obj->wear_loc == WEAR_NONE ) continue; ch->unholy_name = str_dup(ch->name); if (str_cmp(obj->owner,ch->unholy_name) ) { owner = TRUE; } if ( ( IS_OBJ_STAT(obj, ITEM_ANTI_EVIL) && IS_EVIL(ch) ) || ( IS_OBJ_STAT(obj, ITEM_ANTI_GOOD) && IS_GOOD(ch) ) || ( IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch) ) || ( IS_OBJ_STAT(obj, ITEM_ANTI_NEUT) && (ch->pcdata->ethos == 0)) || ( IS_OBJ_STAT(obj, ITEM_ANTI_CHAOTIC) && (ch->pcdata->ethos < 0)) || ( IS_WEAPON_STAT(obj,WEAPON_UNHOLY) && (owner))) { act( "You are zapped by $p.", ch, obj, NULL, TO_CHAR ); act( "$n is zapped by $p.", ch, obj, NULL, TO_ROOM ); obj_from_char( obj ); obj_to_room( obj, ch->in_room ); } } } return; } long quest_credit_compute( CHAR_DATA *ch, CHAR_DATA *victim, int group_amount) { int quest_credit_gain = 0; if (IS_NPC(victim) && victim->quest_credits > 0) quest_credit_gain = victim->quest_credits; else { if (group_amount == 1) { if (victim->level < 45) quest_credit_gain = 0; else quest_credit_gain = (victim->level / 18); } else if (group_amount == 2) { if (victim->level < 45) quest_credit_gain = 0; else quest_credit_gain = (victim->level / 18) / 3; } else if (group_amount == 3) { if (victim->level < 45) quest_credit_gain = 0; else quest_credit_gain = (victim->level / 18) / 3; } else if (group_amount > 3) { if (victim->level < 45) quest_credit_gain = 0; else quest_credit_gain = (victim->level / 18) / (group_amount -2); } } return quest_credit_gain; } /* * Compute xp for a kill. * Also adjust alignment of killer. * Edit this function to change xp computations. */ int xp_compute( CHAR_DATA *gch, CHAR_DATA *victim, int group_amount, int glevel ) { int xp,base_exp; int level_range; double mult; mult=((double)(gch->level)/glevel)*group_amount; if(mult>=1) { mult=(1+mult)/2; } else { mult=mult*mult; } mult = URANGE(.25,mult,1.1); level_range = victim->level - gch->level; /* compute the base exp */ switch (level_range) { default : base_exp = 0; break; case -9 : base_exp = 2; break; case -8 : base_exp = 4; break; case -7 : base_exp = 7; break; case -6 : base_exp = 12; break; case -5 : base_exp = 14; break; case -4 : base_exp = 25; break; case -3 : base_exp = 36; break; case -2 : base_exp = 55; break; case -1 : base_exp = 70; break; case 0 : base_exp = 88; break; case 1 : base_exp = 110; break; case 2 : base_exp = 131; break; case 3 : base_exp = 153; break; case 4 : base_exp = 165; break; } if (level_range > 4) base_exp = 165 + 15 * (level_range - 4); if(mult<1&&level_range>4) base_exp = (2*base_exp+165)/3; if (IS_SET(victim->act,ACT_NOALIGN)) xp = base_exp; else if (gch->alignment > 0) { if (victim->alignment < 0) xp = (base_exp *4)/3; else if (victim->alignment > 0) xp = -30; else xp = base_exp; } else if (gch->alignment < 0) /* for baddies */ { if (victim->alignment > 0) xp = (base_exp * 4)/3; else if (victim->alignment < 0) xp = base_exp/2; else xp = base_exp; } else /* neutral */ { xp = base_exp; } xp = (xp*2)/3; xp=xp*mult; xp = number_range (xp, xp * 5/4); /* adjust for grouping */ if (group_amount == 2) xp = (xp * 5)/3; if (group_amount == 3) xp = (xp * 7)/3; if (group_amount > 3) xp /= (group_amount - 2); return xp; } void dam_message( CHAR_DATA *ch, CHAR_DATA *victim,int dam,int dt,bool immune, char *dnoun, bool isPlural, bool showCharName ) { char buf1[256], buf2[256], buf3[256]; OBJ_DATA *wield; CHAR_DATA *gch; const char *vs; const char *vp; const char *attack; char punct; if (ch == NULL || victim == NULL) return; if (is_affected(victim,skill_lookup("mana shield")) && victim->mana > dam) { vs = "{xis absorbed by the mana shield around"; vp = "{xis absorbed by the mana shield around"; } else { if (is_affected(victim,skill_lookup("mana shield")) && victim->mana <= dam) dam = dam - victim->mana; if (dam < 0) { vs = "fail to harm"; vp = "fails to harm"; dam = 0; } else if ( dam == 0 ) { vs = "miss"; vp = "misses"; } else if ( dam <= 2 ) { vs = "scratch"; vp = "scratches"; } else if ( dam <= 4 ) { vs = "graze"; vp = "grazes"; } else if ( dam <= 7 ) { vs = "hit"; vp = "hits"; } else if ( dam <= 11 ) { vs = "injure"; vp = "injures"; } else if ( dam <= 15 ) { vs = "wound"; vp = "wounds"; } else if ( dam <= 20 ) { vs = "maul"; vp = "mauls"; } else if ( dam <= 25 ) { vs = "decimate"; vp = "decimates"; } else if ( dam <= 30 ) { vs = "devastate"; vp = "devastates"; } else if ( dam <= 37 ) { vs = "maim"; vp = "maims"; } else if ( dam <= 45 ) { vs = "MUTILATE"; vp = "MUTILATES"; } else if ( dam <= 55 ) { vs = "EVISCERATE"; vp = "EVISCERATES"; } else if ( dam <= 65 ) { vs = "DISMEMBER"; vp = "DISMEMBERS"; } else if ( dam <= 85 ) { vs = "MASSACRE"; vp = "MASSACRES"; } else if ( dam <= 100 ) { vs = "MANGLE"; vp = "MANGLES"; } else if ( dam <= 135 ) { vs = "*** DEMOLISH ***"; vp = "*** DEMOLISHES ***"; } else if ( dam <= 160 ) { vs = "*** DEVASTATE ***"; vp = "*** DEVASTATES ***"; } else if ( dam <= 250) { vs = "=== OBLITERATE ==="; vp = "=== OBLITERATES ==="; } else if ( dam <= 330) { vs = ">>> ANNIHILATE <<<"; vp = ">>> ANNIHILATES <<<"; } else if ( dam <= 380) { vs = "<<< ERADICATE >>>"; vp = "<<< ERADICATES >>>"; } else { vs = "do UNSPEAKABLE things to"; vp = "does UNSPEAKABLE things to"; } } punct = (dam <= 25) ? '.' : '!'; if (dt == gsn_dual_wield) { wield = get_eq_char(ch,WEAR_DUAL_WIELD); dt = TYPE_HIT; if (wield != NULL) dt += wield->value[3]; else dt += ch->dam_type; } if ( dt == TYPE_HIT ) { if (ch == victim) { sprintf( buf1, "$n %s $melf%c [%d]",vp,punct,dam); sprintf( buf2, "You %s yourself%c [%d]",vs,punct,dam); } else { for (gch = victim->in_room->people; gch != NULL; gch = gch->next_in_room) { if (gch != ch && gch != victim) { sprintf( buf1, "$n's {r%s{x %s%c [%d]", vp, get_descr_form(victim,gch,FALSE), punct, dam); act(buf1,ch,NULL,gch,TO_VICT); } } sprintf( buf2, "You {r%s{x $N%c [%d]", vs, punct, dam ); sprintf( buf3, "$n {r%s{x you%c [%d]", vp, punct, dam ); } } else { if ( dt >= 0 && dt < MAX_SKILL ) attack = skill_table[dt].noun_damage; else if ( dt >= TYPE_HIT && dt < TYPE_HIT + MAX_DAMAGE_MESSAGE) attack = attack_table[dt - TYPE_HIT].noun; else { dt = TYPE_HIT+17; attack = attack_table[0].noun; } if (dnoun) attack = str_dup(dnoun); if (immune) { if (ch == victim) { if (!showCharName) sprintf(buf1,"$n is unaffected by $s own %s.",attack); else sprintf(buf1,"$n is unaffected by %s.",attack); sprintf(buf2,"Luckily, you are immune to that."); } else { if (showCharName) { sprintf(buf1,"$N is unaffected by $n's %s!",attack); sprintf(buf2,"$N is unaffected by your %s!",attack); sprintf(buf3,"$n's %s is powerless against you.",attack); } else { sprintf(buf1,"$N is unaffected by %s!",attack); sprintf(buf2,"$N is unaffected by %s!",attack); sprintf(buf3,"%s is powerless against you.",attack); } } } else { if (ch == victim) { for (gch = victim->in_room->people; gch != NULL; gch = gch->next_in_room) { if (gch != ch && gch != victim) { if (showCharName) { if (isPlural) sprintf( buf1, "$n's %s {r%s{x $m%c [%d]", attack, vp, punct, dam ); else sprintf( buf1, "$n's %s {r%s{x $m%c [%d]", attack, vs, punct, dam ); } else { if (isPlural) sprintf( buf1, "%s {r%s{x $n%c [%d]", attack, vp, punct, dam ); else sprintf( buf1, "%s {r%s{x $n%c [%d]", attack, vs, punct, dam ); } act(buf1,ch,NULL,gch,TO_VICT); } } if (showCharName) { if (isPlural) sprintf( buf2, "Your %s {r%s{x you%c [%d]",attack,vp,punct, dam); else sprintf( buf2, "Your %s {r%s{x you%c [%d]",attack,vs,punct, dam); } else { if (isPlural) sprintf( buf2, "%s {r%s{x you%c [%d]",attack,vp,punct, dam); else sprintf( buf2, "%s {r%s{x you%c [%d]",attack,vs,punct, dam); } } else { for (gch = victim->in_room->people; gch != NULL; gch = gch->next_in_room) { if (gch != ch && gch != victim) { if (showCharName) { if (isPlural) sprintf(buf1, "$n's %s {r%s{x %s%c [%d]", attack, vp, get_descr_form(victim,gch,FALSE), punct, dam); else sprintf(buf1, "$n's %s {r%s{x %s%c [%d]", attack, vs, get_descr_form(victim,gch,FALSE), punct, dam); } else { if (isPlural) sprintf(buf1, "%s {r%s{x %s%c [%d]", attack, vp, get_descr_form(victim,gch,FALSE), punct, dam); else sprintf(buf1, "%s {r%s{x %s%c [%d]", attack, vs, get_descr_form(victim,gch,FALSE), punct, dam); } act(buf1,ch,NULL,gch,TO_VICT); } } if (showCharName) { if (isPlural) sprintf( buf2, "Your %s {r%s{x $N%c [%d]", attack, vp, punct, dam ); else sprintf( buf2, "Your %s {r%s{x $N%c [%d]", attack, vs, punct, dam ); if (isPlural) sprintf( buf3, "$n's %s {r%s{x you%c [%d]", attack, vp, punct, dam ); else sprintf( buf3, "$n's %s {r%s{x you%c [%d]", attack, vs, punct, dam ); } else { if (isPlural) sprintf( buf2, "%s {r%s{x $N%c [%d]", attack, vp, punct, dam ); else sprintf( buf2, "%s {r%s{x $N%c [%d]", attack, vs, punct, dam ); if (isPlural) sprintf( buf3, "%s {r%s{x you%c [%d]", attack, vp, punct, dam ); else sprintf( buf3, "%s {r%s{x you%c [%d]", attack, vs, punct, dam ); } } } } if (ch == victim) { act_new(buf2,ch,NULL,NULL,TO_CHAR,POS_INCAP); } else { act( buf2, ch, NULL, victim, TO_CHAR ); act( buf3, ch, NULL, victim, TO_VICT ); } if (dt != gsn_poison && dt != gsn_plague && dt != gsn_starvation && dt != gsn_dehydrated) { if (!IS_IMMORTAL(ch)) { if (!IS_NPC(victim)) { ch->pause = 10; } else { ch->pause = 1; } } if (!IS_IMMORTAL(victim)) { if (!IS_NPC(ch)) { victim->pause = 10; } else { ch->pause = 1; } } } return; } /* * Disarm a creature. * Caller must check for successful attack. */ void disarm( CHAR_DATA *ch, CHAR_DATA *victim ) { OBJ_DATA *obj,*obj2; OBJ_DATA *secondary; if ( ( obj = get_eq_char( victim, WEAR_WIELD ) ) == NULL ) return; if (IS_AFFECTED(ch,AFF_BLIND)) { act("You can't see the person to disarm them!",ch,NULL,victim,TO_CHAR); return; } if (IS_NPC(ch) && (IS_AFFECTED(ch,AFF_BLIND))) return; if ( IS_OBJ_STAT(obj,ITEM_NOREMOVE) || IS_OBJ_STAT(obj,ITEM_NODISARM)) { act("$S weapon won't budge!",ch,NULL,victim,TO_CHAR); act("$n tries to disarm you, but your weapon won't budge!", ch,NULL,victim,TO_VICT); act("$n tries to disarm $N, but fails.",ch,NULL,victim,TO_NOTVICT); return; } if (is_affected(ch,gsn_unholy_affinity) && ((obj2 = get_eq_char(ch,WEAR_WIELD)) != NULL) && is_affected_obj(obj2,gsn_unholy_bless)) { act("$n tries to disarm you, but you refuse to let go!",victim,0,ch,TO_CHAR); act("You try to disarm $n, but he won't let go of $s weapon!",victim,0,ch,TO_VICT); act("$N tries to disarm $n, but $n holds onto $s weapon!",victim,0,ch,TO_NOTVICT); return; } act( "$n DISARMS you and sends your weapon flying!", ch, NULL, victim, TO_VICT ); act( "You disarm $N!", ch, NULL, victim, TO_CHAR ); act( "$n disarms $N!", ch, NULL, victim, TO_NOTVICT ); obj_from_char( obj ); if ( IS_OBJ_STAT(obj,ITEM_NODROP) || IS_OBJ_STAT(obj,ITEM_INVENTORY) ) obj_to_char( obj, victim ); else { obj_to_room( obj, victim->in_room ); if (IS_NPC(victim) && victim->wait == 0 && can_see_obj(victim,obj)) get_obj(victim,obj,NULL); //Return to owner if owned item if (strcmp(obj->owner,victim->name) == 0) { act( "$N's $p twitches on the ground, then returns to $M!", ch, obj, victim, TO_NOTVICT); act( "$p twitches on the ground, then returns to yout!", ch, obj, victim, TO_VICT); obj_to_char( obj, victim ); } } reslot_weapon(victim); if ((secondary = get_eq_char(victim,WEAR_DUAL_WIELD)) != NULL) { unequip_char(victim,secondary); equip_char(victim,secondary,WEAR_WIELD); } return; } void do_berserk( CHAR_DATA *ch, char *argument) { int chance, hp_percent; if ((chance = get_skill(ch,gsn_berserk)) == 0 || (IS_NPC(ch) && !IS_SET(ch->off_flags,OFF_BERSERK)) || (!IS_NPC(ch) && ch->level < skill_table[gsn_berserk].skill_level[ch->class])) { send_to_char("You turn red in the face, but nothing happens.\n\r",ch); return; } if (IS_AFFECTED(ch,AFF_BERSERK) || is_affected(ch,gsn_berserk) || is_affected(ch,skill_lookup("frenzy"))) { send_to_char("You get a little madder.\n\r",ch); return; } if (IS_AFFECTED(ch,AFF_CALM)) { send_to_char("You're feeling to mellow to berserk.\n\r",ch); return; } if (IS_AFFECTED(ch,AFF_SLOW)) { send_to_char("You're feeling way too lethargic to berserk.\n\r", ch); return; } if (ch->mana < 100) { send_to_char("You can't get up enough energy.\n\r",ch); return; } if (ch->position == POS_FIGHTING) chance += 10; if (ch->max_hit == 0) hp_percent = 0; else hp_percent = 100 * ch->hit/ch->max_hit; chance += 25 - hp_percent/2; if (number_percent() < chance) { AFFECT_DATA af; WAIT_STATE(ch,PULSE_VIOLENCE); ch->mana -= 100; ch->move /= 1.2; ch->hit += (ch->drain_level + ch->level) * 4; ch->hit = UMIN(ch->hit,ch->max_hit); send_to_char("Your pulse races as you are consumed by rage!\n\r",ch); act("$n gets a wild look in $s eyes.",ch,NULL,NULL,TO_ROOM); check_improve(ch,gsn_berserk,TRUE,2); init_affect(&af); af.where = TO_AFFECTS; af.type = gsn_berserk; af.level = ch->level; af.duration = number_range(4,9); af.modifier = 10; af.bitvector = AFF_BERSERK; af.aftype = AFT_SKILL; af.location = APPLY_HITROLL; affect_to_char(ch,&af); af.location = APPLY_DAMROLL; affect_to_char(ch,&af); af.modifier = -2 * AC_PER_ONE_PERCENT_DECREASE_DAMAGE; af.location = APPLY_AC; affect_to_char(ch,&af); } else { WAIT_STATE(ch,PULSE_VIOLENCE); ch->mana -= 25; send_to_char("Your pulse speeds up, but nothing happens.\n\r",ch); check_improve(ch,gsn_berserk,FALSE,2); } return; } void do_bash( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; int dam, chance; char buf[MSL], arg[MIL]; one_argument(argument,arg); if ( (chance = get_skill(ch,gsn_bash)) == 0 || (IS_NPC(ch) && !IS_SET(ch->off_flags,OFF_BASH)) || (!IS_NPC(ch) && ch->level < skill_table[gsn_bash].skill_level[ch->class])) { send_to_char("Bashing? What's that?\n\r",ch); return; } if (IS_NPC(ch) && IS_AFFECTED(ch,AFF_CHARM)) return; if (arg[0] == '\0') { victim = ch->fighting; if (victim == NULL) { send_to_char("But you aren't fighting anyone!\n\r",ch); return; } } else if ((victim = get_char_room(ch,arg)) == NULL) { send_to_char("They aren't here.\n\r",ch); return; } if (victim->position < POS_FIGHTING) { act("You'll have to let $M get back up first.",ch,NULL,victim,TO_CHAR); return; } if (victim == ch) { send_to_char("You try to bash your brains out, but fail.\n\r",ch); return; } if (is_safe(ch,victim)) return; if (IS_AFFECTED(ch,AFF_CHARM) && ch->master == victim) { act("But $N is your friend!",ch,NULL,victim,TO_CHAR); return; } if (is_affected(victim,gsn_protective_shield)) { act("$N's bash seems to slide around you.",victim,0,ch,TO_CHAR); act("$N's bash seems to slide around $n.",victim,0,ch,TO_NOTVICT); act("Your bash seems to slide around $n.",victim,0,ch,TO_VICT); WAIT_STATE(ch,PULSE_VIOLENCE*.5); return; } if (is_affected(victim,gsn_asscounter)) { act("You deftly sidestep $N's bash, throwing them to the ground.",victim,0,ch,TO_CHAR); act("$n quickly dodges $N's bash, throwing $s down in the process.",victim,0,ch,TO_NOTVICT); act("$n deftly dodges your bash, throwing you to the ground in the process.",victim,0,ch,TO_VICT); WAIT_STATE(ch,2 * PULSE_VIOLENCE); dam = victim->level*2 + number_percent()*2 - 50; damage_old(victim,ch,dam,gsn_throw,DAM_BASH,TRUE); affect_strip( victim, gsn_asscounter ); return; } if (is_affected(victim, skill_lookup("wraithform"))) { act("$N's tries to bash you but stumbles through thin air.",victim,0,ch,TO_CHAR); act("$N's tries to bash $n but stumbles through thin air.",victim,0,ch,TO_NOTVICT); act("You stumble as you try to bash $n but stumble through thin air.",victim,0,ch,TO_VICT); WAIT_STATE(ch,PULSE_VIOLENCE*1); return; } chance += ch->carry_weight / 250; chance -= victim->carry_weight / 200; if (ch->size < victim->size) chance += (ch->size - victim->size) * 20; else chance += (ch->size - victim->size) * 10; /* stats */ chance += get_curr_stat(ch,STAT_STR); chance -= (get_curr_stat(victim,STAT_DEX) * 4)/3; chance -= GET_AC(victim,AC_BASH) /25; /* speed */ if (IS_SET(ch->off_flags,OFF_FAST) || IS_AFFECTED(ch,AFF_HASTE)) chance += 10; if (IS_SET(victim->off_flags,OFF_FAST) || IS_AFFECTED(victim,AFF_HASTE)) chance -= 40; /* level */ chance += (ch->drain_level + ch->level - victim->level - victim->drain_level); if (!IS_NPC(ch) && !IS_NPC(victim) && (victim->fighting == NULL || ch->fighting == NULL)) { sprintf(buf,"Help! %s is bashing me!",PERS(ch,victim)); do_myell(victim,buf); } if (!IS_NPC(victim) && chance < get_skill(victim,gsn_dodge) ) chance -= 3 * (get_skill(victim,gsn_dodge) - chance); /* now the attack */ if (number_percent() < chance ) { act("$n sends you sprawling with a powerful bash!", ch,NULL,victim,TO_VICT); act("You slam into $N, and send $M flying!",ch,NULL,victim,TO_CHAR); act("$n sends $N sprawling with a powerful bash.", ch,NULL,victim,TO_NOTVICT); check_improve(ch,gsn_bash,TRUE,1); WAIT_STATE(victim, 2 * PULSE_VIOLENCE); damage_old(ch,victim,number_range(2,2 + 2 * ch->size + chance/20),gsn_bash, DAM_BASH,TRUE); WAIT_STATE(ch,skill_table[gsn_bash].beats); victim->position = POS_RESTING; } else { damage_old(ch,victim,0,gsn_bash,DAM_BASH,FALSE); act("You fall flat on your face!", ch,NULL,victim,TO_CHAR); act("$n falls flat on $s face.", ch,NULL,victim,TO_NOTVICT); act("You evade $n's bash, causing $m to fall flat on $s face.", ch,NULL,victim,TO_VICT); check_cheap_shot(victim,ch); check_improve(ch,gsn_bash,FALSE,1); ch->position = POS_RESTING; WAIT_STATE(ch,skill_table[gsn_bash].beats); } check_killer(ch,victim); } void do_dirt( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; int chance; char buf[MAX_STRING_LENGTH]; one_argument(argument,arg); if ( (chance = get_skill(ch,gsn_dirt)) == 0 || (IS_NPC(ch) && !IS_SET(ch->off_flags,OFF_KICK_DIRT) && ch->pIndexData->vnum!=MOB_VNUM_ENFORCER) || (!IS_NPC(ch) && ch->level < skill_table[gsn_dirt].skill_level[ch->class])) { send_to_char("You get your feet dirty.\n\r",ch); return; } if (arg[0] == '\0') { victim = ch->fighting; if (victim == NULL) { send_to_char("But you aren't in combat!\n\r",ch); return; } } else if ((victim = get_char_room(ch,arg)) == NULL) { send_to_char("They aren't here.\n\r",ch); return; } if (IS_AFFECTED(victim,AFF_BLIND)) { act("$E's already been blinded.",ch,NULL,victim,TO_CHAR); return; } if(victim->position==POS_SLEEPING) { send_to_char("Their eyes are closed.\n\r",ch); return; } if (victim == ch) { send_to_char("Very funny.\n\r",ch); return; } if (is_safe(ch,victim)) return; if (IS_AFFECTED(ch,AFF_CHARM) && ch->master == victim) { act("But $N is such a good friend!",ch,NULL,victim,TO_CHAR); return; } if (is_affected(victim, gsn_shield_of_dust)) { act("Your dirt is blocked by $N's shield of dust!",ch,NULL,victim,TO_CHAR); act("$n kicks dirt at you but it is stoped by your shield of dust!", ch,NULL,victim,TO_VICT); act("$n's dirt is deflected by $N's shield of dust!",ch,NULL,victim,TO_NOTVICT); return; } /* dexterity */ chance += get_curr_stat(ch,STAT_DEX); chance -= 2 * get_curr_stat(victim,STAT_DEX); /* speed */ if (IS_SET(ch->off_flags,OFF_FAST) || IS_AFFECTED(ch,AFF_HASTE)) chance += 10; if (IS_SET(victim->off_flags,OFF_FAST) || IS_AFFECTED(victim,AFF_HASTE)) chance -= 30; /* level */ chance += (ch->drain_level + ch->level - victim->level - victim->drain_level) * 2; /* sloppy hack to prevent false zeroes */ if (chance % 5 == 0) chance += 1; /* terrain */ switch(ch->in_room->sector_type) { case(SECT_INSIDE): chance -= 20; break; case(SECT_CITY): chance -= 10; break; case(SECT_FIELD): chance += 5; break; case(SECT_FOREST): break; case(SECT_HILLS): break; case(SECT_MOUNTAIN): chance -= 10; break; case(SECT_WATER_SWIM): chance = 0; break; case(SECT_WATER_NOSWIM): chance = 0; break; case(SECT_AIR): chance = 0; break; case(SECT_DESERT): chance += 10; break; } if (chance == 0) { send_to_char("There isn't any dirt to kick.\n\r",ch); return; } /* now the attack */ if (number_percent() < chance) { AFFECT_DATA af; act("$n is blinded by the dirt in $s eyes!",victim,NULL,NULL,TO_ROOM); act("$n kicks dirt in your eyes!",ch,NULL,victim,TO_VICT); if (!IS_NPC(ch) && !IS_NPC(victim) && ( (victim->fighting == NULL) || (ch->fighting == NULL))) do_myell(victim,"Help! Someone just kicked dirt in my eyes!"); damage(ch,victim,number_range(2,5),gsn_dirt,DAM_TRUESTRIKE,TRUE); send_to_char("You can't see a thing!\n\r",victim); check_improve(ch,gsn_dirt,TRUE,2); WAIT_STATE(ch,skill_table[gsn_dirt].beats); init_affect(&af); af.where = TO_AFFECTS; af.type = gsn_dirt; af.aftype = AFT_MALADY; af.level = ch->level + ch->drain_level; af.duration = 0; af.location = APPLY_HITROLL; af.modifier = -4; af.bitvector = AFF_BLIND; affect_to_char(victim,&af); } else { if (!IS_NPC(ch) && !IS_NPC(victim) && (victim->fighting == NULL || ch->fighting == NULL)) { switch(number_range(0,1)) { case (0): sprintf(buf,"Help! %s just tried to kick dirt in my eyes!",PERS(ch,victim)); break; case (1): sprintf(buf,"Die, %s you dirty fool!",PERS(ch,victim)); break; } do_myell(victim,buf); } damage(ch,victim,0,gsn_dirt,DAM_NONE,TRUE); check_improve(ch,gsn_dirt,FALSE,2); WAIT_STATE(ch,skill_table[gsn_dirt].beats); } check_killer(ch,victim); } void do_trip( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; int chance; int dam; AFFECT_DATA af; char buf[MAX_STRING_LENGTH]; one_argument(argument,arg); if ( (chance = get_skill(ch,gsn_trip)) == 0 || (IS_NPC(ch) && !IS_SET(ch->off_flags,OFF_TRIP) && ch->pIndexData->vnum!=MOB_VNUM_ENFORCER) || (!IS_NPC(ch) && ch->level < skill_table[gsn_trip].skill_level[ch->class])) { send_to_char("Tripping? What's that?\n\r",ch); return; } if (arg[0] == '\0') { victim = ch->fighting; if (victim == NULL) { send_to_char("But you aren't fighting anyone!\n\r",ch); return; } } else if ((victim = get_char_room(ch,arg)) == NULL) { send_to_char("They aren't here.\n\r",ch); return; } if (is_safe(ch,victim)) return; if (IS_AFFECTED(victim,AFF_FLYING) && !is_affected(victim,gsn_earthbind)) { act("$S feet aren't on the ground.",ch,NULL,victim,TO_CHAR); return; } if (victim->position < POS_FIGHTING) { act("$N is already down.",ch,NULL,victim,TO_CHAR); return; } if (victim == ch) { send_to_char("You fall flat on your face!\n\r",ch); WAIT_STATE(ch,2 * skill_table[gsn_trip].beats); act("$n trips over $s own feet!",ch,NULL,NULL,TO_ROOM); return; } if (is_affected(victim,gsn_asscounter)) { act("You dart to the side kicking the inside of $N's knee!",victim,0,ch,TO_CHAR); act("$n darts to the side kicking the inside of $N's knee!",victim,0,ch,TO_NOTVICT); act("$n dodges your trip, then kicks the inside of your knee!",victim,0,ch,TO_VICT); WAIT_STATE(victim,1 * PULSE_VIOLENCE); dam = victim->level*2 + number_percent()*2 - 50; damage_old(victim,ch,dam,gsn_legbreak,DAM_BASH,TRUE); if (!is_affected(ch,gsn_legbreak)) { init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_MALADY; af.type = gsn_legbreak; af.level = victim->level; af.duration = victim->level/5; af.bitvector = 0; af.location = APPLY_DEX; af.modifier = 1-(victim->level/5); affect_to_char(ch,&af); } affect_strip( victim, gsn_asscounter ); return; } if (IS_AFFECTED(ch,AFF_CHARM) && ch->master == victim) { act("$N is your beloved master.",ch,NULL,victim,TO_CHAR); return; } /* modifiers */ /* size */ if (ch->size < victim->size) chance += (ch->size - victim->size) * 10; /* bigger = harder to trip */ /* dex */ chance += get_curr_stat(ch,STAT_DEX); chance -= get_curr_stat(victim,STAT_DEX) * 3 / 2; /* speed */ if (IS_SET(ch->off_flags,OFF_FAST) || IS_AFFECTED(ch,AFF_HASTE)) chance += 10; if (IS_SET(victim->off_flags,OFF_FAST) || IS_AFFECTED(victim,AFF_HASTE)) chance -= 40; /* level */ chance += (ch->drain_level + ch->level - victim->level - victim->drain_level) * 2; /* now the attack */ if (number_percent() < chance) { act("$n trips you and you go down!",ch,NULL,victim,TO_VICT); act("You trip $N and $N goes down!",ch,NULL,victim,TO_CHAR); act("$n trips $N, sending $M to the ground.",ch,NULL,victim,TO_NOTVICT); check_improve(ch,gsn_trip,TRUE,1); if (!IS_NPC(ch) && !IS_NPC(victim) && (ch->fighting == NULL || victim->fighting == NULL)) { sprintf(buf,"Help! %s just tripped me!",PERS(ch,victim)); do_myell(victim,buf); } WAIT_STATE(victim,2 * PULSE_VIOLENCE); WAIT_STATE(ch,skill_table[gsn_trip].beats); victim->position = POS_RESTING; damage(ch,victim,number_range(2, 2 + 2 * victim->size),gsn_trip, DAM_BASH,TRUE); check_downstrike(ch,victim); check_cheap_shot(ch,victim); } else { if (!IS_NPC(ch) && !IS_NPC(victim) && (ch->fighting == NULL || victim->fighting == NULL)) { sprintf(buf,"Help! %s just tried to trip me!",PERS(ch,victim)); do_myell(victim,buf); } damage(ch,victim,0,gsn_trip,DAM_BASH,TRUE); WAIT_STATE(ch,skill_table[gsn_trip].beats*2/3); check_improve(ch,gsn_trip,FALSE,1); } check_killer(ch,victim); } void do_hit( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; one_argument( argument, arg ); if ( ch->position != POS_FIGHTING ) { send_to_char( "You're not fighting anyone.\n\r", ch ); return; } if ( arg[0] == '\0' ) { send_to_char( "Switch targets to 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( "Are you crazy?\n\r", ch ); return; } if ( victim->fighting != ch ) { send_to_char( "That person isn't fighting you.\n\r", ch ); return; } ch->fighting = victim; return; } void do_kill( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Kill whom?\n\r", ch ); return; } if ( ( victim = get_char_room( ch, arg ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } /* Allow player killing */ if ( !IS_NPC(victim) ) { send_to_char( "You must MURDER a player.\n\r", ch ); return; } if ( victim == ch ) { send_to_char( "You hit yourself. Ouch!\n\r", ch ); multi_hit( ch, ch, TYPE_UNDEFINED ); return; } if ( is_safe( ch, victim ) ) return; if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim ) { act( "$N is your beloved master.", ch, NULL, victim, TO_CHAR ); return; } if ( ch->position == POS_FIGHTING ) { send_to_char( "You do the best you can!\n\r", ch ); return; } WAIT_STATE( ch, 1 * PULSE_VIOLENCE ); multi_hit( ch, victim, TYPE_UNDEFINED ); return; } void do_murde( CHAR_DATA *ch, char *argument ) { send_to_char( "If you want to MURDER, spell it out.\n\r", ch ); return; } void do_murder( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Murder whom?\n\r", ch ); return; } if ((IS_AFFECTED(ch,AFF_CHARM) || (IS_NPC(ch) && IS_SET(ch->act,ACT_PET))) && !is_centurion(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( "Suicide is a mortal sin.\n\r", ch ); return; } if ( is_safe( ch, victim ) ) return; if (check_chargeset(ch,victim)) {return;} if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim ) { act( "$N is your beloved master.", ch, NULL, victim, TO_CHAR ); return; } if ( ch->position == POS_FIGHTING ) { send_to_char( "You do the best you can!\n\r", ch ); return; } WAIT_STATE( ch, 1 * PULSE_VIOLENCE ); if (IS_NPC(ch)) sprintf(buf, "Help! I am being attacked by %s!",ch->short_descr); else { switch(number_range(1,6)) { default: sprintf(buf, "Help! I am being attacked by %s!",PERS(ch,victim)); break; case (1): sprintf(buf, "Help! I am being attacked by %s!",PERS(ch,victim)); break; case (2): sprintf(buf, "Die %s, you dirty fool!", PERS(ch,victim)); break; case (3): case (4): sprintf(buf, "Help! %s is attacking me!", PERS(ch,victim)); break; case (5): sprintf(buf, "How dare you attack me %s!", PERS(ch,victim)); break; case (6): sprintf(buf, "Help! %s is hurting me!", PERS(ch,victim)); break; } } /* Added a myell hack of yell so Enforcer cabal members can see if a PK yell is faked or not (see myell in act_comm.c for this). -Ceran */ do_myell( victim, buf ); multi_hit( ch, victim, TYPE_UNDEFINED ); return; } void do_backstab( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; OBJ_DATA *obj; int dam; char buf[MAX_STRING_LENGTH]; one_argument( argument, arg ); if ( (get_skill(ch,gsn_backstab) == 0 ) || ch->level < skill_table[gsn_backstab].skill_level[ch->class]) { if (!IS_NPC(ch)) { send_to_char("You don't know how to backstab.\n\r",ch); return; } } if (arg[0] == '\0') { send_to_char("Backstab whom?\n\r",ch); return; } if (ch->fighting != NULL) { send_to_char("You're facing the wrong end.\n\r",ch); return; } else 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; } obj= get_eq_char(ch,WEAR_WIELD); if (obj == NULL) { send_to_char("You must be wielding a weapon to backstab.\n\r",ch); return; } if (obj->value[0] != WEAPON_DAGGER) { obj = get_eq_char(ch,WEAR_DUAL_WIELD); if (obj == NULL) { send_to_char("You must be wielding a weapon to backstab.\n\r",ch); return; } } if (obj->value[0] != WEAPON_DAGGER) { send_to_char("You need to be wielding a dagger to backstab.\n\r",ch); return; } if ( is_safe(ch, victim ) ) return; if (check_chargeset(ch,victim)) {return;} if ( victim->fighting != NULL ) { send_to_char( "That person is moving around too much to backstab.\n\r", ch ); return; } if ((victim->hit < victim->max_hit*9/10)) { act( "$N is hurt and suspicious ... you can't sneak up.", ch, NULL, victim, TO_CHAR ); return; } WAIT_STATE( ch, skill_table[gsn_backstab].beats ); if ( number_percent( ) < get_skill(ch,gsn_backstab) || ( get_skill(ch,gsn_backstab) >= 2 && !IS_AWAKE(victim) ) ) { check_improve(ch,gsn_backstab,TRUE,1); if (!IS_NPC(ch) && !IS_NPC(victim) && victim->fighting == NULL) { switch(number_range(0,1)) { case (0): sprintf(buf,"Die, %s you backstabbing fool!",PERS(ch,victim)); break; case (1): sprintf(buf,"Help! I'm being backstabbed by %s!",PERS(ch,victim)); break; } do_myell(victim,buf); } one_hit_new(ch,victim,gsn_backstab,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,NULL); } else { check_improve(ch,gsn_backstab,FALSE,1); if (!IS_NPC(ch) && !IS_NPC(victim) && victim->fighting == NULL) { switch(number_range(0,1)) { case (0): sprintf(buf,"Die, %s you backstabbing fool!",PERS(ch,victim)); break; case (1): sprintf(buf,"Help! I'm being backstabbed by %s!",PERS(ch,victim)); break; } do_myell(victim,buf); } damage( ch, victim, 0, gsn_backstab,DAM_NONE,TRUE); } if (ch->level < skill_table[gsn_dual_backstab].skill_level[ch->class]) return; if (number_range(0,3) == 0) { if (get_skill(ch,gsn_dual_backstab) != 100) check_improve(ch,gsn_dual_backstab,FALSE,1); return; } if (number_percent() > (get_skill(ch,gsn_dual_backstab) + ch->level - victim->level) ) { check_improve(ch,gsn_dual_backstab,FALSE,1); dam = 0; } else { dam = dice(obj->value[1], obj->value[2]) * get_skill(ch,gsn_dual_backstab)/100; if ((ch->drain_level + ch->level) < 35) dam *= number_range(2,4); else if ((ch->drain_level + ch->level) < 40) dam *= number_range(2,5); else if ((ch->drain_level + ch->level) < 45) dam *= number_range(3,5); else if ((ch->drain_level + ch->level) < 50) dam *= number_range(10,25); /* 4,6 */ else dam *= number_range(15,30); /* 4,7 */ dam += (ch->damroll * get_skill(ch,gsn_dual_backstab)/100); } damage_old(ch,victim,dam,gsn_dual_backstab,DAM_NONE,TRUE); return; } void do_rescue( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; CHAR_DATA *fch; 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( "What about fleeing instead?\n\r", ch ); return; } if ( !IS_NPC(ch) && IS_NPC(victim) ) { send_to_char( "Doesn't need your help!\n\r", ch ); return; } if ( ( fch = victim->fighting ) == NULL ) { send_to_char( "That person is not fighting right now.\n\r", ch ); return; } if (victim->fighting == ch) return send_to_char( "You cannot rescue someone who is attacking you!\n\r",ch); if (ch->fighting == victim) return send_to_char( "Rescue the person you're fighting?\n\r",ch); if (is_safe(ch,victim->fighting)) return; WAIT_STATE( ch, skill_table[gsn_rescue].beats ); if ( number_percent( ) > get_skill(ch,gsn_rescue)) { send_to_char( "You fail the rescue.\n\r", ch ); check_improve(ch,gsn_rescue,FALSE,1); return; } WAIT_STATE(victim,12); act( "You rescue $N!", ch, NULL, victim, TO_CHAR ); act( "$n rescues you!", ch, NULL, victim, TO_VICT ); act( "$n rescues $N!", ch, NULL, victim, TO_NOTVICT ); check_improve(ch,gsn_rescue,TRUE,1); stop_fighting( fch, FALSE ); stop_fighting( victim, FALSE ); set_fighting( ch, fch ); set_fighting( fch, ch ); return; } void do_kick( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; int dam; if ( !IS_NPC(ch) && ch->level < skill_table[gsn_kick].skill_level[ch->class] ) { send_to_char( "You better leave the martial arts to fighters.\n\r", ch ); return; } if (IS_NPC(ch) && !IS_SET(ch->off_flags,OFF_KICK)) return; if ( ( victim = ch->fighting ) == NULL ) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } WAIT_STATE( ch, skill_table[gsn_kick].beats ); if ( get_skill(ch,gsn_kick) > number_percent()) { dam = (ch->drain_level + ch->level)/2; dam += number_range(0,(ch->drain_level + ch->level)/6); dam += number_range(0,(ch->drain_level + ch->level)/6); dam += number_range(0,(ch->drain_level + ch->level)/6); dam += number_range(0,(ch->drain_level + ch->level)/6); dam += number_range(0,(ch->drain_level + ch->level)/6); dam += number_range(0,(ch->drain_level + ch->level)/6); dam += number_range(ch->level/5,ch->level/4); if (!IS_NPC(ch)) { if (!str_cmp(class_table[ch->class].name,"channeler")) if (!str_cmp(class_table[ch->class].name,"necromancer")) if (!str_cmp(class_table[ch->class].name,"elementalist")) { dam *= 3; dam /= 4; } } if (spike_toed_boots(ch)) dam *= 3; damage(ch,victim,dam, gsn_kick,DAM_BASH,TRUE); check_improve(ch,gsn_kick,TRUE,1); check_follow_through(ch,victim,dam); } else { damage( ch, victim, 0, gsn_kick,DAM_BASH,TRUE); check_improve(ch,gsn_kick,FALSE,1); } check_killer(ch,victim); return; } void do_disarm( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim=0; OBJ_DATA *obj,*obj2; int dam; AFFECT_DATA af; int chance,hth,ch_weapon,vict_weapon,ch_vict_weapon; hth = 0; if ((chance = get_skill(ch,gsn_disarm)) == 0) { send_to_char( "You don't know how to disarm opponents.\n\r", ch ); return; } if ( get_eq_char( ch, WEAR_WIELD ) == NULL && ((hth = get_skill(ch,gsn_hand_to_hand)) == 0 || (IS_NPC(ch) && !IS_SET(ch->off_flags,OFF_DISARM)))) { send_to_char( "You must wield a weapon to disarm.\n\r", ch ); return; } if (IS_AFFECTED(ch,AFF_BLIND)) { act("You can't see the person to disarm them!",ch,NULL,victim,TO_CHAR); return; } if (IS_NPC(ch) && (IS_AFFECTED(ch,AFF_BLIND))) return; if ( ( victim = ch->fighting ) == NULL ) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } if (is_affected(victim,gsn_asscounter)) { act("With blinding speed you hit $N's arm, breaking it!",victim,0,ch,TO_CHAR); act("With blinding speed $n hits $N's arm, breaking it!",victim,0,ch,TO_NOTVICT); act("With blinding speed $n hits your arm, breaking it instantly!",victim,0,ch,TO_VICT); WAIT_STATE(victim,2 * PULSE_VIOLENCE); dam = victim->level*2 + number_percent()*2 - 50; damage_old(victim,ch,dam,gsn_armbreak,DAM_BASH,TRUE); if (!is_affected(ch,gsn_armbreak)) { init_affect(&af); af.where = TO_AFFECTS; af.type = gsn_armbreak; af.aftype = AFT_MALADY; af.level = victim->level; af.duration = victim->level/5; af.bitvector = 0; af.location = APPLY_DEX; af.modifier = 1-(victim->level/5); affect_to_char(ch,&af); af.location = APPLY_STR; af.modifier = 1-(victim->level/5); af.bitvector = 0; affect_to_char(ch,&af); } affect_strip( victim, gsn_asscounter ); return; } if ( ( obj = get_eq_char( victim, WEAR_WIELD ) ) == NULL ) { send_to_char( "Your opponent is not wielding a weapon.\n\r", ch ); return; } if (is_affected(victim,gsn_spiderhands) ) { act("You try to disarm $N, but $s hands stick to his weapon.", ch,NULL,victim,TO_CHAR); act("$n tries to disarm you, but your hands stick to your weapon.", ch,NULL,victim,TO_VICT); act("$n tries to disarm $N, but their hands stick to their weapon.", ch,NULL,victim,TO_NOTVICT); return; } if (is_affected(victim,gsn_unholy_affinity) && ((obj2 = get_eq_char(victim,WEAR_WIELD)) != NULL) && is_affected_obj(obj2,gsn_unholy_bless)) { act("$N tries to disarm you, but you refuse to let go!",victim,0,ch,TO_CHAR); act("You try to disarm $n, but he won't let go of $s weapon!",victim,0,ch,TO_VICT); act("$N tries to disarm $n, but $n holds onto $s weapon!",victim,0,ch,TO_NOTVICT); return; } /* find weapon skills */ ch_weapon = get_weapon_skill(ch,get_weapon_sn(ch)); vict_weapon = get_weapon_skill(victim,get_weapon_sn(victim)); ch_vict_weapon = get_weapon_skill(ch,get_weapon_sn(victim)); /* modifiers */ chance *= 8; chance /=10; /* skill */ if ( get_eq_char(ch,WEAR_WIELD) == NULL) chance = chance * hth/150; else chance = chance * ch_weapon/100; chance += (ch_vict_weapon/2 - vict_weapon) / 2; /* dex vs. strength */ chance += get_curr_stat(ch,STAT_DEX); chance -= 1.25 * get_curr_stat(victim,STAT_STR); /* level */ chance += (ch->drain_level + ch->level - victim->drain_level - victim->level) * 2; /* and now the attack */ if (number_percent() < chance) { WAIT_STATE( ch, skill_table[gsn_disarm].beats ); disarm( ch, victim ); check_improve(ch,gsn_disarm,TRUE,1); } else { WAIT_STATE(ch,skill_table[gsn_disarm].beats); act("You fail to disarm $N.",ch,NULL,victim,TO_CHAR); act("$n tries to disarm you, but fails.",ch,NULL,victim,TO_VICT); act("$n tries to disarm $N, but fails.",ch,NULL,victim,TO_NOTVICT); check_improve(ch,gsn_disarm,FALSE,1); } check_killer(ch,victim); return; } void do_circle_stab( CHAR_DATA *ch, char *argument ) { bool attempt_dual; char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; CHAR_DATA *v_check; CHAR_DATA *v_next; OBJ_DATA *obj; int chance; int dam; attempt_dual = FALSE; one_argument(argument,arg); if ( (chance = get_skill(ch,gsn_circle)) == 0 || IS_NPC(ch) || (!IS_NPC(ch) && ch->level < skill_table[gsn_circle].skill_level[ch->class]) ) { send_to_char("Circling? What's that?\n\r",ch); return; } if (arg[0] == '\0') { victim = ch->fighting; if (victim == NULL) { send_to_char("But you aren't fighting anyone.\n\r",ch); return; } } else if ((victim = get_char_room(ch,arg)) == NULL) { send_to_char("They aren't here.\n\r",ch); return; } if (ch->fighting == NULL) { send_to_char("You can't circle someone like that.\n\r",ch); return; } for (v_check = ch->in_room->people; v_check != NULL; v_check = v_next) { v_next = v_check->next_in_room; if (v_check->fighting == ch) { send_to_char("Not while you're defending yourself!\n\r",ch); return; } } if (victim == ch) { send_to_char("huh?\n\r", ch); return; } obj = get_eq_char(ch,WEAR_WIELD); if (obj == NULL || obj->value[0] != WEAPON_DAGGER) { attempt_dual = TRUE; obj = get_eq_char(ch,WEAR_DUAL_WIELD); } if (obj == NULL) { send_to_char("You must wield a dagger to circle stab.\n\r",ch); return; } if (obj->value[0] != 2) { send_to_char("You must wield a dagger to circle stab.\n\r",ch); return; } chance += (ch->drain_level + ch->level - victim->level - victim->drain_level); chance = URANGE(5, chance, 95); WAIT_STATE(ch,skill_table[gsn_circle].beats); if (number_percent() < chance) { act("You circle around $N to land a critical strike.",ch,NULL,victim,TO_CHAR); act("$n cirlces around you to land a critical strike.",ch,NULL,victim,TO_VICT); act("$n circles $N to land a critical strike.",ch,NULL,victim,TO_NOTVICT); check_improve(ch,gsn_circle,TRUE,1); dam = dice(obj->value[1],obj->value[2]); dam += 40; if ((ch->drain_level + ch->level) <= 15) dam *= 1; else if ((ch->drain_level + ch->level) <= 20) dam *= 3/2; else if ((ch->drain_level + ch->level) < 25) dam *= 2; else if ((ch->drain_level + ch->level) < 30) dam *= 7/3; else if ((ch->drain_level + ch->level) < 40) dam *= 5/2; else if ((ch->drain_level + ch->level) <= 49) dam *= 7/2; else if ((ch->drain_level + ch->level) <= 55) dam *= 10/3; else dam *= 10/3; damage_old(ch,victim,dam,gsn_circle, attack_table[obj->value[3]].damage, TRUE); } else { check_improve(ch,gsn_circle,FALSE,1); damage_old(ch,victim,0,gsn_circle,DAM_NONE,TRUE); } return; } void do_surrender( CHAR_DATA *ch, char *argument ) { CHAR_DATA *mob; if ( (mob = ch->fighting) == NULL ) { send_to_char( "But you're not fighting!\n\r", ch ); return; } act( "You surrender to $N!", ch, NULL, mob, TO_CHAR ); act( "$n surrenders to you!", ch, NULL, mob, TO_VICT ); act( "$n tries to surrender to $N!", ch, NULL, mob, TO_NOTVICT ); stop_fighting( ch, TRUE ); } void do_sla( CHAR_DATA *ch, char *argument ) { send_to_char( "If you want to SLAY, spell it out.\n\r", ch ); return; } void do_slay( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Slay 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 == victim ) { send_to_char( "Suicide is a mortal sin.\n\r", ch ); return; } if ( !IS_NPC(victim) && victim->level >= get_trust(ch)) { send_to_char( "You failed.\n\r", ch ); return; } act( "You point at $M and $S heart stops!", ch, NULL, victim, TO_CHAR ); act( "$n points at you and your heart suddenly stops!", ch, NULL, victim, TO_VICT ); act( "$n points at $N and $E falls over clenching his chest!", ch, NULL, victim, TO_NOTVICT ); raw_kill(ch, victim ); n_logf("%s has slain %s", ch->name, victim->name); return; } void spell_evil_eye(int sn,int level, CHAR_DATA *ch,void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam, modify, saves; if (victim == ch) { send_to_char("You can't do such a thing.\n\r",ch); return; } act("$n's eyes turn pitch-black and a surging darkness erupts at $N.",ch,NULL,victim,TO_NOTVICT); act("Your eyes turn pitch-black and a stream of pure negative energy streams out at $N.",ch,NULL,victim,TO_CHAR); send_to_char("You feel a sudden intense agony burning into your skull.\n\r",victim); if (IS_SET(victim->affected_by,AFF_BLIND) ) { dam = dice(level,8); if (saves_spell(level,victim, DAM_NEGATIVE) ) dam /= 2; damage_old(ch,victim,dam,sn,DAM_NEGATIVE, TRUE); return; } saves = 1; for (modify = 0; modify < 4; modify ++) { if (saves_spell(level, victim, DAM_NEGATIVE)) saves++; } if (saves == 0) { act("$n's surging darkness devestates $N's skull, killing $M instantly!",ch,NULL,victim,TO_NOTVICT); act("Your darkness slays $N!",ch,NULL,victim,TO_CHAR); send_to_char("With a violent burning sensation your mind vaporises.\n\r",victim); raw_kill(ch,victim); return; } dam = dice(level, 16); dam /= (saves + 1); damage_old(ch,victim,dam,sn,DAM_NEGATIVE,TRUE); return; } void spell_power_word_kill(int sn,int level,CHAR_DATA *ch,void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam,saves,modify; saves = 0; act("$n points a finger at $N and utters the word, 'Die'.",ch,NULL,victim,TO_NOTVICT); act("$n points a finger at you and utters the word, 'Die'.",ch,NULL,victim,TO_VICT); send_to_char("You intone a word of unholy power.\n\r",ch); for ( modify = 0; modify < 5; modify++) { if (saves_spell(level-1,victim,DAM_NEGATIVE) ) saves++; } if(IS_IMMORTAL(ch) && (victim->level<ch->level)) { saves=0; } if (saves == 0) { act("$N shudders in shock as $S heart explodes!", ch, NULL,victim,TO_NOTVICT); send_to_char("You feel your heart rupture in a violent explosion of pain!\n\r",victim); act("Your word of power vaporises $N's heart, killing $M instantly!",ch,NULL,victim,TO_CHAR); raw_kill(ch,victim); return; } dam = dice(level,14); dam /= saves; damage_old(ch,victim,dam,sn,DAM_NEGATIVE,TRUE); return; } void do_lunge( CHAR_DATA *ch, char *argument) { CHAR_DATA *victim; int chance, dam; char arg[MAX_INPUT_LENGTH]; OBJ_DATA *wield; int multiplier; dam = 0; one_argument(argument,arg); if ((chance = get_skill(ch,gsn_lunge) ) == 0 || (ch->level < skill_table[gsn_lunge].skill_level[ch->class]) ) { send_to_char("Lunging? What's that?\n\r",ch); return; } if (arg[0] == '\0') { victim = ch->fighting; if (victim == NULL) { send_to_char("But you aren't fighting anyone!\n\r",ch); return; } } else 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("You can't lunge at yourself!\n\r",ch); return; } wield = get_eq_char(ch,WEAR_WIELD); if ((wield == NULL) || (( wield->value[0] != WEAPON_SWORD) && ( wield->value[0] != WEAPON_SPEAR) && ( wield->value[0] != WEAPON_POLEARM) )) { send_to_char("You must be wielding a sword, spear or polearm to lunge.\n\r",ch); return; } if (is_safe(ch,victim) ) return; if (check_chargeset(ch,victim)) {return;} chance += ch->carry_weight/25; chance -= victim->carry_weight/20; chance += (ch->size - victim->size)*20; chance -= get_curr_stat(victim,STAT_DEX); chance += get_curr_stat(ch,STAT_STR)/3; chance += get_curr_stat(ch,STAT_DEX)/2; if (IS_AFFECTED(ch,AFF_HASTE) ) chance += 10; if (IS_AFFECTED(victim,AFF_HASTE) ) chance = 20; chance += (ch->drain_level + ch->level - victim->level - victim->drain_level); act("$n attempts to impale $N with a quick lunge!",ch,0,victim,TO_NOTVICT); act("You attempt to impale $N with a quick lunge!",ch,0,victim,TO_CHAR); act("$n attempts to impale you with a quick lunge!",ch,0,victim,TO_VICT); if (number_percent() < chance) { check_improve(ch,gsn_lunge,TRUE,1); WAIT_STATE(ch,skill_table[gsn_lunge].beats); if (wield->pIndexData->new_format) dam = dice(wield->value[1],wield->value[2]); else dam = number_range(wield->value[1],wield->value[2]); if (get_skill(ch,gsn_enhanced_damage) > 0 ) { if (number_percent() <= get_skill(ch,gsn_enhanced_damage) ) { check_improve(ch,gsn_enhanced_damage,TRUE,1); dam += dam*(number_range(60,100)/100) * ch->pcdata->learned[gsn_enhanced_damage]/100; } } dam += GET_DAMROLL(ch); dam *= ch->pcdata->learned[gsn_lunge]; dam /= 100; multiplier = number_range((ch->drain_level + ch->level)/8,(ch->drain_level + ch->level)/4); multiplier /= 10; multiplier += 6/4; dam *= multiplier; if (dam <= 0) dam = 1; damage_old(ch,victim,dam,gsn_lunge,DAM_PIERCE,TRUE); } else { damage_old(ch,victim,dam,gsn_lunge,DAM_PIERCE,TRUE); check_improve(ch,gsn_lunge,FALSE,1); WAIT_STATE(ch,skill_table[gsn_lunge].beats); } return; } void do_bandage(CHAR_DATA *ch,char *argument) { CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; AFFECT_DATA af; one_argument(argument,arg); if ( (get_skill(ch,gsn_bandage) == 0) || (ch->level < skill_table[gsn_bandage].skill_level[ch->class]) ) { send_to_char("Huh?\n\r",ch); return; } if (cabal_down(ch,CABAL_RAGER)) return; if (is_affected(ch,gsn_bandage)) { send_to_char("You can't apply more aid yet.\n\r",ch); return; } if (ch->mana < 50) { send_to_char("You don't have the mana.\n\r",ch); return; } if (arg[0] == '\0') victim = ch; else if ((victim = get_char_room(ch,arg)) == NULL) { send_to_char("They aren't here.\n\r",ch); return; } if (number_percent() > ch->pcdata->learned[gsn_bandage]) { act("You fail to apply battle dressing to $N's wounds.",ch,0,victim,TO_CHAR); act("$n fumbles with $s bandages but fails to use them effectively.",ch,0,0,TO_ROOM); ch->mana -= 35; check_improve(ch,gsn_bandage,FALSE,3); return; } ch->mana -= 50; if (victim != ch) { act("$n applies bandages to $N's battle wounds.",ch,0,victim,TO_NOTVICT); act("You apply bandages to $N's battle wounds.",ch,0,victim,TO_CHAR); act("$n applies bandages to your battle wounds.",ch,0,victim,TO_VICT); } else { act("$n applies bandages to $mself.",ch,0,0,TO_ROOM); send_to_char("You apply battle dressing to yourself.\n\r",ch); } send_to_char("You feel better.\n\r",victim); victim->hit = UMIN(victim->hit + (9*ch->level), victim->max_hit); if (number_percent() < 60) { if (IS_AFFECTED(victim,AFF_PLAGUE)) { affect_strip(victim,gsn_plague); act("The sores on $n's body vanish.\n\r",victim,0,0,TO_ROOM); send_to_char("The sores on your body vanish.\n\r",victim); } } if (number_percent() < 60) { if (is_affected(victim, gsn_blindness)) { affect_strip(victim, gsn_blindness); send_to_char("Your vision returns!\n\r",victim); } } if (number_percent() < 60) { if (is_affected(victim,gsn_poison)) { affect_strip(victim,gsn_poison); send_to_char("A warm feeling goes through your body.\n\r",victim); act("$n looks better.",victim,0,0,TO_ROOM); } if (is_affected(victim,gsn_poison_dust)) { affect_strip(victim,gsn_poison_dust); send_to_char("The dust in your eyes is cleaned out.\n\r",victim); act("The dust in $n's eyes looks cleaned out.",victim,0,0,TO_ROOM); } } check_improve(ch,gsn_bandage,TRUE,3); init_affect(&af); af.where = TO_AFFECTS; af.type = gsn_bandage; af.location = 0; af.duration = number_range(5,8); af.modifier = 0; af.bitvector = 0; char msg_buf[MSL]; sprintf(msg_buf,"unable to bandage"); af.affect_list_msg = str_dup(msg_buf); af.level = ch->level; af.aftype = AFT_POWER; affect_to_char(ch,&af); return; } void do_herb(CHAR_DATA *ch,char *argument) { CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; AFFECT_DATA af; one_argument(argument,arg); if ( (get_skill(ch,gsn_herb) == 0) || (ch->level < skill_table[gsn_herb].skill_level[ch->class]) ) { send_to_char("Huh?\n\r",ch); return; } if (is_affected(ch,gsn_herb)) { send_to_char("You can't find any more herbs.\n\r",ch); return; } if ( (ch->in_room->sector_type != SECT_FOREST) && (ch->in_room->sector_type != SECT_MOUNTAIN) && (ch->in_room->sector_type != SECT_HILLS ) && (ch->in_room->sector_type != SECT_DESERT) && (ch->in_room->sector_type != SECT_FIELD )) { send_to_char("You can't find any herbs here.\n\r",ch); return; } if (arg[0] == '\0') victim = ch; else if ((victim = get_char_room(ch,arg)) == NULL) { send_to_char("They aren't here.\n\r",ch); return; } if (number_percent() > ch->pcdata->learned[gsn_herb]) { send_to_char("You search for herbs but fail to find any.\n\r",ch); act("$n looks about in the bushes but finds nothing.",ch,0,0,TO_ROOM); check_improve(ch,gsn_herb,FALSE,4); return; } if (victim != ch) { act("$n applies herbs to $N.",ch,0,victim,TO_NOTVICT); act("You apply herbs to $N.",ch,0,victim,TO_CHAR); act("$n applies herbs to you.",ch,0,victim,TO_VICT); } if (victim == ch) { act("$n applies herbs to $mself.",ch,0,0,TO_ROOM); send_to_char("You find herbs and apply them to yourself.\n\r",ch); } send_to_char("You feel better.\n\r",victim); if (IS_AFFECTED(victim,AFF_PLAGUE) && number_percent() > 30) { affect_strip(victim,gsn_plague); act("The sores on $n's body vanish.\n\r",victim,0,0,TO_ROOM); send_to_char("The sores on your body vanish.\n\r",victim); } check_improve(ch,gsn_herb,TRUE,4); victim->hit = UMIN(victim->hit + (4*(ch->drain_level + ch->level)), victim->max_hit); init_affect(&af); af.where = TO_AFFECTS; af.type = gsn_herb; af.location = 0; af.duration = 4; af.modifier = 0; af.bitvector = 0; char msg_buf[MSL]; sprintf(msg_buf,"unable to search for herbs"); af.affect_list_msg = str_dup(msg_buf); af.aftype = AFT_SKILL; af.level = ch->level + ch->drain_level; affect_to_char(ch,&af); return; } void do_cleave(CHAR_DATA *ch,char *argument) { OBJ_DATA *weapon; CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; int dam, chance, dam_type; char buf[MAX_STRING_LENGTH]; int sn; int skill; if ( ( ( chance = get_skill(ch,gsn_cleave)) == 0) || (ch->level < skill_table[gsn_cleave].skill_level[ch->class]) ) { send_to_char("You don't know how to cleave.\n\r",ch); return; } one_argument(argument,arg); weapon = get_eq_char(ch,WEAR_WIELD); if (weapon == NULL) { send_to_char("You need to wield a sword or axe to cleave.\n\r",ch); return; } if ((weapon->value[0] != WEAPON_SWORD) && (weapon->value[0] != WEAPON_AXE) ) { send_to_char("You need to wield a sword or axe to cleave.\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("You can't do such a thing.\n\r",ch); return; } if (victim->fighting != NULL) { send_to_char("They are moving too much to cleave.\n\r",ch); return; } if (victim->hit < victim->max_hit*9/10) { send_to_char("They are too hurt and watchful to cleave right now...\n\r",ch); return; } if (is_safe(ch,victim)) return; if (check_chargeset(ch,victim)) {return;} chance /= 5; if ((ch->drain_level + ch->level - victim->drain_level + victim->level) < 0) chance -= (ch->drain_level + ch->level - victim->drain_level - victim->level)*3; else chance += (ch->drain_level + ch->level - victim->level - victim->drain_level); chance += get_curr_stat(ch,STAT_STR)/2; chance -= get_curr_stat(victim,STAT_DEX)/3; /* Improve evasion */ chance -= get_curr_stat(victim,STAT_STR)/4; /* Improve repelling */ chance -= get_curr_stat(victim,STAT_CON)/4; /* Shock survival */ dam_type = attack_table[weapon->value[3]].damage; if (!can_see(victim,ch)) chance += 5; chance -= dice(2,6); chance = URANGE(2,chance,10); if (IS_IMMORTAL(victim)) chance = 0; if (IS_CABAL_OUTER_GUARD(victim)) chance = 0; if (number_percent() < 50) sprintf(buf,"Die, %s you butchering fool!",PERS(ch,victim)); else sprintf(buf,"Help! %s just tried to cleave me in half!",PERS(ch,victim)); sn = get_weapon_sn(ch); skill = get_weapon_skill(ch,sn) + ch->pcdata->learned[gsn_cleave] + 10; skill = URANGE(0,skill/2,100); if (IS_IMP(ch)) { chance += 100; } act("You make a brutal swing at $N in an attempt to cleave them in half.",ch,0,victim,TO_CHAR); act("$n attempts to cleave you in half with a brutal slice.",ch,0,victim,TO_VICT); act("$n makes an attempt to cleave $N in half.",ch,0,victim,TO_NOTVICT); if (IS_IMP(victim)) { act("You make a brutal swing at $N in an attempt to cleave them in half, but miss and chop your own head off.",ch,0,victim,TO_CHAR); act("$n attempts to cleave you in half with a brutal slice, but misses and chops thier own head off.",ch,0,victim,TO_VICT); act("$n makes an attempt to cleave $N in half but misses and chops their own head off!",ch,0,victim,TO_NOTVICT); raw_kill(victim,ch); return; } if (IS_NPC(victim)) victim->last_fought = ch; if (number_percent() > chance) { check_improve(ch,gsn_cleave,FALSE,5); if (weapon->pIndexData->new_format) dam = dice(weapon->value[1],weapon->value[2])*skill/100; else dam = number_range(weapon->value[1]*skill/100,weapon->value[2]*skill/100); dam *= number_range((ch->drain_level + ch->level)/10,(ch->drain_level + ch->level)/7); damage_old(ch,victim,dam,gsn_cleave,dam_type,TRUE); if (!IS_NPC(victim) && !IS_NPC(ch) && victim->hit > 1) do_myell(victim,buf); WAIT_STATE(ch,PULSE_VIOLENCE*3); WAIT_STATE(victim,PULSE_VIOLENCE*2); return; } act("Your cleave slices $S body in half with a clean cut!",ch,0,victim,TO_CHAR); act("$n cleaves you in half, tearing your body into two bloody bits!",ch,0,victim,TO_VICT); act("$n cleaves $N into to bits of bloody flesh!",ch,0,victim,TO_NOTVICT); check_improve(ch,gsn_cleave,TRUE,5); raw_kill(ch,victim); return; } void do_deathstrike(CHAR_DATA *ch,char *argument) { CHAR_DATA *victim; int chance, dam; char arg[MAX_INPUT_LENGTH]; char buf[MAX_INPUT_LENGTH]; /* AFFECT_DATA af; */ one_argument(argument,arg); if (IS_NPC(ch)) return; if ((get_skill(ch,gsn_deathstrike) == 0) || ch->level < skill_table[gsn_deathstrike].skill_level[ch->class]) { send_to_char("Huh?\n\r",ch); return; } if (is_affected(ch,gsn_deathstrike)) { send_to_char("You can't build up the intensity to deathstrike yet.\n\r",ch); return; } if (arg[0] == '\0') { send_to_char("Attempt to destroy who's skull?\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("You can't do that.\n\r",ch); return; } if (victim->fighting != NULL || victim->position == POS_FIGHTING) { send_to_char("They are moving around too much to get in close for the kill.\n\r",ch); return; } if (is_safe(ch,victim)) return; if (victim->hit < victim->max_hit) { send_to_char("They have too much blood on them right now to locate their strike point.\n\r",ch); return; } chance = get_skill(ch,gsn_deathstrike)/2; chance += ch->level; chance -= victim->level * 3/2; chance -= number_range(0,15); if (!can_see(victim,ch)) chance += 10; if (victim->position == POS_FIGHTING) chance -= 25; else if (victim->position == POS_SLEEPING) chance += 10; else chance -= 10; chance /= 2; chance = URANGE(2,chance,90); act("$n strikes out at $N with deadly intensity.",ch,0,victim,TO_NOTVICT); act("You strike out at $N with deadly intensity.",ch,0,victim,TO_CHAR); act("$n strikes at you with deadly intensity.",ch,0,victim,TO_VICT); if (number_percent() < chance) { send_to_char("With agonising pain your skull is smashed by the blow!\n\r",victim); act("Your blow shatters $N's skull into bloody fragments!",ch,0,victim,TO_CHAR); act("$N's skull is shattered into bits of mangled flesh and bone by $n's strike!",ch,0,victim,TO_NOTVICT); raw_kill(ch,victim); check_improve(ch,gsn_deathstrike,TRUE,3); return; } else { send_to_char("You feel a sharp pain searing your skull!\n\r",victim); act("Your deathstrike smashes $N's skull but fails to kill.",ch,0,victim,TO_CHAR); dam = ch->level * 2; dam += dice(ch->level, 4); damage_old(ch,victim,dam,gsn_deathstrike,DAM_PIERCE,TRUE); check_improve(ch,gsn_deathstrike,FALSE,3); if (!IS_NPC(victim) && !IS_NPC(ch) && (victim->hit > 1)) { sprintf(buf,"Help! %s just tried to kill me!",PERS(ch,victim)); do_myell(victim,buf); } multi_hit(victim,ch,TYPE_UNDEFINED); } return; } void do_crush(CHAR_DATA *ch,char *argument) { CHAR_DATA *victim; int chance, dam; if (IS_NPC(ch) && IS_AFFECTED(ch,AFF_CHARM)) return; if ( (chance = get_skill(ch,gsn_crush)) == 0 || ch->level < skill_table[gsn_crush].skill_level[ch->class]) if (!IS_NPC(ch)) { send_to_char("Crushing, how do you do that again?\n\r",ch); return; } if ((victim = ch->fighting) == NULL) { send_to_char("You aren't fighting anyone.\n\r",ch); return; } if (is_affected(victim,gsn_protective_shield)) { act("$N's crush attempt seems to slide around you.",victim,0,ch,TO_CHAR); act("$N's crush attempt seems to slide around $n.",victim,0,ch,TO_NOTVICT); act("Your crush attempt seems to slide around $n.",victim,0,ch,TO_VICT); WAIT_STATE(ch,PULSE_VIOLENCE*2); return; } if (is_affected(victim, skill_lookup("wraithform"))) { act("$N's crush attempt seems to slide around you.",victim,0,ch,TO_CHAR); act("$N's crush attempt seems to slide around $n.",victim,0,ch,TO_NOTVICT); act("Your crush attempt seems to slide around $n.",victim,0,ch,TO_VICT); WAIT_STATE(ch,PULSE_VIOLENCE*2); return; } chance -= chance/4; chance += (ch->drain_level + ch->level - victim->drain_level - victim->level) * 2; chance += get_curr_stat(ch,STAT_STR); chance -= get_curr_stat(victim,STAT_DEX)/3; chance -= get_curr_stat(victim,STAT_STR)/2; if (ch->size < victim->size) chance += (ch->size - victim->size)*25; else chance += (ch->size - victim->size)*10; if (number_percent() < chance) { if (check_roll(ch,victim, gsn_crush)) { check_improve(ch,gsn_crush,TRUE,2); act("$N rolls free of $n's crush.",ch,0,victim,TO_NOTVICT); act("You roll out of $n's crush attempt.",ch,0,victim,TO_VICT); act("$N rolls free of your crush attempt.",ch,0,victim,TO_CHAR); return; } act("$n grabs you and slams you to the ground with bone crushing force!",ch,0,victim,TO_VICT); act("You grab $N and slam $M to the ground with bone crushing force!",ch,0,victim,TO_CHAR); act("$n slams $N to the ground with bone crushing force!",ch,0,victim,TO_NOTVICT); check_improve(ch,gsn_crush,TRUE,4); if ((ch->drain_level + ch->level) < 20) dam = 20; else if ((ch->drain_level + ch->level) < 25) dam = 30; else if ((ch->drain_level + ch->level) < 30) dam = 40; else if ((ch->drain_level + ch->level) < 35) dam = 50; else if ((ch->drain_level + ch->level) < 40) dam = 60; else if ((ch->drain_level + ch->level) < 52) dam = 70; else dam = 70; dam += str_app[get_curr_stat(ch,STAT_STR)].todam; WAIT_STATE(victim,2*PULSE_VIOLENCE); WAIT_STATE(ch,2*PULSE_VIOLENCE); damage_old(ch,victim,dam,gsn_crush,DAM_BASH,TRUE); victim->position = POS_RESTING; if (ch->fighting == victim) check_ground_control(ch,victim,chance,dam); return; } act("Your crush attempt misses $N.",ch,0,victim,TO_CHAR); act("$n lashes out wildly with $s arms but misses.",ch,0,0,TO_ROOM); WAIT_STATE(ch,2*PULSE_VIOLENCE); check_improve(ch,gsn_crush,FALSE,3); return; } void check_ground_control(CHAR_DATA *ch,CHAR_DATA *victim,int chance,int dam) { if (chance < 10) return; if (dam == 0) return; chance += get_skill(ch,gsn_ground_control)/2; chance /= 3; chance -= number_range(5,15); chance = URANGE(5,chance,60); if (ch->level < skill_table[gsn_ground_control].skill_level[ch->class]) return; if (number_percent() > chance) { check_improve(ch,gsn_ground_control,FALSE,3); return; } act("With brutal skill you grind $N against the ground with your weight.",ch,0,victim,TO_CHAR); act("$n takes hold of $N and grinds $M against the ground.",ch,0,victim,TO_NOTVICT); act("$n grinds you against the ground with brutal skill.",ch,0,victim,TO_VICT); dam -= 10; check_improve(ch,gsn_ground_control,TRUE,2); damage_old(ch,victim,dam,gsn_ground_control,DAM_BASH,TRUE); WAIT_STATE(victim,2*PULSE_VIOLENCE); return; } void do_riot(CHAR_DATA *ch,char *argument) { CHAR_DATA *gch; int bonus; AFFECT_DATA af; if ( (get_skill(ch,gsn_riot) == 0 ) || ch->level < skill_table[gsn_riot].skill_level[ch->class]) { send_to_char("Huh?\n\r",ch); return; } if (ch->mana < 40) { send_to_char("You don't have the mana.\n\r",ch); return; } if (is_affected(ch,gsn_riot)) { send_to_char("You can't stir up another riot yet.\n\r",ch); return; } if (number_percent() > ch->pcdata->learned[gsn_riot]) { send_to_char("You try to incite a riot amongst your group but fail.\n\r",ch); act("$n gestures around angrily, trying to build up anger and discord but fails.",ch,0,0,TO_ROOM); ch->mana -= 20; check_improve(ch,gsn_riot,FALSE,2); return; } send_to_char("You stir up a riot with your actions!\n\r",ch); init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_POWER; af.type = gsn_riot; af.level = ch->level + ch->drain_level; af.bitvector = 0; af.duration = ( 2 + (ch->drain_level + ch->level)/8); af.location = APPLY_HITROLL; if ((ch->drain_level + ch->level) < 20) bonus = 6; else if ((ch->drain_level + ch->level) < 25) bonus = 7; else if ((ch->drain_level + ch->level) < 30) bonus = 8; else if ((ch->drain_level + ch->level) < 35) bonus = 9; else if ((ch->drain_level + ch->level) < 38) bonus = 10; else bonus = 12; af.modifier = bonus; affect_to_char(ch,&af); af.location = APPLY_DAMROLL; affect_to_char(ch,&af); send_to_char("You are filled with terrible fury!\n\r",ch); for (gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room) { if (!is_same_group(ch,gch) || !IS_AWAKE(gch)) continue; if (is_affected(gch,gsn_riot)) continue; if (gch->trust > 51) continue; if (gch == ch) continue; af.location = APPLY_DAMROLL; affect_to_char(gch,&af); af.location = APPLY_HITROLL; affect_to_char(gch,&af); send_to_char("You are filled with a terrible fury!\n\r",gch); act("$n gets a terrible look of anger in $s eyes.",gch,0,0,TO_ROOM); } check_improve(ch,gsn_riot,TRUE,2); ch->mana -= 40; return; } void do_tail(CHAR_DATA *ch, char *argument) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; int chance, dam; int knock; one_argument(argument,arg); if (IS_NPC(ch) && IS_AFFECTED(ch,AFF_CHARM)) return; if ( (chance = get_skill(ch,gsn_tail)) == 0 || (IS_NPC(ch) && !IS_SET(ch->off_flags,OFF_TAIL)) || (!IS_NPC(ch) && ch->level < skill_table[gsn_tail].skill_level[ch->class])) { send_to_char("You don't have a tail to strike with like that.\n\r",ch); return; } if (arg[0] == '\0') { victim = ch->fighting; if (victim == NULL) { send_to_char("But you aren't fighting anyone!\n\r",ch); return; } } else if ((victim = get_char_room(ch,arg)) == NULL) { send_to_char("They aren't here.\n\r",ch); return; } chance = URANGE(5,chance,90); chance += (ch->level - victim->level); chance -= get_curr_stat(victim,STAT_DEX); chance += get_curr_stat(ch,STAT_DEX)/3; chance += get_curr_stat(ch,STAT_STR)/3; act("$n violently lashes out with $s tail.",ch,0,0,TO_ROOM); send_to_char("You violently lash out with your tail!\n\r",ch); if (number_percent() > chance) { damage_old(ch,victim,0,gsn_tail,DAM_BASH,TRUE); return; } dam = dice(ch->level, 3); knock = (ch->level + 15); damage_old(ch,victim,dam,gsn_tail,DAM_BASH,TRUE); if (number_percent() < knock) { act("$n is sent crashing to the ground by the force of the blow!",victim,0,0,TO_ROOM); send_to_char("The tail strike sends you crashing to the ground!\n\r",victim); WAIT_STATE(victim,( 3 * PULSE_VIOLENCE/2)); } WAIT_STATE(ch,2*PULSE_VIOLENCE); return; } void do_spellbane(CHAR_DATA *ch, char *argument) { AFFECT_DATA af; if (get_skill(ch,gsn_spellbane) < 10 || ch->level < skill_table[gsn_spellbane].skill_level[ch->class]) { send_to_char("Huh?\n\r",ch); return; } if (is_affected(ch,gsn_spellbane)) { send_to_char("You are already turning spells.\n\r",ch); return; } if (ch->mana < 50) { send_to_char("You don't have the mana.\n\r",ch); return; } if (number_percent() > get_skill(ch,gsn_spellbane)) { send_to_char("You think of your hatred of magic but can not sustain it.\n\r",ch); act("$n makes some angry gestures and goes red in the face, but nothing happens.",ch,0,0,TO_ROOM); ch->mana -= 25; check_improve(ch,gsn_spellbane,FALSE,1); return; } init_affect(&af); af.where = TO_AFFECTS; af.type = gsn_spellbane; af.level = ch->level + ch->drain_level; af.duration = (5 + (ch->drain_level + ch->level)/5); af.location = APPLY_SAVES; af.modifier = (-5 -ch->level/4); af.bitvector = 0; af.aftype = AFT_POWER; affect_to_char(ch,&af); char msg_buf[MSL]; sprintf(msg_buf,"grants a chance to reprise against magic"); af.affect_list_msg = str_dup(msg_buf); af.location = APPLY_NONE; af.modifier = 0; affect_to_char(ch,&af); act("$n fills the air with $s hatred of magic.",ch,0,0,TO_ROOM); send_to_char("You surround yourself with your hatred of magic.\n\r",ch); if (is_affected(ch,gsn_undead_drain)) { if (saves_spell(50,ch,DAM_OTHER)) { send_to_char("Your spellbane burns away the negative draining magic of the undead.\n\r",ch); affect_strip(ch,gsn_undead_drain); } } check_improve(ch,gsn_spellbane,TRUE,1); ch->mana -= 50; return; } bool spellbaned(CHAR_DATA *caster, CHAR_DATA *victim, int sn) { bool status = FALSE; int chance; if (cabal_down_new(victim,CABAL_RAGER,FALSE)) return FALSE; if (!is_affected(victim,gsn_spellbane)) { return FALSE; } if(number_percent()<26) { return FALSE; } if ( sn >= TYPE_HIT && sn < (TYPE_HIT + MAX_DAMAGE_MESSAGE) ) return FALSE; if (skill_table[sn].slot == 0) return FALSE; if (victim->position==POS_SLEEPING) return FALSE; if (caster == victim) return FALSE; if ( skill_table[sn].target == TAR_CHAR_DEFENSIVE) status = TRUE; else { chance = 50 + (victim->level - caster->level) * 2; chance -= victim->saving_throw; chance = URANGE(10,chance,50); if (IS_NPC(victim) && victim->pIndexData->vnum == MOB_VNUM_RAGER) chance += 25; if (number_percent() < chance) status = TRUE; } if (status) { act("$n's spellbane reflects $N's spell!",victim,0,caster,TO_NOTVICT); act("Your spellbane reflects $N's spell!",victim,0,caster,TO_CHAR); act("$n's spellbane reflects your spell!",victim,0,caster,TO_VICT); if (skill_table[sn].target != TAR_CHAR_OFFENSIVE) damage_old(victim,caster,dice(caster->level,2),gsn_spellbane,DAM_ENERGY,TRUE); } return status; } void do_throw(CHAR_DATA *ch,char *argument) { CHAR_DATA *victim; int dam, chance; char arg[MAX_INPUT_LENGTH]; if ( (chance = get_skill(ch,gsn_throw)) == 0 || ch->level < skill_table[gsn_throw].skill_level[ch->class]) { send_to_char("Throwing? What's that?\n\r",ch); return; } one_argument(argument,arg); if (arg[0] == '\0') victim = ch->fighting; else victim = get_char_room(ch,arg); if (victim == NULL) { send_to_char("They aren't here.\n\r",ch); return; } if (victim == ch) { send_to_char("Now that would be a bit stupid.\n\r",ch); return; } if ((victim->fighting != ch) && (ch->fighting != victim)) { send_to_char("But you aren't engaged in combat with them.\n\r",ch); return; } if (hands_full(ch)) { send_to_char("You can't throw, your hands are filled with items.\n\r",ch); return; } /* if (is_affected(ch,gsn_palm)) { send_to_char("You can't throw, you're fighting with open hand palms.\n\r",ch); return; } */ if (is_affected(victim,gsn_protective_shield)) { act("$N's throw seems to slide around you.",victim,0,ch,TO_CHAR); act("$N's throw seems to slide around $n.",victim,0,ch,TO_NOTVICT); act("Your throw seems to slide around $n.",victim,0,ch,TO_VICT); WAIT_STATE(ch,PULSE_VIOLENCE*2); return; } chance += (ch->drain_level + ch->level - victim->level - victim->drain_level); chance -= get_curr_stat(victim,STAT_DEX); chance += get_curr_stat(ch,STAT_DEX)/2; chance *= 9; chance /= 10; chance = URANGE(5, chance, 90); if (number_percent() > chance) { dam = 0; check_improve(ch,gsn_throw,FALSE,3); } else { if (check_roll(ch,victim,gsn_throw)) { check_improve(ch,gsn_throw,TRUE,2); act("$N rolls free of $n's throw.",ch,0,victim,TO_NOTVICT); act("You roll out of $n's throw attempt.",ch,0,victim,TO_VICT); act("$N rolls free of your throw attempt.",ch,0,victim,TO_CHAR); return; } if ((ch->drain_level + ch->level) <= 18) dam = 30; else if ((ch->drain_level + ch->level) <= 22) dam = 35; else if ((ch->drain_level + ch->level) <= 25) dam = 40; else if ((ch->drain_level + ch->level) <= 28) dam = 45; else if ((ch->drain_level + ch->level) <= 32) dam = 48; else if ((ch->drain_level + ch->level) <= 35) dam = 52; else if ((ch->drain_level + ch->level) <= 38) dam = 56; else if ((ch->drain_level + ch->level) <= 40) dam = 60; else if ((ch->drain_level + ch->level) <= 43) dam = 64; else if ((ch->drain_level + ch->level) <= 45) dam = 68; else if ((ch->drain_level + ch->level) <= 48) dam = 70; else dam = 72; act("$n grabs $N and throws $M to the ground with stunning force!",ch,0,victim,TO_NOTVICT); act("You grab $N and throw $M to the ground with stunning force!",ch,0,victim,TO_CHAR); act("$n grabs you and throws you to the ground with stunning force!",ch,0,victim,TO_VICT); dam += str_app[get_curr_stat(ch,STAT_STR)].todam; check_improve(ch,gsn_throw,TRUE,3); WAIT_STATE(victim,2*PULSE_VIOLENCE); } damage_old(ch,victim,dam,gsn_throw,DAM_BASH,TRUE); WAIT_STATE(ch,2*PULSE_VIOLENCE); if (ch->fighting == victim) check_ground_control(ch,victim,chance,dam); return; } void do_palm(CHAR_DATA *ch,char *argument) { AFFECT_DATA af; int chance; if ( (chance = get_skill(ch,gsn_palm)) == 0 || ch->level < skill_table[gsn_palm].skill_level[ch->class]) { send_to_char("You don't have the ability to use palm striking martial arts.\n\r",ch); return; } if (is_affected(ch,gsn_palm)) { send_to_char("You're already fighting with concentrated open hand martial arts.\n\r",ch); return; } if (ch->mana <= 60) { send_to_char("You don't have the mana.\n\r",ch); return; } if (get_eq_char(ch,WEAR_WIELD) != NULL || get_eq_char(ch,WEAR_DUAL_WIELD) != NULL) { send_to_char("You can't start using open palm striking while using weapons.\n\r",ch); return; } if (number_percent() >= chance) { send_to_char("You flex your hands but cannot grasp the concentration required.\n\r",ch); check_improve(ch,gsn_palm,FALSE,2); ch->mana -= 30; return; } act("$n slowly spreads $s hands and a look of deadly concentration clouds $s eyes.",ch,0,0,TO_ROOM); send_to_char("You feel your mind relax and pass power to your opened hands.\n\r",ch); init_affect(&af); af.where = TO_AFFECTS; af.type = gsn_palm; af.location = 0; af.modifier = 0; af.duration = ((ch->drain_level + ch->level)/3); af.level = ch->drain_level + ch->level; af.bitvector = 0; af.aftype = AFT_SKILL; char msg_buf[MSL]; sprintf(msg_buf,"utilizing open palm martial arts"); af.affect_list_msg = str_dup(msg_buf); affect_to_char(ch,&af); check_improve(ch,gsn_palm,TRUE,2); return; } void do_nerve(CHAR_DATA *ch,char *argument) { char buf[MAX_STRING_LENGTH]; CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; AFFECT_DATA af; int chance; if ( (chance = get_skill(ch,gsn_nerve)) == 0 || ch->level < skill_table[gsn_nerve].skill_level[ch->class]) { send_to_char("You don't know how to use nerve pressure tactics.\n\r",ch); return; } one_argument(argument,arg); if (arg[0] == '\0') victim = ch->fighting; else victim = get_char_room(ch,arg); if (victim == NULL) { send_to_char("Attempt to put pressure on who's nerves?\n\r",ch); return; } if (victim == ch) { send_to_char("You can't do that.\n\r",ch); return; } if (is_safe(ch,victim)) return; if (is_affected(victim,gsn_nerve)) { send_to_char("They have already been weakened using nerve pressure.\n\r",ch); return; } chance += (ch->drain_level + ch->level - victim->level - victim->drain_level)*3; chance -= get_curr_stat(victim,STAT_DEX)/3; chance += get_curr_stat(ch,STAT_DEX)/2; chance -= get_curr_stat(victim,STAT_CON)/3; if (number_percent() > chance) { act("$n grasps $N's arm but fails to apply the right pressure point.",ch,0,victim,TO_NOTVICT); act("You grasp $N's arm but fail to apply the right pressure point.",ch,0,victim,TO_CHAR); act("$n grasps your arm but fails to apply the right pressure point.",ch,0,victim,TO_VICT); check_improve(ch,gsn_nerve,FALSE,3); WAIT_STATE(ch,PULSE_VIOLENCE); return; } else { act("$n grasps $N's arm and weakens $m with pressure points.",ch,0,victim,TO_NOTVICT); act("You grasp $N's arm and weaken $m with pressure points.",ch,0,victim,TO_CHAR); act("$n grasps your arm and weakens you with pressure point.",ch,0,victim,TO_VICT); check_improve(ch,gsn_nerve,TRUE,3); init_affect(&af); af.where = TO_AFFECTS; af.type = gsn_nerve; af.location = APPLY_STR; af.duration = ((ch->drain_level + ch->level)/5); af.bitvector = 0; af.modifier = -3; af.aftype = AFT_SKILL; af.level = ch->drain_level + ch->level; affect_to_char(victim,&af); WAIT_STATE(ch,PULSE_VIOLENCE); } if (!IS_NPC(ch) && !IS_NPC(victim) && (ch->fighting == NULL || victim->fighting == NULL) ) { sprintf(buf,"Help, %s is attacking me!",PERS(ch,victim)); do_myell(victim,buf); } if (victim->fighting == NULL) { multi_hit(victim,ch,TYPE_UNDEFINED); } return; } void check_follow_through(CHAR_DATA *ch, CHAR_DATA *victim, int dam) { int chance; chance = get_skill(ch,gsn_follow_through); if (ch->level <skill_table[gsn_follow_through].skill_level[ch->class]) return; chance /= 2; chance -= number_range(0,15); if (IS_AFFECTED(ch, AFF_HASTE)) chance += 15; if (chance <= 0) return; if (number_percent() < chance) { act("$n's leg sweeps around and strikes with a follow through!",ch,0,0,TO_ROOM); act("Your leg sweeps around to land a follow through kick!",ch,0,0,TO_CHAR); damage_old(ch,victim, dam, gsn_follow_through, DAM_BASH,TRUE); check_improve(ch,gsn_follow_through,TRUE,2); } else check_improve(ch,gsn_follow_through,FALSE,3); return; } void do_blindness_dust(CHAR_DATA *ch,char *argument) { CHAR_DATA *vch; CHAR_DATA *vch_next; AFFECT_DATA af; int chance; bool fighting = FALSE; char buf[MAX_STRING_LENGTH]; if ( (chance = get_skill(ch,gsn_blindness_dust)) == 0 || ch->level < skill_table[gsn_blindness_dust].skill_level[ch->class]) { send_to_char("You don't know how to make blindness dust to throw.\n\r",ch); return; } if (ch->mana < 18) { send_to_char("You don't have the mana.\n\r",ch); return; } if (number_percent() > chance) { act("$n hurls some dust into the air but it is blown away.",ch,0,0,TO_ROOM); send_to_char("You throw out some dust but it is blown away.\n\r",ch); ch->mana -= 9; check_improve(ch,gsn_blindness_dust,FALSE,2); WAIT_STATE(ch,12); return; } act("$n hurls a handful of dust into the room!",ch,0,0,TO_ROOM); send_to_char("You throw a handful of blindness dust into the room!\n\r",ch); check_improve(ch,gsn_blindness_dust,TRUE,2); if (ch->fighting != NULL) fighting = TRUE; init_affect(&af); af.where = TO_AFFECTS; af.type = gsn_blindness_dust; af.level = ch->drain_level + ch->level; af.duration = 1; af.bitvector = AFF_BLIND; af.location = APPLY_HIT; af.modifier = -3; af.aftype = AFT_SKILL; ch->mana -= 18; WAIT_STATE(ch,12); for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (is_safe(ch,vch)) continue; if (is_same_group(ch,vch)) continue; if (!IS_AFFECTED(vch,AFF_BLIND) && !saves_spell(ch->drain_level + ch->level,vch,DAM_OTHER)) { act("$n appears blinded.",vch,0,0,TO_ROOM); send_to_char("You get dust in your eyes.\n\r",vch); affect_to_char(vch,&af); } if (!IS_NPC(vch) && !IS_NPC(ch) && (vch->fighting == NULL || (!fighting))) { sprintf(buf,"Help! %s just threw dust in my eyes!",PERS(ch,vch)); do_myell(vch,buf); } if (vch->fighting == NULL) multi_hit(vch,ch,TYPE_UNDEFINED); } return; } void do_poison_dust(CHAR_DATA *ch,char *argument) { CHAR_DATA *vch; CHAR_DATA *vch_next; AFFECT_DATA af; int chance; bool fighting = FALSE; char buf[MAX_STRING_LENGTH]; if ( (chance = get_skill(ch,gsn_poison_dust)) == 0 || ch->level < skill_table[gsn_poison_dust].skill_level[ch->class]) { send_to_char("You don't know how to make poison dust to throw.\n\r",ch); return; } if (ch->mana < 20) { send_to_char("You don't have the mana.\n\r",ch); return; } if (number_percent() > chance) { act("$n hurls some dust into the air but it is blown away.",ch,0,0,TO_ROOM); send_to_char("You throw out some dust but it is blown away.\n\r",ch); ch->mana -= 10; WAIT_STATE(ch,12); check_improve(ch,gsn_poison_dust,FALSE,2); return; } act("$n hurls a handful of dust into the room!",ch,0,0,TO_ROOM); send_to_char("You throw a handful of poison dust into the room!\n\r",ch); check_improve(ch,gsn_poison_dust,TRUE,2); if (ch->fighting != NULL) fighting = TRUE; init_affect(&af); af.where = TO_AFFECTS; af.type = gsn_poison_dust; af.level = ch->drain_level + ch->level; af.duration = (ch->drain_level + ch->level)/5; af.bitvector = AFF_POISON; af.location = APPLY_STR; af.modifier = -3; af.aftype = AFT_SKILL; ch->mana -= 20; WAIT_STATE(ch,12); for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (is_safe(ch,vch)) continue; if (is_same_group(ch,vch)) continue; if (!IS_AFFECTED(vch,AFF_POISON) && !saves_spell(ch->drain_level + ch->level,vch,DAM_OTHER)) { act("$n turns green and looks sick.",vch,0,0,TO_ROOM); send_to_char("You suddenly feel very sick.\n\r",vch); affect_to_char(vch,&af); } if (!IS_NPC(vch) && !IS_NPC(ch) && (vch->fighting == NULL || (!fighting))) { sprintf(buf,"Help! %s just threw dust in my eyes!",PERS(ch,vch)); do_myell(vch,buf); } if (vch->fighting == NULL) multi_hit(vch,ch,TYPE_UNDEFINED); } return; } bool check_roll(CHAR_DATA *ch, CHAR_DATA *victim, int dt) { int chance; if ( (chance = get_skill(victim,gsn_roll)) == 0 || victim->level < skill_table[gsn_roll].skill_level[victim->class]) return FALSE; chance *= 4; chance /= 5; chance += get_curr_stat(victim,STAT_DEX); chance -= victim->carry_weight/100; if (number_percent() > chance) { check_improve(victim,gsn_roll,FALSE,2); return FALSE; } check_improve(victim,gsn_roll,TRUE,2); return TRUE; } void do_warcry(CHAR_DATA *ch,char *argument) { AFFECT_DATA af; int chance; if ( (chance = get_skill(ch,gsn_warcry)) == 0 || ch->level < skill_table[gsn_warcry].skill_level[ch->class]) { send_to_char("You don't know how to warcry properly.\n\r",ch); return; } if (is_affected(ch,gsn_warcry)) { send_to_char("You are already affected by a warcry.\n\r",ch); return; } if (ch->mana < 20) { send_to_char("You don't have the mana.\n\r",ch); return; } if (number_percent() > chance) { act("$n makes some soft grunting noises.",ch,0,0,TO_ROOM); send_to_char("You make soft grunting sounds but nothing happens.\n\r",ch); check_improve(ch,gsn_warcry,FALSE,2); ch->mana -= 10; WAIT_STATE(ch,12); return; } act("$n lets out a blood freezing warcry!",ch,0,0,TO_ROOM); send_to_char("You let out a fierce warcry!\n\r",ch); check_improve(ch,gsn_warcry,TRUE,2); init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_SKILL; af.type = gsn_warcry; af.modifier = (ch->drain_level + ch->level)/7; af.location = APPLY_HITROLL; af.duration = ch->drain_level + ch->level; af.bitvector = 0; af.level = ch->drain_level + ch->level; affect_to_char(ch,&af); af.location = APPLY_SAVES; af.modifier = -(ch->level/10); affect_to_char(ch,&af); ch->mana -= 20; WAIT_STATE(ch,12); return; } void check_downstrike(CHAR_DATA *ch,CHAR_DATA *victim) { OBJ_DATA *wield; int dam; int chance; chance = get_skill(ch,gsn_downstrike); if (chance <= 10) return; if (ch->level < skill_table[gsn_downstrike].skill_level[ch->class]) return; chance /= 4.5; chance += (ch->drain_level + ch->level - victim->level - victim->drain_level); chance -= get_curr_stat(victim,STAT_DEX)/3; chance += get_curr_stat(ch,STAT_DEX)/3; chance = URANGE(2, chance, 35); if (number_percent() > chance) { check_improve(ch,gsn_downstrike,FALSE,1); return; } wield = get_eq_char(ch,WEAR_WIELD); if (wield == NULL || wield->value[0]!=2) wield = get_eq_char(ch,WEAR_DUAL_WIELD); if (wield == NULL || wield->value[0]!=2) return; dam = dice(wield->value[1],wield->value[2]); dam += ch->damroll; act("You strike at $N with a downward thrust of your dagger!",ch,0,victim,TO_CHAR); act("$n strikes at you with a downward thrust of $s dagger!",ch,0,victim,TO_VICT); act("$n strikes at $N with a downward thrust of $s dagger!",ch,0,victim,TO_NOTVICT); check_improve(ch,gsn_downstrike,TRUE,1); damage_old(ch,victim,dam,gsn_downstrike,attack_table[wield->value[3]].damage, TRUE); return; } void do_enlist(CHAR_DATA *ch,char *argument) { CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; int level; char buf[MAX_STRING_LENGTH]; AFFECT_DATA af; int chance; CHAR_DATA *check; chance = get_skill(ch,gsn_enlist); if (chance <= 10 || ch->level < skill_table[gsn_enlist].skill_level[ch->class]) { send_to_char("You do not have the skills required to enlist mercenary aid.\n\r",ch); return; } one_argument(argument,arg); if (is_affected(ch,gsn_enlist)) { send_to_char("You haven't built up the nerve to recruit anyone else yet.\n\r",ch); return; } if (arg[0] == '\0') { send_to_char("Who do you wish to enlist as a follower?\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("You can't recruit yourself.\n\r",ch); return; } if (!IS_NPC(victim)) { send_to_char("Why not just ask them to join you?\n\r",ch); return; } for (check = char_list; check != NULL; check = check->next) { if (is_affected(check,gsn_enlist) && check->master == ch) { send_to_char("You already have a devoted recruit following you.\n\r",ch); return; } } if (!IS_SET(victim->act,ACT_WARRIOR)) { send_to_char("You may only enlist the aid of those trained as warriors.\n\r",ch); return; } level = ch->drain_level + ch->level; if ((IS_GOOD(ch) && IS_EVIL(victim)) || (IS_EVIL(ch) && IS_GOOD(victim))) level = 0; if (IS_NEUTRAL(victim) || IS_NEUTRAL(ch)) level -= 4; if (IS_AFFECTED(victim,AFF_CHARM)) level = 0; if ( (victim->level + 8) > level) level = 0; if (saves_spell(level,victim,DAM_OTHER) || level == 0) { if (number_percent() < 50) do_say(victim,"I don't follow scum such as you!"); else do_say(victim,"You couldn't recruit a mangy dog to your company!"); sprintf(buf,"Help! I'm being attacked by %s!",PERS(victim,ch)); do_myell(ch,buf); multi_hit(victim,ch,TYPE_UNDEFINED); return; } victim->leader = ch; victim->master = ch; init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_SKILL; af.type = gsn_enlist; af.modifier = 0; af.level = ch->drain_level + ch->level; af.bitvector = AFF_CHARM; af.duration = ch->drain_level + ch->level; af.location = 0; affect_to_char(victim,&af); af.bitvector = 0; af.duration = 15; af.affect_list_msg = str_dup("unable to enlist aid"); affect_to_char(ch,&af); act("$N salutes you and prepares to follow into combat.",ch,0,victim,TO_CHAR); act("$N salutes $n and falls into line with $s.",ch,0,victim,TO_NOTVICT); return; } void do_tame(CHAR_DATA *ch, char *argument) { CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; int chance; chance = get_skill(ch,gsn_tame); one_argument(argument,arg); if (arg[0] == '\0') victim = ch->fighting; else victim = get_char_room(ch,arg); if (victim == NULL) { send_to_char("They aren't here to tame though.\n\r",ch); return; } if (!IS_NPC(victim)) { send_to_char("Why not just talk to them about your problems?\n\r",ch); return; } else if (!IS_SET(victim->act,ACT_AGGRESSIVE) && !IS_SET(victim->off_flags,SPAM_MURDER)) { send_to_char("They are as tame as they can be.\n\r",ch); return; } chance += (ch->drain_level + ch->level - victim->level - victim->drain_level)*3; if (chance > 90) chance = 90; WAIT_STATE(ch,12); if (number_percent() > chance) { act("$n tries to calm down $N but fails.",ch,0,victim,TO_NOTVICT); act("$n tries to calm you down but fails.",ch,0,victim,TO_VICT); act("You try to calm $N down but fail.",ch,0,victim,TO_CHAR); check_improve(ch,gsn_tame,FALSE,2); return; } act("$n calms $N down.",ch,0,victim,TO_NOTVICT); act("You calm $N down.",ch,0,victim,TO_CHAR); act("$n calms you down.",ch,0,victim,TO_VICT); check_improve(ch,gsn_tame,TRUE,2); stop_fighting(victim,TRUE); victim->last_fought = NULL; REMOVE_BIT(victim->act,ACT_AGGRESSIVE); REMOVE_BIT(victim->off_flags,SPAM_MURDER); return; } void do_find_water(CHAR_DATA *ch,char *argument) { OBJ_DATA *spring; int chance; chance = get_skill(ch,gsn_find_water); if (chance > 95) chance = 95; if (chance == 0 || ch->level < skill_table[gsn_find_water].skill_level[ch->class]) { send_to_char("You poke the ground with a stick but find no water that way.\n\r",ch); return; } if (ch->mana < 15) { send_to_char("You don't have the mana.\n\r",ch); return; } if (ch->in_room->sector_type == SECT_WATER_SWIM || ch->in_room->sector_type == SECT_WATER_NOSWIM) { send_to_char("Water water all around but not a drop to drink..\n\r",ch); return; } if (number_percent() > chance) { act("$n pokes the ground with a stick then scratches $s head.",ch,0,0,TO_ROOM); send_to_char("You poke about on the ground but fail to find any water.\n\r",ch); check_improve(ch,gsn_find_water,FALSE,1); ch->mana -= 7; WAIT_STATE(ch,18); return; } act("$n pokes at the ground and digs up a spring of natural water!",ch,0,0,TO_ROOM); send_to_char("You poke about for a bit and eventually dig up a spring of water.\n\r",ch); WAIT_STATE(ch,18); ch->mana -= 15; spring = create_object(get_obj_index(OBJ_VNUM_SPRING),0); check_improve(ch,gsn_find_water,TRUE,1); obj_to_room(spring,ch->in_room); return; } void do_track(CHAR_DATA *ch,char *argument) { CHAR_DATA *victim; int chance, dir; char arg[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; dir = 0; chance = get_skill(ch,gsn_track); if (chance == 0 || ch->level < skill_table[gsn_track].skill_level[ch->class]) { send_to_char("You peer intently at the ground but discern nothing.\n\r",ch); return; } one_argument(argument,arg); victim = get_char_world(ch,arg); chance *= 2; chance /= 3; if (ch->in_room->sector_type == SECT_INSIDE) chance -= 40; else if (ch->in_room->sector_type == SECT_CITY) chance -= 35; else if (ch->in_room->sector_type >= SECT_WATER_SWIM && ch->in_room->sector_type < SECT_DESERT) chance = 0; else if (ch->in_room->sector_type == SECT_FOREST) chance += 25; if (victim != NULL && !IS_NPC(victim)) dir = victim->pcdata->track_dir[ch->in_room->vnum]; if (number_percent() > chance || victim == NULL || !IS_NPC(victim) || dir == 0) { act("$n peers intently at the ground but doesn't seem to find anything.",ch,0,0,TO_ROOM); send_to_char("You peer intently at the ground but uncover nothing new.\n\r",ch); check_improve(ch,gsn_track,FALSE,2); WAIT_STATE(ch,18); return; } act("$n peers at the ground and seems more enlightened.",ch,0,0,TO_ROOM); sprintf(buf,"You peer at the surroundings and find that %s left %s last time they were here.\n\r", victim->name, (dir == 1) ? "north" : (dir == 2) ? "east" : (dir == 3) ? "south" : (dir == 4) ? "west" : (dir == 5) ? "up" : "down"); send_to_char(buf,ch); WAIT_STATE(ch,18); check_improve(ch,gsn_track,TRUE,2); return; } void do_shield_cleave(CHAR_DATA *ch,char *argument) { char buf[MAX_STRING_LENGTH]; char arg[MAX_INPUT_LENGTH]; int chance; OBJ_DATA *weapon; OBJ_DATA *shield; bool using_primary = TRUE; CHAR_DATA *victim; one_argument(argument,arg); if (arg[0] == '\0') victim = ch->fighting; else victim = get_char_room(ch,arg); chance = get_skill(ch,gsn_shield_cleave); if (chance == 0 || ch->level < skill_table[gsn_shield_cleave].skill_level[ch->class]) { send_to_char("You don't know the methods to cleave a shield in two.\n\r",ch); return; } weapon = get_eq_char(ch,WEAR_WIELD); if (weapon == NULL) { weapon = get_eq_char(ch,WEAR_DUAL_WIELD); using_primary = FALSE; } if (weapon == NULL || (weapon->value[0] != WEAPON_SWORD && weapon->value[0] != WEAPON_AXE) ) { send_to_char("You must be wielding an axe or sword to shield cleave.\n\r",ch); return; } if (victim == NULL) { send_to_char("But they aren't here.\n\r",ch); return; } if (victim == ch) { send_to_char("That isn't possible.\n\r",ch); return; } if ((shield = get_eq_char(victim,WEAR_SHIELD)) == NULL) { send_to_char("But they aren't using a shield.\n\r",ch); return; } chance *= 9; chance /= 10; chance += (ch->level - victim->level)*3; chance -= shield->level; if(IS_AFFECTED(ch,AFF_BLIND)) chance -= 50; if (!using_primary) chance -= 15; if (!IS_NPC(victim) && ch->fighting != victim) { sprintf(buf,"Help! %s is trying to cleave my shield!",PERS(ch,victim)); do_myell(victim,buf); } if (is_affected(victim,gsn_shield_of_purity)) { act("$n attempts to strike a mighty blow to $N's shield!",ch,0,victim,TO_NOTVICT); act("$n attempts to strike a mighty blow to your shield!",ch,0,victim,TO_VICT); act("You attempt to strike a mighty blow to $N's shield!",ch,0,victim,TO_CHAR); act("$N skillfully deflects your shield-cleave attempt and counters with a powerful strike!",ch,0,victim,TO_CHAR); act("You gracefully deflect $n's shield-cleave attempt and counter with a powerful strike!",ch,0,victim,TO_VICT); act("$N skillfully deflects $n's shield-cleave attempt and counters with a powerful strike!",ch,0,victim,TO_NOTVICT); one_hit_new(victim,ch,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,225,"strike of purity"); check_improve(ch,gsn_shield_cleave,FALSE,1); WAIT_STATE(ch,12); return; } if (is_affected(victim,gsn_shield_of_justice)) { act("$n attempts to strike a mighty blow to $N's shield!",ch,0,victim,TO_NOTVICT); act("$n attempts to strike a mighty blow to your shield!",ch,0,victim,TO_VICT); act("You attempt to strike a mighty blow to $N's shield!",ch,0,victim,TO_CHAR); act("$N meets your shield-cleave attempt with incredible force using $S divine shield, reflecting your attack!",ch,0,victim,TO_CHAR); act("$N meets $n's shield-cleave attempt with incredible force using $S divine shield, reflecting $S attack!",ch,0,victim,TO_NOTVICT); act("You meet $n's shield-cleave with incredible force using your divine shield, reflecting $S attack!",ch,0,victim,TO_VICT); one_hit_new(victim,ch,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,150,"reflected attack"); check_improve(ch,gsn_shield_cleave,FALSE,1); WAIT_STATE(ch,12); return; } if (is_affected(victim,gsn_shield_of_redemption)) { act("$N positions $Mself to minimize the effectiveness of your shield-cleave.",ch,0,victim,TO_CHAR); act("$N positions $Mself to minimize the effectiveness of $n's shield-cleave.",ch,0,victim,TO_NOTVICT); act("You position yourself to minimize the effectiveness of $n's shield-cleave.",ch,0,victim,TO_VICT); chance -= 25; } if (is_affected(victim,gsn_shield_of_truth) && victim->pcdata->learned[skill_lookup("shieldbash")] > 75) { act("Striking preemptively, $N catches you offguard during your shield-cleave attempt and drives at you with $S shield!",ch,0,victim,TO_CHAR); act("$N's slams into you with his shield and sends you flying!",ch,0,victim,TO_CHAR); act("Striking preemptively, $N catches $n offguard during $s shield-cleave attempt and drives at $n with $S shield!",ch,0,victim,TO_NOTVICT); act("$N's slams into $n with his shield and sends $M flying!",ch,0,victim,TO_NOTVICT); act("Striking preemptively, you catch $n offguard during $s shield-cleave attempt and drive at $M with your shield!",ch,0,victim,TO_VICT); act("You slam into $n with your shield and send $M flying!",ch,0,victim,TO_VICT); WAIT_STATE(victim,skill_table[gsn_shieldbash].beats+PULSE_VIOLENCE); ch->position = POS_RESTING; check_improve(victim,gsn_shieldbash,TRUE,1); act("Your god senses the proximity of $n through your shield!",ch,0,victim,TO_VICT); int sapHealth = GET_DAMROLL(victim) * .75; act("The shield's energy reaches out and saps $n's health, using it to fuel your own!",ch,0,victim,TO_VICT); act("The energy surrounding $N's divine shield reaches out and saps your health!",ch,0,victim,TO_CHAR); act("The energy surrounding $N's divine shield reaches out and saps $n's health!",ch,0,victim,TO_NOTVICT); damage_new(victim,ch,sapHealth,TYPE_UNDEFINED,DAM_HOLY,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,100,"strike of truth"); act("$N absorbs your lost health!",ch,0,victim,TO_CHAR); victim->hit += sapHealth; if (victim->hit > victim->max_hit) victim->hit = victim->max_hit; check_improve(ch,gsn_shield_cleave,FALSE,1); return; } if (number_percent() > chance) { act("$n makes a mighty blow at $N's shield but fails to cleave it.",ch,0,victim,TO_NOTVICT); act("$n lands a mighty blow to your shield but fails to cleave it.",ch,0,victim,TO_VICT); act("You strike a mighty blow to $N's shield but fail to cleave it.",ch,0,victim,TO_CHAR); check_improve(ch,gsn_shield_cleave,FALSE,1); WAIT_STATE(ch,12); multi_hit(victim,ch,-1); return; } act("$n's mighty blow cleaves $N's shield in half!",ch,0,victim,TO_NOTVICT); act("Your mighty blow cleaves $N's shield in half!",ch,0,victim,TO_CHAR); act("$n strikes your shield with powerful force, cleaving it in two!",ch,0,victim,TO_VICT); if (is_affected(victim,gsn_shield_of_redemption)) { act("$N's divine shield shatters, consuming you in a torrent of holy energy!",ch,0,victim,TO_CHAR); act("Your divine shield shatters, consuming $n in a torrent of holy energy!",ch,0,victim,TO_VICT); act("$N's divine shield shatters, consuming $n in a torrent of holy energy!",ch,0,victim,TO_NOTVICT);damage_new(victim,ch,victim->level*2 + number_range(1,20),TYPE_UNDEFINED,DAM_HOLY,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"holy fire"); damage_new(victim,ch,victim->level*2 + number_range(1,20),TYPE_UNDEFINED,DAM_HOLY,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"holy fire"); damage_new(victim,ch,victim->level*2 + number_range(1,20),TYPE_UNDEFINED,DAM_HOLY,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"holy fire"); damage_new(victim,ch,victim->level*2 + number_range(1,20),TYPE_UNDEFINED,DAM_HOLY,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"holy fire"); damage_new(victim,ch,victim->level*2 + number_range(1,20),TYPE_UNDEFINED,DAM_HOLY,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"holy fire"); } extract_obj(shield); WAIT_STATE(ch,12); check_improve(ch,gsn_shield_cleave,TRUE,1); multi_hit(victim,ch,-1); return; } /* more race skills...Ceran */ void do_breath_fire(CHAR_DATA *ch,char *argument) { AFFECT_DATA af; CHAR_DATA *victim; OBJ_DATA *obj_lose; OBJ_DATA *obj_next; char arg[MAX_INPUT_LENGTH]; int dam, chance; int hpch, level; level = ch->drain_level + ch->level; chance = get_skill(ch,gsn_breath_fire); if (chance == 0 || ch->level < skill_table[gsn_breath_fire].skill_level[ch->class]) { send_to_char("You aren't able to breath fire.\n\r",ch); return; } if (is_affected(ch,gsn_breath_fire)) { send_to_char("You haven't yet regained the heat in your body to create more flames.\n\r",ch); return; } one_argument(argument,arg); if (arg[0] == '\0') victim = ch->fighting; else victim = get_char_room(ch,arg); if (victim == NULL) { send_to_char("They aren't here.\n\r",ch); return; } if (ch->mana < 20) { send_to_char("You don't have the mana.\n\r",ch); return; } if (number_percent() > chance) { send_to_char("You try to breath forth fire but only smokes comes out.\n\r",ch); act("$n opens $s mouth but only a thick plume of black smoke comes forth.",ch,0,0,TO_ROOM); ch->mana -= 10; check_improve(ch,gsn_breath_fire,FALSE,1); return; } init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_SKILL; af.type = gsn_breath_fire; af.location = 0; af.modifier = 0; af.duration = 4; af.affect_list_msg = str_dup("unable to breath fire"); af.bitvector = 0; af.level = ch->drain_level + ch->level; affect_to_char(ch,&af); act("$n breaths forth a cone of searing flames!",ch,0,0,TO_ROOM); send_to_char("You breath forth a cone of searing flames!\n\r",ch); if ( number_percent( ) < level && !saves_spell( level - 2, victim,DAM_FIRE ) ) { for ( obj_lose = victim->carrying; obj_lose != NULL; obj_lose = obj_next ) { char *msg; obj_next = obj_lose->next_content; if ( number_bits( 2 ) != 0 ) continue; switch ( obj_lose->item_type ) { default: continue; case ITEM_CONTAINER: msg = "$p ignites and burns!"; break; case ITEM_POTION: msg = "$p bubbles and boils!"; break; case ITEM_SCROLL: msg = "$p crackles and burns!"; break; case ITEM_STAFF: msg = "$p smokes and chars!"; break; case ITEM_WAND: msg = "$p sparks and sputters!"; break; case ITEM_FOOD: msg = "$p blackens and crisps!"; break; case ITEM_PILL: msg = "$p melts and drips!"; break; } act( msg, victim, obj_lose, NULL, TO_CHAR ); extract_obj( obj_lose ); } } hpch = UMAX( 10, ch->hit ); dam = number_range( (hpch/7) + 1, hpch/3 ); if ( saves_spell( level - 2, victim, DAM_FIRE ) ) dam /= 2; damage_old( ch, victim, dam, gsn_breath_fire, DAM_FIRE,TRUE); check_improve(ch,gsn_breath_fire,TRUE,1); return; } void do_rear_kick(CHAR_DATA *ch,char *argument) { CHAR_DATA *victim; int dam; /* AFFECT_DATA af; */ if (str_cmp(race_table[ch->race].name,"centaur")) { send_to_char("You don't have a centaur's rear legs to kick like that.\n\r",ch); return; } if ( !IS_NPC(ch) && ch->level < skill_table[gsn_rear_kick].skill_level[ch->class] ) { send_to_char("You do not have the ability to rear kick yet.\n\r",ch ); return; } if (IS_NPC(ch) && !IS_SET(ch->off_flags,OFF_KICK)) return; if ( ( victim = ch->fighting ) == NULL ) { send_to_char( "You are not fighting anyone.\n\r", ch ); return; } WAIT_STATE( ch, 24 ); act("$n whips about and kicks out with $s hind legs!",ch,0,0,TO_ROOM); act("You whip about and kick out with your hind legs!",ch,0,0,TO_CHAR); if ( IS_NPC(ch) || number_percent( ) < ch->pcdata->learned[gsn_rear_kick] ) { dam = number_range(ch->level/2,ch->level); dam += get_curr_stat(ch,STAT_STR); dam += number_range(1,ch->drain_level + ch->level); dam += number_range((ch->drain_level + ch->level)/4, (ch->drain_level + ch->level)/2); if (dam < 1) dam = 1; if (dam > 140) dam = 140; damage_old( ch, victim, dam, gsn_rear_kick,DAM_BASH, TRUE ); check_improve(ch,gsn_rear_kick,TRUE,1); } else { damage_old( ch, victim, 0, gsn_rear_kick,DAM_BASH,TRUE ); check_improve(ch,gsn_rear_kick,FALSE,1); } return; } void do_strap(CHAR_DATA *victim,OBJ_DATA *strap) { CHAR_DATA *vch; CHAR_DATA *vch_next; if (strap->pIndexData->vnum == 5750) { act("\x01B[1;31m$n's $p explodes in a blinding flash of light!\x01B[0;37m",victim,strap,0,TO_ROOM); act("\x01B[1;31mYour $p explodes in a blinding flash of light!\x01B[0;37m",victim,strap,0,TO_CHAR); for (vch = victim->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (vch == victim) { continue; } if (IS_NPC(vch)) { continue; } if (vch->level > LEVEL_HERO) { continue; } act("$n detonates in an eruption of blood and fluids!",vch,strap,0,TO_ROOM); act("You detonate in an eruption of blood and fluids!",vch,strap,0,TO_CHAR); act( "$n is DEAD!!", vch, 0, 0, TO_ROOM ); send_to_char( "You have been KILLED!!\n\r\n\r", vch ); raw_kill(victim,vch); } unequip_char(victim,strap); obj_from_char(strap); extract_obj(strap); } if (strap->pIndexData->vnum == 5751) { unequip_char(victim,strap); obj_from_char(strap); extract_obj(strap); } return; } /* dying of old age */ void age_death(CHAR_DATA *ch) { ROOM_INDEX_DATA *pRoomIndex; char *cname; AFFECT_DATA af; if (IS_NPC(ch)) return; pRoomIndex = get_room_index(1212); if (pRoomIndex == NULL) return; /* For now default to the players recall, or midgaard */ pRoomIndex = get_room_index(hometown_table[ch->hometown].recall); if (pRoomIndex == NULL) pRoomIndex = get_room_index(ROOM_VNUM_TEMPLE); stop_fighting(ch,TRUE); make_corpse(ch,ch); char_from_room(ch); char_to_room(ch,pRoomIndex); do_look(ch,"auto"); send_to_char("You have died and become a permanent ghost, awaiting your final departure.\n\r",ch); cname = str_dup(ch->original_name); if( ((ch->played + (current_time - ch->logon)) / 3600) >= 15) delete_char(cname,TRUE); // >= 15 hours. Make name unusable. else delete_char(cname,FALSE); init_affect(&af); af.aftype = AFT_INVIS; af.type = skill_lookup("age death"); af.duration = -1; af.strippable = FALSE; affect_to_char(ch,&af); return; } void do_forage(CHAR_DATA *ch,char *argument) { OBJ_DATA *berry_1; OBJ_DATA *berry_2; int chance, found; if ( (chance = get_skill(ch,gsn_forage)) == 0 || (ch->level < skill_table[gsn_forage].skill_level[ch->class]) ) { send_to_char("You aren't able to decide on which plants are edible.\n\r",ch); return; } if (ch->in_room->sector_type != SECT_FOREST) { send_to_char("You aren't in a suitable forest region where you can apply your plant lore.\n\r",ch); return; } if (chance > 90) chance = 90; if (number_percent() > chance) { act("$n messes about in the undergrowth but comes up looking perplexed.",ch,0,0,TO_ROOM); send_to_char("You search around but find nothing you can recognise as edible.\n\r",ch); check_improve(ch,gsn_forage,FALSE,2); WAIT_STATE(ch,12); return; } act("$n messes about in the nearby bushes and comes out with some berries.",ch,0,0,TO_ROOM); send_to_char("You search around and find some edible berries in the bushes.\n\r",ch); check_improve(ch,gsn_forage,TRUE,2); found = number_range(1,3); berry_1 = create_object(get_obj_index(OBJ_VNUM_BERRY),1); if (berry_1 == NULL) return; obj_to_char(berry_1,ch); if (found >= 2) { berry_2 = create_object(get_obj_index(OBJ_VNUM_BERRY),1); obj_to_char(berry_2,ch); } /* if (found >= 3) { berry_3 = create_object(get_obj_index(OBJ_VNUM_BERRY),1); obj_to_char(berry_3,ch); } if (found >= 4) { berry_4 = create_object(get_obj_index(OBJ_VNUM_BERRY),1); obj_to_char(berry_4,ch); } */ return; } void do_defend(CHAR_DATA *ch,char *argument) { CHAR_DATA *victim; char arg[MAX_STRING_LENGTH]; char buf[MAX_STRING_LENGTH]; one_argument(argument,arg); if ( (get_skill(ch,gsn_defend) == 0) || (ch->level < skill_table[gsn_defend].skill_level[ch->class]) ) { send_to_char("You aren't able to defend other people.\n\r",ch); return; } if (arg[0] == '\0') { if (ch->defending == NULL) sprintf(buf,"You aren't defending anyone right now.\n\r"); else sprintf(buf,"You are defending %s.\n\r",ch->defending->name); send_to_char(buf,ch); return; } victim = get_char_room(ch,arg); if (victim == NULL) { send_to_char("They aren't here.\n\r",ch); return; } if (victim == ch) { send_to_char("You no longer defend anyone.\n\r",ch); ch->defending = NULL; return; } if (IS_NPC(victim)) { send_to_char("They don't need to be defended.\n\r",ch); return; } if (ch->defending != NULL) { act("You stop defending $N.",ch,0,ch->defending,TO_CHAR); act("$n stops defending you.",ch,0,ch->defending,TO_VICT); } sprintf(buf,"You start defending %s.",victim->name); act(buf,ch,0,victim,TO_CHAR); ch->defending = victim; act("$n is now defending you.",ch,0,victim,TO_VICT); return; } /* New flee...this allows 'flee <direction>' for the thief skill escape. -Ceran */ void do_flee( CHAR_DATA *ch, char *argument ) { ROOM_INDEX_DATA *was_in; ROOM_INDEX_DATA *now_in; CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; int attempt, chance, dir; if ( ( victim = ch->fighting ) == NULL ) { if ( ch->position == POS_FIGHTING ) ch->position = POS_STANDING; send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } if (IS_ROOM_AFFECTED(ch->in_room,AFF_ROOM_WALL_THORNS)) { if (check_wall_thorns(ch)) return; } if (is_affected(ch,gsn_aristaeia)) { send_to_char("You are too filled with righteous wrath to flee!\n\r",ch); check_parting_blow(ch,victim); return; } if (is_affected(ch,gsn_shadowstrike) && number_percent()<20) { act("$n tries to flee but the shadowy arms stop his movements.",ch,0,0,TO_ROOM); act("You try to flee but the shadow arms block you.",ch,0,0,TO_CHAR); WAIT_STATE(ch,2*PULSE_VIOLENCE); return; } if (is_affected(ch,gsn_shackles) && number_percent()<20) { act("$n tries to flee but trips over his shackles.",ch,0,0,TO_ROOM); act("You try to flee but trip over your shackles.",ch,0,0,TO_CHAR); WAIT_STATE(ch,PULSE_VIOLENCE); check_cheap_shot(ch->fighting,ch); return; } if (is_affected(ch,gsn_entwine)) { act("$n tries to flee with $s legs entwined, but trips.",ch,NULL,NULL,TO_ROOM); act("You try to flee with your legs entwined, but trip.",ch,NULL,NULL,TO_CHAR); check_downstrike(victim,ch); check_cheap_shot(victim,ch); WAIT_STATE(ch,PULSE_VIOLENCE); return; } if (is_affected(ch,gsn_bloodthirst) && number_percent()<70 ) { send_to_char("You gasp for breath as you attempt to snap out of your insanity!\n\r",ch); act("$n gasps for breath, attempting to snap out of $s insanity!",ch,NULL,NULL,TO_ROOM); WAIT_STATE(ch,PULSE_VIOLENCE); } if (is_affected(ch,gsn_bind) ) { act("$n attempts to flee but his bindings cause $m to trip up and fall!",ch,0,0,TO_ROOM); act("You attempt to flee but your bindings cause you to trip up and fall!",ch,0,0,TO_CHAR); WAIT_STATE(ch,PULSE_VIOLENCE); check_cheap_shot(ch->fighting,ch); check_parting_blow(ch,victim); return; } if (check_cutoff(ch,victim)) { return; } one_argument(argument,arg); chance = get_skill(ch,gsn_escape); if (chance > 90) chance=90; dir = 10; if (arg[0] == '\0') dir=10; else if (!str_cmp(arg,"north")) dir=0; else if (!str_cmp(arg,"east")) dir=1; else if (!str_cmp(arg,"south")) dir=2; else if (!str_cmp(arg,"west")) dir=3; else if (!str_cmp(arg,"up")) dir=4; else if (!str_cmp(arg,"down")) dir=5; else dir=10; was_in = ch->in_room; if (was_in==NULL) { bug("In do_flee: ch->in_room is NULL.",0); return; } if (chance>0 && number_percent()>chance && dir!=10) { send_to_char("Trying to escape...\n\r",ch); } for ( attempt = 0; attempt < 6; attempt++ ) { EXIT_DATA *pexit; int door; if (dir>5 || dir<0) door=number_door()%6; else door = dir; pexit = was_in->exit[door]; if ( pexit == 0) continue; if (pexit->u1.to_room == NULL || ( IS_SET(pexit->exit_info, EX_CLOSED) && (!IS_AFFECTED(ch,AFF_PASS_DOOR) )) || number_range(0,ch->daze) != 0 || ( IS_NPC(ch) && IS_SET(pexit->u1.to_room->room_flags, ROOM_NO_MOB) ) ) continue; if (attempt == 0) check_parting_blow(ch,victim); move_char( ch, door, FALSE ); if ( ( now_in = ch->in_room ) == was_in ) continue; stop_fighting(ch,TRUE); ch->last_fought = NULL; ch->in_room = was_in; if (is_affected(ch, gsn_owaza)) { send_to_char("Your attempt at owaza fails as you flee.\n\r",ch); affect_strip(ch, gsn_owaza); } act( "$n has fled!", ch, NULL, NULL, TO_ROOM ); ch->in_room = now_in; if ( !IS_NPC(ch) ) { send_to_char( "You flee from combat!\n\r", ch ); if (dir != 10 && get_skill(ch,gsn_escape) > 2) check_improve(ch,gsn_escape,2,TRUE); } return; } send_to_char( "PANIC! You couldn't escape!\n\r", ch ); return; } void do_pugil(CHAR_DATA *ch,char *argument) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; OBJ_DATA *obj; int chance; int dam; one_argument(argument,arg); if ( (chance = get_skill(ch,gsn_pugil)) == 0 || IS_NPC(ch) || (!IS_NPC(ch) && ch->level < skill_table[gsn_pugil].skill_level[ch->class]) ) { send_to_char("You're not trained in the art of pugiling.\n\r",ch); return; } if (arg[0] == '\0') { victim = ch->fighting; if (victim == NULL) { send_to_char("But you aren't fighting anyone.\n\r",ch); return; } } else if ((victim = get_char_room(ch,arg)) == NULL) { send_to_char("They aren't here.\n\r",ch); return; } if (ch->fighting == NULL) { send_to_char("You can't pugil someone like that.\n\r",ch); return; } if (victim == ch) { send_to_char("That would be a bit stupid.\n\r", ch); return; } obj = get_eq_char(ch,WEAR_WIELD); if (obj == NULL || obj->value[0] != WEAPON_STAFF) { send_to_char("You must be wielding a staff to pugil.\n\r",ch); return; } chance += (ch->level - victim->level); chance = URANGE(5, chance, 90); WAIT_STATE(ch,skill_table[gsn_pugil].beats); if (number_percent() < chance) { act("You smash $N with a bone crushing pugil!",ch,NULL,victim,TO_CHAR); act("$n smashes you with a bone crushing pugil!",ch,NULL,victim,TO_VICT); act("$n pugils $N with a bone crushing pugil!",ch,NULL,victim,TO_NOTVICT); check_improve(ch,gsn_pugil,TRUE,1); dam = dice(obj->value[1],obj->value[2]); dam += (get_skill(ch,gsn_enhanced_damage) * dam/100); if (ch->level <= 20) { dam *= number_range(10,13); dam /= 10; } else if (ch->level <= 25) { dam *= number_range(11,14); dam /= 10; } else if (ch->level <= 30) { dam *= number_range(12,15); dam /= 10; } else if (ch->level <= 35) { dam *= number_range(12,17); dam /= 10; } else if (ch->level <= 40) { dam *= number_range(13,18); dam /= 10; } else { dam *= number_range(14,20); dam /= 10; } damage_old(ch,victim,dam,gsn_pugil, attack_table[obj->value[3]].damage, TRUE); } else { check_improve(ch,gsn_pugil,FALSE,1); damage_old(ch,victim,0,gsn_pugil,DAM_NONE,TRUE); } return; } void do_protection_heat_cold(CHAR_DATA *ch,char *argument) { AFFECT_DATA af; int chance; chance = get_skill(ch,gsn_protection_heat_cold); if (chance == 0 || ch->level <skill_table[gsn_protection_heat_cold].skill_level[ch->class]) { send_to_char("You don't know how to protect yourself from the elements.\n\r",ch); return; } if (is_affected(ch,gsn_protection_heat_cold)) { send_to_char("You are already protected from the elements.\n\r",ch); return; } if (number_percent() > chance) { send_to_char("You try to protect yourself from the elements but fail.\n\r",ch); check_improve(ch,gsn_protection_heat_cold,FALSE,1); return; } init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_SKILL; af.type = gsn_protection_heat_cold; af.level = ch->level; af.modifier = 0; af.duration = ch->level; af.bitvector = 0; af.location = 0; af.affect_list_msg = str_dup("grants protection against heat and cold-elemental attacks"); affect_to_char(ch,&af); send_to_char("You are protected from the elements.\n\r",ch); check_improve(ch,gsn_protection_heat_cold,TRUE,1); return; } void do_undead_drain(CHAR_DATA *ch,char *argument) { CHAR_DATA *vch; int sn_drain; if (ch->level < 40) return; for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room) { if (vch->fighting == ch && number_percent() > 70) break; } if (vch == NULL) vch = ch->fighting; sn_drain = skill_lookup("undead drain"); if (sn_drain == -1) return; (*skill_table[sn_drain].spell_fun) (sn_drain,ch->level,ch,vch,TAR_CHAR_OFFENSIVE); return; } char * check_evaluation_fight(CHAR_DATA *ch,CHAR_DATA *victim) { int percent; char wound[100]; char buf[MAX_STRING_LENGTH]; if ((victim = ch->fighting) != NULL && can_see(ch,victim)) { if (victim->max_hit > 0) percent = victim->hit * 100 / victim->max_hit; else percent = -1; if (percent >= 100) sprintf(wound,"is in perfect condition."); else if (percent >= 95) sprintf(wound,"has a few scratches."); else if (percent >= 90) sprintf(wound,"has a few bruises."); else if (percent >= 80) sprintf(wound,"has some small wounds."); else if (percent >= 70) sprintf(wound,"has some big nasty cuts."); else if (percent >= 60) sprintf(wound,"has quite a few wounds."); else if (percent >= 50) sprintf(wound,"is bleeding profusely."); else if (percent >= 40) sprintf(wound,"is gushing blood."); else if (percent >= 30) sprintf(wound,"is screaming in pain."); else if (percent >= 20) sprintf(wound,"is spasming in shock."); else if (percent >= 10) sprintf(wound,"is writhing on the ground."); else if (percent >= 1) sprintf(wound,"is convulsing near death."); else sprintf(wound,"is nearly dead."); } return str_dup(buf); } void do_iron_resolve(CHAR_DATA *ch,char *argument) { AFFECT_DATA af; if (is_affected(ch,gsn_iron_resolve)) { send_to_char("Your mind is already firmly set on your inner being.\n\r",ch); return; } if (ch->mana < 100) { send_to_char("You don't have the mental concentration right now.\n\r",ch); return; } if (number_percent() > get_skill(ch,gsn_iron_resolve)) { send_to_char("You try to concentrate on your inner being but fail to maintain it.\n\r",ch); ch->mana -= 50; WAIT_STATE(ch,12); return; } send_to_char("You feel yourself come together as mind and body.\n\r",ch); init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_SKILL; af.type = gsn_iron_resolve; af.level = ch->level; af.location = 0; af.bitvector = 0; af.modifier = 0; af.duration = ch->level/3; ch->mana -= 100; WAIT_STATE(ch,12); } void do_quiet_movement(CHAR_DATA *ch, char *argument) { AFFECT_DATA af; int chance; chance = get_skill(ch,gsn_quiet_movement); if (chance == 0 || ch->level < skill_table[gsn_quiet_movement].skill_level[ch->class]) { send_to_char("You don't know how to move with silent stealth through the wilderness.\n\r",ch); return; } if (is_affected(ch,gsn_quiet_movement)) { send_to_char("You are already attempting to move silently through the wilderness.\n\r",ch); return; } if (ch->in_room->sector_type == SECT_FOREST) { send_to_char("You attempt to move quietly through the forest.\n\r",ch); } else if (ch->in_room->sector_type == SECT_MOUNTAIN) { send_to_char("You attempt to move quietly through the mountains.\n\r",ch); } else if (ch->in_room->sector_type == SECT_HILLS) { send_to_char("You attempt to move quietly through the hills.\n\r",ch); } else { send_to_char("You aren't in the right kind of wilderness to movee quietly.\n\r",ch); return; } if (number_percent() > chance) { check_improve(ch,gsn_quiet_movement,FALSE,1); return; } check_improve(ch,gsn_quiet_movement,TRUE,1); init_affect(&af); af.where = TO_AFFECTS; af.type = gsn_quiet_movement; af.aftype = AFT_SKILL; af.location = 0; af.modifier = 0; af.duration = ch->level; af.level = ch->level; char msg_buf[MSL]; sprintf(msg_buf,"moving silently"); af.affect_list_msg = str_dup(msg_buf); af.bitvector = 0; affect_to_char(ch,&af); return; } void do_executioners_grace(CHAR_DATA *ch,char *argument) { AFFECT_DATA af; int chance = get_skill(ch,gsn_executioner); bool night=FALSE; if(chance==0) { send_to_char("You don't know how to move with the deadly grace of an executioner.\n\r",ch); return; } if(number_percent() > chance) { send_to_char("You fail to move with the deadly grace of an executioner.\n\r",ch); WAIT_STATE(ch,PULSE_VIOLENCE*4); return; } if(is_affected(ch,gsn_executioner)) { send_to_char("You are already moving with the deadly grace of an executioner.\n\r",ch); WAIT_STATE(ch,PULSE_VIOLENCE*4); return; } send_to_char("You begin to flow with the deadly grace of an executioner.\n\r",ch); night = (weather_info.sunlight == SUN_DARK ? TRUE : FALSE); init_affect(&af); af.where = TO_AFFECTS; af.type = gsn_executioner; af.location = APPLY_DAMROLL; af.modifier = night ? 25 : 15; af.level = ch->level; af.duration = night ? ch->level/2 : ch->level/4; af.bitvector = AFF_BERSERK; af.aftype = AFT_SKILL; ch->mana-=300; affect_to_char(ch,&af); return; } void do_spike(CHAR_DATA *ch,char *argument) { CHAR_DATA *victim; int chance, dam; char arg[MAX_INPUT_LENGTH]; one_argument(argument,arg); if (IS_NPC(ch)) return; if (ch->position == POS_FIGHTING) { send_to_char("You can't spike them in the heat of battle.\n\r",ch); return; } if ((get_skill(ch,gsn_spike) == 0) || ch->level < skill_table[gsn_spike].skill_level[ch->class]) { send_to_char("Huh?\n\r",ch); return; } if (arg[0] == '\0') { send_to_char("Attempt to spike which person?\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("You can't do that.\n\r",ch); return; } if (victim->fighting != NULL || victim->position == POS_FIGHTING) { send_to_char("They are moving around too much to get in close for the kill.\n\r",ch); return; } if (is_safe(ch,victim)) return; chance = get_skill(ch,gsn_spike)/2; chance += ch->level; chance -= victim->level * 3/2; chance -= number_range(0,15); if (!can_see(victim,ch)) chance += 10; if (victim->position == POS_FIGHTING) chance -= 25; else if (victim->position == POS_SLEEPING) chance += 10; else chance -= 10; chance /= 2; chance = URANGE(2,chance,90); act("$n strikes out at $N with deadly intensity.",ch,0,victim,TO_NOTVICT); act("You strike out at $N with deadly intensity.",ch,0,victim,TO_CHAR); act("$n strikes at you with deadly intensity.",ch,0,victim,TO_VICT); if (number_percent() < chance) { send_to_char("With agonising pain your skull is smashed by the blow!\n\r",victim); act("Your blow shatters $N's skull into bloody fragments!",ch,0,victim,TO_CHAR); act("$N's skull is shattered into bits of mangled flesh and bone by $n's strike!",ch,0,victim,TO_NOTVICT); raw_kill(ch,victim); WAIT_STATE(ch,PULSE_VIOLENCE*2); check_improve(ch,gsn_spike,TRUE,2); return; } else { send_to_char("You feel a sharp pain searing your skull!\n\r",victim); act("Your deathstrike smashes $N's skull but fails to kill.",ch,0,victim,TO_CHAR); dam = ch->level * 2; dam += dice(ch->level, 4); damage_old(ch,victim,dam,gsn_spike,DAM_PIERCE,TRUE); WAIT_STATE(ch,PULSE_VIOLENCE); check_improve(ch,gsn_spike,FALSE,1); } return; } bool check_unholy_bless(CHAR_DATA *ch, CHAR_DATA *victim) { AFFECT_DATA af; AFFECT_DATA *paf; AFFECT_DATA *paf_next; int sn, hitmod = 0, manamod = 0, hrollmod = 0, drollmod = 0, vdrollmod = 0, i; if (IS_NPC(victim)) return FALSE; if (!is_affected(ch,gsn_unholy_bless)) { return FALSE; } if (is_affected(victim,gsn_unholy_timer)) { return FALSE; } sn = skill_lookup("unholy bless"); /* check if victim is AP and take his charges */ if (is_affected(victim,gsn_unholy_bless) && victim != ch) { for ( paf = victim->affected; paf != NULL; paf = paf_next ) { paf_next = paf->next; if ( paf->type == sn ) { switch (paf->location) { default: break; case APPLY_DAMROLL: vdrollmod = paf->modifier; break; } } } vdrollmod = (vdrollmod - 1) / 6; if (vdrollmod < 1) { vdrollmod = 0; } } else { vdrollmod = 0; } for (i=0; i < vdrollmod+1; i++) { for ( paf = ch->affected; paf != NULL; paf = paf_next ) { paf_next = paf->next; if ( paf->type == sn ) { switch (paf->location) { default: break; case APPLY_HIT: hitmod = paf->modifier; affect_remove( ch, paf ); break; case APPLY_MANA: manamod = paf->modifier; affect_remove( ch, paf ); break; case APPLY_HITROLL: hrollmod = paf->modifier; affect_remove( ch, paf ); break; case APPLY_DAMROLL: drollmod = paf->modifier; affect_remove( ch, paf ); break; } } } hitmod += 10; manamod += 10; hrollmod += 3; drollmod += 3; init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_SPELL; af.type = sn; af.level = ch->level; af.duration = -1; af.bitvector = 0; af.modifier = hitmod; af.location = APPLY_HIT; affect_to_char(ch,&af); af.modifier = manamod; af.location = APPLY_MANA; affect_to_char(ch,&af); af.modifier = hrollmod; af.location = APPLY_HITROLL; affect_to_char(ch,&af); af.modifier = drollmod; af.location = APPLY_DAMROLL; affect_to_char(ch,&af); act("\x01B[1;31m$n's body pulses as power drains from $N's corpse!\x01B[0;37m",ch,0,victim,TO_NOTVICT); act("\x01B[1;31m$n's body pulses as power drains from your corpse!\x01B[0;37m",ch,0,victim,TO_VICT); act("\x01B[1;31mYour body pulses as you drain power from $N's corpse!\x01B[0;37m",ch,0,victim,TO_CHAR); } return TRUE; } bool check_unholy_new(CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA *obj) { AFFECT_DATA *af,*af_next,paf; int hmod=0, hpmod=0, dmod=0, mmod=0; bool dual = FALSE; if (obj == get_eq_char(ch,WEAR_DUAL_WIELD)) dual = TRUE; if(obj == NULL) return FALSE; int sn = skill_lookup("unholy bless"); if((af = affect_find_obj(obj,sn)) == NULL) return FALSE; if(IS_NPC(victim) || is_affected(victim,skill_lookup("unholy guard"))) return FALSE; for (af = obj->affected; af != NULL; af = af_next ) { af_next = af->next; if ( af->type == sn ) { switch (af->location) { default: break; case APPLY_HIT: hpmod = af->modifier; affect_remove_obj( obj, af ); break; case APPLY_MANA: mmod = af->modifier; affect_remove_obj( obj, af ); break; case APPLY_HITROLL: hmod = af->modifier; affect_remove_obj( obj, af ); break; case APPLY_DAMROLL: dmod = af->modifier; affect_remove_obj( obj, af ); break; } } } hmod += 1; hpmod += 50; mmod += 50; dmod += 1; init_affect(&paf); paf.where = TO_OBJECT; paf.duration = -1; paf.level = ch->level; paf.type = sn; paf.owner_name = str_dup(ch->original_name); paf.location = APPLY_HIT; paf.modifier = hpmod; affect_to_obj(obj,&paf); paf.location = APPLY_MANA; paf.modifier = mmod; affect_to_obj(obj,&paf); paf.location = APPLY_HITROLL; paf.modifier = hmod; affect_to_obj(obj,&paf); paf.location = APPLY_DAMROLL; paf.modifier = dmod; affect_to_obj(obj,&paf); unequip_char(ch,obj); if (dual) equip_char(ch,obj,WEAR_DUAL_WIELD); else equip_char(ch,obj,WEAR_WIELD); act("{R$p writhes in your grip and you feel a new energy enter your body as you steal $N's soul.{x",ch,obj,victim,TO_CHAR); act("{R$p seems to twist and writhe in $n's grip as a chill runs down your spine.{x",ch,obj,0,TO_ROOM); return TRUE; } void do_drive(CHAR_DATA *ch, char *argument) { CHAR_DATA *victim = ch->fighting; AFFECT_DATA af; char buf[MSL]; char arg[MSL]; int direction = -1; one_argument(argument,arg); if (get_skill(ch, skill_lookup("drive")) < 5) return send_to_char("You do not know how to drive others.\n\r",ch); if (victim == NULL) return send_to_char("But you aren't fighting anyone!\n\r",ch); if (arg[0] != '\0' && IS_NPC(victim)) return send_to_char("You cannot seem to budge them.\n\r",ch); if (arg[0] == '\0') return send_to_char("Drive in which direction?\n\r",ch); if (!str_prefix(arg,"east") || !str_prefix(arg,"west") || !str_prefix(arg,"north") || !str_prefix(arg,"south") || !str_prefix(arg,"up") || !str_prefix(arg,"down")) { if (!str_prefix(arg,"east")) direction = DIR_EAST; else if (!str_prefix(arg,"west")) direction = DIR_WEST; else if (!str_prefix(arg,"north")) direction = DIR_NORTH; else if (!str_prefix(arg,"south")) direction = DIR_SOUTH; else if (!str_prefix(arg,"up")) direction = DIR_UP; else if (!str_prefix(arg,"down")) direction = DIR_DOWN; if (number_percent() < get_skill(ch, skill_lookup("drive")) * .75) { sprintf(buf,"Help! %s is driving me away!",ch->name); do_myell(victim,buf); if (direction != DIR_UP && direction != DIR_DOWN) sprintf(buf,"You charge at %s and drive %s to the %s!",IS_NPC(victim) ? victim->short_descr : victim->name, him_her[URANGE(0, victim->sex, 2)], dir_name[direction]); else sprintf(buf,"You charge at %s and drive %s %swards!",IS_NPC(victim) ? victim->short_descr : victim->name, him_her[URANGE(0, victim->sex, 2)], dir_name[direction]); act(buf,ch,0,victim,TO_CHAR); if (direction != DIR_UP && direction != DIR_DOWN) sprintf(buf,"%s charges at %s, driving %s to the %s!",IS_NPC(ch) ? ch->short_descr : ch->name,IS_NPC(victim) ? victim->short_descr : victim->name, him_her[URANGE(0, victim->sex, 2)], dir_name[direction]); else sprintf(buf,"%s charges at %s, driving %s %swards!",IS_NPC(ch) ? ch->short_descr : ch->name,IS_NPC(victim) ? victim->short_descr : victim->name, him_her[URANGE(0, victim->sex, 2)], dir_name[direction]); act(buf,ch,0,victim,TO_NOTVICT); if (direction != DIR_UP && direction != DIR_DOWN) sprintf(buf,"%s charges at you, driving you to the %s!",IS_NPC(ch) ? ch->short_descr : ch->name, dir_name[direction]); else sprintf(buf,"%s charges at you, driving you %swards!",IS_NPC(ch) ? ch->short_descr : ch->name,dir_name[direction]); act(buf,ch,0,victim,TO_VICT); WAIT_STATE(ch,PULSE_VIOLENCE*2); } else { sprintf(buf,"Help! %s is trying to drive me away!",ch->name); do_myell(victim,buf); if (direction != DIR_UP && direction != DIR_DOWN) sprintf(buf,"You charge at %s, but fail to drive %s to the %s!",IS_NPC(victim) ? victim->short_descr : victim->name, him_her[URANGE(0, victim->sex, 2)], dir_name[direction]); else sprintf(buf,"You charge at %s, but fail to drive %s %swards!",IS_NPC(victim) ? victim->short_descr : victim->name, him_her[URANGE(0, victim->sex, 2)], dir_name[direction]); act(buf,ch,0,victim,TO_CHAR); if (direction != DIR_UP && direction != DIR_DOWN) sprintf(buf,"%s charges at %s, but fails to drive %s to the %s!",IS_NPC(ch) ? ch->short_descr : ch->name,IS_NPC(victim) ? victim->short_descr : victim->name, him_her[URANGE(0, victim->sex, 2)], dir_name[direction]); else sprintf(buf,"%s charges at %s, but fails to drive %s %swards!",IS_NPC(ch) ? ch->short_descr : ch->name,IS_NPC(victim) ? victim->short_descr : victim->name, him_her[URANGE(0, victim->sex, 2)], dir_name[direction]); act(buf,ch,0,victim,TO_NOTVICT); if (direction != DIR_UP && direction != DIR_DOWN) sprintf(buf,"%s charges at you, but fails to drive you to the %s!",IS_NPC(ch) ? ch->short_descr : ch->name, dir_name[direction]); else sprintf(buf,"%s charges at you, but fails to drive you %swards!",IS_NPC(ch) ? ch->short_descr : ch->name,dir_name[direction]); act(buf,ch,0,victim,TO_VICT); WAIT_STATE(ch,PULSE_VIOLENCE*2); return; } if (direction != -1) stop_fighting(ch,TRUE); init_affect(&af); af.aftype = AFT_INVIS; af.type = skill_lookup("drive"); affect_to_char(victim,&af); move_char(ch,direction,FALSE); move_char(victim,direction,FALSE); affect_remove(victim,&af); set_fighting(ch,victim); WAIT_STATE(ch,PULSE_VIOLENCE*2); return; } else return send_to_char("That is not a valid direction.",ch); } void do_bind(CHAR_DATA *ch,char *argument) { CHAR_DATA *victim; int chance; AFFECT_DATA af; char arg[MAX_INPUT_LENGTH]; one_argument(argument,arg); if (IS_NPC(ch)) return; if (get_skill(ch,gsn_bind) == 0) { send_to_char("Huh?\n\r",ch); return; } if (arg[0] == '\0') { send_to_char("Attempt to bind who?\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("You can't do that.\n\r",ch); return; } if (victim->position != POS_SLEEPING) { send_to_char("They must be sleeping for you to bind them.\n\r",ch); return; } if (is_affected(victim,gsn_bind)) { send_to_char("They are already bound.\n\r",ch); return; } if (is_safe(victim, ch)) return; chance = get_skill(ch,gsn_bind)-20; if(is_affected(victim,AFF_HASTE)) chance-=30; if(is_affected(ch,AFF_HASTE)) chance+=15; if(get_curr_stat(victim,STAT_DEX)>get_curr_stat(ch,STAT_DEX)) chance-=20; if(number_percent() < chance) { init_affect(&af); af.aftype = AFT_SKILL; af.where = TO_AFFECTS; af.type = gsn_bind; af.level = ch->level; af.duration = -1; af.bitvector = AFF_BLIND; af.modifier = -5; af.location = APPLY_DEX; affect_to_char(victim,&af); act("$n puts a sack over $N's head and ties a rope around his legs tightly.",ch,0,victim,TO_NOTVICT); send_to_char("You feel someone putting something over your head and legs.", victim); act("You put a sack over $N's head and tie a rope around his legs tightly.",ch,0,victim,TO_CHAR); WAIT_STATE(ch,PULSE_VIOLENCE); check_improve(ch,gsn_bind,TRUE,1); } else { act("$n tries to put a sack over $N's head but it rips.",ch,0,victim,TO_NOTVICT); send_to_char("You feel someone trying to put something over your head and legs.",victim); act("You try to put a sack over $N's head but it rips.",ch,0,victim,TO_CHAR); WAIT_STATE(ch,PULSE_VIOLENCE*3); check_improve(ch,gsn_bind,FALSE,3); } return; } void check_cheap_shot(CHAR_DATA *ch, CHAR_DATA *victim) { int chance; int dam; chance=get_skill(ch,gsn_cheap_shot); if(chance<2) return; if(is_affected(victim,AFF_HASTE)) chance-=30; if(is_affected(ch,AFF_HASTE)) chance+=15; if(is_affected(victim,AFF_FLYING)) chance-=20; chance*=.65; if(number_percent() < chance) { act("Seizing upon $N's moment of weakness, you brutally kick him while he's down!",ch,0,victim,TO_CHAR); act("Seizing upon your moment of weakness, $n brutally kicks you while you're down!",ch,0,victim,TO_VICT); act("Seizing upon $N's moment of weakness, $n brutally kicks him while he's down!",ch,0,victim,TO_NOTVICT); dam=40; if(number_percent() < 10) { act("$N grunts in pain as you land a particularly vicious kick!",ch,0,victim,TO_CHAR); act("You grunt in pain as $n lands a particularly vicious kick!",ch,0,victim,TO_VICT); act("$N grunts in pain as $n lands a particularly vicious kick!",ch,0,victim,TO_NOTVICT); dam=125; ADD_WAIT_STATE(victim,PULSE_VIOLENCE); } if (spike_toed_boots(ch)) dam *= 1.5; damage_old(ch,victim,dam,gsn_cheap_shot,DAM_PIERCE,TRUE); check_improve(ch,gsn_cheap_shot,TRUE,1); ADD_WAIT_STATE(victim,PULSE_VIOLENCE); return; } else { send_to_char("You were unable to get a cheap shot in.\n\r",ch); check_improve(ch,gsn_cheap_shot,FALSE,1); return; } } void do_unbind(CHAR_DATA *ch,char *argument) { if(!is_affected(ch,gsn_bind)) { send_to_char("You are not bound.\n\r",ch); return; } if(number_percent()>30) { act("You break free of the bindings on your head and legs.",ch,0,0,TO_CHAR); act("$n breaks free of the bindings on $s head and legs.",ch,0,0,TO_ROOM); affect_strip( ch, gsn_bind ); WAIT_STATE(ch,PULSE_VIOLENCE); } else { act("You fail to break free of the bindings on your head and legs.",ch,0,0,TO_CHAR); act("$n fails to break free of the bindings on $s head and legs.",ch,0,0,TO_ROOM); WAIT_STATE(ch,PULSE_VIOLENCE); } } void do_blitz( CHAR_DATA *ch, char *argument ) // Do not disable this! -Det. { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; int chance, imod; char buf[MAX_STRING_LENGTH]; bool isDS; if (cabal_down(ch,CABAL_RAGER)) return; one_argument(argument,arg); if ((chance = get_skill(ch,gsn_blitz)) == 0) { send_to_char("Blitzing? What's that?\n\r",ch); return; } if (IS_NPC(ch) && IS_AFFECTED(ch,AFF_CHARM)) return; if (arg[0] == '\0') { victim = ch->fighting; if (victim == NULL) { send_to_char("But you aren't fighting anyone!\n\r",ch); return; } } else if ((victim = get_char_room(ch,arg)) == NULL) { send_to_char("They aren't here.\n\r",ch); return; } if (victim->position < POS_FIGHTING) { act("You'll have to let $M get back up first.",ch,NULL,victim,TO_CHAR); return; } if (victim == ch) { send_to_char("You try to blitz your brains out, but fail.\n\r",ch); return; } if ((victim->fighting!=ch) && (ch->fighting != NULL)) { send_to_char("You must be directly fighting that person to blitz them.\n\r",ch); return; } if (is_safe(ch,victim)) return; if (IS_AFFECTED(ch,AFF_CHARM) && ch->master == victim) { act("But $N is your friend!",ch,NULL,victim,TO_CHAR); return; } /* modify chance */ chance += ch->carry_weight / 200; chance -= victim->carry_weight / 200; if (ch->size < victim->size) { chance += (ch->size - victim->size) * 5; } else { chance += (ch->size - victim->size) * 5; } if (is_affected(victim,gsn_protective_shield)) { chance -= 5; } if (is_affected(victim, skill_lookup("wraithform"))) { chance -= 5; } if (is_affected(victim,gsn_fireshield)) { chance -= 5; } chance += get_curr_stat(ch,STAT_STR) + 5; chance -= (get_curr_stat(victim,STAT_DEX)); chance -= GET_AC(victim,AC_BASH) /20; if (IS_SET(ch->off_flags,OFF_FAST) || IS_AFFECTED(ch,AFF_HASTE)) { chance += 10; } if (is_affected(ch,skill_lookup("bloodthirst"))) { chance += 10; } if (is_affected(ch,skill_lookup("berserk"))) { chance += 10; } if (IS_SET(victim->off_flags,OFF_FAST) || IS_AFFECTED(victim,AFF_HASTE)) { chance -= 5; } chance += (ch->level - victim->level); if (!IS_NPC(ch) && !IS_NPC(victim) && (victim->fighting == NULL || ch->fighting == NULL)) { sprintf(buf,"Help! %s is blitzing me!",PERS(ch,victim)); do_myell(victim,buf); } if (!IS_NPC(victim) && chance < get_skill(victim,gsn_dodge) ) { chance -= 3 * (get_skill(victim,gsn_dodge) - chance); } imod = 25; isDS = FALSE; if (!IS_NPC(ch) ) chance += 15; /* now the attack */ if (number_percent() < chance - 20) { act("$n pummels you to the ground with excruciating force!", ch,NULL,victim,TO_VICT); act("You slam into $N, pummeling $M into the ground!",ch,NULL,victim,TO_CHAR); act("$n pummels $N into the ground with a powerful blitz.",ch,NULL,victim,TO_NOTVICT); damage_old(ch,victim,(3 * ch->size + chance),gsn_blitz,DAM_BASH,TRUE); check_improve(ch,gsn_blitz,TRUE,3); WAIT_STATE(victim,PULSE_VIOLENCE*1.5); WAIT_STATE(ch,2*PULSE_VIOLENCE); if (number_percent() > 90) { if (is_affected(victim,gsn_sanctuary) && (number_percent() < chance-imod)) { if (check_dispel(ch->level-3,victim,skill_lookup("sanctuary"))) { act("$n looks stunned as $s mind wanders from $s spells.",victim,0,0,TO_ROOM); act("Your head throbs with pain as you lose control over your spells.",victim,0,0,TO_CHAR); act("The white aura about $n vanishes!",victim,NULL,NULL,TO_ROOM); isDS = TRUE; } } if ((isDS == FALSE) && is_affected(victim,gsn_fireshield) && (number_percent() < chance-imod)) { if (check_dispel(ch->level,victim,skill_lookup("fireshield"))) { act("$n looks stunned as $s mind wanders from $s spells.",victim,0,0,TO_ROOM); act("Your head throbs with pain as you lose control over your spells.",victim,0,0,TO_CHAR); act("The fire around $n vanishes!",victim,NULL,NULL,TO_ROOM); isDS = TRUE; } } if ((isDS == FALSE) && is_affected(victim,gsn_stoneskin) && (number_percent() < chance-imod)) { if (check_dispel(ch->level-2,victim,skill_lookup("stone skin"))) { act("$n looks stunned as $s mind wanders from $s spells.",victim,0,0,TO_ROOM); act("Your head throbs with pain as you lose control over your spells.",victim,0,0,TO_CHAR); act("The skin of $n softens into flesh!",victim,NULL,NULL,TO_ROOM); isDS = TRUE; } } if ((isDS == FALSE) && is_affected(victim,gsn_wraithform) && (number_percent() < chance-imod)) { if (check_dispel(ch->level-2,victim,skill_lookup("wraithform"))) { act("$n looks stunned as $s mind wanders from $s spells.",victim,0,0,TO_ROOM); act("Your head throbs with pain as you lose control over your spells.",victim,0,0,TO_CHAR); act("The body of $n fades back into the Prime Material Plane!",victim,NULL,NULL,TO_ROOM); isDS = TRUE; } } if ((isDS == FALSE) && is_affected(victim,gsn_shroud) && (number_percent() < chance-imod)) { if (check_dispel(ch->level,victim,skill_lookup("shroud"))) { act("$n looks stunned as $s mind wanders from $s spells.",victim,0,0,TO_ROOM); act("Your head throbs with pain as you lose control over your spells.",victim,0,0,TO_CHAR); act("The black aura about $n vanishes!",victim,NULL,NULL,TO_ROOM); isDS = TRUE; } } } } else { damage_old(ch,victim,0,gsn_blitz,DAM_BASH,FALSE); act("You fall over and bite the dust!",ch,NULL,victim,TO_CHAR); act("$n falls flat on $s face, eating a mouthful of dirt.",ch,NULL,victim,TO_NOTVICT); act("You evade $n's blitz, and $e falls flat on $s face.",ch,NULL,victim,TO_VICT); check_cheap_shot(victim,ch); check_improve(ch,gsn_blitz,FALSE,3); ch->position = POS_RESTING; WAIT_STATE(ch,2*PULSE_VIOLENCE); } return; } void check_parting_blow( CHAR_DATA *ch, CHAR_DATA *victim ) { if (get_skill(victim,gsn_parting_blow) > 1) { if (number_percent() < get_skill(victim,gsn_parting_blow)) { act("You get in one more shot as $N flees.",victim,0,ch,TO_CHAR); act("$n gets in one more shot as $N flees.",victim,0,ch,TO_NOTVICT); act("$n gets in one more shot as you flee.",victim,0,ch,TO_VICT); one_hit(victim,ch,gsn_parting_blow); check_improve(victim,gsn_parting_blow,TRUE,1); } else { check_improve(victim,gsn_parting_blow,TRUE,1); } } return; } bool check_ironhands( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { float chance, hit_ratio; char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char *attack; int ch_hitroll, victim_hitroll, str = get_curr_stat(victim,STAT_STR); if ( !IS_AWAKE(victim) ) return FALSE; if (IS_NPC(victim)) return FALSE; if ((chance = get_skill(victim,gsn_ironhands) / 3) == 0) return FALSE; if (get_eq_char(victim,WEAR_WIELD) != NULL) return FALSE; if (get_eq_char(victim,WEAR_SHIELD) != NULL) return FALSE; if (!can_see(ch,victim)) chance *= number_range(6/10,3/4); ch_hitroll = GET_HITROLL(ch); victim_hitroll = GET_HITROLL(victim); //For simplicity... if (victim_hitroll <= 0) victim_hitroll = 1; if (ch_hitroll <= 0) ch_hitroll = 1; if (victim_hitroll < ch_hitroll) { hit_ratio = (float)ch_hitroll / (float)victim_hitroll; if (hit_ratio > 1.1) chance *= 1.1; else chance *= hit_ratio; } if (str <= 5) chance += 0; else if (str <= 10) chance += str/2; else if (str <=15) chance += (str); else if (str <= 20) chance += (6*str/5); else chance += 3*str/2; if ( number_percent( ) >= ((chance + (victim->level +ch->level) - 40)/2)) { check_improve(victim,gsn_ironhands,FALSE,5); return FALSE; } attack=get_dam_message(ch,dt); sprintf(buf1,"You parry $n's %s.",attack); sprintf(buf2,"$N parries your %s.",attack); act(buf1,ch,0,victim,TO_VICT); act(buf2,ch,0,victim,TO_CHAR); check_improve(victim,gsn_ironhands,TRUE,6); return TRUE; } bool check_unarmed_defense( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { int ch_hitroll, victim_hitroll, dex = get_curr_stat(victim,STAT_DEX); float chance, hit_ratio; char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char *attack; if ( !IS_AWAKE(victim) ) return FALSE; if (IS_NPC(victim)) return FALSE; if ((chance = get_skill(victim,gsn_unarmed_defense) /2) == 0) return FALSE; ch_hitroll = GET_HITROLL(ch); victim_hitroll = GET_HITROLL(victim); //For simplicity... if (victim_hitroll <= 0) victim_hitroll = 1; if (ch_hitroll <= 0) ch_hitroll = 1; if (victim_hitroll < ch_hitroll) { hit_ratio = (float)ch_hitroll / (float)victim_hitroll; if (hit_ratio > 1.25) chance *= 1.25; else chance *= hit_ratio; } if (get_eq_char(victim,WEAR_WIELD) != NULL) return FALSE; if (dex <= 5) chance += 0; else if (dex <= 10) chance += dex/2; else if (dex <=15) chance += (2*dex/3); else if (dex <= 20) chance += dex; else chance += 3*dex/2; if (!can_see(ch,victim)) chance /= 2; chance += get_curr_stat(victim,STAT_DEX) - get_curr_stat(ch,STAT_DEX); if (IS_AFFECTED(victim, AFF_HASTE)) chance += 10; if (IS_AFFECTED(ch, AFF_HASTE)) chance -= 10; if (number_percent() >= chance) { check_improve(victim,gsn_unarmed_defense,FALSE,5); return FALSE; } attack=get_dam_message(ch,dt); sprintf(buf1,"You deftly avoid $n's %s.",attack); sprintf(buf2,"$N deftly avoids your %s.",attack); act(buf1,ch,0,victim,TO_VICT); act(buf2,ch,0,victim,TO_CHAR); check_improve(victim,gsn_unarmed_defense,TRUE,6); return TRUE; } char *get_dam_message(CHAR_DATA *ch, int dt) { return get_attack_noun(ch,dt); } char * get_attack_noun(CHAR_DATA *ch, int dt) { OBJ_DATA *wield; int tmp_dt; char *attack; if (is_affected(ch,skill_lookup("valiant wrath"))) { attack = str_dup("valiant wrath"); return attack; } tmp_dt = TYPE_HIT; if (dt == gsn_dual_wield) wield = get_eq_char(ch,WEAR_DUAL_WIELD); else wield = get_eq_char(ch,WEAR_WIELD); if (wield != NULL) tmp_dt += wield->value[3]; else tmp_dt += ch->dam_type; if (tmp_dt > TYPE_HIT && tmp_dt < TYPE_HIT + MAX_DAMAGE_MESSAGE) attack = attack_table[tmp_dt - TYPE_HIT].noun; else { attack = attack_table[17].noun; } return attack; } int get_attack_number(CHAR_DATA *ch, int dt) { OBJ_DATA *wield; int tmp_dt; tmp_dt = TYPE_HIT; if (dt == gsn_dual_wield) wield = get_eq_char(ch,WEAR_DUAL_WIELD); else wield = get_eq_char(ch,WEAR_WIELD); if (wield != NULL) tmp_dt += wield->value[3]; else tmp_dt += ch->dam_type; if (tmp_dt > TYPE_HIT && tmp_dt < TYPE_HIT + MAX_DAMAGE_MESSAGE) return (tmp_dt - TYPE_HIT); return 1; } void do_gslay (CHAR_DATA * ch, char *argument) { CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; one_argument (argument, arg); if (arg[0] == '\0') { send_to_char ("Slay whom?\n\r", ch); return; } if ((victim = get_char_world (ch, arg)) == NULL) { send_to_char ("They aren't here.\n\r", ch); return; } if (ch == victim) { send_to_char ("Suicide is a mortal sin.\n\r", ch); return; } if (!IS_NPC (victim) && victim->level >= get_trust (ch)) { send_to_char ("You failed.\n\r", ch); return; } act ("You slay $M in accordance with your will!", ch, NULL, victim, TO_CHAR); act ("$n slays you according to his will!", ch, NULL, victim, TO_VICT); act ("$n slays $N in accordance with his will!", ch, NULL, victim, TO_NOTVICT); sprintf(buf, "{WAn Immortal {Gglares at {Y%s {Gand he explodes into a million pieces!{x", victim->name); do_echo(ch, buf); raw_kill (ch, victim ); do_help(ch, "rules" ); return; } void do_ambush( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; char buf[MAX_STRING_LENGTH]; int chance; one_argument( argument, arg); if (arg[0] == '\0') { send_to_char("Ambush whom?\n\r",ch); return; } if (ch->fighting != NULL) { send_to_char("But you're still fighting!\n\r",ch); return; } else if ((victim = get_char_room(ch,arg)) == NULL) { send_to_char("They aren't here.\n\r",ch); return; } else if (!IS_AFFECTED(ch, AFF_CAMOUFLAGE) || can_see(victim, ch) ) { send_to_char("But they can still see you.\n\r",ch); return; } if ( victim == ch ) { send_to_char("That's just not possible.\n\r",ch); return; } if ( is_safe( ch, victim ) ) return; if (check_chargeset(ch,victim)) {return;} chance = get_skill(ch,gsn_moving_ambush); if (victim->fighting != NULL && ( chance < 3 || ch->level < skill_table[gsn_moving_ambush].skill_level[ch->class])) { send_to_char("They are moving around too much to ambush.\n\r",ch); return; } if (victim->fighting != NULL && number_percent() >= chance) { send_to_char("You can't quite pin them down for your ambush.\n\r",ch); return; } if (!IS_NPC(ch) && !IS_NPC(victim) && victim->fighting == NULL) { sprintf(buf,"Help! I've been ambushed by %s!",PERS(ch,victim)); do_myell(victim,buf); } WAIT_STATE( ch, skill_table[gsn_ambush].beats ); if ( (number_percent( ) < get_skill(ch, gsn_ambush) ) || ( get_skill(ch,gsn_ambush) >= 2 && !IS_AWAKE(victim) ) ) { check_improve(ch,gsn_ambush, TRUE,1); multi_hit( ch, victim, gsn_ambush ); } else { check_improve(ch,gsn_ambush, FALSE,1); damage( ch, victim, 0, gsn_ambush, DAM_NONE, TRUE); } return; } bool spike_toed_boots(CHAR_DATA *ch) { OBJ_DATA *boots; boots = get_eq_char(ch, WEAR_FEET); if (boots != NULL && boots->pIndexData->vnum == 29801) return TRUE; return FALSE; } bool check_ward_diminution(CHAR_DATA *mage, CHAR_DATA *attacker, int dam, int type, int dt) { AFFECT_DATA *ward; AFFECT_DATA new_ward; int mod=0, duration=0; if (!is_affected(mage, gsn_ward_diminution)) return FALSE; if (number_percent() > 35) return FALSE; if (mage == attacker) return FALSE; if (type > 3) return FALSE; ward = affect_find(mage->affected, gsn_ward_diminution); if (!ward) return FALSE; mod = ward->modifier; duration = ward->duration; if (mod >= mage->max_hit / 2) { act("Your ward of diminution crumbles under the force of $N's attack.", mage, 0, attacker, TO_CHAR); act("$n's ward of diminution crumbles under the force of your attack.", mage, 0, attacker, TO_VICT); act("$n's ward of diminution crumbles under the force of $N's attack.", mage, 0, attacker, TO_NOTVICT); affect_strip(mage, gsn_ward_diminution); return FALSE; } mod += dam; affect_strip(mage, gsn_ward_diminution); init_affect(&new_ward); new_ward.where = TO_AFFECTS; new_ward.aftype = AFT_POWER; new_ward.type = gsn_ward_diminution; new_ward.level = 51; new_ward.duration = duration; new_ward.location = 0; new_ward.modifier = mod; new_ward.bitvector = 0; affect_to_char( mage, &new_ward ); act("Your ward absorbs the pain of $N's attack!", mage, 0, attacker, TO_CHAR); act("$n's ward absorbs the pain of your attack!", mage, 0, attacker, TO_VICT); act("$n's ward absorbs the pain of $N's attack!", mage, 0, attacker, TO_NOTVICT); return TRUE; } void check_paladin_combo(CHAR_DATA *ch, CHAR_DATA *victim) { int level = 0, sn = gsn_paladin_tech_counter_pc; AFFECT_DATA *af, *af_next, affect; OBJ_DATA *wield = get_eq_char(ch,WEAR_WIELD); for (af = ch->affected; af != NULL; af = af_next) { af_next = af->next; if (af->type == sn) level = af->level; } if (!is_affected(ch,sn)) return; if (level == 15 || level == 25 || level == 35 || level == 45 || level == 55 || level == 65) do_say(ch,"Raaaagh!!"); if (level == 15) { act("$n's $p glows softly.",ch,wield,victim,TO_VICT); act("$n's $p glows softly.",ch,wield,victim,TO_NOTVICT); act("$p glows softly.",ch,wield,victim,TO_CHAR); act("$n delivers a powerful slice!",ch,wield,victim,TO_VICT); act("$n delivers a powerful slice!",ch,wield,victim,TO_NOTVICT); act("You slash $N with great force!",ch,wield,victim,TO_CHAR); one_hit_new(ch,victim,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,300,"slice"); affect_strip(ch,sn); return; } if (level == 25) { act("$n's $p glows faintly.",ch,wield,victim,TO_VICT); act("$n's $p glows faintly.",ch,wield,victim,TO_NOTVICT); act("$p glows faintly.",ch,wield,victim,TO_CHAR); act("$n delivers a powerful slice!",ch,wield,victim,TO_VICT); act("$n delivers a powerful slice!",ch,wield,victim,TO_NOTVICT); act("You slash $N with great force!",ch,wield,victim,TO_CHAR); one_hit_new(ch,victim,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,500,"slice"); obj_cast_spell(skill_lookup("cure light"),51,ch,ch,wield); affect_strip(ch,sn); return; } if (level == 35) { act("$n's $p hums loudly.",ch,wield,victim,TO_VICT); act("$n's $p hums loudly.",ch,wield,victim,TO_NOTVICT); act("$p hums loudly.",ch,wield,victim,TO_CHAR); act("$n delivers a powerful strike of faith!",ch,wield,victim,TO_VICT); act("$n delivers a powerful strike of faith!",ch,wield,victim,TO_NOTVICT); act("You slash $N with immense force!",ch,wield,victim,TO_CHAR); one_hit_new(ch,victim,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,700,"strike of faith"); obj_cast_spell(skill_lookup("cure serious"),51,ch,ch,wield); if(number_percent()<50) { act("You feel your bones shatter under the force of $n's attack!",ch,wield,victim,TO_VICT); act("$N's bones shatter under the force of $n's attack!",ch,wield,victim,TO_NOTVICT); act("$N's bones shatter under the force of your attack!",ch,wield,victim,TO_CHAR); init_affect(&affect); affect.aftype = AFT_SKILL; affect.level = 51; affect.type = gsn_boneshatter; affect.duration = 7; affect.location = APPLY_DEX; affect.modifier = -5; affect_to_char(victim,&affect); affect.location = APPLY_STR; affect.modifier = -5; affect_to_char(victim,&affect); } affect_strip(ch,sn); return; } if (level == 45) { act("$n's $p glows with radiant light.",ch,wield,victim,TO_VICT); act("$n's $p glows with radiant light.",ch,wield,victim,TO_NOTVICT); act("$p glows with radiant light.",ch,wield,victim,TO_CHAR); act("$n delivers a powerful strike of fervor!",ch,wield,victim,TO_VICT); act("$n delivers a powerful strike of fervor!",ch,wield,victim,TO_NOTVICT); act("You slash $N with immense force!",ch,wield,victim,TO_CHAR); one_hit_new(ch,victim,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,850,"strike of fervor"); obj_cast_spell(skill_lookup("cure critical"),51,ch,ch,wield); if(number_percent()<50) { act("You feel frail.",ch,wield,victim,TO_VICT); act("$N seems more frail.",ch,wield,victim,TO_NOTVICT); act("$N seems more frail.",ch,wield,victim,TO_CHAR); init_affect(&affect); affect.aftype = AFT_SKILL; affect.type = gsn_soften; affect.level = 51; affect.duration = 3; affect.location = APPLY_DAM_MOD; affect.modifier = 10; affect_to_char(victim,&affect); } affect_strip(ch,sn); return; } if (level == 55) { act("$n's $p shines brightly.",ch,wield,victim,TO_VICT); act("$n's $p shines brightly.",ch,wield,victim,TO_NOTVICT); act("$p shines brightly.",ch,wield,victim,TO_CHAR); act("$n delivers a powerful strike of conviction!",ch,wield,victim,TO_VICT); act("$n delivers a powerful strike of conviction!",ch,wield,victim,TO_NOTVICT); act("You slash $N with immense force!",ch,wield,victim,TO_CHAR); one_hit_new(ch,victim,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,1000,"strike of conviction"); obj_cast_spell(skill_lookup("heal"),51,ch,ch,wield); if(number_percent()<50 && !is_affected(ch,gsn_boneshatter)) { act("You feel your bones shatter under the force of $n's attack!",ch,wield,victim,TO_VICT); act("$N's bones shatter under the force of $n's attack!",ch,wield,victim,TO_NOTVICT); act("$N's bones shatter under the force of your attack!",ch,wield,victim,TO_CHAR); init_affect(&affect); affect.aftype = AFT_SKILL; affect.level = 51; affect.type = gsn_boneshatter; affect.duration = 3; affect.location = APPLY_DEX; affect.modifier = -8; affect_to_char(victim,&affect); affect.location = APPLY_STR; affect.modifier = -8; affect_to_char(victim,&affect); } if(number_percent()<50 && !is_affected(ch,gsn_soften)) { act("You feel frail.",ch,wield,victim,TO_VICT); act("$N seems more frail.",ch,wield,victim,TO_NOTVICT); act("$N seems more frail.",ch,wield,victim,TO_CHAR); init_affect(&affect); affect.aftype = AFT_SKILL; affect.level = 51; affect.type = gsn_soften; affect.duration = 3; affect.location = APPLY_DAM_MOD; affect.modifier = 15; affect_to_char(victim,&affect); } affect_strip(ch,sn); return; } if (level == 65) { act("$n's $p pulses with power!",ch,wield,victim,TO_VICT); act("$n's $p pulses with power!",ch,wield,victim,TO_NOTVICT); act("$p pulses with power!",ch,wield,victim,TO_CHAR); act("$n delivers a powerful strike of virtue!",ch,wield,victim,TO_VICT); act("$n delivers a powerful strike of virtue!",ch,wield,victim,TO_NOTVICT); act("You slash $N with immense force!",ch,wield,victim,TO_CHAR); one_hit_new(ch,victim,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,1200,"strike of divine virtue"); obj_cast_spell(skill_lookup("rejuvenate"),51,ch,ch,wield); if (!is_affected(victim,gsn_boneshatter)) { init_affect(&affect); affect.aftype = AFT_INVIS; affect.level = 51; affect.type = gsn_boneshatter; affect.duration = 3; affect.aftype = AFT_SKILL; affect.location = APPLY_DEX; affect.modifier = -10; affect_to_char(victim,&affect); affect.aftype = AFT_SKILL; affect.location = APPLY_STR; affect.modifier = -10; affect_to_char(victim,&affect); } if (!is_affected(victim,gsn_soften)) { act("You feel frail.",ch,wield,victim,TO_VICT); act("$N seems more frail.",ch,wield,victim,TO_NOTVICT); act("$N seems more frail.",ch,wield,victim,TO_CHAR); init_affect(&affect); affect.aftype = AFT_SKILL; affect.type = gsn_soften; affect.level = 51; affect.duration = 3; affect.location = APPLY_DAM_MOD; affect.modifier = 20; affect_to_char(victim,&affect); } affect_strip(ch,sn); return; } if (level > 65) { act("The power running through your veins becomes too much to bare and you lose your focus!",ch,0,0,TO_CHAR); affect_strip(ch,sn); } return; } void do_swordplay(CHAR_DATA *ch, char *argument) { AFFECT_DATA *af, *af_next, affectCounter, affectLanded, initialAffect; OBJ_DATA *wield = get_eq_char(ch,WEAR_WIELD), *victimWield, *secondary; CHAR_DATA *victim = ch->fighting; int level = 0, sn = gsn_paladin_tech_counter_pc; if (get_skill(ch,gsn_swordplay) < 5) return send_to_char("You are not learned in two-handed swordplay.\n\r",ch); if ( wield == NULL || wield->value[0] != WEAPON_SWORD || ( wield->value[0] == WEAPON_SWORD && !IS_WEAPON_STAT(wield,WEAPON_TWO_HANDS) ) ) return send_to_char("You must be using a two-handed sword to use the paladin techniques.\n\r",ch); if (victim == NULL) return send_to_char("You aren't fighting anyone.\n\r",ch); if (argument[0] == '\0') return send_to_char("Which technique (Jab, Slash, Charge, Thrust, Downslash, Doubleslash, Whirl)?\n\r",ch); if (number_percent() > get_skill(ch,skill_lookup("swordplay"))) { act("$n attempts to execute a complex maneuver with $s sword, but botches it and fails.",ch,0,0,TO_ROOM); return send_to_char("You attempt to execute a swordplay maneuver, but botch it.\n\r",ch); WAIT_STATE(ch,PULSE_VIOLENCE*2); } check_improve(ch,gsn_swordplay,TRUE,4); victimWield = get_eq_char(victim,WEAR_WIELD); secondary = get_eq_char(victim,WEAR_DUAL_WIELD); for (af = ch->affected; af != NULL; af = af_next) { af_next = af->next; if (af->type == sn) level = af->level; } if (!is_affected(ch,sn)) { init_affect(&initialAffect); initialAffect.aftype = AFT_INVIS; initialAffect.level = 0; initialAffect.type = sn; initialAffect.duration = 1; affect_to_char(ch,&initialAffect); } if (!str_prefix(argument,"slash")) { act("Bringing $p around, $n slashes you across the stomach!",ch,wield,victim,TO_VICT); act("Bringing $p sword around, $n slashes $N across the stomach!",ch,wield,victim,TO_NOTVICT); act("Bringing $p around, you slash $N across the stomach!",ch,wield,victim,TO_CHAR); if(number_percent() < 20 && !is_affected(victim,gsn_cross_slice)) { act("$n's slash leaves a deep wound within you!",ch,0,victim,TO_VICT); act("$n's slash leaves a deep wound within $N!",ch,0,victim,TO_NOTVICT); act("Your slash leaves a deep wound within $N!",ch,0,victim,TO_CHAR); init_affect(&affectLanded); affectLanded.where = TO_AFFECTS; affectLanded.aftype = AFT_SKILL; affectLanded.type = gsn_cross_slice; affectLanded.name = "bleeding"; affectLanded.level = 25; affectLanded.duration = 10; affect_to_char(victim,&affectLanded); } one_hit_new(ch,victim,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,150,"slash"); affect_strip(ch,sn); init_affect(&affectCounter); affectCounter.aftype = AFT_INVIS; affectCounter.level = level + 3; affectCounter.type = sn; affectCounter.duration = 1; affect_to_char(ch,&affectCounter); send_to_char("You gain 3 combo points!\n",ch); check_paladin_combo(ch, victim); WAIT_STATE(ch,PULSE_VIOLENCE*1.5); } else if (!str_prefix(argument,"charge")) { act("Yelling a cry, $n charges towards you and uses $s momentum to deliver a powerful slice!",ch,0,victim,TO_VICT); act("Yelling a cry, $n charges towards $N and uses $s momentum to deliver a powerful slice!",ch,0,victim,TO_NOTVICT); act("Yelling a cry, you charge towards $N and use your momentum to deliver a powerful slice!",ch,0,victim,TO_CHAR); if(number_percent() < 30) { act("$n sees an opening in your defenses and charges into you, sending you flying!",ch,0,victim,TO_VICT); act("$n charges into $N, sending $S flying!",ch,0,victim,TO_NOTVICT); act("Seizing a moment of weakness, you charge into $N, sending $M flying!",ch,0,victim,TO_CHAR); WAIT_STATE(victim,PULSE_VIOLENCE*2); } one_hit_new(ch,victim,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,170,"charge"); affect_strip(ch,sn); init_affect(&affectCounter); affectCounter.aftype = AFT_INVIS; affectCounter.level = level + 6; affectCounter.type = sn; affectCounter.duration = 1; affect_to_char(ch,&affectCounter); send_to_char("You gain 6 combo points!\n",ch); check_paladin_combo(ch, victim); WAIT_STATE(ch,PULSE_VIOLENCE*2.5); } else if (!str_prefix(argument,"thrust")) { act("$n thrusts $p past your defenses and into your flesh!",ch,wield,victim,TO_VICT); act("$n thrusts $p past $N's defenses and into $S flesh!",ch,wield,victim,TO_NOTVICT); act("You thrust $p past $N's defenses and into $S flesh!",ch,wield,victim,TO_CHAR); if(number_percent() < 20 && victimWield != NULL && can_see_obj(ch,victimWield)) { if (IS_OBJ_STAT(victimWield,ITEM_NODISARM) || IS_OBJ_STAT(victimWield,ITEM_NOREMOVE) || is_affected(victim,gsn_spiderhands) || (is_affected(victim,gsn_unholy_affinity) && is_affected_obj(victimWield,gsn_unholy_bless))) { act("$n twists $p gracefully, but cannot disarm you! ",ch,wield,victim,TO_VICT); act("$n twists $p gracefully, but cannot disarm $N!",ch,wield,victim,TO_NOTVICT); act("Finding an opening, you twist $p, but cannot disarm $N!",ch,wield,victim,TO_CHAR); } else { act("$n twists $p gracefully and disarms you! ",ch,wield,victim,TO_VICT); act("$n twists $p gracefully and disarms $N!",ch,wield,victim,TO_NOTVICT); act("Finding an opening, you twist $p and disarm $N!",ch,wield,victim,TO_CHAR); obj_from_char( victimWield ); if ( IS_OBJ_STAT(victimWield,ITEM_NODROP) || IS_OBJ_STAT(victimWield,ITEM_INVENTORY) ) obj_to_char( victimWield, victim ); else { obj_to_room( victimWield, victim->in_room ); if (IS_NPC(victim) && victim->wait == 0 && can_see_obj(victim,victimWield)) get_obj(victim,victimWield,NULL); } reslot_weapon(victim); if (secondary != NULL) { unequip_char(victim,secondary); equip_char(victim,secondary,WEAR_WIELD); } } } one_hit_new(ch,victim,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,160,"thrust"); affect_strip(ch,sn); init_affect(&affectCounter); affectCounter.aftype = AFT_INVIS; affectCounter.level = level + 5; affectCounter.type = sn; affectCounter.duration = 1; affect_to_char(ch,&affectCounter); send_to_char("You gain 5 combo points!\n",ch); check_paladin_combo(ch, victim); WAIT_STATE(ch,PULSE_VIOLENCE*2); } else if (!str_prefix(argument,"downslash")) { act("$n swings $p diagonally across your legs!",ch,wield,victim,TO_VICT); act("$n swings $p diagonally across $N's legs!",ch,wield,victim,TO_NOTVICT); act("You swing $p diagonally across $N's legs!",ch,wield,victim,TO_CHAR); if(number_percent() < 20 && !is_affected(victim,gsn_hobble)) { act("A shooting pain runs through your thigh and you find yourself limping!",ch,0,victim,TO_VICT); act("$N's eyes widen as $S thigh begins pouring blood!",ch,0,victim,TO_NOTVICT); act("$N's eyes widen as $S thigh begins pouring blood!",ch,0,victim,TO_CHAR); init_affect(&affectLanded); affectLanded.where = TO_AFFECTS; affectLanded.aftype = AFT_SKILL; affectLanded.type = gsn_hobble; affectLanded.level = 51; affectLanded.duration = number_range(1,3); affect_to_char(victim,&affectLanded); affectLanded.location = APPLY_DEX; affectLanded.modifier = number_range(-6,-4); affect_to_char(victim,&affectLanded); } one_hit_new(ch,victim,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,130,"downslash"); affect_strip(ch,sn); init_affect(&affectCounter); affectCounter.aftype = AFT_INVIS; affectCounter.level = level + 4; affectCounter.type = sn; affectCounter.duration = 1; affect_to_char(ch,&affectCounter); send_to_char("You gain 4 combo points!\n",ch); check_paladin_combo(ch, victim); WAIT_STATE(ch,PULSE_VIOLENCE*1.75); } else if (!str_prefix(argument,"jab")) { act("$n quickly jabs you with $p!",ch,wield,victim,TO_VICT); act("$n quickly jabs $N with $p!",ch,wield,victim,TO_NOTVICT); act("You quickly jab $N with $p!",ch,wield,victim,TO_CHAR); one_hit_new(ch,victim,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,110,"jab"); affect_strip(ch,sn); init_affect(&affectCounter); affectCounter.aftype = AFT_INVIS; affectCounter.level = level + 2; affectCounter.type = sn; affectCounter.duration = 1; affect_to_char(ch,&affectCounter); send_to_char("You gain 2 combo points!\n",ch); check_paladin_combo(ch, victim); WAIT_STATE(ch,PULSE_VIOLENCE); } else if (!str_prefix(argument,"doubleslash")) { act("$n brings $p around and slashes you across the chest!",ch,wield,victim,TO_VICT); act("$n brings $p around and slashes $N across the chest!",ch,wield,victim,TO_NOTVICT); act("You bring $p around and slash $N across the chest!",ch,wield,victim,TO_CHAR); one_hit_new(ch,victim,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,150,"slash"); if (victim != NULL) { act("$n quickly spins and brings $p around a second time, slamming its flat into $N's head!",ch,wield,victim,TO_VICT); act("$n quickly spins and brings $p around a second time, slamming its flat into $N's head!",ch,wield,victim,TO_NOTVICT); act("You quickly spin and bring $p around a second time, slamming its flat into $N's head!",ch,wield,victim,TO_CHAR); one_hit_new(ch,victim,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,150,"smash"); } affect_strip(ch,sn); init_affect(&affectCounter); affectCounter.aftype = AFT_INVIS; affectCounter.level = level + 7; affectCounter.type = sn; affectCounter.duration = 1; affect_to_char(ch,&affectCounter); send_to_char("You gain 7 combo points!\n",ch); check_paladin_combo(ch, victim); WAIT_STATE(ch,PULSE_VIOLENCE*2.5); } else if (!str_prefix(argument,"whirl")) { CHAR_DATA *target, *targetLooper; int whirl; char message[MSL]; for (target = ch->in_room->people; target != NULL; target = targetLooper) { targetLooper = target->next; if (target->fighting == ch) { act("$n whirls and brings $p around, dicing $s enemies!",ch,wield,0,TO_ROOM); whirl = number_range(1,4); if (whirl == 1) sprintf(message,"$n slashes you across the chest!"); else if (whirl == 2) sprintf(message,"$n's slash catches you in the arm!"); else if (whirl == 3) sprintf(message,"$n's slash connects with your stomach!"); else if (whirl == 4) sprintf(message,"$n's slash cleaves into your leg!"); act(message,ch,wield,target,TO_VICT); act("You whirl and bring $p around, dicing your enemies!",ch,wield,target,TO_CHAR); one_hit_new(ch,target,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,100,"whirl"); affect_strip(ch,sn); } } init_affect(&affectCounter); affectCounter.aftype = AFT_INVIS; affectCounter.level = level + 8; affectCounter.type = sn; affectCounter.duration = 1; affect_to_char(ch,&affectCounter); send_to_char("You gain 8 combo points!\n",ch); check_paladin_combo(ch, victim); WAIT_STATE(ch,PULSE_VIOLENCE*3); } else return send_to_char("That is not a known swordplay maneuver.\n\r",ch); return; } void do_lash(CHAR_DATA *ch, char *argument) { char arg[MIL]; CHAR_DATA *victim; int chance; char buf[MSL]; OBJ_DATA *weapon; one_argument(argument,arg); if ((chance = get_skill(ch, gsn_lash)) == 0) { send_to_char("You don't have the skill to lash people's legs.\n\r",ch); return; } if (IS_NPC(ch) && IS_AFFECTED(ch,AFF_CHARM)) return; weapon = get_eq_char(ch,WEAR_WIELD); if (weapon == NULL || (weapon->value[0] != WEAPON_WHIP && weapon->value[0] != WEAPON_FLAIL) ) { chance -= 15; weapon = get_eq_char(ch,WEAR_DUAL_WIELD); } if (weapon == NULL) { send_to_char("You aren't wielding any weapon to lash with.\n\r",ch); return; } if (weapon->value[0] != WEAPON_WHIP && weapon->value[0] != WEAPON_FLAIL) { send_to_char("You need to be wielding a whip or flail to lash.\n\r",ch); return; } if (arg[0] == '\0') { victim = ch->fighting; if (victim == NULL) { send_to_char("But you aren't fighting anyone!\n\r",ch); return; } } else if ((victim = get_char_room(ch, arg)) == NULL) { send_to_char("They aren't here.\n\r",ch); return; } if (victim->position == POS_SLEEPING || victim->position == POS_RESTING) { act("$N isn't on $S feet.",ch,NULL,victim,TO_CHAR); return; } if (victim == ch) { send_to_char("You try to lash your feet and look clumsy doing it.\n\r",ch); return; } if (is_safe(ch, victim)) return; if (IS_AFFECTED(ch,AFF_CHARM) && ch->master == victim) { act("But $N is your friend!",ch,NULL,victim,TO_CHAR); return; } if (IS_SET(ch->off_flags,OFF_FAST) || IS_AFFECTED(ch,AFF_HASTE)) chance += 5; if (IS_SET(victim->off_flags,OFF_FAST) || IS_AFFECTED(victim,AFF_HASTE)) chance -= 15; chance += get_curr_stat(ch,STAT_DEX)/2; chance -= get_curr_stat(victim,STAT_DEX)/2; if (IS_AFFECTED(victim,AFF_FLYING)) chance -= dice(2,5); if (!IS_NPC(ch) && (ch->class == CLASS_CHANNELER || ch->class == CLASS_NECROMANCER || ch->class == CLASS_ELEMENTALIST) ) chance -= 10; chance += (ch->level - victim->level)*3; if (!IS_NPC(ch) && !IS_NPC(victim) && (victim->fighting == NULL || ch->fighting == NULL)) { sprintf(buf,"Help! %s is lashing me!",PERS(ch,victim)); do_myell(victim,buf); } if (number_percent() > chance) { act("$n lashes at $N's legs but misses.",ch,0,victim,TO_NOTVICT); act("$n lashes at your legs but misses.",ch,0,victim,TO_VICT); act("You lash at $N's legs but miss.",ch,0,victim,TO_CHAR); check_improve(ch,gsn_lash,FALSE,1); WAIT_STATE(ch,skill_table[gsn_lash].beats); return; } act("$n lashes $N's legs, sending $M crashing to the ground.",ch,0,victim,TO_NOTVICT); act("$n lashes your legs, sending you crashing to the ground.",ch,0,victim,TO_VICT); act("You lash $N's legs, sending $M crashing to the ground.",ch,0,victim,TO_CHAR); check_improve(ch,gsn_lash,TRUE,1); WAIT_STATE(victim,2 * PULSE_VIOLENCE); WAIT_STATE(ch,PULSE_VIOLENCE*2); damage(ch,victim,dice(2,7),gsn_lash,DAM_BASH,TRUE); check_cheap_shot(ch,victim); victim->position = POS_RESTING; return; } bool check_shield_magnetism( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { OBJ_DATA *weapon; float chance = 0; char *attack; char buf1[MSL], buf2[MSL]; if ( !IS_AWAKE(victim) ) return FALSE; if (!is_affected(victim, skill_lookup("ward of magnetism"))) return FALSE; weapon = (dt == gsn_dual_wield ? get_eq_char(ch, WEAR_DUAL_WIELD) : get_eq_char(ch, WEAR_WIELD)); if (weapon == NULL) return FALSE; if (!IS_METAL(weapon)) return FALSE; chance = 80; //Mobs are dumb and can't swap out weapons. They were getting totally crushed by this skill, so I'm going to reduce its effectiveness against them. Zornath if (!IS_NPC(ch)) chance -= weapon->weight * 3; else { chance -= weapon->weight * 6; if (chance < 15) chance = 15; } chance += get_curr_stat(ch, STAT_STR) * 1.5; chance = UMIN(chance, 95); if (number_percent() > chance) return FALSE; attack = get_dam_message(ch,dt); sprintf(buf1,"$n's %s is repelled by your ward of magnetism.", attack); sprintf(buf2,"Your %s is repelled by $N's ward of magnetism.", attack); act(buf1,ch,0,victim,TO_VICT); act(buf2,ch,0,victim,TO_CHAR); return TRUE; }