summaryrefslogtreewikicommitdiff
path: root/core/src/events/onDamage.kt
blob: 84e29ddd5036119b1c7b8f7dba8deb6de53e49ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package cat.freya.khs.event

import cat.freya.khs.Khs
import cat.freya.khs.game.Game
import cat.freya.khs.player.Player

data class DamageEvent(
    val plugin: Khs,
    val player: Player,
    val attacker: Player?,
    val damage: Double,
) : Event()

/// handles when a player in the game is damaged
fun onDamage(event: DamageEvent) {
    val (plugin, player, attacker, damage) = event
    val game = plugin.game

    // make sure that the attacker (if exists) is allowed to damage us
    if (attacker != null) {
        // players must both be in the game
        if (
            (game.hasPlayer(player) && !game.hasPlayer(attacker)) ||
                (game.hasPlayer(attacker) && !game.hasPlayer(player))
        ) {
            event.cancel()
            return
        }

        // players cant be on the same team
        if (game.sameTeam(player.uuid, attacker.uuid)) {
            event.cancel()
            return
        }

        // cannot attack spectators
        if (game.isSpectator(player) || game.isSpectator(attacker)) {
            event.cancel()
            return
        }

        // ignore if pvp is diabled, and a hider is trying to attack a seeker
        if (!plugin.config.pvp && game.isHider(attacker) && game.isSeeker(player)) {
            event.cancel()
            return
        }
        // if there is no attacker, and the player is not in game, we do not care
    } else if (!game.hasPlayer(player)) {
        return
        // if there is no attacker, it most of been by natural causes...
        // if pvp is disabled, and config doesn't allow natural causes, cancel event
    } else if (!plugin.config.pvp && !plugin.config.allowNaturalCauses) {
        event.cancel()
        return
    }

    // spectators cannot take damage
    if (game.isSpectator(player)) {
        event.cancel()
        val world = player.world ?: return
        if (player.location.y < world.minY) {
            // make sure they dont try to kill them self to the void lol
            game.map?.gameSpawn?.teleport(player)
        }
    }

    // cant take damage until seeking
    if (game.status != Game.Status.SEEKING) {
        event.cancel()
        return
    }

    // check if player dies (pvp mode)
    // if not then it is fine (if so we need to handle it)
    if (plugin.config.pvp && player.health - damage >= 0.5) return

    /* handle death event (player was tagged or killed in pvp) */
    event.cancel()

    // play death sound
    player.playSound(
        if (plugin.shim.supports(9)) "ENTITY_PLAYER_DEATH" else "ENTITY_PLAYER_HURT",
        1.0,
        1.0,
    )

    // reveal a player if their disguised
    player.revealDisguise()

    // respawn player
    if (plugin.config.delayedRespawn.enabled && !plugin.config.respawnAsSpectator) {
        val time = plugin.config.delayedRespawn.delay
        game.map?.seekerLobbySpawn?.teleport(player)
        player.message(plugin.locale.prefix.default + plugin.locale.game.respawn.with(time))
        plugin.shim.scheduleEvent(time * 20UL) {
            if (game.status == Game.Status.SEEKING) game.map?.gameSpawn?.teleport(player)
        }
    } else {
        game.map?.gameSpawn?.teleport(player)
    }

    // update leaderboard
    game.addDeath(player.uuid)
    if (attacker != null) game.addKill(attacker.uuid)

    // broadcast death and update team
    if (game.isSeeker(player)) {
        game.broadcast(plugin.locale.game.player.death.with(player.name))
        game.resetPlayer(player)
        game.giveSeekerItems(player)
    } else {
        val msg =
            if (attacker == null) {
                plugin.locale.game.player.found.with(player.name)
            } else {
                plugin.locale.game.player.foundBy.with(player.name, attacker.name)
            }
        game.broadcast(msg)

        // reset player team and items
        if (plugin.config.respawnAsSpectator) {
            game.setTeam(player.uuid, Game.Team.SPECTATOR)
            game.loadSpectator(player)
        } else {
            game.setTeam(player.uuid, Game.Team.SEEKER)
            game.resetPlayer(player)
            game.giveSeekerItems(player)
        }
    }
}