/***************************************************************************
* 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. *
* *
* Envy Diku Mud improvements copyright (C) 1994 by Michael Quan, David *
* Love, Guilherme 'Willie' Arnold, 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. *
***************************************************************************/
/*$Id: fight.c,v 1.121 2005/04/10 16:29:00 tyrion Exp $*/
#if defined( macintosh )
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "merc.h"
extern char* target_name;
/*
* Local functions.
*/
int damclass_adjust args( ( CHAR_DATA *victim, int dam, int sn) );
void damclass_shield_weaken args( ( CHAR_DATA *vic, int dam, int sn) );
bool check_dodge args( ( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount ) );
bool check_enhanced_dodge args( ( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount ) );
void check_killer args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
bool check_parry args( ( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount ) );
bool check_enhanced_parry args( ( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount ) );
bool check_shield_block args( ( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount ) );
void dam_message args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam,
int dt ) );
void death_cry args( ( CHAR_DATA *ch ) );
void group_gain args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
int xp_compute args( ( CHAR_DATA *gch, CHAR_DATA *victim ) );
int damreduce args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt ) );
bool is_safe args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
bool is_wielding_poisoned args( ( CHAR_DATA *ch ) );
bool is_wielding_flaming args( ( CHAR_DATA *ch ) );
bool is_wielding_chaos args( ( CHAR_DATA *ch ) );
bool is_wielding_icy args( ( CHAR_DATA *ch ) );
bool is_wielding_sparking args( ( CHAR_DATA *ch ) );
bool is_wielding_dispelling args( ( CHAR_DATA *ch ) );
void make_corpse args( ( CHAR_DATA *ch ) );
bool check_hit args( ( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount, bool dual ) );
void one_hit args( ( CHAR_DATA *ch, CHAR_DATA *victim,
int dt ) );
void one_dual args( ( CHAR_DATA *ch, CHAR_DATA *victim,
int dt ) );
void raw_kill args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void set_fighting args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void disarm args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void item_damage args( ( CHAR_DATA *ch, int dam ) );
void use_magical_item args( ( CHAR_DATA *ch ) );
void miss_message args( ( CHAR_DATA* ch, CHAR_DATA* victim, bool dual ) );
bool can_use_attack args( ( int attack_num, CHAR_DATA* ch ) );
bool can_dual args( ( CHAR_DATA* ch ) );
int dam_class_value; /* global damclass value. ewwy */
/*
* Control the fights going on.
* Called periodically by update_handler.
* Slightly less efficient than Merc 2.2. Takes 10% of
* total CPU time.
*/
void violence_update( void )
{
CHAR_DATA *ch;
CHAR_DATA *victim;
CHAR_DATA *rch;
bool mobfighting;
int stun;
for ( ch = char_list; ch; ch = ch->next )
{
if ( !ch->in_room || ch->deleted )
continue;
for (stun = 0; stun < STUN_MAX; stun++)
{
if ( IS_STUNNED( ch, stun ) )
ch->stunned[stun]--;
}
if ( ( victim = ch->fighting ) )
{
if ( IS_AWAKE( ch ) && ch->in_room == victim->in_room )
multi_hit( ch, victim, TYPE_UNDEFINED );
else
stop_fighting( ch, FALSE );
continue;
}
if ( IS_AFFECTED( ch, AFF_BLIND )
|| ( IS_NPC( ch ) && ch->pIndexData->pShop ) )
continue;
/* Ok. So ch is not fighting anyone.
* Is there a fight going on?
*/
mobfighting = FALSE;
for ( rch = ch->in_room->people; rch; rch = rch->next_in_room )
{
if ( rch->deleted
|| !IS_AWAKE( rch )
|| !( victim = rch->fighting ) )
continue;
if ( !IS_NPC( ch )
&& ( !IS_NPC( rch ) || IS_AFFECTED( rch, AFF_CHARM ) )
&& is_same_group( ch, rch )
&& IS_NPC( victim ) )
break;
if ( IS_NPC( ch )
&& IS_NPC( rch )
&& !IS_NPC( victim ) )
{
mobfighting = TRUE;
break;
}
}
if ( !victim || !rch )
continue;
/*
* Now that someone is fighting, consider fighting another pc
* or not at all.
*/
if ( mobfighting )
{
CHAR_DATA *vch;
int number;
number = 0;
for ( vch = ch->in_room->people; vch; vch = vch->next_in_room )
{
if ( can_see( ch, vch )
&& ( vch->level > 5 )
&& is_same_group( vch, victim )
&& number_range( 0, number ) == 0 )
{
victim = vch;
number++;
}
}
if ( ( rch->pIndexData != ch->pIndexData && number_bits( 3 ) != 0 )
|| ( IS_GOOD( ch ) && IS_GOOD( victim ) )
|| abs( victim->level - ch->level ) > 3 )
continue;
}
mprog_hitprcnt_trigger( ch, victim );
mprog_fight_trigger( ch, victim );
multi_hit( ch, victim, TYPE_UNDEFINED );
}
return;
}
/*
* Do one group of attacks.
*/
void multi_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
bool berserk;
bool hit;
bool dual_atk;
int chance;
int chance2;
int chance3;
int attack = 0;
if (!IS_NPC(ch) && ch->pcdata->craft_timer)
destroy_craft(ch, FALSE);
if ( IS_NPC( ch ) )
{
mprog_hitprcnt_trigger( ch, victim );
mprog_fight_trigger( ch, victim );
}
if ( ( IS_AFFECTED2( ch, AFF_CONFUSED ) )
&& number_percent ( ) < 30 )
{
act(AT_YELLOW, "$n looks around confused at what's going on.", ch, NULL, NULL, TO_ROOM );
send_to_char( AT_YELLOW, "You stand confused.\n\r", ch );
return;
}
dual_atk = FALSE;
hit = FALSE;
/* FIRST ATTACK */
one_hit( ch, victim, dt );
if ( ch->fighting != victim || dt == skill_lookup("backstab") )
return;
if ( ch->fighting != victim || dt == skill_lookup("assassinate") )
return;
if ( ch->fighting != victim || dt == skill_lookup("double backstab") )
return;
if ( ch->fighting != victim || dt == skill_lookup("leap of torfi") )
return;
if ( ch->fighting != victim || dt == skill_lookup("triple backstab") )
return;
chance = number_percent( );
chance2 = number_percent( ) / 2;
chance3 = number_percent( );
berserk = FALSE;
if(IS_AFFECTED2(ch, AFF_BERSERK) || IS_AFFECTED3(ch, AFF_BLOODTHIRSTY) )
{
berserk = TRUE;
}
for (attack = 2; attack <= MAX_ATTACKS; attack++)
{
hit = FALSE;
dual_atk = FALSE;
if (victim->position == POS_DEAD || victim->deleted)
return;
if ( can_use_attack( attack, ch ) )
{
if ( ( check_hit(ch, victim, attack, FALSE) ) || berserk )
{
hit = TRUE;
one_hit( ch, victim, dt );
if ( ch->fighting != victim )
{
return;
}
}
else if ( can_dual( ch ) && (dual_atk = TRUE) && check_hit(ch, victim, attack, TRUE) )
{
hit = TRUE;
one_dual( ch, victim, dt );
if ( ch->fighting != victim )
{
return;
}
}
if (!hit)
miss_message( ch, victim, dual_atk );
}
}
hit = FALSE;
dual_atk = FALSE;
/* HASTE ATTACK */
if( is_affected( ch, skill_lookup("quickness") ) || IS_AFFECTED( ch, AFF_HASTE ) )
{
if (victim->position == POS_DEAD || victim->deleted )
return;
if ( ( check_hit(ch, victim, 1, FALSE) ) || berserk )
{
hit = TRUE;
one_hit( ch, victim, dt );
if ( ch->fighting != victim )
{
return;
}
}
else if ( can_dual( ch ) && (dual_atk = TRUE) && check_hit(ch, victim, 1, TRUE) )
{
hit = TRUE;
one_dual( ch, victim, dt );
if ( ch->fighting != victim )
{
return;
}
}
if (!hit)
miss_message(ch, victim, dual_atk );
}
hit = FALSE;
dual_atk = FALSE;
if (victim->position == POS_DEAD || victim->deleted )
return;
/* WILDERNESS MASTERY ATTACK */
if( can_use_skspell( ch, skill_lookup("wilderness mastery") ) )
{
if( !IS_NPC( ch ) )
{
if( ( number_percent( ) < ( ch->pcdata->learned[skill_lookup("wilderness mastery")] / 10 ) ) && IS_OUTSIDE( ch ) && IS_IN_NATURE( ch ) )
{
update_skpell( ch, skill_lookup("wilderness mastery"), 0 );
if ( ( check_hit(ch, victim, 1, FALSE) ) || berserk )
{
hit = TRUE;
one_hit( ch, victim, dt );
if ( ch->fighting != victim )
{
return;
}
}
else if ( can_dual( ch ) && (dual_atk = TRUE) && check_hit(ch, victim, 1, TRUE) )
{
hit = TRUE;
one_dual( ch, victim, dt );
if ( ch->fighting != victim )
{
return;
}
}
if (!hit)
miss_message( ch, victim, dual_atk );
}
}
}
return;
}
/*
Logic to determine if a character hits his victim and deals damage to him.
ch is the character trying to hit
victim is the character being hit
attackCount is which attack this is a check for, first, second third, etc.
dual is whether or not this is a check for your main attack, or the dualed.
*/
bool check_hit( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount, bool dual ) {
/* now defined in merc.h
int MAX_ATTACKS = 8;
*/
int toHit = 0;
int chDex;
int victimDex;
char buf[1000];
OBJ_DATA* wield= NULL;
OBJ_DATA* ammo = NULL;
if (!dual)
wield = get_eq_char( ch, WEAR_WIELD );
else
wield = get_eq_char( ch, WEAR_WIELD_2 );
if ( !IS_NPC(ch) && wield && wield->value[3] == flag_value( weapon_flags, "shot" ) )
{
if (wield->value[0] == flag_value( ammo_flags, "arrow" ) )
ammo = find_arrows( ch );
else if (wield->value[0] == flag_value( ammo_flags, "bullet" ) )
ammo = find_bullets( ch );
else if (wield->value[0] == flag_value( ammo_flags, "bolt" ) )
ammo = find_bolts( ch );
else
ammo = NULL;
if (ammo)
{
/* I don't think this needs to be here, it is causing you to lose double ammo during combat rounds - Tyrion */
/* Leave it here. Remove it from one_hit. This will take care of 99% of ammo checks - Ahsile */
if (!--ammo->value[0])
{
sprintf( buf, "%s has just run out of shots!\n\r", ammo->short_descr );
send_to_char( AT_RED, buf, ch );
extract_obj( ammo );
}
}
}
chDex = get_curr_dex(ch);
victimDex = get_curr_dex(victim);
toHit = GET_HITROLL(ch);
toHit += (chDex - victimDex) * 20;
if (!IS_NPC(ch)) {
if ( can_use_skspell(ch, skill_lookup("enhanced hit")) ) {
toHit += ( ch->pcdata->learned[skill_lookup("enhanced hit")] / 10 );
update_skpell( ch, skill_lookup("enhanced hit"), 0 );
}
if ( can_use_skspell(ch, skill_lookup("enhanced hit two")) ) {
toHit += ( ch->pcdata->learned[skill_lookup("enhanced hit two")] / 10 );
update_skpell( ch, skill_lookup("enhanced hit two"), 0 );
}
}
else {
toHit += 100;
};
toHit += number_range((MAX_ATTACKS - 2)*50, (MAX_ATTACKS)*50);
toHit = toHit*(16-attackCount)/16;
/* Do all the dodge/parry/shield block checks here. */
sprintf(buf, "%s's hitroll value for attack num %d is %d", ch->name, attackCount, toHit);
/*if(!IS_NPC(ch)) bug(buf, 0);*/
/* If this is the dual attack, but they don't have enhanced dual, half the chance to hit */
if (dual)
{
if (!can_use_skspell(ch, skill_lookup("enhanced dual")))
{
toHit /= 2;
}
else
{
update_skpell( ch, skill_lookup("enhanced dual"), 0 );
}
}
if ( number_percent() > toHit/10 ) {
/*
sprintf(buf, "Attack #: %d", attackCount);
bug(buf, 0);
if ( IS_SET( ch->act, PLR_COMBAT ) )
act(AT_GREEN, "You attack $N, but miss.", ch, NULL, victim, TO_CHAR );
if ( IS_SET( victim->act, PLR_COMBAT ) )
act(AT_GREEN, "$n attacks you, but misses.", ch, NULL, victim, TO_VICT );
*/
return FALSE;
}
if (check_parry( ch, victim, attackCount ) )
return FALSE;
if (check_shield_block( ch, victim, attackCount ))
return FALSE;
if (check_dodge( ch, victim, attackCount ))
return FALSE;
if (check_enhanced_parry( ch, victim, attackCount ) )
return FALSE;
if (check_enhanced_dodge( ch, victim, attackCount ) )
return FALSE;
return TRUE;
}
/*
* Hit one guy once.
*/
void one_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
OBJ_DATA *wield;
OBJ_DATA *dual;
char buf [ MAX_STRING_LENGTH ];
int dam;
int val = 0;
int ammo_bonus = 0;
int divisor= 1; /* this is to cut firearm dmg down if no ammo is present */
/*
* Can't beat a dead char!
* Guard against weird room-leavings.
*/
if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_STUNNED( ch, STUN_NON_MAGIC ) ||
IS_STUNNED( ch, STUN_TOTAL ) )
return;
/*
* Figure out the type of damage message.
*/
wield = get_eq_char( ch, WEAR_WIELD );
dual = get_eq_char( ch, WEAR_WIELD_2 );
if ( dt == TYPE_UNDEFINED )
{
dt = TYPE_HIT;
if ( wield && wield->item_type == ITEM_WEAPON )
dt += wield->value[3];
}
/*
* Hit.
* Calc damage.
*/
if ( IS_AFFECTED( victim, AFF_FIRESHIELD ) )
{
if ( number_percent( ) < 50 )
{
damage( victim, ch, spell_fireball ( skill_lookup("fireball"), 25, victim, ch ), skill_lookup("fireball"));
}
}
if ( IS_AFFECTED4( victim, AFF_LEAF_SHIELD ) )
{
if ( number_percent( ) < 50 )
{
damage( victim, ch, spell_leaf_strike ( skill_lookup("leaf strike"), 25, victim, ch ), skill_lookup("leaf strike"));
}
}
if ( IS_AFFECTED3( victim, AFF_DEMONSHIELD ) )
{
if ( number_percent( ) < 30 )
{
damage( victim, ch, spell_demonfire ( skill_lookup("demonfire"), 25, victim, ch ), skill_lookup("demonfire"));
}
}
if ( IS_AFFECTED3( victim, AFF_ACIDSHIELD ) )
{
if ( number_percent( ) < 75 )
damage( victim, ch, spell_acid_blast ( skill_lookup("acid blast"), 25, victim, ch ), skill_lookup("acid blast"));
}
if ( IS_AFFECTED3( victim, AFF_AURA_ANTI_MAGIC ) )
{
if ( number_percent ( ) < 25 )
{
spell_dispel_magic (skill_lookup("dispel magic"), 80, victim, ch );
}
}
if ( IS_AFFECTED3( victim, AFF_COFIRE ) )
{
if ( number_percent( ) < 50 )
{
damage( victim, ch, spell_fireball ( skill_lookup("fireball"), 25, victim, ch ), skill_lookup("fireball"));
}
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_AFFECTED( victim, AFF_ICESHIELD ) )
{
if ( number_percent( ) < 40 )
{
damage( victim, ch, spell_iceball ( skill_lookup("iceball"), 40, victim, ch ), skill_lookup("iceball"));
}
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_AFFECTED3(victim, AFF_BLOODSHIELD ) )
{
if ( number_percent( ) < 40 )
{
damage( victim, ch, spell_blood_gout( skill_lookup("blood gout"), 40, victim, ch ), skill_lookup("blood gout"));
}
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_AFFECTED2(victim, AFF_UNHOLY_STRENGTH ) )
{
if ( number_percent( ) < 40 )
{
damage( victim, ch, spell_blood_gout( skill_lookup("blood gout"), 40, victim, ch ), skill_lookup("blood gout"));
}
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_AFFECTED( victim, AFF_SHOCKSHIELD ) )
{
if ( number_percent( ) < 50 )
{
damage( victim, ch, spell_lightning_bolt ( skill_lookup("lightning bolt"), 35, victim, ch ), skill_lookup("lightning bolt"));
}
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_AFFECTED4( victim, AFF_ESSENCE_OF_GAIA ) )
{
if ( ( number_percent( ) < 40 ) )
{
damage( victim, ch, spell_lightning_bolt( skill_lookup("lightning bolt"), 35, victim, ch ), skill_lookup("lightning bolt") );
}
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_AFFECTED( victim, AFF_CHAOS ) )
{
if ( number_percent( ) < 40 )
{
damage( victim, ch, spell_energy_drain ( skill_lookup("energy drain"), 40, victim, ch ), skill_lookup("energy drain"));
}
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_AFFECTED( victim, AFF_INERTIAL ) )
{
if ( number_percent( ) < 35 )
{
damage( victim, ch, spell_psionic_blast ( skill_lookup("psionic blast"), 25, victim, ch ), skill_lookup("psionic blast"));
}
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_AFFECTED2( victim, AFF_GHOST_SHIELD ) )
{
if ( number_percent( ) < 50 )
damage( victim, ch, spell_harm ( skill_lookup("harm"), 35, victim, ch ), skill_lookup("harm"));
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_AFFECTED3( victim, AFF_SATANIC_INFERNO ) )
{
if ( number_percent( ) < 40 )
{
damage( victim, ch, spell_unholy_fires ( skill_lookup("unholy fires"), 35, victim, ch ), skill_lookup("unholy fires"));
}
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_AFFECTED2( victim, AFF_SHADOW_IMAGE ) )
{
if ( number_percent( ) < 20 )
damage( victim, ch, spell_energy_drain ( skill_lookup("energy drain"), 35, victim, ch ),skill_lookup("energy drain"));
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_AFFECTED2( victim, AFF_BLADE ) )
{
if ( number_percent( ) < 40 )
damage( victim, ch, spell_daggers_of_pain ( skill_lookup("daggers of pain"), 25, victim, ch ),skill_lookup("daggers of pain"));
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_AFFECTED4( victim, AFF_ANGELIC_AURA ) )
{
if ( number_percent( ) < 40 )
damage( victim, ch, spell_holy_fires ( skill_lookup("holy fires"), 40, victim, ch ),skill_lookup("holy fires"));
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_AFFECTED4( victim, AFF_LIQUID_SKIN ) )
{
if ( number_percent( ) < 35 )
damage( victim, ch, spell_waterspike ( skill_lookup("waterspike"), 30, victim, ch ),skill_lookup("waterspike"));
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_AFFECTED4( victim, AFF_ETHEREAL_WOLF ) )
{
if ( number_percent( ) < 40 )
spell_ethereal_wolf_bite ( skill_lookup("ethereal wolf bite"), 35, victim, ch );
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_AFFECTED4( victim, AFF_ETHEREAL_SNAKE ) )
{
if ( number_percent( ) < 40 )
spell_ethereal_snake_strike ( skill_lookup("ethereal snake strike"), 35, victim, ch );
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_AFFECTED3( victim, AFF_RANDOMSHIELD ) )
{
int choice = number_range(1, 7);
if ( number_percent( ) < 40 )
switch( choice )
{
default:
damage( victim, ch, spell_fireball( skill_lookup("fireball"), 25, victim, ch ),skill_lookup("fireball"));
break;
case 1:
damage( victim, ch, spell_fireball( skill_lookup("fireball"), 25, victim, ch ),skill_lookup("fireball"));
break;
case 2:
damage( victim, ch, spell_energy_drain ( skill_lookup("energy drain"), 25, victim, ch ),skill_lookup("energy drain"));
break;
case 3:
damage( victim, ch, spell_harm ( skill_lookup("harm"), 25, victim, ch ),skill_lookup("harm"));
break;
case 4:
damage( victim, ch, spell_unholy_fires ( skill_lookup("unholy fires"), 25, victim, ch ),skill_lookup("unholy fires"));
break;
case 5:
damage( victim, ch, spell_lightning_bolt ( skill_lookup("lightning bolt"), 25, victim, ch ),skill_lookup("lightning bolt"));
break;
case 6:
damage( victim, ch, spell_daggers_of_pain ( skill_lookup("daggers of pain"), 50, victim, ch ),skill_lookup("daggers of pain"));
break;
case 7:
damage( victim, ch, spell_waterspike ( skill_lookup("waterspike"), 25, victim, ch ),skill_lookup("waterspike"));
break;
}
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_AFFECTED2( victim, AFF_IMAGE ) && victim->clan == 3 )
{
AFFECT_DATA *iaf;
for ( iaf = victim->affected2; iaf; iaf = iaf->next )
{
if ( iaf->deleted )
continue;
if ( iaf->type == skill_lookup("image") )
{
if ( number_percent( ) < (iaf->modifier * 7) )
spell_curse(skill_lookup("curse"),
(iaf->modifier * 4), victim, ch );
break;
}
}
}
if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
/* bow stuff here */
if (!IS_NPC(ch) && wield && wield->value[3] == flag_value( weapon_flags, "shot" ) )
{
OBJ_DATA* ammo = NULL;
if ( IS_SET(wield->extra_flags2, ITEM_MAGIC_SHOT) )
ammo = (OBJ_DATA*) 1; // fake out
else if (wield->value[0] == flag_value( ammo_flags, "arrow"))
ammo = find_arrows( ch );
else if (wield->value[0] == flag_value( ammo_flags, "bullet"))
ammo = find_bullets( ch );
else if (wield->value[0] == flag_value( ammo_flags, "bolt"))
ammo = find_bolts( ch );
else
ammo = NULL;
if (!ammo)
{
dt = TYPE_HIT + flag_value( weapon_flags, "crush" ); /* force bludg damage */
divisor = 2; /* half damage if you have no ammo */
ammo_bonus = 0; /* no ammo bonus */
} else
{
if ((int) ammo == 1)
{
ammo_bonus = number_range( ch->level, ch->level / 2 );
val = DAMCLASS_MAGIC;
} else
{
val = ammo->value[1];
ammo_bonus = number_range( ammo->value[2], ammo->value[3] );
}
divisor = 1; /* make sure damage = 100% */
}
} else
{
divisor = 1;
ammo_bonus = 0;
}
/* end bow stuff */
if ( IS_NPC( ch ) )
{
dam = number_range( ch->level / 3, ch->level * 3 / 2 );
if ( wield )
dam += dam / 3;
}
else
{
if ( wield )
{
dam = number_range( wield->value[1], wield->value[2] );
dam += ammo_bonus;
dam = (int) (dam / divisor); /* only necessary for firearms */
}
else
{
if ( ch->class == CLASS_MONK || ch->multied == CLASS_MONK || ch->class == CLASS_WEREWOLF || ch->multied == CLASS_WEREWOLF )
{
dam = number_range( 1, ( ch->level / 20 ) + 4 ) * race_table[ ch->race ].size;
}
else
{
dam = number_range( 1, 4 ) * race_table[ ch->race ].size;
}
}
if ( wield && dam > 1000 && !IS_IMMORTAL(ch) )
{
sprintf( buf, "One_hit dam range > 1000 from %d to %d",
wield->value[1], wield->value[2] );
bug( buf, 0 );
if ( wield->name )
bug( wield->name, 0 );
}
}
/*
* Bonuses.
*/
dam += GET_DAMROLL( ch );
if ( ( ch->class == CLASS_MONK || ch->multied == CLASS_MONK ) && !wield && !dual )
dam += ch->level/2;
if ( ( ch->class == CLASS_WEREWOLF || ch->multied == CLASS_WEREWOLF ) && !wield && !dual )
dam += ch->level/2 + 10;
/* VAMP Mods */
if (ch->class == CLASS_VAMPIRE || ch->multied == CLASS_VAMPIRE)
{
if (time_info.hour < 6 || time_info.hour >= 19)
{
dam += dam / 3;
}
else
{
dam -= dam / 3;
}
}
if ( wield && IS_SET( wield->extra_flags, ITEM_POISONED ) )
dam += dam / 16;
if ( wield && IS_SET( wield->extra_flags, ITEM_FLAME ) )
dam += dam / 16;
if ( wield && IS_SET( wield->extra_flags, ITEM_CHAOS ) )
dam += dam / 16;
if ( wield && IS_SET( wield->extra_flags, ITEM_ICY ) )
dam += dam / 16;
if ( wield && IS_SET( wield->extra_flags2, ITEM_SPARKING ) )
dam += dam / 16;
/* if ( wield && IS_SET( wield->extra_flags, ITEM_ACID ) )
dam += dam / 16;
*/
if ( !IS_NPC( ch ) && ch->pcdata->learned[skill_lookup("enhanced damage")] > 0 )
{
dam += dam / 2 * ch->pcdata->learned[skill_lookup("enhanced damage")] / 1000;
update_skpell( ch, skill_lookup("enhanced damage"), 0 );
}
if ( !IS_NPC( ch ) && ch->pcdata->learned[skill_lookup("enhanced damage two")] > 0 )
{
dam += dam / 6 * ch->pcdata->learned[skill_lookup("enhanced damage two")] / 1000;
update_skpell( ch, skill_lookup("enhanced damage two"), 0 );
}
if ( !IS_NPC( ch ) && ch->pcdata->learned[skill_lookup("enhanced damage three")] > 0 )
{
dam += dam / 6 * ch->pcdata->learned[skill_lookup("enhanced damage three")] / 1600;
update_skpell( ch, skill_lookup("enhanced damage three"), 0 );
}
if ( !IS_AWAKE( victim ) )
dam *= 2;
if ( dt == skill_lookup( "backstab" ) )
{
dam *= 2 + UMIN( ( ch->level / 8) , 4 );
}
if ( dt == skill_lookup( "assassinate" ) )
{
dam = (int)(dam * (1.65 * (2 + UMIN( ( ch->level / 8) , 4 ) ) ));
}
if ( dt == skill_lookup( "leap of torfi" ) )
{
dam *= 2 + UMIN( ( ch->level / 8) , 4 );
if (!str_cmp(ch->name,"Torfi"))
{
dam = (int)(dam * 1.1);
}
}
if ( dt == skill_lookup( "double backstab" ) )
{
dam *= 2 + UMIN( ( ch->level / 8) , 4 );
}
if ( dt == skill_lookup( "triple backstab" ) )
{
dam *= 2 + UMIN( ( ch->level / 8) , 4 );
}
if ( dam <= 0 )
dam = 1;
if (!IS_NPC(victim))
dam = damreduce( ch, victim, dam, dt );
dam_class_value = val;
damage( ch, victim, dam, dt );
dam_class_value = 0;
tail_chain( );
return;
}
void one_dual( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
OBJ_DATA *wield;
OBJ_DATA *dual;
char buf [MAX_STRING_LENGTH ];
int dam;
int val = 0;
int divisor = 1;
int ammo_bonus = 0;
/*
* Can't beat a dead char!
* Guard against weird room-leavings.
*/
if (!get_eq_char ( ch, WEAR_WIELD_2 ) && ( IS_SET( race_table[ch->race].race_abilities,
RACE_WEAPON_WIELD ) ) )
return;
if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_STUNNED( ch, STUN_NON_MAGIC ) ||
IS_STUNNED( ch, STUN_TOTAL ) )
return;
/*
* Figure out the type of damage message.
*/
wield = get_eq_char( ch, WEAR_WIELD_2 );
dual = get_eq_char( ch, WEAR_WIELD );
if ( dt == TYPE_UNDEFINED )
{
dt = TYPE_HIT;
if ( wield && wield->item_type == ITEM_WEAPON )
dt += wield->value[3];
}
/* bow stuff here */
if ( !IS_NPC( ch) && wield && wield->value[3] == flag_value( weapon_flags, "shot" ) )
{
OBJ_DATA* ammo = NULL;
if (wield->value[0] == flag_value( ammo_flags, "arrow"))
ammo = find_arrows( ch );
else if (wield->value[0] == flag_value( ammo_flags, "bullet"))
ammo = find_bullets( ch );
else if (wield->value[0] == flag_value( ammo_flags, "bolt"))
ammo = find_bolts( ch );
else
ammo = NULL;
if (!ammo)
{
dt = TYPE_HIT + flag_value( weapon_flags, "crush" ); /* force bludg damage */
divisor = 2; /* half damage if you have no ammo */
ammo_bonus = 0; /* no ammo bonus */
} else
{
val = ammo->value[1];
divisor = 1; /* make sure damage = 100% */
ammo_bonus = number_range( ammo->value[2], ammo->value[3] );
if (!--ammo->value[0])
{
sprintf(buf, "You have just run out of %s!\n\r", ammo->short_descr);
send_to_char(AT_RED, buf, ch );
extract_obj( ammo );
}
}
} else
{
divisor = 1;
ammo_bonus = 0;
}
/* end bow stuff */
/*
* Hit.
* Calc damage.
*/
if ( IS_NPC( ch ) )
{
dam = number_range( ch->level / 3, ch->level * 3 / 2 );
if ( wield )
dam += dam / 3;
}
else
{
if ( wield )
{
dam = number_range( wield->value[1], wield->value[2] );
dam += ammo_bonus;
dam = (int) (dam / divisor);
}
else
{
if ( ch->class == CLASS_MONK || ch->multied == CLASS_MONK || ch->class == CLASS_WEREWOLF || ch->multied == CLASS_WEREWOLF )
{
dam = number_range( 1, (ch->level / 20 ) + 4 ) * race_table[ ch->race ].size;
}
else
{
dam = number_range( 1, 4 ) * race_table[ ch->race ].size;
}
}
if ( wield && dam > 1000 && !IS_IMMORTAL(ch) )
{
sprintf( buf, "One_hit dam range > 1000 from %d to %d",
wield->value[1], wield->value[2] );
bug( buf, 0 );
if( wield->name )
bug( wield->name, 0 );
}
}
/*
* Bonuses.
*/
dam += GET_DAMROLL( ch );
if ( ch->race == 13 )
dam += ch->level;
if ( ( ch->class == CLASS_MONK || ch->multied == CLASS_MONK ) && !wield && !dual)
dam += ch->level/2;
if ( ( ch->class == CLASS_WEREWOLF || ch->multied == CLASS_WEREWOLF ) && !wield && !dual )
dam += ch->level/2 + 10;
/* VAMP mods */
if ( ch->class == CLASS_VAMPIRE || ch->multied == CLASS_VAMPIRE)
{
if (time_info.hour < 6 || time_info.hour >= 19)
{
dam += dam / 3;
}
else
{
dam -= dam / 3;
}
}
if ( wield && IS_SET( wield->extra_flags, ITEM_POISONED ) )
dam += dam / 16;
if ( wield && IS_SET( wield->extra_flags, ITEM_FLAME ) )
dam += dam / 16;
if ( wield && IS_SET( wield->extra_flags, ITEM_CHAOS ) )
dam += dam / 16;
if ( wield && IS_SET( wield->extra_flags, ITEM_ICY ) )
dam += dam / 16;
if ( wield && IS_SET( wield->extra_flags2, ITEM_SPARKING ) )
dam += dam / 16;
if ( !IS_NPC( ch ) && ch->pcdata->learned[skill_lookup("enhanced damage")] > 0 )
{
dam += dam / 2 * ch->pcdata->learned[skill_lookup("enhanced damage")] / 1000;
update_skpell( ch, skill_lookup("enhanced damage"), 0 );
}
if ( !IS_NPC( ch ) && ch->pcdata->learned[skill_lookup("enhanced damage two")] > 0 )
{
dam += dam / 6 * ch->pcdata->learned[skill_lookup("enhanced damage two")] / 1000;
update_skpell( ch, skill_lookup("enhanced damage two"), 0 );
}
if ( !IS_NPC( ch ) && ch->pcdata->learned[skill_lookup("enhanced damage three")] > 0 )
{
dam += dam / 6 * ch->pcdata->learned[skill_lookup("enhanced damage three")] / 1000;
update_skpell( ch, skill_lookup("enhanced damage three"), 0 );
}
if ( !IS_AWAKE( victim ) )
dam *= 2;
if ( dt == skill_lookup("backstab") )
{
dam *= 2 + UMIN( ( ch->level / 8) , 4 );
}
if ( dt == skill_lookup("assassinate") )
{
dam = (int)(dam * (1.5 * (2 + UMIN( ( ch->level / 8) , 4 ) ) ));
}
if ( dt == skill_lookup("leap of torfi") )
{
dam = (int)(dam * (1.5 * (2 + UMIN( ( ch->level / 8) , 4 ) ) ));
}
if ( dt == skill_lookup("double backstab") )
{
dam *= 2 + UMIN( ( ch->level / 8) , 4 );
}
if ( dt == skill_lookup("triple backstab") )
{
dam *= 2 + UMIN( ( ch->level / 8) , 4 );
}
if ( dam <= 0 )
dam = 1;
if (!IS_NPC(victim))
dam = damreduce( ch, victim, dam, dt );
dam_class_value = val;
damage( ch, victim, dam, dt );
dam_class_value = 0;
tail_chain( );
update_skpell( ch, skill_lookup("dual"), 0 );
return;
}
/* removes an object and put it right back on,
we need this so that when a player get pkilled
the spells on objs don't disappear. */
void remove_requip( CHAR_DATA *ch, int iWear )
{
OBJ_DATA *obj;
if ( !( obj = get_eq_char( ch, iWear ) ) )
return;
unequip_char( ch, obj );
equip_char( ch, obj, iWear );
}
/*
* Inflict damage from a hit.
*/
void damage( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt )
{
AFFECT_DATA *paf;
AFFECT_DATA *paf_next;
int iWear;
if ( victim->position == POS_DEAD )
return;
/* Combat Timer for PVP, and immunity for self damaging attacks
IE: Poison, Meteor Swarm - Ahsile */
if(!IS_NPC(ch) && !IS_NPC(victim) && (victim!=ch) && (dt != skill_lookup("incinerate")
&& dt != skill_lookup("deadly poison") && dt != skill_lookup("tortured soul")
&& dt != skill_lookup("pestilence") && dt != skill_lookup("breathe water")
&& dt != skill_lookup("poison") ) )
{
ch->combat_timer = 90;
victim->combat_timer = 90;
}
/*
* Lets stick in the enhanced spell damage from spellcraft.
*/
/* FIXME needs to check to make sure the damage is magical */
if (!IS_NPC(ch) && (number_percent() < (ch->pcdata->learned[skill_lookup("improved concentration")]/10)))
{
if (skill_table[dt].is_spell) /* FIXED - Ahsile */
{
update_skpell( ch, skill_lookup("improved concentration"), 0 );
dam = number_range(dam , (int) (dam * 1.25));
}
}
/*
* Stop up any residual loopholes.
*/
if ( dam > 6000 )
{
char buf [ MAX_STRING_LENGTH ];
// if ( ( dt != 91 && dt != 268 && dt != 269 && dt != 92 && dt != 229 && dt != 347 && dt != 402 && dt != 304 && dt != 353 && dt != 37 ) && ch->level <= LEVEL_DEMIGOD )
/* 37 - Energy Dragin */
/* 174 - Ultrablast */
/* 269 - Assassinate */
/* 445 - Death Strike */
if ( ( dt != 37 && dt != 174 && dt != 445 && dt != 269 ) && ch->level <= LEVEL_DEMIGOD )
{
if ( IS_NPC( ch ) && ch->desc && ch->desc->original )
sprintf( buf,
"Damage: %d from %s by %s: > 6000 points with %d dt!",
dam, ch->name, ch->desc->original->name, dt );
else
sprintf( buf,
"Damage: %d from %s: > 6000 points with %d dt!",
dam, ch->name, dt );
bug( buf, 0 );
}
}
if ( victim != ch )
{
/*
* Certain attacks are forbidden.
* Most other attacks are returned.
*/
if ( !IS_NPC(ch) && !IS_NPC(victim) && !is_pkillable( ch, victim) )
{
return;
}
if ( is_safe( ch, victim ) )
return;
check_killer( ch, victim );
if ( victim->position > POS_STUNNED )
{
if ( !victim->fighting )
set_fighting( victim, ch );
victim->position = POS_FIGHTING;
}
if ( victim->position > POS_STUNNED )
{
if ( !ch->fighting )
{
ch->initiated = TRUE;
set_fighting( ch, victim );
}
/*
* If victim is charmed, ch might attack victim's master.
*/
if ( IS_NPC( ch )
&& IS_NPC( victim )
&& IS_AFFECTED( victim, AFF_CHARM )
&& victim->master
&& victim->master->in_room == ch->in_room
&& number_bits( 3 ) == 0 )
{
stop_fighting( ch, FALSE );
set_fighting( ch, victim->master );
return;
}
}
/*
* More charm stuff.
*/
if ( victim->master == ch )
stop_follower( victim );
/*
* Inviso attacks ... not.
*/
if ( IS_AFFECTED( ch, AFF_INVISIBLE ) )
{
affect_strip( ch, skill_lookup("invis") );
affect_strip( ch, skill_lookup("mass invis") );
REMOVE_BIT( ch->affected_by, AFF_INVISIBLE );
act(AT_GREY, "$n fades into existence.", ch, NULL, NULL, TO_ROOM );
}
if (IS_AFFECTED2( ch, AFF_PHASED ) )
{
affect_strip( ch, skill_lookup("phase shift") );
REMOVE_BIT( ch->affected_by2, AFF_PHASED );
act(AT_GREY, "$n returns from an alternate plane.", ch, NULL, NULL, TO_ROOM );
}
/* if you or target has shadow plane, and there is combat, this here gets rid of it */
if ( IS_AFFECTED2( ch, AFF_SHADOW_PLANE ) )
{
affect_strip( ch, skill_lookup("shadow plane") );
REMOVE_BIT( ch->affected_by2, AFF_SHADOW_PLANE );
act(AT_BLOOD, "$n returns to reality!", ch, NULL, NULL, TO_ROOM );
}
if ( IS_AFFECTED4( ch, AFF_BURROW ) )
{
affect_strip( ch, skill_lookup("tomba di vemon") );
REMOVE_BIT( ch->affected_by4, AFF_BURROW );
act(AT_BLOOD, "$n is expelled from the earth!", ch, NULL, NULL, TO_ROOM );
}
if ( IS_AFFECTED2( victim, AFF_SHADOW_PLANE ) )
{
affect_strip (victim, skill_lookup("shadow plane") );
REMOVE_BIT( victim->affected_by2, AFF_SHADOW_PLANE );
act(AT_BLOOD, "$n returns to reality!", victim, NULL, NULL, TO_ROOM );
}
if ( IS_AFFECTED4( victim, AFF_BURROW ) )
{
affect_strip (victim, skill_lookup("tomba di vemon") );
REMOVE_BIT( victim->affected_by4, AFF_BURROW );
act(AT_BLOOD, "$n is expelled from the earth!", victim, NULL, NULL, TO_ROOM );
}
/*
* Proficiency modifiers
*/
if (dt > TYPE_HIT && !IS_NPC(ch) )
{
int prof = dt - TYPE_HIT;
int sn = 0;
if ( (
flag_value(weapon_flags, "hit") == prof
|| flag_value(weapon_flags, "claw") == prof
|| flag_value(weapon_flags, "blast") == prof
|| flag_value(weapon_flags, "whip") == prof
|| flag_value(weapon_flags, "grep") == prof
|| flag_value(weapon_flags, "bite") == prof
|| flag_value(weapon_flags, "suction") == prof
)
&& ch->pcdata->learned[(sn = skill_lookup("proficiency hit"))] )
{
dam += (int) ( dam * (ch->pcdata->learned[sn] / 10000.0f) );
update_skpell( ch, sn, 0 );
} else if ( (
flag_value(weapon_flags, "stab") == prof
|| flag_value(weapon_flags, "pierce") == prof
)
&& ch->pcdata->learned[(sn = skill_lookup("proficiency pierce"))] )
{
dam += (int) ( dam * (ch->pcdata->learned[sn] / 10000.0f) );
update_skpell( ch, sn, 0 );
} else if ( (
flag_value(weapon_flags, "slash") == prof
)
&& ch->pcdata->learned[(sn = skill_lookup("proficiency slash"))] )
{
dam += (int) ( dam * (ch->pcdata->learned[sn] / 10000.0f) );
update_skpell( ch, sn, 0 );
} else if ( (
flag_value(weapon_flags, "slice") == prof
)
&& ch->pcdata->learned[(sn = skill_lookup("proficiency slice"))] )
{
dam += (int) ( dam * (ch->pcdata->learned[sn] / 10000.0f) );
update_skpell( ch, sn, 0 );
} else if ( (
flag_value(weapon_flags, "crush") == prof
|| flag_value(weapon_flags, "pound") == prof
)
&& ch->pcdata->learned[(sn = skill_lookup("proficiency crush"))] )
{
dam += (int) ( dam * (ch->pcdata->learned[sn] / 10000.0f) );
update_skpell( ch, sn, 0 );
} else if ( (
flag_value(weapon_flags, "chop") == prof
)
&& ch->pcdata->learned[(sn = skill_lookup("proficiency chop"))] )
{
dam += (int) ( dam * (ch->pcdata->learned[sn] / 10000.0f) );
update_skpell( ch, sn, 0 );
}
}
/*
* Damage modifiers.
*/
if ( !IS_NPC(victim) && !IS_NPC(ch))
{
dam -= dam / 2;
ch->pkill_timer = 0; /* added to insure that if a player is damaging another
player, his pk timer is set to 0 */
}
if ( ch->race == 0 && ch->class == 7)
dam = (int)(dam * 0.8);
if ( IS_AFFECTED( victim, AFF_SANCTUARY ) || IS_AFFECTED4( victim, AFF_BIOFEEDBACK ) || IS_AFFECTED4( victim, AFF_ESSENCE_OF_GAIA ) || IS_SET( race_table[ victim->race ].race_abilities, RACE_SANCT ) )
dam = (int)(dam / 1.5);
if ( IS_AFFECTED4( victim, AFF_EARTHSHIELD ) )
dam = (int)(dam / 1.3);
if ( IS_AFFECTED2( victim, AFF_THICK_SKIN ) )
dam = (int)(dam / 1.15);
if ( IS_AFFECTED2( victim, AFF_GOLDEN_ARMOR ) )
dam = (int)(dam / 1.35);
if ( IS_AFFECTED4( victim, AFF_GOLDEN_SANCTUARY ) )
dam = (int)(dam / 1.5);
if ( IS_AFFECTED2( victim, AFF_SHADOW_IMAGE ) )
dam = (int)(dam / 1.25);
if ( IS_AFFECTED2( victim, AFF_GHOST_SHIELD ) )
dam = (int)(dam / 1.05);
if ( IS_AFFECTED3( victim, AFF_SATANIC_INFERNO ) )
dam = (int)(dam / 1.05);
if ( IS_AFFECTED2( victim, AFF_DANCING ) )
dam = (int)(dam * 1.25);
if ( IS_AFFECTED( victim, AFF_FIRESHIELD ) )
dam = (int)(dam / 1.05);
if ( IS_AFFECTED4( victim, AFF_LEAF_SHIELD ) )
dam = (int)(dam / 1.05);
if ( IS_AFFECTED3( victim, AFF_COFIRE ) )
dam = (int)(dam / 1.05);
if ( IS_AFFECTED3( victim, AFF_AURA_ANTI_MAGIC ) )
dam = (int)(dam / 1.05);
if ( IS_AFFECTED( victim, AFF_ICESHIELD ) )
dam = (int)(dam / 1.05);
if ( IS_AFFECTED2( victim, AFF_MIST) )
dam = (int)(dam / 1.25);
if ( IS_AFFECTED( victim, AFF_CHAOS ) )
dam = (int)(dam / 1.05);
if ( IS_AFFECTED( victim, AFF_SHOCKSHIELD ) )
dam = (int)(dam / 1.15);
if ( IS_AFFECTED3( victim, AFF_BLOODSHIELD ) )
dam = (int)(dam / 1.15);
if ( IS_AFFECTED2( victim, AFF_UNHOLY_STRENGTH ) )
dam = (int)(dam / 1.12);
if ( IS_AFFECTED( victim, AFF_INERTIAL ) )
dam = (int)(dam / 1.05);
if ( IS_AFFECTED3( victim, AFF_DEMONSHIELD ) )
dam = (int)(dam / 1.10);
if ( IS_AFFECTED3( victim, AFF_ACIDSHIELD ) )
dam = (int)(dam / 1.15);
if ( IS_AFFECTED4( victim, AFF_LIQUID_SKIN ) )
dam = (int)(dam / 1.15);
if ( IS_AFFECTED4( victim, AFF_ANGELIC_AURA ) )
dam = (int)(dam / 1.10);
if ( IS_AFFECTED4( victim, AFF_FORCE_OF_NATURE ) )
dam = (int)(dam / 1.15 );
if ( IS_SET( victim->act, PLR_UNDEAD ) )
dam = (int)(dam / 1.05);
if ( ( IS_AFFECTED( victim, AFF_PROTECT )
|| IS_SET( race_table[ victim->race ].race_abilities,
RACE_PROTECTION ) )
&& IS_EVIL( ch ) )
dam = (int)(dam / 1.1);
if ( IS_AFFECTED2( victim, AFF_PROTECTION_GOOD ) )
dam = (int)(dam / 1.1);
/* Damclass Stuff --Manaux */
dam = damclass_adjust(victim, dam, dt);
if ( dam < 0 )
dam = 0;
/*
* Check for disarm, trip, parry, and dodge.
*/
if ( dt >= TYPE_HIT || dt == skill_lookup("kick") || dt == skill_lookup("feed") || dt == skill_lookup("punch") )
{
int leveldiff = ch->level - victim->level;
if ( IS_NPC( ch ) && number_percent( )
< ( leveldiff < -5 ? ch->level / 2 : UMAX( 10, leveldiff ) )
&& dam == 0 && number_bits(4) == 0)
disarm( ch, victim );
if ( IS_NPC( ch )
&& IS_SET( race_table[ ch->race ].race_abilities,
RACE_WEAPON_WIELD )
&& number_percent() < UMIN( 25, UMAX( 10, ch->level ) )
&& !IS_NPC( victim ) )
use_magical_item( ch );
}
}
if ( ( !IS_NPC(ch) ) && ( !IS_NPC(victim) ) )
dam -= dam/4;
/*
* Hurt the victim.
* Inform the victim of his new state.
*/
/* tell the victim how much he got hurt */
if ( dt != TYPE_UNDEFINED )
dam_message( ch, victim, dam, dt );
if ( dam > 25 && number_range( 0, 100 ) <= 15 )
item_damage(victim, dam);
victim->hit -= dam;
if ( !IS_NPC( victim )
&& victim->level >= LEVEL_IMMORTAL
&& victim->hit < 1 )
victim->hit = 1;
if ( IS_AFFECTED4( victim, AFF_IMMORTAL ) && ( victim->hit < 1 ) )
{
victim->hit = 1;
}
/*
if ( !IS_NPC( victim )
&& victim->clev == 5
&& victim->clan == 8
&& victim->hit < 1 )
victim->hit = 1;
*/
if ( dam > 0 && dt > TYPE_HIT
&& is_wielding_poisoned( ch )
&& !saves_spell( ch->level, victim ) )
{
AFFECT_DATA af;
if( !IS_AFFECTED( victim, AFF_POISON ) )
{
af.type = skill_lookup("poison");
af.duration = 1;
af.location = APPLY_STR;
af.modifier = -2;
af.bitvector = AFF_POISON;
affect_join( victim, &af );
add_poison( victim, 1 );
}
}
if ( dam > 0 && dt > TYPE_HIT
&& is_wielding_flaming( ch )
&& number_percent( ) < 30 )
damage( ch, victim, spell_fireball ( skill_lookup("fireball"), 20, ch, victim ), skill_lookup("fireball"));
if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( dam > 0 && dt > TYPE_HIT
&& is_wielding_icy( ch )
&& number_percent( ) < 30 )
damage( ch, victim, spell_icestorm ( skill_lookup("iceball"), 20, ch, victim ), skill_lookup("iceball"));
if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( dam > 0 && dt > TYPE_HIT && is_wielding_sparking( ch )
&& number_percent( ) < 30 )
damage( ch, victim, spell_lightning_bolt ( skill_lookup("lightning bolt"), 20, ch, victim ), skill_lookup("lightning bolt"));
if ( dam > 0 && dt > TYPE_HIT && is_wielding_dispelling( ch )
&& number_percent( ) < 30 )
spell_dispel_magic ( skill_lookup("dispel magic"), 30, ch, victim );
if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( dam > 0 && dt > TYPE_HIT
&& is_wielding_chaos( ch )
&& number_percent( ) < 30 )
damage( ch, victim, spell_energy_drain ( skill_lookup("energy drain"), 45, ch, victim ), skill_lookup("energy drain"));
if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( IS_SET( ch->act, PLR_UNDEAD )
&& !saves_spell(ch->level, victim ) )
{
AFFECT_DATA af;
af.type = skill_lookup("poison");
af.duration = 2;
af.location = APPLY_CON;
af.modifier = -1;
af.bitvector = AFF_POISON;
affect_join( victim, &af );
add_poison( victim, 2 );
}
update_pos( victim );
switch( victim->position )
{
case POS_MORTAL:
send_to_char(AT_RED,
"You are mortally wounded, and will die soon, if not aided.\n\r",
victim );
act(AT_RED, "$n is mortally wounded, and will die soon, if not aided.",
victim, NULL, NULL, TO_ROOM );
break;
case POS_INCAP:
send_to_char(AT_RED,
"You are incapacitated and will slowly die, if not aided.\n\r",
victim );
act(AT_RED, "$n is incapacitated and will slowly die, if not aided.",
victim, NULL, NULL, TO_ROOM );
break;
case POS_STUNNED:
send_to_char(AT_WHITE,"You are stunned, but will probably recover.\n\r",
victim );
act(AT_WHITE, "$n is stunned, but will probably recover.",
victim, NULL, NULL, TO_ROOM );
break;
case POS_DEAD:
send_to_char(AT_BLOOD, "You have been KILLED!!\n\r\n\r", victim );
act(AT_BLOOD, "$n is DEAD!!", victim, NULL, NULL, TO_ROOM );
break;
default:
if ( dam > victim->max_hit / 4 )
send_to_char(AT_RED, "That really did HURT!\n\r", victim );
if ( victim->hit < victim->max_hit / 4 )
send_to_char(AT_RED, "You sure are BLEEDING!\n\r", victim );
break;
}
/*
* Payoff for killing things.
*/
if ( victim->position == POS_DEAD )
{
group_gain( ch, victim );
stop_fighting( victim, FALSE );
stop_fighting( ch, FALSE );
if(((ch->guild != NULL) ? ch->guild->type & GUILD_CHAOS : 0)
&& ch->guild == victim->guild
&& victim->guild_rank > ch->guild_rank)
{
int temp;
temp = ch->guild_rank;
ch->guild_rank = victim->guild_rank;
victim->guild_rank = temp;
}
if ( !IS_NPC(ch) && !IS_NPC(victim) && (ch->name != victim->name) )
{
CLAN_DATA *pClan;
CLAN_DATA *Cland;
RELIGION_DATA *pReligion;
RELIGION_DATA *Religiond;
pClan = get_clan_index(ch->clan);
Cland = get_clan_index(victim->clan);
if(ch->clan != victim->clan )
{
pClan->pkills++;
Cland->pdeaths++;
}
pReligion = get_religion_index(ch->religion );
Religiond = get_religion_index(victim->religion );
if(ch->religion != victim->religion )
{
pReligion->pkills++;
Religiond->pdeaths++;
}
}
if ( ( !IS_NPC(ch) ) && ( IS_NPC(victim) ) )
{
CLAN_DATA *pClan;
pClan=get_clan_index(ch->clan);
pClan->mkills++;
}
if ( ( !IS_NPC(ch) ) && ( IS_NPC(victim) ) )
{
RELIGION_DATA *pReligion;
pReligion=get_religion_index(ch->religion);
pReligion->mkills++;
}
if ( ( IS_NPC(ch) ) && (!IS_NPC(victim)) )
{
CLAN_DATA *pClan;
pClan=get_clan_index(victim->clan);
pClan->mdeaths++;
}
if ( ( IS_NPC(ch) ) && (!IS_NPC( victim ) ) )
{
RELIGION_DATA *pReligion;
pReligion=get_religion_index(victim->religion );
pReligion->mdeaths++;
}
if ( !IS_NPC(ch) ) {
if ( is_affected( ch, skill_lookup("berserk") ) )
{
affect_strip( ch, skill_lookup("berserk") );
send_to_char(C_DEFAULT, skill_table[skill_lookup("berserk")].msg_off,ch);
send_to_char(C_DEFAULT, "\n\r",ch);
}
if ( IS_AFFECTED2(ch, AFF_BERSERK) )
REMOVE_BIT(ch->affected_by2, AFF_BERSERK);
if ( is_affected( ch, skill_lookup("bloodthirsty") ) )
{
affect_strip( ch, skill_lookup("bloodthirsty") );
send_to_char(C_DEFAULT, skill_table[skill_lookup("bloodthirsty")].msg_off,ch);
send_to_char(C_DEFAULT, "\n\r",ch);
}
if ( IS_AFFECTED3(ch, AFF_BLOODTHIRSTY) )
REMOVE_BIT(ch->affected_by3, AFF_BLOODTHIRSTY);
}
if ( !IS_NPC( victim ) )
{
/*
* Dying penalty:
* 1/2 way back to previous level.
*/
if ( IS_NPC(ch))
{
if ( ( victim->exp > 1000 * victim->level ) && ( !IS_SET(victim->act, PLR_GHOST ) ) )
{
gain_exp( victim, ( 1000 * victim->level - victim->exp ) / 2 );
}
}
sprintf( log_buf, "%s killed by %s at %d.", victim->name,
ch->name, victim->in_room->vnum );
log_string( log_buf, CHANNEL_LOG, -1 );
sprintf( log_buf, "%s was slaughtered by %s.", victim->name, ch->name);
if(IS_NPC ( ch ) )
{
sprintf( log_buf, "%s was slaughtered by %s.", victim->name, ch->short_descr );
}
if(!IS_NPC( ch ) && !IS_NPC( victim ) )
{
broadcast_channel( ch, log_buf, CHANNEL_INFO, "!!SOUND(death8.wav V=100 L=1 P=100 T=Pkill)");
}
else
{
int tempvar = number_range( 1, 6 );
switch( tempvar )
{
default:
broadcast_channel( ch, log_buf, CHANNEL_INFO, "!!SOUND(death6.wav V=100 L=1 P=50 T=Combat)");
break;
case 1:
broadcast_channel( ch, log_buf, CHANNEL_INFO, "!!SOUND(death1.wav V=100 L=1 P=50 T=Combat)");
break;
case 2:
broadcast_channel( ch, log_buf, CHANNEL_INFO, "!!SOUND(death2.wav V=100 L=1 P=50 T=Combat)");
break;
case 3:
broadcast_channel( ch, log_buf, CHANNEL_INFO, "!!SOUND(death3.wav V=100 L=1 P=50 T=Combat)");
break;
case 4:
broadcast_channel( ch, log_buf, CHANNEL_INFO, "!!SOUND(death4.wav V=100 L=1 P=50 T=Combat)");
break;
case 5:
broadcast_channel( ch, log_buf, CHANNEL_INFO, "!!SOUND(death5.wav V=100 L=1 P=50 T=Combat)");
break;
case 6:
broadcast_channel( ch, log_buf, CHANNEL_INFO, "!!SOUND(death7.wav V=100 L=1 P=50 T=Combat)");
break;
}
}
stop_fighting(ch,TRUE);
victim->hit = 1;
victim->pkill_timer = time( NULL );
if ( !IS_NPC(ch) && (ch->name != victim->name ) ) {
ch->pcdata->awins += 1;
victim->pcdata->alosses += 1;
}
/* strip the guy */
for ( paf = victim->affected; paf; paf = paf_next )
{
paf_next = paf->next;
if( !paf->deleted )
affect_remove( victim, paf );
}
for ( paf = victim->affected2; paf; paf = paf_next )
{
paf_next = paf->next;
if( !paf->deleted )
affect_remove2( victim, paf );
}
for ( paf = victim->affected3; paf; paf = paf_next )
{
paf_next = paf->next;
if( !paf->deleted )
affect_remove3( victim, paf );
}
for ( paf = victim->affected4; paf; paf = paf_next )
{
paf_next = paf->next;
if( !paf->deleted && paf->type != skill_lookup("newbie slayer"))
{
affect_remove4( victim, paf );
}
}
for ( paf = victim->affected_powers; paf; paf = paf_next )
{
paf_next = paf->next;
if( !paf->deleted )
affect_remove_powers( victim, paf );
}
for ( paf = victim->affected_weaknesses; paf; paf = paf_next )
{
paf_next = paf->next;
if( !paf->deleted )
affect_remove_weaknesses( victim, paf );
}
update_pos( victim );
victim->shields = 0;
save_clans();
save_religions();
if(!IS_NPC( ch ) && !IS_NPC( victim ) && (ch->name != victim->name ) )
{
RELIGION_DATA* pRel = get_religion_index(victim->religion);
char_from_room(victim);
if (pRel->recall != ROOM_VNUM_OUTSIDEMETH )
char_to_room(victim, get_room_index(ROOM_VNUM_ALOSER) );
else
char_to_room(victim,get_room_index(pRel->recall));
for ( iWear = 0; iWear < MAX_WEAR; iWear++ )
{
remove_requip( victim, iWear );
}
return;
}
}
raw_kill( ch, victim );
if( IS_NPC( victim ) && !IS_NPC( ch ) )
{
ch->pcdata->mobkills ++;
}
/* Ok, now we want to remove the deleted flag from the
* PC victim.
*/
if ( !IS_NPC( victim ) )
victim->deleted = FALSE;
if ( !IS_NPC( ch ) && IS_NPC( victim ) )
{
if ( IS_SET( ch->act, PLR_AUTOLOOT ) )
do_get( ch, "all corpse" );
else
do_look( ch, "in corpse" );
if ( IS_SET( ch->act, PLR_AUTOGOLD ) )
do_get( ch, "gold corpse" );
if ( IS_SET( ch->act, PLR_AUTOSAC ) )
do_sacrifice( ch, "corpse" );
}
return;
}
/*
* Sleep spells and extremely wounded folks.
*/
if ( !IS_AWAKE( victim ) )
stop_fighting(victim, FALSE);
if ( victim == ch )
return;
/*
* Take care of link dead people.
*/
if ( !IS_NPC( victim ) && !victim->desc )
{
if ( number_range( 0, victim->wait ) == 0 )
{
do_recall( victim, "" );
return;
}
}
/*
* Wimp out?
*/
if ( IS_NPC( victim ) && dam >= 0 )
{
if ( ( IS_SET( victim->act, ACT_WIMPY ) && number_bits( 1 ) == 0
&& victim->hit < victim->max_hit / 2 )
|| ( IS_AFFECTED( victim, AFF_CHARM ) && victim->master
&& victim->master->in_room != victim->in_room ) )
do_flee( victim, "" );
}
if ( ( !IS_NPC( victim )
&& victim->hit > 0
&& victim->hit <= victim->wimpy
&& victim->wait == 0 )
&& !IS_AFFECTED3(victim, AFF_BLOODTHIRSTY)
&& !IS_AFFECTED2(victim, AFF_BERSERK) )
do_flee( victim, "" );
tail_chain( );
return;
}
void item_damage( CHAR_DATA *ch, int dam )
{
OBJ_DATA *obj_lose;
OBJ_DATA *obj_next;
for ( obj_lose = ch->carrying; obj_lose; obj_lose = obj_next )
{
char *msg;
int damage = 0;
obj_next = obj_lose->next_content;
if( obj_lose->deleted )
continue;
if( number_bits( 2 ) != 0 )
continue;
if( obj_lose->wear_loc == WEAR_NONE )
continue;
if( IS_SET( obj_lose->extra_flags, ITEM_NO_DAMAGE ) )
continue;
damage = obj_lose->durability_cur % 10;
if( damage >= 5 )
damage = 5;
if( damage <= 0 )
continue;
if( obj_lose->weight <= 25 )
{
if( obj_lose->weight * 2 <= number_percent( ) )
continue;
}
else
{
if( number_percent( ) <= 50 )
continue;
}
switch ( obj_lose->item_type )
{
default:
msg = "Your $p gets ruined!";
extract_obj( obj_lose );
break;
case ITEM_DRINK_CON:
case ITEM_POTION:
case ITEM_CONTAINER:
case ITEM_LIGHT:
msg = "Your $p shatters!";
extract_obj( obj_lose );
break;
case ITEM_WEAPON:
case ITEM_ARMOR:
if( obj_lose->durability_cur > 0 )
{
obj_lose->durability_cur -= damage;
}
if( obj_lose->durability_cur <= 0 )
{
OBJ_DATA *pObj;
OBJ_INDEX_DATA *pObjIndex;
char *name;
char buf[MAX_STRING_LENGTH];
pObjIndex = get_obj_index(4);
pObj = create_object(pObjIndex, obj_lose->level);
name = obj_lose->short_descr;
sprintf(buf, pObj->description, name);
free_string(pObj->description);
pObj->description = str_dup(buf);
pObj->weight = obj_lose->weight;
pObj->timer = obj_lose->level;
msg = "$p has been destroyed!";
extract_obj( obj_lose );
obj_to_room ( pObj, ch->in_room );
}
else
{
msg = "$p has been damaged!";
}
break;
}
act(AT_YELLOW, msg, ch, obj_lose, NULL, TO_CHAR );
return;
}
return;
}
bool is_safe( CHAR_DATA *ch, CHAR_DATA *victim )
{
if ( IS_SET( ch->in_room->room_flags, ROOM_SAFE ) ||
IS_SET( victim->in_room->room_flags, ROOM_SAFE ) )
return TRUE;
if( ch->position == POS_GHOST || victim->position == POS_GHOST )
return TRUE;
if ( !IS_NPC(ch) && !IS_NPC(victim) &&
(IS_SET(ch->in_room->room_flags, ROOM_NO_PKILL) ||
IS_SET(victim->in_room->room_flags, ROOM_NO_PKILL)) )
return TRUE;
if ( IS_SET( ch->in_room->room_flags, ROOM_PKILL ) &&
IS_SET( victim->in_room->room_flags, ROOM_PKILL ) )
return FALSE;
if ( IS_NPC( victim ) )
return FALSE;
if ( IS_NPC( ch ) )
{
if ( IS_SET(ch->affected_by, AFF_CHARM) && ch->master )
{
CHAR_DATA *nch;
for ( nch = ch->in_room->people; nch; nch = nch->next )
if ( nch == ch->master )
break;
if ( nch == NULL )
return FALSE;
else
ch = nch; /* Check person who ordered mob for clan stuff.. */
}
else
return FALSE;
}
/* give pkill guilds ability to pkill */
/* Err.. we might not want pkill guilds attacking unguilded.. */
if ( (ch->guild && (ch->guild->type & GUILD_PKILL)) &&
(victim->guild && (victim->guild->type & GUILD_PKILL)) )
{
return FALSE;
}
/* can murder self for testing =) */
if ( ch->clan == victim->clan && ch != victim && (ch->clan != 0 && victim->clan != 0))
{
send_to_char(AT_WHITE, "You cannot murder your own clan member.\n\r",ch);
return TRUE;
}
if ( IS_SET( victim->act, PLR_KILLER ) )
return FALSE;
return FALSE;
}
/*
* See if an attack justifies a KILLER flag.
*/
void check_killer( CHAR_DATA *ch, CHAR_DATA *victim )
{
/*
* NPC's are fair game.
*/
if ( IS_NPC( victim ) )
return;
/* In arena rooms player killing is legal. Doesn't give you any
* experience gain or loss either. -- Maniac --
*/
/*
* NPC's are fair game.
* So are killers and thieves.
*/
if ( IS_SET( victim->act, PLR_KILLER )
|| IS_SET( victim->act, PLR_THIEF ) )
return;
/*
* NPC's are cool of course
* Hitting yourself is cool too (bleeding).
* And current killers stay as they are.
*/
if ( IS_NPC( ch )
|| ch == victim
|| IS_SET( ch->act, PLR_KILLER ) )
return;
if ( ch->clan != 0 )
return;
return;
}
/*
* Check to see if weapon is poisoned.
*/
bool is_wielding_poisoned( CHAR_DATA *ch )
{
OBJ_DATA *obj;
if ( ( obj = get_eq_char( ch, WEAR_WIELD ) )
&& IS_SET( obj->extra_flags, ITEM_POISONED ) )
return TRUE;
return FALSE;
}
bool is_wielding_flaming( CHAR_DATA *ch )
{
OBJ_DATA *obj;
if ( ( obj = get_eq_char( ch, WEAR_WIELD ) )
&& IS_SET( obj->extra_flags, ITEM_FLAME ) )
return TRUE;
return FALSE;
}
bool is_wielding_sparking( CHAR_DATA *ch )
{
OBJ_DATA *obj;
if ( ( obj = get_eq_char( ch, WEAR_WIELD ) )
&& IS_SET( obj->extra_flags2, ITEM_SPARKING ) )
return TRUE;
return FALSE;
}
bool is_wielding_acid( CHAR_DATA *ch )
{
OBJ_DATA *obj;
if ( ( obj = get_eq_char( ch, WEAR_WIELD ) )
&& IS_SET( obj->extra_flags, ITEM_ACID ) )
return TRUE;
return FALSE;
}
bool is_wielding_dispelling( CHAR_DATA *ch )
{
OBJ_DATA *obj;
if ( ( obj = get_eq_char( ch, WEAR_WIELD ) )
&& IS_SET( obj->extra_flags2, ITEM_DISPEL ) )
return TRUE;
return FALSE;
}
bool is_wielding_icy( CHAR_DATA *ch )
{
OBJ_DATA *obj;
if ( ( obj = get_eq_char( ch, WEAR_WIELD ) )
&& IS_SET( obj->extra_flags, ITEM_ICY ) )
return TRUE;
return FALSE;
}
bool is_wielding_chaos( CHAR_DATA *ch )
{
OBJ_DATA *obj;
if ( ( obj = get_eq_char( ch, WEAR_WIELD ) )
&& IS_SET( obj->extra_flags, ITEM_CHAOS ) )
return TRUE;
return FALSE;
}
/*
* Check for parry.
*/
bool check_parry( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount )
{
int chance;
if ( !IS_AWAKE( victim ) )
return FALSE;
if ( IS_NPC( victim ) )
{
chance = UMIN( 50, 2 * victim->level );
if ( !get_eq_char( victim, WEAR_WIELD ) )
return FALSE;
}
else
{
if ( !get_eq_char( victim, WEAR_WIELD ) )
return FALSE;
if (!can_use_skspell( victim, skill_lookup("parry")))
{
return FALSE;
}
chance = victim->pcdata->learned[skill_lookup("parry")] / 20;
}
/* STR mod for high str victim */
chance += get_curr_str(victim) - get_curr_str(ch);
/* Mod for what attack this is in a round */
chance -= (attackCount - 1) * 4;
if(IS_AFFECTED2(victim, AFF_BERSERK) || IS_AFFECTED3(victim, AFF_BLOODTHIRSTY) )
{
chance /= 2;
}
if ( ch->wait == 0 )
chance /= 2;
if ( victim->wait != 0 )
chance /= 2;
if ( !IS_NPC( victim ) )
{
if ( chance < victim->pcdata->learned[skill_lookup("parry")] / 50 )
{
chance = victim->pcdata->learned[skill_lookup("parry")] / 50;
}
}
if ( ( number_percent( ) >= chance ) || IS_AFFECTED2( ch, AFF_BERSERK ) || IS_AFFECTED3( ch, AFF_BLOODTHIRSTY ) )
return FALSE;
update_skpell( victim, skill_lookup("parry"), 0 );
if ( IS_SET( ch->act, PLR_COMBAT ) )
act(AT_GREEN, "$N parries your attack.", ch, NULL, victim, TO_CHAR );
if ( IS_SET( victim->act, PLR_COMBAT ) )
act(AT_GREEN, "You parry $n's attack.", ch, NULL, victim, TO_VICT );
return TRUE;
}
bool check_enhanced_parry( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount )
{
int chance;
if ( !IS_AWAKE( victim ) )
return FALSE;
if ( IS_NPC( victim ) )
{
return FALSE;
}
else
{
if ( !get_eq_char( victim, WEAR_WIELD ) )
return FALSE;
if (!can_use_skspell( victim, skill_lookup("enhanced parry")))
{
return FALSE;
}
chance = victim->pcdata->learned[skill_lookup("enhanced parry")] / 40;
}
/* STR mod for high str victim */
chance += get_curr_str(victim) - get_curr_str(ch);
/* Mod for what attack this is in a round */
chance -= (attackCount - 1) * 4;
if(IS_AFFECTED2(victim, AFF_BERSERK) || IS_AFFECTED3(victim, AFF_BLOODTHIRSTY) )
{
chance /= 2;
}
if ( ch->wait == 0 )
chance /= 2;
if ( victim->wait != 0 )
chance /= 2;
if ( !IS_NPC( victim ) )
{
if ( chance < victim->pcdata->learned[skill_lookup("enhanced parry")] / 50 )
{
chance = victim->pcdata->learned[skill_lookup("enhanced parry")] / 50;
}
}
if ( ( number_percent( ) >= chance ) || IS_AFFECTED2( ch, AFF_BERSERK ) || IS_AFFECTED3( ch, AFF_BLOODTHIRSTY ) )
return FALSE;
update_skpell( victim, skill_lookup("enhanced parry"), 0 );
if ( IS_SET( ch->act, PLR_COMBAT ) )
act(AT_GREEN, "$N parries your attack.", ch, NULL, victim, TO_CHAR );
if ( IS_SET( victim->act, PLR_COMBAT ) )
act(AT_GREEN, "You parry $n's attack.", ch, NULL, victim, TO_VICT );
return TRUE;
}
bool check_shield_block( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount )
{
int chance;
if ( !IS_AWAKE( victim ) )
return FALSE;
if ( !get_eq_char( victim, WEAR_SHIELD ) )
return FALSE;
if ( IS_NPC( victim ) )
{
chance = UMIN( 50, 2 * victim->level );
}
else
{
if( victim->pcdata->learned[skill_lookup("shield block")] < 300 )
{
chance = number_range( 1, 15 );
}
else
{
chance = victim->pcdata->learned[skill_lookup("shield block")] / 20;
}
}
if ( ch->wait == 0 )
chance /= 2;
if ( victim->wait != 0 )
chance /= 2;
/* STR mod for high str victim */
chance += get_curr_str(victim) - get_curr_str(ch);
/* Mod for what attack this is in a round */
chance -= (attackCount - 1) * 4;
if(IS_AFFECTED2(victim, AFF_BERSERK) || IS_AFFECTED3(victim, AFF_BLOODTHIRSTY) )
{
chance /= 2;
}
if ( number_percent( ) >= chance + 10 )
return FALSE;
update_skpell( victim, skill_lookup("shield block"), 0 );
if ( IS_SET( ch->act, PLR_COMBAT ) )
act(AT_GREEN, "$N's shield blocks your attack.", ch, NULL, victim, TO_CHAR );
if ( IS_SET( victim->act, PLR_COMBAT ) )
act(AT_GREEN, "Your shield blocks $n's attack.", ch, NULL, victim, TO_VICT );
return TRUE;
}
/*
* Check for dodge.
*/
bool check_dodge( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount )
{
int chance;
if ( !IS_AWAKE( victim ) )
return FALSE;
if ( IS_NPC( victim ) )
{
return FALSE;
}
else
{
if (!can_use_skspell( victim, skill_lookup("dodge")))
{
return FALSE;
}
chance = victim->pcdata->learned[skill_lookup("dodge")] / 20;
}
/* DEX mod for high str victim */
chance += get_curr_dex(victim) - get_curr_dex(ch);
/* Mod for what attack this is in a round */
chance -= (attackCount - 1) * 4;
if( can_use_skspell( ch, skill_lookup("wilderness lore") ) )
{
if( !IS_NPC( ch ) )
{
if( ( number_percent( ) < ( ch->pcdata->learned[skill_lookup("wilderness master")] / 10 ) ) && IS_OUTSIDE( ch ) && IS_IN_NATURE( ch ) )
{
chance += ch->pcdata->learned[skill_lookup("wilderness lore")] / 80;
update_skpell( ch, skill_lookup("wilderness lore"), 0 );
}
}
}
if(IS_AFFECTED2(victim, AFF_BERSERK) || IS_AFFECTED3(victim, AFF_BLOODTHIRSTY) )
{
chance /= 2;
}
if ( ch->wait == 0 )
chance /= 2;
if ( victim->wait != 0 )
chance /= 2;
if ( !IS_NPC( victim ) )
{
if ( chance < victim->pcdata->learned[skill_lookup("dodge")] / 50 )
{
chance = victim->pcdata->learned[skill_lookup("dodge")] / 50;
}
}
if ( ( number_percent( ) >= chance ) || IS_AFFECTED2( ch, AFF_BERSERK ) || IS_AFFECTED3( ch, AFF_BLOODTHIRSTY ) )
return FALSE;
update_skpell( victim, skill_lookup("dodge"), 0 );
if ( IS_SET( ch->act, PLR_COMBAT ) )
act(AT_GREEN, "$N dodges your attack.", ch, NULL, victim, TO_CHAR );
if ( IS_SET( victim->act, PLR_COMBAT ) )
act(AT_GREEN, "You dodge $n's attack.", ch, NULL, victim, TO_VICT );
return TRUE;
}
bool check_enhanced_dodge( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount )
{
int chance;
if ( !IS_AWAKE( victim ) )
return FALSE;
if ( IS_NPC( victim ) )
{
return FALSE;
}
else
{
if (!can_use_skspell( victim, skill_lookup("enhanced dodge")))
{
return FALSE;
}
chance = victim->pcdata->learned[skill_lookup("enhanced dodge")] / 40;
}
/* DEX mod for high str victim */
chance += get_curr_dex(victim) - get_curr_dex(ch);
/* Mod for what attack this is in a round */
chance -= (attackCount - 1) * 4;
if(IS_AFFECTED2(victim, AFF_BERSERK) || IS_AFFECTED3(victim, AFF_BLOODTHIRSTY) )
{
chance /= 2;
}
if ( ch->wait == 0 )
chance /= 2;
if ( victim->wait != 0 )
chance /= 2;
if ( !IS_NPC( victim ) )
{
if ( chance < victim->pcdata->learned[skill_lookup("enhanced dodge")] / 50 )
{
chance = victim->pcdata->learned[skill_lookup("enhanced dodge")] / 50;
}
}
if ( ( number_percent( ) >= chance ) || IS_AFFECTED2( ch, AFF_BERSERK ) || IS_AFFECTED3( ch, AFF_BLOODTHIRSTY ) )
return FALSE;
update_skpell( victim, skill_lookup("enhanced dodge"), 0 );
if ( IS_SET( ch->act, PLR_COMBAT ) )
act(AT_GREEN, "$N dodges your attack.", ch, NULL, victim, TO_CHAR );
if ( IS_SET( victim->act, PLR_COMBAT ) )
act(AT_GREEN, "You dodge $n's attack.", ch, NULL, victim, TO_VICT );
return TRUE;
}
/*
* Set position of a victim.
*/
void update_pos( CHAR_DATA *victim )
{
if ( victim->hit > 0 )
{
if ( victim->position < POS_STUNNED )
victim->position = POS_STANDING;
return;
}
if ( IS_NPC( victim ) || victim->hit <= -11 )
{
//raw_kill( victim, victim );
victim->position = POS_DEAD;
return;
}
if ( victim->hit <= -6 ) victim->position = POS_MORTAL;
else if ( victim->hit <= -3 ) victim->position = POS_INCAP;
else victim->position = POS_STUNNED;
return;
}
/*
* Start fights.
*/
void set_fighting( CHAR_DATA *ch, CHAR_DATA *victim )
{
char buf [ MAX_STRING_LENGTH ];
if ( ch->fighting )
{
bug( "Set_fighting: already fighting", 0 );
sprintf( buf, "...%s attacking %s at %d",
( IS_NPC( ch ) ? ch->short_descr : ch->name ),
( IS_NPC( victim ) ? victim->short_descr : victim->name ),
victim->in_room->vnum );
bug( buf , 0 );
return;
}
if ( IS_AFFECTED( ch, AFF_SLEEP ) )
affect_strip( ch, skill_lookup("sleep") );
ch->fighting = victim;
ch->position = POS_FIGHTING;
return;
}
/*
* Stop fights.
*/
void stop_fighting( CHAR_DATA *ch, bool fBoth )
{
CHAR_DATA *fch;
for ( fch = char_list; fch; fch = fch->next )
{
if ( fch == ch || ( fBoth && fch->fighting == ch ) )
{
fch->fighting = NULL;
/* fch->hunting = NULL; */
fch->position = POS_STANDING;
fch->initiated = FALSE;
if ( is_affected( fch, skill_lookup("berserk") ) )
{
affect_strip( fch, skill_lookup("berserk") );
send_to_char(C_DEFAULT, skill_table[skill_lookup("berserk")].msg_off,fch);
send_to_char(C_DEFAULT, "\n\r",fch);
}
if ( IS_AFFECTED2(fch, AFF_BERSERK) )
REMOVE_BIT(fch->affected_by2, AFF_BERSERK);
if ( is_affected( fch, skill_lookup("bloodthirsty") ) )
{
affect_strip( fch, skill_lookup("bloodthirsty") );
send_to_char(C_DEFAULT, skill_table[skill_lookup("bloodthirsty")].msg_off,fch);
send_to_char(C_DEFAULT, "\n\r",fch);
}
if ( IS_AFFECTED3(fch, AFF_BLOODTHIRSTY) )
REMOVE_BIT(fch->affected_by3, AFF_BLOODTHIRSTY);
update_pos( fch );
}
}
return;
}
/*
* Make a corpse out of a character.
*/
void make_corpse( CHAR_DATA *ch )
{
OBJ_DATA *corpse;
OBJ_DATA *obj;
OBJ_DATA *obj_next;
char *name;
char buf [ MAX_STRING_LENGTH ];
if ( IS_NPC( ch ) )
{
/*
* This longwinded corpse creation routine comes about because
* we dont want anything created AFTER a corpse to be placed
* INSIDE a corpse. This had caused crashes from obj_update()
* in extract_obj() when the updating list got shifted from
* object_list to obj_free. --- Thelonius (Monk)
*/
if ( ch->gold > 0 )
{
OBJ_DATA * coins;
coins = create_money( ch->gold );
name = ch->short_descr;
if( IS_SET( ch->act, ACT_VEHICLE ) )
{
corpse = create_object(
get_obj_index( OBJ_VNUM_CORPSE_VEHICLE ),
0 );
corpse->value[0] = TAN_NONE;
corpse->value[1] = 0;
}
else
{
corpse = create_object(
get_obj_index( OBJ_VNUM_CORPSE_NPC ),
0 );
corpse->value[0] = TAN_NPC;
corpse->value[1] = ch->pIndexData->vnum;
}
corpse->timer = number_range( 2, 4 );
obj_to_obj( coins, corpse );
ch->gold = 0;
}
else
{
name = ch->short_descr;
if( IS_SET( ch->act, ACT_VEHICLE ) )
{
corpse = create_object(
get_obj_index( OBJ_VNUM_CORPSE_VEHICLE ),
0 );
corpse->value[0] = TAN_NONE;
corpse->value[1] = 0;
}
else
{
corpse = create_object(
get_obj_index( OBJ_VNUM_CORPSE_NPC ),
0 );
corpse->level = ch->pIndexData->level;
corpse->value[0] = TAN_NPC;
corpse->value[1] = ch->pIndexData->vnum;
}
corpse->timer = number_range( 2, 4 );
}
}
else
{
name = ch->name;
corpse = create_object(
get_obj_index( OBJ_VNUM_CORPSE_PC ),
0 );
corpse->value[0] = TAN_PC;
corpse->value[1] = ch->level;
corpse->timer = number_range( 25, 40 );
if ( ( ch->gold > 0 ) && ( ch->level > 5 ) )
{
OBJ_DATA * coins;
coins = create_money( ch->gold );
obj_to_obj( coins, corpse );
ch->gold = 0;
}
}
sprintf( buf, corpse->short_descr, name );
free_string( corpse->short_descr );
corpse->short_descr = str_dup( buf );
sprintf( buf, corpse->description, name );
free_string( corpse->description );
corpse->description = str_dup( buf );
for ( obj = ch->carrying; obj; obj = obj_next )
{
obj_next = obj->next_content;
if ( obj->deleted )
continue;
obj_from_char( obj );
if ( IS_SET( obj->extra_flags, ITEM_INVENTORY ) )
extract_obj( obj );
else
obj_to_obj( obj, corpse );
}
/* quill */
if ( ( ch->level <= 50 && number_percent() <= 1 && number_percent() < 10)
||( ch->level > 50 && ch->level < 90 && number_percent() < 2 )
||( ch->level >= 90 && number_percent() < 3 ) )
{
obj = create_object( get_obj_index( OBJ_VNUM_QUILL ) , 1);
obj_to_obj(obj, corpse);
}
/* pestle */
if ( ( ch->level <= 50 && number_percent() <= 1 && number_percent() < 10)
||( ch->level > 50 && ch->level < 90 && number_percent() < 2 )
||( ch->level >= 90 && number_percent() < 3 ) )
{
obj = create_object( get_obj_index( OBJ_VNUM_PESTLE ) , 1);
obj_to_obj(obj, corpse);
}
/* needle */
if ( ( ch->level <= 50 && number_percent() <= 1 && number_percent() < 10)
||( ch->level > 50 && ch->level < 90 && number_percent() < 2 )
||( ch->level >= 90 && number_percent() < 3 ) )
{
obj = create_object( get_obj_index( OBJ_VNUM_NEEDLE ) , 1);
obj_to_obj(obj, corpse);
}
sprintf( buf, "NPC killed: %s -> %d", ch->name, ch->in_room->vnum );
log_string( buf, CHANNEL_NONE, -1 );
if ( ( IS_NPC( ch ) ) && ( !IS_SET( ch->act, PLR_UNDEAD ) ) )
corpse->ac_vnum=ch->pIndexData->vnum;
if( !IS_SET( ch->act, ACT_NO_CORPSE ) )
{
obj_to_room( corpse, ch->in_room );
}
else
{
extract_obj( corpse );
}
if( !IS_NPC( ch ) )
{
corpse_back(ch, corpse );
}
return;
}
/*
* Improved Death_cry contributed by Diavolo.
*/
void death_cry( CHAR_DATA *ch )
{
ROOM_INDEX_DATA *was_in_room;
char *msg;
int vnum;
int door;
vnum = 0;
switch ( number_bits( 4 ) )
{
default: msg = "You hear $n's death cry."; break;
case 0: msg = "$n hits the ground ... DEAD."; break;
case 1: msg = "$n splatters blood on your armor."; break;
case 2: msg = "$n's innards fall to the ground with a wet splat."; break;
case 3: msg = "$n's severed head plops on the ground.";
vnum = OBJ_VNUM_SEVERED_HEAD; break;
case 4: msg = "$n's heart is torn from $s chest.";
vnum = OBJ_VNUM_TORN_HEART; break;
case 5: msg = "$n's arm is sliced from $s dead body.";
vnum = OBJ_VNUM_SLICED_ARM; break;
case 6: msg = "$n's leg is sliced from $s dead body.";
vnum = OBJ_VNUM_SLICED_LEG; break;
}
act(AT_BLOOD, msg, ch, NULL, NULL, TO_ROOM );
if ( vnum != 0 )
{
OBJ_DATA *obj;
char *name;
char buf [ MAX_STRING_LENGTH ];
name = IS_NPC( ch ) ? ch->short_descr : ch->name;
obj = create_object( get_obj_index( vnum ), 0 );
obj->timer = number_range( 4, 7 );
sprintf( buf, obj->short_descr, name );
free_string( obj->short_descr );
obj->short_descr = str_dup( buf );
sprintf( buf, obj->description, name );
free_string( obj->description );
obj->description = str_dup( buf );
obj_to_room( obj, ch->in_room );
}
vnum = OBJ_VNUM_FINAL_TURD;
if ( vnum != 0 )
{
OBJ_DATA *obj;
obj = create_object( get_obj_index( vnum ), 0 );
obj->timer = number_range( 3, 5 );
obj_to_room( obj, ch->in_room );
}
if ( IS_NPC( ch ) )
msg = "You hear something's death cry.";
else
msg = "You hear someone's death cry.";
was_in_room = ch->in_room;
for ( door = 0; door <= 5; door++ )
{
EXIT_DATA *pexit;
if ( ( pexit = was_in_room->exit[door] )
&& pexit->to_room
&& pexit->to_room != was_in_room )
{
ch->in_room = pexit->to_room;
act(AT_BLOOD, msg, ch, NULL, NULL, TO_ROOM );
}
}
ch->in_room = was_in_room;
return;
}
void raw_kill( CHAR_DATA *ch, CHAR_DATA *victim )
{
AFFECT_DATA *paf;
AFFECT_DATA *paf_next;
ROOM_INDEX_DATA *location;
if (victim->fighting)
stop_fighting( victim, TRUE );
if ( IS_NPC( victim) )
{
mprog_death_trigger( victim, ch );
}
rprog_death_trigger( victim->in_room, victim );
make_corpse( victim );
for ( paf = victim->affected; paf; paf = paf_next )
{
paf_next = paf->next;
affect_remove( victim, paf );
}
for ( paf = victim->affected2; paf; paf = paf_next )
{
paf_next = paf->next;
affect_remove2( victim, paf );
}
for ( paf = victim->affected3; paf; paf = paf_next )
{
paf_next = paf->next;
affect_remove3( victim, paf );
}
for ( paf = victim->affected4; paf; paf = paf_next )
{
paf_next = paf->next;
if (paf->type != skill_lookup("newbie slayer"))
affect_remove4( victim, paf );
}
for ( paf = victim->affected_powers; paf; paf = paf_next )
{
paf_next = paf->next;
affect_remove_powers( victim, paf );
}
for ( paf = victim->affected_weaknesses; paf; paf = paf_next )
{
paf_next = paf->next;
affect_remove_weaknesses( victim, paf );
}
victim->affected_by = 0;
victim->affected_by2 &= CODER;
victim->affected_by3 = 0;
victim->affected_by4 = 0;
victim->affected_by_powers = 0;
victim->affected_by_weaknesses = 0;
victim->shields = 0;
victim->poison_level = 0;
if(!IS_NPC(victim) )
{
victim->pcdata->mod_str = 0;
victim->pcdata->mod_int = 0;
victim->pcdata->mod_dex = 0;
victim->pcdata->mod_wis = 0;
victim->pcdata->mod_con = 0;
}
if ( IS_NPC( victim ) )
{
victim->pIndexData->killed++;
kill_table[URANGE( 0, victim->level, MAX_LEVEL-1 )].killed++;
extract_char( victim, TRUE );
return;
}
location = ch->in_room;
extract_char( victim, FALSE );
if( IS_SET( victim->act, PLR_GHOST ) )
{
char_from_room ( victim );
char_to_room( victim, location );
}
victim->armor = 100;
if(IS_SET(victim->act, PLR_GHOST ) )
{
victim->position = POS_GHOST;
victim->speaking = SPIRITSPEAK;
}
else
{
victim->position = POS_RESTING;
}
/*
victim->hit = UMAX( 1, victim->hit );
victim->mana = UMAX( 1, victim->mana );
victim->bp = UMAX( 1, victim->bp );
victim->move = UMAX( 1, victim->move );
*/
victim->hit = 1;
victim->mana = 1;
victim->bp = 1;
victim->move = 1;
victim->hitroll = 0;
victim->damroll = 0;
victim->saving_throw = 0;
victim->carry_weight = 0;
victim->carry_number = 0;
victim->mounted = 0;
victim->mountshort = "";
victim->mountcharmed = 0;
victim->damage_mods[0] = 0;
victim->damage_mods[1] = 0;
victim->damage_mods[2] = 0;
victim->damage_mods[3] = 0;
victim->damage_mods[4] = 0;
victim->damage_mods[5] = 0;
victim->damage_mods[6] = 0;
victim->damage_mods[7] = 0;
victim->damage_mods[8] = 0;
victim->damage_mods[9] = 0;
victim->damage_mods[10] = 0;
victim->damage_mods[11] = 0;
victim->damage_mods[12] = 0;
victim->damage_mods[13] = 0;
victim->damage_mods[14] = 0;
victim->damage_mods[15] = 0;
victim->damage_mods[16] = 0;
victim->damage_mods[17] = 0;
victim->damage_mods[18] = 0;
victim->damage_mods[19] = 0;
save_char_obj( victim, FALSE );
return;
}
void group_gain( CHAR_DATA *ch, CHAR_DATA *victim )
{
CHAR_DATA *gch;
CHAR_DATA *lch;
char buf[ MAX_STRING_LENGTH ];
int members;
int xp;
/*
* Monsters don't get kill xp's or alignment changes.
* P-killing doesn't help either.
* Dying of mortal wounds or poison doesn't give xp to anyone!
*/
if ( IS_NPC( ch ) || victim == ch )
return;
/*
* Killing in an arena won't get you anywhere either...
* Arena's are for fun not experience...
* -- The Maniac! --
*/
/* if ( !IS_NPC ( victim ) )
return; */
/*
* If you're fighting a PC, and your victim is peaceful
* then no xp for you!
*/
if ((!IS_NPC(victim)) && (!victim->pkill))
return;
members = 0;
for ( gch = ch->in_room->people; gch; gch = gch->next_in_room )
{
if ( is_same_group( gch, ch ) )
members++;
}
if ( members == 0 )
{
bug( "Group_gain: members.", members );
members = 1;
}
lch = ( ch->leader ) ? ch->leader : ch;
for ( gch = ch->in_room->people; gch; gch = gch->next_in_room )
{
OBJ_DATA *obj;
OBJ_DATA *obj_next;
if ( !is_same_group( gch, ch ) )
continue;
// Newbie slayer code.
// If victim is single class, and killer is multi. Tag with newbie slayer.
if ( !IS_NPC(victim) && victim->class == victim->multied && gch->class != gch->multied && !victim->initiated)
{
tag_newbie_slayer( gch );
}
gch->initiated = FALSE;
if (IS_SET(gch->act, PLR_QUESTOR)&&IS_NPC(victim))
{
if (gch->questmob == victim->pIndexData->vnum)
{
send_to_char(AT_WHITE, "You have almost completed your QUEST!\n\r",ch);
send_to_char(AT_WHITE, "Return to the questmaster before your time runs out!\n\r",ch);
ch->questmob = -1;
}
} else if(IS_SET(gch->act2, PLR_RELQUEST)&&IS_NPC(victim))
{
if (gch->rquestmob[gch->relquest_level] == victim->pIndexData->vnum)
{
DESCRIPTOR_DATA* d;
for (d=descriptor_list; d; d = d->next)
{
if ( d->connected != CON_PLAYING )
continue;
if (is_same_group(d->character, gch))
{
send_to_char(AT_WHITE, "This section of your religious quest is almost over!\n\r", d->character);
d->character->rquestmob[gch->relquest_level] = -1;
}
}
}
}
if ( gch->level - lch->level >= 6 )
{
send_to_char(AT_BLUE, "You are too high level for this group.\n\r", gch );
continue;
}
if ( gch->level - lch->level <= -6 )
{
send_to_char(AT_BLUE, "You are too low level for this group.\n\r", gch );
continue;
}
// No xp for non pk's in pk fights
if (!gch->pkill && !IS_NPC(victim))
{
continue;
}
if (((gch->level - victim->level) < -PKILL_RANGE)
&& (!IS_NPC(victim)))
{
send_to_char(AT_BLUE, "You must be within pkill level range for pkill xp.\n\r", gch);
continue;
}
if (((gch->level - victim->level) >= PKILL_RANGE) && (!IS_NPC(victim)))
{
send_to_char(AT_BLUE, "You must be within pkill level range for pkill xp.\n\r", gch);
continue;
}
if (members > 1)
{
// 150% xp because of group
xp = (int) ((float) (xp_compute( gch, victim ) / members) * 1.5);
// 10% bonus for leader
if ( gch == lch )
{
xp = (int) ((float) xp * 1.1);
}
// 10% bonus for killer
if ( ch == gch )
{
xp = (int) ((float) xp * 1.1);
}
// 10% bonus for mob's target
if (gch == victim->fighting)
{
xp = (int) ((float) xp * 1.1);
}
} else
{
xp = xp_compute(gch, victim);
}
if ( IS_AFFECTED4( gch, AFF_LUCK_SHIELD ) )
{
if( gch->level < LEVEL_CHAMP )
{
xp += number_range( 50, 400 );
}
/* if( gch->level == LEVEL_CHAMP || gch->level == LEVEL_DEMIGOD ) */
if( gch->level == LEVEL_CHAMP )
{
xp += number_range( 50, 200 );
}
send_to_char(AT_YELLOW, "The luck of the gods grants you experience.\n\r", gch );
}
if (!gch->pkill || ( gch->level == LEVEL_DEMIGOD ) )
{
if ( xp > 450 )
{
xp = 450;
}
if (gch->multied != gch->class )
{
xp /= 2;
}
if (gch->level == 1 || gch->level == 2 )
{
xp *= 2;
}
if (gch->level == 3 || gch->level == 4 )
{
xp *= 3 / 2;
}
}
if ( !str_infix( race_table[lch->race].race_full,
race_table[gch->race].hate) && members > 1 )
{
send_to_char(AT_WHITE, "You lost a third of your exps due to grouping with scum.\n\r", ch );
xp = (int)(xp * .66);
}
sprintf( buf, "%s -> gains %dxp", gch->name, xp);
log_string( buf, CHANNEL_NONE, -1 );
sprintf( buf, "You receive %d experience points.\n\r", xp );
send_to_char(AT_WHITE, buf, gch );
gain_exp( gch, xp );
for ( obj = ch->carrying; obj; obj = obj_next )
{
obj_next = obj->next_content;
if ( obj->deleted )
continue;
if ( obj->wear_loc == WEAR_NONE )
continue;
if ( !IS_NPC( ch ) )
if ( ( IS_OBJ_STAT( obj, ITEM_ANTI_EVIL )
&& IS_EVIL ( ch ) )
|| ( IS_OBJ_STAT( obj, ITEM_ANTI_GOOD )
&& IS_GOOD ( ch ) )
|| ( IS_OBJ_STAT( obj, ITEM_ANTI_NEUTRAL )
&& IS_NEUTRAL( ch ) ) )
{
act(AT_BLUE, "You are zapped by $p.", ch, obj, NULL, TO_CHAR );
act(AT_BLUE, "$n is zapped by $p.", ch, obj, NULL, TO_ROOM );
obj_from_char( obj );
obj_to_room( obj, ch->in_room );
}
}
}
return;
}
/*
* Compute xp for a kill.
* Also adjust alignment of killer.
* Edit this function to change xp computations.
*/
int xp_compute( CHAR_DATA *gch, CHAR_DATA *victim )
{
OBJ_DATA *obj;
float bonus;
int xp;
int align;
int extra;
int level;
int number;
bonus = 1.0;
xp = 150 - URANGE( -30, gch->level - victim->level, 5 ) * 30;
align = gch->alignment - victim->alignment;
if ( align > 500 )
{
gch->alignment = UMIN( gch->alignment + ( align - 500 ) / 4, 1000 );
xp = 5 * xp / 4;
}
else if ( align < -500 )
{
gch->alignment = UMAX( gch->alignment + ( align + 500 ) / 4, -1000 );
xp = 5 * xp / 4;
}
else
{
gch->alignment -= victim->alignment / 3;
xp = 3 * xp / 4;
}
if ( IS_AFFECTED( victim, AFF_SANCTUARY )
|| IS_SET( race_table[ victim->race ].race_abilities, RACE_SANCT ) )
{
bonus += 1.0/2;
}
if ( ( obj = get_eq_char( victim, WEAR_WIELD ) ) )
{
bonus += 1.0/4;
}
if ( ( obj = get_eq_char( victim, WEAR_WIELD_2 ) ) )
{
bonus +=(float) (1.0/5);
}
if ( !str_infix( race_table[victim->race].race_full,
race_table[gch->race].hate ) )
{
bonus += (float)(1.0/10);
}
if ( victim->race == gch->race )
{
bonus -= (float)(1.0/8);
}
if ( IS_NPC( victim ) )
{
if ( IS_SET( victim->act, ACT_AGGRESSIVE ) )
{
bonus += (float)(1.0/20);
}
if ( victim->pIndexData->pShop != 0 )
bonus -= (float)(1.0/4);
if ( victim->spec_fun != 0 )
{
if ( victim->spec_fun == spec_lookup( "spec_breath_any" )
|| victim->spec_fun == spec_lookup( "spec_cast_psionicist" )
|| victim->spec_fun == spec_lookup( "spec_cast_undead" )
|| victim->spec_fun == spec_lookup( "spec_breath_gas" )
|| victim->spec_fun == spec_lookup( "spec_cast_mage" ) )
bonus += (float)(1.0/3);
if ( victim->spec_fun == spec_lookup( "spec_breath_fire" )
|| victim->spec_fun == spec_lookup( "spec_breath_cold" )
|| victim->spec_fun == spec_lookup( "spec_breath_acid" )
|| victim->spec_fun == spec_lookup( "spec_breath_lightning" )
|| victim->spec_fun == spec_lookup( "spec_cast_cleric" )
|| victim->spec_fun == spec_lookup( "spec_cast_judge" )
|| victim->spec_fun == spec_lookup( "spec_cast_ghost" ) )
bonus += (float)(1.0/5);
if ( victim->spec_fun == spec_lookup( "spec_poison" )
|| victim->spec_fun == spec_lookup( "spec_thief" ) )
bonus += (float)(1.0/20);
if ( victim->spec_fun == spec_lookup( "spec_cast_adept" ) )
bonus -= (float)(1.0/2);
}
}
else
{
bonus *= 2;
}
xp = (int) (xp * bonus);
/*
* Adjust for popularity of target:
* -1/8 for each target over 'par' (down to - 50%)
* +1/8 for each target under 'par' ( up to + 25%)
*/
level = URANGE( 0, victim->level, 99 );
number = UMAX( 1, kill_table[level].number );
if(IS_NPC(victim))
extra = victim->pIndexData->killed - kill_table[level].killed / number;
else
extra = 0;
xp -= xp * URANGE( -2, extra, 4 ) / 8;
xp = number_range( xp * 3 / 4, xp * 5 / 4 );
xp = UMAX( 0, xp );
if(IS_NPC(victim) && IS_SET(victim->act, ACT_NO_EXP ) )
{
xp = 0;
}
if( ( victim->level < LEVEL_HERO ) && gch->level >= LEVEL_CHAMP )
{
xp = 0;
}
return xp;
}
void dam_message( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt )
{
static char * const attack_table [ ] =
{
"hit",
"slice", "stab", "slash", "whip", "claw",
"blast", "pound", "crush", "grep", "bite",
"pierce", "suction", "chop", "blast", "shot"
};
static char * const damclass_attack_table [ ] =
{
"%s hit",
"%s slice", "%s stab", "%s slash", "%s whip", "%s claw",
"%s blast", "%s pound", "%s crush", "%s grep", "%s bite",
"%s pierce", "%s suction", "%s chop", "%s blast", "%s shot"
};
const char *vs;
const char *vp;
const char *attack;
char buf [ MAX_STRING_LENGTH ];
char buf1 [ 256 ];
char buf2 [ 256 ];
char buf3 [ 256 ];
char buf4 [ 256 ];
char buf5 [ 256 ];
char damclassbuf [ MAX_STRING_LENGTH ];
char punct;
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 <= 40 ) { vs = "MUTILATE"; vp = "MUTILATES"; }
else if ( dam <= 44 ) { vs = "DISEMBOWEL"; vp = "DISEMBOWELS"; }
else if ( dam <= 48 ) { vs = "EVISCERATE"; vp = "EVISCERATES"; }
else if ( dam <= 52 ) { vs = "MASSACRE"; vp = "MASSACRES"; }
else if ( dam <= 100 ) { vs = "*** DEMOLISH ***";
vp = "*** DEMOLISHES ***"; }
else if ( dam <= 150 ) { vs = "*** DEVASTATE ***";
vp = "*** DEVASTATES ***"; }
else if ( dam <= 250 ) { vs = "*** OBLITERATE ***";
vp = "*** OBLITERATES ***"; }
else if ( dam <= 300 ) { vs = "=== OBLITERATE ===";
vp = "=== OBLITERATES ==="; }
else if ( dam <= 500 ) { vs = "*** ANNIHILATE ***";
vp = "*** ANNIHILATES ***"; }
else if ( dam <= 750 ) { vs = ">>> ANNIHILATE <<<";
vp = ">>> ANNIHILATES <<<"; }
else if ( dam <= 1000) { vs = "<<< ERADICATE >>>";
vp = "<<< ERADICATES >>>"; }
else if ( dam <= 2000) { vs = "do UNSPEAKABLE things to";
vp = "does UNSPEAKABLE things to"; }
else if ( dam <= 6000) { vs = "open a can of WOOP ASS on";
vp = "opens a can of WOOP ASS on"; }
else { vs = "deal GODLIKE DAMAGE to";
vp = "deals GODLIKE DAMAGE to"; }
punct = ( dam <= 24 ) ? '.' : '!';
if ( dt == TYPE_HIT )
{
if ( ch->race > MAX_RACE )
{
bug( "Dam_message: %d invalid race", ch->race );
ch->race = 0;
}
attack = race_table[ ch->race ].dmg_message;
sprintf( buf1, "Your %s %s $N%c (&R%d&W pts)", attack, vp, punct, dam );
sprintf( buf2, "$n's %s %s you%c (&R%d&W pts)", attack, vp, punct, dam );
sprintf( buf3, "$n's %s %s $N%c (&R%d&W pts)", attack, vp, punct, dam );
sprintf( buf4, "You %s %s yourself%c (&R%d&W pts)", attack, vp, punct, dam );
sprintf( buf5, "$n's %s %s $m%c (&R%d&W pts)", attack, vp, punct, dam );
}
else
{
if ( is_sn(dt) )
attack = skill_table[dt].noun_damage;
else if ( dt >= TYPE_HIT
&& dt < TYPE_HIT
+ sizeof( attack_table )/sizeof( attack_table[0] ) )
{
if (!dam_class_value)
attack = attack_table[dt - TYPE_HIT];
else
{
sprintf(damclassbuf, damclass_attack_table[dt - TYPE_HIT], flag_string( damage_flags, dam_class_value ) );
attack = damclassbuf;
}
}
else
{
sprintf( buf, "Dam_message: bad dt %d caused by %s.", dt,
ch->name );
bug( buf, 0 );
dt = TYPE_HIT;
attack = attack_table[0];
}
if ( dt > TYPE_HIT && is_wielding_poisoned( ch ) )
{
sprintf( buf1, "Your poisoned %s %s $N%c (&R%d&W pts)", attack, vp, punct, dam );
sprintf( buf2, "$n's poisoned %s %s you%c (&R%d&W pts)", attack, vp, punct, dam );
sprintf( buf3, "$n's poisoned %s %s $N%c (&R%d&W pts)", attack, vp, punct, dam );
sprintf( buf4, "Your poisoned %s %s you%c (&R%d&W pts)", attack, vp, punct, dam );
sprintf( buf5, "$n's poisoned %s %s $n%c (&R%d&W pts)", attack, vp, punct, dam );
}
else
{
sprintf( buf1, "Your %s %s $N%c (&R%d&W pts)", attack, vp, punct, dam );
sprintf( buf2, "$n's %s %s you%c (&R%d&W pts)", attack, vp, punct, dam );
sprintf( buf3, "$n's %s %s $N%c (&R%d&W pts)", attack, vp, punct, dam );
sprintf( buf4, "Your %s %s you%c (&R%d&W pts)", attack, vp, punct, dam );
sprintf( buf5, "$n's %s %s $n%c (&R%d&W pts)", attack, vp, punct, dam );
}
}
if ( victim != ch )
{
if ( dam != 0 || IS_SET( ch->act, PLR_COMBAT ) )
act(AT_WHITE, buf1, ch, NULL, victim, TO_CHAR );
if ( dam != 0 || IS_SET( victim->act, PLR_COMBAT ) )
act(AT_WHITE, buf2, ch, NULL, victim, TO_VICT );
act(AT_GREY, buf3, ch, NULL, victim,
dam == 0 ? TO_COMBAT : TO_NOTVICT );
}
else
{
if ( dam != 0 || IS_SET( ch->act, PLR_COMBAT ) )
act(AT_WHITE, buf4, ch, NULL, victim, TO_CHAR );
act(AT_GREY, buf5, ch, NULL, victim,
dam == 0 ? TO_COMBAT : TO_NOTVICT );
}
return;
}
/*
* Disarm a creature.
* Caller must check for successful attack.
*/
void disarm( CHAR_DATA *ch, CHAR_DATA *victim )
{
OBJ_DATA *obj;
if ( ( race_table[ ch->race ].size - race_table[ victim->race ].size )
< -2 )
return;
if ( !( obj = get_eq_char( victim, WEAR_WIELD ) ) )
if ( !( obj = get_eq_char( victim, WEAR_WIELD_2 ) ) )
return;
if ( !get_eq_char( ch, WEAR_WIELD ) && number_bits( 1 ) == 0 )
if ( !get_eq_char( ch, WEAR_WIELD_2 ) && number_bits( 1 ) == 0 )
return;
act(AT_YELLOW, "You disarm $N!", ch, NULL, victim, TO_CHAR );
act(AT_YELLOW, "$n DISARMS you!", ch, NULL, victim, TO_VICT );
act(AT_GREY, "$n DISARMS $N!", ch, NULL, victim, TO_NOTVICT );
obj_from_char( obj );
if ( IS_NPC( victim ) )
obj_to_char( obj, victim );
else
obj_to_char( obj, victim );
return;
}
void do_kill( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
one_argument( argument, arg );
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char( AT_WHITE, "That person is not here.\n\r", ch );
return;
}
if ( is_safe( ch, victim ) )
{
send_to_char( AT_WHITE, "You cannot.\n\r", ch );
return;
}
if ( arg[0] == '\0' )
{
send_to_char(AT_WHITE, "Kill whom?\n\r", ch );
return;
}
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(AT_WHITE, "They aren't here.\n\r", ch );
return;
}
if ( IS_AFFECTED(victim, AFF_PEACE ))
{
send_to_char(AT_WHITE, "A wave of peace overcomes you.\n\r", ch);
return;
}
if ( IS_AFFECTED2( ch, AFF_SHADOW_PLANE ))
{
send_to_char(AT_WHITE, "You must leave the shadow realm.\n\r", ch);
return;
}
if ( IS_AFFECTED4( ch, AFF_BURROW ))
{
send_to_char(AT_WHITE, "You must wait until the earth heals you!\n\r", ch);
return;
}
if ( IS_AFFECTED2( victim, AFF_SHADOW_PLANE ))
{
send_to_char(AT_WHITE, "You can not attack someone who is in the shadow plane.\n\r", ch);
return;
}
if ( IS_AFFECTED4( victim, AFF_BURROW ))
{
send_to_char(AT_WHITE, "You can not attack someone who is burrowed.\n\r", ch);
return;
}
if ( IS_AFFECTED( ch, AFF_PEACE ) )
{
affect_strip( ch, skill_lookup("aura of peace" ));
REMOVE_BIT( ch->affected_by, AFF_PEACE );
}
if ( !IS_NPC( victim ) )
{
if ( !IS_SET( victim->act, PLR_KILLER )
&& !IS_SET( victim->act, PLR_THIEF ) )
{
send_to_char(AT_WHITE, "You must MURDER a player.\n\r", ch );
return;
}
}
else
{
if ( IS_AFFECTED( victim, AFF_CHARM ) && victim->master )
{
send_to_char(AT_WHITE, "You must MURDER a charmed creature.\n\r", ch );
return;
}
}
if ( victim == ch )
{
send_to_char(AT_RED, "You hit yourself. Stupid!\n\r", ch );
multi_hit( ch, ch, TYPE_UNDEFINED );
return;
}
if ( IS_AFFECTED( ch, AFF_CHARM ) && ch->master == victim )
{
act(AT_BLUE, "$N is your beloved master!", ch, NULL, victim, TO_CHAR );
return;
}
if ( ch->position == POS_FIGHTING )
{
send_to_char(C_DEFAULT, "You do the best you can!\n\r", ch );
return;
}
WAIT_STATE( ch, PULSE_VIOLENCE );
check_killer( ch, victim );
multi_hit( ch, victim, TYPE_UNDEFINED );
return;
}
void do_murde( CHAR_DATA *ch, char *argument )
{
send_to_char(C_DEFAULT, "If you want to MURDER, spell it out.\n\r", ch );
return;
}
void do_murder( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
char buf [ MAX_STRING_LENGTH ];
char arg [ MAX_INPUT_LENGTH ];
one_argument( argument, arg );
if ( arg[0] == '\0' )
{
send_to_char(C_DEFAULT, "Murder whom?\n\r", ch );
return;
}
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return;
}
if ( victim == ch ){
send_to_char(C_DEFAULT, "Suicide is a mortal sin.\n\r", ch );
return;
}
if ( !is_pkillable( ch, victim ) ) {
return;
}
if ( IS_AFFECTED(victim, AFF_PEACE ))
{
send_to_char(AT_WHITE, "A wave of peace overcomes you.\n\r", ch);
return;
}
if ( IS_AFFECTED2( ch, AFF_SHADOW_PLANE ))
{
send_to_char(AT_WHITE, "You must leave the shadow realm.\n\r", ch);
return;
}
if ( IS_AFFECTED4( ch, AFF_BURROW ))
{
send_to_char(AT_WHITE, "You must wait until the earth heals you!\n\r", ch);
return;
}
if ( IS_AFFECTED2( victim, AFF_SHADOW_PLANE ))
{
send_to_char(AT_WHITE, "You can not attack someone who is in the shadow plane.\n\r", ch);
return;
}
if ( IS_AFFECTED4( victim, AFF_BURROW ))
{
send_to_char(AT_WHITE, "You can not attack someone who is burrowed.\n\r", ch);
return;
}
if ( IS_AFFECTED( ch, AFF_PEACE ))
{
affect_strip( ch, skill_lookup("aura of peace") );
REMOVE_BIT( ch->affected_by, AFF_PEACE );
}
if (!IS_NPC(victim))
ch->pkill_timer = 0;
if ( IS_AFFECTED( ch, AFF_CHARM ) && ch->master == victim )
{
act(C_DEFAULT, "$N is your beloved master!", ch, NULL, victim, TO_CHAR );
return;
}
if ( ch->position == POS_FIGHTING )
{
send_to_char(C_DEFAULT, "You do the best you can!\n\r", ch );
return;
}
WAIT_STATE( ch, PULSE_VIOLENCE );
sprintf( buf, "Help! I am being attacked by %s!", ch->name );
if( IS_NPC( ch ) )
{
sprintf( buf, "Help! I am being attacked by %s!", ch->short_descr );
}
do_shout( victim, buf );
multi_hit( ch, victim, TYPE_UNDEFINED );
return;
}
int skill_backstab( int sn, int level, CHAR_DATA *ch, void *vo )
{
OBJ_DATA *obj;
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
one_argument( target_name, arg );
if ( arg[0] == '\0' )
{
send_to_char(C_DEFAULT, "Backstab whom?\n\r", ch );
return SKPELL_MISSED;
}
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return SKPELL_BOTCHED;
}
if ( victim == ch )
{
send_to_char(C_DEFAULT, "How can you sneak up on yourself?\n\r", ch );
return SKPELL_BOTCHED;
}
if ( !( obj = get_eq_char( ch, WEAR_WIELD ) )
|| obj->value[3] != 11 )
{
send_to_char(C_DEFAULT, "You need to wield a piercing weapon.\n\r", ch );
return SKPELL_BOTCHED;
}
if ( victim->fighting )
{
send_to_char(C_DEFAULT, "You can't backstab a fighting person.\n\r", ch );
return SKPELL_BOTCHED;
}
if ( victim->hit < (victim->max_hit-200) )
{
act(C_DEFAULT, "$N is hurt and suspicious ... you can't sneak up.",
ch, NULL, victim, TO_CHAR );
return SKPELL_BOTCHED;
}
if ( !is_pkillable( ch, victim ) ) {
return SKPELL_MISSED;
}
if ( IS_AFFECTED2( ch, AFF_SHADOW_PLANE ))
{
send_to_char(AT_WHITE, "You must leave the shadow realm.\n\r", ch);
return SKPELL_MISSED;
}
if ( IS_AFFECTED4( ch, AFF_BURROW ))
{
send_to_char(AT_WHITE, "You must wait until the earth heals you!\n\r", ch);
return SKPELL_MISSED;
}
if ( IS_AFFECTED2( victim, AFF_SHADOW_PLANE ))
{
send_to_char(AT_WHITE, "You can not attack someone who is in the shadow plane.\n\r", ch);
return SKPELL_MISSED;
}
if ( IS_AFFECTED4( victim, AFF_BURROW ))
{
send_to_char(AT_WHITE, "You can not attack someone who is burrowed.\n\r", ch);
return SKPELL_MISSED;
}
if ( IS_AFFECTED( victim, AFF_PEACE ) )
{
send_to_char(AT_WHITE, "A wave of peace overcomes you.\n\r", ch);
return SKPELL_MISSED;
}
if (!IS_NPC(victim))
ch->pkill_timer = 0;
check_killer( ch, victim );
WAIT_STATE( ch, skill_table[sn].beats );
if ( !IS_AWAKE( victim )
|| IS_NPC( ch )
|| number_percent( ) < ( ch->pcdata->learned[sn] / 10 ) )
{
multi_hit( ch, victim, sn );
}
else
damage( ch, victim, 0, sn );
return SKPELL_NO_DAMAGE;
}
int skill_assassinate( int sn, int level, CHAR_DATA *ch, void *vo )
{
OBJ_DATA *obj;
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
int chance;
chance = IS_NPC( ch ) ? 0 : ( ch->pcdata->learned[skill_lookup("mind of fanoom")] / 10 ) ;
if( chance > 0 && !IS_IMMORTAL( ch ) && !IS_NPC( ch ) )
{
chance = chance - ( 10 * ( LEVEL_DEMIGOD - ch->level ) );
}
one_argument( target_name, arg );
if ( arg[0] == '\0' )
{
send_to_char(C_DEFAULT, "Assassinate whom?\n\r", ch );
return SKPELL_MISSED;
}
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return SKPELL_MISSED;
}
if ( victim == ch )
{
send_to_char(C_DEFAULT, "How can you sneak up on yourself?\n\r", ch );
return SKPELL_MISSED;
}
if ( victim->fighting )
{
send_to_char(C_DEFAULT, "You can't assassinate a fighting person.\n\r", ch );
return SKPELL_MISSED;
}
if( chance <= 0 )
{
if ( victim->hit < (victim->max_hit - 200) )
{
act(C_DEFAULT, "$N is hurt and suspicious ... you can't sneak up.",
ch, NULL, victim, TO_CHAR );
return SKPELL_MISSED;
}
}
else
{
if ( ( victim->hit < victim->max_hit/2 || chance < number_percent( ) ) && ( victim->hit < victim->max_hit - 200 ) )
{
act(C_DEFAULT, "$N is hurt and suspicious ... you can't sneak up.",
ch, NULL, victim, TO_CHAR );
return SKPELL_MISSED;
}
}
if ( !( obj = get_eq_char( ch, WEAR_WIELD ) )
|| obj->value[3] != 11 )
{
send_to_char(C_DEFAULT, "You need to wield a piercing weapon.\n\r", ch );
return SKPELL_MISSED;
}
if ( !is_pkillable( ch, victim ) ) {
return SKPELL_MISSED;
}
if ( IS_AFFECTED2( ch, AFF_SHADOW_PLANE ))
{
send_to_char(AT_WHITE, "You must leave the shadow realm.\n\r", ch);
return SKPELL_MISSED;
}
if ( IS_AFFECTED4( ch, AFF_BURROW ))
{
send_to_char(AT_WHITE, "You must wait until the earth heals you!\n\r", ch);
return SKPELL_MISSED;
}
if ( IS_AFFECTED2( victim, AFF_SHADOW_PLANE ))
{
send_to_char(AT_WHITE, "You can not attack someone who is in the shadow plane.\n\r", ch);
return SKPELL_MISSED;
}
if ( IS_AFFECTED4( victim, AFF_BURROW ))
{
send_to_char(AT_WHITE, "You can not attack someone who is burrowed.\n\r", ch);
return SKPELL_MISSED;
}
if ( IS_AFFECTED( victim, AFF_PEACE ) )
{
send_to_char(AT_WHITE, "A wave of peace overcomes you.\n\r", ch);
return SKPELL_MISSED;
}
if ( !IS_NPC ( ch ) )
{
if ( number_percent( ) > ( ch->pcdata->learned[sn] / 10 ) )
{
send_to_char(C_DEFAULT, "You failed.\n\r", ch );
return SKPELL_MISSED;
}
}
if (!IS_NPC(victim))
ch->pkill_timer = 0;
WAIT_STATE( ch, skill_table[sn].beats );
update_skpell( ch, skill_lookup("mind of fanoom"), 0 );
multi_hit( ch, victim, sn );
return SKPELL_NO_DAMAGE;
}
void do_flee( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
ROOM_INDEX_DATA *was_in;
ROOM_INDEX_DATA *now_in;
int attempt;
if ( IS_AFFECTED( ch, AFF_ANTI_FLEE ) )
{
send_to_char( AT_RED, "You cannot!\n\r", ch );
return;
}
if ( !IS_NPC(ch) && (IS_AFFECTED3(ch, AFF_BLOODTHIRSTY) || IS_AFFECTED2(ch, AFF_BERSERK)) )
{
send_to_char( AT_RED, "You cannot!\n\r", ch );
return;
}
if ( !( victim = ch->fighting ) )
{
if ( ch->position == POS_FIGHTING )
ch->position = POS_STANDING;
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
return;
}
if ( IS_SET( ch->in_room->room_flags, ROOM_NO_FLEE ) )
{
send_to_char(C_DEFAULT, "You failed! You lose 10 exps.\n\r", ch );
gain_exp( ch, -10 );
return;
}
was_in = ch->in_room;
for ( attempt = 0; attempt < 6; attempt++ )
{
EXIT_DATA *pexit;
int door;
door = number_door( );
if ( ( pexit = was_in->exit[door] ) == 0
|| !pexit->to_room
|| (IS_SET(pexit->to_room->room_flags, ROOM_SAFE) && ch->pkill)
|| IS_SET( pexit->exit_info, EX_CLOSED )
|| (IS_SET( pexit->exit_info, EX_HIDDEN)
&&
!IS_SET (race_table[ch->race].race_abilities,RACE_DETECT_HIDDEN_EXIT ) )
|| ( IS_NPC( ch )
&& ( IS_SET( pexit->to_room->room_flags, ROOM_NO_MOB )
|| ( IS_SET( ch->act, ACT_STAY_AREA )
&& pexit->to_room->area != ch->in_room->area ) ) ) )
continue;
move_char( ch, door );
if ( ( now_in = ch->in_room ) == was_in )
continue;
ch->in_room = was_in;
act(C_DEFAULT, "$n has fled!", ch, NULL, NULL, TO_ROOM );
ch->in_room = now_in;
if ( !IS_NPC( ch ) )
{
send_to_char(C_DEFAULT, "You flee from combat! You lose 25 exps.\n\r", ch );
gain_exp( ch, -25 );
}
if ( ch->fighting && IS_NPC( ch->fighting ) )
if ( IS_SET( ch->fighting->act, ACT_TRACK ) )
ch->fighting->hunting = ch;
stop_fighting( ch, TRUE );
return;
}
send_to_char(C_DEFAULT, "You failed! You lose 10 exps.\n\r", ch );
gain_exp( ch, -10 );
return;
}
int skill_retreat( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim;
ROOM_INDEX_DATA *was_in;
ROOM_INDEX_DATA *now_in;
int attempt;
if (IS_AFFECTED( ch, AFF_ANTI_FLEE ) )
{
send_to_char( AT_RED, "You cannot!\n\r", ch );
return SKPELL_BOTCHED;
}
if ( !( victim = ch->fighting ) )
{
if ( ch->position == POS_FIGHTING )
ch->position = POS_STANDING;
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
return SKPELL_MISSED;
}
if ( IS_SET( ch->in_room->room_flags, ROOM_NO_FLEE ) )
{
send_to_char(C_DEFAULT, "You failed your retreat!\n\r", ch );
return SKPELL_MISSED;
}
was_in = ch->in_room;
for ( attempt = 0; attempt < 6; attempt++ )
{
EXIT_DATA *pexit;
int door;
door = number_door( );
if ( ( pexit = was_in->exit[door] ) == 0
|| !pexit->to_room
|| (IS_SET(pexit->to_room->room_flags, ROOM_SAFE) && ch->pkill)
|| IS_SET( pexit->exit_info, EX_CLOSED )
|| ( IS_NPC( ch )
&& ( IS_SET( pexit->to_room->room_flags, ROOM_NO_MOB )
|| ( IS_SET( ch->act, ACT_STAY_AREA )
&& pexit->to_room->area != ch->in_room->area ) ) ) )
continue;
move_char( ch, door );
if ( ( now_in = ch->in_room ) == was_in )
continue;
ch->in_room = was_in;
act(C_DEFAULT, "$n has retreated!", ch, NULL, NULL, TO_ROOM );
ch->in_room = now_in;
if ( !IS_NPC( ch ) )
{
send_to_char(C_DEFAULT, "You retreated successfully!\n\r", ch );
}
if ( ch->fighting && IS_NPC( ch->fighting ) )
if ( IS_SET( ch->fighting->act, ACT_TRACK ) )
ch->fighting->hunting = ch;
stop_fighting( ch, TRUE );
return SKPELL_NO_DAMAGE;
}
send_to_char(C_DEFAULT, "You failed your retreat!\n\r", ch );
return SKPELL_MISSED;
}
int skill_rescue( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim;
CHAR_DATA *fch;
char arg [ MAX_INPUT_LENGTH ];
one_argument( target_name, arg );
if ( arg[0] == '\0' )
{
send_to_char(C_DEFAULT, "Rescue whom?\n\r", ch );
return SKPELL_MISSED;
}
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return SKPELL_MISSED;
}
if ( victim == ch )
{
send_to_char(C_DEFAULT, "What about fleeing instead?\n\r", ch );
return SKPELL_MISSED;
}
if ( !IS_NPC( ch ) && IS_NPC( victim ) )
{
send_to_char(C_DEFAULT, "Doesn't need your help!\n\r", ch );
return SKPELL_MISSED;
}
if ( ch->fighting == victim )
{
send_to_char(C_DEFAULT, "Too late.\n\r", ch );
return SKPELL_MISSED;
}
if ( !( fch = victim->fighting ) )
{
send_to_char(C_DEFAULT, "That person is not fighting right now.\n\r", ch );
return SKPELL_MISSED;
}
if ( !is_same_group( ch, victim ) && (ch->clan != victim->clan))
{
send_to_char(C_DEFAULT, "Why would you want to?\n\r", ch );
return SKPELL_MISSED;
}
if ( !check_blind ( ch ) )
return SKPELL_MISSED;
WAIT_STATE( ch, skill_table[sn].beats );
if ( !IS_NPC( ch ) && number_percent( ) > ( ch->pcdata->learned[sn] / 10 ) )
{
send_to_char(C_DEFAULT, "You fail the rescue.\n\r", ch );
return SKPELL_MISSED;
}
act(C_DEFAULT, "You rescue $N!", ch, NULL, victim, TO_CHAR );
act(C_DEFAULT, "$n rescues you!", ch, NULL, victim, TO_VICT );
act(C_DEFAULT, "$n rescues $N!", ch, NULL, victim, TO_NOTVICT );
stop_fighting( fch, FALSE );
set_fighting( fch, ch );
return SKPELL_NO_DAMAGE;
}
int skill_gouge( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
int dam = 0;
if ( !ch->fighting )
{
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
return SKPELL_MISSED;
}
if ( !check_blind( ch ) )
return SKPELL_MISSED;
one_argument( target_name, arg );
victim = ch->fighting;
if ( arg[0] != '\0' )
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return SKPELL_MISSED;
}
WAIT_STATE( ch, skill_table[sn].beats );
if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 ) )
{
dam = number_range(ch->level * 2, ch->level * 5);// damage( ch, victim, number_range( ch->level*2, ch->level*5 ), sn );
if IS_AFFECTED(victim, AFF_BLIND)
return dam;
if IS_AFFECTED2(victim, AFF_BLINDFOLD)
return dam;
else
if ( number_percent( ) < 50 )
{
AFFECT_DATA af;
af.type = skill_lookup("blindness");
af.level = ch->level;
af.duration = 5;
af.location = APPLY_HITROLL;
af.modifier = -50;
af.bitvector = AFF_BLIND;
affect_join( victim, &af );
act(AT_WHITE, "$N is blinded!", ch, NULL, victim, TO_CHAR );
send_to_char(AT_WHITE, "You are blinded!\n\r", victim );
act(AT_WHITE, "$N is blinded!", ch, NULL, victim, TO_NOTVICT );
return dam;
}
update_pos( victim );
}
else
dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_gouge );
return dam;
}
int skill_rake( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
int dam = 0;
if ( !ch->fighting )
{
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
return SKPELL_MISSED;
}
if ( !check_blind( ch ) )
return SKPELL_MISSED;
one_argument( target_name, arg );
victim = ch->fighting;
if ( arg[0] != '\0' )
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return SKPELL_MISSED;
}
WAIT_STATE( ch, skill_table[sn].beats );
if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 ) )
{
dam = number_range(ch->level * 2,ch->level * 5); //damage( ch, victim, number_range( ch->level*2, ch->level*5 ), sn );
if IS_AFFECTED2(victim, AFF_BLINDFOLD)
return dam;
if IS_AFFECTED(victim, AFF_BLIND)
return dam;
else
if ( number_percent( ) < 50 )
{
AFFECT_DATA af;
af.type = skill_lookup("blindness");
af.level = ch->level;
af.duration = 5;
af.location = APPLY_HITROLL;
af.modifier = -50;
af.bitvector = AFF_BLIND;
affect_join( victim, &af );
act(AT_WHITE, "$N is blinded!", ch, NULL, victim, TO_CHAR );
send_to_char(AT_WHITE, "You are blinded!\n\r", victim );
act(AT_WHITE, "$N is blinded!", ch, NULL, victim, TO_NOTVICT );
return dam;
}
update_pos( victim );
}
else
dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_rake );
return dam;
}
int skill_back_kick( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
int dam = 0;
if ( !ch->fighting )
{
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
return SKPELL_MISSED;
}
one_argument( target_name, arg);
victim = ch->fighting;
if ( arg[0] != '\0' )
if ( !(victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return SKPELL_MISSED;
}
WAIT_STATE( ch, skill_table[sn].beats );
if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 ) )
{
dam = number_range( ch->level*5, ch->level*13 );
//damage( ch, victim, number_range( ch->level*5, ch->level*13 ), sn );
}
else
dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, sn );
return dam;
}
int skill_circle( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
int dam = 0;
if ( !ch->fighting )
{
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
return SKPELL_MISSED;
}
if ( !check_blind( ch ) )
return SKPELL_MISSED;
one_argument( target_name, arg );
victim = ch->fighting;
if ( arg[0] != '\0' )
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return SKPELL_MISSED;
}
WAIT_STATE( ch, skill_table[sn].beats/2 );
if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 ) )
{
dam = number_range(ch->level*5, ch->level*14); //damage( ch, victim, number_range( ch->level*5, ch->level*14 ), gsn_circle );
update_pos( victim );
}
else
dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_circle );
return dam;
}
int skill_dim_mak( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
int dam;
if ( IS_NPC( ch ) )
if ( IS_SET( ch->affected_by, AFF_CHARM ) )
return SKPELL_MISSED;
if ( !ch->fighting )
{
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
return SKPELL_MISSED;
}
if ( !check_blind( ch ) )
return SKPELL_MISSED;
one_argument( target_name, arg );
victim = ch->fighting;
if ( arg[0] != '\0' )
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return SKPELL_MISSED;
}
WAIT_STATE( ch, skill_table[sn].beats );
if ( IS_NPC( ch ) || number_percent( ) < (ch->pcdata->learned[sn]/20) )
{
dam = number_range( (int)(victim->hit * .5), (int)(victim->hit * .6) ); //damage( ch, victim, number_range( (int)(victim->hit * .5), (int)(victim->hit * .6) ), gsn_dim_mak );
update_pos( victim );
}
else
dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_dim_mak );
return dam;
}
int skill_kick( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
int dam;
if ( !ch->fighting )
{
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
return SKPELL_MISSED;
}
if ( !check_blind( ch ) )
return SKPELL_MISSED;
one_argument( target_name, arg );
victim = ch->fighting;
if ( arg[0] != '\0' )
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return SKPELL_MISSED;
}
WAIT_STATE( ch, skill_table[sn].beats );
if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 ) )
{
dam = number_range(ch->level*3, ch->level*9); //damage( ch, victim, number_range( ch->level*3, ch->level*9 ), gsn_kick );
}
else
dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_kick );
return dam;
}
int skill_slam( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
int dam;
if ( !ch->fighting )
{
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
return SKPELL_MISSED;
}
if ( !check_blind( ch ) )
return SKPELL_MISSED;
one_argument( target_name, arg );
victim = ch->fighting;
if ( arg[0] != '\0' )
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return SKPELL_MISSED;
}
WAIT_STATE( ch, skill_table[sn].beats );
if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 ) )
{
dam = number_range(ch->level * 8, ch->level * 19); //damage( ch, victim, number_range( ch->level*8, ch->level*19 ), gsn_slam );
}
else
dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_slam );
return dam;
}
int skill_claw( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
int dam;
if ( !ch->fighting )
{
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
return SKPELL_MISSED;
}
if ( !check_blind( ch ) )
return SKPELL_MISSED;
one_argument( target_name, arg );
victim = ch->fighting;
if ( arg[0] != '\0' )
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return SKPELL_MISSED;
}
WAIT_STATE( ch, skill_table[sn].beats );
if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 ) )
{
dam = number_range(ch->level * 5, ch->level * 7); //damage( ch, victim, number_range( ch->level*5, ch->level*7 ), gsn_claw );
}
else
dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_claw );
return dam;
}
int skill_bite( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
int dam = 0;
if ( !ch->fighting )
{
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
return SKPELL_MISSED;
}
if ( !check_blind( ch ) )
return SKPELL_MISSED;
one_argument( target_name, arg );
victim = ch->fighting;
if ( arg[0] != '\0' )
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return SKPELL_MISSED;
}
WAIT_STATE( ch, skill_table[sn].beats );
if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 ) )
{
dam = number_range(ch->level * 7, ch->level * 10); //damage( ch, victim, number_range( ch->level*7, ch->level*10 ), sn );
}
else
dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, sn );
return dam;
}
int skill_shriek( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
int dam = 0;
if IS_AFFECTED2( ch, AFF_SLIT )
{
send_to_char(AT_BLOOD, "You gargle through your slit throat.\n\r", ch);
return SKPELL_MISSED;
}
if ( !ch->fighting )
{
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
return SKPELL_MISSED;
}
one_argument( target_name, arg );
victim = ch->fighting;
if ( arg[0] != '\0' )
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return SKPELL_MISSED;
}
WAIT_STATE( ch, skill_table[sn].beats );
if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 ) )
{
dam = number_range(ch->level * 5, ch->level * 10); //damage( ch, victim, number_range( ch->level*5, ch->level*10),gsn_shriek );
send_to_char(AT_BLOOD, "Your deadly wail shatters the air!\n\r",ch);
send_to_char(AT_BLOOD, "Your hearing is damaged!\n\r", victim );
act(AT_BLOOD, "$n shatters the air with a deadly wail!", ch, NULL, NULL, TO_ROOM );
return dam;
}
else
dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_shriek );
return dam;
}
int skill_dirt_kick( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
int dam;
if ( !ch->fighting )
{
send_to_char(C_DEFAULT, "You kick some dirt into the air.\n\r", ch );
return SKPELL_MISSED;
}
one_argument( target_name, arg );
victim = ch->fighting;
if ( arg[0] != '\0' )
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return SKPELL_MISSED;
}
WAIT_STATE( ch, skill_table[sn].beats );
if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 ) )
{
dam = number_range(ch->level * 2, ch->level * 5); //damage( ch, victim, number_range( ch->level*2, ch->level*5 ), gsn_dirt_kick );
if IS_AFFECTED(victim, AFF_BLIND)
return dam;
if IS_AFFECTED2(victim, AFF_BLINDFOLD)
return dam;
else
if ( number_percent( ) < 40 )
{
AFFECT_DATA af;
af.type = skill_lookup("blindness");
af.level = ch->level;
af.duration = 1;
af.location = APPLY_HITROLL;
af.modifier = -50;
af.bitvector = AFF_BLIND;
affect_join( victim, &af );
act(AT_WHITE, "$N is blinded!", ch, NULL, victim, TO_CHAR );
send_to_char(AT_WHITE, "The dirt blinds you!!\n\r", victim );
act(AT_WHITE, "$N is blinded!", ch, NULL, victim, TO_NOTVICT );
return dam;
}
update_pos( victim );
}
else
dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, sn );
return dam;
}
int skill_chop( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
int dam = 0;
if ( !ch->fighting )
{
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
return SKPELL_MISSED;
}
if ( !check_blind( ch ) )
return SKPELL_MISSED;
one_argument( target_name, arg );
victim = ch->fighting;
if ( arg[0] != '\0' )
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return SKPELL_MISSED;
}
WAIT_STATE( ch, skill_table[sn].beats );
if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 ) )
{
dam = number_range(ch->level * 3, (int)(ch->level * 6.15)); //damage( ch, victim, number_range( ch->level*3, (int)(ch->level*6.15) ), gsn_chop );
}
else
dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_chop );
return dam;
}
int skill_head_butt( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
int dam = 0;
if ( !ch->fighting )
{
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
return SKPELL_MISSED;
}
if ( !check_blind( ch ) )
return SKPELL_MISSED;
one_argument( target_name, arg );
victim = ch->fighting;
if ( arg[0] != '\0' )
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return SKPELL_MISSED;
}
WAIT_STATE( ch, skill_table[sn].beats );
if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 ) )
{
dam = number_range(ch->level * 3, ch->level * 8); //damage( ch, victim, number_range( ch->level*3, ch->level*8 ), gsn_head_butt );
}
else
dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_head_butt );
return dam;
}
int damclass_adjust(CHAR_DATA *victim, int dam, int sn)
{
int mod = 0;
if (sn < TYPE_HIT)
switch (skill_table[sn].damclass)
{
case DAMCLASS_NULL:
break;
case DAMCLASS_ACID :
mod = victim->damage_mods[0];
break;
case DAMCLASS_HOLY :
mod = victim->damage_mods[1];
break;
case DAMCLASS_MAGIC :
mod = victim->damage_mods[2];
break;
case DAMCLASS_FIRE :
mod = victim->damage_mods[3];
break;
case DAMCLASS_ENERGY :
mod = victim->damage_mods[4];
break;
case DAMCLASS_WIND :
mod = victim->damage_mods[5];
break;
case DAMCLASS_WATER :
mod = victim->damage_mods[6];
break;
case DAMCLASS_ILLUSION :
mod = victim->damage_mods[7];
break;
case DAMCLASS_DISPEL :
mod = victim->damage_mods[8];
break;
case DAMCLASS_EARTH :
mod = victim->damage_mods[9];
break;
case DAMCLASS_PSYCHIC :
mod = victim->damage_mods[10];
break;
case DAMCLASS_POISON :
mod = victim->damage_mods[11];
break;
case DAMCLASS_BREATH :
mod = victim->damage_mods[12];
break;
case DAMCLASS_SUMMON :
mod = victim->damage_mods[13];
break;
case DAMCLASS_PHYSICAL :
mod = victim->damage_mods[14];
break;
case DAMCLASS_EXPLOSIVE :
mod = victim->damage_mods[15];
break;
case DAMCLASS_SONG :
mod = victim->damage_mods[16];
break;
case DAMCLASS_NAGAROM :
mod = victim->damage_mods[17];
break;
case DAMCLASS_UNHOLY :
mod = victim->damage_mods[18];
break;
case DAMCLASS_CLAN :
mod = victim->damage_mods[19];
break;
default:
break;
}
if (sn >=TYPE_HIT || sn == TYPE_UNDEFINED)
{
if (!dam_class_value)
mod = victim->damage_mods[14];
else
mod = victim->damage_mods[dam_class_value];
}
mod = URANGE( -75, mod, 75);
damclass_shield_weaken(victim, dam, sn);
dam = dam - (dam * mod) / 100;
return dam;
}
bool can_use_skspell(CHAR_DATA *ch, int skspellNum)
{
/*char buf[1000];
sprintf(buf, "gsn: %d, skillName: %s, level: %d, multi: %d",
skspellNum, skill_table[skspellNum].name,
skill_table[skspellNum].skill_level[ch->class],
skill_table[skspellNum].skill_level[ch->multied]);
if( !IS_NPC(ch) ) {
bug(buf, 0);
}*/
if ( !IS_NPC( ch )&&(( ch->level < skill_table[skspellNum].skill_level[ch->class] )
&& (ch->level < skill_table[skspellNum].skill_level[ch->multied]))) {
return FALSE;
} else if (IS_NPC( ch ))
{
int gsn = skspellNum;
if (ch->level < 5 && ( gsn == skill_lookup("second attack") || gsn == skill_lookup("second strike") ) )
return FALSE;
if (ch->level < 15 && ( gsn == skill_lookup("third attack") || gsn == skill_lookup("third strike") ) )
return FALSE;
if (ch->level < 25 && ( gsn == skill_lookup("fourth attack") || gsn == skill_lookup("fourth strike") ) )
return FALSE;
if (ch->level < 35 && ( gsn == skill_lookup("fifth attack") || gsn == skill_lookup("fifth strike") ) )
return FALSE;
if (ch->level < 40 && ( gsn == skill_lookup("sixth attack") || gsn == skill_lookup("sixth strike") ) )
return FALSE;
if (ch->level < 45 && ( gsn == skill_lookup("seventh attack") || gsn == skill_lookup("seventh strike") ) )
return FALSE;
if (ch->level < 50 && ( gsn == skill_lookup("eighth attack") || gsn == skill_lookup("eighth strike") ) )
return FALSE;
}
return TRUE;
}
void damclass_shield_weaken(CHAR_DATA *victim, int dam, int dt)
{
int adjustment = dam /200;
int damclass = 0;
bool found = FALSE;
int index = 0;
int apply_loc = APPLY_NONE;
AFFECT_DATA * paf;
if (dt >= TYPE_HIT)
damclass = DAMCLASS_PHYSICAL;
else
damclass = skill_table[dt].damclass;
switch (damclass)
{
case DAMCLASS_ACID:
apply_loc = APPLY_DAM_ACID;
index = 0;
break;
case DAMCLASS_HOLY:
apply_loc = APPLY_DAM_HOLY;
index = 1;
break;
case DAMCLASS_MAGIC:
apply_loc = APPLY_DAM_MAGIC;
index = 2;
break;
case DAMCLASS_FIRE:
apply_loc = APPLY_DAM_FIRE;
index = 3;
break;
case DAMCLASS_ENERGY:
apply_loc = APPLY_DAM_ENERGY;
index = 4;
break;
case DAMCLASS_WIND:
apply_loc = APPLY_DAM_WIND;
index = 5;
break;
case DAMCLASS_WATER:
apply_loc = APPLY_DAM_WATER;
index = 6;
break;
case DAMCLASS_ILLUSION:
apply_loc = APPLY_DAM_ILLUSION;
index = 7;
break;
case DAMCLASS_DISPEL:
apply_loc = APPLY_DAM_DISPEL;
index = 8;
break;
case DAMCLASS_EARTH:
apply_loc = APPLY_DAM_EARTH;
index = 9;
break;
case DAMCLASS_PSYCHIC:
apply_loc = APPLY_DAM_PSYCHIC;
index = 10;
break;
case DAMCLASS_POISON:
apply_loc = APPLY_DAM_POISON;
index = 11;
break;
case DAMCLASS_BREATH:
apply_loc = APPLY_DAM_BREATH;
index = 12;
break;
case DAMCLASS_SUMMON:
apply_loc = APPLY_DAM_SUMMON;
index = 13;
break;
case DAMCLASS_PHYSICAL:
apply_loc = APPLY_DAM_PHYSICAL;
index = 14;
break;
case DAMCLASS_EXPLOSIVE:
apply_loc = APPLY_DAM_EXPLOSIVE;
index = 15;
break;
case DAMCLASS_SONG:
apply_loc = APPLY_DAM_SONG;
index = 16;
break;
case DAMCLASS_NAGAROM:
apply_loc = APPLY_DAM_NAGAROM;
index = 17;
break;
case DAMCLASS_UNHOLY:
apply_loc = APPLY_DAM_UNHOLY;
index = 18;
break;
case DAMCLASS_CLAN:
apply_loc = APPLY_DAM_CLAN;
index = 19;
break;
default:
return;
}
for (paf = victim->affected; paf; paf = paf->next)
{
if (paf->deleted)
continue;
if (found)
break;
/* Ok, first we find the right affect... */
if ((paf->location == apply_loc) && (paf->modifier > 0) )
{
victim->damage_mods[index] -=UMIN( adjustment, paf->modifier);
paf->modifier -= adjustment;
paf->modifier = UMAX(0,paf->modifier);
found = TRUE;
}
}
for (paf = victim->affected2; paf; paf = paf->next)
{
if (paf->deleted)
continue;
if (found)
break;
/* Ok, first we find the right affect... */
if ((paf->location == apply_loc) && paf->modifier > 0 )
{
victim->damage_mods[index] -= UMIN( adjustment, paf->modifier);
paf->modifier -= adjustment;
paf->modifier = UMAX(0, paf->modifier);
found = TRUE;
}
}
for (paf = victim->affected3; paf; paf = paf->next)
{
if (paf->deleted)
continue;
if (found)
break;
/* Ok, first we find the right affect... */
if ((paf->location == apply_loc) && paf->modifier > 0 )
{
victim->damage_mods[index] -= UMIN( adjustment, paf->modifier);
paf->modifier -= adjustment;
paf->modifier = UMAX(0, paf->modifier);
found = TRUE;
}
}
for (paf = victim->affected4; paf; paf = paf->next)
{
if (paf->deleted)
continue;
if (found)
break;
/* Ok, first we find the right affect... */
if ((paf->location == apply_loc) && paf->modifier > 0 )
{
victim->damage_mods[index] -= UMIN(adjustment, paf->modifier);
paf->modifier -= adjustment;
paf->modifier = UMAX(0, paf->modifier);
found = TRUE;
}
}
return;
}
int skill_axe_kick( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
int dam = 0;
if ( !ch->fighting )
{
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
return SKPELL_MISSED;
}
if ( !check_blind( ch ) )
return SKPELL_MISSED;
one_argument( target_name, arg );
victim = ch->fighting;
if ( arg[0] != '\0' )
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return SKPELL_MISSED;
}
WAIT_STATE( ch, skill_table[sn].beats );
if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 ) )
{
dam = number_range(ch->level * 4, ch->level * 11); //damage( ch, victim, number_range( ch->level*4, ch->level*11 ), gsn_axe_kick );
}
else
dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_axe_kick );
return dam;
}
// AC Damage Reduction - Ahsile
int damreduce (CHAR_DATA* ch, CHAR_DATA* victim, int dam, int dt)
{
float mod;
//char buf [MAX_STRING_LENGTH];
// No reduction for certain skills
if ( dt == skill_lookup("backstab") || dt == skill_lookup("double backstab") || dt == skill_lookup("assassinate") || dt == skill_lookup("triple backstab") )
return dam;
// Hitroll (you got good aim!)
mod = -(victim->armor) - (IS_NPC(ch) ? (float)(ch->hitroll/4) : (float)(ch->hitroll/2));
// Max out at MAX_ARMOR
mod = (mod > MAX_ARMOR) ? MAX_ARMOR : (mod < -MAX_ARMOR ? -MAX_ARMOR : mod);
// Translate into a number between -0.5 to 0.5
mod /= (MAX_ARMOR*2);
//sprintf(buf, "Mod: %f Orig Dam: %d", mod, dam);
//send_to_char(AT_WHITE, buf, victim);
dam -= (int)(dam*mod);
//sprintf(buf, " New Damage: %d\n\r", dam);
//send_to_char(AT_WHITE, buf, victim);
return dam;
}
/* rewrite insane wield checks - Ahsile */
bool can_use_attack( int attack_num, CHAR_DATA* ch)
{
char buf_att[MAX_STRING_LENGTH];
char buf_str[MAX_STRING_LENGTH];
char buf_sht[MAX_STRING_LENGTH];
char buf [MAX_STRING_LENGTH];
static char* att = "%s attack";
static char* str = "%s strike";
static char* sht = "%s shot";
OBJ_DATA* wielded = get_eq_char( ch, WEAR_WIELD );
OBJ_DATA* dualed = get_eq_char( ch, WEAR_WIELD_2 );
int value = flag_value( weapon_flags, "shot" );
if ( attack_num > 2 && attack_num < 7 && IS_AFFECTED3(ch, AFF_TALE_OF_TERROR) )
return FALSE;
switch ( attack_num )
{
case 2:
strcpy(buf, "second");
break;
case 3:
strcpy(buf, "third");
break;
case 4:
strcpy(buf, "fourth");
break;
case 5:
strcpy(buf, "fifth");
break;
case 6:
strcpy(buf, "sixth");
break;
case 7:
strcpy(buf, "seventh");
break;
case 8:
strcpy(buf, "eighth");
break;
default:
return FALSE;
}
sprintf(buf_att, att, buf); /* make "second attack", etc */
sprintf(buf_str, str, buf); /* make "second strike", etc */
sprintf(buf_sht, sht, buf); /* make "second shot", etc */
if (
(
( can_use_skspell( ch, skill_lookup( buf_att ) ) ) &&
( wielded != NULL || dualed != NULL ) &&
( ( wielded ? wielded->value[3] != value : FALSE ) || ( dualed ? dualed->value[3] != value : FALSE ) ) &&
( IS_NPC(ch) || ( !IS_NPC(ch) && number_percent( ) < ( ch->pcdata->learned[ skill_lookup( buf_att )] / 10 ) ) )
)
|| (
( can_use_skspell( ch, skill_lookup( buf_str ) ) ) &&
( wielded == NULL && dualed == NULL ) &&
( IS_NPC(ch) || ( !IS_NPC(ch) && number_percent( ) < ( ch->pcdata->learned[ skill_lookup( buf_str )] / 10 ) ) )
)
|| (
( can_use_skspell( ch, skill_lookup( buf_sht ) ) ) &&
( wielded != NULL || dualed != NULL ) &&
( ( wielded ? wielded->value[3] == value : FALSE ) || ( dualed ? dualed->value[3] == value : FALSE ) ) &&
( IS_NPC(ch) || ( !IS_NPC(ch) && number_percent( ) < ( ch->pcdata->learned[ skill_lookup( buf_sht )] / 10 ) ) )
)
)
{
if (!wielded && !dualed)
update_skpell(ch, skill_lookup( buf_str ), 0 );
else
{
if (wielded && !dualed)
{
if (IS_SET( wielded->extra_flags2, ITEM_TWO_HANDED ) && wielded->value[3] != flag_value( weapon_flags, "shot" ) )
{
if ( IS_NPC(ch) || number_percent() < (ch->pcdata->learned[skill_lookup("two handed")]/10 ) )
{
update_skpell( ch, skill_lookup("two handed"), 0 );
} else
{
return FALSE; // wielding a two handed weapon, and two handed check failed
}
}
}
if ((wielded && wielded->value[3] == value) || (dualed && dualed->value[3] == value ))
update_skpell( ch, skill_lookup( buf_sht ), 0 );
if ((wielded && wielded->value[3] != value) || (dualed && dualed->value[3] != value ))
update_skpell( ch, skill_lookup( buf_att ), 0 );
}
return TRUE;
}
return FALSE;
}
/* dual actually depends on your skill % now */
bool can_dual( CHAR_DATA* ch)
{
int pct = number_percent();
int sn = skill_lookup("dual");
/* no know dual? fail */
if ( !can_use_skspell(ch, sn ) )
return FALSE;
/* two handed weapon? fail */
if (get_eq_char(ch, WEAR_WIELD) != NULL && IS_SET(get_eq_char(ch, WEAR_WIELD)->extra_flags2, ITEM_TWO_HANDED))
return FALSE;
/* bare fisted? succeed if % check succeeds */
if (get_eq_char(ch, WEAR_WIELD) == NULL && get_eq_char(ch,WEAR_WIELD_2) == NULL )
{
if (IS_NPC(ch) || pct < ( ch->pcdata->learned[sn] / 10 ) )
{
update_skpell( ch, sn, 0 );
return TRUE;
}
}
/* are you actually dual wielding? if so and % check succeeds */
else if (get_eq_char(ch, WEAR_WIELD) != NULL && get_eq_char(ch, WEAR_WIELD_2) != NULL )
{
if (IS_NPC(ch) || pct < ( ch->pcdata->learned[sn] / 10 ) )
{
update_skpell( ch, sn, 0 );
return TRUE;
}
}
/* otherwise, you failed the checks because:
a) you failed a % check
or
b) you are wielding one weapon (either hand)
*/
return FALSE;
}
void miss_message( CHAR_DATA* ch, CHAR_DATA* victim, bool dual )
{
if ( IS_SET( ch->act, PLR_COMBAT ) )
{
if (!dual)
act(AT_GREEN, "You attack $N, but miss.", ch, NULL, victim, TO_CHAR );
else
act(AT_GREEN, "You attack $N and miss both primary and dual attacks.", ch, NULL, victim, TO_CHAR);
}
if ( IS_SET( victim->act, PLR_COMBAT ) )
{
act(AT_GREEN, "$n attacks you, but misses.", ch, NULL, victim, TO_VICT );
}
}