-
Notifications
You must be signed in to change notification settings - Fork 3
/
are.go
506 lines (481 loc) · 14 KB
/
are.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
package bg
import (
"encoding/binary"
"encoding/json"
"io"
"os"
)
type areaHeader struct {
Signature, Version [4]byte `json:"-"`
AreaWed RESREF
LastSaved uint32
AreaFlags uint32
AreaNorth RESREF
AreaNorthFlags uint32
AreaEast RESREF
AreaEastFlags uint32
AreaSouth RESREF
AreaSouthFlags uint32
AreaWest RESREF
AreaWestFlags uint32
Areatype uint16
Rainprobability uint16
SnowProability uint16
FogProbability uint16
LightningProbability uint16
WindSpeed uint16
}
type areaFileOffsets struct {
ActorsOffset uint32
ActorsCount uint16
RegionCount uint16
RegionOffset uint32
SpawnPointOffset uint32
SpawnPointCount uint32
EntranceOffset uint32
EntranceCount uint32
ContainerOffset uint32
ContainerCount uint16
ItemCount uint16
ItemOffset uint32
VertexOffset uint32
VertexCount uint16
AmbientCount uint16
AmbientOffset uint32
VariableOffset uint32
VariableCount uint16
TiledObjectFlagCount uint16
TiledObjectFlagOffset uint32
Script RESREF
ExploredSize uint32
ExploredOffset uint32
DoorsCount uint32
DoorsOffset uint32
AnimationCount uint32
AnimationOffset uint32
TiledObjectCount uint32
TiledObjectOffset uint32
SongEntriesOffset uint32
RestInterruptionsOffset uint32
AutomapOffset uint32
AutomapCount uint32
ProjectileTrapsOffset uint32
ProjectileTrapsCount uint32
RestMovieDay RESREF
RestMovieNight RESREF
Unknown [56]byte `json:"-"`
}
type areaActor struct {
Name LONGSTRING
CurrentX uint16
CurrentY uint16
DestX uint16
DestY uint16
Flags uint32
Type uint16
FirstResSlot byte
AlignByte byte `json:"-"`
AnimationType uint32
Facing uint16
AlignWord uint16 `json:"-"`
ExpirationTime uint32
HuntingRange uint16
FollowRange uint16
TimeOfDayVisible uint32
NumberTimesTalkedTo uint32
Dialog RESREF
OverrideScript RESREF
GeneralScript RESREF
ClassScript RESREF
RaceScript RESREF
DefaultScript RESREF
SpecificScript RESREF
CreatureData RESREF
CreatureOffset uint32 `json:"-"`
CreatureSize uint32 `json:"-"`
Unused [32]uint32 `json:"-"`
}
type areaRegion struct {
Name LONGSTRING
Type uint16
BoundingLeft uint16
BoundingTop uint16
BoundingRight uint16
BoundingBottom uint16
VertexCount uint16
VertexOffset uint32
TriggerValue uint32
CursorType uint32
Destination RESREF
EntranceName LONGSTRING
Flags uint32
InformationText uint32
TrapDetectionDifficulty uint16
TrapDisarmingDifficulty uint16
TrapActivated uint16
TrapDetected uint16
TrapOriginX uint16
TrapOriginY uint16
KeyItem RESREF
RegionScript RESREF
TransitionWalkToX uint16
TransitionWalkToY uint16
Unused [15]uint32 `json:"-"`
}
type areaSpawnPoint struct {
Name LONGSTRING
CoordX uint16
CoordY uint16
RandomCreatures [10]RESREF
RandomCreatureCount uint16
Difficulty uint16
SpawnRate uint16
Flags uint16
LifeSpan uint32
HuntingRange uint32
FollowRange uint32
MaxTypeNum uint32
Activated uint16
TimeOfDay uint32
ProbabilityDay uint16
ProbabilityNight uint16
Unused [14]uint32 `json:"-"`
}
type areaEntrance struct {
Name LONGSTRING
CoordX uint16
CoordY uint16
Orientation uint16
Unused [66]byte `json:"-"`
}
type areaContainer struct {
Name LONGSTRING
CoordX uint16
CoordY uint16
Type uint16
LockDifficulty uint16
Flags uint32
TrapDetectionDifficulty uint16
TrapRemovalDifficulty uint16
ContainerTrapped uint16
TrapDetected uint16
TrapLaunchX uint16
TrapLaunchY uint16
BoundingTopLeft uint16
BoundingTopRight uint16
BoundingBottomRight uint16
BoundingBottomLeft uint16
ItemOffset uint32
ItemCount uint32
TrapScript RESREF
VertexOffset uint32
VertexCount uint16
TriggerRange uint16
OwnedBy LONGSTRING
KeyType RESREF
BreakDifficulty uint32
NotPickableString uint32
Unused [14]uint32 `json:"-"`
}
type areaItem struct {
Resource RESREF
Expiration uint16
UsageCount [3]uint16
Flags uint32
}
type areaVertex struct {
Coordinate uint16
}
type areaAmbient struct {
Name LONGSTRING
CoordinateX uint16
CoordinateY uint16
Range uint16
Alignment1 uint16 `json:"-"`
PitchVariance uint32
VolumeVariance uint16
Volume uint16
Sounds [10]RESREF
SoundCount uint16
Alignment2 uint16 `json:"-"`
Period uint32
PeriodVariance uint32
TimeOfDayActive uint32
Flags uint32
Unused [16]uint32 `json:"-"`
}
type areaVariable struct {
Name LONGSTRING
Type uint16
ResRefType uint16
DWValue uint32
IntValue int32
FloatValue float64
ScriptName LONGSTRING
}
type areaDoor struct {
Name LONGSTRING
DoorID RESREF
Flags uint32
OpenDoorVertexOffset uint32 `json:"-"`
OpenDoorVertexCount uint16 `json:"-"`
ClosedDoorVertexCount uint16 `json:"-"`
CloseDoorVertexOffset uint32 `json:"-"`
OpenBoundingLeft uint16
OpenBoundingTop uint16
OpenBoundingRight uint16
OpenBoundingBottom uint16
ClosedBoundingLeft uint16
ClosedBoundingTop uint16
ClosedBoundingRight uint16
ClosedBoundingBottom uint16
OpenBlockVertexOffset uint32 `json:"-"`
OpenBlockVertexCount uint16 `json:"-"`
ClosedBlockVertexCount uint16 `json:"-"`
ClosedBlockVertexOffset uint32 `json:"-"`
HitPoints uint16
ArmorClass uint16
OpenSound RESREF
ClosedSound RESREF
CursorType uint32
TrapDetectionDifficulty uint16
TrapRemovalDifficulty uint16
DoorIsTrapped uint16
TrapDetected uint16
TrapLaunchTargetX uint16
TrapLaunchTargetY uint16
KeyItem RESREF
DoorScript RESREF
DetectionDifficulty uint32
LockDifficulty uint32
WalkToX1 uint16
WalkToY1 uint16
WalkToX2 uint16
WalkToY2 uint16
NotPickableString uint32
TriggerName LONGSTRING
Unused [3]uint32 `json:"-"`
}
type areaAnimation struct {
Name LONGSTRING
CoordX uint16
CoordY uint16
TimeOfDayVisible uint32
Animation RESREF
BamSequence uint16
BamFrame uint16
Flags uint32
Height int16
Translucency uint16
StartFrameRane uint16
Probability byte
Period byte
Palette RESREF
Unused uint32 `json:"-"`
}
type areaMapNote struct {
CoordX uint16
CoordY uint16
Note uint32
Flags uint32
Id uint32
Unused [9]uint32
}
type areaTiledObject struct {
Name LONGSTRING
TileID RESREF
Flags uint32
PrimarySearchSquareStart uint32
PrimarySearchSquareCount uint16
SecondarySearchSquareCount uint16
SecondarySearcHSquareStart uint32
Unused [12]uint32 `json:"-"`
}
type areaProjectileTrap struct {
Projectile RESREF
EffectBlockOffset uint32
EffectBlockSize uint16
MissileId uint16
DelayCount uint16
RepetitionCount uint16
CoordX uint16
CoordY uint16
CoordZ uint16
TargetType byte
PortraitNum byte
}
type areaSong struct {
DaySong uint32
NightSong uint32
WinSong uint32
BattleSong uint32
LoseSong uint32
AltMusic0 uint32
AltMusic1 uint32
AltMusic2 uint32
AltMusic3 uint32
AltMusic4 uint32
DayAmbient RESREF
DayAmbientExtended RESREF
DayAmbientVolume uint32
NightAmbient RESREF
NightAmbientExtended RESREF
NightAmbientVolume uint32
Unused [16]uint32 `json:"-"`
}
type areaRestEncounter struct {
Name LONGSTRING
RandomCreatureString [10]uint32
RandomCreature [10]RESREF
RandomCreatureNum uint16
Difficulty uint16
LifeSpan uint32
HuntingRange uint16
FollowRange uint16
MaxTypeNum uint16
Activated uint16
ProbabilityDay uint16
ProbabilityNight uint16
Unused [14]uint32 `json:"-"`
}
type Area struct {
Header areaHeader
Offsets areaFileOffsets `json:"-"`
Actors []areaActor
Regions []areaRegion
SpawnPoints []areaSpawnPoint
Entrances []areaEntrance
Containers []areaContainer
Items []areaItem
Vertices []areaVertex
Ambients []areaAmbient
Variables []areaVariable
ExploredBitmask []byte
Doors []areaDoor
Animations []areaAnimation
MapNotes []areaMapNote
TiledObjects []areaTiledObject
Traps []areaProjectileTrap
Song areaSong
RestInterruption areaRestEncounter
}
func OpenArea(r io.ReadSeeker) (*Area, error) {
area := Area{}
err := binary.Read(r, binary.LittleEndian, &area.Header)
if err != nil {
return nil, err
}
err = binary.Read(r, binary.LittleEndian, &area.Offsets)
if err != nil {
return nil, err
}
area.Actors = make([]areaActor, area.Offsets.ActorsCount)
r.Seek(int64(area.Offsets.ActorsOffset), os.SEEK_SET)
err = binary.Read(r, binary.LittleEndian, &area.Actors)
if err != nil {
return nil, err
}
area.Regions = make([]areaRegion, area.Offsets.RegionCount)
r.Seek(int64(area.Offsets.RegionOffset), os.SEEK_SET)
err = binary.Read(r, binary.LittleEndian, &area.Regions)
if err != nil {
return nil, err
}
area.SpawnPoints = make([]areaSpawnPoint, area.Offsets.SpawnPointCount)
r.Seek(int64(area.Offsets.SpawnPointOffset), os.SEEK_SET)
err = binary.Read(r, binary.LittleEndian, &area.SpawnPoints)
if err != nil {
return nil, err
}
area.Entrances = make([]areaEntrance, area.Offsets.EntranceCount)
r.Seek(int64(area.Offsets.EntranceOffset), os.SEEK_SET)
err = binary.Read(r, binary.LittleEndian, &area.Entrances)
if err != nil {
return nil, err
}
area.Containers = make([]areaContainer, area.Offsets.ContainerCount)
r.Seek(int64(area.Offsets.ContainerOffset), os.SEEK_SET)
err = binary.Read(r, binary.LittleEndian, &area.Containers)
if err != nil {
return nil, err
}
area.Items = make([]areaItem, area.Offsets.ItemCount)
r.Seek(int64(area.Offsets.ItemOffset), os.SEEK_SET)
err = binary.Read(r, binary.LittleEndian, &area.Items)
if err != nil {
return nil, err
}
area.Vertices = make([]areaVertex, area.Offsets.VertexCount)
r.Seek(int64(area.Offsets.VertexOffset), os.SEEK_SET)
err = binary.Read(r, binary.LittleEndian, &area.Vertices)
if err != nil {
return nil, err
}
area.Ambients = make([]areaAmbient, area.Offsets.AmbientCount)
r.Seek(int64(area.Offsets.AmbientOffset), os.SEEK_SET)
err = binary.Read(r, binary.LittleEndian, &area.Ambients)
if err != nil {
return nil, err
}
area.Variables = make([]areaVariable, area.Offsets.VariableCount)
r.Seek(int64(area.Offsets.VariableOffset), os.SEEK_SET)
err = binary.Read(r, binary.LittleEndian, &area.Variables)
if err != nil {
return nil, err
}
area.ExploredBitmask = make([]byte, area.Offsets.ExploredSize)
r.Seek(int64(area.Offsets.VariableOffset), os.SEEK_SET)
err = binary.Read(r, binary.LittleEndian, &area.ExploredBitmask)
if err != nil {
return nil, err
}
area.Doors = make([]areaDoor, area.Offsets.DoorsCount)
r.Seek(int64(area.Offsets.DoorsOffset), os.SEEK_SET)
err = binary.Read(r, binary.LittleEndian, &area.Doors)
if err != nil {
return nil, err
}
area.Animations = make([]areaAnimation, area.Offsets.AnimationCount)
r.Seek(int64(area.Offsets.AnimationOffset), os.SEEK_SET)
err = binary.Read(r, binary.LittleEndian, &area.Animations)
if err != nil {
return nil, err
}
area.MapNotes = make([]areaMapNote, area.Offsets.AutomapCount)
r.Seek(int64(area.Offsets.AutomapOffset), os.SEEK_SET)
err = binary.Read(r, binary.LittleEndian, &area.MapNotes)
if err != nil {
return nil, err
}
area.TiledObjects = make([]areaTiledObject, area.Offsets.TiledObjectCount)
r.Seek(int64(area.Offsets.TiledObjectOffset), os.SEEK_SET)
err = binary.Read(r, binary.LittleEndian, &area.TiledObjects)
if err != nil {
return nil, err
}
area.Traps = make([]areaProjectileTrap, area.Offsets.ProjectileTrapsCount)
r.Seek(int64(area.Offsets.ProjectileTrapsOffset), os.SEEK_SET)
err = binary.Read(r, binary.LittleEndian, &area.Traps)
if err != nil {
return nil, err
}
r.Seek(int64(area.Offsets.SongEntriesOffset), os.SEEK_SET)
err = binary.Read(r, binary.LittleEndian, &area.Song)
if err != nil {
return nil, err
}
r.Seek(int64(area.Offsets.RestInterruptionsOffset), os.SEEK_SET)
err = binary.Read(r, binary.LittleEndian, &area.RestInterruption)
if err != nil {
return nil, err
}
return &area, nil
}
func (are *Area) WriteJson(w io.Writer) error {
bytes, err := json.MarshalIndent(are, "", "\t")
if err != nil {
return err
}
_, err = w.Write(bytes)
return err
}