Skip to content

Commit 628c4de

Browse files
Merge pull request #180 from Promises/woodcutting
Birds nests, rare gems, essence mining and gem mining
2 parents e310da0 + 771accc commit 628c4de

File tree

7 files changed

+163
-24
lines changed

7 files changed

+163
-24
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,16 @@ The server runs on the 435 revision of the game, which was a game update made on
109109
* Formula for success :heavy_check_mark:
110110
* Chopping Trees :heavy_check_mark:
111111
* Axes :heavy_check_mark:
112-
* Birds nests :x:
112+
* Birds nests :heavy_check_mark:
113113
* Stump ids :yellow_square:
114+
* Canoes :x:
114115
* Mining
115116
* Formula for success :heavy_check_mark:
116117
* Mining ores :heavy_check_mark:
117118
* Pickaxes :heavy_check_mark:
118-
* Random gems :x:
119-
* Gem ores :x:
120-
* Essence mining :x:
119+
* Random gems :heavy_check_mark:
120+
* Gem ores :heavy_check_mark:
121+
* Essence mining :heavy_check_mark:
121122
* Empty Rock ids :yellow_square:
122123
* Crafting
123124
* Spinning wheel :heavy_check_mark:

src/util/colors.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,22 @@ export function hexToRgb(hex: number): { r: number, b: number, g: number } {
66
};
77
}
88

9+
export function hexToHexString(hex: number): string {
10+
let r = ((hex >> 16) & 0xff).toString(16);
11+
let g = ((hex >> 8) & 0xff).toString(16);
12+
let b = (hex & 0xff).toString(16);
13+
if (r === '0') {
14+
r = '00';
15+
}
16+
if (g === '0') {
17+
g = '00';
18+
}
19+
if (b === '0') {
20+
b = '00';
21+
}
22+
return r + g + b;
23+
}
24+
925
export function rgbTo16Bit(r: number, g: number, b: number): number {
1026
return ((r & 0x1f) << 11) | ((g & 0x3f) << 5) | (b & 0x1f) << 0;
1127
}

src/util/strings.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { hexToHexString } from '@server/util/colors';
2+
13
export const startsWithVowel = (str: string): boolean => {
24
str = str.trim().toLowerCase();
35

@@ -7,7 +9,7 @@ export const startsWithVowel = (str: string): boolean => {
79
};
810

911
// Thank you to the Apollo team for these values. :)
10-
const charWidths = [ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
12+
const charWidths = [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1113
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 7, 14, 9, 12, 12, 4, 5,
1214
5, 10, 8, 4, 8, 4, 7, 9, 7, 9, 8, 8, 8, 9, 7, 9, 9, 4, 5, 7,
1315
9, 7, 9, 14, 9, 8, 8, 8, 7, 7, 9, 8, 6, 8, 8, 7, 10, 9, 9, 8,
@@ -19,7 +21,7 @@ const charWidths = [ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1921
8, 8, 4, 5, 5, 6, 7, 11, 11, 11, 9, 9, 9, 9, 9, 9, 9, 13, 8, 8,
2022
8, 8, 8, 4, 4, 5, 4, 8, 9, 9, 9, 9, 9, 9, 8, 10, 9, 9, 9, 9,
2123
8, 8, 8, 8, 8, 8, 8, 8, 8, 13, 6, 8, 8, 8, 8, 4, 4, 5, 4, 8,
22-
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ];
24+
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8];
2325

2426
export function wrapText(text: string, maxWidth: number): string[] {
2527
const lines = [];
@@ -30,11 +32,11 @@ export function wrapText(text: string, maxWidth: number): string[] {
3032
let widthAfterSpace = 0;
3133
let lastSpaceChar = '';
3234

33-
for(let i = 0; i < text.length; i++) {
35+
for (let i = 0; i < text.length; i++) {
3436
const char = text.charAt(i);
3537

3638
// Ignore <col=> and </col> strings...
37-
if(char === '<' && (text.charAt(i + 1) === '/' || text.charAt(i + 1) === 'c' && text.charAt(i + 2) === 'o' && text.charAt(i + 3) === 'l')) {
39+
if (char === '<' && (text.charAt(i + 1) === '/' || text.charAt(i + 1) === 'c' && text.charAt(i + 2) === 'o' && text.charAt(i + 3) === 'l')) {
3840
const tagCloseIndex = text.indexOf('>', i);
3941
i = tagCloseIndex;
4042
continue;
@@ -44,20 +46,20 @@ export function wrapText(text: string, maxWidth: number): string[] {
4446
width += charWidth;
4547
widthAfterSpace += charWidth;
4648

47-
if(char === ' ' || char === '\n' || char === '-') {
49+
if (char === ' ' || char === '\n' || char === '-') {
4850
lastSpaceChar = char;
4951
lastSpace = i;
5052
widthAfterSpace = 0;
5153
}
5254

53-
if(width >= maxWidth || char === '\n') {
55+
if (width >= maxWidth || char === '\n') {
5456
lines.push(text.substring(lineStartIdx, lastSpaceChar === '-' ? lastSpace + 1 : lastSpace));
5557
lineStartIdx = lastSpace + 1;
5658
width = widthAfterSpace;
5759
}
5860
}
5961

60-
if(lineStartIdx !== text.length - 1) {
62+
if (lineStartIdx !== text.length - 1) {
6163
lines.push(text.substring(lineStartIdx, text.length));
6264
}
6365

@@ -67,14 +69,19 @@ export function wrapText(text: string, maxWidth: number): string[] {
6769
export function stringToLong(s: string): bigint {
6870
let l: bigint = BigInt(0);
6971

70-
for(let i = 0; i < s.length && i < 12; i++) {
72+
for (let i = 0; i < s.length && i < 12; i++) {
7173
const c = s.charAt(i);
7274
const cc = s.charCodeAt(i);
7375
l *= BigInt(37);
74-
if(c >= 'A' && c <= 'Z') l += BigInt((1 + cc) - 65);
75-
else if(c >= 'a' && c <= 'z') l += BigInt((1 + cc) - 97);
76-
else if(c >= '0' && c <= '9') l += BigInt((27 + cc) - 48);
76+
if (c >= 'A' && c <= 'Z') l += BigInt((1 + cc) - 65);
77+
else if (c >= 'a' && c <= 'z') l += BigInt((1 + cc) - 97);
78+
else if (c >= '0' && c <= '9') l += BigInt((27 + cc) - 48);
7779
}
78-
while(l % BigInt(37) == BigInt(0) && l != BigInt(0)) l /= BigInt(37);
80+
while (l % BigInt(37) == BigInt(0) && l != BigInt(0)) l /= BigInt(37);
7981
return l;
8082
}
83+
84+
export function colorText(s: string, hexColor: number): string {
85+
console.log(hexToHexString(hexColor));
86+
return `<col=${hexToHexString(hexColor)}>${s}</col>`;
87+
}

src/world/config/harvestable-object.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,9 @@ export enum Ore {
106106
GOLD,
107107
MITHIL,
108108
ADAMANT,
109-
RUNITE
109+
RUNITE,
110+
RUNE_ESS,
111+
GEM
110112
}
111113

112114

@@ -223,6 +225,16 @@ const Ores: IHarvestable[] = [
223225
respawnHigh: 1200,
224226
baseChance: -10,
225227
break: 100
228+
},
229+
{
230+
objects: new Map<number, number>([[2111, 450]]), // Gem rocks
231+
itemId: 1625,
232+
level: 40,
233+
experience: 65.0,
234+
respawnLow: 200,
235+
respawnHigh: 400,
236+
baseChance: 30,
237+
break: 100
226238
}
227239
];
228240

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { Player } from '@server/world/actor/player/player';
2+
3+
export function checkForGemBoost(player: Player): number {
4+
if (player.hasItemInEquipment(1706) ||
5+
player.hasItemInEquipment(1708) ||
6+
player.hasItemInEquipment(1710) ||
7+
player.hasItemInEquipment(1712)) {
8+
return 86;
9+
}
10+
return 256;
11+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Note if adding hunter, Strung rabbit foot makes this out of 94 instead of 99
2+
import { randomBetween } from '@server/util/num';
3+
import { Item } from '@server/world/items/item';
4+
5+
export function rollBirdsNestType(): Item {
6+
const roll = randomBetween(0, 99);
7+
let itemId;
8+
if (roll > 3) {
9+
// Bird egg
10+
if (roll === 0) {
11+
itemId = 5070; // Red egg
12+
} else if (roll === 1) {
13+
itemId = 5071; // Green egg
14+
} else {
15+
itemId = 5072; // blue egg
16+
}
17+
} else if (roll > 34) {
18+
itemId = 5074; // Ring
19+
} else {
20+
itemId = 5073; // Seeds
21+
}
22+
return {itemId: itemId, amount: 1};
23+
}
24+
25+
export function rollGemType(): Item {
26+
const roll = randomBetween(0, 3);
27+
let itemId;
28+
if (roll === 0) {
29+
itemId = 1617; // Uncut Diamond
30+
} else if (roll === 1) {
31+
itemId = 1619; // Uncut ruby
32+
} else if (roll === 2) {
33+
itemId = 1621; // uncut emerald
34+
} else {
35+
itemId = 1623; // uncut sapphire
36+
}
37+
return {itemId: itemId, amount: 1};
38+
}
39+
40+
export function rollGemRockResult(): Item {
41+
const roll = randomBetween(0, 127);
42+
let itemId;
43+
if (roll < 60) {
44+
itemId = 1625; // Uncut Opal
45+
} else if (roll < 90) {
46+
itemId = 1627; // Uncut Jade
47+
} else if (roll < 105) {
48+
itemId = 1629; // uncut topaz
49+
} else if (roll < 114) {
50+
itemId = 1623; // uncut sapphire
51+
} else if (roll < 119) {
52+
itemId = 1621; // uncut emerald
53+
} else if (roll < 124) {
54+
itemId = 1619; // uncut ruby
55+
} else {
56+
itemId = 1617; // uncut diamond
57+
}
58+
return {itemId: itemId, amount: 1};
59+
}

src/world/skill-util/harvest-skill.ts

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import { loopingAction } from '@server/world/actor/player/action/action';
88
import { randomBetween } from '@server/util/num';
99
import { ObjectActionDetails } from '@server/world/actor/player/action/object-action';
1010
import { colors } from '@server/util/colors';
11+
import { checkForGemBoost } from '@server/world/skill-util/glory-boost';
12+
import { colorText } from '@server/util/strings';
13+
import { rollBirdsNestType, rollGemRockResult, rollGemType } from '@server/world/skill-util/harvest-roll';
1114

1215
export function canInitiateHarvest(player: Player, target: IHarvestable, skill: Skill): undefined | HarvestTool {
1316
if (!target) {
@@ -16,7 +19,7 @@ export function canInitiateHarvest(player: Player, target: IHarvestable, skill:
1619
player.sendMessage('There is current no ore available in this rock.');
1720
break;
1821
default:
19-
player.sendMessage(`<col=${colors.red}>HARVEST SKILL ERROR, PLEASE CONTACT DEVELOPERS</col>`);
22+
player.sendMessage(colorText('HARVEST SKILL ERROR, PLEASE CONTACT DEVELOPERS', colors.red));
2023
break;
2124

2225

@@ -78,7 +81,15 @@ export function canInitiateHarvest(player: Player, target: IHarvestable, skill:
7881
}
7982

8083
export function handleHarvesting(details: ObjectActionDetails, tool: HarvestTool, target: IHarvestable, skill: Skill): void {
81-
let targetName: string = cache.itemDefinitions.get(target.itemId).name.toLowerCase();
84+
let itemToAdd = target.itemId;
85+
if (itemToAdd === 1436 && details.player.skills.hasLevel(Skill.MINING, 30)) {
86+
itemToAdd = 7936;
87+
}
88+
if (details.object.objectId === 2111 && details.player.skills.hasLevel(Skill.MINING, 30)) {
89+
itemToAdd = rollGemRockResult().itemId;
90+
}
91+
let targetName: string = cache.itemDefinitions.get(itemToAdd).name.toLowerCase();
92+
8293
switch (skill) {
8394
case Skill.MINING:
8495
targetName = targetName.replace(' ore', '');
@@ -110,19 +121,41 @@ export function handleHarvesting(details: ObjectActionDetails, tool: HarvestTool
110121
toolLevel = 2;
111122
}
112123
const percentNeeded = target.baseChance + toolLevel + details.player.skills.values[skill].level;
113-
details.player.sendMessage(`roll: ${successChance}, needed: ${percentNeeded}`);
114124
if (successChance <= percentNeeded) {
115125
if (details.player.inventory.hasSpace()) {
116-
126+
let randomLoot = false;
127+
let roll = 0;
117128
switch (skill) {
118129
case Skill.MINING:
119-
details.player.sendMessage(`You manage to mine some ${targetName}.`);
130+
roll = randomBetween(1, checkForGemBoost(details.player));
131+
if (roll === 1) {
132+
randomLoot = true;
133+
details.player.sendMessage(colorText('You found a rare gem.', colors.red));
134+
details.player.giveItem(rollGemType());
135+
}
120136
break;
121137
case Skill.WOODCUTTING:
122-
details.player.sendMessage(`You manage to chop some ${targetName}.`);
138+
roll = randomBetween(1, 256);
139+
if (roll === 1) {
140+
randomLoot = true;
141+
details.player.sendMessage(colorText('A bird\'s nest falls out of the tree.', colors.red));
142+
world.spawnWorldItem(rollBirdsNestType(), details.player.position, details.player, 300);
143+
}
123144
break;
124145
}
125-
details.player.giveItem(target.itemId);
146+
if (!randomLoot) {
147+
switch (skill) {
148+
case Skill.MINING:
149+
details.player.sendMessage(`You manage to mine some ${targetName}.`);
150+
break;
151+
case Skill.WOODCUTTING:
152+
details.player.sendMessage(`You manage to chop some ${targetName}.`);
153+
break;
154+
}
155+
156+
details.player.giveItem(itemToAdd);
157+
158+
}
126159
details.player.skills.addExp(skill, target.experience);
127160
if (randomBetween(0, 100) <= target.break) {
128161
details.player.playSound(soundIds.oreDepeleted);

0 commit comments

Comments
 (0)