diff --git a/game/plugin/api/src/org/apollo/game/plugins/api/player.kt b/game/plugin/api/src/org/apollo/game/plugins/api/player.kt deleted file mode 100644 index 87881bdd..00000000 --- a/game/plugin/api/src/org/apollo/game/plugins/api/player.kt +++ /dev/null @@ -1,28 +0,0 @@ -package org.apollo.game.plugins.api - -import org.apollo.game.model.entity.Player -import org.apollo.game.model.entity.Skill -import org.apollo.game.model.entity.SkillSet - -val Player.skills: SkillSet get() = skillSet -val SkillSet.attack: Skill get() = getSkill(Skill.ATTACK) -val SkillSet.defence: Skill get() = getSkill(Skill.DEFENCE) -val SkillSet.strength: Skill get() = getSkill(Skill.STRENGTH) -val SkillSet.hitpoints: Skill get() = getSkill(Skill.HITPOINTS) -val SkillSet.ranged: Skill get() = getSkill(Skill.RANGED) -val SkillSet.prayer: Skill get() = getSkill(Skill.PRAYER) -val SkillSet.magic: Skill get() = getSkill(Skill.MAGIC) -val SkillSet.cooking: Skill get() = getSkill(Skill.COOKING) -val SkillSet.woodcutting: Skill get() = getSkill(Skill.WOODCUTTING) -val SkillSet.fletching: Skill get() = getSkill(Skill.FLETCHING) -val SkillSet.fishing: Skill get() = getSkill(Skill.FISHING) -val SkillSet.firemaking: Skill get() = getSkill(Skill.FIREMAKING) -val SkillSet.crafting: Skill get() = getSkill(Skill.CRAFTING) -val SkillSet.smithing: Skill get() = getSkill(Skill.SMITHING) -val SkillSet.mining: Skill get() = getSkill(Skill.MINING) -val SkillSet.herblore: Skill get() = getSkill(Skill.HERBLORE) -val SkillSet.agility: Skill get() = getSkill(Skill.AGILITY) -val SkillSet.thieving: Skill get() = getSkill(Skill.THIEVING) -val SkillSet.slayer: Skill get() = getSkill(Skill.SLAYER) -val SkillSet.farming: Skill get() = getSkill(Skill.FARMING) -val SkillSet.runecraft: Skill get() = getSkill(Skill.RUNECRAFT) \ No newline at end of file diff --git a/game/plugin/api/src/player.kt b/game/plugin/api/src/player.kt new file mode 100644 index 00000000..473b13f6 --- /dev/null +++ b/game/plugin/api/src/player.kt @@ -0,0 +1,81 @@ +package org.apollo.game.plugin.api + +import org.apollo.game.model.entity.Player +import org.apollo.game.model.entity.Skill +import org.apollo.game.model.entity.SkillSet + +val Player.attack: SkillProxy get() = SkillProxy(skillSet, Skill.ATTACK) +val Player.defence: SkillProxy get() = SkillProxy(skillSet, Skill.DEFENCE) +val Player.strength: SkillProxy get() = SkillProxy(skillSet, Skill.STRENGTH) +val Player.hitpoints: SkillProxy get() = SkillProxy(skillSet, Skill.HITPOINTS) +val Player.ranged: SkillProxy get() = SkillProxy(skillSet, Skill.RANGED) +val Player.prayer: SkillProxy get() = SkillProxy(skillSet, Skill.PRAYER) +val Player.magic: SkillProxy get() = SkillProxy(skillSet, Skill.MAGIC) +val Player.cooking: SkillProxy get() = SkillProxy(skillSet, Skill.COOKING) +val Player.woodcutting: SkillProxy get() = SkillProxy(skillSet, Skill.WOODCUTTING) +val Player.fletching: SkillProxy get() = SkillProxy(skillSet, Skill.FLETCHING) +val Player.fishing: SkillProxy get() = SkillProxy(skillSet, Skill.FISHING) +val Player.firemaking: SkillProxy get() = SkillProxy(skillSet, Skill.FIREMAKING) +val Player.crafting: SkillProxy get() = SkillProxy(skillSet, Skill.CRAFTING) +val Player.smithing: SkillProxy get() = SkillProxy(skillSet, Skill.SMITHING) +val Player.mining: SkillProxy get() = SkillProxy(skillSet, Skill.MINING) +val Player.herblore: SkillProxy get() = SkillProxy(skillSet, Skill.HERBLORE) +val Player.agility: SkillProxy get() = SkillProxy(skillSet, Skill.AGILITY) +val Player.thieving: SkillProxy get() = SkillProxy(skillSet, Skill.THIEVING) +val Player.slayer: SkillProxy get() = SkillProxy(skillSet, Skill.SLAYER) +val Player.farming: SkillProxy get() = SkillProxy(skillSet, Skill.FARMING) +val Player.runecraft: SkillProxy get() = SkillProxy(skillSet, Skill.RUNECRAFT) + +/** + * A proxy class to allow + */ +class SkillProxy(val skills: SkillSet, val skill: Int) { + + /** + * The maximum level of this skill. + */ + val maximum = skills.getMaximumLevel(skill) + + /** + * The current level of this skill. + */ + val current = skills.getCurrentLevel(skill) + + val experience = ExperienceProxy() + + /** + * A proxy class to make [experience] (effectively) write-only. + */ + inner class ExperienceProxy { + + operator fun plusAssign(amount: Int) = skills.addExperience(skill, amount.toDouble()) + + operator fun plusAssign(amount: Double) = skills.addExperience(skill, amount) + + } + + /** + * Boosts the current level of this skill by [amount], if possible (i.e. if `current + amount <= maximum + amount`). + */ + fun boost(amount: Int) { + val new = Math.min(current + amount, maximum + amount) + skills.setCurrentLevel(skill, new) + } + + /** + * Drains the current level of this skill by [amount], if possible (i.e. if `current - amount >= 0`). + */ + fun drain(amount: Int) { + val new = Math.max(current - amount, 0) + skills.setCurrentLevel(skill, new) + } + + /** + * Restores the current level of this skill by [amount], if possible (i.e. if `current + amount < maximum`). + */ + fun restore(amount: Int) { + val new = Math.max(current + amount, maximum) + skills.setCurrentLevel(skill, new) + } + +} \ No newline at end of file diff --git a/game/plugin/skills/fishing/src/fishing.plugin.kts b/game/plugin/skills/fishing/src/fishing.plugin.kts index cc53c99c..56755edb 100644 --- a/game/plugin/skills/fishing/src/fishing.plugin.kts +++ b/game/plugin/skills/fishing/src/fishing.plugin.kts @@ -1,14 +1,13 @@ + import Fishing_plugin.FishingAction import org.apollo.game.action.ActionBlock import org.apollo.game.action.AsyncDistancedAction import org.apollo.game.message.impl.NpcActionMessage import org.apollo.game.model.Position import org.apollo.game.model.entity.Player -import org.apollo.game.model.entity.Skill +import org.apollo.game.plugin.api.fishing import org.apollo.game.plugin.skills.fishing.FishingSpot import org.apollo.game.plugin.skills.fishing.FishingTool -import org.apollo.game.plugins.api.fishing -import org.apollo.game.plugins.api.skills import java.util.Objects import java.util.Random @@ -62,7 +61,7 @@ class FishingAction(player: Player, position: Position, val option: FishingSpot. mob.playAnimation(tool.animation) wait(FISHING_DELAY) - val level = mob.skills.fishing.currentLevel + val level = mob.fishing.current val fish = option.sample(level) if (successfulCatch(level, fish.level)) { @@ -72,7 +71,7 @@ class FishingAction(player: Player, position: Position, val option: FishingSpot. mob.inventory.add(fish.id) mob.sendMessage("You catch a ${fish.formattedName}.") - mob.skills.addExperience(Skill.FISHING, fish.experience) + mob.fishing.experience += fish.experience if (mob.inventory.freeSlots() == 0) { mob.inventory.forceCapacityExceeded() @@ -91,7 +90,7 @@ class FishingAction(player: Player, position: Position, val option: FishingSpot. * Verifies that the player can gather fish from the [FishingSpot] they clicked. */ private fun verify(): Boolean { - if (mob.skills.fishing.currentLevel < option.level) { + if (mob.fishing.current < option.level) { mob.sendMessage("You need a fishing level of ${option.level} to fish at this spot.") return false } else if (!hasTool(mob, tool)) { @@ -113,7 +112,6 @@ class FishingAction(player: Player, position: Position, val option: FishingSpot. if (javaClass != other?.javaClass) return false other as FishingAction - return option == other.option && position == other.position && mob == other.mob } diff --git a/game/plugin/skills/mining/src/mining.plugin.kts b/game/plugin/skills/mining/src/mining.plugin.kts index 22c9652c..418bcbb8 100644 --- a/game/plugin/skills/mining/src/mining.plugin.kts +++ b/game/plugin/skills/mining/src/mining.plugin.kts @@ -5,52 +5,47 @@ import org.apollo.game.message.impl.ObjectActionMessage import org.apollo.game.model.Position import org.apollo.game.model.World import org.apollo.game.model.entity.Player -import org.apollo.game.model.entity.Skill import org.apollo.game.model.entity.obj.GameObject +import org.apollo.game.plugin.api.mining import org.apollo.game.plugin.skills.mining.Ore import org.apollo.game.plugin.skills.mining.PICKAXES import org.apollo.game.plugin.skills.mining.Pickaxe import org.apollo.game.plugin.skills.mining.lookupOreRock -import org.apollo.game.plugins.api.Definitions -import org.apollo.game.plugins.api.mining -import org.apollo.game.plugins.api.skills import org.apollo.net.message.Message -import java.util.* +import java.util.Optional class MiningTarget(val objectId: Int, val position: Position, val ore: Ore) { + fun getObject(world: World): Optional { val region = world.regionRepository.fromPosition(position) - val obj = region.findObject(position, objectId) - - return obj + return region.findObject(position, objectId) } fun isSuccessful(mob: Player): Boolean { val offset = if (ore.chanceOffset) 1 else 0 - val percent = (ore.chance * mob.skills.mining.currentLevel + offset) * 100 + val percent = (ore.chance * mob.mining.current + offset) * 100 - return rand(100) < percent; + return rand(100) < percent } + } -class MiningAction(player: Player, val tool: Pickaxe, val target: MiningTarget) : AsyncDistancedAction( - PULSES, - true, - player, - target.position, - ORE_SIZE -) { +class MiningAction( + player: Player, + private val tool: Pickaxe, + private val target: MiningTarget +) : AsyncDistancedAction(PULSES, true, player, target.position, ORE_SIZE) { companion object { private val PULSES = 0 - private val ORE_SIZE = 1; + private val ORE_SIZE = 1 fun pickaxeFor(player: Player): Pickaxe? { return PICKAXES - .filter { it.level <= player.skills.mining.currentLevel } - .filter { player.equipment.contains(it.id) || player.inventory.contains(it.id) } - .sortedByDescending { it.level } - .firstOrNull() + .filter { it.level <= player.mining.current } + .filter { player.equipment.contains(it.id) || player.inventory.contains(it.id) } + .sortedByDescending { it.level } + .firstOrNull() } /** @@ -69,10 +64,10 @@ class MiningAction(player: Player, val tool: Pickaxe, val target: MiningTarget) } } - override fun action() : ActionBlock = { + override fun action(): ActionBlock = { mob.turnTo(position) - val level = mob.skills.mining.currentLevel + val level = mob.mining.current if (level < target.ore.level) { mob.sendMessage("You do not have the required level to mine this rock.") stop() @@ -98,7 +93,7 @@ class MiningAction(player: Player, val tool: Pickaxe, val target: MiningTarget) val oreName = Definitions.item(target.ore.id)?.name?.toLowerCase() mob.sendMessage("You manage to mine some $oreName") - mob.skills.addExperience(Skill.MINING, target.ore.exp) + mob.mining.experience += target.ore.exp mob.world.expireObject(obj.get(), target.ore.objects[target.objectId]!!, target.ore.respawn) stop() } @@ -106,25 +101,32 @@ class MiningAction(player: Player, val tool: Pickaxe, val target: MiningTarget) } } -class ExpiredProspectingAction : DistancedAction { - - constructor(mob: Player, position: Position) : super(PROSPECT_PULSES, true, mob, position, ORE_SIZE) +class ExpiredProspectingAction( + mob: Player, + position: Position +) : DistancedAction(PROSPECT_PULSES, true, mob, position, ORE_SIZE) { companion object { private val PROSPECT_PULSES = 0 - private val ORE_SIZE = 1; + private val ORE_SIZE = 1 } override fun executeAction() { mob.sendMessage("There is currently no ore available in this rock.") - stop(); + stop() } + } -class ProspectingAction(val m: Player, val p: Position, val ore: Ore) : AsyncDistancedAction(PROSPECT_PULSES, true, m, p, ORE_SIZE) { +class ProspectingAction( + player: Player, + position: Position, + private val ore: Ore +) : AsyncDistancedAction(PROSPECT_PULSES, true, player, position, ORE_SIZE) { + companion object { private val PROSPECT_PULSES = 3 - private val ORE_SIZE = 1; + private val ORE_SIZE = 1 /** * Starts a [MiningAction] for the specified [Player], terminating the [Message] that triggered it. @@ -135,9 +137,10 @@ class ProspectingAction(val m: Player, val p: Position, val ore: Ore) : AsyncDis message.terminate() } + } - override fun action() : ActionBlock = { + override fun action(): ActionBlock = { mob.sendMessage("You examine the rock for ores...") mob.turnTo(position) @@ -148,22 +151,23 @@ class ProspectingAction(val m: Player, val p: Position, val ore: Ore) : AsyncDis stop() } + } on { ObjectActionMessage::class } - .where { option == 1 } - .then { - val ore = lookupOreRock(id) - if (ore != null) { - MiningAction.start(this, it, ore) - } + .where { option == 1 } + .then { + val ore = lookupOreRock(id) + if (ore != null) { + MiningAction.start(this, it, ore) } + } on { ObjectActionMessage::class } - .where { option == 2 } - .then { - var ore = lookupOreRock(id) - if (ore != null) { - ProspectingAction.start(this, it, ore) - } + .where { option == 2 } + .then { + val ore = lookupOreRock(id) + if (ore != null) { // TODO send expired action if rock is expired + ProspectingAction.start(this, it, ore) } + } diff --git a/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts b/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts index eb769d49..df04e9fe 100644 --- a/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts +++ b/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts @@ -1,4 +1,3 @@ -import org.apollo.cache.def.ItemDefinition import org.apollo.game.GameConstants import org.apollo.game.action.ActionBlock import org.apollo.game.action.AsyncDistancedAction @@ -6,14 +5,14 @@ import org.apollo.game.message.impl.ObjectActionMessage import org.apollo.game.model.Position import org.apollo.game.model.World import org.apollo.game.model.entity.Player -import org.apollo.game.model.entity.Skill import org.apollo.game.model.entity.obj.GameObject -import org.apollo.game.plugin.skills.woodcutting.* -import org.apollo.game.plugins.api.* -import java.util.* +import org.apollo.game.plugin.api.woodcutting +import org.apollo.game.plugin.skills.woodcutting.Axe +import org.apollo.game.plugin.skills.woodcutting.Tree +import java.util.Optional import java.util.concurrent.TimeUnit -class WoodcuttingTarget(val objectId: Int, val position: Position, val tree: Tree) { +class WoodcuttingTarget(private val objectId: Int, val position: Position, val tree: Tree) { /** * Get the tree object in the world @@ -24,33 +23,37 @@ class WoodcuttingTarget(val objectId: Int, val position: Position, val tree: Tre } /** - * Check if the tree was cut down + * Returns whether or not the tree was cut down. */ - fun isCutDown(mob: Player): Boolean { - return rand(100) <= tree.chance * 100 - } + fun isCutDown(): Boolean = rand(100) <= tree.chance * 100 + } -class WoodcuttingAction(val player: Player, val tool: Axe, val target: WoodcuttingTarget) : AsyncDistancedAction(DELAY, true, player, target.position, TREE_SIZE) { +class WoodcuttingAction( + player: Player, + private val tool: Axe, + private val target: WoodcuttingTarget +) : AsyncDistancedAction(DELAY, true, player, target.position, TREE_SIZE) { companion object { - private val DELAY = 0 - private val TREE_SIZE = 2 - private val MINIMUM_RESPAWN_TIME = 30L //In seconds + private const val DELAY = 0 + private const val TREE_SIZE = 2 + private const val MINIMUM_RESPAWN_TIME = 30L // In seconds /** * Find the highest level axe the player has */ private fun axeFor(player: Player): Axe? { return Axe.getAxes() - .filter { it.level <= player.skills.woodcutting.currentLevel } - .filter { player.equipment.contains(it.id) || player.inventory.contains(it.id) } - .sortedByDescending { it.level } - .firstOrNull() + .filter { it.level <= player.woodcutting.current } + .filter { player.equipment.contains(it.id) || player.inventory.contains(it.id) } + .sortedByDescending { it.level } + .firstOrNull() } /** - * Starts a [WoodcuttingAction] for the specified [Player], terminating the [Message] that triggered it. + * Starts a [WoodcuttingAction] for the specified [Player], terminating the [ObjectActionMessage] that triggered + * it. */ fun start(message: ObjectActionMessage, player: Player, wood: Tree) { val axe = axeFor(player) @@ -73,7 +76,7 @@ class WoodcuttingAction(val player: Player, val tool: Axe, val target: Woodcutti override fun action(): ActionBlock = { mob.turnTo(position) - val level = mob.skills.woodcutting.currentLevel + val level = mob.woodcutting.current if (level < target.tree.level) { mob.sendMessage("You do not have the required level to cut down this tree.") stop() @@ -92,12 +95,12 @@ class WoodcuttingAction(val player: Player, val tool: Axe, val target: Woodcutti } if (mob.inventory.add(target.tree.id)) { - val logName = Definitions.item(target.tree.id)?.name?.toLowerCase(); + val logName = Definitions.item(target.tree.id)?.name?.toLowerCase() mob.sendMessage("You managed to cut some $logName.") - mob.skills.addExperience(Skill.WOODCUTTING, target.tree.exp) + mob.woodcutting.experience += target.tree.exp } - if (target.isCutDown(mob)) { + if (target.isCutDown()) { //respawn time: http://runescape.wikia.com/wiki/Trees val respawn = TimeUnit.SECONDS.toMillis(MINIMUM_RESPAWN_TIME + rand(150)) / GameConstants.PULSE_DELAY mob.world.expireObject(obj.get(), target.tree.stump, respawn.toInt())