Skip to content

Commit abc8351

Browse files
committed
refactor: convert firemaking task to new task system
refactor: remove unused
1 parent 6c3462e commit abc8351

File tree

2 files changed

+98
-28
lines changed

2 files changed

+98
-28
lines changed
Lines changed: 95 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,114 @@
1-
import { loopingEvent } from '@engine/plugins';
1+
import { ActorWorldItemInteractionTask } from '@engine/task/impl';
22
import { WorldItem } from '@engine/world';
33
import { Player } from '@engine/world/actor';
44
import { animationIds, soundIds } from '@engine/world/config';
55
import { canLight } from './chance';
6+
import { FIREMAKING_LOGS } from './data';
67
import { lightFire } from './light-fire';
78
import { Burnable } from './types';
89

9-
export function runFiremakingTask(player: Player, worldItemLog: WorldItem, skillInfo: Burnable) {
10-
let canLightFire = false;
11-
let elapsedTicks = 0;
12-
const loop = loopingEvent({ player });
13-
loop.event.subscribe(() => {
14-
if (worldItemLog.removed) {
15-
loop.cancel();
16-
return;
10+
/**
11+
* A firemaking task on a {@link WorldItem} log.
12+
*
13+
* This task extends {@link ActorWorldItemInteractionTask} which is a task that
14+
* handles the interaction between an {@link Actor} and a {@link WorldItem}.
15+
*
16+
* The {@link ActorWalkToTask} (which our parent class extends) automatically
17+
* sets a {@link TaskBreakType} of {@link TaskBreakType.ON_MOVE} which will
18+
* cancel this task if the player clicks to move.
19+
*
20+
* By default, the {@link ActorWalkToTask} also sets a {@link TaskStackType} of
21+
* {@link TaskStackType.NEVER} and a {@link TaskStackGroup} of {@link TaskStackGroup.ACTION}
22+
* which means that this other actions will cancel the firemaking attempts.
23+
*
24+
* @author jameskmonger
25+
*/
26+
class FiremakingTask extends ActorWorldItemInteractionTask<Player> {
27+
private skillInfo: Burnable;
28+
private elapsedTicks = 0;
29+
private canLightFire = false;
30+
31+
/**
32+
* Create a new firemaking task.
33+
*
34+
* @param player The player that is attempting to light the fire.
35+
* @param logWorldItem The world item that represents the log.
36+
*/
37+
constructor(
38+
player: Player,
39+
logWorldItem: WorldItem
40+
) {
41+
super(player, logWorldItem);
42+
43+
this.skillInfo = FIREMAKING_LOGS.find(l => l.logItem.gameId === logWorldItem.itemId);
44+
45+
if (!this.skillInfo) {
46+
throw new Error(`Invalid firemaking log item id: ${logWorldItem.itemId}`);
1747
}
48+
}
1849

19-
if (canLightFire) {
20-
loop.cancel();
21-
player.metadata.busy = true;
22-
setTimeout(() => lightFire(player, player.position, worldItemLog, skillInfo.experienceGained), 1200);
50+
/**
51+
* Execute the main firemaking task loop. This method is called every game tick until the task is completed.
52+
*
53+
* As this task extends {@link ActorWorldItemInteractionTask}, it's important that the
54+
* {@link super.execute} method is called at the start of this method.
55+
*
56+
* The base `execute` performs a number of checks that allow this task to function healthily.
57+
*/
58+
public execute() {
59+
super.execute();
60+
61+
/**
62+
* As this task extends {@link ActorWorldItemInteractionTask}, the base classes {@link ActorWorldItemInteractionTask["worldItem"]}
63+
* property will be null if the item isn't valid anymore or the player isn't in the right position.
64+
*
65+
* Therefore if `worldItem` is null, we can return early here, as our player is likely walking to the task.
66+
*/
67+
if (!this.worldItem) {
2368
return;
2469
}
2570

26-
// @TODO check for existing location objects again (in-case one spawned here during this loop)
27-
// @TODO check for tinderbox in-case it was removed
71+
// store the tick count before incrementing so we don't need to keep track of it in all the separate branches
72+
const tickCount = this.elapsedTicks++;
73+
74+
if (this.canLightFire) {
75+
if (tickCount === 2) {
76+
lightFire(this.actor, this.actor.position, this.worldItem, this.skillInfo.experienceGained);
77+
this.stop();
78+
}
79+
80+
// the rest of the function is for *attempting* to light the fire
81+
// so we can return early here
82+
return;
83+
}
2884

29-
if (elapsedTicks === 0 || elapsedTicks % 12 === 0) {
30-
player.playAnimation(animationIds.lightingFire);
85+
// play animation every 12 ticks
86+
if (tickCount % 12 === 0) {
87+
this.actor.playAnimation(animationIds.lightingFire);
3188
}
3289

33-
canLightFire = elapsedTicks > 10 && canLight(skillInfo.requiredLevel, player.skills.firemaking.level);
90+
// TODO (jameskmonger) reconsider this, is there a minimum tick count?
91+
// OSRS wiki implies that there isn't
92+
// https://oldschool.runescape.wiki/w/Firemaking#Success_chance
93+
const passedMinimumThreshold = tickCount > 10;
94+
this.canLightFire = passedMinimumThreshold && canLight(this.skillInfo.requiredLevel, this.actor.skills.firemaking.level);
3495

35-
if (!canLightFire && (elapsedTicks === 0 || elapsedTicks % 4 === 0)) {
36-
player.playSound(soundIds.lightingFire, 10, 0);
37-
} else if (canLightFire) {
38-
player.playSound(soundIds.fireLit, 7);
96+
// if we can now light the fire, reset the timer so that on the next tick we can begin lighting the fire
97+
if (this.canLightFire) {
98+
this.elapsedTicks = 0;
99+
this.actor.metadata.busy = true;
100+
this.actor.playSound(soundIds.fireLit, 7);
101+
102+
return;
39103
}
40104

41-
elapsedTicks++;
42-
});
105+
// play lighting sound every 4th tick
106+
if (tickCount % 4 === 0) {
107+
this.actor.playSound(soundIds.lightingFire, 10, 0);
108+
}
109+
}
110+
}
111+
112+
export function runFiremakingTask(player: Player, worldItemLog: WorldItem) {
113+
player.enqueueTask(FiremakingTask, [ worldItemLog ]);
43114
}

src/plugins/skills/firemaking/index.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { itemOnItemActionHandler } from '@engine/action';
2-
import { itemIds, soundIds, animationIds } from '@engine/world/config';
3-
import { loopingEvent } from '@engine/plugins';
2+
import { itemIds } from '@engine/world/config';
43
import { FIREMAKING_LOGS } from './data';
5-
import { canChain, canLight } from './chance';
4+
import { canChain } from './chance';
65
import { lightFire } from './light-fire';
76
import { runFiremakingTask } from './firemaking-task';
87

@@ -34,7 +33,7 @@ const action: itemOnItemActionHandler = (details) => {
3433
} else {
3534
player.sendMessage(`You attempt to light the logs.`);
3635

37-
runFiremakingTask(player, worldItemLog, skillInfo);
36+
runFiremakingTask(player, worldItemLog);
3837
}
3938
};
4039

0 commit comments

Comments
 (0)