1
0
Fork 0

Add classes

This commit is contained in:
Moritz Ruth 2020-06-14 13:42:39 +02:00
parent 258673c241
commit 8c9dc40350
No known key found for this signature in database
GPG key ID: AFD57E23E753841B
26 changed files with 371 additions and 172 deletions

View file

@ -4,11 +4,13 @@ import de.moritzruth.spigot_ttt.game.GameManager
import org.bukkit.ChatColor
import org.bukkit.GameMode
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.block.Action
import org.bukkit.event.block.BlockBreakEvent
import org.bukkit.event.block.BlockPlaceEvent
import org.bukkit.event.entity.EntityDamageEvent
import org.bukkit.event.entity.FoodLevelChangeEvent
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.player.PlayerJoinEvent
@ -81,6 +83,13 @@ object TTTListener: Listener {
event.quitMessage = "${TTTPlugin.prefix}${event.player.displayName} ${ChatColor.GOLD}hat das Spiel verlassen."
}
@EventHandler
fun onEntityDamage(event: EntityDamageEvent) {
if (GameManager.phase == null && event.entity is Player) {
event.isCancelled = true
}
}
@EventHandler
fun onFoodLevelChange(event: FoodLevelChangeEvent) {
if (GameManager.phase == null) event.isCancelled = true

View file

@ -17,6 +17,7 @@ class TTTPlugin: JavaPlugin() {
TTTListener.register()
// This is required to prevent a lot of bugs
server.spawnRadius = 0
}

View file

@ -2,7 +2,6 @@ package de.moritzruth.spigot_ttt.game
import com.comphenix.packetwrapper.WrapperPlayServerPlayerInfo
import com.comphenix.protocol.PacketType
import com.comphenix.protocol.ProtocolLibrary
import com.comphenix.protocol.events.PacketAdapter
import com.comphenix.protocol.events.PacketEvent
import com.comphenix.protocol.wrappers.EnumWrappers
@ -26,11 +25,6 @@ import java.util.*
object GameListener : Listener {
private val BLOCKED_COMMANDS = setOf("me", "tell")
fun register() {
plugin.server.pluginManager.registerEvents(this, plugin)
ProtocolLibrary.getProtocolManager().addPacketListener(packetListener)
}
@EventHandler
fun onPlayerJoin(event: PlayerJoinEvent) = PlayerManager.onPlayerJoin(event.player)
@ -73,14 +67,10 @@ object GameListener : Listener {
EntityDamageEvent.DamageCause.ENTITY_SWEEP_ATTACK,
EntityDamageEvent.DamageCause.FALLING_BLOCK,
EntityDamageEvent.DamageCause.SUICIDE
)
)!!
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
fun onEntityDamageLow(event: EntityDamageEvent) {
if (GameManager.phase !== GamePhase.COMBAT) {
event.isCancelled = true
}
if (ZERO_NO_DAMAGE_TICKS_CAUSES.contains(event.cause)) {
val player = event.entity
if (player is Player) {
@ -93,14 +83,9 @@ object GameListener : Listener {
fun onEntityDamageHighest(event: EntityDamageEvent) {
if (event.entity !is Player) return
val tttPlayer = TTTPlayer.of(event.entity as Player) ?: return
if (event.cause == EntityDamageEvent.DamageCause.CUSTOM) return
if (tttPlayer.player.health - event.finalDamage <= 0) {
val damageInfo = tttPlayer.damageInfo
if (damageInfo != null && damageInfo.expectedDamageCause == event.cause) {
tttPlayer.damageInfo = null
tttPlayer.onDeath(damageInfo.deathReason, damageInfo.damager, damageInfo.scream)
} else {
val reason = when (event.cause) {
EntityDamageEvent.DamageCause.FALL -> DeathReason.FALL
EntityDamageEvent.DamageCause.BLOCK_EXPLOSION,
@ -115,7 +100,6 @@ object GameListener : Listener {
}
tttPlayer.onDeath(reason, null)
}
event.damage = 0.0
}
@ -145,7 +129,7 @@ object GameListener : Listener {
}
@EventHandler(priority = EventPriority.HIGHEST)
fun onTTTPlayerDeath(event: TTTPlayerDeathEvent) {
fun onTTTPlayerTrueDeath(event: TTTPlayerTrueDeathEvent) {
if (!setOf(RoleGroup.JACKAL, null).contains(event.winnerRoleGroup) && event.tttPlayer.role == Role.JACKAL) {
val sidekicks = PlayerManager.tttPlayers.filter { it.role == Role.SIDEKICK }
@ -162,7 +146,7 @@ object GameListener : Listener {
}
}
private val packetListener = object : PacketAdapter(plugin, PacketType.Play.Server.PLAYER_INFO) {
val packetListener = object : PacketAdapter(plugin, PacketType.Play.Server.PLAYER_INFO) {
override fun onPacketSending(event: PacketEvent) {
val packet = WrapperPlayServerPlayerInfo(event.packet)

View file

@ -1,6 +1,8 @@
package de.moritzruth.spigot_ttt.game
import com.comphenix.protocol.ProtocolLibrary
import de.moritzruth.spigot_ttt.Settings
import de.moritzruth.spigot_ttt.game.classes.TTTClassManager
import de.moritzruth.spigot_ttt.game.corpses.CorpseListener
import de.moritzruth.spigot_ttt.game.corpses.CorpseManager
import de.moritzruth.spigot_ttt.game.items.ItemManager
@ -28,13 +30,20 @@ object GameManager {
val destroyedBlocks = mutableMapOf<Location, Material>()
private val listeners = ItemManager.listeners
.plus(GameListener)
.plus(ShopListener)
.plus(CorpseListener)
.plus(TTTClassManager.listeners)
private val packetListeners = ItemManager.packetListeners
.plus(GameListener.packetListener)
fun initialize() {
adjustWorld()
ItemManager.registerListeners()
GameListener.register()
ShopListener.register()
CorpseListener.register()
listeners.forEach { plugin.server.pluginManager.registerEvents(it, plugin) }
packetListeners.forEach { ProtocolLibrary.getProtocolManager().addPacketListener(it) }
}
fun letRoleWin(role: Role?) {
@ -129,9 +138,9 @@ object GameManager {
PlayerManager.createTTTPlayers()
PlayerManager.tttPlayers.forEach {
it.reset()
it.player.teleportToWorldSpawn()
it.activateStamina()
it.addDefaultClassItems()
}
GameMessenger.preparingPhaseStarted()
@ -145,9 +154,15 @@ object GameManager {
private fun startCombatPhase() {
ensurePhase(GamePhase.PREPARING)
phase = GamePhase.COMBAT
PlayerManager.tttPlayers.forEach { Shop.setItems(it) }
PlayerManager.tttPlayers.forEach {
Shop.setItems(it)
if (!it.alive) {
it.revive(world.spawnLocation, Settings.initialCredits)
}
}
ScoreboardHelper.forEveryScoreboard { it.updateTeams() }
Timers.playTimerSound()

View file

@ -0,0 +1,18 @@
package de.moritzruth.spigot_ttt.game.classes
import de.moritzruth.spigot_ttt.game.items.TTTItem
import de.moritzruth.spigot_ttt.game.players.TTTPlayer
import org.bukkit.ChatColor
import org.bukkit.event.Listener
abstract class TTTClass(
val displayName: String,
val chatColor: ChatColor,
val defaultItems: Set<TTTItem> = emptySet()
) {
val coloredDisplayName = "$chatColor${ChatColor.BOLD}$displayName"
open val listener: Listener? = null
open fun onInit(tttPlayer: TTTPlayer) {}
}

View file

@ -0,0 +1,26 @@
package de.moritzruth.spigot_ttt.game.classes
import de.moritzruth.spigot_ttt.game.classes.impl.Gambler
import de.moritzruth.spigot_ttt.game.classes.impl.Oracle
import de.moritzruth.spigot_ttt.game.classes.impl.Stuntman
import de.moritzruth.spigot_ttt.game.classes.impl.Warrior
import java.util.*
object TTTClassManager {
private val TTT_CLASSES = setOf(
Warrior, Oracle, Gambler, Stuntman
)
val listeners = TTT_CLASSES.mapNotNull { it.listener }
fun createClassesIterator(count: Int): Iterator<TTTClass?> {
val set: MutableSet<TTTClass?> = TTT_CLASSES.toMutableSet()
val playersWithoutClass = count - TTT_CLASSES.size
if (playersWithoutClass > 0) {
set.addAll(Collections.nCopies(playersWithoutClass, null))
}
return set.shuffled().iterator()
}
}

View file

@ -0,0 +1,11 @@
package de.moritzruth.spigot_ttt.game.classes.impl
import de.moritzruth.spigot_ttt.game.classes.TTTClass
import de.moritzruth.spigot_ttt.game.items.impl.SecondChance
import org.bukkit.ChatColor
object Gambler: TTTClass(
"Gambler",
ChatColor.YELLOW,
setOf(SecondChance)
)

View file

@ -0,0 +1,11 @@
package de.moritzruth.spigot_ttt.game.classes.impl
import de.moritzruth.spigot_ttt.game.classes.TTTClass
import de.moritzruth.spigot_ttt.game.items.impl.Radar
import org.bukkit.ChatColor
object Oracle: TTTClass(
"Oracle",
ChatColor.DARK_AQUA,
setOf(Radar)
)

View file

@ -0,0 +1,34 @@
package de.moritzruth.spigot_ttt.game.classes.impl
import de.moritzruth.spigot_ttt.game.classes.TTTClass
import de.moritzruth.spigot_ttt.game.players.TTTPlayer
import org.bukkit.ChatColor
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.entity.EntityDamageEvent
import java.util.*
object Stuntman: TTTClass(
"Stuntman",
ChatColor.DARK_RED
) {
val IMMUNE_DAMAGE_CAUSES = EnumSet.of(
EntityDamageEvent.DamageCause.FALL,
EntityDamageEvent.DamageCause.BLOCK_EXPLOSION,
EntityDamageEvent.DamageCause.ENTITY_EXPLOSION
)!!
override val listener = object : Listener {
@EventHandler(ignoreCancelled = true)
fun onEntityDamage(event: EntityDamageEvent) {
val entity = event.entity
if (entity !is Player) return
val tttPlayer = TTTPlayer.of(entity) ?: return
if (tttPlayer.tttClass == Stuntman) {
if (IMMUNE_DAMAGE_CAUSES.contains(event.cause)) event.damage = 0.0
}
}
}
}

View file

@ -0,0 +1,31 @@
package de.moritzruth.spigot_ttt.game.classes.impl
import de.moritzruth.spigot_ttt.game.classes.TTTClass
import de.moritzruth.spigot_ttt.game.players.TTTPlayer
import org.bukkit.ChatColor
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.entity.EntityDamageEvent
object Warrior: TTTClass(
"Warrior",
ChatColor.BLUE
) {
override fun onInit(tttPlayer: TTTPlayer) {
tttPlayer.walkSpeed -= 0.05F
}
override val listener = object : Listener {
@EventHandler(ignoreCancelled = true)
fun onEntityDamage(event: EntityDamageEvent) {
val entity = event.entity
if (entity !is Player) return
val tttPlayer = TTTPlayer.of(entity) ?: return
if (tttPlayer.tttClass == Warrior) {
event.damage *= 0.9
}
}
}
}

View file

@ -16,10 +16,6 @@ import java.time.Duration
import java.time.Instant
object CorpseListener: Listener {
fun register() {
plugin.server.pluginManager.registerEvents(this, plugin)
}
@EventHandler
fun onInventoryClick(event: InventoryClickEvent) {
if (event.whoClicked !is Player) return

View file

@ -1,6 +1,5 @@
package de.moritzruth.spigot_ttt.game.items
import com.comphenix.protocol.ProtocolLibrary
import de.moritzruth.spigot_ttt.game.GameManager
import de.moritzruth.spigot_ttt.game.items.impl.*
import de.moritzruth.spigot_ttt.game.items.impl.weapons.BaseballBat
@ -35,14 +34,8 @@ object ItemManager {
val droppedItemStates = mutableMapOf<Int, IState>()
fun registerListeners() {
plugin.server.pluginManager.registerEvents(listener, plugin)
for (item in ITEMS) {
if (item.listener != null) plugin.server.pluginManager.registerEvents(item.listener!!, plugin)
if (item.packetListener != null) ProtocolLibrary.getProtocolManager().addPacketListener(item.packetListener!!)
}
}
val listeners get () = ITEMS.mapNotNull { it.listener }.plus(listener)
val packetListeners get () = ITEMS.mapNotNull { it.packetListener }
private fun getItemByMaterial(material: Material) = ITEMS.find { tttItem -> material === tttItem.itemStack.type }
fun getItemByItemStack(itemStack: ItemStack) = getItemByMaterial(itemStack.type)

View file

@ -23,8 +23,6 @@ interface Buyable {
val buyableBy: EnumSet<Role>
val price: Int
val buyLimit: Int?
fun onBuy(tttPlayer: TTTPlayer) {}
}
val PASSIVE = "${ChatColor.RESET}${ChatColor.RED}(Passiv)"
@ -38,6 +36,9 @@ interface TTTItem {
val itemStack: ItemStack
val type: Type
fun onOwn(tttPlayer: TTTPlayer) {}
fun onRemove(tttPlayer: TTTPlayer) {}
enum class Type(val maxItemsOfTypeInInventory: Int?) {
MELEE(1),
PISTOL_LIKE(1),

View file

@ -1,6 +1,7 @@
package de.moritzruth.spigot_ttt.game.items
import de.moritzruth.spigot_ttt.game.players.TTTPlayer
import de.moritzruth.spigot_ttt.game.players.TTTPlayerDeathEvent
import de.moritzruth.spigot_ttt.utils.isLeftClick
import de.moritzruth.spigot_ttt.utils.isRightClick
import org.bukkit.entity.Player
@ -15,12 +16,21 @@ import org.bukkit.event.player.PlayerItemConsumeEvent
import org.bukkit.event.player.PlayerSwapHandItemsEvent
import org.bukkit.inventory.ItemStack
open class TTTItemListener(private val tttItem: TTTItem, private val cancelDamage: Boolean): Listener {
open class TTTItemListener(
private val tttItem: TTTItem,
private val cancelDamage: Boolean,
private val removeOnDeath: Boolean = true
): Listener {
@EventHandler
open fun onEntityDamageByEntity(event: EntityDamageByEntityEvent) = handle(event) { _, _ ->
if (cancelDamage) event.isCancelled = true
}
@EventHandler
open fun onTTTPlayerDeath(event: TTTPlayerDeathEvent) {
if (removeOnDeath) event.tttPlayer.removeItem(tttItem)
}
@EventHandler
fun onPlayerInteract(event: PlayerInteractEvent) = handle(event) { tttPlayer ->
event.isCancelled = true

View file

@ -80,7 +80,10 @@ object CloakingDevice: TTTItem, Buyable, Selectable {
}
@EventHandler
fun onTTTPlayerDeath(event: TTTPlayerDeathEvent) = isc.get(event.tttPlayer)?.cooldownTask?.cancel()
override fun onTTTPlayerDeath(event: TTTPlayerDeathEvent) {
super.onTTTPlayerDeath(event)
isc.get(event.tttPlayer)?.cooldownTask?.cancel()
}
@EventHandler
fun onGameEnd(event: GameEndEvent) = isc.forEveryState { state, _ -> state.cooldownTask?.cancel() }

View file

@ -1,13 +1,13 @@
package de.moritzruth.spigot_ttt.game.items.impl
import de.moritzruth.spigot_ttt.Resourcepack
import de.moritzruth.spigot_ttt.game.items.TTTItemListener
import de.moritzruth.spigot_ttt.game.GameEndEvent
import de.moritzruth.spigot_ttt.game.GameManager
import de.moritzruth.spigot_ttt.game.players.*
import de.moritzruth.spigot_ttt.game.items.Buyable
import de.moritzruth.spigot_ttt.game.items.PASSIVE
import de.moritzruth.spigot_ttt.game.items.TTTItem
import de.moritzruth.spigot_ttt.game.items.TTTItemListener
import de.moritzruth.spigot_ttt.game.players.*
import de.moritzruth.spigot_ttt.plugin
import de.moritzruth.spigot_ttt.utils.applyMeta
import de.moritzruth.spigot_ttt.utils.createKillExplosion
@ -36,13 +36,13 @@ object MartyrdomGrenade: TTTItem, Buyable {
override val price = 1
val isc = InversedStateContainer(State::class)
override fun onBuy(tttPlayer: TTTPlayer) {
override fun onOwn(tttPlayer: TTTPlayer) {
isc.getOrCreate(tttPlayer)
}
override val listener = object : TTTItemListener(this, true) {
@EventHandler
fun onTTTPlayerDeath(event: TTTPlayerDeathEvent) {
fun onTTTPlayerTrueDeath(event: TTTPlayerTrueDeathEvent) {
val state = isc.get(event.tttPlayer) ?: return
state.explodeTask = plugin.server.scheduler.runTaskLater(plugin, fun() {

View file

@ -50,7 +50,7 @@ object Radar: TTTItem, Buyable {
val isc = InversedStateContainer(State::class)
override fun onBuy(tttPlayer: TTTPlayer) {
override fun onOwn(tttPlayer: TTTPlayer) {
val state = isc.getOrCreate(tttPlayer)
state.bossBar = plugin.server.createBossBar(DISPLAY_NAME, BarColor.BLUE, BarStyle.SOLID)
@ -101,13 +101,17 @@ object Radar: TTTItem, Buyable {
override val listener = object : TTTItemListener(this, true) {
@EventHandler
fun onTTTPlayerDeath(event: TTTPlayerDeathEvent) {
fun onTTTPlayerTrueDeath(event: TTTPlayerTrueDeathEvent) {
isc.get(event.tttPlayer)?.reset(event.tttPlayer)
isc.remove(event.tttPlayer)
}
@EventHandler
fun onGameEnd(event: GameEndEvent) = isc.forEveryState { state, tttPlayer -> state.reset(tttPlayer) }
override fun onRightClick(data: ClickEventData) {
data.event.isCancelled = true
}
}
override val packetListener = object : PacketAdapter(plugin, PacketType.Play.Server.ENTITY_METADATA) {

View file

@ -69,13 +69,13 @@ object SecondChance: TTTItem, Buyable {
})
}
override fun onBuy(tttPlayer: TTTPlayer) {
override fun onOwn(tttPlayer: TTTPlayer) {
isc.getOrCreate(tttPlayer)
}
override val listener = object : TTTItemListener(this, true) {
override val listener = object : TTTItemListener(this, true, false) {
@EventHandler
fun onTTTPlayerDeath(event: TTTPlayerDeathEvent) {
fun onTTTPlayerTrueDeath(event: TTTPlayerTrueDeathEvent) {
val state = isc.get(event.tttPlayer)
if (state != null) {
if (Random.nextBoolean()) {
@ -154,6 +154,7 @@ object SecondChance: TTTItem, Buyable {
isc.remove(tttPlayer)
task.cancel()
tttPlayer.player.closeInventory()
tttPlayer.removeItem(SecondChance)
bossBar.removePlayer(tttPlayer.player)
}
}

View file

@ -1,15 +1,14 @@
package de.moritzruth.spigot_ttt.game.items.impl.weapons
import de.moritzruth.spigot_ttt.Resourcepack
import de.moritzruth.spigot_ttt.game.items.TTTItemListener
import de.moritzruth.spigot_ttt.game.GameManager
import de.moritzruth.spigot_ttt.game.players.DamageInfo
import de.moritzruth.spigot_ttt.game.items.Buyable
import de.moritzruth.spigot_ttt.game.items.LoreHelper
import de.moritzruth.spigot_ttt.game.items.TTTItem
import de.moritzruth.spigot_ttt.game.items.TTTItemListener
import de.moritzruth.spigot_ttt.game.players.DeathReason
import de.moritzruth.spigot_ttt.game.players.Role
import de.moritzruth.spigot_ttt.game.players.roles
import de.moritzruth.spigot_ttt.game.items.Buyable
import de.moritzruth.spigot_ttt.game.items.TTTItem
import de.moritzruth.spigot_ttt.game.items.LoreHelper
import de.moritzruth.spigot_ttt.utils.applyMeta
import de.moritzruth.spigot_ttt.utils.hideInfo
import de.moritzruth.spigot_ttt.utils.removeTTTItemNextTick
@ -20,7 +19,6 @@ import org.bukkit.attribute.Attribute
import org.bukkit.attribute.AttributeModifier
import org.bukkit.event.EventHandler
import org.bukkit.event.entity.EntityDamageByEntityEvent
import org.bukkit.event.entity.EntityDamageEvent
import org.bukkit.inventory.ItemStack
object Knife: TTTItem, Buyable {
@ -50,18 +48,18 @@ object Knife: TTTItem, Buyable {
override val listener = object : TTTItemListener(this, false) {
@EventHandler(ignoreCancelled = true)
override fun onEntityDamageByEntity(event: EntityDamageByEntityEvent) = handle(event) { damagerTTTPlayer, damagedTTTPlayer ->
event.isCancelled = true
if (event.damage == 1.0) {
val distance = damagerTTTPlayer.player.location.distance(damagedTTTPlayer.player.location)
if (distance <= 1.5) {
damagedTTTPlayer.damageInfo = DamageInfo(
damagerTTTPlayer,
damagedTTTPlayer.damage(
1000.0,
DeathReason.Item(Knife),
EntityDamageEvent.DamageCause.ENTITY_ATTACK,
scream = false
damagerTTTPlayer,
false
)
event.damage = 1000.0
event.isCancelled = false
GameManager.world.playSound(
damagedTTTPlayer.player.location,
@ -80,11 +78,8 @@ object Knife: TTTItem, Buyable {
)
damagerTTTPlayer.player.inventory.removeTTTItemNextTick(Knife)
return@handle
}
}
event.isCancelled = true
}
}
}

View file

@ -1,7 +1,6 @@
package de.moritzruth.spigot_ttt.game.items.impl.weapons.guns
import de.moritzruth.spigot_ttt.Resourcepack
import de.moritzruth.spigot_ttt.game.items.TTTItemListener
import de.moritzruth.spigot_ttt.game.GameEndEvent
import de.moritzruth.spigot_ttt.game.GameManager
import de.moritzruth.spigot_ttt.game.GamePhase
@ -136,10 +135,9 @@ abstract class Gun(
}
open fun onHit(tttPlayer: TTTPlayer, hitTTTPlayer: TTTPlayer) {
hitTTTPlayer.damageInfo = DamageInfo(tttPlayer, DeathReason.Item(this))
val actualDamage = computeActualDamage(tttPlayer, hitTTTPlayer.player)
hitTTTPlayer.player.damage(actualDamage)
hitTTTPlayer.damage(actualDamage, DeathReason.Item(this), tttPlayer, true)
tttPlayer.player.playSound(tttPlayer.player.location, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.MASTER, 2f, 1.2f)
hitTTTPlayer.player.velocity = tttPlayer.player.location.direction.multiply(
(actualDamage / 20).coerceAtMost(3.0)
@ -215,7 +213,7 @@ abstract class Gun(
}
@EventHandler
fun onTTTPlayerDeath(event: TTTPlayerDeathEvent) = isc.get(event.tttPlayer)?.reset()
fun onTTTPlayerDeath(event: TTTPlayerTrueDeathEvent) = isc.get(event.tttPlayer)?.reset()
@EventHandler
fun onGameEnd(event: GameEndEvent) = isc.forEveryState { state, _ -> state.reset() }
@ -279,8 +277,4 @@ abstract class Gun(
}
}
}
companion object {
const val INFINITE_DAMAGE: Double = -1.0
}
}

View file

@ -5,8 +5,7 @@ import de.moritzruth.spigot_ttt.game.items.Buyable
import de.moritzruth.spigot_ttt.game.items.ItemManager
import de.moritzruth.spigot_ttt.game.players.PlayerManager
import de.moritzruth.spigot_ttt.game.players.TTTPlayer
import de.moritzruth.spigot_ttt.game.players.TTTPlayerDeathEvent
import de.moritzruth.spigot_ttt.plugin
import de.moritzruth.spigot_ttt.game.players.TTTPlayerTrueDeathEvent
import de.moritzruth.spigot_ttt.utils.sendActionBarMessage
import org.bukkit.ChatColor
import org.bukkit.entity.Player
@ -16,10 +15,6 @@ import org.bukkit.event.inventory.ClickType
import org.bukkit.event.inventory.InventoryClickEvent
object ShopListener: Listener {
fun register() {
plugin.server.pluginManager.registerEvents(this, plugin)
}
@EventHandler(ignoreCancelled = true)
fun onInventoryClick(event: InventoryClickEvent) {
if (event.whoClicked !is Player) return
@ -50,8 +45,6 @@ object ShopListener: Listener {
tttPlayer.boughtItems.add(tttItem)
tttPlayer.credits -= tttItem.price
tttItem.onBuy(tttPlayer)
Shop.setItems(tttPlayer)
} catch (e: TTTPlayer.AlreadyHasItemException) {
tttPlayer.player.sendActionBarMessage("${ChatColor.RED}Du hast dieses Item bereits")
@ -63,7 +56,7 @@ object ShopListener: Listener {
}
@EventHandler
fun onTTTPlayerDeath(event: TTTPlayerDeathEvent) {
fun onTTTPlayerDeath(event: TTTPlayerTrueDeathEvent) {
val killer = event.killer ?: return
if (event.tttPlayer.role.group != killer.role.group) {

View file

@ -6,6 +6,7 @@ import de.moritzruth.spigot_ttt.TTTPlugin
import de.moritzruth.spigot_ttt.game.GameManager
import de.moritzruth.spigot_ttt.game.GameMessenger
import de.moritzruth.spigot_ttt.game.GamePhase
import de.moritzruth.spigot_ttt.game.classes.TTTClassManager
import de.moritzruth.spigot_ttt.plugin
import de.moritzruth.spigot_ttt.utils.nextTick
import de.moritzruth.spigot_ttt.utils.noop
@ -95,34 +96,27 @@ object PlayerManager {
fun createTTTPlayers() {
val playersWithoutRole = availablePlayers.toMutableSet()
var playersWithoutRoleCount = playersWithoutRole.count()
val classesIterator = TTTClassManager.createClassesIterator(playersWithoutRoleCount)
fun createTTTPlayer(role: Role) {
val player = playersWithoutRole.random()
tttPlayers.add(TTTPlayer(player, role, classesIterator.next()))
playersWithoutRole.remove(player)
playersWithoutRoleCount--
}
val traitorCount: Int = if (playersWithoutRoleCount <= 4) 1 else ceil(playersWithoutRoleCount / 4.0).toInt()
for (index in 1..traitorCount) createTTTPlayer(Role.TRAITOR)
for (index in 1..traitorCount) {
val player = playersWithoutRole.random()
tttPlayers.add(TTTPlayer(player, Role.TRAITOR))
playersWithoutRole.remove(player)
playersWithoutRoleCount--
}
if (playersWithoutRoleCount > 1 && Settings.detectiveEnabled) {
val player = playersWithoutRole.random()
tttPlayers.add(TTTPlayer(player, Role.DETECTIVE))
playersWithoutRole.remove(player)
playersWithoutRoleCount--
}
if (playersWithoutRoleCount > 1 && Settings.detectiveEnabled) createTTTPlayer(Role.TRAITOR)
if (playersWithoutRoleCount > 1 && when (Settings.jackalMode) {
JackalMode.ALWAYS -> true
JackalMode.HALF_TIME -> Random.Default.nextBoolean()
JackalMode.NEVER -> false
}) {
val player = playersWithoutRole.random()
tttPlayers.add(TTTPlayer(player, Role.JACKAL))
playersWithoutRole.remove(player)
@Suppress("UNUSED_CHANGED_VALUE")
playersWithoutRoleCount--
}
) createTTTPlayer(Role.JACKAL)
playersWithoutRole.forEach { tttPlayers.add(TTTPlayer(it, Role.INNOCENT)) }
playersWithoutRole.forEach { tttPlayers.add(TTTPlayer(it, Role.INNOCENT, classesIterator.next())) }
}
}

View file

@ -5,10 +5,13 @@ import de.moritzruth.spigot_ttt.Settings
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.ScoreboardHelper
import de.moritzruth.spigot_ttt.game.classes.TTTClass
import de.moritzruth.spigot_ttt.game.corpses.TTTCorpse
import de.moritzruth.spigot_ttt.game.items.ItemManager
import de.moritzruth.spigot_ttt.game.items.Selectable
import de.moritzruth.spigot_ttt.game.items.TTTItem
import de.moritzruth.spigot_ttt.game.items.impl.CloakingDevice
import de.moritzruth.spigot_ttt.game.items.shop.Shop
import de.moritzruth.spigot_ttt.plugin
import de.moritzruth.spigot_ttt.utils.*
@ -17,7 +20,7 @@ import org.bukkit.entity.Player
import org.bukkit.scheduler.BukkitTask
import kotlin.properties.Delegates
class TTTPlayer(player: Player, role: Role) {
class TTTPlayer(player: Player, role: Role, val tttClass: TTTClass?) {
var alive = true
var player by Delegates.observable(player) { _, _, _ -> adjustPlayer() }
@ -26,6 +29,7 @@ class TTTPlayer(player: Player, role: Role) {
if (value !== field) {
field = value
scoreboard.updateRole()
ScoreboardHelper.forEveryScoreboard { it.updateTeams() }
scoreboard.showCorrectSidebarScoreboard()
Shop.setItems(this)
}
@ -35,9 +39,13 @@ class TTTPlayer(player: Player, role: Role) {
var itemInHand by Delegates.observable<TTTItem?>(null) { _, oldItem, newItem ->
if (oldItem !== newItem) onItemInHandChanged(oldItem, newItem)
}
var walkSpeed
get() = player.walkSpeed
set(value) { player.walkSpeed = value }
var credits by Delegates.observable(Settings.initialCredits) { _, _, _ -> scoreboard.updateCredits() }
val boughtItems = mutableListOf<TTTItem>()
var damageInfo: DamageInfo? = null
private var staminaCooldown: Int = 0
private var staminaTask: BukkitTask? = null
@ -48,6 +56,7 @@ class TTTPlayer(player: Player, role: Role) {
init {
adjustPlayer()
scoreboard.initialize()
tttClass?.onInit(this)
}
private fun onItemInHandChanged(oldItem: TTTItem?, newItem: TTTItem?) {
@ -60,8 +69,21 @@ class TTTPlayer(player: Player, role: Role) {
}
}
fun damage(damage: Double, reason: DeathReason, damager: TTTPlayer, scream: Boolean = true) {
if (!alive) return
val finalHealth = player.health - damage
if (finalHealth <= 0.0) onDeath(reason, damager, scream)
else player.damage(damage)
}
fun onDeath(reason: DeathReason, killer: TTTPlayer?, scream: Boolean = true) {
GameManager.ensurePhase(GamePhase.COMBAT)
if (!alive) return
alive = false
player.gameMode = GameMode.SPECTATOR
var reallyScream = scream
player.sendMessage(TTTPlugin.prefix +
if (killer == null) "${ChatColor.RED}${ChatColor.BOLD}Du bist gestorben"
@ -71,28 +93,37 @@ class TTTPlayer(player: Player, role: Role) {
" ${ChatColor.RED}${ChatColor.BOLD}getötet"
)
player.gameMode = GameMode.SPECTATOR
alive = false
val tttCorpse = TTTCorpse.spawn(this, reason)
if (GameManager.phase == GamePhase.PREPARING) {
player.sendMessage("${TTTPlugin.prefix}${ChatColor.GRAY}${ChatColor.ITALIC}Du wirst nach der Vorbereitungsphase wiederbelebt")
player.inventory.clear()
val event = TTTPlayerDeathEvent(
tttPlayer = this,
location = player.location,
killer = killer,
scream = reallyScream
).call()
reallyScream = event.scream
} else {
val tttCorpse = TTTCorpse.spawn(this, reason)
credits = 0
val onlyRemainingRoleGroup = PlayerManager.getOnlyRemainingRoleGroup()
val event = TTTPlayerDeathEvent(
this,
player.location,
tttCorpse,
killer,
scream,
onlyRemainingRoleGroup
val event = TTTPlayerTrueDeathEvent(
tttPlayer = this,
location = player.location,
tttCorpse = tttCorpse,
killer = killer,
scream = reallyScream,
winnerRoleGroup = onlyRemainingRoleGroup
).call()
reallyScream = event.scream
event.winnerRoleGroup?.run { GameManager.letRoleWin(primaryRole) }
}
if (event.scream) {
GameManager.world.playSound(
if (reallyScream) GameManager.world.playSound(
player.location,
Resourcepack.Sounds.playerDeath,
SoundCategory.PLAYERS,
@ -100,7 +131,6 @@ class TTTPlayer(player: Player, role: Role) {
1F
)
}
}
fun revive(location: Location, credits: Int = 0) {
if (alive) throw AlreadyLivingException()
@ -221,9 +251,18 @@ class TTTPlayer(player: Player, role: Role) {
fun addItem(item: TTTItem) {
checkAddItemPreconditions(item)
player.inventory.addItem(item.itemStack.clone())
item.onOwn(this)
updateItemInHand()
}
fun removeItem(item: TTTItem) {
player.inventory.removeTTTItem(CloakingDevice)
item.onRemove(this)
updateItemInHand()
}
fun addDefaultClassItems() = tttClass?.defaultItems?.forEach { addItem(it) }
override fun toString() = "TTTPlayer(${player.name} is $role)"
companion object {

View file

@ -5,13 +5,11 @@ import org.bukkit.Location
import org.bukkit.event.Event
import org.bukkit.event.HandlerList
data class TTTPlayerDeathEvent(
open class TTTPlayerDeathEvent(
val tttPlayer: TTTPlayer,
val location: Location,
val tttCorpse: TTTCorpse,
val killer: TTTPlayer?,
var scream: Boolean = true,
var winnerRoleGroup: RoleGroup? = null
var scream: Boolean = true
): Event() {
override fun getHandlers(): HandlerList {
@Suppress("RedundantCompanionReference") // false positive
@ -25,3 +23,29 @@ data class TTTPlayerDeathEvent(
fun getHandlerList() = handlers
}
}
class TTTPlayerTrueDeathEvent(
tttPlayer: TTTPlayer,
location: Location,
killer: TTTPlayer?,
scream: Boolean = true,
val tttCorpse: TTTCorpse,
var winnerRoleGroup: RoleGroup? = null
): TTTPlayerDeathEvent(
tttPlayer,
location,
killer,
scream
) {
override fun getHandlers(): HandlerList {
@Suppress("RedundantCompanionReference") // false positive
return Companion.handlers
}
companion object {
private val handlers = HandlerList()
@JvmStatic
fun getHandlerList() = handlers
}
}

View file

@ -17,6 +17,7 @@ class TTTScoreboard(private val tttPlayer: TTTPlayer) {
scoreboard.registerNewTeam(ValueTeam.ROLE.teamName).addEntry(ValueTeam.ROLE.entry)
scoreboard.registerNewTeam(ValueTeam.PHASE_AND_TIME.teamName).addEntry(ValueTeam.PHASE_AND_TIME.entry)
scoreboard.registerNewTeam(ValueTeam.CREDITS.teamName).addEntry(ValueTeam.CREDITS.entry)
scoreboard.registerNewTeam(ValueTeam.CLASS.teamName).addEntry(ValueTeam.CLASS.entry)
scoreboard.registerNewObjective(
INACTIVE_OBJECTIVE,
@ -44,6 +45,7 @@ class TTTScoreboard(private val tttPlayer: TTTPlayer) {
ValueTeam.PHASE_AND_TIME.entry,
" ",
ValueTeam.ROLE.entry,
ValueTeam.CLASS.entry,
" "
)
@ -61,6 +63,7 @@ class TTTScoreboard(private val tttPlayer: TTTPlayer) {
ValueTeam.PHASE_AND_TIME.entry,
" ",
ValueTeam.ROLE.entry,
ValueTeam.CLASS.entry,
ValueTeam.CREDITS.entry,
" "
)
@ -82,6 +85,8 @@ class TTTScoreboard(private val tttPlayer: TTTPlayer) {
setOption(Team.Option.NAME_TAG_VISIBILITY, Team.OptionStatus.NEVER)
}
setValue(ValueTeam.CLASS, "Klasse: ${tttPlayer.tttClass?.coloredDisplayName ?: "${ChatColor.GRAY}Keine"}")
updateEverything()
showCorrectSidebarScoreboard()
}
@ -106,7 +111,10 @@ class TTTScoreboard(private val tttPlayer: TTTPlayer) {
when (GameManager.phase) {
null -> setValue(ValueTeam.ROLE, "")
GamePhase.PREPARING -> setValue(ValueTeam.ROLE, "Du bist: ${ChatColor.MAGIC}xxxxxxxx")
GamePhase.COMBAT, GamePhase.OVER -> setValue(ValueTeam.ROLE, "Du bist: " + tttPlayer.role.coloredDisplayName.toUpperCase())
GamePhase.COMBAT, GamePhase.OVER -> setValue(
ValueTeam.ROLE,
"Du bist: ${tttPlayer.role.chatColor}${ChatColor.BOLD}${tttPlayer.role.displayName}"
)
}
}
@ -170,7 +178,8 @@ class TTTScoreboard(private val tttPlayer: TTTPlayer) {
private enum class ValueTeam(val teamName: String, val entry: String) {
PHASE_AND_TIME("_phase-and-time", "${ChatColor.AQUA}"),
ROLE("_role", "${ChatColor.BLACK}"),
CREDITS("_credits", "${ChatColor.GOLD}")
CREDITS("_credits", "${ChatColor.GOLD}"),
CLASS("_class", "${ChatColor.GREEN}")
}
companion object {

View file

@ -1,11 +1,10 @@
package de.moritzruth.spigot_ttt.utils
import de.moritzruth.spigot_ttt.game.GameManager
import de.moritzruth.spigot_ttt.game.players.DamageInfo
import de.moritzruth.spigot_ttt.game.players.DeathReason
import de.moritzruth.spigot_ttt.game.players.PlayerManager
import de.moritzruth.spigot_ttt.game.players.TTTPlayer
import de.moritzruth.spigot_ttt.game.classes.impl.Stuntman
import de.moritzruth.spigot_ttt.game.items.impl.Fireball
import de.moritzruth.spigot_ttt.game.players.DeathReason
import de.moritzruth.spigot_ttt.game.players.TTTPlayer
import org.bukkit.Location
import org.bukkit.Particle
import org.bukkit.entity.Player
@ -18,12 +17,16 @@ fun createKillExplosion(tttPlayer: TTTPlayer, location: Location, radius: Double
radius, radius, radius
)
val nearbyTTTPlayers = GameManager.world.getNearbyEntities(
GameManager.world.getNearbyEntities(
location, radius, radius, radius
) { it is Player }.mapNotNull { TTTPlayer.of(it as Player) }
for (nearbyTTTPlayer in nearbyTTTPlayers) {
nearbyTTTPlayer.damageInfo = DamageInfo(tttPlayer, DeathReason.Item(Fireball))
nearbyTTTPlayer.player.damage(20.0)
) { it is Player }
.mapNotNull { TTTPlayer.of(it as Player) }
.forEach {
it.damage(
if (it.tttClass == Stuntman) 0.0 else 1000.0,
DeathReason.Item(Fireball),
tttPlayer,
true
)
}
}