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 ////////////////////////////////////////////////////////////////////////////////////