@@ -4,32 +4,135 @@ import { Position } from '../position';
4
4
import { Chunk } from '@server/world/map/chunk' ;
5
5
import { Tile } from '@runejs/cache-parser' ;
6
6
7
+ class Point {
8
+
9
+ private _parent : Point = null ;
10
+ private _cost : number ;
11
+ private _heuristic : number ;
12
+ private _depth : number ;
13
+
14
+ public constructor ( private readonly _x : number , private readonly _y : number ) {
15
+ }
16
+
17
+ public compare ( point : Point ) : number {
18
+ return this . _cost - point . _cost ;
19
+ }
20
+
21
+ public equals ( point : Point ) : boolean {
22
+ if ( this . _cost === point . _cost && this . _heuristic === point . _heuristic && this . _depth === point . _depth ) {
23
+ if ( this . _parent === null && point . _parent !== null ) {
24
+ return false ;
25
+ } else if ( this . _parent !== null && ! this . _parent . equals ( point . _parent ) ) {
26
+ return false ;
27
+ }
28
+
29
+ return this . _x === point . _x && this . _y === point . _y ;
30
+ }
31
+
32
+ return false ;
33
+ }
34
+
35
+ public get x ( ) : number {
36
+ return this . _x ;
37
+ }
38
+
39
+ public get y ( ) : number {
40
+ return this . _y ;
41
+ }
42
+
43
+ public get parent ( ) : Point {
44
+ return this . _parent ;
45
+ }
46
+
47
+ public set parent ( value : Point ) {
48
+ this . _parent = value ;
49
+ }
50
+
51
+ public get cost ( ) : number {
52
+ return this . _cost ;
53
+ }
54
+
55
+ public set cost ( value : number ) {
56
+ this . _cost = value ;
57
+ }
58
+
59
+ public get heuristic ( ) : number {
60
+ return this . _heuristic ;
61
+ }
62
+
63
+ public set heuristic ( value : number ) {
64
+ this . _heuristic = value ;
65
+ }
66
+
67
+ public get depth ( ) : number {
68
+ return this . _depth ;
69
+ }
70
+
71
+ public set depth ( value : number ) {
72
+ this . _depth = value ;
73
+ }
74
+
75
+ }
76
+
7
77
export class Pathfinding {
8
78
79
+ private currentPoint : Point ;
80
+ private points : Point [ ] [ ] ;
81
+ private closedPoints : Point [ ] = [ ] ;
82
+ private openPoints : Point [ ] = [ ] ;
83
+
9
84
public constructor ( private actor : Actor ) {
10
85
}
11
86
12
- public pathTo ( destinationX : number , destinationY : number ) : void {
13
- const path : Position [ ] [ ] = new Array ( 16 ) . fill ( new Array ( 16 ) ) ;
14
- }
87
+ public pathTo ( destinationX : number , destinationY : number , diameter : number = 32 ) : void {
88
+ // @TODO check if destination is too far away
15
89
16
- public canMoveTo ( origin : Position , destination : Position ) : boolean {
17
- let destinationChunk : Chunk = world . chunkManager . getChunkForWorldPosition ( destination ) ;
18
- const positionAbove : Position = new Position ( destination . x , destination . y , destination . level + 1 ) ;
19
- const chunkAbove : Chunk = world . chunkManager . getChunkForWorldPosition ( positionAbove ) ;
20
- let tile : Tile = chunkAbove . getTile ( positionAbove ) ;
21
-
22
- if ( ! tile || ! tile . bridge ) {
23
- tile = destinationChunk . getTile ( destination ) ;
24
- } else {
25
- // Destination is a bridge, so we need to check the chunk above to get the bridge tiles instead of the level we're currently on
26
- destinationChunk = chunkAbove ;
90
+ const currentPos = this . actor . position ;
91
+ const radius = Math . floor ( diameter / 2 ) ;
92
+ const startX = currentPos . x ;
93
+ const startY = currentPos . y ;
94
+ const pathingStartX = startX - radius ;
95
+ const pathingStartY = startY - radius ;
96
+
97
+ this . points = new Array ( diameter ) . fill ( new Array ( diameter ) ) ;
98
+
99
+ for ( let x = 0 ; x < diameter ; x ++ ) {
100
+ for ( let y = 0 ; y < diameter ; y ++ ) {
101
+ this . points [ x ] [ y ] = new Point ( x + startX , y + startY ) ;
102
+ }
27
103
}
28
104
29
- if ( tile ) {
30
- if ( tile . nonWalkable ) {
31
- return false ;
105
+ // Center point
106
+ this . openPoints . push ( this . points [ radius + 1 ] [ radius + 1 ] ) ;
107
+
108
+ while ( this . openPoints . length > 0 ) {
109
+ this . currentPoint = this . calculateBestPoint ( ) ;
110
+
111
+ if ( this . currentPoint === this . points [ destinationX - pathingStartX ] [ destinationY - pathingStartY ] ) {
112
+ break ;
32
113
}
114
+
115
+ this . openPoints . splice ( this . openPoints . indexOf ( this . currentPoint ) , 1 ) ;
116
+ this . closedPoints . push ( this . currentPoint ) ;
117
+
118
+ let x = this . currentPoint . x ;
119
+ let y = this . currentPoint . y ;
120
+ let level = this . actor . position . level ;
121
+ let currentPosition = new Position ( x , y , level ) ;
122
+
123
+ let testPosition = new Position ( x - 1 , y , level ) ;
124
+ if ( this . canMoveTo ( currentPosition , testPosition ) ) {
125
+ const point = this . points [ x - 1 ] [ y ] ;
126
+ }
127
+ }
128
+ }
129
+
130
+ public canMoveTo ( origin : Position , destination : Position ) : boolean {
131
+ const destinationChunk : Chunk = world . chunkManager . getChunkForWorldPosition ( destination ) ;
132
+ const tile : Tile = destinationChunk . getTile ( destination ) ;
133
+
134
+ if ( tile && tile . nonWalkable ) {
135
+ return false ;
33
136
}
34
137
35
138
const initialX : number = origin . x ;
@@ -38,10 +141,6 @@ export class Pathfinding {
38
141
const destinationLocalX : number = destination . x - destinationChunk . collisionMap . insetX ;
39
142
const destinationLocalY : number = destination . y - destinationChunk . collisionMap . insetY ;
40
143
41
- // @TODO check objects moving from bridge tile to non bridge tile
42
- // ^ currently possible to clip through some bridge walls thanks to this issue
43
- // not the most important thing since you still can't walk on water or anything
44
-
45
144
// West
46
145
if ( destination . x < initialX && destination . y == initialY ) {
47
146
if ( ( destinationAdjacency [ destinationLocalX ] [ destinationLocalY ] & 0x1280108 ) != 0 ) {
@@ -133,4 +232,21 @@ export class Pathfinding {
133
232
return { localX, localY, chunk : cornerChunk } ;
134
233
}
135
234
235
+ private calculateBestPoint ( ) : Point {
236
+ let bestPoint : Point = null ;
237
+
238
+ for ( const point of this . openPoints ) {
239
+ if ( bestPoint === null ) {
240
+ bestPoint = point ;
241
+ continue ;
242
+ }
243
+
244
+ if ( point . cost < bestPoint . cost ) {
245
+ bestPoint = point ;
246
+ }
247
+ }
248
+
249
+ return bestPoint ;
250
+ }
251
+
136
252
}
0 commit comments