diff --git a/CHANGELOG b/CHANGELOG index b2cf500e8..6741f4a75 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -69,3 +69,4 @@ < --- ABOVE Released December 4, 2021 https://gitlab.com/2009scape/2009scape/-/tags/Dec-4-2021 ---- > - Shooting star discovery bonus xp is now gradually disbursed instead of lump-sum. - Spending points to cancel your slayer task no longer sets your task streak to 0. +- Stars now have bots that will spawn and help mine for stars higher than level 5. \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/ai/general/scriptrepository/ShootingStarBot.kt b/Server/src/main/kotlin/rs09/game/ai/general/scriptrepository/ShootingStarBot.kt new file mode 100644 index 000000000..cd02989d7 --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/ai/general/scriptrepository/ShootingStarBot.kt @@ -0,0 +1,97 @@ +package rs09.game.ai.general.scriptrepository + +import core.game.node.entity.skill.Skills +import core.game.node.item.Item +import core.game.world.map.Location +import core.tools.RandomFunction +import org.rs09.consts.Items +import rs09.game.ai.general.GeneralBotCreator +import rs09.game.ai.general.ScriptAPI +import rs09.game.content.global.worldevents.WorldEvents +import rs09.game.content.global.worldevents.shootingstar.ShootingStarEvent +import rs09.game.interaction.InteractionListener.Companion.SCENERY +import rs09.game.interaction.InteractionListeners +import kotlin.concurrent.timer + +class ShootingStarBot : Script() { + private var state = State.FULL_IDLE + private var timerCountdown = 0 + val star = (WorldEvents.get("shooting-stars") as? ShootingStarEvent)!!.star + + override fun tick() { + bot.fullRestore() + + if(timerCountdown > 0) { + --timerCountdown + return + } + + when(state) { + State.FULL_IDLE -> {} + + State.TELEPORT_TO -> { + scriptAPI.teleport(star.crash_locations[star.location]!!.transform(0, -1, 0)) + state = State.MINING + timerCountdown = 15 + } + + State.MINING -> { + InteractionListeners.run(star.starObject.id, SCENERY, "mine", bot, star.starObject) + } + + State.TELEPORT_BACK -> { + scriptAPI.teleport(spawnLoc) + timerCountdown = 15 + } + } + } + + init { + skills[Skills.ATTACK] = 41 + skills[Skills.RANGE] = RandomFunction.random(30,99) + skills[Skills.MINING] = 99 + skills[Skills.HITPOINTS] = 99 + skills[Skills.DEFENCE] = 99 + skills[Skills.SUMMONING] = 99 + skills[Skills.PRAYER] = 99 + inventory.add(Item(Items.RUNE_PICKAXE_1275)) + } + + override fun newInstance(): Script { + return ShootingStarBot() + } + + fun activate(instant: Boolean) { + state = State.TELEPORT_TO + if(!instant) + timerCountdown = RandomFunction.random(500) + } + + fun sleep() { + state = State.TELEPORT_BACK + } + + fun isMining() : Boolean { + return state == State.MINING + } + + fun isIdle() : Boolean { + return state == State.FULL_IDLE + } + + internal enum class State { + FULL_IDLE, + TELEPORT_TO, + MINING, + TELEPORT_BACK + } + + companion object { + val spawnLoc = Location.create(2230, 3339, 0) + fun new() : ShootingStarBot { + val script = ShootingStarBot() + GeneralBotCreator(spawnLoc, script) + return script + } + } +} \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/content/global/worldevents/shootingstar/ShootingStar.kt b/Server/src/main/kotlin/rs09/game/content/global/worldevents/shootingstar/ShootingStar.kt index 0d5a35009..28f3ad97c 100644 --- a/Server/src/main/kotlin/rs09/game/content/global/worldevents/shootingstar/ShootingStar.kt +++ b/Server/src/main/kotlin/rs09/game/content/global/worldevents/shootingstar/ShootingStar.kt @@ -8,6 +8,7 @@ import core.game.world.map.Location import rs09.ServerStore.getBoolean import rs09.ServerStore.getInt import rs09.ServerStore.getString +import rs09.game.ai.general.scriptrepository.ShootingStarBot import rs09.game.world.repository.Repository /** @@ -55,12 +56,15 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando var isSpawned = false var spriteSpawned = false var firstStar = true + var selfBots = ArrayList() + var activePlayers = HashSet() /** * Degrades a ShootingStar (or removes the starObject and spawns a Star Sprite if it's the last star) */ fun degrade() { if(level.ordinal == 0){ + selfBots.filter { it.isMining() }.forEach { it.sleep() } SceneryBuilder.remove(starObject) isSpawned = false starSprite.location = starObject.location @@ -93,6 +97,14 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando rebuildVars() clearSprite() SceneryBuilder.add(starObject) + if(!isSpawned) { + (0..2).forEach { + selfBots.add(ShootingStarBot.new()) + } + } + if (level.ordinal + 1 > 5) { + selfBots.filter { it.isIdle() }.forEach { it.activate(true) } + } isSpawned = true Repository.sendNews("A shooting star level ${level.ordinal + 1} just crashed near ${location.toLowerCase()}!") } @@ -149,6 +161,28 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando player.dialogueInterpreter.sendDialogue("This is a size " + (level.ordinal + 1) + " star. A Mining level of at least " + miningLevel + " is", "required to mine this layer. There is $dustLeft stardust remaining", "until the next layer.") } + /** + * Notifies the star when a player begins mining it + */ + fun notifyNewPlayer(player: Player) { + if(activePlayers.size < 3){ + val leavingBot = selfBots.firstOrNull { it.isMining() } + leavingBot?.sleep() + } + activePlayers.add(player) + } + + /** + * Notifies the star when a player stops mining it + */ + fun notifyPlayerLeave(player: Player) { + activePlayers.remove(player) + if (activePlayers.size < 3){ + val newBot = selfBots.firstOrNull() { it.isIdle() } + newBot?.activate(true) + } + } + /** * Gets the mining level required based on the star's current level ordinal. */ diff --git a/Server/src/main/kotlin/rs09/game/content/global/worldevents/shootingstar/ShootingStarMiningPulse.kt b/Server/src/main/kotlin/rs09/game/content/global/worldevents/shootingstar/ShootingStarMiningPulse.kt index 198ad286b..763d1a910 100644 --- a/Server/src/main/kotlin/rs09/game/content/global/worldevents/shootingstar/ShootingStarMiningPulse.kt +++ b/Server/src/main/kotlin/rs09/game/content/global/worldevents/shootingstar/ShootingStarMiningPulse.kt @@ -24,16 +24,28 @@ class ShootingStarMiningPulse(player: Player?, node: Scenery?, val star: Shootin private var ticks = 0 override fun start() { if(!star.isSpawned) return + + if(!player.isArtificial) { + star.notifyNewPlayer(player) + } super.start() } + override fun stop() { + super.stop() + + if(!player.isArtificial){ + star.notifyPlayerLeave(player) + } + } + override fun checkRequirements(): Boolean { tool = SkillingTool.getPickaxe(player) if (!star.starObject.isActive || !star.isSpawned) { return false } //checks if the star has been discovered and if not, awards the bonus xp. Xp can be awarded regardless of mining level as per the wiki. - if (!star.isDiscovered) { + if (!star.isDiscovered && !player.isArtificial) { val bonusXp = 75 * player.skills.getStaticLevel(Skills.MINING) player.incrementAttribute("/save:shooting-star:bonus-xp", bonusXp) Repository.sendNews(player.username + " is the discoverer of the crashed star near " + star.location + "!")