Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions data/config/npc-spawns/alkharid/alkharid-general.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,11 @@
"spawn_x": 3272,
"spawn_y": 3182,
"movement_radius": 2
},
{
"npc": "rs:tanner_ellis",
"spawn_x": 3274,
"spawn_y": 3191,
"movement_radius": 3
}
]
3 changes: 3 additions & 0 deletions data/config/npcs/alkharid.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@
},
"rs:alkharid_karim": {
"game_id": 543
},
"rs:tanner_ellis": {
"game_id": 2824
}
}
3 changes: 2 additions & 1 deletion data/config/widgets.json5
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,6 @@
christmas: 23,
killcount: 24
},
whatWouldYouLikeToSpin: 459
whatWouldYouLikeToSpin: 459,
tanningHidesInterface: 324
}
8,136 changes: 8,101 additions & 35 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/game-engine/net/inbound-packets/npc-interaction-packet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const npcInteractionPacket = (player: Player, packet: PacketData) => {
logger.info(npc);
logger.error(`1: Invalid npc ${morphedNpc?.gameId || npc.id} option ${actionIdx + 1}, options: ${JSON.stringify(options)}`);
if (morphedNpc) {
logger.warn(`Note: (id-${morphedNpc.gameId}) is a morphed NPC. The parent NPC is (id-${npc.id}).`);
logger.warn(`Note: (id: ${morphedNpc.gameId}) is a morphed NPC. The parent NPC is (id: ${npc.id}).`);
}
return;
}
Expand All @@ -62,7 +62,7 @@ const npcInteractionPacket = (player: Player, packet: PacketData) => {
// Invalid action
logger.error(`2: Invalid npc ${morphedNpc?.gameId || npc.id} option ${actionIdx + 1}, options: ${JSON.stringify(options)}`);
if (morphedNpc) {
logger.warn(`Note: (id-${morphedNpc.gameId}) is a morphed NPC. The parent NPC is (id-${npc.id}).`);
logger.warn(`Note: (id: ${morphedNpc.gameId}) is a morphed NPC. The parent NPC is (id: ${npc.id}).`);
}
return;
}
Expand Down
3 changes: 2 additions & 1 deletion src/game-engine/util/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ export const colors = {
green: 0x00ff00,
yellow: 0xffff00,
red: 0xff0000,
lightred: 0xef101f,
black: 0x000000,
blue: 0x01bdfe,
lightred: 0xef101f
cyan: 0x00ffff,
};
4 changes: 2 additions & 2 deletions src/game-engine/world/action/item-on-npc.action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ const itemOnNpcActionPipe = (player: Player, npc: Npc, position: Position, item:

if(matchingHooks.length === 0) {
player.outgoingPackets.chatboxMessage(`Unhandled item on npc interaction: ${ item.itemId } on ${ morphedNpc?.name || npc.name } ` +
`(id-${ morphedNpc?.gameId || npc.id }) @ ${ position.x },${ position.y },${ position.level }`);
`(id: ${ morphedNpc?.gameId || npc.id }) @ ${ position.x },${ position.y },${ position.level }`);
if (morphedNpc) {
player.outgoingPackets.chatboxMessage(`Note: (id-${morphedNpc.gameId}) is a morphed NPC. The parent NPC is (id-${npc.id}).`);
player.outgoingPackets.chatboxMessage(`Note: (id: ${morphedNpc.gameId}) is a morphed NPC. The parent NPC is (id: ${npc.id}).`);
}
return null;
}
Expand Down
2 changes: 1 addition & 1 deletion src/game-engine/world/action/item-on-object.action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ const itemOnObjectActionPipe = (player: Player, landscapeObject: LandscapeObject

if(matchingHooks.length === 0) {
player.outgoingPackets.chatboxMessage(`Unhandled item on object interaction: ${ item.itemId } on ${ objectConfig.name } ` +
`(id-${ landscapeObject.objectId }) @ ${ position.x },${ position.y },${ position.level }`);
`(id: ${ landscapeObject.objectId }) @ ${ position.x },${ position.y },${ position.level }`);
return null;
}

Expand Down
4 changes: 2 additions & 2 deletions src/game-engine/world/action/npc-interaction.action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ const npcInteractionActionPipe = (player: Player, npc: Npc, position: Position,
}

if(matchingHooks.length === 0) {
player.outgoingPackets.chatboxMessage(`Unhandled NPC interaction: ${option} ${morphedNpc?.key || npc.key} (id-${morphedNpc?.gameId || npc.id}) @ ${position.x},${position.y},${position.level}`);
player.outgoingPackets.chatboxMessage(`Unhandled NPC interaction: ${option} ${morphedNpc?.key || npc.key} (id: ${morphedNpc?.gameId || npc.id}) @ ${position.x},${position.y},${position.level}`);
if (morphedNpc) {
player.outgoingPackets.chatboxMessage(`Note: (id-${morphedNpc.gameId}) is a morphed NPC. The parent NPC is (id-${npc.id}).`);
player.outgoingPackets.chatboxMessage(`Note: (id: ${morphedNpc.gameId}) is a morphed NPC. The parent NPC is (id: ${npc.id}).`);
}
return null;
}
Expand Down
2 changes: 1 addition & 1 deletion src/game-engine/world/action/object-interaction.action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const objectInteractionActionPipe = (player: Player, landscapeObject: LandscapeO

if(matchingHooks.length === 0) {
player.outgoingPackets.chatboxMessage(`Unhandled object interaction: ${option} ${objectConfig.name} ` +
`(id-${landscapeObject.objectId}) @ ${position.x},${position.y},${position.level}`);
`(id: ${landscapeObject.objectId}) @ ${position.x},${position.y},${position.level}`);
return null;
}

Expand Down
15 changes: 11 additions & 4 deletions src/game-engine/world/actor/player/player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -697,9 +697,16 @@ export class Player extends Actor {
return slot;
}

public hasCoins(amount: number): number {
return this.inventory.items
.findIndex(item => item !== null && item.itemId === itemIds.coins && item.amount >= amount);
public hasEnoughCoins(amount: number): boolean {
return this.inventory.items.filter(item => item != null && item.itemId === itemIds.coins && item.amount >= amount).length !== 0;
}

public removeCoins(buyCost: number): void {
const coinsIndex = this.inventory.items.findIndex(item => item != null && item.itemId === itemIds.coins && item.amount >= buyCost);
const coins = this.inventory.items[coinsIndex];
const amountAfterRemoval = coins.amount - buyCost;
this.inventory.set(coinsIndex, { itemId: itemIds.coins, amount: amountAfterRemoval });
this.outgoingPackets.sendUpdateSingleWidgetItem(widgets.inventory, coinsIndex, { itemId: itemIds.coins, amount: amountAfterRemoval });
}

public removeItem(slot: number): void {
Expand Down Expand Up @@ -1022,7 +1029,7 @@ export class Player extends Actor {

const npcDetails = findNpc(originalNpc.childrenIds[morphIndex]);
if (!npcDetails.key) {
logger.warn(`Fetched a morphed NPC, but it isn't yet registered on the server. (id-${originalNpc.id}) (morphedId-${npcDetails.gameId})`);
logger.warn(`Fetched a morphed NPC, but it isn't yet registered on the server. (id: ${originalNpc.id}) (morphedId-${npcDetails.gameId})`);
}
return npcDetails;
}
Expand Down
18 changes: 18 additions & 0 deletions src/game-engine/world/config/item-ids.ts
Original file line number Diff line number Diff line change
Expand Up @@ -526,4 +526,22 @@ export const itemIds = {
untrimmed: 9813,
},
},
hides: {
cowhide: 1739,
black_dragonhide: 1747,
red_dragonhide: 1749,
blue_dragonhide: 1751,
green_dragonhide: 1753,
snake_hide: 7801,
snake_hide_temple_trekking: 7801
},
leather: {
leather: 1741,
hard_leather: 1743,
green_d_leather: 1745,
blue_d_leather: 2505,
red_d_leather: 2507,
black_d_leather: 2509,
snakeskin: 6289
}
};
2 changes: 1 addition & 1 deletion src/plugins/items/shopping/buy-from-shop.plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const handler: itemInteractionActionHandler = (details) => {
const buyItem = findItem(itemId);
const buyItemValue = buyItem.value || 0;
let buyCost = buyAmount * buyItemValue;
const coinsIndex = player.hasCoins(buyCost);
const coinsIndex = player.hasEnoughCoins(buyCost);

if(coinsIndex === -1) {
player.sendMessage(`You don't have enough coins.`);
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/items/shopping/sell-to-shop.plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const handler: itemInteractionActionHandler = (details) => {

const sellPrice = sellAmount * itemValue; // @TODO scale price per item, not per sale
if(sellPrice > 0) {
let coinsIndex = player.hasCoins(1);
let coinsIndex = player.hasEnoughCoins(1);

if(coinsIndex === -1) {
coinsIndex = inventory.getFirstOpenSlot();
Expand Down
133 changes: 133 additions & 0 deletions src/plugins/skills/crafting/tanning-hides/tanning-hides-constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { Item } from '@engine/world/items/item';
import { widgets } from '@engine/config';
import { itemIds } from '@engine/world/config/item-ids';

interface TanableHide {
hideId: number;
Comment thread
SchauweM marked this conversation as resolved.
requiredLevel: number;
ingredients: Item;
output: Item & { label: string };
cost: number;
}

interface TanButton {
shouldTakeInput: boolean;
count: number;
hide: TanableHide;
}

const COWHIDE_LEATHER: TanableHide = {
hideId: itemIds.hides.cowhide,
requiredLevel: 1,
ingredients: { itemId: itemIds.hides.cowhide, amount: 1 },
output: { label: `Soft leather`, itemId: itemIds.leather.leather, amount: 1 },
cost: 1,
}

const COWHIDE_HARDLEATHER: TanableHide = {
hideId: itemIds.hides.cowhide,
requiredLevel: 28,
ingredients: { itemId: itemIds.hides.cowhide, amount: 1 },
output: { label: `Hard leather`, itemId: itemIds.leather.hard_leather, amount: 1 },
cost: 3,
}

const SNAKEHIDE: TanableHide = {
hideId: itemIds.hides.snake_hide,
requiredLevel: 45,
ingredients: { itemId: itemIds.hides.snake_hide, amount: 1 },
output: { label: `Snakeskin`, itemId: itemIds.leather.snakeskin, amount: 1 },
cost: 15,
}

const SNAKEHIDE_TEMPLE_TREKKING: TanableHide = {
hideId: itemIds.hides.snake_hide_temple_trekking,
requiredLevel: 45,
ingredients: { itemId: itemIds.hides.snake_hide_temple_trekking, amount: 1 },
output: { label: `Snakeskin`, itemId: itemIds.leather.snakeskin, amount: 1 },
cost: 20,
}

const GREEN_D_HIDE: TanableHide = {
hideId: itemIds.hides.green_dragonhide,
requiredLevel: 57,
ingredients: { itemId: itemIds.hides.green_dragonhide, amount: 1 },
output: { label: `Green d'hide`, itemId: itemIds.leather.green_d_leather, amount: 1 },
cost: 20,
}

const BLUE_D_HIDE: TanableHide = {
hideId: itemIds.hides.blue_dragonhide,
requiredLevel: 66,
ingredients: { itemId: itemIds.hides.blue_dragonhide, amount: 1 },
output: { label: `Blue d'hide`, itemId: itemIds.leather.blue_d_leather, amount: 1 },
cost: 20,
}

const RED_D_HIDE: TanableHide = {
hideId: itemIds.hides.red_dragonhide,
requiredLevel: 73,
ingredients: { itemId: itemIds.hides.red_dragonhide, amount: 1 },
output: { label: `Red d'hide`, itemId: itemIds.leather.red_d_leather, amount: 1 },
cost: 20,
}

const BLACK_D_HIDE: TanableHide = {
hideId: itemIds.hides.black_dragonhide,
requiredLevel: 79,
ingredients: { itemId: itemIds.hides.black_dragonhide, amount: 1 },
output: { label: `Black d'hide`, itemId: itemIds.leather.black_d_leather, amount: 1 },
cost: 20,
}

/**
* Defines the widget model and item slots.
*/
export const widgetModelSlots = [
{ slotId: 100, titleLabel: 108, costLabel: 116, item: COWHIDE_LEATHER },
{ slotId: 101, titleLabel: 109, costLabel: 117, item: COWHIDE_HARDLEATHER },
{ slotId: 102, titleLabel: 110, costLabel: 118, item: SNAKEHIDE },
{ slotId: 103, titleLabel: 111, costLabel: 119, item: SNAKEHIDE_TEMPLE_TREKKING },
{ slotId: 104, titleLabel: 112, costLabel: 120, item: GREEN_D_HIDE },
{ slotId: 105, titleLabel: 113, costLabel: 121, item: BLUE_D_HIDE },
{ slotId: 106, titleLabel: 114, costLabel: 122, item: RED_D_HIDE },
{ slotId: 107, titleLabel: 115, costLabel: 123, item: BLACK_D_HIDE }
];

/**
* Defines the widget button ids.
*/
export const widgetButtonIds: Map<number, TanButton> = new Map<number, TanButton>([
[148, { shouldTakeInput: false, count: 1, hide: COWHIDE_LEATHER }],
[140, { shouldTakeInput: false, count: 5, hide: COWHIDE_LEATHER }],
[132, { shouldTakeInput: true, count: 0, hide: COWHIDE_LEATHER }],
[124, { shouldTakeInput: false, count: 0, hide: COWHIDE_LEATHER }],
[149, { shouldTakeInput: false, count: 1, hide: COWHIDE_HARDLEATHER }],
[141, { shouldTakeInput: false, count: 5, hide: COWHIDE_HARDLEATHER }],
[133, { shouldTakeInput: true, count: 0, hide: COWHIDE_HARDLEATHER }],
[125, { shouldTakeInput: false, count: 0, hide: COWHIDE_HARDLEATHER }],
[150, { shouldTakeInput: false, count: 1, hide: SNAKEHIDE }],
[142, { shouldTakeInput: false, count: 5, hide: SNAKEHIDE }],
[134, { shouldTakeInput: true, count: 0, hide: SNAKEHIDE }],
[126, { shouldTakeInput: false, count: 0, hide: SNAKEHIDE }],
[151, { shouldTakeInput: false, count: 1, hide: SNAKEHIDE_TEMPLE_TREKKING }],
[143, { shouldTakeInput: false, count: 5, hide: SNAKEHIDE_TEMPLE_TREKKING }],
[135, { shouldTakeInput: true, count: 0, hide: SNAKEHIDE_TEMPLE_TREKKING }],
[127, { shouldTakeInput: false, count: 0, hide: SNAKEHIDE_TEMPLE_TREKKING }],
[152, { shouldTakeInput: false, count: 1, hide: GREEN_D_HIDE }],
[144, { shouldTakeInput: false, count: 5, hide: GREEN_D_HIDE }],
[136, { shouldTakeInput: true, count: 0, hide: GREEN_D_HIDE }],
[128, { shouldTakeInput: false, count: 0, hide: GREEN_D_HIDE }],
[153, { shouldTakeInput: false, count: 1, hide: BLUE_D_HIDE }],
[145, { shouldTakeInput: false, count: 5, hide: BLUE_D_HIDE }],
[137, { shouldTakeInput: true, count: 0, hide: BLUE_D_HIDE }],
[129, { shouldTakeInput: false, count: 0, hide: BLUE_D_HIDE }],
[154, { shouldTakeInput: false, count: 1, hide: RED_D_HIDE }],
[146, { shouldTakeInput: false, count: 5, hide: RED_D_HIDE }],
[138, { shouldTakeInput: true, count: 0, hide: RED_D_HIDE }],
[130, { shouldTakeInput: false, count: 0, hide: RED_D_HIDE }],
[155, { shouldTakeInput: false, count: 1, hide: BLACK_D_HIDE }],
[147, { shouldTakeInput: false, count: 5, hide: BLACK_D_HIDE }],
[139, { shouldTakeInput: true, count: 0, hide: BLACK_D_HIDE }],
[131, { shouldTakeInput: false, count: 0, hide: BLACK_D_HIDE }],
]);
Loading