wc3maptranslator 3.0.3 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.codeclimate.yml +0 -1
- package/.eslintignore +0 -1
- package/.github/workflows/codeql-analysis.yml +54 -0
- package/.nycrc +1 -2
- package/.travis.yml +1 -2
- package/CHANGELOG.md +78 -0
- package/LICENSE.md +23 -0
- package/README.md +68 -75
- package/index.js +11 -15
- package/index.ts +12 -30
- package/lib/CommonInterfaces.ts +22 -0
- package/lib/HexBuffer.ts +11 -14
- package/lib/W3Buffer.ts +7 -3
- package/lib/translators/CamerasTranslator.ts +36 -41
- package/lib/translators/DoodadsTranslator.ts +57 -55
- package/lib/translators/ImportsTranslator.ts +29 -31
- package/lib/translators/InfoTranslator.ts +252 -204
- package/lib/translators/{object/ObjectsTranslator.ts → ObjectsTranslator.ts} +84 -82
- package/lib/translators/RegionsTranslator.ts +40 -58
- package/lib/translators/SoundsTranslator.ts +112 -96
- package/lib/translators/StringsTranslator.ts +23 -49
- package/lib/translators/TerrainTranslator.ts +166 -97
- package/lib/translators/UnitsTranslator.ts +98 -97
- package/lib/translators/index.ts +0 -1
- package/package.json +23 -16
- package/test/.mocharc.json +4 -0
- package/test/HexBufferTest.ts +11 -15
- package/test/TranslatorReversion.ts +104 -115
- package/test/W3BufferTest.ts +19 -13
- package/test/data/cameras.json +16 -0
- package/test/data/doodads.json +2730 -0
- package/test/data/imports.json +386 -0
- package/test/data/info.json +250 -0
- package/test/data/obj-abilities.json +4892 -0
- package/test/data/obj-buffs.json +38 -0
- package/test/data/obj-destructables.json +31 -0
- package/test/data/obj-doodads.json +38 -0
- package/test/data/obj-items.json +31 -0
- package/test/data/obj-units.json +40 -0
- package/test/data/obj-upgrades.json +38 -0
- package/test/data/regions.json +206 -0
- package/test/data/sounds.json +50 -0
- package/test/data/strings.json +115 -0
- package/test/data/terrain.json +1 -0
- package/test/data/units.json +452 -0
- package/test/data/war3map.doo +0 -0
- package/test/data/war3map.imp +0 -0
- package/test/data/war3map.j +3442 -0
- package/test/data/war3map.shd +0 -0
- package/test/data/war3map.w3a +0 -0
- package/test/data/war3map.w3b +0 -0
- package/test/data/war3map.w3c +0 -0
- package/test/data/war3map.w3d +0 -0
- package/test/data/war3map.w3e +0 -0
- package/test/data/war3map.w3h +0 -0
- package/test/data/war3map.w3i +0 -0
- package/test/data/war3map.w3q +0 -0
- package/test/data/war3map.w3r +0 -0
- package/test/data/war3map.w3s +0 -0
- package/test/data/war3map.w3t +0 -0
- package/test/data/war3map.w3u +0 -0
- package/test/data/war3map.wts +631 -0
- package/test/data/war3mapUnits.doo +0 -0
- package/examples/index.js +0 -123
- package/examples/index.ts +0 -134
- package/examples/json/cameras.json +0 -16
- package/examples/json/doodads.json +0 -28499
- package/examples/json/imports.json +0 -10
- package/examples/json/info.json +0 -111
- package/examples/json/object-abilities.json +0 -31
- package/examples/json/object-buffs.json +0 -24
- package/examples/json/object-destructables.json +0 -31
- package/examples/json/object-doodads.json +0 -24
- package/examples/json/object-items.json +0 -45
- package/examples/json/object-units.json +0 -45
- package/examples/json/object-upgrades.json +0 -31
- package/examples/json/regions.json +0 -36
- package/examples/json/sounds.json +0 -46
- package/examples/json/strings.json +0 -83
- package/examples/json/terrain.json +0 -46633
- package/examples/json/units.json +0 -332
- package/examples/package.json +0 -17
- package/examples/tsconfig.json +0 -27
- package/examples/war/war3map.doo +0 -0
- package/examples/war/war3map.imp +0 -0
- package/examples/war/war3map.w3a +0 -0
- package/examples/war/war3map.w3b +0 -0
- package/examples/war/war3map.w3c +0 -0
- package/examples/war/war3map.w3d +0 -0
- package/examples/war/war3map.w3e +0 -0
- package/examples/war/war3map.w3h +0 -0
- package/examples/war/war3map.w3i +0 -0
- package/examples/war/war3map.w3q +0 -0
- package/examples/war/war3map.w3r +0 -0
- package/examples/war/war3map.w3s +0 -0
- package/examples/war/war3map.w3t +0 -0
- package/examples/war/war3map.w3u +0 -0
- package/examples/war/war3map.wts +0 -99
- package/lib/translators/index.js +0 -16
- package/test/mocha.opts +0 -4
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { HexBuffer } from '../HexBuffer';
|
|
2
2
|
import { W3Buffer } from '../W3Buffer';
|
|
3
|
+
import { WarResult, JsonResult } from '../CommonInterfaces'
|
|
3
4
|
|
|
4
5
|
interface Map {
|
|
5
6
|
name: string;
|
|
@@ -11,28 +12,38 @@ interface Map {
|
|
|
11
12
|
mainTileType: string;
|
|
12
13
|
}
|
|
13
14
|
|
|
15
|
+
interface GameVersion {
|
|
16
|
+
major: number;
|
|
17
|
+
minor: number;
|
|
18
|
+
patch: number;
|
|
19
|
+
build: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
14
22
|
interface Camera {
|
|
15
23
|
bounds: number[];
|
|
16
24
|
complements: number[];
|
|
17
25
|
}
|
|
18
26
|
|
|
19
27
|
interface MapFlags {
|
|
20
|
-
hideMinimapInPreview: boolean;
|
|
21
|
-
modifyAllyPriorities: boolean;
|
|
22
|
-
isMeleeMap: boolean;
|
|
23
|
-
|
|
28
|
+
hideMinimapInPreview: boolean; // 0x0001: 1=hide minimap in preview screens
|
|
29
|
+
modifyAllyPriorities: boolean; // 0x0002: 1=modify ally priorities
|
|
30
|
+
isMeleeMap: boolean; // 0x0004: 1=melee map
|
|
31
|
+
// 0x0008: 1=playable map size was large and has never been reduced to medium (?)
|
|
24
32
|
maskedPartiallyVisible: boolean; // 0x0010: 1=masked area are partially visible
|
|
25
|
-
fixedPlayerSetting: boolean;
|
|
26
|
-
useCustomForces: boolean;
|
|
27
|
-
useCustomTechtree: boolean;
|
|
28
|
-
useCustomAbilities: boolean;
|
|
29
|
-
useCustomUpgrades: boolean;
|
|
30
|
-
|
|
33
|
+
fixedPlayerSetting: boolean; // 0x0020: 1=fixed player setting for custom forces
|
|
34
|
+
useCustomForces: boolean; // 0x0040: 1=use custom forces
|
|
35
|
+
useCustomTechtree: boolean; // 0x0080: 1=use custom techtree
|
|
36
|
+
useCustomAbilities: boolean; // 0x0100: 1=use custom abilities
|
|
37
|
+
useCustomUpgrades: boolean; // 0x0200: 1=use custom upgrades
|
|
38
|
+
// 0x0400: 1=map properties menu opened at least once since map creation (?)
|
|
31
39
|
waterWavesOnCliffShores: boolean; // 0x0800: 1=show water waves on cliff shores
|
|
32
40
|
waterWavesOnRollingShores: boolean; // 0x1000: 1=show water waves on rolling shores
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
// 0x2000: 1=unknown
|
|
42
|
+
// 0x4000: 1=unknown
|
|
43
|
+
useItemClassificationSystem: boolean; // 0x8000: 1=use item classification system
|
|
44
|
+
enableWaterTinting: boolean; // 0x10000
|
|
45
|
+
useAccurateProbabilityForCalculations: boolean; // 0x20000
|
|
46
|
+
useCustomAbilitySkins: boolean; // 0x40000
|
|
36
47
|
}
|
|
37
48
|
|
|
38
49
|
interface LoadingScreen {
|
|
@@ -43,8 +54,14 @@ interface LoadingScreen {
|
|
|
43
54
|
subtitle: string;
|
|
44
55
|
}
|
|
45
56
|
|
|
57
|
+
enum FogType {
|
|
58
|
+
Linear = 0,
|
|
59
|
+
Exponential1 = 1,
|
|
60
|
+
Exponential2 = 2
|
|
61
|
+
}
|
|
62
|
+
|
|
46
63
|
interface Fog {
|
|
47
|
-
type:
|
|
64
|
+
type: FogType;
|
|
48
65
|
startHeight: number;
|
|
49
66
|
endHeight: number;
|
|
50
67
|
density: number;
|
|
@@ -65,7 +82,10 @@ interface Prologue {
|
|
|
65
82
|
|
|
66
83
|
interface Info {
|
|
67
84
|
saves: number;
|
|
85
|
+
gameVersion: GameVersion;
|
|
68
86
|
editorVersion: number;
|
|
87
|
+
scriptLanguage: ScriptLanguage;
|
|
88
|
+
supportedModes: SupportedModes;
|
|
69
89
|
map: Map;
|
|
70
90
|
camera: Camera;
|
|
71
91
|
prologue: Prologue;
|
|
@@ -85,26 +105,10 @@ interface PlayerStartingPosition {
|
|
|
85
105
|
fixed: boolean;
|
|
86
106
|
}
|
|
87
107
|
|
|
88
|
-
enum PlayerType {
|
|
89
|
-
// 1=Human, 2=Computer, 3=Neutral, 4=Rescuable
|
|
90
|
-
'Human' = 1,
|
|
91
|
-
'Computer',
|
|
92
|
-
'Neutral',
|
|
93
|
-
'Rescuable'
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
enum PlayerRace {
|
|
97
|
-
// 1=Human, 2=Orc, 3=Undead, 4=Night Elf
|
|
98
|
-
'Human' = 1,
|
|
99
|
-
'Orc',
|
|
100
|
-
'Undead',
|
|
101
|
-
'NightElf'
|
|
102
|
-
}
|
|
103
|
-
|
|
104
108
|
interface Player {
|
|
105
109
|
playerNum: number;
|
|
106
|
-
type:
|
|
107
|
-
race:
|
|
110
|
+
type: number; // 1=Human, 2=Computer, 3=Neutral, 4=Rescuable
|
|
111
|
+
race: number; // 1=Human, 2=Orc, 3=Undead, 4=Night Elf
|
|
108
112
|
|
|
109
113
|
name: string;
|
|
110
114
|
startingPos: PlayerStartingPosition;
|
|
@@ -125,39 +129,50 @@ interface Force {
|
|
|
125
129
|
name: string;
|
|
126
130
|
}
|
|
127
131
|
|
|
128
|
-
|
|
132
|
+
enum ScriptLanguage {
|
|
133
|
+
JASS = 0,
|
|
134
|
+
Lua = 1
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
enum SupportedModes {
|
|
138
|
+
SD = 1,
|
|
139
|
+
HD = 2,
|
|
140
|
+
Both = 3
|
|
141
|
+
}
|
|
129
142
|
|
|
130
|
-
|
|
131
|
-
private _outBufferToJSON: W3Buffer;
|
|
143
|
+
export abstract class InfoTranslator {
|
|
132
144
|
|
|
133
|
-
|
|
145
|
+
public static jsonToWar(infoJson: Info): WarResult {
|
|
146
|
+
const outBufferToWar = new HexBuffer();
|
|
134
147
|
|
|
135
|
-
|
|
136
|
-
|
|
148
|
+
outBufferToWar.addInt(31); // file version, 0x1F
|
|
149
|
+
outBufferToWar.addInt(infoJson.saves || 0);
|
|
150
|
+
outBufferToWar.addInt(infoJson.editorVersion || 0);
|
|
137
151
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
152
|
+
outBufferToWar.addInt(infoJson.gameVersion.major);
|
|
153
|
+
outBufferToWar.addInt(infoJson.gameVersion.minor);
|
|
154
|
+
outBufferToWar.addInt(infoJson.gameVersion.patch);
|
|
155
|
+
outBufferToWar.addInt(infoJson.gameVersion.build);
|
|
141
156
|
|
|
142
157
|
// Map information
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
158
|
+
outBufferToWar.addString(infoJson.map.name);
|
|
159
|
+
outBufferToWar.addString(infoJson.map.author);
|
|
160
|
+
outBufferToWar.addString(infoJson.map.description);
|
|
161
|
+
outBufferToWar.addString(infoJson.map.recommendedPlayers);
|
|
147
162
|
|
|
148
163
|
// Camera bounds (8 floats total)
|
|
149
164
|
for (let cbIndex = 0; cbIndex < 8; cbIndex++) {
|
|
150
|
-
|
|
165
|
+
outBufferToWar.addFloat(infoJson.camera.bounds[cbIndex]);
|
|
151
166
|
}
|
|
152
167
|
|
|
153
168
|
// Camera complements (4 floats total)
|
|
154
169
|
for (let ccIndex = 0; ccIndex < 4; ccIndex++) {
|
|
155
|
-
|
|
170
|
+
outBufferToWar.addInt(infoJson.camera.complements[ccIndex]);
|
|
156
171
|
}
|
|
157
172
|
|
|
158
173
|
// Playable area
|
|
159
|
-
|
|
160
|
-
|
|
174
|
+
outBufferToWar.addInt(infoJson.map.playableArea.width);
|
|
175
|
+
outBufferToWar.addInt(infoJson.map.playableArea.height);
|
|
161
176
|
|
|
162
177
|
/*
|
|
163
178
|
* Flags
|
|
@@ -167,119 +182,132 @@ export class InfoTranslator {
|
|
|
167
182
|
if (infoJson.map.flags.hideMinimapInPreview) flags |= 0x0001; // hide minimap in preview screens
|
|
168
183
|
if (infoJson.map.flags.modifyAllyPriorities) flags |= 0x0002; // modify ally priorities
|
|
169
184
|
if (infoJson.map.flags.isMeleeMap) flags |= 0x0004; // melee map
|
|
170
|
-
|
|
185
|
+
// 0x0008 - unknown; // playable map size was large and never reduced to medium (?)
|
|
171
186
|
if (infoJson.map.flags.maskedPartiallyVisible) flags |= 0x0010; // masked area are partially visible
|
|
172
187
|
if (infoJson.map.flags.fixedPlayerSetting) flags |= 0x0020; // fixed player setting for custom forces
|
|
173
188
|
if (infoJson.map.flags.useCustomForces) flags |= 0x0040; // use custom forces
|
|
174
189
|
if (infoJson.map.flags.useCustomTechtree) flags |= 0x0080; // use custom techtree
|
|
175
190
|
if (infoJson.map.flags.useCustomAbilities) flags |= 0x0100; // use custom abilities
|
|
176
191
|
if (infoJson.map.flags.useCustomUpgrades) flags |= 0x0200; // use custom upgrades
|
|
177
|
-
|
|
192
|
+
// 0x0400 - unknown; // map properties menu opened at least once since map creation (?)
|
|
178
193
|
if (infoJson.map.flags.waterWavesOnCliffShores) flags |= 0x0800; // show water waves on cliff shores
|
|
179
194
|
if (infoJson.map.flags.waterWavesOnRollingShores) flags |= 0x1000; // show water waves on rolling shores
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if (infoJson.map.flags.
|
|
195
|
+
// 0x2000: 1=unknown
|
|
196
|
+
// 0x4000: 1=unknown
|
|
197
|
+
if (infoJson.map.flags.useItemClassificationSystem) flags |= 0x8000
|
|
198
|
+
if (infoJson.map.flags.enableWaterTinting) flags |= 0x10000
|
|
199
|
+
if (infoJson.map.flags.useAccurateProbabilityForCalculations) flags |= 0x20000
|
|
200
|
+
if (infoJson.map.flags.useCustomAbilitySkins) flags |= 0x40000
|
|
183
201
|
}
|
|
184
202
|
|
|
185
|
-
|
|
203
|
+
// Unknown, but these seem to always be on, at least for default maps
|
|
204
|
+
flags |= 0x8000;
|
|
205
|
+
flags |= 0x4000;
|
|
206
|
+
flags |= 0x0400;
|
|
207
|
+
|
|
208
|
+
outBufferToWar.addInt(flags); // Add flags
|
|
186
209
|
|
|
187
210
|
// Map main ground type
|
|
188
|
-
|
|
211
|
+
outBufferToWar.addChar(infoJson.map.mainTileType);
|
|
189
212
|
|
|
190
213
|
// Loading screen
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
214
|
+
outBufferToWar.addInt(infoJson.loadingScreen.background);
|
|
215
|
+
outBufferToWar.addString(infoJson.loadingScreen.path);
|
|
216
|
+
outBufferToWar.addString(infoJson.loadingScreen.text);
|
|
217
|
+
outBufferToWar.addString(infoJson.loadingScreen.title);
|
|
218
|
+
outBufferToWar.addString(infoJson.loadingScreen.subtitle);
|
|
196
219
|
|
|
197
220
|
// Use game data set (Unsupported)
|
|
198
|
-
|
|
221
|
+
outBufferToWar.addInt(0);
|
|
199
222
|
|
|
200
223
|
// Prologue
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
224
|
+
outBufferToWar.addString(infoJson.prologue.path);
|
|
225
|
+
outBufferToWar.addString(infoJson.prologue.text);
|
|
226
|
+
outBufferToWar.addString(infoJson.prologue.title);
|
|
227
|
+
outBufferToWar.addString(infoJson.prologue.subtitle);
|
|
205
228
|
|
|
206
229
|
// Fog
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
230
|
+
outBufferToWar.addInt(infoJson.fog.type);
|
|
231
|
+
outBufferToWar.addFloat(infoJson.fog.startHeight);
|
|
232
|
+
outBufferToWar.addFloat(infoJson.fog.endHeight);
|
|
233
|
+
outBufferToWar.addFloat(infoJson.fog.density);
|
|
234
|
+
outBufferToWar.addByte(infoJson.fog.color[0]);
|
|
235
|
+
outBufferToWar.addByte(infoJson.fog.color[1]);
|
|
236
|
+
outBufferToWar.addByte(infoJson.fog.color[2]);
|
|
237
|
+
outBufferToWar.addByte(255); // Fog alpha - unsupported
|
|
215
238
|
|
|
216
239
|
// Misc.
|
|
217
240
|
// If globalWeather is not defined or is set to 'none', use 0 sentinel value, else add char[4]
|
|
218
241
|
if (!infoJson.globalWeather || infoJson.globalWeather.toLowerCase() === 'none') {
|
|
219
|
-
|
|
242
|
+
outBufferToWar.addInt(0);
|
|
220
243
|
} else {
|
|
221
|
-
|
|
244
|
+
outBufferToWar.addChars(infoJson.globalWeather); // char[4] - lookup table
|
|
222
245
|
}
|
|
223
|
-
|
|
224
|
-
|
|
246
|
+
outBufferToWar.addString(infoJson.customSoundEnvironment || '');
|
|
247
|
+
outBufferToWar.addChar(infoJson.customLightEnv || 'L');
|
|
225
248
|
|
|
226
249
|
// Custom water tinting
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
250
|
+
outBufferToWar.addByte(infoJson.water[0]);
|
|
251
|
+
outBufferToWar.addByte(infoJson.water[1]);
|
|
252
|
+
outBufferToWar.addByte(infoJson.water[2]);
|
|
253
|
+
outBufferToWar.addByte(255); // Water alpha - unsupported
|
|
254
|
+
|
|
255
|
+
outBufferToWar.addInt(infoJson.scriptLanguage);
|
|
256
|
+
outBufferToWar.addInt(infoJson.supportedModes);
|
|
257
|
+
outBufferToWar.addInt(0); // unknown
|
|
231
258
|
|
|
232
259
|
// Players
|
|
233
|
-
|
|
260
|
+
outBufferToWar.addInt(infoJson.players.length);
|
|
234
261
|
infoJson.players.forEach((player) => {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
262
|
+
outBufferToWar.addInt(player.playerNum);
|
|
263
|
+
outBufferToWar.addInt(player.type);
|
|
264
|
+
outBufferToWar.addInt(player.race);
|
|
265
|
+
outBufferToWar.addInt(player.startingPos.fixed ? 1 : 0);
|
|
266
|
+
outBufferToWar.addString(player.name);
|
|
267
|
+
outBufferToWar.addFloat(player.startingPos.x);
|
|
268
|
+
outBufferToWar.addFloat(player.startingPos.y);
|
|
269
|
+
outBufferToWar.addInt(0); // ally low prio flags - unsupported
|
|
270
|
+
outBufferToWar.addInt(0); // ally high prio flags - unsupported
|
|
271
|
+
outBufferToWar.addInt(0); // enemy low prio flags - unsupported
|
|
272
|
+
outBufferToWar.addInt(0); // enemy high prio flags - unsupported
|
|
244
273
|
});
|
|
245
274
|
|
|
246
275
|
// Forces
|
|
247
|
-
|
|
276
|
+
outBufferToWar.addInt(infoJson.forces.length);
|
|
248
277
|
infoJson.forces.forEach((force) => {
|
|
249
278
|
// Calculate flags
|
|
250
279
|
let forceFlags = 0;
|
|
251
280
|
if (force.flags.allied) forceFlags |= 0x0001;
|
|
252
281
|
if (force.flags.alliedVictory) forceFlags |= 0x0002;
|
|
253
|
-
|
|
282
|
+
// Skip 0x0004
|
|
283
|
+
if (force.flags.shareVision) forceFlags |= 0x0008;
|
|
254
284
|
if (force.flags.shareUnitControl) forceFlags |= 0x0010;
|
|
255
285
|
if (force.flags.shareAdvUnitControl) forceFlags |= 0x0020;
|
|
256
286
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
this._outBufferToWar.addByte(255); // force players - unsupported
|
|
261
|
-
this._outBufferToWar.addByte(255); // force players - unsupported
|
|
262
|
-
this._outBufferToWar.addString(force.name, true);
|
|
287
|
+
outBufferToWar.addInt(forceFlags);
|
|
288
|
+
outBufferToWar.addInt(force.players);
|
|
289
|
+
outBufferToWar.addString(force.name);
|
|
263
290
|
});
|
|
264
291
|
|
|
265
292
|
// Upgrades - unsupported
|
|
266
|
-
|
|
293
|
+
outBufferToWar.addInt(0);
|
|
267
294
|
|
|
268
295
|
// Tech availability - unsupported
|
|
269
|
-
|
|
296
|
+
outBufferToWar.addInt(0);
|
|
270
297
|
|
|
271
298
|
// Unit table (random) - unsupported
|
|
272
|
-
|
|
299
|
+
outBufferToWar.addInt(0);
|
|
273
300
|
|
|
274
301
|
// Item table (random) - unsupported
|
|
275
|
-
|
|
302
|
+
outBufferToWar.addInt(0);
|
|
276
303
|
|
|
277
304
|
return {
|
|
278
305
|
errors: [],
|
|
279
|
-
buffer:
|
|
306
|
+
buffer: outBufferToWar.getBuffer()
|
|
280
307
|
};
|
|
281
308
|
}
|
|
282
|
-
|
|
309
|
+
|
|
310
|
+
public static warToJson(buffer: Buffer): JsonResult<Info> {
|
|
283
311
|
const result: Info = {
|
|
284
312
|
map: {
|
|
285
313
|
name: '',
|
|
@@ -293,21 +321,22 @@ export class InfoTranslator {
|
|
|
293
321
|
mainTileType: '',
|
|
294
322
|
flags: {
|
|
295
323
|
hideMinimapInPreview: false, // 0x0001: 1=hide minimap in preview screens
|
|
296
|
-
modifyAllyPriorities:
|
|
324
|
+
modifyAllyPriorities: true, // 0x0002: 1=modify ally priorities
|
|
297
325
|
isMeleeMap: false, // 0x0004: 1=melee map
|
|
298
|
-
|
|
326
|
+
// 0x0008: 1=playable map size was large and has never been reduced to medium (?)
|
|
299
327
|
maskedPartiallyVisible: false, // 0x0010: 1=masked area are partially visible
|
|
300
328
|
fixedPlayerSetting: false, // 0x0020: 1=fixed player setting for custom forces
|
|
301
329
|
useCustomForces: false, // 0x0040: 1=use custom forces
|
|
302
330
|
useCustomTechtree: false, // 0x0080: 1=use custom techtree
|
|
303
331
|
useCustomAbilities: false, // 0x0100: 1=use custom abilities
|
|
304
332
|
useCustomUpgrades: false, // 0x0200: 1=use custom upgrades
|
|
305
|
-
|
|
333
|
+
// 0x0400: 1=map properties menu opened at least once since map creation (?)
|
|
306
334
|
waterWavesOnCliffShores: false, // 0x0800: 1=show water waves on cliff shores
|
|
307
335
|
waterWavesOnRollingShores: false, // 0x1000: 1=show water waves on rolling shores
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
336
|
+
useItemClassificationSystem: false, // 0x8000: 1=use item classification system
|
|
337
|
+
enableWaterTinting: false, // 0x10000
|
|
338
|
+
useAccurateProbabilityForCalculations: false, // 0x20000
|
|
339
|
+
useCustomAbilitySkins: false // 0x40000
|
|
311
340
|
}
|
|
312
341
|
},
|
|
313
342
|
loadingScreen: {
|
|
@@ -322,7 +351,7 @@ export class InfoTranslator {
|
|
|
322
351
|
title: '',
|
|
323
352
|
subtitle: ''
|
|
324
353
|
}, fog: {
|
|
325
|
-
type:
|
|
354
|
+
type: FogType.Linear,
|
|
326
355
|
startHeight: 0,
|
|
327
356
|
endHeight: 0,
|
|
328
357
|
density: 0,
|
|
@@ -337,93 +366,110 @@ export class InfoTranslator {
|
|
|
337
366
|
],
|
|
338
367
|
saves: 0,
|
|
339
368
|
editorVersion: 0,
|
|
369
|
+
scriptLanguage: ScriptLanguage.JASS,
|
|
370
|
+
supportedModes: SupportedModes.Both,
|
|
371
|
+
gameVersion: {
|
|
372
|
+
major: 0,
|
|
373
|
+
minor: 0,
|
|
374
|
+
patch: 0,
|
|
375
|
+
build: 0
|
|
376
|
+
},
|
|
340
377
|
globalWeather: '',
|
|
341
378
|
customSoundEnvironment: '',
|
|
342
379
|
customLightEnv: '',
|
|
343
380
|
water: []
|
|
344
381
|
};
|
|
345
|
-
|
|
382
|
+
const outBufferToJSON = new W3Buffer(buffer);
|
|
383
|
+
|
|
384
|
+
const fileVersion = outBufferToJSON.readInt();
|
|
346
385
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
editorVersion = this._outBufferToJSON.readInt(); // editor version
|
|
386
|
+
result.saves = outBufferToJSON.readInt(),
|
|
387
|
+
result.editorVersion = outBufferToJSON.readInt();
|
|
350
388
|
|
|
351
|
-
result.
|
|
352
|
-
|
|
389
|
+
result.gameVersion = {
|
|
390
|
+
major: outBufferToJSON.readInt(),
|
|
391
|
+
minor: outBufferToJSON.readInt(),
|
|
392
|
+
patch: outBufferToJSON.readInt(),
|
|
393
|
+
build: outBufferToJSON.readInt()
|
|
394
|
+
};
|
|
353
395
|
|
|
354
|
-
result.map.name =
|
|
355
|
-
result.map.author =
|
|
356
|
-
result.map.description =
|
|
357
|
-
result.map.recommendedPlayers =
|
|
396
|
+
result.map.name = outBufferToJSON.readString();
|
|
397
|
+
result.map.author = outBufferToJSON.readString();
|
|
398
|
+
result.map.description = outBufferToJSON.readString();
|
|
399
|
+
result.map.recommendedPlayers = outBufferToJSON.readString();
|
|
358
400
|
|
|
359
401
|
result.camera.bounds = [
|
|
360
|
-
|
|
361
|
-
|
|
402
|
+
outBufferToJSON.readFloat(), outBufferToJSON.readFloat(), outBufferToJSON.readFloat(), outBufferToJSON.readFloat(),
|
|
403
|
+
outBufferToJSON.readFloat(), outBufferToJSON.readFloat(), outBufferToJSON.readFloat(), outBufferToJSON.readFloat()
|
|
362
404
|
];
|
|
363
405
|
|
|
364
406
|
result.camera.complements = [
|
|
365
|
-
|
|
407
|
+
outBufferToJSON.readInt(), outBufferToJSON.readInt(), outBufferToJSON.readInt(), outBufferToJSON.readInt()
|
|
366
408
|
];
|
|
367
409
|
|
|
368
410
|
result.map.playableArea = {
|
|
369
|
-
width:
|
|
370
|
-
height:
|
|
411
|
+
width: outBufferToJSON.readInt(),
|
|
412
|
+
height: outBufferToJSON.readInt()
|
|
371
413
|
};
|
|
372
414
|
|
|
373
|
-
const flags =
|
|
415
|
+
const flags = outBufferToJSON.readInt();
|
|
374
416
|
result.map.flags = {
|
|
375
|
-
hideMinimapInPreview: !!(flags &
|
|
376
|
-
modifyAllyPriorities: !!(flags &
|
|
377
|
-
isMeleeMap: !!(flags &
|
|
378
|
-
|
|
379
|
-
maskedPartiallyVisible: !!(flags &
|
|
380
|
-
fixedPlayerSetting: !!(flags &
|
|
381
|
-
useCustomForces: !!(flags &
|
|
382
|
-
useCustomTechtree: !!(flags &
|
|
383
|
-
useCustomAbilities: !!(flags &
|
|
384
|
-
useCustomUpgrades: !!(flags &
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
417
|
+
hideMinimapInPreview: !!(flags & 0x0001),
|
|
418
|
+
modifyAllyPriorities: !!(flags & 0x0002),
|
|
419
|
+
isMeleeMap: !!(flags & 0x0004),
|
|
420
|
+
// skip 0x008
|
|
421
|
+
maskedPartiallyVisible: !!(flags & 0x0010),
|
|
422
|
+
fixedPlayerSetting: !!(flags & 0x0020),
|
|
423
|
+
useCustomForces: !!(flags & 0x0040),
|
|
424
|
+
useCustomTechtree: !!(flags & 0x0080),
|
|
425
|
+
useCustomAbilities: !!(flags & 0x0100),
|
|
426
|
+
useCustomUpgrades: !!(flags & 0x0200),
|
|
427
|
+
waterWavesOnCliffShores: !!(flags & 0x0800),
|
|
428
|
+
waterWavesOnRollingShores: !!(flags & 0x1000),
|
|
429
|
+
// skip 0x2000
|
|
430
|
+
// skip 0x4000
|
|
431
|
+
useItemClassificationSystem: !!(flags & 0x8000),
|
|
432
|
+
enableWaterTinting: !!(flags & 0x10000),
|
|
433
|
+
useAccurateProbabilityForCalculations: !!(flags & 0x20000),
|
|
434
|
+
useCustomAbilitySkins: !!(flags & 0x40000)
|
|
391
435
|
};
|
|
392
436
|
|
|
393
|
-
result.map.mainTileType =
|
|
437
|
+
result.map.mainTileType = outBufferToJSON.readChars();
|
|
394
438
|
|
|
395
|
-
result.loadingScreen =
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
subtitle: this._outBufferToJSON.readString()
|
|
401
|
-
};
|
|
439
|
+
result.loadingScreen.background = outBufferToJSON.readInt();
|
|
440
|
+
result.loadingScreen.path = outBufferToJSON.readString();
|
|
441
|
+
result.loadingScreen.text = outBufferToJSON.readString();
|
|
442
|
+
result.loadingScreen.title = outBufferToJSON.readString();
|
|
443
|
+
result.loadingScreen.subtitle = outBufferToJSON.readString();
|
|
402
444
|
|
|
403
|
-
const gameDataSet =
|
|
445
|
+
const gameDataSet = outBufferToJSON.readInt(); // 0 = standard
|
|
404
446
|
|
|
405
447
|
result.prologue = {
|
|
406
|
-
path:
|
|
407
|
-
text:
|
|
408
|
-
title:
|
|
409
|
-
subtitle:
|
|
448
|
+
path: outBufferToJSON.readString(),
|
|
449
|
+
text: outBufferToJSON.readString(),
|
|
450
|
+
title: outBufferToJSON.readString(),
|
|
451
|
+
subtitle: outBufferToJSON.readString()
|
|
410
452
|
};
|
|
411
453
|
|
|
412
454
|
result.fog = {
|
|
413
|
-
type:
|
|
414
|
-
startHeight:
|
|
415
|
-
endHeight:
|
|
416
|
-
density:
|
|
417
|
-
color: [
|
|
455
|
+
type: outBufferToJSON.readInt(),
|
|
456
|
+
startHeight: outBufferToJSON.readFloat(),
|
|
457
|
+
endHeight: outBufferToJSON.readFloat(),
|
|
458
|
+
density: outBufferToJSON.readFloat(),
|
|
459
|
+
color: [outBufferToJSON.readByte(), outBufferToJSON.readByte(), outBufferToJSON.readByte(), outBufferToJSON.readByte()] // R G B A
|
|
418
460
|
};
|
|
419
461
|
|
|
420
|
-
result.globalWeather =
|
|
421
|
-
result.customSoundEnvironment =
|
|
422
|
-
result.customLightEnv =
|
|
423
|
-
result.water = [
|
|
462
|
+
result.globalWeather = outBufferToJSON.readChars(4);
|
|
463
|
+
result.customSoundEnvironment = outBufferToJSON.readString();
|
|
464
|
+
result.customLightEnv = outBufferToJSON.readChars();
|
|
465
|
+
result.water = [outBufferToJSON.readByte(), outBufferToJSON.readByte(), outBufferToJSON.readByte(), outBufferToJSON.readByte()]; // R G B A
|
|
466
|
+
|
|
467
|
+
result.scriptLanguage = outBufferToJSON.readInt();
|
|
468
|
+
result.supportedModes = outBufferToJSON.readInt();
|
|
469
|
+
outBufferToJSON.readInt(); // unknown
|
|
424
470
|
|
|
425
471
|
// Struct: players
|
|
426
|
-
const numPlayers =
|
|
472
|
+
const numPlayers = outBufferToJSON.readInt();
|
|
427
473
|
for (let i = 0; i < numPlayers; i++) {
|
|
428
474
|
const player: Player = {
|
|
429
475
|
name: '',
|
|
@@ -433,27 +479,29 @@ export class InfoTranslator {
|
|
|
433
479
|
race: 0
|
|
434
480
|
};
|
|
435
481
|
|
|
436
|
-
player.playerNum =
|
|
437
|
-
player.type =
|
|
438
|
-
player.race =
|
|
482
|
+
player.playerNum = outBufferToJSON.readInt();
|
|
483
|
+
player.type = outBufferToJSON.readInt(); // 1=Human, 2=Computer, 3=Neutral, 4=Rescuable
|
|
484
|
+
player.race = outBufferToJSON.readInt(); // 1=Human, 2=Orc, 3=Undead, 4=Night Elf
|
|
439
485
|
|
|
440
|
-
const isPlayerStartPositionFixed: boolean =
|
|
486
|
+
const isPlayerStartPositionFixed: boolean = outBufferToJSON.readInt() === 1; // 00000001 = fixed start position
|
|
441
487
|
|
|
442
|
-
player.name =
|
|
488
|
+
player.name = outBufferToJSON.readString();
|
|
443
489
|
player.startingPos = {
|
|
444
|
-
x:
|
|
445
|
-
y:
|
|
490
|
+
x: outBufferToJSON.readFloat(),
|
|
491
|
+
y: outBufferToJSON.readFloat(),
|
|
446
492
|
fixed: isPlayerStartPositionFixed
|
|
447
493
|
};
|
|
448
494
|
|
|
449
|
-
|
|
450
|
-
|
|
495
|
+
outBufferToJSON.readInt(); // ally low priorities flags (bit "x"=1 --> set for player "x")
|
|
496
|
+
outBufferToJSON.readInt(); // ally high priorities flags (bit "x"=1 --> set for player "x")
|
|
497
|
+
outBufferToJSON.readInt(); // enemy low priorities flags
|
|
498
|
+
outBufferToJSON.readInt(); // enemy high priorities flags
|
|
451
499
|
|
|
452
500
|
result.players.push(player);
|
|
453
501
|
}
|
|
454
502
|
|
|
455
503
|
// Struct: forces
|
|
456
|
-
const numForces =
|
|
504
|
+
const numForces = outBufferToJSON.readInt();
|
|
457
505
|
for (let i = 0; i < numForces; i++) {
|
|
458
506
|
const force: Force = {
|
|
459
507
|
flags: { allied: false, alliedVictory: true, shareVision: true, shareUnitControl: false, shareAdvUnitControl: false },
|
|
@@ -461,7 +509,7 @@ export class InfoTranslator {
|
|
|
461
509
|
name: ''
|
|
462
510
|
};
|
|
463
511
|
|
|
464
|
-
const forceFlag =
|
|
512
|
+
const forceFlag = outBufferToJSON.readInt();
|
|
465
513
|
force.flags = {
|
|
466
514
|
allied: !!(forceFlag & 0b1), // 0x00000001: allied (force 1)
|
|
467
515
|
alliedVictory: !!(forceFlag & 0b10), // 0x00000002: allied victory
|
|
@@ -470,59 +518,59 @@ export class InfoTranslator {
|
|
|
470
518
|
shareUnitControl: !!(forceFlag & 0b10000), // 0x00000010: share unit control
|
|
471
519
|
shareAdvUnitControl: !!(forceFlag & 0b100000) // 0x00000020: share advanced unit control
|
|
472
520
|
};
|
|
473
|
-
force.players =
|
|
474
|
-
force.name =
|
|
521
|
+
force.players = outBufferToJSON.readInt(); // UNSUPPORTED: (bit "x"=1 --> player "x" is in this force; but carried over for accurate translation
|
|
522
|
+
force.name = outBufferToJSON.readString();
|
|
475
523
|
|
|
476
524
|
result.forces.push(force);
|
|
477
525
|
}
|
|
478
526
|
|
|
479
527
|
// UNSUPPORTED: Struct: upgrade avail.
|
|
480
|
-
const numUpgrades =
|
|
528
|
+
const numUpgrades = outBufferToJSON.readInt();
|
|
481
529
|
for (let i = 0; i < numUpgrades; i++) {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
530
|
+
outBufferToJSON.readInt(); // Player Flags (bit "x"=1 if this change applies for player "x")
|
|
531
|
+
outBufferToJSON.readChars(4); // upgrade id (as in UpgradeData.slk)
|
|
532
|
+
outBufferToJSON.readInt(); // Level of the upgrade for which the availability is changed (this is actually the level - 1, so 1 => 0)
|
|
533
|
+
outBufferToJSON.readInt(); // Availability (0 = unavailable, 1 = available, 2 = researched)
|
|
486
534
|
}
|
|
487
535
|
|
|
488
536
|
// UNSUPPORTED: Struct: tech avail.
|
|
489
|
-
const numTech =
|
|
537
|
+
const numTech = outBufferToJSON.readInt();
|
|
490
538
|
for (let i = 0; i < numTech; i++) {
|
|
491
|
-
|
|
492
|
-
|
|
539
|
+
outBufferToJSON.readInt(); // Player Flags (bit "x"=1 if this change applies for player "x")
|
|
540
|
+
outBufferToJSON.readChars(4); // tech id (this can be an item, unit or ability)
|
|
493
541
|
}
|
|
494
542
|
|
|
495
543
|
// UNSUPPORTED: Struct: random unit table
|
|
496
|
-
const numUnitTable =
|
|
544
|
+
const numUnitTable = outBufferToJSON.readInt();
|
|
497
545
|
for (let i = 0; i < numUnitTable; i++) {
|
|
498
|
-
|
|
499
|
-
|
|
546
|
+
outBufferToJSON.readInt(); // Group number
|
|
547
|
+
outBufferToJSON.readString(); // Group name
|
|
500
548
|
|
|
501
|
-
const numPositions =
|
|
549
|
+
const numPositions = outBufferToJSON.readInt(); // Number "m" of positions
|
|
502
550
|
for (let j = 0; j < numPositions; j++) {
|
|
503
|
-
|
|
551
|
+
outBufferToJSON.readInt(); // unit table (=0), a building table (=1) or an item table (=2)
|
|
504
552
|
|
|
505
|
-
const numLinesInTable =
|
|
553
|
+
const numLinesInTable = outBufferToJSON.readInt();
|
|
506
554
|
for (let k = 0; k < numLinesInTable; k++) {
|
|
507
|
-
|
|
508
|
-
|
|
555
|
+
outBufferToJSON.readInt(); // Chance of the unit/item (percentage)
|
|
556
|
+
outBufferToJSON.readChars(4); // unit/item id's for this line specified
|
|
509
557
|
}
|
|
510
558
|
}
|
|
511
559
|
}
|
|
512
560
|
|
|
513
561
|
// UNSUPPORTED: Struct: random item table
|
|
514
|
-
const numItemTable =
|
|
562
|
+
const numItemTable = outBufferToJSON.readInt();
|
|
515
563
|
for (let i = 0; i < numItemTable; i++) {
|
|
516
|
-
|
|
517
|
-
|
|
564
|
+
outBufferToJSON.readInt(); // Table number
|
|
565
|
+
outBufferToJSON.readString(); // Table name
|
|
518
566
|
|
|
519
|
-
const itemSetsCurrentTable =
|
|
567
|
+
const itemSetsCurrentTable = outBufferToJSON.readInt(); // Number "m" of item sets on the current item table
|
|
520
568
|
for (let j = 0; j < itemSetsCurrentTable; j++) {
|
|
521
569
|
|
|
522
|
-
const itemsInItemSet =
|
|
570
|
+
const itemsInItemSet = outBufferToJSON.readInt(); // Number "i" of items on the current item set
|
|
523
571
|
for (let k = 0; k < itemsInItemSet; k++) {
|
|
524
|
-
|
|
525
|
-
|
|
572
|
+
outBufferToJSON.readInt(); // Percentual chance
|
|
573
|
+
outBufferToJSON.readChars(4); // Item id (as in ItemData.slk)
|
|
526
574
|
}
|
|
527
575
|
|
|
528
576
|
}
|