/*************************************************************************** * 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@efn.org) * * Gabrielle Taylor * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * ***************************************************************************/ #if defined(macintosh) #include <types.h> #else #include <sys/types.h> #endif #include <stdlib.h> #include <ctype.h> #include <stdio.h> #include <string.h> #include <time.h> #include "merc.h" #include "utils.h" #include "recycle.h" int hitchance; int diceroll; /* * Tables for wrath */ char *const pos_table[] = { "dead", "mortal", "incap", "stun", "sleep", "rest", "sit", "fight", "stand", NULL }; char *const eq_table[] = { "light", "finger_l", "finger_r", "neck_1", "neck_2", "torso", "head", "legs", "feet", "hands", "arms", "shield", "body", "waist", "wrist_l", "wrist_r", "wield", "hold", "float", NULL }; /* command procedures needed */ DECLARE_DO_FUN(do_backstab); DECLARE_DO_FUN(do_assassinate); DECLARE_DO_FUN(do_emote); DECLARE_DO_FUN(do_bash); DECLARE_DO_FUN(do_berserk); DECLARE_DO_FUN(do_trip); DECLARE_DO_FUN(do_dirt); DECLARE_DO_FUN(do_flee); DECLARE_DO_FUN(do_kick); DECLARE_DO_FUN(do_disarm); DECLARE_DO_FUN(do_get); DECLARE_DO_FUN(do_recall); DECLARE_DO_FUN(do_yell); DECLARE_DO_FUN(do_sacrifice); DECLARE_DO_FUN(do_kill); DECLARE_DO_FUN(do_circle); DECLARE_DO_FUN(do_whirl); DECLARE_DO_FUN(do_arial); DECLARE_DO_FUN(do_stand); DECLARE_DO_FUN(do_feed); DECLARE_DO_FUN(do_flee); DECLARE_DO_FUN(do_land); DECLARE_ATTACK_FUN(attack_hit); /* * Local functions. */ void check_assist args((CHAR_DATA * ch, CHAR_DATA * victim)); bool check_dodge args((CHAR_DATA * ch, CHAR_DATA * victim)); bool check_duck args((CHAR_DATA * ch, CHAR_DATA * victim, char *attack_type)); void check_killer args((CHAR_DATA * ch, CHAR_DATA * victim)); bool check_parry args((CHAR_DATA * ch, CHAR_DATA * victim)); bool check_shield_block args((CHAR_DATA * ch, CHAR_DATA * victim)); void dam_message args((CHAR_DATA * ch, CHAR_DATA * victim, int dam, int dt, bool immune)); void death_cry args((CHAR_DATA * ch, CHAR_DATA * victim)); void group_gain args((CHAR_DATA * ch, CHAR_DATA * victim)); int xp_compute args((CHAR_DATA * gch, CHAR_DATA * victim, int total_levels)); bool is_safe args((CHAR_DATA * ch, CHAR_DATA * victim)); void make_corpse args((CHAR_DATA * ch, bool can_loot)); void death_penalty args((CHAR_DATA * ch)); void raw_kill args((CHAR_DATA * ch, CHAR_DATA * victim)); 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 set_fighting args((CHAR_DATA * ch, CHAR_DATA * victim)); void disarm args((CHAR_DATA * ch, CHAR_DATA * victim)); bool has_number args((char *string)); /* * Control the fights going on. * Called periodically by update_handler. */ void violence_update(void) { CHAR_DATA *ch; CHAR_DATA *ch_next; CHAR_DATA *victim; for (ch = char_list; ch != NULL; ch = ch->next) { ch_next = ch->next; if ((victim = ch->fighting) == NULL || ch->in_room == NULL) continue; 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; if (IS_NPC(ch)) { if (HAS_TRIGGER(ch, TRIG_FIGHT)) mp_percent_trigger(ch, victim, NULL, NULL, TRIG_FIGHT); if (HAS_TRIGGER(ch, TRIG_HPCNT)) mp_hprct_trigger(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_AWAKE(rch) && rch->fighting == NULL) { /* 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; /* decrement the wait */ if (ch->desc == NULL) ch->wait = UMAX(0, ch->wait - PULSE_VIOLENCE); if (ch->desc == NULL) ch->daze = UMAX(0, ch->daze - PULSE_VIOLENCE); /* no attacks for stunnies -- just a check */ if (ch->position < POS_RESTING) return; if (dt == gsn_assassinate) { one_hit(victim, ch, dt); return; } if (IS_NPC(ch)) { mob_hit(ch, victim, dt); return; } one_hit(ch, victim, dt); if (ch->fighting != victim) return; if (IS_AFFECTED(ch, AFF_HASTE)) one_hit(ch, victim, dt); if (ch->fighting != victim || dt == gsn_backstab) return; chance = get_skill(ch, gsn_second_attack) / 2; if (number_percent() < chance) { one_hit(ch, victim, dt); check_improve(ch, gsn_second_attack, TRUE, 5); if (ch->fighting != victim) return; } chance = get_skill(ch, gsn_third_attack) / 4; if (number_percent() < chance) { one_hit(ch, victim, dt); check_improve(ch, gsn_third_attack, TRUE, 6); if (ch->fighting != victim) return; } chance = get_skill(ch, gsn_fourth_attack) / 4; if (number_percent() < chance) { one_hit(ch, victim, dt); check_improve(ch, gsn_fourth_attack, TRUE, 6); if (ch->fighting != victim) return; } chance = get_skill(ch, gsn_fifth_attack) / 4; if (number_percent() < chance) { one_hit(ch, victim, dt); check_improve(ch, gsn_fifth_attack, TRUE, 6); if (ch->fighting != victim) return; } chance = get_skill(ch, gsn_sixth_attack) / 4; if (number_percent() < chance) { one_hit(ch, victim, dt); check_improve(ch, gsn_sixth_attack, TRUE, 6); if (ch->fighting != victim) return; } return; } /* procedure for all mobile attacks */ /* Grb: deprecated. mobs attack just like players. left this here for historical reasons */ void mob_hit(CHAR_DATA * ch, CHAR_DATA * victim, int dt) { one_hit(ch, victim, dt); return; } /* * dt is the pointer to the element id in the attack_table */ int correct_dt(int dt, CHAR_DATA * ch, OBJ_DATA * 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; } return dt; } /* * dam_type is the DAM_TYPE for the elemener in the attack_table */ int calc_dam_type(CHAR_DATA * ch, OBJ_DATA * wield, int dt) { int dam_type; if (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 < 0) dam_type = DAM_BASH; return dam_type; } /* * Calc damage from a hit. * Returns total damage, including from, etc special weapon flags */ int calc_damage(CHAR_DATA * ch, CHAR_DATA * victim, OBJ_DATA * wield, int sn, int skill, int dt) { int dam; if (IS_NPC(ch) && wield == NULL) 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; /* sharpness! */ if (IS_WEAPON_STAT(wield, WEAPON_SHARP) && (wield->condition <= (wield->level * 2))) { int percent; if ((percent = number_percent()) <= (skill / 8)) dam = 2 * dam + (dam * 2 * percent / 100); /* Condition Flagging! Wdl */ wield->condition++; if (wield->condition == (wield->level * 2)) { REMOVE_BIT(wield->value[4], WEAPON_SHARP); send_to_char ("{gYour weapon seems to dull slightly...{x\r\n", ch); } } } else dam = number_range(1 + 4 * skill / 100, 2 * ch->level / 3 * skill / 100); } /* * Bonuses. */ if (get_skill(ch, gsn_enhanced_damage) > 0) { diceroll = number_percent(); if (diceroll <= get_skill(ch, gsn_enhanced_damage)) { check_improve(ch, gsn_enhanced_damage, TRUE, 6); dam += (3 * (ch->level)) / 20; } } if (get_skill(ch, gsn_ultra_damage) > 0) { diceroll = number_percent(); if (diceroll <= get_skill(ch, gsn_ultra_damage)) { check_improve(ch, gsn_ultra_damage, TRUE, 6); dam += (2 * (ch->level)) / 9; } } if (!IS_AWAKE(victim)) dam *= 2; else if (victim->position < POS_FIGHTING) dam = dam * 3 / 2; /* Backstab Damage */ if (dt == gsn_backstab && wield != NULL) { dam *= 1 + (ch->level / 16); } dam += GET_DAMROLL(ch) * UMIN(100, skill) / 100; if (wield != NULL && ch->fighting == victim) { if (IS_WEAPON_STAT(wield, WEAPON_POISON)) { int level; 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)) { 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); af.where = TO_AFFECTS; af.type = gsn_poison; af.level = level * 3 / 4; af.duration = level / 2; af.location = APPLY_STR; af.modifier = -1; af.bitvector = AFF_POISON; 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->level == 0 || poison->duration == 0) act("The poison on $p has worn off.", ch, wield, NULL, TO_CHAR); } return dam; } if (IS_WEAPON_STAT(wield, WEAPON_VAMPIRIC)) { dam += number_range(1, wield->level / 2 + 1); 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(ch, victim, dam, 0, DAM_NEGATIVE, FALSE); ch->alignment = UMAX(-1000, ch->alignment - 1); ch->hit += dam / 2; return dam; } if (IS_WEAPON_STAT(wield, WEAPON_HOLY)) { dam += number_range(1, wield->level / 5 + 1); act("$p absorbs life force from $n.", victim, wield, NULL, TO_ROOM); act("You feel $p taking life force away from you.", victim, wield, NULL, TO_CHAR); ch->alignment = UMAX(-1000, ch->alignment + 1); if (ch->alignment > 1000) { ch->alignment = 1000; } return dam; } if (IS_WEAPON_STAT(wield, WEAPON_VORPAL)) { dam += number_range(1, wield->level / 5 + 1); act("$p makes $n weak and tired!", victim, wield, NULL, TO_ROOM); act("You feel $p draining your strength!", victim, wield, NULL, TO_CHAR); victim->move -= dam / 2; if (victim->move < 1) { do_land(victim, ""); victim->move = 0; } return dam; } if (IS_WEAPON_STAT(wield, WEAPON_FLAMING)) { 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); return dam; } if (IS_WEAPON_STAT(wield, WEAPON_FROST)) { 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); return dam; } if (IS_WEAPON_STAT(wield, WEAPON_SHOCKING)) { 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); return dam; } if (IS_WEAPON_STAT(wield, WEAPON_QUICKPOISON)) { dam += ((wield->level * 18) / 10); act("$n is infected by $p.", victim, wield, NULL, TO_ROOM); act("poison is flooding into your body", victim, wield, NULL, TO_CHAR); return dam; } } return dam; } /* * chance-to-hit calculations */ int calc_hit_chance(int hitchance, CHAR_DATA * ch, CHAR_DATA * victim, int skill, int dt, int dam_type) { int victim_ac; #ifdef DEBUG char buf[MAX_STRING_LENGTH]; #endif hitchance = 50; hitchance += ((ch->level - victim->level) / 5); #ifdef DEBUG sprintf(buf, "{YBased on level, chance to hit is %d{x\r\n", hitchance); send_to_char(buf, ch); #endif // size - smaller opponents are harder to hit hitchance -= ((ch->size - victim->size) * 3); #ifdef DEBUG sprintf(buf, "{YBased on size, chance to hit is %d{x\r\n", hitchance); send_to_char(buf, ch); #endif // fatigue - we fight better when fresh // should reduce hit chance by 1 for every % below 50 char's mv is // should increase hit chance by 1 for every % above 90 char's mv is //FIXME: hitchance += (20 - ((ch->max_move - ch->move) / 25)); #ifdef DEBUG sprintf(buf, "{YBased on fatigue, chance to hit is %d{x\r\n", hitchance); send_to_char(buf, ch); #endif // strength - plus to hit if stronger than opponent hitchance += (get_curr_stat(ch, STAT_STR) - get_curr_stat(victim, STAT_STR)); #ifdef DEBUG sprintf(buf, "{YBased on str, chance to hit is %d{x\r\n", hitchance); send_to_char(buf, ch); #endif // dexterity hitchance += (get_curr_stat(ch, STAT_DEX) - get_curr_stat(victim, STAT_DEX)); #ifdef DEBUG sprintf(buf, "{YBased on dex, chance to hit is %d{x\r\n", hitchance); send_to_char(buf, ch); #endif // int hitchance += (get_curr_stat(ch, STAT_INT) - get_curr_stat(victim, STAT_INT)); #ifdef DEBUG sprintf(buf, "{YBased on int, chance to hit is %d{x\r\n", hitchance); send_to_char(buf, ch); #endif // wisdom hitchance += (get_curr_stat(ch, STAT_WIS) - get_curr_stat(victim, STAT_WIS)); #ifdef DEBUG sprintf(buf, "{YBased on wis, chance to hit is %d{x\r\n", hitchance); send_to_char(buf, ch); #endif // burden hitchance += (100 - (get_carry_weight(ch) / can_carry_w(ch) * 100)); #ifdef DEBUG sprintf(buf, "{YBased on burden, chance to hit is %d{x\r\n", hitchance); send_to_char(buf, ch); #endif // skill bonus hitchance += (skill / 10); #ifdef DEBUG sprintf(buf, "{YBased on skill, chance to hit is %d{x\r\n", hitchance); send_to_char(buf, ch); #endif // hitroll hitchance += ch->hitroll; #ifdef DEBUG sprintf(buf, "{YAfter HR check, chance to hit is %d{x\r\n", hitchance); send_to_char(buf, ch); #endif if (IS_AFFECTED(ch, AFF_BLIND)) hitchance -= 125; if (IS_AFFECTED(victim, AFF_BLIND)) hitchance += 60; if (dt == gsn_backstab) { hitchance -= 6 * (100 - get_skill(ch, gsn_backstab)); } switch (dam_type) { case (DAM_PIERCE): victim_ac = GET_AC(victim, AC_PIERCE) / 25; break; case (DAM_BASH): victim_ac = GET_AC(victim, AC_BASH) / 25; break; case (DAM_SLASH): victim_ac = GET_AC(victim, AC_SLASH) / 25; break; default: victim_ac = GET_AC(victim, AC_EXOTIC) / 25; break; }; if (victim->position < POS_FIGHTING) victim_ac += 12; if (victim->position < POS_RESTING) victim_ac += 20; hitchance += victim_ac / 100; #ifdef DEBUG sprintf(buf, "{YOpponent's AC is %d{x\r\n", victim_ac); send_to_char(buf, ch); sprintf(buf, "{YAfter AC check, chance to hit is %d{x\r\n", hitchance); send_to_char(buf, ch); #endif if (IS_DWARF(ch) && ch->pcdata->condition[COND_DRUNK] > 10) hitchance += ch->pcdata->condition[COND_DRUNK] / 3; else if (!IS_DWARF(ch) && !IS_NPC(ch) && ch->pcdata->condition[COND_DRUNK] > 10) hitchance -= ch->pcdata->condition[COND_DRUNK] / 3; #ifdef DEBUG sprintf(buf, "{YAfter drunk check, chance to hit is %d{x\r\n", hitchance); send_to_char(buf, ch); #endif /* turf bonus */ if (ch->clan) { if (ch->in_room->turf_clan && (ch->in_room->turf_clan == ch->clan)) { hitchance += UMIN(20, (ch->in_room->turf_level / 10)); } else if (ch->in_room->turf_clan && (ch->in_room->turf_clan != ch->clan)) { hitchance -= UMIN(20, (ch->in_room->turf_level / 10)); } } if (hitchance < 0) hitchance = 0; #ifdef DEBUFG sprintf(buf, "{YAfter turf check, chance to hit is %d{x\r\n", hitchance); send_to_char(buf, ch); #endif return hitchance; } int execute_attack(CHAR_DATA * ch, int attack, CHAR_DATA * victim, OBJ_DATA * wield, int sn, int skill, int dam_type, int dt) { ATTACK_FUN *attack_fun; int damroll, dam; attack_fun = attack_table[attack].function; ch->cwait += attack_table[attack].cwait; damroll *= attack_table[attack].dr_mod; dam += (ch->damroll / 5); //FIXME: modify attacker's AC attack_fun(ch, victim, dt); dam = calc_damage(ch, victim, wield, sn, skill, dt); damage(ch, victim, dam, dt, dam_type, TRUE); return dam; } /* * One attack stack * The meat of the attacks has been moved to attacks.c */ void one_hit(CHAR_DATA * ch, CHAR_DATA * victim, int dt) { OBJ_DATA *wield; int sn, skill; int dam_type; int current_attack; char buf[MAX_STRING_LENGTH]; sn = -1; //just in case if (victim == ch || ch == NULL || victim == NULL || victim->position == POS_DEAD || ch->in_room != victim->in_room) return; // execute an attack stack, one at a time, until out of attacks or time. while ((ch->cwait + attack_table[ch->current_attack + 1].cwait) < COMBAT_WAIT_LENGTH) { //FIXME: Make sure to check for zero-time attacks so this can't hang if (victim == ch || ch == NULL || victim == NULL || victim->position == POS_DEAD || ch->in_room != victim->in_room) break; // if ch has no attack stack set, use default attack.. ("hit") if (!ch->current_attack && ch->attack_stack[ch->current_attack] == -1) current_attack = 0; if (ch->attack_stack[ch->current_attack] == -1) ch->current_attack = 0; current_attack = ch->attack_stack[ch->current_attack]; hitchance = 0; #ifdef DEBUG sprintf(buf, "{Ycwait is %d{x\r\n", ch->cwait); send_to_char(buf, ch); #endif // decide if we're attacking with a weapon or hand to hand wield = get_eq_char(ch, WEAR_WIELD); dt = correct_dt(dt, ch, wield); dam_type = calc_dam_type(ch, wield, dt); // and set up the skill skill = get_weapon_skill(ch, get_weapon_sn(ch)); // decide % chance to hit hitchance = calc_hit_chance(hitchance, ch, victim, skill, dt, dam_type); diceroll = number_range(0, 99); #ifdef DEBUG sprintf(buf, "{YDiceroll was %d{x\r\n", diceroll); send_to_char(buf, ch); #endif if (diceroll == 0 || (diceroll != 100 && diceroll > hitchance)) { // whiffed tail_chain(); return; } #ifdef DEBUG sprintf(buf, "{YExecuting attack %d\r\n", current_attack); send_to_char(buf, ch); #endif // kick some ass execute_attack(ch, current_attack, victim, wield, sn, skill, dam_type, dt); if (ch->attack_stack[ch->current_attack] == -1 || ch->attack_stack[ch->current_attack++] == -1) ch->current_attack = 0; } // while (GET_CWAIT (ch) + #ifdef DEBUG sprintf(buf, "{YResetting CWAIT..\r\n"); send_to_char(buf, ch); #endif ch->cwait = 0; tail_chain(); return; } /* * Inflict damage from a hit. */ bool damage(CHAR_DATA * ch, CHAR_DATA * victim, int dam, int dt, int dam_type, bool show) { //char buf[MAX_STRING_LENGTH]; char buf4[MAX_STRING_LENGTH]; OBJ_DATA *corpse; bool immune; bool displaced = FALSE; //displace spell if (victim->position == POS_DEAD) return FALSE; if (victim != ch) { /* * Certain attacks are forbidden. * Most other attacks are returned. */ if (is_safe(ch, victim)) return FALSE; check_killer(ch, victim); if (victim->position > POS_STUNNED) { if (!is_same_group(ch, victim)) { if (victim->fighting == NULL) { if (ch->master) { int percent = number_range(1, 12); if (percent < 6) { set_fighting(victim, ch->master); } else { set_fighting(victim, ch); } } else { set_fighting(victim, ch); } if (victim->timer <= 4) victim->position = POS_FIGHTING; } } } if (victim->position > POS_STUNNED) { if (!is_same_group(ch, victim)) { if (ch->fighting == NULL) set_fighting(ch, victim); } } /* * More charm stuff. */ if (victim->master == ch) stop_follower(victim); } /* * Inviso attacks ... not. */ if (IS_AFFECTED(ch, AFF_INVISIBLE)) { affect_strip(ch, gsn_invis); affect_strip(ch, gsn_mass_invis); REMOVE_BIT(ch->affected_by, AFF_INVISIBLE); act("$n fades into existence.", ch, NULL, NULL, TO_ROOM); send_to_char("You fade into existence.\n\r", ch); } /* * Damage modifiers. */ if IS_DWARF (victim) { if (dam > 1 && victim->pcdata->condition[COND_DRUNK] > 10) dam -= dam / 5; if (dam < 0) dam = 0; } if (dam > 1 && IS_AFFECTED(victim, AFF_SANCTUARY)) dam = (3 * dam) / 4; if (dam > 1 && IS_AFFECTED(victim, AFF_HEAVENLY_SANCTUARY)) dam = (23 * dam) / 25; if (dam > 1 && ((IS_AFFECTED(victim, AFF_PROTECT_EVIL) && IS_EVIL(ch)) || (IS_AFFECTED(victim, AFF_PROTECT_GOOD) && IS_GOOD(ch)))) dam = (22 * dam) / 25; if (ch->clan) { if (ch->in_room->turf_clan && (ch->in_room->turf_clan == ch->clan)) { dam += URANGE(0, (ch->in_room->turf_level / 10), 20); } else if (ch->in_room->turf_clan && (ch->in_room->turf_clan != ch->clan)) { dam -= URANGE(0, (ch->in_room->turf_level / 10), 20); } } if (dam < 0) dam = 0; immune = FALSE; /* * Check for parry, dodge, shield block, and displaced */ if (dt >= TYPE_HIT && ch != victim && dt != gsn_whirl && dt != gsn_circle) { if (check_parry(ch, victim)) return FALSE; if (check_dodge(ch, victim)) return FALSE; if (check_shield_block(ch, victim)) return FALSE; //Check if displaced if (is_affected(victim, skill_lookup("displace"))) { if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) { //You're hitting the displaced version displaced = TRUE; if (IS_NPC(victim) || !IS_SET(victim->act, PLR_AUTODEFENSE)) act("{y$n hits your displaced version.{x", ch, NULL, victim, TO_VICT); if (IS_NPC(ch) || !IS_SET(ch->act, PLR_AUTODEFENSE)) act("{yYour hit goes right through $N.{x", ch, NULL, victim, TO_CHAR); return FALSE; } } } switch (check_immune(victim, dam_type)) { case (IS_IMMUNE): immune = TRUE; dam = 0; break; case (IS_RESISTANT): dam = (21 * dam) / 25; break; case (IS_VULNERABLE): dam = (113 * dam) / 100; break; } if (show) dam_message(ch, victim, dam, dt, immune); if (dam <= 0) return FALSE; /* * Hurt the victim. * Inform the victim of his new state. */ victim->hit -= dam; if (!IS_NPC(victim) && victim->level >= LEVEL_IMMORTAL && victim->hit < 1) victim->hit = 1; if (IS_VAMPIRE(victim) && victim->hit < 1 && victim->blood > 5) { send_to_char("Your partial immortality has saved you!\n\r", victim); act("$n's partial immortality has saved $m!", victim, NULL, NULL, TO_ROOM); if ((victim->blood > 4) && (!DAYTIME)) { victim->hit = victim->blood * 3; victim->blood = 3; } else { if ((victim->blood > 4) && (DAYTIME)) { victim->hit = victim->blood * 2; victim->blood = 3; } } } 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("{R$n is DEAD!!{x", victim, 0, 0, TO_ROOM); break; default: if (dam > victim->max_hit / 4) send_to_char("{RThat really did HURT!{x\n\r", victim); if (victim->hit < victim->max_hit / 4) { send_to_char("{RYou sure are BLEEDING!{x\n\r", victim); create_blood_pool(victim); } break; } /* * Sleep spells and extremely wounded folks. */ if (!IS_AWAKE(victim)) stop_fighting(victim, FALSE); /* * Payoff for killing things. */ // may kill imms in arena. if (victim->position == POS_DEAD || (IS_IMMORTAL(victim) && (victim->hit < 2) && (victim->arena))) { // fake death in the arena, no corpse, no pain if (victim->arena == global_last_arena_id && ch->arena) { stop_fighting(ch, FALSE); stop_fighting(victim, FALSE); sprintf(buf4, "\r\n{c[{RARENA OF DEATH{c] %s just killed %s in the arena!{x", ch->name, victim->name); announce(buf4, ch); arena_death(victim); return FALSE; } 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 : ch->name), ch->in_room->vnum); log_string(log_buf); /* For PKill, dying penalty is done in group_gain */ if (IS_NPC(ch)) { /* * Dying penalty: * 2/3 way back to previous level. */ gain_exp(victim, -250); } sprintf(log_buf, "%s has been killed by %s at %s [room %ld]", (IS_NPC(victim) ? victim->short_descr : victim->name), (IS_NPC(ch) ? ch->short_descr : ch->name), ch->in_room->name, ch->in_room->vnum); } if (IS_NPC(victim)) wiznet(log_buf, NULL, NULL, WIZ_MOBDEATHS, 0, 0); else wiznet(log_buf, NULL, NULL, WIZ_DEATHS, 0, 0); /* * Death trigger */ /* RT new auto commands */ 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 if (IS_VAMPIRE(ch)) { do_feed(ch, "corpse"); } 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 (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)) do_flee(victim, ""); } if (!IS_NPC(victim) && victim->hit > 0 && victim->hit <= victim->wimpy && victim->wait < PULSE_VIOLENCE / 2) do_flee(victim, ""); tail_chain(); return TRUE; } bool is_safe(CHAR_DATA * ch, CHAR_DATA * victim) { if (victim->in_room == NULL || ch->in_room == NULL) return TRUE; if (victim->fighting == ch || victim == ch) return FALSE; if (IS_IMMORTAL(ch) || IS_IMMORTAL(victim)) return FALSE; /* killing mobiles */ if (IS_NPC(victim)) { /* safe room? */ if (IS_SET(victim->in_room->room_flags, ROOM_SAFE)) { send_to_char("Not in this room.\n\r", ch); return TRUE; } if (victim->pIndexData->pShop != NULL) { send_to_char("No killing shopkeepers.\n\r", ch); 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_REPAIR) || IS_SET(victim->act, ACT_NO_ATTACK) || IS_SET(victim->act, ACT_IS_HEALER) || IS_SET(victim->act, ACT_BANKER)) { send_to_char("No killing healers, trainers, etc.\n\r", ch); return TRUE; } if (!IS_NPC(ch)) { /* no pets */ if (IS_SET(victim->act, ACT_PET)) { act("But $N looks so cute and cuddly...", ch, NULL, victim, TO_CHAR); return TRUE; } /* no charmed creatures unless owner */ if (IS_AFFECTED(victim, AFF_CHARM) && (ch != victim->master)) { send_to_char("You don't own that monster.\n\r", ch); return TRUE; } if (IS_AFFECTED(ch, AFF_CHARM) && IS_AFFECTED(victim, AFF_CHARM)) { return TRUE; } } } /* killing players */ else { /* NPC doing the killing */ if (IS_NPC(ch)) { /* safe room check */ if (IS_SET(victim->in_room->room_flags, ROOM_SAFE)) { send_to_char("Not in this room.\n\r", ch); return TRUE; } /* charmed mobs and pets cannot attack players while owned */ if (IS_AFFECTED(ch, AFF_CHARM) && ch->master != NULL && ch->master->fighting != victim) { send_to_char("Players are your friends!\n\r", ch); return TRUE; } } /* player doing the killing */ else { /* Have to be a PKILL to kill */ if (!IS_SET(ch->act, PLR_PKILL) && (!ch->tmp_pkill)) { send_to_char ("You must type {YPKILL{x twice before you can kill or steal from anyone.\n\r", ch); return TRUE; } /* Not allowed killing NON-Pkillers */ if (!IS_SET(victim->act, PLR_PKILL) && (!victim->tmp_pkill)) { send_to_char("No killing non-pkillers.\n\r", ch); return TRUE; } if (IS_SET(victim->in_room->room_flags, ROOM_SAFE)) { send_to_char("You're in a safe room.\n\r", ch); return TRUE; } if (!ch->tmp_pkill && !victim->tmp_pkill) { if (ch->level > victim->level + 25) { send_to_char("Pick on someone your own size!\n\r", ch); return TRUE; } else if (ch->level < victim->level - 25) { send_to_char("Pick on someone your own size!\n\r", ch); 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; /* 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_BANKER)) 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_SET(ch->act, PLR_PKILL)) return TRUE; if (!IS_SET(victim->act, PLR_PKILL)) return TRUE; // PK range check if ((IS_SET(ch->act, PLR_PKILL) && (IS_SET(victim->act, PLR_PKILL)) && (victim->level < (ch->level - 25)))) return TRUE; if (IS_SET(victim->in_room->room_flags, ROOM_SAFE)) return TRUE; } } return FALSE; } /* * See if an attack justifies a KILLER flag. */ void check_killer(CHAR_DATA * ch, CHAR_DATA * victim) { /* This function is currenly unused. Taken out by Bloodbath. */ return; } /* * Check for parry. */ bool check_parry(CHAR_DATA * ch, CHAR_DATA * victim) { int chance; if (!IS_AWAKE(victim)) return FALSE; if (get_skill(victim, gsn_parry) == 0) return FALSE; /*Mobs don't need weapons to parry anymore. Only players do. Severhand */ if (victim->pIndexData == NULL) if (get_eq_char(victim, WEAR_WIELD) == NULL) { return FALSE; } chance = get_skill(victim, gsn_parry); if ((!can_see(ch, victim)) && (!IS_NPC(ch))) chance *= 2; if (!can_see(ch, victim)) chance = (chance * 3) / (chance * 2); if (!can_see(victim, ch)) chance /= 2; if (number_percent() >= ((chance - 60) / 2)) return FALSE; /*if (number_percent() >= chance + victim->level - ch->level) return FALSE; */ if (IS_NPC(victim) || !IS_SET(victim->act, PLR_AUTODEFENSE)) act("{yYou parry $n's attack.{x", ch, NULL, victim, TO_VICT); if (IS_NPC(ch) || !IS_SET(ch->act, PLR_AUTODEFENSE)) act("{y$N parries your attack.{x", ch, NULL, victim, TO_CHAR); check_improve(victim, gsn_parry, TRUE, 6); return TRUE; } /* * Check for shield block. */ bool check_shield_block(CHAR_DATA * ch, CHAR_DATA * victim) { int chance; if (!IS_AWAKE(victim)) return FALSE; if (get_skill(victim, gsn_shield_block) == 0) return FALSE; chance = get_skill(victim, gsn_shield_block); if ((!can_see(ch, victim)) && (!IS_NPC(ch))) chance *= 2; if (!can_see(ch, victim)) chance *= 1, 5; if (!can_see(victim, ch)) chance /= 2; chance += get_curr_stat(victim, STAT_STR); chance -= get_curr_stat(ch, STAT_STR); if (get_eq_char(victim, WEAR_SHIELD) == NULL) return FALSE; if (number_percent() >= ((chance - 40) / 2)) return FALSE; /* if (number_percent() >= chance + victim->level - ch->level) return FALSE;*/ if (IS_NPC(victim) || !IS_SET(victim->act, PLR_AUTODEFENSE)) act("{yYou block $n's attack with your shield.{x", ch, NULL, victim, TO_VICT); if (IS_NPC(ch) || !IS_SET(ch->act, PLR_AUTODEFENSE)) act("{y$N blocks your attack with a shield.{x", ch, NULL, victim, TO_CHAR); check_improve(victim, gsn_shield_block, TRUE, 6); return TRUE; } /* * Check for dodge. */ bool check_dodge(CHAR_DATA * ch, CHAR_DATA * victim) { int chance; if (!IS_AWAKE(victim)) return FALSE; if (get_skill(victim, gsn_dodge) == 0) return FALSE; chance = get_skill(victim, gsn_dodge); if ((!can_see(ch, victim)) && (!IS_NPC(ch))) chance *= 2; if (!can_see(ch, victim)) chance *= 1, 5; if (!can_see(victim, ch)) chance /= 2; chance -= get_curr_stat(ch, STAT_DEX); chance += get_curr_stat(victim, STAT_DEX); if (number_percent() >= ((chance - 60) / 2)) return FALSE; /* if (number_percent() >= chance + victim->level - ch->level) return FALSE;*/ if (IS_NPC(victim) || !IS_SET(victim->act, PLR_AUTODEFENSE)) act("{yYou dodge $n's attack.{x", ch, NULL, victim, TO_VICT); if (IS_NPC(ch) || !IS_SET(ch->act, PLR_AUTODEFENSE)) act("{y$N dodges your attack.{x", ch, NULL, victim, TO_CHAR); check_improve(victim, gsn_dodge, TRUE, 6); 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 ((victim->desc != NULL) && (victim->position == POS_MORPHED)) { 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) { if (ch->fighting != NULL) { bug("Set_fighting: already fighting", 0); return; } if (IS_AFFECTED(ch, AFF_SLEEP)) affect_strip(ch, gsn_sleep); ch->fighting = victim; ch->position = POS_FIGHTING; return; } 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; } /* * Take 1 point from the highest modified stat on death. * Reset char's affs and whatnot. * Called by raw_kill and kill_self. */ void death_penalty(CHAR_DATA * ch) { int h, i, j = 0, highstat = 0; if (IS_NPC(ch)) { ch->pIndexData->killed++; kill_table[URANGE(0, ch->level, MAX_LEVEL - 1)].killed++; extract_char(ch, TRUE); return; } ch->pcdata->deaths++; /* Increase deaths by 1 */ if (ch->pcdata->deaths % 10 == 0) { for (h = 0; h <= (ch->level / 50); h++) { for (i = 0; i < MAX_STATS; i++) { if (ch->perm_stat[i] > highstat) { highstat = ch->perm_stat[i]; j = i; } } } ch->perm_stat[j] -= 1; /*Decrease Stat by 1 */ } extract_char(ch, FALSE); while (ch->affected) affect_remove(ch, ch->affected); ch->affected_by = ch->race->aff; for (i = 0; i < 4; i++) ch->armor[i] = 100; ch->position = POS_RESTING; ch->hit = 1; ch->mana = 1; ch->move = 1; if (IS_VAMPIRE(ch)) ch->blood = UMAX(10, ch->blood); if (ch->max_mana > 10) ch->max_mana -= 3; if (ch->max_move > 10) ch->max_move -= 3; if (ch->max_hit > 10) ch->max_hit -= 3; if (!IS_WRAITH(ch) && !IS_VAMPIRE(ch)) { ch->pcdata->condition[COND_HUNGER] = 12; ch->pcdata->condition[COND_THIRST] = 12; } ch->pcdata->condition[COND_DRUNK] = 0; ch->move = ch->max_move / 75; ch->mana = ch->max_mana / 75; if ((ch->clan == 2) || (ch->clan == 9) || (ch->clan == 10) || (ch->clan == 7) || (ch->clan == 4) || (ch->clan == 3)) { SET_BIT(ch->comm, PLR_PKILL); } return; } /* * Make a corpse out of a character. */ void make_corpse(CHAR_DATA * ch, bool can_loot) { char buf[MAX_STRING_LENGTH]; OBJ_DATA *corpse; OBJ_DATA *obj; OBJ_DATA *obj_next; char *name; if (IS_NPC(ch)) { name = ch->short_descr; corpse = create_object(get_obj_index(OBJ_VNUM_CORPSE_NPC), 0); corpse->timer = number_range(3, 6); if (ch->gold > 0) { obj_to_obj(create_money(ch->gold), corpse); ch->gold = 0; } corpse->cost = 0; } else { name = ch->name; corpse = create_object(get_obj_index(OBJ_VNUM_CORPSE_PC), 0); corpse->timer = number_range(25, 40); if (!can_loot) REMOVE_BIT(ch->act, PLR_CANLOOT); if (!IS_SET(ch->act, PLR_PKILL)) { corpse->owner = str_dup(ch->name); corpse->oname = str_dup(ch->name); } else { corpse->owner = NULL; corpse->oname = str_dup(ch->name); if (ch->gold > 1) { obj_to_obj(create_money(ch->gold / 2), corpse); ch->gold -= ch->gold / 2; } } corpse->cost = 0; } corpse->level = ch->level; 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); for (obj = ch->carrying; obj != NULL; obj = obj_next) { bool floating = FALSE; obj_next = obj->next_content; if (obj->wear_loc == WEAR_FLOAT) floating = TRUE; 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) && !floating) { obj->timer = number_range(5, 10); REMOVE_BIT(obj->extra_flags, ITEM_ROT_DEATH); } REMOVE_BIT(obj->extra_flags, ITEM_VIS_DEATH); if (IS_SET(obj->extra_flags, ITEM_INVENTORY)) extract_obj(obj); else if (floating) { if (IS_OBJ_STAT(obj, ITEM_ROT_DEATH)) { /* get rid of it! */ if (obj->contains != NULL) { OBJ_DATA *in, *in_next; act("$p evaporates,scattering its contents.", ch, obj, NULL, TO_ROOM); for (in = obj->contains; in != NULL; in = in_next) { in_next = in->next_content; obj_from_obj(in); obj_to_room(in, ch->in_room); } } else // floating, rot death, not a container act("$p evaporates.", ch, obj, NULL, TO_ROOM); extract_obj(obj); } else { // floating, not rot death act("$p falls to the floor.", ch, obj, NULL, TO_ROOM); obj_to_room(obj, ch->in_room); } // not floating, not rot death } else { obj_to_obj(obj, corpse); /* if (obj->bound) { obj_to_char(obj, ch); } else */ } } // end for loop obj_to_room(corpse, ch->in_room); return; } void death_cry(CHAR_DATA * ch, CHAR_DATA * victim) { ROOM_INDEX_DATA *was_in_room; char buf[MAX_STRING_LENGTH]; char *msg; char *msg2; char *msg3; int door, i; long vnum[4]; int number; if (ch == victim) return; buf[0] = '\0'; /* * msg goes only to the killer * msg2 goes only to the victim * msg3 goes to everyone else act ($p = weapon act $n = victim msg $N = victim msg $n = agressor */ vnum[0] = 0; vnum[1] = 0; vnum[2] = 0; vnum[3] = 0; msg = "You grab $N's neck and twist it sharply. *SNAP*"; msg2 = "$n grabs your neck and gives it a sharp twist! *SNAP*"; msg3 = "$n grabs $N's neck and gives it a sharp twist. *SNAP*"; number = number_range(0, 8); // vorpal weapons always yield heads. ;) if (get_eq_char(ch, WEAR_WIELD) && IS_WEAPON_STAT(get_eq_char(ch, WEAR_WIELD), WEAPON_VORPAL)) number = 3; switch (number) { case 0: msg = "Gurgling blood, $N falls to the ground and spasms violently."; msg2 = "Gurgling blood, you fall to the ground and spasm violently!"; msg3 = "Gurgling blood, $N falls to the ground and spasms violently."; break; case 1: if (IS_SET(victim->parts, PART_GUTS) && get_weapon_sn(ch) == gsn_sword) { msg = "Slicing $N's stomach open, you watch as $E trips over $S own guts."; msg2 = "$n slices your stomach open, and you trip over your own intestines!"; msg3 = "$n slices $N's stomach open, causing $M to trip over $S own intestines."; vnum[0] = OBJ_VNUM_GUTS; } else if (IS_SET(victim->parts, PART_GUTS) && get_weapon_sn(ch) == gsn_dagger) { msg = "Thrusting your dagger through $N's stomach, you unmercifully tear $S guts from $S body."; msg2 = "$n thrusts $s dagger into your stomach, wrapping your slimy guts around $s blade."; msg3 = "Intestines spill on the ground as $n's dagger pierces $N one final time."; } else if (IS_SET(victim->parts, PART_GUTS) && get_weapon_sn(ch) == gsn_axe) { msg = "Hacking open $N's stomach, you chop at $S guts."; msg2 = "$n savagely rips your stomach open with $s axe!"; msg3 = "$n hacks into $N's midsection, and cracked ribs pop out amid bloody ribbons of tissue."; vnum[0] = OBJ_VNUM_GUTS; vnum[1] = OBJ_VNUM_TORN_HEART; } else if (IS_SET(victim->parts, PART_GUTS) && get_weapon_sn(ch) == gsn_whip) { msg = "Your whip easily slices into $N's stomach, and $S guts slide from $S body."; msg2 = "The head of $n's whip carves an arc deep into your stomach, blood oozing in its wake!"; msg3 = "$n carves out $N's guts with a graceful flick of $s whip."; vnum[0] = OBJ_VNUM_GUTS; } else if (IS_SET(victim->parts, PART_GUTS) && get_weapon_sn(ch) == gsn_polearm) { msg = "Your polearm thrusts into $N's stomach, exposing $S insides to the open air."; msg2 = "$n brings $s polearm down into your stomach, flinging your guts into the air as it exits."; msg3 = "$n brings $s polearm down into $N's stomach, and guts explode from $N's body."; vnum[1] = OBJ_VNUM_TORN_HEART; vnum[0] = OBJ_VNUM_GUTS; } else if (IS_SET(victim->parts, PART_GUTS) && get_weapon_sn(ch) == gsn_spear) { msg = "Thrusting your sharp spear into $N's stomach, you force $S entrails from $S body."; msg2 = "A single thrust of $n's spear guts you, and your entrails spill out of the ragged wound."; msg3 = "A single thrust of $n's spear carves a hole in $N's stomach, spilling $S guts down $S legs."; vnum[0] = OBJ_VNUM_GUTS; } else { msg = "Ripping $N's stomach open, you watch as $E trips over $S own guts."; msg2 = "$n rips your stomach open, and you trip over your own guts!"; msg3 = "$n rips $N stomach open, causing $N to trip over $S own guts."; vnum[0] = OBJ_VNUM_GUTS; } break; case 2: if (IS_SET(victim->parts, PART_GUTS) && get_weapon_sn(ch) == gsn_sword) { msg = "With one mighty swipe of your sword, you sever $N's spine and $S guts spill from both halves."; msg2 = "$n's cold blade slices you in half, and your warm, frothy guts pour down over your body!"; msg3 = "$n slices $N in half, causing $N to trip over $S own guts."; } else if (IS_SET(victim->parts, PART_GUTS) && get_weapon_sn(ch) == gsn_dagger) { msg = "Piercing $N's stomach, $S entrails are visable."; msg2 = "$n pierces your stomach, you die staring in awe of them!"; msg3 = "$n pierces $N stomach, $N dies while they are exposed from $S body."; } else if (IS_SET(victim->parts, PART_GUTS) && get_weapon_sn(ch) == gsn_axe) { msg = "Hacking $N's stomach, $S entrails are exposed."; msg2 = "$n opens your stomach!"; msg3 = "$n pierces $N stomach, $N dies watching $S innards leave $S body."; vnum[0] = OBJ_VNUM_GUTS; } else if (IS_SET(victim->parts, PART_GUTS) && get_weapon_sn(ch) == gsn_whip) { msg = "Whipping $N's stomach, $S entrails are exposed."; msg2 = "$n opens your stomach!"; msg3 = "$n's whip opens $N's torso!"; } else if (IS_SET(victim->parts, PART_GUTS) && get_weapon_sn(ch) == gsn_polearm) { msg = "$n opens $N's stomach with a long stroke from $S polearm forcing $S guts from $S body."; msg2 = "$n opens your stomach!"; msg3 = "$n opens $N's stomach with his polearm."; vnum[0] = OBJ_VNUM_GUTS; } else if (IS_SET(victim->parts, PART_GUTS) && get_weapon_sn(ch) == gsn_spear) { msg = "Thrusting at $N's stomach you expose $N's entrails."; msg2 = "$n thrusts $S spear into your stomach, exposing your entrails."; msg3 = "$n thrusts $S spear deep into $N's stomach."; } else { msg = "As you pound $N, $S entrails become visable."; msg2 = "$n's pounding rips you open!"; msg3 = "$n rips $N open and exposes $S entrails."; } break; case 3: if (IS_SET(victim->parts, PART_HEAD) && get_weapon_sn(ch) == gsn_sword) { msg = "$n connects $s sword just under $N's head, instantly decapitating $M."; msg2 = "$n's sword connects with your neck, instantly decapitating you!"; msg3 = "$n's sword decapitates $N, sending blood everywhere!"; vnum[0] = OBJ_VNUM_SEVERED_HEAD; } else if (IS_SET(victim->parts, PART_HEAD) && get_weapon_sn(ch) == gsn_dagger) { msg = "You dig deep into $N's head and dislodge an eye!"; msg2 = "$n's plundges $S dagger deep into your eye!"; msg3 = "$n's dagger plunges deep into $N's head, poping out $S eye."; vnum[0] = OBJ_VNUM_EYE; vnum[1] = OBJ_VNUM_SEVERED_HEAD; } else if (IS_SET(victim->parts, PART_HEAD) && get_weapon_sn(ch) == gsn_axe) { msg = "Your hack off $N's ear, then swing around, instantly decapitating $M."; msg2 = "$n's axe hacks off your ear, swings around, and decapitates you!"; msg3 = "$n's axe connects with $N's head with explosive force! Body parts fly everywhere!"; vnum[0] = OBJ_VNUM_EAR; vnum[1] = OBJ_VNUM_EYE; vnum[2] = OBJ_VNUM_SEVERED_HEAD; } else if (IS_SET(victim->parts, PART_HEAD) && get_weapon_sn(ch) == gsn_whip) { msg = "Your whip wraps tightly around $N's neck, gruesomely pulling it from $S body."; msg2 = "$n's whip wraps around your neck and rips your head off!"; msg3 = "$n's whip wraps $N's neck, $n yanks, and messily decapitates $M."; vnum[0] = OBJ_VNUM_SEVERED_HEAD; } else if (IS_SET(victim->parts, PART_HEAD) && get_weapon_sn(ch) == gsn_polearm) { msg = "Your polearm connects with $N's neck, instantly decapitating $M."; msg2 = "$n's polearm connects with your neck, instantly decapitating you!"; msg3 = "$n's polearm connects with $N's neck, instantly decapitating $M."; vnum[0] = OBJ_VNUM_SEVERED_HEAD; vnum[1] = OBJ_VNUM_EAR; } else if (IS_SET(victim->parts, PART_HEAD) && get_weapon_sn(ch) == gsn_spear) { msg = "Your thrust separates $N's neck from his head."; msg2 = "$n's thrust separates $S neck from $S head!"; msg3 = "$n's thrust takes $N's head, from $M neck."; vnum[0] = OBJ_VNUM_SEVERED_HEAD; } else { msg = "You knock $N's head off! $S head plops onto the ground."; msg2 = "$n knocks your head off! Your head plops onto the ground."; msg3 = "$n knocks $N's head off! $S head plops onto the ground."; vnum[0] = OBJ_VNUM_SEVERED_HEAD; vnum[1] = OBJ_VNUM_EYE; } break; case 4: if (IS_SET(victim->parts, PART_HEART) && get_weapon_sn(ch) == gsn_sword) { msg = "Your intricate swordwork cuts $N's heart from $S chest."; msg2 = "$n sword cuts your heart from your chest!"; msg3 = "$n cuts $N's heart from $S chest."; vnum[0] = OBJ_VNUM_TORN_HEART; } else if (IS_SET(victim->parts, PART_HEART) && get_weapon_sn(ch) == gsn_dagger) { msg = "You plunge your dagger deep into $N's heart, extinguishing $S life."; msg2 = "$n pokes $s dagger into your chest, penetrating your heart!"; msg3 = "$n stabs $s dagger deep into $N's chest!"; } else if (IS_SET(victim->parts, PART_HEART) && get_weapon_sn(ch) == gsn_axe) { msg = "Your axe tears $N's heart and entrails from $S torso."; msg2 = "$n tears your guts from your torso!"; msg3 = "$n tears $N's heart and entrails from $S torso."; vnum[0] = OBJ_VNUM_TORN_HEART; vnum[1] = OBJ_VNUM_GUTS; } else if (IS_SET(victim->parts, PART_HEART) && get_weapon_sn(ch) == gsn_whip) { msg = "You send your whip into $N's chest and tear out $S heart."; msg2 = "$n tears your heart from your chest!"; msg3 = "$n's tears into $N's chest, tearing out $S heart."; vnum[0] = OBJ_VNUM_TORN_HEART; } else if (IS_SET(victim->parts, PART_HEART) && get_weapon_sn(ch) == gsn_polearm) { msg = "You hack $N's insides from $S torso."; msg2 = "$n hacks your heart and entrails from your torso!"; msg3 = "$n's polearm hacks $N's heart and entrails from $S torso."; vnum[0] = OBJ_VNUM_GUTS; vnum[1] = OBJ_VNUM_TORN_HEART; } else if (IS_SET(victim->parts, PART_HEART) && get_weapon_sn(ch) == gsn_spear) { msg = "Using labyrinthine thrusts, you remove $N's heart from $S torso."; msg2 = "$n removes your heart from your chest with a series of complex thrusts!"; msg3 = "$n removes $N's heart from $S chest after a series of complex thrusts."; vnum[0] = OBJ_VNUM_TORN_HEART; } else { msg = "You tear $N's heart from $S chest and crush it in your hand."; msg2 = "$n tears your heart from your chest and crushes it in $s hand!"; msg3 = "$n tears $N's heart from $S chest and crushes it in $s hand."; vnum[0] = OBJ_VNUM_TORN_HEART; } break; case 5: if (IS_SET(victim->parts, PART_ARMS) && get_weapon_sn(ch) == gsn_sword) { msg = "Savagely, you slice $N's arm and watch it fall from $S corpse."; msg2 = "Savagely, $n slices your arm off!"; msg3 = "Savagely, $n cuts $N's arm off."; vnum[0] = OBJ_VNUM_SLICED_ARM; } else if (IS_SET(victim->parts, PART_ARMS) && get_weapon_sn(ch) == gsn_dagger) { msg = "Savagely, you cut into some of $N's fingers as $S raises his arm in defense."; msg2 = "Raising your hand in defense $n cuts into some of your fingers!"; msg3 = "$N raises $S arm in defense, $n cuts into some of $S fingers."; } else if (IS_SET(victim->parts, PART_ARMS) && get_weapon_sn(ch) == gsn_axe) { msg = "Savagely, you hack $N's arm off!"; msg2 = "Savagely, $n hacks your arm off!"; msg3 = "Savagely, $n hacks $N's arm off."; vnum[0] = OBJ_VNUM_SLICED_ARM; } else if (IS_SET(victim->parts, PART_ARMS) && get_weapon_sn(ch) == gsn_whip) { msg = "Savagely, you rip $N's arm from $S torso off with your whip."; msg2 = "Savagely, $n rips your arm off with $s whip!"; msg3 = "Savagely, $n rips $N's arm off with $s whip."; vnum[0] = OBJ_VNUM_SLICED_ARM; } else if (IS_SET(victim->parts, PART_ARMS) && get_weapon_sn(ch) == gsn_polearm) { msg = "Savagely, you separate $N's arm from $S torso."; msg2 = "Savagely, $n separates your arm from your torso!"; msg3 = "Savagely, $n separates $N's arm from his torso."; vnum[0] = OBJ_VNUM_SLICED_ARM; } else if (IS_SET(victim->parts, PART_ARMS) && get_weapon_sn(ch) == gsn_spear) { msg = "Savagely, you thrust your spear between $N's arm and $S torso."; msg2 = "Savagely, $n thrusts {s spear between your arm and torso!"; msg3 = "Savagely, $n thrusts {s spear between $N's arm and $S torso."; vnum[0] = OBJ_VNUM_SLICED_ARM; } else { msg = "Savagely, you rip $N's arm from $S corpse."; msg2 = "Savagely, $n rips your arm off!"; msg3 = "Savagely, $n rips $N's arm off."; vnum[0] = OBJ_VNUM_SLICED_ARM; } break; case 6: if (IS_SET(victim->parts, PART_LEGS) && get_weapon_sn(ch) == gsn_sword) { msg = "You slice $N's leg off with your sword."; msg2 = "$n slices your leg off with $s sword!"; msg3 = "$n slices $N's leg with $s sword."; vnum[0] = OBJ_VNUM_SLICED_LEG; } else if (IS_SET(victim->parts, PART_LEGS) && get_weapon_sn(ch) == gsn_dagger) { msg = "You stab at $N's legs as $E dies."; msg2 = "$n stabs into your legs with $s dagger!"; msg3 = "$n stabs into $N's legs with $s dagger as $N dies."; } else if (IS_SET(victim->parts, PART_LEGS) && get_weapon_sn(ch) == gsn_axe) { msg = "You hack both of $N's legs off with your axe!"; msg2 = "$n hacks your legs off with $s axe!"; msg3 = "$n hacks $N's legs off with $s axe."; vnum[0] = OBJ_VNUM_SLICED_LEG; vnum[1] = OBJ_VNUM_SLICED_LEG; } else if (IS_SET(victim->parts, PART_LEGS) && get_weapon_sn(ch) == gsn_whip) { msg = "You wrap your whip around $N's leg, and rip it off!"; msg2 = "$n wraps his whip around your leg and rips it off!"; msg3 = "$n wraps $s whip around $N's leg, ripping it off."; vnum[0] = OBJ_VNUM_SLICED_LEG; } else if (IS_SET(victim->parts, PART_LEGS) && get_weapon_sn(ch) == gsn_polearm) { msg = "Your sweeping polearm takes $N's legs from $S fresh corpse."; msg2 = "$n hacks your legs from your body!"; msg3 = "$n's polearm hacks $N's leg from $S body."; vnum[0] = OBJ_VNUM_SLICED_LEG; vnum[1] = OBJ_VNUM_SLICED_LEG; } else if (IS_SET(victim->parts, PART_LEGS) && get_weapon_sn(ch) == gsn_spear) { msg = "Your thrust snaps $N's leg off."; msg2 = "$n snaps your leg off with $s spear!"; msg3 = "$n spear separates $N's leg from $S body."; vnum[0] = OBJ_VNUM_SLICED_LEG; } else { msg = "You knock $N's leg off and stuff it down $S throat."; msg2 = "$n knocks your leg off and stuffs it down your throat!"; msg3 = "$n knocks $N's leg off and stuffs it down $S throat."; vnum[0] = OBJ_VNUM_SLICED_LEG; } break; case 7: if (IS_SET(victim->parts, PART_BRAINS) && get_weapon_sn(ch) == gsn_sword) { msg = "Your slice cuts $N's head wide open, and $S brains spill out."; msg2 = "$n's slice splits your head wide open, and your brains spill out!"; msg3 = "$n's slice splits $N's head wide open, and $S brains spill out."; vnum[0] = OBJ_VNUM_BRAINS; } else if (IS_SET(victim->parts, PART_BRAINS) && get_weapon_sn(ch) == gsn_dagger) { msg = "Your stab cracks $N's head wide open, and $S brains spill out."; msg2 = "$n's stab cracks your head wide open, and your brains spill out!"; msg3 = "$n's stab cracks $N's head wide open, and $S brains spill out."; vnum[0] = OBJ_VNUM_BRAINS; } else if (IS_SET(victim->parts, PART_BRAINS) && get_weapon_sn(ch) == gsn_axe) { msg = "Your hack splits $N's head wide open."; msg2 = "$n's hack splits your head wide open!"; msg3 = "$n's hack splits $N's head wide open."; vnum[0] = OBJ_VNUM_EYE; vnum[1] = OBJ_VNUM_EAR; vnum[2] = OBJ_VNUM_BRAINS; } else if (IS_SET(victim->parts, PART_BRAINS) && get_weapon_sn(ch) == gsn_whip) { msg = "Your whip splits $N's head wide open, and $S brains spill out."; msg2 = "$n's whip splits your head wide open, and your brains spill out!"; msg3 = "$n's whip splits $N's head wide open, and $S brains spill out."; vnum[0] = OBJ_VNUM_BRAINS; } else if (IS_SET(victim->parts, PART_BRAINS) && get_weapon_sn(ch) == gsn_polearm) { msg = "Your slice splits $N's head wide open."; msg2 = "$n's blow splits your head wide open!"; msg3 = "$n's polearm splits $N's head wide open."; vnum[0] = OBJ_VNUM_EYE; vnum[1] = OBJ_VNUM_BRAINS; } else if (IS_SET(victim->parts, PART_BRAINS) && get_weapon_sn(ch) == gsn_spear) { msg = "Your thrust takes off the top of $N's head."; msg2 = "$n's thrust take off the top of your head!"; msg3 = "$n's thrust takes off the top of $N's head."; vnum[0] = OBJ_VNUM_BRAINS; } else { msg = "Your blow splits $N's head wide open, and $S brains spill out."; msg2 = "$n's blow splits your head wide open, and your brains spill out!"; msg3 = "$n's blow splits $N's head wide open, and $S brains spill out."; vnum[0] = OBJ_VNUM_BRAINS; } break; case 8: if (get_weapon_sn(ch) == gsn_sword) { msg = "Dropping to a crouch, you drive your blade upward, impaling $N."; msg2 = "Dropping to a crouch, $n drives $s blade upward, impaling you!"; msg3 = "Dropping to a crouch, $n drives $s blade upward, impaling $N."; } else if (get_weapon_sn(ch) == gsn_dagger) { msg = "Dropping to a crouch, you drive your dagger up into $N."; msg2 = "Dropping to a crouch, $n drives $s dagger deep into you!"; msg3 = "Dropping to a crouch, $n drives $s dagger into $N."; } else if (get_weapon_sn(ch) == gsn_axe) { msg = "Dropping to a crouch, your axe sends parts of $N everywhere."; msg2 = "Dropping to a crouch, $n sends parts of you everywhere!"; msg3 = "Dropping to a crouch, $n sends parts of $N everywhere."; vnum[0] = OBJ_VNUM_SLICED_ARM; vnum[1] = OBJ_VNUM_EAR; vnum[2] = OBJ_VNUM_BRAINS; vnum[3] = OBJ_VNUM_SLICED_LEG; } else if (get_weapon_sn(ch) == gsn_whip) { msg = "Backing up, you strink deep into $N."; msg2 = "Backing up, $n strikes $s whip deep into you!"; msg3 = "Backing up, $n strikes his whip deep into $N."; } else if (get_weapon_sn(ch) == gsn_polearm) { msg = "Dropping to a crouch, your polearm send parts of $N everywhere."; msg2 = "Dropping to a crouch, $n sends parts of you everywhere!"; msg3 = "Dropping to a crouch, $n sends parts of $N everywhere."; vnum[0] = OBJ_VNUM_SLICED_ARM; vnum[1] = OBJ_VNUM_EYE; vnum[2] = OBJ_VNUM_SEVERED_HEAD; vnum[3] = OBJ_VNUM_SLICED_LEG; } else if (get_weapon_sn(ch) == gsn_spear) { msg = "Dropping to a crouch, you drive your spear upward, impaling $N."; msg2 = "Dropping to a crouch, $n drives $s spear upward, impaling you!"; msg3 = "Dropping to a crouch, $n drives $s spear upward, impaling $N."; } else { msg = "Dropping to a crouch, you swing upward, destroying $N."; msg2 = "Dropping to a crouch, $n swings upward, destroying you!"; msg3 = "Dropping to a crouch, $n swings upward, destroying $N."; vnum[0] = OBJ_VNUM_EAR; vnum[1] = OBJ_VNUM_EYE; vnum[2] = OBJ_VNUM_SEVERED_HEAD; vnum[3] = OBJ_VNUM_SLICED_LEG; } break; } if (!IS_NPC(victim) && victim->pcdata->bounty > 0) { msg = "You smash $N's head off! $S head plops onto the ground...perhaps there's a reward."; msg2 = "$n smashes your head off! Your head plops onto the ground."; msg3 = "$n smashes $N's head off! $S head plops onto the ground."; vnum[0] = OBJ_VNUM_SEVERED_HEAD; } act_new(msg, ch, NULL, victim, TO_CHAR, POS_RESTING); /* Only to Killer */ act_new(msg2, ch, NULL, victim, TO_VICT, POS_DEAD); /* Only to victim */ act_new(msg3, ch, NULL, victim, TO_NOTVICT, POS_RESTING); /* Everyone else */ for (i = 0; i < 4; i++) { if (vnum[i] != 0) { EXTRA_DESCR_DATA *ed; OBJ_DATA *obj; char *name; name = IS_NPC(victim) ? victim->short_descr : victim->name; obj = create_object(get_obj_index(vnum[i]), 0); if (!IS_NPC(victim) && victim->pcdata->bounty > 0) obj->timer = 0; else obj->timer = number_range(10, 20); 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 (!IS_NPC(victim) && victim->pcdata->bounty > 0) { sprintf(buf, "{MTake this to %s and get a bounty of %d gold!{x\n\r", victim->pcdata->bountier, victim->pcdata->bounty); ed = new_extra_descr(); ed->keyword = str_dup("head"); ed->description = str_dup(buf); ed->next = obj->extra_descr; obj->extra_descr = ed; victim->pcdata->bounty = 0; free_string(victim->pcdata->bountier); victim->pcdata->bountier = str_dup(""); } if (obj->item_type == ITEM_FOOD) { if (IS_SET(victim->form, FORM_POISON)) obj->value[3] = 1; else if (!IS_SET(ch->form, FORM_EDIBLE)) obj->item_type = ITEM_TRASH; } if (obj->item_type == ITEM_PILL) obj->value[0] = (obj->level / 2) + 1; obj_to_room(obj, victim->in_room); } } if (IS_NPC(victim)) 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, victim, TO_NOTVICT); } } ch->in_room = was_in_room; buf[0] = '\0'; return; } void raw_kill(CHAR_DATA * ch, CHAR_DATA * victim) { char buf4[MSL]; stop_fighting(victim, TRUE); if (IS_NPC(victim) && HAS_TRIGGER(victim, TRIG_DEATH)) { victim->position = POS_STANDING; mp_percent_trigger(victim, ch, NULL, NULL, TRIG_DEATH); } death_cry(ch, victim); // fake death in the arena, no corpse, no pain if (victim->arena == global_last_arena_id && ch->arena) { stop_fighting(ch, FALSE); stop_fighting(victim, FALSE); sprintf(buf4, "{c[{RARENA OF DEATH{c] %s just killed %s in the arena!{x", ch->name, victim->name); announce(buf4, ch); arena_death(victim); return; } /* For the Announce Channel */ if (!IS_NPC(victim)) { DESCRIPTOR_DATA *d; for (d = descriptor_list; d != NULL; d = d->next) { CHAR_DATA *wch; wch = d->original ? d->original : d->character; if (d->connected == CON_PLAYING && d->character != ch && d->character != victim && IS_SET(wch->comm, COMM_ANNOUNCE) && !IS_SET(wch->comm, COMM_QUIET)) { sprintf(log_buf, "{c[{RK{rI{RL{rL{RE{rD{c] %s forces $n into Death's willing embrace!{x", capitalize(PERS(ch, d->character))); act_new(log_buf, victim, NULL, d->character, TO_VICT, POS_DEAD); } } } make_corpse(victim, IS_NPC(ch) ? FALSE : TRUE); death_penalty(victim); return; } void kill_self(CHAR_DATA * ch) { ROOM_INDEX_DATA *was_in_room; char *msg; int door; stop_fighting(ch, TRUE); send_to_char("{RYou have DIED!!{x\n\r\n\r", ch); 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; /* For the Announce Channel */ if (!IS_NPC(ch)) { DESCRIPTOR_DATA *d; for (d = descriptor_list; d != NULL; d = d->next) { CHAR_DATA *wch; wch = d->original ? d->original : d->character; if (d->connected == CON_PLAYING && d->character != ch && IS_SET(wch->comm, COMM_ANNOUNCE) && !IS_SET(wch->comm, COMM_QUIET)) { act_new("{c[{RANNOUNCE{c] $n has killed $mself!{x", ch, NULL, d->character, TO_VICT, POS_DEAD); } } } make_corpse(ch, FALSE); death_penalty(ch); return; } 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; int high_level; if (ch == victim) kill_self(victim); else { create_blood_pool(victim); raw_kill(ch, victim); send_to_char ("\n{R{*Ow! Ow! Ow! Ow! Ow! That SUCKED! You're dead. :({x\n\r\n\r", victim); } /* * 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; if (!victim->no_exp) turf_mod(ch, victim); members = 0; group_levels = 0; high_level = 0; for (gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room) { if (is_same_group(gch, ch)) { members++; group_levels += gch->level; if (gch->level > high_level) high_level = gch->level; } } if (members == 0) { bug("Group_gain: members.", members); members = 1; group_levels = ch->level; } lch = (ch->leader != NULL) ? ch->leader : ch; for (gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room) { if (!is_same_group(gch, ch) || IS_NPC(gch)) continue; xp = (xp_compute(gch, victim, high_level)); xp = xp / members; if ((ch->desc && victim->desc) && (!str_cmp(victim->desc->host, ch->desc->host))) { send_to_char ("Cheat attempt logged, no experience for you!\r\n", ch); return; } // to stop guardian/summon farming. if (victim->no_exp) xp = 0; sprintf(buf, "{RYou receive %d experience points.{x\n\r", xp); send_to_char(buf, gch); gain_exp(gch, xp); if (!IS_NPC(gch) && !IS_NPC(victim)) ++gch->pcdata->kills; /* Now for the poor PKillers who lost */ if (!IS_NPC(gch) && !IS_NPC(victim)) { gain_exp(victim, xp * -1); if (IS_SET(victim->act, PLR_PKILL)) /* No longer a PKILLER */ REMOVE_BIT(victim->act, PLR_PKILL); sprintf(buf, "{RYou lose %d experience points.{x\n\r", xp); send_to_char(buf, victim); } } return; } /* * 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 total_levels) { int xp, base_exp; int level_range; // int base_align; level_range = victim->level - total_levels; // exp = 0; /* compute the base exp */ switch (level_range) { default: base_exp = 0; break; case -9: base_exp = 5; break; case -8: base_exp = 7; break; case -7: base_exp = 9; break; case -6: base_exp = 11; break; case -5: base_exp = 13; break; case -4: base_exp = 17; break; case -3: base_exp = 35; break; case -2: base_exp = 45; break; case -1: base_exp = 55; break; case 0: base_exp = 100; break; case 1: base_exp = 115; break; case 2: base_exp = 120; break; case 3: base_exp = 125; break; case 4: base_exp = 130; break; case 5: base_exp = 135; break; case 6: base_exp = 140; break; case 7: base_exp = 145; break; case 8: base_exp = 150; break; case 9: base_exp = 155; break; case 10: base_exp = 160; break; case 11: base_exp = 165; break; case 12: base_exp = 170; break; case 13: base_exp = 175; break; case 14: base_exp = 180; break; case 15: base_exp = 185; break; case 16: base_exp = 190; break; case 17: base_exp = 195; break; case 18: base_exp = 200; break; case 19: base_exp = 205; break; case 20: base_exp = 215; break; case 21: base_exp = 225; break; case 22: base_exp = 235; break; case 23: base_exp = 245; break; case 24: base_exp = 255; break; case 25: base_exp = 265; break; case 26: base_exp = 275; break; case 27: base_exp = 285; break; case 28: base_exp = 295; break; case 29: base_exp = 305; break; case 30: base_exp = 315; break; case 31: base_exp = 325; break; case 32: base_exp = 335; break; case 33: base_exp = 345; break; case 34: base_exp = 355; break; case 35: base_exp = 365; break; case 36: base_exp = 375; break; case 37: base_exp = 385; break; case 38: base_exp = 395; break; case 39: base_exp = 405; break; case 40: base_exp = 415; break; } if (level_range > 40) { base_exp = 450; } xp = base_exp; /*********************************************************** * checks for remort * ***********************************************************/ xp = (xp / (gch->remorts + 1)); if (xp < 0) { xp = 0; } /* randomize the rewards */ xp = number_range(xp * 4 / 5, xp * 5 / 4); if (gch->level < 10) xp = xp * 4; if (gch->level < 20 && gch->level >= 10) xp = xp * 3; if (gch->level < 30 && gch->level >= 20) xp = xp * 2; /* if (victim->alignment > 0) gch->alignment -= base_align; if (gch->alignment < -1000) gch->alignment = -1000; else gch->alignment += base_align; if (gch->alignment > 1000) gch->alignment = 1000;*/ if (xp > 450) xp = 450; return xp; } void dam_message(CHAR_DATA * ch, CHAR_DATA * victim, int dam, int dt, bool immune) { char buf1[256], buf2[256], buf3[256], buf4[256]; char cdam[256], vdam[256], selfdam[256]; const char *vs; const char *vp; const char *attack; char punct; if (ch == NULL || victim == NULL) return; if (dam == 0) { vs = "{Wmiss{x"; vp = "{Wmisses{x"; } else if (dam <= 4) { vs = "{Cscratch{x"; vp = "{Cscratches{x"; } else if (dam <= 8) { vs = "{Cgraze{x"; vp = "{Cgrazes{x"; } else if (dam <= 12) { vs = "{Chit{x"; vp = "{Chits{x"; } else if (dam <= 16) { vs = "{Rinjure{x"; vp = "{Rinjures{x"; } else if (dam <= 22) { vs = "{Rwound{x"; vp = "{Rwounds{x"; } else if (dam <= 29) { vs = "{Rmaul{x"; vp = "{Rmauls{x"; } else if (dam <= 36) { vs = "{Ydecimate{x"; vp = "{Ydecimates{x"; } else if (dam <= 43) { vs = "{Ydevastate{x"; vp = "{Ydevastates{x"; } else if (dam <= 50) { vs = "{Ymaim{x"; vp = "{Ymaims{x"; } else if (dam <= 59) { vs = "{GMUTILATE{x"; vp = "{GMUTILATES{x"; } else if (dam <= 72) { vs = "{GDISEMBOWEL{x"; vp = "{GDISEMBOWELS{x"; } else if (dam <= 88) { vs = "{GDISMEMBER{x"; vp = "{GDISMEMBERS{x"; } else if (dam <= 105) { vs = "{MMASSACRE{x"; vp = "{MMASSACRES{x"; } else if (dam <= 125) { vs = "{MMANGLE{x"; vp = "{MMANGLES{x"; } else if (dam <= 150) { vs = "{M*** DEMOLISH ***{x"; vp = "{M*** DEMOLISHES ***{x"; } else if (dam <= 175) { vs = "{m*** DEVASTATE ***{x"; vp = "{M*** DEVASTATES ***{x"; } else if (dam <= 245) { vs = "{M=== OBLITERATE ==={x"; vp = "{M=== OBLITERATES ==={x"; } else if (dam <= 350) { vs = "{M>>> ANNIHILATE <<<{x"; vp = "{M>>> ANNIHILATES <<<{x"; } else if (dam <= 550) { vs = "{M<<< ERADICATE >>>{x"; vp = "{M<<< ERADICATES >>>{x"; } else if (dam <= 850) { vs = "{M<<< LIQUIDATE >>>{x"; vp = "{M<<< LIQUIDATES >>>{x"; } else { vs = "{Ydo {RUNSPEAKABLE {Ythings to{x"; vp = "{Ydoes {RUNSPEAKABLE {Ythings to{x"; } punct = (dam <= 24) ? '.' : '!'; if (IS_SET(ch->act, PLR_AUTODAMAGE)) { sprintf(cdam, " {W[{C%d{W]", dam); sprintf(selfdam, " {W[{R%d{W]", dam); } else { cdam[0] = '\0'; selfdam[0] = '\0'; } if (IS_SET(victim->act, PLR_AUTODAMAGE)) sprintf(vdam, " {W[{R%d{W]", dam); else vdam[0] = '\0'; if (dt == TYPE_HIT) { if (ch == victim) { sprintf(buf1, "$n %s $melf%c", vp, punct); sprintf(buf2, "You %s yourself%c%s{x", vs, punct, selfdam); } else { sprintf(buf1, "$n %s $N%c", vp, punct); sprintf(buf2, "{gYou %s{g $N%c%s{x", vs, punct, cdam); sprintf(buf3, "{g$n %s{g you%c%s{x", vp, punct, vdam); } } 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 { bug("Dam_message: bad dt %d.", dt); sprintf(buf4, "char: did it! %s target was %s", ch->name, victim->name); bug(buf4, 0); dt = TYPE_HIT; attack = attack_table[0].name; } if (immune) { if (ch == victim) { sprintf(buf1, "$n is unaffected by $s own %s.", attack); sprintf(buf2, "Luckily, you are immune to that."); } else { sprintf(buf1, "$N is unaffected by $n's %s!", attack); sprintf(buf2, "{G$N is unaffected by your %s!{x", attack); sprintf(buf3, "{G$n's %s is powerless against you.{x", attack); } } else { if (ch == victim) { sprintf(buf1, "$n's %s %s $m%c", attack, vp, punct); sprintf(buf2, "Your %s %s you%c%s{x", attack, vp, punct, selfdam); } else { sprintf(buf1, "$n's %s %s $N%c", attack, vp, punct); sprintf(buf2, "{gYour %s %s{g $N%c%s{x", attack, vp, punct, cdam); sprintf(buf3, "{g$n's %s %s{g you%c%s{x", attack, vp, punct, vdam); } } } if (ch == victim) { act(buf1, ch, NULL, NULL, TO_ROOM); act(buf2, ch, NULL, NULL, TO_CHAR); } else { act(buf1, ch, NULL, victim, TO_NOTVICT); act(buf2, ch, NULL, victim, TO_CHAR); act(buf3, ch, NULL, victim, TO_VICT); } return; } /* * Disarm a creature. * Caller must check for successful attack. */ void disarm(CHAR_DATA * ch, CHAR_DATA * victim) { OBJ_DATA *obj; bool displaced; displaced = FALSE; //displace spell if ((obj = get_eq_char(victim, WEAR_WIELD)) == NULL) return; if (IS_OBJ_STAT(obj, ITEM_NOREMOVE)) { 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(victim, AFF_TALON)) { act("$S weapon sticks to $M like glue!", ch, NULL, victim, TO_CHAR); act("$n tries to disarm you, but your weapon sticks like glue!", ch, NULL, victim, TO_VICT); act("$n tries to disarm $N, but $N's weapon sticks to $M like glue.", ch, NULL, victim, TO_NOTVICT); return; } //Check if displaced if (is_affected(victim, skill_lookup("displace"))) if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) { //You're disarming the displaced version send_to_char("Your aim goes right through the weapon...\n\r", ch); displaced = TRUE; return; } act("{M$n {YDISARMS {Myou and sends your weapon flying!{x", 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; } 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 (ch->mana < 50) { send_to_char("You can't get up enough energy.\n\r", ch); return; } /* modifiers */ /* fighting */ if (ch->position == POS_FIGHTING) chance += 10; /* damage -- below 50% of hp helps, above hurts */ hp_percent = 100 * ch->hit / ch->max_hit; chance += 25 - hp_percent / 2; if (number_percent() < chance) { AFFECT_DATA af; if (ch->level < 300) WAIT_STATE(ch, 12); ch->mana -= 50; ch->move /= 2; /* heal a little damage */ ch->hit += ch->level * 2; 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); af.where = TO_AFFECTS; af.type = gsn_berserk; af.level = ch->level; af.duration = number_fuzzy(ch->level / 8); af.modifier = UMAX(1, ch->level / 5); af.bitvector = AFF_BERSERK; af.location = APPLY_HITROLL; affect_to_char(ch, &af); af.location = APPLY_DAMROLL; affect_to_char(ch, &af); af.modifier = UMAX(10, 10 * (ch->level / 5)); af.location = APPLY_AC; affect_to_char(ch, &af); } else { if (ch->level < 300) WAIT_STATE(ch, 36); ch->mana -= 25; ch->move /= 2; send_to_char("Your pulse speeds up, but nothing happens.\n\r", ch); check_improve(ch, gsn_berserk, FALSE, 2); } } void do_bash(CHAR_DATA * ch, char *argument) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; int chance; bool displaced; displaced = FALSE; //displace spell 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 (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 (victim->fighting != NULL && !is_same_group(ch, victim->fighting)) { send_to_char("Kill stealing is not permitted.\n\r", ch); return; } if (IS_NPC(victim) && victim->fighting != NULL && !is_same_group(ch, victim->fighting)) { send_to_char("Kill stealing is not permitted.\n\r", ch); return; } if (IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim) { act("But $N is your friend!", ch, NULL, victim, TO_CHAR); return; } /* modifiers */ /* size and weight */ chance += ch->carry_weight / 250; chance -= victim->carry_weight / 200; if (ch->size < victim->size) chance += (ch->size - victim->size) * 15; 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 -= 30; /* level */ /*chance += (ch->level - victim->level); */ if (!IS_NPC(victim) && chance < get_skill(victim, gsn_dodge)) { /* act("$n tries to bash you, but you dodge it.",ch,NULL,victim,TO_VICT); act("$N dodges your bash, you fall flat on your face.",ch,NULL,victim,TO_CHAR); WAIT_STATE(ch,skill_table[gsn_bash].beats); return; */ chance -= 3 * (get_skill(victim, gsn_dodge) - chance); } //Check if displaced if (is_affected(victim, skill_lookup("displace"))) if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) { //You're bashing the displaced version send_to_char("You charge and... fly through him...\n\r", ch); chance = 0; displaced = TRUE; } /* 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); DAZE_STATE(victim, PULSE_VIOLENCE); WAIT_STATE(ch, skill_table[gsn_bash].beats); damage(ch, victim, number_range(2, 2 + 2 * ch->size + chance / 20), gsn_bash, DAM_BASH, TRUE); } else { damage(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_improve(ch, gsn_bash, FALSE, 1); WAIT_STATE(ch, skill_table[gsn_bash].beats * 3 / 2); } check_killer(ch, victim); } void do_dirt(CHAR_DATA * ch, char *argument) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; int chance; bool displaced; displaced = FALSE; //displace spell one_argument(argument, arg); if ((chance = get_skill(ch, gsn_dirt)) == 0 || (!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 == ch) { send_to_char("Very funny.\n\r", ch); return; } if (is_safe(ch, victim)) return; if (victim->fighting != NULL && !is_same_group(ch, victim->fighting)) { send_to_char("Kill stealing is not permitted.\n\r", ch); return; } if (IS_NPC(victim) && victim->fighting != NULL && !is_same_group(ch, victim->fighting)) { send_to_char("Kill stealing is not permitted.\n\r", ch); return; } if (IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim) { act("But $N is such a good friend!", ch, NULL, victim, TO_CHAR); return; } /* modifiers */ /* 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 -= 25; /* 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; } //Check if displaced if (is_affected(victim, skill_lookup("displace"))) if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) { //You're throwing dirt at the displaced version send_to_char("The dirt... flies through him...\n\r", ch); chance = 0; displaced = TRUE; } /* 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); damage(ch, victim, number_range(2, 5), gsn_dirt, DAM_NONE, FALSE); 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); af.where = TO_AFFECTS; af.type = gsn_dirt; af.level = ch->level; af.duration = 2; af.location = APPLY_HITROLL; af.modifier = -4; af.bitvector = AFF_BLIND; affect_to_char(victim, &af); } else { 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; bool displaced; displaced = FALSE; //displace spell one_argument(argument, arg); if ((chance = get_skill(ch, gsn_trip)) == 0 || (IS_NPC(ch) && (IS_AFFECTED(ch, AFF_BLIND))) || (!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 (victim->fighting != NULL && !is_same_group(ch, victim->fighting)) { send_to_char("Kill stealing is not permitted.\n\r", ch); return; } if (IS_NPC(victim) && victim->fighting != NULL && !is_same_group(ch, victim->fighting)) { send_to_char("Kill stealing is not permitted.\n\r", ch); return; } if (IS_AFFECTED(victim, AFF_FLYING)) { 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(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 -= 20; /* level */ /*chance += (ch->level - victim->level) * 2; */ //Check if displaced if (is_affected(victim, skill_lookup("displace"))) if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) { //You're trying to trip the displaced version send_to_char("The attempt passes through the legs...\n\r", ch); chance = 0; displaced = TRUE; } /* 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); DAZE_STATE(victim, 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); } else { 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_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; } 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 (victim->fighting != NULL && !is_same_group(ch, victim->fighting)) { send_to_char("Kill stealing is not permitted.\n\r", ch); 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; } if (ch->level < 201) WAIT_STATE(ch, 12); if (IS_NPC(ch)) { mob_remember(victim, ch, MEM_HOSTILE); } check_killer(ch, victim); 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) { do_kill(ch, argument); return; } void do_backstab(CHAR_DATA * ch, char *argument) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; // OBJ_DATA *obj; OBJ_DATA *wield; int chance; bool displaced; displaced = FALSE; //displace spell one_argument(argument, arg); if (!IS_NPC(ch)) chance = (get_skill(ch, gsn_backstab)); else chance = UMIN(ch->level, 100); if (chance <= 1) { send_to_char("You don't know how to backstab, silly.\r\n", ch); return; } if (arg[0] == '\0') { send_to_char("Backstab whom?\n\r", ch); return; } if (ch->fighting != NULL) { send_to_char("You can't backstab someone you're 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; } if (victim == ch) { send_to_char("How can you sneak up on yourself?\n\r", ch); return; } if (is_safe(ch, victim)) return; if (victim->fighting != NULL && !is_same_group(ch, victim->fighting)) { send_to_char("Kill stealing is not permitted.\n\r", ch); return; } if (IS_NPC(victim) && victim->fighting != NULL && !is_same_group(ch, victim->fighting)) { send_to_char("Kill stealing is not permitted.\n\r", ch); return; } if (victim->hit < victim->max_hit / 3) { act("$N is hurt and suspicious ... you can't sneak up.", ch, NULL, victim, TO_CHAR); return; } if (!IS_NPC(ch)) { /*Only certain weapons can be used */ wield = get_eq_char(ch, WEAR_WIELD); if (wield == NULL || wield->item_type != ITEM_WEAPON) { send_to_char ("You do need to use some sort of a weapon to backstab.\n\r", ch); return; } else { switch (wield->value[0]) { case (WEAPON_SWORD): chance -= 10; break; case (WEAPON_DAGGER): chance = chance; break; case (WEAPON_SPEAR): send_to_char ("You realy should try a different weapon next time\n\r", ch); return; break; case (WEAPON_MACE): send_to_char ("How do you expect to stab someone with a mace?\n\r", ch); return; break; case (WEAPON_AXE): send_to_char("A axe blow is to slow for a backstab\n\r", ch); return; break; case (WEAPON_FLAIL): send_to_char("Flails can't be used to backstab\n\r", ch); return; break; case (WEAPON_EXOTIC): send_to_char ("Your knowledge of this weapon isn't great enough\n\r", ch); return; break; case (WEAPON_WHIP): send_to_char("It's impossible to backstab with a whip\n\r", ch); return; break; case (WEAPON_POLEARM): send_to_char("You realy should use a other weapon\n\r", ch); return; break; default: send_to_char("You realy should use a weapon with a blade", ch); return; break; } } check_killer(ch, victim); } WAIT_STATE(ch, skill_table[gsn_backstab].beats); //Check if displaced if (is_affected(victim, skill_lookup("displace"))) if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) { //You're backstabbing the displaced version send_to_char ("The stab mysteriously goes right through the back...\n\r", ch); chance = 0; displaced = TRUE; } if ((number_percent() <= chance) || (chance >= 2 && !IS_AWAKE(victim))) { check_improve(ch, gsn_backstab, TRUE, 1); one_hit(ch, victim, gsn_backstab); } else { check_improve(ch, gsn_backstab, FALSE, 1); damage(ch, victim, 0, gsn_backstab, DAM_NONE, TRUE); } return; } void do_assassinate(CHAR_DATA * ch, char *argument) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; int chance; bool displaced; displaced = FALSE; //displace spell one_argument(argument, arg); if (arg[0] == '\0') { send_to_char("Assassinate whom?\n\r", ch); return; } if (ch->fighting != NULL) { send_to_char("It's a little too late for that now.\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("Perhaps you should try delete.\n\r", ch); return; } if (IS_IMMORTAL(victim) && victim->arena == FALSE) { send_to_char("Assassinate an immortal? Are you crazy!?\n\r", ch); return; } if (is_safe(ch, victim)) return; if (victim->fighting != NULL && !is_same_group(ch, victim->fighting)) { send_to_char("Kill stealing is not permitted.\n\r", ch); return; } if (IS_NPC(victim) && victim->fighting != NULL) { send_to_char("Kill stealing is not permitted.\n\r", ch); return; } if (get_eq_char(ch, WEAR_WIELD) == NULL) { send_to_char("You need to wield a weapon to assassinate.\n\r", ch); return; } /*Assassination chance */ chance = ((get_skill(ch, gsn_assassinate) / 3)); if (!IS_AWAKE(victim)) chance += 75; if (IS_AFFECTED(ch, AFF_SNEAK)) chance += 15; else if (get_trust(victim) < ch->invis_level || IS_AFFECTED(victim, AFF_BLIND) || (IS_AFFECTED(ch, AFF_INVISIBLE) && !IS_AFFECTED(victim, AFF_DETECT_INVIS)) || (room_is_dark(victim->in_room) && !IS_AFFECTED(victim, AFF_INFRARED))) chance += 10; chance = URANGE(1, chance, 1100); if (can_see(victim, ch)) chance -= 50; if (get_skill(ch, gsn_assassinate) <= 1) { send_to_char("You don't know how to assassinate, silly.\r\n", ch); return; } check_killer(ch, victim); //Check if displaced if (is_affected(victim, skill_lookup("displace"))) if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) { //You're trying to kill the displaced version send_to_char("Your attempt goes right through...\n\r", ch); chance = 0; displaced = TRUE; } if (number_percent() <= chance) { act("You assassinate $N in cold blood!", ch, NULL, victim, TO_CHAR); act("$n assassinates you in cold blood!", ch, NULL, victim, TO_VICT); act("$n assassinates $N in cold blood!", ch, NULL, victim, TO_NOTVICT); check_improve(ch, gsn_assassinate, TRUE, 1); if (victim->arena == FALSE) if (IS_SET(victim->act, PLR_PKILL)) /* No longer a PKILLER */ REMOVE_BIT(victim->act, PLR_PKILL); victim->hit = 1; raw_kill(ch, victim); } else { WAIT_STATE(ch, skill_table[gsn_assassinate].beats); act("Your assassination attempt on $N failed!", ch, NULL, victim, TO_CHAR); act("$n's assassination attempt on you failed!", ch, NULL, victim, TO_VICT); act("$n's assassination attempt on $N failed!", ch, NULL, victim, TO_NOTVICT); check_improve(ch, gsn_assassinate, FALSE, 1); multi_hit(ch, victim, TYPE_UNDEFINED); } return; } void do_flee(CHAR_DATA * ch, char *argument) { ROOM_INDEX_DATA *was_in; ROOM_INDEX_DATA *now_in; CHAR_DATA *victim; int attempt; 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 (ch->position < POS_FIGHTING) { do_stand(ch, ""); } if (IS_AFFECTED(ch, AFF_LETHARGY)) { send_to_char("You are too lethargic to flee.\n\r", ch); return; } if (ch->daze) { send_to_char("You are too dazed to flee!\n\r", ch); return; } was_in = ch->in_room; for (attempt = 0; attempt < 6; attempt++) { EXIT_DATA *pexit; int door; door = number_door(); if ((pexit = was_in->exit[door]) == 0 || pexit->u1.to_room == NULL || IS_SET(pexit->exit_info, EX_CLOSED) || number_range(0, ch->daze) != 0 || (IS_NPC(ch) && IS_SET(pexit->u1. to_room-> room_flags, ROOM_NO_MOB))) continue; move_char(ch, door, FALSE, FALSE); if ((now_in = ch->in_room) == was_in) continue; ch->in_room = was_in; 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 (IS_AFFECTED(ch, AFF_SNEAK)) { if ((ch->class == 2) && (number_percent() > 10)) { send_to_char("You snuck away safely.\n\r", ch); } if ((ch->class == 4) && (number_percent() > 10)) { send_to_char("You snuck away safely.\n\r", ch); } if ((ch->class == 0) && (number_percent() > 30)) { send_to_char("You snuck away safely.\n\r", ch); } if ((ch->class == 1) && (number_percent() > 30)) { send_to_char("You snuck away safely.\n\r", ch); } if ((ch->class == 3) && (number_percent() > 40)) { send_to_char("You snuck away safely.\n\r", ch); } if ((ch->class == 5) && (number_percent() > 60)) { send_to_char("You snuck away safely.\n\r", ch); } if ((ch->class == 6) && (number_percent() > 30)) { send_to_char("You snuck away safely.\n\r", ch); } } else { if (ch->arena == FALSE) { send_to_char("You lost 10 exp.\n\r", ch); ch->exp -= 10; } } } stop_fighting(ch, TRUE); return; } send_to_char("PANIC! You couldn't escape!\n\r", ch); return; } void do_rescue(CHAR_DATA * ch, char *argument) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; CHAR_DATA *fch; bool displaced; displaced = FALSE; //displace spell 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 (ch->fighting == victim) { send_to_char("Too late.\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 != NULL && !is_same_group(ch, victim->fighting)) { send_to_char("Kill stealing is not permitted.\n\r", ch); return; } if (IS_NPC(fch) && !is_same_group(ch, victim)) { send_to_char("Kill stealing is not permitted.\n\r", ch); return; } WAIT_STATE(ch, skill_table[gsn_rescue].beats); //Check if displaced if (is_affected(victim, skill_lookup("displace"))) if (displace_new_effect(ch, (void *) victim, -50, 0, 0)) { //You're rescuing the displaced version send_to_char ("You, amazingly, accidently step through the person while trying to rescue...\n\r", ch); displaced = TRUE; send_to_char("You fail the rescue.\n\r", ch); check_improve(ch, gsn_rescue, FALSE, 1); return; } 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; } 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); check_killer(ch, fch); set_fighting(ch, fch); set_fighting(fch, ch); return; } void do_kick(CHAR_DATA * ch, char *argument) { CHAR_DATA *victim; bool displaced; displaced = FALSE; //displace spell 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 (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; } WAIT_STATE(ch, skill_table[gsn_kick].beats); //Check if displaced if (is_affected(victim, skill_lookup("displace"))) if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) { //You're kicking the displaced version send_to_char("Your boot goes right through...\n\r", ch); displaced = TRUE; damage(ch, victim, 0, gsn_kick, DAM_BASH, TRUE); check_improve(ch, gsn_kick, FALSE, 1); return; } if (get_skill(ch, gsn_kick) > number_percent()) { damage(ch, victim, number_range(1, ch->level), gsn_kick, DAM_BASH, TRUE); check_improve(ch, gsn_kick, TRUE, 1); } else { damage(ch, victim, 0, gsn_kick, DAM_BASH, TRUE); check_improve(ch, gsn_kick, FALSE, 1); } check_killer(ch, victim); return; } void do_arial(CHAR_DATA * ch, char *argument) { CHAR_DATA *victim; bool displaced; displaced = FALSE; //displace spell if (!IS_NPC(ch) && ch->level < skill_table[gsn_arial].skill_level[ch->class]) { send_to_char("You better leave the flying to the birds.\n\r", ch); return; } if (IS_NPC(ch) && !IS_SET(ch->off_flags, OFF_ARIAL)) return; if ((victim = ch->fighting) == NULL) { send_to_char("You aren't fighting anyone.\n\r", ch); return; } WAIT_STATE(ch, skill_table[gsn_arial].beats); //Check if displaced if (is_affected(victim, skill_lookup("displace"))) if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) { //You're trying to land on the displaced version send_to_char("You land right on top... and through...\n\r", ch); displaced = TRUE; damage(ch, victim, 0, gsn_arial, DAM_BASH, TRUE); check_improve(ch, gsn_arial, FALSE, 1); return; } if (get_skill(ch, gsn_arial) > number_percent()) { damage(ch, victim, number_range(15, ch->level), gsn_arial, DAM_BASH, TRUE); check_improve(ch, gsn_arial, TRUE, 1); } else { damage(ch, victim, 0, gsn_arial, DAM_BASH, TRUE); check_improve(ch, gsn_arial, FALSE, 1); } check_killer(ch, victim); return; } void do_whirl(CHAR_DATA * ch, char *argument) { CHAR_DATA *victim; int chance; bool displaced; displaced = FALSE; //displace spell if (ch->position < POS_FIGHTING) { return; } if ((chance = get_skill(ch, gsn_whirl)) == 0) { send_to_char("You don't know how to whirl around opponents.\n\r", ch); 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 (!can_see(ch, victim)) { send_to_char("You can't see your opponent well enough to aim.\n\r", ch); return; } /* check duck */ if (check_duck(ch, victim, "whirl")) { WAIT_STATE(ch, skill_table[gsn_whirl].beats); return; } //Check if displaced if (is_affected(victim, skill_lookup("displace"))) if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) { //You're whirling the displaced version send_to_char("You whirl and swing... right through...\n\r", ch); chance = 0; displaced = TRUE; } /* and now the attack */ if (number_percent() < chance) { WAIT_STATE(ch, skill_table[gsn_whirl].beats); act("You whirl your body around $N and flank $M!", ch, NULL, victim, TO_CHAR); act("$n whirls $s body around you and flanks you!", ch, NULL, victim, TO_VICT); act("$n whirls $s body around $N and flanks $M!", ch, NULL, victim, TO_NOTVICT); check_improve(ch, gsn_whirl, TRUE, 1); one_hit(ch, victim, gsn_whirl); if (ch->fighting != victim) return; if (IS_AFFECTED(ch, AFF_HASTE)) one_hit(ch, victim, gsn_whirl); if (ch->fighting != victim) return; chance = get_skill(ch, gsn_second_attack) / 4; if (number_percent() < chance) { one_hit(ch, victim, gsn_whirl); check_improve(ch, gsn_second_attack, TRUE, 5); if (ch->fighting != victim) return; } chance = get_skill(ch, gsn_third_attack) / 6; if (number_percent() < chance) { one_hit(ch, victim, gsn_whirl); check_improve(ch, gsn_third_attack, TRUE, 6); if (ch->fighting != victim) return; } chance = get_skill(ch, gsn_fourth_attack) / 8; if (number_percent() < chance) { one_hit(ch, victim, gsn_whirl); check_improve(ch, gsn_fourth_attack, TRUE, 6); if (ch->fighting != victim) return; } chance = get_skill(ch, gsn_fifth_attack) / 10; if (number_percent() < chance) { one_hit(ch, victim, gsn_whirl); check_improve(ch, gsn_fifth_attack, TRUE, 6); if (ch->fighting != victim) return; } chance = get_skill(ch, gsn_sixth_attack) / 16; if (number_percent() < chance) { one_hit(ch, victim, gsn_whirl); check_improve(ch, gsn_sixth_attack, TRUE, 6); if (ch->fighting != victim) return; } chance = get_skill(ch, gsn_fifth_attack) / 10; if (number_percent() < chance) { one_hit(ch, victim, gsn_whirl); check_improve(ch, gsn_fifth_attack, TRUE, 6); if (ch->fighting != victim) return; } } else { WAIT_STATE(ch, skill_table[gsn_whirl].beats); act("You fail to whirl your body around $N.", ch, NULL, victim, TO_CHAR); act("$n tries to whirl $s body around you, but fails.", ch, NULL, victim, TO_VICT); act("$n tries to whirl $s body around $N, but fails.", ch, NULL, victim, TO_NOTVICT); check_improve(ch, gsn_whirl, FALSE, 1); } check_killer(ch, victim); return; } void do_circle(CHAR_DATA * ch, char *argument) { CHAR_DATA *victim; int chance; bool displaced; displaced = FALSE; //displace spell if (ch->position < POS_FIGHTING) { return; } if ((chance = get_skill(ch, gsn_circle)) == 0) { send_to_char("You don't know how to circle opponents.\n\r", ch); return; } if ((victim = ch->fighting) == NULL) { send_to_char("You aren't fighting anyone.\n\r", ch); return; } if (!can_see(ch, victim)) { send_to_char("You can't see your opponent well enough to aim.\n\r", ch); return; } /* check duck */ if (check_duck(ch, victim, "circle")) { WAIT_STATE(ch, skill_table[gsn_circle].beats); return; } //Check if displaced if (is_affected(victim, skill_lookup("displace"))) if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) { //You're circling the displaced version send_to_char("You circle and swing... right through...\n\r", ch); chance = 0; displaced = TRUE; } /* and now the attack */ if (number_percent() < chance) { WAIT_STATE(ch, (skill_table[gsn_circle].beats * 2) / 3); act("You circle around $N and attack!", ch, NULL, victim, TO_CHAR); act("$n circles around you and attacks!", ch, NULL, victim, TO_VICT); act("$n circles around $N and attacks!", ch, NULL, victim, TO_NOTVICT); check_improve(ch, gsn_circle, TRUE, 1); one_hit(ch, victim, gsn_circle); if (ch->fighting != victim) return; if (IS_AFFECTED(ch, AFF_HASTE)) one_hit(ch, victim, gsn_circle); if (ch->fighting != victim) return; chance = get_skill(ch, gsn_second_attack) / 4; if (number_percent() < chance) { one_hit(ch, victim, gsn_circle); check_improve(ch, gsn_second_attack, TRUE, 5); if (ch->fighting != victim) return; } chance = get_skill(ch, gsn_third_attack) / 6; if (number_percent() < chance) { one_hit(ch, victim, gsn_circle); check_improve(ch, gsn_third_attack, TRUE, 6); if (ch->fighting != victim) return; } chance = get_skill(ch, gsn_fourth_attack) / 8; if (number_percent() < chance) { one_hit(ch, victim, gsn_circle); check_improve(ch, gsn_fourth_attack, TRUE, 6); if (ch->fighting != victim) return; } chance = get_skill(ch, gsn_fifth_attack) / 12; if (number_percent() < chance) { one_hit(ch, victim, gsn_circle); check_improve(ch, gsn_fifth_attack, TRUE, 6); if (ch->fighting != victim) return; } chance = get_skill(ch, gsn_sixth_attack) / 16; if (number_percent() < chance) { one_hit(ch, victim, gsn_circle); check_improve(ch, gsn_sixth_attack, TRUE, 6); if (ch->fighting != victim) return; } } else { WAIT_STATE(ch, (skill_table[gsn_circle].beats * 2) / 3); act("You fail to circle around $N.", ch, NULL, victim, TO_CHAR); act("$n tries to circle around you, but fails.", ch, NULL, victim, TO_VICT); act("$n tries to circle around $N, but fails.", ch, NULL, victim, TO_NOTVICT); check_improve(ch, gsn_circle, FALSE, 1); } check_killer(ch, victim); return; } bool check_duck(CHAR_DATA * ch, CHAR_DATA * victim, char *attack_type) { int chance; if (!IS_AWAKE(victim)) return FALSE; chance = get_skill(victim, gsn_duck) * 3 / 4; if (!can_see(victim, ch)) chance /= 2; if (number_percent() >= chance) return FALSE; if (IS_NPC(victim) || !IS_SET(victim->act, PLR_AUTODEFENSE)) act("{yYou duck $n's $t.{x", ch, attack_type, victim, TO_VICT); if (IS_NPC(ch) || !IS_SET(ch->act, PLR_AUTODEFENSE)) act("{y$N ducks your $t.{x", ch, attack_type, victim, TO_CHAR); check_improve(victim, gsn_duck, TRUE, 6); return TRUE; } void do_disarm(CHAR_DATA * ch, char *argument) { CHAR_DATA *victim; OBJ_DATA *obj; int chance, hth, ch_weapon, vict_weapon, ch_vict_weapon; bool displaced; displaced = FALSE; //displace spell 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 ((victim = ch->fighting) == NULL) { send_to_char("You aren't fighting anyone.\n\r", ch); return; } if ((obj = get_eq_char(victim, WEAR_WIELD)) == NULL) { send_to_char("Your opponent is not wielding a weapon.\n\r", ch); return; } /* 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 */ /* 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 -= 2 * get_curr_stat(victim, STAT_STR); //Check if displaced if (is_affected(victim, skill_lookup("displace"))) if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) { //You're disarming the displaced version send_to_char("You attempt to disarm goes right through...\n\r", ch); chance = 0; displaced = TRUE; } /* 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_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); if (!IS_NPC(ch) && IS_NPC(mob) && (!HAS_TRIGGER(mob, TRIG_SURR) || !mp_percent_trigger(mob, ch, NULL, NULL, TRIG_SURR))) { act("$N seems to ignore your cowardly act!", ch, NULL, mob, TO_CHAR); multi_hit(mob, ch, TYPE_UNDEFINED); return; } if (!IS_NPC(mob)) { act("$N seems to ignore your cowardly act!", ch, NULL, mob, TO_CHAR); multi_hit(mob, ch, TYPE_UNDEFINED); return; } send_to_char("You lost 10 exp.\n\r", ch); gain_exp(ch, -10); } 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') && ch->position != POS_FIGHTING) { send_to_char("Slay whom?\n\r", ch); return; } if (((victim = get_char_room(ch, arg)) == NULL) && ch->position != POS_FIGHTING) { send_to_char("They aren't here.\n\r", ch); return; } if (ch->position == POS_FIGHTING) victim = ch->fighting; if (victim == NULL) { send_to_char("Victim == NULL, blue sucks.\n\r", ch); return; } if (ch == victim) { send_to_char("Suicide is a mortal sin.\n\r", ch); return; } if (IS_IMMORTAL(victim)) { if (!IS_NPC(ch)) { send_to_char("You failed.\n\r", ch); return; } } if (IS_IMMORTAL(victim) && ch->level <= victim->level) { send_to_char("You failed.\n\r", ch); return; } act("You slay $M in cold blood!", ch, NULL, victim, TO_CHAR); act("$n slays you in cold blood!", ch, NULL, victim, TO_VICT); act("$n slays $N in cold blood!", ch, NULL, victim, TO_NOTVICT); raw_kill(ch, victim); return; } void do_retribution(CHAR_DATA * ch, char *argument) { char buf[MAX_STRING_LENGTH]; if (IS_NPC(ch)) return; if (argument[0] != '\0') { buf[0] = '\0'; smash_tilde(argument); if (argument[0] == '-') { int len; bool found = FALSE; if (ch->pcdata->wrath == NULL || ch->pcdata->wrath[0] == '\0') { send_to_char("No lines left to remove.\n\r", ch); return; } strcpy(buf, ch->pcdata->wrath); for (len = strlen(buf); len > 0; len--) { if (buf[len] == '\r') { if (!found) { /* back it up */ if (len > 0) len--; found = TRUE; } else /* found the second one */ { buf[len + 1] = '\0'; free_string(ch->pcdata->wrath); ch->pcdata->wrath = str_dup(buf); send_to_char ("Your divine fury takes the form of:\n\r", ch); send_to_char(ch->pcdata->wrath ? ch->pcdata-> wrath : "(None).\n\r", ch); return; } } } buf[0] = '\0'; free_string(ch->pcdata->wrath); ch->pcdata->wrath = str_dup(buf); send_to_char ("Mortals no longer need fear your mark upon them.\n\r", ch); return; } if (argument[0] == '+') { if (ch->pcdata->wrath != NULL) strcat(buf, ch->pcdata->wrath); argument++; while (isspace(*argument)) argument++; } if (strlen(buf) >= 1024) { send_to_char ("Your fury is great indeed, too great. Use less lines.\n\r", ch); return; } strcat(buf, argument); strcat(buf, "\n\r"); free_string(ch->pcdata->wrath); ch->pcdata->wrath = str_dup(buf); } send_to_char("Your divine fury takes the form of:\n\r", ch); send_to_char(ch->pcdata->wrath ? ch->pcdata->wrath : "(None).\n\r", ch); return; } void do_wrath(CHAR_DATA * ch, char *argument) { char arg1[MAX_INPUT_LENGTH]; /* Lot of arguments */ char arg2[MAX_INPUT_LENGTH]; char arg3[MAX_INPUT_LENGTH]; char arg4[MAX_INPUT_LENGTH]; char arg5[MAX_INPUT_LENGTH]; char arg6[MAX_INPUT_LENGTH]; char buf[MAX_INPUT_LENGTH]; CHAR_DATA *victim; OBJ_DATA *SmittenEQ; const int MAX_WRATH_FRACTION = 95; int hp_percent = 0; int mana_percent = 0; int move_percent = 0; int pos = 0; int eq = 0; argument = one_argument(argument, arg1); /* Combine the arguments */ argument = one_argument(argument, arg2); argument = one_argument(argument, arg3); argument = one_argument(argument, arg4); argument = one_argument(argument, arg5); argument = one_argument(argument, arg6); if (IS_NPC(ch)) return; if (arg1[0] == '\0') { send_to_char("Syntax:\n\r", ch); send_to_char ("Wrath <victim> <hp> <mana> <move> <position> <equipment>\n\r", ch); return; } if ((victim = get_char_world(ch, arg1)) == NULL) { send_to_char("They are saved only through their absence.\n\r", ch); return; } if (!IS_NPC(victim) && get_trust(victim) >= get_trust(ch)) { send_to_char("Your reach exceeds your grasp.\n\r", ch); return; } if (arg2[0] != '\0') hp_percent = atoi(arg2); else hp_percent = 50; if (hp_percent > MAX_WRATH_FRACTION || hp_percent < 0) { send_to_char("Hp percent must be between 0 and 95.\n\r", ch); return; } if (arg3[0] != '\0') mana_percent = atoi(arg3); else mana_percent = 0; if (mana_percent > MAX_WRATH_FRACTION || mana_percent < 0) { send_to_char("Mana percent must be between 0 and 95.\n\r", ch); return; } if (arg4[0] != '\0') move_percent = atoi(arg4); else move_percent = 0; if (move_percent > MAX_WRATH_FRACTION || move_percent < 0) { send_to_char("Move percent must be between 0 and 95.\n\r", ch); return; } if (ch->alignment > 300) { act_new("Your actions have brought the holy power of $n upon you!", ch, NULL, victim, TO_VICT, POS_DEAD); act_new("$N has brought the holy power of $n upon themselves!", ch, NULL, victim, TO_NOTVICT, POS_DEAD); } if (ch->alignment > -301 && ch->alignment < 301) { act_new("Your actions have called the divine fury of $n upon you!", ch, NULL, victim, TO_VICT, POS_DEAD); act_new("$N has called the divine fury of $n upon themselves!", ch, NULL, victim, TO_NOTVICT, POS_DEAD); } if (ch->alignment < -300) { act_new("You are struck down by the infernal power of $n!!", ch, NULL, victim, TO_VICT, POS_DEAD); act_new ("The hellspawned, infernal power of $n has struck down $N!!", ch, NULL, victim, TO_NOTVICT, POS_DEAD); } if (ch->pcdata->wrath[0] != '\0') { send_to_char(ch->pcdata->wrath, victim); } if (hp_percent > 75 && victim->hit > victim->max_hit / 4) send_to_char("{RThat really did HURT!{x\n\r", victim); for (eq = 0; eq_table[eq] != NULL; eq++) { if (!str_prefix(eq_table[eq], arg6)) { if ((SmittenEQ = get_eq_char(victim, eq)) != NULL) { sprintf(buf, "$n's %s is blown away!", SmittenEQ->short_descr); act(buf, victim, NULL, NULL, TO_ROOM); sprintf(buf, "Your %s is blown away!\n\r", SmittenEQ->short_descr); send_to_char(buf, victim); unequip_char(victim, SmittenEQ); obj_from_char(SmittenEQ); obj_to_room(SmittenEQ, victim->in_room); } break; } } for (pos = 0; pos_table[pos] != NULL; pos++) { if (!str_prefix(pos_table[pos], arg5)) { victim->position = pos; /* This only works because of the way the pos_table is arranged. */ if (victim->position == POS_FIGHTING) victim->position = POS_STANDING; /* POS_FIGHTING is bad */ if (victim->position < POS_STUNNED) victim->position = POS_STUNNED; if (victim->position == 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); } if (victim->position == POS_RESTING || victim->position == POS_SITTING) { act("$n is knocked onto $s butt!", victim, NULL, NULL, TO_ROOM); send_to_char("You are knocked onto your butt!\n\r", victim); } break; } } /* Calculate total hp loss */ victim->hit -= ((victim->hit * hp_percent) / 100); if (victim->hit < 1) victim->hit = 1; /* Calculate total mana loss */ victim->mana -= ((victim->mana * mana_percent) / 100); if (victim->mana < 1) victim->mana = 1; /* Calculate total move loss */ victim->move -= ((victim->move * move_percent) / 100); if (victim->move < 1) victim->move = 1; send_to_char("Your will is done, your power felt.\n\r", ch); return; } bool has_number(char *string) { if (string[0] == '\0') return FALSE; for (; *string != '\0'; string++) { if (isdigit(*string)) return TRUE; } return FALSE; }