-
Notifications
You must be signed in to change notification settings - Fork 68
Combat
The bow attack is possible every (256-pc.attr[SPEED])/16+4
frames.
If the melee attack didn't affect any targets, and one of 8 neighboring threatened cells contain a chest or a door, the bashing is performed.
(to do)
The speed of arrows and spells is 100 units/frame. Two collision checks are made per frame, for 50 and 100 unit distance.
The arrows and spells exist for 30 frames.
The spell projectiles have a light radius of 500.
The armor class is separate for each of 7 paperdoll slots. It is calculated as the sum of the corresponding item AC, shield AC if the shield covers the corresponding slot, and any AC-affecting items the (N)PC has equipped.
7-item byte arrays for each shield type are located @45159
, @45160
, @45168
, and @4516F
. If the corresponding element is non-zero, the shield AC is added.
Successful attacks break the invisibility for 20 frames.
if attacker.race in (REDGUARD, DARKELF, WOODELF) then
racial <- attacker.level*256/100
else
racial <- 0
endif
chance1 <- 128+((attacker.level-defender.level)*5)*256/100+(attacker.luckBonus-defender.luckBonus)+racial+(attacker.hitBonus-defender.defenceBonus)-defender.AC[slot]
chance2 <- player.level*256/100+51
return (rnd(256)<max(chance1,chance2))
Critical hit is an x3 multiplier. It's chances are:
- Thieves: 2%/level if no ranged weapon equipped (ranged weapons include daggers for some reason)
- Assassins: 3%/level
- Monks: 3%/(level*2)
- Archers: 3%/level if a ranged weapon equipped
- Everyone else who has Critical hit: 1%/level, no ranged weapon.
Unarmored damage depends on the equipped gauntlets type. It is stored in pairs are 6-byte array @475FC
.
The primary damage lies in the minDamage .. (maxDamage - 1)
range. (That is probably a bug.)
If a weapon is equipped, a racial bonus is added:
- Dark elves:
npc.level/4
- Redguards:
npc.level/3
if a ranged weapon equipped (see above). (That is probably a bug.) - Wood elves:
npc.level/3
if no ranged weapon equipped.
For rangers, their npc.level+1
is added if the target is not undead. (This is broken in the original game.)
int ApplyRangerBonus(NPCDATA* npcData, int damage)
{
if (npcData->Class == 0xe) // is a Ranger
{
// There are 2 bugs here. The player's status flags are checked instead of the opponent's, and IsUndead() is
// passed the current damage total although it expects the enemy type ID.
if ((npcData->StatusFlags & 0x1000) && IsUndead(damage)) // The 0x1000 flag means a creature (non-class) enemy.
{
return damage; // No bonus.
}
damage = damage + (npcData->Level + 1);
}
return damage;
}
bool IsUndead(int creatureID)
{
int i = 7;
int index = 0;
do {
if ((UndeadCreatureIDs[index] == creatureID)
{
return true;
}
index++;
i--;
} while (i != 0);
return false;
}
UndeadCreatureIDs
are the seven from the list @47624
.
If the target is undead, and the weapon is silver, the damage is doubled.
The damage at this point is used to calculate the weapon degradation.
If the target is a Skeleton, and the weapon is in blade/axe/bow family, the damage is halved.
The damage at this point is used to calculate the target's armor degradation.
If the weapon is Volendrung or the Auriel's Bow, the damage is tripled.
If the weapon is Volendrung and the target is not a Knight, the target is paralyzed for 10 minutes (?), and the weapon's health is decreased by 800.
If the weapon is Ebony Blade, the half of the damage is added to the player.
- Golems are resistant to materials below
ELVEN + (race - ICEGOLEM)
. - Fire demons and higher monsters are resistant to materials given in the 4-element array
@4762B
. - Vampires are also not resistant to silver.
Successful material resistance is equivalent to a miss.
itm <- defender.equipped[SHIELD]
if itm and not shieldHasAC(itm, slot) then itm <- none
if not itm then itm <- defender.equipped[slot]
if itm then
dmg <- (damage * materialStrength[itm.material] + 50) / 100
if itm.isArtifact then dmg <- dmg / 2
itm.damage(dmg)
endif
dmg <- damage
if itm.isArtifact then dmg <- dmg / 2
itm.damage(dmg)