1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
|
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* Based on the Reverse Engineering work of Christophe Fontanel,
* maintainer of the Dungeon Master Encyclopaedia (http://dmweb.free.fr/)
*/
#ifndef DM_GROUP_H
#define DM_GROUP_H
#include "dm/dm.h"
namespace DM {
class Champion;
class TimelineEvent;
class CreatureInfo;
// this doesn't seem to be used anywhere at all
/* Creature types */
enum CreatureType {
k0_CreatureTypeGiantScorpionScorpion = 0, // @ C00_CREATURE_GIANT_SCORPION_SCORPION
k1_CreatureTypeSwampSlimeSlime = 1, // @ C01_CREATURE_SWAMP_SLIME_SLIME_DEVIL
k2_CreatureTypeGiggler = 2, // @ C02_CREATURE_GIGGLER
k3_CreatureTypeWizardEyeFlyingEye = 3, // @ C03_CREATURE_WIZARD_EYE_FLYING_EYE
k4_CreatureTypePainRatHellHound = 4, // @ C04_CREATURE_PAIN_RAT_HELLHOUND
k5_CreatureTypeRuster = 5, // @ C05_CREATURE_RUSTER
k6_CreatureTypeScreamer = 6, // @ C06_CREATURE_SCREAMER
k7_CreatureTypeRockpile = 7, // @ C07_CREATURE_ROCK_ROCKPILE
k8_CreatureTypeGhostRive = 8, // @ C08_CREATURE_GHOST_RIVE
k9_CreatureTypeStoneGolem = 9, // @ C09_CREATURE_STONE_GOLEM
k10_CreatureTypeMummy = 10, // @ C10_CREATURE_MUMMY
k11_CreatureTypeBlackFlame = 11, // @ C11_CREATURE_BLACK_FLAME
k12_CreatureTypeSkeleton = 12, // @ C12_CREATURE_SKELETON
k13_CreatureTypeCouatl = 13, // @ C13_CREATURE_COUATL
k14_CreatureTypeVexirk = 14, // @ C14_CREATURE_VEXIRK
k15_CreatureTypeMagnetaWormWorm = 15, // @ C15_CREATURE_MAGENTA_WORM_WORM
k16_CreatureTypeTrolinAntman = 16, // @ C16_CREATURE_TROLIN_ANTMAN
k17_CreatureTypeGiantWaspMuncher = 17, // @ C17_CREATURE_GIANT_WASP_MUNCHER
k18_CreatureTypeAnimatedArmourDethKnight = 18, // @ C18_CREATURE_ANIMATED_ARMOUR_DETH_KNIGHT
k19_CreatureTypeMaterializerZytaz = 19, // @ C19_CREATURE_MATERIALIZER_ZYTAZ
k20_CreatureTypeWaterElemental = 20, // @ C20_CREATURE_WATER_ELEMENTAL
k21_CreatureTypeOitu = 21, // @ C21_CREATURE_OITU
k22_CreatureTypeDemon = 22, // @ C22_CREATURE_DEMON
k23_CreatureTypeLordChaos = 23, // @ C23_CREATURE_LORD_CHAOS
k24_CreatureTypeRedDragon = 24, // @ C24_CREATURE_RED_DRAGON
k25_CreatureTypeLordOrder = 25, // @ C25_CREATURE_LORD_ORDER
k26_CreatureTypeGreyLord = 26, // @ C26_CREATURE_GREY_LORD
k255_CreatureTypeSingleCenteredCreature = 255 // @ C255_SINGLE_CENTERED_CREATURE
};
#define k0_MaskCreatureSizeQuarter 0 // @ C0_SIZE_QUARTER_SQUARE
#define k1_MaskCreatureSizeHalf 1 // @ C1_SIZE_HALF_SQUARE
#define k2_MaskCreatureSizeFull 2 // @ C2_SIZE_FULL_SQUARE
#define k0x0003_MaskCreatureInfo_size 0x0003 // @ MASK0x0003_SIZE
#define k0x0004_MaskCreatureInfo_sideAttack 0x0004 // @ MASK0x0004_SIDE_ATTACK
#define k0x0008_MaskCreatureInfo_preferBackRow 0x0008 // @ MASK0x0008_PREFER_BACK_ROW
#define k0x0010_MaskCreatureInfo_attackAnyChamp 0x0010 // @ MASK0x0010_ATTACK_ANY_CHAMPION
#define k0x0020_MaskCreatureInfo_levitation 0x0020 // @ MASK0x0020_LEVITATION
#define k0x0040_MaskCreatureInfo_nonMaterial 0x0040 // @ MASK0x0040_NON_MATERIAL
#define k0x0200_MaskCreatureInfo_dropFixedPoss 0x0200 // @ MASK0x0200_DROP_FIXED_POSSESSIONS
#define k0x0400_MaskCreatureInfo_keepThrownSharpWeapon 0x0400 // @ MASK0x0400_KEEP_THROWN_SHARP_WEAPONS
#define k0x0800_MaskCreatureInfo_seeInvisible 0x0800 // @ MASK0x0800_SEE_INVISIBLE
#define k0x1000_MaskCreatureInfo_nightVision 0x1000 // @ MASK0x1000_NIGHT_VISION
#define k0x2000_MaskCreatureInfo_archenemy 0x2000 // @ MASK0x2000_ARCHENEMY
#define k0x4000_MaskCreatureInfo_magicmap 0x4000 // @ MASK0x4000_MAGICMAP
#define k0x0040_MaskActiveGroupFlipBitmap 0x0040 // @ MASK0x0040_FLIP_BITMAP
#define k0x0080_MaskActiveGroupIsAttacking 0x0080 // @ MASK0x0080_IS_ATTACKING
class ActiveGroup {
public:
int16 _groupThingIndex;
Direction _directions;
byte _cells;
byte _lastMoveTime;
byte _delayFleeingFromTarget;
byte _targetMapX;
byte _targetMapY;
byte _priorMapX;
byte _priorMapY;
byte _homeMapX;
byte _homeMapY;
byte _aspect[4];
}; // @ ACTIVE_GROUP
class Group {
public:
Thing _nextThing;
Thing _slot;
uint16 _type;
uint16 _cells;
uint16 _health[4];
uint16 _flags;
public:
explicit Group(uint16 *rawDat) : _nextThing(rawDat[0]), _slot(rawDat[1]), _type(rawDat[2]),
_cells(rawDat[3]), _flags(rawDat[8]) {
_health[0] = rawDat[4];
_health[1] = rawDat[5];
_health[2] = rawDat[6];
_health[3] = rawDat[7];
}
uint16 &getActiveGroupIndex() { return _cells; }
uint16 getBehaviour() { return _flags & 0xF; }
uint16 setBehaviour(uint16 val) { _flags = (_flags & ~0xF) | (val & 0xF); return (val & 0xF); }
uint16 getCount() { return (_flags >> 5) & 0x3; }
void setCount(uint16 val) { _flags = (_flags & ~(0x3 << 5)) | ((val & 0x3) << 5); }
Direction getDir() { return (Direction)((_flags >> 8) & 0x3); }
void setDir(uint16 val) { _flags = (_flags & ~(0x3 << 8)) | ((val & 0x3) << 8); }
uint16 getDoNotDiscard() { return (_flags >> 10) & 0x1; }
void setDoNotDiscard(bool val) { _flags = (_flags & ~(1 << 10)) | ((val & 1) << 10); }
}; // @ GROUP
#define k0_behavior_WANDER 0 // @ C0_BEHAVIOR_WANDER
#define k2_behavior_USELESS 2 // @ C2_BEHAVIOR_USELESS
#define k3_behavior_USELESS 3 // @ C3_BEHAVIOR_USELESS
#define k4_behavior_USELESS 4 // @ C4_BEHAVIOR_USELESS
#define k5_behavior_FLEE 5 // @ C5_BEHAVIOR_FLEE
#define k6_behavior_ATTACK 6 // @ C6_BEHAVIOR_ATTACK
#define k7_behavior_APPROACH 7 // @ C7_BEHAVIOR_APPROACH
#define k15_immuneToFear 15 // @ C15_IMMUNE_TO_FEAR
#define k255_immobile 255 // @ C255_IMMOBILE
#define kM1_wholeCreatureGroup -1 // @ CM1_WHOLE_CREATURE_GROUP
int32 M32_setTime(int32 &map_time, int32 time); // @ M32_SET_TIME
class GroupMan {
DMEngine *_vm;
byte _dropMovingCreatureFixedPossessionsCell[4]; // @ G0392_auc_DropMovingCreatureFixedPossessionsCells
uint16 _dropMovingCreatureFixedPossCellCount; // @ G0391_ui_DropMovingCreatureFixedPossessionsCellCount
uint16 _fluxCageCount; // @ G0386_ui_FluxCageCount
int16 _fluxCages[4]; // @ G0385_ac_FluxCages
int16 _currentGroupMapX; // @ G0378_i_CurrentGroupMapX
int16 _currentGroupMapY; // @ G0379_i_CurrentGroupMapY
Thing _currGroupThing; // @ G0380_T_CurrentGroupThing
int16 _groupMovementTestedDirections[4]; // @ G0384_auc_GroupMovementTestedDirections
uint16 _currGroupDistanceToParty; // @ G0381_ui_CurrentGroupDistanceToParty
int16 _currGroupPrimaryDirToParty; // @ G0382_i_CurrentGroupPrimaryDirectionToParty
int16 _currGroupSecondaryDirToParty; // @ G0383_i_CurrentGroupSecondaryDirectionToParty
Thing _groupMovementBlockedByGroupThing; // @ G0388_T_GroupMovementBlockedByGroupThing
bool _groupMovementBlockedByDoor; // @ G0389_B_GroupMovementBlockedByDoor
bool _groupMovementBlockedByParty; // @ G0390_B_GroupMovementBlockedByParty
bool _groupMovBlockedByWallStairsPitFakeWalFluxCageTeleporter; // @ G0387_B_GroupMovementBlockedByWallStairsPitFakeWallFluxcageTeleporter
int32 twoHalfSquareSizedCreaturesGroupLastDirectionSetTime; // @ G0395_l_TwoHalfSquareSizedCreaturesGroupLastDirectionSetTime
uint16 toggleFlag(uint16 &val, uint16 mask); // @ M10_TOGGLE
public:
uint16 _maxActiveGroupCount; // @ G0376_ui_MaximumActiveGroupCount
ActiveGroup *_activeGroups; // @ G0375_ps_ActiveGroups
uint16 _currActiveGroupCount; // @ G0377_ui_CurrentActiveGroupCount
explicit GroupMan(DMEngine *vm);
~GroupMan();
void initActiveGroups(); // @ F0196_GROUP_InitializeActiveGroups
uint16 getGroupCells(Group *group, int16 mapIndex); // @ F0145_DUNGEON_GetGroupCells
uint16 getGroupDirections(Group *group, int16 mapIndex); // @ F0147_DUNGEON_GetGroupDirections
int16 getCreatureOrdinalInCell(Group *group, uint16 cell); // @ F0176_GROUP_GetCreatureOrdinalInCell
uint16 getCreatureValue(uint16 groupVal, uint16 creatureIndex); // @ M50_CREATURE_VALUE
void dropGroupPossessions(int16 mapX, int16 mapY, Thing groupThing, int16 mode); // @ F0188_GROUP_DropGroupPossessions
void dropCreatureFixedPossessions(uint16 creatureType, int16 mapX, int16 mapY, uint16 cell,
int16 mode); // @ F0186_GROUP_DropCreatureFixedPossessions
int16 getDirsWhereDestIsVisibleFromSource(int16 srcMapX, int16 srcMapY,
int16 destMapX, int16 destMapY); // @ F0228_GROUP_GetDirectionsWhereDestinationIsVisibleFromSource
bool isDestVisibleFromSource(uint16 dir, int16 srcMapX, int16 srcMapY, int16 destMapX,
int16 destMapY); // @ F0227_GROUP_IsDestinationVisibleFromSource
bool groupIsDoorDestoryedByAttack(uint16 mapX, uint16 mapY, int16 attack,
bool magicAttack, int16 ticks); // @ F0232_GROUP_IsDoorDestroyedByAttack
Thing groupGetThing(int16 mapX, int16 mapY); // @ F0175_GROUP_GetThing
int16 groupGetDamageCreatureOutcome(Group *group, uint16 creatureIndex,
int16 mapX, int16 mapY, int16 damage, bool notMoving); // @ F0190_GROUP_GetDamageCreatureOutcome
void groupDelete(int16 mapX, int16 mapY); // @ F0189_GROUP_Delete
void groupDeleteEvents(int16 mapX, int16 mapY); // @ F0181_GROUP_DeleteEvents
uint16 getGroupValueUpdatedWithCreatureValue(uint16 groupVal, uint16 creatureIndex, uint16 creatureVal); // @ F0178_GROUP_GetGroupValueUpdatedWithCreatureValue
int16 getDamageAllCreaturesOutcome(Group *group, int16 mapX, int16 mapY, int16 attack, bool notMoving); // @ F0191_GROUP_GetDamageAllCreaturesOutcome
int16 groupGetResistanceAdjustedPoisonAttack(uint16 creatreType, int16 poisonAttack); // @ F0192_GROUP_GetResistanceAdjustedPoisonAttack
void processEvents29to41(int16 eventMapX, int16 eventMapY, int16 eventType, uint16 ticks); // @ F0209_GROUP_ProcessEvents29to41
bool isMovementPossible(CreatureInfo *creatureInfo, int16 mapX, int16 mapY,
uint16 dir, bool allowMovementOverImaginaryPitsAndFakeWalls); // @ F0202_GROUP_IsMovementPossible
int16 getDistanceBetweenSquares(int16 srcMapX, int16 srcMapY, int16 destMapX,
int16 destMapY); // @ F0226_GROUP_GetDistanceBetweenSquares
int16 groupGetDistanceToVisibleParty(Group *group, int16 creatureIndex, int16 mapX, int16 mapY); // @ F0200_GROUP_GetDistanceToVisibleParty
int16 getDistanceBetweenUnblockedSquares(int16 srcMapX, int16 srcMapY,
int16 destMapX, int16 destMapY, bool (GroupMan::*isBlocked)(uint16, uint16)); // @ F0199_GROUP_GetDistanceBetweenUnblockedSquares
bool isViewPartyBlocked(uint16 mapX, uint16 mapY); // @ F0197_GROUP_IsViewPartyBlocked
int32 getCreatureAspectUpdateTime(ActiveGroup *activeGroup, int16 creatureIndex,
bool isAttacking); // @ F0179_GROUP_GetCreatureAspectUpdateTime
void setGroupDirection(ActiveGroup *activeGroup, int16 dir, int16 creatureIndex, bool twoHalfSquareSizedCreatures); // @ F0205_GROUP_SetDirection
void addGroupEvent(TimelineEvent *event, uint32 time); // @ F0208_GROUP_AddEvent
int16 getSmelledPartyPrimaryDirOrdinal(CreatureInfo *creatureInfo, int16 mapY, int16 mapX); // @ F0201_GROUP_GetSmelledPartyPrimaryDirectionOrdinal
bool isSmellPartyBlocked(uint16 mapX, uint16 mapY); // @ F0198_GROUP_IsSmellPartyBlocked
int16 getFirstPossibleMovementDirOrdinal(CreatureInfo *info, int16 mapX, int16 mapY,
bool allowMovementOverImaginaryPitsAndFakeWalls); // @ F0203_GROUP_GetFirstPossibleMovementDirectionOrdinal
void setDirGroup(ActiveGroup *activeGroup, int16 dir, int16 creatureIndex,
int16 creatureSize); // @ F0206_GROUP_SetDirectionGroup
void stopAttacking(ActiveGroup *group, int16 mapX, int16 mapY);// @ F0182_GROUP_StopAttacking
bool isArchenemyDoubleMovementPossible(CreatureInfo *info, int16 mapX, int16 mapY, uint16 dir); // @ F0204_GROUP_IsArchenemyDoubleMovementPossible
bool isCreatureAttacking(Group *group, int16 mapX, int16 mapY, uint16 creatureIndex); // @ F0207_GROUP_IsCreatureAttacking
void setOrderedCellsToAttack(signed char *orderedCellsToAttack, int16 targetMapX,
int16 targetMapY, int16 attackerMapX, int16 attackerMapY, uint16 cellSource); // @ F0229_GROUP_SetOrderedCellsToAttack
void stealFromChampion(Group *group, uint16 championIndex); // @ F0193_GROUP_StealFromChampion
int16 getChampionDamage(Group *group, uint16 champIndex); // @ F0230_GROUP_GetChampionDamage
void dropMovingCreatureFixedPossession(Thing thing, int16 mapX, int16 mapY); // @ F0187_GROUP_DropMovingCreatureFixedPossessions
void startWandering(int16 mapX, int16 mapY); // @ F0180_GROUP_StartWandering
void addActiveGroup(Thing thing, int16 mapX, int16 mapY); // @ F0183_GROUP_AddActiveGroup
void removeActiveGroup(uint16 activeGroupIndex); // @ F0184_GROUP_RemoveActiveGroup
void removeAllActiveGroups(); // @ F0194_GROUP_RemoveAllActiveGroups
void addAllActiveGroups(); // @ F0195_GROUP_AddAllActiveGroups
Thing groupGetGenerated(int16 creatureType, int16 healthMultiplier, uint16 creatureCount, Direction dir, int16 mapX, int16 mapY); // @ F0185_GROUP_GetGenerated
bool isSquareACorridorTeleporterPitOrDoor(int16 mapX, int16 mapY); // @ F0223_GROUP_IsSquareACorridorTeleporterPitOrDoor
int16 getMeleeTargetCreatureOrdinal(int16 groupX, int16 groupY, int16 partyX, int16 paryY,
uint16 champCell); // @ F0177_GROUP_GetMeleeTargetCreatureOrdinal
int16 getMeleeActionDamage(Champion *champ, int16 champIndex, Group *group, int16 creatureIndex,
int16 mapX, int16 mapY, uint16 actionHitProbability, uint16 actionDamageFactor, int16 skillIndex); // @ F0231_GROUP_GetMeleeActionDamage
void fluxCageAction(int16 mapX, int16 mapY); // @ F0224_GROUP_FluxCageAction
uint16 isLordChaosOnSquare(int16 mapX, int16 mapY); // @ F0222_GROUP_IsLordChaosOnSquare
bool isFluxcageOnSquare(int16 mapX, int16 mapY); // @ F0221_GROUP_IsFluxcageOnSquare
void fuseAction(uint16 mapX, uint16 mapY); // @ F0225_GROUP_FuseAction
void saveActiveGroupPart(Common::OutSaveFile *file);
void loadActiveGroupPart(Common::InSaveFile *file);
};
}
#endif
|