Removed explosive potion AoE, temp backdoor thieving success changes

This commit is contained in:
dam 2026-05-11 16:55:07 +03:00
parent 8fb52b6eda
commit 87210b4b3c
No known key found for this signature in database
GPG key ID: 4AF4E722399663FB
5 changed files with 138 additions and 28 deletions

View file

@ -86,14 +86,14 @@ object CastleWarsConstants {
const val ENERGY_BARRIER_DRAIN = 4.0
// ==================== Backdoor Pick-Lock ====================
/** Thieving level required for pick-lock (1 = no real requirement, all players can attempt) */
const val BACKDOOR_PICKLOCK_LEVEL = 1
/** Thieving level required for pick-lock, matching Knight of Ardougne pickpocketing */
const val BACKDOOR_PICKLOCK_LEVEL = 55
/** Base pick-lock success chance (out of 100) at minimum level */
const val BACKDOOR_PICKLOCK_BASE_CHANCE = 50
/** Low roll bound for pick-lock success, matching Knight of Ardougne pickpocketing */
const val BACKDOOR_PICKLOCK_LOW = 50.0
/** Maximum pick-lock success chance (out of 100) */
const val BACKDOOR_PICKLOCK_MAX_CHANCE = 95
/** High roll bound for pick-lock success, matching Knight of Ardougne pickpocketing */
const val BACKDOOR_PICKLOCK_HIGH = 240.0
/** Ticks to lock player during pick-lock attempt */
const val BACKDOOR_PICKLOCK_TICKS = 3

View file

@ -219,8 +219,6 @@ class CastleWarsItemHandler : InteractionListener {
}
cleanupDeadBarricades()
dealExplosiveAoeDamage(player, player.location)
return@on true
}
@ -348,4 +346,3 @@ class CastleWarsItemHandler : InteractionListener {
.filter { it.id in barricadeIds && it.isActive }
}
}

View file

@ -15,6 +15,7 @@ import core.game.global.action.SpecialLadders
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import core.game.node.entity.player.link.TeleportManager
import core.game.node.item.Item
import core.game.node.scenery.Scenery
@ -27,6 +28,7 @@ import core.game.world.map.RegionManager
import core.game.world.update.flag.chunk.ObjectUpdateFlag
import core.game.world.update.flag.context.Animation
import core.tools.Log
import core.tools.RandomFunction
import org.rs09.consts.Components
import org.rs09.consts.Items
import org.rs09.consts.Sounds
@ -48,24 +50,24 @@ private val barrierCoordinates: Map<Int, List<BarrierData>> = mapOf(
BarrierData(
Location.create(2373, 3127, 1), Direction.WEST,
Location.create(2373, 3126, 1),
Location.create(2373, 3128, 1)
Location.create(2373, 3127, 1)
),
BarrierData(
Location.create(2376, 3131, 1), Direction.SOUTH,
Location.create(2377, 3131, 1),
Location.create(2375, 3131, 1)
Location.create(2376, 3131, 1)
)
),
CastleWars.saradominEnergyBarrier to listOf(
BarrierData(
Location.create(2426, 3080, 1),
Direction.EAST, Location.create(2426, 3081, 1),
Location.create(2426, 3079, 1)
Location.create(2426, 3080, 1)
),
BarrierData(
Location.create(2423, 3076, 1), Direction.NORTH,
Location.create(2422, 3076, 1),
Location.create(2424, 3076, 1)
Location.create(2423, 3076, 1)
)
)
)
@ -142,6 +144,9 @@ internal fun isOnClimbingRopeBaseSide(playerLoc: Location, rope: Scenery): Boole
}
internal fun getClimbingRopeInteractionDestination(playerLoc: Location, rope: Scenery): Location {
if (playerLoc == rope.location) {
return playerLoc
}
val traversal = getClimbingRopeTraversal(rope)
return if (isOnClimbingRopeBaseSide(playerLoc, rope)) {
traversal.baseOfWallTile
@ -151,7 +156,15 @@ internal fun getClimbingRopeInteractionDestination(playerLoc: Location, rope: Sc
}
internal fun canClimbUpClimbingRope(playerLoc: Location, rope: Scenery): Boolean {
return playerLoc == getClimbingRopeTraversal(rope).baseOfWallTile
return playerLoc == rope.location || playerLoc == getClimbingRopeTraversal(rope).baseOfWallTile
}
internal fun getBackdoorPicklockSuccessChance(thievingLevel: Int): Double {
return RandomFunction.getSkillSuccessChance(
CastleWarsConstants.BACKDOOR_PICKLOCK_LOW,
CastleWarsConstants.BACKDOOR_PICKLOCK_HIGH,
thievingLevel
)
}
class CastleWarsListeners : InteractionListener {
@ -567,19 +580,21 @@ class CastleWarsListeners : InteractionListener {
sendMessage(player, "You can't pick the lock from this side.")
return@on true
}
val thievingLevel = player.skills.getLevel(Skills.THIEVING)
if (thievingLevel < CastleWarsConstants.BACKDOOR_PICKLOCK_LEVEL) {
sendMessage(
player,
"You need a Thieving level of ${CastleWarsConstants.BACKDOOR_PICKLOCK_LEVEL} to pick this lock."
)
return@on true
}
lock(player, CastleWarsConstants.BACKDOOR_PICKLOCK_TICKS)
animate(player, 2246)
sendMessage(player, "You attempt to pick the lock...")
val thievingLevel = player.skills.getLevel(core.game.node.entity.skill.Skills.THIEVING)
val successChance = (CastleWarsConstants.BACKDOOR_PICKLOCK_BASE_CHANCE +
(thievingLevel - CastleWarsConstants.BACKDOOR_PICKLOCK_LEVEL))
.coerceIn(
CastleWarsConstants.BACKDOOR_PICKLOCK_BASE_CHANCE,
CastleWarsConstants.BACKDOOR_PICKLOCK_MAX_CHANCE
)
val successChance = getBackdoorPicklockSuccessChance(thievingLevel)
runTask(player, CastleWarsConstants.BACKDOOR_PICKLOCK_TICKS) {
if ((1..100).random() <= successChance) {
if (RandomFunction.randomDouble(1.0, 100.0) <= successChance) {
openBackdoor(player, door)
sendMessage(player, "You successfully pick the lock!")
} else {
@ -589,7 +604,7 @@ class CastleWarsListeners : InteractionListener {
return@on true
}
on(CastleWars.backdoorOpenIds, IntType.SCENERY, "Close") { player, node ->
on(CastleWars.backdoorOpenIds, IntType.SCENERY, "Close", "Lock") { player, node ->
val door = node.asScenery()
val doorTeam = if (door.id == CastleWars.saradominBackdoorOpen) CastleWarsTeam.SARADOMIN
else CastleWarsTeam.ZAMORAK

View file

@ -35,7 +35,7 @@ object CatapultConfig {
const val DEFAULT_X = CastleWarsConstants.CATAPULT_DEFAULT_X
const val DEFAULT_Y = CastleWarsConstants.CATAPULT_DEFAULT_Y
const val CENTER_OFFSET = 15
const val HORIZONTAL_TILE_SCALE = 2
const val TILE_SCALE = 2
const val SOUND_FIRE = 1440
const val SOUND_IMPACT = 851
@ -82,21 +82,21 @@ enum class CatapultButton(val buttonId: Int, val deltaX: Int, val deltaY: Int) {
enum class CatapultTeam {
SARADOMIN {
override fun calculateTargetX(catapultX: Int, interfaceX: Int): Int {
return catapultX + ((interfaceX - CatapultConfig.CENTER_OFFSET) * CatapultConfig.HORIZONTAL_TILE_SCALE)
return catapultX + ((interfaceX - CatapultConfig.CENTER_OFFSET) * CatapultConfig.TILE_SCALE)
}
override fun calculateTargetY(catapultY: Int, interfaceY: Int): Int {
return catapultY + interfaceY
return catapultY + (interfaceY * CatapultConfig.TILE_SCALE)
}
},
ZAMORAK {
override fun calculateTargetX(catapultX: Int, interfaceX: Int): Int {
return catapultX - ((interfaceX - CatapultConfig.CENTER_OFFSET) * CatapultConfig.HORIZONTAL_TILE_SCALE)
return catapultX - ((interfaceX - CatapultConfig.CENTER_OFFSET) * CatapultConfig.TILE_SCALE)
}
override fun calculateTargetY(catapultY: Int, interfaceY: Int): Int {
return catapultY - interfaceY
return catapultY - (interfaceY * CatapultConfig.TILE_SCALE)
}
};

View file

@ -3,16 +3,20 @@ package content.minigame.castlewars
import TestUtils
import content.minigame.castlewars.areas.CastleWarsGameArea
import content.minigame.castlewars.areas.CastleWarsWaitingArea
import content.global.skill.thieving.Pickpockets
import core.api.EquipmentSlot
import core.game.node.entity.skill.Skills
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.node.scenery.Scenery
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.Test
@ -26,6 +30,13 @@ class CastleWarsTests {
if (InteractionListeners.get("equip", IntType.ITEM.ordinal) == null) {
EquipHandler().defineListeners()
}
if (InteractionListeners.get(CastleWars.saradominBackdoorOpen, IntType.SCENERY.ordinal, "lock") == null) {
CastleWarsListeners().defineDestinationOverrides()
CastleWarsListeners().defineListeners()
}
if (InteractionListeners.get(CastleWars.cwExplosivePotion, IntType.ITEM.ordinal, "drop") == null) {
CastleWarsItemHandler().defineListeners()
}
}
}
@ -176,4 +187,91 @@ class CastleWarsTests {
}
}
}
@Test
fun ownTeamBackdoorLockOptionIsHandled() {
assertNotNull(
InteractionListeners.get(CastleWars.saradominBackdoorOpen, IntType.SCENERY.ordinal, "lock")
)
assertNotNull(
InteractionListeners.get(CastleWars.zamorakBackdoorOpen, IntType.SCENERY.ordinal, "lock")
)
}
@Test
fun backdoorPicklockMatchesKnightOfArdougneDifficulty() {
TestUtils.getMockPlayer("cwthief").use { player ->
player.skills.setStaticLevel(Skills.THIEVING, CastleWarsConstants.BACKDOOR_PICKLOCK_LEVEL)
player.skills.setLevel(Skills.THIEVING, CastleWarsConstants.BACKDOOR_PICKLOCK_LEVEL)
assertEquals(Pickpockets.KNIGHT_OF_ADROUGNE.requiredLevel, CastleWarsConstants.BACKDOOR_PICKLOCK_LEVEL)
assertEquals(
Pickpockets.KNIGHT_OF_ADROUGNE.getSuccessChance(player),
getBackdoorPicklockSuccessChance(player.skills.getLevel(Skills.THIEVING))
)
}
}
@Test
fun catapultInterfaceCoordinatesScaleByTwoTilesOnBothAxes() {
val handler = CatapultFiringHandler()
val catapult = Location.create(2400, 3100, 0)
val saradominBase = handler.calculateTargetLocation(CatapultTeam.SARADOMIN, catapult, Coordinate(8, 13))
val saradominEast = handler.calculateTargetLocation(CatapultTeam.SARADOMIN, catapult, Coordinate(9, 13))
val saradominNorth = handler.calculateTargetLocation(CatapultTeam.SARADOMIN, catapult, Coordinate(8, 14))
assertEquals(2, saradominEast.x - saradominBase.x)
assertEquals(2, saradominNorth.y - saradominBase.y)
val zamorakBase = handler.calculateTargetLocation(CatapultTeam.ZAMORAK, catapult, Coordinate(8, 13))
val zamorakEast = handler.calculateTargetLocation(CatapultTeam.ZAMORAK, catapult, Coordinate(9, 13))
val zamorakNorth = handler.calculateTargetLocation(CatapultTeam.ZAMORAK, catapult, Coordinate(8, 14))
assertEquals(-2, zamorakEast.x - zamorakBase.x)
assertEquals(-2, zamorakNorth.y - zamorakBase.y)
}
@Test
fun climbingRopeOnPlayerTileCanBeClimbed() {
val rope = Scenery(CastleWars.cwCastleClimbingRope, Location.create(2420, 3078, 1), 4, 0)
assertEquals(rope.location, getClimbingRopeInteractionDestination(rope.location, rope))
assertTrue(canClimbUpClimbingRope(rope.location, rope))
}
@Test
fun respawnEnergyBarrierPassesAcrossOneWallTile() {
val barrierTile = Location.create(2426, 3080, 1)
val outsideTile = Location.create(2426, 3081, 1)
val barrier = BarrierData(barrierTile, core.game.world.map.Direction.EAST, outsideTile, barrierTile)
assertEquals(outsideTile to barrierTile, getBarrierPassTiles(outsideTile, barrier))
assertEquals(barrierTile to outsideTile, getBarrierPassTiles(barrierTile, barrier))
}
@Test
fun droppingExplosivePotionOnlyDamagesDropper() {
TestUtils.getMockPlayer("cwexploder").use { dropper ->
TestUtils.getMockPlayer("cwtarget").use { target ->
dropper.location = Location.create(2400, 3100, 0)
target.location = Location.create(2401, 3100, 0)
dropper.skills.lifepoints = 50
target.skills.lifepoints = 50
CastleWarsGameArea.ticksLeftInGame = 100
CastleWarsGameArea.saradominPlayers.add(dropper)
CastleWarsGameArea.zamorakPlayers.add(target)
dropper.inventory.add(Item(CastleWars.cwExplosivePotion))
InteractionListeners.run(
CastleWars.cwExplosivePotion,
IntType.ITEM,
"drop",
dropper,
dropper.inventory[0]
)
assertEquals(35, dropper.skills.lifepoints)
assertEquals(50, target.skills.lifepoints)
}
}
}
}