diff --git a/src/plugins/buttons/player-emotes-plugin.ts b/src/plugins/buttons/player-emotes-plugin.ts index 3afa41d14..f83d15e11 100644 --- a/src/plugins/buttons/player-emotes-plugin.ts +++ b/src/plugins/buttons/player-emotes-plugin.ts @@ -2,6 +2,7 @@ import { buttonAction } from '@server/world/actor/player/action/button-action'; import { ActionType, RunePlugin } from '@server/plugins/plugin'; import { widgets } from '@server/world/config/widget'; import { Player } from '@server/world/actor/player/player'; +import { itemIds } from '@server/world/config/item-ids'; interface Emote { animationId: number; @@ -10,6 +11,38 @@ interface Emote { graphicId?: number; } +interface SkillcapeEmote extends Emote { + itemIds: Array; +} + +const { skillCapes } = itemIds; + +export const skillCapeEmotes: SkillcapeEmote[] = [ + { animationId: 4959, name: 'Attack', itemIds: [skillCapes.attack.untrimmed, skillCapes.attack.trimmed], graphicId: 823 }, + { animationId: 4981, name: 'Strength', itemIds: [skillCapes.strength.untrimmed, skillCapes.strength.trimmed], graphicId: 828 }, + { animationId: 4961, name: 'Defence', itemIds: [skillCapes.defence.untrimmed, skillCapes.defence.trimmed], graphicId: 824 }, + { animationId: 4973, name: 'Ranged', itemIds: [skillCapes.ranged.untrimmed, skillCapes.ranged.trimmed], graphicId: 832 }, + { animationId: 4979, name: 'Prayer', itemIds: [skillCapes.prayer.untrimmed, skillCapes.prayer.trimmed], graphicId: 829 }, + { animationId: 4939, name: 'Magic', itemIds: [skillCapes.magic.untrimmed, skillCapes.magic.trimmed], graphicId: 813 }, + { animationId: 4947, name: 'Runecrafting', itemIds: [skillCapes.runecrafting.untrimmed, skillCapes.runecrafting.trimmed], graphicId: 817 }, + { animationId: 4971, name: 'Constitution', itemIds: [skillCapes.constitution.untrimmed, skillCapes.constitution.trimmed], graphicId: 833 }, + { animationId: 4977, name: 'Agility', itemIds: [skillCapes.agility.untrimmed, skillCapes.agility.trimmed], graphicId: 830 }, + { animationId: 4969, name: 'Herblore', itemIds: [skillCapes.herblore.untrimmed, skillCapes.herblore.trimmed], graphicId: 835 }, + { animationId: 4965, name: 'Thieving', itemIds: [skillCapes.thieving.untrimmed, skillCapes.thieving.trimmed], graphicId: 826 }, + { animationId: 4949, name: 'Crafting', itemIds: [skillCapes.crafting.untrimmed, skillCapes.crafting.trimmed], graphicId: 818 }, + { animationId: 4937, name: 'Fletching', itemIds: [skillCapes.fletching.untrimmed, skillCapes.fletching.trimmed], graphicId: 812 }, + { animationId: 4967, name: 'Slayer', itemIds: [skillCapes.slayer.untrimmed, skillCapes.slayer.trimmed], graphicId: 827 }, + { animationId: 4953, name: 'Construction', itemIds: [skillCapes.construction.untrimmed, skillCapes.construction.trimmed], graphicId: 820 }, + { animationId: 4941, name: 'Mining', itemIds: [skillCapes.mining.untrimmed, skillCapes.mining.trimmed], graphicId: 814 }, + { animationId: 4943, name: 'Smithing', itemIds: [skillCapes.smithing.untrimmed, skillCapes.smithing.trimmed], graphicId: 815 }, + { animationId: 4951, name: 'Fishing', itemIds: [skillCapes.fishing.untrimmed, skillCapes.fishing.trimmed], graphicId: 819 }, + { animationId: 4955, name: 'Cooking', itemIds: [skillCapes.cooking.untrimmed, skillCapes.cooking.trimmed], graphicId: 821 }, + { animationId: 4975, name: 'Firemaking', itemIds: [skillCapes.firemaking.untrimmed, skillCapes.firemaking.trimmed], graphicId: 831 }, + { animationId: 4957, name: 'Woodcutting', itemIds: [skillCapes.woodcutting.untrimmed, skillCapes.woodcutting.trimmed], graphicId: 822 }, + { animationId: 4963, name: 'Farming', itemIds: [skillCapes.farming.untrimmed, skillCapes.farming.trimmed], graphicId: 825 }, + { animationId: 4945, name: 'Quest point', itemIds: [skillCapes.questpoint.untrimmed], graphicId: 816 }, +]; + export const emotes: { [key: number]: Emote } = { 1: { animationId: 855, name: 'YES' }, 2: { animationId: 856, name: 'NO' }, @@ -117,9 +150,17 @@ export const action: buttonAction = (details) => { const { player, buttonId } = details; const emote = emotes[buttonId]; - + if(emote.name === 'SKILLCAPE') { - player.sendMessage(`You need to be wearing a skillcape in order to perform that emote.`); + if (player.getItemInEquipmentSlot('BACK')) { + if (skillCapeEmotes.some(item => item.itemIds.includes(player.getItemInEquipmentSlot('BACK')?.itemId))) { + const skillcapeEmote = skillCapeEmotes.filter(item => item.itemIds.includes(player.getItemInEquipmentSlot('BACK')?.itemId)); + player.playAnimation(skillcapeEmote[0].animationId); + player.playGraphics({id: skillcapeEmote[0].graphicId, delay: 0, height: 0}); + } + } else { + player.sendMessage(`You need to be wearing a skillcape in order to perform that emote.`, true); + } } else { if(emote.unlockable) { const unlockedEmotes: string[] = player.savedMetadata.unlockedEmotes || []; diff --git a/src/plugins/equipment/equip-item-plugin.ts b/src/plugins/equipment/equip-item-plugin.ts index 5eba0b148..ad03ced49 100644 --- a/src/plugins/equipment/equip-item-plugin.ts +++ b/src/plugins/equipment/equip-item-plugin.ts @@ -3,9 +3,6 @@ import { widgets } from '@server/world/config/widget'; import { itemAction } from '@server/world/actor/player/action/item-action'; import { equipmentSlotIndex } from '@server/world/config/item-data'; - - - export const action: itemAction = (details) => { const { player, itemId, itemSlot, itemDetails } = details; diff --git a/src/plugins/equipment/unequip-item-plugin.ts b/src/plugins/equipment/unequip-item-plugin.ts index be94acfee..4c388ad8f 100644 --- a/src/plugins/equipment/unequip-item-plugin.ts +++ b/src/plugins/equipment/unequip-item-plugin.ts @@ -1,10 +1,10 @@ import { ActionType, RunePlugin } from '@server/plugins/plugin'; import { widgets } from '@server/world/config/widget'; import { getItemFromContainer, itemAction } from '@server/world/actor/player/action/item-action'; -import { updateBonusStrings } from '@server/plugins/equipment/equipment-stats-plugin'; +import { equipmentSlotIndex } from '@server/world/config/item-data'; export const action: itemAction = (details) => { - const { player, itemId, itemSlot, widgetId } = details; + const { player, itemId, itemSlot, itemDetails } = details; const equipment = player.equipment; const item = getItemFromContainer(itemId, itemSlot, equipment); @@ -14,28 +14,8 @@ export const action: itemAction = (details) => { return; } - const inventory = player.inventory; - const inventorySlot = inventory.getFirstOpenSlot(); - - if(inventorySlot === -1) { - player.sendMessage(`You don't have enough free space to do that.`); - return; - } - - equipment.remove(itemSlot); - inventory.set(inventorySlot, item); - - player.updateBonuses(); - - player.outgoingPackets.sendUpdateSingleWidgetItem(widgets.inventory, inventorySlot, item); - player.outgoingPackets.sendUpdateSingleWidgetItem(widgets.equipment, itemSlot, null); - - if(widgetId === widgets.equipmentStats.widgetId) { - player.outgoingPackets.sendUpdateSingleWidgetItem(widgets.equipmentStats, itemSlot, null); - updateBonusStrings(player); - } - - player.updateFlags.appearanceUpdateRequired = true; + const equipmentSlot = equipmentSlotIndex(itemDetails.equipment.slot); + player.unequipItem(equipmentSlot); }; export default new RunePlugin({ diff --git a/src/plugins/items/capes/skillcape-emotes.ts b/src/plugins/items/capes/skillcape-emotes.ts new file mode 100644 index 000000000..f173869d0 --- /dev/null +++ b/src/plugins/items/capes/skillcape-emotes.ts @@ -0,0 +1,32 @@ +import { lockEmote, unlockEmote } from '@server/plugins/buttons/player-emotes-plugin'; +import { ActionType, RunePlugin } from '@server/plugins/plugin'; +import { equipAction } from '@server/world/actor/player/action/equip-action'; +import { itemIds } from '@server/world/config/item-ids'; + +export const skillcapeIds: Array = Object.keys( + itemIds.skillCapes).flatMap(skill => [itemIds.skillCapes[skill].untrimmed, itemIds.skillCapes[skill].trimmed] +); + +export const equip: equipAction = (details) => { + const {player} = details; + unlockEmote(player, 'SKILLCAPE'); +}; + +export const unequip: equipAction = (details) => { + const {player} = details; + lockEmote(player, 'SKILLCAPE'); + player.stopAnimation(); + player.stopGraphics(); +}; + +export default new RunePlugin([{ + type: ActionType.EQUIP_ACTION, + equipType: 'EQUIP', + action: equip, + itemIds: skillcapeIds +}, { + type: ActionType.EQUIP_ACTION, + equipType: 'UNEQUIP', + action: unequip, + itemIds: skillcapeIds +}]); diff --git a/src/world/actor/actor.ts b/src/world/actor/actor.ts index aa9cba990..f2471e0a0 100644 --- a/src/world/actor/actor.ts +++ b/src/world/actor/actor.ts @@ -174,6 +174,11 @@ export abstract class Actor { this.updateFlags.animation = animation; } + public stopAnimation(): void { + const animation = {id: -1, delay: 0}; + this.updateFlags.animation = animation; + } + public playGraphics(graphics: number | Graphic): void { if(typeof graphics === 'number') { graphics = {id: graphics, delay: 0, height: 120}; @@ -182,6 +187,11 @@ export abstract class Actor { this.updateFlags.graphics = graphics; } + public stopGraphics(): void { + const graphics = {id: -1, delay: 0, height: 120}; + this.updateFlags.graphics = graphics; + } + public removeItem(slot: number): void { this._inventory.remove(slot); } diff --git a/src/world/actor/player/player.ts b/src/world/actor/player/player.ts index 463529a3c..8b4a9124b 100644 --- a/src/world/actor/player/player.ts +++ b/src/world/actor/player/player.ts @@ -648,6 +648,10 @@ export class Player extends Actor { return this._equipment.has(item); } + public getItemInEquipmentSlot(slot: string): Item { + return this._equipment.items[EquipmentSlot[slot]]; + } + public hasItemOnPerson(item: number | Item): boolean { return this.hasItemInInventory(item) || this.hasItemInEquipment(item); } diff --git a/src/world/config/item-ids.ts b/src/world/config/item-ids.ts index e603363ef..4690effd2 100644 --- a/src/world/config/item-ids.ts +++ b/src/world/config/item-ids.ts @@ -52,6 +52,99 @@ export const itemIds = { runiteBar: 2363, runiteOre: 451, beer: 1917, + skillCapes: { + attack: { + untrimmed: 9747, + trimmed: 9748, + }, + strength: { + untrimmed: 9750, + trimmed: 9751, + }, + defence: { + untrimmed: 9753, + trimmed: 9754, + }, + ranged: { + untrimmed: 9756, + trimmed: 9757, + }, + prayer: { + untrimmed: 9759, + trimmed: 9760, + }, + magic: { + untrimmed: 9762, + trimmed: 9763, + }, + runecrafting: { + untrimmed: 9765, + trimmed: 9766, + }, + constitution: { + untrimmed: 9768, + trimmed: 9769, + }, + agility: { + untrimmed: 9771, + trimmed: 9772, + }, + herblore: { + untrimmed: 9774, + trimmed: 9775, + }, + thieving: { + untrimmed: 9777, + trimmed: 9775, + }, + crafting: { + untrimmed: 9780, + trimmed: 9781, + }, + fletching: { + untrimmed: 9783, + trimmed: 9784, + }, + slayer: { + untrimmed: 9786, + trimmed: 9786, + }, + construction: { + untrimmed: 9789, + trimmed: 9790, + }, + mining: { + untrimmed: 9792, + trimmed: 9793, + }, + smithing: { + untrimmed: 9795, + trimmed: 9796, + }, + fishing: { + untrimmed: 9798, + trimmed: 9799, + }, + cooking: { + untrimmed: 9801, + trimmed: 9802, + }, + firemaking: { + untrimmed: 9804, + trimmed: 9805, + }, + woodcutting: { + untrimmed: 9807, + trimmed: 9808, + }, + farming: { + untrimmed: 9810, + trimmed: 9811, + }, + questpoint: { + untrimmed: 9813, + }, + }, essence: { pure: 7936, rune: 1436