R3EXS 1.0.2 → 1.0.3

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.
data/lib/R3EXS/utils.rb CHANGED
@@ -1,971 +1,971 @@
1
- # frozen_string_literal: true
2
-
3
- require 'oj'
4
- require_relative 'RGSS3_R3EXS'
5
-
6
- module R3EXS
7
-
8
- # 工具模块
9
- # 主要用来提供一些读取,写入,转换等功能
10
- module Utils
11
-
12
- # 用来匹配读取的 rvdata2 文件名
13
- RVDATA2_FILE_NAME =
14
- [
15
- /\AActors\.rvdata2\z/,
16
- /\AAnimations\.rvdata2\z/,
17
- /\AArmors\.rvdata2\z/,
18
- /\AClasses\.rvdata2\z/,
19
- /\ACommonEvents\.rvdata2\z/,
20
- /\AEnemies\.rvdata2\z/,
21
- /\AItems\.rvdata2\z/,
22
- /\AMap\d{3}\.rvdata2\z/,
23
- /\AMapInfos\.rvdata2\z/,
24
- /\AScripts\.rvdata2\z/,
25
- /\ASkills\.rvdata2\z/,
26
- /\AStates\.rvdata2\z/,
27
- /\ASystem\.rvdata2\z/,
28
- /\ATilesets\.rvdata2\z/,
29
- /\ATroops\.rvdata2\z/,
30
- /\AWeapons\.rvdata2\z/
31
- ]
32
-
33
- # 用来匹配读取的 JSON 文件名
34
- JSON_FILE_NAME =
35
- [
36
- /\AActors\.json\z/,
37
- /\AAnimations\.json\z/,
38
- /\AArmors\.json\z/,
39
- /\AClasses\.json\z/,
40
- /\ACommonEvents\.json\z/,
41
- /\AEnemies\.json\z/,
42
- /\AItems\.json\z/,
43
- /\AMap\d{3}\.json\z/,
44
- /\AMapInfos\.json\z/,
45
- /\ASkills\.json\z/,
46
- /\AStates\.json\z/,
47
- /\ASystem\.json\z/,
48
- /\ATilesets\.json\z/,
49
- /\ATroops\.json\z/,
50
- /\AWeapons\.json\z/
51
- ]
52
-
53
- # 用来匹配读取的文件名到对应的R3EXS的类
54
- FILE_BASENAME_TO_CLASS_R3EXS = {
55
- /\AActors\z/ => R3EXS::Actor,
56
- /\AAnimations\z/ => R3EXS::Animation,
57
- /\AArmors\z/ => R3EXS::Armor,
58
- /\AClasses\z/ => R3EXS::Class,
59
- /\ACommonEvents\z/ => R3EXS::CommonEvent,
60
- /\AEnemies\z/ => R3EXS::Enemy,
61
- /\AItems\z/ => R3EXS::Item,
62
- /\AMap\d{3}\z/ => R3EXS::Map,
63
- /\AMapInfos\z/ => R3EXS::MapInfo,
64
- /\ASkills\z/ => R3EXS::Skill,
65
- /\AStates\z/ => R3EXS::State,
66
- /\ASystem\z/ => R3EXS::System,
67
- /\ATilesets\z/ => R3EXS::Tileset,
68
- /\ATroops\z/ => R3EXS::Troop,
69
- /\AWeapons\z/ => R3EXS::Weapon
70
- }
71
-
72
- # 用来匹配读取的文件名到对应的RPG的类
73
- FILE_BASENAME_TO_CLASS_RPG = {
74
- /\AActors\z/ => RPG::Actor,
75
- /\AAnimations\z/ => RPG::Animation,
76
- /\AArmors\z/ => RPG::Armor,
77
- /\AClasses\z/ => RPG::Class,
78
- /\ACommonEvents\z/ => RPG::CommonEvent,
79
- /\AEnemies\z/ => RPG::Enemy,
80
- /\AItems\z/ => RPG::Item,
81
- /\AMap\d{3}\z/ => RPG::Map,
82
- /\AMapInfos\z/ => RPG::MapInfo,
83
- /\ASkills\z/ => RPG::Skill,
84
- /\AStates\z/ => RPG::State,
85
- /\ASystem\z/ => RPG::System,
86
- /\ATilesets\z/ => RPG::Tileset,
87
- /\ATroops\z/ => RPG::Troop,
88
- /\AWeapons\z/ => RPG::Weapon
89
- }
90
-
91
- # 事件指令的命令名称
92
- EVENT_COMMANDS = {
93
- 0 => 'Empty',
94
-
95
- =begin
96
- [string(Face Graphic name)]---[int(Face Graphic index)]---[int:{0:Normal Window, 1:Dim Background, 2:Transparent}]---[int:{0:Top, 1:Middle, 2:Bottom}]---END
97
- =end
98
- 101 => 'ShowTextAttributes',
99
-
100
- =begin
101
- [Array<string>(Choices Array)]---[int:{0:Disallow, 1:Choice 1, 2:Choice 2, 3:Choice 3, 4:Choice 4, 5:Branch}(When Cancel)]---END
102
- =end
103
- 102 => 'ShowChoices',
104
-
105
- =begin
106
- [int(Variable for Number)]---[int:{1~8}(Digits)]---END
107
- =end
108
- 103 => 'InputNumber',
109
-
110
- =begin
111
- [int(Variable for Item ID)]---END
112
- =end
113
- 104 => 'SelectKeyItem',
114
-
115
- =begin
116
- [int:{1~8}(Speed)]---[bool(No Fast Forward)]---END
117
- =end
118
- 105 => 'ShowScrollingTextAttributes',
119
-
120
- =begin
121
- [string]---END
122
- =end
123
- 108 => 'Comment',
124
-
125
- =begin
126
- |--[int:0(Switch)]---[int(Switch ID)]---[int{0:ON, 1:OFF}]---END
127
- |
128
- | |--[int:0(Compare to Constant)]---[int(Number)]-------|
129
- |--[int:1(Variable)]---[int(Variable ID)]--| |--[int{0:==, 1:>=, 2:<=, 3:>, 4:<, 5:!=}]---END
130
- | |--[int:1(Compare to Variable)]---[int(Variable ID)]--|
131
- |
132
- |--[int:2(Self Switch)]---[string{'A', 'B', 'C', 'D'}]---[int{0:ON, 1:OFF}]---END
133
- |
134
- |--[int:3(Timer)]---[int:{0~5999}(sec)]---[int{0:>=, 1:<=}]---END
135
- |
136
- | |--[int:0(In the Party)]---END
137
- | |
138
- | |--[int:1(Name)]---[string]---END
139
- | |
140
- | |--[int:2(Class)]---[int(Class ID)]---END
141
- | |
142
- |--[int:4(Actor)]---[int(Actor ID)]--------|--[int:3(Skill)]---[int(Skill ID)]---END
143
- | |
144
- | |--[int:4(Weapon)]---[int(Wwapon ID)]---END
145
- | |
146
- | |--[int:5(Armor)]---[int(Armor ID)]---END
147
- | |
148
- | |--[int:6(State)]---[int(State ID)]---END
149
- |
150
- | |--[int:0(Appeared)---END
151
- |--[int:5(Enemy)]---[int(Enemy ID)]--------|
152
- | |--[int:1(State)]---[int(State ID)]---END
153
- |
154
- |--[int:6(Character)]---[int:{-1:Player, 0:This event, 1:EV001, ...}]---[int:{2:Down, 4:Left, 6:Right, 8:Up}]---END
155
- |
156
- |--[int:7(Gold)]---[int(Money)]---[int{0:>=, 1:<=, 2:<}]---END
157
- |
158
- |--[int:8(Item)]---[int(Item ID)]---END
159
- |
160
- |--[int:9(Weapon)]---[int(Weapon ID)]---[bool(Include Equipments)]---END
161
- |
162
- |--[int:10(Armor)]---[int(Armor ID)]---[bool(Include Equipments)]---END
163
- |
164
- |--[int:11(Button)]---[int:{2:Down, 4:Left, 6:Right, 8:Up, 11:A, 12:B, 13:C, 14:X, 15:Y, 16:Z, 17:L, 18:R}]---END
165
- |
166
- |--[int:12(Script)]---[string]---END
167
- |
168
- |--[int:13(Vehicle)]---[int:{0:Boat, 1:Ship, 2:Airship}]---END
169
- =end
170
- 111 => 'ConditionalBranch',
171
- 112 => 'Loop',
172
- 113 => 'BreakLoop',
173
- 115 => 'ExitEventProcessing',
174
-
175
- =begin
176
- [int(Common Event ID)]---END
177
- =end
178
- 117 => 'CallCommonEvent',
179
-
180
- =begin
181
- [string]---END
182
- =end
183
- 118 => 'Label',
184
-
185
- =begin
186
-
187
- [string]---END
188
- =end
189
- 119 => 'JumpToLabel',
190
-
191
- =begin
192
- [int(Switch Begin ID)]---[int(Switch End ID)]---[int:{0:ON, 1:OFF}]---END
193
- =end
194
- 121 => 'ControlSwitches',
195
-
196
- =begin
197
- |--[int:0(Constant)]---[int(Number)]---END
198
- |
199
- |--[int:1(Variable)]---[int(Variable ID)]---END
200
- |
201
- |--[int:2(Random)]---[int(Min)]---[int(Max)]---END
202
- |
203
- | |--[int:{0:Item, 1:Weapon, 2:Armor}]---[int(Corresponded Item ID)]---[int:0]---END
204
- | |
205
- [int(Variable Begin ID)]---[int(Variable End ID)]---[int:{0:Set, 1:Add, 2:Sub, 3:Mul, 4:Div, 5:Mod}]--| |--[int:3(Actor)]---[int:(Actor ID)]---[int:{0:Level, 1:EXP, 2:HP, 3:MP, 4:MHP, 5:MMP, 6:ATK, 7:DEF, 8:MAT, 9:MDF, 10:AGI, 11:LUK}]---END
206
- | |
207
- | |--[int:4(Enemy)]---[int:(Enemy ID)]---[int:{0:HP, 1:MP, 2:MHP, 3:MMP, 4:ATK, 5:DEF, 6:MAT, 7:MDF, 8:AGI, 9:LUK}]---END
208
- |--[int:3(Game Data)]--|
209
- | |--[int:5(Character)]---[int:{-1:Player, 0:This Event, 1:EV001, ...}]---[int:{0:Map X, 1:Map Y, 2:Direction, 3:Screen X ,4:Screen Y}]---END
210
- | |
211
- | |--[int:6(Party)]---[int:{0~7}(Member ID)]---[int:0]---END('s Actor ID)
212
- | |
213
- | |--[int:7(Other)]---[int:{0(Map ID), 1(Party Members), 2(Gold), 3(Steps), 4(Play Time), 5(Timer), 6(Save Count), 7(Battle Count)}]---[int:0]---END
214
- |
215
- |--[int:4(Scripts)]---[string]---END
216
- =end
217
- 122 => 'ControlVariables',
218
-
219
- =begin
220
- [string:{'A', 'B', 'C', 'D'}(Self Switch Name)]---[int:{0:ON, 1:OFF}]---END
221
- =end
222
- 123 => 'ControlSelfSwitch',
223
-
224
- =begin
225
- [int:{0:Start, 1:Stop}]---[int:{0~5999}(sec)]---END
226
- =end
227
- 124 => 'ControlTimer',
228
-
229
- =begin
230
- |--[int:0(Constant)]---[int:{0~9999999}(Number)]---END
231
- [int:{0:Increase, 1:Decrease}]--|
232
- |--[int:1(Variable)]---[int(Variable ID)]---END
233
- =end
234
- 125 => 'ChangeGold',
235
-
236
- =begin
237
- |--[int:0(Constant)]---[int:{0~9999999}(Number)]---END
238
- [int(Item ID)]---[int:{0:Increase, 1:Decrease}]--|
239
- |--[int:1(Variable)]---[int(Variable ID)]---END
240
- =end
241
- 126 => 'ChangeItems',
242
-
243
- =begin
244
- |--[int:0(Constant)]---[int:{0~9999999}(Number)]--|
245
- |--[int:0(Increase)]--| |--[bool:false(Include Equipment)]---END
246
- | |--[int:1(Variable)]---[int(Variable ID)]---------|
247
- [int(Weapon ID)]--|
248
- | |--[int:0(Constant)]---[int:{0~9999999}(Number)]--|
249
- |--[int:1(Decrease)]--| |--[bool(Include Equipment)]---END
250
- |--[int:1(Variable)]---[int(Variable ID)]---------|
251
- =end
252
- 127 => 'ChangeWeapons',
253
-
254
- =begin
255
- |--[int:0(Constant)]---[int:{0~9999999}(Number)]--|
256
- |--[int:0(Increase)]--| |--[bool:false(Include Equipment)]---END
257
- | |--[int:1(Variable)]---[int(Variable ID)]---------|
258
- [int(Armor ID)]--|
259
- | |--[int:0(Constant)]---[int:{0~9999999}(Number)]--|
260
- |--[int:1(Decrease)]--| |--[bool(Include Equipment)]---END
261
- |--[int:1(Variable)]---[int(Variable ID)]---------|
262
- =end
263
- 128 => 'ChangeArmor',
264
-
265
- =begin
266
- [int(Actor ID)]---[int:{0:Add, 1:Remove}]---[int:{0:NO, 1:YES}(Initialize)]---END
267
- =end
268
- 129 => 'ChangePartyMember',
269
-
270
- =begin
271
- [RPG::BGM]---END
272
- =end
273
- 132 => 'ChangeBattleBGM',
274
-
275
- =begin
276
- [RPG::ME]---END
277
- =end
278
- 133 => 'ChangeBattleEndME',
279
-
280
- =begin
281
- [int:{0:Disable, 1:Enable}]---END
282
- =end
283
- 134 => 'ChangeSaveAccess',
284
-
285
- =begin
286
- [int:{0:Disable, 1:Enable}]---END
287
- =end
288
- 135 => 'ChangeMenuAccess',
289
-
290
- =begin
291
- [int:{0:Disable, 1:Enable}]---END
292
- =end
293
- 136 => 'ChangeEncounter',
294
-
295
- =begin
296
- [int:{0:Disable, 1:Enable}]---END
297
- =end
298
- 137 => 'ChangeFormationAccess',
299
-
300
- =begin
301
- [RPG::Tone]---END
302
- =end
303
- 138 => 'ChangeWindowColor',
304
-
305
- =begin
306
- |--[int:0(Direct Designation)]---[int(Map ID)]---[int(Map X)]---[int(Map Y)]-------------------------------------------------------------------------------------|
307
- | |--[int:{0:Retain, 2:Down, 4:Left, 6:Right, 8:Up}(Direction)]---[int:{0:Normal, 1:White, 2:None}(Fade)]---END
308
- |--[int:1(Designation with Variables)]---[int(Map ID Corresponded Variable ID)]---[int(Map X Corresponded Variable ID)]---[int(Map Y Corresponded Variable ID)]--|
309
- =end
310
- 201 => 'TransferPlayer',
311
-
312
- =begin
313
- |--[int:0(Direct Designation)]---[int(Map ID)]---[int(Map X)]---[int(Map Y)]---END
314
- [int:{0:Boat, 1:Ship, 2:Airship}]--|
315
- |--[int:1(Designation with Variables)]---[int(Map ID Corresponded Variable ID)]---[int(Map X Corresponded Variable ID)]---[int(Map Y Corresponded Variable ID)]---END
316
- =end
317
- 202 => 'SetVehicleLocation',
318
-
319
- =begin
320
- |--[int:0(Direct Designation)]---[int(Map X)]---[int(Map Y)]------------------------------------------------------------|
321
- | |
322
- [int:{0:This Event, 1:EV001, ...}]----------|--[int:1(Designation with Variables)]---[int(Map X Corresponded Variable ID)]---[int(Map Y Corresponded Variable ID)]--|--[int:{0:Retain, 2:Down, 4:Left, 6:Right, 8:Up}(Direction)]---END
323
- | |
324
- |--[int:2(Exchange with Another Event)]---[int(Exchanged Event ID)]---[int:0]----------------------------------------- |
325
- =end
326
- 203 => 'SetEventLocation',
327
-
328
- =begin
329
- [int:{2:Down, 4:Left, 6:Right, 8:Up}]---[int:{0~100}(Distance)]---[int:{1:1/8 Speed, 2:1/4 Speed, 3:1/2 Speed, 4:Normal, 5:2 Speed, 6:4 Speed}]---END
330
- =end
331
- 204 => 'ScrollMap',
332
-
333
- =begin
334
- [int:{-1:Player, 0:This Event, 1:EV001, ...}]---[RPG::MoveRoute(45 is Script)]---END
335
- =end
336
- 205 => 'SetMoveRoute',
337
-
338
- =begin
339
- END
340
- =end
341
- 206 => 'GetSwitchVehicle',
342
-
343
- =begin
344
- [int:{0:ON, 1:OFF}]---END
345
- =end
346
- 211 => 'ChangeTransparency',
347
-
348
- =begin
349
- [int:{-1:Player, 0:This Event, 1:EV001, ...}]---[int(Animation ID)]---[bool(Wait for Completion)]---END
350
- =end
351
- 212 => 'ShowAnimation',
352
-
353
- =begin
354
- [int:{-1:Player, 0:This Event, 1:EV001, ...}]---[int(Ballon Icon ID)]---[bool(Wait for Completion)]---END
355
- =end
356
- 213 => 'ShowBalloonIcon',
357
- 214 => 'EraseEvent',
358
-
359
- =begin
360
- [int:{0:ON, 1:OFF}]---END
361
- =end
362
- 216 => 'ChangePlayerFollowers',
363
- 217 => 'GatherFollowers',
364
- 221 => 'FadeoutScreen',
365
- 222 => 'FadeinScreen',
366
-
367
- =begin
368
- [RPG::Tone]---[int:{0~600}(Time 1/60 sec)]---[bool(Wait for Completion)]---END
369
- =end
370
- 223 => 'TintScreen',
371
-
372
- =begin
373
- [RPG::Color]---[int:{0~600}(Time 1/60 sec)]---[bool(Wait for Completion)]---END
374
- =end
375
- 224 => 'FlashScreen',
376
-
377
- =begin
378
- [int:{1~9}(Power)]---[int:{1~9}(Speed)]---[int:{0~600}(Time 1/60 sec)]---[bool(Wait for Completion)]---END
379
- =end
380
- 225 => 'ShakeScreen',
381
-
382
- =begin
383
- [int:{0~999}(Time 1/60 sec)]---END
384
- =end
385
- 230 => 'Wait',
386
-
387
- =begin
388
- |--[int:0(Constant)]---[int:{-9999~9999}(Map X)]---[int:{-9999~9999}(Map Y)]--------------------------|
389
- [int:{1~100}(Number)]---[string(Picture Graphic Name)]---[int:{0:Upper Left, 1:Center}(Origin)]--| |--[int:{0~2000}(Width %)]---[int:{0~2000}(Height %)]---[int:{0~255}(Opacity)]---[int:{0:Normal, 1:Add, 2:Sub}]---END
390
- |--[int:1(Variable)]---[int(Map X Corresponded Variable ID)]---[int(Map Y Corresponded Variable ID)]--|
391
- =end
392
- 231 => 'ShowPicture',
393
-
394
- =begin
395
- |--[int:0(Constant)]---[int:{-9999~9999}(Map X)]---[int:{-9999~9999}(Map Y)]--------------------------|
396
- [int:{1~100}(Number)]---[int:{0:Upper Left, 1:Center}(Origin)]--| |--[int:{0~2000}(Width %)]---[int:{0~2000}(Height %)]---[int:{0~255}(Opacity)]---[int:{0:Normal, 1:Add, 2:Sub}]---[int:{0~600}(Time 1/60 sec)]---[bool(Wait for Completion)]---END
397
- |--[int:1(Variable)]---[int(Map X Corresponded Variable ID)]---[int(Map Y Corresponded Variable ID)]--|
398
- =end
399
- 232 => 'MovePicture',
400
-
401
- =begin
402
- [int:{1~100}(Number)]-[int:{-90~90}(Speed)]--END
403
- =end
404
- 233 => 'RotatePicture',
405
-
406
- =begin
407
- [int:{1~100}(Number)]---[RPG::Tone]---[int:{0~600}(Time 1/60 sec)]---[bool(Wait for Completion)]---END
408
- =end
409
- 234 => 'TintPicture',
410
-
411
- =begin
412
- [int:{1~100}(Number)]---END
413
- =end
414
- 235 => 'ErasePicture',
415
-
416
- =begin
417
- [string:{":none", ":rain", ":storm", ":snow"}]---[int:{0~9}(Power)]---[int:{0~600}(Time 1/60 sec)]---[bool(Wait for Completion)]---END
418
- =end
419
- 236 => 'SetWeatherEffects',
420
-
421
- =begin
422
- [RPG::BGM]---END
423
- =end
424
- 241 => 'PlayBGM',
425
-
426
- =begin
427
- [int:{1~60}(Time sec)]---END
428
- =end
429
- 242 => 'FadeoutBGM',
430
- 243 => 'SaveBGM',
431
- 244 => 'ReplayBGM',
432
-
433
- =begin
434
- [RPG::BGM]---END
435
- =end
436
- 245 => 'PlayBGS',
437
-
438
- =begin
439
- [int:{1~60}(Time sec)]---END
440
- =end
441
- 246 => 'FadeoutBGS',
442
-
443
- =begin
444
- [RPG::ME]---END
445
- =end
446
- 249 => 'PlayME',
447
-
448
- =begin
449
- [RPG::SE]---END
450
- =end
451
- 250 => 'PlaySE',
452
- 251 => 'StopSE',
453
-
454
- =begin
455
- [string(Movie Name)]---END
456
- =end
457
- 261 => 'PlayMovie',
458
-
459
- =begin
460
- [int:{0:ON, 1:OFF}]---END
461
- =end
462
- 281 => 'ChangeMapNameDisplay',
463
-
464
- =begin
465
- [int(Tileset ID)]---END
466
- =end
467
- 282 => 'ChangeTileset',
468
-
469
- =begin
470
- [string(Floor Picture)]---[string(Wall Picture)]---END
471
- =end
472
- 283 => 'ChangeBattleBack',
473
-
474
- =begin
475
- [string(Distant view Picture)]---[bool(Loop Horizontal)]---[bool(Loop Vertical)]---[int(-32~32)(Horizontal Scroll)]---[int(-32~32)(Vertical Scrool)]---END
476
- =end
477
- 284 => 'ChangeParallaxBack',
478
-
479
- =begin
480
- |--[int:0(Direct Designation)]---[int(Map X)]---[int(Map Y)]---END
481
- [int(Variable for Info)]---[int:{0:Terrain, 1:Event ID, 2:Tile ID(Layer 1), 3:Tile ID(Layer 2), 4:Tile ID(Layer 3), 5:Region ID}(Info Type)]--|
482
- |--[int:1(Designation with Variables)]---[int(Map X Corresponded Variable ID)]---[int(Map Y Corresponded Variable ID)]---END
483
- =end
484
- 285 => 'GetLocationInfo',
485
-
486
- =begin
487
- |--[int:0(Direct Designation)]---[int(Enemy ID)]-----------------------------------|
488
- | |--[bool(Can Escape)]---[bool(Continue Even When Loser)]---END
489
- |--[int:1(Designation with Variables)]---[int(Enemy ID Corresponded Variable ID)]--|
490
- =end
491
- 301 => 'BattleProcessing',
492
-
493
- =begin
494
- |--[int:0(Price: Standard)]---[int:0]------------------|
495
- [int:{0:Item, 1:Weapon, 2:Armor}]---[int(Corresponded Item ID)]--| |--[bool(Purchase Only)]---END
496
- |--[int:1(Price: Specify)]---[int:{0~9999999}(Price)]--|
497
- =end
498
- 302 => 'ShopProcessing',
499
-
500
- =begin
501
- [int(Actor ID)]---[int:{1~16}(Max Characters)]---END
502
- =end
503
- 303 => 'NameInputProcessing',
504
-
505
- =begin
506
- |--[int:0(Constant)]---[int:{1~9999}(Number)]--|
507
- |--[int:0(Increase)]--| |--[bool:false(Allow Knockout)]---END
508
- | |--[int:1(Variable)]---[int(Variable ID)]------|
509
- |--[int:0(Fixed)]---[int:{0:Entire Party, 1:Actor 001, ...}]--|
510
- | | |--[int:0(Constant)]---[int:{1~9999}(Number)]--|
511
- | |--[int:1(Decrease)]--| |--[bool(Allow Knockout)]---END
512
- | |--[int:1(Variable)]---[int(Variable ID)]------|
513
- |
514
- | |--[int:0(Constant)]---[int:{1~9999}(Number)]--|
515
- | |--[int:0(Increase)]--| |--[bool:false(Allow Knockout)]---END
516
- | | |--[int:1(Variable)]---[int(Variable ID)]------|
517
- |--[int:1(Variable)]---[int(Variable ID)]-----------------------|
518
- | |--[int:0(Constant)]---[int:{1~9999}(Number)]--|
519
- |--[int:1(Decrease)]--| |--[bool(Allow Knockout)]---END
520
- |--[int:1(Variable)]---[int(Variable ID)]------|
521
- =end
522
- 311 => 'ChangeHP',
523
-
524
- =begin
525
- |--[int:0(Fixed)]---[int:{0:Entire Party, 1:Actor 001, ...}]--| |--[int:0(Constant)]---[int:{1~9999}(Number)]---END
526
- | |--[int:{0:Increase, 1:Decrease}]--|
527
- |--[int:1(Variable)]---[int(Variable ID)]---------------------| |--[int:1(Variable)]---[int(Variable ID)]---END
528
- =end
529
- 312 => 'ChangeMP',
530
-
531
- =begin
532
- |--[int:0(Fixed)]---[int:{0:Entire Party, 1:Actor 001, ...}]--|
533
- | |--[int:{0:Add, 1:Remove}]---[int(State ID)]---END
534
- |--[int:1(Variable)]---[int(Variable ID)]---------------------|
535
- =end
536
- 313 => 'ChangeState',
537
-
538
- =begin
539
- |--[int:0(Fixed)]---[int:{0:Entire Party, 1:Actor 001, ...}]---END
540
- |
541
- |--[int:1(Variable)]---[int(Variable ID)]---END
542
- =end
543
- 314 => 'RecoverAll',
544
-
545
- =begin
546
- |--[int:0(:Constant)]---[int:{1~9999999}(Number)]--|
547
- |--[int:0(Increase)]--| |--[bool(Show Level Up Message)]---END
548
- | |--[int:1(Variable)]---[int(Variable ID)]----------|
549
- |--[int:0(Fixed)]---[int:{0:Entire Party, 1:Actor 001, ...}]--|
550
- | | |--[int:0(Constant)]---[int:{1~9999999}(Number)]--|
551
- | |--[int:1(Decrease)]--| |--[bool:false(Show Level Up Message)]---END
552
- | |--[int:1(Variable)]------------------------------|
553
- |
554
- | |--[int:0(Constant)]---[int:{1~9999999}(Number)]--|
555
- | |--[int:0(Increase)]--| |--[bool(Show Level Up Message)]---END
556
- | | |--[int:1(Variable)]---[int(Variable ID)]---------|
557
- |--[int:1(Variable)]---[int(Variable ID)]---------------------|
558
- | |--[int:0(Constant)]---[int:{1~9999999}(Number)]--|
559
- |--[int:1(Decrease)]--| |--[bool:false(Show Level Up Message)]---END
560
- |--[int:1(Variable)]---[int(Variable ID)]---------|
561
- =end
562
- 315 => 'ChangeEXP',
563
-
564
- =begin
565
- |--[int:0(Constant)]---[int:{1~98}(Number)]--|
566
- |--[int:0(Increase)]--| |--[bool(Show Level Up Message)]---END
567
- | |--[int:1(Variable)]---[int(Variable ID)]----|
568
- |--[int:0(Fixed)]---[int:{0:Entire Party, 1:Actor 001, ...}]--|
569
- | | |--[int:0(Constant)]---[int:{1~98}(Number)]--|
570
- | |--[int:1(Decrease)]--| |--[bool:false(Show Level Up Message)]---END
571
- | |--[int:1(Variable)]---[int(Variable ID)]----|
572
- |
573
- | |--[int:0(Constant)]---[int:{1~98}(Number)]--|
574
- | |--[int:0(Increase)]--| |--[bool(Show Level Up Message)]---END
575
- | | |--[int:1(Variable)]---[int(Variable ID)]----|
576
- |--[int:1(Variable)]---[int(Variable ID)]---------------------|
577
- | |--[int:0(Constant)]---[int:{1~98}(Number)]--|
578
- |--[int:1(Decrease)]--| |--[bool:false(Show Level Up Message)]---END
579
- |--[int:1(Variable)]---[int(Variable ID)]------|
580
- =end
581
- 316 => 'ChangeLevel',
582
-
583
- =begin
584
- |--[int:0(Fixed)]---[int:{0:Entire Party, 1:Actor 001, ...}]--| |--[int:0(Constant)]---[int:{0~9999999}(Number)]---END
585
- | |--[int:{0:MHP, 1:MMP, 2:ATK, 3:DEF, 4:MAT, 5:MDF, 6:AGI, 7:LUK}]---[int:{0:Increase, 1:Decrease}]--|
586
- |--[int:1(Variable)]---[int(Variable ID)]---------------------| |--[int:1(Variable)]---[int(Variable ID)]---END
587
- =end
588
- 317 => 'ChangeParameters',
589
-
590
- =begin
591
- |--[int:0(Fixed)]---[int:{0:Entire Party, 1:Actor 001, ...}]--|
592
- | |--[int:{0:Learn, 1:Forget}]---[int(Skill ID)]---END
593
- |--[int:1(Variable)]---[int(Variable ID)]---------------------|
594
- =end
595
- 318 => 'ChangeSkills',
596
-
597
- =begin
598
- [int(Actor ID)]---[int:{0:Weapon, 1:Shield, 2:Head, 3:Boby, 4:Accessory}]---[int:{0:None, 1:Equipment 001, ...}(Equipment ID)]---END
599
- =end
600
- 319 => 'ChangeEquipment',
601
-
602
- =begin
603
- [int(Actor ID)]---[string(New Actor Name)]---END
604
- =end
605
- 320 => 'ChangeActorName',
606
-
607
- =begin
608
- [int(Actor ID)]---[int(New Class ID)]---END
609
- =end
610
- 321 => 'ChangeActorClass',
611
-
612
- =begin
613
- [int(Actor ID)]---[string(New Actor walking Picture Name)]---[int(New Actor Walking Picture Index)]---[string(New Actor Portrait Picture Name)]---[int(New Actor Portrait Picture Index)]---END
614
- =end
615
- 322 => 'ChangeActorGraphic',
616
-
617
- =begin
618
- [int:{0:Boat, 1:Ship, 2:Airship}]---[string(New Vehicle Picture Name)]---[int(New Vehicle Picture Index)]---END
619
- =end
620
- 323 => 'ChangeVehicleGraphic',
621
-
622
- =begin
623
- [int(Actor ID)]---[string(New Actor Nickname)]---END
624
- =end
625
- 324 => 'ChangeActorNickname',
626
-
627
- =begin
628
- |--[int:0(Constant)]---[int:{1~999999}(Number)]--|
629
- |--[int:0(Increase)]--| |--[bool:false(Allow Knockout)]---END
630
- | |--[int:1(Variable)]---[int(Variable ID)]--------|
631
- [int:{-1:Entire Troop, 0:Troop 001, ...}]--|
632
- | |--[int:0(Constant)]---[int:{1~999999}(Number)]--|
633
- |--[int:1(Decrease)]--| |--[bool(Allow Knockout)]---END
634
- |--[int:1(Variable)]---[int(Variable ID)]--------|
635
-
636
- =end
637
- 331 => 'ChangeEnemyHP',
638
-
639
- =begin
640
- |--[int:0(Constant)]---[int:{1~9999}(Number)]---END
641
- [int:{-1:Entire Troop, 0:Troop 001, ...}]---[int:{0:Increase, 1:Decrease}]--|
642
- |--[int:1(Variable)]---[int(Variable ID)]---END
643
- =end
644
- 332 => 'ChangeEnemyMP',
645
-
646
- =begin
647
- [int:{-1:Entire Troop, 0:Troop 001, ...}]---[int:{0:Add, 1:Remove}]---[int(State ID)]---END
648
- =end
649
- 333 => 'ChangeEnemyState',
650
-
651
- =begin
652
- [int:{-1:Entire Troop, 0:Troop 001, ...}]---END
653
- =end
654
- 334 => 'EnemyRecoverAll',
655
-
656
- =begin
657
- [int:{-1:Entire Troop, 0:Troop 001, ...}]---END
658
- =end
659
- 335 => 'EnemyAppear',
660
-
661
- =begin
662
- [int(Troop ID)]---[int(Enemy ID)]---END
663
- =end
664
- 336 => 'EnemyTransform',
665
-
666
- =begin
667
- [int:{-1:Entire Troop, 0:Troop 001, ...}]---[int(Animation ID)]---END
668
- =end
669
- 337 => 'ShowBattleAnimation',
670
-
671
- =begin
672
- |--[int:0(Enemy)]---[int(Troop ID)]--|
673
- | |--[int(Skill ID)]---[int:{-2:Last Target, -1:Random, 0:Index 1,...}]---END
674
- |--[int:1(Actor)]---[int(Actor ID)]--|
675
- =end
676
- 339 => 'ForceAction',
677
- 340 => 'AbortBattle',
678
- 351 => 'OpenMenuScreen',
679
- 352 => 'OpenSaveScreen',
680
- 353 => 'GameOver',
681
- 354 => 'ReturnToTitleScreen',
682
-
683
- =begin
684
- [string]---END
685
- =end
686
- 355 => 'Script',
687
-
688
- =begin
689
- [string]---END
690
- =end
691
- 401 => 'ShowText',
692
-
693
- =begin
694
- [int(Choice Index)]---[string(Choice Name)]---END
695
- =end
696
- 402 => 'When',
697
- 403 => 'WhenCancel',
698
- 404 => 'ChoicesEnd',
699
-
700
- =begin
701
- [string]---END
702
- =end
703
- 405 => 'ShowScrollingText',
704
-
705
- =begin
706
- [string]---END
707
- =end
708
- 408 => 'CommentMore',
709
- 411 => 'Else',
710
- 412 => 'BranchEnd',
711
- 413 => 'RepeatAbove',
712
-
713
- =begin
714
- [RPG::MoveCommand(45 is script)]---END
715
- =end
716
- 505 => 'MoveRoute',
717
- 601 => 'IfWin',
718
- 602 => 'IfEscape',
719
- 603 => 'IfLose',
720
- 604 => 'BattleProcessingEnd',
721
-
722
- =begin
723
- |--[int:0(Price: Standard)]---[int:0]---END
724
- [int:{0:Item, 1:Weapon, 2:Armor}]---[int(Corresponded Item ID)]--|
725
- |--[int:1(Price: Specify)]---[int:{0~9999999}(Price)]---END
726
- =end
727
- 605 => 'ShopItem',
728
-
729
- =begin
730
- [string]---END
731
- =end
732
- 655 => 'ScriptMore' }
733
-
734
- # 红色
735
- RED_COLOR = "\e[31m"
736
-
737
- # 绿色
738
- GREEN_COLOR = "\e[32m"
739
-
740
- # 黄色
741
- YELLOW_COLOR = "\e[33m"
742
-
743
- # 蓝色
744
- BLUE_COLOR = "\e[34m"
745
-
746
- # 紫色
747
- MAGENTA_COLOR = "\e[35m"
748
-
749
- # 青色
750
- CYAN_COLOR = "\e[36m"
751
-
752
- # 重置颜色
753
- RESET_COLOR = "\e[0m"
754
-
755
- # 清除行
756
- ESCAPE = "\e[2K"
757
-
758
- # 根据 file_basename 检查 object 的类型在 module_name 中是否正确
759
- #
760
- # @param object [Object] 待检查的对象
761
- # @param file_basename [String] 文件名(不包含扩展名)
762
- # @param is_compact [Boolean] 是否为紧凑模式
763
- # @param module_name [Symbol] 模块名
764
- #
765
- # @raise [RPGTypeError] object 的类型不在 RPG 模块中
766
- # @raise [R3EXSTypeError] object 的类型不在 R3EXS 模块中
767
- # @raise [ModuleNameError] module_name 不是 :RPG 或 :R3EXS
768
- # @raise [FileBaseNameError] file_basename 无法匹配到对应的类
769
- #
770
- # @return [void]
771
- def Utils.check_type(object, file_basename, is_compact, module_name)
772
- case module_name
773
- when :RPG
774
- matched_class = FILE_BASENAME_TO_CLASS_RPG.find { |pattern, _| file_basename =~ pattern }&.last
775
- matched_class or raise FileBaseNameError.new(file_basename), "Invalid file basename: #{file_basename}"
776
- if object.is_a?(Array)
777
- if is_compact
778
- object.compact.all? { |item| item.is_a?(matched_class) } or raise RPGTypeError.new(object), "Invalid Object: #{object}, it's not an Array<#{matched_class}>"
779
- else
780
- object.all? { |item| item.is_a?(matched_class) } or raise RPGTypeError.new(object), "Invalid Object: #{object}, it's not an Array<#{matched_class}>"
781
- end
782
- elsif object.is_a?(Hash)
783
- if is_compact
784
- object.compact.values.all? { |item| item.is_a?(matched_class) } or raise RPGTypeError.new(object), "Invalid Object: #{object}, it's not a Hash<#{matched_class}>"
785
- else
786
- object.values.all? { |item| item.is_a?(matched_class) } or raise RPGTypeError.new(object), "Invalid Object: #{object}, it's not a Hash<#{matched_class}>"
787
- end
788
- else
789
- object.is_a?(matched_class) or raise RPGTypeError.new(object), "Invalid Object: #{object}, it's not a #{matched_class}"
790
- end
791
- when :R3EXS
792
- matched_class = FILE_BASENAME_TO_CLASS_R3EXS.find { |pattern, _| file_basename =~ pattern }&.last
793
- matched_class or raise FileBaseNameError.new(file_basename), "Invalid file basename: #{file_basename}"
794
- if object.is_a?(Array)
795
- if is_compact
796
- object.compact.all? { |item| item.is_a?(matched_class) } or raise R3EXSTypeError.new(object), "Invalid object: #{object}, it's not an Array<#{matched_class}>"
797
- else
798
- object.all? { |item| item.is_a?(matched_class) } or raise R3EXSTypeError.new(object), "Invalid object: #{object}, it's not an Array<#{matched_class}>"
799
- end
800
- elsif object.is_a?(Hash)
801
- if is_compact
802
- object.compact.values.all? { |item| item.is_a?(matched_class) } or raise R3EXSTypeError.new(object), "Invalid object: #{object}, it's not a Hash<#{matched_class}>"
803
- else
804
- object.values.all? { |item| item.is_a?(matched_class) } or raise R3EXSTypeError.new(object), "Invalid object: #{object}, it's not a Hash<#{matched_class}>"
805
- end
806
- else
807
- object.is_a?(matched_class) or raise R3EXSTypeError.new(object), "Invalid object: #{object}, it's not #{matched_class}"
808
- end
809
- else
810
- raise ModuleNameError.new(module_name), "Invalid module name: #{module_name}"
811
- end
812
-
813
- end
814
-
815
- # 将 RPG 中的对象转化为 R3EXS 对象
816
- #
817
- # @param object [Object] 待转化的 RPG 对象
818
- # @param file_basename [String] 文件名(不包含扩展名)
819
- # @param with_notes [Boolean] 是否包含注释
820
- #
821
- # @raise [RPGTypeError] object 的类型不在 RPG 模块中
822
- # @raise [FileBaseNameError] file_basename 无法匹配到对应的类
823
- #
824
- # @return [Object]
825
- def Utils.rpg_r3exs(object, file_basename, with_notes)
826
- check_type(object, file_basename, true, :RPG)
827
-
828
- # 首先根据 file_basename 找到对应的类
829
- matched_class = Utils::FILE_BASENAME_TO_CLASS_R3EXS.find { |pattern, _| file_basename =~ pattern }.last
830
-
831
- # 然后根据 object 的类型进行处理
832
- # 如果 object 是数组,则遍历数组,对每个元素进行处理
833
- # 如果 object 是哈希,则遍历哈希,对每个值进行处理
834
- # 如果 object 是其他类型,则直接处理
835
- if object.is_a?(Array)
836
- temp = []
837
- object.each_with_index do |obj, index|
838
- next if obj.nil?
839
- obj_r3exs = matched_class.new(obj, index, with_notes)
840
- temp << obj_r3exs unless obj_r3exs.empty?
841
- end
842
- elsif object.is_a?(Hash) # 只有 RPG::MapInfo 是Hash
843
- temp = []
844
- object.each do |key, obj|
845
- next if obj.nil?
846
- temp << matched_class.new(obj, key, with_notes)
847
- end
848
- else
849
- # 只有 RPG::Map 和 RPG::System 是单独一个对象,且不可能为 nil
850
- temp = matched_class.new(object, with_notes)
851
- end
852
- temp
853
- end
854
-
855
- # 读取 target_dir 下的所有 rvdata2 文件,将其反序列化为对象,并调用 block
856
- #
857
- # @note 注意传入 block 的 object
858
- # - 如果 object 是数组或哈希,则其中可能存在 nil 元素
859
- # - 如果 object 是单独一个对象,则不可能为 nil
860
- # @param target_dir [String] 目标目录
861
- #
862
- # @yieldparam object [Object] rvdata2 文件反序列化后的对象
863
- # @yieldparam file_basename [String] 文件名(不包含扩展名)
864
- # @yieldreturn [void]
865
- #
866
- # @raise [Rvdata2FileError] rvdata2 文件可能损坏
867
- # @raise [Rvdata2DirError] target_dir 不存在
868
- #
869
- # @return [void]
870
- def Utils.all_rvdata2_files(target_dir)
871
- # 检查 target_dir 是否存在
872
- Dir.exist?(target_dir) or raise Rvdata2DirError.new(target_dir), "rvdata2 directory not found: #{target_dir}"
873
- # 获取 target_dir 下的所有文件
874
- Dir.each_child(target_dir) do |file_name|
875
- # 检查文件名是否在 RVDATA2_FILE_NAME 中与其正则表达式匹配
876
- next unless RVDATA2_FILE_NAME.any? { |pattern| file_name =~ pattern }
877
-
878
- file_path = File.join(target_dir, file_name)
879
- print "#{ESCAPE}#{BLUE_COLOR}Reading and Deserializing from #{RESET_COLOR}#{file_path}...\r" if $global_options[:verbose]
880
- object = File.open(file_path, 'rb') { |file| Marshal.load(file) }
881
-
882
- file_basename = File.basename(file_name, '.rvdata2')
883
- # 如果文件名不是 'Scripts',则检查 object 的类型是否正确
884
- unless file_basename == 'Scripts'
885
- # 检查 object 的类型是否正确
886
- # 这里的类型检查要用紧凑模式,因为 rvdata2 文件中可能存在 nil 元素,必须忽略
887
- begin
888
- check_type(object, file_basename, true, :RPG)
889
- rescue RPGTypeError
890
- raise Rvdata2FileError.new(file_path), "Invalid rvdata2 file: #{file_path}"
891
- end
892
- end
893
-
894
- yield object, file_basename
895
- end
896
- end
897
-
898
- # 读取 target_dir 下的 JSON 所有文件,将其反序列化为对象,并调用 block
899
- #
900
- # @note 注意传入 block 的 object
901
- # - 在 module_name 为 RPG 时,如果 object 是数组或哈希,则其中可能存在 nil 元素。如果 object 是单独一个对象,则不可能为 nil
902
- # - 在 module_name 为 R3EXS 时,object 不会为 nil
903
- # @param target_dir [String] 目标目录
904
- # @param module_name [Symbol] 模块名
905
- #
906
- # @yieldparam object [Object] JSON 文件反序列化后的对象
907
- # @yieldparam file_basename [String] 文件名(不包含扩展名)
908
- # @yieldreturn [void]
909
- #
910
- # @raise [RPGJsonFileError] json 文件不是 RPG 模块中的对象
911
- # @raise [R3EXSJsonFileError] json 文件不是 R3EXS 模块中的对象
912
- # @raise [ModuleNameError] module_name 不是 :RPG 或 :R3EXS
913
- # @raise [JsonDirError] target_dir 不存在
914
- #
915
- # @return [void]
916
- def Utils.all_json_files(target_dir, module_name)
917
- # 检查 target_dir 是否存在
918
- Dir.exist?(target_dir) or raise JsonDirError.new(target_dir), "JSON directory not found: #{target_dir}"
919
- # 获取 target_dir 下的所有文件
920
- Dir.each_child(target_dir) do |file_name|
921
- # 检查文件名是否在 JSON_FILE_NAME 中与其正则表达式匹配
922
- next unless JSON_FILE_NAME.any? { |pattern| file_name =~ pattern }
923
-
924
- file_path = File.join(target_dir, file_name)
925
- print "#{ESCAPE}#{BLUE_COLOR}Reading and Deserializing #{RESET_COLOR}#{file_path}...\r" if $global_options[:verbose]
926
- object = Oj.load_file(file_path)
927
-
928
- file_basename = File.basename(file_name, '.json')
929
- case module_name
930
- when :RPG
931
- # 这里的类型检查要用紧凑模式,因为这是从 rvdata2 文件直接全部序列化后的 JSON 文件中读取的 object,其中可能存在 nil 元素
932
- begin
933
- check_type(object, file_basename, true, module_name)
934
- rescue RPGTypeError
935
- raise RPGJsonFileError.new(file_path), "Invalid RPG JSON file: #{file_path}"
936
- end
937
- when :R3EXS
938
- # 这里的类型检查不能用紧凑模式,因为这是从 R3EXS 模块的类序列化后的 JSON 文件中读取的 object,程序设计中不应该存在 nil 元素
939
- begin
940
- check_type(object, file_basename, false, module_name)
941
- rescue R3EXSTypeError
942
- raise R3EXSJsonFileError.new(file_path), "Invalid R3EXS JSON file: #{file_path}"
943
- end
944
- else
945
- raise ModuleNameError.new(module_name), "Invalid module name: #{module_name}"
946
- end
947
-
948
- yield object, file_basename
949
- end
950
- end
951
-
952
- # 将 object 序列化为 json 文件
953
- #
954
- # @param object [Object] 待序列化的对象
955
- # @param output_file [String] 输出文件路径
956
- # @return [void]
957
- def Utils.object_json(object, output_file)
958
- File.write(output_file, Oj.dump(object, indent: 2), mode: 'w')
959
- end
960
-
961
- # 将 object 序列化为 rvdata2 文件
962
- #
963
- # @param object [Object] 待序列化的对象
964
- # @param output_file [String] 输出文件路径
965
- # @return [void]
966
- def Utils.object_rvdata2(object, output_file)
967
- File.write(output_file, Marshal.dump(object), mode: 'wb')
968
- end
969
-
970
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'oj'
4
+ require_relative 'RGSS3_R3EXS'
5
+
6
+ module R3EXS
7
+
8
+ # 工具模块
9
+ # 主要用来提供一些读取,写入,转换等功能
10
+ module Utils
11
+
12
+ # 用来匹配读取的 rvdata2 文件名
13
+ RVDATA2_FILE_NAME =
14
+ [
15
+ /\AActors\.rvdata2\z/,
16
+ /\AAnimations\.rvdata2\z/,
17
+ /\AArmors\.rvdata2\z/,
18
+ /\AClasses\.rvdata2\z/,
19
+ /\ACommonEvents\.rvdata2\z/,
20
+ /\AEnemies\.rvdata2\z/,
21
+ /\AItems\.rvdata2\z/,
22
+ /\AMap\d{3}\.rvdata2\z/,
23
+ /\AMapInfos\.rvdata2\z/,
24
+ /\AScripts\.rvdata2\z/,
25
+ /\ASkills\.rvdata2\z/,
26
+ /\AStates\.rvdata2\z/,
27
+ /\ASystem\.rvdata2\z/,
28
+ /\ATilesets\.rvdata2\z/,
29
+ /\ATroops\.rvdata2\z/,
30
+ /\AWeapons\.rvdata2\z/
31
+ ]
32
+
33
+ # 用来匹配读取的 JSON 文件名
34
+ JSON_FILE_NAME =
35
+ [
36
+ /\AActors\.json\z/,
37
+ /\AAnimations\.json\z/,
38
+ /\AArmors\.json\z/,
39
+ /\AClasses\.json\z/,
40
+ /\ACommonEvents\.json\z/,
41
+ /\AEnemies\.json\z/,
42
+ /\AItems\.json\z/,
43
+ /\AMap\d{3}\.json\z/,
44
+ /\AMapInfos\.json\z/,
45
+ /\ASkills\.json\z/,
46
+ /\AStates\.json\z/,
47
+ /\ASystem\.json\z/,
48
+ /\ATilesets\.json\z/,
49
+ /\ATroops\.json\z/,
50
+ /\AWeapons\.json\z/
51
+ ]
52
+
53
+ # 用来匹配读取的文件名到对应的R3EXS的类
54
+ FILE_BASENAME_TO_CLASS_R3EXS = {
55
+ /\AActors\z/ => R3EXS::Actor,
56
+ /\AAnimations\z/ => R3EXS::Animation,
57
+ /\AArmors\z/ => R3EXS::Armor,
58
+ /\AClasses\z/ => R3EXS::Class,
59
+ /\ACommonEvents\z/ => R3EXS::CommonEvent,
60
+ /\AEnemies\z/ => R3EXS::Enemy,
61
+ /\AItems\z/ => R3EXS::Item,
62
+ /\AMap\d{3}\z/ => R3EXS::Map,
63
+ /\AMapInfos\z/ => R3EXS::MapInfo,
64
+ /\ASkills\z/ => R3EXS::Skill,
65
+ /\AStates\z/ => R3EXS::State,
66
+ /\ASystem\z/ => R3EXS::System,
67
+ /\ATilesets\z/ => R3EXS::Tileset,
68
+ /\ATroops\z/ => R3EXS::Troop,
69
+ /\AWeapons\z/ => R3EXS::Weapon
70
+ }
71
+
72
+ # 用来匹配读取的文件名到对应的RPG的类
73
+ FILE_BASENAME_TO_CLASS_RPG = {
74
+ /\AActors\z/ => RPG::Actor,
75
+ /\AAnimations\z/ => RPG::Animation,
76
+ /\AArmors\z/ => RPG::Armor,
77
+ /\AClasses\z/ => RPG::Class,
78
+ /\ACommonEvents\z/ => RPG::CommonEvent,
79
+ /\AEnemies\z/ => RPG::Enemy,
80
+ /\AItems\z/ => RPG::Item,
81
+ /\AMap\d{3}\z/ => RPG::Map,
82
+ /\AMapInfos\z/ => RPG::MapInfo,
83
+ /\ASkills\z/ => RPG::Skill,
84
+ /\AStates\z/ => RPG::State,
85
+ /\ASystem\z/ => RPG::System,
86
+ /\ATilesets\z/ => RPG::Tileset,
87
+ /\ATroops\z/ => RPG::Troop,
88
+ /\AWeapons\z/ => RPG::Weapon
89
+ }
90
+
91
+ # 事件指令的命令名称
92
+ EVENT_COMMANDS = {
93
+ 0 => 'Empty',
94
+
95
+ =begin
96
+ [string(Face Graphic name)]---[int(Face Graphic index)]---[int:{0:Normal Window, 1:Dim Background, 2:Transparent}]---[int:{0:Top, 1:Middle, 2:Bottom}]---END
97
+ =end
98
+ 101 => 'ShowTextAttributes',
99
+
100
+ =begin
101
+ [Array<string>(Choices Array)]---[int:{0:Disallow, 1:Choice 1, 2:Choice 2, 3:Choice 3, 4:Choice 4, 5:Branch}(When Cancel)]---END
102
+ =end
103
+ 102 => 'ShowChoices',
104
+
105
+ =begin
106
+ [int(Variable for Number)]---[int:{1~8}(Digits)]---END
107
+ =end
108
+ 103 => 'InputNumber',
109
+
110
+ =begin
111
+ [int(Variable for Item ID)]---END
112
+ =end
113
+ 104 => 'SelectKeyItem',
114
+
115
+ =begin
116
+ [int:{1~8}(Speed)]---[bool(No Fast Forward)]---END
117
+ =end
118
+ 105 => 'ShowScrollingTextAttributes',
119
+
120
+ =begin
121
+ [string]---END
122
+ =end
123
+ 108 => 'Comment',
124
+
125
+ =begin
126
+ |--[int:0(Switch)]---[int(Switch ID)]---[int{0:ON, 1:OFF}]---END
127
+ |
128
+ | |--[int:0(Compare to Constant)]---[int(Number)]-------|
129
+ |--[int:1(Variable)]---[int(Variable ID)]--| |--[int{0:==, 1:>=, 2:<=, 3:>, 4:<, 5:!=}]---END
130
+ | |--[int:1(Compare to Variable)]---[int(Variable ID)]--|
131
+ |
132
+ |--[int:2(Self Switch)]---[string{'A', 'B', 'C', 'D'}]---[int{0:ON, 1:OFF}]---END
133
+ |
134
+ |--[int:3(Timer)]---[int:{0~5999}(sec)]---[int{0:>=, 1:<=}]---END
135
+ |
136
+ | |--[int:0(In the Party)]---END
137
+ | |
138
+ | |--[int:1(Name)]---[string]---END
139
+ | |
140
+ | |--[int:2(Class)]---[int(Class ID)]---END
141
+ | |
142
+ |--[int:4(Actor)]---[int(Actor ID)]--------|--[int:3(Skill)]---[int(Skill ID)]---END
143
+ | |
144
+ | |--[int:4(Weapon)]---[int(Wwapon ID)]---END
145
+ | |
146
+ | |--[int:5(Armor)]---[int(Armor ID)]---END
147
+ | |
148
+ | |--[int:6(State)]---[int(State ID)]---END
149
+ |
150
+ | |--[int:0(Appeared)---END
151
+ |--[int:5(Enemy)]---[int(Enemy ID)]--------|
152
+ | |--[int:1(State)]---[int(State ID)]---END
153
+ |
154
+ |--[int:6(Character)]---[int:{-1:Player, 0:This event, 1:EV001, ...}]---[int:{2:Down, 4:Left, 6:Right, 8:Up}]---END
155
+ |
156
+ |--[int:7(Gold)]---[int(Money)]---[int{0:>=, 1:<=, 2:<}]---END
157
+ |
158
+ |--[int:8(Item)]---[int(Item ID)]---END
159
+ |
160
+ |--[int:9(Weapon)]---[int(Weapon ID)]---[bool(Include Equipments)]---END
161
+ |
162
+ |--[int:10(Armor)]---[int(Armor ID)]---[bool(Include Equipments)]---END
163
+ |
164
+ |--[int:11(Button)]---[int:{2:Down, 4:Left, 6:Right, 8:Up, 11:A, 12:B, 13:C, 14:X, 15:Y, 16:Z, 17:L, 18:R}]---END
165
+ |
166
+ |--[int:12(Script)]---[string]---END
167
+ |
168
+ |--[int:13(Vehicle)]---[int:{0:Boat, 1:Ship, 2:Airship}]---END
169
+ =end
170
+ 111 => 'ConditionalBranch',
171
+ 112 => 'Loop',
172
+ 113 => 'BreakLoop',
173
+ 115 => 'ExitEventProcessing',
174
+
175
+ =begin
176
+ [int(Common Event ID)]---END
177
+ =end
178
+ 117 => 'CallCommonEvent',
179
+
180
+ =begin
181
+ [string]---END
182
+ =end
183
+ 118 => 'Label',
184
+
185
+ =begin
186
+
187
+ [string]---END
188
+ =end
189
+ 119 => 'JumpToLabel',
190
+
191
+ =begin
192
+ [int(Switch Begin ID)]---[int(Switch End ID)]---[int:{0:ON, 1:OFF}]---END
193
+ =end
194
+ 121 => 'ControlSwitches',
195
+
196
+ =begin
197
+ |--[int:0(Constant)]---[int(Number)]---END
198
+ |
199
+ |--[int:1(Variable)]---[int(Variable ID)]---END
200
+ |
201
+ |--[int:2(Random)]---[int(Min)]---[int(Max)]---END
202
+ |
203
+ | |--[int:{0:Item, 1:Weapon, 2:Armor}]---[int(Corresponded Item ID)]---[int:0]---END
204
+ | |
205
+ [int(Variable Begin ID)]---[int(Variable End ID)]---[int:{0:Set, 1:Add, 2:Sub, 3:Mul, 4:Div, 5:Mod}]--| |--[int:3(Actor)]---[int:(Actor ID)]---[int:{0:Level, 1:EXP, 2:HP, 3:MP, 4:MHP, 5:MMP, 6:ATK, 7:DEF, 8:MAT, 9:MDF, 10:AGI, 11:LUK}]---END
206
+ | |
207
+ | |--[int:4(Enemy)]---[int:(Enemy ID)]---[int:{0:HP, 1:MP, 2:MHP, 3:MMP, 4:ATK, 5:DEF, 6:MAT, 7:MDF, 8:AGI, 9:LUK}]---END
208
+ |--[int:3(Game Data)]--|
209
+ | |--[int:5(Character)]---[int:{-1:Player, 0:This Event, 1:EV001, ...}]---[int:{0:Map X, 1:Map Y, 2:Direction, 3:Screen X ,4:Screen Y}]---END
210
+ | |
211
+ | |--[int:6(Party)]---[int:{0~7}(Member ID)]---[int:0]---END('s Actor ID)
212
+ | |
213
+ | |--[int:7(Other)]---[int:{0(Map ID), 1(Party Members), 2(Gold), 3(Steps), 4(Play Time), 5(Timer), 6(Save Count), 7(Battle Count)}]---[int:0]---END
214
+ |
215
+ |--[int:4(Scripts)]---[string]---END
216
+ =end
217
+ 122 => 'ControlVariables',
218
+
219
+ =begin
220
+ [string:{'A', 'B', 'C', 'D'}(Self Switch Name)]---[int:{0:ON, 1:OFF}]---END
221
+ =end
222
+ 123 => 'ControlSelfSwitch',
223
+
224
+ =begin
225
+ [int:{0:Start, 1:Stop}]---[int:{0~5999}(sec)]---END
226
+ =end
227
+ 124 => 'ControlTimer',
228
+
229
+ =begin
230
+ |--[int:0(Constant)]---[int:{0~9999999}(Number)]---END
231
+ [int:{0:Increase, 1:Decrease}]--|
232
+ |--[int:1(Variable)]---[int(Variable ID)]---END
233
+ =end
234
+ 125 => 'ChangeGold',
235
+
236
+ =begin
237
+ |--[int:0(Constant)]---[int:{0~9999999}(Number)]---END
238
+ [int(Item ID)]---[int:{0:Increase, 1:Decrease}]--|
239
+ |--[int:1(Variable)]---[int(Variable ID)]---END
240
+ =end
241
+ 126 => 'ChangeItems',
242
+
243
+ =begin
244
+ |--[int:0(Constant)]---[int:{0~9999999}(Number)]--|
245
+ |--[int:0(Increase)]--| |--[bool:false(Include Equipment)]---END
246
+ | |--[int:1(Variable)]---[int(Variable ID)]---------|
247
+ [int(Weapon ID)]--|
248
+ | |--[int:0(Constant)]---[int:{0~9999999}(Number)]--|
249
+ |--[int:1(Decrease)]--| |--[bool(Include Equipment)]---END
250
+ |--[int:1(Variable)]---[int(Variable ID)]---------|
251
+ =end
252
+ 127 => 'ChangeWeapons',
253
+
254
+ =begin
255
+ |--[int:0(Constant)]---[int:{0~9999999}(Number)]--|
256
+ |--[int:0(Increase)]--| |--[bool:false(Include Equipment)]---END
257
+ | |--[int:1(Variable)]---[int(Variable ID)]---------|
258
+ [int(Armor ID)]--|
259
+ | |--[int:0(Constant)]---[int:{0~9999999}(Number)]--|
260
+ |--[int:1(Decrease)]--| |--[bool(Include Equipment)]---END
261
+ |--[int:1(Variable)]---[int(Variable ID)]---------|
262
+ =end
263
+ 128 => 'ChangeArmor',
264
+
265
+ =begin
266
+ [int(Actor ID)]---[int:{0:Add, 1:Remove}]---[int:{0:NO, 1:YES}(Initialize)]---END
267
+ =end
268
+ 129 => 'ChangePartyMember',
269
+
270
+ =begin
271
+ [RPG::BGM]---END
272
+ =end
273
+ 132 => 'ChangeBattleBGM',
274
+
275
+ =begin
276
+ [RPG::ME]---END
277
+ =end
278
+ 133 => 'ChangeBattleEndME',
279
+
280
+ =begin
281
+ [int:{0:Disable, 1:Enable}]---END
282
+ =end
283
+ 134 => 'ChangeSaveAccess',
284
+
285
+ =begin
286
+ [int:{0:Disable, 1:Enable}]---END
287
+ =end
288
+ 135 => 'ChangeMenuAccess',
289
+
290
+ =begin
291
+ [int:{0:Disable, 1:Enable}]---END
292
+ =end
293
+ 136 => 'ChangeEncounter',
294
+
295
+ =begin
296
+ [int:{0:Disable, 1:Enable}]---END
297
+ =end
298
+ 137 => 'ChangeFormationAccess',
299
+
300
+ =begin
301
+ [RPG::Tone]---END
302
+ =end
303
+ 138 => 'ChangeWindowColor',
304
+
305
+ =begin
306
+ |--[int:0(Direct Designation)]---[int(Map ID)]---[int(Map X)]---[int(Map Y)]-------------------------------------------------------------------------------------|
307
+ | |--[int:{0:Retain, 2:Down, 4:Left, 6:Right, 8:Up}(Direction)]---[int:{0:Normal, 1:White, 2:None}(Fade)]---END
308
+ |--[int:1(Designation with Variables)]---[int(Map ID Corresponded Variable ID)]---[int(Map X Corresponded Variable ID)]---[int(Map Y Corresponded Variable ID)]--|
309
+ =end
310
+ 201 => 'TransferPlayer',
311
+
312
+ =begin
313
+ |--[int:0(Direct Designation)]---[int(Map ID)]---[int(Map X)]---[int(Map Y)]---END
314
+ [int:{0:Boat, 1:Ship, 2:Airship}]--|
315
+ |--[int:1(Designation with Variables)]---[int(Map ID Corresponded Variable ID)]---[int(Map X Corresponded Variable ID)]---[int(Map Y Corresponded Variable ID)]---END
316
+ =end
317
+ 202 => 'SetVehicleLocation',
318
+
319
+ =begin
320
+ |--[int:0(Direct Designation)]---[int(Map X)]---[int(Map Y)]------------------------------------------------------------|
321
+ | |
322
+ [int:{0:This Event, 1:EV001, ...}]----------|--[int:1(Designation with Variables)]---[int(Map X Corresponded Variable ID)]---[int(Map Y Corresponded Variable ID)]--|--[int:{0:Retain, 2:Down, 4:Left, 6:Right, 8:Up}(Direction)]---END
323
+ | |
324
+ |--[int:2(Exchange with Another Event)]---[int(Exchanged Event ID)]---[int:0]----------------------------------------- |
325
+ =end
326
+ 203 => 'SetEventLocation',
327
+
328
+ =begin
329
+ [int:{2:Down, 4:Left, 6:Right, 8:Up}]---[int:{0~100}(Distance)]---[int:{1:1/8 Speed, 2:1/4 Speed, 3:1/2 Speed, 4:Normal, 5:2 Speed, 6:4 Speed}]---END
330
+ =end
331
+ 204 => 'ScrollMap',
332
+
333
+ =begin
334
+ [int:{-1:Player, 0:This Event, 1:EV001, ...}]---[RPG::MoveRoute(45 is Script)]---END
335
+ =end
336
+ 205 => 'SetMoveRoute',
337
+
338
+ =begin
339
+ END
340
+ =end
341
+ 206 => 'GetSwitchVehicle',
342
+
343
+ =begin
344
+ [int:{0:ON, 1:OFF}]---END
345
+ =end
346
+ 211 => 'ChangeTransparency',
347
+
348
+ =begin
349
+ [int:{-1:Player, 0:This Event, 1:EV001, ...}]---[int(Animation ID)]---[bool(Wait for Completion)]---END
350
+ =end
351
+ 212 => 'ShowAnimation',
352
+
353
+ =begin
354
+ [int:{-1:Player, 0:This Event, 1:EV001, ...}]---[int(Ballon Icon ID)]---[bool(Wait for Completion)]---END
355
+ =end
356
+ 213 => 'ShowBalloonIcon',
357
+ 214 => 'EraseEvent',
358
+
359
+ =begin
360
+ [int:{0:ON, 1:OFF}]---END
361
+ =end
362
+ 216 => 'ChangePlayerFollowers',
363
+ 217 => 'GatherFollowers',
364
+ 221 => 'FadeoutScreen',
365
+ 222 => 'FadeinScreen',
366
+
367
+ =begin
368
+ [RPG::Tone]---[int:{0~600}(Time 1/60 sec)]---[bool(Wait for Completion)]---END
369
+ =end
370
+ 223 => 'TintScreen',
371
+
372
+ =begin
373
+ [RPG::Color]---[int:{0~600}(Time 1/60 sec)]---[bool(Wait for Completion)]---END
374
+ =end
375
+ 224 => 'FlashScreen',
376
+
377
+ =begin
378
+ [int:{1~9}(Power)]---[int:{1~9}(Speed)]---[int:{0~600}(Time 1/60 sec)]---[bool(Wait for Completion)]---END
379
+ =end
380
+ 225 => 'ShakeScreen',
381
+
382
+ =begin
383
+ [int:{0~999}(Time 1/60 sec)]---END
384
+ =end
385
+ 230 => 'Wait',
386
+
387
+ =begin
388
+ |--[int:0(Constant)]---[int:{-9999~9999}(Map X)]---[int:{-9999~9999}(Map Y)]--------------------------|
389
+ [int:{1~100}(Number)]---[string(Picture Graphic Name)]---[int:{0:Upper Left, 1:Center}(Origin)]--| |--[int:{0~2000}(Width %)]---[int:{0~2000}(Height %)]---[int:{0~255}(Opacity)]---[int:{0:Normal, 1:Add, 2:Sub}]---END
390
+ |--[int:1(Variable)]---[int(Map X Corresponded Variable ID)]---[int(Map Y Corresponded Variable ID)]--|
391
+ =end
392
+ 231 => 'ShowPicture',
393
+
394
+ =begin
395
+ |--[int:0(Constant)]---[int:{-9999~9999}(Map X)]---[int:{-9999~9999}(Map Y)]--------------------------|
396
+ [int:{1~100}(Number)]---[int:{0:Upper Left, 1:Center}(Origin)]--| |--[int:{0~2000}(Width %)]---[int:{0~2000}(Height %)]---[int:{0~255}(Opacity)]---[int:{0:Normal, 1:Add, 2:Sub}]---[int:{0~600}(Time 1/60 sec)]---[bool(Wait for Completion)]---END
397
+ |--[int:1(Variable)]---[int(Map X Corresponded Variable ID)]---[int(Map Y Corresponded Variable ID)]--|
398
+ =end
399
+ 232 => 'MovePicture',
400
+
401
+ =begin
402
+ [int:{1~100}(Number)]-[int:{-90~90}(Speed)]--END
403
+ =end
404
+ 233 => 'RotatePicture',
405
+
406
+ =begin
407
+ [int:{1~100}(Number)]---[RPG::Tone]---[int:{0~600}(Time 1/60 sec)]---[bool(Wait for Completion)]---END
408
+ =end
409
+ 234 => 'TintPicture',
410
+
411
+ =begin
412
+ [int:{1~100}(Number)]---END
413
+ =end
414
+ 235 => 'ErasePicture',
415
+
416
+ =begin
417
+ [string:{":none", ":rain", ":storm", ":snow"}]---[int:{0~9}(Power)]---[int:{0~600}(Time 1/60 sec)]---[bool(Wait for Completion)]---END
418
+ =end
419
+ 236 => 'SetWeatherEffects',
420
+
421
+ =begin
422
+ [RPG::BGM]---END
423
+ =end
424
+ 241 => 'PlayBGM',
425
+
426
+ =begin
427
+ [int:{1~60}(Time sec)]---END
428
+ =end
429
+ 242 => 'FadeoutBGM',
430
+ 243 => 'SaveBGM',
431
+ 244 => 'ReplayBGM',
432
+
433
+ =begin
434
+ [RPG::BGM]---END
435
+ =end
436
+ 245 => 'PlayBGS',
437
+
438
+ =begin
439
+ [int:{1~60}(Time sec)]---END
440
+ =end
441
+ 246 => 'FadeoutBGS',
442
+
443
+ =begin
444
+ [RPG::ME]---END
445
+ =end
446
+ 249 => 'PlayME',
447
+
448
+ =begin
449
+ [RPG::SE]---END
450
+ =end
451
+ 250 => 'PlaySE',
452
+ 251 => 'StopSE',
453
+
454
+ =begin
455
+ [string(Movie Name)]---END
456
+ =end
457
+ 261 => 'PlayMovie',
458
+
459
+ =begin
460
+ [int:{0:ON, 1:OFF}]---END
461
+ =end
462
+ 281 => 'ChangeMapNameDisplay',
463
+
464
+ =begin
465
+ [int(Tileset ID)]---END
466
+ =end
467
+ 282 => 'ChangeTileset',
468
+
469
+ =begin
470
+ [string(Floor Picture)]---[string(Wall Picture)]---END
471
+ =end
472
+ 283 => 'ChangeBattleBack',
473
+
474
+ =begin
475
+ [string(Distant view Picture)]---[bool(Loop Horizontal)]---[bool(Loop Vertical)]---[int(-32~32)(Horizontal Scroll)]---[int(-32~32)(Vertical Scrool)]---END
476
+ =end
477
+ 284 => 'ChangeParallaxBack',
478
+
479
+ =begin
480
+ |--[int:0(Direct Designation)]---[int(Map X)]---[int(Map Y)]---END
481
+ [int(Variable for Info)]---[int:{0:Terrain, 1:Event ID, 2:Tile ID(Layer 1), 3:Tile ID(Layer 2), 4:Tile ID(Layer 3), 5:Region ID}(Info Type)]--|
482
+ |--[int:1(Designation with Variables)]---[int(Map X Corresponded Variable ID)]---[int(Map Y Corresponded Variable ID)]---END
483
+ =end
484
+ 285 => 'GetLocationInfo',
485
+
486
+ =begin
487
+ |--[int:0(Direct Designation)]---[int(Enemy ID)]-----------------------------------|
488
+ | |--[bool(Can Escape)]---[bool(Continue Even When Loser)]---END
489
+ |--[int:1(Designation with Variables)]---[int(Enemy ID Corresponded Variable ID)]--|
490
+ =end
491
+ 301 => 'BattleProcessing',
492
+
493
+ =begin
494
+ |--[int:0(Price: Standard)]---[int:0]------------------|
495
+ [int:{0:Item, 1:Weapon, 2:Armor}]---[int(Corresponded Item ID)]--| |--[bool(Purchase Only)]---END
496
+ |--[int:1(Price: Specify)]---[int:{0~9999999}(Price)]--|
497
+ =end
498
+ 302 => 'ShopProcessing',
499
+
500
+ =begin
501
+ [int(Actor ID)]---[int:{1~16}(Max Characters)]---END
502
+ =end
503
+ 303 => 'NameInputProcessing',
504
+
505
+ =begin
506
+ |--[int:0(Constant)]---[int:{1~9999}(Number)]--|
507
+ |--[int:0(Increase)]--| |--[bool:false(Allow Knockout)]---END
508
+ | |--[int:1(Variable)]---[int(Variable ID)]------|
509
+ |--[int:0(Fixed)]---[int:{0:Entire Party, 1:Actor 001, ...}]--|
510
+ | | |--[int:0(Constant)]---[int:{1~9999}(Number)]--|
511
+ | |--[int:1(Decrease)]--| |--[bool(Allow Knockout)]---END
512
+ | |--[int:1(Variable)]---[int(Variable ID)]------|
513
+ |
514
+ | |--[int:0(Constant)]---[int:{1~9999}(Number)]--|
515
+ | |--[int:0(Increase)]--| |--[bool:false(Allow Knockout)]---END
516
+ | | |--[int:1(Variable)]---[int(Variable ID)]------|
517
+ |--[int:1(Variable)]---[int(Variable ID)]-----------------------|
518
+ | |--[int:0(Constant)]---[int:{1~9999}(Number)]--|
519
+ |--[int:1(Decrease)]--| |--[bool(Allow Knockout)]---END
520
+ |--[int:1(Variable)]---[int(Variable ID)]------|
521
+ =end
522
+ 311 => 'ChangeHP',
523
+
524
+ =begin
525
+ |--[int:0(Fixed)]---[int:{0:Entire Party, 1:Actor 001, ...}]--| |--[int:0(Constant)]---[int:{1~9999}(Number)]---END
526
+ | |--[int:{0:Increase, 1:Decrease}]--|
527
+ |--[int:1(Variable)]---[int(Variable ID)]---------------------| |--[int:1(Variable)]---[int(Variable ID)]---END
528
+ =end
529
+ 312 => 'ChangeMP',
530
+
531
+ =begin
532
+ |--[int:0(Fixed)]---[int:{0:Entire Party, 1:Actor 001, ...}]--|
533
+ | |--[int:{0:Add, 1:Remove}]---[int(State ID)]---END
534
+ |--[int:1(Variable)]---[int(Variable ID)]---------------------|
535
+ =end
536
+ 313 => 'ChangeState',
537
+
538
+ =begin
539
+ |--[int:0(Fixed)]---[int:{0:Entire Party, 1:Actor 001, ...}]---END
540
+ |
541
+ |--[int:1(Variable)]---[int(Variable ID)]---END
542
+ =end
543
+ 314 => 'RecoverAll',
544
+
545
+ =begin
546
+ |--[int:0(:Constant)]---[int:{1~9999999}(Number)]--|
547
+ |--[int:0(Increase)]--| |--[bool(Show Level Up Message)]---END
548
+ | |--[int:1(Variable)]---[int(Variable ID)]----------|
549
+ |--[int:0(Fixed)]---[int:{0:Entire Party, 1:Actor 001, ...}]--|
550
+ | | |--[int:0(Constant)]---[int:{1~9999999}(Number)]--|
551
+ | |--[int:1(Decrease)]--| |--[bool:false(Show Level Up Message)]---END
552
+ | |--[int:1(Variable)]------------------------------|
553
+ |
554
+ | |--[int:0(Constant)]---[int:{1~9999999}(Number)]--|
555
+ | |--[int:0(Increase)]--| |--[bool(Show Level Up Message)]---END
556
+ | | |--[int:1(Variable)]---[int(Variable ID)]---------|
557
+ |--[int:1(Variable)]---[int(Variable ID)]---------------------|
558
+ | |--[int:0(Constant)]---[int:{1~9999999}(Number)]--|
559
+ |--[int:1(Decrease)]--| |--[bool:false(Show Level Up Message)]---END
560
+ |--[int:1(Variable)]---[int(Variable ID)]---------|
561
+ =end
562
+ 315 => 'ChangeEXP',
563
+
564
+ =begin
565
+ |--[int:0(Constant)]---[int:{1~98}(Number)]--|
566
+ |--[int:0(Increase)]--| |--[bool(Show Level Up Message)]---END
567
+ | |--[int:1(Variable)]---[int(Variable ID)]----|
568
+ |--[int:0(Fixed)]---[int:{0:Entire Party, 1:Actor 001, ...}]--|
569
+ | | |--[int:0(Constant)]---[int:{1~98}(Number)]--|
570
+ | |--[int:1(Decrease)]--| |--[bool:false(Show Level Up Message)]---END
571
+ | |--[int:1(Variable)]---[int(Variable ID)]----|
572
+ |
573
+ | |--[int:0(Constant)]---[int:{1~98}(Number)]--|
574
+ | |--[int:0(Increase)]--| |--[bool(Show Level Up Message)]---END
575
+ | | |--[int:1(Variable)]---[int(Variable ID)]----|
576
+ |--[int:1(Variable)]---[int(Variable ID)]---------------------|
577
+ | |--[int:0(Constant)]---[int:{1~98}(Number)]--|
578
+ |--[int:1(Decrease)]--| |--[bool:false(Show Level Up Message)]---END
579
+ |--[int:1(Variable)]---[int(Variable ID)]------|
580
+ =end
581
+ 316 => 'ChangeLevel',
582
+
583
+ =begin
584
+ |--[int:0(Fixed)]---[int:{0:Entire Party, 1:Actor 001, ...}]--| |--[int:0(Constant)]---[int:{0~9999999}(Number)]---END
585
+ | |--[int:{0:MHP, 1:MMP, 2:ATK, 3:DEF, 4:MAT, 5:MDF, 6:AGI, 7:LUK}]---[int:{0:Increase, 1:Decrease}]--|
586
+ |--[int:1(Variable)]---[int(Variable ID)]---------------------| |--[int:1(Variable)]---[int(Variable ID)]---END
587
+ =end
588
+ 317 => 'ChangeParameters',
589
+
590
+ =begin
591
+ |--[int:0(Fixed)]---[int:{0:Entire Party, 1:Actor 001, ...}]--|
592
+ | |--[int:{0:Learn, 1:Forget}]---[int(Skill ID)]---END
593
+ |--[int:1(Variable)]---[int(Variable ID)]---------------------|
594
+ =end
595
+ 318 => 'ChangeSkills',
596
+
597
+ =begin
598
+ [int(Actor ID)]---[int:{0:Weapon, 1:Shield, 2:Head, 3:Boby, 4:Accessory}]---[int:{0:None, 1:Equipment 001, ...}(Equipment ID)]---END
599
+ =end
600
+ 319 => 'ChangeEquipment',
601
+
602
+ =begin
603
+ [int(Actor ID)]---[string(New Actor Name)]---END
604
+ =end
605
+ 320 => 'ChangeActorName',
606
+
607
+ =begin
608
+ [int(Actor ID)]---[int(New Class ID)]---END
609
+ =end
610
+ 321 => 'ChangeActorClass',
611
+
612
+ =begin
613
+ [int(Actor ID)]---[string(New Actor walking Picture Name)]---[int(New Actor Walking Picture Index)]---[string(New Actor Portrait Picture Name)]---[int(New Actor Portrait Picture Index)]---END
614
+ =end
615
+ 322 => 'ChangeActorGraphic',
616
+
617
+ =begin
618
+ [int:{0:Boat, 1:Ship, 2:Airship}]---[string(New Vehicle Picture Name)]---[int(New Vehicle Picture Index)]---END
619
+ =end
620
+ 323 => 'ChangeVehicleGraphic',
621
+
622
+ =begin
623
+ [int(Actor ID)]---[string(New Actor Nickname)]---END
624
+ =end
625
+ 324 => 'ChangeActorNickname',
626
+
627
+ =begin
628
+ |--[int:0(Constant)]---[int:{1~999999}(Number)]--|
629
+ |--[int:0(Increase)]--| |--[bool:false(Allow Knockout)]---END
630
+ | |--[int:1(Variable)]---[int(Variable ID)]--------|
631
+ [int:{-1:Entire Troop, 0:Troop 001, ...}]--|
632
+ | |--[int:0(Constant)]---[int:{1~999999}(Number)]--|
633
+ |--[int:1(Decrease)]--| |--[bool(Allow Knockout)]---END
634
+ |--[int:1(Variable)]---[int(Variable ID)]--------|
635
+
636
+ =end
637
+ 331 => 'ChangeEnemyHP',
638
+
639
+ =begin
640
+ |--[int:0(Constant)]---[int:{1~9999}(Number)]---END
641
+ [int:{-1:Entire Troop, 0:Troop 001, ...}]---[int:{0:Increase, 1:Decrease}]--|
642
+ |--[int:1(Variable)]---[int(Variable ID)]---END
643
+ =end
644
+ 332 => 'ChangeEnemyMP',
645
+
646
+ =begin
647
+ [int:{-1:Entire Troop, 0:Troop 001, ...}]---[int:{0:Add, 1:Remove}]---[int(State ID)]---END
648
+ =end
649
+ 333 => 'ChangeEnemyState',
650
+
651
+ =begin
652
+ [int:{-1:Entire Troop, 0:Troop 001, ...}]---END
653
+ =end
654
+ 334 => 'EnemyRecoverAll',
655
+
656
+ =begin
657
+ [int:{-1:Entire Troop, 0:Troop 001, ...}]---END
658
+ =end
659
+ 335 => 'EnemyAppear',
660
+
661
+ =begin
662
+ [int(Troop ID)]---[int(Enemy ID)]---END
663
+ =end
664
+ 336 => 'EnemyTransform',
665
+
666
+ =begin
667
+ [int:{-1:Entire Troop, 0:Troop 001, ...}]---[int(Animation ID)]---END
668
+ =end
669
+ 337 => 'ShowBattleAnimation',
670
+
671
+ =begin
672
+ |--[int:0(Enemy)]---[int(Troop ID)]--|
673
+ | |--[int(Skill ID)]---[int:{-2:Last Target, -1:Random, 0:Index 1,...}]---END
674
+ |--[int:1(Actor)]---[int(Actor ID)]--|
675
+ =end
676
+ 339 => 'ForceAction',
677
+ 340 => 'AbortBattle',
678
+ 351 => 'OpenMenuScreen',
679
+ 352 => 'OpenSaveScreen',
680
+ 353 => 'GameOver',
681
+ 354 => 'ReturnToTitleScreen',
682
+
683
+ =begin
684
+ [string]---END
685
+ =end
686
+ 355 => 'Script',
687
+
688
+ =begin
689
+ [string]---END
690
+ =end
691
+ 401 => 'ShowText',
692
+
693
+ =begin
694
+ [int(Choice Index)]---[string(Choice Name)]---END
695
+ =end
696
+ 402 => 'When',
697
+ 403 => 'WhenCancel',
698
+ 404 => 'ChoicesEnd',
699
+
700
+ =begin
701
+ [string]---END
702
+ =end
703
+ 405 => 'ShowScrollingText',
704
+
705
+ =begin
706
+ [string]---END
707
+ =end
708
+ 408 => 'CommentMore',
709
+ 411 => 'Else',
710
+ 412 => 'BranchEnd',
711
+ 413 => 'RepeatAbove',
712
+
713
+ =begin
714
+ [RPG::MoveCommand(45 is script)]---END
715
+ =end
716
+ 505 => 'MoveRoute',
717
+ 601 => 'IfWin',
718
+ 602 => 'IfEscape',
719
+ 603 => 'IfLose',
720
+ 604 => 'BattleProcessingEnd',
721
+
722
+ =begin
723
+ |--[int:0(Price: Standard)]---[int:0]---END
724
+ [int:{0:Item, 1:Weapon, 2:Armor}]---[int(Corresponded Item ID)]--|
725
+ |--[int:1(Price: Specify)]---[int:{0~9999999}(Price)]---END
726
+ =end
727
+ 605 => 'ShopItem',
728
+
729
+ =begin
730
+ [string]---END
731
+ =end
732
+ 655 => 'ScriptMore' }
733
+
734
+ # 红色
735
+ RED_COLOR = "\e[31m"
736
+
737
+ # 绿色
738
+ GREEN_COLOR = "\e[32m"
739
+
740
+ # 黄色
741
+ YELLOW_COLOR = "\e[33m"
742
+
743
+ # 蓝色
744
+ BLUE_COLOR = "\e[34m"
745
+
746
+ # 紫色
747
+ MAGENTA_COLOR = "\e[35m"
748
+
749
+ # 青色
750
+ CYAN_COLOR = "\e[36m"
751
+
752
+ # 重置颜色
753
+ RESET_COLOR = "\e[0m"
754
+
755
+ # 清除行
756
+ ESCAPE = "\e[2K"
757
+
758
+ # 根据 file_basename 检查 object 的类型在 module_name 中是否正确
759
+ #
760
+ # @param object [Object] 待检查的对象
761
+ # @param file_basename [String] 文件名(不包含扩展名)
762
+ # @param is_compact [Boolean] 是否为紧凑模式
763
+ # @param module_name [Symbol] 模块名
764
+ #
765
+ # @raise [RPGTypeError] object 的类型不在 RPG 模块中
766
+ # @raise [R3EXSTypeError] object 的类型不在 R3EXS 模块中
767
+ # @raise [ModuleNameError] module_name 不是 :RPG 或 :R3EXS
768
+ # @raise [FileBaseNameError] file_basename 无法匹配到对应的类
769
+ #
770
+ # @return [void]
771
+ def Utils.check_type(object, file_basename, is_compact, module_name)
772
+ case module_name
773
+ when :RPG
774
+ matched_class = FILE_BASENAME_TO_CLASS_RPG.find { |pattern, _| file_basename =~ pattern }&.last
775
+ matched_class or raise FileBaseNameError.new(file_basename), "Invalid file basename: #{file_basename}"
776
+ if object.is_a?(Array)
777
+ if is_compact
778
+ object.compact.all? { |item| item.is_a?(matched_class) } or raise RPGTypeError.new(object), "Invalid Object: #{object}, it's not an Array<#{matched_class}>"
779
+ else
780
+ object.all? { |item| item.is_a?(matched_class) } or raise RPGTypeError.new(object), "Invalid Object: #{object}, it's not an Array<#{matched_class}>"
781
+ end
782
+ elsif object.is_a?(Hash)
783
+ if is_compact
784
+ object.compact.values.all? { |item| item.is_a?(matched_class) } or raise RPGTypeError.new(object), "Invalid Object: #{object}, it's not a Hash<#{matched_class}>"
785
+ else
786
+ object.values.all? { |item| item.is_a?(matched_class) } or raise RPGTypeError.new(object), "Invalid Object: #{object}, it's not a Hash<#{matched_class}>"
787
+ end
788
+ else
789
+ object.is_a?(matched_class) or raise RPGTypeError.new(object), "Invalid Object: #{object}, it's not a #{matched_class}"
790
+ end
791
+ when :R3EXS
792
+ matched_class = FILE_BASENAME_TO_CLASS_R3EXS.find { |pattern, _| file_basename =~ pattern }&.last
793
+ matched_class or raise FileBaseNameError.new(file_basename), "Invalid file basename: #{file_basename}"
794
+ if object.is_a?(Array)
795
+ if is_compact
796
+ object.compact.all? { |item| item.is_a?(matched_class) } or raise R3EXSTypeError.new(object), "Invalid object: #{object}, it's not an Array<#{matched_class}>"
797
+ else
798
+ object.all? { |item| item.is_a?(matched_class) } or raise R3EXSTypeError.new(object), "Invalid object: #{object}, it's not an Array<#{matched_class}>"
799
+ end
800
+ elsif object.is_a?(Hash)
801
+ if is_compact
802
+ object.compact.values.all? { |item| item.is_a?(matched_class) } or raise R3EXSTypeError.new(object), "Invalid object: #{object}, it's not a Hash<#{matched_class}>"
803
+ else
804
+ object.values.all? { |item| item.is_a?(matched_class) } or raise R3EXSTypeError.new(object), "Invalid object: #{object}, it's not a Hash<#{matched_class}>"
805
+ end
806
+ else
807
+ object.is_a?(matched_class) or raise R3EXSTypeError.new(object), "Invalid object: #{object}, it's not #{matched_class}"
808
+ end
809
+ else
810
+ raise ModuleNameError.new(module_name), "Invalid module name: #{module_name}"
811
+ end
812
+
813
+ end
814
+
815
+ # 将 RPG 中的对象转化为 R3EXS 对象
816
+ #
817
+ # @param object [Object] 待转化的 RPG 对象
818
+ # @param file_basename [String] 文件名(不包含扩展名)
819
+ # @param with_notes [Boolean] 是否包含注释
820
+ #
821
+ # @raise [RPGTypeError] object 的类型不在 RPG 模块中
822
+ # @raise [FileBaseNameError] file_basename 无法匹配到对应的类
823
+ #
824
+ # @return [Object]
825
+ def Utils.rpg_r3exs(object, file_basename, with_notes)
826
+ check_type(object, file_basename, true, :RPG)
827
+
828
+ # 首先根据 file_basename 找到对应的类
829
+ matched_class = Utils::FILE_BASENAME_TO_CLASS_R3EXS.find { |pattern, _| file_basename =~ pattern }.last
830
+
831
+ # 然后根据 object 的类型进行处理
832
+ # 如果 object 是数组,则遍历数组,对每个元素进行处理
833
+ # 如果 object 是哈希,则遍历哈希,对每个值进行处理
834
+ # 如果 object 是其他类型,则直接处理
835
+ if object.is_a?(Array)
836
+ temp = []
837
+ object.each_with_index do |obj, index|
838
+ next if obj.nil?
839
+ obj_r3exs = matched_class.new(obj, index, with_notes)
840
+ temp << obj_r3exs unless obj_r3exs.empty?
841
+ end
842
+ elsif object.is_a?(Hash) # 只有 RPG::MapInfo 是Hash
843
+ temp = []
844
+ object.each do |key, obj|
845
+ next if obj.nil?
846
+ temp << matched_class.new(obj, key, with_notes)
847
+ end
848
+ else
849
+ # 只有 RPG::Map 和 RPG::System 是单独一个对象,且不可能为 nil
850
+ temp = matched_class.new(object, with_notes)
851
+ end
852
+ temp
853
+ end
854
+
855
+ # 读取 target_dir 下的所有 rvdata2 文件,将其反序列化为对象,并调用 block
856
+ #
857
+ # @note 注意传入 block 的 object
858
+ # - 如果 object 是数组或哈希,则其中可能存在 nil 元素
859
+ # - 如果 object 是单独一个对象,则不可能为 nil
860
+ # @param target_dir [String] 目标目录
861
+ #
862
+ # @yieldparam object [Object] rvdata2 文件反序列化后的对象
863
+ # @yieldparam file_basename [String] 文件名(不包含扩展名)
864
+ # @yieldreturn [void]
865
+ #
866
+ # @raise [Rvdata2FileError] rvdata2 文件可能损坏
867
+ # @raise [Rvdata2DirError] target_dir 不存在
868
+ #
869
+ # @return [void]
870
+ def Utils.all_rvdata2_files(target_dir)
871
+ # 检查 target_dir 是否存在
872
+ Dir.exist?(target_dir) or raise Rvdata2DirError.new(target_dir), "rvdata2 directory not found: #{target_dir}"
873
+ # 获取 target_dir 下的所有文件
874
+ Dir.each_child(target_dir) do |file_name|
875
+ # 检查文件名是否在 RVDATA2_FILE_NAME 中与其正则表达式匹配
876
+ next unless RVDATA2_FILE_NAME.any? { |pattern| file_name =~ pattern }
877
+
878
+ file_path = File.join(target_dir, file_name)
879
+ print "#{ESCAPE}#{BLUE_COLOR}Reading and Deserializing from #{RESET_COLOR}#{file_path}...\r" if $global_options[:verbose]
880
+ object = File.open(file_path, 'rb') { |file| Marshal.load(file) }
881
+
882
+ file_basename = File.basename(file_name, '.rvdata2')
883
+ # 如果文件名不是 'Scripts',则检查 object 的类型是否正确
884
+ unless file_basename == 'Scripts'
885
+ # 检查 object 的类型是否正确
886
+ # 这里的类型检查要用紧凑模式,因为 rvdata2 文件中可能存在 nil 元素,必须忽略
887
+ begin
888
+ check_type(object, file_basename, true, :RPG)
889
+ rescue RPGTypeError
890
+ raise Rvdata2FileError.new(file_path), "Invalid rvdata2 file: #{file_path}"
891
+ end
892
+ end
893
+
894
+ yield object, file_basename
895
+ end
896
+ end
897
+
898
+ # 读取 target_dir 下的 JSON 所有文件,将其反序列化为对象,并调用 block
899
+ #
900
+ # @note 注意传入 block 的 object
901
+ # - 在 module_name 为 RPG 时,如果 object 是数组或哈希,则其中可能存在 nil 元素。如果 object 是单独一个对象,则不可能为 nil
902
+ # - 在 module_name 为 R3EXS 时,object 不会为 nil
903
+ # @param target_dir [String] 目标目录
904
+ # @param module_name [Symbol] 模块名
905
+ #
906
+ # @yieldparam object [Object] JSON 文件反序列化后的对象
907
+ # @yieldparam file_basename [String] 文件名(不包含扩展名)
908
+ # @yieldreturn [void]
909
+ #
910
+ # @raise [RPGJsonFileError] json 文件不是 RPG 模块中的对象
911
+ # @raise [R3EXSJsonFileError] json 文件不是 R3EXS 模块中的对象
912
+ # @raise [ModuleNameError] module_name 不是 :RPG 或 :R3EXS
913
+ # @raise [JsonDirError] target_dir 不存在
914
+ #
915
+ # @return [void]
916
+ def Utils.all_json_files(target_dir, module_name)
917
+ # 检查 target_dir 是否存在
918
+ Dir.exist?(target_dir) or raise JsonDirError.new(target_dir), "JSON directory not found: #{target_dir}"
919
+ # 获取 target_dir 下的所有文件
920
+ Dir.each_child(target_dir) do |file_name|
921
+ # 检查文件名是否在 JSON_FILE_NAME 中与其正则表达式匹配
922
+ next unless JSON_FILE_NAME.any? { |pattern| file_name =~ pattern }
923
+
924
+ file_path = File.join(target_dir, file_name)
925
+ print "#{ESCAPE}#{BLUE_COLOR}Reading and Deserializing #{RESET_COLOR}#{file_path}...\r" if $global_options[:verbose]
926
+ object = Oj.load_file(file_path)
927
+
928
+ file_basename = File.basename(file_name, '.json')
929
+ case module_name
930
+ when :RPG
931
+ # 这里的类型检查要用紧凑模式,因为这是从 rvdata2 文件直接全部序列化后的 JSON 文件中读取的 object,其中可能存在 nil 元素
932
+ begin
933
+ check_type(object, file_basename, true, module_name)
934
+ rescue RPGTypeError
935
+ raise RPGJsonFileError.new(file_path), "Invalid RPG JSON file: #{file_path}"
936
+ end
937
+ when :R3EXS
938
+ # 这里的类型检查不能用紧凑模式,因为这是从 R3EXS 模块的类序列化后的 JSON 文件中读取的 object,程序设计中不应该存在 nil 元素
939
+ begin
940
+ check_type(object, file_basename, false, module_name)
941
+ rescue R3EXSTypeError
942
+ raise R3EXSJsonFileError.new(file_path), "Invalid R3EXS JSON file: #{file_path}"
943
+ end
944
+ else
945
+ raise ModuleNameError.new(module_name), "Invalid module name: #{module_name}"
946
+ end
947
+
948
+ yield object, file_basename
949
+ end
950
+ end
951
+
952
+ # 将 object 序列化为 json 文件
953
+ #
954
+ # @param object [Object] 待序列化的对象
955
+ # @param output_file [String] 输出文件路径
956
+ # @return [void]
957
+ def Utils.object_json(object, output_file)
958
+ File.write(output_file, Oj.dump(object, indent: 2), mode: 'w')
959
+ end
960
+
961
+ # 将 object 序列化为 rvdata2 文件
962
+ #
963
+ # @param object [Object] 待序列化的对象
964
+ # @param output_file [String] 输出文件路径
965
+ # @return [void]
966
+ def Utils.object_rvdata2(object, output_file)
967
+ File.write(output_file, Marshal.dump(object), mode: 'wb')
968
+ end
969
+
970
+ end
971
971
  end