diff --git a/source/games/blood/src/player.cpp b/source/games/blood/src/player.cpp index b32c5e76d..e1ea32080 100644 --- a/source/games/blood/src/player.cpp +++ b/source/games/blood/src/player.cpp @@ -2328,4 +2328,78 @@ void SerializePlayers(FSerializer& arc) +DEFINE_FIELD_X(BloodPlayer, PLAYER, newWeapon) +DEFINE_FIELD_X(BloodPlayer, PLAYER, weaponQav) +DEFINE_FIELD_X(BloodPlayer, PLAYER, qavCallback) +DEFINE_FIELD_X(BloodPlayer, PLAYER, isRunning) +DEFINE_FIELD_X(BloodPlayer, PLAYER, posture) // stand, crouch, swim +DEFINE_FIELD_X(BloodPlayer, PLAYER, sceneQav) // by NoOne: used to keep qav id +DEFINE_FIELD_X(BloodPlayer, PLAYER, bobPhase) +DEFINE_FIELD_X(BloodPlayer, PLAYER, bobAmp) +DEFINE_FIELD_X(BloodPlayer, PLAYER, bobHeight) +DEFINE_FIELD_X(BloodPlayer, PLAYER, bobWidth) +DEFINE_FIELD_X(BloodPlayer, PLAYER, swayPhase) +DEFINE_FIELD_X(BloodPlayer, PLAYER, swayAmp) +DEFINE_FIELD_X(BloodPlayer, PLAYER, swayHeight) +DEFINE_FIELD_X(BloodPlayer, PLAYER, swayWidth) +DEFINE_FIELD_X(BloodPlayer, PLAYER, nPlayer) // Connect id +DEFINE_FIELD_X(BloodPlayer, PLAYER, nSprite) +DEFINE_FIELD_X(BloodPlayer, PLAYER, lifeMode) +DEFINE_FIELD_X(BloodPlayer, PLAYER, zView) +DEFINE_FIELD_X(BloodPlayer, PLAYER, zViewVel) +DEFINE_FIELD_X(BloodPlayer, PLAYER, zWeapon) +DEFINE_FIELD_X(BloodPlayer, PLAYER, zWeaponVel) +DEFINE_FIELD_X(BloodPlayer, PLAYER, slope) +DEFINE_FIELD_X(BloodPlayer, PLAYER, isUnderwater) +DEFINE_FIELD_X(BloodPlayer, PLAYER, hasKey) +DEFINE_FIELD_X(BloodPlayer, PLAYER, hasFlag) +DEFINE_FIELD_X(BloodPlayer, PLAYER, damageControl) +DEFINE_FIELD_X(BloodPlayer, PLAYER, curWeapon) +DEFINE_FIELD_X(BloodPlayer, PLAYER, nextWeapon) +DEFINE_FIELD_X(BloodPlayer, PLAYER, weaponTimer) +DEFINE_FIELD_X(BloodPlayer, PLAYER, weaponState) +DEFINE_FIELD_X(BloodPlayer, PLAYER, weaponAmmo) //rename +DEFINE_FIELD_X(BloodPlayer, PLAYER, hasWeapon) +DEFINE_FIELD_X(BloodPlayer, PLAYER, weaponMode) +DEFINE_FIELD_X(BloodPlayer, PLAYER, weaponOrder) +DEFINE_FIELD_X(BloodPlayer, PLAYER, ammoCount) +DEFINE_FIELD_X(BloodPlayer, PLAYER, qavLoop) +DEFINE_FIELD_X(BloodPlayer, PLAYER, fuseTime) +DEFINE_FIELD_X(BloodPlayer, PLAYER, throwTime) +DEFINE_FIELD_X(BloodPlayer, PLAYER, throwPower) +DEFINE_FIELD_X(BloodPlayer, PLAYER, aim) // world +DEFINE_FIELD_X(BloodPlayer, PLAYER, aimTarget) // aim target sprite +DEFINE_FIELD_X(BloodPlayer, PLAYER, aimTargetsCount) +DEFINE_FIELD_X(BloodPlayer, PLAYER, aimTargets) +DEFINE_FIELD_X(BloodPlayer, PLAYER, deathTime) +DEFINE_FIELD_X(BloodPlayer, PLAYER, pwUpTime) +DEFINE_FIELD_X(BloodPlayer, PLAYER, fragCount) +DEFINE_FIELD_X(BloodPlayer, PLAYER, fragInfo) +DEFINE_FIELD_X(BloodPlayer, PLAYER, underwaterTime) +DEFINE_FIELD_X(BloodPlayer, PLAYER, bubbleTime) +DEFINE_FIELD_X(BloodPlayer, PLAYER, restTime) +DEFINE_FIELD_X(BloodPlayer, PLAYER, kickPower) +DEFINE_FIELD_X(BloodPlayer, PLAYER, laughCount) +DEFINE_FIELD_X(BloodPlayer, PLAYER, godMode) +DEFINE_FIELD_X(BloodPlayer, PLAYER, fallScream) +DEFINE_FIELD_X(BloodPlayer, PLAYER, cantJump) +DEFINE_FIELD_X(BloodPlayer, PLAYER, packItemTime) // pack timer +DEFINE_FIELD_X(BloodPlayer, PLAYER, packItemId) // pack id 1: diving suit, 2: crystal ball, 3: +DEFINE_FIELD_X(BloodPlayer, PLAYER, packSlots) // at325 1]: diving suit, [2]: crystal ball, +DEFINE_FIELD_X(BloodPlayer, PLAYER, armor) // armor +DEFINE_FIELD_X(BloodPlayer, PLAYER, voodooTarget) +DEFINE_FIELD_X(BloodPlayer, PLAYER, flickerEffect) +DEFINE_FIELD_X(BloodPlayer, PLAYER, tiltEffect) +DEFINE_FIELD_X(BloodPlayer, PLAYER, visibility) +DEFINE_FIELD_X(BloodPlayer, PLAYER, painEffect) +DEFINE_FIELD_X(BloodPlayer, PLAYER, blindEffect) +DEFINE_FIELD_X(BloodPlayer, PLAYER, chokeEffect) +DEFINE_FIELD_X(BloodPlayer, PLAYER, handTime) +DEFINE_FIELD_X(BloodPlayer, PLAYER, hand) // if true, there is hand start choking the player +DEFINE_FIELD_X(BloodPlayer, PLAYER, pickupEffect) +DEFINE_FIELD_X(BloodPlayer, PLAYER, flashEffect) // if true, reduce pPlayer->visibility counter +DEFINE_FIELD_X(BloodPlayer, PLAYER, quakeEffect) +DEFINE_FIELD_X(BloodPlayer, PLAYER, player_par) +DEFINE_FIELD_X(BloodPlayer, PLAYER, nWaterPal) + END_BLD_NS diff --git a/source/games/blood/src/sbar.cpp b/source/games/blood/src/sbar.cpp index 245d9ee9d..a91cb89fe 100644 --- a/source/games/blood/src/sbar.cpp +++ b/source/games/blood/src/sbar.cpp @@ -55,26 +55,6 @@ static const char* gPackIcons[5] = { "PackIcon1", "PackIcon2", "PackIcon3", "PackIcon4", "PackIcon5" }; -static const char* packIcons2[] = { "Pack2Icon1", "Pack2Icon2", "Pack2Icon3", "Pack2Icon4", "Pack2Icon5" }; -static const char* ammoIcons[] = { nullptr, "AmmoIcon1", "AmmoIcon2", "AmmoIcon3", "AmmoIcon4", "AmmoIcon5", "AmmoIcon6", - "AmmoIcon7", "AmmoIcon8", "AmmoIcon9", "AmmoIcon10", "AmmoIcon11" }; - -static const float packScale[] = { 0.5f, 0.3f, 0.6f, 0.5f, 0.4f }; -static const int packYoffs[] = { 0, 0, 0, -4, 0 }; -static const float ammoScale[] = { 0, 0.5f, 0.8f, 0.7f, 0.5f, 0.7f, 0.5f, 0.3f, 0.3f, 0.6f, 0.5f, 0.45f }; -static const int ammoYoffs[] = { 0, 0, 0, 3, -6, 2, 4, -6, -6, -6, 2, 2 }; - - -struct POWERUPDISPLAY -{ - int nTile; - float nScaleRatio; - int yOffset; - int remainingDuration; -}; - - - class DBloodStatusBar : public DBaseStatusBar { DECLARE_CLASS(DBloodStatusBar, DBaseStatusBar) @@ -259,29 +239,6 @@ private: } } - - //--------------------------------------------------------------------------- - // - // - // - //--------------------------------------------------------------------------- - enum { nPowerUps = 11 }; - - void sortPowerUps(POWERUPDISPLAY* powerups) { - for (int i = 1; i < nPowerUps; i++) - { - for (int j = 0; j < nPowerUps - i; j++) - { - if (powerups[j].remainingDuration > powerups[j + 1].remainingDuration) - { - POWERUPDISPLAY temp = powerups[j]; - powerups[j] = powerups[j + 1]; - powerups[j + 1] = temp; - } - } - } - } - //--------------------------------------------------------------------------- // // @@ -290,37 +247,49 @@ private: void viewDrawPowerUps(PLAYER* pPlayer) { + enum { nPowerUps = 11 }; + + static const float powerScale[] = { 0.4f, 0.4f, 0.3f, 0.3f, 0.4f, 0.3f, 0.4f, 0.5f, 0.3f, 0.4f, 0.4f }; + static const int powerYoffs[] = { 0, 5, 9, 5, 9, 7, 4, 5, 9, 4, 4 }; + + static const int powerOrder[] = { kPwUpShadowCloak, kPwUpReflectShots, kPwUpDeathMask, kPwUpTwoGuns, kPwUpShadowCloakUseless, kPwUpFeatherFall, + kPwUpGasMask, kPwUpDoppleganger, kPwUpAsbestArmor, kPwUpGrowShroom, kPwUpShrinkShroom }; + if (!hud_powerupduration) return; - POWERUPDISPLAY powerups[nPowerUps]; - powerups[0] = { gPowerUpInfo[kPwUpShadowCloak].picnum, 0.4f, 0, pPlayer->pwUpTime[kPwUpShadowCloak] }; // Invisibility - powerups[1] = { gPowerUpInfo[kPwUpReflectShots].picnum, 0.4f, 5, pPlayer->pwUpTime[kPwUpReflectShots] }; // Reflects enemy shots - powerups[2] = { gPowerUpInfo[kPwUpDeathMask].picnum, 0.3f, 9, pPlayer->pwUpTime[kPwUpDeathMask] }; // Invulnerability - powerups[3] = { gPowerUpInfo[kPwUpTwoGuns].picnum, 0.3f, 5, pPlayer->pwUpTime[kPwUpTwoGuns] }; // Guns Akimbo - powerups[4] = { gPowerUpInfo[kPwUpShadowCloakUseless].picnum, 0.4f, 9, pPlayer->pwUpTime[kPwUpShadowCloakUseless] }; // Does nothing, only appears at near the end of Cryptic Passage's Lost Monastery (CP04) + int powersort[nPowerUps]; - // Not in official maps, but custom maps can use them - powerups[5] = { gPowerUpInfo[kPwUpFeatherFall].picnum, 0.3f, 7, pPlayer->pwUpTime[kPwUpFeatherFall] }; // Makes player immune to fall damage - powerups[6] = { gPowerUpInfo[kPwUpGasMask].picnum, 0.4f, 4, pPlayer->pwUpTime[kPwUpGasMask] }; // Makes player immune to choke damage - powerups[7] = { gPowerUpInfo[kPwUpDoppleganger].picnum, 0.5f, 5, pPlayer->pwUpTime[kPwUpDoppleganger] }; // Works in multiplayer, it swaps player's team colors, so enemy team player thinks it's a team mate - powerups[8] = { gPowerUpInfo[kPwUpAsbestArmor].picnum, 0.3f, 9, pPlayer->pwUpTime[kPwUpAsbestArmor] }; // Makes player immune to fire damage and draws HUD - powerups[9] = { gPowerUpInfo[kPwUpGrowShroom].picnum, 0.4f, 4, pPlayer->pwUpTime[kPwUpGrowShroom] }; // Grows player size, works only if gModernMap == true - powerups[10] = { gPowerUpInfo[kPwUpShrinkShroom].picnum, 0.4f, 4, pPlayer->pwUpTime[kPwUpShrinkShroom] }; // Shrinks player size, works only if gModernMap == true + for (int i = 0; i < nPowerUps; i++) powersort[i] = i; - sortPowerUps(powerups); + for (int i = 0; i < nPowerUps; i++) + { + int power1 = powersort[i]; + for (int j = i + 1; j < nPowerUps; j++) + { + int power2 = powersort[j]; + if (pPlayer->pwUpTime[powerOrder[power1]] > pPlayer->pwUpTime[powerOrder[power2]]) + { + powersort[i] = power2; + powersort[j] = power1; + } + } + } const int warningTime = 5; const int x = 15; int y = -50; for (int i = 0; i < nPowerUps; i++) { - if (powerups[i].remainingDuration) + int order = powersort[i]; + int power = powerOrder[order]; + int time = pPlayer->pwUpTime[power]; + if (time > 0) { - int remainingSeconds = powerups[i].remainingDuration / 100; + int remainingSeconds = time / 100; if (remainingSeconds > warningTime || (PlayClock & 32)) { - DrawStatMaskedSprite(powerups[i].nTile, x, y + powerups[i].yOffset, 0, 0, 256, (int)(65536 * powerups[i].nScaleRatio), DI_SCREEN_LEFT_CENTER); + DrawStatMaskedSprite(gPowerUpInfo[power].picnum, x, y + powerYoffs[order], 0, 0, 256, (int)(65536 * powerScale[order]), DI_SCREEN_LEFT_CENTER); } DrawStatNumber("%d", remainingSeconds, "SBarNumberInv", x + 15, y, 0, remainingSeconds > warningTime ? 0 : 2, 256, 65536 * 0.5, DI_SCREEN_LEFT_CENTER); @@ -389,6 +358,10 @@ private: void DrawPackItemInStatusBar2(PLAYER* pPlayer, int x, int y, int x2, int y2, int nStat, int nScale) { + static const char* packIcons2[] = { "Pack2Icon1", "Pack2Icon2", "Pack2Icon3", "Pack2Icon4", "Pack2Icon5" }; + static const float packScale[] = { 0.5f, 0.3f, 0.6f, 0.5f, 0.4f }; + static const int packYoffs[] = { 0, 0, 0, -4, 0 }; + if (pPlayer->packItemId < 0) return; DrawStatMaskedSprite(packIcons2[pPlayer->packItemId], x, y + packYoffs[pPlayer->packItemId], 0, 0, nStat, packScale[pPlayer->packItemId] * 65536); @@ -711,6 +684,12 @@ private: void DrawHUD2() { + static const char* ammoIcons[] = { nullptr, "AmmoIcon1", "AmmoIcon2", "AmmoIcon3", "AmmoIcon4", "AmmoIcon5", "AmmoIcon6", + "AmmoIcon7", "AmmoIcon8", "AmmoIcon9", "AmmoIcon10", "AmmoIcon11" }; + + static const float ammoScale[] = { 0, 0.5f, 0.8f, 0.7f, 0.5f, 0.7f, 0.5f, 0.3f, 0.3f, 0.6f, 0.5f, 0.45f }; + static const int ammoYoffs[] = { 0, 0, 0, 3, -6, 2, 4, -6, -6, -6, 2, 2 }; + PLAYER* pPlayer = gView; XSPRITE* pXSprite = pPlayer->pXSprite; diff --git a/wadsrc/static/zscript/games/blood/bloodgame.zs b/wadsrc/static/zscript/games/blood/bloodgame.zs index 839b2f6cb..145136eb3 100644 --- a/wadsrc/static/zscript/games/blood/bloodgame.zs +++ b/wadsrc/static/zscript/games/blood/bloodgame.zs @@ -6,3 +6,92 @@ struct Blood native native static void sndStartSample(int resid, int volume, int channel, bool loop = false, int chanflags = 0); native static void sndStartSampleNamed(String sname, int volume, int channel); } + +struct PACKINFO // not native! +{ + bool isActive; + int curAmount; +} + +struct BloodPlayer native +{ + //spritetype* pSprite; + //XSPRITE* pXSprite; + //DUDEINFO* pDudeInfo; + //PlayerHorizon horizon; + //PlayerAngle angle; + native uint8 newWeapon; + native int weaponQav; + native int qavCallback; + native bool isRunning; + native int posture; // stand, crouch, swim + native int sceneQav; // by NoOne: used to keep qav id + native int bobPhase; + native int bobAmp; + native int bobHeight; + native int bobWidth; + native int swayPhase; + native int swayAmp; + native int swayHeight; + native int swayWidth; + native int nPlayer; // Connect id + native int nSprite; + native int lifeMode; + native int zView; + native int zViewVel; + native int zWeapon; + native int zWeaponVel; + native int slope; + native bool isUnderwater; + native bool hasKey[8]; + native int8 hasFlag; + native int damageControl[7]; + native int8 curWeapon; + native int8 nextWeapon; + native int weaponTimer; + native int weaponState; + native int weaponAmmo; //rename + native bool hasWeapon[14]; + native int weaponMode[14]; + native int weaponOrder[2][14]; + native int ammoCount[12]; + native bool qavLoop; + native int fuseTime; + native int throwTime; + native int throwPower; + //native Aim aim; // world + native int aimTarget; // aim target sprite + native int aimTargetsCount; + native short aimTargets[16]; + native int deathTime; + native int pwUpTime[51]; // kMaxPowerUps + native int fragCount; + native int fragInfo[8]; + native int underwaterTime; + native int bubbleTime; + native int restTime; + native int kickPower; + native int laughCount; + native bool godMode; + native bool fallScream; + native bool cantJump; + native int packItemTime; // pack timer + native int packItemId; // pack id 1: diving suit, 2: crystal ball, 3: beast vision 4: jump boots + native PACKINFO packSlots[5]; // at325 [1]: diving suit, [2]: crystal ball, [3]: beast vision [4]: jump boots + native int armor[3]; // armor + native int voodooTarget; + native int flickerEffect; + native int tiltEffect; + native int visibility; + native int painEffect; + native int blindEffect; + native int chokeEffect; + native int handTime; + native bool hand; // if true, there is hand start choking the player + native int pickupEffect; + native bool flashEffect; // if true, reduce pPlayer->visibility counter + native int quakeEffect; + native int player_par; + native int nWaterPal; + //POSTURE pPosture[kModeMax][kPostureMax]; +};