aboutsummaryrefslogtreecommitdiff
path: root/engines/dm/group.h
blob: ad68a032169341fba6402d569c7972fd5be3da2a (plain)
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
255
256
257
258
259
260
261
/* 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 

enum SoundMode {
	kDMSoundModeDoNotPlaySound = -1, // @ CM1_MODE_DO_NOT_PLAY_SOUND
	kDMSoundModePlayImmediately = 0, // @ C00_MODE_PLAY_IMMEDIATELY
	kDMSoundModePlayIfPrioritized = 1, // @ C01_MODE_PLAY_IF_PRIORITIZED
	kDMSoundModePlayOneTickLater = 2 // @ C02_MODE_PLAY_ONE_TICK_LATER
};

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, SoundMode mode); // @ F0188_GROUP_DropGroupPossessions
	void dropCreatureFixedPossessions(uint16 creatureType, int16 mapX, int16 mapY, uint16 cell,
										   SoundMode soundMode); // @ 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