diff --git a/Server/src/main/content/global/skill/magic/MagicAltarListener.kt b/Server/src/main/content/global/skill/magic/MagicAltarListener.kt index eb4e61fc5..1ce52cf50 100644 --- a/Server/src/main/content/global/skill/magic/MagicAltarListener.kt +++ b/Server/src/main/content/global/skill/magic/MagicAltarListener.kt @@ -10,6 +10,8 @@ import core.game.node.entity.skill.Skills import org.rs09.consts.Scenery import org.rs09.consts.Sounds import content.data.Quests +import core.game.event.SpellbookChangeEvent +import core.game.node.entity.player.link.SpellBookManager class MagicAltarListener : InteractionListener { override fun defineListeners() { @@ -46,15 +48,25 @@ class MagicAltarListener : InteractionListener { player.skills.decrementPrayerPoints(player.skills.prayerPoints) } - if (SpellBook.forInterface(player.spellBookManager.spellBook) == if (altar.id == ANCIENT_ALTAR) SpellBook.ANCIENT else SpellBook.LUNAR) { - sendMessage(player, if (altar.id == ANCIENT_ALTAR) "You feel a strange drain upon your memory..." else "Modern spells activated!") - player.spellBookManager.setSpellBook(SpellBook.MODERN) - player.spellBookManager.update(player) - } else { - sendMessage(player, if (altar.id == ANCIENT_ALTAR) "You feel a strange wisdom fill your mind..." else "Lunar spells activated!") - player.spellBookManager.setSpellBook(if (altar.id == ANCIENT_ALTAR) SpellBook.ANCIENT else SpellBook.LUNAR) - player.spellBookManager.update(player) - } + if (SpellBook.forInterface(player.spellBookManager.spellBook) == if (altar.id == ANCIENT_ALTAR) SpellBook.ANCIENT else SpellBook.LUNAR) { + player.dispatch(SpellbookChangeEvent( + SpellBook.forInterface(player.spellBookManager.spellBook), + SpellBook.MODERN, + SpellBookManager.SpellbookChangeSource.ALTAR) + ) + sendMessage(player, if (altar.id == ANCIENT_ALTAR) "You feel a strange drain upon your memory..." else "Modern spells activated!") + player.spellBookManager.setSpellBook(SpellBook.MODERN) + player.spellBookManager.update(player) + } else { + player.dispatch(SpellbookChangeEvent( + SpellBook.forInterface(player.spellBookManager.spellBook), + if (altar.id == ANCIENT_ALTAR) SpellBook.ANCIENT else SpellBook.LUNAR, + SpellBookManager.SpellbookChangeSource.ALTAR) + ) + sendMessage(player, if (altar.id == ANCIENT_ALTAR) "You feel a strange wisdom fill your mind..." else "Lunar spells activated!") + player.spellBookManager.setSpellBook(if (altar.id == ANCIENT_ALTAR) SpellBook.ANCIENT else SpellBook.LUNAR) + player.spellBookManager.update(player) + } } companion object { diff --git a/Server/src/main/content/global/skill/magic/SpellbookSwapDialogue.java b/Server/src/main/content/global/skill/magic/SpellbookSwapDialogue.java index 8f9a62c8e..647db3be0 100644 --- a/Server/src/main/content/global/skill/magic/SpellbookSwapDialogue.java +++ b/Server/src/main/content/global/skill/magic/SpellbookSwapDialogue.java @@ -2,9 +2,12 @@ package content.global.skill.magic; import core.game.component.Component; import core.game.dialogue.DialoguePlugin; +import core.game.event.SpellbookChangeEvent; import core.game.node.entity.player.Player; -import core.plugin.Initializable; +import core.game.node.entity.player.link.SpellBookManager.SpellbookChangeSource; import core.game.node.entity.player.link.SpellBookManager.SpellBook; +import core.plugin.Initializable; + /** * Handles the SpellbookSwapDialogue dialogue. @@ -73,6 +76,11 @@ public class SpellbookSwapDialogue extends DialoguePlugin { break; } final SpellBook book = type == 1 ? SpellBook.ANCIENT : SpellBook.MODERN; + player.dispatch(new SpellbookChangeEvent( + SpellBook.LUNAR, + book, + SpellbookChangeSource.SPELLBOOK_SWAP_CAST) + ); player.getSpellBookManager().setSpellBook(book); player.getInterfaceManager().openTab(new Component(book.getInterfaceId())); end(); diff --git a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt index b89b1a3c7..4ff7b2419 100644 --- a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt +++ b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt @@ -24,12 +24,17 @@ import core.game.system.config.NPCConfigParser import core.game.system.task.Pulse import core.game.system.timer.impl.PoisonImmunity import core.game.system.timer.impl.SkillRestore +import core.game.system.timer.impl.SpellbookSwap import core.game.world.map.Location import core.game.world.map.RegionManager import core.game.world.repository.Repository import core.game.world.update.flag.context.Animation import core.tools.RandomFunction -import org.rs09.consts.* +import org.rs09.consts.Animations +import org.rs09.consts.Components +import org.rs09.consts.Graphics +import org.rs09.consts.Items +import org.rs09.consts.Sounds import kotlin.math.floor class LunarListeners : SpellListener("lunar"), Commands { @@ -280,9 +285,14 @@ class LunarListeners : SpellListener("lunar"), Commands { */ // Level 96 - /** - * Spellbook Swap - */ + onCast(Lunar.SPELLBOOK_SWAP, NONE) { player, _ -> + requires(player, 96, arrayOf( + Item(Items.LAW_RUNE_563, 1), + Item(Items.COSMIC_RUNE_564, 2), + Item(Items.ASTRAL_RUNE_9075, 3) + )) + spellbookSwap(player) + } } // Spell handlers @@ -785,9 +795,15 @@ class LunarListeners : SpellListener("lunar"), Commands { */ // Level 96 - /** - * Spellbook Swap - */ + private fun spellbookSwap(player : Player) { + removeRunes(player, true) + lock(player, 9) + visualizeSpell(player, 6299, 1062) + player.dialogueInterpreter.open(3264731) + registerTimer(player, SpellbookSwap()) + addXP(player, 130.0) + setDelay(player, false) + } // Other/Multi spell use-case private fun sendTeleport(player: Player, xp: Double, loc: Location){ diff --git a/Server/src/main/content/global/skill/magic/lunar/SpellbookSwapSpell.java b/Server/src/main/content/global/skill/magic/lunar/SpellbookSwapSpell.java deleted file mode 100644 index 15f609be1..000000000 --- a/Server/src/main/content/global/skill/magic/lunar/SpellbookSwapSpell.java +++ /dev/null @@ -1,86 +0,0 @@ -package content.global.skill.magic.lunar; - -import core.game.component.Component; -import core.game.node.entity.combat.spell.MagicSpell; -import core.game.node.entity.combat.spell.Runes; -import core.game.node.Node; -import core.game.node.entity.Entity; -import core.game.node.entity.combat.spell.SpellType; -import core.game.node.entity.player.Player; -import core.game.node.entity.player.link.SpellBookManager.SpellBook; -import core.game.node.item.Item; -import core.game.system.task.Pulse; -import core.game.world.GameWorld; -import core.game.world.update.flag.context.Animation; -import core.game.world.update.flag.context.Graphics; -import core.plugin.Initializable; -import core.plugin.Plugin; -import core.tools.RandomFunction; - -import static core.tools.TickUtilsKt.minutesToTicks; - -/** - * The spellbook swap spell. - * @author 'Vexia - */ -@Initializable -public class SpellbookSwapSpell extends MagicSpell { - - /** - * Represents the animation of this spell. - */ - private final Animation ANIMATION = new Animation(6299); - - /** - * Represents the graphics of this spell. - */ - private final Graphics GRAPHIC = new Graphics(1062); - - /** - * Constructs a new {@code SpellbookSwapSpell} {@code Object}. - */ - public SpellbookSwapSpell() { - super(SpellBook.LUNAR, 96, 130, null, null, null, new Item[] { new Item(Runes.LAW_RUNE.getId(), 1), new Item(Runes.COSMIC_RUNE.getId(), 2), new Item(Runes.ASTRAL_RUNE.getId(), 3) }); - } - - @Override - public Plugin newInstance(SpellType arg) throws Throwable { - SpellBook.LUNAR.register(12, this); - return this; - } - - @Override - public boolean cast(Entity entity, Node target) { - final Player player = (Player) entity; - if (!super.meetsRequirements(player, true, true)) { - return false; - } - player.lock(9); - player.animate(ANIMATION); - player.graphics(GRAPHIC); - player.getDialogueInterpreter().open(3264731); - final int id = RandomFunction.random(1, 500000); - player.setAttribute("spell:swap", id); - GameWorld.getPulser().submit(new Pulse(minutesToTicks(2), player) { - @Override - public boolean pulse() { - if (player.getAttribute("spell:swap", 0) == id) { - removeTemporarySpell(player); - } - return true; - } - - }); - return true; - } - - /** - * Method used to remove the temp spell swap. - * @param player the player. - */ - public static void removeTemporarySpell(final Player player) { - player.removeAttribute("spell:swap"); - player.getSpellBookManager().setSpellBook(SpellBook.LUNAR); - player.getInterfaceManager().openTab(new Component(SpellBook.LUNAR.getInterfaceId())); - } -} diff --git a/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt b/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt index eae541c70..e87f2ce83 100644 --- a/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt +++ b/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt @@ -18,6 +18,7 @@ import core.cache.def.impl.ItemDefinition import core.tools.END_DIALOGUE import org.rs09.consts.Items import content.data.Quests +import core.game.event.SpellbookChangeEvent enum class SkillcapePerks(val attribute: String, val effect: ((Player) -> Unit)? = null) { BAREFISTED_SMITHING("cape_perks:barefisted-smithing"), @@ -201,19 +202,21 @@ enum class SkillcapePerks(val attribute: String, val effect: ((Player) -> Unit)? } end() - if(spellbook != null){ - if (spellbook == SpellBookManager.SpellBook.ANCIENT) { - if (!hasRequirement(player, Quests.DESERT_TREASURE)) - return true - } - else if (spellbook == SpellBookManager.SpellBook.LUNAR) { - if (!hasRequirement(player, Quests.LUNAR_DIPLOMACY)) - return true - } - player.spellBookManager.setSpellBook(spellbook) - player.interfaceManager.openTab(Component(spellbook.interfaceId)) - player.incrementAttribute("/save:cape_perks:librarian-magus-charges",-1) - } + if (spellbook != null) { + if (spellbook == SpellBookManager.SpellBook.ANCIENT) { + if (!hasRequirement(player, Quests.DESERT_TREASURE)) return true + } else if (spellbook == SpellBookManager.SpellBook.LUNAR) { + if (!hasRequirement(player, Quests.LUNAR_DIPLOMACY)) return true + } + player.dispatch(SpellbookChangeEvent( + SpellBookManager.SpellBook.forInterface(player.spellBookManager.spellBook), + spellbook, + SpellBookManager.SpellbookChangeSource.MAGIC_CAPE_PERK) + ) + player.spellBookManager.setSpellBook(spellbook) + player.interfaceManager.openTab(Component(spellbook.interfaceId)) + player.incrementAttribute("/save:cape_perks:librarian-magus-charges", -1) + } return true } diff --git a/Server/src/main/core/api/Event.kt b/Server/src/main/core/api/Event.kt index 1c1bc1ea1..6400008d7 100644 --- a/Server/src/main/core/api/Event.kt +++ b/Server/src/main/core/api/Event.kt @@ -23,6 +23,7 @@ object Event { @JvmStatic val AttributeSet = AttributeSetEvent::class.java @JvmStatic val AttributeRemoved = AttributeRemoveEvent::class.java @JvmStatic val SpellCast = SpellCastEvent::class.java + @JvmStatic val SpellbookChange = SpellbookChangeEvent::class.java @JvmStatic val ItemAlchemized = ItemAlchemizationEvent::class.java @JvmStatic val ItemEquipped = ItemEquipEvent::class.java @JvmStatic val ItemUnequipped = ItemUnequipEvent::class.java diff --git a/Server/src/main/core/game/event/Events.kt b/Server/src/main/core/game/event/Events.kt index 900b41629..b11d6241b 100644 --- a/Server/src/main/core/game/event/Events.kt +++ b/Server/src/main/core/game/event/Events.kt @@ -6,6 +6,7 @@ import core.game.node.Node import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import core.game.node.entity.player.link.SpellBookManager.SpellBook +import core.game.node.entity.player.link.SpellBookManager.SpellbookChangeSource import core.game.node.entity.player.link.TeleportManager.TeleportType import core.game.node.entity.player.link.prayer.PrayerType import core.game.node.item.Item @@ -34,6 +35,7 @@ data class InterfaceCloseEvent(val component: Component) : Event data class AttributeSetEvent(val entity: Entity, val attribute: String, val value: Any) : Event data class AttributeRemoveEvent(val entity: Entity, val attribute: String) : Event data class SpellCastEvent(val spellBook: SpellBook, val spellId: Int, val target: Node? = null) : Event +data class SpellbookChangeEvent(val oldSpellBook: SpellBook, val newSpellBook: SpellBook, val source: SpellbookChangeSource) : Event data class ItemAlchemizationEvent(val itemId: Int, val isHigh: Boolean) : Event data class ItemEquipEvent(val itemId: Int, val slotId: Int) : Event data class ItemUnequipEvent(val itemId: Int, val slotId: Int) : Event diff --git a/Server/src/main/core/game/node/entity/player/link/SpellBookManager.java b/Server/src/main/core/game/node/entity/player/link/SpellBookManager.java index 7e0e456c4..72fd3005a 100644 --- a/Server/src/main/core/game/node/entity/player/link/SpellBookManager.java +++ b/Server/src/main/core/game/node/entity/player/link/SpellBookManager.java @@ -55,6 +55,16 @@ public final class SpellBookManager { return spellBook; } + /** + * All the possible ways a SpellBook can get changed. + */ + public enum SpellbookChangeSource { + ALTAR, + MAGIC_CAPE_PERK, + SPELLBOOK_SWAP_CAST, + SPELLBOOK_SWAP_RESTORE + } + /** * Represents a characters spell book. * @author 'Vexia @@ -134,5 +144,4 @@ public final class SpellBookManager { return spells.get(buttonId); } } - } \ No newline at end of file diff --git a/Server/src/main/core/game/system/timer/impl/SpellbookSwap.kt b/Server/src/main/core/game/system/timer/impl/SpellbookSwap.kt new file mode 100644 index 000000000..d52329fad --- /dev/null +++ b/Server/src/main/core/game/system/timer/impl/SpellbookSwap.kt @@ -0,0 +1,71 @@ +package core.game.system.timer.impl + +import core.api.Event.SpellCast +import core.api.Event.SpellbookChange +import core.api.removeTimer +import core.game.event.EventHook +import core.game.event.SpellCastEvent +import core.game.event.SpellbookChangeEvent +import core.game.node.entity.Entity +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.SpellBookManager.* +import core.game.system.timer.PersistTimer +import core.tools.minutesToTicks + +class SpellbookSwap : PersistTimer(runInterval = minutesToTicks(2), identifier = "spellbook:swap") { + private val spellCastHook = object : EventHook { + override fun process(entity : Entity, event : SpellCastEvent) { + if (event.spellBook == SpellBook.LUNAR && event.spellId == 12) return + + revertSpellbook(entity) + removeTimer(entity) + } + } + + private val spellBookChangeHook = object : EventHook { + override fun process(entity : Entity, event : SpellbookChangeEvent) { + if (event.source != SpellbookChangeSource.SPELLBOOK_SWAP_CAST && event.source != SpellbookChangeSource.SPELLBOOK_SWAP_RESTORE) { + removeTimer(entity) + } + } + } + + override fun run(entity : Entity) : Boolean { + revertSpellbook(entity) + return true + } + + override fun onRegister(entity : Entity) { + entity.hook(SpellCast, spellCastHook) + entity.hook(SpellbookChange, spellBookChangeHook) + /* + if (entity is Player) { + registerLogoutListener(entity, "spellbook:swap") { player -> + revertSpellbook(player) + } + } + */ + } + + override fun onRemoval(entity : Entity) { + entity.unhook(spellCastHook) + entity.unhook(spellBookChangeHook) + /* + if (entity is Player) { + clearLogoutListener(entity, "spellbook:swap") + } + */ + } + + private fun revertSpellbook(entity : Entity) { + if (entity !is Player) return + if (SpellBook.forInterface(entity.spellBookManager.spellBook) == SpellBook.LUNAR) return + entity.dispatch(SpellbookChangeEvent( + SpellBook.forInterface(entity.spellBookManager.spellBook), + SpellBook.LUNAR, + SpellbookChangeSource.SPELLBOOK_SWAP_RESTORE) + ) + entity.spellBookManager.setSpellBook(SpellBook.LUNAR) + entity.spellBookManager.update(entity) + } +}