Implemented ::addxp command (admin), add xp to a skill

Implemented ::charge command (admin), get and set the charge of an item
Implemented ::setslayertask command (admin), set the slayer task npc with optional quantity
This commit is contained in:
RiL
2023-05-09 00:02:51 +00:00
committed by Ryan
parent 69f4f11bc7
commit 52633544ff
12 changed files with 228 additions and 29 deletions
@@ -0,0 +1,80 @@
package content.data
import core.api.toIntArray
import core.cache.def.impl.ItemDefinition
import org.rs09.consts.Items
/**
* Represents a distinct charged item, i.e. items with (#).
* Not to be confused with items with internal charge, like degradation.
* @author RiL
*/
enum class ChargedItem(val ids: IntArray) {
AMULET_OF_GLORY((Items.AMULET_OF_GLORY4_1712 downTo Items.AMULET_OF_GLORY_1704 step 2).toIntArray()),
RING_OF_DUELLING((Items.RING_OF_DUELLING8_2552..Items.RING_OF_DUELLING1_2566 step 2).toIntArray()),
GAMES_NECKLACE((Items.GAMES_NECKLACE8_3853..Items.GAMES_NECKLACE1_3867 step 2).toIntArray()),
BROODOO_SHIELDA((Items.BROODOO_SHIELD_10_6215..Items.BROODOO_SHIELD_6235 step 2).toIntArray()),
BROODOO_SHIELDB((Items.BROODOO_SHIELD_10_6237..Items.BROODOO_SHIELD_6257 step 2).toIntArray()),
BROODOO_SHIELDC((Items.BROODOO_SHIELD_10_6259..Items.BROODOO_SHIELD_6279 step 2).toIntArray()),
ROD_OF_IVANDIS((Items.ROD_OF_IVANDIS10_7639..Items.ROD_OF_IVANDIS1_7648).toIntArray()),
BLACK_MASK((Items.BLACK_MASK_10_8901..Items.BLACK_MASK_8921 step 2).toIntArray()),
AMULET_OF_GLORYT((Items.AMULET_OF_GLORYT4_10354..Items.AMULET_OF_GLORYT_10362 step 2).toIntArray()),
CASTLEWAR_BRACE((Items.CASTLEWAR_BRACE3_11079..Items.CASTLEWAR_BRACE1_11083 step 2).toIntArray()),
FORINTHRY_BRACE((Items.FORINTHRY_BRACE5_11095..Items.FORINTHRY_BRACE1_11103 step 2).toIntArray()),
SKILLS_NECKLACE((Items.SKILLS_NECKLACE4_11105..Items.SKILLS_NECKLACE_11113 step 2).toIntArray()),
COMBAT_BRACELET((Items.COMBAT_BRACELET4_11118..Items.COMBAT_BRACELET_11126 step 2).toIntArray()),
DIGSITE_PENDANT((Items.DIGSITE_PENDANT_5_11194 downTo Items.DIGSITE_PENDANT_1_11190).toIntArray()),
VOID_SEAL((Items.VOID_SEAL8_11666..Items.VOID_SEAL1_11673).toIntArray()),
AMULET_OF_FARMING((Items.AMULET_OF_FARMING8_12622 downTo Items.AMULET_OF_FARMING1_12608 step 2).toIntArray()),
IVANDIS_FLAIL((Items.IVANDIS_FLAIL_30_13117..Items.IVANDIS_FLAIL_1_13146).toIntArray()),
RING_OF_SLAYING((Items.RING_OF_SLAYING8_13281..Items.RING_OF_SLAYING1_13288).toIntArray()),
RING_OF_WEALTH((Items.RING_OF_WEALTH4_14646 downTo Items.RING_OF_WEALTH_14638 step 2).toIntArray());
/**
* Get the item id for a specific [charge].
* If [charge] is outside the valid range, return the item id with the closest charge.
*/
fun forCharge(charge: Int): Int {
return ids[maxCharge() - if (charge < 1) 1 + maxCharge() - ids.size else if (charge > maxCharge()) maxCharge() else charge]
}
/**
* Get the max charge of this ChargedItem.
*/
fun maxCharge(): Int = maxCharges[ordinal]
companion object {
private val CHARGE_REGEX = Regex("""\(\D?(\d+)\)""")
private val idMap = HashMap<Int, ChargedItem>()
private val maxCharges = IntArray(values().size)
init {
values().forEach { chargedItem ->
maxCharges[chargedItem.ordinal] = getMaxCharge(chargedItem)
chargedItem.ids.forEach { idMap[it] = chargedItem }
}
}
private fun getMaxCharge(chargedItem: ChargedItem): Int {
return CHARGE_REGEX.find(ItemDefinition.forId(chargedItem.ids.first()).name)!!.groups[1]!!.value.toInt()
}
/**
* Check if the item id is a charged item.
*/
fun contains(id: Int): Boolean = idMap.containsKey(id)
/**
* Get the ChargedItem enum for an item id, or null if it's not a charged item.
*/
fun forId(id: Int): ChargedItem? = idMap[id]
/**
* Get the charge value of an item id, or null if it's not a charged item.
*/
fun getCharge(id: Int): Int? {
val chargedItem = forId(id) ?: return null
return chargedItem.maxCharge() - chargedItem.ids.indexOf(id)
}
}
}
@@ -8,7 +8,7 @@ import core.game.interaction.IntType
class HatStand : InteractionListener { class HatStand : InteractionListener {
val hats = ItemDefinition.getDefinitions().values.filter { it.getConfiguration("equipment_slot",0) == EquipmentSlot.HAT.ordinal }.map { it.id }.toIntArray() val hats = ItemDefinition.getDefinitions().values.filter { it.getConfiguration("equipment_slot",0) == EquipmentSlot.HEAD.ordinal }.map { it.id }.toIntArray()
val hat_stand = 374 val hat_stand = 374
override fun defineListeners() { override fun defineListeners() {
@@ -112,7 +112,7 @@ class MiningListener : InteractionListener {
chance = (chance / 1.5).toInt() chance = (chance / 1.5).toInt()
altered = true altered = true
} }
val necklace = getItemFromEquipment(player, EquipmentSlot.AMULET) val necklace = getItemFromEquipment(player, EquipmentSlot.NECK)
if (necklace != null && necklace.id in 1705..1713) { if (necklace != null && necklace.id in 1705..1713) {
chance = (chance / 1.5).toInt() chance = (chance / 1.5).toInt()
altered = true altered = true
@@ -178,7 +178,7 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul
chance = (chance / 1.5).toInt() chance = (chance / 1.5).toInt()
altered = true altered = true
} }
val necklace = getItemFromEquipment(player, EquipmentSlot.AMULET) val necklace = getItemFromEquipment(player, EquipmentSlot.NECK)
if (necklace != null && necklace.id in 1705..1713) { if (necklace != null && necklace.id in 1705..1713) {
chance = (chance / 1.5).toInt() chance = (chance / 1.5).toInt()
altered = true altered = true
@@ -24,10 +24,10 @@ object SlayerEquipmentFlags {
else if(hasItem(player, Items.NOSE_PEG_4168)) flags = 1 else if(hasItem(player, Items.NOSE_PEG_4168)) flags = 1
else if(hasItem(player, Items.EARMUFFS_4166)) flags = flags or (1 shl 1) else if(hasItem(player, Items.EARMUFFS_4166)) flags = flags or (1 shl 1)
else if(hasItem(player, Items.FACE_MASK_4164)) flags = flags or (1 shl 2) else if(hasItem(player, Items.FACE_MASK_4164)) flags = flags or (1 shl 2)
else if((getItemFromEquipment(player, EquipmentSlot.HAT)?.id ?: 0) in blackMasks) flags = flags or (1 shl 3) else if((getItemFromEquipment(player, EquipmentSlot.HEAD)?.id ?: 0) in blackMasks) flags = flags or (1 shl 3)
else if(hasItem(player, Items.SPINY_HELMET_4551)) flags = flags or (1 shl 4) else if(hasItem(player, Items.SPINY_HELMET_4551)) flags = flags or (1 shl 4)
if((getItemFromEquipment(player, EquipmentSlot.AMULET)?.id ?: 0) == Items.WITCHWOOD_ICON_8923) flags = flags or (1 shl 7) if((getItemFromEquipment(player, EquipmentSlot.NECK)?.id ?: 0) == Items.WITCHWOOD_ICON_8923) flags = flags or (1 shl 7)
if((getItemFromEquipment(player, EquipmentSlot.SHIELD)?.id ?: 0) == Items.MIRROR_SHIELD_4156) flags = flags or (1 shl 8) if((getItemFromEquipment(player, EquipmentSlot.SHIELD)?.id ?: 0) == Items.MIRROR_SHIELD_4156) flags = flags or (1 shl 8)
SlayerManager.getInstance(player).flags.equipmentFlags = flags SlayerManager.getInstance(player).flags.equipmentFlags = flags
} }
@@ -78,7 +78,7 @@ object SlayerEquipmentFlags {
} }
private fun hasItem(player: Player, id: Int): Boolean{ private fun hasItem(player: Player, id: Int): Boolean{
return (getItemFromEquipment(player, EquipmentSlot.HAT)?.id ?: 0) == id return (getItemFromEquipment(player, EquipmentSlot.HEAD)?.id ?: 0) == id
} }
fun isSlayerEq(item: Int): Boolean{ fun isSlayerEq(item: Int): Boolean{
@@ -158,7 +158,7 @@ class CastleWarsListeners : InteractionListener {
private fun capeOrHelmetError(player: Player): String? { private fun capeOrHelmetError(player: Player): String? {
val wornCape = getItemFromEquipment(player, EquipmentSlot.CAPE)?.id ?: -1 val wornCape = getItemFromEquipment(player, EquipmentSlot.CAPE)?.id ?: -1
val wornHelmet = getItemFromEquipment(player, EquipmentSlot.HAT)?.id ?: -1 val wornHelmet = getItemFromEquipment(player, EquipmentSlot.HEAD)?.id ?: -1
if (wornCape != -1 || wornHelmet != -1) return "You can't wear hats, capes, or helms in the arena." if (wornCape != -1 || wornHelmet != -1) return "You can't wear hats, capes, or helms in the arena."
return null return null
+3 -8
View File
@@ -4,14 +4,9 @@ import core.game.node.item.Item
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
fun IntRange.toIntArray(): IntArray { fun IntProgression.toIntArray(): IntArray {
if (last < first) val result = IntArray((last - first) / step + 1)
return IntArray(0) forEachIndexed { index, i -> result[index] = i }
val result = IntArray(last - first + 1)
var index = 0
for (element in this)
result[index++] = element
return result return result
} }
+28 -3
View File
@@ -1,9 +1,9 @@
package core.api package core.api
enum class EquipmentSlot { enum class EquipmentSlot {
HAT, HEAD,
CAPE, CAPE,
AMULET, NECK,
WEAPON, WEAPON,
CHEST, CHEST,
SHIELD, SHIELD,
@@ -14,5 +14,30 @@ enum class EquipmentSlot {
FEET, FEET,
HIDDEN_3, HIDDEN_3,
RING, RING,
AMMO AMMO;
companion object {
private val slotMap = HashMap<String, EquipmentSlot>()
init {
slotMap["head"] = HEAD; slotMap["helm"] = HEAD; slotMap ["helmet"] = HEAD
slotMap["cape"] = CAPE; slotMap["back"] = CAPE
slotMap["neck"] = NECK; slotMap["amulet"] = NECK
slotMap["weapon"] = WEAPON; slotMap["main"] = WEAPON
slotMap["chest"] = CHEST; slotMap["body"] = CHEST; slotMap["torso"] = CHEST
slotMap["shield"] = SHIELD; slotMap["off"] = SHIELD
slotMap["legs"] = LEGS; slotMap["leg"] = LEGS
slotMap["hands"] = HANDS; slotMap["hand"] = HANDS; slotMap["brace"] = HANDS; slotMap["bracelet"] = HANDS;
slotMap["feet"] = FEET
slotMap["ring"] = RING
slotMap["ammo"] = AMMO; slotMap["ammunition"] = AMMO
}
/**
* Return the equipment slot by name. Return null if matching no slot.
*/
fun slotByName(input: String): EquipmentSlot? {
return slotMap[input.lowercase()]
}
}
} }
@@ -145,7 +145,7 @@ open class MeleeSwingHandler
// attack bonus for specialized equipments (salve amulets, slayer equips) // attack bonus for specialized equipments (salve amulets, slayer equips)
if (entity is Player) { if (entity is Player) {
val amuletId = getItemFromEquipment(entity, EquipmentSlot.AMULET)?.id ?: 0 val amuletId = getItemFromEquipment(entity, EquipmentSlot.NECK)?.id ?: 0
if ((amuletId == Items.SALVE_AMULET_4081 || amuletId == Items.SALVE_AMULETE_10588) && checkUndead(victimName)) { if ((amuletId == Items.SALVE_AMULET_4081 || amuletId == Items.SALVE_AMULETE_10588) && checkUndead(victimName)) {
effectiveAttackLevel *= if (amuletId == Items.SALVE_AMULET_4081) 1.15 else 1.2 effectiveAttackLevel *= if (amuletId == Items.SALVE_AMULET_4081) 1.15 else 1.2
} else if (getSlayerTask(entity)?.ids?.contains((entity.properties.combatPulse?.getVictim()?.id ?: 0)) == true) { } else if (getSlayerTask(entity)?.ids?.contains((entity.properties.combatPulse?.getVictim()?.id ?: 0)) == true) {
@@ -29,7 +29,6 @@ import core.game.ge.GrandExchange
import content.global.handlers.iface.RulesAndInfo import content.global.handlers.iface.RulesAndInfo
import content.global.skill.farming.FarmingState import content.global.skill.farming.FarmingState
import content.minigame.fishingtrawler.TrawlerLoot import content.minigame.fishingtrawler.TrawlerLoot
import core.tools.SystemLogger
import core.game.system.command.CommandMapping import core.game.system.command.CommandMapping
import core.game.system.command.Privilege import core.game.system.command.Privilege
import core.game.world.repository.Repository import core.game.world.repository.Repository
@@ -362,7 +361,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
* Set a specific skill to a specific level * Set a specific skill to a specific level
*/ */
define("setlevel", Privilege.ADMIN, "::setlevel <lt>SKILL NAME<gt> <lt>LEVEL<gt>", "Sets SKILL NAME to LEVEL."){player,args -> define("setlevel", Privilege.ADMIN, "::setlevel <lt>SKILL NAME<gt> <lt>LEVEL<gt>", "Sets SKILL NAME to LEVEL."){player,args ->
if(args.size < 2) reject(player,"Usage: ::setlevel skillname level") if(args.size != 3) reject(player,"Usage: ::setlevel skillname level")
val skillname = args[1] val skillname = args[1]
val desiredLevel: Int? = args[2].toIntOrNull() val desiredLevel: Int? = args[2].toIntOrNull()
if(desiredLevel == null){ if(desiredLevel == null){
@@ -378,6 +377,21 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
player.skills.updateCombatLevel() player.skills.updateCombatLevel()
} }
/**
* Add xp to skill
*/
define("addxp", Privilege.ADMIN, "::addxp <lt>skill name | id<gt> <lt>xp<gt>", "Add xp to skill") { player, args ->
if (args.size != 3) reject(player, "Usage: ::addxp <lt>skill name | id<gt> <lt>xp<gt>")
val skill = args[1].toIntOrNull() ?: Skills.getSkillByName(args[1])
if (skill < 0 || skill >= Skills.NUM_SKILLS) reject(player, "Must use valid skill name or id.")
val xp = args[2].toDoubleOrNull()
if (xp == null || xp <= 0) reject(player, "Xp must be a positive number.")
player.skills.addExperience(skill, xp!!)
}
define("completediaries", Privilege.ADMIN, "", "Completes all diaries."){player,_ -> define("completediaries", Privilege.ADMIN, "", "Completes all diaries."){player,_ ->
player.achievementDiaryManager.diarys.forEach { player.achievementDiaryManager.diarys.forEach {
for(level in it.taskCompleted.indices){ for(level in it.taskCompleted.indices){
@@ -1,9 +1,12 @@
package core.game.system.command.sets package core.game.system.command.sets
import content.global.skill.slayer.Master
import content.global.skill.slayer.SlayerManager import content.global.skill.slayer.SlayerManager
import content.global.skill.slayer.SlayerUtils
import content.global.skill.slayer.Tasks
import core.game.node.entity.npc.NPC import core.game.node.entity.npc.NPC
import core.plugin.Initializable
import core.game.system.command.Privilege import core.game.system.command.Privilege
import core.plugin.Initializable
@Initializable @Initializable
class SlayerCommandSet : CommandSet(Privilege.ADMIN){ class SlayerCommandSet : CommandSet(Privilege.ADMIN){
@@ -35,5 +38,19 @@ class SlayerCommandSet : CommandSet(Privilege.ADMIN){
SlayerManager.getInstance(player).slayerPoints = amount!! SlayerManager.getInstance(player).slayerPoints = amount!!
notify(player, "Set slayer points to $amount.") notify(player, "Set slayer points to $amount.")
} }
define("setslayertask", Privilege.ADMIN, "::setslayertask <lt>npc id<gt> [amount]", "Set the slayer task to npc. Amount optional.") { player, args ->
if (args.size < 2) reject(player, "Usage: ::setslayertask <lt>npc id<gt> [amount]")
val npc = (args[1].toIntOrNull() ?: reject(player, "Must enter valid npc id")) as Int
val task = (Tasks.forId(npc) ?: reject(player, "Must enter valid npc id")) as Tasks
val amount = args.getOrNull(2)?.toIntOrNull()
?.let { if (it !in 1..255) reject(player, "Amount must be an integer: 1-255.") else it } as Int?
val slayer = SlayerManager.getInstance(player)
if (slayer.hasTask()) slayer.task = task else SlayerUtils.assign(player, task, Master.values().random())
if (amount != null) slayer.amount = amount
player.varpManager.get(2502).setVarbit(0, slayer.flags.taskFlags shr 4).send(player)
}
} }
} }
@@ -1,19 +1,17 @@
package core.game.system.command.sets package core.game.system.command.sets
import core.api.InputType import content.data.ChargedItem
import core.api.runTask import core.api.*
import core.api.sendDialogue
import core.api.sendInputDialogue
import core.cache.def.impl.ItemDefinition import core.cache.def.impl.ItemDefinition
import core.game.node.entity.player.Player
import core.game.node.item.Item import core.game.node.item.Item
import core.game.system.SystemManager import core.game.system.SystemManager
import core.game.system.SystemState import core.game.system.SystemState
import core.plugin.Initializable
import org.rs09.consts.Items
import core.tools.SystemLogger
import core.game.system.command.Privilege import core.game.system.command.Privilege
import core.game.world.GameWorld import core.game.world.GameWorld
import core.game.world.repository.Repository import core.game.world.repository.Repository
import core.plugin.Initializable
import org.rs09.consts.Items
import kotlin.system.exitProcess import kotlin.system.exitProcess
@Initializable @Initializable
@@ -236,5 +234,75 @@ class SystemCommandSet : CommandSet(Privilege.ADMIN) {
exitProcess(0) exitProcess(0)
} }
/**
* Command to get and set the charge of an item.
* Can handle both the internal charge used for things like degradation, and distinct (#) charge that's different items.
* The default behavior without any flags is to get the internal charge of an item.
* param equipment slot name | item id - selects the item, either by using the equipment slot name, or item id.
* param sd - optional flags, where s = set charge, d = distinct charge.
* param charge - the charge to set on the item. Only necessary when the set flag is toggled.
* @author RiL
*/
define("charge", Privilege.ADMIN, "::charge <lt>equipment slot name | item id<gt> [sd] [<lt>charge<gt>]", "Get/set the charge of an item. Flags: s = set, d = distinct(#).") { player, args ->
if (args.size < 2) reject(
player,
"Usage: ::charge <lt>equipment slot name | item id<gt> [sd] [<lt>charge<gt>]",
"Get internal: ::charge 4718",
"Get distinct: ::charge ring d",
"Set internal: ::charge head s 500",
"Set distinct: ::charge 1704 sd 4"
)
@Suppress("UNCHECKED_CAST")
val itemInfo = (args[1].toIntOrNull()?.let {
getItemAndContainer(player, it) ?: reject(player, "Item not found: $it.")
} ?: EquipmentSlot.slotByName(args[1])?.ordinal?.let {
Pair(player.equipment.get(it) ?: reject(player, "No item equipped at slot: ${args[1]}."), player.equipment)
} ?: reject(player, "No slot: ${args[1]}.")) as Pair<Item, core.game.container.Container>
val item = itemInfo.first
when (val flags = args.getOrElse(2) { "" }) {
"" -> { // get internal charge
notify(player, "${item.name}: ${item.charge} charge.")
}
"d" -> { // get distinct charge
ChargedItem.forId(item.id)?.run {
notify(player, "${item.name}: (${ChargedItem.getCharge(item.id)}) charge.")
} ?: reject(player, "${item.name} is not a distinct(#) item.")
}
"s", "sd", "ds" -> {
if (args.size < 4) reject(player, "Must enter a charge value.")
val charge = (args[3].toIntOrNull() ?: reject(player, "Charge must be an integer.")) as Int
if (flags == "s") { // set internal charge
if (charge < 1) reject(player, "Charge must be a positive integer.")
item.charge = charge
notify(player, "Set internal charge of ${item.name} to $charge.")
} else { // set distinct charge
ChargedItem.forId(item.id)?.forCharge(charge)?.let {
itemInfo.second.replace(Item(it), item.slot)
notify(player, "Set distinct charge of ${item.name} to (${ChargedItem.getCharge(it)}).")
} ?: reject(player, "${item.name} is not a distinct(#) item.")
}
}
else -> {
reject(player, "Please enter valid flags: no flag/empty, s, d, sd.", "Use ::charge for examples.")
}
}
}
}
/**
* Search for item in player and return item and container if found. Return null if not found
*/
private fun getItemAndContainer(player: Player, id: Int): Pair<Item, core.game.container.Container>? {
if (id !in 0 until ItemDefinition.getDefinitions().size) return null
arrayOf(player.inventory, player.equipment, player.bankPrimary, player.bankSecondary).forEach { container ->
container.toArray().firstOrNull { it?.id == id }?.let { return Pair(it, container) }
}
return null
} }
} }