mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2026-08-25 04:15:14 -06:00
Cleanup, burning catapults, player cap removed, stepping stone fixes
This commit is contained in:
parent
f1bf63d353
commit
6b76a3f8d0
10 changed files with 155 additions and 209 deletions
|
|
@ -4,6 +4,7 @@ import content.minigame.castlewars.CastleWarsConstants.GAME_COOLDOWN_MINUTES
|
|||
import content.minigame.castlewars.CastleWarsConstants.GAME_TIME_MINUTES
|
||||
import content.minigame.castlewars.CastleWarsConstants.ROPE_DURATION_TICKS
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.RegionManager
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.NPCs
|
||||
|
|
@ -21,11 +22,22 @@ object CastleWars {
|
|||
const val castleWaterTap: Int = Scenery.TAP_4482
|
||||
const val cwSteppingStones: Int = Scenery.STEPPING_STONE_4411
|
||||
|
||||
// Stepping stone tile locations for flag auto-return check.
|
||||
// If a flag is dropped on any of these tiles, it immediately returns to base.
|
||||
private val steppingStoneLocations: Set<Location> by lazy(LazyThreadSafetyMode.NONE) {
|
||||
val locations = mutableSetOf<Location>()
|
||||
for (x in 2368..2431) {
|
||||
for (y in 3072..3135) {
|
||||
val location = Location.create(x, y, 0)
|
||||
if (RegionManager.getObject(location)?.id == cwSteppingStones) {
|
||||
locations += location
|
||||
}
|
||||
}
|
||||
}
|
||||
locations
|
||||
}
|
||||
|
||||
// Stepping stone tile locations are cached so dropped flag scenery cannot mask the underlying stone tile.
|
||||
fun isSteppingStoneTile(location: Location): Boolean {
|
||||
val obj = core.game.world.map.RegionManager.getObject(location)
|
||||
return obj != null && obj.id == cwSteppingStones
|
||||
return steppingStoneLocations.contains(Location.create(location))
|
||||
}
|
||||
|
||||
// Energy barriers
|
||||
|
|
@ -71,15 +83,24 @@ object CastleWars {
|
|||
const val tunnelRocksWeakened: Int = 4438 // Weakened rocks (1 explosive hit, still blocking)
|
||||
const val caveWall: Int = 4448 // Cave wall for causing collapse
|
||||
|
||||
// Catapults - can be operated, destroyed, and repaired
|
||||
// Both 4381 and 4382 are operational catapults (different orientations in the map)
|
||||
// Both 4385 and 4386 are damaged/destroyed catapults (have "Repair" option instead of "Operate")
|
||||
// Catapults - can be operated, set on fire, destroyed, and repaired.
|
||||
// 4381/4382 are the operational variants, 4904/4905 are the burning variants, 4385/4386 are damaged.
|
||||
const val catapult: Int = 4381 // Operational catapult variant 1
|
||||
const val catapultAlt: Int = 4382 // Operational catapult variant 2 (different orientation)
|
||||
const val catapultBurning1: Int = 4904 // Burning catapult variant 1
|
||||
const val catapultBurning2: Int = 4905 // Burning catapult variant 2
|
||||
const val catapultDamaged1: Int = 4385 // Damaged catapult variant 1
|
||||
const val catapultDamaged2: Int = 4386 // Damaged catapult variant 2
|
||||
val burningCatapultIds: IntArray = intArrayOf(catapultBurning1, catapultBurning2)
|
||||
val damagedCatapultIds: IntArray = intArrayOf(catapultDamaged1, catapultDamaged2)
|
||||
val allCatapultIds: IntArray = intArrayOf(catapult, catapultAlt, catapultDamaged1, catapultDamaged2)
|
||||
val allCatapultIds: IntArray = intArrayOf(
|
||||
catapult,
|
||||
catapultAlt,
|
||||
catapultBurning1,
|
||||
catapultBurning2,
|
||||
catapultDamaged1,
|
||||
catapultDamaged2
|
||||
)
|
||||
|
||||
fun getOperationalCatapultId(team: CastleWarsTeam): Int = when (team) {
|
||||
CastleWarsTeam.SARADOMIN -> catapultAlt
|
||||
|
|
@ -91,6 +112,11 @@ object CastleWars {
|
|||
CastleWarsTeam.ZAMORAK -> catapultDamaged1
|
||||
}
|
||||
|
||||
fun getBurningCatapultId(team: CastleWarsTeam): Int = when (team) {
|
||||
CastleWarsTeam.SARADOMIN -> catapultBurning2
|
||||
CastleWarsTeam.ZAMORAK -> catapultBurning1
|
||||
}
|
||||
|
||||
// Trapdoors - allow going down from 2nd floor to respawn room
|
||||
const val saradominTrapdoor: Int = 4471 // Saradomin castle trapdoor
|
||||
const val zamorakTrapdoor: Int = 4472 // Zamorak castle trapdoor
|
||||
|
|
@ -144,7 +170,7 @@ object CastleWars {
|
|||
const val cwBandages: Int = Items.BANDAGES_4049
|
||||
const val cwToolkit: Int = Items.TOOLKIT_4051
|
||||
const val cwBarricade: Int = Items.BARRICADE_4053
|
||||
const val cwManualBook: Int = Items.CASTLEWARS_MANUAL_4055 // TODO: unused? what happened
|
||||
const val cwManualBook: Int = Items.CASTLEWARS_MANUAL_4055
|
||||
const val cwTicketRewardCurrency: Int = Items.CASTLE_WARS_TICKET_4067
|
||||
|
||||
// Authoritative list of items to remove from players on game end or area exit.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import org.rs09.consts.NPCs
|
|||
/**
|
||||
* Custom NPC class for Castle Wars barricades.
|
||||
*
|
||||
* - Block all entity movement through them (like Pest Control Brawlers) TODO: so... it sucks? shit
|
||||
* - Block all entity movement through them (like Pest Control Brawlers)
|
||||
* - Never retaliate when attacked (this was scary man they squared up)
|
||||
* - Never turn to face attackers or any direction
|
||||
* - Cannot attack or move
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ object CastleWarsConstants {
|
|||
/** Grace period after picking up own flag before castle entry check (prevents instant return) */
|
||||
const val FLAG_RETURN_GRACE_PERIOD_TICKS = 3
|
||||
|
||||
/** Ticks before a dropped flag automatically returns to its stand (~90 seconds) */
|
||||
/** Ticks before a dropped flag automatically returns to its stand */
|
||||
const val FLAG_AUTO_RETURN_TICKS = 150
|
||||
|
||||
/** Duration of climbing ropes before despawning (45 seconds at 600ms/tick) */
|
||||
/** Duration of climbing ropes before despawning */
|
||||
const val ROPE_DURATION_TICKS = 75
|
||||
|
||||
/** Burning barricade pulse interval (3 ticks = 1.8 seconds) */
|
||||
|
|
@ -39,23 +39,20 @@ object CastleWarsConstants {
|
|||
/** Maximum barricades per team */
|
||||
const val MAX_BARRICADES_PER_TEAM = 10
|
||||
|
||||
/** Maximum players per team */
|
||||
const val MAX_PLAYERS_PER_TEAM = 25 // TODO: I dont believe this, where? Says who
|
||||
|
||||
/** Minimum players per team required to start a game */
|
||||
const val MIN_PLAYERS_PER_TEAM = 2
|
||||
|
||||
/** Catapult targeting inaccuracy radius */
|
||||
const val CATAPULT_INACCURACY_RADIUS = 2 // TODO: says who
|
||||
const val CATAPULT_INACCURACY_RADIUS = 2
|
||||
|
||||
/** Catapult impact damage radius */
|
||||
const val CATAPULT_IMPACT_RADIUS = 3 // TODO: says who
|
||||
const val CATAPULT_IMPACT_RADIUS = 3
|
||||
|
||||
/** Catapult minimum damage */
|
||||
const val CATAPULT_MIN_DAMAGE = 10 // TODO: says who
|
||||
const val CATAPULT_MIN_DAMAGE = 10
|
||||
|
||||
/** Catapult maximum damage */
|
||||
const val CATAPULT_MAX_DAMAGE = 20 // TODO: says who
|
||||
const val CATAPULT_MAX_DAMAGE = 20
|
||||
|
||||
// ==================== Coordinate Defaults ====================
|
||||
/** Default X coordinate for catapult targeting */
|
||||
|
|
@ -75,7 +72,7 @@ object CastleWarsConstants {
|
|||
const val BANDAGE_RUN_ENERGY_RESTORE = 30.0
|
||||
|
||||
/** Bandage cooldown in ticks (1 tick = faster than food's 2 ticks) */
|
||||
const val BANDAGE_COOLDOWN_TICKS = 1 // TODO: says who
|
||||
const val BANDAGE_COOLDOWN_TICKS = 1
|
||||
|
||||
// ==================== Castle Wars Bracelet ====================
|
||||
/** Bracelet damage bonus multiplier against flag carriers (20% extra) */
|
||||
|
|
@ -88,7 +85,7 @@ object CastleWarsConstants {
|
|||
/** Run energy drained when passing through an energy barrier */
|
||||
const val ENERGY_BARRIER_DRAIN = 4.0
|
||||
|
||||
// ==================== Backdoor Pick-Lock ==================== // TODO: says who
|
||||
// ==================== Backdoor Pick-Lock ====================
|
||||
/** Thieving level required for pick-lock (1 = no real requirement, all players can attempt) */
|
||||
const val BACKDOOR_PICKLOCK_LEVEL = 1
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import org.rs09.consts.Sounds
|
|||
* - Uses player's attack speed based on weapon
|
||||
* - Calculates damage based on combat stats
|
||||
* - Damages door health until destroyed or player stops
|
||||
* TODO: 100% wild guesses and needs a fat refactoring
|
||||
*/
|
||||
class CastleWarsDoorAttackPulse(
|
||||
private val player: Player,
|
||||
|
|
|
|||
|
|
@ -155,39 +155,6 @@ class CastleWarsFlagHandler : InteractionListener {
|
|||
}
|
||||
}
|
||||
|
||||
return@on true
|
||||
}
|
||||
// Legacy: Handle picking up dropped flags from the ground (ground items)
|
||||
// This is kept for backwards compatibility but scenery is the primary method now
|
||||
// TODO: cut
|
||||
on(intArrayOf(CastleWars.saradominFlag, CastleWars.zamorakFlag), IntType.GROUNDITEM, "take") { player, node ->
|
||||
if (!CastleWarsGameState.isGameActive) {
|
||||
return@on false
|
||||
}
|
||||
val playerTeam = CastleWarsGameState.getPlayerTeam(player) ?: return@on false
|
||||
val groundItem = node as? GroundItem ?: return@on false
|
||||
val flagTeam = when (groundItem.id) {
|
||||
CastleWars.saradominFlag -> CastleWarsTeam.SARADOMIN
|
||||
CastleWars.zamorakFlag -> CastleWarsTeam.ZAMORAK
|
||||
else -> return@on false
|
||||
}
|
||||
val isDroppedFlag = when (flagTeam) {
|
||||
CastleWarsTeam.SARADOMIN -> CastleWarsGameState.saradominFlagState == FlagState.DROPPED
|
||||
CastleWarsTeam.ZAMORAK -> CastleWarsGameState.zamorakFlagState == FlagState.DROPPED
|
||||
}
|
||||
if (!isDroppedFlag) {
|
||||
return@on false
|
||||
}
|
||||
if (flagTeam == playerTeam) {
|
||||
if (CastleWarsGameState.pickUpOwnFlag(player, flagTeam)) {
|
||||
return@on true
|
||||
}
|
||||
} else {
|
||||
if (CastleWarsGameState.pickUpFlag(player, flagTeam)) {
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -266,14 +266,8 @@ object CastleWarsGameState {
|
|||
for (key in boulderLocations.keys) {
|
||||
updateBoulderScenery(key, BoulderState.COLLAPSED)
|
||||
}
|
||||
replaceCatapultScenery(
|
||||
saradominCatapultLocation,
|
||||
CastleWars.getOperationalCatapultId(CastleWarsTeam.SARADOMIN)
|
||||
)
|
||||
replaceCatapultScenery(
|
||||
zamorakCatapultLocation,
|
||||
CastleWars.getOperationalCatapultId(CastleWarsTeam.ZAMORAK)
|
||||
)
|
||||
updateCatapultScenery(CastleWarsTeam.SARADOMIN)
|
||||
updateCatapultScenery(CastleWarsTeam.ZAMORAK)
|
||||
resetBattlefield()
|
||||
}
|
||||
|
||||
|
|
@ -575,23 +569,21 @@ object CastleWarsGameState {
|
|||
*/
|
||||
fun dropFlag(player: Player) {
|
||||
val carriedFlag = getCarriedFlag(player) ?: return
|
||||
val dropLocation = Location.create(player.location)
|
||||
val shouldReturnToStand = CastleWars.isSteppingStoneTile(dropLocation)
|
||||
when (carriedFlag) {
|
||||
CastleWarsTeam.SARADOMIN -> {
|
||||
saradominFlagCarrier = null
|
||||
saradominFlagState = FlagState.DROPPED
|
||||
val droppedFlag = Scenery(CastleWars.saradominDroppedFlagScenery, player.location, 10, 0)
|
||||
SceneryBuilder.add(droppedFlag)
|
||||
saradominDroppedFlagScenery = droppedFlag
|
||||
saradominFlagDroppedTick = getWorldTicks()
|
||||
if (!shouldReturnToStand) {
|
||||
addDroppedFlagScenery(CastleWarsTeam.SARADOMIN, dropLocation)
|
||||
}
|
||||
}
|
||||
|
||||
CastleWarsTeam.ZAMORAK -> {
|
||||
zamorakFlagCarrier = null
|
||||
zamorakFlagState = FlagState.DROPPED
|
||||
val droppedFlag = Scenery(CastleWars.zamorakDroppedFlagScenery, player.location, 10, 0)
|
||||
SceneryBuilder.add(droppedFlag)
|
||||
zamorakDroppedFlagScenery = droppedFlag
|
||||
zamorakFlagDroppedTick = getWorldTicks()
|
||||
if (!shouldReturnToStand) {
|
||||
addDroppedFlagScenery(CastleWarsTeam.ZAMORAK, dropLocation)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (player.equipment.get(EquipmentContainer.SLOT_WEAPON)?.id == carriedFlag.flagItemId) {
|
||||
|
|
@ -601,13 +593,12 @@ object CastleWarsGameState {
|
|||
player.inventory.remove(Item(carriedFlag.flagItemId))
|
||||
}
|
||||
removeAttribute(player, CastleWarsConstants.ATTR_FLAG_PICKUP_TICK)
|
||||
announceToAllPlayers("${carriedFlag.teamName} flag has been dropped!")
|
||||
updateAllOverlays()
|
||||
updateAllHintIcons()
|
||||
// Stepping stone auto-return: if the flag was dropped on a stepping stone tile,
|
||||
// immediately return it to the base stand (authentic RS behavior)
|
||||
if (CastleWars.isSteppingStoneTile(player.location)) {
|
||||
if (shouldReturnToStand) {
|
||||
returnFlagToStand(carriedFlag)
|
||||
} else {
|
||||
announceToAllPlayers("${carriedFlag.teamName} flag has been dropped!")
|
||||
updateAllOverlays()
|
||||
updateAllHintIcons()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -617,23 +608,21 @@ object CastleWarsGameState {
|
|||
*/
|
||||
fun dropOwnFlag(player: Player) {
|
||||
val carriedFlag = getOwnCarriedFlag(player) ?: return
|
||||
val dropLocation = Location.create(player.location)
|
||||
val shouldReturnToStand = CastleWars.isSteppingStoneTile(dropLocation)
|
||||
when (carriedFlag) {
|
||||
CastleWarsTeam.SARADOMIN -> {
|
||||
saradominOwnFlagCarrier = null
|
||||
saradominFlagState = FlagState.DROPPED
|
||||
val droppedFlag = Scenery(CastleWars.saradominDroppedFlagScenery, player.location, 10, 0)
|
||||
SceneryBuilder.add(droppedFlag)
|
||||
saradominDroppedFlagScenery = droppedFlag
|
||||
saradominFlagDroppedTick = getWorldTicks()
|
||||
if (!shouldReturnToStand) {
|
||||
addDroppedFlagScenery(CastleWarsTeam.SARADOMIN, dropLocation)
|
||||
}
|
||||
}
|
||||
|
||||
CastleWarsTeam.ZAMORAK -> {
|
||||
zamorakOwnFlagCarrier = null
|
||||
zamorakFlagState = FlagState.DROPPED
|
||||
val droppedFlag = Scenery(CastleWars.zamorakDroppedFlagScenery, player.location, 10, 0)
|
||||
SceneryBuilder.add(droppedFlag)
|
||||
zamorakDroppedFlagScenery = droppedFlag
|
||||
zamorakFlagDroppedTick = getWorldTicks()
|
||||
if (!shouldReturnToStand) {
|
||||
addDroppedFlagScenery(CastleWarsTeam.ZAMORAK, dropLocation)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (player.equipment.get(EquipmentContainer.SLOT_WEAPON)?.id == carriedFlag.flagItemId) {
|
||||
|
|
@ -642,13 +631,12 @@ object CastleWarsGameState {
|
|||
if (player.inventory.contains(carriedFlag.flagItemId, 1)) {
|
||||
player.inventory.remove(Item(carriedFlag.flagItemId))
|
||||
}
|
||||
announceToAllPlayers("${carriedFlag.teamName} flag has been dropped!")
|
||||
updateAllOverlays()
|
||||
updateAllHintIcons()
|
||||
// Stepping stone auto-return: if the flag was dropped on a stepping stone tile,
|
||||
// immediately return it to the base stand (authentic RS behavior)
|
||||
if (CastleWars.isSteppingStoneTile(player.location)) {
|
||||
if (shouldReturnToStand) {
|
||||
returnFlagToStand(carriedFlag)
|
||||
} else {
|
||||
announceToAllPlayers("${carriedFlag.teamName} flag has been dropped!")
|
||||
updateAllOverlays()
|
||||
updateAllHintIcons()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -660,25 +648,23 @@ object CastleWarsGameState {
|
|||
* @param dropLocation The location where the flag should be dropped
|
||||
*/
|
||||
fun dropFlagAtLocation(player: Player, dropLocation: Location) {
|
||||
val actualDropLocation = Location.create(dropLocation)
|
||||
val shouldReturnToStand = CastleWars.isSteppingStoneTile(actualDropLocation)
|
||||
val carriedEnemyFlag = getCarriedFlag(player)
|
||||
if (carriedEnemyFlag != null) {
|
||||
when (carriedEnemyFlag) {
|
||||
CastleWarsTeam.SARADOMIN -> {
|
||||
saradominFlagCarrier = null
|
||||
saradominFlagState = FlagState.DROPPED
|
||||
val droppedFlag = Scenery(CastleWars.saradominDroppedFlagScenery, dropLocation, 10, 0)
|
||||
SceneryBuilder.add(droppedFlag)
|
||||
saradominDroppedFlagScenery = droppedFlag
|
||||
saradominFlagDroppedTick = getWorldTicks()
|
||||
if (!shouldReturnToStand) {
|
||||
addDroppedFlagScenery(CastleWarsTeam.SARADOMIN, actualDropLocation)
|
||||
}
|
||||
}
|
||||
|
||||
CastleWarsTeam.ZAMORAK -> {
|
||||
zamorakFlagCarrier = null
|
||||
zamorakFlagState = FlagState.DROPPED
|
||||
val droppedFlag = Scenery(CastleWars.zamorakDroppedFlagScenery, dropLocation, 10, 0)
|
||||
SceneryBuilder.add(droppedFlag)
|
||||
zamorakDroppedFlagScenery = droppedFlag
|
||||
zamorakFlagDroppedTick = getWorldTicks()
|
||||
if (!shouldReturnToStand) {
|
||||
addDroppedFlagScenery(CastleWarsTeam.ZAMORAK, actualDropLocation)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (player.equipment.get(EquipmentContainer.SLOT_WEAPON)?.id == carriedEnemyFlag.flagItemId) {
|
||||
|
|
@ -687,12 +673,12 @@ object CastleWarsGameState {
|
|||
if (player.inventory.contains(carriedEnemyFlag.flagItemId, 1)) {
|
||||
player.inventory.remove(Item(carriedEnemyFlag.flagItemId))
|
||||
}
|
||||
announceToAllPlayers("${carriedEnemyFlag.teamName} flag has been dropped!")
|
||||
updateAllOverlays()
|
||||
updateAllHintIcons()
|
||||
// Stepping stone auto-return check
|
||||
if (CastleWars.isSteppingStoneTile(dropLocation)) {
|
||||
if (shouldReturnToStand) {
|
||||
returnFlagToStand(carriedEnemyFlag)
|
||||
} else {
|
||||
announceToAllPlayers("${carriedEnemyFlag.teamName} flag has been dropped!")
|
||||
updateAllOverlays()
|
||||
updateAllHintIcons()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -701,20 +687,16 @@ object CastleWarsGameState {
|
|||
when (carriedOwnFlag) {
|
||||
CastleWarsTeam.SARADOMIN -> {
|
||||
saradominOwnFlagCarrier = null
|
||||
saradominFlagState = FlagState.DROPPED
|
||||
val droppedFlag = Scenery(CastleWars.saradominDroppedFlagScenery, dropLocation, 10, 0)
|
||||
SceneryBuilder.add(droppedFlag)
|
||||
saradominDroppedFlagScenery = droppedFlag
|
||||
saradominFlagDroppedTick = getWorldTicks()
|
||||
if (!shouldReturnToStand) {
|
||||
addDroppedFlagScenery(CastleWarsTeam.SARADOMIN, actualDropLocation)
|
||||
}
|
||||
}
|
||||
|
||||
CastleWarsTeam.ZAMORAK -> {
|
||||
zamorakOwnFlagCarrier = null
|
||||
zamorakFlagState = FlagState.DROPPED
|
||||
val droppedFlag = Scenery(CastleWars.zamorakDroppedFlagScenery, dropLocation, 10, 0)
|
||||
SceneryBuilder.add(droppedFlag)
|
||||
zamorakDroppedFlagScenery = droppedFlag
|
||||
zamorakFlagDroppedTick = getWorldTicks()
|
||||
if (!shouldReturnToStand) {
|
||||
addDroppedFlagScenery(CastleWarsTeam.ZAMORAK, actualDropLocation)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (player.equipment.get(EquipmentContainer.SLOT_WEAPON)?.id == carriedOwnFlag.flagItemId) {
|
||||
|
|
@ -723,13 +705,32 @@ object CastleWarsGameState {
|
|||
if (player.inventory.contains(carriedOwnFlag.flagItemId, 1)) {
|
||||
player.inventory.remove(Item(carriedOwnFlag.flagItemId))
|
||||
}
|
||||
announceToAllPlayers("${carriedOwnFlag.teamName} flag has been dropped!")
|
||||
updateAllOverlays()
|
||||
updateAllHintIcons()
|
||||
|
||||
// Stepping stone auto-return check
|
||||
if (CastleWars.isSteppingStoneTile(dropLocation)) {
|
||||
if (shouldReturnToStand) {
|
||||
returnFlagToStand(carriedOwnFlag)
|
||||
} else {
|
||||
announceToAllPlayers("${carriedOwnFlag.teamName} flag has been dropped!")
|
||||
updateAllOverlays()
|
||||
updateAllHintIcons()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addDroppedFlagScenery(flagTeam: CastleWarsTeam, dropLocation: Location) {
|
||||
when (flagTeam) {
|
||||
CastleWarsTeam.SARADOMIN -> {
|
||||
saradominFlagState = FlagState.DROPPED
|
||||
val droppedFlag = Scenery(CastleWars.saradominDroppedFlagScenery, dropLocation, 10, 0)
|
||||
SceneryBuilder.add(droppedFlag)
|
||||
saradominDroppedFlagScenery = droppedFlag
|
||||
saradominFlagDroppedTick = getWorldTicks()
|
||||
}
|
||||
|
||||
CastleWarsTeam.ZAMORAK -> {
|
||||
zamorakFlagState = FlagState.DROPPED
|
||||
val droppedFlag = Scenery(CastleWars.zamorakDroppedFlagScenery, dropLocation, 10, 0)
|
||||
SceneryBuilder.add(droppedFlag)
|
||||
zamorakDroppedFlagScenery = droppedFlag
|
||||
zamorakFlagDroppedTick = getWorldTicks()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -855,45 +856,6 @@ object CastleWarsGameState {
|
|||
updateAllHintIcons()
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a dropped flag to its stand (legacy)
|
||||
* TODO: This is now only used for ground item pickup which is being cut coz its fake. Not real
|
||||
* The new behavior uses pickUpOwnFlag() and castle entry detection.
|
||||
* @param player The player returning the flag
|
||||
* @param flagTeam The team whose flag is being returned
|
||||
* @return true if the flag was successfully returned
|
||||
*/
|
||||
fun returnFlag(player: Player, flagTeam: CastleWarsTeam): Boolean {
|
||||
val playerTeam = getPlayerTeam(player) ?: return false
|
||||
if (playerTeam != flagTeam) {
|
||||
return false
|
||||
}
|
||||
val flagState =
|
||||
if (flagTeam == CastleWarsTeam.SARADOMIN) saradominFlagState else zamorakFlagState
|
||||
if (flagState != FlagState.DROPPED) {
|
||||
return false
|
||||
}
|
||||
when (flagTeam) {
|
||||
CastleWarsTeam.SARADOMIN -> {
|
||||
saradominFlagState = FlagState.SAFE
|
||||
saradominDroppedFlagScenery?.let { SceneryBuilder.remove(it) }
|
||||
saradominDroppedFlagScenery = null
|
||||
updateFlagStandObject(CastleWarsTeam.SARADOMIN, FlagState.SAFE)
|
||||
}
|
||||
|
||||
CastleWarsTeam.ZAMORAK -> {
|
||||
zamorakFlagState = FlagState.SAFE
|
||||
zamorakDroppedFlagScenery?.let { SceneryBuilder.remove(it) }
|
||||
zamorakDroppedFlagScenery = null
|
||||
updateFlagStandObject(CastleWarsTeam.ZAMORAK, FlagState.SAFE)
|
||||
}
|
||||
}
|
||||
announceToTeam(flagTeam, "${player.username} has returned the ${flagTeam.teamName} flag!")
|
||||
updateAllOverlays()
|
||||
updateAllHintIcons()
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a dropped flag directly to its stand (instant, no player involved).
|
||||
* Used for auto-return (timeout, stepping stone) scenarios.
|
||||
|
|
@ -1429,15 +1391,18 @@ object CastleWarsGameState {
|
|||
* Destroy a team's catapult
|
||||
*/
|
||||
fun destroyCatapult(team: CastleWarsTeam) {
|
||||
val location = when (team) {
|
||||
CastleWarsTeam.SARADOMIN -> saradominCatapultLocation
|
||||
CastleWarsTeam.ZAMORAK -> zamorakCatapultLocation
|
||||
}
|
||||
when (team) {
|
||||
CastleWarsTeam.SARADOMIN -> saradominCatapultOperational = false
|
||||
CastleWarsTeam.ZAMORAK -> zamorakCatapultOperational = false
|
||||
CastleWarsTeam.SARADOMIN -> {
|
||||
saradominCatapultOperational = false
|
||||
saradominCatapultOnFire = false
|
||||
}
|
||||
|
||||
CastleWarsTeam.ZAMORAK -> {
|
||||
zamorakCatapultOperational = false
|
||||
zamorakCatapultOnFire = false
|
||||
}
|
||||
}
|
||||
replaceCatapultScenery(location, CastleWars.getDamagedCatapultId(team))
|
||||
updateCatapultScenery(team)
|
||||
updateAllOverlays()
|
||||
}
|
||||
|
||||
|
|
@ -1450,6 +1415,7 @@ object CastleWarsGameState {
|
|||
CastleWarsTeam.SARADOMIN -> saradominCatapultOnFire = true
|
||||
CastleWarsTeam.ZAMORAK -> zamorakCatapultOnFire = true
|
||||
}
|
||||
updateCatapultScenery(team)
|
||||
updateAllOverlays()
|
||||
}
|
||||
|
||||
|
|
@ -1461,6 +1427,7 @@ object CastleWarsGameState {
|
|||
CastleWarsTeam.SARADOMIN -> saradominCatapultOnFire = false
|
||||
CastleWarsTeam.ZAMORAK -> zamorakCatapultOnFire = false
|
||||
}
|
||||
updateCatapultScenery(team)
|
||||
updateAllOverlays()
|
||||
}
|
||||
|
||||
|
|
@ -1478,15 +1445,18 @@ object CastleWarsGameState {
|
|||
* Repair a team's catapult
|
||||
*/
|
||||
fun repairCatapult(team: CastleWarsTeam) {
|
||||
val location = when (team) {
|
||||
CastleWarsTeam.SARADOMIN -> saradominCatapultLocation
|
||||
CastleWarsTeam.ZAMORAK -> zamorakCatapultLocation
|
||||
}
|
||||
when (team) {
|
||||
CastleWarsTeam.SARADOMIN -> saradominCatapultOperational = true
|
||||
CastleWarsTeam.ZAMORAK -> zamorakCatapultOperational = true
|
||||
CastleWarsTeam.SARADOMIN -> {
|
||||
saradominCatapultOperational = true
|
||||
saradominCatapultOnFire = false
|
||||
}
|
||||
|
||||
CastleWarsTeam.ZAMORAK -> {
|
||||
zamorakCatapultOperational = true
|
||||
zamorakCatapultOnFire = false
|
||||
}
|
||||
}
|
||||
replaceCatapultScenery(location, CastleWars.getOperationalCatapultId(team))
|
||||
updateCatapultScenery(team)
|
||||
updateAllOverlays()
|
||||
}
|
||||
|
||||
|
|
@ -1614,6 +1584,19 @@ object CastleWarsGameState {
|
|||
* Replace catapult scenery at a location with a new catapult ID.
|
||||
* Searches for any catapult object at the location and replaces it.
|
||||
*/
|
||||
private fun updateCatapultScenery(team: CastleWarsTeam) {
|
||||
val location = when (team) {
|
||||
CastleWarsTeam.SARADOMIN -> saradominCatapultLocation
|
||||
CastleWarsTeam.ZAMORAK -> zamorakCatapultLocation
|
||||
}
|
||||
val newId = when {
|
||||
!isCatapultOperational(team) -> CastleWars.getDamagedCatapultId(team)
|
||||
isCatapultOnFire(team) -> CastleWars.getBurningCatapultId(team)
|
||||
else -> CastleWars.getOperationalCatapultId(team)
|
||||
}
|
||||
replaceCatapultScenery(location, newId)
|
||||
}
|
||||
|
||||
private fun replaceCatapultScenery(location: Location, newId: Int) { // Get the object at the catapult location
|
||||
val existingObj = RegionManager.getObject(location)
|
||||
if (existingObj != null && existingObj.id in CastleWars.allCatapultIds) {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import org.rs09.consts.NPCs
|
|||
/**
|
||||
* Handles Castle Wars item mechanics:
|
||||
* - Bandages: Heal 10% of max HP, restore 30% run energy, can heal teammates
|
||||
* - Barricades: Place barricade NPC with 5000 HP, max 10 per team TODO: 5000 HP BARRICADE HAHHAH FAT CHANCE. keeping that in for now
|
||||
* - Barricades: Place barricade NPC with 50 HP, max 10 per team
|
||||
* - Explosive Potions: Instant-destroy barricades, 15% max HP self-damage on drop
|
||||
*/
|
||||
class CastleWarsItemHandler : InteractionListener {
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ private val barrierCoordinates: Map<Int, List<BarrierData>> = mapOf(
|
|||
)
|
||||
|
||||
private val castleWarsStairDestinationOverrides: Map<Location, Location> = mapOf(
|
||||
Location.create(2419, 3077, 0) to Location.create(2420, 3080, 1),
|
||||
Location.create(2419, 3078, 0) to Location.create(2420, 3080, 1),
|
||||
Location.create(2425, 3076, 2) to Location.create(2426, 3074, 3),
|
||||
Location.create(2425, 3074, 3) to Location.create(2425, 3077, 2),
|
||||
Location.create(2430, 3081, 2) to Location.create(2427, 3081, 1),
|
||||
|
|
@ -179,10 +181,6 @@ class CastleWarsListeners : InteractionListener {
|
|||
on(CastleWars.joinSaradominTeamPortal, IntType.SCENERY, "Enter") { player, _ ->
|
||||
if (GameWorld.settings?.enable_castle_wars != true) return@on false
|
||||
if (!player.isArtificial && joinError(player)) return@on true
|
||||
if (CastleWarsWaitingArea.waitingSaradominPlayers.size + CastleWarsGameArea.saradominPlayers.size >= CastleWarsConstants.MAX_PLAYERS_PER_TEAM) {
|
||||
sendMessage(player, "The team is currently full.")
|
||||
return@on true
|
||||
}
|
||||
player.properties.teleportLocation = CastleWarsWaitingArea.saradominWaitingRoom.randomWalkableLoc
|
||||
player.setAttribute(CastleWars.portalAttribute, CastleWars.saradominName)
|
||||
return@on true
|
||||
|
|
@ -190,10 +188,6 @@ class CastleWarsListeners : InteractionListener {
|
|||
on(CastleWars.joinZamorakTeamPortal, IntType.SCENERY, "Enter") { player, _ ->
|
||||
if (GameWorld.settings?.enable_castle_wars != true) return@on false
|
||||
if (!player.isArtificial && joinError(player)) return@on true
|
||||
if (CastleWarsWaitingArea.waitingZamorakPlayers.size + CastleWarsGameArea.zamorakPlayers.size >= CastleWarsConstants.MAX_PLAYERS_PER_TEAM) {
|
||||
sendMessage(player, "The team is currently full.")
|
||||
return@on true
|
||||
}
|
||||
player.properties.teleportLocation = CastleWarsWaitingArea.zamorakWaitingRoom.randomWalkableLoc
|
||||
player.setAttribute(CastleWars.portalAttribute, CastleWars.zamorakName)
|
||||
return@on true
|
||||
|
|
@ -212,21 +206,7 @@ class CastleWarsListeners : InteractionListener {
|
|||
val saraTotal =
|
||||
CastleWarsWaitingArea.waitingSaradominPlayers.size + CastleWarsGameArea.saradominPlayers.size
|
||||
val zamTotal = CastleWarsWaitingArea.waitingZamorakPlayers.size + CastleWarsGameArea.zamorakPlayers.size
|
||||
val saraFull = saraTotal >= CastleWarsConstants.MAX_PLAYERS_PER_TEAM
|
||||
val zamFull = zamTotal >= CastleWarsConstants.MAX_PLAYERS_PER_TEAM
|
||||
if (saraFull && zamFull) {
|
||||
sendMessage(player, "The team is currently full.")
|
||||
return@on true
|
||||
}
|
||||
when {
|
||||
saraFull -> {
|
||||
player.properties.teleportLocation = CastleWarsWaitingArea.zamorakWaitingRoom.randomWalkableLoc
|
||||
}
|
||||
|
||||
zamFull -> {
|
||||
player.properties.teleportLocation = CastleWarsWaitingArea.saradominWaitingRoom.randomWalkableLoc
|
||||
}
|
||||
|
||||
saraTotal < zamTotal -> {
|
||||
player.properties.teleportLocation = CastleWarsWaitingArea.saradominWaitingRoom.randomWalkableLoc
|
||||
}
|
||||
|
|
@ -323,11 +303,6 @@ class CastleWarsListeners : InteractionListener {
|
|||
return@on true
|
||||
}
|
||||
|
||||
if (CastleWarsGameState.isCarryingAnyFlag(player)) {
|
||||
CastleWarsGameState.dropFlagAtLocation(player, player.location)
|
||||
sendMessage(player, "You drop the flag as you jump across!")
|
||||
}
|
||||
|
||||
lock(player, 3)
|
||||
AgilityHandler.forceWalk(player, -1, player.location, stone.location, Animation(741), 10, 0.0, null, 1)
|
||||
runTask(player, 1) {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import core.game.world.update.flag.context.Animation
|
|||
* This pulse replaces the instant 3-tick delay with proper mining mechanics
|
||||
* where players must successfully "hit" the rock multiple times to clear it.
|
||||
*/
|
||||
class CastleWarsTunnelMiningPulse( // TODO: tunnels in general are working great. but this... needs a thorough check from start to finish
|
||||
class CastleWarsTunnelMiningPulse(
|
||||
private val player: Player,
|
||||
private val rocks: Scenery,
|
||||
private val boulderKey: String,
|
||||
|
|
|
|||
|
|
@ -116,7 +116,6 @@ class CastleWarsGameArea : CastleWarsArea(), TickListener {
|
|||
CastleWarsTeam.ZAMORAK -> zamorakPlayers
|
||||
}
|
||||
if (waitingSet.isEmpty()) return
|
||||
if (gameSet.size >= CastleWarsConstants.MAX_PLAYERS_PER_TEAM) return
|
||||
val replacement = waitingSet.first()
|
||||
waitingSet.remove(replacement)
|
||||
gameSet.add(replacement)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue