ScummVM API documentation
timeline.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 /*
23  * Based on the Reverse Engineering work of Christophe Fontanel,
24  * maintainer of the Dungeon Master Encyclopaedia (http://dmweb.free.fr/)
25  */
26 
27 #ifndef DM_TIMELINE_H
28 #define DM_TIMELINE_H
29 
30 #include "dm/dm.h"
31 
32 namespace DM {
33  class Champion;
34  class Sensor;
35 
36 /* Event types */
37 enum TimelineEventType {
38 /* Used when a creature in a group was damaged or killed by a Poison Cloud or by a closing door or if Lord Chaos is surrounded by = 3, Fluxcages */
39  kDMEventTypeCreateReactionDangerOnSquare = -3, // @ CM3_EVENT_CREATE_REACTION_EVENT_29_DANGER_ON_SQUARE
40 /* Used when a projectile impacts with a creature in a group */
41  kDMEventTypeCreateReactionHitByProjectile = -2, // @ CM2_EVENT_CREATE_REACTION_EVENT_30_HIT_BY_PROJECTILE
42 /* Used when the party bumps into a group or performs a melee attack */
43  kDMEventTypeCreateReactionPartyIsAdjacent = -1, // @ CM1_EVENT_CREATE_REACTION_EVENT_31_PARTY_IS_ADJACENT
44  kDMEventTypeNone = 0, // @ C00_EVENT_NONE
45  kDMEventTypeDoorAnimation = 1, // @ C01_EVENT_DOOR_ANIMATION
46  kDMEventTypeDoorDestruction = 2, // @ C02_EVENT_DOOR_DESTRUCTION
47  kDMEventTypeCorridor = 5, // @ C05_EVENT_CORRIDOR
48  kDMEventTypeWall = 6, // @ C06_EVENT_WALL
49  kDMEventTypeFakeWall = 7, // @ C07_EVENT_FAKEWALL
50  kDMEventTypeTeleporter = 8, // @ C08_EVENT_TELEPORTER
51  kDMEventTypePit = 9, // @ C09_EVENT_PIT
52  kDMEventTypeDoor = 10, // @ C10_EVENT_DOOR
53  kDMEventTypeEnableChampionAction = 11, // @ C11_EVENT_ENABLE_CHAMPION_ACTION
54  kDMEventTypeHideDamageReceived = 12, // @ C12_EVENT_HIDE_DAMAGE_RECEIVED
55  kDMEventTypeViAltarRebirth = 13, // @ C13_EVENT_VI_ALTAR_REBIRTH
56  kDMEventTypePlaySound = 20, // @ C20_EVENT_PLAY_SOUND
57  kDMEventTypeCPSE = 22, // @ C22_EVENT_CPSE
58  kDMEventTypeRemoveFluxcage = 24, // @ C24_EVENT_REMOVE_FLUXCAGE
59  kDMEventTypeExplosion = 25, // @ C25_EVENT_EXPLOSION
60  kDMEventTypeGroupReactionDangerOnSquare = 29, // @ C29_EVENT_GROUP_REACTION_DANGER_ON_SQUARE
61  kDMEventTypeGroupReacionHitByProjectile = 30, // @ C30_EVENT_GROUP_REACTION_HIT_BY_PROJECTILE
62  kDMEventTypeGroupReactionPartyIsAdjecent = 31, // @ C31_EVENT_GROUP_REACTION_PARTY_IS_ADJACENT
63  kDMEventTypeUpdateAspectGroup = 32, // @ C32_EVENT_UPDATE_ASPECT_GROUP
64 /* Events = 33,-36 and = 38,-41 are used for individual creatures only while the group is attacking the party */
65  kDMEventTypeUpdateAspectCreature0 = 33, // @ C33_EVENT_UPDATE_ASPECT_CREATURE_0
66  kDMEventTypeUpdateAspectCreature1 = 34, // @ C34_EVENT_UPDATE_ASPECT_CREATURE_1
67  kDMEventTypeUpdateAspectCreature2 = 35, // @ C35_EVENT_UPDATE_ASPECT_CREATURE_2
68  kDMEventTypeUpdateAspectCreature3 = 36, // @ C36_EVENT_UPDATE_ASPECT_CREATURE_3
69  kDMEventTypeUpdateBehaviourGroup = 37, // @ C37_EVENT_UPDATE_BEHAVIOR_GROUP
70  kDMEventTypeUpdateBehavior0 = 38, // @ C38_EVENT_UPDATE_BEHAVIOR_CREATURE_0
71  kDMEventTypeUpdateBehavior1 = 39, // @ C39_EVENT_UPDATE_BEHAVIOR_CREATURE_1
72  kDMEventTypeUpdateBehavior2 = 40, // @ C40_EVENT_UPDATE_BEHAVIOR_CREATURE_2
73  kDMEventTypeUpdateBehavior3 = 41, // @ C41_EVENT_UPDATE_BEHAVIOR_CREATURE_3
74 /* Projectiles created by a champion (by casting a spell, shooting a weapon or throwing an object) or by a creature (by casting a spell) ignore impacts during their first movement otherwise an impact would always occur immediately as these projectiles are created on the champion or creature square */
75  kDMEventTypeMoveProjectileIgnoreImpacts = 48, // @ C48_EVENT_MOVE_PROJECTILE_IGNORE_IMPACTS
76 /* Projectiles created by projectile launcher sensors never ignore impacts as well as all other projectiles after their first movement */
77  kDMEventTypeMoveProjectile = 49, // @ C49_EVENT_MOVE_PROJECTILE
78  kDMEventTypeWatchdoge = 53, // @ C53_EVENT_WATCHDOG
79  kDMEventTypeMoveGroupSilent = 60, // @ C60_EVENT_MOVE_GROUP_SILENT
80  kDMEventTypeMoveGroupAudible = 61, // @ C61_EVENT_MOVE_GROUP_AUDIBLE
81  kDMEventTypeEnableGroupGenerator = 65, // @ C65_EVENT_ENABLE_GROUP_GENERATOR
82  kDMEventTypeLight = 70, // @ C70_EVENT_LIGHT
83  kDMEventTypeInvisibility = 71, // @ C71_EVENT_INVISIBILITY
84  kDMEventTypeChampionShield = 72, // @ C72_EVENT_CHAMPION_SHIELD
85  kDMEventTypeThievesEye = 73, // @ C73_EVENT_THIEVES_EYE
86  kDMEventTypePartyShield = 74, // @ C74_EVENT_PARTY_SHIELD
87  kDMEventTypePoisonChampion = 75, // @ C75_EVENT_POISON_CHAMPION
88  kDMEventTypeSpellShield = 77, // @ C77_EVENT_SPELLSHIELD
89  kDMEventTypeFireShield = 78, // @ C78_EVENT_FIRESHIELD
90  kDMEventTypeFootprints = 79, // @ C79_EVENT_FOOTPRINTS
91  kDMEventTypeMagicMap0 = 80, // @ C80_EVENT_MAGIC_MAP
92  kDMEventTypeMagicMap1 = 81, // @ C81_EVENT_MAGIC_MAP
93  kDMEventTypeMagicMap2 = 82, // @ C82_EVENT_MAGIC_MAP
94  kDMEventTypeMagicMap3 = 83 // @ C83_EVENT_MAGIC_MAP
95 };
96 
97 #define kDMMaskGeneratedCreatureCount 0x0007 // @ MASK0x0007_GENERATED_CREATURE_COUNT
98 #define kDMMaskRandomizeGeneratedCreatureCount 0x0008 // @ MASK0x0008_RANDOMIZE_GENERATED_CREATURE_COUNT
99 
101 public:
102  int32 _mapTime;
103  TimelineEventType _type;
104  byte _priority; // CHECKME: byte? or int16? Inconsistency in the code
105 
106  uint16 getTypePriority() { return (_type << 8) + _priority; }
107 
109  struct {
110  byte _mapX;
111  byte _mapY;
112  } _location;
113  int16 _attack;
114  int16 _defense;
115  int16 _lightPower;
116  uint16 _slot; // Thing
117  int16 _slotOrdinal;
118  };
119 
121 
122  int16 getMapXY() { return (_Bu._location._mapX << 8) + _Bu._location._mapY; }
123 
125  struct {
126  byte _cell;
127  byte _effect;
128  } A;
129 
130  class {
131  uint16 _backing;
132  public:
133  uint16 getMapX() { return _backing & 0x1F; }
134  uint16 getMapY() { return (_backing >> 5) & 0x1F; }
135  Direction getDir() { return (Direction)((_backing >> 10) & 0x3); }
136  uint16 getStepEnergy() { return (_backing >> 12) & 0xF; }
137  void setMapX(uint16 val) { _backing = (_backing & ~0x1F) | (val & 0x1F); }
138  void setMapY(uint16 val) { _backing = (_backing & ~(0x1F << 5)) | ((val & 0x1F) << 5); }
139  void setDir(Direction val) { _backing = (_backing & ~(0x3 << 10)) | ((val & 0x3) << 10); }
140  void setStepEnergy(uint16 val) { _backing = (_backing & ~(0xF << 12)) | ((val & 0xF) << 12); }
141  } _projectile;
142 
143  uint16 _slot;
144  int16 _soundIndex;
145  byte _ticks;
146  };
147 
149 }; // @ EVENT
150 
151 class Timeline {
152  DMEngine *_vm;
153 public:
154  uint16 _eventMaxCount; // @ G0369_ui_EventMaximumCount
155  TimelineEvent *_events; // @ G0370_ps_Events
156  uint16 _eventCount; // @ G0372_ui_EventCount
157  uint16 *_timeline; // @ G0371_pui_Timeline
158  uint16 _firstUnusedEventIndex; // @ G0373_ui_FirstUnusedEventIndex
159 
160  explicit Timeline(DMEngine *vm);
161  ~Timeline();
162  void initTimeline(); // @ F0233_TIMELINE_Initialize
163  void deleteEvent(uint16 eventIndex);// @ F0237_TIMELINE_DeleteEvent
164  void fixChronology(uint16 timelineIndex); // @ F0236_TIMELINE_FixChronology
165  bool isEventABeforeB(TimelineEvent *eventA, TimelineEvent *eventB); // @ F0234_TIMELINE_IsEventABeforeEventB
166  uint16 getIndex(uint16 eventIndex); // @ F0235_TIMELINE_GetIndex
167  uint16 addEventGetEventIndex(TimelineEvent *event); // @ F0238_TIMELINE_AddEvent_GetEventIndex_CPSE
168  void processTimeline(); // @ F0261_TIMELINE_Process_CPSEF
169  bool isFirstEventExpiered(); // @ F0240_TIMELINE_IsFirstEventExpired_CPSE
170  void extractFirstEvent(TimelineEvent *event); // @ F0239_TIMELINE_ExtractFirstEvent
171  void processEventDoorAnimation(TimelineEvent *event); // @ F0241_TIMELINE_ProcessEvent1_DoorAnimation
172  void processEventSquareFakewall(TimelineEvent *event); // @ F0242_TIMELINE_ProcessEvent7_Square_FakeWall
173  void processEventDoorDestruction(TimelineEvent *event); // @ F0243_TIMELINE_ProcessEvent2_DoorDestruction
174  void processEventSquareDoor(TimelineEvent *event); // @ F0244_TIMELINE_ProcessEvent10_Square_Door
175  void processEventSquarePit(TimelineEvent *event); // @ F0251_TIMELINE_ProcessEvent9_Square_Pit
176  void moveTeleporterOrPitSquareThings(uint16 mapX, uint16 mapY); // @ F0249_TIMELINE_MoveTeleporterOrPitSquareThings
177  void processEventSquareTeleporter(TimelineEvent *event); // @ F0250_TIMELINE_ProcessEvent8_Square_Teleporter
178  void processEventSquareWall(TimelineEvent *event); // @ F0248_TIMELINE_ProcessEvent6_Square_Wall
179  void triggerProjectileLauncher(Sensor *sensor, TimelineEvent *event); // @ F0247_TIMELINE_TriggerProjectileLauncher
180  void processEventSquareCorridor(TimelineEvent *event); // @ F0245_TIMELINE_ProcessEvent5_Square_Corridor
181  void processEventsMoveGroup(TimelineEvent *event); // @ F0252_TIMELINE_ProcessEvents60to61_MoveGroup
182  void procesEventEnableGroupGenerator(TimelineEvent *event); // @ F0246_TIMELINE_ProcessEvent65_EnableGroupGenerator
183  void processEventEnableChampionAction(uint16 champIndex); // @ F0253_TIMELINE_ProcessEvent11Part1_EnableChampionAction
184  void processEventMoveWeaponFromQuiverToSlot(uint16 champIndex, uint16 slotIndex);// @ F0259_TIMELINE_ProcessEvent11Part2_MoveWeaponFromQuiverToSlot
185  bool hasWeaponMovedSlot(int16 champIndex, Champion *champ,
186  uint16 sourceSlotIndex, int16 destSlotIndex); // @ F0258_TIMELINE_HasWeaponMovedToSlot
187  void processEventHideDamageReceived(uint16 champIndex); // @ F0254_TIMELINE_ProcessEvent12_HideDamageReceived
188  void processEventLight(TimelineEvent *event); // @ F0257_TIMELINE_ProcessEvent70_Light
189  void refreshAllChampionStatusBoxes(); // @ F0260_TIMELINE_RefreshAllChampionStatusBoxes
190  void processEventViAltarRebirth(TimelineEvent *event); // @ F0255_TIMELINE_ProcessEvent13_ViAltarRebirth
191  void saveEventsPart(Common::OutSaveFile *file);
192  void saveTimelinePart(Common::OutSaveFile *file);
193  void loadEventsPart(Common::InSaveFile *file);
194  void loadTimelinePart(Common::InSaveFile *file);
195 
196  signed char _actionDefense[44]; // @ G0495_ac_Graphic560_ActionDefense
197 
198  void initConstants();
199 };
200 
201 }
202 
203 #endif
Definition: savefile.h:54
Definition: stream.h:745
Definition: timeline.h:100
Definition: champion.h:35
Definition: timeline.h:124
Definition: timeline.h:108
Definition: dungeonman.h:377
Definition: dm.h:155
Definition: champion.h:398
Definition: timeline.h:151