1
- import { itemOnObjectActionHandler } from '@engine/world/action/item-on-object.action' ;
1
+ import { itemOnObjectActionHandler , ItemOnObjectActionHook } from '@engine/world/action/item-on-object.action' ;
2
2
import { widgets } from '@engine/config' ;
3
3
import { Skill } from '@engine/world/actor/skills' ;
4
- import { bars , smithables , widgetItems } from '@plugins/skills/smithing/forging-constants' ;
4
+ import { anvilIds , bars , smithables , widgetItems } from '@plugins/skills/smithing/forging-constants' ;
5
5
import { itemIds } from '@engine/world/config/item-ids' ;
6
6
import { Smithable } from '@plugins/skills/smithing/forging-types' ;
7
- import { itemInteractionActionHandler } from '@engine/world/action/item-interaction.action' ;
8
- import { loopingEvent } from '@engine/game-server' ;
7
+ import {
8
+ ItemInteractionAction ,
9
+ ItemInteractionActionHook
10
+ } from '@engine/world/action/item-interaction.action' ;
9
11
import { Player } from '@engine/world/actor/player/player' ;
10
12
import { findItem } from '@engine/config' ;
13
+ import { TaskExecutor } from '@engine/world/action' ;
14
+ import { Position } from '@engine/world/position' ;
15
+
16
+ /**
17
+ * The amount of items the player wants to forge.
18
+ */
19
+ let wantedAmount = 0 ;
20
+
21
+ /**
22
+ * The amount of items already forged.
23
+ */
24
+ let forgedAmount = 0 ;
11
25
12
26
const mapWidgetItemsToFlatArray = ( input ) => {
13
27
const result = [ ] ;
@@ -29,91 +43,118 @@ const mapToFlatArray = (input) => {
29
43
return results ;
30
44
} ;
31
45
46
+ /**
47
+ * Lookup a smithable from just an item id.
48
+ * @param itemId
49
+ */
32
50
const findSmithableByItemId = ( itemId ) : Smithable => {
33
51
return mapToFlatArray ( smithables ) . find ( ( smithable ) => {
34
52
return smithable . item . itemId === itemId ;
35
53
} ) ;
36
54
} ;
37
55
38
- const smithItem : itemInteractionActionHandler = ( details ) => {
39
- const { player, option, itemDetails } = details ;
40
-
41
- const smithable = findSmithableByItemId ( itemDetails . gameId ) ;
42
-
56
+ /**
57
+ * Check if the player is able to perform the action.
58
+ * @param task
59
+ */
60
+ const canActivate = ( task : TaskExecutor < ItemInteractionAction > ) : boolean => {
61
+ const { actor, player, actionData } = task . getDetails ( ) ;
62
+ const itemId = actionData . itemId ;
63
+ const smithable = findSmithableByItemId ( itemId ) ;
43
64
44
65
// In case the smithable doesn't exist.
45
66
if ( ! smithable ) {
46
- return ;
67
+ return false ;
47
68
}
48
69
49
70
// Check if the player has the level required.
50
71
if ( smithable . level > player . skills . getLevel ( Skill . SMITHING ) ) {
51
72
const item = findItem ( smithable . item . itemId ) ;
52
73
player . sendMessage ( `You have to be at least level ${ smithable . level } to smith ${ item . name } s.` , true ) ;
53
- return ;
74
+ return false ;
54
75
}
55
76
56
- const amountInInventory = player . inventory . findAll ( smithable . ingredient . itemId ) . length ;
77
+ // Check if the player has sufficient materials.
78
+ if ( ! hasMaterials ( player , smithable ) ) {
79
+ const bar = findItem ( smithable . ingredient . itemId ) ;
80
+ player . sendMessage ( `You don't have enough ${ bar . name } s.` , true ) ;
81
+ return false ;
82
+ }
57
83
58
- // Close the forging interface.
59
84
player . interfaceState . closeAllSlots ( ) ;
60
85
61
- const loop = loopingEvent ( { player : details . player } ) ;
62
- let elapsedTicks = 0 ;
63
- let wantedAmount = 0 ;
64
- let forgedAmount = 0 ;
86
+ return true ;
87
+ } ;
88
+
89
+ /**
90
+ * The actual forging loop.
91
+ * @param task
92
+ * @param taskIteration
93
+ */
94
+ const activate = ( task : TaskExecutor < ItemInteractionAction > , taskIteration : number ) : boolean => {
95
+ const { player, actionData } = task . getDetails ( ) ;
96
+ const itemId = actionData . itemId ;
97
+ const smithable = findSmithableByItemId ( itemId ) ;
65
98
66
99
// How many? Quick and dirty.
67
- switch ( option ) {
100
+ switch ( actionData . option ) {
68
101
case 'make' : wantedAmount = 1 ; break ;
69
102
case 'make-5' : wantedAmount = 5 ; break ;
70
103
case 'make-10' : wantedAmount = 10 ; break ;
71
104
}
72
105
73
- if ( ! hasIngredients ( details . player , smithable ) ) {
74
- player . interfaceState . closeAllSlots ( ) ;
75
- const bar = findItem ( smithable . ingredient . itemId ) ;
76
- player . sendMessage ( `You don't have enough ${ bar . name } s.` , true ) ;
77
- }
78
-
79
- loop . event . subscribe ( ( ) => {
80
- if ( ! hasIngredients ( details . player , smithable ) || wantedAmount === forgedAmount ) {
81
- loop . cancel ( ) ;
82
- return ;
83
- }
84
-
85
- if ( elapsedTicks % 5 === 0 ) {
86
- player . playAnimation ( 898 ) ;
106
+ for ( let m = 0 ; m < wantedAmount ; m ++ ) {
107
+ player . playAnimation ( 898 ) ;
108
+ if ( taskIteration % 4 === 0 ) {
109
+ if ( ! hasMaterials ( player , smithable ) || wantedAmount === forgedAmount ) {
110
+ return false ;
111
+ }
87
112
88
113
// Remove ingredients
89
114
for ( let i = 0 ; i < smithable . ingredient . amount ; i ++ ) {
90
115
player . inventory . removeFirst ( smithable . ingredient . itemId ) ;
91
- details . player . outgoingPackets . sendUpdateAllWidgetItems ( widgets . inventory , details . player . inventory ) ;
92
116
}
93
117
94
118
// Add item to inventory
95
- for ( let i = 0 ; i < smithable . item . amount ; i ++ ) {
96
- player . inventory . add ( smithable . item . itemId ) ;
97
- }
119
+ player . inventory . add ( {
120
+ itemId : smithable . item . itemId , amount : smithable . item . amount
121
+ } ) ;
98
122
99
- // Give the experience
123
+ player . outgoingPackets . sendUpdateAllWidgetItems ( widgets . inventory , player . inventory ) ;
100
124
player . skills . addExp ( Skill . SMITHING , smithable . experience ) ;
101
125
102
126
forgedAmount ++ ;
127
+ return true ;
103
128
}
129
+ }
104
130
105
- elapsedTicks ++ ;
106
- } ) ;
131
+ // Reset the properties, and strap in for the next batch.
132
+ if ( forgedAmount === wantedAmount ) {
133
+ forgedAmount = 0 ;
134
+ wantedAmount = 0 ;
135
+ return false ;
136
+ }
107
137
} ;
108
138
109
- const hasIngredients = ( player : Player , smithable : Smithable ) => {
139
+ /**
140
+ * Checks if the player has enough materials
141
+ * @param player
142
+ * @param smithable
143
+ */
144
+ const hasMaterials = ( player : Player , smithable : Smithable ) => {
110
145
return smithable . ingredient . amount <= player . inventory . findAll ( smithable . ingredient . itemId ) . length ;
111
146
} ;
112
147
148
+ /**
149
+ * Opens the forging interface, and loads the items.
150
+ * @param details
151
+ */
113
152
const openForgingInterface : itemOnObjectActionHandler = ( details ) => {
114
- const { player, item } = details ;
153
+ const { player, item, object } = details ;
115
154
const amountInInventory = player . inventory . findAll ( item ) . length ;
116
155
156
+ player . face ( new Position ( object . x , object . y ) ) ;
157
+
117
158
// The player does not have a hammer.
118
159
if ( ! player . inventory . has ( itemIds . hammer ) ) {
119
160
player . sendMessage ( `You need a hammer to work the metal with.` , true ) ;
@@ -143,17 +184,28 @@ const openForgingInterface: itemOnObjectActionHandler = (details) => {
143
184
} ) ;
144
185
} ;
145
186
146
- export default [
147
- {
148
- type : 'item_on_object' ,
149
- itemIds : [ ...bars . keys ( ) ] ,
150
- objectIds : [ 2783 ] ,
151
- options : [ 'use' ] ,
152
- action : openForgingInterface
153
- } ,
154
- {
155
- type : 'item_action' ,
156
- itemIds : [ ...mapWidgetItemsToFlatArray ( widgetItems ) ] ,
157
- action : smithItem
158
- }
159
- ] ;
187
+ export default {
188
+ pluginId : 'rs:forging' ,
189
+ hooks : [
190
+ {
191
+ type : 'item_on_object' ,
192
+ itemIds : [ ...bars . keys ( ) ] ,
193
+ objectIds : anvilIds ,
194
+ walkTo : true ,
195
+
196
+ cancelOtherActions : true ,
197
+ handler : openForgingInterface
198
+ } as ItemOnObjectActionHook ,
199
+ {
200
+ type : 'item_interaction' ,
201
+ itemIds : [ ...mapWidgetItemsToFlatArray ( smithables ) ] ,
202
+ options : [ 'make' , 'make-5' , 'make-10' ] ,
203
+ cancelOtherActions : true ,
204
+ task : {
205
+ canActivate,
206
+ activate,
207
+ interval : 1
208
+ }
209
+ } as ItemInteractionActionHook
210
+ ]
211
+ } ;
0 commit comments