ScummVM API documentation
script.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef HARVESTER_SCRIPT_H
23 #define HARVESTER_SCRIPT_H
24 
25 #include "common/array.h"
26 #include "common/str.h"
27 #include "harvester/monster.h"
28 
29 namespace Common {
30 class Serializer;
31 }
32 
33 namespace Harvester {
34 
35 class ResourceManager;
36 
38  int posX = 0;
39  int posY = 0;
40  int posZ = 0;
41  int facing = -1;
42  Common::String direction;
43  Common::String roomName;
44  Common::String entranceName;
45 };
46 
48  int mapX = 0;
49  int mapY = 0;
50  int initialPanelIndex = 0;
51  Common::String entryName;
52 };
53 
55  int minX = 0;
56  int minY = 0;
57  int maxX = 0;
58  int maxY = 0;
59  int panelIndex = 0;
60  int labelX = 0;
61  int labelY = 0;
62  Common::String labelText;
63  Common::String destinationEntranceName;
64 };
65 
66 struct RoomRecord {
67  int minZ = 0;
68  int maxZ = 0;
69  int maxZScreenY = 0;
70  int minZScreenY = 0;
71  int fullScaleZ = 0;
72  int maxZScalePercent = 100;
73  float perspectiveScale = 0.0f;
74  float zVelocityStep = 1.0f;
75  Common::String roomName;
76  Common::String musicPath;
77  Common::String reservedString38;
78  Common::String reservedString3c;
79  Common::String reservedString40;
80  Common::String palettePath;
81  Common::String onEnterCommand;
82  Common::String onExitCommand;
83  bool dimmable = false;
84 };
85 
86 struct ObjectRecord {
87  int initialX = 0;
88  int initialY = 0;
89  int initialZ = 0;
90  int currentX = 0;
91  int currentY = 0;
92  int currentZ = 0;
93  int boundsX2 = 0;
94  int boundsY2 = 0;
95  int zExtent = 0;
96  Common::String actionTag;
97  Common::String spritePath;
98  Common::String altSpritePath;
99  Common::String objectName;
100  Common::String reservedXFlag;
101  Common::String identTextKey;
102  Common::String currentOwnerOrRoom;
103  Common::String reservedString40;
104  Common::String inventoryTextKey;
105  Common::String initialOwnerOrRoom;
106  Common::String interactionLabel;
107  bool operatable = false;
108  bool visible = false;
109  bool runtimeVisible = false;
110  bool identShown = false;
111 };
112 
113 struct AnimRecord {
114  int x = 0;
115  int y = 0;
116  int z = 0;
117  int frameDelay = 0;
118  Common::String roomName;
119  Common::String resourcePath;
120  Common::String animName;
121  bool active = false;
122  bool visible = false;
123  bool looping = false;
124  bool backward = false;
125  bool pingPong = false;
126  bool remove = false;
127  bool runtimeActive = false;
128  bool runtimeVisible = false;
129  int runtimeState = -1;
130 };
131 
132 struct NpcRecord {
133  int posX = 0;
134  int posY = 0;
135  int posZ = 0;
136  int frameDelay = 0;
137  Common::String onDeathActionTag;
138  Common::String modelPath;
139  Common::String npcName;
140  Common::String monsterfyTargetName;
141  Common::String roomName;
142  bool deathOrMonsterfyFlag = false;
143  bool runtimeSpawned = false;
144  int runtimeState = -1;
145  bool active = false;
146  bool visible = false;
147  bool savedVisible = false;
148  int deathDamageType = 0;
149  Common::String audioPath;
150  Common::String entityInitArg;
151 };
152 
153 struct TimerRecord {
154  int initialValue = 0;
155  int currentValue = 0;
156  Common::String timerName;
157  Common::String arg1;
158  Common::String arg2;
159  bool enabled = false;
160  bool looping = false;
161  bool global = false;
162 };
163 
164 struct RegionRecord {
165  int left = 0;
166  int top = 0;
167  int right = 0;
168  int bottom = 0;
169  int minZ = 0;
170  int maxZ = 0;
171  int desiredFacing = -1;
172  Common::String regionName;
173  Common::String direction;
174  Common::String roomName;
175  Common::String actionTag;
176  bool startEnabled = false;
177  bool cursorEnabled = false;
178 };
179 
180 struct FlagRecord {
181  Common::String name;
182  bool value = false;
183 };
184 
186  Common::String triggerTag;
187  Common::String opcodeName;
188  Common::String arg1;
189  Common::String arg2;
190  Common::String arg3;
191  Common::String arg4;
192 };
193 
195  Common::String listName;
197 };
198 
199 struct TextRecord {
200  Common::String key;
201  Common::String boxName;
202  Common::String value;
203 };
204 
205 struct HeadRecord {
206  Common::String headId;
207  Common::String portraitPath;
208 };
209 
211  Common::String itemName;
212  Common::String ownerOrRoom;
213  Common::String targetName;
214  Common::String actionTag;
215 };
216 
217 enum StartupDialogueTextMode {
218  kStartupDialogueTextNone = 0,
219  kStartupDialogueTextYes = 1,
220  kStartupDialogueTextClick = 2
221 };
222 
223 enum StartupAudioCommandType {
224  kStartupAudioCommandStartWav,
225  kStartupAudioCommandStartSingleWav,
226  kStartupAudioCommandLoadWav,
227  kStartupAudioCommandPlayWav,
228  kStartupAudioCommandDeleteWav
229 };
230 
231 struct AudioCommand {
232  StartupAudioCommandType type = kStartupAudioCommandStartWav;
233  Common::String path;
234  int slot = -1;
235 };
236 
238  Common::String entranceName;
239  Common::String roomName;
240  Common::String backgroundObjectName;
241  Common::String palettePath;
242  Common::String backgroundPath;
243  Common::String musicPath;
244  int discNumber = 0;
245  int roomMinZ = 0;
246  int roomMaxZ = 0;
247  int roomMaxZScreenY = 0;
248  int roomMinZScreenY = 0;
249  int roomFullScaleZ = 0;
250  int roomMaxZScalePercent = 100;
251  float roomPerspectiveScale = 0.0f;
252  float roomZVelocityStep = 1.0f;
253  bool hasEntrance = false;
254  int playerSpawnX = 0;
255  int playerSpawnY = 0;
256  int playerSpawnZ = 0;
257  int playerFacing = -1;
258  float paletteBrightness = 1.0f;
259  Common::Array<ObjectRecord> activeObjects;
260  Common::Array<ObjectRecord> roomObjects;
261  Common::Array<AnimRecord> roomAnimations;
262  Common::Array<NpcRecord> roomNpcs;
263  Common::Array<MonsterRecord> roomMonsters;
264  Common::Array<TimerRecord> roomTimers;
265  Common::Array<RegionRecord> roomRegions;
266  Common::Array<AudioCommand> audioCommands;
267 };
268 
269 enum StartupRoomTransitionKind {
270  kStartupRoomTransitionNone = 0,
271  kStartupRoomTransitionChangeRoom,
272  kStartupRoomTransitionCloseup
273 };
274 
275 enum StartupLightingCommand {
276  kStartupLightingCommandNone = 0,
277  kStartupLightingCommandDim,
278  kStartupLightingCommandNormal,
279  kStartupLightingCommandBlack,
280  kStartupLightingCommandFadeIn
281 };
282 
283 struct ResolvedText {
284  Common::String boxName;
285  Common::String value;
286 };
287 
289  Common::String musicPath;
290  Common::String nextRoomName;
291  Common::String cutscenePath;
292  Common::String deathFlicPath;
293  Common::String dialogueNpcName;
294  Common::String dialogueContinuationTag;
295  Common::String continuationTag;
296  Common::String moveEntityToPlayerZName;
297  ResolvedText modalText;
298  Common::Array<AudioCommand> audioCommands;
299  Common::Array<TimerRecord> previousTimerRecords;
300  StartupRoomTransitionKind roomTransition = kStartupRoomTransitionNone;
301  StartupLightingCommand lightingCommand = kStartupLightingCommandNone;
302  int cdChangeDisc = 0;
303  int playerDeathDamageType = 0;
304  int playerGotoX = 0;
305  int playerGotoZ = 0;
306  bool requestPlayerDeath = false;
307  bool requestPlayerGotoXZ = false;
308  bool requestPlayerGotoZ = false;
309  bool requestRoomRestart = false;
310  Common::String roomRestartTargetName;
311  bool requestCloseupExit = false;
312  bool requestMainMenu = false;
313  bool requestDemoEnding = false;
314  bool abortRemainingCommandChain = false;
315  bool mutatedRuntimeState = false;
316  bool visualRuntimeStateChanged = false;
317 };
318 
319 class Script {
320 public:
321  static const int kDefaultPlayerHitPoints = 30;
322 
323  bool load(ResourceManager &resources);
324  bool reloadTownWorld(ResourceManager &resources);
325 
326  const Common::String &getPath() const { return _path; }
327  const Common::Array<byte> &getData() const { return _data; }
328  const Common::Array<EntranceRecord> &getEntrances() const { return _entrances; }
329  const Common::Array<MapEntranceRecord> &getMapEntrances() const { return _mapEntrances; }
330  const Common::Array<MapLocationRecord> &getMapLocations() const { return _mapLocations; }
331  const Common::Array<RoomRecord> &getRooms() const { return _rooms; }
332  const Common::Array<ObjectRecord> &getObjects() const { return _objects; }
333  const Common::Array<AnimRecord> &getAnimations() const { return _animations; }
334  const Common::Array<NpcRecord> &getNpcs() const { return _npcs; }
335  const Common::Array<MonsterRecord> &getMonsters() const { return _monsters; }
336  const Common::Array<TimerRecord> &getTimers() const { return _timers; }
337  const Common::Array<RegionRecord> &getRegions() const { return _regions; }
338  const Common::Array<FlagRecord> &getFlags() const { return _flags; }
339  const Common::Array<CommandRecord> &getCommands() const { return _commands; }
340  const Common::Array<ExecListRecord> &getExecLists() const { return _execLists; }
341  const Common::Array<TextRecord> &getTexts() const { return _texts; }
342  const Common::Array<HeadRecord> &getHeads() const { return _heads; }
343  const Common::Array<UseItemRecord> &getUseItems() const { return _useItems; }
344  bool isQuickTipsEnabled() const { return _quickTipsEnabled; }
345  void setQuickTipsEnabled(bool enabled) { _quickTipsEnabled = enabled; }
346  const Common::String &getVoicePath() const { return _voicePath; }
347  bool isGoreEnabled() const { return _goreEnabled; }
348  void setGoreEnabled(bool enabled) { _goreEnabled = enabled; }
349  StartupDialogueTextMode getDialogueTextMode() const { return _dialogueTextMode; }
350  void setDialogueTextMode(StartupDialogueTextMode mode) { _dialogueTextMode = mode; }
351  int getFxVolumeLevel() const { return _fxVolumeLevel; }
352  void setFxVolumeLevel(int level);
353  int getMusicVolumeLevel() const { return _musicVolumeLevel; }
354  void setMusicVolumeLevel(int level);
355  int getGammaLevel() const { return _gammaLevel; }
356  void setGammaLevel(int level);
357  const Common::String &getParentalPassword() const { return _parentalPassword; }
358  void setParentalPassword(const Common::String &password) { _parentalPassword = password; }
359  bool saveConfig() const;
360  void resetRuntimeState();
361  void syncRuntimeSaveState(Common::Serializer &s);
362  bool resolveRoomSetupState(const Common::String &entranceName, RoomSetupState &state,
363  ResourceManager &resources);
364  bool resolveRoomSetupStateByRoomName(const Common::String &roomName, RoomSetupState &state,
365  ResourceManager &resources);
366  bool materializeRoomState(const Common::String &entranceName, const Common::String &roomName,
367  RoomSetupState &state, ResourceManager &resources) const;
368  bool hasRoomSetupTarget(const Common::String &entranceName, const Common::String &roomName) const;
369  bool executeRoomEnterCommands(const Common::String &roomName, InteractionResult &result);
370  bool executeRoomExitCommands(const Common::String &roomName, InteractionResult &result);
371  bool resolveObjectInteraction(const ObjectRecord &object, InteractionResult &result,
372  const Common::String &roomName = Common::String());
373  bool resolveRegionInteraction(const RegionRecord &region, InteractionResult &result,
374  const Common::String &roomName = Common::String());
375  bool resolveUseItemInteraction(const Common::String &itemName, const ObjectRecord &target,
376  InteractionResult &result, const Common::String &roomName = Common::String());
377  bool executeDebugCommand(const CommandRecord &command, InteractionResult &result,
378  bool allowTransitions = true);
379  bool executeActionTag(const Common::String &tag, InteractionResult &result,
380  bool allowTransitions = true, const Common::String &roomName = Common::String());
381  bool executeTimerAction(const Common::String &timerName, InteractionResult &result,
382  bool allowTransitions = true, const Common::String &roomName = Common::String());
383  bool executeNestedActionTag(const Common::String &tag, InteractionResult &result,
384  bool allowTransitions = true);
385  bool isPickupObject(const ObjectRecord &object) const;
386  bool isPickupBlockedByAction(const ObjectRecord &object,
387  InteractionResult *result = nullptr) const;
388  bool hasObjectInteraction(const ObjectRecord &object) const;
389  bool hasUseItemInteraction(const Common::String &itemName, const ObjectRecord &target) const;
390  void getVisibleInventoryObjects(Common::Array<ObjectRecord> &objects) const;
391  bool isObjectInInventory(const Common::String &objectName) const;
392  void markObjectIdentShown(const ObjectRecord &object);
393  bool resolveObjectInspectText(const ObjectRecord &object, ResolvedText &text) const;
394  bool resolveTextRecord(const Common::String &key, ResolvedText &text) const;
395  Common::String resolveInventoryTooltipText(const ObjectRecord &object) const;
396  Common::String resolveObjectLabel(const ObjectRecord &object) const;
397  Common::String resolveTextValue(const Common::String &key) const;
398  const HeadRecord *findHeadRecord(const Common::String &headId) const;
399  const EntranceRecord *findEntranceRecord(const Common::String &entranceName) const;
400  const MapEntranceRecord *findMapEntranceRecord(const Common::String &entryName) const;
401  bool getFlagValue(const Common::String &flagName) const;
402  const TimerRecord *findRuntimeTimerRecord(const Common::String &timerName) const;
403  const NpcRecord *findRuntimeNpcRecord(const Common::String &npcName) const;
404  bool setRuntimeFlagValue(const Common::String &flagName, bool value);
405  bool resetRuntimeObjectToInitialState(const Common::String &objectName);
406  bool addRuntimeObjectToInventory(const Common::String &objectName);
407  bool syncRuntimeObjectRecord(const ObjectRecord &object);
408  bool setRuntimeObjectVisible(const Common::String &ownerOrRoom, const Common::String &objectName,
409  bool visible);
410  bool setRuntimeNpcState(const Common::String &npcName, bool active, bool visible);
411  bool queueRuntimeNpcDeathOrMonsterfy(const Common::String &npcName, int deathDamageType = 0);
412  enum { kNoMonsterfyPosZOverride = 0x7fffffff };
413  bool finalizeRuntimeNpcDeathOrMonsterfy(const Common::String &npcName, int deathDamageType = 0,
414  bool preserveCorpse = false, int corpseFrame = -1,
415  int monsterfyPosZ = kNoMonsterfyPosZOverride);
416  void pushDeferredLiveNpcDeathTransitions();
417  void popDeferredLiveNpcDeathTransitions();
418  bool isNamedNpcDeathTypeClear(const Common::String &npcName) const;
419  int getCurrentStoryDayIndex() const;
420  int getPlayerCurrentHitPoints() const { return _playerCurrentHitPoints; }
421  int getPlayerCombatLoadout() const { return _playerCombatLoadout; }
422  int getPlayerCombatResourceCount(int loadout) const;
423  bool consumePlayerCombatResourceUnit(int loadout);
424  bool isPlayerControlPaused() const { return _playerControlPaused; }
425  bool adjustPlayerCurrentHitPoints(int delta);
426  bool setPlayerCombatLoadout(int loadout);
427  bool setPlayerControlPaused(bool paused);
428  bool syncRuntimeAnimState(const Common::String &animName, bool active, bool visible, int currentFrame);
429  bool syncRuntimeMonsterRecord(const MonsterRecord &monster);
430  bool syncRuntimeTimerRecord(const TimerRecord &timer);
431  bool setRuntimeRegionEnabled(const Common::String &regionName, bool enabled);
432  bool setRuntimeTimerEnabled(const Common::String &timerName, bool enabled);
433 
434 private:
435  bool loadConfig(ResourceManager &resources);
436  void decode();
437  void parseTownRecords(ResourceManager &resources);
438  const RoomRecord *findRoomRecord(const Common::String &roomName) const;
439  const CommandRecord *findCommandRecord(const Common::String &tag) const;
440  const ExecListRecord *findExecListRecord(const Common::String &name) const;
441  const TextRecord *findTextRecord(const Common::String &key) const;
442  const UseItemRecord *findUseItemRecord(const Common::String &itemName,
443  const ObjectRecord &target) const;
444  const FlagRecord *findRuntimeFlag(const Common::String &flagName) const;
445  FlagRecord *findRuntimeFlag(const Common::String &flagName);
446  ObjectRecord *findRuntimeObject(const Common::String &ownerOrRoom, const Common::String &objectName);
447  AnimRecord *findRuntimeAnim(const Common::String &animName);
448  RegionRecord *findRuntimeRegion(const Common::String &regionName);
449  NpcRecord *findRuntimeNpc(const Common::String &npcName);
450  const NpcRecord *findRuntimeNpc(const Common::String &npcName) const;
451  MonsterRecord *findRuntimeMonster(const Common::String &monsterName);
452  const MonsterRecord *findRuntimeMonster(const Common::String &monsterName) const;
453  MonsterRecord *findRuntimeMonster(const MonsterRecord &monster);
454  const MonsterRecord *findRuntimeMonster(const MonsterRecord &monster) const;
455  const MonsterRecord *findBaseMonster(const MonsterRecord &monster) const;
456  TimerRecord *findRuntimeTimer(const Common::String &timerName);
457  const TimerRecord *findRuntimeTimer(const Common::String &timerName) const;
458  bool buildRuntimeRoomState(const RoomRecord &room, const EntranceRecord *entrance,
459  ResourceManager &resources, RoomSetupState &state) const;
460  void executeCommandChain(const Common::String &initialTag, const char *contextLabel,
461  const Common::String &contextName, const Common::String &contextRoomName,
462  bool allowTransitions, Common::String *musicPath,
463  Common::Array<AudioCommand> *audioCommands, Common::String *nextRoomName,
464  StartupRoomTransitionKind *roomTransition,
465  Common::String *cutscenePath, Common::String *deathFlicPath, bool *requestMainMenu,
466  bool *requestDemoEnding,
467  int *cdChangeDisc,
468  Common::String *dialogueNpcName, Common::String *dialogueContinuationTag,
469  Common::String *continuationTag, ResolvedText *modalText,
470  StartupLightingCommand *lightingCommand, Common::String *moveEntityToPlayerZName,
471  bool *requestPlayerGotoXZ, bool *requestPlayerGotoZ,
472  int *playerGotoX, int *playerGotoZ,
473  bool *requestPlayerDeath, int *playerDeathDamageType,
474  bool *mutatedRuntimeState, bool *visualRuntimeStateChanged,
475  Common::Array<TimerRecord> *previousTimerRecords, bool *requestCloseupExit);
476  bool probePickupBlockingCommandChain(const Common::String &initialTag,
477  const Common::String &contextName, InteractionResult &result, uint recursionDepth) const;
478  bool hasActionableCommandChain(const Common::String &initialTag) const;
479  bool setPlayerCurrentHitPoints(int hitPoints);
480  int *getPlayerCombatResourceCountPtr(int loadout);
481  const int *getPlayerCombatResourceCountPtr(int loadout) const;
482  bool adjustPlayerCombatResourceCount(int loadout, int delta, int maxCount,
483  const Common::String &reason);
484  void logRuntimeSaveState(const char *operation) const;
485 
486  Common::String _path;
487  Common::Array<byte> _data;
489  Common::Array<MapEntranceRecord> _mapEntrances;
490  Common::Array<MapLocationRecord> _mapLocations;
493  Common::Array<AnimRecord> _animations;
504  Common::Array<FlagRecord> _currentFlags;
505  Common::Array<ObjectRecord> _currentObjects;
506  Common::Array<AnimRecord> _currentAnimations;
507  Common::Array<RegionRecord> _currentRegions;
508  Common::Array<NpcRecord> _currentNpcs;
509  Common::Array<MonsterRecord> _currentMonsters;
510  Common::Array<TimerRecord> _currentTimers;
511  int _nailgunAmmoCount = 0;
512  int _shotgunShellCount = 0;
513  int _nineGunBulletCount = 0;
514  int _thirtyEightGunBulletCount = 0;
515  int _chainsawFuelCount = 0;
516  int _playerCurrentHitPoints = 30;
517  int _playerCombatLoadout = 0;
518  bool _playerControlPaused = false;
519  int _fxVolumeLevel = 9;
520  int _musicVolumeLevel = 3;
521  int _gammaLevel = 0;
522  bool _quickTipsEnabled = true;
523  bool _goreEnabled = true;
524  Common::String _voicePath = "SOUND/VOICE/";
525  Common::String _parentalPassword;
526  Common::String _savePath = "./";
527  Common::String _townPath = "HARVEST.SCR";
528  Common::String _cdRomPath;
529  Common::String _drive1Path;
530  Common::String _drive2Path;
531  Common::String _drive3Path;
532  StartupDialogueTextMode _dialogueTextMode = kStartupDialogueTextYes;
533  int _deferredLiveNpcDeathTransitionDepth = 0;
534 };
535 
536 } // End of namespace Harvester
537 
538 #endif // HARVESTER_SCRIPT_H
Definition: script.h:237
Definition: str.h:59
Definition: script.h:37
Definition: art.h:31
Definition: script.h:132
Definition: script.h:319
Definition: script.h:185
Definition: script.h:153
Definition: script.h:210
Definition: script.h:86
Definition: script.h:66
Definition: script.h:199
Definition: serializer.h:80
Definition: script.h:194
Definition: script.h:205
Definition: script.h:283
Definition: algorithm.h:29
Definition: script.h:231
Definition: script.h:47
Definition: script.h:113
Definition: script.h:180
Definition: resources.h:32
Definition: script.h:164
Definition: monster.h:31
Definition: script.h:288
Definition: script.h:54