1+ package game.combat.npcHooks.dragons
2+
3+ import api.predef.*
4+ import engine.combat.prayer.CombatPrayer
5+ import game.item.consumable.potion.PotionEffect.Companion.hasAntiFire
6+ import game.player.Sound
7+ import io.luna.game.model.mob.Mob
8+ import io.luna.game.model.mob.Npc
9+ import io.luna.game.model.mob.Player
10+ import io.luna.game.model.mob.block.Animation
11+ import io.luna.game.model.mob.block.Graphic
12+ import io.luna.game.model.mob.combat.attack.MagicCombatAttack
13+ import io.luna.game.model.mob.combat.damage.CombatDamage
14+ import io.luna.game.model.mob.combat.damage.CombatDamageRequest
15+ import io.luna.game.model.mob.combat.damage.CombatDamageType
16+ import java.lang.Double.max
17+ import kotlin.math.floor
18+
19+ /* *
20+ * A dragonfire-based [MagicCombatAttack] used by dragons.
21+ *
22+ * Protection against this attack is calculated from a combination of:
23+ * - An anti-dragon shield
24+ * - An antifire potion
25+ * - Protect from Magic
26+ *
27+ * The total protection value is then used to reduce both the attack's effective
28+ * accuracy and maximum damage.
29+ *
30+ * @param attacker The dragon performing the attack.
31+ * @param victim The target of the attack.
32+ * @param maxHit The maximum damage before protection is applied.
33+ */
34+ class DragonFireCombatAttack (
35+ attacker : Npc ,
36+ victim : Mob ,
37+ private val maxHit : Int = 50
38+ ) : MagicCombatAttack<Npc>(
39+ attacker,
40+ victim,
41+ DRAGON_FIRE_CAST_ANIMATION ,
42+ DRAGON_FIRE_START_GRAPHIC ,
43+ null ,
44+ null ,
45+ Sound .DRAGONBREATH ,
46+ null ,
47+ attacker.combatDef().attackSpeed,
48+ 1
49+ ) {
50+
51+ companion object {
52+
53+ /* *
54+ * The standard anti-dragon shield item id.
55+ */
56+ val DRAGON_FIRE_SHIELD = 1540
57+
58+ /* *
59+ * The starting graphic displayed for the dragonfire attack.
60+ */
61+ val DRAGON_FIRE_START_GRAPHIC = Graphic (1 , 100 , 0 )
62+
63+ /* *
64+ * The cast animation used when the dragon breathes fire.
65+ */
66+ val DRAGON_FIRE_CAST_ANIMATION = Animation (81 )
67+ }
68+
69+ /* *
70+ * The total protection currently applied against this dragonfire attack.
71+ *
72+ * This value is built from the victim's active defensive sources during damage calculation.
73+ */
74+ private var protection = 0.0
75+
76+ /* *
77+ * Calculates the dragonfire damage against the supplied target.
78+ *
79+ * If the target is a player, the following protection values are added:
80+ * - Anti-dragon shield: 80%
81+ * - Antifire potion: 20%
82+ * - Protect from Magic: 40%
83+ *
84+ * The final protection value is used to reduce:
85+ * - Effective accuracy
86+ * - Resulting maximum hit
87+ *
88+ * @param other The target being evaluated for damage.
89+ * @return The resolved combat damage for this attack.
90+ */
91+ override fun calculateDamage (other : Mob ? ): CombatDamage {
92+ if (other is Player ) {
93+ protection + = if (other.equipment.shield?.id == DRAGON_FIRE_SHIELD ) 0.80 else 0.0
94+ protection + = if (other.hasAntiFire()) 0.20 else 0.0
95+ protection + = if (other.combat.prayers.isActive(CombatPrayer .PROTECT_FROM_MAGIC )) 0.40 else 0.0
96+ }
97+
98+ return CombatDamageRequest .Builder (attacker, victim, CombatDamageType .MAGIC )
99+ .setFlatBonusAccuracy(max(1.0 - protection, 0.0 ))
100+ .setBaseMaxHit((maxHit - floor(maxHit * protection).toInt()).coerceAtLeast(0 ))
101+ .ignoreProtectionPrayers()
102+ .build()
103+ .resolve()
104+ }
105+
106+ override fun onAttackArrived (damage : CombatDamage ? ) {
107+ if (damage != null && damage.amount.isPresent && victim is Player ) {
108+ if (protection >= 0.8 ) {
109+ victim.sendMessage(" Your shield absorbs most of the dragon fire!" )
110+ } else if (protection <= 0.2 ) {
111+ victim.sendMessage(" You're horribly burnt by the dragon fire!" )
112+ } else {
113+ victim.sendMessage(" You manage to resist some of the dragon fire!" )
114+ }
115+ }
116+ }
117+ }
0 commit comments