/***************************************************************************
* 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 Envy Diku Mud, you must comply with *
* the original Diku license in 'license.doc', the Merc license in *
* 'license.txt', as well as the Envy license in 'license.nvy'. *
* 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-1998 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@hypercube.org) *
* Gabrielle Taylor (gtaylor@hypercube.org) *
* 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 *
* *
* Code Adapted and Improved by Abandoned Realms Mud *
* and Aabahran: The Forsaken Lands Mud by Virigoth *
* *
* Continued Production of this code is available at www.flcodebase.com *
***************************************************************************/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include "merc.h"
#include "magic.h"
#include "interp.h"
#include "recycle.h"
#include "jail.h"
#include "cabal.h"
#include "bounty.h"
#include "armies.h"
#include "clan.h"
#include "autoquest.h"
extern void dreamprobe_cast( CHAR_DATA* victim, char* msg );
CHAR_DATA* masochism_effect( CHAR_DATA* ch, int dam, int dt );
extern bool forms(CHAR_DATA *ch, char *argument, AFFECT_DATA* paf);
extern void fulfill_bounty( CHAR_DATA *ch, CHAR_DATA *victim, char* name);
extern CHAR_DATA* undead_check_guard args( (CHAR_DATA* ch, CHAR_DATA* mob) );
extern CHAR_DATA* knight_rescue args( (CHAR_DATA* ch, CHAR_DATA* victim, int dam, int dt) );
extern void throw(CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA *obj, int throw, bool fThief, bool fAutoMiss);
extern bool check_melee_actions( CHAR_DATA* ch);
extern bool check_secart_actions( CHAR_DATA* ch);
extern void deathblow( CHAR_DATA* ch, CHAR_DATA* victim, int type, bool fMiss );
extern void fire_ranged_weapons( CHAR_DATA* ch, CHAR_DATA* victim );
//checks if doomsinger works
bool doomsingerCheck( CHAR_DATA* ch ){
if (IS_NPC(ch))
return FALSE;
else if (ch->class != gcn_blademaster)
return FALSE;
else if (!is_affected(ch, gsn_doomsinger))
return FALSE;
else if (!has_twohanded(ch))
return FALSE;
return TRUE;
}
//checks for possibility of deathstrike when blademaster dies to pc
bool deathstrikeCheck( CHAR_DATA* ch, CHAR_DATA* victim){
const int sn = skill_lookup("deathstrike");
int skill, anat, dur, dam;
if (ch == NULL || victim == NULL)
return FALSE;
else if (ch == victim)
return FALSE;
else if (ch->in_room == NULL || victim->in_room == NULL || ch->in_room != victim->in_room)
return FALSE;
else if (IS_IMMORTAL(ch))
return FALSE;
else if (IS_NPC(ch))
return FALSE;
else if (IS_NPC(victim))
return FALSE;
else if (getBmWep(victim, TRUE) == NULL)
return FALSE;
//get the skill/chance
skill = get_skill(victim, sn );
if (skill < 2)
return FALSE;
skill = (skill - 50) * 2;
skill += (get_curr_stat(victim, STAT_LUCK) - get_curr_stat(ch, STAT_LUCK)) * 5;
if (number_percent() > skill){
check_improve(victim, sn, FALSE, -99);
dam = 0;
}
else{
check_improve(victim, sn, TRUE, -99);
dam = ch->max_hit / 3;
}
//get the duration based on anatomy
anat = anatomy_lookup(race_table[ch->race].name);
anat = victim->pcdata->anatomy[anat];
if (anat < 101)
dur = 0;
else if (anat < 111)
dur = 1;
else
dur = 2;
act("$n suddenly spins about, $s back against your chest!", victim, NULL, ch, TO_VICT );
act("$n suddenly spins about, $s back against $N's chest!", victim, NULL, ch, TO_NOTVICT );
act_new("You spin about placing your back against $N's chest!", victim, NULL, ch, TO_CHAR, POS_DEAD );
//if they can survive the hit, just damage, otherwise, mortal wound
if (ch->hit < dam){
int temp_hp = ch->hit;
int temp_mana = ch->mana;
int temp_pos = victim->position;
victim->position = POS_STANDING;
//fake messages
dam_message( victim, victim, NULL, dam, sn, FALSE, FALSE, sn, TRUE );
dam_message( victim, ch, NULL, dam, sn, FALSE, FALSE, sn, TRUE );
mercy_effect(victim, ch, dur );
victim->position = temp_pos;
ch->hit = temp_hp;
ch->mana = temp_mana;
return TRUE;
}
else{
int temp_pos = victim->position;
victim->position = POS_STANDING;
dam /= 2;
dam_message( victim, victim, NULL, dam, sn, FALSE, FALSE, sn, TRUE );
damage(victim, ch, dam, sn, DAM_INTERNAL, TRUE );
victim->position = temp_pos;
return FALSE;
}
}
//blademaster deathweaver defense check
CHAR_DATA* bmDeathweaverCheck( CHAR_DATA* att, CHAR_DATA* weaver){
const int MAX_CHARS = 6;
CHAR_DATA* vch;
CHAR_DATA* chars[MAX_CHARS];
int max = 0;
if (IS_NPC(weaver))
return NULL;
else if (weaver->class != gcn_blademaster)
return NULL;
else if (weaver->mana < 2)
return NULL;
else if (!is_affected(weaver, gsn_deathweaver))
return NULL;
else if (number_percent() < (get_skill(weaver, gsn_deathweaver) / 2 + (get_curr_stat(weaver, STAT_LUCK) - 14) * 2) )
return NULL;
check_improve(weaver, gsn_deathweaver, TRUE, 1);
/* find possible redirection targets */
for (vch = att->in_room->people; vch; vch = vch->next_in_room){
if (vch->fighting == NULL || vch->fighting != weaver || vch == att)
continue;
else
chars[max++] = vch;
}
if (max < 1)
return NULL;
else
return (chars[number_range(0, max - 1)]);
}
/* checks if person has sheathed weapons, and no primaries */
bool is_sheathed(CHAR_DATA* ch){
if (get_eq_char(ch, WEAR_SHEATH_L) == NULL)
return FALSE;
if (get_eq_char(ch, WEAR_SHEATH_R) == NULL)
return FALSE;
if (get_eq_char(ch, WEAR_WIELD) != NULL)
return FALSE;
if (get_eq_char(ch, WEAR_SECONDARY) != NULL)
return FALSE;
return TRUE;
}
/* ninja shadow arts */
bool shadow_strike(CHAR_DATA* ch, CHAR_DATA* victim){
const int skill = get_skill(ch, gsn_shadow_strike);
const int damage_ch = (skill / 2)
+ 2 * (get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK))
+ (skill > 80? 3 : 0) + (skill > 90? 6 : 0) + (skill > 99? 9 : 0);
int chance = 20;
chance += UMAX(0, (skill - 75) * 2);
if (IS_NPC(ch))
return FALSE;
if (skill < 2 || number_percent() > chance)
return FALSE;
if (ch->fighting != victim)
return FALSE;
act("You feign and strike at $N's nerve point.", ch, NULL, victim, TO_CHAR);
act("$n feigns and reaches out towards $N.",ch, NULL, victim, TO_NOTVICT);
act("$n feigns and reaches out towards you.",ch, NULL, victim, TO_VICT);
if (number_percent() < damage_ch){
AFFECT_DATA af, *paf;
int high = -99;
int high_loc = 0;
bool fMax = FALSE;
check_improve(ch, gsn_shadow_strike, TRUE, 1);
af.location = number_range(1, 5); //(str to con)
//check for maximum -3 penalty
for (paf = victim->affected; paf; paf = paf->next){
if (paf->type != gsn_shadow_strike)
continue;
if (paf->location == af.location && paf->modifier <= -3)
fMax = TRUE;
if (paf->modifier > high){
high = paf->modifier;
high_loc = paf->location;
}
}
//if highest value is lower then -3 we do nothing
if (high != -99 && high < -3)
return FALSE;
//switch location if required
if (fMax){
if (high > -3 && high_loc)
af.location = high_loc;
else{
damage(ch, victim, number_range(1 + ch->level / 2, 1 + ch->level), gsn_shadow_strike, DAM_PIERCE, TRUE);
return FALSE;
}
}
af.type = gsn_shadow_strike;
af.level = ch->level;
af.duration = number_range(1, 3);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.modifier = -1;
affect_join(victim, &af);
damage(ch, victim, number_range(1 + ch->level / 2, 1 + ch->level), gsn_shadow_strike, DAM_PIERCE, TRUE);
return TRUE;
}
else{
damage(ch, victim, 0, gsn_shadow_strike, DAM_BASH, TRUE);
check_improve(ch, gsn_shadow_strike, FALSE, 2);
return FALSE;
}
}
/* this kicks in when a person fleels giving skilled opponent chance
for free hit to the back
*/
bool throw_effect(CHAR_DATA* ch, CHAR_DATA* victim, bool fAutoMiss){
/* all we do here is check for ninja/thief and their types of
ammo, then try to throw */
bool fThief = ch->class == class_lookup("thief");
bool fNinja = ch->class == class_lookup("ninja");
OBJ_DATA* obj;
int throws = (get_skill(ch, gsn_throw) - 60) / 8;
int i = 1;
//need double sheeth and empty sheaths
if (get_skill(ch, gsn_sheath) < 2
|| (get_eq_char(ch, WEAR_SHEATH_L) != NULL
&& get_eq_char(ch, WEAR_SHEATH_R) != NULL)
){
return FALSE;
}
else if ((!fThief && !fNinja) || !can_see(ch, victim))
return FALSE;
else if (number_percent() > get_skill(ch, gsn_throw)){
check_improve(ch, gsn_throw, FALSE, 1);
return FALSE;
}
/* get ammo */
for (obj = ch->carrying; obj; obj = obj->next_content){
if (obj->item_type != ITEM_THROW)
continue;
if (fNinja && obj->cost != 0)
continue;
if (fThief && obj->cost != 1)
continue;
break;
}
if (obj == NULL || obj->value[0] < 1)
return FALSE;
if (fNinja)
i = number_range(1, throws);
check_improve(ch, gsn_throw, TRUE, 1);
throw(ch, victim, obj, i, fThief, fAutoMiss);
return TRUE;
}
bool backcutter_effect(CHAR_DATA* ch, CHAR_DATA* victim, bool fAutoMiss){
OBJ_DATA* obj;
int chance = 0;
int sn = skill_lookup("backcutter");
int dam_type = DAM_PIERCE;
int dam = number_range(ch->level, 2 * ch->level);
const int cost = skill_table[sn].min_mana;
/* safety */
if (ch == NULL)
return FALSE;
if (IS_NPC(ch) || is_safe_quiet(ch, victim))
return FALSE;
if ( (chance = get_skill(ch, gsn_orealts_2nd)) < 1){
if ( (chance = get_skill(ch, sn)) < 1)
return FALSE;
}
/* final parting effect */
if (is_affected(ch, gsn_fpart) || is_affected(victim, gsn_fpart)){
/* check if fleeing person gets hit */
if (victim->hit < (25 * victim->max_hit / 100)){
int dam = number_range(2 * victim->level, 3 * victim->level);
if (is_affected(ch, gsn_fpart)){
affect_strip(ch, gsn_fpart);
act_new(skill_table[gsn_fpart].msg_off,ch,NULL,NULL,TO_CHAR,POS_DEAD);
}
if (is_affected(victim, gsn_fpart)){
affect_strip(victim, gsn_fpart);
act_new(skill_table[gsn_fpart].msg_off,victim,NULL,NULL,TO_CHAR,POS_DEAD);
}
damage(ch, victim, dam, gsn_fpart, DAM_INTERNAL, TRUE);
return TRUE;
}//sucessful final parting
}//final part check
/* check for mana */
if (ch->mana < cost)
return FALSE;
/* get weapon to be used if any */
obj = get_eq_char( ch, WEAR_WIELD );
/* warriors can only do this using spears and staffs */
if ((!obj || (obj->value[0] != WEAPON_SPEAR
&& obj->value[0] != WEAPON_STAFF))
&& ch->class == class_lookup("warrior")){
return FALSE;
}
if (fAutoMiss || number_percent() > chance){
check_improve(ch, gsn_orealts_2nd, FALSE, 1);
check_improve(ch, sn, FALSE, 1);
dam = 0;
}
/* draw mana only on success */
ch->mana -= cost;
/* hit them */
dam_type = obj ? attack_table[obj->value[3]].damage : DAM_BASH;
damage(ch, victim, dam, sn, dam_type, TRUE);
check_improve(ch, gsn_orealts_2nd, FALSE, 1);
check_improve(ch, sn, FALSE, 1);
return TRUE;
}
/* checks and validates if ch is on crusade against victim */
/* Returns CRUSADE_NONE, CRUSADE_MATCH, CRUSADE_NOTMATCH */
/* used in defense checks */
int check_crusade(CHAR_DATA* ch, CHAR_DATA* victim){
AFFECT_DATA* paf;
if (IS_NPC(ch) || IS_NPC(victim))
return CRUSADE_NONE;
if ( (paf = affect_find(ch->affected, gen_crusade)) == NULL)
return CRUSADE_NONE;
/* start checking */
switch(paf->level){
case CRUSADE_RACE:
if (paf->modifier == -1
&& IS_AVATAR(victim))
return CRUSADE_MATCH;
else if (paf->modifier == race_lookup("undead") && IS_UNDEAD(victim))
return CRUSADE_MATCH;
else if (paf->modifier == victim->race)
return CRUSADE_MATCH;
break;
case CRUSADE_CLASS:
if (paf->modifier == victim->class)
return CRUSADE_MATCH;
break;
case CRUSADE_CABAL:
if (victim->pCabal && paf->modifier == get_parent(victim->pCabal)->vnum)
return CRUSADE_MATCH;
break;
default:
return CRUSADE_NONE;
}
return CRUSADE_NOTMATCH;
}
/* checks for avenger match, uses same codes as check_crusade */
int check_avenger(CHAR_DATA* ch, CHAR_DATA* victim){
AFFECT_DATA* paf, *baf;
if (IS_NPC(ch))
return CRUSADE_NONE;
/* check for the paf */
if ( (paf = affect_find(ch->affected, gen_avenger)) == NULL)
return CRUSADE_NONE;
/* we know the char is avenger, check victim now */
if (!is_name(paf->string, victim->name))
return CRUSADE_NOTMATCH;
/* now if npc we check if this is the victim we are looking for */
if (IS_NPC(victim)){
for (baf = victim->affected; baf != NULL; baf = baf->next){
if (baf->type == gsn_avenger
&& baf->modifier == paf->modifier)
return CRUSADE_MATCH;
}
return CRUSADE_NOTMATCH;
}
else
return CRUSADE_MATCH;
}
/* handle all combinations of defenses */
bool check_defenses( CHAR_DATA *ch,
CHAR_DATA *victim,
OBJ_DATA* obj,
int dt,
int h_roll,
int lvl,
bool fVirt,
int sn){
const int MAX_DEF = 9; //Current maximum number of defenses
int seed[MAX_DEF];
int order[MAX_DEF];
int i;
int cur_max = MAX_DEF;
int cur_order = 0;
/* absolute fails */
if (victim->position < POS_FIGHTING
|| is_affected(victim, gsn_mortally_wounded)
|| is_affected(ch, gsn_feign))
return FALSE;
/* check for mirage */
if (ch->class == gcn_psi
&& is_affected(ch, gsn_mirage)
&& !saves_spell(ch->level, victim, DAM_MENTAL, skill_table[gsn_mirage].spell_type)){
return FALSE;
}
/* we first fill the seed with ordered defense numbers */
for (i = 0; i < MAX_DEF; i++){
seed[i] = i;
order[i] = -1;
}
/* begin to randomly put seed in order */
for (i = 0; i < MAX_DEF; i++){
int rand = number_range(0, cur_max - 1);
int j = 0;
/* place a random seed into a spot in order */
order[cur_order++] = seed[rand];
/* set that seed spot to -1 indicating empty */
seed[rand] = -1;
/* now we need to compact the seed array */
for (j = 0; j < cur_max; j++){
/* we check if the current sport is empty */
if (seed[j] == -1 ){
/* we compact by bubbling the empty spot up */
seed[j] = seed[j + 1];
seed[j + 1] = -1;
}
}
/* lower current max by one, since the empty spot is now at top */
cur_max--;
}
/* DEBUG
sendf(ch, "Defense Order [");
for (i = 0; i < MAX_DEF; i++)
sendf(ch, "%d ", order[i]);
sendf(ch, "]\n\r");
*/
/* now we apply the defenses */
/* PARRY 0
* DUAL PARRY 1
* MONK FIRST PARRY 2
* MONK SECOND PARRY 3
* DODGE 4
* SHIELD BLOCK 5
* WEAPON BLOCK 6
* RIPOSTE 7
* BLINK 8
*/
for (i = 0; i < MAX_DEF; i++){
switch (order[i]){
/* PARRY */
case 0:
if (check_parry( ch, victim, obj, dt, h_roll, lvl, fVirt, sn))
return TRUE;
break;
/* DUAL PARRY */
case 1:
if (check_dual_parry( ch, victim, obj, dt, h_roll, lvl, fVirt, sn))
return TRUE;
break;
/* MONK FIRST PARRY */
case 2:
if ( check_parry_monk( ch, victim, obj, dt, h_roll, lvl, FALSE, fVirt, sn))
return TRUE;
break;
/* MONK SECOND PARRY */
case 3:
if ( check_parry_monk( ch, victim, obj, dt, h_roll, lvl, TRUE, fVirt, sn))
return TRUE;
break;
/* DODGE */
case 4:
if ( check_dodge( ch, victim, obj, dt, h_roll, lvl, fVirt, sn) )
return TRUE;
break;
/* SHIELD BLOCK */
case 5:
if ( check_shield_block( ch, victim, obj, dt, h_roll, lvl, fVirt, sn) )
return TRUE;
break;
/* WEAPON BLOCK */
case 6:
if ( check_block( ch, victim, obj, dt, h_roll, lvl, fVirt, sn) )
return TRUE;
break;
/* RIPOSTE */
case 7:
if ( check_riposte( ch, victim, obj, dt, h_roll, lvl, fVirt, sn) )
return TRUE;
break;
/* BLINK */
case 8:
if ( check_blink( ch, victim, obj, dt, h_roll, lvl, fVirt, sn) )
return TRUE;
break;
}
/* END DEFENSES */
}
return FALSE;
}
/* Used to morph a mob to current victims level and power */
/* Assumes that the original stats for the mob were set for */
/* an opponent of level 50 */
void morph_mob(CHAR_DATA* mob, CHAR_DATA* victim){
MOB_INDEX_DATA* pMobIndex;
int mod = 0;
int hp_level = 0;
int level = mob->level;
int i = 0;
int hitroll = 0;
int damroll = 0;
bool fWarrior = FALSE;
bool fHalfWar = FALSE;
bool fRouge = FALSE;
bool fMage = FALSE;
/* decide what type of character this is */
if (IS_NPC(victim))
fWarrior = TRUE;
else if (victim->class == gcn_blademaster)
fWarrior = TRUE;
else if (victim->class == class_lookup("monk"))
fHalfWar = TRUE;
else if (victim->class == class_lookup("vampire"))
fWarrior = TRUE;
else{
int attack = 1;
int defense = 0;
/* Offense */
if (victim->pcdata->learned[gsn_second_attack])
attack++;
if (victim->pcdata->learned[gsn_third_attack])
attack++;
if (victim->pcdata->learned[gsn_fourth_attack])
attack++;
if (victim->pcdata->learned[gsn_blades])
attack += 2;
if (victim->pcdata->learned[gsn_dan_blade])
attack++;
/* defense */
if (victim->pcdata->learned[gsn_parry])
defense++;
if (victim->pcdata->learned[gsn_dual_parry])
defense++;
if (victim->pcdata->learned[gsn_dodge])
defense++;
if (victim->pcdata->learned[gsn_shield_block]
|| victim->pcdata->learned[gsn_2hands])
defense++;
if (victim->pcdata->learned[gsn_terra_shield])
defense++;
if (victim->pcdata->learned[gsn_blades])
defense++;
if (victim->pcdata->learned[skill_lookup("blur")])
defense++;
/* select which type this is */
if (attack > 3 || defense > 3)
fWarrior = TRUE;
else if (attack > 2 || defense > 1){
if (victim->pcdata->learned[gsn_hide]
|| victim->pcdata->learned[gsn_camouflage])
fRouge = TRUE;
else
fHalfWar = TRUE;
}
else
fMage = TRUE;
}
act("$n seems to change in size and shape to match yours.",
mob, NULL, victim, TO_VICT);
act("$n seems to change in size and shape to match $N's.",
mob, NULL, victim, TO_NOTVICT);
/* adjust things base on general archtype */
/* most of this is based on special guards plus few modifications */
if (!IS_NPC(mob)){
bug("morph_mob: PC passed as mob.", 0);
return;
}
else{
if ( ( pMobIndex = get_mob_index( mob->pIndexData->vnum)) == NULL){
bug("morph_mob: mob index not found.", mob->pIndexData->vnum);
return;
}
}
if (fWarrior){
level += 2;
hitroll += level/5;
damroll += level/6;
}
else if (fHalfWar){
level += 1;
hitroll += level/6;
damroll += level/6;
}
else if (fRouge){
hitroll -= level/6;
damroll -= level/8;
}
else if (fMage){
level --;
hitroll -= level/8;
damroll -= level/10;
}
mob->size = victim->size;
level = UMAX(5, (victim->level + (victim->level/15) ));
mod = 100 * victim->level / pMobIndex->level;
mob->level = level;
for (i=0;i < MAX_STATS; i++)
mob->perm_stat[i] = get_max_train(victim, i);
for (i=0; i < 4; i++)
mob->armor[i] = pMobIndex->ac[i] * mod / 100;
hp_level = 100 * mob->hit / mob->max_hit;
mob->max_hit = UMAX(1, mod * mob->max_hit / 100);
mob->hit = UMAX(1, hp_level * mob->max_hit / 100);
damroll = pMobIndex->damage[DICE_BONUS] * mod / 100;
hitroll = pMobIndex->hitroll * mod / 100;
mob->hitroll = hitroll;
mob->damroll = damroll;
mob->damage[DICE_NUMBER] = UMAX(1, mod * pMobIndex->damage[DICE_NUMBER] / 100);
}
/* PREVOILENCE_CHECK */
/* Called in fight.c only */
/* same args as set_fighting in which it will be called. */
int PREVIOLENCE_CHECK( CHAR_DATA *ch, CHAR_DATA *victim)
{
CHAR_DATA* vch = ch;
AFFECT_DATA* paf;
AFFECT_DATA* paf_next;
int fSuccess = TRUE;
int result = 0;
for (paf = vch->affected; paf != NULL; paf = paf_next) {
paf_next = paf->next;
//we only run the update once per effect.
if (paf_next != NULL)
if (paf->type == paf_next->type)
continue;
if (IS_GEN(paf->type)) {
if ((result = run_effect_update(vch, paf, victim, paf->type, NULL, NULL,
TRUE, EFF_UPDATE_PREVIOLENCE)) != TRUE) {
if (result == -1) {
return -1;
}
else {
fSuccess = result;
}
}
}
}
return fSuccess;
}//end PREVIOLENCE_CHECK
/* POSTVOILENCE_CHECK */
/* Called in fight.c only */
/* same args as stop_fighting in which it will be called. */
int POSTVIOLENCE_CHECK( CHAR_DATA *ch)
{
CHAR_DATA* vch = ch;
AFFECT_DATA* paf;
AFFECT_DATA* paf_next;
int fSuccess = TRUE;
int result = 0;
for (paf = vch->affected; paf != NULL; paf = paf_next) {
paf_next = paf->next;
//we only run the update once per effect.
if (paf_next != NULL) {
if (paf->type == paf_next->type) {
continue;
}
}
if (IS_GEN(paf->type)) {
if ((result = run_effect_update(vch, paf, NULL, paf->type,
NULL, NULL, TRUE, EFF_UPDATE_POSTVIOLENCE)) != TRUE) {
if (result == -1) {
return -1;
}
else {
fSuccess = result;
}
}
}
}
return fSuccess;
}//end POSTVIOLENCE_CHECK
/* DODGE_CHECK */
/* Called in fight.c only */
inline int DODGE_CHECK( CHAR_DATA *ch, CHAR_DATA *victim, int dt)
{
int fSuccess = TRUE;
CHAR_DATA* vch = ch;
AFFECT_DATA* paf;
AFFECT_DATA* paf_next;
int result = 0;
for (paf = vch->affected; paf != NULL; paf = paf_next) {
paf_next = paf->next;
//we only run the update once per effect.
if (paf_next != NULL) {
if (paf->type == paf_next->type) {
continue;
}
}
//GENS THAT ARE HANDLED SEPERATLY
if (IS_GEN(paf->type)) {
if ((result = run_effect_update(vch, victim, paf, paf->type,
&dt, NULL, TRUE, EFF_UPDATE_DODGE)) != TRUE) {
if (result == -1) {
return -1;
}
else {
fSuccess = result;
}
}
}
}
return fSuccess;
}// end DODGE_CHECK
/* PARRY_CHECK */
/* Called in fight.c only */
inline int PARRY_CHECK( CHAR_DATA *ch, OBJ_DATA* obj, OBJ_DATA* vobj, int dt)
{
int fSuccess = TRUE;
CHAR_DATA* vch = ch;
AFFECT_DATA* paf;
AFFECT_DATA* paf_next;
int result = 0;
//OBJECT ORIENTATED EFFECS>
if (obj == NULL || vobj == NULL) {
return fSuccess;
}
for (paf = obj->affected; paf != NULL; paf = paf_next) {
paf_next = paf->next;
//we only run the update once per effect.
if (paf_next != NULL) {
if (paf->type == paf_next->type) {
continue;
}
}
//GENS THAT ARE HANDLED SEPERATLY
if (IS_GEN(paf->type)) {
if ((result = run_effect_update(vch, obj, vobj, paf->type,
&dt, NULL, TRUE, EFF_UPDATE_PARRY)) != TRUE) {
if (result == -1) {
return -1;
}
else {
fSuccess = result;
}
}
}
}
return fSuccess;
}// end PARRY_CHECK
/* SHBLOCK_CHECK */
/* Called in fight.c only */
inline int SHBLOCK_CHECK( CHAR_DATA *ch, OBJ_DATA* obj, OBJ_DATA* vobj, int dt)
{
int fSuccess = TRUE;
CHAR_DATA* vch = ch;
AFFECT_DATA* paf;
AFFECT_DATA* paf_next;
int result = 0;
//OBJECT ORIENTATED EFFECS>
if (obj == NULL || vobj == NULL) {
return fSuccess;
}
for (paf = obj->affected; paf != NULL; paf = paf_next) {
paf_next = paf->next;
//we only run the update once per effect.
if (paf_next != NULL) {
if (paf->type == paf_next->type) {
continue;
}
}
//GENS THAT ARE HANDLED SEPERATLY
if (IS_GEN(paf->type)) {
if ((result = run_effect_update(vch, obj, vobj, paf->type, &dt,
NULL, TRUE, EFF_UPDATE_SHBLOCK)) != TRUE) {
if (result == -1) {
return -1;
}
else {
fSuccess = result;
}
}
}
}
return fSuccess;
}// end SHBLOCK_CHECK
/* PREKILL_CHECK */
/* Called in fight.c only */
/* same args as raw_kill in which it will be called. */
int PREKILL_CHECK( CHAR_DATA *ch, CHAR_DATA *victim)
{
CHAR_DATA* vch = ch;
AFFECT_DATA* paf;
AFFECT_DATA* paf_next;
int fSuccess = TRUE;
int result = 0;
for (paf = vch->affected; paf != NULL; paf = paf_next) {
paf_next = paf->next;
//we only run the update once per effect.
if (paf_next != NULL) {
if (paf->type == paf_next->type) {
continue;
}
}
if (IS_GEN(paf->type)) {
if ((result = run_effect_update(vch, victim, paf, paf->type,
NULL, NULL, TRUE, EFF_UPDATE_PREKILL)) != TRUE) {
if (result == -1) {
return -1;
}
else {
fSuccess = result;
}
}
}
}
return fSuccess;
}//end PREKILL_CHECK
/* PREDEATH_CHECK */
/* Called in fight.c only */
/* same args as raw_kill in which it will be called. */
int PREDEATH_CHECK( CHAR_DATA *ch, CHAR_DATA *victim)
{
CHAR_DATA* vch = ch;
AFFECT_DATA* paf;
AFFECT_DATA* paf_next;
int fSuccess = TRUE;
int result = 0;
//MALFORM WEAPON
run_effect_update(victim, vch, NULL, gen_malform, NULL, NULL, TRUE, EFF_UPDATE_PREDEATH);
for (paf = vch->affected; paf != NULL; paf = paf_next) {
paf_next = paf->next;
//we only run the update once per effect.
if (paf_next != NULL) {
if (paf->type == paf_next->type) {
continue;
}
}
if (IS_GEN(paf->type)) {
if ((result = run_effect_update(vch, victim, paf, paf->type,
NULL, NULL, TRUE, EFF_UPDATE_PREDEATH)) != TRUE) {
if (result == -1) {
return -1;
}
else {
fSuccess = result;
}
}
}
}
return fSuccess;
}//end PREDEAH_CHECK
/* POSTKILL_CHECK */
/* Called in fight.c only */
/* same args as raw_kill in which it will be called. */
int POSTKILL_CHECK( CHAR_DATA *ch, CHAR_DATA *victim)
{
CHAR_DATA* vch = ch;
AFFECT_DATA* paf;
AFFECT_DATA* paf_next;
int fSuccess = TRUE;
int result = 0;
//MALFORM WEAPON//
run_effect_update(vch, victim, NULL, gen_malform, NULL, NULL, TRUE, EFF_UPDATE_POSTKILL);
//COUP
run_effect_update(vch, victim, NULL, gen_coup, NULL, NULL, TRUE, EFF_UPDATE_POSTKILL);
for (paf = vch->affected; paf != NULL; paf = paf_next) {
paf_next = paf->next;
//we only run the update once per effect.
if (paf_next != NULL) {
if (paf->type == paf_next->type) {
continue;
}
}
//SPECIAL GENS HERE
if (paf->type == gen_malform
|| paf->type == gen_coup) {
continue;
}
if (IS_GEN(paf->type)) {
if ((result = run_effect_update(vch, victim, paf, paf->type,
NULL, NULL, TRUE, EFF_UPDATE_POSTKILL)) != TRUE) {
if (result == -1) {
return -1;
}
else {
fSuccess = result;
}
}
}
}
return fSuccess;
}//end POSTKILL_CHECK
/* POSTDEATH_CHECK */
/* Called in fight.c only */
/* same args as raw_kill in which it will be called. */
/* FIRST argument is the attacker, SECOND the person that died */
int POSTDEATH_CHECK( CHAR_DATA *ch, CHAR_DATA *victim)
{
CHAR_DATA* vch = victim;
AFFECT_DATA* paf;
AFFECT_DATA* paf_next;
int fSuccess = TRUE;
int result = 0;
//COUP
run_effect_update(victim, ch, NULL, gen_coup, NULL, NULL, TRUE, EFF_UPDATE_POSTDEATH);
for (paf = vch->affected; paf != NULL; paf = paf_next) {
paf_next = paf->next;
//we only run the update once per effect.
if (paf_next != NULL) {
if (paf->type == paf_next->type) {
continue;
}
}
//SPECIAL GENS HERE
if (paf->type == gen_coup) {
continue;
}
if (IS_GEN(paf->type)) {
if ((result = run_effect_update(victim, vch, paf, paf->type,
NULL, NULL, TRUE, EFF_UPDATE_POSTDEATH)) != TRUE) {
if (result == -1) {
return -1;
}
else {
fSuccess = result;
}
}
}
}
return fSuccess;
}//end POSTDEATH_CHECK
/* PRECOMBAT_CHECK */
/* Called in fight.c only */
/* same args as multi_hit in which it will be called. */
int PRECOMBAT_CHECK( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
//This is the function that perfomrs checking for any
//PRE_COMBAT effects.
CHAR_DATA* vch = ch;
AFFECT_DATA* paf;
AFFECT_DATA* paf_next;
int fSuccess = TRUE;
int result = 0;
/* victim check
for (paf = victim->affected; paf != NULL; paf = paf_next) {
paf_next = paf->next;
//we only run the update once per effect.
if (paf_next != NULL) {
if (paf->type == paf_next->type) {
continue;
}
}
if (IS_GEN(paf->type)) {
if ((result = run_effect_update(vch, paf, victim, paf->type,
&dt, NULL, TRUE, EFF_UPDATE_PRECOMBAT)) != TRUE) {
if (result == -1) {
return -1;
}
else {
fSuccess = result;
}
}
}
}
*/
for (paf = vch->affected; paf != NULL; paf = paf_next) {
paf_next = paf->next;
//we only run the update once per effect.
if (paf_next != NULL) {
if (paf->type == paf_next->type) {
continue;
}
}
//SPECIAL GENS HERE
if (IS_GEN(paf->type)) {
if ((result = run_effect_update(vch, paf, victim, paf->type,
&dt, NULL, TRUE, EFF_UPDATE_PRECOMBAT)) != TRUE) {
if (result == -1) {
return -1;
}
else {
fSuccess = result;
}
}
}
}
return fSuccess;
}//end PRECOMBAT CHECK
/* POSTCOMBAT_CHECK */
/* Called in fight.c only */
/* same args as multi_hit in which it will be called. */
int POSTCOMBAT_CHECK( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
CHAR_DATA* vch = ch;
AFFECT_DATA* paf;
AFFECT_DATA* paf_next;
int result = 0;
int fSuccess = TRUE;
//SPECIAL GENS
//-----PANIC---//
if (vch->class == class_lookup("berserker")) {
fSuccess = run_effect_update(vch, NULL, victim, gen_panic, NULL,
NULL, TRUE, EFF_UPDATE_POSTCOMBAT);
}
//-----PLUMBUM---//
if ( (paf = affect_find(ch->affected, gsn_plumbum)) != NULL) {
run_effect_update(ch, victim, paf, gen_plumbum, NULL, NULL, dt, EFF_UPDATE_POSTCOMBAT);
}
for (paf = vch->affected; paf != NULL; paf = paf_next) {
paf_next = paf->next;
//we only run the update once per effect.
if (paf_next != NULL) {
if (paf->type == paf_next->type) {
continue;
}
}
//GENS THAT ARE HANDLED SEPERATLY
if (paf->type == gen_panic
|| paf->type == gen_plumbum) {
continue;
}
if (IS_GEN(paf->type)) {
if ((result = run_effect_update(vch, victim, paf, paf->type,
NULL, NULL, dt, EFF_UPDATE_POSTCOMBAT)) != TRUE) {
if (result == -1) {
return -1;
}
else {
fSuccess = result;
}
}
}
}
return fSuccess;
}//end POSTCOMBAT CHECK
/* PREDAMAGE_CHECK */
/* Called in fight.c only */
/* same args as damage in which it will be called. */
int PREDAMAGE_CHECK(CHAR_DATA *ch,CHAR_DATA *victim,int* dam,int* dt,int* dam_type)
{
//This is the function that perfomrs checking for any
//PRE_DAMAGE effects.
CHAR_DATA* vch = ch;
AFFECT_DATA* paf;
AFFECT_DATA* paf_next;
int result = 0;
int fSuccess = TRUE;
//SPECIAL GENS
//----POSITION----//
if (victim->position == POS_MEDITATE) {
act_new("You stop meditating and stand up.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n stops meditating and stands up.",victim,NULL,NULL,TO_ROOM);
// victim->position = POS_STANDING;
}
for (paf = victim->affected; paf; paf = paf_next ){
paf_next = paf->next;
//-----BLADES----- ON VICTIM (DEFLECT)
if ( paf->type == gen_blades){
run_effect_update(ch, victim, paf, paf->type, dam, dam_type, *dt, EFF_UPDATE_PREDAMAGE);
}
//-----TERRASHIELD----- ON VICTIM (DEFLECT)
else if ( paf->type == gen_terra_shield){
run_effect_update(ch, victim, paf, paf->type, dam, dam_type, *dt, EFF_UPDATE_PREDAMAGE);
}
//-----REFLECTIVE SHIELD----- ON VICTIM (REFLECT)
else if ( paf->type == gen_ref_shield) {
run_effect_update(ch, victim, paf, paf->type, dam, dam_type,*dt, EFF_UPDATE_PREDAMAGE);
}
//-----CHRONO SHIELD----- ON VICTIM (ABSORB)
else if ( paf->type == gen_chron) {
run_effect_update(ch, victim, paf, paf->type, dam, dam_type,*dt, EFF_UPDATE_PREDAMAGE);
}
//-----EFUZAN'S WARD----- ON VICTIM (REDUCTION)
else if ( paf->type == gen_sav_ward) {
run_effect_update(ch, victim, paf, paf->type, dam, dam_type, *dt, EFF_UPDATE_PREDAMAGE);
}
//------PC CHARM ON VICTIM (WAKE UP)
else if (paf->type == gen_pc_charm) {
run_effect_update(victim, victim, paf, paf->type, dam, dt, TRUE, EFF_UPDATE_PREDAMAGE);
}
//------REQUEST ON VICTIM (SHATTER)
else if (paf->type == gen_request) {
run_effect_update(victim, victim, paf, paf->type, dam, dt, TRUE, EFF_UPDATE_PREDAMAGE);
}
//------CONJURE ON VICTIM (SHATTER)
else if ( paf->type == gen_conjure) {
run_effect_update(victim, victim, paf, paf->type, dam, dt, TRUE, EFF_UPDATE_PREDAMAGE);
}
//------CHANT ON VICTIM (DRAIN)
else if (paf->type == gen_chant) {
run_effect_update(victim, victim, paf, paf->type, dam, dt, TRUE, EFF_UPDATE_PREDAMAGE);
}
}
/* NORMAL PAFS */
for (paf = vch->affected; paf != NULL; paf = paf_next) {
paf_next = paf->next;
//we only run the update once per effect.
if (paf_next != NULL) {
if (paf->type == paf_next->type) {
continue;
}
}
//GENS THAT ARE HANDLED IN ABOVE
if (paf->type == gen_blades
|| paf->type == gen_terra_shield
|| paf->type == gen_sav_ward
|| paf->type == gen_ref_shield
|| paf->type == gen_chron) {
continue;
}
/* special check for apierce */
if (paf->type == gen_apierce){
if ((result = run_effect_update(vch, victim, paf, paf->type, dam,
dam_type, *dt, EFF_UPDATE_PREDAMAGE)) == TRUE){
*dt = gen_apierce;
}
}
//------BATTER( NEEDS A DAMAGE CHANGE IF CON DAMAGE ACTIVE)
else if ( paf->type == gen_batter){
if (number_percent() < (get_skill(ch, gsn_con_damage) - 60) * 2){
*dam_type = DAM_BASH;
if (*dt >= TYPE_NOBLOCKHIT)
*dt = attack_lookup("slap") + TYPE_NOBLOCKHIT;
else if (*dt >= TYPE_HIT)
*dt = attack_lookup("slap") + TYPE_HIT;
check_improve(vch, gsn_con_damage, TRUE, 1);
}
run_effect_update(vch, victim, paf, paf->type, dam, dam_type, *dt, EFF_UPDATE_PREDAMAGE);
}
else if (IS_GEN(paf->type)) {
if ((result = run_effect_update(vch, victim, paf, paf->type, dam,
dam_type, *dt, EFF_UPDATE_PREDAMAGE)) != TRUE) {
if (result == -1) {
return -1;
}
else {
fSuccess = result;
}
}
}
}
return fSuccess;
}//end PREDAMAGE CHECK
/* POSTDAMAGE_CHECK */
/* Called in fight.c only */
/* same args as damage in which it will be called. */
int POSTDAMAGE_CHECK(CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA* obj, int dam,int dt,int dam_type)
{
//THIS IS SPLIT INTO TW PARTS:
//OBJECT AND CHARATER
CHAR_DATA* vch = ch;
AFFECT_DATA* paf;
AFFECT_DATA* paf_next;
int result = 0;
int fSuccess = TRUE;
//-----VENGEGEANCE----- ON VICTIM (REFLECT)
if ( (paf = affect_find(victim->affected, gen_vengeance)) != NULL) {
run_effect_update(vch, victim, paf, paf->type, &dam, &dam_type, dt, EFF_UPDATE_POSTDAMAGE);
}
//-----TEMPORAL AVENGER----- ON VICTIM (COLLECT)
if ( (paf = affect_find(victim->affected, gen_temp_avenger)) != NULL) {
run_effect_update(vch, victim, paf, paf->type, &dam, &dam_type, dt, EFF_UPDATE_POSTDAMAGE);
}
//REST OF EFFECTCS
for (paf = vch->affected; paf != NULL; paf = paf_next) {
paf_next = paf->next;
//we only run the update once per effect.
if (paf_next != NULL) {
if (paf->type == paf_next->type) {
continue;
}
}
//GENS THAT ARE HANDLED SEPERATLY
if (paf->type == gen_vengeance)
continue;
if (IS_GEN(paf->type)) {
if ((result = run_effect_update(vch, victim, paf, paf->type, &dam,
&dam_type, dt, EFF_UPDATE_POSTDAMAGE)) != TRUE) {
if (result == -1) {
return -1;
}
else {
fSuccess = result;
}
}
}
}
//OBJECT ORIENTATED EFFECS>
if (obj == NULL || victim == NULL)
return fSuccess;
for (paf = obj->affected; paf != NULL; paf = paf_next)
{
paf_next = paf->next;
//we only run the update once per effect.
if (paf_next != NULL) {
if (paf->type == paf_next->type) {
continue;
}
}
//GENS THAT ARE HANDLED SEPERATLY
if (IS_GEN(paf->type)) {
if ((result = run_effect_update(vch, victim, obj, paf->type, &dam,
&dam_type, dt, EFF_UPDATE_POSTDAMAGE)) != TRUE) {
if (result == -1) {
return -1;
}
else {
fSuccess = result;
}
}
}
}
return fSuccess;
/*
//-----DARK METAMORPHOSIS---//
if ( (paf = affect_find(obj->affected, gen_dark_meta)) != NULL)
fSuccess = run_effect_update(ch, victim, obj, gen_dark_meta, &dam,
&dam_type, TRUE, EFF_UPDATE_POSTDAMAGE);
//-----Soul Reaver---//
if ( (paf = affect_find(obj->affected, gen_soul_reaver)) != NULL)
fSuccess = run_effect_update(ch, victim, obj, gen_soul_reaver, &dam, &dam_type, TRUE, EFF_UPDATE_POSTDAMAGE);
//-----Hand of Chaos---//
if ( (paf = affect_find(obj->affected, gen_handof_chaos)) != NULL)
fSuccess = run_effect_update(ch, victim, obj, gen_handof_chaos, &dam, &dam_type, TRUE, EFF_UPDATE_POSTDAMAGE);
*/
return fSuccess;
}//end POSTDAMAGE CHECK
//-----------------------------------END CHECKS----------------------------//
/* ogre damage ignore */
bool ogre_ignore(CHAR_DATA* ch, CHAR_DATA* victim, OBJ_DATA* obj, int dam, int dt, bool fVirt)
{
int chance = 5 + (dam > 50? 5 : 0)
+ (dam > 120 ? 80 : 0)
+ (dam > 350 ? 45 : 0);
bool fOgre = victim->race == grn_ogre;
bool fBlood = get_skill(victim, gsn_bloodhaze) > 1;
//safety
if (obj == NULL )
fVirt = FALSE;
if (ch == NULL || victim == NULL || ch == victim)
return FALSE;
if (!fOgre && !fBlood){
return FALSE;
}
/* bonus from bloodhaze for ogres */
if (fOgre && fBlood){
chance += 15;
}
if (dam < 1 ) {
return FALSE;
}
//roll for ignore
if (number_range(1, 1000) < chance) {
char buf[MIL];
sprintf(buf, "You roar in pain and ignore %s %s.",
fVirt? "$p's" : "$N's",
get_vir_attack(dt));
act(buf, victim, obj, ch, TO_CHAR);
sprintf(buf, "$n roars in pain and ignores %s %s.",
fVirt? "$p's" : "$N's",
get_vir_attack(dt));
act(buf, victim, obj, ch, TO_NOTVICT);
sprintf(buf, "$n roars in pain and ignores %s %s.",
fVirt? "$p's" : "your",
get_vir_attack(dt));
act(buf, victim, obj, ch, TO_VICT);
return TRUE;
}
return FALSE;
}
/* juggernaut plate damage ignore */
bool jugger_ignore(CHAR_DATA* ch, CHAR_DATA* victim, OBJ_DATA* obj, int dam, int dt, bool fVirt)
{
int chance = 40 + (dam < 41 ? (41 - dam) * 4 : 0);
//safety
if (obj == NULL)
fVirt = FALSE;
if (ch == victim)
return FALSE;
if (is_armor_enhanced(victim) < ENHANCE_JUGGER){
return FALSE;
}
if (dam < 1) {
return FALSE;
}
//roll for ignore
if (number_range(1, 1000) < chance) {
char buf[MIL];
sprintf(buf, "%s %s glances off of the Juggernaut Plate.",
fVirt? "$p's" : "$N's",
get_vir_attack(dt));
act(buf, victim, obj, ch, TO_ALL);
return TRUE;
}
return FALSE;
}
/* check_anatomy */
/* returns TRUE if learned, -1 if mob level reached. */
inline int check_anatomy_improve(CHAR_DATA* ch, int anatomy, bool fMOB, int iMobLvl)
{
/*
runs a check for improvement of monk anatomies.
Anatomies are learned from mobs bit slower then pc's but the
maximum level is npc_max of the mob level.
*/
const int npc_max = 200;//(lvl 50 mob can teach up to 100 anatom.)
const int npc_pen = -10;//penatly to learnm from npc
const int npc_extra = 4000;
const int pc_extra = 1000;
int chance = 50 + (anatomy? 0: npc_pen); //base level
int max = get_max_anat(ch, anatomy);
//Check for max anatomy
if (ch->pcdata->anatomy[anatomy] >= max)
{
ch->pcdata->anatomy[anatomy] = max;
return FALSE;
}
//INT
chance += int_app[get_curr_stat(ch,STAT_INT)].learn / 5;
//LEVEL
chance += ch->level / 4;
//WIS
chance += get_curr_stat(ch,STAT_WIS) / 2;
//CURRENT VALUE
chance -= ch->pcdata->anatomy[anatomy] / 2;
//Check to learn
if (number_range(1,(fMOB? npc_extra: pc_extra)) < chance)
{
//MOB LEARN CHECK
if (fMOB && (ch->pcdata->anatomy[anatomy] >= (npc_max * iMobLvl / 100 )))
return -1;
ch->pcdata->anatomy[anatomy]++;
return TRUE;
}
return FALSE;
}
/* check_anatomy */
/* returns damage increase or 0 in percent */
inline int check_anatomy(CHAR_DATA* ch, CHAR_DATA* victim)
{
int diceroll = 0;
int result = 0;
int anatomy = 0;
bool fMOB = IS_NPC(victim);
if ( IS_NPC(ch) || get_skill(ch,gsn_anatomy) < 1)
return FALSE;
diceroll = number_percent();
diceroll -= 2*(get_curr_stat(ch,STAT_LUCK) - 16);
if (diceroll <= get_skill(ch,gsn_anatomy))
{
if (race_table[victim->race].pc_race)
anatomy = anatomy_lookup(pc_race_table[victim->race].anatomy);
//check for improve of anatomies.
check_improve(ch,gsn_anatomy,TRUE,1);
result = check_anatomy_improve(ch, anatomy, fMOB, victim->level);
if (result == -1)
sendf(ch, "You sense there is little more you can learn about %s here.\n\r", anatomy_table[anatomy].name);
else if (result)
sendf(ch,"You have gained knowledge about %s!\n\r", anatomy_table[anatomy].name);
result = number_range(ch->pcdata->anatomy[anatomy] / 3, get_skill(ch,gsn_anatomy) / 5 + ch->pcdata->anatomy[anatomy]);
return (UMIN(result, 110));
}//end success check
return 0;
}
/*Unholy Gift*/
/*exists only in fight.c*/
bool unholy_gift(CHAR_DATA* ch, CHAR_DATA* victim)
{
//This is the ability only given to a single head vamp.
//It allows for conversion of race to _undead_ when killed.
int chance_mod = 30;
int skill;
//EZ
if ( (ch==NULL) || (victim == NULL) )
return FALSE;
//This only works if the character is not undead. and is an PC
if (IS_NPC(victim) || IS_UNDEAD(victim))
return FALSE;
//Also only works if the charcter is not mob and vampire.
if (IS_NPC(ch) || ch->class != class_lookup("vampire"))
return FALSE;
//The attacker must have the skill
if( (skill = get_skill(ch, gsn_unholy_gift)) == 0)
return FALSE;
//If al those are ok, then we make a roll.
if (number_percent() > chance_mod)
return FALSE;
//Else we succeeded. So we begin spitting out messages.
act_new("The last thing you feel is $n's fangs in your neck.", ch, NULL, victim, TO_VICT, POS_DEAD);
act("Aura of evil fills the room as $n buries $s fangs in $N's neck.", ch, NULL, victim, TO_NOTVICT);
act("You bless $N with your dark gift and bury your fangs in $S throat.", ch, NULL, victim, TO_CHAR);
//Now we simply slay him.
raw_kill(ch, victim);
act_new( "You have been `1EMBRACED!!``", victim,NULL,NULL,TO_CHAR,POS_DEAD);
/* cast unlife on him */
spell_unholy_gift(gsn_unholy_gift, ch->level, ch, victim, 0);
return TRUE;
}//end unholygift.
/*MULT_HIT_WOLF*/
/*exists only in fight.c*/
void multi_hit_wolf(CHAR_DATA* ch, CHAR_DATA* victim)
{
//Modifiers:
const int haste_mod = 25;
const int slow_mod = 20;
const int poison_mod = 20;
const int bite_mod = 30;
//variables.
int i =0;
bool haste = FALSE;
bool slow = FALSE;
//holders for attack skills.
int skill_2 = 0;
int skill_3 = 0;
int skill_4 = 0;
//Poison Afffect.
AFFECT_DATA af;
//EZ cases.
if ((ch == NULL) || (victim == NULL) )
return;
if(!is_affected(ch, gsn_wolf_form))
return;
//First few checks for haste/slow:
if (IS_AFFECTED(ch, AFF_HASTE))
haste = TRUE;
//day is equivalent to being slow.
if (IS_AFFECTED(ch, AFF_SLOW)
|| vamp_day_check(ch) )
slow = TRUE;
if(haste && slow)
haste = slow = FALSE;
//and skills.
skill_2 = (get_skill(ch, gsn_second_attack)*3)/4;
skill_4 = (get_skill(ch, gsn_third_attack)*3)/4;
skill_3 = (skill_2 + skill_4)/2;
//now we slap on modifiers
if (haste){skill_2 = 100;skill_3+=haste_mod;skill_4+=haste_mod;}
if (slow){skill_2-=slow_mod;skill_3-=slow_mod;skill_4=0;}
//Executes the whole round of attaks for wolf_form.
//chance of attacks is based on 1/2/3 attack skill.
//the whole thing is run twice.
for(i = 0; i < 2; i++)
{
//First attack always succeeds.
one_hit(ch, victim, attack_lookup("claw") + TYPE_HIT, FALSE);
if ( ch->fighting != victim )
return;
//second attack
if (number_percent() < skill_2){
one_hit( ch, victim, attack_lookup("charge") + TYPE_HIT, FALSE );
if ( ch->fighting != victim )
return;
}
//third
if (number_percent() < skill_3){
//we do a roll here for poison bite
if (number_percent() < bite_mod)
{
//we roll if we actuly bite him.
if( (number_percent() < poison_mod) && (!is_affected(victim, gsn_poison)) )
{
AFFECT_DATA* baf;
//we apply poison
act("$n's jaws dig deep into your flesh, the bite setting your blood afire with pain.",ch,NULL,victim,TO_VICT);
act("$n's jaws dig deep into $N's flesh and $E screams in pain.",ch,NULL,victim,TO_NOTVICT);
act("You tear a big chunk of $N's flesh out with your slavering teeth.",ch,NULL,victim,TO_CHAR);
//we cast a little spell.
af.where = TO_AFFECTS;
af.type = gsn_poison;
af.level = ch->level;
af.duration = ch->level/5;
af.location = APPLY_STR;
af.modifier = -2;
af.bitvector = AFF_POISON;
baf = affect_to_char( victim, &af );
if (!IS_NPC(ch))
string_to_affect(baf, ch->name);
act_new( "You feel very sick.", victim,NULL,NULL,TO_CHAR,POS_DEAD );
act("$n looks very ill.",victim,NULL,NULL,TO_ROOM);
}//end if poison
else
{
//we didnt poison him.
//we didnt poison him.
act("$n's jaws dig deep into your flesh, the bite flashing with seering pain.",ch,NULL,victim,TO_VICT);
act("$n's jaws dig deep into $N's flesh and $E winces in pain.",ch,NULL,victim,TO_NOTVICT);
act("You tear a big chunk of $N's flesh out with your slavering teeth.",ch,NULL,victim,TO_CHAR);
}//end else
}//end poiso roll
//end we make the attack.
one_hit(ch, victim, attack_lookup("bite")+ TYPE_HIT, FALSE);
if ( ch->fighting != victim )
return;
}//end if third.
//fourth (only if not slow ie: not slow, in home terrain and at night.)
if (number_percent() < skill_4 && !slow){
one_hit(ch, victim, attack_lookup("slash") + TYPE_HIT, FALSE);
if ( ch->fighting != victim )
return;
}
//end of run we do it again.
}//end for
}//end multi_hit_wolf;
/*exists only in fight.c*/
void multi_hit_werebeast(CHAR_DATA* ch, CHAR_DATA* victim){
AFFECT_DATA* paf;
//Modifiers:
const int haste_mod = 25;
const int slow_mod = 25;
//variables.
int i = 0, max = 2;
bool haste = FALSE;
bool slow = FALSE;
//holders for attack skills.
int skill_2 = 0;
int skill_3 = 0;
//EZ cases.
if ((ch == NULL) || (victim == NULL) )
return;
//First few checks for haste/slow:
if (IS_AFFECTED(ch, AFF_HASTE))
haste = TRUE;
if (IS_AFFECTED(ch, AFF_SLOW) )
slow = TRUE;
if(haste && slow)
haste = slow = FALSE;
//and skills.
skill_2 = 2 * get_skill(ch, gsn_second_attack) / 3;
skill_3 = get_skill(ch, gsn_third_attack) / 2;
//now we slap on modifiers
if (haste){skill_2 = 100; skill_3 += haste_mod;}
if (slow){skill_2 -= slow_mod; skill_3 -= 0;}
//Executes the whole round of attaks for wereform
//chance of attacks is based on 1/2/3 attack skill.
//the whole thing is run twice.
if ( (paf = affect_find(ch->affected, gsn_wlock)) != NULL && paf->modifier > 0)
max = 1;
else
max = 2;
for(i = 0; i < max; i++){
//First attack always succeeds.
one_hit(ch, victim, ch->dam_type + TYPE_HIT, FALSE);
if ( ch->fighting != victim )
return;
//mob spec attacks
if (IS_NPC(ch)){
CHAR_DATA* vch, *vch_next;
int number;
if (IS_SET(ch->off_flags,OFF_AREA_ATTACK)){
for (vch = ch->in_room->people; vch != NULL; vch = vch_next){
vch_next = vch->next_in_room;
if ((vch != victim && vch->fighting == ch))
one_hit(ch, vch, ch->dam_type + TYPE_HIT,FALSE);
}
}
if (ch->wait > 0)
return;
number = number_range(0,8);
switch(number) {
case (0) :
if (IS_SET(ch->off_flags,OFF_BASH))
do_bash(ch,""); break;
case (1) :
if (IS_SET(ch->off_flags,OFF_BERSERK) && !IS_AFFECTED(ch,AFF_BERSERK))
do_berserk(ch,""); break;
case (2) :
if (IS_SET(ch->off_flags,OFF_DISARM) || (get_weapon_sn(ch,FALSE) != gsn_hand_to_hand && IS_SET(ch->act,ACT_WARRIOR)))
do_disarm(ch,""); break;
case (3) :
if (IS_SET(ch->off_flags,OFF_KICK))
do_kick(ch,""); break;
case (4) :
if (IS_SET(ch->off_flags,OFF_KICK_DIRT))
do_dirt(ch,""); break;
case (5) :
break;
case (6) :
if (IS_SET(ch->off_flags,OFF_TRIP))
do_trip(ch,""); break;
case (7) :
if (IS_SET(ch->act,ACT_WARRIOR))
do_shield_disarm(ch,""); break;
case (8) :
break;
}
}
//second attack
if (number_percent() < skill_2){
one_hit( ch, victim, ch->dam_type + TYPE_HIT, FALSE );
}
if ( ch->fighting != victim )
return;
//third
if (number_percent() < skill_3){
one_hit(ch, victim, ch->dam_type + TYPE_HIT, FALSE);
}//end if third.
if ( ch->fighting != victim )
return;
}
}
/* holy hands evade */
bool holy_hands_evade(CHAR_DATA* ch, CHAR_DATA* victim, int dt)
{
//ability of the cleric to sptop a blow with his holy hands.
int base_chance = 30 + (number_percent())/10;
int lvl_mod = 1;
base_chance+= (victim->level - ch->level) *lvl_mod;
//now we make a quick roll
if (number_percent() < base_chance)
{
//we evaded!
act("$n stretches his hands, palms out and the blow stops short.", victim, NULL, NULL, TO_ROOM);
act("Your faith holding fast, you stop the blow with $g's power.", victim, NULL, NULL, TO_CHAR);
victim->mana = UMAX(0, victim->mana - 1);
return TRUE;
}
else
return FALSE;
}
/*wolf evade*/
/*used only in fight.c*/
bool wolf_evade(CHAR_DATA* ch, CHAR_DATA* victim, int dt)
{
//This is much like spell_blur except more mundane and works
//in places that vamp wolf can sneak.
int base_chance = 15 + (number_percent())/5;
int haste_mod = 15;
int dex_mod = 2;
int lvl_mod = 1;
bool haste = FALSE;
bool slow = FALSE;
//EZ cases
if( (ch == NULL || victim == NULL))
return FALSE;
if (ch == victim)
return FALSE;
if (!is_affected(victim, gsn_wolf_form))
return FALSE;
if (!vamp_can_sneak(victim, victim->in_room))
return FALSE;
//now we add things up.
//First few checks for haste/slow:
if (IS_AFFECTED(ch, AFF_HASTE))
haste = TRUE;
//day is equivalent to being slow.
if (IS_AFFECTED(ch, AFF_SLOW) || vamp_day_check(ch))
slow = TRUE;
if(haste && slow)
haste = slow = FALSE;
if (haste) base_chance+=haste_mod;
if (slow)base_chance-=haste_mod;
base_chance+= (get_curr_stat(victim, STAT_DEX) - get_curr_stat(ch, STAT_DEX)) * dex_mod;
base_chance+= (victim->level - ch->level) *lvl_mod;
//now we make a quick roll
if (number_percent() < base_chance)
{
//we evaded!
act("Blurring with speed, $N disappears in undergrowth and evades the blow.", ch, NULL, victim, TO_NOTVICT);
act("$N disappears in undergrowth momentarly and your blow lands short.", ch, NULL, victim, TO_CHAR);
act("Confident in your enviroment, you easly evade the blow.", ch, NULL, victim, TO_VICT);
return TRUE;
}
//we didn't.
return FALSE;
}//end wolf_evade
/*check_dodge_wolf*/
/*linked only to fight.c*/
bool check_dodge_wolf( CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA* vir_obj, int dt, int h_roll, int level, bool fVirt, int sn)
{
//this is the dodge for vamp wolves.
//they get huge bonus to dodge
//in order to boost the defenses to match that of a human form or more.
//EZ
if (ch == NULL || victim == NULL)
return FALSE;
if (!is_affected(victim, gsn_wolf_form))
return FALSE;
//and this little eazy check.
if (!check_dodge( ch, victim, vir_obj, dt, h_roll, level, fVirt, sn))
{
if (!check_dodge( ch, victim, vir_obj, dt, h_roll, level, fVirt, sn))
return FALSE;
}
return TRUE;
}//end check_dodge_wolf
void seasons_dam(CHAR_DATA *ch, int season)
{
CHAR_DATA *vch, *vch_next;
int dam = ch->level + 25 + dice(5,9);
for (vch = ch->in_room->people; vch != NULL; vch = vch_next)
{
vch_next = vch->next_in_room;
if ( !is_area_safe(ch,vch))
{
s_yell(ch,vch,FALSE);
if (saves_spell(ch->level,vch,DAM_OTHER,song_table[gsn_seasons].spell_type))
dam /= 2;
switch (season)
{
case (0):
damage( ch,vch,dam,skill_lookup("deluge water"), DAM_DROWNING,TRUE);
break;
case (1):
damage( ch,vch,dam,skill_lookup("fireball"), DAM_FIRE,TRUE);
break;
case (2):
damage( ch,vch,dam,skill_lookup("call lightning"), DAM_LIGHTNING,TRUE);
break;
case (3):
damage( ch,vch,dam,skill_lookup("iceball"), DAM_COLD,TRUE);
break;
}
}
}
}
/* Control the fights going on. *
* Called periodically by update_handler. */
void violence_update( void )
{
CHAR_DATA *ch, *ch_next, *victim;
AFFECT_DATA af, *paf;
OBJ_DATA *wield, *second;
char buf[MSL];
OBJ_DATA *obj, *obj_next;
bool room_trig = FALSE;
for ( ch = char_list; ch != NULL; ch = ch_next )
{
ch_next = ch->next;
if (IS_STONED(ch))
continue;
if ( !IS_NPC(ch) && ch->position > POS_SLEEPING )
{
int wie_p, wie_s;
wield = get_eq_char(ch,WEAR_WIELD);
second = get_eq_char(ch,WEAR_SECONDARY);
wie_p = get_obj_weight(wield);
wie_s = get_obj_weight(second);
if (ch->fighting && do_combatdraw(ch, wield, second)){
wield = get_eq_char(ch,WEAR_WIELD);
second = get_eq_char(ch,WEAR_SECONDARY);
}
if (second != NULL && (get_eq_char(ch,WEAR_WIELD) == NULL))
{
unequip_char(ch, second);
equip_char( ch, second, WEAR_WIELD);
act( "$n switches $p to their good hand.",ch,second,NULL,TO_ROOM);
act( "You switch your weapon to your good hand.",ch,second,NULL,TO_CHAR);
}
if (wield != NULL
&& second != NULL
&& (ch->race != grn_minotaur || wield->value[0] != WEAPON_AXE || second->value[0] != WEAPON_AXE)
&& !IS_AFFECTED2(ch,AFF_RAGE)
&& wie_s > 3 * wie_p / 4
&& wie_s > 100
&& get_skill(ch, gsn_bladework) < 2)
{
unequip_char(ch,second);
act("Your secondary weapon becomes too heavy for you to wield.",ch,second,NULL,TO_CHAR);
act("$p becomes too heavy for $n to wield.",ch,second,NULL,TO_ROOM);
}
}
if (!IS_NPC(ch) && IS_AFFECTED2(ch,AFF_SHADOWFORM) && get_charmed_by(ch))
{
send_to_char("Your followers have given you away.\n\r", ch);
affect_strip ( ch, gsn_shadowform );
REMOVE_BIT ( ch->affected2_by, AFF_SHADOWFORM );
act_new("Your body regains its substance, and you materialize into existence.",ch,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n's body regains its substance, and $e materializes into existence.",ch,NULL,NULL,TO_ROOM);
}
if (!IS_NPC(ch) && IS_AFFECTED(ch,AFF_TREEFORM) && get_charmed_by(ch))
{
send_to_char("Your followers have given you away.\n\r", ch);
affect_strip ( ch, gsn_treeform );
REMOVE_BIT ( ch->affected_by, AFF_TREEFORM );
act_new("Your body returns to its normal form.",ch,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n's body returns to its normal form.",ch,NULL,NULL,TO_ROOM);
}
if (IS_AFFECTED2(ch, AFF_CATALEPSY) && ch->position != POS_SLEEPING)
do_revive(ch, "");
if (IS_AFFECTED2(ch, AFF_RAGE) && ch->fighting == NULL && IS_AWAKE(ch) && !IS_AFFECTED(ch,AFF_CALM))
{
CHAR_DATA *vch, *vch_next;
bool found = FALSE;
bool fight = FALSE;
int count = 0;
victim = NULL;
for ( vch = ch->in_room->people; vch != NULL; vch = vch_next )
{
vch_next = vch->next_in_room;
if ( is_area_safe_quiet(ch,vch) || !can_see( ch, vch ) || ch == vch)
continue;
if (!IS_NPC(vch))
{
found = TRUE;
if ( number_range( 0, count ) == 0 )
{
victim = vch;
fight = TRUE;
}
count++;
}
}
if (found && !fight)
{
REMOVE_BIT(ch->affected2_by, AFF_RAGE);
affect_strip(ch,gsn_rage);
act("After finding no one to fight, you snap out of your madness.",ch,NULL,NULL,TO_CHAR);
act("$n gasps for air as $e snaps out of $s insanity.",ch,NULL,NULL,TO_ROOM);
ch->hit -= (ch->level * ch->perm_stat[STAT_CON]) /3;
if (IS_IMMORTAL(ch))
ch->hit = UMAX(1,ch->hit);
if (ch->hit < -2)
{
int shock_mod = (25 * (0 - ch->hit)) / ch->max_hit;
if (number_percent( ) < con_app[UMAX(1,ch->perm_stat[STAT_CON] - shock_mod)].shock)
{
act_new("Your body suddenly awakens to the wounds you've sustained and you lose consciousness.",ch,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n suddenly clutches $s wounds and slumps to the ground, unconscious.",ch,NULL,NULL,TO_ROOM);
ch->hit = -2;
ch->position = POS_STUNNED;
act("$n is stunned, but will probably recover.",ch,NULL,NULL,TO_ROOM);
act_new("You are stunned, but will probably recover.",ch,NULL,NULL,TO_CHAR,POS_DEAD);
}
else
{
act_new("Your body could not sustain the injuries you've suffered.",ch,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n suddenly clutches $s wounds and slumps to the ground.",ch,NULL,NULL,TO_ROOM);
act( "$n is DEAD!!", ch, NULL, NULL, TO_ROOM );
act_new( "You have been KILLED!!", ch,NULL,NULL,TO_CHAR,POS_DEAD);
raw_kill( ch, ch );
}
}
continue;
}
if ( victim != NULL )
do_murder( ch, victim->name );
}
if ( ch == NULL || ch->in_room == NULL )
continue;
update_violence(ch);
if ( ch == NULL || ch->in_room == NULL )
continue;
if ( is_song_affected(ch,gsn_dance_song))
{
if (!IS_AWAKE(ch) && !IS_AFFECTED(ch,AFF_SLEEP))
do_wake(ch,"");
do_visible(ch,NULL);
send_to_char("You can't stop dancing!\n\r",ch);
act("$n dances wildly in front of you!",ch,NULL,NULL,TO_ROOM);
ch->move--;
}
if ( is_song_affected(ch,gsn_seasons))
{
AFFECT_DATA *paf = affect_find(ch->affected2,gsn_seasons);
if (paf != NULL)
{
switch (paf->modifier)
{
case (0):
sprintf(buf,"Rains of spring in flooding tides.");
song_to_room(ch,buf,FALSE,FALSE,FALSE);
paf->modifier++;
seasons_dam(ch,0);
break;
case (1):
sprintf(buf,"Summer's heat is scorching high.");
song_to_room(ch,buf,FALSE,FALSE,FALSE);
paf->modifier++;
seasons_dam(ch,1);
break;
case (2):
sprintf(buf,"Autumn storms lights up the skies.");
song_to_room(ch,buf,FALSE,FALSE,FALSE);
paf->modifier++;
seasons_dam(ch,2);
break;
case (3):
sprintf(buf,"Glaciers in winter made of ice.");
song_to_room(ch,buf,FALSE,FALSE,FALSE);
paf->modifier++;
seasons_dam(ch,3);
break;
default:
song_affect_remove(ch,paf);
break;
}
}
}
victim = NULL;
if ( ( victim = ch->fighting ) != NULL ){
if ( IS_AWAKE(ch)
&& ch->in_room == victim->in_room
&& !is_affected(ch,gsn_ecstacy))
{
multi_hit( ch, victim, TYPE_UNDEFINED );
// POSTCOMBAT CHECK //
if ( POSTCOMBAT_CHECK(ch, victim, TYPE_UNDEFINED ) == -1)
bug("Error at: PostcombatCheck, returned fail\n\r", 0);
}
else
stop_fighting( ch, FALSE );
if (ch == NULL)
continue;
if ( ( victim = ch->fighting ) == NULL ){
continue;
}
/* OLD MPROG */
if (IS_NPC(ch) && ch->pIndexData->progtypes & FIGHT_PROG)
mprog_fight_trigger( ch, victim );
if (ch == NULL || !ch->fighting)
continue;
if (IS_NPC(ch) && ch->pIndexData->progtypes & HITPRCNT_PROG)
mprog_hitprcnt_trigger( ch, victim );
if (ch == NULL || !ch->fighting)
continue;
/* NEW PROGS */
if (IS_NPC(ch)){
if (HAS_TRIGGER_MOB(ch, TRIG_FIGHT))
p_percent_trigger( ch, NULL, NULL, victim, NULL, NULL, TRIG_FIGHT);
if (ch == NULL || !ch->fighting)
continue;
if ( HAS_TRIGGER_MOB(ch, TRIG_HPCNT) )
p_hprct_trigger( ch, victim );
}
if (ch == NULL || !ch->fighting)
continue;
for ( obj = ch->carrying; obj; obj = obj_next )
{
obj_next = obj->next_content;
if ( obj->wear_loc != WEAR_NONE && HAS_TRIGGER_OBJ( obj, TRIG_FIGHT ) )
p_percent_trigger( NULL, obj, NULL, victim, NULL, ch, TRIG_FIGHT );
if (ch == NULL || !ch->fighting)
continue;
}
if ( HAS_TRIGGER_ROOM( ch->in_room, TRIG_FIGHT ) && room_trig == FALSE )
{
room_trig = TRUE;
p_percent_trigger( NULL, NULL, ch->in_room, victim, NULL, NULL, TRIG_FIGHT );
}
/* amke sure we are fighting after trigger */
if (!ch->fighting)
continue;
if ( is_affected(ch,gsn_refrain) && number_percent() > 50)
{
AFFECT_DATA *saf;
saf = affect_find(ch->affected,gsn_refrain);
if (refrain_sing(ch,saf->modifier))
affect_strip(ch,gsn_refrain);
}
check_assist(ch,victim);
if ( IS_AFFECTED(ch,AFF_SLEEP) && ch->position > POS_SLEEPING )
{
REMOVE_BIT(ch->affected_by, AFF_SLEEP);
affect_strip(ch,gsn_sleep);
affect_strip(ch,gsn_hypnosis);
affect_strip(ch,gsn_coffin);
if ( is_affected(ch, gsn_camp)){
send_to_char( "You feel drained from deprivation of sleep.\n\r", ch);
if (!is_affected(ch, gsn_drained)){
af.where = TO_AFFECTS;
af.type = gsn_drained;
af.level = ch->level;
af.duration = 10;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = 0;
affect_to_char(ch,&af);
affect_strip(ch,gsn_camp);
}
}
affect_strip(ch,gsn_entomb);
song_strip(ch,gsn_lullaby);
}
if ( IS_AFFECTED(victim,AFF_SLEEP) && victim->position > POS_SLEEPING )
{
REMOVE_BIT(victim->affected_by, AFF_SLEEP);
affect_strip(victim,gsn_sleep);
affect_strip(victim,gsn_hypnosis);
affect_strip(victim,gsn_coffin);
affect_strip(victim,gsn_entomb);
song_strip(victim,gsn_lullaby);
if ( is_affected(victim, gsn_camp)){
send_to_char( "You feel drained from deprivation of sleep.\n\r", ch);
if (!is_affected(victim, gsn_drained)){
af.where = TO_AFFECTS;
af.type = gsn_drained;
af.level = victim->level;
af.duration = 10;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = 0;
affect_to_char(victim,&af);
affect_strip(victim,gsn_camp);
}
}
}
}
if (ch == NULL)
continue;
/* after violence cleanup */
if ( is_affected(ch,gsn_rake) )
{
send_to_char("You gain control of your weapon.\n\r",ch);
affect_strip(ch,gsn_rake);
}
if (!IS_NPC(ch)){
affect_strip(ch,gsn_feign);
}
if (!IS_NPC(ch)
&& (paf = affect_find(ch->affected,gsn_cyclone)) != NULL
&& --paf->duration < 1){
affect_strip(ch, gsn_cyclone);
}
if (!IS_NPC(ch)
&& (paf = affect_find(ch->affected,gsn_maelstrom)) != NULL
&& --paf->duration < 1){
affect_strip(ch, gsn_maelstrom);
}
if (!IS_NPC(ch)
&& (paf = affect_find(ch->affected,gsn_onslaught)) != NULL
&& --paf->duration < 1){
affect_strip(ch, gsn_onslaught);
}
}
}
void check_assist(CHAR_DATA *ch,CHAR_DATA *victim)
{
CHAR_DATA *rch, *rch_next;
char buf[MSL];
if (ch->in_room == NULL)
return;
for (rch = ch->in_room->people; rch != NULL; rch = rch_next)
{
rch_next = rch->next_in_room;
if (IS_AWAKE(rch) && rch->fighting == NULL && !is_affected(rch,gsn_ecstacy)){
/* quick check for ASSIST_PLAYER */
if (!IS_NPC(ch) && IS_NPC(rch) && IS_SET(rch->off_flags,ASSIST_PLAYERS)
&& rch->level + 6 > victim->level && !IS_AFFECTED2(ch, AFF_HOLD) && can_see(rch,victim)){
act("$n screams and attacks!",rch,NULL,victim,TO_ALL);
multi_hit(rch,victim,TYPE_UNDEFINED);
continue;
}
/* PCs next */
else if (!IS_NPC(ch)
|| IS_AFFECTED(ch,AFF_CHARM)
|| IS_AFFECTED(rch,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) )
{
if ( IS_NPC(rch)
&& !IS_NPC(victim)
&& rch->master != NULL
&& rch->master != victim
&& !IS_NPC(rch->master)
&& !is_pk(rch->master, victim) )
continue;
/* JUSTICE GUARD CAPTAIN/HOUND ASSIST CHECK */
if (IS_NPC(rch)
&& rch->in_room
&& (rch->pIndexData->vnum == MOB_VNUM_SPECIAL_GUARD
|| rch->pIndexData->vnum == MOB_VNUM_HOUND)
&& !IS_LEADER( ch )
&& !IS_AREA(rch->in_room->area, AREA_LAWFUL)
&& !IS_WANTED(victim))
continue;
if (IS_NPC(rch) && IS_SET(rch->act, ACT_NONCOMBAT))
continue;
/*Viri: sheath check for ps's didn't want this to be run
as often as the if's above
*/
if (!IS_NPC(rch) && is_sheathed(rch))
continue;
a_yell(rch,victim);
if (!IS_NPC(rch))
{
sprintf(buf, "Help! I am being attacked by %s!",PERS(rch,victim));
j_yell(victim, buf );
}
if (IS_NPC(rch)
&& (rch->pIndexData->vnum == MOB_VNUM_SPECIAL_GUARD
|| rch->pIndexData->vnum == MOB_VNUM_HOUND)){
rch->fighting = victim;
spec_special_guard(rch);
}
else
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))))
|| (is_same_group(ch,rch) && !is_safe(rch, victim) )
|| (rch->pIndexData == ch->pIndexData && IS_SET(rch->off_flags,ASSIST_VNUM)))
&& !(IS_AFFECTED(rch,AFF_CHARM) && rch->master != ch)
&& !IS_SET(rch->act, ACT_IS_HEALER) )
{
CHAR_DATA *vch, *target = NULL;
int number = 0;
if (number_bits(1) == 0)
continue;
for (vch = ch->in_room->people; vch; vch = vch->next_in_room)
if (can_see(rch,vch) && is_same_group(vch,victim) && number_range(0,number) == 0)
{
target = vch;
number++;
}
if (target != NULL && !IS_AFFECTED2(rch, AFF_HOLD) && can_see(rch,target))
{
act("$n screams and attacks!",rch,NULL,target,TO_ALL);
multi_hit(rch,target,TYPE_UNDEFINED);
}
}
}
}
}
void multi_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
int chance, chance1 = 0, change = victim->hit;
AFFECT_DATA *paf, *paf_next, *form;
CHAR_DATA *vch, *vch_next;
OBJ_DATA *hold, *obj;
int melee_loc = number_range(1, 3); //after which attack we do meleeactions
int secart_loc = number_range(1, 3);//after which attack we do sec-arts
int shadow_loc = number_range(1, 3);//after which attack we do sec-arts
//bool
bool fHaste = (IS_AFFECTED(ch, AFF_HASTE) && !IS_AFFECTED(ch, AFF_SLOW));
bool fSlow = (!IS_AFFECTED(ch, AFF_HASTE) && IS_AFFECTED(ch, AFF_SLOW));
bool fPugil = FALSE;
bool fFeign = !IS_NPC(ch) && is_affected(ch, gsn_feign);
bool fWlock = !IS_NPC(ch) && ((paf = affect_find(ch->affected, gsn_wlock)) != NULL && paf->modifier > 0);
bool fWerebeastMultiHit = FALSE;
//check for blademaster bladestorm haste
if (fHaste && ch->class == gcn_blademaster && is_affected(ch, gsn_bladestorm) && get_eq_char( ch, WEAR_SECONDARY) == NULL)
fHaste = FALSE;
if ( victim != ch && victim->in_room == ch->in_room)
{
if ( ch->position > POS_STUNNED )
{
if ( ch->fighting == NULL )
set_fighting( ch, victim);
if (ch->timer <= 4)
ch->position = POS_FIGHTING;
}
/*
if ( victim->position > POS_STUNNED )
{
if ( victim->fighting == NULL )
set_fighting( victim, ch);
if (victim->timer <= 4)
victim->position = POS_FIGHTING;
}
*/
}
if (ch->desc == NULL)
ch->wait = UMAX(0,ch->wait - PULSE_VIOLENCE);
// PRECOMBAT CHECK //
if ( PRECOMBAT_CHECK(ch, victim, dt) == -1)
bug("Error at: PrecombatCheck, returned fail\n\r", 0);
if (ch->class == class_lookup("monk"))
for ( paf = ch->affected; paf != NULL; paf = paf_next )
{
paf_next = paf->next;
if ( paf->type == gsn_throw )
if (paf->duration-- == 0)
{
act_new(skill_table[gsn_throw].msg_off,ch,NULL,NULL,TO_CHAR,POS_DEAD);
affect_remove( ch, paf);
}
}
if ( is_affected(ch,gsn_mortally_wounded) )
return;
if ( is_affected(ch,gsn_ecstacy) )
return;
if (ch->position < POS_RESTING)
return;
/* Make sure they are fighting at this point */
if (!ch->fighting)
return;
else if (ch->fighting != victim)
return;
if ( dt == gsn_backstab || dt == gsn_cleave
|| dt == gsn_assassinate || dt == gsn_charge || dt == gsn_ambush)
return;
if (!IS_NPC(victim))
victim = check_guard(victim,ch);
/* ranged weapons fire */
fire_ranged_weapons( ch, victim );
if (ch->fighting != victim )
return;
/* check for future use of pugil here */
if ( (obj = get_eq_char(ch, WEAR_WIELD)) != NULL
&& obj->item_type == ITEM_WEAPON
&& obj->value[0] == WEAPON_STAFF
&& get_eq_char(ch, WEAR_SECONDARY) == NULL
&& get_eq_char(ch, WEAR_SHIELD) == NULL
&& get_eq_char(ch, WEAR_HOLD) == NULL
&& number_percent() < get_skill(ch, gsn_pugil)){
check_improve(ch, gsn_pugil, TRUE, 1);
// send_to_char("PUGIL\n\r", ch);
fPugil = TRUE;
}
/* auto-deathblow check */
if (is_affected(ch, gsn_cyclone) && is_affected(ch, gsn_maelstrom)){
deathblow( ch, victim, DB_FULL, FALSE );
affect_strip(ch, gsn_cyclone );
affect_strip(ch, gsn_maelstrom );
}
if (ch->fighting == NULL)
return;
/* form execution */
if ( (form = affect_find(ch->affected, gsn_forms)) != NULL
&& form->modifier++ % 2 != 0
&& form->has_string){
forms(ch, form->string, form);
if (ch->fighting != victim)
return;
}
/* transorm check */
if (ch != victim && ch->race == grn_werebeast && ch->level >= 15 && ch->hit < ch->max_hit / 2){
int transchance = 20 - (20 * ch->hit / ch->max_hit);
if (number_percent() < transchance){
if (!is_affected(ch,gsn_transform))
beast_transform(ch);
}
}
/* check if we are going to run werebeast multihit */
for (paf = ch->affected; paf; paf = paf->next){
if (paf->type == gsn_weretiger
|| paf->type == gsn_werewolf
|| paf->type == gsn_werebear
|| paf->type == gsn_werefalcon){
fWerebeastMultiHit = TRUE;
break;
}
}
if (ch->race == grn_werebeast && fWerebeastMultiHit){
multi_hit_werebeast(ch, victim);
multi_hit_extra( ch, victim, dt, change );
}
else if (ch->race == grn_vampire && is_affected(ch, gsn_wolf_form))
multi_hit_wolf(ch, victim);
else if (IS_NPC(ch)){
mob_hit(ch,victim,dt);
multi_hit_extra( ch, victim, dt, change );
return;
}
//otherwise we proced with all this junk that will need to be cleaned up.
else
{
if (ch->fighting != NULL && ch->fighting->fighting != NULL && ch->fighting->fighting == ch
&& ch->class == class_lookup("monk") && ch->hit > 0 && ch->hit < ch->max_hit / 10
&& (hold = get_eq_char(ch, WEAR_HOLD)) != NULL && hold->pIndexData->vnum == OBJ_VNUM_PRAYER_BEADS)
{
int anatomy = 0;
if (!IS_NPC(victim))
anatomy = anatomy_lookup(pc_race_table[victim->race].anatomy);
chance = 25 + ch->pcdata->anatomy[anatomy] / 10;
chance += get_skill(ch,gsn_anatomy) / 20;
chance += (get_curr_stat(ch,STAT_DEX) - get_curr_stat(victim,STAT_DEX))/2;
chance += get_curr_stat(ch,STAT_LUCK) - get_curr_stat(ch,STAT_LUCK);
if (IS_NPC(victim) && IS_SET(victim->act,ACT_TOO_BIG) )
chance = 0;
if ( number_percent( ) < chance && !IS_IMMORTAL(victim) && !IS_SET(victim->act, ACT_UNDEAD))
{
AFFECT_DATA af;
af.type = gsn_strangle;
af.level = ch->level;
af.duration = number_range(1, 2);
af.location = APPLY_NONE;
af.where = TO_AFFECTS;
af.modifier = 0;
af.bitvector = AFF_SLEEP;
affect_to_char(victim,&af);
act("$n places $s prayer beads around your neck and tightens.",ch,NULL,victim,TO_VICT);
act("You place your prayer beads around $N's neck and tighten.",ch,NULL,victim,TO_CHAR);
act("$n places $s prayer beads around $N's neck and tightens.",ch,NULL,victim,TO_NOTVICT);
stop_fighting( ch, FALSE );
stop_fighting( victim, FALSE );
do_sleep(victim,"");
if ( number_percent( ) > chance )
{
act("The string breaks and the prayer beads fall apart.",ch,NULL,NULL,TO_ALL);
obj_from_char( hold );
extract_obj( hold );
}
return;
}
}
if (ch->class == class_lookup("monk") && get_eq_char( ch, WEAR_WIELD ) == NULL )
{
/* monk first attack */
if (!fFeign)
one_hit( ch, victim, number_range(1053,1055), FALSE );
if ( ch->fighting != victim )
return;
if (melee_loc == 1 && check_melee_actions(ch))
return;
if (secart_loc == 1 && check_secart_actions(ch))
return;
if (shadow_loc == 1 && shadow_strike(ch, victim)){
if (ch->fighting != victim)
return;
}
if (is_affected(ch,gsn_monkey) && monk_good(ch, WEAR_ABOUT) && monk_good(ch, WEAR_WAIST) )
{
chance = 100;
if (!IS_AFFECTED(ch,AFF_HASTE) && IS_AFFECTED(ch,AFF_SLOW))
chance = 50;
if (number_percent( ) < chance){
one_hit( ch, victim, number_range(1053,1055), FALSE );
check_improve(ch, gsn_monkey, TRUE, 1);
if ( ch->fighting != victim )
return;
}
}
}
else
{
/* first attack */
if (ch->class == gcn_blademaster && getBmWearLoc(ch, TRUE) == WEAR_SECONDARY)
one_hit( ch, victim, dt, TRUE );
else
one_hit( ch, victim, dt, FALSE );
if ( ch->fighting != victim )
return;
if (melee_loc == 1 && check_melee_actions(ch))
return;
if (secart_loc == 1 && check_secart_actions(ch))
return;
if (shadow_loc == 1 && shadow_strike(ch, victim)){
if (ch->fighting != victim)
return;
}
//Additional attack due to haste
if (fHaste && ch->fighting){
if (ch->class == gcn_blademaster && getBmWearLoc(ch, TRUE) == WEAR_SECONDARY)
one_hit( ch, victim, dt, TRUE );
else
one_hit( ch, victim, dt, FALSE );
if ( ch->fighting != victim )
return;
}
/* first dual attack */
chance = get_skill(ch, gsn_dual_wield);
if (!fFeign
&& !fWlock
&& (fPugil || get_eq_char(ch,WEAR_SECONDARY))
&& number_percent( ) < chance){
one_hit( ch,victim,dt,TRUE);
check_improve(ch,gsn_dual_wield,TRUE,1);
if (ch->fighting != victim)
return;
}
}
if (IS_AFFECTED2(ch, AFF_RAGE)){
for (vch = ch->in_room->people; vch != NULL; vch = vch_next){
vch_next = vch->next_in_room;
if ((vch != victim && vch->fighting == ch)){
if (IS_NPC(ch))
one_hit(ch,vch,dt,FALSE);
if (!IS_NPC(ch) && number_percent( ) < 2 * get_skill(ch, gsn_swing) /3){
one_hit(ch,vch,dt,FALSE);
check_improve(ch,gsn_swing, TRUE, 1);
if (!IS_NPC(ch) && number_percent( ) < get_skill(ch, gsn_swing)/2
&& (fPugil || get_eq_char(ch, WEAR_SECONDARY)) && number_percent( ) < get_skill(ch, gsn_dual_wield)){
check_improve(ch, gsn_swing, TRUE, 1);
one_hit(ch,vch,dt,TRUE);
}
}
}
}
}
else if ( ((chance = get_skill(ch, gsn_cusinart))
|| is_affected(ch, gsn_windmill))
&& has_twohanded(ch) != NULL){
/* you hit a mate if they are near by */
if ( chance < 2 && (vch = get_group_room(ch, FALSE)) != NULL ){
if (ch->fighting == NULL || ch->fighting != vch
|| vch->fighting == NULL || vch->fighting != ch ){
char buf[MIL];
sprintf(buf, "Die %s you inconsiderate fool!", PERS2(ch));
a_yell(ch, vch);
j_yell(vch, buf);
}
one_hit(ch,vch,dt,FALSE);
}
for (vch = ch->in_room->people; vch != NULL; vch = vch_next){
vch_next = vch->next_in_room;
if ((vch == victim || vch->fighting != ch))
continue;
if (IS_NPC(ch))
one_hit(ch,vch,dt,FALSE);
if (!IS_NPC(ch) && number_percent( ) < 2 * get_skill(ch, gsn_swing) /3){
one_hit(ch,vch,dt,FALSE);
check_improve(ch,gsn_windmill, TRUE, 1);
check_improve(ch,gsn_swing, TRUE, 1);
}
}
if (chance > 1){
for (vch = ch->in_room->people; vch != NULL; vch = vch_next){
vch_next = vch->next_in_room;
if ((vch == victim || vch->fighting != ch))
continue;
if (IS_NPC(ch))
one_hit(ch,vch,dt,FALSE);
if (!IS_NPC(ch) && number_percent( ) < 2 * chance / 3){
one_hit(ch,vch,dt,FALSE);
check_improve(ch,gsn_swing, TRUE, 1);
check_improve(ch,gsn_cusinart, TRUE, 1);
}
}
}
}
//BEGIN MONK MULTI HIT
if (ch->class == class_lookup("monk"))
{
//check for items wornd
int items = 0;
OBJ_DATA *hold;
if (get_eq_char( ch, WEAR_WIELD ) != NULL )
items = 3;
if (get_eq_char( ch, WEAR_SHIELD ) != NULL )
items++;
hold = get_eq_char( ch, WEAR_HOLD);
if ( hold != NULL && hold->pIndexData->vnum != OBJ_VNUM_PRAYER_BEADS)
items++;
//Second attack
chance = get_skill(ch, gsn_martial_arts_b);
if (!fWlock && items < 3 && number_percent( ) < chance && monk_good(ch, WEAR_ARMS))
{
one_hit( ch, victim, number_range(1053,1055), FALSE );
check_improve(ch,gsn_martial_arts_b,TRUE,1);
if ( ch->fighting != victim )
return;
}
if (melee_loc == 2 && check_melee_actions(ch))
return;
if (secart_loc == 2 && check_secart_actions(ch))
return;
if (shadow_loc == 2 && shadow_strike(ch, victim)){
if (ch->fighting != victim)
return;
}
//third attack
chance = get_skill(ch, gsn_kickboxing_b);
if (items < 2 && number_percent( ) < chance && monk_good(ch, WEAR_LEGS))
{
one_hit( ch, victim, number_range(1059,1061), FALSE );
check_improve(ch,gsn_kickboxing_b,TRUE,1);
if ( ch->fighting != victim )
return;
//zaf 11-14-99 (extra atack hasted.)
if (IS_AFFECTED(ch,AFF_HASTE) && !IS_AFFECTED(ch,AFF_SLOW))
{
one_hit( ch, victim, number_range(1059,1061), FALSE );
check_improve(ch,gsn_kickboxing_b,TRUE,0);
if ( ch->fighting != victim )
return;
}
}
if (melee_loc == 3 && check_melee_actions(ch))
return;
if (secart_loc == 3 && check_secart_actions(ch))
return;
if (shadow_loc == 3 && shadow_strike(ch, victim)){
if (ch->fighting != victim)
return;
}
//ADVANCED ATTACKS
//FIRST
chance = get_skill(ch, gsn_martial_arts_a)/2;
if (!fWlock && items < 2 && is_empowered_quiet(ch,3) && number_percent( ) < chance && monk_good(ch, WEAR_HANDS))
{
one_hit( ch, victim, number_range(1056,1058), FALSE );
check_improve(ch,gsn_martial_arts_a,TRUE,0);
if ( ch->fighting != victim )
return;
//zaf 11-14-99 (extra attack)
if (IS_AFFECTED(ch,AFF_HASTE) && !IS_AFFECTED(ch,AFF_SLOW))
{
one_hit( ch, victim, number_range(1056,1058), FALSE );
check_improve(ch,gsn_martial_arts_a,TRUE,0);
if ( ch->fighting != victim )
return;
}
}
//SECOND
chance = get_skill(ch, gsn_kickboxing_a)/2;
if (items < 1 && is_empowered_quiet(ch,0) && number_percent( ) < chance && monk_good(ch, WEAR_FEET))
{
one_hit( ch, victim, number_range(1062,1064), FALSE );
check_improve(ch,gsn_kickboxing_a,TRUE,0);
if ( ch->fighting != victim )
return;
}
multi_hit_extra( ch, victim, dt, change );
if ( ch->fighting != victim )
return;
//MONKEY STANCE ATTACKS
if (!is_affected(ch,gsn_monkey) || !monk_good(ch, WEAR_ABOUT) || !monk_good(ch, WEAR_WAIST))
return;
check_improve(ch, gsn_monkey, TRUE, 1);
//FIRST
chance = get_skill(ch, gsn_martial_arts_b);
if (!IS_AFFECTED(ch,AFF_HASTE) && IS_AFFECTED(ch,AFF_SLOW))
chance /= 2;
if (items < 3 && number_percent( ) < chance && monk_good(ch, WEAR_ARMS))
{
one_hit( ch, victim, number_range(1053,1055), FALSE );
check_improve(ch,gsn_martial_arts_b,TRUE,0);
if ( ch->fighting != victim )
return;
}
//SECOND
chance = get_skill(ch, gsn_kickboxing_b);
if (!IS_AFFECTED(ch,AFF_HASTE) && IS_AFFECTED(ch,AFF_SLOW))
chance /= 2;
if (items < 3 && number_percent( ) < chance && monk_good(ch, WEAR_LEGS))
{
one_hit( ch, victim, number_range(1059,1061), FALSE );
check_improve(ch,gsn_kickboxing_b,TRUE,0);
if ( ch->fighting != victim )
return;
}
//THIRD
chance = get_skill(ch, gsn_martial_arts_a)/2;
if (!IS_AFFECTED(ch,AFF_HASTE) && IS_AFFECTED(ch,AFF_SLOW))
chance /= 2;
if (items < 1 && number_percent( ) < chance && monk_good(ch, WEAR_HANDS))
{
one_hit( ch, victim, number_range(1056,1058), FALSE );
check_improve(ch,gsn_martial_arts_a,TRUE,0);
if ( ch->fighting != victim )
return;
}
//FOURTH
chance = get_skill(ch, gsn_kickboxing_a)/2;
if (!IS_AFFECTED(ch,AFF_HASTE) && IS_AFFECTED(ch,AFF_SLOW))
chance /= 2;
if (items < 2 && number_percent( ) < chance && monk_good(ch, WEAR_FEET))
{
one_hit( ch, victim, number_range(1062,1064), FALSE );
check_improve(ch,gsn_kickboxing_a,TRUE,0);
if ( ch->fighting != victim )
return;
}
////////////////
//RETURNS HERE//
////////////////
return;
}//END MONK ATTACKS
//NORMAL ATTACKS
/* Second Attack */
if (fSlow)
chance = 0;
//this stance requires 2 weapons, but the attack is lost even without 2 weapons
else if (ch->class == gcn_blademaster && is_affected(ch, gsn_iron_curtain))
chance = 0;
else if (fHaste){
if (ch->class == gcn_blademaster && monk_good(ch, WEAR_FEET))
chance = 100;
else
chance = get_skill(ch, gsn_second_attack);
}
else{
if (ch->class == gcn_blademaster && monk_good(ch, WEAR_FEET))
chance = get_skill(ch, gsn_footwork);
else
chance = get_skill(ch, gsn_second_attack)/2;
}
//fury for ferals
if (ch->race == grn_feral)
chance += ch->level;
if ( has_twohanded(ch) != NULL
&& number_percent() < get_skill( ch, gsn_adv_handling) ){
check_improve(ch, gsn_adv_handling, TRUE, 0);
chance += 15;
}
/* Second Primary Attack */
if (number_percent( ) < chance )
{
if (ch->class == gcn_blademaster && getBmWearLoc(ch, FALSE) == WEAR_SECONDARY)
one_hit( ch, victim, dt, TRUE );
else
one_hit( ch, victim, dt, FALSE );
check_improve(ch, gsn_footwork, TRUE, 0);
check_improve(ch,gsn_second_attack,TRUE,0);
if ( ch->fighting != victim )
return;
}
if (melee_loc == 2 && check_melee_actions(ch))
return;
if (secart_loc == 2 && check_secart_actions(ch))
return;
if (shadow_loc == 2 && shadow_strike(ch, victim)){
if (ch->fighting != victim)
return;
}
/* Secondary Dual Attack */
if (fSlow )
chance = 0;
else if (fHaste)
chance = 4 * get_skill(ch, gsn_second_attack)/ 5;
else
chance = get_skill(ch, gsn_second_attack)/2;
//fury for ferals
if (chance && ch->race == grn_feral)
chance += ch->level;
if ( !fWlock
&& (fPugil || get_eq_char(ch,WEAR_SECONDARY))
&& number_percent( ) < chance
&& ((!IS_NPC(ch)
&& get_skill(ch,gsn_dual_wield) > number_range( 0, 100 ))
|| IS_NPC(ch)) )
{
one_hit( ch,victim,dt,TRUE);
check_improve(ch,gsn_dual_wield,TRUE,1);
if (ch->fighting != victim)
return;
}
/* Third Attack */
/* Third attack Primary */
if (fSlow)
chance = 0;
else if (fHaste){
if (ch->class == gcn_blademaster)
chance = 8 * get_skill(ch, gsn_bladework) / 10;
else
chance = get_skill(ch, gsn_third_attack) / 2;
}
else{
if (ch->class == gcn_blademaster)
chance = 7 * get_skill(ch, gsn_bladework) / 10;
else
chance = get_skill(ch, gsn_third_attack) / 4;
}
//Psi Time Compression
if (chance == 0 && !fSlow
&& ch->class == gcn_psi
&& is_affected(ch, gsn_time_comp))
chance = fHaste ? 50 : 25;
//fury for ferals
if (ch->race == grn_feral)
chance += ch->level;
if ( has_twohanded(ch) != NULL
&& number_percent() < get_skill( ch, gsn_adv_handling) ){
check_improve(ch, gsn_adv_handling, TRUE, 1);
chance += 10;
}
if (melee_loc == 3 && check_melee_actions(ch))
return;
if (secart_loc == 3 && check_secart_actions(ch))
return;
if (shadow_loc == 3 && shadow_strike(ch, victim)){
if (ch->fighting != victim)
return;
}
if ( number_percent( ) < chance )
{
if (ch->class == gcn_blademaster && getBmWearLoc(ch, TRUE) == WEAR_SECONDARY)
one_hit( ch, victim, dt, TRUE );
else
one_hit( ch, victim, dt, FALSE );
check_improve(ch, gsn_bladework, TRUE, 0);
check_improve(ch,gsn_third_attack,TRUE,1);
if ( ch->fighting != victim )
return;
}
/* Third attack Secondary */
if (fSlow || fWlock)
chance = 0;
else if (fHaste)
chance = 3 * get_skill(ch, gsn_third_attack) /5;
else
chance = get_skill(ch, gsn_third_attack) / 5;
if ((fPugil
|| get_eq_char(ch,WEAR_SECONDARY)) && number_percent( ) < chance
&& ( ( !IS_NPC(ch) && get_skill(ch,gsn_dual_wield) > number_range( 0, 100 ))
|| IS_NPC(ch)) )
{
one_hit( ch,victim,dt,TRUE);
check_improve(ch,gsn_dual_wield,TRUE, 1);
if (ch->fighting != victim)
return;
}
/* Fourth Attack */
/* Fourth attack Primary */
if (fSlow || fPugil)
chance = 0;
else if (fHaste){
if (ch->class == gcn_blademaster && monk_good(ch, WEAR_LEGS))//same chance as not hasted
chance = 5 * get_skill(ch, gsn_battlestance) / 10;
else
chance = get_skill(ch, gsn_fourth_attack) / 4;
}
else{
if (ch->class == gcn_blademaster && monk_good(ch, WEAR_LEGS))//same chance as hsted
chance = 5 * get_skill(ch, gsn_battlestance) / 10;
else
chance = get_skill(ch, gsn_fourth_attack) / 6;
}
//Psi Time Compression
if (chance == 0 && !fSlow
&& ch->class == gcn_psi
&& is_affected(ch, gsn_time_comp))
chance = fHaste ? 30 : 15;
if ( has_twohanded(ch) != NULL
&& number_percent() < get_skill( ch, gsn_adv_handling) ){
check_improve(ch, gsn_adv_handling, TRUE, 1);
chance += 10;
}
if ( number_percent( ) < chance
|| (ch->class == gcn_vampire
&& !vamp_day_check(ch)))
{
if (ch->class == gcn_blademaster && getBmWearLoc(ch, FALSE) == WEAR_SECONDARY)
one_hit( ch, victim, dt, TRUE );
else
one_hit( ch, victim, dt, FALSE );
check_improve(ch, gsn_battlestance, TRUE, 0);
check_improve(ch,gsn_fourth_attack,TRUE,0);
if ( ch->fighting != victim )
return;
}
/* Fourth Attack Secondary */
if (fSlow || fPugil || fWlock)
chance = 0;
else if (fHaste)
chance = get_skill(ch, gsn_fourth_attack) / 6;
else
chance = get_skill(ch, gsn_fourth_attack) / 8;
if ( (get_eq_char(ch,WEAR_SECONDARY)) && number_percent( ) < chance
&& ( ( !IS_NPC(ch) && get_skill(ch,gsn_dual_wield) > number_range( 0, 100 ))
|| IS_NPC(ch))
)
{
one_hit( ch,victim,dt,TRUE);
check_improve(ch,gsn_dual_wield,TRUE,1);
if (ch->fighting != victim)
return;
}
/* fifth attack for blademasters */
if (fSlow || fPugil)
chance = 0;
else if (fHaste){
chance = 3 * get_skill(ch, gsn_avatar_of_steel) / 10;
}
else{
chance = 3 * get_skill(ch, gsn_avatar_of_steel) / 10;
}
if ( has_twohanded(ch) != NULL
&& number_percent() < get_skill( ch, gsn_adv_handling) ){
check_improve(ch, gsn_adv_handling, TRUE, 1);
chance += 10;
}
if ( number_percent( ) < chance ){
bool fPrim = number_percent() < 50;
if (ch->class == gcn_blademaster && getBmWearLoc(ch, fPrim) == WEAR_SECONDARY)
one_hit( ch, victim, dt, TRUE );
else
one_hit( ch, victim, dt, FALSE );
check_improve(ch, gsn_avatar_of_steel, TRUE, 0);
if ( ch->fighting != victim )
return;
}
/* END OF REGUARL 5 ATTCKS */
if (ch->class == gcn_bard && IS_AREA(ch->in_room->area, AREA_CITY)){
if ( (chance = get_skill(ch,gsn_brawl)) > 1 ){
chance /= 2;
if ( number_percent( ) < chance ){
one_hit( ch, victim, dt, FALSE);
check_improve(ch,gsn_brawl,TRUE,1);
}
if ( ch->fighting != victim )
return;
}
}
multi_hit_extra( ch, victim, dt, change );
if ( ch->fighting != victim )
return;
if (ch->class == class_lookup("berserker") && !IS_AFFECTED2(ch,AFF_RAGE) && !IS_NPC(ch) && ch->level >= 6)
{
chance1 = 4;
if (IS_AFFECTED(ch, AFF_SLOW) && !IS_AFFECTED(ch, AFF_HASTE))
chance1 = 0;
if (IS_AFFECTED(ch, AFF_CALM))
chance1 = 0;
if (100 * ch->hit / ch->max_hit > 75 - ch->level)
chance1 = 0;
if (chance1 != 0)
{
if (IS_AFFECTED(ch, AFF_BERSERK))
chance1 += 1;
if (ch->race == race_lookup("dwarf"))
chance1 += 1;
if (IS_AFFECTED(ch,AFF_HASTE))
chance1 += 1;
chance1 += ((75 - ch->level) - (100 * ch->hit / ch->max_hit))/5;
chance1 -= (get_skill(ch,gsn_rage)/25);
chance1 = UMAX(1, chance1);
}
if (number_percent( ) < chance1)
{
AFFECT_DATA af;
act("You feel your veins course with power as the madness engulfs you!",ch,NULL,NULL,TO_CHAR);
act("$n's eyes suddenly burn like hot coals as $e is gripped by insanity!",ch,NULL,NULL,TO_ROOM);
af.where = TO_AFFECTS2;
af.type = gsn_rage;
af.level = ch->level;
af.duration = UMAX(0, 4 - number_fuzzy(ch->level / 11));
af.location = APPLY_STR;
af.modifier = ch->size * 2;
af.bitvector = AFF_RAGE;
affect_to_char(ch,&af);
af.location = APPLY_HITROLL;
af.modifier = str_app[get_curr_stat(ch,STAT_STR)].tohit + ch->level/4;
affect_to_char(ch,&af);
af.location = APPLY_DAMROLL;
af.modifier = str_app[get_curr_stat(ch,STAT_STR)].todam + ch->level/4;
affect_to_char(ch,&af);
af.location = APPLY_HIT;
af.modifier = (ch->level * ch->perm_stat[STAT_CON])/3;
affect_to_char(ch,&af);
ch->hit += (ch->level * ch->perm_stat[STAT_CON]) / 3;
check_improve(ch,gsn_rage,TRUE,1);
}
}
}//end if WOLF
}
void multi_hit_extra( CHAR_DATA *ch, CHAR_DATA *victim, int dt, int change )
{
int chance = ch->level, iWear, cycle;
OBJ_DATA *wield, *claw, *obj;
wield = get_eq_char(ch,WEAR_WIELD);
claw = get_eq_char(ch, WEAR_HANDS);
if ( ch->fighting != victim )
return;
if (is_affected(victim, gsn_mortally_wounded))
return;
if (claw && claw->pIndexData->vnum == OBJ_VNUM_CLAWS){
damage(ch,victim,number_range(0, (claw->level + ch->level)/4),1005,DAM_SLASH,TRUE);
if (ch->fighting != victim)
return;
}
for ( iWear = 0; iWear < MAX_WEAR; iWear++ ){
obj = get_eq_char( ch, iWear );
//cast combat spells.
if( obj != NULL
&& (obj->eldritched || obj->pIndexData->spell != NULL)
&& ch->fighting != NULL)
do_obj_spell( obj, ch, victim );
if ( ch->fighting != victim )
return;
}
/* check prim/sec */
for (cycle = 0; cycle < 2; cycle++){
if (cycle == 0)
wield = getBmWep(ch, TRUE);
else
wield = getBmWep(ch, FALSE);
if (wield == NULL)
continue;
else
chance = wield->level;
if (number_percent( ) < chance ){
int dam;
if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_POISON)){
int level;
AFFECT_DATA *poison, af, *paf;
if ((poison = affect_find(wield->affected,gsn_poison)) == NULL)
level = UMAX(wield->level,1);
else
level = poison->level;
if (!saves_spell(level / 2,victim,DAM_POISON,skill_table[gsn_poison].spell_type)) {
bool fNew = is_affected(victim, gsn_poison);
act("You feel poison coursing through your veins.", victim,wield,NULL,TO_CHAR);
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 / 10;
af.location = APPLY_STR;
af.modifier = fNew ? -1 : 0;
af.bitvector = AFF_POISON;
affect_join( victim, &af );
paf = affect_find( victim->affected, gsn_poison );
if (!IS_NPC(ch))
string_to_affect(paf, ch->name);
/* Set bit preventing damage till first tick. */
if (ch->class != class_lookup("shaman") && fNew)
SET_BIT(paf->bitvector, AFF_FLAG);
}
if (ch->fighting == NULL)
return;
}
if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_VAMPIRIC)){
dam = number_range(1, wield->level / 3 + 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,33 + TYPE_NOBLOCKHIT,DAM_NEGATIVE,TRUE);
ch->hit += dam/2;
if (ch->fighting == NULL)
return;
}
if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_FLAMING)){
dam = number_range(1,wield->level / 3 + 5);
act("$n's flesh is seared by the flaming $p.",victim,wield,NULL,TO_ROOM);
act("$p sears your flesh with flames.",victim,wield,NULL,TO_CHAR);
fire_effect(victim,wield->level,dam,TARGET_CHAR);
if (ch->fighting == NULL)
return;
damage(ch,victim,dam,29 + TYPE_NOBLOCKHIT,DAM_FIRE,TRUE);
if (ch->fighting == NULL)
return;
}
if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_FROST)){
dam = number_range(5,wield->level / 3 + 15);
act("The cold touch of $p surrounds $n with ice.",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,dam,TARGET_CHAR);
if (ch->fighting == NULL)
return;
damage(ch,victim,dam,30 + TYPE_NOBLOCKHIT,DAM_COLD,TRUE);
if (ch->fighting == NULL)
return;
}
if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_SHOCKING)){
dam = number_range(10,wield->level/3 + 10);
act("$n is shocked by the lightning from $p.",victim,wield,NULL,TO_ROOM);
act("You are shocked by the lightning from $p.",victim,wield,NULL,TO_CHAR);
shock_effect(victim,wield->level/2,dam,TARGET_CHAR);
if (ch->fighting == NULL)
return;
damage(ch,victim,dam,28 + TYPE_NOBLOCKHIT,DAM_LIGHTNING,TRUE);
}
if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_PARALYZE)){
dam = number_range(10,wield->level/3 + 10);
act("$p tears into your nerves.",victim,wield,NULL,TO_CHAR);
act("$p tears into $n's nerves.",victim,wield,NULL,TO_ROOM);
paralyze_effect(victim,wield->level,dam,TARGET_CHAR);
if (ch->fighting == NULL)
return;
}
if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_VORPAL)){
dam = number_range(1,wield->level/5 + 1);
act("$p burns $n with corrosive acid.",victim,wield,NULL,TO_ROOM);
act("You are burned by the corrosive acid on $p.",victim,wield,NULL,TO_CHAR);
acid_effect(victim,wield->level,dam,TARGET_CHAR);
if (ch->fighting == NULL)
return;
damage(ch,victim,dam,31 + TYPE_NOBLOCKHIT,DAM_POISON,TRUE);
if (ch->fighting == NULL)
return;
}
if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_SHARP)){
dam = number_range(15,wield->level/2 + ch->level / 2);
act("$p digs into $n's body.",victim,wield,NULL,TO_ROOM);
act("You can feel $p dig into your body.",victim,wield,NULL,TO_CHAR);
damage(ch,victim,dam,18 + TYPE_NOBLOCKHIT,DAM_SLASH,TRUE);
if (ch->fighting == NULL)
return;
}
if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_WOUNDS)){
wound_effect( ch, victim, ch->level, 0);
if (ch->fighting == NULL)
return;
}
if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_DEADLY)
&& !IS_UNDEAD(ch->fighting)){
dam = number_range(15,wield->level/2 + 25);
if (!saves_spell(3 * wield->level / 4 + dam / 15, victim,
DAM_SLASH, SPELL_AFFLICTIVE)){
AFFECT_DATA af, *paf;
act("A spray of blood shoots forth from $n's wound!", victim, NULL, NULL, TO_ROOM);
act("A spray of blood shoots forth from your wound!", victim, NULL, NULL, TO_CHAR);
if ( (paf = affect_find(victim->affected, gen_bleed)) == NULL){
af.type = gen_bleed;
af.level = ch->level;
af.duration = number_range(3, 6);
af.where = TO_NONE;
af.bitvector = 0;
af.location = APPLY_NONE;
/* modifier controls duration of damage (10/tick)*/
af.modifier = number_range(5, 15);
paf = affect_to_char(victim, &af);
string_to_affect(paf, ch->name);
}
else{
/* modifier controls duration of damage (10/tick)*/
paf->modifier = number_range(5, 15);
string_to_affect(paf, ch->name);
}
}
}
}
if ( ch->fighting == NULL || ch->fighting != victim )
return;
if (wield && !str_cmp(wield->material,"practice") && number_percent( ) < 10){
if (ch->max_hit != 0 && ch->hit*100/ch->max_hit <= 20)
act( "$p whispers 'Run away!'", ch, wield, NULL, TO_CHAR);
else if (ch->max_hit != 0 && ch->hit*100/ch->max_hit <= 60)
act( "$p whispers 'You can do it!'", ch, wield, NULL, TO_CHAR);
else
act( "$p whispers 'You're doing great!'", ch, wield, NULL, TO_CHAR);
}
}//END PRIM/SEC LOOP
if ( change != victim->hit && IS_AFFECTED2(victim, AFF_ICE_SHIELD) ){
damage(victim,ch,number_range(victim->level/2,3*victim->level/2),skill_lookup("ice shield"),DAM_COLD,TRUE);
if ( ch->fighting == NULL || ch->fighting != victim )
return;
}
if ( change != victim->hit && IS_AFFECTED2(victim, AFF_FIRE_SHIELD) ){
damage(victim,ch,number_range(victim->level/2,3*victim->level/2),skill_lookup("fire shield"),DAM_FIRE,TRUE);
if ( ch->fighting == NULL || ch->fighting != victim )
return;
}
if ( is_affected(victim, skill_lookup("divine retribution")) && !IS_GOOD(ch)){
int dam2;
dam2 = number_range(victim->level, 3*victim->level/2);
if (IS_NEUTRAL(ch))
dam2 = 2*dam2/3;
damage(victim,ch,dam2,skill_lookup("divine retribution"),DAM_HOLY,TRUE);
if ( ch->fighting == NULL || ch->fighting != victim )
return;
}
if ( change != victim->hit && is_affected(victim, skill_lookup("shield of thorns"))){
int dam2;
dam2 = number_range(2*victim->level/3,3*victim->level/2);
damage(victim,ch,dam2,skill_lookup("shield of thorns"),DAM_PIERCE,TRUE);
if ( ch->fighting == NULL || ch->fighting != victim )
return;
}
if ( change != victim->hit && is_affected(victim, gsn_steel_wall )){
int dam2;
dam2 = number_range( victim->level / 2, 3 * victim->level / 2);
damage(victim, ch, dam2, gsn_steel_wall ,DAM_SLASH, TRUE);
if ( ch->fighting == NULL || ch->fighting != victim )
return;
}
if (ch->race == race_lookup("slith") && number_percent() < 15 + ch->level
&& get_curr_stat(ch, STAT_STR) > 12){
if (number_percent() < 75)
damage(ch,victim,number_range(ch->level, 3 * ch->level / 2 - (30 - ch->perm_stat[STAT_STR])),1071,DAM_PIERCE,TRUE);
else
{
act("You strike with your tail at $N's legs.", ch, NULL, victim, TO_CHAR);
act("$n strikes with $s tail at $N's legs.", ch, NULL, victim, TO_NOTVICT);
act("$n strikes with $s tail at your legs.", ch, NULL, victim, TO_VICT);
trip(ch, victim, 50);
}
if ( ch->fighting == NULL || ch->fighting != victim )
return;
}
if ( ch->fighting != victim )
return;
}
void mob_hit (CHAR_DATA *ch, CHAR_DATA *victim, int dt)
{
int chance, number, change = victim->hit;
CHAR_DATA *vch, *vch_next;
char buf[MSL];
if (IS_SET(ch->act,ACT_THIEF) && ch->fighting == NULL)
{
buf[0]='\0';
strcat(buf,str_dup(victim->name));
do_backstab(ch,buf);
}
one_hit(ch,victim,dt,FALSE);
if (ch->fighting != victim)
return;
if (ch->fighting != victim || dt == gsn_backstab || dt == gsn_cleave
|| dt == gsn_assassinate || dt == gsn_charge || dt == gsn_ambush)
return;
if (IS_SET(ch->off_flags,OFF_AREA_ATTACK)){
for (vch = ch->in_room->people; vch != NULL; vch = vch_next)
{
vch_next = vch->next_in_room;
if ((vch != victim && vch->fighting == ch))
one_hit(ch,vch,dt,FALSE);
}
}
if (ch->fighting != victim)
return;
if ( (IS_AFFECTED(ch,AFF_HASTE) || IS_SET(ch->off_flags,OFF_FAST)) && !IS_AFFECTED(ch,AFF_SLOW))
one_hit(ch,victim,dt,FALSE);
if (ch->fighting != victim)
return;
if (IS_SET(ch->off_flags,OFF_EXTRA_ATTACK))
one_hit(ch,victim,dt,FALSE);
if (ch->fighting != victim)
return;
chance = get_skill(ch,gsn_second_attack)/2;
if (IS_AFFECTED(ch,AFF_SLOW) && !IS_SET(ch->off_flags,OFF_FAST) && !IS_AFFECTED(ch,AFF_HASTE))
chance /= 2;
if (number_percent() < chance)
{
one_hit(ch,victim,dt,FALSE);
if (ch->fighting != victim)
return;
}
chance = get_skill(ch,gsn_third_attack)/4;
if (IS_AFFECTED(ch,AFF_SLOW) && !IS_SET(ch->off_flags,OFF_FAST) && !IS_AFFECTED(ch,AFF_HASTE))
chance = 0;
if (number_percent() < chance)
{
one_hit(ch,victim,dt,FALSE);
if (ch->fighting != victim)
return;
}
if ( change != victim->hit && IS_AFFECTED2(victim, AFF_ICE_SHIELD) )
damage(victim,ch,number_range(victim->level/2,3*victim->level/2),skill_lookup("ice shield"),DAM_COLD,TRUE);
if (ch->fighting != victim)
return;
if ( chance != victim->hit && IS_AFFECTED2(victim, AFF_FIRE_SHIELD) )
damage(victim,ch,number_range(victim->level/2,3*victim->level/2),skill_lookup("fire shield"),DAM_FIRE,TRUE);
if (ch->fighting != victim)
return;
if ( is_affected(victim, skill_lookup("divine retribution")) && !IS_GOOD(ch))
{
int dam2;
dam2 = number_range(victim->level,3*victim->level/2);
if (IS_NEUTRAL(ch))
dam2 = 2*dam2/3;
damage(victim,ch,dam2,skill_lookup("divine retribution"),DAM_HOLY,TRUE);
}
if (ch->fighting != victim)
return;
if ( is_affected(victim, skill_lookup("shield of thorns")))
{
int dam2;
dam2 = number_range(2*victim->level/3,3*victim->level/2);
damage(victim,ch,dam2,skill_lookup("shield of thorns"),DAM_PIERCE,TRUE);
}
if (ch->fighting != victim)
return;
if (ch->wait > 0)
return;
number = number_range(0,8);
switch(number)
{
case (0) :
if (IS_SET(ch->off_flags,OFF_BASH))
do_bash(ch,""); break;
case (1) :
if (IS_SET(ch->off_flags,OFF_BERSERK) && !IS_AFFECTED(ch,AFF_BERSERK))
do_berserk(ch,""); break;
case (2) :
if (IS_SET(ch->off_flags,OFF_DISARM) || (get_weapon_sn(ch,FALSE) != gsn_hand_to_hand && IS_SET(ch->act,ACT_WARRIOR)))
do_disarm(ch,""); break;
case (3) :
if (IS_SET(ch->off_flags,OFF_KICK))
do_kick(ch,""); break;
case (4) :
if (IS_SET(ch->off_flags,OFF_KICK_DIRT))
do_dirt(ch,""); break;
case (5) :
break;
case (6) :
if (IS_SET(ch->off_flags,OFF_TRIP))
do_trip(ch,""); break;
case (7) :
if (IS_SET(ch->act,ACT_WARRIOR))
do_shield_disarm(ch,""); break;
case (8) :
break;
}
}
int get_AC(CHAR_DATA *ch, CHAR_DATA *victim, int dt, int dam_type, bool fVirt)
{
/* LOWER ac results in more MISSES */
//data
int victim_ac;
//AC PENALTY
switch(dam_type)
{
case(DAM_PIERCE): victim_ac = GET_AC(victim,AC_PIERCE)/10; break;
case(DAM_BASH): victim_ac = GET_AC(victim,AC_BASH)/10; break;
case(DAM_SLASH): victim_ac = GET_AC(victim,AC_SLASH)/10; break;
default: victim_ac = GET_AC(victim,AC_EXOTIC)/10; break;
};
//smaller bonus for large ac.
if (!IS_NPC(victim) && victim_ac < -25)
victim_ac = (victim_ac + 25) / 2 - 25;
if (get_skill(ch, gsn_apierce) > 1)
victim_ac /= 2;
//BLINDNESS
if ( !can_see( ch, victim ) && !fVirt)
{
if (!IS_NPC(ch)
&& UMAX(1,number_percent() - (get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK))) < get_skill(ch,gsn_blind_fighting))
{
check_improve(ch,gsn_blind_fighting, TRUE, 1);
if (!is_affected(ch, gsn_battletrance))
victim_ac -= 2;
}
else
{
check_improve(ch,gsn_blind_fighting, FALSE, 1);
victim_ac -= 5;
}
}
if ( !can_see( victim, ch ) )
{
if (!IS_NPC(victim) && UMAX(1,number_percent() - (get_curr_stat(victim,STAT_LUCK) - get_curr_stat(ch,STAT_LUCK))) < get_skill(victim,gsn_blind_fighting))
{
check_improve(victim,gsn_blind_fighting, TRUE, 1);
if (!is_affected(victim, gsn_battletrance))
victim_ac += 3;
}
else
{
check_improve(victim,gsn_blind_fighting, FALSE, 1);
victim_ac += 10;
}
}
//POSITONS
if ( victim->position < POS_FIGHTING)
victim_ac += 4;
if (victim->position < POS_RESTING)
victim_ac += 6;
return victim_ac;
}
/* RETURNS THAC0 of CH against Victim. use fNpc to switch between PC/NPC Thac0 */
int get_THAC0(CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA* obj, int dt, bool secondary, bool fNpc, long act, bool fVirt, int gsn, int level)
{
/* HIGHER thac0 results in more MISSES */
//DATA
int thac0;
int thac0_00;
int thac0_32;
int sn = -1;
int skill = 0;
//Get damage text (split into weapon/spell/skill)
//for thac0 calc.
//NPC THAC0
if (fNpc )
{
thac0_00 = 20;
if (IS_SET(act, ACT_WARRIOR))
thac0_32 = -10;
else if (IS_SET(act, ACT_THIEF))
thac0_32 = -4;
else if (IS_SET(act, ACT_CLERIC))
thac0_32 = 2;
else if (IS_SET(act, ACT_MAGE))
thac0_32 = 6;
else
thac0_32 = -4;
}
else
//PC THAC0
{
thac0_00 = class_table[ch->class].thac0_00;
thac0_32 = class_table[ch->class].thac0_32;
}
sn = (fVirt? gsn : get_weapon_sn(ch,secondary));
skill = 20 + (fVirt? get_skill(ch, gsn) : get_weapon_skill_obj(ch,obj));
//COMMON THAC0
thac0 = interpolate( level, thac0_00, thac0_32 );
thac0 -= (GET_HITROLL(ch) / 2) * UMIN(100, skill) /100;
//Penalty for skills.
if (dt == gsn_backstab
|| dt == gsn_dual_backstab
|| dt == gsn_cleave
|| dt == gsn_assassinate
|| dt == gsn_charge
|| dt == gsn_ambush
|| dt == gsn_circle
|| dt == gsn_riposte
)
//penalty for weapon skill
thac0 += 5 * (100 - skill) / 100;
//Penalty for secondary weapon
if (get_eq_char(ch,WEAR_SECONDARY) != NULL && !fVirt
&& ( ch->class != class_lookup("warrior")
&& ch->class != class_lookup("ranger")) )
thac0 += 10;
return thac0;
}
void one_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt, bool secondary)
{
OBJ_DATA *wield;
AFFECT_DATA *paf;
int apierce = 0;
//BOOL
bool fReverse = FALSE;
bool fPugil = FALSE;
int victim_ac, thac0, dam, diceroll, sn = -1, skill, dam_type, success, dam_limit = 30000;
int result = 0;
int temp = 0;
int ac_red = 1600;
int hroll, droll;
if ( is_affected(ch,gsn_mortally_wounded) )
return;
if ( is_affected(ch,gsn_ecstacy) )
return;
if (victim == ch || ch == NULL || victim == NULL)
return;
if ( ch->in_room != victim->in_room )
return;
if ( ( paf = affect_find(ch->affected,gsn_rake)) != NULL )
{
if (!secondary && paf->modifier == 1)
{
act("Your primary weapon has been pushed aside!",ch,NULL,NULL,TO_CHAR);
act("$n's primary weapon has been pushed aside!",ch,NULL,victim,TO_VICT);
return;
}
if (secondary && paf->modifier == 0)
{
act("Your secondary weapon has been raked aside!",ch,NULL,NULL,TO_CHAR);
act("$n's secondary weapon has been raked aside!",ch,NULL,victim,TO_VICT);
return;
}
}
else{
//DRAW WEAPON
OBJ_DATA* wield, *second;
wield = get_eq_char(ch,WEAR_WIELD);
second = get_eq_char(ch,WEAR_SECONDARY);
do_combatdraw(ch, wield, second);
}
if (!secondary)
wield = get_eq_char( ch, WEAR_WIELD );
/* check for use of pugil here */
else if ( (wield = get_eq_char(ch, WEAR_WIELD)) != NULL
&& wield->item_type == ITEM_WEAPON
&& wield->value[0] == WEAPON_STAFF
&& get_eq_char(ch, WEAR_SECONDARY) == NULL
&& get_eq_char(ch, WEAR_SHIELD) == NULL
&& get_eq_char(ch, WEAR_HOLD) == NULL){
check_improve(ch, gsn_pugil, TRUE, 1);
fPugil = TRUE;
}
else
wield = get_eq_char( ch, WEAR_SECONDARY );
if (wield != NULL){
AFFECT_DATA* paf;
if ( (paf = affect_find(ch->affected, gsn_con_damage)) != NULL
&& number_percent() < ((get_skill(ch, gsn_con_damage) - 50) * 2)){
dam_type = attack_table[paf->modifier].damage;
dt = paf->modifier + TYPE_HIT;
check_improve(ch, gsn_con_damage, TRUE, 1);
}
}
if ( dt == TYPE_UNDEFINED )
{
dt = TYPE_HIT;
if ( wield != NULL && wield->item_type == ITEM_WEAPON )
dt += wield->value[3];
else
dt += ch->dam_type;
}
if (dt < TYPE_HIT)
{
/* check for control damage here, stored in paf->modifier */
if (wield != NULL){
dam_type = attack_table[wield->value[3]].damage;
}
else
dam_type = attack_table[ch->dam_type].damage;
}
else{
/* check for monk magical chii level 2 */
if ( (paf = affect_find(ch->affected, gsn_chii_bolt)) != NULL
&& paf->modifier == 2)
dam_type = attack_table[attack_lookup("magic")].damage;
else
dam_type = attack_table[dt - TYPE_HIT].damage;
}
if (dam_type == -1)
dam_type = DAM_BASH;
if (!secondary || fPugil)
sn = get_weapon_sn(ch,FALSE);
else
sn = get_weapon_sn(ch,TRUE);
skill = 20 + get_weapon_skill_obj(ch, wield);
//GET thac0 and AC
thac0 = get_THAC0(ch, victim, wield, dt, secondary, IS_NPC(ch), ch->act,
FALSE, dt, ch->level);
victim_ac = get_AC(ch, victim, dt, dam_type, FALSE);
/* debug */
/* sendf(ch, "your thaco: %d, their ac %d", thac0, victim_ac); */
//sendf(ch, "sn: %d\n\r", sn);
// PRACTICE BONUS
if (sn != -1)
{
if (wield && !str_cmp(wield->material,"practice"))
check_improve(ch,sn,TRUE,3);
else
check_improve(ch,sn,TRUE,1);
if (wield != NULL &&
(IS_WEAPON_STAT(wield, WEAPON_TWO_HANDS) || is_affected(ch, gsn_double_grip)))
check_improve(ch,gsn_2hands,TRUE,1);
if (wield && is_affected(ch, gsn_double_grip))
check_improve(ch,gsn_double_grip,TRUE,1);
}
//ROLL FOR HIT
while ( ( diceroll = number_bits( 5 ) ) >= 20 );
if ((diceroll == 0 || ( diceroll != 19 && diceroll < thac0 - victim_ac )) )
{
//MISS
damage( ch, victim, 0, dt, dam_type, TRUE );
tail_chain( );
return;
}
if ( IS_NPC(ch) && (!ch->pIndexData->new_format || wield == NULL))
{
if (!ch->pIndexData->new_format)
{
dam = number_range( ch->level / 2, ch->level * 3 / 2 );
if ( wield != NULL )
dam += dam / 2;
}
else
dam = dice(ch->damage[DICE_NUMBER],ch->damage[DICE_TYPE]);
}
else
//SUCCESSFULL HIT
{
//DAMAGE/DDAMTYPE CALC.
if ( wield != NULL )
{
//New Format
//PC (skill = weaponskill + 20)
if (wield->pIndexData->new_format)
{
//powerstrike
if (number_percent() < get_skill(ch, gsn_powerstrike) / 2
&& get_eq_char(ch, WEAR_WIELD) != NULL
&& get_eq_char(ch, WEAR_SECONDARY) != NULL
&& monk_good(ch, WEAR_WAIST) ){
int chance = (get_curr_stat(ch, STAT_LUCK) - 14) * 3;
check_improve(ch, gsn_powerstrike, TRUE, 0);
if (number_percent() < chance)
dam = wield->value[1] * wield->value[2] * skill / 120;
else
dam = dice(wield->value[1],wield->value[2]) * skill/120;
}
else
dam = dice(wield->value[1],wield->value[2]) * skill/120;
if (wield->level > ch->level && wield->level > 10)
dam = dam * URANGE(15, ch->level, 50) / UMIN(50, 1 + wield->level);
dam_limit = 3 * wield->value[1] * (wield->value[2] + 1);
}
else
{
//OLD FORMAT
dam = number_range( wield->value[1] * skill/120, wield->value[2] * skill/120);
if (wield->level > (5 * ch->level/4) && wield->level > 20)
{
//DAMAGE PENALTY FOR LVL
if (ch->level < 15)
dam = dam * URANGE(15,ch->level,45) / UMIN(50, 5 * wield->level/4);
else
dam = dam * URANGE(15,5 * ch->level/4,45) / UMIN(45, wield->level);
}
dam_limit = 3 * (wield->value[1] + wield->value[2]);
}
}
//HAND TO HAND ENHANCERS
else if (is_affected(ch, gsn_body_weaponry))
dam = dice(ch->level / 4, 7);
else if ( is_affected(ch, gen_holy_hands))
dam = dice(ch->level, 3) / 5;
/* monk h2h */
else if (get_skill(ch, gsn_martial_arts_b) > 1)
dam = dice(1 + (ch->level / 6), 6) * skill / 120;
else if (ch->race == grn_werebeast)
dam = dice(1 + (ch->level / 7), 6);
else
dam = dice(ch->level, 3) * skill / 750;
}
//AVENGER and other crusader benefits
if ( (temp = check_avenger(ch, victim)) != CRUSADE_NONE){
if (temp == CRUSADE_MATCH)
dam += 15 * dam / 100;
else if (temp == CRUSADE_NOTMATCH)
dam -= 10 * dam / 100;
}
else if (dam_type == DAM_BASH && number_percent() < get_skill(ch, gsn_dam_masteryB)){
dam += number_range(5, 20) * dam / 100;
check_improve(ch, gsn_dam_masteryB, TRUE, 1);
}
else if (dam_type == DAM_SLASH && number_percent() < get_skill(ch, gsn_dam_masteryS)){
dam += number_range(5, 20) * dam / 100;
check_improve(ch, gsn_dam_masteryS, TRUE, 1);
}
else if (dam_type == DAM_PIERCE && number_percent() < get_skill(ch, gsn_dam_masteryP)){
dam += number_range(5, 20) * dam / 100;
check_improve(ch, gsn_dam_masteryP, TRUE, 1);
}
//ENHANCED DAMAGE
if ( get_skill(ch,gsn_enhanced_damage) > 0 && !vamp_check(ch))
{
diceroll = number_percent();
diceroll -= 2*(get_curr_stat(ch,STAT_LUCK) - 16);
if (diceroll <= get_skill(ch,gsn_enhanced_damage))
{
check_improve(ch,gsn_enhanced_damage,TRUE,1);
dam += (dam * URANGE(20,diceroll,60)) /100;
/* Extra race bonus */
if (ch->race == race_lookup("ogre") )
dam += (dam * URANGE(0,diceroll,20)) /100;
else if ( ch->race == race_lookup("fire")
&& wield
&& (dam_type == DAM_FIRE || !str_cmp("fire", wield->material)) )
dam += (dam * URANGE(0,diceroll,20)) /100;
}
}
//DOUBLE GRIP /2handed (not staffs )
if (is_affected(ch,gsn_double_grip)
&& get_skill(ch,gsn_double_grip) > 0)
{
diceroll = number_percent();
diceroll -= (get_curr_stat(ch,STAT_LUCK) - 16);
if (diceroll <= get_skill(ch,gsn_double_grip)){
dam += (dam * number_range(5, 15)) /100;
check_improve(ch, gsn_double_grip, TRUE, 1);
}
}
else if ( wield
&& (IS_WEAPON_STAT(wield, WEAPON_TWO_HANDS) || is_affected(ch, gsn_double_grip))
&& wield->value[0] != WEAPON_STAFF)
dam += (dam * 15) / 100;
//ANATOMY
dam += dam * check_anatomy(ch, victim) / 200;
//CEILING
if (dam > dam_limit)
dam = dam_limit;
//HORSE
if (!IS_NPC(victim) && victim->pcdata->pStallion != NULL && number_percent() < get_skill(victim, gsn_mounted)){
dam -= dam/6;
check_improve(victim, gsn_mounted, TRUE, 1);
}
//BAKCSTABS
if ( dt == gsn_backstab )
{
dam = UMIN(ch->level/12, 4) * dam + UMIN(50,GET_DAMROLL(ch))*2;
if (dam > 400)
dam = 400;
}
if ( dt == gsn_dual_backstab )
{
dam = UMIN(ch->level/12, 3) * dam + UMIN(50,GET_DAMROLL(ch));
if (dam > 300)
dam = 300;
}
//POSITONS
if ( !IS_AWAKE(victim))
{
if (dt == gsn_backstab || dt == gsn_dual_backstab || dt == gsn_cleave || dt == gsn_assassinate || dt == gsn_ambush)
dam *= 1.5;
else
dam *= 2;
}
else if (victim->position < POS_FIGHTING)
{
if (dt == gsn_backstab || dt == gsn_dual_backstab || dt == gsn_cleave || dt == gsn_assassinate || dt == gsn_ambush)
dam *= 1.2;
else
dam *= 1.5;
}
//MORE ATTACK DAMGE CHANGES
if (dt == gsn_cleave)
dam = (dam * 2) + ch->level;
if (dt == gsn_assassinate)
dam *= 2;
if (dt == gsn_charge)
dam = 3 * dam / 2;
if (dt == gsn_ambush)
{
if (!can_see(victim,ch) && IS_AFFECTED2(ch,AFF_CAMOUFLAGE))
dam = (3 * dam) + ch->level;
else
dam = (2 * dam) + ch->level;
if (victim->fighting != NULL)
dam *= 2/3;
}
if (dt == gsn_circle || dt == gsn_sheath)
dam += UMIN(dam, (2 * dam * UMIN(ch->level,50)) / 80) + ch->level;
if (dt == gsn_riposte )
dam /= 4;
/* damage increase due to rage */
if (IS_AFFECTED2(ch, AFF_RAGE)){
int chance = 2 * get_skill(ch, gsn_rage) / 3 + ch->level / 3;
chance += 2 * (get_curr_stat(ch,STAT_LUCK) - 16);
chance = UMAX(1, chance);
/* check if we do rage */
if (number_percent() < chance){
int str_bonus = get_curr_stat(ch, STAT_STR);
int lvl_bonus = ch->level / 2;
/* path of devastation = str_bonus + level bonus
path of fury = str_bonus;
path of anger = str_bonus / 4;
otherwise = str_bonus / 2
*/
if (get_skill(ch, gsn_path_dev))
dam += dam * (str_bonus + lvl_bonus) / 100;
else if (get_skill(ch, gsn_path_fury))
dam += dam * str_bonus / 100;
else if (get_skill(ch, gsn_path_anger))
dam += dam * str_bonus / 400;
else
dam += dam * str_bonus / 200;
check_improve(ch,gsn_rage,TRUE,1);
}
}
//HROLL and DROLL
hroll = GET_HITROLL(ch);
droll = GET_DAMROLL(ch);
/* racial enemy */
if (!IS_NPC(ch) && ch->pcdata->enemy_race && victim->race == ch->pcdata->enemy_race){
hroll += ch->level / 5;
droll += ch->level / 5;
}
//CAPS
if (hroll > 25)
hroll = (hroll - 25) / 2 + 25;
else if (hroll > 50)
hroll = (hroll - 50) / 3 + (25 / 2) + 25;
if (droll > (ch->level * 2) && droll > 20){
int tdam, ddam, i;
tdam = droll - (ch->level * 2);
ddam = 0;
for(i = 3;tdam > 10;i++){
tdam -= 10;
ddam += UMAX(0,7 - i);
}
ddam += (tdam / (i + 1)) + (ch->level * 2);
dam += ddam * UMIN(100,skill) /100;
}
else if (droll <= (ch->level * 2) || droll <= 20)
dam += droll * UMIN(80, skill) / 100;
if (dam > 750)
dam = 750;
//DAMAGE REDUCTION DUE TO AC
if (is_armor_enhanced(ch) > ENHANCE_NONE)
ac_red = 1200;
else
ac_red = 1600;
switch(dam_type)
{
case(DAM_PIERCE):temp = GET_AC(victim,AC_PIERCE) * dam / ac_red;break;
case(DAM_BASH): temp = GET_AC(victim,AC_BASH) * dam / ac_red;break;
case(DAM_SLASH): temp = GET_AC(victim,AC_SLASH) * dam / ac_red;break;
default: temp = GET_AC(victim,AC_EXOTIC) * dam / ac_red;break;
};
/* armor piercing */
/* better chance of ignore blow when using skill and has chance for
damaging blow */
apierce = get_skill(ch, gsn_apierce);
if ( temp < 0 && (paf = affect_find(ch->affected, gen_apierce)) != NULL
&& paf->modifier >= 0 //modifer set to -1 after success in gen
&& number_percent() < apierce){
/* gen will attempt armor destroying blow */
paf->modifier = 1;
check_improve(ch, gsn_apierce, TRUE, 1);
}
else if (number_percent() < apierce / 2){
check_improve(ch, gsn_apierce, TRUE, 1);
}
else
dam = UMAX(1, dam + temp);
//MORE DAMAGE CAPPING
if (ch->level < 15)
dam = UMIN(dam, (25 + (ch->level * 2)));
dam = UMAX(0,dam);
//COUNTER
if (victim->class == gcn_monk
&& victim->fighting
&& is_affected(victim, gsn_horse)
&& is_empowered_quiet(victim,1)){
success = get_skill(victim, gsn_horse);
success = ((success > 99?10:(success > 95?5:0)) + (success - 75)/5) + 10;
check_improve(victim, gsn_horse, TRUE, 1);
fReverse = TRUE;
}
else
success = get_skill(victim, gsn_counter);
//skill modifiers
if (success > 0){
success += victim->level - ch->level;
success += get_curr_stat(victim,STAT_STR) - get_curr_stat(ch,STAT_STR);
success += (get_curr_stat(victim,STAT_DEX) - get_curr_stat(ch,STAT_DEX)) *2;
success += (get_curr_stat(victim,STAT_LUCK) - get_curr_stat(ch,STAT_LUCK));
success = UMIN(90, success);
}
if (fReverse
&& victim->fighting
&& number_percent() < success
&& (victim->class == gcn_monk
&& is_affected(victim, gsn_horse)
&& is_empowered_quiet(victim,1)
&& victim->mana >= 2
&& victim->fighting == ch
)
){
victim->mana -= 2;
act("You reverse $n's attack against $m.",ch,NULL,victim,TO_VICT);
act("$N moves suddenly and reverses your attack against you.",ch,NULL,victim,TO_CHAR);
act("$N reverses $n's attack against $m.",ch,NULL,victim,TO_NOTVICT);
result = virtual_damage( victim, ch, wield, dam, dt, dam_type, hroll, ch->level, TRUE, FALSE, 0);
}
else if (victim->fighting == NULL && counter_check(ch, victim, success, dam, dam_type, gsn_counter)){
set_fighting( ch, victim );
}
else{
//Avenger boosts hitroll
if ( (temp = check_avenger(ch, victim)) != CRUSADE_NONE){
if (temp == CRUSADE_MATCH)
hroll += 20 * hroll / 100;
else if (temp == CRUSADE_NOTMATCH)
hroll -= 15 * hroll / 100;
}
//////////////////
//DO DAMAGE HERE//
//////////////////
result = virtual_damage( ch, victim, wield, dam, dt, dam_type,
hroll, ch->level, TRUE, FALSE, 0);
}
tail_chain( );
}
int dam_spell(CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dam_type)
{
AFFECT_DATA *paf;
//Damage Non is not affected by any of this.
if (dam < 1)
return 0;
if (dam_type == DAM_INTERNAL)
return dam;
if (dam_type != DAM_NONE)
{
/* area ownwers */
if (ch->in_room && ch->in_room->area->pCabal && IS_EVIL(ch) && IS_CABAL(ch->in_room->area->pCabal, CABAL_SWARM) && !is_same_cabal(ch->in_room->area->pCabal, victim->pCabal))
dam = 11 * dam / 10;
/* force field */
if ((dam > 1 && dam_type == DAM_BASH) && ((paf = affect_find(victim->affected, gsn_forcefield)) != NULL))
dam = UMIN(dam, paf->modifier);
if (dam > 1 && ((paf = affect_find(victim->affected, gen_discord)) != NULL))
dam -= (paf->modifier? dam / 4 : 0);
if (dam > 1 && ((paf = affect_find(ch->affected, gen_discord)) != NULL))
dam += (paf->modifier? 0 : 15 * dam / 100);
if ( dam > 1 && (dam_type <= DAM_SLASH) && is_affected(victim, gsn_air_shield))
dam = 2 * dam / 3;
if ( dam > 1 && !IS_NPC(victim) && victim->pcdata->condition[COND_DRUNK] > 10 ) dam = dam * 8 / 10;
if ( dam > 1 && is_affected(victim, gsn_mental_barrier) && dam_type == DAM_MENTAL) dam -= dam / 3;
if ( dam > 1 && is_affected(victim, gsn_psychic_purge)
&& dam_type == DAM_MENTAL
&& check_immune(victim, DAM_MENTAL, FALSE) < IS_VULNERABLE)
dam += dam / 4;
if ( dam > 1 && is_affected(victim, gen_watchtower) ) dam = 3 * dam / 4;
/* EXCLUSIVE SANC LIKE EFFECTS */
if ( dam > 1 && IS_AFFECTED(victim, AFF_SANCTUARY) ) dam /= 2;
else if ( dam > 1 && is_affected(victim, gsn_lifeforce) ) dam /= 2;
else if ( dam > 1 && is_affected(victim, gsn_pyramid_of_force) ) dam = 5 * dam / 10;
if ( dam > 1 && !IS_NPC(ch) && IS_SET(ch->act2,PLR_GIMP) ) dam /= 2;
if ( dam > 1 && IS_AFFECTED2(victim, AFF_ICE_SHIELD) && dam_type == DAM_FIRE) dam /= 2;
if ( dam > 1 && IS_AFFECTED2(victim, AFF_FIRE_SHIELD) && dam_type == DAM_COLD) dam /= 2;
if ( dam > 1 && IS_AFFECTED2(victim, AFF_ICE_SHIELD) && dam_type == DAM_COLD) dam = dam * 3 / 2;
if ( dam > 1 && IS_AFFECTED2(victim, AFF_FIRE_SHIELD) && dam_type == DAM_FIRE) dam = dam * 3 / 2;
if ( dam > 1 && is_affected(victim, gsn_wolf_form) && dam_type > 3) dam = 7 * dam / 10;
if (dam > 1 && dam_type == DAM_MENTAL && IS_SET(victim->act, ACT_UNDEAD)) dam = dam / 2;
if ( dam > 1 && (paf = affect_find(victim->affected, gen_dvoid)) != NULL
&& paf->modifier < -6)
dam -= dam / 4;
else if ( dam > 1 && ((IS_AFFECTED(victim, AFF_PROTECT_EVIL) && IS_EVIL(ch))
|| (IS_AFFECTED(victim, AFF_PROTECT_GOOD) && IS_GOOD(ch) )))
dam -= dam / 4;
else if ( dam > 1 && (IS_GOOD(ch) || IS_EVIL(ch))
&& is_affected(victim, gsn_greenheart)){
dam -= dam / 4;
}
if ( dam > 1 && (IS_GOOD(victim) || IS_EVIL(victim))
&& is_affected(ch, gsn_greenheart)){
dam = 11 * dam / 10;
}
if ( dam > 1 && IS_AFFECTED(victim, AFF_WARD_LIGHT) ){
dam -= dam / 5;
}
if ( is_affected(victim,gsn_horse) && monk_good(ch, WEAR_HEAD))
dam -= dam / 5;
if ( is_affected(victim,gsn_aura) )
dam -= dam / 6;
if ( victim->class == gcn_blademaster && is_affected(victim,gsn_iron_curtain) && get_eq_char(victim, WEAR_SECONDARY) != NULL)
dam -= dam / 4;
if ( is_affected(victim,gsn_stance) ) dam = dam / 2;
else if ( is_affected(victim,gsn_sacred_runes) )
dam = dam / 2;
}
if ( dam > 1 && IS_AFFECTED2(victim, AFF_MANA_SHIELD) && dam_type > 3)
{
if (dam / 5 <= victim->mana)
victim->mana -= dam / 5;
else
{
dam -= victim->mana * (victim->level/5);
victim->mana = 0;
REMOVE_BIT(victim->affected2_by,AFF_MANA_SHIELD);
if (is_affected(ch, skill_lookup("mana shield"))){
act("Your mana shield flares brightly then dissipates.",victim,NULL,NULL,TO_CHAR);
act("$n's mana shield flares brightly then dissipates.",victim,NULL,NULL,TO_ROOM);
}
else{
act("Your magical protection dissipates.",victim,NULL,NULL,TO_CHAR);
act("$n's magical protection dissipates.",victim,NULL,NULL,TO_ROOM);
}
}
}
if ( dam > 1 && IS_AFFECTED2(victim, AFF_BARRIER) && (dam_type <= 3 && dam_type))
{
if (dam / 3 <= victim->mana)
victim->mana -= dam / 3;
else
{
dam -= victim->mana * (victim->level/3);
victim->mana = 0;
REMOVE_BIT(victim->affected2_by,AFF_BARRIER);
act("Your physical barrier flares brightly then dissipates.",victim,NULL,NULL,TO_CHAR);
act("$n's physical barrier flares brightly then dissipates.",victim,NULL,NULL,TO_ROOM);
}
}
return dam;
}
int dam_monk(CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt)
{
int chance = 0, anatomy = 0, shield = 0;
bool fIgnore = FALSE;
bool fCrane = FALSE;
bool fTiger = FALSE;
bool fDragon = FALSE;
bool fMonkey = FALSE;
int Chak = 0; //duration to shave off of a prot. shield if present.
if (race_table[victim->race].pc_race)
anatomy = anatomy_lookup(pc_race_table[victim->race].anatomy);
if (is_empowered_quiet(ch, 0)){
chance = ch->pcdata->anatomy[anatomy] / 2;
chance += get_skill(ch,gsn_anatomy) / 10;
chance += GET_HITROLL(ch) / 2;
chance += URANGE(-5, (ch->level - victim->level), 5);
chance += (get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK));
chance = URANGE(0, chance, 70);
}
//get which stance we are in.
if (is_affected(ch, gsn_crane) && is_empowered_quiet(ch, 0))
fCrane = TRUE;
else if (is_affected(ch, gsn_tiger) && is_empowered_quiet(ch, 0))
fTiger = TRUE;
else if (is_affected(ch, gsn_dragon) && is_empowered_quiet(ch, 0))
fDragon = TRUE;
else if (is_affected(ch, gsn_monkey) && is_empowered_quiet(ch, 0))
fMonkey = TRUE;
if (fMonkey)
dam = 6 * dam / 10;
if (fCrane && number_percent() < get_skill(ch, gsn_crane))
{
chance += 5 + UMAX(0, get_skill(ch,gsn_crane) - 80);
check_improve(ch, gsn_crane, TRUE, 1);
}
//IMMUNES
shield = get_lagprot(victim);
if (IS_SET(victim->act, ACT_UNDEAD)
|| (victim->race == race_lookup("ogre")
&& number_percent() < victim->level
)
|| shield == LAG_SHIELD_PROT
|| shield == LAG_SHIELD_FFIELD
|| shield == LAG_SHIELD_ARMOR
|| shield == LAG_SHIELD_NONCORP
|| shield == LAG_SHIELD_IWILL
)
fIgnore = TRUE;
if (fIgnore && is_affected(ch, gsn_invigorate))
fIgnore = FALSE;
switch (dt)
{
case (1053): dam = 5 * dam / 8; break;
case (1054): dam = 7 * dam / 8; break;
case (1055): dam = dam;
if ( fCrane && number_percent() < chance)
{
act("$n's elbow brutaly connects with your temple.", ch, NULL, victim, TO_VICT);
act("$n's elbow brutaly connects with $N's temple.", ch, NULL, victim, TO_NOTVICT);
act("Your elbow brutaly connects with $N's temple.", ch, NULL, victim, TO_CHAR);
check_improve(ch, gsn_crane, TRUE, 1);
if (fIgnore)
{
send_to_char("You easly shrug off the feeble blow.\n\r", victim);
act("$n seems to not even notice!", victim, NULL, victim, TO_ROOM);
}
else
{
victim->mana -= victim->max_mana / UMAX(1,(70 - chance / 2));
victim->mana = UMAX(0, victim->mana);
WAIT_STATE2(victim, 6);
}
}
break;
case (1056): dam = dam;
if ( fCrane && number_percent() < chance)
{
act("$n drives his palm into your torso with crushing strength.", ch, NULL, victim, TO_VICT);
act("$n drives his palm into $N's torso with crushing strength", ch, NULL, victim, TO_NOTVICT);
act("You drive your palm into a sensetive spot on $N's torso.", ch, NULL, victim, TO_CHAR);
check_improve(ch, gsn_crane, TRUE, 1);
if (fIgnore)
{
send_to_char("You easly shrug off the feeble blow.\n\r", victim);
act("$n seems to not even notice!", victim, NULL, victim, TO_ROOM);
}
else
{
WAIT_STATE2(victim, 6);
dam = 6 * dam / 5;
}
}
break;
case (1057): dam = 8 * dam / 7;
if (number_percent() < chance )
{
if (fTiger && number_percent() < 2 * (get_skill(ch, gsn_tiger) - 50) )
{
act("$n executes \"twin tiger claw\", stunning you.",ch,NULL,victim,TO_VICT);
act("You execute \"twin tiger claw\", stunning $N.",ch,NULL,victim,TO_CHAR);
act("$n executes \"twin tiger claw\", stunning $N.",ch,NULL,victim,TO_NOTVICT);
check_improve(ch, gsn_tiger, TRUE, -99);
WAIT_STATE2(victim, 34);
Chak += 4;
damage(ch, victim, UMIN(3 * dam / 2, victim->hit - 1), gsn_tiger, DAM_PIERCE, TRUE);
if (victim->position <= POS_STUNNED)
dam = 0;
else
dam += victim->hit/10;
}
else
{
act("$n strikes a chakera point, stunning you.",ch,NULL,victim,TO_VICT);
act("You strike a chakera point, stunning $N.",ch,NULL,victim,TO_CHAR);
act("$n strikes a chakera point stunning $N.",ch,NULL,victim,TO_NOTVICT);
/* get the right stance improv */
if (fCrane)
check_improve(ch, gsn_crane, TRUE, 0);
else if (fTiger)
check_improve(ch, gsn_tiger, TRUE, 0);
else if (fDragon)
check_improve(ch, gsn_dragon, TRUE, 0);
else if (fMonkey)
check_improve(ch, gsn_dragon, TRUE, 0);
if (fIgnore)
{
send_to_char("You easly shrug off the feeble blow.\n\r", victim);
act("$N seems to not even notice!", victim, NULL, victim, TO_ROOM);
Chak += 2;
}
else
{
dam += victim->hit/10;
WAIT_STATE2(victim, 24);
}//end not igonre
}
}
break;
case (1058): dam = 8 * dam / 7;
if ( number_percent() < (fDragon? 10 + chance/3 : chance / 3) && !fCrane)
{
if (fDragon && number_percent() < 2 * (get_skill(ch, gsn_dragon) - 50))
{
act("$n executes \"strike of the phantom dragon\".",ch,NULL,victim,TO_VICT);
act("You execute \"strike of the phantom dragon\".",ch,NULL,victim,TO_CHAR);
act("$n executes \"strike of the phantom dragon\"",ch,NULL,victim,TO_NOTVICT);
WAIT_STATE2(victim, number_range(3, 4) * 12);
Chak += 10;
dam = dam * ch->level / 15;
act("A phantasmal dragon rears its head and breaths.",ch,NULL,victim,TO_ALL);
damage(ch, victim, 3 * UMIN(dam, victim->hit - 1) / 2, gsn_phantom_dragon, DAM_ENERGY, TRUE);
check_improve(ch, gsn_dragon, TRUE, -99);
if (victim->position <= POS_STUNNED
|| !victim->fighting )
dam = 0;
else
{
act("Blood spraying about, $n buries $s fingers in $N's torso!", ch, NULL, victim, TO_NOTVICT);
act("The power of Dragon in your veins you bury your fingers in $N's torso!", ch, NULL,victim, TO_CHAR);
act("The world dims with pain as $n buries his fingers in your torso.", ch, NULL, victim, TO_VICT);
}
}
else
{
act("$n strikes a chakera point, forcefully sending you collapsing to the ground.",ch,NULL,victim,TO_VICT);
act("You struck a chakera point, forcefully sending $N collapsing to the ground.",ch,NULL,victim,TO_CHAR);
act("$n strikes a chakera point, forcefully sending $N collapsing to the ground.",ch,NULL,victim,TO_NOTVICT);
/* get the right stance improv */
if (fCrane)
check_improve(ch, gsn_crane, TRUE, 0);
else if (fTiger)
check_improve(ch, gsn_tiger, TRUE, 0);
else if (fDragon)
check_improve(ch, gsn_dragon, TRUE, 0);
else if (fMonkey)
check_improve(ch, gsn_dragon, TRUE, 0);
if (fIgnore)
{
send_to_char("You easly shrug off the feeble blow.\n\r", victim);
act("$N seems to not even notice!", victim, NULL, victim, TO_ROOM);
Chak += 2;
}
else
{
WAIT_STATE2(victim, 24);
dam = dam * number_range(45, ch->pcdata->anatomy[anatomy]) / 30;
dam += victim->hit / 15;
}
}//END REGULAR DRAGON
}//END STRIKE OF DRAGON
break;
case (1059): dam = 5 * dam / 8; break;
case (1060): dam = 7 * dam / 8; break;
case (1061): dam = dam; break;
case (1062): dam = dam; break;
case (1063): dam = 8 * dam / 7; break;
case (1064): dam = 8 * dam / 7; break;
}
//do the effects for the kicks.
if ( fCrane && number_percent() < chance
&& dt <= 1064 && dt >= 1062)
{
act("$n's kick brutaly connects with your leg.", ch, NULL, victim, TO_VICT);
act("$n's kick brutaly connects with $N's leg.", ch, NULL, victim, TO_NOTVICT);
act("Your kick brutaly connects with $N's leg.", ch, NULL, victim, TO_CHAR);
check_improve(ch, gsn_crane, TRUE, 1);
dam = 6 * dam / 5;
if (fIgnore)
{
send_to_char("You easly shrug off the feeble blow.\n\r", victim);
act("$n seems to not even notice!", victim, NULL, victim, TO_ROOM);
}
else
{
victim->move -= victim->max_move * 2 / UMAX(1,(70 - chance / 2));
victim->move = UMAX(0, victim->move);
WAIT_STATE2(victim, 6);
}
}
/* check for weakening of prot. shield */
if (fIgnore && Chak && !IS_NPC(victim)){
AFFECT_DATA* paf;
if ( (paf = affect_find(victim->affected, gsn_protective_shield)) != NULL){
paf->duration -= Chak;
if (paf->duration < 0){
affect_strip(victim, gsn_protective_shield);
if ( skill_table[paf->type].msg_off )
act_new(skill_table[paf->type].msg_off,ch,NULL,NULL,TO_CHAR,POS_DEAD);
if ( skill_table[paf->type].msg_off2 )
act(skill_table[paf->type].msg_off2,ch,NULL,NULL,TO_ROOM);
}
}
else if ( (paf = affect_find(victim->affected, gsn_forcefield)) != NULL){
paf->duration -= Chak;
if (paf->duration < 0){
affect_strip(victim, gsn_forcefield);
if ( skill_table[paf->type].msg_off )
act_new(skill_table[paf->type].msg_off,ch,NULL,NULL,TO_CHAR,POS_DEAD);
if ( skill_table[paf->type].msg_off2 )
act(skill_table[paf->type].msg_off2,ch,NULL,NULL,TO_ROOM);
}
}
else if ( (paf = affect_find(victim->affected, gsn_iron_will)) != NULL){
paf->duration -= Chak;
if (paf->duration < 0){
affect_strip(victim, gsn_iron_will);
if ( skill_table[paf->type].msg_off )
act_new(skill_table[paf->type].msg_off,ch,NULL,NULL,TO_CHAR,POS_DEAD);
if ( skill_table[paf->type].msg_off2 )
act(skill_table[paf->type].msg_off2,ch,NULL,NULL,TO_ROOM);
}
}
}
return dam;
}
void dam_update(CHAR_DATA *ch, CHAR_DATA *victim, int dam)
{
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 );
act_new("You are mortally wounded, and will die soon, if not aided.",victim, NULL, NULL, TO_CHAR, POS_DEAD );
break;
case POS_INCAP:
act("$n is incapacitated and will slowly die, if not aided.",victim, NULL, NULL, TO_ROOM );
act_new("You are incapacitated and will slowly die, if not aided.",victim, NULL, NULL, TO_CHAR, POS_DEAD );
break;
case POS_STUNNED:
act("$n is stunned, but will probably recover.",victim, NULL, NULL, TO_ROOM );
act_new("You are stunned, but will probably recover.",victim, NULL, NULL, TO_CHAR, POS_DEAD );
break;
case POS_DEAD:
if (!IS_NPC(victim)
&& ( (!IS_NPC(ch) && is_challenger(ch,victim))
|| (IS_NPC(ch)
&& ch->master
&& is_challenger(ch->master,victim))
)
)
{
act( "$n is mortally wounded!!", victim, NULL, NULL, TO_ROOM);
act_new( "You have been mortally wounded!!", victim, NULL, NULL, TO_CHAR, POS_DEAD );
}
else if ( !IS_NPC(victim)
&& victim->pcdata->pbounty
&& can_collect(victim->pcdata->pbounty, ch )){
if (!is_affected(victim, gsn_mortally_wounded)){
act( "$n is mortally wounded!!", victim, NULL, NULL, TO_ROOM);
act_new( "You have been mortally wounded!!", victim, NULL, NULL, TO_CHAR, POS_DEAD );
}
}
else if (!IS_NPC(victim) && IS_SET(victim->act, PLR_WANTED)
&& ch != victim
&& ( (!IS_NPC(ch) && ch->pCabal && IS_CABAL(ch->pCabal, CABAL_JUSTICE))
|| (IS_NPC(ch) && ch->leader
&& ch->leader->pCabal && IS_CABAL(ch->leader->pCabal, CABAL_JUSTICE))
|| (IS_NPC(ch) && IS_SET(ch->act2, ACT_LAWFUL))
)
){
act("$n stops short of a killing blow.", ch, NULL, victim, TO_ROOM);
act_new("$n stops short of a killing blow.", ch, NULL, victim, TO_VICT, POS_DEAD);
act("You stop short of a killing blow.", ch, NULL, victim, TO_CHAR);
}
else if (ch != victim
&& !IS_NPC(ch)
&& !IS_NPC(victim)
&& (IS_GAME(ch, GAME_MERCY) || (ch->in_room && IS_ROOM2(ch->in_room, ROOM_MERCY)))
&& !is_affected(victim, gsn_mercy_wait)
){
act("At the last moment you halt your deathblow.", ch, NULL, NULL, TO_CHAR);
act("At the last moment $n halts $s deathblow.", ch, NULL, NULL, TO_ROOM);
}
/* BLADEMASTER DEATHSTRIKE */
else if (deathstrikeCheck(ch, victim)){
act( "$n is DEAD!!", victim, NULL, NULL, TO_ROOM );
act_new( "You have been `1KILLED``!!\n\r", victim, NULL, NULL, TO_CHAR, POS_DEAD );
}
else if (IS_SET(victim->act,ACT_UNDEAD))
{
act( "$n is SLAIN!!", victim, NULL, NULL, TO_ROOM );
act_new( "You have been `1SLAYED``!!\n\r", victim, NULL, NULL, TO_CHAR, POS_DEAD );
}
else
{
act( "$n is DEAD!!", victim, NULL, NULL, TO_ROOM );
act_new( "You have been `1KILLED``!!\n\r", victim, NULL, NULL, TO_CHAR, POS_DEAD );
}
break;
default:
if ( dam > victim->max_hit / 4 )
{
//Continuum message.
continuum(victim, CONTINUUM_HURT);
send_to_char( "That really did HURT!\n\r", victim );
if (number_percent( ) > (victim->level * 2) && !IS_AFFECTED(victim,AFF_CALM) && victim->level >= 6
&& !IS_AFFECTED2(victim,AFF_RAGE) && !IS_NPC(victim) && victim->class == class_lookup("berserker"))
{
AFFECT_DATA af;
act("You feel your veins course with power as the madness engulfs you!",victim,NULL,NULL,TO_CHAR);
act("$n's eyes suddenly burn like hot coals as $e is gripped by insanity!",victim,NULL,NULL,TO_ROOM);
af.where = TO_AFFECTS2;
af.type = gsn_rage;
af.level = victim->level;
af.duration = UMAX(0, 4 - number_fuzzy(victim->level / 11));
af.location = APPLY_STR;
af.modifier = victim->size *2;
af.bitvector = AFF_RAGE;
affect_to_char(victim,&af);
af.location = APPLY_HITROLL;
af.modifier = str_app[get_curr_stat(victim,STAT_STR)].tohit + victim->level/4;
affect_to_char(victim,&af);
af.location = APPLY_DAMROLL;
af.modifier = str_app[get_curr_stat(victim,STAT_STR)].todam + victim->level/4;
affect_to_char(victim,&af);
af.location = APPLY_HIT;
af.modifier = (victim->level * victim->perm_stat[STAT_CON]) / 3;
affect_to_char(victim,&af);
victim->hit += (victim->level * victim->perm_stat[STAT_CON]) / 3;
check_improve(victim,gsn_rage,TRUE,1);
}
}
if ( victim->hit < victim->max_hit / 4 )
send_to_char( "You sure are BLEEDING!\n\r", victim );
break;
}
}
void dam_dead(CHAR_DATA *ch, CHAR_DATA *victim)
{
bool fBountyCheck = TRUE;
if (!IS_NPC(victim)
&& ( (!IS_NPC(ch)
&& is_challenger(ch,victim))
|| (IS_NPC(ch)
&& ch->master
&& is_challenger(ch->master,victim)) ))
{
mortal_wound(ch,victim);
return;
}
else if ( !IS_NPC(victim)
&& victim->pcdata->pbounty
&& can_collect(victim->pcdata->pbounty, ch )){
if (!is_affected(victim, gsn_mortally_wounded)){
mercy_effect(ch, victim, 4);
return;
}
else{
send_to_char( "You have been `1KILLED`` by a Bounty Hunter!\n\r\n\r",victim );
fulfill_bounty( ch, victim, "1" );
fBountyCheck = FALSE;
affect_strip(ch, skill_lookup("analyze"));
}
}
/* ACT_NODEATH mobs */
else if (IS_NPC(ch)
&& !IS_NPC(victim)
&& IS_SET(ch->act2, ACT_NODEATH)){
int pos = POS_STANDING;
OBJ_DATA* obj = NULL;
mortal_wound(ch,victim);
pos = ch->position;
/* triggers */
/* we save position so we can allow mobs to do things on death. */
ch->position = POS_STANDING;
if (HAS_TRIGGER_MOB(ch, TRIG_KILL))
p_percent_trigger(ch, NULL, NULL, victim, NULL, NULL, TRIG_KILL);
/* Objects */
for ( obj = ch->carrying; obj != NULL; obj = obj->next_content ){
if (HAS_TRIGGER_OBJ(obj, TRIG_KILL))
p_percent_trigger(NULL, obj, NULL, victim, NULL, NULL, TRIG_KILL);
}
/* Room Triggers */
if (HAS_TRIGGER_ROOM(ch->in_room, TRIG_KILL))
p_percent_trigger(NULL, NULL, ch->in_room, ch, NULL, NULL, TRIG_KILL);
ch->position = pos;
return;
}
/* jail captuer for justice */
else if (!IS_NPC(victim)
&& IS_SET(victim->act, PLR_WANTED)
&& ch != victim
&& ( (!IS_NPC(ch) && ch->pCabal && IS_CABAL(ch->pCabal, CABAL_JUSTICE))
|| (IS_NPC(ch) && ch->leader
&& ch->leader->pCabal && IS_CABAL(ch->leader->pCabal, CABAL_JUSTICE))
|| (IS_NPC(ch) && IS_SET(ch->act2, ACT_LAWFUL))
)
){
jail_char(ch, victim);
return;
}
/* MERCY KILL FOR WARRIORS */
else if (ch != victim
&& !IS_NPC(ch)
&& !IS_NPC(victim)
&& (IS_GAME(ch, GAME_MERCY)
|| (ch->in_room && IS_ROOM2(ch->in_room, ROOM_MERCY)))
&& !is_affected(victim, gsn_mercy_wait)
){
mercy_effect(ch, victim, 2);
return;
}
/* CABAL ALTAR DEATH */
else if (ch != victim
&& IS_NPC(victim)
&& (victim->pIndexData->vnum == MOB_VNUM_ALTAR || IS_SET(victim->off_flags, CABAL_GUARD))){
cabal_altar_death( ch, victim);
return;
}
if (unholy_gift(ch, victim))
return;
group_gain( ch, victim );
if ((victim == ch && victim->class != class_lookup("vampire"))
|| (IS_NPC(ch) && !IS_AFFECTED(ch,AFF_CHARM)) ){
if (IS_NPC(ch) && IS_SET(ch->act2, ACT_NOLOSS))
send_to_char("Somehow you are spared the loss of your experience!\n\r", victim);
else
victim->exp -= UMIN(15000,UMIN(exp_per_level(victim,victim->level),
victim->exp/10));
}
_raw_kill( ch, victim, fBountyCheck );
if (ch != victim)
do_autos(ch);
if (IS_AFFECTED2(ch,AFF_RAGE))
{
REMOVE_BIT(ch->affected2_by,AFF_RAGE);
affect_strip(ch,gsn_rage);
act("You snap out of your madness at the death of your opponent.",ch,NULL,NULL,TO_CHAR);
act("$n gasps for air as $e snaps out of $s insanity.",ch,NULL,NULL,TO_ROOM);
ch->hit -= (ch->level * ch->perm_stat[STAT_CON]) /3;
if (IS_IMMORTAL(ch))
ch->hit = UMAX(1,ch->hit);
if (ch->hit < -2)
{
int shock_mod = (25 * (0 - ch->hit)) / ch->max_hit;
if (number_percent( ) < con_app[UMAX(1,ch->perm_stat[STAT_CON] - shock_mod)].shock + 2*(get_curr_stat(ch,STAT_LUCK) - 16))
{
act_new("Your body suddenly awakens to the wounds you've sustained and you lose consciousness.",ch,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n suddenly clutches $s wounds and slumps to the ground, unconscious.",ch,NULL,NULL,TO_ROOM);
ch->hit = -2;
ch->position = POS_STUNNED;
act( "$n is stunned, but will probably recover.",ch, NULL, NULL, TO_ROOM );
act_new("You are stunned, but will probably recover.",ch, NULL, NULL, TO_CHAR, POS_DEAD );
}
else
{
act_new("Your body could not sustain the injuries you've suffered.",ch,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n suddenly clutches $s wounds and slumps to the ground.",ch,NULL,NULL,TO_ROOM);
act( "$n is DEAD!!",ch, 0, 0, TO_ROOM );
act_new( "You have been `1KILLED``!!", ch,NULL,NULL,TO_CHAR,POS_DEAD);
raw_kill( ch, ch );
}
}
}
}
void dam_after(CHAR_DATA *ch, CHAR_DATA *victim, int dam)
{
if ( !IS_NPC(victim) && victim->desc == NULL && victim->level < 11)
if ( number_range( 0, victim->wait ) == 0 )
{
do_recall( victim, ch->name );
return;
}
if ( IS_NPC(victim) && dam > 0 && victim->wait < PULSE_VIOLENCE / 4)
if ( ( IS_SET(victim->act, ACT_WIMPY)
&& number_bits( 2 ) == 0 && victim->hit < victim->max_hit / 5)
|| ( IS_AFFECTED(victim, AFF_CHARM)
&& victim->master != NULL
&& victim->master->in_room != victim->in_room
&& !is_affected(victim,gsn_linked_mind))
|| ( IS_NPC(victim) && IS_SET(victim->special,SPECIAL_COWARD))
|| ( IS_NPC(ch) && !IS_AFFECTED(ch,AFF_CHARM)
&& !IS_AFFECTED(victim,AFF_CHARM)
&& !IS_SET(victim->act, ACT_SENTINEL)
&& !IS_SET(victim->act, ACT_RAIDER )
&& !IS_SET(ch->act, ACT_RAIDER )
&& ch->level > victim->level
&& !IS_SET(victim->off_flags,CABAL_GUARD)
&& !IS_SET(victim->off_flags,GUILD_GUARD)
&& !is_affected(victim,gsn_timer)
&& !is_affected(ch,gsn_timer) ))
do_flee( victim, ch->name );
if ( !IS_NPC(victim)
&& victim->hit > 0
&& victim->hit <= victim->wimpy
&& victim->wait < PULSE_VIOLENCE / 4)
do_flee( victim, ch->name );
}
/* Virtual damage function */
/*(X = Virtual only)
ch = character doing the damage
vic = character receving damage
obj = obj doing the damage (X)
dam = damage to be done + race vuln.
dam_type = type of damage: slash, fire, ice etc.
h_roll = hitroll to be used for parry/block
lvl = level of the attacker / obj/spell
show = damage shown?
fVirt = Virtual attack (obj/spell/skill that can be blocked etc. like reg. attack.) (X)
sn = skill/spell doing the virtual attack (X)
*/
int virtual_damage(CHAR_DATA *ch,CHAR_DATA *victim, OBJ_DATA* obj, int dam, int dt, int dam_type, int h_roll, int lvl, bool set_combat, bool fVirt, int sn)
{
bool immune;
AFFECT_DATA* paf;
if (ch->in_room == NULL || ch->in_room->vnum == ROOM_VNUM_LIMBO )
/* Viri || ch->in_room->vnum == ROOM_VNUM_BURROW) */
return FALSE;
if (IS_NPC(victim) && is_affected(victim,gsn_mirror_image))
{
extract_char(victim,TRUE);
return FALSE;
}
if (IS_NPC(victim) && is_affected(victim,gsn_decoy))
{
CHAR_DATA* vch = victim->summoner ? victim->summoner : victim;
send_to_char("It's a trap!\n\r",ch);
act("$n explodes, a powdery dust spills from it.",victim,NULL,NULL,TO_ALL);
spell_poison(gsn_poison,victim->level + 3,vch,(void *) ch,TARGET_CHAR);
spell_blindness(gsn_blindness,victim->level + 3,vch,(void *) ch,TARGET_CHAR);
WAIT_STATE2(victim, 2 * PULSE_VIOLENCE);
paralyze_effect(victim, victim->level, number_range(victim->level, 2 * victim->level), TARGET_CHAR);
extract_char(victim,TRUE);
return FALSE;
}
//DRAW WEAPONS
else if (ch != victim && ch->in_room == victim->in_room && set_combat){
OBJ_DATA* wield, *second;
wield = get_eq_char(ch,WEAR_WIELD);
second = get_eq_char(ch,WEAR_SECONDARY);
do_combatdraw(ch, wield, second);
wield = get_eq_char(victim,WEAR_WIELD);
second = get_eq_char(victim,WEAR_SECONDARY);
do_combatdraw(victim, wield, second);
/* set the right dam. message for attacker */
}
if ( victim != ch && ch->in_room == victim->in_room)
{
if ( ch->position > POS_STUNNED && set_combat)
{
if ( ch->fighting == NULL )
set_fighting( ch, victim);
if (ch->timer <= 4)
ch->position = POS_FIGHTING;
}
if ( victim->position > POS_STUNNED && set_combat)
{
if ( victim->fighting == NULL )
set_fighting( victim, ch );
if (victim->timer <= 4)
victim->position = POS_FIGHTING;
}
//CHARMIE DEFENDER CHECK
if ( ch->position > POS_STUNNED && set_combat)
{
if ( ch->fighting == NULL )
set_fighting( ch, victim );
if ( IS_NPC(ch)
&& IS_NPC(victim)
&& !IS_AFFECTED(ch,AFF_CHARM)
&& IS_AFFECTED(victim, AFF_CHARM)
&& ch->in_room == victim->in_room
&& victim->master != NULL
&& victim->master->in_room == ch->in_room
&& victim->master != ch->fighting
&& number_bits( 3 ) == 0 )
{
stop_fighting( ch, FALSE );
multi_hit( ch, victim->master, TYPE_UNDEFINED );
return FALSE;
}
}
if ( victim->master == ch && set_combat)
stop_follower( victim );
}
//VISIBLE THE CH
if (set_combat || ch->fighting == victim)
do_visible(ch,NULL);
do_visible(victim, "");
/* adjust damage if object passed */
if (obj){
dam = UMAX(0, get_curr_cond( obj ) * dam / 100);
}
/* masochism check */
if (ch != victim && dt >= TYPE_HIT && dam > 0 && set_combat){
CHAR_DATA* och = masochism_effect(ch, dam, dt);
if (och){
victim = ch;
ch = och;
dt = gsn_masochism;
dam /= 2;
if (number_percent() < 10)
act("A bit of drool drips from $n's lips.", victim, NULL, victim, TO_ROOM);
}
}//End masochism check
//PREDAMAGE CHECK
if (PREDAMAGE_CHECK(ch, victim, &dam, &dt, &dam_type) == -1)
bug("Error at: PREDAMAGE_CHECK\n\r", 0);
/* IMPORTANT, MISS can still be blocked, but damage marked as < 0 returned from (terra shield, etc..) should not*/
if (dam < 0)
return 0;
//Do Damage reduction
dam = dam_spell(ch,victim,dam,dam_type);
immune = FALSE;
/* we cheat here abit to allow normal weapon dmage text to be unblockable */
/* if we add TYPE_NOBLOCK onto the "dt" it will not be blocked, and will
be subracted later
*/
if ((dt >= TYPE_HIT
&& dt < TYPE_NOBLOCKHIT
&& dt < 5000
&& (dt < 1065 || dt > 1070)
&& ch != victim)
|| (fVirt && dt >= TYPE_HIT && dt < TYPE_NOBLOCKHIT)){
//Psionist body weaponry.
if (is_affected(ch, gsn_body_weaponry)){
dt = number_range(1028, 1030);
dam_type = attack_table[dt - 1000].damage;
}
//VAMPIRE WOLF.
if (is_affected(victim, gsn_wolf_form)){
if (wolf_evade(ch, victim, dt))
dam = 0;
else if (check_dodge_wolf( ch, victim, obj, dt, h_roll, lvl, fVirt, sn))
return FALSE;
}
//END WOLF DEFENSE.
else{
if (check_defenses(ch, victim, obj, dt, h_roll, lvl, fVirt, sn)){
CHAR_DATA* tmp = NULL;
if (ch == NULL || ch->fighting == NULL)
return FALSE;
if (dam > 0 && victim->class == gcn_blademaster)
tmp = bmDeathweaverCheck(ch, victim);
else if (dam > 0 && doomsingerCheck( ch )){
tmp = victim;
dam /= 8;
}
if (tmp)
victim = tmp;
else
return FALSE;
}
if (ch == NULL || ch->fighting == NULL)
return FALSE;
}//END ELSE FROM WOLF.
if (IS_AFFECTED2(victim,AFF_BLUR)
&& ch != victim
&& !(dam_type == DAM_NONE || dam_type == DAM_INTERNAL)
&& number_percent() < 15 + (get_curr_stat(victim,STAT_LUCK) - 14)){
if (is_affected(victim, gsn_forestmeld)){
if (victim->in_room->sector_type == SECT_FOREST){
act( "$n swings wildly and misses you by a mile.", ch, NULL, victim, TO_VICT );
act( "You swing right through $N's blurred image.", ch, NULL, victim, TO_CHAR );
return FALSE;
}
}
else{
act( "$n swings wildly and misses you by a mile.", ch, NULL, victim, TO_VICT );
act( "You swing right through $N's blurred image.", ch, NULL, victim, TO_CHAR );
return FALSE;
}
}
//Holy Hands
if (is_affected(victim, gen_holy_hands) && get_eq_char(victim, WEAR_WIELD) == NULL)
if (holy_hands_evade(ch, victim, dt))
return FALSE;
}//END DEFESE CHECKS
/* check for TYPE_NOBLOCKHIT */
if (dt >= TYPE_NOBLOCKHIT)
dt -= (TYPE_NOBLOCKHIT- TYPE_HIT);
//MONK DAMAGE
if (dam > 0 && !IS_NPC(ch) && dt >= 1053 && dt <= 1064)
dam = dam_monk(ch,victim,dam,dt);
/* check for torment bind Moloch (location = AFFL_LEVEL) */
if ( (paf = affect_find(ch->affected, gsn_torment_bind)) == NULL
|| paf->location != APPLY_AFFL_LEVEL){
switch(check_immune(victim,dam_type, FALSE))
{
case(IS_IMMUNE): immune = TRUE; dam = 0; break;
case(IS_RESISTANT):
/* high sight/gladiator hth form */
if (dt > TYPE_HIT
&& (number_percent() < get_skill(ch, gsn_high_sight)
|| is_affected(ch, gsn_enhanced_damage))
)
check_improve(ch, gsn_high_sight, TRUE, 1);
else
dam -= dam/3;
break;
case(IS_NORMAL):
/* high sight */
if (dt > TYPE_HIT && number_percent() < get_skill(ch, gsn_high_sight)
&& victim->vuln_flags != 0){
check_improve(ch, gsn_high_sight, TRUE, 1);
dam = 12 * dam / 10;
}
break;
case(IS_VULNERABLE): dam += dam/2; break;
}
}
if (IS_STONED(victim)){
dam = 0;
immune = TRUE;
}
if ( IS_AFFECTED(victim, AFF_SLEEP) )
{
REMOVE_BIT(ch->affected_by,AFF_SLEEP);
affect_strip( ch,gsn_sleep );
affect_strip( ch,gsn_hypnosis );
affect_strip(ch,gsn_coffin);
affect_strip(ch,gsn_entomb);
song_strip(ch,gsn_lullaby);
}
if ( is_affected(victim, gsn_camp)){
send_to_char( "You feel drained from deprivation of sleep.\n\r", victim);
if (!is_affected(victim, gsn_drained)){
AFFECT_DATA af;
af.where = TO_AFFECTS;
af.type = gsn_drained;
af.level = victim->level;
af.duration = 10;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = 0;
affect_to_char(victim ,&af);
affect_strip(victim, gsn_camp);
}
}
if (is_affected(victim, gsn_coffin))
affect_strip(victim, gsn_coffin);
if (is_affected(victim, gsn_burrow))
do_unburrow(victim, "");
if (victim->position >= POS_MEDITATE
&& victim->position <= POS_SITTING){
send_to_char("The pain gets you to your feet.\n\r", victim);
if (!IS_AWAKE(ch)){
victim->position = POS_STANDING;
dreamprobe_cast(ch, NULL );
}
else
victim->position = POS_STANDING;
}
// Ogre ignore check
if (dam_type != DAM_INTERNAL && ogre_ignore(ch,victim, obj, dam, dt, fVirt))
dam = 5;
if (dam_type != DAM_INTERNAL && jugger_ignore(ch,victim, obj, dam, dt, fVirt))
dam = -1;
/* Dont show damage if done to self and sn = -1 */
if (sn != -1 || dam < 0){
/* we show a fake splitting if this is dblow and it might kill */
if (dt == gsn_forms && victim->hit + 20 < dam){
act("$n cleaves $N `1IN HALF``!!", ch, NULL, victim, TO_NOTVICT);
act("You cleave $N `1IN HALF``!!", ch, NULL, victim, TO_CHAR);
act_new( "$n cleaves you `1IN HALF``!!", ch,NULL,victim,TO_VICT,POS_DEAD);
}
else if (dt == gsn_behead && victim->hit + 20 < dam){
act("$n's head flies off as $N cleaves $S neck in twain.",
victim, NULL, ch, TO_ROOM);
act("The last thing you feel is $n's blade bite into your neck.",
ch, NULL, victim, TO_VICT);
act("You have been `1BEHEADED``!!.", ch, NULL, victim, TO_VICT);
act("$N has been `1BEHEADED``!!.", victim, NULL, victim, TO_ROOM);
}
else{
int dam_show = dam;
if (!IS_NPC(victim)){
if (is_affected(victim, gsn_numbness))
dam_show = 2 * dam / 3;
if (is_affected(victim, gsn_nerve_amp))
dam_show = 3 * dam / 2;
}
dam_message( ch, victim, obj, dam_show, dt, immune, fVirt, sn, set_combat );
}
}
//Mist form revert. done here as we want mist to revert after the whole round.
if (is_affected(victim, gsn_mist_form))
do_revert(victim, NULL);
//Return if immune and such.
if (dam <= 0)
return FALSE;
//Loose hp
victim->hit -= dam;
if (ch == NULL || victim == NULL)
return FALSE;
if (tarot_find(victim->affected) == 12 && tarot_find(ch->affected) != 12 && ch != victim && number_percent() > 50)
damage(ch,ch,dam,dt,dam_type, set_combat);
//Check for ecstacy
if (is_affected(victim,gsn_ecstacy))
{
send_to_char("You snap back into reality.\n\r",victim);
affect_strip(victim,gsn_ecstacy);
}
//Immortal HP check (MASTERS CAN DIE TO MOBS AND MASTERS)
if ( victim->hit < 1
&& !IS_NPC(victim)
&& victim->level >= LEVEL_IMMORTAL){
if ((!IS_NPC(ch) && ch != victim && ch->level < MASTER) || victim->level > MASTER)
victim->hit = 1;
}
//Illithid HP drain save.
else if (victim->hit < 1 && !IS_NPC(victim) && victim->race == race_lookup("illithid") && !is_affected(victim,gsn_drained))
{
AFFECT_DATA iaf;
iaf.where = TO_AFFECTS;
iaf.type = gsn_drained;
iaf.level = victim->level;
iaf.duration = 12;
iaf.modifier = 0;
iaf.location = 0;
iaf.bitvector = 0;
affect_to_char(victim,&iaf);
act("You enter a state of shock, and you redirect your energy to sustain your body.",victim,NULL,NULL,TO_CHAR);
act("$n enters a state of shock, and redirects $s energy to sustain $s body.",victim,NULL,NULL,TO_ROOM);
victim->hit = victim->mana/3;
victim->mana = 0;
}
//Tarto save
else if (victim->hit < 1 && !IS_NPC(victim) && tarot_find(victim->affected) == 21)
{
affect_strip(victim,gsn_tarot);
victim->hit = 1;
send_to_char("You were meant to die but somehow you cheat death!\n\r",victim);
act("$n was supposed to die but somehow cheats death!",victim,NULL,NULL,TO_ROOM);
stop_fighting( victim, TRUE );
return dam;
}
else if (IS_NPC(victim) && victim->hit < 1 && victim->pIndexData->vnum == MOB_VNUM_SERPENT_U3 && victim->level >= 50)
{
victim->hit = victim->max_hit / 2;
send_to_char("You were meant to die but somehow you cheat death!\n\r",victim);
act("$n was supposed to die but somehow cheats death!",victim,NULL,NULL,TO_ROOM);
stop_fighting( victim, TRUE );
victim->level --;
return dam;
}
//Vicarious redemption
else if (victim->hit < 2 && !IS_NPC(victim) && is_affected(victim,gsn_vredem)){
ROOM_INDEX_DATA *location;
location = get_room_index(get_temple(victim));
if (location != NULL && !is_affected(victim,gsn_damnation)
&& !IS_SET(victim->act,PLR_OUTCAST)){
act("A nearby peasant says '`#Quick! Devout father $n is in trouble!``'.",
victim, NULL,NULL,TO_ALL);
act("As your vision fades you feel yourself being dragged away.",
victim,NULL,NULL,TO_CHAR);
act("A swarm of The One God's followers snatches $n's body and carries it away.",
victim,NULL,victim,TO_ROOM);
victim->hit = victim->mana/3;
victim->mana = 0;
if (victim->fighting != NULL){
if ( IS_NPC(victim->fighting)
&& !IS_SET(victim->fighting->act2, ACT_LAWFUL)
&& !IS_SET(victim->fighting->act, ACT_RAIDER)
&& !IS_SET(victim->fighting->off_flags,CABAL_GUARD)){
if (!IS_NPC(victim))
victim->fighting->hunting = victim;
else if (victim->master != NULL)
victim->fighting->hunting = victim->master;
else
victim->fighting->hunting = victim;
victim->fighting->hunttime = 0;
}
stop_fighting(victim,TRUE);
}//end if fighting
victim->move /= 2;
if (!IS_NPC(victim) && victim->pcdata->pStallion != NULL ){
victim->pcdata->pStallion = NULL;
}
char_from_room(victim);
char_to_room(victim,location);
mercy_effect(ch, victim, 1);
act("A swarm of The One God's followers drags $n's body into the room.", victim,NULL,victim,TO_ROOM);
act("A nearby peasant says '`#We did what we could kids, lets go.``'.", victim, NULL,NULL,TO_ALL);
affect_strip(victim, gsn_vredem);
act_new(skill_table[gsn_vredem].msg_off,ch,NULL,NULL,TO_CHAR,POS_DEAD);
}
}
else if (victim->hit < 2
&& !IS_NPC(victim)
&& number_percent() < get_skill(victim, gsn_adrenaline_rush) / 3
&& !is_affected(victim, gsn_drained)){
AFFECT_DATA iaf;
send_to_char("A potent rush of adrenaline floods your veins!\n\r", ch);
act("$n's eyes bulge out in their sockets as a rush of adrenaline revives $m!", victim, NULL, NULL, TO_ROOM);
iaf.where = TO_AFFECTS;
iaf.type = gsn_drained;
iaf.level = victim->level;
iaf.duration = 12;
iaf.modifier = 0;
iaf.location = 0;
iaf.bitvector = 0;
affect_to_char(victim,&iaf);
victim->hit = victim->max_hit / 4;
victim->mana = 0;
}
else
victim = knight_rescue(ch, victim, dam, dt);
//Update state
dam_update(ch,victim, dam);
/* Viri: dam_dead should do this
//Stop combat if knocked out etc.
if ( !IS_AWAKE(victim))
stop_fighting( victim, FALSE );
*/
//Check if we kill him.
if ( victim->position == POS_DEAD )
{
dam_dead(ch,victim);
return dam;
}
//POSTEDAMAGE CHECK
if (POSTDAMAGE_CHECK(ch, victim, obj, dam, dt, dam_type) == -1)
bug("Error at: POSTDAMAGE_CHECK\n\r", 0);
if ( victim == ch )
return dam;
//Wimpy etc.
dam_after(ch,victim,dam);
tail_chain( );
return dam;
}//END VIRTUAL DAMAGE
int damage(CHAR_DATA *ch,CHAR_DATA *victim,int dam,int dt,int dam_type, bool show)
{
/* we do a bit of screwing around here, since the "show" flag enedup being used elsewhere,
so, we use last argument (sn) when the int damage show is false, and victim = null, we make ch = vitim
and the sn = -1 which skips all damage messages. (used in mobprogs) All this mess needs to eb fixed
when we rewrite fight.c */
if (!victim && !show)
return virtual_damage(ch, ch, NULL, dam, dt, dam_type, GET_HITROLL(ch), ch->level, show, FALSE, -1) ;
else
return virtual_damage(ch, victim, NULL, dam, dt, dam_type, GET_HITROLL(ch), ch->level, show, FALSE, 0) ;
}
/* used in is_safe checks */
inline bool check_mercy_safe( CHAR_DATA* ch, CHAR_DATA* victim, bool fSilent){
if (ch->in_room
&& IS_ROOM2(ch->in_room, ROOM_MERCY)
&& is_affected(victim, gsn_mortally_wounded)){
if (!fSilent)
send_to_char("They are already mortally wounded!\n\r", ch);
return TRUE;
}
else if (IS_GAME(ch, GAME_MERCY)
&& is_affected(victim, gsn_mortally_wounded)){
if (!fSilent)
send_to_char("They are already mortally wounded!\n\r", ch);
return TRUE;
}
else
return FALSE;
}
bool is_area_safe_quiet(CHAR_DATA *ch, CHAR_DATA *victim)
{
if (victim->in_room == NULL || ch->in_room == NULL)
return TRUE;
else if (victim == ch )
return TRUE;
else if (victim->fighting == ch)
return FALSE;
else if (IS_NPC(ch) && IS_GOOD(ch) && IS_GOOD(victim))
return TRUE;
else if (IS_NPC(victim) && IS_SET(victim->act, ACT_NONCOMBAT)){
return TRUE;
}
/* Area attacks from mobs only affect those whom the mob is fighting */
else if (IS_NPC(ch) && ch->fighting && !is_same_group(ch->fighting, victim))
return TRUE;
else if (IS_IMMORTAL(victim) && victim->invis_level > 2)
return TRUE;
else if (!IS_NPC(ch) && !IS_NPC(victim) && !IS_IMMORTAL(ch) && IS_IMMORTAL(victim))
return TRUE;
else if ( !IS_NPC(victim) && !is_fight_delay(victim,120) && victim->desc == NULL && !is_affected(ch,gsn_linked_mind))
return TRUE;
else if (is_ghost(victim,600) && !IS_SET(ch->off_flags, GUILD_GUARD) && !IS_SET(ch->off_flags, CABAL_GUARD))
return TRUE;
else if ( !IS_NPC(ch) && !IS_NPC(victim) && is_challenger(ch, victim) && challenge_safe(ch, victim))
return TRUE;
if ( IS_AFFECTED2(ch, AFF_HOLD) )
return TRUE;
/* killing mobiles */
if (IS_NPC(victim))
{
if (IS_SET(victim->in_room->room_flags,ROOM_SAFE))
return TRUE;
if ( IS_SET(victim->act,ACT_PET) && victim->master == ch)
return TRUE;
if (victim->pIndexData->vnum == MOB_VNUM_SHADOW && ch != victim->hunting)
return TRUE;
if (victim->pIndexData->vnum == MOB_VNUM_NEMESIS && ch != victim->hunting)
return TRUE;
if ( victim->summoner == ch)
return TRUE;
if ( victim->master != NULL && !is_pk(ch,victim->master) )
return TRUE;
if (is_same_group(ch,victim))
return TRUE;
}
/* killing players */
else
{
AFFECT_DATA* paf;
if (IS_SET(victim->in_room->room_flags,ROOM_SAFE))
return TRUE;
if (check_mercy_safe(ch, victim, TRUE))
return TRUE;
if (IS_NPC(ch) && ch->master != NULL && !IS_NPC(ch->master) && !is_pk(ch->master,victim))
return TRUE;
if (IS_NPC(ch))
return FALSE;
if (is_same_group(ch,victim))
return TRUE;
if (!is_pk(ch,victim))
return TRUE;
else if ( (paf = affect_find(victim->affected, gen_diplomacy)) != NULL && paf->modifier == TRUE)
return TRUE;
}
if (!IS_NPC(ch))
ch->pcdata->ghost = (time_t)NULL;
return FALSE;
}
bool is_safe_quiet_all(CHAR_DATA *ch, CHAR_DATA *victim)
{
if (victim->in_room == NULL || ch->in_room == NULL)
return TRUE;
else if (victim == ch )
return TRUE;
else if (victim->fighting == ch)
return FALSE;
else if (IS_NPC(ch) && IS_GOOD(ch) && IS_GOOD(victim))
return TRUE;
else if (IS_NPC(victim) && IS_SET(victim->act, ACT_NONCOMBAT)){
return TRUE;
}
else if (IS_IMMORTAL(victim) && victim->invis_level > 2)
return TRUE;
else if (IS_IMMORTAL(ch) && IS_IMMORTAL(victim) && victim->level > LEVEL_IMMORTAL && !is_same_group(ch,victim))
return FALSE;
else if ( !IS_NPC(victim) && !is_fight_delay(victim,120) && victim->desc == NULL && !is_affected(ch,gsn_linked_mind))
return TRUE;
else if (is_ghost(victim,600) && !IS_SET(ch->off_flags, GUILD_GUARD) && !IS_SET(ch->off_flags, CABAL_GUARD))
return TRUE;
else if ( !IS_NPC(ch) && !IS_NPC(victim) && is_challenger(ch, victim)
&& challenge_safe(ch, victim))
return TRUE;
else if ( IS_AFFECTED2(ch, AFF_HOLD) )
return TRUE;
/* killing mobiles */
if (IS_NPC(victim))
{
if (IS_SET(victim->in_room->room_flags,ROOM_SAFE))
return TRUE;
if ( IS_SET(victim->act,ACT_PET) && victim->master == ch)
return TRUE;
if (victim->pIndexData->vnum == MOB_VNUM_SHADOW && ch != victim->hunting)
return TRUE;
if (victim->pIndexData->vnum == MOB_VNUM_NEMESIS && ch != victim->hunting)
return TRUE;
if ( victim->summoner == ch)
return TRUE;
if ( victim->master != NULL && !is_pk(ch,victim->master) )
return TRUE;
if (is_same_group(ch,victim))
return TRUE;
}
/* killing players */
else
{
AFFECT_DATA* paf;
if (IS_SET(victim->in_room->room_flags,ROOM_SAFE))
return TRUE;
if (check_mercy_safe(ch, victim, TRUE))
return TRUE;
if (IS_NPC(ch) && ch->master != NULL && !IS_NPC(ch->master) && !is_pk(ch->master,victim))
return TRUE;
if (IS_NPC(ch))
return FALSE;
if (!is_pk(ch,victim))
return TRUE;
else if ( (paf = affect_find(victim->affected, gen_diplomacy)) != NULL && paf->modifier == TRUE)
return TRUE;
}
if (!IS_NPC(ch))
ch->pcdata->ghost = (time_t)NULL;
return FALSE;
}
bool is_area_safe(CHAR_DATA *ch, CHAR_DATA *victim)
{
if (victim->in_room == NULL || ch->in_room == NULL)
return TRUE;
else if (victim == ch )
return TRUE;
else if (victim->fighting == ch)
return FALSE;
else if (IS_NPC(ch) && IS_GOOD(ch) && IS_GOOD(victim))
return TRUE;
else if (IS_NPC(victim) && IS_SET(victim->act, ACT_NONCOMBAT)){
sendf(ch, "%s cannot be attacked this way.\n\r", PERS(victim, ch ));
return TRUE;
}
/* Area attacks from mobs only affect those whom the mob is fighting */
else if (IS_NPC(ch) && ch->fighting && !is_same_group(ch->fighting, victim))
return TRUE;
else if (IS_IMMORTAL(victim) && victim->invis_level > 2)
return TRUE;
else if (IS_IMMORTAL(ch) && IS_IMMORTAL(victim) && victim->level > LEVEL_IMMORTAL && !is_same_group(ch,victim))
return FALSE;
else if (IS_IMMORTAL(ch) && victim->level < ch->level && !is_same_group(ch,victim))
return FALSE;
else if (!IS_NPC(ch) && !IS_NPC(victim) && !IS_IMMORTAL(ch) && IS_IMMORTAL(victim))
{
send_to_char("Do you honestly think you can kill a god?\n\r",ch);
return TRUE;
}
else if ( !IS_NPC(victim) && !is_fight_delay(victim,120) && victim->desc == NULL && !is_affected(ch,gsn_linked_mind))
{
sendf(ch, "%s is lost.\n\r", PERS(victim,ch));
return TRUE;
}
else if (is_ghost(victim,600) && !IS_SET(ch->off_flags, GUILD_GUARD) && !IS_SET(ch->off_flags, CABAL_GUARD))
{
send_to_char("You can't kill a ghost!\n\r",ch);
return TRUE;
}
else if ( !IS_NPC(ch) && !IS_NPC(victim) && is_challenger(ch, victim)
&& challenge_safe(ch, victim)){
sendf(ch, "You can't attack %s yet.\n\r",PERS(victim,ch));
return TRUE;
}
else if ( IS_AFFECTED2(ch, AFF_HOLD) )
{
send_to_char("You are barred from your agressive nature.\n\r",ch);
return TRUE;
}
/* killing mobiles */
else if (IS_NPC(victim))
{
if (IS_SET(victim->in_room->room_flags,ROOM_SAFE))
{
send_to_char("Not in this room.\n\r",ch);
return TRUE;
}
if ( IS_SET(victim->act,ACT_PET) && victim->master == ch)
{
sendf(ch, "But %s looks so cute and cuddly...\n\r",PERS(victim,ch));
return TRUE;
}
if (victim->pIndexData->vnum == MOB_VNUM_SHADOW && ch != victim->hunting)
{
send_to_char("You can't attack that, it's just a shadow.\n\r",ch);
return TRUE;
}
if (victim->pIndexData->vnum == MOB_VNUM_NEMESIS && ch != victim->hunting)
{
send_to_char("You can't seem to harm it.\n\r",ch);
return TRUE;
}
if ( victim->summoner == ch)
{
send_to_char("Why would you turn on your own creation?\n\r",ch);
return TRUE;
}
if ( victim->master != NULL && !is_pk(ch,victim->master) )
{
sendf(ch,"The gods protect %s.\n\r",PERS(victim,ch));
return TRUE;
}
if (is_same_group(ch,victim))
return TRUE;
}
/* killing players */
else
{
AFFECT_DATA* paf;
if (IS_SET(victim->in_room->room_flags,ROOM_SAFE))
{
send_to_char("Not in this room.\n\r",ch);
return TRUE;
}
if (check_mercy_safe(ch, victim, FALSE))
return TRUE;
if (IS_NPC(ch) && ch->master != NULL && !IS_NPC(ch->master) && !is_pk(ch->master,victim))
return TRUE;
if (IS_NPC(ch))
return FALSE;
if (is_same_group(ch,victim))
return TRUE;
if (!is_pk(ch,victim))
{
act("The gods protect $N from $n.",ch,NULL,victim, TO_ALL);
return TRUE;
}
else if ( (paf = affect_find(victim->affected, gen_diplomacy)) != NULL && paf->modifier == TRUE){
act("$n's royal entourage protects $m from $N.", victim, NULL, ch, TO_NOTVICT);
act("$n's royal entourage protects you from $N.", victim, NULL, ch, TO_CHAR);
act("$n's royal entourage protects $m from you.", victim, NULL, ch, TO_VICT);
return TRUE;
}
}
if (!IS_NPC(ch))
ch->pcdata->ghost = (time_t)NULL;
return FALSE;
}
bool is_safe(CHAR_DATA *ch, CHAR_DATA *victim)
{
if (victim->in_room == NULL || ch->in_room == NULL)
return TRUE;
else if (victim == ch )
return TRUE;
else if (victim->fighting == ch)
return FALSE;
else if (IS_NPC(victim) && IS_SET(victim->act, ACT_NONCOMBAT)){
sendf(ch, "%s cannot be attacked this way.\n\r", PERS(victim, ch ));
return TRUE;
}
else if (!IS_NPC(ch) && IS_IMMORTAL(ch) && victim->level < ch->level )
return FALSE;
else if (IS_NPC(ch) && IS_GOOD(ch) && IS_GOOD(victim))
return TRUE;
else if (!IS_NPC(ch) && !IS_NPC(victim) && !IS_IMMORTAL(ch) && IS_IMMORTAL(victim))
{
if (can_see(ch,victim))
send_to_char("Do you honestly think you can kill a god?\n\r",ch);
return TRUE;
}
if ( !IS_NPC(victim)
&& !is_fight_delay(victim,80)
&& victim->desc == NULL
&& !is_affected(victim,gsn_linked_mind)
&& !(!IS_NPC(victim)
&& (IS_SET(victim->act2,PLR_NOQUIT)
|| is_affected(victim,gsn_noquit)
|| is_affected(victim,gen_ensnare))))
{
sendf(ch,"%s is lost.\n\r",PERS(victim,ch));
return TRUE;
}
if (is_ghost(victim,600) && !IS_SET(ch->off_flags, GUILD_GUARD) && !IS_SET(ch->off_flags, CABAL_GUARD))
{
send_to_char("You can't kill a ghost!\n\r",ch);
return TRUE;
}
if ( !IS_NPC(ch) && !IS_NPC(victim) && challenge_safe(ch,victim) && is_challenger(ch,victim))
{
sendf(ch,"You can't attack %s yet.\n\r",PERS(victim,ch));
return TRUE;
}
if ( IS_AFFECTED2(victim,AFF_SHADOWFORM) )
{
sendf(ch,"Your attacks seem to pass right through %s.\n\r",PERS(victim,ch));
return TRUE;
}
if ( IS_AFFECTED2(victim,AFF_TREEFORM) )
{
sendf(ch,"You cannot seem to move to attack %s.\n\r",PERS(victim,ch));
return TRUE;
}
if ( IS_AFFECTED2(ch, AFF_HOLD) )
{
send_to_char("You are barred from your agressive nature.\n\r",ch);
return TRUE;
}
/* killing mobiles */
if (IS_NPC(victim))
{
if (IS_SET(victim->in_room->room_flags,ROOM_SAFE))
{
send_to_char("Not in this room.\n\r",ch);
return TRUE;
}
if (victim->pIndexData->vnum == MOB_VNUM_SHADOW && ch != victim->hunting)
{
send_to_char("You can't attack that, it's just a shadow.\n\r",ch);
return TRUE;
}
if (victim->pIndexData->vnum == MOB_VNUM_NEMESIS && ch != victim->hunting)
{
send_to_char("You can't seem to harm it.\n\r",ch);
return TRUE;
}
if ( victim->summoner == ch)
{
send_to_char("Why would you turn on your own creation?\n\r",ch);
return TRUE;
}
/* wanted people can attack special guards */
if ( victim->master != NULL )
{
if ( (victim->pIndexData->vnum == MOB_VNUM_SPECIAL_GUARD || victim->pIndexData->vnum == MOB_VNUM_HOUND)
&& ((!IS_NPC(ch) && IS_SET(ch->act,PLR_WANTED))
|| (IS_NPC(ch) && ch->master != NULL && IS_SET(ch->master->act,PLR_WANTED))))
return FALSE;
if ((!IS_NPC(ch) && !is_pk(ch,victim->master)) || (IS_NPC(ch) && ch->master != NULL && !is_pk(ch->master,victim->master)))
{
sendf(ch,"The gods protect %s.\n\r",PERS(victim,ch));
return TRUE;
}
}
}
/* killing players */
else
{
AFFECT_DATA* paf;
if (IS_SET(victim->in_room->room_flags,ROOM_SAFE))
{
send_to_char("Not in this room.\n\r",ch);
return TRUE;
}
if (check_mercy_safe(ch, victim, FALSE))
return TRUE;
if (IS_NPC(ch) && ch->master != NULL && !IS_NPC(ch->master) && !is_pk(ch->master,victim))
return TRUE;
if (IS_NPC(ch))
return FALSE;
if (!is_pk(ch,victim))
{
act("The gods protect $N from $n.",ch,NULL,victim, TO_ALL);
return TRUE;
}
else if ( (paf = affect_find(victim->affected, gen_diplomacy)) != NULL && paf->modifier == TRUE){
act("$n's royal entourage protects $m from $N.", victim, NULL, ch, TO_NOTVICT);
act("$n's royal entourage protects you from $N.", victim, NULL, ch, TO_CHAR);
act("$n's royal entourage protects $m from you.", victim, NULL, ch, TO_VICT);
return TRUE;
}
}
if (!IS_NPC(ch))
ch->pcdata->ghost = (time_t)NULL;
return FALSE;
}
bool is_safe_quiet(CHAR_DATA *ch, CHAR_DATA *victim)
{
if (victim->in_room == NULL || ch->in_room == NULL)
return TRUE;
else if (victim == ch )
return TRUE;
else if (victim->fighting == ch)
return FALSE;
else if (IS_NPC(victim) && IS_SET(victim->act, ACT_NONCOMBAT)){
return TRUE;
}
else if (!IS_NPC(ch) && IS_IMMORTAL(ch) && victim->level < ch->level )
return FALSE;
else if (IS_NPC(ch) && IS_GOOD(ch) && IS_GOOD(victim))
return TRUE;
if ( !IS_NPC(victim) && !is_fight_delay(victim,80) && victim->desc == NULL && !is_affected(victim,gsn_linked_mind) && !(!IS_NPC(victim) && (IS_SET(victim->act2,PLR_NOQUIT)
|| is_affected(victim,gsn_noquit) || is_affected(victim,gen_ensnare))))
return TRUE;
if (is_ghost(victim,600) && !IS_SET(ch->off_flags, GUILD_GUARD) && !IS_SET(ch->off_flags, CABAL_GUARD))
return TRUE;
if ( !IS_NPC(ch) && !IS_NPC(victim) && challenge_safe(ch,victim) && is_challenger(ch,victim))
return TRUE;
if ( IS_AFFECTED2(victim,AFF_SHADOWFORM) )
return TRUE;
if ( IS_AFFECTED(victim,AFF_TREEFORM) )
return TRUE;
if ( IS_AFFECTED2(ch, AFF_HOLD) )
return TRUE;
/* killing mobiles */
if (IS_NPC(victim))
{
if (IS_SET(victim->in_room->room_flags,ROOM_SAFE))
return TRUE;
if (IS_NPC(victim) && IS_SET(victim->act, ACT_NONCOMBAT)){
return TRUE;
}
if (victim->pIndexData->vnum == MOB_VNUM_SHADOW && ch != victim->hunting)
return TRUE;
if (victim->pIndexData->vnum == MOB_VNUM_NEMESIS && ch != victim->hunting)
return TRUE;
if ( victim->summoner == ch)
return TRUE;
if ( victim->master != NULL && victim->in_room == victim->master->in_room)
{
/* wanted people can attack the guard */
if ( (victim->pIndexData->vnum == MOB_VNUM_SPECIAL_GUARD || victim->pIndexData->vnum == MOB_VNUM_HOUND)
&& ((!IS_NPC(ch) && IS_SET(ch->act,PLR_WANTED))
|| (IS_NPC(ch) && ch->master != NULL && IS_SET(ch->master->act,PLR_WANTED))))
return FALSE;
if ((!IS_NPC(ch) && !is_pk(ch,victim->master)) || (IS_NPC(ch) && ch->master != NULL && !is_pk(ch->master,victim->master)))
return TRUE;
}
}
/* killing players */
else
{
AFFECT_DATA* paf;
if (IS_SET(victim->in_room->room_flags,ROOM_SAFE))
return TRUE;
if (check_mercy_safe(ch, victim, FALSE))
return TRUE;
if (IS_NPC(ch) && ch->master != NULL && !IS_NPC(ch->master) && !is_pk(ch->master,victim))
return TRUE;
if (IS_NPC(ch))
return FALSE;
if (!is_pk(ch,victim))
return TRUE;
else if ( (paf = affect_find(victim->affected, gen_diplomacy)) != NULL && paf->modifier == TRUE){
return TRUE;
}
}
if (!IS_NPC(ch))
ch->pcdata->ghost = (time_t)NULL;
return FALSE;
}
int get_dchance( int ini_skill, int cur_skill, int hitroll ){
if (cur_skill <= ini_skill / 2)
return cur_skill;
else
return ( UMAX(ini_skill / 2, cur_skill - hitroll));
}
bool check_parry_monk( CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA* vir_obj, int dt, int h_roll, int level, bool Second, bool fVirt, int sn)
{
AFFECT_DATA* paf;
OBJ_DATA *obj;
OBJ_DATA* obj2 = (vir_obj != NULL? vir_obj : NULL);
int items = 0, chance, ch_weapon, vict_weapon, ch_vict_weapon, v_wtype, c_wtype = 0;
int temp, ini_chance;
char buf1[MSL], buf2[MSL], buf3[MSL], buf4[MSL];
//easy hits.
if ( !IS_AWAKE(victim) || is_affected(victim,gsn_ecstacy))
return FALSE;
if (victim->class != class_lookup("monk"))
return FALSE;
//get which parry is possible.
if (get_eq_char( victim, WEAR_WIELD ) != NULL )
return FALSE;
if (get_eq_char( victim, WEAR_SHIELD ) != NULL )
items++;
obj = get_eq_char( victim, WEAR_HOLD);
if ( obj != NULL && obj->pIndexData->vnum != OBJ_VNUM_PRAYER_BEADS)
items++;
if (Second)
{
if (items > 0
|| !is_empowered_quiet(victim,1)
|| ((paf = affect_find(victim->affected, gsn_wlock)) && paf->modifier != 0)
|| (chance = get_skill(victim,gsn_second_parry) / 3) == 0)
return FALSE;
}
else
{
if (items > 1 || (chance = get_skill(victim,gsn_first_parry) / 2) == 0)
return FALSE;
}
ini_chance = chance;
//bonus/penalty for blind.
//we only check if character can see if this is not virtual attack.
if (!can_see(ch,victim) && !fVirt)
{
if (!IS_NPC(ch) && number_percent() < get_skill(ch,gsn_blind_fighting)){
if (!is_affected(ch, gsn_battletrance))
chance *= 1.1;
}
else
chance *= 1.3;
}
if (!can_see(victim,ch))
{
if (!IS_NPC(victim) && number_percent() < get_skill(victim,gsn_blind_fighting)){
if (!is_affected(victim, gsn_battletrance))
chance /= 1.1;
}
else
chance /= 1.3;
}
/* crusade effects */
if ( (temp = check_crusade(ch, victim)) != CRUSADE_NONE){
/* if attacker is on crusade against victim */
if (temp == CRUSADE_MATCH)
chance /= 1.3;
/* if attacker is on crusade but not agaisnt victim */
else if (temp == CRUSADE_NOTMATCH)
chance *= 1.1;
}
if ( (temp = check_crusade(victim, ch)) != CRUSADE_NONE){
/* if victim is on crusade against attacker */
if (temp == CRUSADE_MATCH)
chance *= 1.3;
/* if victim is on crusade but not against attacker */
else if (temp == CRUSADE_NOTMATCH)
chance /= 1.1;
}
/* end crusade bonuses */
/* check weapon position */
if (!IS_NPC(ch)){
/* harder to block for victim if attacker is high */
if (ch->pcdata->wep_pos == WEPPOS_HIGH)
chance -= 10;
/* easier to block for victim if attacker is low */
else if (ch->pcdata->wep_pos == WEPPOS_LOW)
chance += 5;
}
if (!IS_NPC(victim)){
/* harder to block for victim if victim is high */
if (victim->pcdata->wep_pos == WEPPOS_HIGH)
chance -= 5;
/* easier to block for victim if victim is low */
else if (victim->pcdata->wep_pos == WEPPOS_LOW)
chance += 10;
}
//we use the held item if this is not virtual attack.
if (!fVirt)
obj2 = get_eq_char(ch,WEAR_WIELD);
//weapons skills.
if (!IS_NPC(ch))
{
ch_weapon = (fVirt? get_skill(ch, sn) : get_weapon_skill_obj(ch,obj2));
ch_vict_weapon = (fVirt? 2 * victim->level : get_weapon_skill_obj(victim, obj2));
}
else
{
ch_weapon = 100;
ch_vict_weapon = (fVirt? 2 * victim->level : get_weapon_skill_obj(victim,obj2));
}
vict_weapon = get_weapon_skill_obj(victim, obj);
//DEFENDER'S WEAPON
v_wtype = get_weapon_obj_rating( NULL, WEAPON_DEF );
//ATTACKER'S WEAPON
if (fVirt){
if (dt == gen_blades || dt == gen_dan_blade)
c_wtype = URANGE(-2, (ch_weapon - 80) / 5, 5);
else
c_wtype = 0;
}
else if ( ch->class == gcn_psi
&& (paf = affect_find( ch->affected, gsn_false_weapon)) != NULL)
c_wtype = get_weapon_rating( paf->modifier, WEAPON_ATT );
else
c_wtype = get_weapon_obj_rating( obj2, WEAPON_ATT );
//Calcualte chance
chance = chance * vict_weapon / 100;
if (Second)
chance += (v_wtype - c_wtype) * 4;
else
chance += (v_wtype - c_wtype) * 3;
chance += (ch_vict_weapon - ch_weapon) / 5;
chance += get_curr_stat(victim,STAT_DEX) - get_curr_stat(ch,STAT_DEX);
chance += get_curr_stat(victim,STAT_STR) - get_curr_stat(ch,STAT_STR);
chance += get_curr_stat(victim,STAT_LUCK) - get_curr_stat(ch,STAT_LUCK);
if (!IS_NPC(ch)){
chance = get_dchance(ini_chance, chance, (h_roll - victim->level/5)/3);
}
else
chance -= h_roll/4;
if (!IS_NPC(ch) && ch->pcdata->pStallion != NULL && number_percent() < get_skill(ch, gsn_mounted)){
chance -= 3;
check_improve(ch, gsn_mounted, TRUE, 1);
}
if (IS_NPC(ch) && IS_SET(ch->off_flags, CABAL_GUARD))
chance -= 10;
else
chance += victim->level - level;
if (!IS_NPC(victim) && IS_SET(victim->act2,PLR_GIMP))
chance /= 2;
//Check for success
if ( number_percent( ) >= chance)
return FALSE;
//show text
if (Second)
sprintf(buf3, "second");
else
sprintf(buf3, "first");
if (fVirt)
{
/* We select two types of origin of the virual attack.
1) obj
2) spell
*/
sprintf(buf1, "You parry a %s's %s with your %s hand.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt), buf3);
sprintf(buf2, "$N parries %s's %s with $S %s hand.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt), buf3);
sprintf(buf4, "$N parries a %s's %s with $S %s hand.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt), buf3);
}
else
{
sprintf(buf1, "You parry $n's attack with your %s hand.", buf3);
sprintf(buf2, "$N parries your attack with $S %s hand.", buf3);
sprintf(buf4, "$N parries $n's attack with $S %s hand.", buf3);
}
if (!doomsingerCheck(ch)){
act( buf1, ch, vir_obj, victim, TO_VICT );
act( buf2, ch, vir_obj, victim, TO_CHAR );
act( buf4, ch, vir_obj, victim, TO_WATCHROOM);
}
if (Second){
check_improve(victim,gsn_second_parry,TRUE, 0);
if (ch && victim && ch->fighting == victim
&& check_ccombat_actions( victim, ch, CCOMBAT_DPARRY))
return TRUE;
}
else
check_improve(victim,gsn_first_parry,TRUE, 0);
return TRUE;
}
bool check_parry( CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA* vir_obj, int dt, int h_roll, int level, bool fVirt, int sn)
{
OBJ_DATA *obj = NULL;
OBJ_DATA* obj2 = (vir_obj!= NULL? vir_obj : NULL);
int chance, ini_chance, ch_weapon, vict_weapon, ch_vict_weapon, c_wtype = 0, v_wtype = 0;
int temp = 0;
char buf1[MSL], buf2[MSL], buf3[MSL];
AFFECT_DATA* paf;
bool fIll = FALSE;
//easy hits.
if ( !IS_AWAKE(victim) || is_affected(victim,gsn_ecstacy))
return FALSE;
//skill check
if ((chance = get_skill(victim,gsn_parry) / 2) == 0)
return FALSE;
if ( (obj = getBmWep( victim, TRUE ) ) == NULL ){
fIll = victim->race == grn_illithid;
if (IS_NPC(victim))
chance /= 2;
else if ( !fIll
&& !is_affected(victim, gsn_body_weaponry) )
return FALSE;
}
ini_chance = chance;
/* weapon raked away */
if ( ( paf = affect_find(ch->affected,gsn_rake)) != NULL
&& paf->modifier == 1)
return FALSE;
//bonus/penalty for blind.
//we only check if character can see if this is not virtual attack.
if (!can_see(ch,victim) && !fVirt)
{
if (!IS_NPC(ch) && number_percent() < get_skill(ch,gsn_blind_fighting)){
if (!is_affected(ch, gsn_battletrance))
chance *= 1.1;
}
else
chance *= 1.3;
}
if (!can_see(victim,ch))
{
if (!IS_NPC(victim) && number_percent() < get_skill(victim,gsn_blind_fighting)){
if (!is_affected(victim, gsn_battletrance))
chance /= 1.1;
}
else
chance /= 1.3;
}
/* crusade effects */
if ( (temp = check_crusade(ch, victim)) != CRUSADE_NONE){
/* if attacker is on crusade against victim */
if (temp == CRUSADE_MATCH)
chance /= 1.3;
/* if attacker is on crusade but not agaisnt victim */
else if (temp == CRUSADE_NOTMATCH)
chance *= 1.1;
}
if ( (temp = check_crusade(victim, ch)) != CRUSADE_NONE){
/* if victim is on crusade against attacker */
if (temp == CRUSADE_MATCH)
chance *= 1.3;
/* if victim is on crusade but not against attacker */
else if (temp == CRUSADE_NOTMATCH)
chance /= 1.1;
}
/* end crusade bonuses */
/* check weapon position */
if (!IS_NPC(ch)){
/* harder to block for victim if attacker is high */
if (ch->pcdata->wep_pos == WEPPOS_HIGH)
chance -= 10;
/* easier to block for victim if attacker is low */
else if (ch->pcdata->wep_pos == WEPPOS_LOW)
chance += 5;
}
if (!IS_NPC(victim)){
/* harder to block for victim if victim is high */
if (victim->pcdata->wep_pos == WEPPOS_HIGH)
chance -= 5;
/* easier to block for victim if victim is low */
else if (victim->pcdata->wep_pos == WEPPOS_LOW)
chance += 10;
}
//we use the held item if this is not virtual attack.
if (!fVirt)
obj2 = getBmWep(ch,TRUE);
//weapons skills.
if (!IS_NPC(ch))
{
ch_weapon = (fVirt? get_skill(ch, sn) : get_weapon_skill_obj(ch,obj2));
ch_vict_weapon = (fVirt? 2 * victim->level : get_weapon_skill_obj(victim,obj2));
}
else
{
ch_weapon = 100;
ch_vict_weapon = (fVirt? 2 * victim->level : get_weapon_skill_obj(victim,obj2));
}
vict_weapon = get_weapon_skill_obj(victim, obj);
//DEFENDER'S WEAPON MODIFIER
v_wtype = get_weapon_obj_rating( obj, WEAPON_DEF );
//ATTACKER'S WEAPON MODIFIER
if (fVirt){
if (dt == gen_blades || dt == gen_dan_blade)
c_wtype = URANGE(-2, (ch_weapon - 80) / 5, 5);
else
c_wtype = 0;
}
else if ( ch->class == gcn_psi
&& (paf = affect_find( ch->affected, gsn_false_weapon)) != NULL)
c_wtype = get_weapon_rating( paf->modifier, WEAPON_ATT );
else
c_wtype = get_weapon_obj_rating( obj2, WEAPON_ATT );
chance = chance * vict_weapon / 100;
chance += (v_wtype - c_wtype) * 3;
chance += (ch_vict_weapon - ch_weapon) / 5;
chance += get_curr_stat(victim,STAT_DEX) - get_curr_stat(ch,STAT_DEX);
chance += get_curr_stat(victim,STAT_STR) - get_curr_stat(ch,STAT_STR);
chance += get_curr_stat(victim,STAT_LUCK) - get_curr_stat(ch,STAT_LUCK);
/* DEBUG
sendf(ch, "`#Char Weapon skill: `!%d``\n\r"\
"`#Vic Weapon skill: `!%d``\n\r"\
"`#Vict with char Weapon skill: `!%d``\n\r"\
"`#Chance: `!%d``\n\r"\
,ch_weapon, vict_weapon, ch_vict_weapon, chance);
*/
if (!IS_NPC(ch)){
chance = get_dchance(ini_chance, chance, (h_roll - victim->level/5)/3);
}
else
chance -= h_roll/4;
if (!IS_NPC(ch) && ch->pcdata->pStallion != NULL && number_percent() < get_skill(ch, gsn_mounted)){
chance -= 3;
check_improve(ch, gsn_mounted, TRUE, 1);
}
if (IS_NPC(ch) && IS_SET(ch->off_flags, CABAL_GUARD))
chance -= 15;
else
chance += victim->level - level;
if (!IS_NPC(victim) && IS_SET(victim->act2,PLR_GIMP))
chance /= 2;
//Check for success
if ( number_percent( ) >= chance)
return FALSE;
if (fVirt)
{
/* We select two types of origin of the virual attack.
1) obj
2) spell
*/
sprintf(buf1, "You parry a %s's %s.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
sprintf(buf2, "$N parries a %s's %s.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
sprintf(buf3, "$N parries a %s's %s.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
}
else
{
sprintf(buf1, "You parry $n's attack.");
sprintf(buf2, "$N parries your attack.");
sprintf(buf3, "$N parries $n's attack.");
}
if (!doomsingerCheck(ch)){
act( buf1, ch, vir_obj, victim, TO_VICT );
act( buf2, ch, vir_obj, victim, TO_CHAR );
act( buf3, ch, vir_obj, victim, TO_WATCHROOM);
}
check_improve(victim,gsn_parry,TRUE, 0);
//PARRY CHECK
if (PARRY_CHECK(ch, obj, obj2, dt) == -1)
bug("Error at: PARRY_CHECK\n\r", 0);
return TRUE;
}
bool check_dual_parry( CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA* vir_obj, int dt, int h_roll, int level, bool fVirt, int sn)
{
OBJ_DATA *obj = NULL;
OBJ_DATA* obj2 = (vir_obj != NULL? vir_obj : NULL);
int chance, ini_chance, ch_weapon, vict_weapon, ch_vict_weapon, c_wtype = 0, v_wtype = 0;
int temp = 0;
char buf1[MSL], buf2[MSL], buf3[MSL];
AFFECT_DATA* paf;
//easy hits.
if ( !IS_AWAKE(victim)
|| is_affected(victim,gsn_ecstacy)
|| ((paf = affect_find(victim->affected, gsn_wlock)) && paf->modifier != 0)
)
return FALSE;
//skill
chance = get_skill(victim,gsn_dual_parry) / 3;
ini_chance = chance;
//Obj check
if ( get_eq_char(victim, WEAR_SECONDARY) == NULL || ( obj = getBmWep( victim, FALSE ) ) == NULL){
if (IS_NPC(victim) && get_eq_char( victim, WEAR_SHIELD ) == NULL)
chance /= 2;
else
return FALSE;
}
//Item check
if (obj && CAN_WEAR(obj, ITEM_PARRY)){
if (chance == 0)
chance = 15;
else
chance += 5;
}
if (chance < 1)
return FALSE;
if (obj && obj->value[0] == WEAPON_DAGGER)
chance += 5;
/* weapon raked away */
if ( ( paf = affect_find(ch->affected,gsn_rake)) != NULL
&& paf->modifier == 0)
return FALSE;
//bonus/penalty for blind.
//we only check if character can see if this is not virtual attack.
if (!can_see(ch,victim) && !fVirt)
{
if (!IS_NPC(ch) && number_percent() < get_skill(ch,gsn_blind_fighting)){
if (!is_affected(ch, gsn_battletrance))
chance *= 1.1;
}
else
chance *= 1.3;
}
if (!can_see(victim,ch))
{
if (!IS_NPC(victim) && number_percent() < get_skill(victim,gsn_blind_fighting)){
if (!is_affected(victim, gsn_battletrance))
chance /= 1.1;
}
else
chance /= 1.3;
}
/* crusade effects */
if ( (temp = check_crusade(ch, victim)) != CRUSADE_NONE){
/* if attacker is on crusade against victim */
if (temp == CRUSADE_MATCH)
chance /= 1.3;
/* if attacker is on crusade but not agaisnt victim */
else if (temp == CRUSADE_NOTMATCH)
chance *= 1.1;
}
if ( (temp = check_crusade(victim, ch)) != CRUSADE_NONE){
/* if victim is on crusade against attacker */
if (temp == CRUSADE_MATCH)
chance *= 1.3;
/* if victim is on crusade but not against attacker */
else if (temp == CRUSADE_NOTMATCH)
chance /= 1.1;
}
/* end crusade bonuses */
/* check weapon position */
if (!IS_NPC(ch)){
/* harder to block for victim if attacker is high */
if (ch->pcdata->wep_pos == WEPPOS_HIGH)
chance -= 10;
/* easier to block for victim if attacker is low */
else if (ch->pcdata->wep_pos == WEPPOS_LOW)
chance += 5;
}
if (!IS_NPC(victim)){
/* harder to block for victim if victim is high */
if (victim->pcdata->wep_pos == WEPPOS_HIGH)
chance -= 5;
/* easier to block for victim if victim is low */
else if (victim->pcdata->wep_pos == WEPPOS_LOW)
chance += 10;
}
//we use the held item if this is not virtual attack.
if (!fVirt)
obj2 = getBmWep(ch, TRUE);
//weapons skills.
if (!IS_NPC(ch)){
ch_weapon = (fVirt? get_skill(ch, sn) : get_weapon_skill_obj(ch, obj2));
ch_vict_weapon = (fVirt? 2 * victim->level : get_weapon_skill_obj(victim, obj2));
}
else{
ch_weapon = 100;
ch_vict_weapon = (fVirt? 2 * victim->level : get_weapon_skill_obj(victim, obj2));
}
vict_weapon = get_weapon_skill_obj(victim, obj);
//DEFENDER'S WEAPON MODIFIER (penalty to defense due to dual parry)
v_wtype = UMAX(-5, get_weapon_obj_rating( obj, WEAPON_DEF ) - 2);
//ATTACKER'S WEAPON MODIFIER
if (fVirt){
if (dt == gen_blades || dt == gen_dan_blade)
c_wtype = URANGE(-2, (ch_weapon - 80) / 5, 5);
else
c_wtype = 0;
}
else if ( ch->class == gcn_psi
&& (paf = affect_find( ch->affected, gsn_false_weapon)) != NULL)
c_wtype = get_weapon_rating( paf->modifier, WEAPON_ATT );
else
c_wtype = get_weapon_obj_rating( obj2, WEAPON_ATT );
chance = chance * vict_weapon/100;
chance += (v_wtype - c_wtype) * 4;
chance += (ch_vict_weapon - ch_weapon) / 5;
chance += get_curr_stat(victim,STAT_DEX) - get_curr_stat(ch,STAT_DEX);
chance += get_curr_stat(victim,STAT_STR) - get_curr_stat(ch,STAT_STR);
chance += get_curr_stat(victim,STAT_LUCK) - get_curr_stat(ch,STAT_LUCK);
/* Viri: make dual parry very affected by hitroll and blind */
if (!IS_NPC(ch)){
chance -= (h_roll - victim->level/5) / 2;
}
else
chance -= h_roll/4;
if (!IS_NPC(ch) && ch->pcdata->pStallion != NULL && number_percent() < get_skill(ch, gsn_mounted)){
chance -= 3;
check_improve(ch, gsn_mounted, TRUE, 1);
}
if (IS_NPC(ch) && IS_SET(ch->off_flags, CABAL_GUARD))
chance -= 10;
else
chance += victim->level - level;
if (!IS_NPC(victim) && IS_SET(victim->act2,PLR_GIMP))
chance /= 2;
//Check for success
if ( number_percent( ) >= chance)
return FALSE;
if (fVirt)
{
/* We select two types of origin of the virual attack.
1) obj
2) spell
*/
sprintf(buf1, "You dual parry a %s's %s.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
sprintf(buf2, "$N dual parries a %s's %s.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
sprintf(buf3, "$N dual parries a %s's %s.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
}
else
{
sprintf(buf1, "You dual parry $n's attack.");
sprintf(buf2, "$N dual parries your attack.");
sprintf(buf3, "$N dual parries $n's attack.");
}
if (!doomsingerCheck(ch)){
act( buf1, ch, vir_obj, victim, TO_VICT );
act( buf2, ch, vir_obj, victim, TO_CHAR );
act( buf3, ch, vir_obj, victim, TO_WATCHROOM );
}
check_improve(victim,gsn_dual_parry,TRUE, 0);
if (ch && victim && ch->fighting == victim
&& check_ccombat_actions( victim, ch, CCOMBAT_DPARRY))
return TRUE;
//PARRY CHECK
if (obj && obj2 && PARRY_CHECK(ch, obj, obj2, dt) == -1)
bug("Error at: PARRY_CHECK\n\r", 0);
return TRUE;
}
bool check_shield_block( CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA* vir_obj, int dt, int h_roll, int level, bool fVirt, int sn)
{
OBJ_DATA *obj = NULL;
OBJ_DATA* obj2 = (vir_obj != NULL? vir_obj : get_eq_char(ch,WEAR_WIELD));
int chance, ini_chance, temp = 0;
char buf1[MSL], buf2[MSL], buf3[MSL];
AFFECT_DATA* paf;
//Sure hit
if ( !IS_AWAKE(victim)
|| ((paf = affect_find(victim->affected, gsn_wlock)) && paf->modifier != 0)
|| is_affected(victim,gsn_ecstacy))
return FALSE;
//Skill check
if ( (chance = get_skill(victim,gsn_shield_block) / 2) == 0)
return FALSE;
//Item check
if ( !is_affected(victim, skill_lookup("spirit shield")) && (obj = get_eq_char( victim, WEAR_SHIELD )) == NULL )
return FALSE;
ini_chance = chance;
//bonus/penalty for blind.
//we only check if character can see if this is not virtual attack.
if (!can_see(ch,victim) && !fVirt)
{
if (!IS_NPC(ch) && number_percent() < get_skill(ch,gsn_blind_fighting)){
if (!is_affected(ch, gsn_battletrance))
chance *= 1.1;
}
else
chance *= 1.3;
}
if (!can_see(victim,ch))
{
if (!IS_NPC(victim) && number_percent() < get_skill(victim,gsn_blind_fighting)){
if (!is_affected(victim, gsn_battletrance))
chance /= 1.1;
}
else
chance /= 1.3;
}
/* crusade effects */
if ( (temp = check_crusade(ch, victim)) != CRUSADE_NONE){
/* if attacker is on crusade against victim */
if (temp == CRUSADE_MATCH)
chance /= 1.3;
/* if attacker is on crusade but not agaisnt victim */
else if (temp == CRUSADE_NOTMATCH)
chance *= 1.1;
}
if ( (temp = check_crusade(victim, ch)) != CRUSADE_NONE){
/* if victim is on crusade against attacker */
if (temp == CRUSADE_MATCH)
chance *= 1.3;
/* if victim is on crusade but not against attacker */
else if (temp == CRUSADE_NOTMATCH)
chance /= 1.1;
}
/* end crusade bonuses */
/* check weapon position */
if (!IS_NPC(ch)){
/* harder to block for victim if attacker is high */
if (ch->pcdata->wep_pos == WEPPOS_HIGH)
chance -= 10;
/* easier to block for victim if attacker is low */
else if (ch->pcdata->wep_pos == WEPPOS_LOW)
chance += 5;
}
if (!IS_NPC(victim)){
/* harder to block for victim if victim is high */
if (victim->pcdata->wep_pos == WEPPOS_HIGH)
chance -= 5;
/* easier to block for victim if victim is low */
else if (victim->pcdata->wep_pos == WEPPOS_LOW)
chance += 10;
}
//bonus for bless
if (obj && IS_GOOD(victim) && IS_OBJ_STAT(obj,ITEM_BLESS))
chance += 5;
else if (obj && IS_EVIL(victim) && IS_OBJ_STAT(obj,ITEM_DARK))
chance += 5;
chance += get_curr_stat(victim,STAT_STR) - get_curr_stat(ch,STAT_STR);
chance += get_curr_stat(victim,STAT_DEX) - get_curr_stat(ch,STAT_DEX);
chance += get_curr_stat(victim,STAT_LUCK) - get_curr_stat(ch,STAT_LUCK);
if (!IS_NPC(ch) && ch->pcdata->pStallion != NULL && number_percent() < get_skill(ch, gsn_mounted)){
chance -= 3;
check_improve(ch, gsn_mounted, TRUE, 1);
}
if (IS_NPC(ch) && IS_SET(ch->off_flags, CABAL_GUARD))
chance -= 10;
else
chance += victim->level - level;
if (!IS_NPC(ch)){
chance = get_dchance(ini_chance, chance, (h_roll - victim->level/5)/4);
}
else
chance -= h_roll/4;
if (!IS_NPC(victim) && IS_SET(victim->act2,PLR_GIMP) )
chance /= 2;
if ( number_percent( ) >= chance )
return FALSE;
if (fVirt)
{
/* We select two types of origin of the virual attack.
1) obj
2) spell
*/
sprintf(buf1, "You block a %s's %s with your shield.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
sprintf(buf2, "$N blocks a %s's %s with $S shield.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
sprintf(buf3, "$N blocks a %s's %s with $S shield.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
}
else
{
sprintf(buf1, "You block $n's attack with your shield.");
sprintf(buf2, "$N blocks your attack with $S shield.");
sprintf(buf3, "$N blocks $n's attack with $S shield.");
}
if (!doomsingerCheck(ch)){
act( buf1, ch, vir_obj, victim, TO_VICT );
act( buf2, ch, vir_obj, victim, TO_CHAR );
act( buf3, ch, vir_obj, victim, TO_WATCHROOM );
}
check_improve(victim,gsn_shield_block,TRUE, 0);
//SHBLOCK CHECK
if (SHBLOCK_CHECK(ch, obj2, obj, dt) == -1)
bug("Error at: BLOCK_CHECK\n\r", 0);
return TRUE;
}
bool check_blink( CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA* vir_obj, int dt, int h_roll, int level, bool fVirt, int sn)
{
int chance, ini_chance, temp = 0;
char buf1[MSL], buf2[MSL], buf3[MSL];
//Sure hit
if ( !IS_AWAKE(victim) || victim->class != gcn_psi
|| !is_affected(victim, gsn_blink)
|| is_affected(victim,gsn_ecstacy))
return FALSE;
//Skill check
if ( (chance = get_skill(victim,gsn_blink) / 2) == 0)
return FALSE;
ini_chance = chance;
//bonus/penalty for blind.
//we only check if character can see if this is not virtual attack.
if (!can_see(ch,victim) && !fVirt){
if (!IS_NPC(ch) && number_percent() < get_skill(ch,gsn_blind_fighting)){
if (!is_affected(ch, gsn_battletrance))
chance *= 1.1;
}
else
chance *= 1.3;
}
if (!can_see(victim,ch)){
if (!IS_NPC(victim) && number_percent() < get_skill(victim,gsn_blind_fighting)){
if (!is_affected(victim, gsn_battletrance))
chance /= 1.1;
}
else
chance /= 1.3;
}
/* crusade effects */
if ( (temp = check_crusade(ch, victim)) != CRUSADE_NONE){
/* if attacker is on crusade against victim */
if (temp == CRUSADE_MATCH)
chance /= 1.3;
/* if attacker is on crusade but not agaisnt victim */
else if (temp == CRUSADE_NOTMATCH)
chance *= 1.1;
}
if ( (temp = check_crusade(victim, ch)) != CRUSADE_NONE){
/* if victim is on crusade against attacker */
if (temp == CRUSADE_MATCH)
chance *= 1.3;
/* if victim is on crusade but not against attacker */
else if (temp == CRUSADE_NOTMATCH)
chance /= 1.1;
}
/* end crusade bonuses */
/* check weapon position */
if (!IS_NPC(ch)){
/* harder to block for victim if attacker is high */
if (ch->pcdata->wep_pos == WEPPOS_HIGH)
chance -= 10;
/* easier to block for victim if attacker is low */
else if (ch->pcdata->wep_pos == WEPPOS_LOW)
chance += 5;
}
if (!IS_NPC(victim)){
/* harder to block for victim if victim is high */
if (victim->pcdata->wep_pos == WEPPOS_HIGH)
chance -= 5;
/* easier to block for victim if victim is low */
else if (victim->pcdata->wep_pos == WEPPOS_LOW)
chance += 10;
}
chance += 3 * (get_curr_stat(victim,STAT_LUCK) - get_curr_stat(ch,STAT_LUCK));
if (!IS_NPC(ch) && ch->pcdata->pStallion != NULL && number_percent() < get_skill(ch, gsn_mounted)){
chance -= 3;
check_improve(ch, gsn_mounted, TRUE, 1);
}
if (IS_NPC(ch) && IS_SET(ch->off_flags, CABAL_GUARD))
chance -= 10;
else
chance += victim->level - level;
if (!IS_NPC(ch)){
chance = get_dchance(ini_chance, chance, (h_roll - victim->level/5)/4);
}
else
chance -= h_roll/4;
if (!IS_NPC(victim) && IS_SET(victim->act2,PLR_GIMP) )
chance /= 2;
if ( number_percent( ) >= chance )
return FALSE;
if (fVirt){
/* We select two types of origin of the virual attack.
1) obj
2) spell
*/
sprintf(buf1, "You blink out before a %s's %s.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
sprintf(buf2, "$N blinks out before a %s's %s.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
sprintf(buf3, "$N blocks a %s's %s with $S shield.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
}
else{
sprintf(buf1, "You blink out before $n's attack.");
sprintf(buf2, "$N blinks out before your attack.");
sprintf(buf3, "$N blinks out before $n's attack.");
}
if (!doomsingerCheck(ch)){
act( buf1, ch, vir_obj, victim, TO_VICT );
act( buf2, ch, vir_obj, victim, TO_CHAR );
act( buf3, ch, vir_obj, victim, TO_WATCHROOM );
}
check_improve(victim, gsn_blink, TRUE, 0);
return TRUE;
}
bool check_block( CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA* vir_obj, int dt, int h_roll, int level, bool fVirt, int sn)
{
AFFECT_DATA* paf;
OBJ_DATA *obj = get_eq_char(victim, WEAR_WIELD);
OBJ_DATA* obj2 = (vir_obj != NULL? vir_obj : get_eq_char(ch,WEAR_WIELD));
int chance, ini_chance, temp = 0, ch_weapon, vict_weapon, ch_vict_weapon, c_wtype = 0, v_wtype = 0;
char buf1[MSL], buf2[MSL], buf3[MSL];
//Sure hit
if ( !IS_AWAKE(victim)
|| ((paf = affect_find(victim->affected, gsn_wlock)) && paf->modifier != 0)
|| is_affected(victim,gsn_ecstacy))
return FALSE;
if (obj == NULL)
return FALSE;
//Skill check
if ( (chance = get_skill(victim,gsn_2hands) / 2) == 0)
return FALSE;
//Item check (must be 2 h weapon)
if (!IS_WEAPON_STAT(obj,WEAPON_TWO_HANDS)
&& !is_affected(victim, gsn_double_grip))
return FALSE;
//heck ifheld in 2 hands (second hand empty.)
if (get_eq_char(victim,WEAR_SHIELD) || get_eq_char(victim,WEAR_SECONDARY)
|| get_eq_char(victim,WEAR_HOLD))
return FALSE;
ini_chance = chance;
//bonus/penalty for blind.
//we only check if character can see if this is not virtual attack.
if (!can_see(ch,victim) && !fVirt)
{
if (!IS_NPC(ch) && number_percent() < get_skill(ch,gsn_blind_fighting)){
if (!is_affected(ch, gsn_battletrance))
chance *= 1.1;
}
else
chance *= 1.3;
}
if (!can_see(victim,ch))
{
if (!IS_NPC(victim) && number_percent() < get_skill(victim,gsn_blind_fighting)){
if (!is_affected(victim, gsn_battletrance))
chance /= 1.1;
}
else
chance /= 1.3;
}
/* crusade effects */
if ( (temp = check_crusade(ch, victim)) != CRUSADE_NONE){
/* if attacker is on crusade against victim */
if (temp == CRUSADE_MATCH)
chance /= 1.3;
/* if attacker is on crusade but not agaisnt victim */
else if (temp == CRUSADE_NOTMATCH)
chance *= 1.1;
}
if ( (temp = check_crusade(victim, ch)) != CRUSADE_NONE){
/* if victim is on crusade against attacker */
if (temp == CRUSADE_MATCH)
chance *= 1.3;
/* if victim is on crusade but not against attacker */
else if (temp == CRUSADE_NOTMATCH)
chance /= 1.1;
}
/* end crusade bonuses */
/* check weapon position */
if (!IS_NPC(ch)){
/* harder to block for victim if attacker is high */
if (ch->pcdata->wep_pos == WEPPOS_HIGH)
chance -= 10;
/* easier to block for victim if attacker is low */
else if (ch->pcdata->wep_pos == WEPPOS_LOW)
chance += 5;
}
if (!IS_NPC(victim)){
/* harder to block for victim if victim is high */
if (victim->pcdata->wep_pos == WEPPOS_HIGH)
chance -= 5;
/* easier to block for victim if victim is low */
else if (victim->pcdata->wep_pos == WEPPOS_LOW)
chance += 10;
}
//weapons skills.
if (!IS_NPC(ch)){
ch_weapon = (fVirt? get_skill(ch, sn) : get_weapon_skill_obj(ch, obj2));
ch_vict_weapon = (fVirt? 2 * victim->level : get_weapon_skill_obj(victim, obj2));
}
else{
ch_weapon = 100;
ch_vict_weapon = (fVirt? 2 * victim->level : get_weapon_skill_obj(victim, obj2));
}
vict_weapon = get_weapon_skill_obj(victim, obj);
//DEFENDER'S WEAPON MODIFIER
v_wtype = get_weapon_obj_rating( obj, WEAPON_DEF );
//ATTACKER'S WEAPON MODIFIER
if (fVirt){
if (dt == gen_blades || dt == gen_dan_blade)
c_wtype = URANGE(-2, (ch_weapon - 80) / 5, 5);
else
c_wtype = 0;
}
else if ( ch->class == gcn_psi
&& (paf = affect_find( ch->affected, gsn_false_weapon)) != NULL)
c_wtype = get_weapon_rating( paf->modifier, WEAPON_ATT );
else
c_wtype = get_weapon_obj_rating( obj2, WEAPON_ATT );
chance = chance * vict_weapon/100;
chance += (v_wtype - c_wtype) * 3;
chance += (ch_vict_weapon - ch_weapon) / 5;
chance += (get_curr_stat(victim,STAT_STR) - get_curr_stat(ch,STAT_STR)) * 2;
chance += get_curr_stat(victim,STAT_DEX) - get_curr_stat(ch,STAT_DEX);
chance += get_curr_stat(victim,STAT_LUCK) - get_curr_stat(ch,STAT_LUCK);
if (!IS_NPC(ch) && ch->pcdata->pStallion != NULL && number_percent() < get_skill(ch, gsn_mounted)){
chance -= 3;
check_improve(ch, gsn_mounted, TRUE, 1);
}
if (!IS_NPC(victim) && IS_AFFECTED2(victim,AFF_RAGE)
&& get_skill(victim, gsn_path_fury) > 1){
chance += 5;
}
if (IS_NPC(ch) && IS_SET(ch->off_flags, CABAL_GUARD))
chance -= 10;
else
chance += victim->level - level;
if (!IS_NPC(ch)){
chance = get_dchance(ini_chance, chance, (h_roll - victim->level/5)/4);
}
else
chance -= h_roll/4;
if (!IS_NPC(victim) && IS_SET(victim->act2,PLR_GIMP) )
chance /= 2;
if ( number_percent( ) >= chance )
return FALSE;
if (fVirt)
{
/* We select two types of origin of the virual attack.
1) obj
2) spell
*/
sprintf(buf1, "You block a %s's %s with your weapon.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
sprintf(buf2, "$N blocks a %s's %s with $S weapon.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
sprintf(buf3, "$N blocks a %s's %s with $S weapon.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
}
else
{
sprintf(buf1, "You block $n's attack with your weapon.");
sprintf(buf2, "$N blocks your attack with $S weapon.");
sprintf(buf3, "$N blocks $n's attack with $S weapon.");
}
if (!doomsingerCheck(ch)){
act( buf1, ch, vir_obj, victim, TO_VICT );
act( buf2, ch, vir_obj, victim, TO_CHAR );
act( buf3, ch, vir_obj, victim, TO_WATCHROOM );
}
check_improve(victim,gsn_2hands,TRUE, 0);
//SHBLOCK CHECK
if (SHBLOCK_CHECK(ch, obj2, obj, dt) == -1)
bug("Error at: BLOCK_CHECK\n\r", 0);
return TRUE;
}
bool check_dodge( CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA* vir_obj, int dt, int h_roll, int level, bool fVirt, int sn)
{
int chance, ini_chance, temp = 0;
char buf1[MSL], buf2[MSL], buf3[MSL];
bool fDrunk = FALSE;
bool fWereBeast = FALSE;
//Sure hit
if ( !IS_AWAKE(victim) || is_affected(victim,gsn_ecstacy))
return FALSE;
//Skill check
if ( ( chance = get_skill(victim,gsn_dodge) / 2) == 0)
return FALSE;
/* try for sidestep */
if (ch && victim && ch->fighting == victim
&& check_ccombat_actions( victim, ch, CCOMBAT_EVADE))
return TRUE;
ini_chance = chance;
//bonus/penalty for blind.
//we only check if character can see if this is not virtual attack.
if (!can_see(ch,victim) && !fVirt)
{
if (!IS_NPC(ch) && number_percent() < get_skill(ch,gsn_blind_fighting)){
if (!is_affected(ch, gsn_battletrance))
chance *= 1.1;
}
else
chance *= 1.3;
}
if (!can_see(victim,ch))
{
if (!IS_NPC(victim) && number_percent() < get_skill(victim,gsn_blind_fighting)){
if (!is_affected(victim, gsn_battletrance))
chance /= 1.1;
}
else
chance /= 1.3;
}
/* crusade effects */
if ( (temp = check_crusade(ch, victim)) != CRUSADE_NONE){
/* if attacker is on crusade against victim */
if (temp == CRUSADE_MATCH)
chance /= 1.3;
/* if attacker is on crusade but not agaisnt victim */
else if (temp == CRUSADE_NOTMATCH)
chance *= 1.1;
}
if ( (temp = check_crusade(victim, ch)) != CRUSADE_NONE){
/* if victim is on crusade against attacker */
if (temp == CRUSADE_MATCH)
chance *= 1.3;
/* if victim is on crusade but not against attacker */
else if (temp == CRUSADE_NOTMATCH)
chance /= 1.1;
}
/* end crusade bonuses */
/* check weapon position */
if (!IS_NPC(ch)){
/* harder to block for victim if attacker is high */
if (ch->pcdata->wep_pos == WEPPOS_HIGH)
chance -= 10;
/* easier to block for victim if attacker is low */
else if (ch->pcdata->wep_pos == WEPPOS_LOW)
chance += 5;
}
if (!IS_NPC(victim)){
/* harder to block for victim if victim is high */
if (victim->pcdata->wep_pos == WEPPOS_HIGH)
chance -= 5;
/* easier to block for victim if victim is low */
else if (victim->pcdata->wep_pos == WEPPOS_LOW)
chance += 10;
}
chance += get_curr_stat(victim,STAT_LUCK) - get_curr_stat(ch,STAT_LUCK);
if (!IS_NPC(ch)){
chance = get_dchance(ini_chance, chance, (h_roll - victim->level/5)/4);
}
else
chance -= h_roll/4;
//WOLF CHECK
if (is_affected(victim, gsn_wolf_form) && vamp_can_sneak(victim, victim->in_room))
chance *= 1.2;
else if (victim->race == grn_werebeast){
AFFECT_DATA* paf = victim->affected;
for (;paf; paf = paf->next){
if (paf->type == gsn_weretiger
|| paf->type == gsn_werewolf
|| paf->type == gsn_werebear
|| paf->type == gsn_werefalcon)
break;
}
if (paf != NULL){
fWereBeast = TRUE;
chance = 10 + 12 * chance / 10;
}
}
if (!fWereBeast && IS_AFFECTED2(victim,AFF_RAGE))
return FALSE;
if (!IS_NPC(ch) && ch->pcdata->pStallion != NULL && number_percent() < get_skill(ch, gsn_mounted)){
chance -= 3;
check_improve(ch, gsn_mounted, TRUE, 1);
}
if (IS_NPC(ch) && IS_SET(ch->off_flags, CABAL_GUARD))
chance -= 10;
else
chance += victim->level - level;
if (!IS_NPC(victim) && is_affected(victim,gsn_drunken)
&& is_empowered_quiet(victim,1)){
if (number_percent() < get_skill(victim, gsn_drunken)){
chance += 5 + URANGE(10,victim->pcdata->condition[COND_DRUNK],35);
check_improve(victim, gsn_drunken, TRUE, 0);
fDrunk = TRUE;
}
}
if (!IS_NPC(victim) && IS_SET(victim->act2,PLR_GIMP) )
chance /= 2;
if ( number_percent( ) >= chance )
return FALSE;
if (fVirt)
{
/* We select two types of origin of the virual attack.
1) obj
2) spell
*/
sprintf(buf1, "You dodge a %s's %s.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
sprintf(buf2, "$N dodges %s's %s.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
sprintf(buf3, "$N dodges %s's %s.",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
}
else if (fDrunk){
sprintf(buf1, "You stagger wildly out of $n's attack.");
sprintf(buf2, "$N staggers wildly out of your attack.");
sprintf(buf3, "$N staggers wildly out of $n's attack.");
}
else if (victim->class == gcn_blademaster && is_affected(victim, gsn_deathweaver)){
sprintf(buf1, "You weave out of $n's attack.");
sprintf(buf2, "$N weaves out of your attack.");
sprintf(buf3, "$N weaves out of $n's attack.");
}
else
{
sprintf(buf1, "You dodge $n's attack.");
sprintf(buf2, "$N dodges your attack.");
sprintf(buf3, "$N dodges $n's attack.");
}
if (!doomsingerCheck(ch)){
act( buf1, ch, vir_obj, victim, TO_VICT );
act( buf2, ch, vir_obj, victim, TO_CHAR );
act( buf3, ch, vir_obj, victim, TO_WATCHROOM );
}
check_improve(victim,gsn_dodge,TRUE, 0);
return TRUE;
}
bool check_riposte( CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA* vir_obj, int dt, int h_roll, int level, bool fVirt, int sn)
{
AFFECT_DATA* paf;
OBJ_DATA *vic_obj = NULL;
OBJ_DATA *ch_obj = (fVirt? vir_obj : get_eq_char( ch, WEAR_WIELD));
int ch_weapon, vict_weapon, ch_vict_weapon, c_wtype = 0, v_wtype = 0;
int chance, ini_chance, temp = 0;
char buf1[MSL], buf2[MSL], buf3[MSL];
//Sure hit
if ( !IS_AWAKE(victim) || is_affected(victim,gsn_ecstacy))
return FALSE;
//Skill
if ( (chance = get_skill(victim,gsn_riposte) / 3) == 0)
return FALSE;
//virtual attacks are hard to riposte
if (fVirt)
chance /= 3;
//item check
if ( (vic_obj = get_eq_char( victim, WEAR_WIELD )) == NULL)
return FALSE;
ini_chance = chance;
//bonus/penalty for blind.
//we only check if character can see if this is not virtual attack.
if (!can_see(ch,victim) && !fVirt){
if (!IS_NPC(ch) && number_percent() < get_skill(ch,gsn_blind_fighting)){
if (!is_affected(ch, gsn_battletrance))
chance *= 1.1;
}
else
chance *= 1.3;
}
if (!can_see(victim,ch))
{
if (!IS_NPC(victim) && number_percent() < get_skill(victim,gsn_blind_fighting)){
if (!is_affected(victim, gsn_battletrance))
chance /= 1.2;
}
else
chance /= 1.4;
}
/* crusade effects */
if ( (temp = check_crusade(ch, victim)) != CRUSADE_NONE){
/* if attacker is on crusade against victim */
if (temp == CRUSADE_MATCH)
chance /= 1.3;
/* if attacker is on crusade but not agaisnt victim */
else if (temp == CRUSADE_NOTMATCH)
chance *= 1.1;
}
if ( (temp = check_crusade(victim, ch)) != CRUSADE_NONE){
/* if victim is on crusade against attacker */
if (temp == CRUSADE_MATCH)
chance *= 1.3;
/* if victim is on crusade but not against attacker */
else if (temp == CRUSADE_NOTMATCH)
chance /= 1.1;
}
/* end crusade bonuses */
/* check weapon position */
if (!IS_NPC(ch)){
/* harder to block for victim if attacker is high */
if (ch->pcdata->wep_pos == WEPPOS_HIGH)
chance -= 10;
/* easier to block for victim if attacker is low */
else if (ch->pcdata->wep_pos == WEPPOS_LOW)
chance += 5;
}
if (!IS_NPC(victim)){
/* harder to block for victim if victim is high */
if (victim->pcdata->wep_pos == WEPPOS_HIGH)
chance -= 5;
/* easier to block for victim if victim is low */
else if (victim->pcdata->wep_pos == WEPPOS_LOW)
chance += 10;
}
//weapons skills.
if (!IS_NPC(ch)){
ch_weapon = (fVirt? get_skill(ch, sn) : get_weapon_skill_obj(ch, ch_obj));
ch_vict_weapon = (fVirt? 2 * victim->level : get_weapon_skill_obj(victim, ch_obj));
}
else{
ch_weapon = 100;
ch_vict_weapon = (fVirt? 2 * victim->level : get_weapon_skill_obj(victim, ch_obj));
}
vict_weapon = get_weapon_skill_obj(victim, vic_obj);
//DEFENDER'S WEAPON MODIFIER
v_wtype = get_weapon_obj_rating( vic_obj, WEAPON_DEF );
//ATTACKER'S WEAPON MODIFIER
if (fVirt){
if (dt == gen_blades || dt == gen_dan_blade)
c_wtype = URANGE(-2, (ch_weapon - 80) / 5, 5);
else
c_wtype = 0;
}
else if ( ch->class == gcn_psi
&& (paf = affect_find( ch->affected, gsn_false_weapon)) != NULL)
c_wtype = get_weapon_rating( paf->modifier, WEAPON_ATT );
else
c_wtype = get_weapon_obj_rating( ch_obj, WEAPON_ATT );
chance = chance * vict_weapon/100;
chance += (v_wtype - c_wtype) * 3;
chance += (ch_vict_weapon - ch_weapon) / 5;
chance += get_curr_stat(victim,STAT_DEX) - get_curr_stat(ch,STAT_DEX);
chance += get_curr_stat(victim,STAT_STR) - get_curr_stat(ch,STAT_STR);
chance += get_curr_stat(victim,STAT_LUCK) - get_curr_stat(ch,STAT_LUCK);
if (!IS_NPC(ch) && ch->pcdata->pStallion != NULL && number_percent() < get_skill(ch, gsn_mounted)){
chance -= 3;
check_improve(ch, gsn_mounted, TRUE, 1);
}
if (IS_NPC(ch) && IS_SET(ch->off_flags, CABAL_GUARD))
chance -= 10;
else
chance += victim->level - level;
if (!IS_NPC(ch)){
chance = get_dchance(ini_chance, chance, (h_roll - victim->level/5)/2);
}
else
chance -= h_roll/4;
if (!IS_NPC(victim) && IS_SET(victim->act2,PLR_GIMP) )
chance /= 2;
if (IS_AFFECTED2(victim,AFF_RAGE))
return FALSE;
if ( number_percent( ) >= chance )
return FALSE;
if (fVirt)
{
/* We select two types of origin of the virual attack.
1) obj
2) spell
*/
sprintf(buf1, "You blocka %s's %s and attempts to strike at $n through the brief opening",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
sprintf(buf2, "$N blocks your %s's %s and attempts to strike at you through the brief opening",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
sprintf(buf3, "$N blocks a %s's %s and attempts to strike at $n through the brief opening",
(vir_obj == NULL? get_vir_attack(sn) : "$p"),
get_vir_attack(dt));
}
else
{
sprintf(buf1, "You block $n's attack and attempt to strike at the brief opening.");
sprintf(buf2, "$N blocks your attack and attempts to strike at the brief opening.");
sprintf(buf3, "$N blocks $n's attack and attempts to strike at the brief opening.");
}
if (!doomsingerCheck(ch)){
act( buf1, ch, vir_obj, victim, TO_VICT );
act( buf2, ch, vir_obj, victim, TO_CHAR );
act( buf3, ch, vir_obj, victim, TO_WATCHROOM );
/* hit back */
one_hit(victim,ch,gsn_riposte,FALSE);
}
check_improve(victim,gsn_riposte,TRUE, 0);
return TRUE;
}
void update_pos( CHAR_DATA *victim )
{
if ( victim->hit > 0 )
{
if ( victim->position <= POS_STUNNED )
victim->position = POS_STANDING;
return;
}
if ( IS_NPC(victim) && victim->hit < 1 )
{
victim->position = POS_DEAD;
return;
}
if ( victim->hit <= -11)
{
victim->position = POS_DEAD;
return;
}
if ( victim->hit <= -6)
victim->position = POS_MORTAL;
else if ( victim->hit <= -3)
victim->position = POS_INCAP;
else
victim->position = POS_STUNNED;
}
void set_fighting( CHAR_DATA *ch, CHAR_DATA *victim )
{
if (ch == NULL || victim == NULL)
return;
if ( IS_AFFECTED(ch, AFF_SLEEP) )
{
REMOVE_BIT(ch->affected_by,AFF_SLEEP);
affect_strip( ch,gsn_sleep );
affect_strip( ch,gsn_hypnosis );
affect_strip(ch,gsn_coffin);
affect_strip(ch,gsn_entomb);
song_strip(ch,gsn_lullaby);
}
if ( IS_AFFECTED2(ch, AFF_CATALEPSY) )
do_revive(ch, "");
if (is_affected(victim,gsn_prayer))
{
send_to_char("Your prayer has been disrupted.\n\r",victim);
affect_strip(victim,gsn_prayer);
}
if (is_affected(ch,gsn_prayer))
{
send_to_char("Your prayer has been disrupted.\n\r",ch);
affect_strip(ch,gsn_prayer);
}
if (is_affected(victim,gsn_trap_silvanus))
{
send_to_char("You lost your trap in the frey.\n\r",victim);
affect_strip(victim,gsn_trap_silvanus);
}
if (is_affected(ch,gsn_trap_silvanus))
{
send_to_char("You lost your trap in the frey.\n\r",ch);
affect_strip(ch,gsn_trap_silvanus);
}
if (is_affected(victim,gsn_empower))
{
send_to_char("You cannot concentrate on empowering while fighting!\n\r",victim);
affect_strip(victim,gsn_empower);
affect_strip(victim,gsn_offensive);
affect_strip(victim,gsn_defensive);
}
if (is_affected(ch,gsn_empower))
{
send_to_char("You cannot concentrate on empowering while fighting!\n\r",ch);
affect_strip(ch,gsn_empower);
affect_strip(ch,gsn_offensive);
affect_strip(ch,gsn_defensive);
}
if (IS_NPC(ch) && is_affected(ch,gsn_mirror_image))
{
extract_char(ch,TRUE);
return;
}
if (IS_NPC(ch) && is_affected(ch,gsn_decoy))
{
send_to_char("It's a trap!\n\r",victim);
act("$n explodes, a powdery dust spills from it.",ch,NULL,NULL,TO_ALL);
spell_poison(gsn_poison,victim->level,ch,(void *) victim,TARGET_CHAR);
spell_blindness(gsn_blindness,victim->level,ch,(void *) victim,TARGET_CHAR);
extract_char(ch,TRUE);
return;
}
// PREVIOLENCE CHECK //
if ( PREVIOLENCE_CHECK(ch, victim) == -1)
bug("Error at: PreViolenceCheck, returned fail\n\r", 0);
/* morph check */
if ( IS_NPC(ch) && !IS_NPC(victim) && IS_SET(ch->act2, ACT_MORPH)
&& ch->fighting != victim)
morph_mob(ch, victim);
ch->fighting = victim;
ch->position = POS_FIGHTING;
set_delay(ch, victim);
}
void stop_fighting( CHAR_DATA *ch, bool fBoth )
{
CHAR_DATA *fch;
AFFECT_DATA* paf;
for ( fch = char_list; fch != NULL; fch = fch->next ){
if ( fch == ch || ( fBoth && fch->fighting == ch ) ){
// POSTVIOLENCE CHECK //
if ( POSTVIOLENCE_CHECK(fch) == -1)
bug("Error at: PreViolenceCheck, returned fail\n\r", 0);
fch->fighting = NULL;
fch->position = IS_NPC(fch) ? fch->default_pos : POS_STANDING;
update_pos( fch );
//clear ranged weapon reload status
fch->reload = 0;
affect_strip( fch, gsn_phantasmal_griffon );
affect_strip( fch, gsn_illusionary_spectre );
affect_strip( fch, gsn_phantom_dragon );
affect_strip( fch, gsn_throw );
affect_strip( fch, gsn_forms );
affect_strip( fch, gsn_onslaught );
if ( (paf = affect_find(fch->affected, gsn_wlock)) != NULL){
if (paf->modifier != 0)
act(skill_table[gsn_wlock].msg_off, fch, NULL, NULL, TO_CHAR);
affect_strip(fch, gsn_wlock);
}
if (fch == ch || fch->in_room != ch->in_room)
continue;
set_delay(ch, fch);
}
}
}
OBJ_DATA* make_corpse( CHAR_DATA *ch )
{
char buf[MSL];
OBJ_DATA *corpse, *obj, *obj_next;
char *name;
if (ch->in_room == NULL)
return NULL;
//not on mirrors
if (IS_NPC(ch)) if (ch->pIndexData->vnum == MOB_VNUM_DECOY || ch->pIndexData->vnum == MOB_VNUM_DUMMY)
return NULL;
if ( IS_NPC(ch) )
{
name = str_dup(ch->short_descr);
corpse = create_object(get_obj_index(OBJ_VNUM_CORPSE_NPC), 0);
corpse->timer = number_range( 3, 6 );
corpse->owner = ch->pIndexData->vnum;
}
else
{
name = str_dup(ch->name);
corpse = create_object(get_obj_index(OBJ_VNUM_CORPSE_PC), 0);
corpse->timer = number_range( 25, 40 );
corpse->owner = ch->id;
corpse->pCabal = get_parent(ch->pCabal);
}
if (ch->gold > 0 )
{
obj_to_obj(create_money(ch->gold), corpse);
ch->gold = 0;
}
corpse->cost = 0;
corpse->recall = get_temple_pitroom(ch);
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 );
/* transfer eq */
if (IS_IMMORTAL(ch) || is_affected(ch, gsn_life_insurance)){
AFFECT_DATA* paf = affect_find(ch->affected, gsn_life_insurance);
if (paf)
CP_GAIN(ch, -paf->modifier, TRUE);
obj_to_room( corpse, ch->in_room );
return corpse;
}
for ( obj = ch->carrying; obj != NULL; obj = obj_next ){
obj_next = obj->next_content;
affect_strip_obj( obj, gsn_bloodvow);
REMOVE_BIT(obj->extra_flags,ITEM_INVENTORY);
obj_from_char( obj );
if (obj->item_type == ITEM_POTION)
obj->timer = number_range(500,1000);
if (obj->item_type == ITEM_HERB)
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) && !IS_NPC(ch)){
/* Changed to instant poof for non-keys: Viri */
if (obj->item_type == ITEM_KEY){
obj->timer = number_range(5,10);
REMOVE_BIT(obj->extra_flags,ITEM_ROT_DEATH);
}
else{
act("$p crumbles to dust.", ch, obj, NULL, TO_CHAR);
extract_obj(obj);
continue;
}
}
REMOVE_BIT(obj->extra_flags,ITEM_VIS_DEATH);
if (CAN_WEAR(obj, ITEM_UNIQUE) && obj->pIndexData->count > obj->pIndexData->cost){
act_new("$p crumbles to dust.", ch, obj, NULL, TO_CHAR, POS_DEAD);
if (obj->item_type == ITEM_SOCKET && obj->in_obj
&& IS_OBJ_STAT(obj->in_obj, ITEM_SOCKETABLE)){
unadorn_obj(obj, obj->in_obj, ch);
}
extract_obj( obj );
}
else if (!can_exist( obj->pIndexData )){
act_new("$p crumbles to dust.", ch, obj, NULL, TO_CHAR, POS_DEAD);
if (obj->item_type == ITEM_SOCKET && obj->in_obj
&& IS_OBJ_STAT(obj->in_obj, ITEM_SOCKETABLE)){
unadorn_obj(obj, obj->in_obj, ch);
}
extract_obj( obj );
}
else
obj_to_obj( obj, corpse );
}
obj_to_room( corpse, ch->in_room );
return corpse;
}
void dump_corpse( CHAR_DATA *ch )
{
OBJ_DATA *obj, *obj_next;
if (ch->gold > 0 )
{
obj_to_room(create_money(ch->gold), ch->in_room);
ch->gold = 0;
}
if (IS_IMMORTAL(ch) || is_affected(ch, gsn_life_insurance)){
AFFECT_DATA* paf = affect_find(ch->affected, gsn_life_insurance);
if (paf)
CP_GAIN(ch, -paf->modifier, TRUE);
act("$n's body disintegrates into dust.",ch,NULL,NULL,TO_ROOM);
return;
}
for ( obj = ch->carrying; obj != NULL; obj = obj_next ){
obj_next = obj->next_content;
affect_strip_obj( obj, gsn_bloodvow);
REMOVE_BIT(obj->extra_flags,ITEM_INVENTORY);
obj_from_char( obj );
if (obj->item_type == ITEM_POTION)
obj->timer = number_range(500,1000);
if (obj->item_type == ITEM_HERB)
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) && !IS_NPC(ch))
{
/* Changed to instant poof for non-keys: Viri */
if (obj->item_type == ITEM_KEY){
obj->timer = number_range(5,10);
REMOVE_BIT(obj->extra_flags,ITEM_ROT_DEATH);
}
else{
act("$p crumbles to dust.", ch, obj, NULL, TO_CHAR);
extract_obj(obj);
continue;
}
}
REMOVE_BIT(obj->extra_flags,ITEM_VIS_DEATH);
if (!can_exist( obj->pIndexData ))
extract_obj( obj );
else{
obj_to_room( obj, ch->in_room );
if (is_affected_obj(obj, gsn_levitate))
act( "$p slowly rises and stays suspended in mid-air.", ch, obj, NULL, TO_ALL );
}
}
act("$n's body disintegrates into dust.",ch,NULL,NULL,TO_ROOM);
}
void death_cry( CHAR_DATA *ch, CHAR_DATA* killer )
{
ROOM_INDEX_DATA *was_in_room;
AFFECT_DATA *paf;
CHAR_DATA* vch;
char *msg = "You hear $n's death cry.";
bool fFound = FALSE;
int door, vnum = 0;
if (ch->in_room == NULL)
return;
switch ( number_range(0,19))
{
case 0: msg = "$n hits the ground ... DEAD."; break;
case 1: msg = "$n splatters blood on your armor."; break;
case 2: if (IS_SET(ch->parts,PART_GUTS))
{ msg = "$n spills $s guts all over the floor."; vnum = OBJ_VNUM_GUTS; } break;
case 3: if (IS_SET(ch->parts,PART_HEAD))
{ msg = "$n's severed head plops on the ground."; vnum = OBJ_VNUM_SEVERED_HEAD; } break;
case 4: if (IS_SET(ch->parts,PART_HEART))
{ msg = "$n's heart is torn from $s chest."; vnum = OBJ_VNUM_TORN_HEART; } break;
case 5: if (IS_SET(ch->parts,PART_ARMS))
{ msg = "$n's arm is dismembered from $s dead body."; vnum = OBJ_VNUM_SLICED_ARM; } break;
case 6: if (IS_SET(ch->parts,PART_LEGS))
{ msg = "$n's leg is dismembered from $s dead body."; vnum = OBJ_VNUM_SLICED_LEG; } break;
case 7: if (IS_SET(ch->parts,PART_BRAINS))
{ msg = "$n's head is shattered, and $s brains splash all over you."; vnum = OBJ_VNUM_BRAINS; } break;
case 8: if (IS_SET(ch->parts,PART_HANDS))
{ msg = "$n's hand is ripped from $s arm."; vnum = OBJ_VNUM_HAND; } break;
case 9: if (IS_SET(ch->parts,PART_FEET))
{ msg = "$n's foot is ripped from $s leg."; vnum = OBJ_VNUM_FOOT; } break;
case 10: if (IS_SET(ch->parts,PART_FINGERS))
{ msg = "$n's fingers are severed from $s hand."; vnum = OBJ_VNUM_FINGERS; } break;
case 11: if (IS_SET(ch->parts,PART_EAR))
{ msg = "$n's ear is ripped off of $s head."; vnum = OBJ_VNUM_EAR; } break;
case 12: if (IS_SET(ch->parts,PART_EYE))
{ msg = "$n's eyes are pulled out of $s head."; vnum = OBJ_VNUM_EYES; } break;
case 13: if (IS_SET(ch->parts,PART_LONG_TONGUE))
{ msg = "$n's tongue is ripped out of $s head."; vnum = OBJ_VNUM_TONGUE; } break;
case 14: if (IS_SET(ch->parts,PART_WINGS))
{ msg = "$n's wings slowly float to the ground."; vnum = OBJ_VNUM_WINGS; } break;
case 15: if (IS_SET(ch->parts,PART_TAIL))
{ msg = "$n's tail is severed from $s dead body."; vnum = OBJ_VNUM_TAIL; } break;
case 16: if (IS_SET(ch->parts,PART_CLAWS))
{ msg = "$n's claws fall to the ground."; vnum = OBJ_VNUM_CLAWS; } break;
case 17: if (IS_SET(ch->parts,PART_FANGS))
{ msg = "$n's fangs are extracted from $s head."; vnum = OBJ_VNUM_FANGS; } break;
case 18: if (IS_SET(ch->parts,PART_HORNS))
{ msg = "$n's horn is extracted from $s head."; vnum = OBJ_VNUM_HORN; } break;
case 19: if (IS_SET(ch->parts,PART_TUSKS))
{ msg = "$n's tusk is extracted from $s head."; vnum = OBJ_VNUM_TUSK; } break;
}
for (vch = killer->in_room->people; vch; vch = vch->next_in_room){
if (is_same_group(vch, killer) && vch->race == race_lookup("illithid")){
fFound = TRUE;
break;
}
}
if (fFound && vnum){
act("You expertly extract a still warm brain from $n's corpse.", ch, NULL, vch, TO_VICT);
vnum = OBJ_VNUM_BRAINS;
act( "$N expertly extracts a still warm brain from $n's corpse.", ch, NULL, vch, TO_NOTVICT);
}
else
act( msg, ch, NULL, killer, TO_ROOM );
if ( vnum != 0 )
{
char buf[MSL];
char *name = IS_NPC(ch) ? ch->short_descr : ch->name;
OBJ_DATA *obj = create_object( get_obj_index( vnum ), 0);
obj->timer = number_range( 4, 7 );
sprintf( buf, obj->short_descr, name );
free_string( obj->short_descr );
obj->short_descr = str_dup( buf );
sprintf( buf, obj->description, name );
free_string( obj->description );
obj->description = str_dup( buf );
if (obj->item_type == ITEM_FOOD)
{
if (IS_SET(ch->form,FORM_POISON))
obj->value[3] = 1;
else if (!IS_SET(ch->form,FORM_EDIBLE))
obj->item_type = ITEM_TRASH;
}
if (vnum == OBJ_VNUM_SEVERED_HEAD)
{
paf = new_affect();
paf->type = 0;
paf->level = ch->level;
paf->duration = -1;
paf->location = APPLY_DAMROLL;
paf->modifier = ch->level/10;
paf->bitvector = 0;
paf->next = obj->affected;
obj->affected = paf;
}
if (vnum == OBJ_VNUM_EYES)
{
paf = new_affect();
paf->type = 0;
paf->level = ch->level;
paf->duration = -1;
paf->location = APPLY_HITROLL;
paf->modifier = ch->level/10;
paf->bitvector = 0;
paf->next = obj->affected;
obj->affected = paf;
}
if (vnum == OBJ_VNUM_TAIL || vnum == OBJ_VNUM_FANGS || vnum == OBJ_VNUM_HORN || vnum == OBJ_VNUM_TUSK)
{
obj->value[1] = number_range(ch->level-3, ch->level+3)/3 + 2;
obj->value[2] = 2;
}
if (vnum == OBJ_VNUM_CLAWS)
obj->level = ch->level;
obj_to_room( obj, ch->in_room );
}
if ( IS_NPC(ch) )
msg = "You hear something's death cry.";
else
msg = "You hear someone's death cry.";
was_in_room = ch->in_room;
for ( door = 0; door <= 5; door++ )
{
EXIT_DATA *pexit;
if ( was_in_room != NULL && ( pexit = was_in_room->exit[door] ) != NULL
&& pexit->to_room != NULL && pexit->to_room != was_in_room )
{
ch->in_room = pexit->to_room;
act( msg, ch, NULL, NULL, TO_ROOM );
}
}
ch->in_room = was_in_room;
}
/* run to check if a crusader wtih psalm of one god is about in group */
bool onegod_resurrect(CHAR_DATA* victim, ROOM_INDEX_DATA* room){
CHAR_DATA* vch;
if (IS_NPC(victim))
return FALSE;
for (vch = player_list; vch; vch = vch->next){
if (!IS_NPC(vch)
&& vch->hit < vch->max_hit / 3
&& vch != victim
&& is_same_group(vch, victim)
&& is_affected(vch, gsn_ogtrium))
return TRUE;
}
return FALSE;
}
void _raw_kill( CHAR_DATA *ch, CHAR_DATA *victim, bool fBountyCheck)
{
OBJ_DATA *tattoo = NULL, *crown = NULL, *locker = NULL;
OBJ_DATA* corpse = NULL;
OBJ_DATA* obj;
CHAR_DATA *vch, *vch_next;
AFFECT_DATA af, *paf, *paf_next;
bool is_lag = FALSE;
bool fRes = FALSE;
bool fNoDeathCount = FALSE;
char strsave[MIL];
//PREKILLCHECK
if (PREKILL_CHECK(ch, victim) == -1)
bug("Error at: PREKILL_CHECK\n\r", 0);
//PREDEATH
if (PREDEATH_CHECK(ch, victim) == -1)
bug("Error at: PREDEATH_CHECK\n\r", 0);
/* check for one god resurrection */
if (victim->in_room)
fRes = onegod_resurrect(victim, victim->in_room);
//Continuum message.
continuum(victim, CONTINUUM_DEATH);
if (IS_NPC(ch)){
int pos = ch->position;
/* we save position so we can allow mobs to do things on death. */
ch->position = POS_STANDING;
if (HAS_TRIGGER_MOB(ch, TRIG_KILL)){
p_percent_trigger(ch, NULL, NULL, victim, NULL, NULL, TRIG_KILL);
if (ch == NULL || victim == NULL || ch->in_room == NULL || victim->in_room == NULL)
return;
}
ch->position = pos;
}
/* Objects */
for ( obj = ch->carrying; obj != NULL; obj = obj->next_content ){
if (HAS_TRIGGER_OBJ(obj, TRIG_KILL)){
p_percent_trigger(NULL, obj, NULL, victim, NULL, NULL, TRIG_KILL);
if (ch == NULL || victim == NULL || ch->in_room == NULL || victim->in_room == NULL)
return;
}
}
if (IS_NPC(victim)){
int pos = victim->position;
/* we save position so we can allow mobs to do things on death. */
victim->position = POS_STANDING;
if (HAS_TRIGGER_MOB(victim, TRIG_DEATH)){
p_percent_trigger(victim, NULL, NULL, ch, NULL, NULL, TRIG_DEATH);
if (ch == NULL || victim == NULL || ch->in_room == NULL || victim->in_room == NULL)
return;
}
victim->position = pos;
}
/* Objects */
for ( obj = victim->carrying; obj != NULL; obj = obj->next_content ){
if (HAS_TRIGGER_OBJ(obj, TRIG_DEATH)){
p_percent_trigger(NULL, obj, NULL, victim, NULL, NULL, TRIG_DEATH);
if (ch == NULL || victim == NULL || ch->in_room == NULL || victim->in_room == NULL)
return;
}
}
/* Room Triggers */
if (ch->in_room){
if (HAS_TRIGGER_ROOM(ch->in_room, TRIG_KILL)){
p_percent_trigger(NULL, NULL, ch->in_room, ch, NULL, NULL, TRIG_KILL);
if (ch == NULL || victim == NULL || ch->in_room == NULL || victim->in_room == NULL)
return;
}
sprintf( log_buf, "`&%s got toasted by %s at %s [room %d]``",
(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(ch) && IS_IMMORTAL(ch) && victim->level >= 50)
nlogf( "%s imm killed by %s at %d", victim->name, (IS_NPC(ch) ? ch->short_descr : ch->name), ch->in_room->vnum );
if (!IS_NPC(victim)){
nlogf( "%s killed by %s at %d", victim->name, (IS_NPC(ch) ? ch->short_descr : ch->name), ch->in_room->vnum );
wiznet(log_buf,NULL,NULL,WIZ_DEATHS,0,0);
}
}//end if in room
/* race kills increase */
if (!IS_NPC(ch) && victim->race < MAX_PC_RACE && victim->race > 0 && ch->pcdata->race_kills[victim->race] < 255){
int aos_level = ch->pcdata->race_kills[victim->race] / AOS_KILLS_PER_LEVEL;
ch->pcdata->race_kills[victim->race] += IS_NPC(victim) ? 1 : 5;
if (ch->pcdata->race_kills[victim->race] / AOS_KILLS_PER_LEVEL != aos_level){
sendf(ch, "Your %s reputation has decreased. (see \"help reputation\")\n\r", pc_race_table[victim->race].name);
}
}
/* crown, lockers and tattoo */
if (!IS_NPC(victim)){
if ( (tattoo = get_eq_char(victim, WEAR_TATTOO)) != NULL)
obj_from_char(tattoo);
if ( (crown = get_eq_char(victim, WEAR_HEAD)) != NULL){
if(crown->vnum == OBJ_VNUM_CROWN)
obj_from_char(crown);
else
crown = NULL;
}
for (locker = victim->carrying; locker; locker = locker->next_content){
if (locker->vnum == OBJ_VNUM_LOCKER){
obj_from_char( locker );
break;
}
}
}
if ( !IS_NPC(victim) ){
/* CTF item transfer, checks all cases where victim was a PC */
handle_ctf_kill( ch, victim );
/*
warmaster main cabal members (do not have subcabal) do not get deaths
counted
*/
if (victim->pCabal && victim->pCabal->parent == NULL
&& IS_CABAL(victim->pCabal, CABAL_NOMAGIC)){
fNoDeathCount = TRUE;
}
else if (crown == NULL)
victim->pcdata->dall++;
else
victim->pcdata->dall += 5;
if (!IS_NPC(ch)){
bool fRougeB = FALSE;
victim->pcdata->dpc++;
mud_data.deaths++;
if (ch != victim)
ch->pcdata->kpc++;
//penalty warning for goods killing goods
if (ch != victim && ch->level > 15
&& IS_GOOD(ch) && IS_GOOD(victim)
&& !IS_IMMORTAL(ch) && !IS_IMMORTAL(victim)){
char buf[MIL];
sprintf(buf, warn_table[WARN_GOODPK].subj, ch->name, victim->name);
do_hal("immortal", buf, warn_table[WARN_GOODPK].text, NOTE_PENALTY);
}
/* CTF item transfer */
handle_ctf_kill( ch, victim );
/* penatly for killing pcs if a bounty is present */
if (fBountyCheck)
fRougeB = check_rouge_bounty( ch, -50 );
/* cabal update to points */
if (!fRougeB
&& fBountyCheck
&& ch->pCabal
&& victim->pCabal )
cp_event(ch, victim, NULL, CP_EVENT_PC);
/* avatar */
divfavor_update(ch, victim);
/* raid mob */
raidmob_check( ch, victim );
/* stalker vs unnatural reward */
stalker_reward( ch, victim );
/* MURDER CRIME CHECK */
if (ch->in_room && is_crime(ch->in_room, CRIME_MURDER, victim)){
set_crime(ch, victim, ch->in_room->area, CRIME_MURDER);
}
}
else
{
/* Give credit to master of charmies if they kill */
if (IS_AFFECTED(ch,AFF_CHARM)){
if (ch->master != NULL && !IS_NPC(ch->master)){
bool fRougeB = FALSE;
ch->master->pcdata->kpc++;
victim->pcdata->dpc++;
/* cabal update to points */
/* penatly for killing pcs if a bounty is present */
if (fBountyCheck)
fRougeB = check_rouge_bounty( ch->master, -50 );
/* cabal update to points */
if (!fRougeB
&& fBountyCheck
&& ch->master->pCabal
&& victim->pCabal)
cp_event(ch->master, victim, NULL, CP_EVENT_PC);
/* avatar */
divfavor_update(ch, victim);
/* raid mob */
raidmob_check( ch, victim );
/* stalker vs unnatural reward */
stalker_reward( ch, victim );
}
else
victim->pcdata->dnpc++;
}
else
victim->pcdata->dnpc++;
mud_data.deaths++;
}
/* check for PK warning violation */
if (!IS_NPC(ch) && ch != victim && IS_GAME(ch, GAME_PKWARN)){
char buf[MIL];
sprintf(buf, warn_table[WARN_PK_VIO].subj, ch->name);
do_hal("immortal", buf, warn_table[WARN_PK_VIO].text, NOTE_PENALTY);
}
}
else
{
wiznet(log_buf,NULL,NULL,WIZ_MOBDEATHS,0,0);
if (!IS_NPC(ch)){
ch->pcdata->knpc++;
/* ASSAULT CRIME CHECK */
if (ch->in_room && is_crime(ch->in_room, CRIME_ASSAULT, victim)){
set_crime(ch, victim, ch->in_room->area, CRIME_ASSAULT);
}
}
/* raid mob */
raidmob_check( ch, victim );
/* quest check */
QuestKillCheck(ch, victim );
}//END NPC DEATH
stop_fighting( victim, TRUE );
if (!IS_NPC(victim) && IS_SET(victim->act, PLR_DOOF))
REMOVE_BIT(victim->act, PLR_DOOF);
if (IS_NPC(victim)){
if (victim->pIndexData->progtypes & DEATH_PROG)
mprog_death_trigger( ch, victim );
}
if (!IS_NPC(victim))
{
if (!is_affected(victim,gsn_mortally_wounded))
death_cry( victim, ch );
for ( vch = char_list; vch != NULL; vch = vch_next )
{
vch_next = vch->next;
if (IS_NPC(vch) && vch->hunting != NULL && vch->hunting == victim )
{
vch->hunting = NULL;
if (IS_SET(vch->act,ACT_AGGRESSIVE))
{
act( "$n slowly disappears.",vch,NULL,NULL,TO_ROOM );
extract_char( vch, TRUE );
}
}
}
}
else
death_cry( victim, ch );
/* Cheat check */
if ( (IS_IMMORTAL(ch)
|| (ch->leader && IS_IMMORTAL(ch->leader))
|| (ch->master && IS_IMMORTAL(ch->master))
|| (IS_NPC(ch) && ch->desc && !is_affected(ch, gsn_linked_mind)))
&& IS_NPC(victim) ){
OBJ_DATA* obj;
char buf[MIL];
for ( obj = victim->carrying; obj != NULL; obj = obj->next_content ){
if (IS_LIMITED(obj)
&& !IS_SET(obj->wear_flags, ITEM_HAS_OWNER)){
SET_BIT(obj->extra_flags, ITEM_STAIN);
sprintf(buf, "%s stained by %s.", obj->short_descr, PERS2(ch));
send_to_char(buf, ch);
log_string(buf);
}
}
}
if (!IS_IMMORTAL(victim)
&& ((IS_NPC(victim)
&& IS_SET(victim->form,FORM_INSTANT_DECAY))
|| IS_SET(victim->act,ACT_UNDEAD)))
dump_corpse( victim );
else
corpse = make_corpse( victim );
/* For future resurrection */
if (corpse && !IS_NPC(victim)){
af.type = gsn_resurrection;
af.level = victim->pcdata->dall % 5 == 0 ? TRUE : FALSE;
af.duration = 24;
af.where = TO_NONE;
/* bit vector has original duration */
af.bitvector = af.duration;
af.location = APPLY_NONE;
/* exp is refunded based on duration remaning when accepted */
/* set to 0 if PC kill */
af.modifier = ( (IS_NPC(ch) && !IS_SET(ch->act2, ACT_NOLOSS)) || ch == victim) ? UMIN(15000,UMIN(exp_per_level(victim,victim->level),victim->exp/10)) : 0;
if ( (paf = affect_to_obj(corpse, &af)) != NULL)
string_to_affect(paf, victim->name);
/* for future avengers */
af.type = skill_lookup("avenger");
af.level = 60;
af.duration = -1;
af.where = TO_NONE;
af.bitvector = 0;
af.location = APPLY_NONE;
/* modifier stores if it was an npc that killed the person */
/* if it was npc then the npc gets an avenger too with matching. */
/* id in modifier */
if (IS_NPC(ch)){
af.modifier = ch->id;
if ( (paf = affect_to_obj(corpse, &af)) != NULL)
string_to_affect(paf, ch->name);
affect_to_char(ch, &af);
}
else{
af.modifier = 0;
if ( (paf = affect_to_obj(corpse, &af)) != NULL)
string_to_affect(paf, ch->name);
}
}
if ( IS_NPC(victim) )
{
kill_table[URANGE(0, victim->level, MAX_LEVEL-1)].killed++;
if (victim->summoner
&& !IS_NPC(victim->summoner)
&& victim->summoner->pcdata->pStallion
&& victim->pIndexData == victim->summoner->pcdata->pStallion
&& victim->summoner->in_room
&& victim->in_room
&& victim->in_room == victim->summoner->in_room){
victim->summoner->pcdata->pStallion = NULL;
act("You fall flat on your back!",victim->summoner,NULL,NULL,TO_CHAR);
act("$n falls flat on $s back!",victim->summoner,NULL,NULL,TO_ROOM);
victim->summoner->position = POS_RESTING;
}
if (victim->pIndexData->vnum >= MOB_VNUM_SERVANT_FIRE
&& victim->pIndexData->vnum <= MOB_VNUM_SERVANT_EARTH
&& victim->summoner != NULL
&& !IS_NPC(victim->summoner))
{
if (is_affected(victim->summoner,gsn_familiar_link))
{
AFFECT_DATA faf;
send_to_char("Your energy drains out as your familiar dies.\n\r",victim->summoner);
affect_strip(victim->summoner,gsn_familiar_link);
faf.where = TO_AFFECTS;
faf.type = gsn_drained;
faf.level = victim->level;
faf.duration = 12;
faf.modifier = 0;
faf.location = 0;
faf.bitvector = 0;
affect_to_char(victim->summoner,&faf);
}
victim->summoner->pcdata->familiar=NULL;
}
//POSTKILLCHECK
if (POSTKILL_CHECK(ch, victim) == -1)
bug("Error at: POSTKILL_CHECK\n\r", 0);
if (POSTDEATH_CHECK(ch, victim) == -1)
bug("Error at: POSTDEATH_CHECK\n\r", 0);
extract_char( victim, TRUE );
return;
}
//A check just in case.
if (IS_NPC(victim))
{
send_to_char("You turn into an invincible ghost for a few minutes.\n\r", victim);
send_to_char("As long as you don't attack anything.\n\r", victim);
}
else
{
sendf(victim, "As the cold chill of death descends upon you %s grants you yet another chance.\n\r"\
"You have been granted a temporary sanctuary as an invincible ghost.\n\rAs long as you don't attack"\
" anything.\n\r", (victim->pcdata->deity[0] == '\0' ? "The Creator" : victim->pcdata->deity));
}
//POSTKILLCHECK
if (POSTKILL_CHECK(ch, victim) == -1)
bug("Error at: POSTKILL_CHECK\n\r", 0);
if (POSTDEATH_CHECK(ch, victim) == -1)
bug("Error at: POSTDEATH_CHECK\n\r", 0);
if ((victim->alignment > 0 && victim->in_room == get_room_index( hometown_table[victim->hometown].g_vnum ) )
|| (victim->alignment == 0 && victim->in_room == get_room_index( hometown_table[victim->hometown].n_vnum ) )
|| (victim->alignment < 0 && victim->in_room == get_room_index( hometown_table[victim->hometown].e_vnum ) ))
is_lag = TRUE;
extract_char( victim, FALSE );
victim->summoner=NULL;
//strip effects.
for (paf = victim->affected; paf; paf = paf_next ){
paf_next = paf->next;
if (paf->type == gsn_wanted
|| paf->type == gsn_exile
|| paf->type == gsn_mark_fear
|| paf->type == gen_unlife
|| (IS_GEN(paf->type) && IS_SET(effect_table[GN_POS(paf->type)].flags, EFF_F1_NODEATH))
|| IS_GNBIT(paf->type, GN_NODEATH))
continue;
else
affect_remove( victim, paf );
}
while (victim->affected2)
song_affect_remove( victim, victim->affected2);
clear_nskill(victim);
if (victim->race == grn_vampire){
free_string( victim->short_descr );
victim->short_descr = str_dup ( "" );
victim->dam_type = 17;
}
if (victim->race == grn_werebeast){
victim->dam_type = 17;
}
victim->position = POS_STANDING;
victim->hit = 1;
victim->mana = 1;
victim->move = UMAX( 100, victim->move );
if (is_lag)
WAIT_STATE2(victim,24);
if (!IS_NPC(victim))
{
victim->pcdata->ghost = time(NULL);
//unbloody the victim
victim->pcdata->fight_delay = mud_data.current_time - 600;
victim->pcdata->pk_delay = mud_data.current_time - 600;
victim->pcdata->condition[COND_HUNGER]=48;
victim->pcdata->condition[COND_THIRST]=48;
if (is_affected(victim,gsn_familiar_link))
{
send_to_char("Your energy drains out as you lose link with your familiar.\n\r",victim);
affect_strip(victim,gsn_familiar_link);
}
if (!IS_NPC(victim) && victim->pcdata->familiar != NULL)
{
extract_char( victim->pcdata->familiar, TRUE );
victim->pcdata->familiar=NULL;
}
if (victim->pcdata->dall > 60 && get_trust(victim) < MASTER)
{
send_to_char("You have died due to failing health.\n\r",victim);
sprintf( strsave, "%s%s", PLAYER_DIR, capitalize( victim->name ) );
wiznet("$N dies due to failing health.",victim,NULL,0,0,0);
victim->pcdata->dall = 0;
if (victim->level > 20)
deny_record(victim);
if (victim->pCabal){
CABAL_DATA* pCab = victim->pCabal;
update_cabal_skills(victim, victim->pCabal, TRUE, TRUE);
char_from_cabal( victim );
CHANGE_CABAL(pCab);
save_cabals( TRUE, NULL );
}
if (HAS_CLAN(victim)){
CharFromClan( victim );
}
if (victim->pcdata->pbounty){
rem_bounty( victim->pcdata->pbounty );
free_bounty( victim->pcdata->pbounty );
}
extract_char( victim, TRUE );
if ( victim->desc != NULL )
close_socket( victim->desc );
unlink(strsave);
return;
}
if ( !IS_MASTER(victim)
&& victim->perm_stat[STAT_CON] > 3
&& !fNoDeathCount){
if (victim->pcdata->dall%5 == 0)
{
victim->perm_stat[STAT_CON]--;
send_to_char("You feel less healthy.\n\r",victim);
}
}
if (tattoo != NULL) {
obj_to_char(tattoo, victim);
equip_char(victim, tattoo, WEAR_TATTOO);
}
if (crown != NULL) {
obj_to_char(crown, victim);
equip_char(victim, crown, WEAR_HEAD);
}
if (locker != NULL){
obj_to_char( locker, victim );
}
/* Cabal Requip */
cabal_requip(victim);
save_char_obj( victim );
if (fRes){
AFFECT_DATA* paf, af;
/* all seems ok, set an affect to let the player accept */
af.type = gsn_resurrection;
af.duration = 6;
af.level = victim->level;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
paf = affect_to_char(victim, &af);
string_to_affect(paf, ch->name);
act("$n has called onto $g to grant you a chance for a new life.\n\r"\
"Use \"accept\" to accept the resurrection.", ch, NULL, victim, TO_VICT);
}
}//END !IS_NPC(vic)
}
void raw_kill( CHAR_DATA *ch, CHAR_DATA *victim ){
_raw_kill( ch, victim, TRUE );
}
void group_gain( CHAR_DATA *ch, CHAR_DATA *victim )
{
CHAR_DATA *gch, *gch_next_in_room;
int xp, members = 0, group_levels = 0;
// char buf[MAX_STRING_LENGTH];
if ( victim == ch )
return;
for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room )
if ( is_same_group( gch, ch ) )
{
if (IS_NPC(gch))
continue;
members++;
group_levels += gch->level;
}
if ( members == 0 && !IS_NPC(ch) )
{
bug( "Group_gain: members.", members );
members = 1;
group_levels = ch->level ;
}
for ( gch = ch->in_room->people; gch != NULL; gch = gch_next_in_room )
{
gch_next_in_room = gch->next_in_room;
if ( !is_same_group( gch, ch ) || IS_NPC(gch))
continue;
xp = xp_compute( gch, victim, group_levels, members );
if (IS_PERK(gch, PERK_ADVENTURER))
xp = 115 * xp / 100;
//DIETY CHECK
if (!IS_NPC(gch) && !IS_IMMORTAL(gch) && gch->level >= 10 && gch->pcdata->way == 0) {
send_to_char("`@\n\rYou may not proceed past 10th rank until "\
"you choose your religion.\n\rUse <religion> for more "\
"info.``\n\r\n\r", gch);
}
else if (!IS_NPC(gch) && !IS_IMMORTAL(gch) && gch->level >= 15
&& IS_SET(gch->act2, PLR_DESC)) {
send_to_char("`@\n\rYou may not proceed past 15th rank until "\
"your description has been approved."\
"\n\rUse <help desc> for more info.``\n\r\n\r", gch);
}
else if (!IS_GAME(gch, GAME_NOEXP))
{
sendf( gch, "You receive %d experience points.\n\r", xp );
gain_exp( gch, xp );
}
if (IS_AFFECTED2(gch,AFF_RAGE))
{
REMOVE_BIT(gch->affected2_by,AFF_RAGE);
affect_strip(gch,gsn_rage);
act("You snap out of your madness at the death of your opponent.",gch,NULL,NULL,TO_CHAR);
act("$n gasps for air as $e snaps out of $s insanity.",gch,NULL,NULL,TO_ROOM);
gch->hit -= (gch->level * gch->perm_stat[STAT_CON]) /3;
if (IS_IMMORTAL(gch))
gch->hit = UMAX(1,gch->hit);
if (gch->hit < -2)
{
int shock_mod = (25 * (0 - gch->hit)) / gch->max_hit;
if (number_percent( ) < con_app[UMAX(1,gch->perm_stat[STAT_CON] - shock_mod)].shock)
{
act_new("Your body suddenly awakens to the wounds you've sustained and you lose consciousness.",gch,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n suddenly clutches $s wounds and slumps to the ground, unconscious.",gch,NULL,NULL,TO_ROOM);
gch->hit = -2;
gch->position = POS_STUNNED;
act( "$n is stunned, but will probably recover.",gch, NULL, NULL, TO_ROOM );
act_new("You are stunned, but will probably recover.",gch, NULL, NULL, TO_CHAR, POS_DEAD );
}
else
{
act_new("Your body could not sustain the injuries you've suffered.",gch,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n suddenly clutches $s wounds and slumps to the ground.",gch,NULL,NULL,TO_ROOM);
act( "$n is DEAD!!",gch, 0, 0, TO_ROOM );
act_new( "You have been `1KILLED``!!", gch,NULL,NULL,TO_CHAR,POS_DEAD);
raw_kill( gch, gch );
}
}
}
}
}
int xp_compute( CHAR_DATA *gch, CHAR_DATA *victim, int total_levels, int members )
{
int xp, base_exp, level_range = victim->level - gch->level;
if (IS_NPC(victim) && IS_SET(victim->act2,ACT_NOEXP))
return 0;
else if (IS_NPC(victim) && IS_SET(victim->act, ACT_RAIDER)){
level_range = 9;
members = UMAX(members, 3);
total_levels = UMAX(total_levels, 3 * gch->level);
}
switch (level_range)
{
default : base_exp = 0; break;
case -9 : base_exp = 1; break;
case -8 : base_exp = 2; break;
case -7 : base_exp = 5; break;
case -6 : base_exp = 9; break;
case -5 : base_exp = 11; break;
case -4 : base_exp = 22; break;
case -3 : base_exp = 33; break;
case -2 : base_exp = 50; break;
case -1 : base_exp = 66; break;
case 0 : base_exp = 83; break;
case 1 : base_exp = 105; break;
case 2 : base_exp = 130; break;
case 3 : base_exp = 165; break;
case 4 : base_exp = 200; break;
case 5 : base_exp = 240; break;
case 6 : base_exp = 260; break;
case 7 : base_exp = 265; break;
case 8 : base_exp = 270; break;
case 9 : base_exp = 270; break;
}
if (level_range > 9)
base_exp = 270;
if (gch->in_room && IS_AREA(gch->in_room->area, AREA_MUDSCHOOL)){
base_exp = 3 * base_exp;
}
/* align based computations */
if (IS_NPC(victim) && IS_SET(victim->act,ACT_NOALIGN))
xp = base_exp;
else if ((IS_EVIL(gch) && IS_GOOD(victim))
|| (IS_EVIL(victim) && IS_GOOD(gch)))
xp = base_exp * 8/5;
else if ( IS_GOOD(gch)
&& IS_GOOD(victim) && !IS_AFFECTED(victim, AFF_CHARM)
&& !is_affected(gch, gsn_damnation)) {
xp = -5000;
if (!IS_NPC(victim) && IS_SET(victim->act,PLR_WANTED))
xp = 0;
else{
sendf( gch, "The heavens frown upon your actions.\n\r");
spell_damnation(gsn_damnation, gch->level, gch, gch,TARGET_CHAR);
}
return xp;
}
else if ( !IS_NEUTRAL(gch) && IS_NEUTRAL(victim) )
xp = base_exp * 1.1;
else if ( IS_NEUTRAL(gch) && !IS_NEUTRAL(victim) )
xp = base_exp * 1.3;
else xp = base_exp;
/* randomize the rewards */
xp = number_range (xp * 3/4, xp * 5/4);
/* the xp is distributed based on level, high level characters in a group get bigger share */
xp = xp * gch->level/total_levels;
/* group bonuses */
if (members == 2)
xp = 2 * xp;
else if (members > 2 && members < 5 )
xp = 4 * xp;
return xp;
}
inline char* parse_dam_message(CHAR_DATA* ch, CHAR_DATA* victim, CHAR_DATA* to,
OBJ_DATA* obj, const char* string, bool fMiss){
static char * const him_her [] = { "it", "him", "her" };
static char * const his_her [] = { "its", "his", "her" };
static char dest[256];
/* color prefixes */
static char* nor = "`1"; //normal red
static char* com = "`3"; //common damage
static char* oth = "`8"; //other damage
static char* mis = "`6"; //miss
const char* sptr = string;
char* dptr = dest;
const char* i;
/* Init */
dest[0] = '\0';
/* safety */
if (!ch || !victim || !to)
return dest;
/* begin the format */
while (*sptr != '\0'){
if (*sptr != '$'){
*dptr++ = *sptr++;
continue;
}
/* hit a format character */
switch ( *++sptr ){
default: i = "< @@@ >"; break;
case 'n': i = PERS(ch, to); break;
case 'N': i = PERS(victim, to); break;
case 'p': i = obj ? (can_see_obj(to, obj) ? obj->short_descr :
"something") : "< @@@ >"; break;
case 'c':
if (fMiss)
i = mis; /* MISS */
else if (!IS_COLOR(to, COLOR_DAMAGE))
i = nor; /* NON COLORED DAMAGE */
else if (victim == to)
i = nor; /* SHOWN TO VICTIM */
else if (ch == to)
i = com; /* SHOWN TO ATTACKER */
else if (to->fighting && ch->fighting && to->fighting == ch->fighting
&& is_same_group(ch, to))
i = com; /* SHOWN TO GROUP IF COMMON TARGET */
else
i = oth; /* DAMAGE SHOWN TO EVERYONE ELSE */
break;
case 'm': i = (ch->doppel != NULL && !IS_IMMORTAL(to)
&& is_affected(ch, gsn_doppelganger) ) ?
him_her[URANGE(0,ch->doppel->sex,2)] : him_her[URANGE(0,ch->sex,2)];
break;
case 's': i = (ch->doppel != NULL && !IS_IMMORTAL(to)
&& is_affected(ch,gsn_doppelganger)) ?
his_her[URANGE(0,ch->doppel->sex,2)] :
his_her[URANGE(0,ch->sex,2)];
break;
}
++sptr;
while ( (*dptr = *i) != '\0' ){
++dptr, ++i;
}
}
/* formatting done */
*dptr++ = '\n';
*dptr++ = '\r';
*dptr++ = '\0';
dest[0] = UPPER(dest[0]);
return dest;
}
void dam_message( CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA* obj, int dam, int dt, bool immune, bool fVirt, int sn, bool fShow ){
char buf1[256], buf2[256], buf3[256];
char ori_buf[MIL];
int len;
static ROOM_INDEX_DATA* room;
static CHAR_DATA* vch, *vch_next;
static Double_List * tmp_list;
const char *vs, *vp, *attack;
char punct;
/* origin strings (origin pointer poinst to these or ori_buf) */
static char * ori_obj = "$p";
static char * ori_ch = "$n";
char * origin = ori_ch;
if (ch == NULL || victim == NULL)
return;
//DAMAGE VERB SELECTION
if ( dam == 0 ) { vs = "miss``"; vp = "misses``";}
else if ( dam <= 4 ) { vs = "scratch``"; vp = "scratches``"; }
else if ( dam <= 8 ) { vs = "graze``"; vp = "grazes``"; }
else if ( dam <= 12 ) { vs = "hit``"; vp = "hits``"; }
else if ( dam <= 16 ) { vs = "injure``"; vp = "injures``"; }
else if ( dam <= 20 ) { vs = "wound``"; vp = "wounds``"; }
else if ( dam <= 24 ) { vs = "maul``"; vp = "mauls``"; }
else if ( dam <= 28 ) { vs = "decimate``"; vp = "decimates``"; }
else if ( dam <= 32 ) { vs = "devastate``"; vp = "devastates``"; }
else if ( dam <= 36 ) { vs = "maim``"; vp = "maims``"; }
else if ( dam <= 42 ) { vs = "MUTILATE``"; vp = "MUTILATES``"; }
else if ( dam <= 52 ) { vs = "LACERATE``"; vp = "LACERATES``"; }
else if ( dam <= 65 ) { vs = "DISMEMBER``"; vp = "DISMEMBERS``"; }
else if ( dam <= 80 ) { vs = "MASSACRE``"; vp = "MASSACRES``"; }
else if ( dam <= 100 ) { vs = "MANGLE``"; vp = "MANGLES``"; }
else if ( dam <= 130 ) { vs = "*** DEMOLISH ***``"; vp = "*** DEMOLISHES ***``"; }
else if ( dam <= 175) { vs = "*** OBLITERATE ***``"; vp = "*** OBLITERATES ***``"; }
else if ( dam <= 250) { vs = "=== DISINTEGRATE ===``"; vp = "=== DISINTEGRATES ===``"; }
else if ( dam <= 325) {vs = ">>> ANNIHILATE <<<``"; vp = ">>> ANNIHILATES <<<``";}
else if ( dam <= 400) {vs = "<<< ERADICATE >>>``"; vp = "<<< ERADICATES >>>``";}
else{vs = "do UNSPEAKABLE things to``"; vp = "does UNSPEAKABLE things to``";}
//PUNCTUATION
punct = (dam <= 24) ? '.' : '!';
//ORIGIN
/* NOTICE: (viri)
The origin of damage for non-obj virtual attacks is
taken form the noun_damage of the sn.
As both dt and sn are under your control this gives
you quite a bit of control with picking origin (sn)
damage text (dt)
*/
/* select origin based on fvirtual objects status */
if (fVirt){
if (obj != NULL)
origin = ori_obj;
else{
strcpy(ori_buf, get_vir_attack(sn));
origin = ori_buf;
}
}
/* no damage noun case */
if ( dt == TYPE_HIT ){
if (ch == victim){
if (fVirt){
sprintf( buf1, "$n's %s $c%s $m%c",origin, vp, punct);
sprintf( buf2, "Your %s $c%s you%c",origin,vp,punct);
}
else{
sprintf( buf1, "$n $c%s $mself%c",vp, punct);
sprintf( buf2, "You $c%s yourself%c",vs,punct);
}
}
else{
if (fVirt){
sprintf( buf1, "$n's %s $c%s $N%c",origin, vp, punct);
sprintf( buf2, "Your %s $c%s $N%c",origin, vs, punct);
sprintf( buf3, "$n's %s $c%s you%c",origin, vp, punct);
}
else{
sprintf( buf1, "$n $c%s $N%c", vp, punct);
sprintf( buf2, "You $c%s $N%c", vs, punct);
sprintf( buf3, "$n $c%s you%c", vp, punct);
}
}
}
else{
/* normal damage text case */
if ( (attack = get_vir_attack(dt)) == NULL){
bug( "Dam_message: bad dt %d.", dt );
dt = TYPE_HIT;
attack = attack_table[0].name;
}
//check if the damage noun is a plural, then we use singular verbs for both
//ex: HELLSTREAM LACERATES but HELLSTREAMS LACERTATE
len = strlen( attack );
if (len > 0 && attack[ len - 1] == 's' && (len < 2 || attack[len - 2] != 's'))
vp = vs;
/* case of immunity */
if (immune){
if (ch == victim){
if (fVirt){
sprintf(buf1,"$n is unaffected by a %s's %s.",origin, attack);
}
else{
sprintf(buf1,"$n is unaffected by $s own %s.",attack);
}
sprintf(buf2,"Luckily, you are immune to that.");
} //END IMMUNE SELF
else{
if (fVirt){
sprintf(buf1,"$N is unaffected by a %s's %s!",origin, attack);
sprintf(buf2,"$N is unaffected by your %s's %s!",origin, attack);
sprintf(buf3,"a %s's %s is powerless against you.",origin, attack);
}
else{
sprintf(buf1,"$N is unaffected by $n's %s!",attack);
sprintf(buf2,"$N is unaffected by your %s!",attack);
sprintf(buf3,"$n's %s is powerless against you.",attack);
}
}//END IUMMUNE TARGET
}//END IMMUNE
else{
/* normal damage */
if (ch == victim){
if (dt == 1052){
sprintf( buf1, "The sun's %s $c%s $n%c", attack, vp, punct);
sprintf( buf2, "The sun's %s $c%s you%c", attack, vp, punct);
}
else{
if (fVirt){
sprintf( buf1, "%s%s's %s $c%s $m%c",
obj == NULL ? "a ":"", origin,attack,vp, punct);
sprintf( buf2, "%s%s's %s $c%s you%c",
obj == NULL ? "a ":"", origin,attack,vp, punct);
}
else{
sprintf( buf1, "$n's %s $c%s $m%c",attack, vp, punct);
sprintf( buf2, "Your %s $c%s you%c",attack ,vp, punct);
}
}//END HIT SELF
}
else{
if (fVirt){
sprintf( buf1, "%s%s's %s $c%s $N%c",
obj == NULL ? "a ":"", origin,attack, vp, punct);
sprintf( buf2, "%s%s's %s $c%s $N%c",
obj == NULL ? "Your ":"", origin, attack, vp, punct);
sprintf( buf3, "%s%s's %s $c%s you%c",
obj == NULL ? "a ":"", origin, attack, vp, punct);
}
else{
sprintf( buf1, "$n's %s $c%s $N%c", attack, vp, punct);
sprintf( buf2, "Your %s $c%s $N%c", attack, vp, punct);
sprintf( buf3, "$n's %s $c%s you%c", attack, vp, punct);
}
}//END HIT TARGET
}//END NON-IMMUNE
}
/* SHOW THE MESSAGES HERE */
/*
This is a simple version of ACT_NEW code, which only parses buf1-3
for six things:
$n = character
$N = victim
$m = character him_/her,
$c = color chance to damage if needed.
*/
/* first send the messages to character and victim */
if (IS_AWAKE(ch) && ch->desc && (ch->in_room == victim->in_room || fShow))
send_to_char(parse_dam_message(ch, victim, ch, obj, buf2, dam == 0), ch);
if (IS_AWAKE(victim) && victim->desc && ch != victim)
send_to_char(parse_dam_message(ch, victim, victim, obj, buf3, dam == 0), victim);
/* conditions when room message is not shown */
if (victim->in_room == NULL
/* Viri: Damage done about victim now,should not need this
|| (ch->in_room != victim->in_room && !fShow) //remote damage etc.
*/
|| (dt == 1052 && dam < 40) ) //sun hitting vamps
return;
else
room = victim->in_room;
/* print the messages to people in the room now */
for (vch = room->people; vch != NULL; vch = vch_next){
vch_next = vch->next_in_room;
if (vch != ch && vch != victim && IS_AWAKE(vch) && vch->desc){
send_to_char(parse_dam_message(ch, victim, vch, obj, buf1, dam == 0), vch);
}
}
/* watchrooms */
if ( (tmp_list = room->watch_vnums) == NULL)
return;
while (tmp_list != NULL) {
if ( (room = get_room_index ((int)tmp_list->cur_entry)) != NULL){
for (vch = room->people; vch != NULL; vch = vch_next){
vch_next = vch->next_in_room;
if (vch != victim && IS_AWAKE(vch) && vch->desc){
sendf (vch, "[%s] %s", ch->in_room->name,
parse_dam_message(ch, victim, vch, obj, buf1, dam == 0));
}
}//end for
}//end get room
tmp_list = tmp_list->next_node;
}//end while
/* Viri: LEFT HERE FOR REFENCE
if (ch == victim){
if( dt != 1052 || (dt == 1052 && dam > 40))
act(buf1,ch,NULL, NULL,TO_DAMCOLOR);
act(buf2,ch,NULL,NULL,TO_CHAR);
}
else{
if (ch->in_room == victim->in_room || fShow){
act( buf1, ch, obj, victim, TO_DAMCOLOR );
act( buf2, ch, obj, victim, TO_CHAR );
}
act( buf3, ch, obj, victim, TO_VICT );
}
*/
}
void do_kill( CHAR_DATA *ch, char *argument )
{
char buf[MSL], arg[MIL];
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, NULL, arg ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if (ch == victim){
send_to_char("Ouch!\n\r", ch);
return;
}
if ( is_safe( ch, victim ) )
return;
/* JUSTICE GUARD CAPTAIN CHECK */
if (IS_NPC(ch)
&& (ch->pIndexData->vnum == MOB_VNUM_SPECIAL_GUARD
|| ch->pIndexData->vnum == MOB_VNUM_HOUND)
&& ch->master && !IS_LEADER(ch->master)
&& !IS_AREA(ch->in_room->area, AREA_LAWFUL)){
if (ch->pIndexData->vnum == MOB_VNUM_SPECIAL_GUARD)
do_say(ch, "Do your own dirty work. Sir." );
else if (ch->pIndexData->vnum == MOB_VNUM_HOUND)
check_social(ch, "whine", "");
return;
}
if (IS_NPC(ch) && IS_SET(ch->act, ACT_NONCOMBAT)){
return;
}
if (ch->position == POS_FIGHTING)
{
if (victim == ch->fighting)
send_to_char( "You do the best you can!\n\r",ch);
else if ( !is_same_group(victim->fighting, ch) )
send_to_char( "One battle at a time.\n\r", ch );
else
{
sendf(ch,"You start aiming at %s.\n\r",PERS(victim,ch));
ch->fighting = victim;
}
return;
}
if (is_sheathed(ch)){
send_to_char("Your weapons are sheathed!\n\r", ch);
return;
}
if ( !IS_NPC(victim) )
{
send_to_char( "You must MURDER a player.\n\r", ch );
return;
}
if ( victim == ch )
{
send_to_char( "You hit yourself. Ouch!\n\r", ch );
return;
}
if ( is_safe( ch, victim ) )
return;
if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
{
sendf(ch, "%s is your beloved master.\n\r", PERS(victim,ch));
return;
}
WAIT_STATE2( ch, 1 * PULSE_VIOLENCE );
sprintf(buf, "Help! I am being attacked by %s!",PERS(ch,victim));
j_yell(victim, buf );
a_yell(ch,victim);
multi_hit( ch, victim, TYPE_UNDEFINED );
}
void do_murde( CHAR_DATA *ch, char *argument )
{
send_to_char( "If you want to MURDER, spell it out.\n\r", ch );
}
void do_murder( CHAR_DATA *ch, char *argument )
{
char buf[MSL], arg[MIL];
CHAR_DATA *victim;
one_argument( argument, arg );
if ( arg[0] == '\0' )
{
send_to_char( "Murder whom?\n\r", ch );
return;
}
if (IS_AFFECTED(ch,AFF_CHARM) || (IS_NPC(ch) && IS_SET(ch->act,ACT_PET)))
return;
if ( ( victim = get_char_room( ch, NULL, arg ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if ( victim == ch )
{
send_to_char( "Suicide is a mortal sin.\n\r", ch );
return;
}
if ( is_safe( ch, victim ) )
return;
if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
{
sendf(ch, "%s is your beloved master.\n\r", PERS(victim,ch));
return;
}
if ( ch->position == POS_FIGHTING )
{
send_to_char( "You do the best you can!\n\r", ch );
return;
}
if (is_sheathed(ch)){
send_to_char("Your weapons are sheathed!\n\r", ch);
return;
}
WAIT_STATE2( ch, 1 * PULSE_VIOLENCE );
sprintf(buf, "Help! I am being attacked by %s!",PERS(ch,victim));
j_yell(victim, buf);
a_yell(ch,victim);
multi_hit( ch, victim, TYPE_UNDEFINED );
if (ch->fighting == victim && !is_ghost(victim, 600) && get_skill(ch, gsn_throw) > 84){
throw_effect(ch, victim, FALSE);
}
}
//generates a random list of doors to check in room
//does not check for anything other then existance of an exit
int* gen_door_order( ROOM_INDEX_DATA* room, int* max_door ){
static int doors[MAX_DOOR];
int temp, i, j, max_doors = 0;
memset( doors, 0, sizeof( int ) * MAX_DOOR );
*max_door = 0;
/*1) Fill doors with exits in the room */
for (i = 0; i < MAX_DOOR; i++){
if (room->exit[i] != NULL)
doors[max_doors++] = i;
}
if (max_doors < 1)
return NULL;
/* randomly swap each spot for another spot */
for (i = 0; i < max_doors; i++){
j = rand() % max_doors;
temp = doors[i];
doors[i] = doors[j];
doors[j] = temp;
}
*max_door = max_doors;
return doors;
}
//tries to flee a character from his room into given direction
bool flee_char( CHAR_DATA* ch, CHAR_DATA* victim, int door, bool fRetreat, bool fShadow ){
EXIT_DATA* pexit = ch->in_room->exit[door];
char* str_flee = "flee";
char* str_fled = "fled";
if (pexit == NULL || pexit->to_room == NULL)
return FALSE;
else if (!fShadow
&& IS_SET(pexit->exit_info, EX_CLOSED)
&& !IS_AFFECTED(ch, AFF_PASS_DOOR))
return FALSE;
else if ( IS_NPC(ch) && IS_SET(pexit->to_room->room_flags, ROOM_NO_MOB))
return FALSE;
/* CAN FLEE */
stop_fighting( ch, TRUE );
if (fRetreat){
str_flee = "retreat";
str_fled = "retreated";
}
act( "$n has $t!", ch, str_fled, NULL, TO_ROOM );
if ( !IS_NPC(ch) ){
if (ch->level > 34 && ch->class == class_lookup("warrior"))
sendf(ch, "You %s %s from combat!\n\r", str_flee, dir_name[door]);
else
sendf(ch, "You %s from combat!\n\r", str_flee );
send_to_char( "You lost 10 exp.\n\r", ch);
gain_exp( ch, -10 );
}
move_char( ch, door, TRUE );
if (ch->in_room == NULL)
return TRUE;
if ( IS_NPC(victim)
&& !IS_SET(victim->act2, ACT_LAWFUL)
&& !IS_SET(victim->off_flags,CABAL_GUARD)
&& !IS_SET(victim->act, ACT_RAIDER)
&& !IS_AFFECTED(ch, AFF_CHARM)
&& victim->pIndexData->vnum != MOB_VNUM_ALTAR
&& !IS_AFFECTED(victim, AFF_CHARM)){
if (!IS_NPC(ch))
victim->hunting = ch;
else if (ch->master != NULL)
victim->hunting = ch->master;
else if (ch->leader != NULL)
victim->hunting = ch->leader;
else
victim->hunting = ch;
victim->hunttime = 0;
}
return TRUE;
}
void do_flee( CHAR_DATA *ch, char *argument ){
ROOM_INDEX_DATA *was_in;
CHAR_DATA *victim, *och;
AFFECT_DATA* paf;
int retreat = get_skill(ch, skill_lookup("retreat"));
int i, max_doors = 0, *doors, door = -1, flee_door;
int chance;
bool fRetreat = FALSE;
bool fShadow = FALSE;
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;
}
else if (IS_AFFECTED2(ch, AFF_RAGE)){
send_to_char("You can't flee, you're fighting to the DEATH!\n\r",ch);
return;
}
if (is_affected(ch, gsn_shadow_door))
fShadow = TRUE;
/* flee failures */
chance = 35 + 3 * (16 - get_curr_stat(ch,STAT_LUCK));
if (IS_SET(ch->act, PLR_DOOF) && number_percent() < chance){
send_to_char("You attempt to flee, but the gods only laugh at your misery.\n\r",ch);
WAIT_STATE2(ch, PULSE_VIOLENCE);
return;
}
else if (!fShadow
&& (paf = affect_find(ch->affected, gsn_wlock)) != NULL){
act("You've been weapon locked!", ch, NULL, victim, TO_CHAR);
act("$n tries to flee but $s weapon is all tangled up!", ch, NULL, NULL, TO_ROOM);
WAIT_STATE2(ch, PULSE_VIOLENCE );
if (--paf->modifier < 1)
check_dispel(-99, ch, gsn_wlock);
return;
}
else if (!fShadow
&& is_affected(ch,gsn_hysteria)
&& number_percent() < chance){
send_to_char("You panic and couldn't escape!\n\r",ch);
WAIT_STATE2(ch, PULSE_VIOLENCE );
return;
}
else if (!fShadow && (paf = affect_find(ch->affected, gsn_leash) ) != NULL
&& paf->has_string
&& !IS_NULLSTR(paf->string)
&& (och = get_char( paf->string)) != NULL){
if (--paf->modifier < 1){
check_dispel( -99, ch, gsn_leash );
}
WAIT_STATE2(ch, PULSE_VIOLENCE / 3 );
damage(och, ch, 3, gsn_leash, DAM_INTERNAL, FALSE );
return;
}
else
WAIT_STATE2(ch, PULSE_VIOLENCE / 3);
/* RETREAT */
/* check if we are fleeing or retreating */
if (number_percent() < 4 * retreat / 5){
fRetreat = TRUE;
check_improve(ch, skill_lookup("retreat"), TRUE, 1);
}
else
check_improve(ch, skill_lookup("retreat"), FALSE, 1);
if (retreat > 1 && !IS_NULLSTR(argument)){
if ( !str_cmp( argument, "n" )
|| !str_cmp( argument, "north" ) ) door = DIR_NORTH;
else if ( !str_cmp( argument, "s" )
|| !str_cmp( argument, "south" ) ) door = DIR_SOUTH;
else if ( !str_cmp( argument, "e" )
|| !str_cmp( argument, "east" ) ) door = DIR_EAST;
else if ( !str_cmp( argument, "w" )
|| !str_cmp( argument, "west" ) ) door = DIR_WEST;
else if ( !str_cmp( argument, "u" )
|| !str_cmp( argument, "up" ) ) door = DIR_UP;
else if ( !str_cmp( argument, "d" )
|| !str_cmp( argument, "down" ) ) door = DIR_DOWN;
else
door = -1;
}
//remember the room we are in
was_in = ch->in_room;
doors = gen_door_order( was_in, &max_doors );
for ( i = 0; i < max_doors; i++ ){
/* if we tried to retreat in direction try that once first */
if (door > -1){
flee_door = door;
door = i = -1;
}
else
flee_door = doors[i];
/* flat out chance of failing */
if (!fShadow && !fRetreat && number_percent() < (100 / (1 + max_doors)))
continue;
//DEBUG sendf(ch, "Trying %s.\n\r", dir_name[flee_door]);
if (!flee_char( ch, victim, flee_door, fRetreat, fShadow ) || ch->in_room == was_in)
continue;
//check if we are alive still
/* SUCESS we escaped! */
//get shadow door to invis us immediatly
if (fShadow)
spell_shadow_door( gsn_shadow_door, ch->level, ch, ch, -1 );
else
WAIT_STATE2(ch, PULSE_VIOLENCE / 3);
if ( IS_NPC(ch) && IS_SET(ch->special,SPECIAL_COWARD)
&& ch->summoner != NULL){
REMOVE_BIT(ch->special,SPECIAL_COWARD);
SET_BIT(ch->special,SPECIAL_RETURN);
}
/* remove stand ground */
affect_strip(ch, gsn_stand_ground );
if (!is_safe_quiet(ch, victim)){
/* See the character tries to flee, we attempt a backcutter */
if (backcutter_effect(victim, ch, fRetreat || fShadow))
return;
if (get_skill(victim, gsn_throw) > 90
&& throw_effect(victim, ch, fRetreat || fShadow))
return;
}
return;
}
send_to_char( "You couldn't escape!\n\r", ch );
}
void do_sla( CHAR_DATA *ch, char *argument )
{
send_to_char( "If you want to SLAY, spell it out.\n\r", ch );
}
void do_sever( CHAR_DATA *ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
char buf[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
OBJ_DATA *obj;
one_argument( argument, arg );
if ( arg[0] == '\0' )
{
send_to_char("Who are you going to rip in half?\n\r",ch);
return;
}
if ( ( victim = get_char_room( ch, NULL,arg ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if(victim == ch)
{
send_to_char("You reach your neck fine, but can't get your ankles.\n\r",ch);
return;
}
if(IS_AFFECTED2(victim, AFF_SEVERED))
{
send_to_char("They have no legs to rip off.\n\r",ch);
return;
}
if ( !IS_NPC(victim) && victim->level >= get_trust(ch) && ch != victim)
{
sendf(ch, "You failed to slay %s.\n\r", PERS2(victim) );
return;
}
SET_BIT(victim->affected2_by,AFF_SEVERED);
set_delay(victim, ch);
act( "You rip off $N's arms and legs in total fury!", ch, NULL, victim, TO_CHAR);
act_new( "`!$n rips off both of your arms and legs!``", ch, NULL, victim, TO_VICT, POS_DEAD );
act( "`!$n tears off $N's arms and legs in a fit of rage!``", ch, NULL, victim, TO_NOTVICT );
sprintf(buf,"GAAAAAAAAAAHHH!!!!");
do_yell(victim, buf);
obj = create_object( get_obj_index(OBJ_VNUM_LEGS ), 0 );
obj->timer = 5;
if(IS_NPC(victim))
sprintf(buf,"A pair of %s's arms are here, twitching.",victim->short_descr);
else
sprintf(buf,"A pair of %s's arms are here, twitching.",victim->name);
free_string(obj->description);
obj->description = str_dup( buf );
if(IS_NPC(victim))
sprintf(buf,"A pair of %s's arms",victim->short_descr);
else
sprintf(buf,"A pair of %s's arms",victim->name);
free_string(obj->short_descr);
obj->short_descr = str_dup( buf );
obj_to_char(obj,ch);
}
void do_slay( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
char arg[MIL];
one_argument( argument, arg );
if ( arg[0] == '\0' )
{
send_to_char( "Slay whom?\n\r", ch );
return;
}
if ( ( victim = get_char_room( ch, NULL,arg ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if ( victim == ch && ch->desc == NULL )
return;
if ( !IS_NPC(victim) && victim->level >= get_trust(ch) && ch != victim )
{
sendf(ch, "You failed to slay %s.\n\r", PERS2(victim) );
return;
}
act( "You slay $M in cold blood!", ch, NULL, victim, TO_CHAR );
act_new( "$n slays you in cold blood!", ch, NULL, victim, TO_VICT, POS_DEAD );
act( "$n slays $N in cold blood!", ch, NULL, victim, TO_NOTVICT );
raw_kill( ch, victim );
}
void do_qslay( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
char arg[MIL];
one_argument( argument, arg );
if ( arg[0] == '\0' )
{
send_to_char( "Slay whom?\n\r", ch );
return;
}
if ( ( victim = get_char_room( ch, NULL,arg ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if ( victim == ch && ch->desc == NULL )
return;
if ( !IS_NPC(victim) && victim->level >= get_trust(ch) && ch != victim )
{
sendf(ch, "You failed to slay %s.\n\r", PERS2(victim) );
return;
}
act( "You slay $M quietly.", ch, NULL, victim, TO_CHAR );
raw_kill( ch, victim );
}
void do_smite( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
char arg[MIL];
char buf1[MIL];
char buf2[MIL];
argument = one_argument( argument, arg );
if ( arg[0] == '\0' )
{
send_to_char( "Smite whom?\n\r", ch );
return;
}
if ( ( victim = get_char_world( ch, arg ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if ( !IS_NPC(victim) && victim->level > get_trust(ch) && ch != victim )
{
sendf(ch, "You failed to smite %s.\n\r", PERS2(victim) );
return;
}
act( "You send a thunderbolt to smite $N!", ch, NULL, victim, TO_CHAR );
if (argument[0] != '\0')
{
sendf( victim, "%s\n\r", argument);
sprintf(buf1, "%s", victim->name);
sprintf(buf2, "%s's", victim->name);
str_replace( argument, "Your", buf2);
str_replace( argument, "You", buf1);
act( argument, ch, NULL, victim, TO_NOTVICT);
}
else
{
send_to_char( "A bolt from the heavens smites you!\n\r",victim);
act( "A bolt from the heavens smites $N!", ch, NULL, victim, TO_NOTVICT );
}
victim->hit/=2;
}
/* oengod psalm */
CHAR_DATA* onegod_check_guard(CHAR_DATA* ch, CHAR_DATA* mob)
{
const int MAX_CHS = 12;
CHAR_DATA* och;
CHAR_DATA* och_next;
CHAR_DATA* chs[MAX_CHS];
int tot_chs = 0;
/* Put all avaliable saving chars in an array */
for ( och = ch->in_room->people; och != NULL; och = och_next ){
och_next = och->next_in_room;
if (IS_NPC(och)
|| och->hit < och->max_hit / 3
|| och->fighting == NULL
|| ch->fighting == NULL
|| och->fighting != ch->fighting
|| och->fighting == ch
|| ch->fighting == och
|| och == mob
|| och == ch
|| IS_AFFECTED(och, AFF_CHARM)
|| !is_same_group(ch, och)
|| !can_see(och, ch)
|| !is_affected(och, gsn_ogtrium)
)
continue;
chs[tot_chs++] = och;
}//end for
/* now we pick one character out of all possible choices */
if (tot_chs == 0)
return NULL;
/* we return a random pick */
och = chs[number_range(0, UMAX(0, tot_chs - 1))];
return och;
}
CHAR_DATA *check_guard(CHAR_DATA *ch, CHAR_DATA *mob)
{
int chance;
CHAR_DATA *och, *och_next, *sub = NULL;
/* Ranger MindLink */
if (!IS_NPC(ch))
chance = (get_skill(ch,gsn_mind_link) / 3 + (1.5 * (ch->level - mob->level)));
else
chance = 0;
if (number_percent() < UMIN(95, chance)){
/* Find any beasts */
for ( och = ch->in_room->people; och != NULL; och = och_next ){
och_next = och->next_in_room;
if ( IS_AFFECTED(och, AFF_CHARM) && IS_NPC(och)
&& och->master == ch
&& can_see(och, ch)
&& och->fighting != ch
&& och->pIndexData->vnum == MOB_VNUM_MAMMOTH)
{sub = och;break;}
}//End If is guarding
/* Check if any found if not continue to next check*/
if (sub != NULL)
{
act("$n jumps in front of $N!",sub,NULL,ch,TO_NOTVICT);
act("$n jumps in front of you!",sub,NULL,ch,TO_VICT);
act("You jump in front of $N!",sub,NULL,ch,TO_CHAR);
check_improve(ch,gsn_mind_link,TRUE,1);
return sub;
}
}
/* GUARD CAPTAIN */
if (!IS_NPC(ch) && ch->pet && ch->pet->pIndexData->vnum == MOB_VNUM_SPECIAL_GUARD
&& ch->pet->fighting && number_percent() < 25){
sub = ch->pet;
act("$n jumps in front of $N!",sub,NULL,ch,TO_NOTVICT);
act("$n jumps in front of you!",sub,NULL,ch,TO_VICT);
act("You jump in front of $N!",sub,NULL,ch,TO_CHAR);
return sub;
}
/* Virigoth Tattoo */
if (ch->tattoo == deity_lookup("cycle"))
chance = ch->level + 3 * (ch->level - mob->level);
else
chance = 0;
if (number_percent() < UMIN(95, chance)){
sub = undead_check_guard(ch, mob);
/* Check if any found if not continue to next check*/
if (sub != NULL)
{
act("$n jumps in front of $N!",sub,NULL,ch,TO_NOTVICT);
act("$n jumps in front of you!",sub,NULL,ch,TO_VICT);
act("You jump in front of $N!",sub,NULL,ch,TO_CHAR);
return sub;
}
}
/* One God Psalm */
if (!IS_NPC(ch) && number_percent() < 20){
sub = onegod_check_guard(ch, mob);
/* Check if any found if not continue to next check*/
if (sub != NULL)
{
act("$n steps in front of $N!",sub,NULL,ch,TO_NOTVICT);
act("$n steps in front of you!",sub,NULL,ch,TO_VICT);
act("You step in front of $N!",sub,NULL,ch,TO_CHAR);
return sub;
}
}
/* Guard Skill */
if (!IS_NPC(ch) && ch->pcdata->guarded_by != NULL
&& ch->in_room == ch->pcdata->guarded_by->in_room
&& can_see(ch->pcdata->guarded_by, ch))
chance = get_skill(ch->pcdata->guarded_by, gsn_guard);
else
chance = 0;
if (number_percent() < UMIN(100,chance))
{
if (number_percent() < ch->level + 1.5 * (ch->level - mob->level))
{
act("$n jumps in front of $N!",ch->pcdata->guarded_by,NULL,ch,TO_NOTVICT);
act("$n jumps in front of you!",ch->pcdata->guarded_by,NULL,ch,TO_VICT);
act("You jump in front of $N!",ch->pcdata->guarded_by,NULL,ch,TO_CHAR);
check_improve(ch->pcdata->guarded_by,gsn_guard,TRUE,1);
return ch->pcdata->guarded_by;
}
else
{
check_improve(ch->pcdata->guarded_by, gsn_guard, FALSE, 1);
return ch;
}
}//end guard success
return ch;
}///end check guard
void mortal_wound( CHAR_DATA *och, CHAR_DATA *victim )
{
CHAR_DATA* ch = och;
AFFECT_DATA af;
char buf[MSL];
/* check for npc/master */
if (IS_NPC(och)){
if (och->master)
ch = och->master;
else{
ch = och;
}
}
if (IS_NPC(victim))
return;
stop_fighting( victim, TRUE );
stop_fighting( och, TRUE);
if (IS_AFFECTED2(victim,AFF_RAGE))
{
REMOVE_BIT(victim->affected2_by,AFF_RAGE);
affect_strip(victim,gsn_rage);
}
affect_strip(victim,gen_firestorm);
affect_strip(victim,gen_anger);
affect_strip(victim,gsn_poison);
affect_strip(victim,gen_bleed);
affect_strip(victim,gsn_plague);
affect_strip(victim,gsn_insect_swarm);
affect_strip(victim,skill_lookup("visitation"));
affect_strip(victim,skill_lookup("dysentery"));
victim->pcdata->condition[COND_HUNGER]=15;
victim->pcdata->condition[COND_THIRST]=15;
victim->hit = 1;
victim->mana = 1;
victim->position = POS_RESTING;
die_follower(victim, FALSE);
if (!IS_NPC(ch)){
if (is_challenger(ch,victim))
{
if (ch->pCabal && IS_SET(ch->pCabal->progress, PROGRESS_CHALL)){
update_challenge( ch, ch->name, victim->name, 1, 0, 0, 0 );
sendf(ch, "You've gained some worth in eyes of [%s]!\n\r",
ch->pCabal->who_name);
CP_GAIN( ch, number_range(15, 50), TRUE );
}
if (victim->pCabal && IS_SET(victim->pCabal->progress, PROGRESS_CHALL)){
update_challenge( victim, victim->name, ch->name, 0, 1, 0, 0 );
sendf(victim, "You've gained some worth in eyes of [%s]!\n\r",
victim->pCabal->who_name);
CP_GAIN( victim, number_range(15, 50), TRUE );
}
save_challenges();
remove_challenge(ch,victim);
send_to_char("You have won your challenge.\n\r",ch);
send_to_char("You have lost the challenge.\n\r",victim);
send_to_char("`!FINISH THEM!``\n\r",ch);
}
if (ch->pCabal){
sprintf(buf,"%s has claimed victory over %s.", PERS2(ch), PERS2(victim));
cabal_echo(ch->pCabal, buf);
}
if (victim->pCabal){
sprintf(buf,"%s has been defeated by %s.",PERS2(victim),PERS2(ch));
cabal_echo(victim->pCabal, buf);
}
}
if (IS_AFFECTED2(ch,AFF_RAGE))
{
REMOVE_BIT(ch->affected2_by,AFF_RAGE);
affect_strip(ch,gsn_rage);
act("You snap out of your madness at the death of your opponent.",ch,NULL,NULL,TO_CHAR);
act("$n gasps for air as $e snaps out of $s insanity.",ch,NULL,NULL,TO_ROOM);
ch->hit -= (ch->level * ch->perm_stat[STAT_CON]) /3;
if (IS_IMMORTAL(ch))
ch->hit = UMAX(1,ch->hit);
if (ch->hit < -2)
{
int shock_mod = (25 * (0 - ch->hit)) / ch->max_hit;
if (number_percent( ) < con_app[UMAX(1,ch->perm_stat[STAT_CON] - shock_mod)].shock)
{
act_new("Your body suddenly awakens to the wounds you've sustained and you lose consciousness.",ch,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n suddenly clutches $s wounds and slumps to the ground, unconscious.",ch,NULL,NULL,TO_ROOM);
ch->hit = -2;
ch->position = POS_STUNNED;
act( "$n is stunned, but will probably recover.",ch, NULL, NULL, TO_ROOM );
act_new("You are stunned, but will probably recover.",ch,NULL,NULL,TO_CHAR,POS_DEAD );
}
else
{
act_new("Your body could not sustain the injuries you've suffered.",ch,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n suddenly clutches $s wounds and slumps to the ground.",ch,NULL,NULL,TO_ROOM);
act( "$n is DEAD!!",ch, 0, 0, TO_ROOM );
act_new( "You have been `1KILLED``!!", ch,NULL,NULL,TO_CHAR,POS_DEAD);
raw_kill( ch, ch );
}
}
}
af.type = gsn_mortally_wounded;
af.level = victim->level;
af.duration = IS_NPC(ch) ? 4 : 2;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = 0;
affect_to_char(victim,&af);
send_to_char("You are too hurt to do anything for a while.\n\r",victim);
}
void mercy_effect( CHAR_DATA *och, CHAR_DATA *victim, int dur )
{
CHAR_DATA* ch = och;
AFFECT_DATA af;
/* check for npc/master */
if (IS_NPC(och)){
if (och->master)
ch = och->master;
else{
ch = och;
}
}
stop_fighting( victim, TRUE );
if (IS_AFFECTED2(victim,AFF_RAGE))
{
REMOVE_BIT(victim->affected2_by,AFF_RAGE);
affect_strip(victim,gsn_rage);
}
affect_strip(victim,gsn_poison);
affect_strip(victim,gen_bleed);
affect_strip(victim,gsn_plague);
affect_strip(victim,gsn_insect_swarm);
affect_strip(victim,skill_lookup("visitation"));
affect_strip(victim,skill_lookup("dysentery"));
victim->pcdata->condition[COND_HUNGER]=15;
victim->pcdata->condition[COND_THIRST]=15;
victim->hit = 1;
victim->mana = 1;
victim->position = POS_RESTING;
die_follower(victim, FALSE);
if (IS_AFFECTED2(ch,AFF_RAGE))
{
REMOVE_BIT(ch->affected2_by,AFF_RAGE);
affect_strip(ch,gsn_rage);
act("You snap out of your madness at the death of your opponent.",ch,NULL,NULL,TO_CHAR);
act("$n gasps for air as $e snaps out of $s insanity.",ch,NULL,NULL,TO_ROOM);
ch->hit -= (ch->level * ch->perm_stat[STAT_CON]) /3;
if (IS_IMMORTAL(ch))
ch->hit = UMAX(1,ch->hit);
if (ch->hit < -2)
{
int shock_mod = (25 * (0 - ch->hit)) / ch->max_hit;
if (number_percent( ) < con_app[UMAX(1,ch->perm_stat[STAT_CON] - shock_mod)].shock)
{
act_new("Your body suddenly awakens to the wounds you've sustained and you lose consciousness.",ch,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n suddenly clutches $s wounds and slumps to the ground, unconscious.",ch,NULL,NULL,TO_ROOM);
ch->hit = -2;
ch->position = POS_STUNNED;
act( "$n is stunned, but will probably recover.",ch, NULL, NULL, TO_ROOM );
act_new("You are stunned, but will probably recover.",ch,NULL,NULL,TO_CHAR,POS_DEAD );
}
else
{
act_new("Your body could not sustain the injuries you've suffered.",ch,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n suddenly clutches $s wounds and slumps to the ground.",ch,NULL,NULL,TO_ROOM);
act( "$n is DEAD!!",ch, 0, 0, TO_ROOM );
act_new( "You have been `1KILLED``!!", ch,NULL,NULL,TO_CHAR,POS_DEAD);
raw_kill( ch, ch );
}
}
}
af.type = gsn_mortally_wounded;
af.level = victim->level;
af.duration = dur;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = 0;
if (!is_affected(victim, af.type))
affect_to_char(victim,&af);
//anti abuse check for people mercing someone over and over again
af.type = gsn_mercy_wait;
af.duration = dur + 1;
affect_strip(victim, af.type );
affect_to_char(victim, &af);
send_to_char("You are too hurt to do anything for a while.\n\r",victim);
}
/* returns if challenger can fight yet */
bool challenge_safe(CHAR_DATA* ch, CHAR_DATA* victim){
if ( !IS_NPC(ch) && !IS_NPC(victim) && is_challenger(ch, victim)){
AFFECT_DATA* paf;
for (paf = ch->affected; paf; paf = paf->next){
if (paf->type != gen_challenge || paf->modifier < 1)
continue;
if (str_cmp(victim->name, paf->string))
continue;
return TRUE;
}
}
return FALSE;
}
/* returns if character is in challange with victim */
bool is_challenger( CHAR_DATA *och, CHAR_DATA *victim )
{
CHAR_DATA* ch = och;
AFFECT_DATA* paf;
bool fCh = FALSE; //check if victim name found on character
bool fVch = FALSE; //check if character name found on victim
if (IS_NPC(victim))
return FALSE;
if (IS_NPC(och)){
if (och->master && !IS_NPC(och->master))
ch = och;
else
return FALSE;
}
/* check if ch has challenged victim */
for (paf = ch->affected; paf; paf = paf->next){
if (paf->type != gen_challenge
|| !paf->has_string)
continue;
if (str_cmp(victim->name, paf->string))
continue;
fCh = TRUE;
break;
}
if (!fCh)
return FALSE;
/* check if victim has challenged ch */
for (paf = victim->affected; paf; paf = paf->next){
if (paf->type != gen_challenge
|| !paf->has_string)
continue;
if (str_cmp(ch->name, paf->string))
continue;
fVch = TRUE;
break;
}
if (!fVch)
return FALSE;
return TRUE;
}
void remove_challenge( CHAR_DATA *ch, CHAR_DATA *victim){
AFFECT_DATA* paf;
AFFECT_DATA* paf_next;
/* we scan through effects knocking out the paf */
/* the gen will attempt to knock the other path automaticly */
for (paf = ch->affected; paf; paf = paf_next){
paf_next = paf->next;
if (paf->type != gen_challenge
|| !paf->has_string)
continue;
if (str_cmp(victim->name, paf->string))
continue;
affect_remove(ch, paf);
}
}
/////////////////////
//get_spell_damage //
////////////////////
//Calculates the damage that will be done to target
//returns FALSE if immune or not affected by that particular dam_type
//Returns -1 if damge is not allowed (ie: safe rooms etc.)
/*
!!!NOTE!!!
This function does not duplicate damage done by phantasmal stuff
as the damage was calculated INSIDE the damage function, not by
a spell or skill function outside.
That will have to be changed later.
*/
int get_spell_damage(CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dam_type)
{
//Vars needed for the below
AFFECT_DATA *paf;//effects
//THINGS THAT ARE NOT IMMUNE BUT DO NOT TAKE DAMAGE
//DEAD
if ( victim->position == POS_DEAD)
return FALSE;
//LIMBO
if (ch->in_room == NULL || ch->in_room->vnum == ROOM_VNUM_LIMBO)
return -1;
//MIRROR IMAGE
if (IS_NPC(victim) && is_affected(victim,gsn_mirror_image))
return -1;
//DECOY
if (IS_NPC(victim) && is_affected(victim,gsn_decoy))
return -1;
//THINGS THAT CAUSE IMMUNITY
//MANA SHIELD
if (IS_AFFECTED2(victim, AFF_MANA_SHIELD) && dam_type > 3)
{
if (dam / 5 <= victim->mana)
dam = FALSE;
else
UMIN(0, dam -= victim->mana * (victim->level/5));
}
//BARRIER
if (dam > 1 && IS_AFFECTED2(victim, AFF_BARRIER) && dam_type <= 3)
{
if (dam / 2 <= victim->mana)
dam = FALSE;
else
UMIN(0, dam -= victim->mana * (victim->level/2));
}
//---------END EASY CASES CALCULATE DAMAGE -----------//
//These are the standard modifiers to damage.
if ( dam > 1 && !IS_NPC(victim) && victim->pcdata->condition[COND_DRUNK] > 10 ) dam = dam * 9 / 10;
if ( dam > 1 && is_affected(victim, gsn_pyramid_of_force) ) dam = 3 * dam / 5;
if ( dam > 1 && is_affected(victim, gsn_mental_barrier) && dam_type == DAM_MENTAL) dam -= dam / 4;
if ( dam > 1 && IS_AFFECTED(victim, AFF_SANCTUARY) ) dam /= 2;
if ( dam > 1 && !IS_NPC(ch) && IS_SET(ch->act2,PLR_GIMP) ) dam /= 2;
if ( dam > 1 && IS_AFFECTED2(victim, AFF_ICE_SHIELD) && dam_type == DAM_FIRE) dam /= 2;
if ( dam > 1 && IS_AFFECTED2(victim, AFF_FIRE_SHIELD) && dam_type == DAM_COLD) dam /= 2;
if ( dam > 1 && IS_AFFECTED2(victim, AFF_ICE_SHIELD) && dam_type == DAM_COLD) dam = dam * 3 / 2;
if ( dam > 1 && IS_AFFECTED2(victim, AFF_FIRE_SHIELD) && dam_type == DAM_FIRE) dam = dam * 3 / 2;
if ( dam > 1 && is_affected(victim, gsn_wolf_form) && dam_type > 3) dam = 7 * dam / 10;
if (dam > 1 && dam_type == DAM_MENTAL && IS_SET(victim->act, ACT_UNDEAD)) dam = dam / 2;
if ( dam > 1 && ((IS_AFFECTED(victim, AFF_PROTECT_EVIL) && IS_EVIL(ch) )
|| (IS_AFFECTED(victim, AFF_PROTECT_GOOD) && IS_GOOD(ch) ))) dam -= dam / 4;
if ( dam > 1 && IS_AFFECTED(victim, AFF_WARD_LIGHT) )
{
if (IS_AFFECTED(victim, AFF_PROTECT_GOOD) && IS_GOOD(ch) ) dam -= dam / 20;
else dam -= dam / 6;
}
if ( is_affected(victim,gsn_horse) && monk_good(ch, WEAR_HEAD) ) dam -= dam / 5;
if ( is_affected(victim,gsn_aura) ) dam -= dam / 6;
if ( is_affected(victim,gsn_stance) ) dam = dam * 3 / 5;
if ( is_affected(victim,gsn_chii_bolt) && (paf = affect_find(victim->affected,gsn_chii_bolt)) != NULL && paf->modifier == 2)
dam = dam * 3 / 5;
//WE DO FINAL CHECK ON DAMAGE:
//RACE/CLASS CHECK:
switch(check_immune(victim,dam_type, FALSE))
{
case(IS_IMMUNE): return 0; break;
case(IS_RESISTANT): dam -= dam/3; break;
case(IS_VULNERABLE): dam += dam/2; break;
}
//RETURN THE FINAL DAMAGE
return dam;
}//END check_damage(..
/*continuum ability of vamps*/
/*exists only in fight.c*/
inline void set_continuum(CHAR_DATA* ch)
{
//we add the continuum affect if not already there.
AFFECT_DATA con;
if (!is_affected(ch, gsn_continuum))
{
con.type = gsn_continuum;
con.level = ch->level;
con.duration = 0;
con.where = TO_NONE;
con.location = APPLY_NONE;
con.modifier = 0;
con.bitvector = 0;
affect_to_char( ch, &con );
}
}//end set_continuum
void continuum(CHAR_DATA* ch, int type)
{
//single buf for message.
char buf[MIL];
DESCRIPTOR_DATA *d;
bool send = FALSE;
//We send out messages to all the vamps.
//most messages add the continuum effect, so they will not be reapeated
//and spammed to all the vamps.
//make a vamp sheck first of all
if (ch->class != class_lookup("vampire"))
return;
//now we begin to check for different type of messages.
switch (type)
{
case CONTINUUM_NONE:
break;
case CONTINUUM_DEATH:
sprintf(buf,"A cold emptiness invades your mind as you sense %s's passing.", ch->name);
send = TRUE;
break;
case CONTINUUM_ATTACK:
if(!is_affected(ch, gsn_continuum))
{
sprintf(buf,"You have a strong hunch that %s has just been attacked.", ch->name);
set_continuum(ch);
send = TRUE;
}//end if not continuum
else
return;
break;
case CONTINUUM_HURT:
sprintf(buf,"You feel a sharp pain, and you become certain that %s has just been seriously hurt.", ch->name);
send = TRUE;
break;
}//end switch (type)
//now we send out the message.
if( (!IS_IMMORTAL(ch)) && send)
{
for ( d = descriptor_list; d; d = d->next )
{
if ( ( d->connected == CON_PLAYING ) && (IS_UNDEAD(d->character) && d->character != ch) )
sendf( d->character, "`7[`8Continuum`7]`8\t%s\n\r``", buf );
}//end for
}//end if not immortal. (we dont broadcast immortal stuff.)
}//end continuum.
// 03-25 ~12:00 Viri: created the bool affect_dark_metamophosis(..), it does
//the whole dark met. thing, as well as returns true for success.
//03-28 13:00 Viri: created the get_spell_damage(..) so
//we can properly calculate damage done by spells at least.
//04-05 23:00 Viri: Addec continuum for vamps.
//01-10-01 Viri: added checks for ch->in_romm == victim->in_room in multi_hit/virt_Damage
// for setting fight status on victim/ch and autoredirct on charmies.
//05-21-01 Ath: added messages fro NONVICT for dodge, parry, shield_block, etc..