Skip to content

Commit b7e5d07

Browse files
committed
target laser
Fixes #22
1 parent 3848846 commit b7e5d07

File tree

4 files changed

+226
-4
lines changed

4 files changed

+226
-4
lines changed
Lines changed: 206 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,215 @@
11
package dev.betrix.superSmashMobsBrawl.abilities
22

3-
import dev.betrix.superSmashMobsBrawl.extensions.sendDebugMessage
3+
import dev.betrix.superSmashMobsBrawl.disguises.GuardianDisguise
4+
import dev.betrix.superSmashMobsBrawl.events.BrawlDamageEvent
5+
import dev.betrix.superSmashMobsBrawl.events.BrawlDamageType
6+
import dev.betrix.superSmashMobsBrawl.events.BrawlDeathEvent
7+
import dev.betrix.superSmashMobsBrawl.events.Damager
8+
import dev.betrix.superSmashMobsBrawl.extensions.disguise
9+
import dev.betrix.superSmashMobsBrawl.extensions.event
10+
import dev.betrix.superSmashMobsBrawl.extensions.isOnBlock
11+
import gg.flyte.twilight.event.event
12+
import gg.flyte.twilight.extension.getNearbyEntities
13+
import gg.flyte.twilight.scheduler.TwilightRunnable
14+
import gg.flyte.twilight.scheduler.repeatingTask
15+
import org.bukkit.Effect
16+
import org.bukkit.Material
17+
import org.bukkit.Particle
418
import org.bukkit.entity.Player
519

620
class TargetLaserAbility(player: Player) : BrawlAbility("target_laser", player) {
21+
22+
private val maxRange: Double = metadata.double("maxRange") ?: 11.0
23+
private val damageIncrease: Double = metadata.double("damageIncrease") ?: 2.0
24+
private val knockbackIncreaseMultiplier: Double =
25+
metadata.double("knockbackIncreaseMultiplier") ?: 1.25
26+
private val maxTimeMs: Long = (metadata.long("maxTimeMs") ?: 8000L).coerceAtLeast(0L)
27+
private val breakDamagePerSecond: Double = metadata.double("breakDamagePerSecond") ?: 0.5
28+
29+
private var targetPlayer: Player? = null
30+
private var laserTask: TwilightRunnable? = null
31+
32+
override fun setup() {
33+
super.setup()
34+
35+
listeners.add(
36+
event<BrawlDamageEvent> {
37+
val target = targetPlayer ?: return@event
38+
39+
if (victim != target) {
40+
return@event
41+
}
42+
43+
val attackerLivingEntity =
44+
(damager as? Damager.DamagerLivingEntity)?.livingEntity ?: return@event
45+
46+
if (attackerLivingEntity != this@TargetLaserAbility.player) {
47+
return@event
48+
}
49+
50+
damage += damageIncrease
51+
knockbackMultiplier *= knockbackIncreaseMultiplier
52+
53+
target.world.playEffect(
54+
target.location.add(0.0, 0.5, 0.0),
55+
Effect.STEP_SOUND,
56+
Material.REDSTONE_BLOCK,
57+
)
58+
}
59+
)
60+
61+
listeners.add(
62+
event<BrawlDeathEvent> {
63+
val target = targetPlayer ?: return@event
64+
65+
if (player != target) {
66+
return@event
67+
}
68+
69+
setCooldown(0)
70+
stopLaser()
71+
}
72+
)
73+
}
74+
75+
override fun canActivate(sendMessage: Boolean): Boolean {
76+
if (!super.canActivate(sendMessage)) {
77+
return false
78+
}
79+
80+
if (targetPlayer != null) {
81+
if (sendMessage) {
82+
player.sendMessage(
83+
lang.t("messages.abilities.targetLaser.alreadyTargeting") {
84+
"abilityId" to id
85+
}
86+
)
87+
}
88+
return false
89+
}
90+
91+
if (!player.isOnBlock()) {
92+
if (sendMessage) {
93+
player.sendMessage(
94+
lang.t("messages.abilities.targetLaser.mustBeOnGround") {
95+
"abilityId" to id
96+
}
97+
)
98+
}
99+
return false
100+
}
101+
102+
return true
103+
}
104+
7105
override fun activate() {
106+
val target = findNearestTarget()
107+
108+
if (target == null) {
109+
player.sendMessage(
110+
lang.t("messages.abilities.targetLaser.noTargetsInRange") { "abilityId" to id }
111+
)
112+
return
113+
}
114+
8115
super.activate()
9-
player.sendDebugMessage("Target Laser ability pending implementation")
116+
targetPlayer = target
117+
setGuardianTarget(target)
118+
119+
player.sendMessage(
120+
lang.t("messages.abilities.targetLaser.targeted") {
121+
"abilityId" to id
122+
"target" to target.name
123+
}
124+
)
125+
target.sendMessage(
126+
lang.t("messages.abilities.targetLaser.targetedBy") {
127+
"abilityId" to id
128+
"attacker" to player.name
129+
}
130+
)
131+
132+
startLaserTask()
133+
}
134+
135+
override fun teardown() {
136+
stopLaser()
137+
super.teardown()
138+
}
139+
140+
private fun findNearestTarget(): Player? {
141+
val minigame = minigameService.getMinigameForPlayer(player) ?: return null
142+
143+
return player.location
144+
.getNearbyEntities(maxRange, maxRange, maxRange)
145+
.filterIsInstance<Player>()
146+
.filter { it != player }
147+
.filter { !minigame.arePlayersOnSameTeam(player, it) }
148+
.filter { it.location.distance(player.location) <= maxRange }
149+
.minByOrNull { it.location.distance(player.location) }
150+
}
151+
152+
private fun startLaserTask() {
153+
laserTask?.cancel()
154+
val activationTime = lastUsed
155+
156+
laserTask =
157+
repeatingTask(0, 5) {
158+
val target = targetPlayer
159+
if (target == null || !target.isValid || !target.isOnline) {
160+
stopLaser()
161+
cancel()
162+
return@repeatingTask
163+
}
164+
165+
Particle.ENCHANTED_HIT
166+
.builder()
167+
.location(target.location.add(0.0, 0.5, 0.0))
168+
.offset(0.5, 1.0, 0.5)
169+
.count(10)
170+
.extra(0.1)
171+
.receivers(96, true)
172+
.spawn()
173+
174+
val timeElapsed = System.currentTimeMillis() - activationTime
175+
val distance = player.location.distance(target.location)
176+
177+
if (distance > maxRange || timeElapsed >= maxTimeMs) {
178+
val seconds = timeElapsed / 1000.0
179+
val breakDamage = breakDamagePerSecond * seconds
180+
181+
player.sendMessage(
182+
lang.t("messages.abilities.targetLaser.laserBroke") {
183+
"abilityId" to id
184+
"target" to target.name
185+
}
186+
)
187+
188+
BrawlDamageEvent(
189+
target,
190+
Damager.DamagerLivingEntity(player),
191+
breakDamage,
192+
0.0,
193+
BrawlDamageType.Explosion,
194+
)
195+
.callEvent()
196+
197+
stopLaser()
198+
cancel()
199+
}
200+
}
201+
202+
laserTask?.let { runnables.add(it) }
203+
}
204+
205+
private fun stopLaser() {
206+
laserTask?.cancel()
207+
laserTask = null
208+
setGuardianTarget(null)
209+
targetPlayer = null
210+
}
211+
212+
private fun setGuardianTarget(target: Player?) {
213+
(player.disguise as? GuardianDisguise)?.setTarget(target)
10214
}
11215
}

plugin/src/main/kotlin/dev/betrix/superSmashMobsBrawl/disguises/GuardianDisguise.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,15 @@ package dev.betrix.superSmashMobsBrawl.disguises
33
import dev.betrix.superSmashMobsBrawl.models.Hitbox
44
import me.libraryaddict.disguise.disguisetypes.DisguiseType
55
import me.libraryaddict.disguise.disguisetypes.MobDisguise
6+
import me.libraryaddict.disguise.disguisetypes.watchers.GuardianWatcher
7+
import org.bukkit.entity.Entity
68
import org.bukkit.entity.Player
79

810
class GuardianDisguise(player: Player) : BrawlDisguise(player) {
911
override val disguise = MobDisguise(DisguiseType.GUARDIAN)
1012
override val hitbox = Hitbox(0.85, 0.85)
13+
14+
fun setTarget(target: Entity?) {
15+
(disguise.watcher as? GuardianWatcher)?.setTarget(target)
16+
}
1117
}

plugin/src/main/resources/data/abilities.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,12 @@ abilities:
272272
usage: right_click
273273
hotbarItem: iron_sword
274274
displayItem: prismarine_crystals
275-
metadata: {}
275+
metadata:
276+
maxRange: 11.0
277+
damageIncrease: 2.0
278+
knockbackIncreaseMultiplier: 1.25
279+
maxTimeMs: 8000
280+
breakDamagePerSecond: 0.5
276281

277282
- id: blizzard
278283
cooldown: 0.0

plugin/src/main/resources/data/lang/en.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ abilities:
114114
description: "Burst upward on a wave of water to recover and reposition"
115115
target_laser:
116116
name: "Target Laser"
117-
description: "Charge a focused beam that scorches enemies in front of you"
117+
description: "Lock onto a foe with your laser to amplify damage and knockback"
118118
slime_rocket:
119119
name: "Slime Rocket"
120120
description: "Launch a sticky slime shot that detonates on contact"
@@ -183,6 +183,13 @@ messages:
183183
cooldown: "{lang:prefix} <warning>{lang:abilities.{abilityId}.name}</warning> <text>is on cooldown for</text> <yellow>{seconds}s</yellow>!"
184184
explode:
185185
alreadyCharging: "{lang:prefix} <warning>Already charging explosion!</warning>"
186+
targetLaser:
187+
alreadyTargeting: "{lang:prefix} <warning>Already targeting a player!</warning>"
188+
mustBeOnGround: "{lang:prefix} <warning>You must be on the ground to use {lang:abilities.{abilityId}.name}!</warning>"
189+
noTargetsInRange: "{lang:prefix} <warning>No targets within range!</warning>"
190+
targeted: "{lang:prefix} <text>You targeted <primary>{target}</primary> <text>with <primary>{lang:abilities.{abilityId}.name}"
191+
targetedBy: "{lang:prefix} <warning>{attacker}</warning> <text>targeted you with their <warning>{lang:abilities.{abilityId}.name}"
192+
laserBroke: "{lang:prefix} <text>Your laser broke, dealing damage to <primary>{target}"
186193
kits:
187194
select:
188195
success: "{lang:prefix} <text>You have selected kit <primary>{lang:kits.{kitId}.name}"

0 commit comments

Comments
 (0)