diff --git a/Server/src/main/content/minigame/barbassault/BarbassDevHelper.kt b/Server/src/main/content/minigame/barbassault/BarbassDevHelper.kt index 1c154dc97..8b111916b 100644 --- a/Server/src/main/content/minigame/barbassault/BarbassDevHelper.kt +++ b/Server/src/main/content/minigame/barbassault/BarbassDevHelper.kt @@ -33,6 +33,19 @@ class BarbassDevHelper : CommandSet(Privilege.ADMIN) { player.teleport(Location.create(1885, 5403, 0)) } + define("hch"){ player,args-> + val chId = args[1].toIntOrNull() + if (chId != null) { + player.packetDispatch.sendInterfaceConfig(493, chId,true) + } + } + define("vch"){ player,args-> + val chId = args[1].toIntOrNull() + if (chId != null) { + player.packetDispatch.sendInterfaceConfig(493, chId,false) + } + } + define("trap"){ player,args-> var thistrap = Location.create(1901, 5474, 0) var thistrapscen = core.game.node.scenery.Scenery(Scenery.RUNNER_TRAP2_20135, Location(1901, 5474)) diff --git a/Server/src/main/content/minigame/barbassault/BarbassaultListeners.kt b/Server/src/main/content/minigame/barbassault/BarbassaultListeners.kt index c88dc22a3..a375e9fa5 100644 --- a/Server/src/main/content/minigame/barbassault/BarbassaultListeners.kt +++ b/Server/src/main/content/minigame/barbassault/BarbassaultListeners.kt @@ -32,7 +32,9 @@ class BarbassaultListeners : InteractionListener { on(Scenery.LADDER_20227, IntType.SCENERY, "Climb-up") { player, _ -> //Remove Roster/scroll val loc = Location(2535 , 3572 ) + player.inventory.removeAll(Items.SCROLL_10512) teleport(player, loc) // find ladder code latter + return@on true } @@ -84,6 +86,8 @@ class BarbassaultListeners : InteractionListener { Items.NATURE_RUNE_561 //add food //add ammo + //summoning pouches + ) for (item in player.inventory.toArray()) { @@ -117,7 +121,7 @@ class BarbSelectRole : InterfaceListener { //Accpting invite text " Your application has been accepted" //The applicant declined your offer. //the other player hasn't confirmed their role yet. -//the applicant has chosen a role.0 +//the applicant has chosen a role[0] //You removed the person from the team. override fun defineInterfaceListeners() { onOpen(493) { player, _ -> // change this for roles diff --git a/Server/src/main/content/minigame/barbassault/arena/BarbassaultActivity.kt b/Server/src/main/content/minigame/barbassault/arena/BarbassaultActivity.kt index 97cfe080c..c388acbc8 100644 --- a/Server/src/main/content/minigame/barbassault/arena/BarbassaultActivity.kt +++ b/Server/src/main/content/minigame/barbassault/arena/BarbassaultActivity.kt @@ -1,58 +1,70 @@ package content.minigame.barbassault +import content.minigame.barbassault.arena.BarbassaultSession +import content.minigame.barbassault.arena.BarbassaultState +import content.minigame.barbassault.lobby.baSession +import content.minigame.barbassault.activity import content.minigame.fishingtrawler.FishingTrawlerActivity -import core.api.MapArea +import core.api.sendMessage +import core.game.activity.ActivityManager +import core.game.activity.ActivityPlugin import core.game.node.entity.player.Player import core.game.system.task.Pulse import core.game.world.GameWorld import core.game.world.map.Location -import core.game.world.map.build.DynamicRegion +import core.game.world.map.zone.ZoneBorders import core.game.world.map.zone.ZoneRestriction import core.plugin.Initializable -import core.tools.ticksToSeconds -import core.game.activity.ActivityManager -import core.game.activity.ActivityPlugin -import core.game.world.map.zone.ZoneBorders -import core.tools.colorize +private val sessions = mutableListOf() private var activity: BarbassaultActivity? = null @Initializable -class BarbassaultActivity : ActivityPlugin("barbassault",false,false,true,ZoneRestriction.CANNON,ZoneRestriction.FIRES,ZoneRestriction.FOLLOWERS,ZoneRestriction.RANDOM_EVENTS), MapArea { - +class BarbassaultActivity : ActivityPlugin("barbassault",true, true, true, + ZoneRestriction.CANNON, + ZoneRestriction.FIRES, + ZoneRestriction.FOLLOWERS, + ZoneRestriction.RANDOM_EVENTS +) { init { activity = this } + override fun configure() { + GameWorld.Pulser.submit(object : Pulse(10) { + override fun pulse(): Boolean { + sessions.removeIf { + it.state == BarbassaultState.END + } + return false + } + }) } override fun start(player: Player?, login: Boolean, vararg args: Any?): Boolean { - player ?: return false - //waitingPlayers.add(player) return true } - fun addPlayer(player: Player){ - - } - - fun removePlayer(player: Player){ - // waitingPlayers.remove(player) - } - override fun newInstance(p: Player?): ActivityPlugin { ActivityManager.register(this) return this } override fun getSpawnLocation(): Location { - return Location.create(2667, 3161, 0) + return Location.create(2593, 5264, 0) } - override fun defineAreaBorders(): Array { - return arrayOf(ZoneBorders(2668, 3165, 2675, 3184)) - } - override fun getRestrictions(): Array { - return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.TELEPORT) + + companion object { + fun createSession(leader: Player): BarbassaultSession { + val activity = ActivityManager.getActivity("barbassault") as BarbassaultActivity + val session = BarbassaultSession(activity) + sessions += session + + leader.baSession = session + + + return session + } } -} \ No newline at end of file +} diff --git a/Server/src/main/content/minigame/barbassault/arena/BarbassaultArena.kt b/Server/src/main/content/minigame/barbassault/arena/BarbassaultArena.kt new file mode 100644 index 000000000..b641fd7f1 --- /dev/null +++ b/Server/src/main/content/minigame/barbassault/arena/BarbassaultArena.kt @@ -0,0 +1,44 @@ +package content.minigame.barbassault.arena + +import core.api.MapArea +import core.api.getRegionBorders +import core.game.node.entity.player.Player +import core.game.world.map.build.DynamicRegion +import core.game.world.map.zone.ZoneBorders +import core.game.world.map.zone.ZoneRestriction + +class BarbassaultArena( + private val session: BarbassaultSession +) : MapArea { + + private lateinit var region: DynamicRegion + + fun create() { + region = DynamicRegion.create(BarbassaultGameArea.BA_ARENA.MAIN) + //zone.register(*defineAreaBorders()) + } + + fun spawnPlayers(players: List) { + val base = region.baseLocation + players.forEach { + it.properties.teleportLocation = + base.transform(36, 24, 0) + } + } + + fun destroy() { + //zone.unregister(*defineAreaBorders()) + region.clear() + } + + override fun defineAreaBorders(): Array = + arrayOf(getRegionBorders(7509)) + + override fun getRestrictions(): Array = + arrayOf( + ZoneRestriction.CANNON, + ZoneRestriction.FIRES, + ZoneRestriction.RANDOM_EVENTS, + ZoneRestriction.TELEPORT + ) +} diff --git a/Server/src/main/content/minigame/barbassault/arena/BarbassaultGameArea.kt b/Server/src/main/content/minigame/barbassault/arena/BarbassaultGameArea.kt index 1ecf157c9..9cd53980f 100644 --- a/Server/src/main/content/minigame/barbassault/arena/BarbassaultGameArea.kt +++ b/Server/src/main/content/minigame/barbassault/arena/BarbassaultGameArea.kt @@ -1,7 +1,10 @@ package content.minigame.barbassault.arena +import content.minigame.barbassault.BarbRole import content.minigame.barbassault.BarbassaultTut +import content.minigame.barbassault.BarbassaultTut.Companion.TutorialItemSpawn import content.minigame.barbassault.arena.scenery.DefenderTrap +import content.minigame.barbassault.lobby.baSession import core.api.* import core.game.global.action.DropListener @@ -19,6 +22,7 @@ import core.game.node.item.GroundItemManager import core.game.node.item.Item import core.game.system.task.Pulse import core.game.world.GameWorld +import core.game.world.map.Direction import core.game.world.map.Location import core.game.world.map.zone.ZoneBorders import core.game.world.update.flag.context.Animation @@ -40,14 +44,32 @@ import org.rs09.consts.Scenery //sendMessage(player,"The barbarians forbid the use of prayer in their arena as they don't ~ value such methods!") //should be multicombat +val ATTACKER_ICON = 10556 +val DEFENDER_ICON = 10558 +val COLLECTOR_ICON = 10557 +val HEALER_ICON = 10559 class BarbassaultGameArea : InteractionListener, MapArea { - val ATTACKER_ICON = 10556 - val DEFENDER_ICON = 10558 - val COLLECTOR_ICON = 10557 - val HEALER_ICON = 10559 - val ROLE_ICON = intArrayOf(ATTACKER_ICON,DEFENDER_ICON,COLLECTOR_ICON,HEALER_ICON) - val Fix_trap_IDs = intArrayOf(Scenery.RUNNER_TRAP1_20230,Scenery.BROKEN_TRAP0_20231) + val ROLE_ICON = intArrayOf( ATTACKER_ICON, DEFENDER_ICON, COLLECTOR_ICON, HEALER_ICON ) + val Fix_trap_IDs = intArrayOf( Scenery.RUNNER_TRAP1_20230, Scenery.BROKEN_TRAP0_20231 ) + object BA_ARENA { val MAIN = 7509; val QUEEN = 7508; val all = listOf(MAIN, QUEEN) } + + //base.transform(0,0,0) + data class arenaItems(val id: Int,val x: Int, val y: Int, val z: Int) + val arenaItemSpawn: List = listOf( + arenaItems(Items.HAMMER_2347,32,42,0), + arenaItems(Items.LOGS_11760,30,46,0), + arenaItems(Items.LOGS_11760,29,47,0) + ) + enum class pennanceNPC { runner, healer, fighter, ranger } + data class npcSpawnLoc(val tunnel:pennanceNPC, val x: Int,val y: Int,val z: Int,val direction: Direction) + val npcSpawns: List = listOf( + npcSpawnLoc(pennanceNPC.runner,42,45,0,Direction.SOUTH), + npcSpawnLoc(pennanceNPC.healer,36,46,0,Direction.SOUTH), + + npcSpawnLoc(pennanceNPC.fighter,24,46,0,Direction.SOUTH), + npcSpawnLoc(pennanceNPC.ranger,36,46,0,Direction.SOUTH), + ) override fun defineAreaBorders(): Array { //block standard teleports. @@ -80,13 +102,13 @@ class BarbassaultGameArea : InteractionListener, MapArea { override fun defineListeners() { on(Fix_trap_IDs, IntType.SCENERY, "Fix") { player, node -> - if (checkHasTools(player)) { return@on true } + if (hasTools(player)) { return@on true } playerChangeScenery(player,5416,node,Scenery.RUNNER_TRAP2_20135,5,"You fixed the Penance Runner trap.") return@on true } on(Scenery.PENANCE_CAVE_20237, IntType.SCENERY, "block") { player, node -> - if (checkHasTools(player)) { return@on true } + if (hasTools(player)) { return@on true } playerChangeScenery(player,5417,node,Scenery.PENANCE_CAVE_20238,4) return@on true } @@ -97,7 +119,7 @@ class BarbassaultGameArea : InteractionListener, MapArea { } on(Scenery.PENANCE_CAVE_20239, IntType.SCENERY, "fix") { player, node -> - if (checkHasTools(player)) { return@on true } + if (hasTools(player)) { return@on true } playerChangeScenery(player,5417,node,Scenery.PENANCE_CAVE_20238,4) return@on true } @@ -142,6 +164,10 @@ class BarbassaultGameArea : InteractionListener, MapArea { //CATALYTIC_RUNE_12851, ELEMENTAL_RUNE_12850 onUnequip(ROLE_ICON) { player, _ -> + if (player.baSession?.state == BarbassaultState.IN_ARENA){ + sendMessage(player, "You can't remove that!") // is there a proper message for this? + return@onUnequip false + } defineAreaBorders().forEach { border -> if (border.insideBorder(player)) { sendMessage(player, "You can't remove that!") // is there a proper message for this? @@ -152,6 +178,9 @@ class BarbassaultGameArea : InteractionListener, MapArea { } onEquip(ROLE_ICON) { player, _ -> + if (player.baSession?.state == BarbassaultState.IN_ARENA) { + sendMessage(player, "You can't remove that!") + } defineAreaBorders().forEach { border -> if (border.insideBorder(player)) { sendMessage(player, "You can't remove that!") @@ -184,33 +213,9 @@ class BarbassaultGameArea : InteractionListener, MapArea { } } - - private fun exitMiniGame(player: Player) { - openOverlay(player,493) // work around to actually close interfaces. - player.interfaceManager.closeOverlay()//maybe im doing this wrong. - removeTimer(player, "teleblock") - - - val barbassItems = arrayListOf( - - Items.WORMS_10515,Items.CRACKERS_10513,Items.TOFU_10514,Items.LOGS_11760,Items.LOGS_11760,Items.HAMMER_2347,Items.DEFENDER_HORN_10538, //Defender Inv Items - Items.HEALING_VIAL_10546,Items.HEALING_VIAL1_10545,Items.HEALING_VIAL2_10544,Items.HEALING_VIAL3_10543,Items.HEALING_VIAL4_10542, //Healer Inv Items - Items.HEALER_HORN_10526,Items.HEALER_HORN_10527,Items.HEALER_HORN_10528,Items.HEALER_HORN_10529,Items.HEALER_HORN_10530, - Items.POISONED_WORMS_10540,Items.POISONED_TOFU_10539,Items.POISONED_MEAT_10541, - ) - removeAll(player, barbassItems) - - //todo should probably make sure familiars can't smuggle items out - //(player.familiarManager.familiar as? BurdenBeast)?.container?.removeAll(barbassItems)//just in case someone smuggles a pet in. - //award points, set Tp location to next wave - //or lost game Send back to wave room - - } private fun lureDrop(player: Player,item:Item){ //val gi = GroundItemManager.create(GroundItem(item.dropItem,player.location,-1,null)) - - queueScript(player, strength = QueueStrength.SOFT) { val current = player.inventory.get(item.slot) if (current == null || current !== item) { @@ -242,15 +247,6 @@ class BarbassaultGameArea : InteractionListener, MapArea { return removedAny } - fun getIconInterfaceId(itemId: Int): Int? { - return when (itemId) { - ATTACKER_ICON -> Components.BARBASSAULT_OVER_ATT_485 - COLLECTOR_ICON -> Components.BARBASSAULT_OVER_COL_486 - DEFENDER_ICON -> Components.BARBASSAULT_OVER_DEF_487 - HEALER_ICON -> Components.BARBASSAULT_OVER_HEAL_488 - else -> null - } - } fun playerChangeScenery(player: Player,anim: Int ,node: Node, newSceneryId: Int, pulseDelay: Int = 3, message: String = "") { player.animate(Animation(anim)) @@ -268,7 +264,7 @@ class BarbassaultGameArea : InteractionListener, MapArea { } }) } - fun checkHasTools(player: Player): Boolean{ + fun hasTools(player: Player): Boolean{ if (getItemFromEquipment(player, EquipmentSlot.CAPE)?.id != DEFENDER_ICON) {return true} val requiredItems = listOf(Items.HAMMER_2347, Items.LOGS_11760) for (item in requiredItems) { @@ -279,26 +275,42 @@ class BarbassaultGameArea : InteractionListener, MapArea { } return false } - - - fun spawnPartyMembers(){ - //1 - //2 //3 - //5 //4 - // party slot effects where you start/spawn - val RedLeader1 = Location.create(1886, 5458, 0) - val RedLeader2 = Location.create(1885, 5457, 0) - val RedLeader3 = Location.create(1887, 5457, 0) - val RedLeader4 = Location.create(1884, 5456, 0) - val RedLeader5 = Location.create(1888, 5456, 0) - } } +fun exitMiniGame(player: Player) { + // openOverlay(player,493) // work around to actually close interfaces. + //player.interfaceManager.closeOverlay()//maybe im doing this wrong. + removeTimer(player, "teleblock") -object BA_ARENA { - const val MAIN = 7509 - const val QUEEN = 7508 - val all = listOf(MAIN, QUEEN) + val barbassItems = arrayListOf( + + Items.WORMS_10515,Items.CRACKERS_10513,Items.TOFU_10514,Items.LOGS_11760,Items.LOGS_11760,Items.HAMMER_2347,Items.DEFENDER_HORN_10538, //Defender Inv Items + Items.HEALING_VIAL_10546,Items.HEALING_VIAL1_10545,Items.HEALING_VIAL2_10544,Items.HEALING_VIAL3_10543,Items.HEALING_VIAL4_10542, //Healer Inv Items + Items.HEALER_HORN_10526,Items.HEALER_HORN_10527,Items.HEALER_HORN_10528,Items.HEALER_HORN_10529,Items.HEALER_HORN_10530, + Items.POISONED_WORMS_10540,Items.POISONED_TOFU_10539,Items.POISONED_MEAT_10541, + ) + removeAll(player, barbassItems) + + //todo should probably make sure familiars can't smuggle items out + //(player.familiarManager.familiar as? BurdenBeast)?.container?.removeAll(barbassItems)//just in case someone smuggles a pet in. + //award points, set Tp location to next wave + //or lost game Send back to wave room + +} +val BA_ROLE_CAPE = mapOf( BarbRole.ATTACKER to 10556, BarbRole.DEFENDER to 10558, BarbRole.COLLECTOR to 10557, BarbRole.HEALER to 10559 ) +fun equipBARoleIcon(player: Player, role: BarbRole) { + val itemId = BA_ROLE_CAPE[role] ?: return + player.equipment.add(Item(itemId),true,false) + //player.getEquipment().add(Item(itemId), true) +} +fun getIconInterfaceId(itemId: Int): Int? { + return when (itemId) { + ATTACKER_ICON -> Components.BARBASSAULT_OVER_ATT_485 + COLLECTOR_ICON -> Components.BARBASSAULT_OVER_COL_486 + DEFENDER_ICON -> Components.BARBASSAULT_OVER_DEF_487 + HEALER_ICON -> Components.BARBASSAULT_OVER_HEAL_488 + else -> null + } } diff --git a/Server/src/main/content/minigame/barbassault/arena/BarbassaultSession.kt b/Server/src/main/content/minigame/barbassault/arena/BarbassaultSession.kt index 95d453fa9..2d6fb1cef 100644 --- a/Server/src/main/content/minigame/barbassault/arena/BarbassaultSession.kt +++ b/Server/src/main/content/minigame/barbassault/arena/BarbassaultSession.kt @@ -1,8 +1,13 @@ package content.minigame.barbassault.arena -import content.minigame.barbassault.arena.LureItem +import content.minigame.barbassault.BarbRole +import content.minigame.barbassault.BarbassaultActivity +import content.minigame.barbassault.BarbassaultTut +import content.minigame.barbassault.lobby.BarbTeam +import content.minigame.barbassault.lobby.BarbTeamManager +import content.minigame.barbassault.lobby.SelectRole +import content.minigame.barbassault.lobby.baSession import core.api.* -import core.game.component.Component import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player @@ -10,114 +15,170 @@ import core.game.system.task.Pulse import core.game.world.GameWorld import core.game.world.map.Location import core.game.world.map.build.DynamicRegion +import core.game.world.map.zone.MapZone +import core.game.world.map.zone.Zone import core.game.world.map.zone.ZoneBorders import core.game.world.map.zone.ZoneRestriction import core.tools.Log -import core.tools.RandomFunction import core.tools.secondsToTicks +import core.tools.ticksToSeconds import org.rs09.consts.NPCs -import kotlin.math.ceil +import org.rs09.consts.Music +import org.rs09.consts.Music.ASSAULT_AND_BATTERY_604 +import org.rs09.consts.Music.PIRATES_OF_PENANCE_211 +import kotlin.math.roundToInt + +/* +Player +└─ attribute "baSession" : BarbassaultSession? + ├─ state : BarbassaultState (STARTING, IN_ARENA, END) + ├─ arena : DynamicRegion / MapArea + ├─ lifecycle : start → play → end + └─ team : BarbTeam? + ├─ leader : Player + ├─ slots : List + └─ recruit : PendingRecruit? + └─ player : Player + └─ role : BarbRole? +*/ + +enum class BarbassaultState { PARTY_CREATION, STARTING, IN_ARENA, COMPLETE, END } + +class BarbassaultSession( val activity: BarbassaultActivity ? = null) : MapArea { + constructor(region: DynamicRegion, activity: BarbassaultActivity) : this(activity) {this.region = region; this.base = region.baseLocation} -class BarbassaultSession(val activity: BarbassaultSession? = null) : MapArea { - constructor(region: DynamicRegion, activity: BarbassaultSession) : this(activity) {this.region = region; this.base = region.baseLocation} - var players: ArrayList = ArrayList() - val LureItemNodes = mutableListOf() lateinit var region: DynamicRegion lateinit var base: Location - var isActive = false - val npcs = ArrayList() - var inactiveTicks = 0 - var timeLeft = secondsToTicks(600) + + var state: BarbassaultState = BarbassaultState.PARTY_CREATION + private set + lateinit var team: BarbTeam - fun start(pl: ArrayList){ - region.setMusicId(434) - // region.setMusicId(51) - this.players.addAll(pl) - isActive = true + fun beginStartingPhase() { + if (state != BarbassaultState.PARTY_CREATION) return - GameWorld.Pulser.submit(BarbassPulse(this)) - for(player in pl){ - //player.interfaceManager.openOverlay(Component(OVERLAY_ID)) - //player.interfaceManager.open(Component(TUTORIAL_ID)) - //updateOverlay(player) - player.properties.teleportLocation = base.transform(36,24,0) - player.setAttribute("ba-session",this) - registerLogoutListener(player, "ba-logout") { - val session = player.getAttribute("ba-session",null) ?: return@registerLogoutListener - player.location = Location.create(2667, 3161, 0) //return to - session.players.remove(player) - player.locks.unlockTeleport() - } + state = BarbassaultState.STARTING + createArena() + startCountdown() + } + + private fun enterArena() { + state = BarbassaultState.IN_ARENA + region.setMusicId(ASSAULT_AND_BATTERY_604) + + for (player in team.allPlayers()) { + player.baSession?.team?.getRoleForPlayer(player)?.let { equipBARoleIcon(player, it) } + player.properties.teleportLocation = team.spawnLocationFor(player) //base.transform(36, 24, 0) + + registerLogoutListener(player, "ba-logout") { handleLogout(player) } //todo make sure this works } + + GameWorld.Pulser.submit(GamePulse()) + } + + fun endSession() { + if (state == BarbassaultState.END) return + state = BarbassaultState.END + + for (player in team.allPlayers()) { + clearLogoutListener(player, "ba-logout") + // player.removeAttribute("ba-session") + player.properties.teleportLocation = Location.create(2593, 5264, 0) + player.interfaceManager.closeOverlay() + } + destroyArena() + } + + private fun startCountdown() { + var ticks = secondsToTicks(12) + + team.allPlayers().forEach { openOverlay(it, 494);setInterfaceText(it, "60", 494, 0) } + GameWorld.Pulser.submit(object : Pulse(1) { + override fun pulse(): Boolean { + if (state != BarbassaultState.STARTING) return true + ticks-- + + if (ticks <= 0) { + enterArena() + return true + } + + val secondsLeft = ticksToSeconds(ticks) + val display = secondsLeft.toString().padStart(2, '0') + + team.allPlayers().forEach { + setInterfaceText(it, display, 494, 0) + // it.sendMessage("Barbarian Assault starts in $display seconds.") + } + + return false + } + }) + } + + private inner class GamePulse : Pulse(1) { + override fun pulse(): Boolean { + if (state != BarbassaultState.IN_ARENA) return true + + // TODO: wave logic, timers, win/lose + return false + } + } + + private fun createArena() { + region = DynamicRegion.create(BarbassaultGameArea.BA_ARENA.MAIN) + base = region.baseLocation zone.register(getRegionBorders(region.id)) } - class BarbassPulse(val session: BarbassaultSession) : Pulse(){ - var ticks = 0 - override fun pulse(): Boolean { - ticks++ - session.timeLeft-- - //session.zone.unregister(getRegionBorders(session.region.id)) + private fun destroyArena() { + if (!this::region.isInitialized) return + zone.unregister(getRegionBorders(region.id)) + region.clear() + } - if(session.timeLeft <= 0){ - session.isActive = false - for(player in session.players){ - player.interfaceManager.closeOverlay() - player.properties.teleportLocation = Location.create(2666, 3162, 0) // return to - // player.incrementAttribute("/save:$STATS_BASE:$FISHING_TRAWLER_GAMES_WON") - player.removeAttribute("ba-session") - clearLogoutListener(player, "ba-logout") - } - session.zone.unregister(getRegionBorders(session.region.id)) - } + private fun handleLogout(player: Player) { + team.removePlayer(player) + player.properties.teleportLocation = Location.create(2593, 5264, 0) + player.locks.unlockTeleport() - for(player in session.players){ - //session.updateOverlay(player) - if(session.timeLeft <= 1) { - lockInteractions(player, 2) - } - } - return !session.isActive + if (team.allPlayers().isEmpty()) { + endSession() } } - fun clearNPCs(){ - npcs.forEach { - it.clear() - } - npcs.clear() - } + override fun defineAreaBorders(): Array = emptyArray() - fun initCannons(){ - // NPC.create(NPCs.EGG_LAUNCHER_5026, Location.create(1896, 5474, 0), Direction.NORTH), - // NPC.create(NPCs.EGG_LAUNCHER_5026, Location.create(1877, 5474, 0), Direction.NORTH) - for(loc in arrayOf(base.transform(38,17,0), - base.transform(33,18,0))){ - val npc = NPC(NPCs.EGG_LAUNCHER_5026) - npc.location = loc - npcs.add(npc) - npc.isRespawn = false - npc.isWalks = false - npc.init() - } - } - - override fun defineAreaBorders(): Array { - return arrayOf() - } - - override fun getRestrictions(): Array { - return arrayOf(ZoneRestriction.CANNON, ZoneRestriction.FIRES, ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.TELEPORT) - } + override fun getRestrictions(): Array = arrayOf( + ZoneRestriction.CANNON, + ZoneRestriction.FIRES, + ZoneRestriction.RANDOM_EVENTS, + ZoneRestriction.TELEPORT + ) override fun areaEnter(entity: Entity) { - super.areaEnter(entity) - log(this::class.java, Log.FINE, "ENTERED BarbAssault") + log(this::class.java, Log.FINE, "ENTERED Barbassault Arena") + + val player = entity as? Player ?: return + val wornIconId = getItemFromEquipment(player, EquipmentSlot.CAPE)?.id + val interfaceId = getIconInterfaceId(wornIconId ?: -1) + if (interfaceId != null) { + //sendMessage(player,----- Wave: $Num -----") + openOverlay(player, interfaceId) + } + BarbassaultTut.BarbassTutNPCs.forEach { + npc -> npc.init() + npc.isWalks = false + + } + BarbassaultTut.spawnItems() } override fun areaLeave(entity: Entity, logout: Boolean) { - super.areaLeave(entity, logout) - log(this::class.java, Log.FINE, "EXITED BarbAssault") + log(this::class.java, Log.FINE, "LEFT Barbassault Arena") + var player = entity as Player + exitMiniGame(player) + removeTimer(player, "teleblock") } } \ No newline at end of file diff --git a/Server/src/main/content/minigame/barbassault/arena/scenery/DefenderTrap.kt b/Server/src/main/content/minigame/barbassault/arena/scenery/DefenderTrap.kt index af61d7adc..e616505e5 100644 --- a/Server/src/main/content/minigame/barbassault/arena/scenery/DefenderTrap.kt +++ b/Server/src/main/content/minigame/barbassault/arena/scenery/DefenderTrap.kt @@ -1,6 +1,5 @@ package content.minigame.barbassault.arena.scenery -import content.minigame.barbassault.arena.machines.ItemMachine.Companion.addArrayOfItems import content.minigame.barbassault.arena.monsters.PENANCE_RUNNER_IDS import core.api.* import core.game.node.Node @@ -36,6 +35,7 @@ class DefenderTrap : MapArea { val TRAP_WEST_ZONE: ZoneBorders = ZoneBorders(1870, 5474, 1872, 5472, 0) val TRAP_WEST = Location.create(1871, 5473, 0) val TRAPS_ZONE = arrayOf(TRAP_EAST_ZONE,TRAP_WEST_ZONE) + val Fix_trap_IDs = intArrayOf( Scenery.RUNNER_TRAP1_20230, Scenery.BROKEN_TRAP0_20231 ) val TRAPS = arrayOf(TRAP_WEST,TRAP_EAST) val playersInArea = mutableListOf() @@ -63,7 +63,7 @@ class DefenderTrap : MapArea { fun killRunner(entity: Entity){ entity.sendChat(TRAP_HIT) entity.startDeath(entity) - var thistrap = Location.create(1901, 5474, 0) + val thistrap = Location.create(1901, 5474, 0) val scenery = getScenery(thistrap) //animateScenery(scenery!!, 5076)//5076 @@ -97,11 +97,12 @@ class DefenderTrap : MapArea { sendMessage(player,"Entered Trap Area") } } +} //sendMessage(player,"A Penance Runner broke a trap to the east/west!") //When a runner dies to trap announce to Defenders //replaceScenery() //animateScenery //5076 -} + diff --git a/Server/src/main/content/minigame/barbassault/lobby/AcceptRoleInterface.kt b/Server/src/main/content/minigame/barbassault/lobby/AcceptRoleInterface.kt new file mode 100644 index 000000000..54f9514d7 --- /dev/null +++ b/Server/src/main/content/minigame/barbassault/lobby/AcceptRoleInterface.kt @@ -0,0 +1,109 @@ +package content.minigame.barbassault.lobby + +import content.minigame.barbassault.BarbRole +import content.minigame.barbassault.lobby.BarbTeamManager.abandonTeam +import content.minigame.barbassault.lobby.CurrentTeam.ROLE_MODEL_MAP +import content.minigame.barbassault.lobby.CurrentTeam.modelZoom +import core.api.closeInterface +import core.api.sendMessage +import core.api.setInterfaceModel +import core.api.setInterfaceText +import core.game.component.Component +import core.game.component.ComponentDefinition +import core.game.component.ComponentPlugin +import core.game.node.entity.player.Player +import core.plugin.Initializable +import core.plugin.Plugin + +@Initializable +class AcceptRoleInterface : ComponentPlugin() { + override fun newInstance(arg: Any?): Plugin { + ComponentDefinition.forId(AcceptRole.ID).plugin = this + return this + } + override fun handle(player: Player?,component: Component?, opcode: Int, button: Int, slot: Int, itemId: Int ): Boolean { + when (button) { + AcceptRole.AcceptButton, AcceptRole.AcceptButtonText -> { handleAccept(player); return true } + AcceptRole.DeclineButton, AcceptRole.DeclineButtonText -> { handleDecline(player); return true } + } + + val slotIndex = AcceptRole.team.indexOfFirst { it.remove == button } + if (slotIndex != -1) { handleRemove(player!!, slotIndex); return true } + + return true + } + override fun open(player: Player?, component: Component?) { + super.open(player, component) + var isopen = true + player ?: return + val team = player.baSession?.team + val recruit = team?.recruit?.player + val teamLeader = team?.getLeader() + component?.setCloseEvent{ _, _ -> if (recruit != null && isopen) { closeInterface(recruit); isopen = false }; return@setCloseEvent true } + + for (slotIndex in 0 until BarbTeam.MAX_SLOTS) { + val uiSlot = AcceptRole.team[slotIndex] + val partySlot: PartySlot? = team?.getSlot(slotIndex) + val slotPlayer: Player? = partySlot?.player + + if (slotPlayer != null) { + val formattedRole = slotPlayer.baSession?.team?.getRoleForPlayer(slotPlayer)?.toString()?.lowercase()?.replaceFirstChar { it.uppercase() }?: AcceptRole.defaultText + val wave = slotPlayer.getAttribute("barbass:wave", 1) ?: 0 + setInterfaceText(player, slotPlayer.name.capitalizeWords(), AcceptRole.ID, uiSlot.name ) + setInterfaceText(player, formattedRole, AcceptRole.ID, uiSlot.role ) + setInterfaceText(player, wave.toString(), AcceptRole.ID, uiSlot.wave ) + } else { + setInterfaceText(player, AcceptRole.defaultText, AcceptRole.ID,uiSlot.name ) + setInterfaceText(player, AcceptRole.defaultText, AcceptRole.ID,uiSlot.role ) + setInterfaceText(player, "0", AcceptRole.ID,uiSlot.wave ) + } + } + } +} +private fun handleAccept(player: Player?) { + sendMessage(player!!,"Accepted Clicked") + return +} +private fun handleDecline(player: Player?) { + if (player == null) return + closeInterface(player) + val leader = player.baSession?.team?.getLeader()?.player + if (leader != null && leader != player) { + closeInterface(leader) + } +} +private fun handleRemove(player: Player, slotIndex: Int){ + val team = player.baSession?.team + val follower = team?.getSlot(slotIndex)?.player ?: return + val uiSlot = AcceptRole.team[slotIndex] + + sendMessage(player,"You removed the person from the team.") + setInterfaceText(player, AcceptRole.defaultText, AcceptRole.ID,uiSlot.name ) + setInterfaceText(player, AcceptRole.defaultText, AcceptRole.ID,uiSlot.role ) + setInterfaceText(player, "0", AcceptRole.ID,uiSlot.wave ) + + abandonTeam(follower) +} + +object AcceptRole { + const val ID = 492 + const val defaultText = "none set" + const val AcceptButtonText = 4 + const val DeclineButtonText = 2 + const val AcceptButton = 35 + const val DeclineButton = 3 + + data class Slot(val name: Int, val role: Int,val remove: Int, val wave: Int) + + val team = listOf( + Slot(15,20,-1,26), + Slot(16,21,47,31), + Slot(17,22,27,32), + Slot(18,23,28,33), + Slot(19,24,29,34), + ) + object Status { + const val selectedRole = 6 + const val levelRole = 46 + } +} diff --git a/Server/src/main/content/minigame/barbassault/lobby/BarbTeam.kt b/Server/src/main/content/minigame/barbassault/lobby/BarbTeam.kt new file mode 100644 index 000000000..a7cc43719 --- /dev/null +++ b/Server/src/main/content/minigame/barbassault/lobby/BarbTeam.kt @@ -0,0 +1,232 @@ +package content.minigame.barbassault.lobby + +import content.minigame.barbassault.BarbRole +import content.minigame.barbassault.BarbassaultActivity +import content.minigame.barbassault.arena.BarbassaultSession +import content.minigame.barbassault.arena.BarbassaultState +import core.api.clearLogoutListener +import core.api.sendMessage +import core.game.node.entity.player.Player +import core.game.world.map.Location + + +/* +Player +└─ attribute "ba-session" + └─ BarbassaultSession : MapArea + └─ team : BarbTeam + └─ slots → Players +*/ + +private const val BA_SESSION_KEY = "ba-session" + +var Player.baSession: BarbassaultSession? + get() = getAttribute(BA_SESSION_KEY) + set(value) { + if (value == null) removeAttribute(BA_SESSION_KEY) + else setAttribute(BA_SESSION_KEY, value) + } + +/** +private val playerTeams = mutableMapOf() +var Player.team: BarbTeam? + get() = playerTeams[this] + set(value) { + if (value == null) playerTeams.remove(this) + else playerTeams[this] = value + }*/ + +data class PartySlot( val index: Int, val player: Player, var role: BarbRole? = null ) +data class PendingRecruit( var player: Player, var role: BarbRole? = null ) +private val PartySpawns = arrayOf(30 to 18, 29 to 17, 31 to 17, 28 to 16, 32 to 16) + +class BarbTeam(val session: BarbassaultSession, leader: Player) { + companion object { + const val MAX_SLOTS = 5 + const val LEADER_SLOT = 0 + } + + var recruit: PendingRecruit? = null + private val slots: Array = arrayOfNulls(MAX_SLOTS) + + init { + slots[LEADER_SLOT] = PartySlot(LEADER_SLOT, leader) + } + + fun slotOf(player: Player): Int = + slots.indexOfFirst { it?.player == player } + + fun getSlot(index: Int): PartySlot? = + slots.getOrNull(index) + + fun allPlayers(): List = + slots.filterNotNull().map { it.player } + + fun isLeader(player: Player): Boolean = + slotOf(player) == LEADER_SLOT + + fun isFull(): Boolean = + slots.all { it != null } + + fun addRecruit(player: Player): Boolean { + recruit = PendingRecruit(player) + return true + } + fun addPlayer(player: Player): Boolean { + if (slotOf(player) != -1) return false + + val freeIndex = slots.indexOfFirst { it == null } + if (freeIndex == -1) return false + + slots[freeIndex] = PartySlot(freeIndex, player) + return true + } + + /** fun removePlayer(player: Player) { + val idx = slotOf(player) + if (idx == -1) return + + slots[idx] = null + player.team = null + player.removeAttribute(BA_SESSION_KEY) + clearLogoutListener(player, BA_SESSION_KEY) + //remove from barbsession barbmteam + }*/ + fun removePlayer(player: Player) { + val idx = slotOf(player) + if (idx == -1) return + slots[idx] = null + } + + fun setRoleForPlayer(player: Player, role: BarbRole): Boolean { + val idx = slotOf(player) + if (idx == -1) return false + + slots[idx]?.role = role + allPlayers().forEach { updateRoleAvailabilityFor(it) } + return true + } + + fun getRoleForPlayer(player: Player): BarbRole? { + val idx = slotOf(player) + return slots.getOrNull(idx)?.role + } + + fun getLeader(): PartySlot? { + return slots[0] + } + fun roleCounts(): RoleCounts { + var att = 0 + var def = 0 + var coll = 0 + var heal = 0 + + slots.forEach { slot -> + when (slot?.role) { + BarbRole.ATTACKER -> att++ + BarbRole.DEFENDER -> def++ + BarbRole.COLLECTOR -> coll++ + BarbRole.HEALER -> heal++ + null -> {} + } + } + + return RoleCounts(att, def, coll, heal) + } + fun updateRoleAvailabilityFor(player: Player) { + updateRoleAvailability(roleCounts(),assignedRoleCount(),player ) + } + + fun assignedRoleCount(): Int = + slots.count { it?.role != null } + + fun spawnLocationFor(player: Player): Location { + val idx = slotOf(player) + val (x, y) = PartySpawns[idx] + return session.base.transform(x, y, 0) + } +} + +data class RoleCounts(val att: Int, val def: Int, val coll: Int, val heal: Int ) + +object BarbTeamManager { + + fun createTeam(leader: Player): Boolean { + val session = BarbassaultActivity.createSession(leader) +// if (session.team != null) return false + + val team = BarbTeam(session, leader) + session.team = team + + sendMessage(leader, "TeamCreated") + updateTeam(team) + return true + } + + fun disbandTeam(session: BarbassaultSession) { + val team = session.team ?: return + + team.allPlayers().forEach { + it.sendMessage("Your leader has left the room and therefore cleared the team!") + it.removeAttribute("ba-session") + updateCurrentTeam(it) + if (session.state == BarbassaultState.STARTING) { + it.properties.teleportLocation = Location.create(2593, 5264, 0) + } + } + session.endSession() + } + + fun joinTeam(player: Player, role: BarbRole): Boolean { + val session = player.baSession ?: return false + val team = session.team ?: return false + team.recruit = null + if (!team.addPlayer(player)) { + player.sendMessage("That party is full.") + return false + } + team.setRoleForPlayer(player, role) + team.allPlayers().forEach { + updateCurrentTeam(it) + if (it != player) + it.sendMessage("Your application has been accepted") + } + return true + } + + fun abandonTeam(player: Player) { + val session = player.baSession ?: return + val team = session.team ?: return + if (team.isLeader(player)) { + disbandTeam(session) + return + } + team.removePlayer(player) + player.baSession = null + updateCurrentTeam(player) + updateTeam(team) + } + + fun updateTeam(team: BarbTeam) { + team.allPlayers().forEach { + updateCurrentTeam(it) + } + } + fun acceptInvite(player: Player, role: BarbRole) { + val session = player.baSession ?: return + val team = session.team ?: return + val recruit = team.recruit ?: return + if (recruit.player != player) return + joinTeam(player, role) + team.recruit = null + } +} + +//Leader leaving room and causing disband "Your leader has left the room and therefore cleared the team!" +// //"Your recruiter exited the room." +//Accpting invite text " Your application has been accepted" +//The applicant declined your offer. + +//the other player hasn't confirmed their role yet. +//the applicant has chosen a role.0 +//You removed the person from the team. diff --git a/Server/src/main/content/minigame/barbassault/lobby/BarbassaultLobby.kt b/Server/src/main/content/minigame/barbassault/lobby/BarbassaultLobby.kt index c38ca4a34..8bbac85c6 100644 --- a/Server/src/main/content/minigame/barbassault/lobby/BarbassaultLobby.kt +++ b/Server/src/main/content/minigame/barbassault/lobby/BarbassaultLobby.kt @@ -1,28 +1,31 @@ package content.minigame.barbassault.lobby import content.minigame.barbassault.BarbRole -import content.minigame.barbassault.party.Party -import content.minigame.barbassault.party.PartyHandler -import content.minigame.barbassault.party.PartyService +import content.minigame.barbassault.BarbassaultActivity +import content.minigame.barbassault.arena.BarbassaultSession +import content.minigame.barbassault.arena.BarbassaultState +import content.minigame.barbassault.lobby.BarbTeamManager.abandonTeam +import content.minigame.barbassault.lobby.BarbTeamManager.createTeam +import content.minigame.barbassault.lobby.BarbTeamManager.disbandTeam +import content.minigame.barbassault.lobby.BarbTeamManager.joinTeam +import content.minigame.duel.DuelSession import core.api.* +import core.game.component.Component import core.game.interaction.IntType import core.game.interaction.InteractionListener import core.game.node.Node import core.game.node.entity.Entity import core.game.node.entity.player.Player import core.game.node.item.Item -import core.game.system.task.Pulse -import core.game.world.GameWorld.ticks import core.game.world.map.zone.ZoneBorders -import content.minigame.barbassault.arena.BarbassaultSession -import core.game.world.map.build.DynamicRegion import org.rs09.consts.Items import org.rs09.consts.Scenery +import org.rs09.consts.Sounds //"-- Next wave no longer starting" - +private var activity: BarbassaultActivity? = null class BarbassaultLobby : InteractionListener, MapArea { override fun defineAreaBorders(): Array { @@ -32,16 +35,16 @@ class BarbassaultLobby : InteractionListener, MapArea { updatePlayerWave(entity) // openOverlay(entity, 256) // Components.BARBASSAULT_PLAYERSTAT_490 - sendMessage(entity as Player,"Party system is NOT Fully Implemented!!") } override fun areaLeave(entity: Entity, logout: Boolean) { if (entity is Player) { entity.interfaceManager.closeOverlay() val barbassItems = intArrayOf(Items.POISONED_WORMS_10540) - + //abandonTeam(entity) // Right here, its breaking things entity.equipment.removeAll(barbassItems) entity.inventory.removeAll(barbassItems) + } } fun updatePlayerWave(entity: Entity) { @@ -67,23 +70,31 @@ class BarbassaultLobby : InteractionListener, MapArea { //collector 20563 : ch13 //healer 20569 : ch14 override fun defineListeners() { - onUseWithPlayer(Items.SCROLL_10512) { inviter, _, invitee -> - val role = BarbRole.DEFENDER - PartyService.inviteToParty(inviter, invitee as Player, role) + onUseWithPlayer(Items.SCROLL_10512) { leader, _, node -> + val follower = node.asPlayer() + val session = leader.baSession + val team = session?.team - val partyId = inviter.getAttribute("barbass:party-id") - val party = partyId?.let { PartyHandler.getParty(it) } - - if (party != null) { - for (member in party.allMembers()) { - PartyService.updatePartyInterface(member.player) - } + if (team == null) { + leader.sendMessage("No active session found.") + return@onUseWithPlayer false } - return@onUseWithPlayer true + follower.baSession?.let { return@onUseWithPlayer false } // already on a team + + team.recruit = PendingRecruit(follower) + follower.baSession = session + //leader.sendMessage(team.recruit?.player?.username ?: "null") + // joinTeam(follower,BarbRole.DEFENDER) + + openInterface(follower, 493) + openInterface(leader, 492) + + return@onUseWithPlayer true } on(Items.SCROLL_10512, IntType.ITEM, "Read") { player, _ -> //https://youtu.be/GYh6JPKNOSA?t=233 -- I know 2017, but only example for read scroll iv found. + // ima cry, that YT account got deleted. // waveAdvance(player) return@on true @@ -91,43 +102,49 @@ class BarbassaultLobby : InteractionListener, MapArea { on(Items.SCROLL_10512, IntType.ITEM, "Write-Role") { player, _ -> //player.interfaceManager.open(Component(493)) //setInterfaceModel(player, 20561, 493, 8,1) - sendDialogueOptions( - player, - "Which role would you like to perform?", - "Attacker", "Defender","Collector","Healer","Cancel") - addDialogueAction(player) { player , buttonId -> - writeRole(player,buttonId) - } + sendDialogueOptions(player, "Which role would you like to perform?","Attacker", "Defender","Collector","Healer","Cancel") + addDialogueAction(player) { _ , buttonId -> writeRole(player,buttonId) } return@on true } on(Items.SCROLL_10512, IntType.ITEM, "Clear") { player, _ -> - val partyId = player.getAttribute("barbass:party-id") ?: return@on true - val party = PartyHandler.getParty(partyId) ?: return@on true - if (party.getLeader() != player) { - player.sendMessage("Only the party leader can clear the party.") - return@on true + val session = player.baSession + val team = session?.team + if (team != null) { + disbandTeam(session) + createTeam(player) + } else { + createTeam(player) } - val members = party.allMembers().map { it.player } - for (member in members) { - member.removeAttribute("barbass:party-id") - sendMessage(member,"The party has been cleared.") - closeOverlay(member) - openOverlay(member, 256) - PartyService.updatePartyInterface(member) - } - - PartyHandler.removeParty(partyId) return@on true } - + on(Items.SCROLL_10512, IntType.ITEM, "Destroy") { player, item -> + player.dialogueInterpreter.sendDestroyItem(item.id, item.name) + addDialogueAction(player) { _, button -> + if (button == 3) { + if (removeItem(player, item)) { + playAudio(player, Sounds.DESTROY_OBJECT_2381) + abandonTeam(player) + //updateCurrentTeam(player) + } + } + } + return@on true + } on(Scenery.LADDER_20193, IntType.SCENERY, "Climb-down") { player, _ -> + val session = player.baSession ?: run { + player.sendMessage("You are not in a session!") + return@on true + } + if (session.state != BarbassaultState.PARTY_CREATION) { + player.sendMessage("Your team is already starting or in the arena!") + return@on true + } + closeOverlay(player) // close party, - openOverlay(player, 494)// open countdown, Make a Count DownHandler - //start a session - // val session = BarbassaultSession(DynamicRegion.create(8011), activity!!) - // session.start(intArrayOf(player)) + openOverlay(player, 494)// open countdown, + session.beginStartingPhase() return@on true } on(Scenery.DOOR_20209, IntType.SCENERY, "Pass") { player, node -> @@ -156,7 +173,9 @@ class BarbassaultLobby : InteractionListener, MapArea { when (buttonId) { 2 -> { if (player.inventory.add(Item(Items.SCROLL_10512, 1))) { - player.sendMessage("You take scroll from table") + if (createTeam(player)){ + player.sendMessage("You take scroll from table") + } } else { player.sendMessage("You dont have enough inventory space") } @@ -213,35 +232,17 @@ class BarbassaultLobby : InteractionListener, MapArea { else -> null } } - fun createPartyAsLeader(leader: Player, role: BarbRole): Int { - val (partyId, party) = PartyHandler.createNewParty() - val success = party.add(leader, role) - sendMessage(leader, "Party created with ID: $partyId") - if (!success) { - PartyHandler.removeParty(partyId) - } - return partyId - } fun writeRole(player: Player, buttonId: Int) { if (buttonId == 6) return val playerRole = getRoleFromButton(buttonId) ?: return - val partyId = player.getAttribute("barbass:party-id") - val party = partyId?.let { PartyHandler.getParty(it) } - if (party != null) { - val roleCount = party.allMembers().count { it.role == playerRole } - if (roleCount >= 2) { - sendMessage(player,"That role is already full.") - return - } - party.changeRole(player, playerRole) - PartyService.updatePartyInterface(player) - } else { - val newPartyId = createPartyAsLeader(player, playerRole) - PartyService.updatePartyInterface(player) + if (player.baSession?.team != null) { + player.baSession?.team?.setRoleForPlayer(player, playerRole) + BarbTeamManager.updateTeam(player.baSession?.team!!) + sendMessage(player, "You've set your role to ${playerRole.name.lowercase().replaceFirstChar { it.uppercase() }}" + ) } - sendMessage(player,"You've set your role to ${playerRole.name.lowercase().replaceFirstChar { it.uppercase() }}") } fun handlePlayerOptionDoor(player: Player, roomRoleOptions:(RoomRole) -> Unit){ @@ -285,20 +286,22 @@ class BarbassaultLobby : InteractionListener, MapArea { val insideRoom = playerLoc.y <= doorLoc.y val moveY = if (insideRoom) 1 else -1 //ToDo fix walking trough wall when Using door from side. + if (insideRoom) { forceMove(player, playerLoc, doorLoc, 25, 60, null, 819) } forceMove(player, playerLoc, playerLoc.transform(0, moveY, 0), 25, 60, null, 819) { if (insideRoom) { + //player.baSession = null + abandonTeam(player) closeOverlay(player) - PartyService.leaveParty(player) + player.inventory.removeAll(Items.SCROLL_10512) } else { openOverlay(player, iface) - player.sendMessage("you enter wave ${BARBWAVEDOOR[node.id]}") } } } } fun waveAdvance(player: Player) { - var wave = player.getAttribute("barbass:wave", 1) + val wave = player.getAttribute("barbass:wave", 1) if (wave in 1..waveLobbies.size) { val targetLobby = waveLobbies[wave] teleport(player, targetLobby.randomWalkableLoc) @@ -349,7 +352,8 @@ class BarbassaultLobby : InteractionListener, MapArea { MAIN_LOBBY ) - val BARBDOORS = intArrayOf( Scenery.DOOR_20199, + val BARBDOORS = intArrayOf( + Scenery.DOOR_20199, Scenery.DOOR_20200, Scenery.DOOR_20201, Scenery.DOOR_20202, @@ -359,7 +363,7 @@ class BarbassaultLobby : InteractionListener, MapArea { Scenery.DOOR_20206, Scenery.DOOR_20207, Scenery.DOOR_20208, - ) + ) } val BARBWAVEDOOR = hashMapOf( 20199 to 1, diff --git a/Server/src/main/content/minigame/barbassault/lobby/CurrentTeamInterface.kt b/Server/src/main/content/minigame/barbassault/lobby/CurrentTeamInterface.kt new file mode 100644 index 000000000..fcb4efaea --- /dev/null +++ b/Server/src/main/content/minigame/barbassault/lobby/CurrentTeamInterface.kt @@ -0,0 +1,74 @@ +package content.minigame.barbassault.lobby + +import content.minigame.barbassault.BarbRole +import content.minigame.barbassault.lobby.CurrentTeam.ROLE_MODEL_MAP +import content.minigame.barbassault.lobby.CurrentTeam.modelZoom +import core.api.sendMessage +import core.api.setInterfaceModel +import core.api.setInterfaceText +import core.game.component.Component +import core.game.component.ComponentDefinition +import core.game.component.ComponentPlugin +import core.game.node.entity.player.Player +import core.game.node.item.Item +import core.plugin.Initializable +import core.plugin.Plugin +import org.rs09.consts.Items + +@Initializable +class CurrentTeamInterface : ComponentPlugin() { + override fun newInstance(arg: Any?): Plugin { + ComponentDefinition.forId(CurrentTeam.ID).plugin = this + return this + } + + override fun handle(player: Player?,component: Component?,opcode: Int,button: Int,slot: Int,itemId: Int ): Boolean { + return true + } + + override fun open(player: Player?, component: Component?) { + super.open(player, component) + player ?: return + if(player.inventory.containsItem(Item(Items.SCROLL_10512, 1)) ) { + setInterfaceText(player, player.username, CurrentTeam.ID, CurrentTeam.team[0].name) + //the leader might be able to take scroll between rooms? need Proof + } + } + +} +fun updateCurrentTeam(player: Player) { + val team = player.baSession?.team + + + for (slotIndex in 0 until BarbTeam.MAX_SLOTS) { + val uiSlot = CurrentTeam.team[slotIndex] + val partySlot = team?.getSlot(slotIndex) + val slotPlayer = partySlot?.player + val slotRole = partySlot?.role + + val nameText = slotPlayer?.name?.capitalizeWords() ?: CurrentTeam.defaultText + val model = slotRole?.let { ROLE_MODEL_MAP[it] } ?: -1 + setInterfaceText(player, nameText, CurrentTeam.ID, uiSlot.name) + setInterfaceModel(player, model, CurrentTeam.ID, uiSlot.role, modelZoom) + } +} + + +fun String.capitalizeWords(): String = split('_').joinToString("_") { it.replaceFirstChar { c -> c.uppercaseChar() } } + +object CurrentTeam { + const val ID = 256 + val defaultText = "-----" + val modelZoom = 2372 + val ROLE_MODEL_MAP = mapOf(BarbRole.ATTACKER to 20561,BarbRole.COLLECTOR to 20563,BarbRole.DEFENDER to 20566,BarbRole.HEALER to 20569) + data class Slot(val role: Int, val name: Int) + val team = listOf( + Slot(16, 6), + Slot(17, 7), + Slot(18, 8), + Slot(19, 9), + Slot(20, 10) + ) +} + + diff --git a/Server/src/main/content/minigame/barbassault/lobby/RoleSelectInterface.kt b/Server/src/main/content/minigame/barbassault/lobby/RoleSelectInterface.kt new file mode 100644 index 000000000..bb95c010c --- /dev/null +++ b/Server/src/main/content/minigame/barbassault/lobby/RoleSelectInterface.kt @@ -0,0 +1,159 @@ +package content.minigame.barbassault.lobby + +import content.minigame.barbassault.BarbRole +import content.minigame.barbassault.lobby.BarbTeamManager.joinTeam +import core.api.* +import core.game.component.Component +import core.game.component.ComponentDefinition +import core.game.component.ComponentPlugin +import core.game.node.entity.player.Player +import core.plugin.Initializable +import core.plugin.Plugin + +@Initializable +class RoleSelectInterface : ComponentPlugin() { + override fun open(player: Player?, component: Component?) { + super.open(player, component) + var isopen = true + player ?: return + val team = player.baSession?.team; + if (team != null) { team.updateRoleAvailabilityFor(player) } + + component?.setCloseEvent { player, c -> + val leader = team?.getLeader()?.player; + + if (leader != null && leader != player && isopen) { + isopen = false + closeInterface(leader) + //if team.recruit not on team, team.recruit?.player?.baSession = null + team.recruit?.player?.baSession = null + team.recruit = null + } + return@setCloseEvent true + } + + val leaderData = player.baSession?.team?.getLeader() ?: run { + player.sendMessage("No leader found for your team.") + return + } + setInterfaceText(player, leaderData!!.player.name.capitalizeWords(),SelectRole.ID,SelectRole.Leader.name) + setInterfaceText(player, leaderData.role.toString(),SelectRole.ID,SelectRole.Leader.role) + setInterfaceText(player,"0",SelectRole.ID,SelectRole.Leader.wave) + + } + + var selectedButton = -1 + val roleButtons = mapOf( SelectRole.Att to listOf(8, 9), SelectRole.Def to listOf(10, 11), SelectRole.Col to listOf(12, 13),SelectRole.Heal to listOf(14,15) ) + val buttonRoleMap = roleButtons.flatMap { (role, buttons) -> buttons.map { it to role }}.toMap() + val selectRoleToBarbRole = mapOf(SelectRole.Att to BarbRole.ATTACKER,SelectRole.Def to BarbRole.DEFENDER, SelectRole.Col to BarbRole.COLLECTOR, SelectRole.Heal to BarbRole.HEALER ) + + override fun handle(player: Player?, component: Component?, opcode: Int, button: Int, slot: Int, itemId: Int): Boolean { + if (player == null) return true + val team = player.baSession?.team; + val pending = team?.recruit ?: return true + + when (button) { + SelectRole.AcceptButton, SelectRole.AcceptButtonText -> { + val selectedRole = pending.role + if (selectedRole != null) { + joinTeam(pending.player, selectedRole) + player.sendMessage("You have joined as ${selectedRole.name}.") + team.recruit = null + } else { + player.sendMessage("You must select a role first!") + } + return true + } + SelectRole.DeclineButton, SelectRole.DeclineButtonText -> { + handleDecline(player) + return true + } + } + + val clickedSelectRole = buttonRoleMap[button] + if (clickedSelectRole != null && clickedSelectRole.isActive) { + pending.role = selectRoleToBarbRole[clickedSelectRole] + + val displayName = pending.role?.name ?: "Unknown" + setInterfaceText(player, displayName, SelectRole.ID, SelectRole.Status.CurrentRole) + + selectedButton = button + } else { + } + return true + } + + override fun newInstance(arg: Any?): Plugin { + ComponentDefinition.forId(SelectRole.ID).plugin = this + return this + } +} + +fun updateRoleAvailability( counts: RoleCounts, partySize: Int, player: Player ) { + fun canAdd(current: Int, missingRoles: Int): Boolean { + if (partySize >= 5) return false + if (current >= 2) return false + + val remainingSlots = 5 - (partySize + 1) + return remainingSlots >= missingRoles + } + + val missingRoles = listOf(counts.att, counts.def, counts.coll, counts.heal ).count { it == 0 } + + setRoleActive( SelectRole.Att, canAdd( counts.att, if ( counts.att == 0) maxOf(0, missingRoles - 1) else missingRoles ), player ) + setRoleActive( SelectRole.Def, canAdd( counts.def, if ( counts.def == 0) maxOf(0, missingRoles - 1) else missingRoles ), player ) + setRoleActive( SelectRole.Col, canAdd( counts.coll,if (counts.coll == 0) maxOf(0, missingRoles - 1) else missingRoles ), player ) + setRoleActive(SelectRole.Heal, canAdd( counts.heal,if (counts.heal == 0) maxOf(0, missingRoles - 1) else missingRoles ), player ) +} + +private fun setRoleActive(role: SelectRole.Role, active: Boolean, player: Player) { + role.setActive(active) + setInterfaceModel(player,role.model,SelectRole.ID,role.componentId,0) + setComponentVisibility(player,SelectRole.ID,role.activeChild,!role.isActive) +} +private fun handleAccept(player: Player){ + return +} +private fun handleDecline(player: Player) { + closeInterface(player) + val leader = player.baSession?.team?.getLeader()?.player + if (leader != null && leader != player) { + closeInterface(leader) + sendMessage(leader, "The applicant declined your offer.") + } +} + + +object SelectRole { + const val ID = 493 + const val AcceptButton = 16 + const val AcceptButtonText = 17 + const val DeclineButton = 18 + const val DeclineButtonText = 7 + + + class Role(val roleName: String, val componentId: Int, val activeModel: Int, val inactiveModel: Int, val activeChild: Int) { + var isActive: Boolean = false; private set + fun setActive(active: Boolean) { isActive = active } + val model: Int get() = if (isActive) activeModel else inactiveModel + } + + val Att = Role("Attacker",8, 20561, 20560, 20) + val Def = Role("Defender",10, 20566, 20567, 55) + val Col = Role("Collector",13, 20563, 20564, 54) + val Heal = Role("Healer", 14, 20569, 20570, 53) + + data class Slot(val name: Int, val role: Int, val wave: Int) + val Leader = Slot(28, 33, 39) + val Followers = listOf( + Slot(29, 34, 40), + Slot(30, 35, 41), + Slot(31, 36, 42), + Slot(32, 37, 43), + ) + + object Status { + const val CurrentRole = 19 + const val WaitingForAccept = 22 + } +} \ No newline at end of file diff --git a/Server/src/main/content/minigame/barbassault/party/Party.kt b/Server/src/main/content/minigame/barbassault/party/Party.kt deleted file mode 100644 index e46082e9d..000000000 --- a/Server/src/main/content/minigame/barbassault/party/Party.kt +++ /dev/null @@ -1,106 +0,0 @@ -package content.minigame.barbassault.party - -import content.minigame.barbassault.BarbRole -import core.game.node.entity.player.Player - -//todo fix party system. Maybe toss it all away and start over. -data class PartyMember(val player: Player, var role: BarbRole) - -class Party(val id: Int) { - companion object { - const val MAX_MEMBERS = 5 - const val MAX_PER_ROLE = 2 - } - - private val slots = MutableList(MAX_MEMBERS) { null } - - private var leader: Player? = null - - fun add(player: Player, role: BarbRole): Boolean { - // Check if player is already in party - if (slots.any { it?.player == player }) return false - // Check if party full - if (slots.count { it != null } >= MAX_MEMBERS) return false - // Check role limit - if (slots.count { it?.role == role } >= MAX_PER_ROLE) return false - - // Find first empty slot - val emptyIndex = slots.indexOfFirst { it == null } - if (emptyIndex == -1) return false // no empty slots - - slots[emptyIndex] = PartyMember(player, role) - if (leader == null) leader = player - - player.setAttribute("barbass:party-id", this.id) - updateInterfaces() - return true - } - - fun remove(player: Player): Boolean { - val index = slots.indexOfFirst { it?.player == player } - if (index == -1) return false // not in party - - slots[index]?.player?.removeAttribute("barbass:party-id") - slots[index] = null - - if (leader == player) { - disband() - } else { - updateInterfaces() - } - return true - } - - fun updateInterfaces() { - slots.filterNotNull().forEach { - PartyService.updatePartyInterface(it.player) - } - } - - fun disband() { - slots.filterNotNull().forEach { - it.player.removeAttribute("barbass:party-id") - it.player.sendMessage("The party has been disbanded.") - PartyService.updatePartyInterface(it.player) - } - PartyHandler.removeParty(id) - slots.fill(null) - leader = null - } - - fun getLeader(): Player? = leader - - fun setLeader(player: Player) { - if (slots.any { it?.player == player }) { - leader = player - updateInterfaces() - } - } - - fun getRole(player: Player): BarbRole? = - slots.find { it?.player == player }?.role - - fun changeRole(player: Player, newRole: BarbRole): Boolean { - val slot = slots.find { it?.player == player } ?: return false - if (slots.count { it?.role == newRole } >= MAX_PER_ROLE) return false - slot.role = newRole - updateInterfaces() - return true - } - - fun contains(player: Player): Boolean = - slots.any { it?.player == player } - - fun size(): Int = slots.count { it != null } - - fun allMembers(): List = slots.filterNotNull() - fun getSlots(): List = slots.toList() - fun clear() { - slots.filterNotNull().forEach { - it.player.removeAttribute("barbass:party-id") - } - slots.fill(null) - leader = null - updateInterfaces() - } -} diff --git a/Server/src/main/content/minigame/barbassault/party/PartyHandler.kt b/Server/src/main/content/minigame/barbassault/party/PartyHandler.kt deleted file mode 100644 index d89fa5a60..000000000 --- a/Server/src/main/content/minigame/barbassault/party/PartyHandler.kt +++ /dev/null @@ -1,39 +0,0 @@ -package content.minigame.barbassault.party - -object PartyHandler { - private val parties = mutableMapOf() - private val freedIds = ArrayDeque() - private var nextPartyId = 1 - - fun createNewParty(): Pair { - val id = if (freedIds.isNotEmpty()) freedIds.removeFirst() else nextPartyId++ - val party = Party(id) - parties[id] = party - return id to party - } - - fun getOrCreateParty(id: Int): Party = - parties.getOrPut(id) { Party(id) } - - fun getParty(id: Int): Party? = parties[id] - - fun removeParty(id: Int) { - if (parties.remove(id) != null) { - freedIds.add(id) - } - } - - fun allParties(): Map = parties.toMap() - - fun cleanupOfflineParties() { - val toRemove = parties.filter { (_, party) -> - val leader = party.getLeader() - leader == null || !leader.isActive() - }.keys - - for (partyId in toRemove) { - removeParty(partyId) - println("Removed party $partyId because leader was offline or null.") - } - } -} diff --git a/Server/src/main/content/minigame/barbassault/party/PartyService.kt b/Server/src/main/content/minigame/barbassault/party/PartyService.kt deleted file mode 100644 index e7f1b613b..000000000 --- a/Server/src/main/content/minigame/barbassault/party/PartyService.kt +++ /dev/null @@ -1,107 +0,0 @@ -package content.minigame.barbassault.party - -import content.minigame.barbassault.BarbRole -import core.api.sendMessage -import core.api.setInterfaceModel -import core.api.setInterfaceText -import core.game.node.entity.player.Player - -class PartyService { - companion object { - fun inviteToParty(inviter: Player, invitee: Player, role: BarbRole) { - val partyId = inviter.getAttribute("barbass:party-id") - val party = partyId?.let { PartyHandler.getParty(it) } - - when { - partyId == null -> sendMessage(inviter, "You're not in a party.") - - party == null -> sendMessage(inviter, "Party $partyId not found.") - - !party.contains(inviter) -> sendMessage(inviter, "You are not a member of party $partyId.") - - invitee.getAttribute("barbass:party-id") != null -> sendMessage(inviter, "${invitee.name} is already in a party.") - - party.size() >= Party.MAX_MEMBERS -> sendMessage(inviter, "Party is full.") - - party.allMembers().count { it.role == role } >= Party.MAX_PER_ROLE -> sendMessage(inviter, "Too many players with the role $role.") - - !party.add(invitee, role) -> sendMessage(inviter, "Failed to add ${invitee.name} as $role.") - - party.getLeader() != inviter -> sendMessage(inviter, "Only the party leader can invite players.") - - else -> { - invitee.setAttribute("barbass:party-id", partyId) - val formattedRole = role.name.lowercase().replaceFirstChar { it.uppercase() } - sendMessage(inviter, "${invitee.name} joined your party as $formattedRole.") - } - } - } - - fun updatePartyInterface(player: Player) { - val ROLE_MODEL_MAP = mapOf( - BarbRole.ATTACKER to 20561, - BarbRole.COLLECTOR to 20563, - BarbRole.DEFENDER to 20566, - BarbRole.HEALER to 20569 - ) - val iLeaderText = 6 - val iPlayerTextStart = 7 - val iModelOffset = 10 - val modelZoom = 2372 - val iDefaultText = "-----" - val partyId = player.getAttribute("barbass:party-id") ?: return - val party = PartyHandler.getParty(partyId) ?: return - val members = party.allMembers() - val leader = party.getLeader() - - if (leader != null) { - val leaderMember = members.find { it.player == leader } - setInterfaceText(player, leader.username, 256, iLeaderText) - setInterfaceModel(player, ROLE_MODEL_MAP[leaderMember?.role] ?: 20561, 256, iLeaderText + iModelOffset, modelZoom) - } else { - setInterfaceText(player, iDefaultText, 256, iLeaderText) - setInterfaceModel(player, 20561, 256, iLeaderText + iModelOffset, modelZoom) - } - - val otherMembers = members.filter { it.player != leader } - for (i in 0 until 4) { - val slotTextId = iPlayerTextStart + i - val slotModelId = slotTextId + iModelOffset - - if (i < otherMembers.size) { - val member = otherMembers[i] - setInterfaceText(player, member.player.username, 256, slotTextId) - setInterfaceModel(player, ROLE_MODEL_MAP[member.role] ?: 20561, 256, slotModelId, modelZoom) - } else { - setInterfaceText(player, iDefaultText, 256, slotTextId) - setInterfaceModel(player, -1, 256, slotModelId, modelZoom) // Default to attacker icon for empty - } - } - } - - fun leaveParty(player: Player) { - val partyId = player.getAttribute("barbass:party-id") ?: return - val party = PartyHandler.getParty(partyId) ?: return - - if (!party.remove(player)) { - player.sendMessage("Failed to leave the party.") - return - } - - player.removeAttribute("barbass:party-id") - player.sendMessage("You have left the party.") - updatePartyInterface(player) - - // Update remaining party members - for (member in party.allMembers()) { - updatePartyInterface(member.player) - } - - if (party.allMembers().isEmpty()) { - PartyHandler.removeParty(partyId) - } - } - - - } -}