mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2026-08-24 20:05:13 -06:00
Match idle dur to -1, logging out grace fix, head/cape fixes, flag carrying fixes, some tests
This commit is contained in:
parent
6b76a3f8d0
commit
8fb52b6eda
10 changed files with 266 additions and 5 deletions
|
|
@ -53,6 +53,8 @@ class CastleWarsCommands : Commands {
|
|||
val zamSnapshot = zamorakPlayers.toSet()
|
||||
CastleWarsGameState.endGame()
|
||||
CastleWarsItemHandler.clearAllBarricades()
|
||||
CastleWarsGameArea.ticksLeftInGame = -1
|
||||
CastleWarsWaitingArea.gameStartCountdown = -1
|
||||
for (p in saraSnapshot) {
|
||||
p.interaction.remove(Option._P_ATTACK)
|
||||
p.properties.teleportLocation = CastleWars.lobbyBankArea.randomWalkableLoc
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
package content.minigame.castlewars
|
||||
|
||||
import content.minigame.castlewars.areas.CastleWarsGameArea
|
||||
import content.minigame.castlewars.areas.CastleWarsRespawnArea
|
||||
import content.minigame.castlewars.areas.CastleWarsWaitingArea
|
||||
import core.api.EquipmentSlot
|
||||
import core.api.sendMessage
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.GroundItemManager
|
||||
|
||||
object CastleWarsEquipmentRestrictions {
|
||||
private val restrictedSlots = intArrayOf(
|
||||
EquipmentSlot.HEAD.ordinal,
|
||||
EquipmentSlot.CAPE.ordinal
|
||||
)
|
||||
private val castleWarsTeamCapeIds = intArrayOf(
|
||||
CastleWars.saradominTeamHoodedCloak,
|
||||
CastleWars.zamorakTeamHoodedCloak
|
||||
)
|
||||
|
||||
fun blocksEquip(player: Player, equipmentSlot: Int): Boolean {
|
||||
if (equipmentSlot !in restrictedSlots || !isInCastleWarsArea(player)) {
|
||||
return false
|
||||
}
|
||||
|
||||
sendMessage(player, "You can't wear hats, capes, or helms in the arena.")
|
||||
return true
|
||||
}
|
||||
|
||||
fun removeInvalidEquipment(player: Player) {
|
||||
removeEquipment(player, EquipmentSlot.HEAD.ordinal)
|
||||
|
||||
val cape = player.equipment[EquipmentSlot.CAPE.ordinal] ?: return
|
||||
if (cape.id !in castleWarsTeamCapeIds) {
|
||||
removeEquipment(player, EquipmentSlot.CAPE.ordinal)
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeEquipment(player: Player, slot: Int) {
|
||||
val item = player.equipment[slot] ?: return
|
||||
player.equipment.remove(item)
|
||||
if (!player.inventory.add(item)) {
|
||||
GroundItemManager.create(item.copy(), player.location, player)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isInCastleWarsArea(player: Player): Boolean {
|
||||
val allCastleWarsBorders = CastleWarsGameArea.areaBorders.toList() +
|
||||
CastleWarsWaitingArea.areaBorders.toList() +
|
||||
listOf(CastleWarsRespawnArea.saradominRespawnRoom, CastleWarsRespawnArea.zamorakRespawnRoom)
|
||||
return allCastleWarsBorders.any { it.insideBorder(player.location) }
|
||||
}
|
||||
}
|
||||
|
|
@ -513,7 +513,7 @@ object CastleWarsGameState {
|
|||
sendMessage(player, "You can't pick up your own team's flag!")
|
||||
return false
|
||||
}
|
||||
if (isCarryingFlag(player)) {
|
||||
if (isCarryingAnyFlag(player)) {
|
||||
sendMessage(player, "You're already carrying a flag!")
|
||||
return false
|
||||
}
|
||||
|
|
@ -1643,6 +1643,10 @@ object CastleWarsGameState {
|
|||
*/
|
||||
fun transferFlag(from: Player, to: Player) {
|
||||
val carriedFlag = getCarriedFlag(from) ?: return
|
||||
if (isCarryingAnyFlag(to)) {
|
||||
sendMessage(to, "You're already carrying a flag!")
|
||||
return
|
||||
}
|
||||
if (from.equipment.get(EquipmentContainer.SLOT_WEAPON)?.id == carriedFlag.flagItemId) {
|
||||
from.equipment.remove(Item(carriedFlag.flagItemId), EquipmentContainer.SLOT_WEAPON, true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,6 @@ class CastleWarsShutdownHandler : ShutdownListener {
|
|||
CastleWarsWaitingArea.waitingSaradominPlayers.clear()
|
||||
CastleWarsWaitingArea.waitingZamorakPlayers.clear()
|
||||
|
||||
CastleWarsGameArea.ticksLeftInGame = 0
|
||||
CastleWarsGameArea.ticksLeftInGame = -1
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package content.minigame.castlewars.areas
|
|||
|
||||
import content.global.skill.summoning.familiar.BurdenBeast
|
||||
import content.minigame.castlewars.CastleWars
|
||||
import content.minigame.castlewars.CastleWarsEquipmentRestrictions
|
||||
import core.api.LogoutListener
|
||||
import core.api.MapArea
|
||||
import core.api.removeTimer
|
||||
|
|
@ -12,6 +13,11 @@ import core.game.node.entity.player.Player
|
|||
|
||||
abstract class CastleWarsArea : MapArea, LogoutListener, InteractionListener {
|
||||
|
||||
override fun areaEnter(entity: Entity) {
|
||||
val player = entity as? Player ?: return
|
||||
CastleWarsEquipmentRestrictions.removeInvalidEquipment(player)
|
||||
}
|
||||
|
||||
override fun areaLeave(entity: Entity, logout: Boolean) {
|
||||
super.areaLeave(entity, logout)
|
||||
exitArea(entity as? Player ?: return)
|
||||
|
|
|
|||
|
|
@ -67,11 +67,12 @@ class CastleWarsGameArea : CastleWarsArea(), TickListener {
|
|||
/** Players who have logged out but are within the grace period. Maps Player -> logout tick. */
|
||||
val loggedOutPlayers = mutableMapOf<Player, Int>()
|
||||
|
||||
var ticksLeftInGame = 0
|
||||
var ticksLeftInGame = -1
|
||||
|
||||
fun startGame() {
|
||||
CastleWarsGameState.resetGame()
|
||||
CastleWarsItemHandler.clearAllBarricades()
|
||||
CastleWarsWaitingArea.gameStartCountdown = -1
|
||||
saradominPlayers.addAll(CastleWarsWaitingArea.waitingSaradominPlayers)
|
||||
zamorakPlayers.addAll(CastleWarsWaitingArea.waitingZamorakPlayers)
|
||||
CastleWarsWaitingArea.waitingSaradominPlayers.clear()
|
||||
|
|
@ -159,6 +160,7 @@ class CastleWarsGameArea : CastleWarsArea(), TickListener {
|
|||
CastleWarsWaitingArea.postGameCooldown = true
|
||||
CastleWarsGameState.endGame()
|
||||
CastleWarsItemHandler.clearAllBarricades()
|
||||
ticksLeftInGame = -1
|
||||
saradominPlayers.forEach { player ->
|
||||
player.unhook(SaradominInterfaceCloseHook)
|
||||
player.properties.teleportLocation = CastleWars.lobbyBankArea.randomWalkableLoc
|
||||
|
|
@ -242,6 +244,7 @@ class CastleWarsGameArea : CastleWarsArea(), TickListener {
|
|||
}
|
||||
CastleWarsGameState.clearHintIconForPlayer(player)
|
||||
// Do NOT remove from team sets -- grace period keeps them on the team
|
||||
return
|
||||
} else {
|
||||
// No active game or not on a team -- full cleanup
|
||||
CastleWarsGameState.handlePlayerLeave(player)
|
||||
|
|
@ -253,6 +256,13 @@ class CastleWarsGameArea : CastleWarsArea(), TickListener {
|
|||
}
|
||||
|
||||
override fun tick() {
|
||||
if (ticksLeftInGame < 0) {
|
||||
return
|
||||
}
|
||||
if (ticksLeftInGame == 0) {
|
||||
endGame()
|
||||
return
|
||||
}
|
||||
val previousMinutes = (ticksLeftInGame + ticksPerMinute - 1) / ticksPerMinute
|
||||
ticksLeftInGame--
|
||||
val currentMinutes = (ticksLeftInGame + ticksPerMinute - 1) / ticksPerMinute
|
||||
|
|
@ -266,6 +276,7 @@ class CastleWarsGameArea : CastleWarsArea(), TickListener {
|
|||
}
|
||||
if (ticksLeftInGame == 0) {
|
||||
endGame()
|
||||
return
|
||||
} else if (currentMinutes != previousMinutes) {
|
||||
CastleWarsGameState.updateAllOverlays()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ class CastleWarsRespawnArea : CastleWarsArea(), TickListener {
|
|||
|
||||
override fun areaEnter(entity: Entity) {
|
||||
val player = entity as? Player ?: return
|
||||
super.areaEnter(player)
|
||||
if (CastleWarsGameState.isCarryingAnyFlag(player)) {
|
||||
if (CastleWarsGameState.isCarryingFlag(player)) {
|
||||
CastleWarsGameState.dropFlag(player)
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ class CastleWarsWaitingArea : CastleWarsArea(), TickListener {
|
|||
override fun tick() {
|
||||
var nextStart = Int.MAX_VALUE
|
||||
// The game will start when there's enough players and CastleWarsGameArea.ticksLeftInGame = -5 minutes
|
||||
if (CastleWarsGameArea.ticksLeftInGame >= 0) {
|
||||
if (CastleWarsGameArea.ticksLeftInGame > 0) {
|
||||
// A game is going on, display 5 minutes + remaining game time
|
||||
gameStartCountdown = -1 // Reset countdown while game is active
|
||||
nextStart = CastleWarsGameArea.ticksLeftInGame + CastleWars.gameCooldownMinutes * ticksPerMinute
|
||||
|
|
@ -144,7 +144,7 @@ class CastleWarsWaitingArea : CastleWarsArea(), TickListener {
|
|||
for (player in waitingSaradominPlayers + waitingZamorakPlayers) {
|
||||
CastleWarsOverlay.sendLobbyUpdate(
|
||||
player,
|
||||
(waitingSaradominPlayers.size >= minPlayers && waitingZamorakPlayers.size >= minPlayers) || CastleWarsGameArea.ticksLeftInGame >= 0,
|
||||
(waitingSaradominPlayers.size >= minPlayers && waitingZamorakPlayers.size >= minPlayers) || CastleWarsGameArea.ticksLeftInGame > 0,
|
||||
(nextStart - 1) / ticksPerMinute + 1 // Displays max 5 minutes, min 1 minute, seems authentic
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package core.game.global.action
|
||||
|
||||
import content.minigame.castlewars.CastleWarsEquipmentRestrictions
|
||||
import core.game.event.ItemEquipEvent
|
||||
import core.game.event.ItemUnequipEvent
|
||||
import core.game.container.impl.EquipmentContainer
|
||||
|
|
@ -35,6 +36,10 @@ class EquipHandler : InteractionListener {
|
|||
val item = node.asItem()
|
||||
val itemEquipmentSlot = item.definition.getConfiguration<Int>(ItemConfigParser.EQUIP_SLOT, -1)
|
||||
|
||||
if (CastleWarsEquipmentRestrictions.blocksEquip(player, itemEquipmentSlot)) {
|
||||
return
|
||||
}
|
||||
|
||||
val currentEquippedItem = player.equipment[itemEquipmentSlot]
|
||||
if (item == null || currentEquippedItem == item || item.name.toLowerCase().contains("goblin mail")) {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -0,0 +1,179 @@
|
|||
package content.minigame.castlewars
|
||||
|
||||
import TestUtils
|
||||
import content.minigame.castlewars.areas.CastleWarsGameArea
|
||||
import content.minigame.castlewars.areas.CastleWarsWaitingArea
|
||||
import core.api.EquipmentSlot
|
||||
import core.game.global.action.EquipHandler
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.InteractionListeners
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.Location
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertFalse
|
||||
import org.junit.jupiter.api.Assertions.assertNull
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class CastleWarsTests {
|
||||
|
||||
companion object {
|
||||
init {
|
||||
TestUtils.preTestSetup()
|
||||
if (InteractionListeners.get("equip", IntType.ITEM.ordinal) == null) {
|
||||
EquipHandler().defineListeners()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun cleanup() {
|
||||
CastleWarsGameArea.saradominPlayers.clear()
|
||||
CastleWarsGameArea.zamorakPlayers.clear()
|
||||
CastleWarsGameArea.loggedOutPlayers.clear()
|
||||
CastleWarsWaitingArea.waitingSaradominPlayers.clear()
|
||||
CastleWarsWaitingArea.waitingZamorakPlayers.clear()
|
||||
CastleWarsWaitingArea.gameStartCountdown = -1
|
||||
CastleWarsWaitingArea.postGameCooldown = false
|
||||
CastleWarsGameArea.ticksLeftInGame = -1
|
||||
CastleWarsGameState.resetGame()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun idleGameAreaTickDoesNotCountDownForever() {
|
||||
CastleWarsGameArea.ticksLeftInGame = -1
|
||||
|
||||
CastleWarsGameArea().tick()
|
||||
|
||||
assertEquals(-1, CastleWarsGameArea.ticksLeftInGame)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun matchEndReturnsLifecycleToIdle() {
|
||||
CastleWarsGameArea.ticksLeftInGame = 1
|
||||
|
||||
CastleWarsGameArea().tick()
|
||||
|
||||
assertEquals(-1, CastleWarsGameArea.ticksLeftInGame)
|
||||
assertTrue(CastleWarsWaitingArea.postGameCooldown)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun activeGameLogoutKeepsPlayerInGraceSet() {
|
||||
TestUtils.getMockPlayer("cwlogout").use { player ->
|
||||
val startLocation = Location.create(2400, 3100, 0)
|
||||
player.location = startLocation
|
||||
CastleWarsGameArea.ticksLeftInGame = 100
|
||||
CastleWarsGameArea.saradominPlayers.add(player)
|
||||
|
||||
CastleWarsGameArea().logout(player)
|
||||
|
||||
assertTrue(CastleWarsGameArea.saradominPlayers.contains(player))
|
||||
assertTrue(CastleWarsGameArea.loggedOutPlayers.containsKey(player))
|
||||
assertEquals(startLocation, player.location)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun castleWarsPlayersCannotEquipHelmsAfterEntry() {
|
||||
TestUtils.getMockPlayer("cwhelm").use { player ->
|
||||
player.location = Location.create(2380, 9490, 0)
|
||||
player.inventory.add(Item(Items.BRONZE_FULL_HELM_1155))
|
||||
|
||||
InteractionListeners.run(
|
||||
Items.BRONZE_FULL_HELM_1155,
|
||||
IntType.ITEM,
|
||||
"wear",
|
||||
player,
|
||||
player.inventory[0]
|
||||
)
|
||||
|
||||
assertNull(player.equipment[EquipmentSlot.HEAD.ordinal])
|
||||
assertTrue(player.inventory.contains(Items.BRONZE_FULL_HELM_1155, 1))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun castleWarsPlayersCannotManuallyEquipTeamCloaksAfterEntry() {
|
||||
TestUtils.getMockPlayer("cwcloak").use { player ->
|
||||
player.location = Location.create(2380, 9490, 0)
|
||||
player.inventory.add(Item(Items.HOODED_CLOAK_4041))
|
||||
|
||||
InteractionListeners.run(
|
||||
Items.HOODED_CLOAK_4041,
|
||||
IntType.ITEM,
|
||||
"wear",
|
||||
player,
|
||||
player.inventory[0]
|
||||
)
|
||||
|
||||
assertNull(player.equipment[EquipmentSlot.CAPE.ordinal])
|
||||
assertTrue(player.inventory.contains(Items.HOODED_CLOAK_4041, 1))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun castleWarsRestrictionDoesNotReplaceNormalEquipListenersOutsideArena() {
|
||||
var didRun = false
|
||||
object : InteractionListener {
|
||||
override fun defineListeners() {
|
||||
onEquip(Items.BRONZE_MED_HELM_1139) { _, _ ->
|
||||
didRun = true
|
||||
return@onEquip true
|
||||
}
|
||||
}
|
||||
}.defineListeners()
|
||||
|
||||
TestUtils.getMockPlayer("cwoutside").use { player ->
|
||||
player.location = Location.create(3222, 3222, 0)
|
||||
player.inventory.add(Item(Items.BRONZE_MED_HELM_1139))
|
||||
|
||||
InteractionListeners.run(
|
||||
Items.BRONZE_MED_HELM_1139,
|
||||
IntType.ITEM,
|
||||
"wear",
|
||||
player,
|
||||
player.inventory[0]
|
||||
)
|
||||
|
||||
assertTrue(didRun)
|
||||
assertEquals(Items.BRONZE_MED_HELM_1139, player.equipment[EquipmentSlot.HEAD.ordinal]?.id)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun castleWarsAreaEntryRemovesBypassedHelms() {
|
||||
TestUtils.getMockPlayer("cwentryhelm").use { player ->
|
||||
player.location = CastleWarsWaitingArea.saradominWaitingRoom.randomWalkableLoc
|
||||
player.equipment.replace(Item(Items.BRONZE_FULL_HELM_1155), EquipmentSlot.HEAD.ordinal)
|
||||
|
||||
CastleWarsWaitingArea().areaEnter(player)
|
||||
|
||||
assertNull(player.equipment[EquipmentSlot.HEAD.ordinal])
|
||||
assertTrue(player.inventory.contains(Items.BRONZE_FULL_HELM_1155, 1))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun ownFlagCarrierCannotPickUpEnemyFlag() {
|
||||
TestUtils.getMockPlayer("cwsara").use { saradomin ->
|
||||
TestUtils.getMockPlayer("cwzam").use { zamorak ->
|
||||
saradomin.location = Location.create(2400, 3100, 0)
|
||||
zamorak.location = Location.create(2401, 3100, 0)
|
||||
CastleWarsGameArea.saradominPlayers.add(saradomin)
|
||||
CastleWarsGameArea.zamorakPlayers.add(zamorak)
|
||||
|
||||
assertTrue(CastleWarsGameState.pickUpFlag(zamorak, CastleWarsTeam.SARADOMIN))
|
||||
CastleWarsGameState.dropFlag(zamorak)
|
||||
assertTrue(CastleWarsGameState.pickUpOwnFlag(saradomin, CastleWarsTeam.SARADOMIN))
|
||||
|
||||
assertFalse(CastleWarsGameState.pickUpFlag(saradomin, CastleWarsTeam.ZAMORAK))
|
||||
assertTrue(CastleWarsGameState.isCarryingOwnFlag(saradomin))
|
||||
assertFalse(CastleWarsGameState.isCarryingFlag(saradomin))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue