1
0
Fork 0

Fix Knife and add Defibrillator

This commit is contained in:
Moritz Ruth 2020-06-08 16:34:53 +02:00
parent adc51120c8
commit ccd269e4da
No known key found for this signature in database
GPG key ID: AFD57E23E753841B
10 changed files with 225 additions and 25 deletions

View file

@ -6,7 +6,7 @@ object ResourcePack {
object Items {
val textureless = Material.WHITE_STAINED_GLASS_PANE
val deathReason = Material.GRAY_STAINED_GLASS_PANE
val questionMark = Material.IRON_BLOCK
val questionMark = Material.GRASS_BLOCK
val time = Material.CLOCK
// Roles
@ -22,6 +22,7 @@ object ResourcePack {
val teleporter = Material.SPRUCE_WOOD
val martyrdomGrenade = Material.BIRCH_LOG
val fakeCorpse = Material.SPRUCE_LOG
val defibrillator = Material.IRON_INGOT
// Weapons
val deagle = Material.IRON_HOE

View file

@ -5,6 +5,7 @@ import de.moritzruth.spigot_ttt.game.players.Role
import de.moritzruth.spigot_ttt.plugin
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
import org.bukkit.event.Listener
import org.bukkit.event.inventory.InventoryClickEvent
import org.golde.bukkit.corpsereborn.CorpseAPI.events.CorpseClickEvent
@ -25,7 +26,7 @@ object CorpseListener: Listener {
}
}
@EventHandler
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)
fun onCorpseClick(event: CorpseClickEvent) {
// bug: always ClickType.UNKNOWN
// if (event.clickType !== ClickType.RIGHT) return

View file

@ -12,7 +12,6 @@ import de.moritzruth.spigot_ttt.utils.applyMeta
import de.moritzruth.spigot_ttt.utils.secondsToTicks
import org.bukkit.ChatColor
import org.bukkit.Location
import org.bukkit.entity.Player
import org.bukkit.event.inventory.InventoryType
import org.bukkit.inventory.ItemStack
import org.bukkit.scheduler.BukkitTask
@ -21,7 +20,7 @@ import org.golde.bukkit.corpsereborn.nms.Corpses
import java.time.Instant
class TTTCorpse private constructor(
private val player: Player,
val tttPlayer: TTTPlayer,
location: Location,
private val role: Role,
private val reason: DeathReason,
@ -29,8 +28,8 @@ class TTTCorpse private constructor(
) {
var status = Status.UNIDENTIFIED; private set
val corpse: Corpses.CorpseData?
val inventory = player.server.createInventory(null, InventoryType.HOPPER, "${role.chatColor}${player.displayName}")
val corpse: Corpses.CorpseData
val inventory = tttPlayer.player.server.createInventory(null, InventoryType.HOPPER, "${role.chatColor}${tttPlayer.player.displayName}")
val timestamp: Instant = Instant.now()
private var fullMinutesSinceDeath = 0
@ -44,7 +43,7 @@ class TTTCorpse private constructor(
setItems()
corpse = CorpseAPI.spawnCorpse(player, location)
corpse = CorpseAPI.spawnCorpse(tttPlayer.player, location)
updateTimeListener = plugin.server.scheduler.runTaskTimer(plugin, fun() {
fullMinutesSinceDeath += 1
@ -91,8 +90,9 @@ class TTTCorpse private constructor(
}
fun identify(tttPlayer: TTTPlayer, inspect: Boolean) {
ensureNotDestroyed()
if (status == Status.UNIDENTIFIED) {
GameMessenger.corpseIdentified(tttPlayer.player.displayName, player.displayName, role)
GameMessenger.corpseIdentified(tttPlayer.player.displayName, tttPlayer.player.displayName, role)
if (!inspect) {
status = Status.IDENTIFIED
@ -117,13 +117,25 @@ class TTTCorpse private constructor(
}
}
fun revive() {
ensureNotDestroyed()
tttPlayer.revive(corpse.trueLocation, credits)
destroy()
}
fun destroy() {
if (corpse !== null) CorpseAPI.removeCorpse(corpse)
status = Status.DESTROYED
CorpseAPI.removeCorpse(corpse)
updateTimeListener.cancel()
inventory.viewers.toSet().forEach { it.closeInventory() }
}
private fun ensureNotDestroyed() {
if (status == Status.DESTROYED) throw IllegalStateException("This corpse was destroyed")
}
enum class Status {
DESTROYED,
UNIDENTIFIED,
IDENTIFIED,
INSPECTED
@ -136,7 +148,7 @@ class TTTCorpse private constructor(
fun spawn(tttPlayer: TTTPlayer, reason: DeathReason) {
CorpseManager.add(TTTCorpse(
tttPlayer.player,
tttPlayer,
tttPlayer.player.location,
tttPlayer.role,
reason,
@ -144,9 +156,9 @@ class TTTCorpse private constructor(
))
}
fun spawnFake(role: Role, player: Player, location: Location) {
fun spawnFake(role: Role, tttPlayer: TTTPlayer, location: Location) {
CorpseManager.add(TTTCorpse(
player,
tttPlayer,
location,
role,
DeathReason.Item(Pistol),

View file

@ -1,5 +1,6 @@
package de.moritzruth.spigot_ttt.game.players
import de.moritzruth.spigot_ttt.TTTPlugin
import de.moritzruth.spigot_ttt.game.GameManager
import de.moritzruth.spigot_ttt.game.GamePhase
import de.moritzruth.spigot_ttt.game.corpses.TTTCorpse
@ -13,6 +14,7 @@ import de.moritzruth.spigot_ttt.utils.secondsToTicks
import de.moritzruth.spigot_ttt.utils.teleportPlayerToWorldSpawn
import org.bukkit.ChatColor
import org.bukkit.GameMode
import org.bukkit.Location
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.potion.PotionEffect
@ -89,11 +91,30 @@ class TTTPlayer(player: Player, role: Role) {
credits = 0
Shop.clear(this)
PlayerManager.letRemainingRoleGroupWin()
// PlayerManager.letRemainingRoleGroupWin()
plugin.server.pluginManager.callEvent(TTTPlayerDeathEvent(this, player.location))
}
fun revive(location: Location, credits: Int = 0) {
if (alive) throw AlreadyLivingException()
alive = true
this.credits = credits
player.health = 20.0
player.teleport(location)
Shop.setItems(this)
player.sendMessage(TTTPlugin.prefix + "${ChatColor.GREEN}${ChatColor.BOLD}Du wurdest wiederbelebt")
plugin.server.scheduler.runTask(plugin, fun() {
player.gameMode = GameMode.SURVIVAL
})
}
class AlreadyLivingException: Exception("The player already lives")
private fun adjustPlayer() {
player.scoreboard = scoreboard.scoreboard
}

View file

@ -29,7 +29,7 @@ object ItemManager {
BaseballBat,
CloakingDevice, Rifle,
EnderPearl, Radar, HealingPotion, Fireball,
Teleporter, MartyrdomGrenade, FakeCorpse
Teleporter, MartyrdomGrenade, FakeCorpse, Defibrillator
)
val droppedItemStates = mutableMapOf<Int, IState>()

View file

@ -0,0 +1,152 @@
package de.moritzruth.spigot_ttt.items.impl
import com.connorlinfoot.actionbarapi.ActionBarAPI
import de.moritzruth.spigot_ttt.ResourcePack
import de.moritzruth.spigot_ttt.game.corpses.CorpseManager
import de.moritzruth.spigot_ttt.game.players.*
import de.moritzruth.spigot_ttt.items.Buyable
import de.moritzruth.spigot_ttt.items.TTTItem
import de.moritzruth.spigot_ttt.items.isRelevant
import de.moritzruth.spigot_ttt.plugin
import de.moritzruth.spigot_ttt.utils.*
import org.bukkit.ChatColor
import org.bukkit.boss.BarColor
import org.bukkit.boss.BarStyle
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.inventory.ItemStack
import org.bukkit.scheduler.BukkitTask
import org.golde.bukkit.corpsereborn.CorpseAPI.events.CorpseClickEvent
import java.time.Duration
import java.time.Instant
object Defibrillator: TTTItem, Buyable {
private const val REVIVE_DURATION = 10.0
override val type = TTTItem.Type.SPECIAL
override val itemStack = ItemStack(ResourcePack.Items.defibrillator).applyMeta {
setDisplayName("${ChatColor.RESET}${ChatColor.BOLD}Defibrillator")
hideInfo()
lore = listOf(
"",
"${ChatColor.GOLD}Belebe einen Spieler wieder"
)
}
override val buyableBy = roles(Role.TRAITOR, Role.DETECTIVE, Role.JACKAL)
override val price = 2
override val buyLimit = 1
private val isc = InversedStateContainer(State::class)
override val listener = object : Listener {
@EventHandler
fun onPlayerInteract(event: PlayerInteractEvent) {
if (event.isRelevant(Defibrillator)) event.isCancelled = true
}
@EventHandler
fun onCorpseClick(event: CorpseClickEvent) {
val tttPlayer = PlayerManager.getTTTPlayer(event.clicker) ?: return
if (tttPlayer.player.inventory.itemInMainHand.type != itemStack.type) return
val tttCorpse = CorpseManager.getTTTCorpse(event.corpse) ?: return
event.isCancelled = true
val state = isc.getOrCreate(tttPlayer)
state.bossBar.addPlayer(tttPlayer.player)
when(val action = state.action) {
null -> state.action = Action.Reviving(tttPlayer, state)
is Action.Reviving -> {
action.cancelTask.cancel()
action.cancelTask = action.createCancelTask()
val progress = action.duration / REVIVE_DURATION
if (progress >= 1) {
try {
tttCorpse.revive()
ActionBarAPI.sendActionBar(
tttPlayer.player,
"${ChatColor.BOLD}${tttCorpse.tttPlayer.player.displayName} " +
"${ChatColor.GREEN}wurde wiederbelebt"
)
action.cancelTask.cancel()
tttPlayer.player.inventory.removeTTTItemNextTick(Defibrillator)
state.reset(tttPlayer)
isc.remove(tttPlayer)
} catch(e: TTTPlayer.AlreadyLivingException) {
// do not cancel the cancelTask
}
} else state.bossBar.progress = progress
}
is Action.Canceled -> noop()
}
}
}
sealed class Action(val tttPlayer: TTTPlayer) {
open fun reset() {}
class Reviving(tttPlayer: TTTPlayer, val state: State): Action(tttPlayer) {
var cancelTask = createCancelTask()
private val startedAt: Instant = Instant.now()
val duration get() = Duration.between(startedAt, Instant.now()).toMillis().toDouble() / 1000
fun createCancelTask() = plugin.server.scheduler.runTaskLater(plugin, fun() {
state.action = Canceled(tttPlayer)
}, 10)
init {
state.bossBar.color = BarColor.GREEN
state.bossBar.addPlayer(tttPlayer.player)
}
override fun reset() = cancelTask.cancel()
}
class Canceled(tttPlayer: TTTPlayer): Action(tttPlayer) {
private var switches: Int = 0
private lateinit var task: BukkitTask
init {
task = plugin.server.scheduler.runTaskTimer(plugin, fun() {
val state = isc.get(tttPlayer) ?: return@runTaskTimer
if (switches == SWITCHES_COUNT) {
task.cancel()
state.action = null
state.bossBar.removePlayer(tttPlayer.player)
} else {
state.bossBar.progress = 1.0
state.bossBar.color = if (switches % 2 == 0) BarColor.RED else BarColor.WHITE
switches += 1
}
}, 0, secondsToTicks(0.2).toLong())
}
override fun reset() = task.cancel()
companion object {
const val SWITCHES_COUNT = 6
}
}
}
class State: IState {
var action: Action? = null
var bossBar = plugin.server.createBossBar(
"${ChatColor.BOLD}Defibrillator",
BarColor.GREEN,
BarStyle.SOLID
)
override fun reset(tttPlayer: TTTPlayer) {
bossBar.removePlayer(tttPlayer.player)
action?.reset()
}
}
}

View file

@ -1,5 +1,6 @@
package de.moritzruth.spigot_ttt.items.impl
import com.connorlinfoot.actionbarapi.ActionBarAPI
import de.moritzruth.spigot_ttt.ResourcePack
import de.moritzruth.spigot_ttt.game.corpses.TTTCorpse
import de.moritzruth.spigot_ttt.game.players.*
@ -10,6 +11,7 @@ import de.moritzruth.spigot_ttt.plugin
import de.moritzruth.spigot_ttt.utils.applyMeta
import de.moritzruth.spigot_ttt.utils.hideInfo
import de.moritzruth.spigot_ttt.utils.isRightClick
import de.moritzruth.spigot_ttt.utils.removeTTTItem
import org.bukkit.ChatColor
import org.bukkit.Material
import org.bukkit.entity.Player
@ -117,11 +119,16 @@ object FakeCorpse: TTTItem, Buyable {
state.choosePlayerInventory -> {
tttPlayer.player.closeInventory()
val player = plugin.server.getPlayer((item.itemMeta as SkullMeta).owningPlayer!!.uniqueId)!!
TTTCorpse.spawnFake(state.chosenRole!!, player, tttPlayer.player.location)
val corpsePlayer = plugin.server.getPlayer((item.itemMeta as SkullMeta).owningPlayer!!.uniqueId)!!
val corpseTTTPlayer = PlayerManager.getTTTPlayer(corpsePlayer)
val itemIndex = tttPlayer.player.inventory.indexOfFirst { it.type == itemStack.type }
tttPlayer.player.inventory.clear(itemIndex)
if (corpseTTTPlayer == null) {
ActionBarAPI.sendActionBar(tttPlayer.player, "${ChatColor.RED}Das hat nicht funktioniert")
} else {
TTTCorpse.spawnFake(state.chosenRole!!, corpseTTTPlayer, tttPlayer.player.location)
tttPlayer.player.inventory.removeTTTItem(FakeCorpse)
}
}
}
}

View file

@ -12,7 +12,6 @@ import de.moritzruth.spigot_ttt.utils.createKillExplosion
import de.moritzruth.spigot_ttt.utils.hideInfo
import de.moritzruth.spigot_ttt.utils.secondsToTicks
import org.bukkit.ChatColor
import org.bukkit.Sound
import org.bukkit.SoundCategory
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
@ -71,7 +70,7 @@ object MartyrdomGrenade: TTTItem, Buyable {
state.explodeTask = plugin.server.scheduler.runTaskLater(plugin, fun() {
GameManager.world.playSound(
event.location,
Sound.ENTITY_GENERIC_EXPLODE,
ResourcePack.Sounds.grenadeExplode,
SoundCategory.PLAYERS,
1F,
1F

View file

@ -6,10 +6,7 @@ import de.moritzruth.spigot_ttt.items.Buyable
import de.moritzruth.spigot_ttt.items.TTTItem
import de.moritzruth.spigot_ttt.items.isRelevant
import de.moritzruth.spigot_ttt.items.weapons.LoreHelper
import de.moritzruth.spigot_ttt.utils.applyMeta
import de.moritzruth.spigot_ttt.utils.clearHeldItemSlot
import de.moritzruth.spigot_ttt.utils.hideInfo
import de.moritzruth.spigot_ttt.utils.isLeftClick
import de.moritzruth.spigot_ttt.utils.*
import org.bukkit.ChatColor
import org.bukkit.Sound
import org.bukkit.SoundCategory
@ -60,6 +57,9 @@ object Knife: TTTItem, Buyable {
if (distance > 1.5) event.isCancelled = true else {
damagedTTTPlayer.damageInfo = DamageInfo(damagerTTTPlayer, DeathReason.Item(Knife))
event.damage = 1000.0
damagerTTTPlayer.player.playSound(damagerTTTPlayer.player.location, Sound.ENTITY_ITEM_BREAK, SoundCategory.PLAYERS, 1F, 1F)
damagerTTTPlayer.player.inventory.removeTTTItemNextTick(Knife)
}
}
}

View file

@ -1,5 +1,7 @@
package de.moritzruth.spigot_ttt.utils
import de.moritzruth.spigot_ttt.items.TTTItem
import de.moritzruth.spigot_ttt.plugin
import org.bukkit.inventory.Inventory
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.PlayerInventory
@ -8,6 +10,11 @@ fun Inventory.setAllToItem(indexes: Iterable<Int>, itemStack: ItemStack) {
indexes.forEach { setItem(it, itemStack) }
}
fun Inventory.removeTTTItem(tttItem: TTTItem) = clear(indexOfFirst { it.type == tttItem.itemStack.type })
fun Inventory.removeTTTItemNextTick(tttItem: TTTItem) = plugin.server.scheduler.runTask(plugin, fun() {
removeTTTItem(tttItem)
})
fun PlayerInventory.clearHeldItemSlot() = clear(heldItemSlot)
val PlayerInventory.hotbarContents get() = this.contents.slice(0..8) as List<ItemStack?>