mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2026-08-24 20:05:13 -06:00
Catapult cooldown
Player who fires catapult has to wait for their shot to land before being able to operate catapult again
This commit is contained in:
parent
7d72b4b09d
commit
eca0f81a1c
5 changed files with 115 additions and 48 deletions
|
|
@ -53,6 +53,11 @@ class CastleWarsCatapultInterface : InterfaceListener {
|
|||
}
|
||||
|
||||
private fun handleFire(player: Player, coord: Coordinate, team: CastleWarsTeam): Boolean {
|
||||
if (CatapultFiringHandler.hasShotInFlight(player)) {
|
||||
CatapultFiringHandler.sendShotInFlightMessage(player)
|
||||
return closeAndReturn(player, true)
|
||||
}
|
||||
|
||||
if (!hasRocks(player)) {
|
||||
sendMessage(player, "You don't have any rocks to fire!")
|
||||
return true
|
||||
|
|
|
|||
|
|
@ -228,8 +228,8 @@ class CastleWarsListeners : InteractionListener {
|
|||
} else {
|
||||
val formattedItemName =
|
||||
(ItemDefinition.forId(rewardItem).name.lowercase() + "s.").replace("pes.", "pe.").replace(
|
||||
"bronze ", ""
|
||||
)
|
||||
"bronze ", ""
|
||||
)
|
||||
|
||||
if (rewardItem == Items.TOOLKIT_4051) {
|
||||
sendDialogue(player, "Your inventory is too full to hold a toolkit.")
|
||||
|
|
@ -700,6 +700,10 @@ class CastleWarsListeners : InteractionListener {
|
|||
sendMessage(player, "The catapult is on fire! Use a bucket of water to extinguish it.")
|
||||
return@on true
|
||||
}
|
||||
if (CatapultFiringHandler.hasShotInFlight(player)) {
|
||||
CatapultFiringHandler.sendShotInFlightMessage(player)
|
||||
return@on true
|
||||
}
|
||||
if (!inInventory(player, CastleWars.cwRock)) {
|
||||
sendMessage(player, "You need rocks to fire the catapult!")
|
||||
return@on true
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ object CatapultConfig {
|
|||
const val INACCURACY_RADIUS = CastleWarsConstants.CATAPULT_INACCURACY_RADIUS
|
||||
|
||||
const val ATTR_LOCATION = "catapult:location"
|
||||
const val ATTR_SHOT_IN_FLIGHT = "catapult:shot-in-flight"
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -63,14 +64,10 @@ object CatapultConfig {
|
|||
*/
|
||||
enum class CatapultButton(val buttonId: Int, val deltaX: Int, val deltaY: Int) {
|
||||
LEFT(CatapultConfig.BUTTON_LEFT, -1, 0), RIGHT(CatapultConfig.BUTTON_RIGHT, 1, 0), UP(
|
||||
CatapultConfig.BUTTON_UP,
|
||||
0,
|
||||
1
|
||||
CatapultConfig.BUTTON_UP, 0, 1
|
||||
),
|
||||
DOWN(CatapultConfig.BUTTON_DOWN, 0, -1), FIRE(CatapultConfig.BUTTON_FIRE, 0, 0), CLOSE(
|
||||
CatapultConfig.BUTTON_CLOSE,
|
||||
0,
|
||||
0
|
||||
CatapultConfig.BUTTON_CLOSE, 0, 0
|
||||
),
|
||||
UNKNOWN(-1, 0, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package content.minigame.castlewars
|
||||
|
||||
import content.minigame.castlewars.CatapultConfig.ATTR_SHOT_IN_FLIGHT
|
||||
import content.minigame.castlewars.CatapultConfig.GFX_BOULDER_PROJECTILE
|
||||
import content.minigame.castlewars.CatapultConfig.GFX_IMPACT
|
||||
import content.minigame.castlewars.CatapultConfig.IMPACT_RADIUS
|
||||
|
|
@ -28,6 +29,24 @@ import core.tools.RandomFunction
|
|||
*/
|
||||
class CatapultFiringHandler {
|
||||
|
||||
companion object {
|
||||
internal fun hasShotInFlight(player: Player): Boolean {
|
||||
return getAttribute(player, ATTR_SHOT_IN_FLIGHT, false)
|
||||
}
|
||||
|
||||
internal fun markShotInFlight(player: Player) {
|
||||
setAttribute(player, ATTR_SHOT_IN_FLIGHT, true)
|
||||
}
|
||||
|
||||
internal fun clearShotInFlight(player: Player) {
|
||||
removeAttribute(player, ATTR_SHOT_IN_FLIGHT)
|
||||
}
|
||||
|
||||
internal fun sendShotInFlightMessage(player: Player) {
|
||||
sendMessage(player, "You need to wait for your previous catapult shot to land.")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires the catapult at the specified coordinates.
|
||||
* @param player The player firing the catapult
|
||||
|
|
@ -36,6 +55,13 @@ class CatapultFiringHandler {
|
|||
* @param catapultLocation The actual world location of the catapult
|
||||
*/
|
||||
fun fire(player: Player, coord: Coordinate, team: CatapultTeam, catapultLocation: Location) {
|
||||
if (hasShotInFlight(player)) {
|
||||
sendShotInFlightMessage(player)
|
||||
return
|
||||
}
|
||||
|
||||
markShotInFlight(player)
|
||||
|
||||
val targetLocation = calculateTargetLocation(team, catapultLocation, coord)
|
||||
val finalLocation = applyInaccuracy(targetLocation)
|
||||
|
||||
|
|
@ -94,22 +120,25 @@ class CatapultFiringHandler {
|
|||
private fun scheduleImpact(player: Player, targetLocation: Location, impactDelayTicks: Int) {
|
||||
submitWorldPulse(object : Pulse(impactDelayTicks) {
|
||||
override fun pulse(): Boolean {
|
||||
dealImpactDamage(player, targetLocation)
|
||||
try {
|
||||
dealImpactDamage(player, targetLocation)
|
||||
} finally {
|
||||
clearShotInFlight(player)
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun dealImpactDamage(attacker: Player, targetLocation: Location) {
|
||||
RegionManager.getLocalPlayers(targetLocation, IMPACT_RADIUS).filter { isValidTarget(it, attacker) }
|
||||
.forEach { target ->
|
||||
RegionManager.getLocalPlayers(targetLocation, IMPACT_RADIUS).filter { isValidTarget(it) }.forEach { target ->
|
||||
val damage = RandomFunction.random(MIN_DAMAGE, MAX_DAMAGE)
|
||||
target.impactHandler.manualHit(attacker, damage, ImpactHandler.HitsplatType.NORMAL)
|
||||
sendMessage(target, "You are hit by a catapult rock!")
|
||||
}
|
||||
}
|
||||
|
||||
private fun isValidTarget(target: Player, attacker: Player): Boolean {
|
||||
private fun isValidTarget(target: Player): Boolean {
|
||||
return CastleWarsGameState.getPlayerTeam(target) != null
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,23 +5,17 @@ import content.minigame.castlewars.areas.CastleWarsGameArea
|
|||
import content.minigame.castlewars.areas.CastleWarsRespawnArea
|
||||
import content.minigame.castlewars.areas.CastleWarsWaitingArea
|
||||
import core.api.*
|
||||
import core.game.interaction.Option
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.component.Component
|
||||
import core.game.global.action.EquipHandler
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.InteractionListeners
|
||||
import core.game.interaction.*
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.Item
|
||||
import core.game.node.scenery.Scenery
|
||||
import core.game.world.GameWorld
|
||||
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.assertNotNull
|
||||
import org.junit.jupiter.api.Assertions.assertNull
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.Assertions.*
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.rs09.consts.Items
|
||||
|
||||
|
|
@ -40,6 +34,9 @@ class CastleWarsTests {
|
|||
if (InteractionListeners.get(CastleWars.cwExplosivePotion, IntType.ITEM.ordinal, "drop") == null) {
|
||||
CastleWarsItemHandler().defineListeners()
|
||||
}
|
||||
if (InterfaceListeners.get(CatapultConfig.INTERFACE_ID) == null) {
|
||||
CastleWarsCatapultInterface().defineInterfaceListeners()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -440,11 +437,7 @@ class CastleWarsTests {
|
|||
player.inventory.add(Item(Items.BRONZE_FULL_HELM_1155))
|
||||
|
||||
InteractionListeners.run(
|
||||
Items.BRONZE_FULL_HELM_1155,
|
||||
IntType.ITEM,
|
||||
"wear",
|
||||
player,
|
||||
player.inventory[0]
|
||||
Items.BRONZE_FULL_HELM_1155, IntType.ITEM, "wear", player, player.inventory[0]
|
||||
)
|
||||
|
||||
assertNull(player.equipment[EquipmentSlot.HEAD.ordinal])
|
||||
|
|
@ -459,11 +452,7 @@ class CastleWarsTests {
|
|||
player.inventory.add(Item(Items.HOODED_CLOAK_4041))
|
||||
|
||||
InteractionListeners.run(
|
||||
Items.HOODED_CLOAK_4041,
|
||||
IntType.ITEM,
|
||||
"wear",
|
||||
player,
|
||||
player.inventory[0]
|
||||
Items.HOODED_CLOAK_4041, IntType.ITEM, "wear", player, player.inventory[0]
|
||||
)
|
||||
|
||||
assertNull(player.equipment[EquipmentSlot.CAPE.ordinal])
|
||||
|
|
@ -488,11 +477,7 @@ class CastleWarsTests {
|
|||
player.inventory.add(Item(Items.BRONZE_MED_HELM_1139))
|
||||
|
||||
InteractionListeners.run(
|
||||
Items.BRONZE_MED_HELM_1139,
|
||||
IntType.ITEM,
|
||||
"wear",
|
||||
player,
|
||||
player.inventory[0]
|
||||
Items.BRONZE_MED_HELM_1139, IntType.ITEM, "wear", player, player.inventory[0]
|
||||
)
|
||||
|
||||
assertTrue(didRun)
|
||||
|
|
@ -570,6 +555,59 @@ class CastleWarsTests {
|
|||
assertEquals(-2, zamorakNorth.y - zamorakBase.y)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun catapultShotInFlightBlocksOnlyShooterUntilLanding() {
|
||||
TestUtils.getMockPlayer("cwcatlock1").use { shooter ->
|
||||
TestUtils.getMockPlayer("cwcatlock2").use { other ->
|
||||
val catapult = Scenery(
|
||||
CastleWars.getOperationalCatapultId(CastleWarsTeam.SARADOMIN),
|
||||
CastleWarsGameState.saradominCatapultLocation,
|
||||
10,
|
||||
0
|
||||
)
|
||||
val operateCatapult = InteractionListeners.get(
|
||||
catapult.id, IntType.SCENERY.ordinal, "operate"
|
||||
)!!
|
||||
|
||||
CastleWarsGameArea.saradominPlayers.addAll(listOf(shooter, other))
|
||||
shooter.inventory.add(Item(CastleWars.cwRock, 2))
|
||||
other.inventory.add(Item(CastleWars.cwRock))
|
||||
|
||||
operateCatapult(shooter, catapult)
|
||||
assertTrue(shooter.interfaceManager.hasMainComponent(CatapultConfig.INTERFACE_ID))
|
||||
|
||||
InterfaceListeners.run(
|
||||
shooter, Component(CatapultConfig.INTERFACE_ID), 0, CatapultConfig.BUTTON_FIRE, 0, 0
|
||||
)
|
||||
|
||||
assertTrue(CatapultFiringHandler.hasShotInFlight(shooter))
|
||||
assertFalse(CatapultFiringHandler.hasShotInFlight(other))
|
||||
assertFalse(shooter.interfaceManager.hasMainComponent(CatapultConfig.INTERFACE_ID))
|
||||
|
||||
val rocksAfterFirstShot = shooter.inventory.getAmount(CastleWars.cwRock)
|
||||
shooter.setAttribute(CatapultConfig.ATTR_LOCATION, catapult.location)
|
||||
shooter.interfaceManager.open(Component(CatapultConfig.INTERFACE_ID))
|
||||
InterfaceListeners.run(
|
||||
shooter, Component(CatapultConfig.INTERFACE_ID), 0, CatapultConfig.BUTTON_FIRE, 0, 0
|
||||
)
|
||||
assertEquals(rocksAfterFirstShot, shooter.inventory.getAmount(CastleWars.cwRock))
|
||||
assertFalse(shooter.interfaceManager.hasMainComponent(CatapultConfig.INTERFACE_ID))
|
||||
|
||||
operateCatapult(shooter, catapult)
|
||||
assertFalse(shooter.interfaceManager.hasMainComponent(CatapultConfig.INTERFACE_ID))
|
||||
|
||||
operateCatapult(other, catapult)
|
||||
assertTrue(other.interfaceManager.hasMainComponent(CatapultConfig.INTERFACE_ID))
|
||||
|
||||
TestUtils.advanceTicks(10, false)
|
||||
|
||||
assertFalse(CatapultFiringHandler.hasShotInFlight(shooter))
|
||||
operateCatapult(shooter, catapult)
|
||||
assertTrue(shooter.interfaceManager.hasMainComponent(CatapultConfig.INTERFACE_ID))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun climbingRopeOnPlayerTileCanBeClimbed() {
|
||||
val rope = Scenery(CastleWars.cwCastleClimbingRope, Location.create(2420, 3078, 1), 4, 0)
|
||||
|
|
@ -602,11 +640,7 @@ class CastleWarsTests {
|
|||
dropper.inventory.add(Item(CastleWars.cwExplosivePotion))
|
||||
|
||||
InteractionListeners.run(
|
||||
CastleWars.cwExplosivePotion,
|
||||
IntType.ITEM,
|
||||
"drop",
|
||||
dropper,
|
||||
dropper.inventory[0]
|
||||
CastleWars.cwExplosivePotion, IntType.ITEM, "drop", dropper, dropper.inventory[0]
|
||||
)
|
||||
|
||||
assertEquals(35, dropper.skills.lifepoints)
|
||||
|
|
@ -634,7 +668,9 @@ class CastleWarsTests {
|
|||
TestUtils.getMockPlayer("cwbrace2").use { sara2 ->
|
||||
TestUtils.getMockPlayer("cwbracez1").use { zam1 ->
|
||||
TestUtils.getMockPlayer("cwbracez2").use { zam2 ->
|
||||
braceletPlayer.equipment.replace(Item(Items.CASTLEWAR_BRACE3_11079), EquipmentSlot.HANDS.ordinal)
|
||||
braceletPlayer.equipment.replace(
|
||||
Item(Items.CASTLEWAR_BRACE3_11079), EquipmentSlot.HANDS.ordinal
|
||||
)
|
||||
CastleWarsWaitingArea.waitingSaradominPlayers.addAll(listOf(braceletPlayer, sara2))
|
||||
CastleWarsWaitingArea.waitingZamorakPlayers.addAll(listOf(zam1, zam2))
|
||||
|
||||
|
|
@ -662,11 +698,7 @@ class CastleWarsTests {
|
|||
player.inventory.add(Item(CastleWars.cwBandages))
|
||||
|
||||
InteractionListeners.run(
|
||||
CastleWars.cwBandages,
|
||||
IntType.ITEM,
|
||||
"Heal",
|
||||
player,
|
||||
player.inventory[0]
|
||||
CastleWars.cwBandages, IntType.ITEM, "Heal", player, player.inventory[0]
|
||||
)
|
||||
|
||||
assertEquals(59, player.skills.lifepoints)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue