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 {
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
override fun defineListeners() {
@@ -112,7 +112,7 @@ class MiningListener : InteractionListener {
chance = (chance / 1.5).toInt()
altered = true
}
val necklace = getItemFromEquipment(player, EquipmentSlot.AMULET)
val necklace = getItemFromEquipment(player, EquipmentSlot.NECK)
if (necklace != null && necklace.id in 1705..1713) {
chance = (chance / 1.5).toInt()
altered = true
@@ -178,7 +178,7 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul
chance = (chance / 1.5).toInt()
altered = true
}
val necklace = getItemFromEquipment(player, EquipmentSlot.AMULET)
val necklace = getItemFromEquipment(player, EquipmentSlot.NECK)
if (necklace != null && necklace.id in 1705..1713) {
chance = (chance / 1.5).toInt()
altered = true
@@ -24,10 +24,10 @@ object SlayerEquipmentFlags {
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.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)
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)
SlayerManager.getInstance(player).flags.equipmentFlags = flags
}
@@ -78,7 +78,7 @@ object SlayerEquipmentFlags {
}
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{
@@ -158,7 +158,7 @@ class CastleWarsListeners : InteractionListener {
private fun capeOrHelmetError(player: Player): String? {
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."
return null
+3 -8
View File
@@ -4,14 +4,9 @@ import core.game.node.item.Item
import java.util.*
import kotlin.collections.ArrayList
fun IntRange.toIntArray(): IntArray {
if (last < first)
return IntArray(0)
val result = IntArray(last - first + 1)
var index = 0
for (element in this)
result[index++] = element
fun IntProgression.toIntArray(): IntArray {
val result = IntArray((last - first) / step + 1)
forEachIndexed { index, i -> result[index] = i }
return result
}
+28 -3
View File
@@ -1,9 +1,9 @@
package core.api
enum class EquipmentSlot {
HAT,
HEAD,
CAPE,
AMULET,
NECK,
WEAPON,
CHEST,
SHIELD,
@@ -14,5 +14,30 @@ enum class EquipmentSlot {
FEET,
HIDDEN_3,
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)
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)) {
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) {
@@ -29,7 +29,6 @@ import core.game.ge.GrandExchange
import content.global.handlers.iface.RulesAndInfo
import content.global.skill.farming.FarmingState
import content.minigame.fishingtrawler.TrawlerLoot
import core.tools.SystemLogger
import core.game.system.command.CommandMapping
import core.game.system.command.Privilege
import core.game.world.repository.Repository
@@ -362,7 +361,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
* 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 ->
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 desiredLevel: Int? = args[2].toIntOrNull()
if(desiredLevel == null){
@@ -378,6 +377,21 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
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,_ ->
player.achievementDiaryManager.diarys.forEach {
for(level in it.taskCompleted.indices){
@@ -1,9 +1,12 @@
package core.game.system.command.sets
import content.global.skill.slayer.Master
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.plugin.Initializable
import core.game.system.command.Privilege
import core.plugin.Initializable
@Initializable
class SlayerCommandSet : CommandSet(Privilege.ADMIN){
@@ -35,5 +38,19 @@ class SlayerCommandSet : CommandSet(Privilege.ADMIN){
SlayerManager.getInstance(player).slayerPoints = 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
import core.api.InputType
import core.api.runTask
import core.api.sendDialogue
import core.api.sendInputDialogue
import content.data.ChargedItem
import core.api.*
import core.cache.def.impl.ItemDefinition
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.game.system.SystemManager
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.world.GameWorld
import core.game.world.repository.Repository
import core.plugin.Initializable
import org.rs09.consts.Items
import kotlin.system.exitProcess
@Initializable
@@ -236,5 +234,75 @@ class SystemCommandSet : CommandSet(Privilege.ADMIN) {
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
}
}