1+ package game.combat.npcHooks
2+
3+ import api.combat.npc.NpcCombatHandler.combat
4+ import api.predef.*
5+ import game.player.Sound
6+ import io.luna.game.model.LocalProjectile
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.Animation.AnimationPriority
12+ import io.luna.game.model.mob.block.Graphic
13+ import io.luna.game.model.mob.combat.attack.MagicCombatAttack
14+ import io.luna.game.model.mob.combat.damage.CombatDamage
15+ import io.luna.game.model.mob.combat.damage.CombatDamageRequest
16+ import io.luna.game.model.mob.combat.damage.CombatDamageType
17+
18+ /* *
19+ * The wearable nose peg item id.
20+ */
21+ val NOSE_PEG = 4168
22+
23+ /* *
24+ * The cast animation used by aberrant spectres for their magic attack.
25+ */
26+ val CAST_ANIMATION = Animation (1507 , AnimationPriority .HIGH )
27+
28+ /* *
29+ * The starting graphic displayed when the attack is cast.
30+ */
31+ val START_GRAPHIC = Graphic (334 , 600 , 0 )
32+
33+ /* *
34+ * Creates the aberrant spectre magic projectile.
35+ */
36+ val MAGIC_PROJECTILE : (Mob , Mob ) -> LocalProjectile = { mob, other ->
37+ // TODO Projectile looks a bit off.
38+ LocalProjectile .followEntity(ctx)
39+ .setSourceEntity(mob)
40+ .setTargetEntity(other)
41+ .setId(335 )
42+ .setTicksToStart(44 )
43+ .setTicksToEnd(3 )
44+ .setStartHeight(43 )
45+ .setEndHeight(31 )
46+ .setInitialSlope(0 )
47+ .build()
48+ }
49+
50+ /* *
51+ * The ending graphic displayed when the projectile reaches the victim.
52+ */
53+ val END_GRAPHIC = Graphic (336 , 500 , 0 )
54+
55+ /* *
56+ * Handles the aberrant spectre special magic attack.
57+ *
58+ * Victims wearing a nose peg take a normal magic hit. Victims without a nose peg take a magic hit that ignores
59+ * protection prayers, and may also have one or more combat-related skills reduced when the projectile lands.
60+ *
61+ * @author lare96
62+ */
63+ class AberrantSpectreMagicAttack (attacker : Npc , victim : Mob ) : MagicCombatAttack<Npc>(
64+ attacker,
65+ victim,
66+ CAST_ANIMATION ,
67+ START_GRAPHIC ,
68+ MAGIC_PROJECTILE ,
69+ END_GRAPHIC ,
70+ Sound .GOO_HIT ,
71+ null ,
72+ attacker.combatDef().attackSpeed,
73+ 6 ) {
74+
75+ /* *
76+ * Whether the victim is protected by a nose peg.
77+ */
78+ private val protected = victim is Player && victim.equipment.head?.id == NOSE_PEG
79+
80+ override fun calculateDamage (other : Mob ? ): CombatDamage {
81+ val request = CombatDamageRequest .builder(attacker, victim, CombatDamageType .MAGIC )
82+
83+ if (! protected) {
84+ // 25% Increased accuracy and ignores prayer when not wearing nose peg.
85+ request.setFlatBonusAccuracy(0.25 )
86+ request.ignoreProtectionPrayers()
87+ }
88+
89+ return request.build().resolve()
90+ }
91+
92+ override fun onDamageApplied (damage : CombatDamage ? ) {
93+ // Weakens the player when not wearing a nose peg.
94+ if (! protected && victim is Player ) {
95+ if (randBoolean()) {
96+ victim.attack.adjustLevel(- rand(10 , 20 ))
97+ }
98+ if (randBoolean()) {
99+ victim.strength.adjustLevel(- rand(10 , 20 ))
100+ }
101+ if (randBoolean()) {
102+ victim.defence.adjustLevel(- rand(10 , 20 ))
103+ }
104+ if (randBoolean()) {
105+ victim.ranged.adjustLevel(- rand(10 , 20 ))
106+ }
107+ if (randBoolean()) {
108+ victim.magic.adjustLevel(- rand(10 , 20 ))
109+ }
110+ victim.sendMessage(" You have been weakened." )
111+ }
112+ }
113+ }
114+
115+ // Registers aberrant spectre magic behaviour for all aberrant spectre npc variants.
116+ combat(1604 , 1605 , 1606 , 1607 ) {
117+ attack { AberrantSpectreMagicAttack (npc, other) }
118+ }
0 commit comments