Rewrote the swing/attack handler for authenticity:
Fixed a lot of off-by-1 miscalculations Fixed the void ranger bonus, which should be 20% Fixed granite maul spec not giving xp and ignoring protection prayers Fixed accuracy being too high Fixed set bonuses that boost attack or defence being applied twice or to all attacks Fixed ranged attacks not taking into account prayers that boost defence or defensive attack styles Fixed red chinchompa having the same damage as normal chinchompas Fixed some specs being boosted by offensive prayers ::calcmaxhit now has better formatting ::calc_accuracy renamed to ::calcaccuracy for consistency with other commands, and now also gives the actual hit chance
This commit is contained in:
@@ -323,9 +323,6 @@ public final class EquipmentContainer extends Container {
|
||||
if (item != null) {
|
||||
int[] bonus = item.getDefinition().getConfiguration(ItemConfigParser.BONUS, new int[15]);
|
||||
for (int i = 0; i < bonus.length; i++) {
|
||||
if (i == 14 && bonuses[i] != 0) {
|
||||
continue;
|
||||
}
|
||||
bonuses[i] += bonus[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,26 +173,21 @@ abstract class CombatSwingHandler(var type: CombatStyle?) {
|
||||
* @return `True` if the hit is accurate.
|
||||
*/
|
||||
fun isAccurateImpact(entity: Entity?, victim: Entity?, style: CombatStyle?, accuracyMod: Double, defenceMod: Double): Boolean {
|
||||
var mod = 1.33
|
||||
var mod = 1.0
|
||||
if (victim == null || style == null) {
|
||||
return false
|
||||
}
|
||||
if (victim is Player && entity is Familiar && victim.prayer[PrayerType.PROTECT_FROM_SUMMONING]) {
|
||||
mod = 0.0
|
||||
}
|
||||
val attack = calculateAccuracy(entity) * accuracyMod * mod * getSetMultiplier(entity, Skills.ATTACK)
|
||||
val defence = calculateDefence(victim, entity) * defenceMod * getSetMultiplier(victim, Skills.DEFENCE)
|
||||
val attack = calculateAccuracy(entity) * accuracyMod * mod
|
||||
val defence = calculateDefence(victim, entity) * defenceMod
|
||||
val chance: Double = if (attack > defence) {
|
||||
1 - ((defence + 2) / ((2 * attack) + 1))
|
||||
1 - ((defence + 2) / (2 * (attack + 1)))
|
||||
} else {
|
||||
attack / ((2 * defence) + 1)
|
||||
attack / (2 * (defence + 1))
|
||||
}
|
||||
val ratio = chance * 100
|
||||
val accuracy = floor(ratio)
|
||||
val block = floor(101 - ratio)
|
||||
val acc = Math.random() * accuracy
|
||||
val def = Math.random() * block
|
||||
return (acc > def).also { if(entity?.username?.toLowerCase() == "test10") log(this::class.java, Log.FINE, "Should hit: $it") }
|
||||
return Math.random() < chance
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package core.game.node.entity.combat
|
||||
|
||||
import content.global.skill.skillcapeperks.SkillcapePerks
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.combat.equipment.ArmourSet
|
||||
import core.game.node.entity.combat.spell.SpellType
|
||||
@@ -61,7 +62,7 @@ open class MagicSwingHandler (vararg flags: SwingHandlerFlag)
|
||||
for (s in state.targets) {
|
||||
var hit = -1
|
||||
s.spell = spell
|
||||
if (isAccurateImpact(entity, s.victim, CombatStyle.MAGIC, 1.3, 1.0)) {
|
||||
if (isAccurateImpact(entity, s.victim, CombatStyle.MAGIC)) {
|
||||
s.maximumHit = max
|
||||
hit = RandomFunction.random(max)
|
||||
}
|
||||
@@ -136,31 +137,31 @@ open class MagicSwingHandler (vararg flags: SwingHandlerFlag)
|
||||
}
|
||||
|
||||
override fun calculateAccuracy(entity: Entity?): Int {
|
||||
val baseLevel = entity!!.skills.getStaticLevel(Skills.MAGIC)
|
||||
var spellRequirement = baseLevel
|
||||
if (entity is Player) {
|
||||
if (entity.getProperties().spell != null) {
|
||||
spellRequirement = entity.getProperties().spell.level
|
||||
} else if (entity.getProperties().autocastSpell != null) {
|
||||
spellRequirement = entity.getProperties().autocastSpell.level
|
||||
entity ?: return 0
|
||||
|
||||
val styleAttackBonus = entity.properties.bonuses[WeaponInterface.BONUS_MAGIC] + 64
|
||||
when (entity) {
|
||||
is Player -> {
|
||||
var effectiveMagicLevel = entity.skills.getLevel(Skills.MAGIC, true).toDouble()
|
||||
if(!flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_ACCURACY))
|
||||
effectiveMagicLevel = floor(effectiveMagicLevel + (entity.prayer.getSkillBonus(Skills.MAGIC) * effectiveMagicLevel))
|
||||
effectiveMagicLevel += 8
|
||||
effectiveMagicLevel *= getSetMultiplier(entity, Skills.MAGIC)
|
||||
effectiveMagicLevel = floor(effectiveMagicLevel)
|
||||
|
||||
if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_ACCURACY))
|
||||
effectiveMagicLevel *= styleAttackBonus
|
||||
else effectiveMagicLevel *= 64
|
||||
|
||||
return effectiveMagicLevel.toInt()
|
||||
}
|
||||
is NPC -> {
|
||||
val magicLevel = entity.skills.getLevel(Skills.MAGIC) + 9
|
||||
return magicLevel * styleAttackBonus
|
||||
}
|
||||
}
|
||||
var spellBonus = 0.0
|
||||
if (baseLevel > spellRequirement) {
|
||||
spellBonus = (baseLevel - spellRequirement) * .3
|
||||
}
|
||||
val level = entity.skills.getLevel(Skills.MAGIC, true)
|
||||
var prayer = 1.0
|
||||
if (entity is Player && !flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_ACCURACY)) {
|
||||
prayer += entity.prayer.getSkillBonus(Skills.MAGIC)
|
||||
}
|
||||
val additional = getSetMultiplier(entity, Skills.MAGIC)
|
||||
val effective = floor(level * prayer * additional + spellBonus)
|
||||
val bonus =
|
||||
if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_ACCURACY))
|
||||
entity.properties.bonuses[WeaponInterface.BONUS_MAGIC]
|
||||
else 0
|
||||
return floor((effective + 8) * (bonus + 64) / 10).toInt()
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun calculateHit(entity: Entity?, victim: Entity?, modifier: Double): Int {
|
||||
@@ -183,14 +184,31 @@ open class MagicSwingHandler (vararg flags: SwingHandlerFlag)
|
||||
}
|
||||
|
||||
override fun calculateDefence(victim: Entity?, attacker: Entity?): Int {
|
||||
val level = victim!!.skills.getLevel(Skills.DEFENCE, true)
|
||||
var prayer = 1.0
|
||||
if (victim is Player) {
|
||||
prayer += victim.prayer.getSkillBonus(Skills.MAGIC)
|
||||
victim ?: return 0
|
||||
attacker ?: return 0
|
||||
|
||||
val styleDefenceBonus = victim.properties.bonuses[WeaponInterface.BONUS_MAGIC + 5] + 64
|
||||
when (victim) {
|
||||
is Player -> {
|
||||
var effectiveDefenceLevel = victim.skills.getLevel(Skills.DEFENCE).toDouble()
|
||||
effectiveDefenceLevel = floor(effectiveDefenceLevel + (victim.prayer.getSkillBonus(Skills.DEFENCE) * effectiveDefenceLevel))
|
||||
if (victim.properties.attackStyle.style == WeaponInterface.STYLE_DEFENSIVE || victim.properties.attackStyle.style == WeaponInterface.STYLE_LONG_RANGE) effectiveDefenceLevel += 3
|
||||
else if (victim.properties.attackStyle.style == WeaponInterface.STYLE_CONTROLLED) effectiveDefenceLevel += 1
|
||||
effectiveDefenceLevel *= getSetMultiplier(victim, Skills.DEFENCE)
|
||||
|
||||
var effectiveMagicLevel = victim.skills.getLevel(Skills.MAGIC).toDouble()
|
||||
effectiveMagicLevel = floor(effectiveMagicLevel + (victim.prayer.getSkillBonus(Skills.MAGIC) * effectiveMagicLevel))
|
||||
|
||||
effectiveDefenceLevel = effectiveDefenceLevel * 0.3 + effectiveMagicLevel * 0.7 + 8
|
||||
return effectiveDefenceLevel.toInt() * styleDefenceBonus
|
||||
}
|
||||
is NPC -> {
|
||||
val defLevel = victim.skills.getLevel(Skills.MAGIC) + 9
|
||||
return defLevel * styleDefenceBonus
|
||||
}
|
||||
}
|
||||
val effective = floor(level * prayer * 0.3) + victim.skills.getLevel(Skills.MAGIC, true) * 0.7
|
||||
val equipment = victim.properties.bonuses[WeaponInterface.BONUS_MAGIC + 5]
|
||||
return floor((effective + 8) * (equipment + 64) / 10).toInt()
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun getSetMultiplier(e: Entity?, skillId: Int): Double {
|
||||
|
||||
@@ -64,13 +64,16 @@ open class MeleeSwingHandler (vararg flags: SwingHandlerFlag)
|
||||
if (entity is Player) {
|
||||
state.weapon = Weapon(entity.equipment[3])
|
||||
}
|
||||
if (entity!!.properties.armourSet === ArmourSet.VERAC && RandomFunction.random(100) < 21) {
|
||||
if (entity!!.properties.armourSet === ArmourSet.VERAC && RandomFunction.random(100) < 25) {
|
||||
state.armourEffect = ArmourSet.VERAC
|
||||
}
|
||||
if (state.armourEffect === ArmourSet.VERAC || isAccurateImpact(entity, victim, CombatStyle.MELEE)) {
|
||||
val max = calculateHit(entity, victim, 1.0)
|
||||
var max = calculateHit(entity, victim, 1.0)
|
||||
if (victim != null) {
|
||||
if (entity is NPC && state.armourEffect === ArmourSet.VERAC && victim.hasProtectionPrayer(CombatStyle.MELEE)) max = max * 2 / 3
|
||||
}
|
||||
state.maximumHit = max
|
||||
hit = RandomFunction.random(max + 1)
|
||||
hit = RandomFunction.random(max + 1) + (if (entity is Player && state.armourEffect === ArmourSet.VERAC) 1 else 0)
|
||||
}
|
||||
state.estimatedHit = hit
|
||||
if(victim != null) {
|
||||
@@ -128,68 +131,79 @@ open class MeleeSwingHandler (vararg flags: SwingHandlerFlag)
|
||||
override fun calculateAccuracy(entity: Entity?): Int {
|
||||
//formula taken from wiki: https://oldschool.runescape.wiki/w/Damage_per_second/Melee#Step_six:_Calculate_the_hit_chance Yes I know it's old school. It's the best resource we have for potentially authentic formulae.
|
||||
entity ?: return 0
|
||||
var effectiveAttackLevel = entity.skills.getLevel(Skills.ATTACK).toDouble()
|
||||
if(entity is Player && !flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_ACCURACY))
|
||||
effectiveAttackLevel = floor(effectiveAttackLevel + (entity.prayer.getSkillBonus(Skills.ATTACK) * effectiveAttackLevel))
|
||||
if(entity.properties.attackStyle.style == WeaponInterface.STYLE_ACCURATE) effectiveAttackLevel += 3
|
||||
else if(entity.properties.attackStyle.style == WeaponInterface.STYLE_CONTROLLED) effectiveAttackLevel += 1
|
||||
effectiveAttackLevel += 8
|
||||
if(entity is Player && SkillcapePerks.isActive(SkillcapePerks.PRECISION_STRIKES, entity)){ //Attack skillcape perk
|
||||
effectiveAttackLevel += 6
|
||||
}
|
||||
effectiveAttackLevel *= getSetMultiplier(entity, Skills.ATTACK)
|
||||
effectiveAttackLevel = floor(effectiveAttackLevel)
|
||||
|
||||
if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_ACCURACY))
|
||||
effectiveAttackLevel *= (entity.properties.bonuses[entity.properties.attackStyle.bonusType] + 64)
|
||||
else effectiveAttackLevel *= 64
|
||||
val styleAttackBonus = entity.properties.bonuses[entity.properties.attackStyle.bonusType] + 64
|
||||
when (entity) {
|
||||
is Player -> {
|
||||
var effectiveAttackLevel = entity.skills.getLevel(Skills.ATTACK).toDouble()
|
||||
if(!flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_ACCURACY))
|
||||
effectiveAttackLevel = floor(effectiveAttackLevel + (entity.prayer.getSkillBonus(Skills.ATTACK) * effectiveAttackLevel))
|
||||
if(entity.properties.attackStyle.style == WeaponInterface.STYLE_ACCURATE) effectiveAttackLevel += 3
|
||||
else if(entity.properties.attackStyle.style == WeaponInterface.STYLE_CONTROLLED) effectiveAttackLevel += 1
|
||||
effectiveAttackLevel += 8
|
||||
if(SkillcapePerks.isActive(SkillcapePerks.PRECISION_STRIKES, entity)){ //Attack skillcape perk
|
||||
effectiveAttackLevel += 6
|
||||
}
|
||||
effectiveAttackLevel *= getSetMultiplier(entity, Skills.ATTACK)
|
||||
effectiveAttackLevel = floor(effectiveAttackLevel)
|
||||
if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_ACCURACY))
|
||||
effectiveAttackLevel *= styleAttackBonus
|
||||
else effectiveAttackLevel *= 64
|
||||
|
||||
val victimName = entity.properties.combatPulse.getVictim()?.name ?: "none"
|
||||
val victimName = entity.properties.combatPulse.getVictim()?.name ?: "none"
|
||||
|
||||
// attack bonus for specialized equipments (salve amulets, slayer equips)
|
||||
if (entity is Player) {
|
||||
val amuletId = getItemFromEquipment(entity, EquipmentSlot.NECK)?.id ?: 0
|
||||
if ((amuletId == Items.SALVE_AMULET_4081 || amuletId == Items.SALVE_AMULETE_10588) && checkUndead(victimName)) {
|
||||
effectiveAttackLevel *= if (amuletId == Items.SALVE_AMULET_4081) 1.15 else 1.2
|
||||
} else if (getSlayerTask(entity)?.ids?.contains((entity.properties.combatPulse?.getVictim()?.id ?: 0)) == true) {
|
||||
effectiveAttackLevel *= SlayerEquipmentFlags.getDamAccBonus(entity) //Slayer Helm/ Black Mask/ Slayer cape
|
||||
if (getSlayerTask(entity)?.dragon == true && inEquipment(entity, Items.DRAGON_SLAYER_GLOVES_12862))
|
||||
effectiveAttackLevel *= 1.1
|
||||
// attack bonus for specialized equipments (salve amulets, slayer equips)
|
||||
val amuletId = getItemFromEquipment(entity, EquipmentSlot.NECK)?.id ?: 0
|
||||
if ((amuletId == Items.SALVE_AMULET_4081 || amuletId == Items.SALVE_AMULETE_10588) && checkUndead(victimName)) {
|
||||
effectiveAttackLevel *= if (amuletId == Items.SALVE_AMULET_4081) 1.15 else 1.2
|
||||
} else if (getSlayerTask(entity)?.ids?.contains((entity.properties.combatPulse?.getVictim()?.id ?: 0)) == true) {
|
||||
effectiveAttackLevel *= SlayerEquipmentFlags.getDamAccBonus(entity) //Slayer Helm/ Black Mask/ Slayer cape
|
||||
if (getSlayerTask(entity)?.dragon == true && inEquipment(entity, Items.DRAGON_SLAYER_GLOVES_12862))
|
||||
effectiveAttackLevel *= 1.1
|
||||
}
|
||||
|
||||
return effectiveAttackLevel.toInt()
|
||||
}
|
||||
is NPC -> {
|
||||
val attackLevel = entity.skills.getLevel(Skills.ATTACK) + 9
|
||||
return attackLevel * styleAttackBonus
|
||||
}
|
||||
}
|
||||
|
||||
return floor(effectiveAttackLevel).toInt()
|
||||
return 0
|
||||
|
||||
|
||||
}
|
||||
|
||||
override fun calculateHit(entity: Entity?, victim: Entity?, modifier: Double): Int {
|
||||
val level = entity!!.skills.getLevel(Skills.STRENGTH)
|
||||
var bonus = entity.properties.bonuses[11]
|
||||
var prayer = 1.0
|
||||
if (entity is Player && !flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_DAMAGE)) {
|
||||
prayer += entity.prayer.getSkillBonus(Skills.STRENGTH)
|
||||
}
|
||||
var cumulativeStr = floor(level * prayer)
|
||||
if (entity.properties.attackStyle.style == WeaponInterface.STYLE_AGGRESSIVE) {
|
||||
cumulativeStr += 3.0
|
||||
} else if (entity.properties.attackStyle.style == WeaponInterface.STYLE_CONTROLLED) {
|
||||
cumulativeStr += 1.0
|
||||
entity ?: return 0
|
||||
|
||||
var styleStrengthBonus = entity.properties.bonuses[11] + 64
|
||||
when (entity) {
|
||||
is Player -> {
|
||||
var effectiveStrengthLevel = entity.skills.getLevel(Skills.STRENGTH).toDouble()
|
||||
if(!flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_DAMAGE))
|
||||
effectiveStrengthLevel = floor(effectiveStrengthLevel + (entity.prayer.getSkillBonus(Skills.STRENGTH) * effectiveStrengthLevel))
|
||||
if(entity.properties.attackStyle.style == WeaponInterface.STYLE_AGGRESSIVE) effectiveStrengthLevel += 3
|
||||
else if (entity.properties.attackStyle.style == WeaponInterface.STYLE_CONTROLLED) effectiveStrengthLevel += 1
|
||||
effectiveStrengthLevel += 8
|
||||
effectiveStrengthLevel *= getSetMultiplier(entity, Skills.STRENGTH)
|
||||
effectiveStrengthLevel = floor(effectiveStrengthLevel)
|
||||
if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_DAMAGE))
|
||||
effectiveStrengthLevel *= styleStrengthBonus
|
||||
else effectiveStrengthLevel *= 64
|
||||
if (getSlayerTask(entity)?.ids?.contains((entity.properties.combatPulse?.getVictim()?.id ?: 0)) == true)
|
||||
effectiveStrengthLevel *= SlayerEquipmentFlags.getDamAccBonus(entity) //Slayer Helm/ Black Mask/ Slayer cape
|
||||
|
||||
return (floor((0.5 + (effectiveStrengthLevel / 640.0))) * modifier).toInt()
|
||||
}
|
||||
is NPC -> {
|
||||
val strengthLevel = entity.skills.getLevel(Skills.STRENGTH) + 9
|
||||
return (floor((0.5 + (strengthLevel * styleStrengthBonus / 640.0))) * modifier).toInt()
|
||||
}
|
||||
}
|
||||
|
||||
//Strength skillcape perk
|
||||
if(entity is Player && SkillcapePerks.isActive(SkillcapePerks.FINE_ATTUNEMENT, entity) && getItemFromEquipment(entity, EquipmentSlot.WEAPON)?.definition?.getRequirement(Skills.STRENGTH) != 0)
|
||||
bonus = ceil(bonus * 1.20).toInt()
|
||||
|
||||
if (flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_DAMAGE))
|
||||
bonus = 0
|
||||
|
||||
cumulativeStr *= getSetMultiplier(entity, Skills.STRENGTH)
|
||||
|
||||
if(entity is Player && getSlayerTask(entity)?.ids?.contains((entity.properties.combatPulse?.getVictim()?.id ?: 0)) == true)
|
||||
cumulativeStr *= SlayerEquipmentFlags.getDamAccBonus(entity) //Slayer helm/black mask/skillcape
|
||||
|
||||
/*val hit = (16 + cumulativeStr + bonus / 8 + cumulativeStr * bonus * 0.016865) * modifier
|
||||
return (hit / 10).toInt() + 1*/
|
||||
return ((1.3 + (cumulativeStr / 10) + (bonus / 80) + ((cumulativeStr * bonus) / 640)) * modifier).toInt()
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun calculateDefence(victim: Entity?, attacker: Entity?): Int {
|
||||
@@ -197,19 +211,19 @@ open class MeleeSwingHandler (vararg flags: SwingHandlerFlag)
|
||||
victim ?: return 0
|
||||
attacker ?: return 0
|
||||
|
||||
when(victim){
|
||||
val styleDefenceBonus = victim.properties.bonuses[attacker.properties.attackStyle.bonusType + 5] + 64
|
||||
when (victim) {
|
||||
is Player -> {
|
||||
var effectiveDefenceLevel = victim.skills.getLevel(Skills.DEFENCE).toDouble()
|
||||
effectiveDefenceLevel = floor(effectiveDefenceLevel + (victim.prayer.getSkillBonus(Skills.DEFENCE) * effectiveDefenceLevel))
|
||||
if(victim.properties.attackStyle.style == WeaponInterface.STYLE_DEFENSIVE) effectiveDefenceLevel += 3
|
||||
else if(victim.properties.attackStyle.style == WeaponInterface.STYLE_CONTROLLED) effectiveDefenceLevel += 1
|
||||
if (victim.properties.attackStyle.style == WeaponInterface.STYLE_DEFENSIVE || victim.properties.attackStyle.style == WeaponInterface.STYLE_LONG_RANGE) effectiveDefenceLevel += 3
|
||||
else if (victim.properties.attackStyle.style == WeaponInterface.STYLE_CONTROLLED) effectiveDefenceLevel += 1
|
||||
effectiveDefenceLevel += 8
|
||||
effectiveDefenceLevel = floor(effectiveDefenceLevel)
|
||||
return floor(effectiveDefenceLevel * (victim.properties.bonuses[attacker.properties.attackStyle.bonusType + 5] + 64)).toInt()
|
||||
effectiveDefenceLevel *= getSetMultiplier(victim, Skills.DEFENCE)
|
||||
return effectiveDefenceLevel.toInt() * styleDefenceBonus
|
||||
}
|
||||
is NPC -> {
|
||||
val defLevel = victim.skills.getLevel(Skills.DEFENCE)
|
||||
val styleDefenceBonus = victim.properties.bonuses[attacker.properties.attackStyle.bonusType + 5] + 64
|
||||
val defLevel = victim.skills.getLevel(Skills.DEFENCE) + 9
|
||||
return defLevel * styleDefenceBonus
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,14 +13,14 @@ import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.GroundItem
|
||||
import core.game.node.item.GroundItemManager
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.config.ItemConfigParser
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.GameWorld
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.RegionManager
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import core.tools.RandomFunction
|
||||
import core.tools.SystemLogger
|
||||
import core.game.world.GameWorld
|
||||
import core.tools.Log
|
||||
import core.tools.RandomFunction
|
||||
import java.util.*
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.floor
|
||||
@@ -83,7 +83,7 @@ open class RangeSwingHandler (vararg flags: SwingHandlerFlag)
|
||||
state.estimatedHit = hit
|
||||
if (state.weapon.type == WeaponType.DOUBLE_SHOT) {
|
||||
if (isAccurateImpact(entity, victim, CombatStyle.RANGE)) {
|
||||
hit = RandomFunction.random(calculateHit(entity, victim, 1.0))
|
||||
hit = RandomFunction.random(calculateHit(entity, victim, 1.0) + 1)
|
||||
}
|
||||
state.secondaryHit = hit
|
||||
}
|
||||
@@ -183,56 +183,92 @@ open class RangeSwingHandler (vararg flags: SwingHandlerFlag)
|
||||
|
||||
override fun calculateAccuracy(entity: Entity?): Int {
|
||||
entity ?: return 0
|
||||
var effectiveRangedLevel = entity.skills.getLevel(Skills.RANGE).toDouble()
|
||||
if(entity is Player && !flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_ACCURACY))
|
||||
effectiveRangedLevel = floor(effectiveRangedLevel + (entity.prayer.getSkillBonus(Skills.RANGE) * effectiveRangedLevel))
|
||||
if(entity.properties.attackStyle.style == WeaponInterface.STYLE_RANGE_ACCURATE) effectiveRangedLevel += 3
|
||||
effectiveRangedLevel += 8
|
||||
effectiveRangedLevel *= getSetMultiplier(entity, Skills.RANGE)
|
||||
if(entity is Player && SkillcapePerks.isActive(SkillcapePerks.ACCURATE_MARKSMAN,entity)) effectiveRangedLevel *= 1.1
|
||||
|
||||
effectiveRangedLevel = floor(effectiveRangedLevel)
|
||||
if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_ACCURACY))
|
||||
effectiveRangedLevel *= (entity.properties.bonuses[entity.properties.attackStyle.bonusType] + 64)
|
||||
else effectiveRangedLevel *= 64
|
||||
val styleAttackBonus = entity.properties.bonuses[entity.properties.attackStyle.bonusType] + 64
|
||||
when (entity) {
|
||||
is Player -> {
|
||||
var effectiveRangedLevel = entity.skills.getLevel(Skills.RANGE).toDouble()
|
||||
if(!flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_ACCURACY))
|
||||
effectiveRangedLevel = floor(effectiveRangedLevel + (entity.prayer.getSkillBonus(Skills.RANGE) * effectiveRangedLevel))
|
||||
if(entity.properties.attackStyle.style == WeaponInterface.STYLE_RANGE_ACCURATE) effectiveRangedLevel += 3
|
||||
effectiveRangedLevel += 8
|
||||
effectiveRangedLevel *= getSetMultiplier(entity, Skills.RANGE)
|
||||
if(SkillcapePerks.isActive(SkillcapePerks.ACCURATE_MARKSMAN,entity)) effectiveRangedLevel *= 1.1
|
||||
|
||||
return floor(effectiveRangedLevel).toInt()
|
||||
effectiveRangedLevel = floor(effectiveRangedLevel)
|
||||
if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_ACCURACY))
|
||||
effectiveRangedLevel *= styleAttackBonus
|
||||
else effectiveRangedLevel *= 64
|
||||
|
||||
return effectiveRangedLevel.toInt()
|
||||
}
|
||||
is NPC -> {
|
||||
val rangedLevel = entity.skills.getLevel(Skills.RANGE) + 9
|
||||
return rangedLevel * styleAttackBonus
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun calculateHit(entity: Entity?, victim: Entity?, modifier: Double): Int {
|
||||
val level = entity!!.skills.getLevel(Skills.RANGE)
|
||||
val bonus = entity.properties.bonuses[14]
|
||||
var prayer = 1.0
|
||||
if (entity is Player && !flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_DAMAGE)) {
|
||||
prayer += entity.prayer.getSkillBonus(Skills.RANGE)
|
||||
}
|
||||
var cumulativeStr = floor(level * prayer)
|
||||
if (entity.properties.attackStyle.style == WeaponInterface.STYLE_RANGE_ACCURATE) {
|
||||
cumulativeStr += 3.0
|
||||
}
|
||||
cumulativeStr *= getSetMultiplier(entity, Skills.RANGE)
|
||||
entity ?: return 0
|
||||
|
||||
if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_DAMAGE))
|
||||
cumulativeStr *= (bonus + 64)
|
||||
else cumulativeStr *= 64
|
||||
var styleStrengthBonus = entity.properties.bonuses[14] + 64
|
||||
when (entity) {
|
||||
is Player -> {
|
||||
if(entity.equipment[EquipmentContainer.SLOT_WEAPON] != null && RangeWeapon.get(entity.equipment[EquipmentContainer.SLOT_WEAPON].id).ammunitionSlot != EquipmentContainer.SLOT_ARROWS && entity.equipment[EquipmentContainer.SLOT_ARROWS] != null)
|
||||
styleStrengthBonus -= entity.equipment[EquipmentContainer.SLOT_ARROWS].definition.getConfiguration<IntArray>(ItemConfigParser.BONUS)[14]
|
||||
var effectiveStrengthLevel = entity.skills.getLevel(Skills.RANGE).toDouble()
|
||||
if(!flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_DAMAGE))
|
||||
effectiveStrengthLevel = floor(effectiveStrengthLevel + (entity.prayer.getSkillBonus(Skills.RANGE) * effectiveStrengthLevel))
|
||||
if(entity.properties.attackStyle.style == WeaponInterface.STYLE_RANGE_ACCURATE) effectiveStrengthLevel += 3
|
||||
effectiveStrengthLevel += 8
|
||||
effectiveStrengthLevel *= getSetMultiplier(entity, Skills.RANGE)
|
||||
effectiveStrengthLevel = floor(effectiveStrengthLevel)
|
||||
if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_DAMAGE))
|
||||
effectiveStrengthLevel *= styleStrengthBonus
|
||||
else effectiveStrengthLevel *= 64
|
||||
|
||||
return floor((1.5 + (ceil(cumulativeStr) / 640.0)) * modifier).toInt()
|
||||
//return ((14 + cumulativeStr + bonus / 8 + cumulativeStr * bonus * 0.016865) * modifier).toInt() / 10 + 1
|
||||
return (floor((0.5 + (effectiveStrengthLevel / 640.0))) * modifier).toInt()
|
||||
}
|
||||
is NPC -> {
|
||||
val rangedLevel = entity.skills.getLevel(Skills.RANGE) + 9
|
||||
return (floor((0.5 + (rangedLevel * styleStrengthBonus / 640.0))) * modifier).toInt()
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun calculateDefence(victim: Entity?, attacker: Entity?): Int {
|
||||
victim ?: return 0
|
||||
attacker ?: return 0
|
||||
|
||||
val defLevel = victim.skills.getLevel(Skills.DEFENCE)
|
||||
val styleDefenceBonus = victim.properties.bonuses[attacker.properties.attackStyle.bonusType + 5] + 64
|
||||
return defLevel * styleDefenceBonus
|
||||
when (victim) {
|
||||
is Player -> {
|
||||
var effectiveDefLevel = victim.skills.getLevel(Skills.DEFENCE).toDouble()
|
||||
effectiveDefLevel = floor(effectiveDefLevel + (victim.prayer.getSkillBonus(Skills.DEFENCE) * effectiveDefLevel))
|
||||
if (victim.properties.attackStyle.style == WeaponInterface.STYLE_DEFENSIVE || victim.properties.attackStyle.style == WeaponInterface.STYLE_LONG_RANGE) effectiveDefLevel += 3
|
||||
else if (victim.properties.attackStyle.style == WeaponInterface.STYLE_CONTROLLED) effectiveDefLevel += 1
|
||||
effectiveDefLevel += 8
|
||||
effectiveDefLevel *= getSetMultiplier(victim, Skills.DEFENCE)
|
||||
return effectiveDefLevel.toInt() * styleDefenceBonus
|
||||
}
|
||||
is NPC -> {
|
||||
val defLevel = victim.skills.getLevel(Skills.DEFENCE) + 9
|
||||
return defLevel * styleDefenceBonus
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun getSetMultiplier(e: Entity?, skillId: Int): Double {
|
||||
if(skillId == Skills.RANGE) {
|
||||
if(e is Player && e.isWearingVoid(CombatStyle.RANGE)) {
|
||||
return 1.1
|
||||
return 1.2
|
||||
}
|
||||
}
|
||||
return 1.0
|
||||
|
||||
@@ -21,7 +21,7 @@ public enum ArmourSet {
|
||||
AHRIM(new Graphics(401, 96), new int[][] { { 4708, 4856, 4857, 4858, 4859 }, { 4710, 4862, 4863, 4864, 4865 }, { 4712, 4868, 4869, 4870, 4871 }, { 4714, 4874, 4875, 4876, 4877 } }) {
|
||||
@Override
|
||||
public boolean effect(Entity e, Entity victim, BattleState state) {
|
||||
if (RandomFunction.random(100) < 20) {
|
||||
if (RandomFunction.random(100) < 25 && state.getEstimatedHit() > -1) {
|
||||
victim.getSkills().updateLevel(Skills.STRENGTH, -5, 0);
|
||||
return true;
|
||||
}
|
||||
@@ -78,8 +78,8 @@ public enum ArmourSet {
|
||||
KARIL(new Graphics(400, 96), new int[][] { { 4732, 4928, 4929, 4930, 4931 }, { 4734, 4934, 4935, 4936, 4937 }, { 4736, 4940, 4941, 4942, 4943 }, { 4738, 4946, 4947, 4948, 4949 } }) {
|
||||
@Override
|
||||
public boolean effect(Entity e, Entity victim, BattleState state) {
|
||||
if (state.getEstimatedHit() > 9 && RandomFunction.random(100) < 20) {
|
||||
victim.getSkills().updateLevel(Skills.AGILITY, -(state.getEstimatedHit() / 10), 0);
|
||||
if (state.getEstimatedHit() > 0 && RandomFunction.random(100) < 25) {
|
||||
victim.getSkills().updateLevel(Skills.AGILITY, -(victim.getSkills().getDynamicLevels()[Skills.AGILITY] / 5), 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -100,7 +100,7 @@ public enum ArmourSet {
|
||||
TORAG(new Graphics(399, 96), new int[][] { { 4745, 4952, 4953, 4954, 4955 }, { 4747, 4958, 4959, 4960, 4961 }, { 4749, 4964, 4965, 4966, 4967 }, { 4751, 4970, 4971, 4972, 4973 } }) {
|
||||
@Override
|
||||
public boolean effect(Entity e, Entity victim, BattleState state) {
|
||||
if (state.getEstimatedHit() > 0 && RandomFunction.random(100) < 20) {
|
||||
if (state.getEstimatedHit() > 0 && RandomFunction.random(100) < 25) {
|
||||
if (victim instanceof Player) {
|
||||
((Player) victim).getSettings().updateRunEnergy(20);
|
||||
}
|
||||
|
||||
@@ -46,10 +46,11 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
|
||||
player.toggleDebug()
|
||||
}
|
||||
|
||||
define("calc_accuracy", Privilege.STANDARD, "::calc_accuracy <lt>NPC ID<gt>", "Calculates and prints your current chance to hit a given NPC."){ player, args ->
|
||||
define("calcaccuracy", Privilege.STANDARD, "::calcaccuracy <lt>NPC ID<gt>", "Calculates and prints your current chance to hit a given NPC."){ player, args ->
|
||||
val handler = player.getSwingHandler(false)
|
||||
player.sendMessage("handler type: ${handler.type}")
|
||||
player.sendMessage("calculateAccuracy: ${handler.calculateAccuracy(player)}")
|
||||
val accuracy = handler.calculateAccuracy(player)
|
||||
player.sendMessage("calculateAccuracy: ${accuracy}")
|
||||
|
||||
if (args.size > 1)
|
||||
{
|
||||
@@ -57,7 +58,14 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
|
||||
val npc = NPC(npcId)
|
||||
npc.initConfig()
|
||||
player.sendMessage("npc: ${npc.name}. npc defence: ${npc.skills.getLevel(Skills.DEFENCE)}")
|
||||
player.sendMessage("calculateDefence: ${handler.calculateDefence(npc, player)}")
|
||||
val defence = handler.calculateDefence(npc, player)
|
||||
player.sendMessage("calculateDefence: ${defence}")
|
||||
val chance: Double = if (accuracy > defence) {
|
||||
1.0 - ((defence + 2.0) / (2.0 * (accuracy + 1.0)))
|
||||
} else {
|
||||
accuracy / (2.0 * (defence + 1.0))
|
||||
}
|
||||
player.sendMessage("chance to hit: ${chance}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +115,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
|
||||
define("calcmaxhit", Privilege.STANDARD, "", "Calculates and shows you your current max hit.") { player, _ ->
|
||||
val swingHandler = player.getSwingHandler(false)
|
||||
val hit = swingHandler.calculateHit(player, player, 1.0)
|
||||
notify(player, "max hit (${(swingHandler as Object).getClass().getName()}): ${hit}")
|
||||
notify(player, "max hit: ${hit} (${(swingHandler as Object).getClass().getName()})")
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user