- Added ifdefs for NOONE_EXTENSIONS that provides modern features for mappers

and changes that was required to minimize their amount in code.

# Conflicts:
#	source/blood/src/actor.cpp
#	source/blood/src/ai.h
#	source/blood/src/aiunicult.cpp
#	source/blood/src/aiunicult.h
#	source/blood/src/db.cpp
#	source/blood/src/db.h
#	source/blood/src/dude.h
#	source/blood/src/gameutil.cpp
#	source/blood/src/loadsave.cpp
#	source/blood/src/player.h
#	source/blood/src/sfx.cpp
#	source/blood/src/triggers.h
#	source/blood/src/view.cpp
#	source/blood/src/weapon.cpp
This commit is contained in:
NoOneBlood 2020-01-26 14:19:01 +03:00 committed by Christoph Oelckers
parent 5db1f95b29
commit 0693b0efc8
27 changed files with 1564 additions and 1350 deletions

File diff suppressed because it is too large Load diff

View file

@ -64,16 +64,12 @@ enum VECTOR_TYPE {
VECTOR_TYPE_19,
VECTOR_TYPE_20,
VECTOR_TYPE_21,
VECTOR_TYPE_22,
#ifdef NOONE_EXTENSIONS
kVectorGenDudePunch,
#endif
kVectorMax,
};
enum {
kRandomizeItem = 0,
kRandomizeDude = 1,
kRandomizeTX = 2,
};
struct THINGINFO
{
short startHealth;
@ -89,7 +85,6 @@ struct THINGINFO
unsigned char xrepeat; // xrepeat
unsigned char yrepeat; // yrepeat
int dmgControl[kDamageMax]; // damage
bool allowThrow; // By NoOne: indicates if kDudeModernCustom can throw it
};
struct AMMOITEMDATA
@ -138,8 +133,6 @@ struct MissileType
unsigned char yrepeat;
char shade;
unsigned char clipDist;
int fireSound[2]; // By NoOne: predefined fire sounds. used by kDudeModernCustom, but can be used for something else.
bool dmgType[kDamageMax]; // By NoOne: list of damages types missile can use
};
struct EXPLOSION
@ -147,7 +140,7 @@ struct EXPLOSION
unsigned char repeat;
char dmg;
char dmgRng;
int radius; // radius
int radius;
int dmgType;
int burnTime;
int ticks;
@ -172,22 +165,8 @@ struct VECTORDATA {
int bloodSplats; // blood splats
int splatChance; // blood splat chance
SURFHIT surfHit[15];
int fireSound[2]; // By NoOne: predefined fire sounds. used by kDudeModernCustom, but can be used for something else.
};
// by NoOne: sprite mass info for getSpriteMassBySize();
struct SPRITEMASS {
int seqId;
short picnum; // mainly needs for moving debris
short xrepeat;
short yrepeat;
short clipdist; // mass multiplier
int mass;
short airVel; // mainly needs for moving debris
int fraction; // mainly needs for moving debris
};
extern AMMOITEMDATA gAmmoItemData[];
extern WEAPONITEMDATA gWeaponItemData[];
extern ITEMDATA gItemData[];
@ -281,6 +260,9 @@ void actFireVector(spritetype *pShooter, int a2, int a3, int a4, int a5, int a6,
void actPostSprite(int nSprite, int nStatus);
void actPostProcess(void);
void MakeSplash(spritetype *pSprite, XSPRITE *pXSprite);
void actBuildMissile(spritetype* pMissile, int nXSprite, int nSprite);
#ifdef NOONE_EXTENSIONS
spritetype* DropRandomPickupObject(spritetype* pSprite, short prevItem);
spritetype* spawnRandomDude(spritetype* pSprite);
int GetDataVal(spritetype* pSprite, int data);
@ -290,13 +272,46 @@ bool sfxPlayVectorSound(spritetype* pSprite, int vectorId);
spritetype* actSpawnCustomDude(spritetype* pSprite, int nDist);
int getSpriteMassBySize(spritetype* pSprite);
bool ceilIsTooLow(spritetype* pSprite);
void actBuildMissile(spritetype* pMissile, int nXSprite, int nSprite);
int isDebris(int nSprite);
int debrisGetFreeIndex(void);
void debrisMove(int listIndex);
void debrisConcuss(int nOwner, int listIndex, int x, int y, int z, int dmg);
bool isImmune(spritetype* pSprite, int dmgType, int minScale = 16);
enum {
kRandomizeItem = 0,
kRandomizeDude = 1,
kRandomizeTX = 2,
};
// sprite mass info for getSpriteMassBySize();
struct SPRITEMASS {
int seqId;
short picnum; // mainly needs for moving debris
short xrepeat;
short yrepeat;
short clipdist; // mass multiplier
int mass;
short airVel; // mainly needs for moving debris
int fraction; // mainly needs for moving debris
};
struct THINGINFO_EXTRA {
bool allowThrow; // indicates if kDudeModernCustom can throw it
};
struct VECTORINFO_EXTRA {
int fireSound[2]; // predefined fire sounds. used by kDudeModernCustom, but can be used for something else.
};
struct MISSILEINFO_EXTRA {
int fireSound[2]; // predefined fire sounds. used by kDudeModernCustom, but can be used for something else.
bool dmgType[kDamageMax]; // list of damages types missile can use
};
extern THINGINFO_EXTRA gThingInfoExtra[kThingMax];
extern VECTORINFO_EXTRA gVectorInfoExtra[kVectorMax];
extern MISSILEINFO_EXTRA gMissileInfoExtra[kMissileMax];
extern SPRITEMASS gSpriteMass[kMaxXSprites];
extern short gProxySpritesList[kMaxSuperXSprites];
extern short gSightSpritesList[kMaxSuperXSprites];
@ -304,6 +319,8 @@ extern short gPhysSpritesList[kMaxSuperXSprites];
extern short gProxySpritesCount;
extern short gSightSpritesCount;
extern short gPhysSpritesCount;
#endif
extern int DudeDifficulty[];
END_BLD_NS

View file

@ -48,7 +48,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "aitchern.h"
#include "aizomba.h"
#include "aizombf.h"
#include "aiunicult.h" // By NoOne: add custom dude
#include "aiunicult.h"
#include "blood.h"
#include "db.h"
#include "dude.h"
@ -77,7 +77,7 @@ AISTATE genIdle = {kAiStateGenIdle, 0, -1, 0, NULL, NULL, NULL, NULL };
AISTATE genRecoil = {kAiStateRecoil, 5, -1, 20, NULL, NULL, NULL, &genIdle };
int dword_138BB0[5] = {0x2000, 0x4000, 0x8000, 0xa000, 0xe000};
#ifdef NOONE_EXTENSIONS
void aiSetGenIdleState(spritetype* pSprite, XSPRITE* pXSprite) {
switch (pSprite->type) {
case kDudeModernCustom:
@ -89,6 +89,7 @@ void aiSetGenIdleState(spritetype* pSprite, XSPRITE* pXSprite) {
break;
}
}
#endif
bool sub_5BDA8(spritetype *pSprite, int nSeq)
{
@ -166,7 +167,8 @@ bool CanMove(spritetype *pSprite, int a2, int nAngle, int nRange)
if (pXSector->Depth)
Depth = 1;
if (sector[nSector].type == kSectorDamage || pXSector->damageType > 0) {
// By NoOne: a quick fix for Cerberus spinning in E3M7-like maps, where damage sectors is used.
#ifdef NOONE_EXTENSIONS
// a quick fix for Cerberus spinning in E3M7-like maps, where damage sectors is used.
// It makes ignore danger if enemy immune to N damageType. As result Cerberus start acting like
// in Blood 1.0 so it can move normally to player. It's up to you for adding rest of enemies here as
// i don't think it will broke something in game.
@ -180,6 +182,9 @@ bool CanMove(spritetype *pSprite, int a2, int nAngle, int nRange)
Crusher = 1;
break;
}
#else
Crusher = 1;
#endif
}
}
int nUpper = gUpperLink[nSector];
@ -233,11 +238,13 @@ bool CanMove(spritetype *pSprite, int a2, int nAngle, int nRange)
if (floorZ - bottom > 0x2000)
return false;
break;
#ifdef NOONE_EXTENSIONS
case kDudeModernCustom:
case kDudeModernCustomBurning:
if ((Crusher && !isImmune(pSprite, pXSector->damageType)) || ((Water || Underwater) && !canSwim(pSprite))) return false;
return true;
fallthrough__;
#endif
case kDudeZombieAxeNormal:
case kDudePhantasm:
case kDudeGillBeast:
@ -407,7 +414,7 @@ void aiActivateDude(spritetype *pSprite, XSPRITE *pXSprite)
}
break;
}
#ifdef NOONE_EXTENSIONS
case kDudeModernCustom:
{
DUDEEXTRA_at6_u1* pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1;
@ -427,6 +434,7 @@ void aiActivateDude(spritetype *pSprite, XSPRITE *pXSprite)
if (pXSprite->target == -1) aiGenDudeNewState(pSprite, &genDudeBurnSearch);
else aiGenDudeNewState(pSprite, &genDudeBurnChase);
break;
#endif
case kDudeCultistTommyProne: {
DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1;
pDudeExtraE->at8 = 1; pDudeExtraE->at0 = 0;
@ -679,7 +687,9 @@ void aiActivateDude(spritetype *pSprite, XSPRITE *pXSprite)
}
case kDudeGargoyleStatueFlesh:
case kDudeGargoyleStatueStone:
// By NoOne: play gargoyle statue breaking animation if data1 = 1.
#ifdef NOONE_EXTENSIONS
// play gargoyle statue breaking animation if data1 = 1.
if (gModernMap && pXSprite->data1 == 1) {
if (pSprite->type == kDudeGargoyleStatueFlesh) aiNewState(pSprite, pXSprite, &statueFBreakSEQ);
else aiNewState(pSprite, pXSprite, &statueSBreakSEQ);
@ -690,6 +700,13 @@ void aiActivateDude(spritetype *pSprite, XSPRITE *pXSprite)
if (pSprite->type == kDudeGargoyleStatueFlesh) aiNewState(pSprite, pXSprite, &gargoyleFMorph);
else aiNewState(pSprite, pXSprite, &gargoyleSMorph);
}
#else
if (Chance(0x4000)) aiPlay3DSound(pSprite, 1401, AI_SFX_PRIORITY_1, -1);
else aiPlay3DSound(pSprite, 1400, AI_SFX_PRIORITY_1, -1);
if (pSprite->type == kDudeGargoyleStatueFlesh) aiNewState(pSprite, pXSprite, &gargoyleFMorph);
else aiNewState(pSprite, pXSprite, &gargoyleSMorph);
#endif
break;
case kDudeCerberusTwoHead:
if (pXSprite->target == -1)
@ -1006,6 +1023,7 @@ int aiDamageSprite(spritetype *pSprite, XSPRITE *pXSprite, int nSource, DAMAGE_T
evKill(nSprite, 3, kCallbackFXFlameLick);
}
break;
#ifdef NOONE_EXTENSIONS
case kDudeModernCustomBurning:
if (Chance(0x2000) && gDudeExtra[pSprite->extra].at0 < (int)gFrameClock) {
playGenDudeSound(pSprite, kGenDudeSndBurning);
@ -1077,6 +1095,7 @@ int aiDamageSprite(spritetype *pSprite, XSPRITE *pXSprite, int nSource, DAMAGE_T
}
break;
}
#endif
case kDudeCultistBeast:
if (pXSprite->health <= (unsigned int)pDudeInfo->fleeHealth)
{
@ -1110,6 +1129,7 @@ void RecoilDude(spritetype *pSprite, XSPRITE *pXSprite)
if (pSprite->statnum == kStatDude && (pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) {
DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type-kDudeBase];
switch (pSprite->type) {
#ifdef NOONE_EXTENSIONS
case kDudeModernCustom: {
GENDUDEEXTRA* pExtra = genDudeExtra(pSprite); int rChance = getRecoilChance(pSprite);
if (pExtra->canElectrocute && pDudeExtra->at4 && !spriteIsUnderwater(pSprite, false)) {
@ -1156,6 +1176,7 @@ void RecoilDude(spritetype *pSprite, XSPRITE *pXSprite)
pDudeExtra->at4 = 0;
break;
}
#endif
case kDudeCultistTommy:
case kDudeCultistShotgun:
case kDudeCultistTesla:
@ -1186,9 +1207,11 @@ void RecoilDude(spritetype *pSprite, XSPRITE *pXSprite)
case kDudeBurningCultist:
aiNewState(pSprite, pXSprite, &cultistBurnGoto);
break;
#ifdef NOONE_EXTENSIONS
case kDudeModernCustomBurning:
aiGenDudeNewState(pSprite, &genDudeBurnGoto);
break;
#endif
case kDudeZombieButcher:
aiPlay3DSound(pSprite, 1202, AI_SFX_PRIORITY_2, -1);
if (pDudeExtra->at4)
@ -1454,13 +1477,15 @@ void aiProcessDudes(void) {
int nXSprite = pSprite->extra;
XSPRITE *pXSprite = &xsprite[nXSprite]; DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type - kDudeBase];
if (IsPlayerSprite(pSprite) || pXSprite->health == 0) continue;
pXSprite->stateTimer = ClipLow(pXSprite->stateTimer-4, 0);
if (pSprite->type >= kDudeVanillaMax && pSprite->type < kDudeMax)
switch (pSprite->type){
#ifdef NOONE_EXTENSIONS
case kDudeModernCustom:
case kDudeModernCustomBurning:
genDudeProcess(pSprite, pXSprite);
else {
break;
#endif
default:
if (pXSprite->aiState->moveFunc)
pXSprite->aiState->moveFunc(pSprite, pXSprite);
@ -1478,7 +1503,7 @@ void aiProcessDudes(void) {
pXSprite->data3 = cumulDamage[nXSprite];
RecoilDude(pSprite, pXSprite);
}
break;
}
}
memset(cumulDamage, 0, sizeof(cumulDamage));
@ -1505,6 +1530,7 @@ void aiInitSprite(spritetype *pSprite)
pDudeExtra->at4 = 0;
pDudeExtra->at0 = 0;
switch (pSprite->type) {
#ifdef NOONE_EXTENSIONS
case kDudeModernCustom: {
DUDEEXTRA_at6_u1* pDudeExtraE = &gDudeExtra[nXSprite].at6.u1;
pDudeExtraE->at8 = pDudeExtraE->at0 = 0;
@ -1516,6 +1542,7 @@ void aiInitSprite(spritetype *pSprite)
aiGenDudeNewState(pSprite, &genDudeBurnGoto);
pXSprite->burnTime = 1200;
break;
#endif
case kDudeCultistTommy:
case kDudeCultistShotgun:
case kDudeCultistTesla:
@ -1707,10 +1734,11 @@ void aiInitSprite(spritetype *pSprite)
case kDudeZombieAxeLaying:
pSprite->flags = 7;
break;
case kDudePodMother: // by NoOne: FakeDude type
#ifdef NOONE_EXTENSIONS
case kDudePodMother: // FakeDude type
if (gModernMap) break;
fallthrough__;
// By NoOne: Allow put pods and tentacles on ceilings if sprite is y-flipped.
// Allow put pods and tentacles on ceilings if sprite is y-flipped.
case kDudePodGreen:
case kDudeTentacleGreen:
case kDudePodFire:
@ -1723,6 +1751,7 @@ void aiInitSprite(spritetype *pSprite)
}
fallthrough__;
// go default
#endif
default:
pSprite->flags = 15;
break;

View file

@ -106,8 +106,9 @@ void aiInit(void);
void aiInitSprite(spritetype *pSprite);
bool CanMove(spritetype* pSprite, int a2, int nAngle, int nRange);
void RecoilDude(spritetype* pSprite, XSPRITE* pXSprite);
// By NoOne: this function required for kModernDudeTargetChanger
#ifdef NOONE_EXTENSIONS
// this function required for kModernDudeTargetChanger
void aiSetGenIdleState(spritetype* pSprite, XSPRITE* pXSprite);
#endif
END_BLD_NS

View file

@ -128,9 +128,11 @@ static void thinkGoto(spritetype *pSprite, XSPRITE *pXSprite)
case kDudeBurningTinyCaleb:
aiNewState(pSprite, pXSprite, &tinycalebBurnSearch);
break;
#ifdef NOONE_EXTENSIONS
case kDudeModernCustomBurning:
aiNewState(pSprite, pXSprite, &genDudeBurnSearch);
break;
#endif
}
}
aiThinkTarget(pSprite, pXSprite);
@ -160,9 +162,11 @@ static void thinkChase(spritetype *pSprite, XSPRITE *pXSprite)
case kDudeBurningTinyCaleb:
aiNewState(pSprite, pXSprite, &tinycalebBurnGoto);
break;
#ifdef NOONE_EXTENSIONS
case kDudeModernCustomBurning:
aiNewState(pSprite, pXSprite, &genDudeBurnGoto);
break;
#endif
}
return;
}
@ -196,9 +200,11 @@ static void thinkChase(spritetype *pSprite, XSPRITE *pXSprite)
case kDudeBurningTinyCaleb:
aiNewState(pSprite, pXSprite, &tinycalebBurnSearch);
break;
#ifdef NOONE_EXTENSIONS
case kDudeModernCustomBurning:
aiNewState(pSprite, pXSprite, &genDudeBurnSearch);
break;
#endif
}
return;
}
@ -234,9 +240,11 @@ static void thinkChase(spritetype *pSprite, XSPRITE *pXSprite)
case kDudeBurningTinyCaleb:
aiNewState(pSprite, pXSprite, &tinycalebBurnAttack);
break;
#ifdef NOONE_EXTENSIONS
case kDudeModernCustomBurning:
aiNewState(pSprite, pXSprite, &genDudeBurnSearch);
break;
#endif
}
}
return;
@ -264,9 +272,11 @@ static void thinkChase(spritetype *pSprite, XSPRITE *pXSprite)
case kDudeBurningTinyCaleb:
aiNewState(pSprite, pXSprite, &tinycalebBurnGoto);
break;
#ifdef NOONE_EXTENSIONS
case kDudeModernCustomBurning:
aiNewState(pSprite, pXSprite, &genDudeBurnSearch);
break;
#endif
}
pXSprite->target = -1;
}

View file

@ -24,11 +24,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "ns.h" // Must come before everything else!
#include "common_game.h"
#ifdef NOONE_EXTENSIONS
#include "compat.h"
#include "build.h"
#include "pragmas.h"
#include "mmulti.h"
#include "common_game.h"
#include "actor.h"
#include "ai.h"
#include "aiunicult.h"
@ -222,7 +224,7 @@ static void punchCallback(int, int nXIndex) {
if (!playGenDudeSound(pSprite, kGenDudeSndAttackMelee))
sfxPlay3DSound(pSprite, 530, 1, 0);
actFireVector(pSprite, 0, 0, dx, dy, dz,VECTOR_TYPE_22);
actFireVector(pSprite, 0, 0, dx, dy, dz,kVectorGenDudePunch);
}
}
@ -315,7 +317,7 @@ static void ThrowThing(int nXIndex, bool impact) {
if (weaponType != kGenDudeWeaponThrow) return;
const THINGINFO* pThinkInfo = &thingInfo[curWeapon - kThingBase];
if (!pThinkInfo->allowThrow) return;
if (!gThingInfoExtra[curWeapon - kThingBase].allowThrow) return;
else if (!playGenDudeSound(pSprite, kGenDudeSndAttackThrow))
sfxPlay3DSound(pSprite, 455, -1, 0);
@ -521,7 +523,7 @@ static void thinkChase( spritetype* pSprite, XSPRITE* pXSprite ) {
spritetype* pLeech = leechIsDropped(pSprite); VECTORDATA* meleeVector = &gVectorData[22];
if (weaponType == kGenDudeWeaponThrow) {
if (klabs(losAngle) < kAng15) {
if (!thingInfo[curWeapon - kThingBase].allowThrow) {
if (!gThingInfoExtra[curWeapon - kThingBase].allowThrow) {
if (spriteIsUnderwater(pSprite)) aiGenDudeNewState(pSprite, &genDudeChaseW);
else aiGenDudeNewState(pSprite, &genDudeChaseL);
return;
@ -870,7 +872,7 @@ static void thinkChase( spritetype* pSprite, XSPRITE* pXSprite ) {
else if (hit == 3 && (failed = (pHSprite->statnum != kStatThing || pXHSprite == NULL || pXHSprite->locked)) == false) {
// check also for damage resistance (all possible damages missile can use)
for (int i = 0; i < kDmgMax; i++) {
if (missileInfo[curWeapon - kMissileBase].dmgType[i] && (failed = isImmune(pHSprite, i)) == false)
if (gMissileInfoExtra[curWeapon - kMissileBase].dmgType[i] && (failed = isImmune(pHSprite, i)) == false)
break;
}
}
@ -1993,4 +1995,4 @@ bool genDudePrepare(spritetype* pSprite, int propId) {
return true;
}
END_BLD_NS
#endifEND_BLD_NS

View file

@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
//-------------------------------------------------------------------------
#pragma once
#ifdef NOONE_EXTENSIONS
#include "ai.h"
#include "eventq.h"
@ -220,4 +221,4 @@ bool genDudePrepare(spritetype* pSprite, int propId = kGenDudePropertyAll);
void genDudeUpdate(spritetype* pSprite);
void genDudeProcess(spritetype* pSprite, XSPRITE* pXSprite);
bool genDudeAdjustSlope(spritetype* pSprite, XSPRITE* pXSprite, int dist, int weaponType, int by = 64);
END_BLD_NS
#endifEND_BLD_NS

View file

@ -593,6 +593,7 @@ void StartLevel(GAMEOPTIONS *gameOptions)
}
#ifdef NOONE_EXTENSIONS
if (gModernMap) {
switch (pSprite->type) {
@ -664,6 +665,7 @@ void StartLevel(GAMEOPTIONS *gameOptions)
}
}
}
#endif
}
}
scrLoadPLUs();
@ -675,7 +677,8 @@ void StartLevel(GAMEOPTIONS *gameOptions)
gStartZone[i].sectnum = startsectnum;
gStartZone[i].ang = startang;
// By NoOne: Create spawn zones for players in teams mode.
#ifdef NOONE_EXTENSIONS
// Create spawn zones for players in teams mode.
if (gModernMap && i <= kMaxPlayers / 2) {
gStartZoneTeam1[i].x = startpos.x;
gStartZoneTeam1[i].y = startpos.y;
@ -689,6 +692,7 @@ void StartLevel(GAMEOPTIONS *gameOptions)
gStartZoneTeam2[i].sectnum = startsectnum;
gStartZoneTeam2[i].ang = startang;
}
#endif
}
InitSectorFX();
warpInit();

View file

@ -344,8 +344,10 @@ void CounterCheck(int nSector) // 12
{
dassert(nSector >= 0 && nSector < kMaxSectors);
// By NoOne: remove check below, so every sector can be counter if command 12 (this callback) received.
//if (pSector->type != kSectorCounter) return;
// remove check below, so every sector can be counter if command 12 (this callback) received.
#ifndef NOONE_EXTENSIONS
if (sector[nSector].type != kSectorCounter) return;
#endif
if (sector[nSector].extra <= 0) return;
XSECTOR *pXSector = &xsector[sector[nSector].extra];
@ -566,7 +568,9 @@ void LeechStateTimer(int nSprite) // 20
if (pSprite->statnum == kStatThing && !(pSprite->flags & 32)) {
switch (pSprite->type) {
case kThingDroppedLifeLeech:
#ifdef NOONE_EXTENSIONS
case kModernThingEnemyLifeLeech:
#endif
xsprite[pSprite->extra].stateTimer = 0;
break;
}
@ -708,6 +712,7 @@ void DropVoodoo(int nSprite) // unused
}
}
#ifdef NOONE_EXTENSIONS
void UniMissileBurst(int nSprite) // 22
{
dassert(nSprite >= 0 && nSprite < kMaxSprites);
@ -766,12 +771,13 @@ void makeMissileBlocking(int nSprite) // 23
sprite[nSprite].cstat |= CSTAT_SPRITE_BLOCK;
}
void genDudeUpdateCallback(int nSprite) // 24
{
if (spriRangeIsFine(nSprite))
genDudeUpdate(&sprite[nSprite]);
}
#endif
void(*gCallback[kCallbackMax])(int) =
{
fxFlameLick,
@ -796,9 +802,11 @@ void(*gCallback[kCallbackMax])(int) =
fxPodBloodSplat,
LeechStateTimer,
DropVoodoo, // unused
#ifdef NOONE_EXTENSIONS
UniMissileBurst,
makeMissileBlocking,
genDudeUpdateCallback,
#endif
};
END_BLD_NS

View file

@ -49,9 +49,11 @@ enum CALLBACK_ID {
kCallbackFXPodBloodSplat = 19,
kCallbackLeechStateTimer = 20,
kCallbackDropVoodoo = 21, // unused
#ifdef NOONE_EXTENSIONS
kCallbackMissileBurst = 22, // by NoOne
kCallbackMissileSpriteBlock = 23, // by NoOne
kCallbackGenDudeUpdate = 24, // by NoOne
#endif
kCallbackMax,
};

View file

@ -85,9 +85,12 @@ void _consoleSysMsg(const char* pMessage, ...);
// defined by NoOne:
// -------------------------------
#define kMaxPAL 5
#define kFreeQAVEntry 108
/////////////////////////////////////////////////////////////
#define NOONE_EXTENSIONS 1
////////////////////////////////////////////////////////////
#define kMaxPAL 5
#define kUserPLUStart 15
#define kDmgFall 0
@ -126,11 +129,9 @@ kStatSpares = 13,
kStatFlare = 14,
kStatDebris = 15,
kStatPathMarker = 16,
kStatModernDudeTargetChanger = 20, // gModernMap only
kStatFree = 1024,
};
// POWERUPS /////////////////////////////////////////////////////
enum {
kPwUpFeatherFall = 12,
@ -196,30 +197,12 @@ enum {
kSwitchPadlock = 23,
kSwitchMax = 24,
// modern types (gModernMap only)
kModernCustomDudeSpawn = 24,
kModernRandomTX = 25,
kModernSequentialTX = 26,
kModernSeqSpawner = 27,
kModernObjPropertiesChanger = 28,
kModernObjPicnumChanger = 29,
kModernObjSizeChanger = 31,
kModernDudeTargetChanger = 33,
kModernSectorFXChanger = 34,
kModernObjDataChanger = 35,
kModernSpriteDamager = 36,
kModernObjDataAccumulator = 37,
kModernEffectSpawner = 38,
kModernWindGenerator = 39,
kModernPlayerControl = 500, /// WIP
// decorations
kDecorationTorch = 30,
kDecorationCandle = 32,
// (weapons)
kItemWeaponBase = 40,
kModernRandom = 40, // gModernMap only
kItemWeaponSawedoff = 41,
kItemWeaponTommygun = 42,
kItemWeaponVoodooDoll = 44,
@ -231,7 +214,6 @@ enum {
kItemAmmoSawedoffFew = 67,
kItemAmmoTommygunFew = 69,
kAmmoItemVoodooDoll = 70,
kModernRandom2 = 80, // gModernMap Only
kItemAmmoMax = 81,
kItemBase = 100,
@ -266,8 +248,6 @@ enum {
kItemReflectShots = 124,
kItemBeastVision = 125,
kItemShroomDelirium = 128,
kItemShroomGrow = 129, // gModernMap only
kItemShroomShrink = 130, // gModernMap only
kItemArmorAsbest = 139,
kItemArmorBasic = 140,
@ -280,7 +260,6 @@ enum {
kItemFlagBBase = 146,
kItemFlagA = 147,
kItemFlagB = 148,
kItemModernMapLevel = 150, // once picked up, draws whole minimap
kItemMax = 151,
// dudes
@ -339,8 +318,6 @@ enum {
kDudeBurningTinyCaleb = 252,
kDudeBurningBeast = 253,
kDudeVanillaMax = 254,
kDudeModernCustom = kDudeVanillaMax, // gModern map only
kDudeModernCustomBurning = 255, // gModern map only
kDudeMax = 256,
kMissileBase = 300,
@ -394,9 +371,6 @@ enum {
kThingPodGreenBall = 430,
kThingDroppedLifeLeech = 431,
kThingVoodooHead = 432, // unused
kModernThingTNTProx = 433, // gModernMap only - detects only players
kModernThingThrowableRock = 434, // gModernMap only - does small damage if hits target
kModernThingEnemyLifeLeech = 435, // gModernMap only - the same as normal, except it aims in specified target only
kThingMax = 436,
// traps
@ -410,8 +384,7 @@ enum {
kGenDripWater = 701,
kGenDripBlood = 702,
kGenMissileFireball = 703,
kGenMissileEctoSkull = 704, // does not work in vanilla
kGenModernMissileUniversal = 704, // gModernMap only
kGenMissileEctoSkull = 704,
kGenDart = 705,
kGenBubble = 706,
kGenBubbleMulti = 707,
@ -422,6 +395,54 @@ enum {
kSoundPlayer = 711,
};
#ifdef NOONE_EXTENSIONS
// modern types (gModernMap only)
enum {
kModernCustomDudeSpawn = 24,
kModernRandomTX = 25,
kModernSequentialTX = 26,
kModernSeqSpawner = 27,
kModernObjPropertiesChanger = 28,
kModernObjPicnumChanger = 29,
kModernObjSizeChanger = 31,
kModernDudeTargetChanger = 33,
kModernSectorFXChanger = 34,
kModernObjDataChanger = 35,
kModernSpriteDamager = 36,
kModernObjDataAccumulator = 37,
kModernEffectSpawner = 38,
kModernWindGenerator = 39,
kModernRandom = 40,
kModernRandom2 = 80,
kItemShroomGrow = 129,
kItemShroomShrink = 130,
kItemModernMapLevel = 150, // once picked up, draws whole minimap
kDudeModernCustom = kDudeVanillaMax,
kDudeModernCustomBurning = 255,
kModernThingTNTProx = 433, // detects only players
kModernThingThrowableRock = 434, // does small damage if hits target
kModernThingEnemyLifeLeech = 435, // the same as normal, except it aims in specified target only
kModernPlayerControl = 500, /// WIP
kGenModernMissileUniversal = 704,
};
// modern statnums (gModernMap only)
enum {
kStatModernDudeTargetChanger = 20,
};
// additional physics attributes for debris sprites
#define kPhysDebrisFly 0x0008 // *debris* affected by negative gravity (fly instead of falling, DO NOT mess with kHitagAutoAim)
#define kPhysDebrisSwim 0x0016 // *debris* can swim underwater (instead of drowning)
#define kPhysDebrisVector 0x0400 // *debris* can be affected by vector weapons
#define kPhysDebrisExplode 0x0800 // *debris* can be affected by explosions
// *modern types only hitag*
#define kModernTypeFlag0 0x0
#define kModernTypeFlag1 0x1
#define kModernTypeFlag2 0x2
#define kModernTypeFlag3 0x3
#endif
// WALL TYPES /////////////////////////////////////////////////
enum {
@ -471,18 +492,6 @@ kAiStateAttack = 6,
#define kPhysMove 0x0001 // affected by movement physics
#define kPhysGravity 0x0002 // affected by gravity
#define kPhysFalling 0x0004 // currently in z-motion
// additional physics attributes for debris sprites
#define kPhysDebrisFly 0x0008 // *debris* affected by negative gravity (fly instead of falling, DO NOT mess with kHitagAutoAim)
#define kPhysDebrisSwim 0x0016 // *debris* can swim underwater (instead of drowning)
#define kPhysDebrisVector 0x0400 // *debris* can be affected by vector weapons
#define kPhysDebrisExplode 0x0800 // *debris* can be affected by explosions
// *modern types only hitag*
#define kModernTypeFlag0 0x0
#define kModernTypeFlag1 0x1
#define kModernTypeFlag2 0x2
#define kModernTypeFlag3 0x3
// sector cstat
#define kSecCParallax 0x01
@ -495,7 +504,6 @@ kAiStateAttack = 6,
#define kSecCRelAlign 0x40
#define kSecCFloorShade 0x8000
#define kAng5 28
#define kAng15 85
#define kAng30 170

View file

@ -54,7 +54,9 @@ PolymerLight_t gPolymerLight[kMaxSprites];
char qsprite_filler[kMaxSprites], qsector_filler[kMaxSectors];
int gVisibility;
#ifdef NOONE_EXTENSIONS
bool gModernMap = false;
#endif
void dbCrypt(char *pPtr, int nLength, int nKey)
{
@ -639,8 +641,9 @@ int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short
memset(show2dsector, 0, sizeof(show2dsector));
memset(show2dwall, 0, sizeof(show2dwall));
memset(show2dsprite, 0, sizeof(show2dsprite));
#ifdef NOONE_EXTENSIONS
gModernMap = false;
#endif
#ifdef USE_OPENGL
Polymost_prepare_loadboard();
@ -680,10 +683,12 @@ int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short
if ((header.version & 0xff00) == 0x700) {
byte_1A76C8 = 1;
// by NoOne: indicate if the map requires modern features to work properly
#ifdef NOONE_EXTENSIONS
// indicate if the map requires modern features to work properly
// for maps wich created in PMAPEDIT BETA13 or higher versions. Since only minor version changed,
// the map is still can be loaded with vanilla BLOOD / MAPEDIT and should work in other ports too.
if ((header.version & 0x00ff) == 0x001) gModernMap = true;
#endif
} else {
initprintf("Map file is wrong version");
@ -1094,10 +1099,12 @@ int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short
xsprite[sprite[i].extra].lT |= xsprite[sprite[i].extra].lB;
}
// by NoOne: indicate if the map requires modern features to work properly
#ifdef NOONE_EXTENSIONS
// indicate if the map requires modern features to work properly
// for maps wich created in different editors (include vanilla MAPEDIT) or in PMAPEDIT version below than BETA13
if (!gModernMap && pXSprite->rxID == kChannelMapModernize && pXSprite->rxID == pXSprite->txID && pXSprite->command == kCmdModernFeaturesEnable)
gModernMap = true;
#endif
}
if ((sprite[i].cstat & 0x30) == 0x30)
{

View file

@ -28,8 +28,12 @@ BEGIN_BLD_NS
#define kMaxXWalls 512
#define kMaxXSectors 512
// by NoOne additional non-thing proximity, sight and physics sprites
#ifdef NOONE_EXTENSIONS
// additional non-thing proximity, sight and physics sprites
#define kMaxSuperXSprites 128
extern bool gModernMap;
#endif
// by NoOne: functions to quckly check range of specifical arrays
inline bool xspriRangeIsFine(int nXindex) {
@ -43,9 +47,6 @@ inline bool xsectRangeIsFine(int nXindex) {
inline bool xwallRangeIsFine(int nXindex) {
return (nXindex >= 0 && nXindex < kMaxXWalls);
}
extern bool gModernMap;
#pragma pack(push, 1)
struct AISTATE;
@ -115,9 +116,12 @@ struct XSPRITE {
unsigned int height : 16;
unsigned int stateTimer : 16; // ai timer
AISTATE* aiState; // ai
#ifdef NOONE_EXTENSIONS
signed int sysData1 : 16; // used to keep here various system data, so user can't change it in map editor
unsigned int physAttr : 12; // currently used by additional physics sprites to keep it's attributes.
#endif
signed int scale; // used for scaling SEQ size on sprites
};
struct XSECTOR {
@ -189,7 +193,11 @@ struct XSECTOR {
unsigned int floorpal : 4; // Floor pal2
unsigned int floorYPanFrac : 8; // Floor y panning frac
unsigned int locked : 1; // Locked
unsigned int windVel : 32; // Wind vel (by NoOne: changed from 10 bit to use higher velocity values)
#ifdef NOONE_EXTENSIONS
unsigned int windVel : 32; // Wind vel (changed from 10 bit to use higher velocity values)
#else
unsigned int windVel : 10;
#endif
unsigned int windAng : 11; // Wind ang
unsigned int windAlways : 1; // Wind always
unsigned int dudeLockout : 1;

View file

@ -380,11 +380,13 @@ void evSend(int nIndex, int nType, int rxId, COMMAND_ID command)
case kChannelLevelExitSecret:
levelEndLevel(1);
return;
// By NoOne: finished level and load custom level ¹ via numbered command.
#ifdef NOONE_EXTENSIONS
// finished level and load custom level ¹ via numbered command.
case kChannelModernEndLevelCustom:
if (command >= kCmdNumberic) levelEndLevelCustom(command - kCmdNumberic);
else viewSetSystemMessage("Invalid Level-Exit# command by xobject #%d (object type %d)", nIndex, nType);
return;
#endif
case kChannelSetTotalSecrets:
if (command >= kCmdNumberic) levelSetupSecret(command - kCmdNumberic);
else viewSetSystemMessage("Invalid Total-Secrets command by xobject #%d (object type %d)", nIndex, nType);
@ -436,7 +438,7 @@ void evSend(int nIndex, int nType, int rxId, COMMAND_ID command)
break;
}
#ifdef NOONE_EXTENSIONS
if (gModernMap) {
// allow to send commands on player sprites
@ -452,7 +454,7 @@ void evSend(int nIndex, int nType, int rxId, COMMAND_ID command)
}
}
#endif
for (int i = bucketHead[rxId]; i < bucketHead[rxId+1]; i++) {
if (event.type != rxBucket[i].type || event.index != rxBucket[i].index) {
switch (rxBucket[i].type) {

View file

@ -917,12 +917,14 @@ int picHeight(short nPic, short repeat) {
return ClipLow((tilesiz[nPic].y * repeat) << 2, 0);
}
// by NoOne: used for better randomness in single player
#ifdef NOONE_EXTENSIONS
// used for better randomness in single player
int STD_Random(int a, int b) {
std::default_random_engine stdRandom;
stdRandom.seed(std::random_device()());
std::uniform_int_distribution<int> dist_a_b(a, b);
return dist_a_b(stdRandom);
}
#endif
END_BLD_NS

View file

@ -358,7 +358,8 @@ void levelEndLevel(int arg)
}
}
// By NoOne: this function can be called via sending numbered command to TX kChannelModernEndLevelCustom
#ifdef NOONE_EXTENSIONS
// this function can be called via sending numbered command to TX kChannelModernEndLevelCustom
// This allows to set custom next level instead of taking it from INI file.
void levelEndLevelCustom(int nLevel) {
@ -374,6 +375,7 @@ void levelEndLevelCustom(int nLevel) {
gNextLevel = nLevel;
}
#endif
void levelRestart(void)
{

View file

@ -118,8 +118,10 @@ void levelGetNextLevels(int nEpisode, int nLevel, int *pnEndingA, int *pnEndingB
// arg: 0 is normal exit, 1 is secret level
void levelEndLevel(int arg);
// By NoOne: custom level selection via numbered command which sent to TX ID 6.
#ifdef NOONE_EXTENSIONS
// custom level selection via numbered command which sent to TX ID 6.
void levelEndLevelCustom(int nLevel);
#endif
void levelRestart(void);
int levelGetMusicIdx(const char *str);

View file

@ -314,7 +314,9 @@ void MyLoadSave::Load(void)
Read(&gMapRev, sizeof(gMapRev));
Read(&gSongId, sizeof(gSkyCount));
Read(&gFogMode, sizeof(gFogMode));
#ifdef NOONE_EXTENSIONS
Read(&gModernMap, sizeof(gModernMap));
#endif
gCheatMgr.sub_5BCF4();
}
@ -395,7 +397,9 @@ void MyLoadSave::Save(void)
Write(&gMapRev, sizeof(gMapRev));
Write(&gSongId, sizeof(gSkyCount));
Write(&gFogMode, sizeof(gFogMode));
#ifdef NOONE_EXTENSIONS
Write(&gModernMap, sizeof(gModernMap));
#endif
}
void LoadSavedInfo(void)

View file

@ -124,33 +124,6 @@ int Handicap[] = {
144, 208, 256, 304, 368
};
/*int gDefaultAccel[] = {
// normal human
0x4000, 0x1200, 0x2000, // stand (front, side, back) / swim (front, side, back) / crouch (front, side, back)
// normal beast
0x4000, 0x1200, 0x2000, // stand (front, side, back) / swim (front, side, back) / crouch (front, side, back)
// shrink human
10384, 2108, 2192, // stand (front, side, back) / swim (front, side, back) / crouch (front, side, back)
// grown human
19384, 5608, 11192, // stand (front, side, back) / swim (front, side, back) / crouch (front, side, back)
};
int gDefaultJumpZ[] = {
// normal human
-0xbaaaa, -0x175555, 0x5b05, 0, 0, 0, // stand (normal jump, pwup jump) / swim (normal jump, pwup jump) / crouch (normal jump, pwup jump)
// normal beast
-0xbaaaa, -0x175555, 0x5b05, 0, 0, 0, // stand (normal jump, pwup jump) / swim (normal jump, pwup jump) / crouch (normal jump, pwup jump)
// shrink human
-564586, -1329173, 0x5b05, 0, 0, 0, // stand (normal jump, pwup jump) / swim (normal jump, pwup jump) / crouch (normal jump, pwup jump)
// grown human
-1014586, -1779173, 0x5b05, 0, 0, 0, // stand (normal jump, pwup jump) / swim (normal jump, pwup jump) / crouch (normal jump, pwup jump)
};*/
POSTURE gPostureDefaults[kModeMax][kPostureMax] = {
// normal human
@ -281,6 +254,7 @@ DAMAGEINFO damageInfo[7] = {
{ 0, 0, 0, 0, 0, 0, 0 }
};
#ifdef NOONE_EXTENSIONS
TRPLAYERCTRL gPlayerCtrl[kMaxPlayers];
QAV* qavSceneLoad(int qavId) {
@ -292,8 +266,6 @@ QAV* qavSceneLoad(int qavId) {
return pQav;
}
void qavSceneDraw(PLAYER* pPlayer, int a2, int a3, int a4, int a5) {
if (pPlayer == NULL || pPlayer->sceneQav == -1) return;
@ -347,16 +319,6 @@ void qavScenePlay(PLAYER* pPlayer) {
}
}
int powerupCheck(PLAYER *pPlayer, int nPowerUp)
{
dassert(pPlayer != NULL);
dassert(nPowerUp >= 0 && nPowerUp < kMaxPowerUps);
int nPack = powerupToPackItem(nPowerUp);
if (nPack >= 0 && !packItemActive(pPlayer, nPack))
return 0;
return pPlayer->pwUpTime[nPowerUp];
}
bool isGrown(spritetype* pSprite) {
if (powerupCheck(&gPlayer[pSprite->type - kDudePlayer1], kPwUpGrowShroom) > 0) return true;
else if (pSprite->extra >= 0 && xsprite[pSprite->extra].scale >= 512) return true;
@ -386,6 +348,7 @@ bool resetPlayerSize(PLAYER* pPlayer) {
pPlayer->pXSprite->scale = 0;
return true;
}
#endif
void deactivateSizeShrooms(PLAYER* pPlayer) {
powerupDeactivate(pPlayer, kPwUpGrowShroom);
@ -418,6 +381,16 @@ PLAYER* getPlayerById(short id) {
return NULL;
}
int powerupCheck(PLAYER *pPlayer, int nPowerUp)
{
dassert(pPlayer != NULL);
dassert(nPowerUp >= 0 && nPowerUp < kMaxPowerUps);
int nPack = powerupToPackItem(nPowerUp);
if (nPack >= 0 && !packItemActive(pPlayer, nPack))
return 0;
return pPlayer->pwUpTime[nPowerUp];
}
char powerupActivate(PLAYER *pPlayer, int nPowerUp)
{
@ -430,6 +403,7 @@ char powerupActivate(PLAYER *pPlayer, int nPowerUp)
pPlayer->packSlots[nPack].isActive = 1;
switch (nPowerUp + kItemBase) {
#ifdef NOONE_EXTENSIONS
case kItemModernMapLevel:
if (gModernMap) gFullMap = true;
break;
@ -452,6 +426,7 @@ char powerupActivate(PLAYER *pPlayer, int nPowerUp)
actDamageSprite(pPlayer->pSprite->xvel, pPlayer->pSprite, DAMAGE_TYPE_3, 65535);
}
break;
#endif
case kItemFeatherFall:
case kItemJumpBoots:
pPlayer->damageControl[0]++;
@ -491,6 +466,7 @@ void powerupDeactivate(PLAYER *pPlayer, int nPowerUp)
pPlayer->packSlots[nPack].isActive = 0;
switch (nPowerUp + kItemBase) {
#ifdef NOONE_EXTENSIONS
case kItemShroomShrink:
if (gModernMap) {
resetPlayerSize(pPlayer);
@ -501,6 +477,7 @@ void powerupDeactivate(PLAYER *pPlayer, int nPowerUp)
case kItemShroomGrow:
if (gModernMap) resetPlayerSize(pPlayer);
break;
#endif
case kItemFeatherFall:
case kItemJumpBoots:
pPlayer->damageControl[0]--;
@ -800,7 +777,8 @@ void playerStart(int nPlayer)
if (gGameOptions.nGameType <= 1)
pStartZone = &gStartZone[nPlayer];
// By NoOne: let's check if there is positions of teams is specified
#ifdef NOONE_EXTENSIONS
// let's check if there is positions of teams is specified
// if no, pick position randomly, just like it works in vanilla.
else if (gModernMap && gGameOptions.nGameType == 3 && gTeamsSpawnUsed == true) {
int maxRetries = 5;
@ -822,7 +800,10 @@ void playerStart(int nPlayer)
if (pStartZone != NULL)
break;
}
} else {
}
#endif
else {
pStartZone = &gStartZone[Random(8)];
}
@ -914,7 +895,9 @@ void playerStart(int nPlayer)
pPlayer->weaponTimer = 0;
pPlayer->weaponState = 0;
pPlayer->weaponQav = -1;
#ifdef NOONE_EXTENSIONS
playerResetQavScene(pPlayer); // reset qav scene
#endif
pPlayer->hand = 0;
pPlayer->nWaterPal = 0;
playerResetPowerUps(pPlayer);
@ -975,25 +958,29 @@ void playerReset(PLAYER *pPlayer)
pPlayer->packSlots[i].isActive = 0;
pPlayer->packSlots[i].curAmount = 0;
}
#ifdef NOONE_EXTENSIONS
/////////////////
// reset qav scene
playerResetQavScene(pPlayer);
#endif
// reset posture (mainly required for resetting movement speed and jump height)
playerResetPosture(pPlayer);
/////////////////
}
void playerResetPosture(PLAYER* pPlayer) {
memcpy(pPlayer->pPosture, gPostureDefaults, sizeof(gPostureDefaults));
}
#ifdef NOONE_EXTENSIONS
void playerResetQavScene(PLAYER* pPlayer) {
QAVSCENE* pQavScene = &gPlayerCtrl[pPlayer->nPlayer].qavScene;
pQavScene->index = pQavScene->dummy = pPlayer->sceneQav = -1;
pQavScene->qavResrc = NULL;
}
#endif
int dword_21EFB0[8];
ClockTicks dword_21EFD0[8];
@ -1036,10 +1023,16 @@ char PickupItem(PLAYER *pPlayer, spritetype *pItem) {
switch (pItem->type) {
case kItemShadowCloak:
#ifdef NOONE_EXTENSIONS
if (isGrown(pPlayer->pSprite) || !powerupActivate(pPlayer, nType)) return false;
#else
if (!powerupActivate(pPlayer, nType)) return false;
#endif
break;
#ifdef NOONE_EXTENSIONS
case kItemShroomShrink:
case kItemShroomGrow:
if (gModernMap) {
switch (pItem->type) {
case kItemShroomShrink:
@ -1052,7 +1045,9 @@ char PickupItem(PLAYER *pPlayer, spritetype *pItem) {
powerupActivate(pPlayer, nType);
}
break;
#endif
case kItemFlagABase:
case kItemFlagBBase: {
if (gGameOptions.nGameType != 3 || pItem->extra <= 0) return 0;
@ -1203,9 +1198,11 @@ char PickupItem(PLAYER *pPlayer, spritetype *pItem) {
case kItemHealthLifeSeed:
case kItemHealthRedPotion: {
int addPower = gPowerUpInfo[nType].bonusTime;
// by NoOne: allow custom amount for item
#ifdef NOONE_EXTENSIONS
// allow custom amount for item
if (gModernMap && sprite[pItem->xvel].extra >= 0 && xsprite[sprite[pItem->xvel].extra].data1 > 0)
addPower = xsprite[sprite[pItem->xvel].extra].data1;
#endif
if (!actHealDude(pXSprite, addPower, gPowerUpInfo[nType].maxTime)) return 0;
return 1;
@ -1230,11 +1227,12 @@ char PickupAmmo(PLAYER* pPlayer, spritetype* pAmmo) {
int nAmmoType = pAmmoItemData->type;
if (pPlayer->ammoCount[nAmmoType] >= gAmmoInfo[nAmmoType].max) return 0;
else if (!gModernMap || pAmmo->extra < 0 || xsprite[pAmmo->extra].data1 <= 0)
pPlayer->ammoCount[nAmmoType] = ClipHigh(pPlayer->ammoCount[nAmmoType]+pAmmoItemData->count, gAmmoInfo[nAmmoType].max);
// by NoOne: allow custom amount for item
else
#ifdef NOONE_EXTENSIONS
else if (gModernMap && pAmmo->extra >= 0 && xsprite[pAmmo->extra].data1 > 0) // allow custom amount for item
pPlayer->ammoCount[nAmmoType] = ClipHigh(pPlayer->ammoCount[nAmmoType] + xsprite[pAmmo->extra].data1, gAmmoInfo[nAmmoType].max);
#endif
else
pPlayer->ammoCount[nAmmoType] = ClipHigh(pPlayer->ammoCount[nAmmoType]+pAmmoItemData->count, gAmmoInfo[nAmmoType].max);
if (pAmmoItemData->weaponType) pPlayer->hasWeapon[pAmmoItemData->weaponType] = 1;
sfxPlay3DSound(pPlayer->pSprite, 782, -1, 0);
@ -1250,11 +1248,13 @@ char PickupWeapon(PLAYER *pPlayer, spritetype *pWeapon) {
return 0;
pPlayer->hasWeapon[nWeaponType] = 1;
if (nAmmoType == -1) return 0;
// By NoOne: allow to set custom ammo count for weapon pickups
if (!gModernMap || pWeapon->extra < 0 || xsprite[pWeapon->extra].data1 <= 0)
pPlayer->ammoCount[nAmmoType] = ClipHigh(pPlayer->ammoCount[nAmmoType] + pWeaponItemData->count, gAmmoInfo[nAmmoType].max);
else
// allow to set custom ammo count for weapon pickups
#ifdef NOONE_EXTENSIONS
else if (gModernMap && pWeapon->extra >= 0 && xsprite[pWeapon->extra].data1 > 0)
pPlayer->ammoCount[nAmmoType] = ClipHigh(pPlayer->ammoCount[nAmmoType] + xsprite[pWeapon->extra].data1, gAmmoInfo[nAmmoType].max);
#endif
else
pPlayer->ammoCount[nAmmoType] = ClipHigh(pPlayer->ammoCount[nAmmoType] + pWeaponItemData->count, gAmmoInfo[nAmmoType].max);
int nNewWeapon = WeaponUpgrade(pPlayer, nWeaponType);
if (nNewWeapon != pPlayer->curWeapon) {
@ -1266,10 +1266,12 @@ char PickupWeapon(PLAYER *pPlayer, spritetype *pWeapon) {
}
if (!actGetRespawnTime(pWeapon) || nAmmoType == -1 || pPlayer->ammoCount[nAmmoType] >= gAmmoInfo[nAmmoType].max) return 0;
else if (!gModernMap || pWeapon->extra < 0 || xsprite[pWeapon->extra].data1 <= 0)
pPlayer->ammoCount[nAmmoType] = ClipHigh(pPlayer->ammoCount[nAmmoType]+pWeaponItemData->count, gAmmoInfo[nAmmoType].max);
else
#ifdef NOONE_EXTENSIONS
else if (gModernMap && pWeapon->extra >= 0 && xsprite[pWeapon->extra].data1 > 0)
pPlayer->ammoCount[nAmmoType] = ClipHigh(pPlayer->ammoCount[nAmmoType] + xsprite[pWeapon->extra].data1, gAmmoInfo[nAmmoType].max);
#endif
else
pPlayer->ammoCount[nAmmoType] = ClipHigh(pPlayer->ammoCount[nAmmoType]+pWeaponItemData->count, gAmmoInfo[nAmmoType].max);
sfxPlay3DSound(pPlayer->pSprite, 777, -1, 0);
return 1;
@ -1281,12 +1283,13 @@ void PickUp(PLAYER *pPlayer, spritetype *pSprite)
int nType = pSprite->type;
char pickedUp = 0;
int customMsg = -1;
if (gModernMap) { // by NoOne: allow custom INI message instead "Picked up"
#ifdef NOONE_EXTENSIONS
if (gModernMap) { // allow custom INI message instead "Picked up"
XSPRITE* pXSprite = (pSprite->extra >= 0) ? &xsprite[pSprite->extra] : NULL;
if (pXSprite != NULL && pXSprite->txID != 3 && pXSprite->lockMsg > 0)
customMsg = pXSprite->lockMsg;
}
#endif
if (nType >= kItemBase && nType <= kItemMax) {
pickedUp = PickupItem(pPlayer, pSprite);
@ -1578,7 +1581,9 @@ void ProcessInput(PLAYER *pPlayer)
break;
default:
if (!pPlayer->cantJump && pInput->buttonFlags.jump && pXSprite->height == 0) {
#ifdef NOONE_EXTENSIONS
if ((packItemActive(pPlayer, 4) && pPosture->pwupJumpZ != 0) || pPosture->normalJumpZ != 0)
#endif
sfxPlay3DSound(pSprite, 700, 0, 0);
if (packItemActive(pPlayer, 4)) zvel[nSprite] = pPosture->pwupJumpZ; //-0x175555;
@ -2332,17 +2337,18 @@ void PlayerLoadSave::Load(void)
Read(&gNetPlayers, sizeof(gNetPlayers));
Read(&gProfile, sizeof(gProfile));
Read(&gPlayer, sizeof(gPlayer));
#ifdef NOONE_EXTENSIONS
Read((void*)&buffer, sizeof(kPlayerCtrlSigStart));
Read(&gPlayerCtrl, sizeof(gPlayerCtrl));
Read((void*)&buffer, sizeof(kPlayerCtrlSigEnd));
#endif
for (int i = 0; i < gNetPlayers; i++) {
gPlayer[i].pSprite = &sprite[gPlayer[i].nSprite];
gPlayer[i].pXSprite = &xsprite[gPlayer[i].pSprite->extra];
gPlayer[i].pDudeInfo = &dudeInfo[gPlayer[i].pSprite->type-kDudeBase];
// by NoOne: load qav scene
#ifdef NOONE_EXTENSIONS
// load qav scene
if (gPlayer[i].sceneQav != -1) {
if (gPlayerCtrl[i].qavScene.qavResrc == NULL)
gPlayer[i].sceneQav = -1;
@ -2356,13 +2362,8 @@ void PlayerLoadSave::Load(void)
}
}
}
#endif
// by NoOne: load posture info
/*for (int a = 0; a < kModeMax; a++) {
for (int b = 0; b < kPostureMax; b++) {
gPosture[a][b] = gPlayerCtrl[i].posture[a][b];
}
}*/
}
}
@ -2373,19 +2374,11 @@ void PlayerLoadSave::Save(void)
Write(&gProfile, sizeof(gProfile));
Write(&gPlayer, sizeof(gPlayer));
////// by NoOne: copy posture to TRPLAYERCTRL before saving the game
/*for (int i = 0; i < gNetPlayers; i++) {
for (int a = 0; a < kModeMax; a++) {
for (int b = 0; b < kPostureMax; b++) {
gPlayerCtrl[i].posture[a][b] = gPosture[a][b];
}
}
}*/
#ifdef NOONE_EXTENSIONS
Write((void*)kPlayerCtrlSigStart, sizeof(kPlayerCtrlSigStart));
Write(&gPlayerCtrl, sizeof(gPlayerCtrl));
Write((void*)kPlayerCtrlSigEnd, sizeof(kPlayerCtrlSigEnd));
//////
#endif
}
static PlayerLoadSave *myLoadSave;

View file

@ -61,11 +61,6 @@ struct PACKINFO
int curAmount = 0; // remaining percent
};
// by NoOne: defaut player movement speeds of all move states for gPosture
extern int gDefaultAccel[12];
// by NoOne: defaut player jump heights of all move states for gPosture
extern int gDefaultJumpZ[24];
struct POSTURE
{
int frontAccel;
@ -224,19 +219,34 @@ struct POWERUPINFO
int maxTime;
};
// by NoOne: this one stores qavs anims that can be played by trigger
struct QAVSCENE {
#ifdef NOONE_EXTENSIONS
// this one stores qavs anims that can be played by trigger
struct QAVSCENE
{
short index = -1; // index of sprite which triggered qav scene
QAV * qavResrc = NULL;
short dummy = -1;
};
// by NoOne: this one for controlling the player using triggers (movement speed, jumps and other stuff)
// this one for controlling the player using triggers (movement speed, jumps and other stuff)
struct TRPLAYERCTRL {
QAVSCENE qavScene;
};
extern TRPLAYERCTRL gPlayerCtrl[kMaxPlayers];
bool isGrown(spritetype *pSprite);
bool isShrinked(spritetype *pSprite);
bool shrinkPlayerSize(PLAYER *pPlayer, int divider);
bool growPlayerSize(PLAYER *pPlayer, int multiplier);
bool resetPlayerSize(PLAYER *pPlayer);
void deactivateSizeShrooms(PLAYER *pPlayer);
PLAYER * getPlayerById(short id);
QAV * qavSceneLoad(int qavId);
void qavScenePlay(PLAYER *pPlayer);
void qavSceneDraw(PLAYER *pPlayer, int a2, int a3, int a4, int a5);
void playerResetQavScene(PLAYER *pPlayer);
#endif
void playerResetPosture(PLAYER* pPlayer);
extern PLAYER gPlayer[kMaxPlayers];
extern PLAYER *gMe, *gView;
@ -324,17 +334,5 @@ void sub_41250(PLAYER *pPlayer);
void playerLandingSound(PLAYER *pPlayer);
void PlayerSurvive(int, int nXSprite);
void PlayerKneelsOver(int, int nXSprite);
bool isGrown(spritetype *pSprite);
bool isShrinked(spritetype *pSprite);
bool shrinkPlayerSize(PLAYER *pPlayer, int divider);
bool growPlayerSize(PLAYER *pPlayer, int multiplier);
bool resetPlayerSize(PLAYER *pPlayer);
void deactivateSizeShrooms(PLAYER *pPlayer);
PLAYER * getPlayerById(short id);
QAV * qavSceneLoad(int qavId);
void qavScenePlay(PLAYER *pPlayer);
void qavSceneDraw(PLAYER *pPlayer, int a2, int a3, int a4, int a5);
void playerResetPosture(PLAYER* pPlayer);
void playerResetQavScene(PLAYER *pPlayer);
END_BLD_NS

View file

@ -302,10 +302,11 @@ void SEQINST::Update(ACTIVE *pActive)
sfxPlay3DSound(&sprite[xsprite[pActive->xindex].reference], sound, -1, 0);
}
// by NoOne: add surfaceSound trigger feature
spritetype* pSprite = &sprite[xsprite[pActive->xindex].reference];
if (!VanillaMode() && pSequence->frames[frameIndex].surfaceSound && zvel[pSprite->xvel] == 0 && xvel[pSprite->xvel] != 0) {
// by NoOne: add surfaceSound trigger feature
if (gUpperLink[pSprite->sectnum] >= 0) break; // don't play surface sound for stacked sectors
int surf = tileGetSurfType(pSprite->sectnum + 0x4000); if (!surf) break;
static int surfSfxMove[15][4] = {
@ -336,8 +337,6 @@ void SEQINST::Update(ACTIVE *pActive)
sfxPlay3DSoundCP(pSprite, sndId, -1, 0, 0, (surfSfxMove[surf][2] != relVol) ? relVol : surfSfxMove[surf][3]);
}
}
break;
}
case 4:

File diff suppressed because it is too large Load diff

View file

@ -32,9 +32,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "player.h"
BEGIN_BLD_NS
#define kPlayerCtrlSigStart "<<<<TRPLAYERCTRL{" // save game TRPLAYERCTRL block start
#define kPlayerCtrlSigEnd "}TRPLAYERCTRL>>>>" // save game TRPLAYERCTRL block end
void trTriggerSector(unsigned int nSector, XSECTOR *pXSector, int command);
void trMessageSector(unsigned int nSector, EVENT event);
void trTriggerWall(unsigned int nWall, XWALL *pXWall, int command);
@ -45,8 +42,12 @@ void trProcessBusy(void);
void trInit(void);
void trTextOver(int nId);
// By NoOne: functions required for new features
#ifdef NOONE_EXTENSIONS
// functions required for new features
// -------------------------------------------------------
#define kPlayerCtrlSigStart "<<<<TRPLAYERCTRL{" // save game TRPLAYERCTRL block start
#define kPlayerCtrlSigEnd "}TRPLAYERCTRL>>>>" // save game TRPLAYERCTRL block end
void pastePropertiesInObj(int type, int nDest, EVENT event);
spritetype* getTargetInRange(spritetype* pSprite, int minDist, int maxDist, short data, short teamMode);
bool isMateOf(XSPRITE* pXDude, XSPRITE* pXSprite);
@ -86,6 +87,8 @@ bool valueIsBetween(int val, int min, int max);
void trPlayerCtrlLink(XSPRITE* pXSource, PLAYER* pPlayer);
void trPlayerCtrlStartScene(XSPRITE* pXSource, PLAYER* pPlayer);
void trPlayerCtrlStopScene(XSPRITE* pXSource, PLAYER* pPlayer);
char modernTypeSetSpriteState(int nSprite, XSPRITE* pXSprite, int nState);
// -------------------------------------------------------
#endif// -------------------------------------------------------
END_BLD_NS

View file

@ -3498,12 +3498,17 @@ void viewDrawScreen(bool sceneonly)
nPalette = pSector->floorpal;
}
#ifdef NOONE_EXTENSIONS
if (gView->sceneQav < 0) WeaponDraw(gView, nShade, cX, cY, nPalette);
else if (gView->pXSprite->health > 0) qavSceneDraw(gView, nShade, cX, cY, nPalette);
else {
gView->sceneQav = gView->weaponQav = -1;
gView->weaponTimer = gView->curWeapon = 0;
}
#else
WeaponDraw(gView, nShade, cX, cY, nPalette);
#endif
}

View file

@ -36,11 +36,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS
ZONE gStartZone[8];
#ifdef NOONE_EXTENSIONS
ZONE gStartZoneTeam1[8];
ZONE gStartZoneTeam2[8];
bool gTeamsSpawnUsed = false;
#endif
void warpInit(void)
{
for (int i = 0; i < kMaxSectors; i++)
@ -48,7 +48,9 @@ void warpInit(void)
gUpperLink[i] = -1;
gLowerLink[i] = -1;
}
#ifdef NOONE_EXTENSIONS
int team1 = 0; int team2 = 0; gTeamsSpawnUsed = false; // increment if team start positions specified.
#endif
for (int nSprite = 0; nSprite < kMaxSprites; nSprite++)
{
if (sprite[nSprite].statnum < kMaxStatus) {
@ -79,7 +81,8 @@ void warpInit(void)
pZone->sectnum = pSprite->sectnum;
pZone->ang = pSprite->ang;
// By NoOne: fill player spawn position according team of player in TEAMS mode.
#ifdef NOONE_EXTENSIONS
// fill player spawn position according team of player in TEAMS mode.
if (gModernMap && gGameOptions.nGameType == 3) {
if (pXSprite->data2 == 1) {
pZone = &gStartZoneTeam1[team1];
@ -100,6 +103,8 @@ void warpInit(void)
team2++;
}
}
#endif
}
DeleteSprite(nSprite);
}
@ -135,6 +140,7 @@ void warpInit(void)
}
}
#ifdef NOONE_EXTENSIONS
// check if there is enough start positions for teams, if any used
if (team1 > 0 || team2 > 0) {
gTeamsSpawnUsed = true;
@ -143,6 +149,7 @@ void warpInit(void)
viewSetSystemMessage("Team A positions: %d, Team B positions: %d.", team1, team2);
}
}
#endif
for (int i = 0; i < kMaxSectors; i++)
{

View file

@ -30,9 +30,11 @@ struct ZONE {
short sectnum, ang;
};
extern ZONE gStartZone[8];
#ifdef NOONE_EXTENSIONS
extern ZONE gStartZoneTeam1[8];
extern ZONE gStartZoneTeam2[8];
extern bool gTeamsSpawnUsed;
#endif
void warpInit(void);
int CheckLink(spritetype *pSprite);

View file

@ -1936,7 +1936,7 @@ char sub_4F484(PLAYER *pPlayer)
void WeaponProcess(PLAYER *pPlayer) {
pPlayer->flashEffect = ClipLow(pPlayer->flashEffect - 1, 0);
#ifdef NOONE_EXTENSIONS
if (gPlayerCtrl[pPlayer->nPlayer].qavScene.index >= 0 && pPlayer->pXSprite->health > 0) {
QAVSCENE* pQavScene = &gPlayerCtrl[pPlayer->nPlayer].qavScene;
@ -1960,6 +1960,7 @@ void WeaponProcess(PLAYER *pPlayer) {
return;
}
#endif
if (pPlayer->pXSprite->health == 0)
{