1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 2010-2019 EDuke32 developers and contributors
4 Copyright (C) 2019 Nuke.YKT
5 Copyright (C) NoOne
6 
7 This file is part of NBlood.
8 
9 NBlood is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License version 2
11 as published by the Free Software Foundation.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 
17 See the GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22 */
23 //-------------------------------------------------------------------------
24 
25 
26 ////////////////////////////////////////////////////////////////////////////////////
27 // This file provides modern features for mappers.
28 // For full documentation please visit http://cruo.bloodgame.ru/xxsystem
29 /////////////////////////////////////////////////////////////////////////
30 
31 
32 #ifdef NOONE_EXTENSIONS
33 #pragma once
34 #include "common_game.h"
35 #include "eventq.h"
36 #include "qav.h"
37 #include "actor.h"
38 #include "dude.h"
39 #include "player.h"
40 #include "warp.h"
41 #include "triggers.h"
42 
43 // CONSTANTS
44 // additional non-thing proximity, sight and physics sprites
45 #define kMaxSuperXSprites 128
46 #define kMaxTrackingConditions 64
47 #define kMaxTracedObjects 32 // per one tracking condition
48 
49 // additional physics attributes for debris sprites
50 #define kPhysDebrisFloat 0x0008 // *debris* slowly goes up and down from it's position
51 #define kPhysDebrisFly 0x0010 // *debris* affected by negative gravity (fly instead of falling)
52 #define kPhysDebrisSwim 0x0020 // *debris* can swim underwater (instead of drowning)
53 #define kPhysDebrisTouch 0x0040 // *debris* can be moved via touch
54 //#define kPhysDebrisPush 0x0080 // *debris* can be moved via push
55 #define kPhysDebrisVector 0x0400 // *debris* can be affected by vector weapons
56 #define kPhysDebrisExplode 0x0800 // *debris* can be affected by explosions
57 
58 // *modern types only hitag*
59 #define kModernTypeFlag0 0x0000
60 #define kModernTypeFlag1 0x0001
61 #define kModernTypeFlag2 0x0002
62 #define kModernTypeFlag3 0x0003
63 #define kModernTypeFlag4 0x0004
64 
65 #define kMaxRandomizeRetries 16
66 #define kPercFull 100
67 #define kCondRange 100
68 
69 #define kPatrolStateSize 27
70 #define kMaxPatrolVelocity 500000
71 #define kMaxPatrolCrouchVelocity kMaxPatrolVelocity >> 1
72 #define kMaxPatrolSpotValue 500
73 
74 #define kDudeFlagStealth    0x0001
75 #define kDudeFlagCrouch     0x0002
76 
77 #define kSlopeDist 0x20
78 
79 // modern statnums
80 enum {
81 kStatModernBase                     = 20,
82 kStatModernDudeTargetChanger        = kStatModernBase,
83 kStatModernCondition                = 21,
84 kStatModernEventRedirector          = 22,
85 kStatModernPlayerLinker             = 23,
86 kStatModernBrokenDudeLeech          = 24,
87 kStatModernQavScene                 = 25,
88 kStatModernTmp                      = 39,
89 kStatModernMax                      = 40,
90 };
91 
92 // modern sprite types
93 enum {
94 kModernSlopeChanger                 = 16,
95 kModernCustomDudeSpawn              = 24,
96 kModernRandomTX                     = 25,
97 kModernSequentialTX                 = 26,
98 kModernSeqSpawner                   = 27,
99 kModernObjPropertiesChanger         = 28,
100 kModernObjPicnumChanger             = 29,
101 kModernObjSizeChanger               = 31,
102 kModernDudeTargetChanger            = 33,
103 kModernSectorFXChanger              = 34,
104 kModernObjDataChanger               = 35,
105 kModernSpriteDamager                = 36,
106 kModernObjDataAccumulator           = 37,
107 kModernEffectSpawner                = 38,
108 kModernWindGenerator                = 39,
109 kModernRandom                       = 40,
110 kModernRandom2                      = 80,
111 kItemShroomGrow                     = 129,
112 kItemShroomShrink                   = 130,
113 kItemModernMapLevel                 = 150,  // once picked up, draws whole minimap
114 kDudeModernCustom                   = kDudeVanillaMax,
115 kDudeModernCustomBurning            = 255,
116 kModernThingTNTProx                 = 433, // detects only players
117 kModernThingThrowableRock           = 434, // does small damage if hits target
118 kModernThingEnemyLifeLeech          = 435, // the same as normal, except it aims in specified target only
119 kModernPlayerControl                = 500, /// WIP
120 kModernCondition                    = 501, /// WIP, sends command only if specified conditions == true
121 kModernConditionFalse               = 502, /// WIP, sends command only if specified conditions != true
122 kGenModernMissileUniversal          = 704,
123 kGenModernSound                     = 708,
124 };
125 
126 // type of random
127 enum {
128 kRandomizeItem                      = 0,
129 kRandomizeDude                      = 1,
130 kRandomizeTX                        = 2,
131 };
132 
133 // type of object
134 enum {
135 OBJ_WALL                            = 0,
136 OBJ_SPRITE                          = 3,
137 OBJ_SECTOR                          = 6,
138 };
139 
140 enum {
141 kCondMixedBase                      = 100,
142 kCondMixedMax                       = 200,
143 kCondWallBase                       = 200,
144 kCondWallMax                        = 300,
145 kCondSectorBase                     = 300,
146 kCondSectorMax                      = 400,
147 kCondPlayerBase                     = 400,
148 kCondPlayerMax                      = 450,
149 kCondDudeBase                       = 450,
150 kCondDudeMax                        = 500,
151 kCondSpriteBase                     = 500,
152 kCondSpriteMax                      = 600,
153 };
154 
155 enum {
156 kCondSerialSector                   = 10000,
157 kCondSerialWall                     = 20000,
158 kCondSerialSprite                   = 30000,
159 kCondSerialMax                      = 40000,
160 };
161 
162 // - STRUCTS ------------------------------------------------------------------
163 struct SPRITEMASS { // sprite mass info for getSpriteMassBySize();
164     int seqId;
165     short picnum; // mainly needs for moving debris
166     short xrepeat;
167     short yrepeat;
168     short clipdist; // mass multiplier
169     int mass;
170     short airVel; // mainly needs for moving debris
171     int fraction; // mainly needs for moving debris
172 };
173 
174 struct QAVSCENE { // this one stores qavs anims that can be played by trigger
175     short index = -1;  // index of sprite which triggered qav scene
176     QAV* qavResrc = NULL;
177     short dummy = -1;
178 };
179 
180 struct THINGINFO_EXTRA {
181     bool allowThrow; // indicates if kDudeModernCustom can throw it
182 };
183 
184 struct VECTORINFO_EXTRA {
185     int fireSound[2]; // predefined fire sounds. used by kDudeModernCustom, but can be used for something else.
186 };
187 
188 struct MISSILEINFO_EXTRA {
189     int fireSound[2]; // predefined fire sounds. used by kDudeModernCustom, but can be used for something else.
190     bool dmgType[kDamageMax]; // list of damages types missile can use
191     bool allowImpact; // allow to trigger object with Impact flag enabled with this missile
192 };
193 
194 struct DUDEINFO_EXTRA {
195     bool flying;                    // used by kModernDudeTargetChanger (ai fight)
196     bool melee;                     // used by kModernDudeTargetChanger (ai fight)
197     int idlgseqofs : 6;             // used for patrol
198     int mvegseqofs : 6;             // used for patrol
199     int idlwseqofs : 6;             // used for patrol
200     int mvewseqofs : 6;             // used for patrol
201     int idlcseqofs : 6;             // used for patrol
202     int mvecseqofs : 6;             // used for patrol
203 };
204 
205 struct TRPLAYERCTRL { // this one for controlling the player using triggers (movement speed, jumps and other stuff)
206     QAVSCENE qavScene;
207 };
208 
209 struct OBJECTS_TO_TRACK {
210     signed int type:     3;
211     unsigned int index:  16;
212     unsigned int cmd:    8;
213 };
214 
215 struct TRCONDITION {
216     signed   int xindex:    16;
217     unsigned int length:    8;
218     OBJECTS_TO_TRACK obj[kMaxTracedObjects];
219 };
220 
221 // - VARIABLES ------------------------------------------------------------------
222 extern bool gTeamsSpawnUsed;
223 extern bool gEventRedirectsUsed;
224 extern ZONE gStartZoneTeam1[kMaxPlayers];
225 extern ZONE gStartZoneTeam2[kMaxPlayers];
226 extern THINGINFO_EXTRA gThingInfoExtra[kThingMax];
227 extern VECTORINFO_EXTRA gVectorInfoExtra[kVectorMax];
228 extern MISSILEINFO_EXTRA gMissileInfoExtra[kMissileMax];
229 extern DUDEINFO_EXTRA gDudeInfoExtra[kDudeMax];
230 extern TRPLAYERCTRL gPlayerCtrl[kMaxPlayers];
231 extern SPRITEMASS gSpriteMass[kMaxXSprites];
232 extern TRCONDITION gCondition[kMaxTrackingConditions];
233 extern short gProxySpritesList[kMaxSuperXSprites];
234 extern short gSightSpritesList[kMaxSuperXSprites];
235 extern short gPhysSpritesList[kMaxSuperXSprites];
236 extern short gImpactSpritesList[kMaxSuperXSprites];
237 extern short gProxySpritesCount;
238 extern short gSightSpritesCount;
239 extern short gPhysSpritesCount;
240 extern short gImpactSpritesCount;
241 extern short gTrackingCondsCount;
242 extern AISTATE genPatrolStates[kPatrolStateSize];
243 
244 // - FUNCTIONS ------------------------------------------------------------------
245 bool nnExtEraseModernStuff(spritetype* pSprite, XSPRITE* pXSprite);
246 void nnExtInitModernStuff(bool bSaveLoad);
247 void nnExtProcessSuperSprites(void);
248 bool nnExtIsImmune(spritetype* pSprite, int dmgType, int minScale = 16);
249 int nnExtRandom(int a, int b);
250 void nnExtResetGlobals();
251 void nnExtTriggerObject(int objType, int objIndex, int command);
252 //  -------------------------------------------------------------------------   //
253 spritetype* randomDropPickupObject(spritetype* pSprite, short prevItem);
254 spritetype* randomSpawnDude(spritetype* pSprite);
255 int GetDataVal(spritetype* pSprite, int data);
256 int randomGetDataValue(XSPRITE* pXSprite, int randType);
257 void sfxPlayMissileSound(spritetype* pSprite, int missileId);
258 void sfxPlayVectorSound(spritetype* pSprite, int vectorId);
259 //  -------------------------------------------------------------------------   //
260 int debrisGetIndex(int nSprite);
261 int debrisGetFreeIndex(void);
262 void debrisBubble(int nSprite);
263 void debrisMove(int listIndex);
264 void debrisConcuss(int nOwner, int listIndex, int x, int y, int z, int dmg);
265 //  -------------------------------------------------------------------------   //
266 void aiSetGenIdleState(spritetype* pSprite, XSPRITE* pXSprite);
267 
268 // triggers related
269 //  -------------------------------------------------------------------------   //
270 int aiFightGetTargetDist(spritetype* pSprite, DUDEINFO* pDudeInfo, spritetype* pTarget);
271 int aiFightGetFineTargetDist(spritetype* pSprite, spritetype* pTarget);
272 bool aiFightDudeCanSeeTarget(XSPRITE* pXDude, DUDEINFO* pDudeInfo, spritetype* pTarget);
273 bool aiFightUnitCanFly(spritetype* pDude);
274 bool aiFightIsMeleeUnit(spritetype* pDude);
275 bool aiFightDudeIsAffected(XSPRITE* pXDude);
276 bool aiFightMatesHaveSameTarget(XSPRITE* pXLeader, spritetype* pTarget, int allow);
277 bool aiFightGetDudesForBattle(XSPRITE* pXSprite);
278 bool aiFightIsMateOf(XSPRITE* pXDude, XSPRITE* pXSprite);
279 void aiFightAlarmDudesInSight(spritetype* pSprite, int max);
280 void aiFightActivateDudes(int rx);
281 void aiFightFreeTargets(int nSprite);
282 void aiFightFreeAllTargets(XSPRITE* pXSource);
283 spritetype* aiFightGetTargetInRange(spritetype* pSprite, int minDist, int maxDist, short data, short teamMode);
284 spritetype* aiFightTargetIsPlayer(XSPRITE* pXSprite);
285 spritetype* aiFightGetMateTargets(XSPRITE* pXSprite);
286 //  -------------------------------------------------------------------------   //
287 void useSlopeChanger(XSPRITE* pXSource, int objType, int objIndex);
288 void useSectorWindGen(XSPRITE* pXSource, sectortype* pSector);
289 void useEffectGen(XSPRITE* pXSource, spritetype* pSprite);
290 void useSeqSpawnerGen(XSPRITE* pXSource, int objType, int index);
291 void damageSprites(XSPRITE* pXSource, spritetype* pSprite);
292 void useTeleportTarget(XSPRITE* pXSource, spritetype* pSprite);
293 void useObjResizer(XSPRITE* pXSource, short objType, int objIndex);
294 void useRandomItemGen(spritetype* pSource, XSPRITE* pXSource);
295 void useUniMissileGen(int, int nXSprite);
296 void useSoundGen(XSPRITE* pXSource, spritetype* pSprite);
297 void useIncDecGen(XSPRITE* pXSource, short objType, int objIndex);
298 void useDataChanger(XSPRITE* pXSource, int objType, int objIndex);
299 void useSectorLigthChanger(XSPRITE* pXSource, XSECTOR* pXSector);
300 void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite);
301 void usePictureChanger(XSPRITE* pXSource, int objType, int objIndex);
302 void usePropertiesChanger(XSPRITE* pXSource, short objType, int objIndex);
303 void useSequentialTx(XSPRITE* pXSource, COMMAND_ID cmd, bool setState);
304 void useRandomTx(XSPRITE* pXSource, COMMAND_ID cmd, bool setState);
305 bool txIsRanged(XSPRITE* pXSource);
306 void seqTxSendCmdAll(XSPRITE* pXSource, int nIndex, COMMAND_ID cmd, bool modernSend);
307 //  -------------------------------------------------------------------------   //
308 void trPlayerCtrlLink(XSPRITE* pXSource, PLAYER* pPlayer, bool checkCondition);
309 void trPlayerCtrlSetRace(XSPRITE* pXSource, PLAYER* pPlayer);
310 void trPlayerCtrlStartScene(XSPRITE* pXSource, PLAYER* pPlayer, bool force);
311 void trPlayerCtrlStopScene(PLAYER* pPlayer);
312 void trPlayerCtrlSetMoveSpeed(XSPRITE* pXSource, PLAYER* pPlayer);
313 void trPlayerCtrlSetJumpHeight(XSPRITE* pXSource, PLAYER* pPlayer);
314 void trPlayerCtrlSetScreenEffect(XSPRITE* pXSource, PLAYER* pPlayer);
315 void trPlayerCtrlSetLookAngle(XSPRITE* pXSource, PLAYER* pPlayer);
316 void trPlayerCtrlEraseStuff(XSPRITE* pXSource, PLAYER* pPlayer);
317 void trPlayerCtrlGiveStuff(XSPRITE* pXSource, PLAYER* pPlayer, TRPLAYERCTRL* pCtrl);
318 void trPlayerCtrlUsePackItem(XSPRITE* pXSource, PLAYER* pPlayer, int evCmd);
319 //  -------------------------------------------------------------------------   //
320 void modernTypeTrigger(int type, int nDest, EVENT event);
321 char modernTypeSetSpriteState(int nSprite, XSPRITE* pXSprite, int nState);
322 bool modernTypeOperateSector(int nSector, sectortype* pSector, XSECTOR* pXSector, EVENT event);
323 bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite, EVENT event);
324 bool modernTypeOperateWall(int nWall, walltype* pWall, XWALL* pXWall, EVENT event);
325 void modernTypeSendCommand(int nSprite, int channel, COMMAND_ID command);
326 //  -------------------------------------------------------------------------   //
327 bool playerSizeShrink(PLAYER* pPlayer, int divider);
328 bool playerSizeGrow(PLAYER* pPlayer, int multiplier);
329 bool playerSizeReset(PLAYER* pPlayer);
330 void playerDeactivateShrooms(PLAYER* pPlayer);
331 //  -------------------------------------------------------------------------   //
332 QAV* playerQavSceneLoad(int qavId);
333 void playerQavSceneProcess(PLAYER* pPlayer, QAVSCENE* pQavScene);
334 void playerQavScenePlay(PLAYER* pPlayer);
335 void playerQavSceneDraw(PLAYER* pPlayer, int a2, int a3, int a4, int a5);
336 void playerQavSceneReset(PLAYER* pPlayer);
337 //  -------------------------------------------------------------------------   //
338 void callbackUniMissileBurst(int nSprite);
339 void callbackMakeMissileBlocking(int nSprite);
340 void callbackGenDudeUpdate(int nSprite);
341 //  -------------------------------------------------------------------------   //
342 PLAYER* getPlayerById(short id);
343 bool isGrown(spritetype* pSprite);
344 bool isShrinked(spritetype* pSprite);
345 bool valueIsBetween(int val, int min, int max);
346 bool IsBurningDude(spritetype* pSprite);
347 bool IsKillableDude(spritetype* pSprite);
348 bool isActive(int nSprite);
349 int getDataFieldOfObject(int objType, int objIndex, int dataIndex);
350 bool setDataValueOfObject(int objType, int objIndex, int dataIndex, int value);
351 bool incDecGoalValueIsReached(XSPRITE* pXSprite);
352 void windGenStopWindOnSectors(XSPRITE* pXSource);
353 int getSpriteMassBySize(spritetype* pSprite);
354 bool ceilIsTooLow(spritetype* pSprite);
355 void levelEndLevelCustom(int nLevel);
356 int useCondition(spritetype* pSource, XSPRITE* pXSource, EVENT event);
357 bool condPush(XSPRITE* pXSprite, int objType, int objIndex);
358 bool condRestore(XSPRITE* pXSprite);
359 bool condCmp(int val, int arg1, int arg2, int comOp);
360 bool condCmpne(int arg1, int arg2, int comOp);
361 void condError(XSPRITE* pXCond, const char* pzFormat, ...);
362 bool condCheckMixed(XSPRITE* pXCond, EVENT event, int cmpOp, bool PUSH);
363 bool condCheckSector(XSPRITE* pXCond, int cmpOp, bool PUSH);
364 bool condCheckWall(XSPRITE* pXCond, int cmpOp, bool PUSH);
365 bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH);
366 bool condCheckPlayer(XSPRITE* pXCond, int cmpOp, bool PUSH);
367 bool condCheckDude(XSPRITE* pXCond, int cmpOp, bool PUSH);
368 void condUpdateObjectIndex(int objType, int oldIndex, int newIndex);
369 XSPRITE* evrListRedirectors(int objType, int objXIndex, XSPRITE* pXRedir, int* tx);
370 XSPRITE* evrIsRedirector(int nSprite);
371 int listTx(XSPRITE* pXRedir, int tx);
372 void seqSpawnerOffSameTx(XSPRITE* pXSource);
373 //  -------------------------------------------------------------------------   //
374 void aiPatrolSetMarker(spritetype* pSprite, XSPRITE* pXSprite);
375 void aiPatrolThink(spritetype* pSprite, XSPRITE* pXSprite);
376 void aiPatrolStop(spritetype* pSprite, int target, bool alarm = false);
377 void aiPatrolAlarm(spritetype* pSprite, bool chain);
378 void aiPatrolState(spritetype* pSprite, int state);
379 void aiPatrolMove(spritetype* pSprite, XSPRITE* pXSprite);
380 int aiPatrolMarkerBusy(int nExcept, int nMarker);
381 bool aiPatrolMarkerReached(spritetype* pSprite, XSPRITE* pXSprite);
382 AISTATE* aiInPatrolState(AISTATE* pAiState);
383 //  -------------------------------------------------------------------------   //
384 bool readyForCrit(spritetype* pHunter, spritetype* pVictim);
385 int sectorInMotion(int nSector);
386 #endif
387 
388 ////////////////////////////////////////////////////////////////////////
389 // This file provides modern features for mappers.
390 // For full documentation please visit http://cruo.bloodgame.ru/xxsystem
391 ////////////////////////////////////////////////////////////////////////////////////