/*
* Hit one guy once.
*/
void one_hit( Character *ch, Character *victim, int dt )
{
Object *wield;
int victim_ac;
int thac0;
int thac0_00;
int thac0_32;
int dam;
int diceroll;
int sn,skill;
int dam_type;
bool result;
sn = -1;
/* just in case */
if (victim == ch || ch == NULL || victim == NULL)
return;
/*
* Can't beat a dead char!
* Guard against weird room-leavings.
*/
if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
/*
* Figure out the type of damage message.
*/
wield = get_eq_char( ch, WEAR_WIELD );
if ( dt == TYPE_UNDEFINED )
{
dt = TYPE_HIT;
if ( wield != NULL && wield->item_type == ITEM_WEAPON )
dt += wield->value[3];
else
dt += ch->dam_type;
}
if (dt < TYPE_HIT)
if (wield != NULL)
dam_type = attack_table[wield->value[3]].damage;
else
dam_type = attack_table[ch->dam_type].damage;
else
dam_type = attack_table[dt - TYPE_HIT].damage;
if (dam_type == -1)
dam_type = DAM_BASH;
/* get the weapon skill */
sn = get_weapon_sn(ch);
skill = 20 + get_weapon_skill(ch,sn);
/*
* Calculate to-hit-armor-klass-0 versus armor.
*/
if ( IS_NPC(ch) )
{
thac0_00 = 20;
thac0_32 = -4; /* as good as a thief */
if (IS_SET(ch->act,ACT_WARRIOR))
thac0_32 = -10;
else if (IS_SET(ch->act,ACT_THIEF))
thac0_32 = -4;
else if (IS_SET(ch->act,ACT_CLERIC))
thac0_32 = 2;
else if (IS_SET(ch->act,ACT_MAGE))
thac0_32 = 6;
}
else
{
thac0_00 = class_table[ch->klass].thac0_00;
thac0_32 = class_table[ch->klass].thac0_32;
}
thac0 = interpolate( ch->level, thac0_00, thac0_32 );
if (thac0 < 0)
thac0 = thac0/2;
if (thac0 < -5)
thac0 = -5 + (thac0 + 5) / 2;
thac0 -= GET_HITROLL(ch) * skill/100;
thac0 += 5 * (100 - skill) / 100;
if (dt == gsn_backstab)
thac0 -= 10 * (100 - get_skill(ch,gsn_backstab));
switch(dam_type)
{
case(DAM_PIERCE):victim_ac = GET_AC(victim,AC_PIERCE)/10; break;
case(DAM_BASH): victim_ac = GET_AC(victim,AC_BASH)/10; break;
case(DAM_SLASH): victim_ac = GET_AC(victim,AC_SLASH)/10; break;
default: victim_ac = GET_AC(victim,AC_EXOTIC)/10; break;
};
if (victim_ac < -15)
victim_ac = (victim_ac + 15) / 5 - 15;
if ( !can_see( ch, victim ) )
victim_ac -= 4;
if ( victim->position < POS_FIGHTING)
victim_ac += 4;
if (victim->position < POS_RESTING)
victim_ac += 6;
/*
* The moment of excitement!
*/
while ( ( diceroll = number_bits( 5 ) ) >= 20 )
;
if ( diceroll == 0
|| ( diceroll != 19 && diceroll < thac0 - victim_ac ) )
{
/* Miss. */
damage( ch, victim, 0, dt, dam_type, TRUE );
tail_chain( );
return;
}
/*
* Hit.
* Calc damage.
*/
if ( IS_NPC(ch) && (!ch->pIndexData->new_format || wield == NULL))
if (!ch->pIndexData->new_format)
{
dam = number_range( ch->level / 2, ch->level * 3 / 2 );
if ( wield != NULL )
dam += dam / 2;
}
else
dam = dice(ch->damage[DICE_NUMBER],ch->damage[DICE_TYPE]);
else
{
if (sn != -1)
check_improve(ch,sn,TRUE,5);
if ( wield != NULL )
{
if (wield->pIndexData->new_format)
dam = dice(wield->value[1],wield->value[2]) * skill/100;
else
dam = number_range( wield->value[1] * skill/100,
wield->value[2] * skill/100);
if (get_eq_char(ch,WEAR_SHIELD) == NULL) /* no shield = more */
dam = dam * 11/10;
/* sharpness! */
if (IS_WEAPON_STAT(wield,WEAPON_SHARP))
{
int percent;
if ((percent = number_percent()) <= (skill / 8))
dam = 2 * dam + (dam * 2 * percent / 100);
}
}
else
dam = number_range( 1 + 4 * skill/100, 2 * ch->level/3 * skill/100);
}
/*
* Bonuses.
*/
if ( get_skill(ch,gsn_enhanced_damage) > 0 )
{
diceroll = number_percent();
if (diceroll <= get_skill(ch,gsn_enhanced_damage))
{
check_improve(ch,gsn_enhanced_damage,TRUE,6);
dam += 2 * ( dam * diceroll/300);
}
}
if ( !IS_AWAKE(victim) )
dam *= 2;
else if (victim->position < POS_FIGHTING)
dam = dam * 3 / 2;
if ( dt == gsn_backstab && wield != NULL)
if ( wield->value[0] != 2 )
dam *= 2 + (ch->level / 10);
else
dam *= 2 + (ch->level / 8);
dam += GET_DAMROLL(ch) * UMIN(100,skill) /100;
if ( dam <= 0 )
dam = 1;
result = damage( ch, victim, dam, dt, dam_type, TRUE );
/* but do we have a funky weapon? */
if (result && wield != NULL)
{
int dam;
if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_POISON))
{
int level;
AFFECT_DATA *poison, af;
if ((poison = affect_find(wield->affected,gsn_poison)) == NULL)
level = wield->level;
else
level = poison->level;
if (!saves_spell(level / 2,victim,DAM_POISON))
{
send_to_char("You feel poison coursing through your veins.",
victim);
act("$n is poisoned by the venom on $p.",
victim,wield,NULL,TO_ROOM);
af.where = TO_AFFECTS;
af.type = gsn_poison;
af.level = level * 3/4;
af.duration = level / 2;
af.location = APPLY_STR;
af.modifier = -1;
af.bitvector = AFF_POISON;
affect_join( victim, &af );
}
/* weaken the poison if it's temporary */
if (poison != NULL)
{
poison->level = UMAX(0,poison->level - 2);
poison->duration = UMAX(0,poison->duration - 1);
if (poison->level == 0 || poison->duration == 0)
act("The poison on $p has worn off.",ch,wield,NULL,TO_CHAR);
}
}
if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_VAMPIRIC))
{
dam = number_range(1, wield->level / 5 + 1);
act("$p draws life from $n.",victim,wield,NULL,TO_ROOM);
act("You feel $p drawing your life away.",
victim,wield,NULL,TO_CHAR);
damage(ch,victim,dam,0,DAM_NEGATIVE,FALSE);
ch->alignment = UMAX(-1000,ch->alignment - 1);
ch->hit += dam/2;
}
if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_FLAMING))
{
dam = number_range(1,wield->level / 4 + 1);
act("$n is burned by $p.",victim,wield,NULL,TO_ROOM);
act("$p sears your flesh.",victim,wield,NULL,TO_CHAR);
fire_effect( (void *) victim,wield->level/2,dam,TARGET_CHAR);
damage(ch,victim,dam,0,DAM_FIRE,FALSE);
}
if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_FROST))
{
dam = number_range(1,wield->level / 6 + 2);
act("$p freezes $n.",victim,wield,NULL,TO_ROOM);
act("The cold touch of $p surrounds you with ice.",
victim,wield,NULL,TO_CHAR);
cold_effect(victim,wield->level/2,dam,TARGET_CHAR);
damage(ch,victim,dam,0,DAM_COLD,FALSE);
}
if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_SHOCKING))
{
dam = number_range(1,wield->level/5 + 2);
act("$n is struck by lightning from $p.",victim,wield,NULL,TO_ROOM);
act("You are shocked by $p.",victim,wield,NULL,TO_CHAR);
shock_effect(victim,wield->level/2,dam,TARGET_CHAR);
damage(ch,victim,dam,0,DAM_LIGHTNING,FALSE);
}
}
tail_chain( );
return;
}
if (IS_NPC (ch))
{
thac0_00 = 20;
thac0_32 = -4; /* as good as a thief */
if (IS_SET (ch->act, ACT_WARRIOR))
thac0_32 = -10;
else if (IS_SET (ch->act, ACT_THIEF))
thac0_32 = -4;
else if (IS_SET (ch->act, ACT_CLERIC))
thac0_32 = 2;
else if (IS_SET (ch->act, ACT_MAGE))
thac0_32 = 6;
}
else
{
thac0_00 = class_table[ch->class].thac0_00;
thac0_32 = class_table[ch->class].thac0_32;
}
thac0 = interpolate (ch->level, thac0_00, thac0_32);
if (thac0 < 0)
thac0 = thac0 / 2;
if (thac0 < -5)
thac0 = -5 + (thac0 + 5) / 2;
thac0 -= GET_HITROLL (ch) * skill / 100;
thac0 += 5 * (100 - skill) / 100;