Add sidekick deagle and sidekick functionality
This commit is contained in:
parent
9d05ff74ab
commit
6d364fa3eb
18 changed files with 197 additions and 102 deletions
|
@ -21,7 +21,7 @@ object CustomItems {
|
|||
|
||||
// Weapons
|
||||
val deagle = Material.IRON_HOE
|
||||
val goldenDeagle = Material.GOLDEN_HOE
|
||||
val sidekickDeagle = Material.GOLDEN_HOE
|
||||
val glock = Material.STONE_HOE
|
||||
val pistol = Material.WOODEN_HOE
|
||||
val shotgun = Material.IRON_AXE
|
||||
|
|
|
@ -36,7 +36,7 @@ object GameManager {
|
|||
|
||||
PlayerManager.tttPlayers.forEach {
|
||||
it.setMuted(false)
|
||||
Shop.hide(it)
|
||||
Shop.clear(it)
|
||||
}
|
||||
|
||||
Timers.startOverPhaseTimer(plugin.config.getInt("duration.over", 10)) {
|
||||
|
@ -96,7 +96,7 @@ object GameManager {
|
|||
ensurePhase(GamePhase.PREPARING)
|
||||
|
||||
phase = GamePhase.COMBAT
|
||||
PlayerManager.tttPlayers.forEach { Shop.show(it) }
|
||||
PlayerManager.tttPlayers.forEach { Shop.setItems(it) }
|
||||
ScoreboardHelper.forEveryScoreboard { it.updateTeams() }
|
||||
Shop.startCreditsTimer()
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ enum class Role(
|
|||
DETECTIVE(ChatColor.YELLOW, "Detective", CustomItems.detective, true),
|
||||
TRAITOR(ChatColor.RED, "Traitor", CustomItems.traitor, true),
|
||||
JACKAL(ChatColor.AQUA, "Jackal", CustomItems.jackal, true),
|
||||
SIDEKICK(ChatColor.AQUA, "Sidekick", CustomItems.sidekick, true);
|
||||
SIDEKICK(ChatColor.AQUA, "Sidekick", CustomItems.sidekick, false);
|
||||
|
||||
val coloredDisplayName = "$chatColor$displayName${ChatColor.RESET}"
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import de.moritzruth.spigot_ttt.shop.Shop
|
|||
import de.moritzruth.spigot_ttt.utils.hotbarContents
|
||||
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.Material
|
||||
import org.bukkit.entity.Player
|
||||
|
@ -23,15 +24,25 @@ import kotlin.properties.Delegates
|
|||
|
||||
class TTTPlayer(player: Player, role: Role) {
|
||||
var alive = true
|
||||
var player by Delegates.observable(player) { _, _, _ -> initializePlayer() }
|
||||
var player by Delegates.observable(player) { _, _, _ -> adjustPlayer() }
|
||||
|
||||
var role by Delegates.observable(role) { _, _, _ -> scoreboard.updateRole() }
|
||||
var role = role
|
||||
private set(value) {
|
||||
if (value !== field) {
|
||||
field = value
|
||||
scoreboard.updateRole()
|
||||
scoreboard.showCorrectSidebarScoreboard()
|
||||
Shop.setItems(this)
|
||||
}
|
||||
}
|
||||
val roleHistory = mutableListOf<Role>()
|
||||
|
||||
var itemInHand by Delegates.observable<TTTItem?>(null) { _, oldItem, newItem ->
|
||||
if (oldItem !== newItem) onItemInHandChanged(oldItem, newItem)
|
||||
}
|
||||
var credits by Delegates.observable(10) { _, _, _ -> scoreboard.updateCredits() }
|
||||
val boughtItems = mutableListOf<TTTItem>()
|
||||
|
||||
var invisible by Delegates.observable(false) { _, _, value ->
|
||||
if (value) {
|
||||
PlayerManager.tttPlayers.forEach {
|
||||
|
@ -58,18 +69,11 @@ class TTTPlayer(player: Player, role: Role) {
|
|||
private val discordUser get() = DiscordInterface.getUserByPlayerUUID(player.uniqueId)
|
||||
|
||||
init {
|
||||
initializePlayer()
|
||||
adjustPlayer()
|
||||
scoreboard.initialize()
|
||||
}
|
||||
|
||||
private fun initializePlayer() {
|
||||
player.scoreboard = scoreboard.scoreboard
|
||||
}
|
||||
|
||||
private fun onItemInHandChanged(oldItem: TTTItem?, newItem: TTTItem?) {
|
||||
println(oldItem)
|
||||
println(newItem)
|
||||
|
||||
if (oldItem !== null && oldItem is Selectable) {
|
||||
oldItem.onDeselect(this)
|
||||
}
|
||||
|
@ -79,6 +83,27 @@ class TTTPlayer(player: Player, role: Role) {
|
|||
}
|
||||
}
|
||||
|
||||
fun onDeath(reason: DeathReason = DeathReason.SUICIDE) {
|
||||
GameManager.ensurePhase(GamePhase.COMBAT)
|
||||
|
||||
player.gameMode = GameMode.SPECTATOR
|
||||
alive = false
|
||||
|
||||
TTTCorpse.spawn(this, reason)
|
||||
credits = 0
|
||||
|
||||
Shop.clear(this)
|
||||
setMuted(true)
|
||||
|
||||
PlayerManager.letRemainingRoleGroupWin()
|
||||
}
|
||||
|
||||
private fun adjustPlayer() {
|
||||
player.scoreboard = scoreboard.scoreboard
|
||||
}
|
||||
|
||||
private fun getOwningTTTItems() = player.inventory.hotbarContents.mapNotNull { it?.run { ItemManager.getItemByItemStack(this) } }
|
||||
|
||||
fun activateStamina() {
|
||||
if (staminaTask != null) return
|
||||
|
||||
|
@ -96,21 +121,23 @@ class TTTPlayer(player: Player, role: Role) {
|
|||
}, 0, secondsToTicks(0.5).toLong())
|
||||
}
|
||||
|
||||
fun onDeath(reason: DeathReason = DeathReason.SUICIDE) {
|
||||
GameManager.ensurePhase(GamePhase.COMBAT)
|
||||
fun changeRole(newRole: Role) {
|
||||
roleHistory.add(role)
|
||||
role = newRole
|
||||
|
||||
player.gameMode = GameMode.SPECTATOR
|
||||
alive = false
|
||||
val message = if (role == Role.SIDEKICK) {
|
||||
val jackal = PlayerManager.tttPlayers.find { it.role == Role.JACKAL }
|
||||
?: throw NoJackalLivingException()
|
||||
|
||||
TTTCorpse.spawn(this, reason)
|
||||
credits = 0
|
||||
|
||||
Shop.hide(this)
|
||||
setMuted(true)
|
||||
"${ChatColor.WHITE}Du bist jetzt ${role.coloredDisplayName} von ${jackal.role.chatColor}${jackal.player.displayName}"
|
||||
} else "${ChatColor.WHITE}Du bist jetzt ${role.coloredDisplayName}"
|
||||
|
||||
player.sendTitle("", message, secondsToTicks(0.2), secondsToTicks(3), secondsToTicks(0.5))
|
||||
PlayerManager.letRemainingRoleGroupWin()
|
||||
}
|
||||
|
||||
class NoJackalLivingException: Exception("There is no living jackal for this sidekick")
|
||||
|
||||
fun resetAfterGameEnd() {
|
||||
if (!alive) {
|
||||
teleportToSpawn()
|
||||
|
@ -138,7 +165,6 @@ class TTTPlayer(player: Player, role: Role) {
|
|||
setMuted(false)
|
||||
invisible = false
|
||||
|
||||
alive = true
|
||||
player.gameMode = GameMode.SURVIVAL
|
||||
player.activePotionEffects.forEach { player.removePotionEffect(it.type) }
|
||||
player.health = 20.0
|
||||
|
@ -182,6 +208,9 @@ class TTTPlayer(player: Player, role: Role) {
|
|||
throw TooManyItemsOfTypeException()
|
||||
}
|
||||
}
|
||||
class AlreadyHasItemException: Exception("The player already owns this item")
|
||||
|
||||
class TooManyItemsOfTypeException: Exception("The player already owns too much items of this type")
|
||||
|
||||
fun addItem(item: TTTItem) {
|
||||
checkAddItemPreconditions(item)
|
||||
|
@ -189,10 +218,5 @@ class TTTPlayer(player: Player, role: Role) {
|
|||
updateItemInHand()
|
||||
}
|
||||
|
||||
class AlreadyHasItemException: Exception("The player already owns this item")
|
||||
class TooManyItemsOfTypeException: Exception("The player already owns too much items of this type")
|
||||
|
||||
private fun getOwningTTTItems() = player.inventory.hotbarContents.mapNotNull { it?.run { ItemManager.getItemByItemStack(this) } }
|
||||
|
||||
override fun toString() = "TTTPlayer(${player.name} is $role)"
|
||||
}
|
||||
|
|
|
@ -9,12 +9,7 @@ import de.moritzruth.spigot_ttt.items.impl.CloakingDevice
|
|||
import de.moritzruth.spigot_ttt.items.impl.EnderPearl
|
||||
import de.moritzruth.spigot_ttt.items.impl.HealingPotion
|
||||
import de.moritzruth.spigot_ttt.items.impl.Radar
|
||||
import de.moritzruth.spigot_ttt.items.weapons.guns.impl.GoldenDeagle
|
||||
import de.moritzruth.spigot_ttt.items.weapons.guns.impl.Deagle
|
||||
import de.moritzruth.spigot_ttt.items.weapons.guns.impl.Glock
|
||||
import de.moritzruth.spigot_ttt.items.weapons.guns.impl.Pistol
|
||||
import de.moritzruth.spigot_ttt.items.weapons.guns.impl.Shotgun
|
||||
import de.moritzruth.spigot_ttt.items.weapons.guns.impl.Rifle
|
||||
import de.moritzruth.spigot_ttt.items.weapons.guns.impl.*
|
||||
import de.moritzruth.spigot_ttt.items.weapons.impl.BaseballBat
|
||||
import de.moritzruth.spigot_ttt.items.weapons.impl.Knife
|
||||
import de.moritzruth.spigot_ttt.plugin
|
||||
|
@ -33,7 +28,7 @@ import org.bukkit.inventory.ItemStack
|
|||
object ItemManager {
|
||||
val ITEMS: Set<TTTItem> = setOf(
|
||||
Pistol,
|
||||
Knife, Glock, Deagle, Shotgun, GoldenDeagle,
|
||||
Knife, Glock, Deagle, Shotgun, SidekickDeagle,
|
||||
BaseballBat,
|
||||
CloakingDevice, Rifle,
|
||||
EnderPearl, Radar, HealingPotion
|
||||
|
@ -78,7 +73,10 @@ object ItemManager {
|
|||
|
||||
if (tttItem.type != TTTItem.Type.SPECIAL) {
|
||||
if (tttItem is DropHandler) {
|
||||
tttItem.onDrop(tttPlayer, event.itemDrop)
|
||||
if (!tttItem.onDrop(tttPlayer, event.itemDrop)) {
|
||||
event.isCancelled = true
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
plugin.server.scheduler.runTask(plugin, fun() {
|
||||
|
|
|
@ -17,13 +17,14 @@ interface Selectable {
|
|||
}
|
||||
|
||||
interface DropHandler {
|
||||
fun onDrop(tttPlayer: TTTPlayer, itemEntity: Item)
|
||||
fun onDrop(tttPlayer: TTTPlayer, itemEntity: Item): Boolean
|
||||
fun onPickup(tttPlayer: TTTPlayer, itemEntity: Item)
|
||||
}
|
||||
|
||||
interface Buyable {
|
||||
val buyableBy: EnumSet<Role>
|
||||
val price: Int
|
||||
val buyLimit: Int?
|
||||
}
|
||||
|
||||
// Marker
|
||||
|
|
|
@ -33,6 +33,7 @@ object CloakingDevice: TTTItem,
|
|||
override val type = TTTItem.Type.SPECIAL
|
||||
override val price = 2
|
||||
override val buyableBy = roles(Role.TRAITOR, Role.JACKAL)
|
||||
override val buyLimit = 1
|
||||
|
||||
val isc = InversedStateContainer(State::class)
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ object EnderPearl: TTTItem, Buyable {
|
|||
}
|
||||
override val buyableBy = roles(Role.TRAITOR, Role.JACKAL, Role.DETECTIVE)
|
||||
override val price = 1
|
||||
override val buyLimit: Int? = null
|
||||
|
||||
override val listener = object : Listener {
|
||||
@EventHandler
|
||||
|
|
|
@ -37,6 +37,7 @@ object HealingPotion: TTTItem, Buyable {
|
|||
override val type = TTTItem.Type.SPECIAL
|
||||
override val buyableBy = roles(Role.TRAITOR, Role.JACKAL, Role.DETECTIVE)
|
||||
override val price = 1
|
||||
override val buyLimit = 2
|
||||
|
||||
override val listener = object : Listener {
|
||||
@EventHandler
|
||||
|
|
|
@ -48,6 +48,7 @@ object Radar: TTTItem, Buyable {
|
|||
override val type = TTTItem.Type.SPECIAL
|
||||
override val buyableBy: EnumSet<Role> = EnumSet.of(Role.TRAITOR, Role.DETECTIVE, Role.JACKAL)
|
||||
override val price = 2
|
||||
override val buyLimit: Int? = null
|
||||
|
||||
val isc = InversedStateContainer(State::class)
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ abstract class Gun(
|
|||
}
|
||||
|
||||
fun shoot(tttPlayer: TTTPlayer, itemStack: ItemStack, state: State = isc.getOrCreate(tttPlayer)) {
|
||||
onBeforeShoot(tttPlayer, itemStack, state)
|
||||
if (!onBeforeShoot(tttPlayer, itemStack, state)) return
|
||||
|
||||
if (state.remainingShots == 0) {
|
||||
GameManager.world.playSound(tttPlayer.player.location, Sound.BLOCK_ANVIL_PLACE, SoundCategory.PLAYERS, 1f, 1.3f)
|
||||
|
@ -89,14 +89,7 @@ abstract class Gun(
|
|||
val damagedTTTPlayer = PlayerManager.getTTTPlayer(entity)
|
||||
|
||||
if (damagedTTTPlayer != null) {
|
||||
damagedTTTPlayer.damageInfo = DamageInfo(tttPlayer, DeathReason.Item(this))
|
||||
val actualDamage = computeActualDamage(tttPlayer, entity)
|
||||
|
||||
entity.damage(actualDamage)
|
||||
tttPlayer.player.playSound(tttPlayer.player.location, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.MASTER, 2f, 1.2f)
|
||||
entity.velocity = tttPlayer.player.location.direction.multiply(
|
||||
(actualDamage / 20).coerceAtMost(3.0)
|
||||
)
|
||||
onHit(tttPlayer, damagedTTTPlayer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,8 +109,20 @@ abstract class Gun(
|
|||
|
||||
open fun computeActualDamage(tttPlayer: TTTPlayer, receiver: Player) = if (damage < 0 ) 1000.0 else damage
|
||||
|
||||
open fun onBeforeShoot(tttPlayer: TTTPlayer, item: ItemStack, state: State = isc.getOrCreate(tttPlayer)) {
|
||||
open fun onBeforeShoot(tttPlayer: TTTPlayer, item: ItemStack, state: State = isc.getOrCreate(tttPlayer)): Boolean {
|
||||
if (state.currentAction !== null) throw ActionInProgressError()
|
||||
return true
|
||||
}
|
||||
|
||||
open fun onHit(tttPlayer: TTTPlayer, hitTTTPlayer: TTTPlayer) {
|
||||
hitTTTPlayer.damageInfo = DamageInfo(tttPlayer, DeathReason.Item(this))
|
||||
val actualDamage = computeActualDamage(tttPlayer, hitTTTPlayer.player)
|
||||
|
||||
hitTTTPlayer.player.damage(actualDamage)
|
||||
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)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onSelect(tttPlayer: TTTPlayer) {
|
||||
|
@ -140,8 +145,8 @@ abstract class Gun(
|
|||
}
|
||||
}
|
||||
|
||||
override fun onDrop(tttPlayer: TTTPlayer, itemEntity: Item) {
|
||||
val state = isc.get(tttPlayer) ?: return
|
||||
override fun onDrop(tttPlayer: TTTPlayer, itemEntity: Item): Boolean {
|
||||
val state = isc.get(tttPlayer) ?: return true
|
||||
|
||||
when(val currentAction = state.currentAction) {
|
||||
is Action.Reloading -> {
|
||||
|
@ -157,7 +162,7 @@ abstract class Gun(
|
|||
|
||||
ItemManager.droppedItemStates[itemEntity.entityId] = state
|
||||
isc.remove(tttPlayer)
|
||||
return
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onPickup(tttPlayer: TTTPlayer, itemEntity: Item) {
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
package de.moritzruth.spigot_ttt.items.weapons.guns.impl
|
||||
|
||||
import de.moritzruth.spigot_ttt.CustomItems
|
||||
import de.moritzruth.spigot_ttt.game.players.Role
|
||||
import de.moritzruth.spigot_ttt.game.players.roles
|
||||
import de.moritzruth.spigot_ttt.items.Buyable
|
||||
import de.moritzruth.spigot_ttt.items.TTTItem
|
||||
import de.moritzruth.spigot_ttt.items.weapons.guns.Gun
|
||||
import org.bukkit.ChatColor
|
||||
|
||||
object GoldenDeagle: Gun(
|
||||
stateClass = State::class,
|
||||
displayName = "${ChatColor.GOLD}${ChatColor.BOLD}Golden Deagle",
|
||||
damage = INFINITE_DAMAGE,
|
||||
cooldown = 1.0,
|
||||
magazineSize = 1,
|
||||
reloadTime = 20.0,
|
||||
itemMaterial = CustomItems.goldenDeagle
|
||||
), Buyable {
|
||||
override val buyableBy = roles(Role.TRAITOR, Role.JACKAL, Role.DETECTIVE)
|
||||
override val price = 3
|
||||
override val type = TTTItem.Type.PISTOL_LIKE
|
||||
|
||||
class State: Gun.State(magazineSize)
|
||||
}
|
||||
|
||||
|
|
@ -66,9 +66,9 @@ object Shotgun: Gun(
|
|||
ownState.currentAction = ReloadingAction(itemStack, ownState, tttPlayer).also { it.start() }
|
||||
}
|
||||
|
||||
override fun onBeforeShoot(tttPlayer: TTTPlayer, item: ItemStack, state: Gun.State) {
|
||||
override fun onBeforeShoot(tttPlayer: TTTPlayer, item: ItemStack, state: Gun.State): Boolean {
|
||||
val ownState = state as State
|
||||
if (ownState.remainingShots == 0) return
|
||||
if (ownState.remainingShots == 0) return true
|
||||
|
||||
when(val currentAction = ownState.currentAction) {
|
||||
is Action.Cooldown -> throw ActionInProgressError()
|
||||
|
@ -82,6 +82,8 @@ object Shotgun: Gun(
|
|||
item.itemMeta = damageMeta as ItemMeta
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
class State: Gun.State(magazineSize)
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
package de.moritzruth.spigot_ttt.items.weapons.guns.impl
|
||||
|
||||
import com.connorlinfoot.actionbarapi.ActionBarAPI
|
||||
import de.moritzruth.spigot_ttt.CustomItems
|
||||
import de.moritzruth.spigot_ttt.game.players.Role
|
||||
import de.moritzruth.spigot_ttt.game.players.TTTPlayer
|
||||
import de.moritzruth.spigot_ttt.game.players.roles
|
||||
import de.moritzruth.spigot_ttt.items.Buyable
|
||||
import de.moritzruth.spigot_ttt.items.TTTItem
|
||||
import de.moritzruth.spigot_ttt.items.weapons.guns.Gun
|
||||
import de.moritzruth.spigot_ttt.utils.applyMeta
|
||||
import de.moritzruth.spigot_ttt.utils.hideInfo
|
||||
import org.bukkit.ChatColor
|
||||
import org.bukkit.entity.Item
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
object SidekickDeagle: Gun(
|
||||
stateClass = State::class,
|
||||
displayName = "${ChatColor.AQUA}${ChatColor.BOLD}Sidekick Deagle",
|
||||
damage = 0.1, // Not really
|
||||
cooldown = 1.0,
|
||||
magazineSize = 1,
|
||||
reloadTime = 0.0,
|
||||
itemMaterial = CustomItems.sidekickDeagle
|
||||
), Buyable {
|
||||
override val buyableBy = roles(Role.JACKAL)
|
||||
override val price = 1
|
||||
override val type = TTTItem.Type.PISTOL_LIKE
|
||||
override val buyLimit = 1
|
||||
|
||||
override val itemStack = ItemStack(CustomItems.sidekickDeagle).applyMeta {
|
||||
hideInfo()
|
||||
setDisplayName("${ChatColor.AQUA}${ChatColor.BOLD}Sidekick Deagle")
|
||||
lore = listOf(
|
||||
"",
|
||||
"${ChatColor.GOLD}Mache einen Spieler zu deinem Sidekick",
|
||||
"",
|
||||
"${ChatColor.RED}Nur ein Schuss"
|
||||
)
|
||||
}
|
||||
|
||||
override fun reload(tttPlayer: TTTPlayer, itemStack: ItemStack, state: Gun.State) {
|
||||
ActionBarAPI.sendActionBar(tttPlayer.player, "${ChatColor.RED}Du kannst diese Waffe nicht nachladen")
|
||||
}
|
||||
|
||||
override fun onHit(tttPlayer: TTTPlayer, hitTTTPlayer: TTTPlayer) {
|
||||
hitTTTPlayer.changeRole(Role.SIDEKICK)
|
||||
}
|
||||
|
||||
override fun onDrop(tttPlayer: TTTPlayer, itemEntity: Item): Boolean {
|
||||
val state = isc.get(tttPlayer) ?: return true
|
||||
|
||||
return if (tttPlayer.role != Role.JACKAL || state.remainingShots == 0) {
|
||||
isc.remove(tttPlayer)
|
||||
itemEntity.remove()
|
||||
state.currentAction?.task?.cancel()
|
||||
true
|
||||
} else false
|
||||
}
|
||||
|
||||
override fun onBeforeShoot(tttPlayer: TTTPlayer, item: ItemStack, state: Gun.State): Boolean {
|
||||
if (tttPlayer.role != Role.JACKAL) {
|
||||
ActionBarAPI.sendActionBar(tttPlayer.player, "${ChatColor.RED}Diese Waffe kann nur der Jackal benutzen")
|
||||
return false
|
||||
}
|
||||
|
||||
return super.onBeforeShoot(tttPlayer, item, state)
|
||||
}
|
||||
|
||||
class State: Gun.State(magazineSize)
|
||||
}
|
||||
|
||||
|
|
@ -36,6 +36,7 @@ object BaseballBat: TTTItem, Buyable, Selectable {
|
|||
}
|
||||
override val buyableBy = roles(Role.TRAITOR, Role.JACKAL)
|
||||
override val price = 1
|
||||
override val buyLimit: Int? = null
|
||||
|
||||
override fun onSelect(tttPlayer: TTTPlayer) {
|
||||
tttPlayer.player.walkSpeed = 0.3F
|
||||
|
|
|
@ -34,6 +34,7 @@ object Knife: TTTItem, Buyable {
|
|||
override val buyableBy = roles(Role.TRAITOR, Role.JACKAL)
|
||||
override val price = 1
|
||||
override val type = TTTItem.Type.MELEE
|
||||
override val buyLimit = 1
|
||||
|
||||
override val listener = object : Listener {
|
||||
@EventHandler
|
||||
|
|
|
@ -5,7 +5,9 @@ import de.moritzruth.spigot_ttt.game.players.PlayerManager
|
|||
import de.moritzruth.spigot_ttt.game.players.TTTPlayer
|
||||
import de.moritzruth.spigot_ttt.items.Buyable
|
||||
import de.moritzruth.spigot_ttt.items.ItemManager
|
||||
import de.moritzruth.spigot_ttt.items.TTTItem
|
||||
import de.moritzruth.spigot_ttt.plugin
|
||||
import de.moritzruth.spigot_ttt.utils.applyMeta
|
||||
import de.moritzruth.spigot_ttt.utils.secondsToTicks
|
||||
import org.bukkit.ChatColor
|
||||
import org.bukkit.scheduler.BukkitTask
|
||||
|
@ -21,29 +23,29 @@ object Shop {
|
|||
|
||||
private var creditsTimer: BukkitTask? = null
|
||||
|
||||
fun getBuyableItems(tttPlayer: TTTPlayer) = ItemManager.ITEMS.filter { it is Buyable && it.buyableBy.contains(tttPlayer.role) }.toSet()
|
||||
private fun getBuyableItems(tttPlayer: TTTPlayer) = ItemManager.ITEMS.filter { it is Buyable && it.buyableBy.contains(tttPlayer.role) }.toSet()
|
||||
|
||||
fun show(tttPlayer: TTTPlayer) {
|
||||
fun setItems(tttPlayer: TTTPlayer) {
|
||||
clear(tttPlayer)
|
||||
val itemsIterator = getBuyableItems(tttPlayer).iterator()
|
||||
|
||||
for(index in SHOP_SLOTS) {
|
||||
if (!itemsIterator.hasNext()) break
|
||||
|
||||
val tttItem = itemsIterator.next()
|
||||
val itemStack = tttItem.itemStack.clone()
|
||||
val meta = itemStack.itemMeta!!
|
||||
meta.setDisplayName(meta.displayName + "${ChatColor.RESET} - ${ChatColor.BOLD}$${(tttItem as Buyable).price}")
|
||||
itemStack.itemMeta = meta
|
||||
if (tttItem !is Buyable) throw Error("Item is not buyable")
|
||||
|
||||
tttPlayer.player.inventory.setItem(index, itemStack)
|
||||
tttPlayer.player.inventory.setItem(index, tttItem.itemStack.clone().applyMeta {
|
||||
val displayNameSuffix =
|
||||
if (isOutOfStock(tttPlayer, tttItem)) "${ChatColor.RED}Ausverkauft"
|
||||
else "$${tttItem.price}"
|
||||
|
||||
setDisplayName("$displayName${ChatColor.RESET} - ${ChatColor.BOLD}$displayNameSuffix")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun hide(tttPlayer: TTTPlayer) {
|
||||
val range = 9..19
|
||||
|
||||
range + (1..8)
|
||||
|
||||
fun clear(tttPlayer: TTTPlayer) {
|
||||
for(index in 9..35) tttPlayer.player.inventory.clear(index) // All slots except the hotbar and armor
|
||||
}
|
||||
|
||||
|
@ -62,4 +64,9 @@ object Shop {
|
|||
fun stopCreditsTimer() {
|
||||
creditsTimer?.cancel()
|
||||
}
|
||||
|
||||
fun isOutOfStock(tttPlayer: TTTPlayer, tttItem: TTTItem): Boolean {
|
||||
if (tttItem !is Buyable) throw Error("Item is not buyable")
|
||||
return tttItem.buyLimit != null && tttPlayer.boughtItems.filter { it == tttItem }.count() >= tttItem.buyLimit!!
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,17 +36,23 @@ object ShopListener: Listener {
|
|||
val tttItem = ItemManager.getItemByItemStack(itemStack)
|
||||
if (tttItem === null || tttItem !is Buyable || !tttItem.buyableBy.contains(tttPlayer.role)) return
|
||||
|
||||
if (tttPlayer.credits < tttItem.price) {
|
||||
ActionBarAPI.sendActionBar(tttPlayer.player, "${ChatColor.RED}Du hast nicht genug Credits")
|
||||
}
|
||||
when {
|
||||
Shop.isOutOfStock(tttPlayer, tttItem) ->
|
||||
ActionBarAPI.sendActionBar(tttPlayer.player, "${ChatColor.RED}Dieses Item ist ausverkauft")
|
||||
|
||||
try {
|
||||
tttPlayer.addItem(tttItem)
|
||||
tttPlayer.credits -= tttItem.price
|
||||
} catch (e: TTTPlayer.AlreadyHasItemException) {
|
||||
ActionBarAPI.sendActionBar(tttPlayer.player, "${ChatColor.RED}Du hast dieses Item bereits")
|
||||
} catch (e: TTTPlayer.TooManyItemsOfTypeException) {
|
||||
ActionBarAPI.sendActionBar(tttPlayer.player, "${ChatColor.RED}Du hast keinen Platz dafür")
|
||||
tttPlayer.credits < tttItem.price ->
|
||||
ActionBarAPI.sendActionBar(tttPlayer.player, "${ChatColor.RED}Du hast nicht genug Credits")
|
||||
|
||||
else -> try {
|
||||
tttPlayer.addItem(tttItem)
|
||||
tttPlayer.boughtItems.add(tttItem)
|
||||
tttPlayer.credits -= tttItem.price
|
||||
Shop.setItems(tttPlayer)
|
||||
} catch (e: TTTPlayer.AlreadyHasItemException) {
|
||||
ActionBarAPI.sendActionBar(tttPlayer.player, "${ChatColor.RED}Du hast dieses Item bereits")
|
||||
} catch (e: TTTPlayer.TooManyItemsOfTypeException) {
|
||||
ActionBarAPI.sendActionBar(tttPlayer.player, "${ChatColor.RED}Du hast keinen Platz dafür")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue