From 64fc0b66b27393e47d2b30f544c68842f5437092 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 6 Jul 2021 10:26:43 +0200 Subject: [PATCH] - SW: added countermeasure to re-enable lower skills on mods not implementing them. Aside from spawning the enemies from the lowest supported skill it will also reduce the threat level by reducing health of some enemies or by replacing the harder Ninja variants with the base type. --- source/games/sw/src/coolie.cpp | 2 +- source/games/sw/src/game.h | 1 + source/games/sw/src/girlninj.cpp | 2 +- source/games/sw/src/ninja.cpp | 12 ++++-- source/games/sw/src/save.cpp | 1 + source/games/sw/src/sprite.cpp | 63 +++++++++++++++++++++++--------- 6 files changed, 57 insertions(+), 24 deletions(-) diff --git a/source/games/sw/src/coolie.cpp b/source/games/sw/src/coolie.cpp index d6a7743f3..8eac328ce 100644 --- a/source/games/sw/src/coolie.cpp +++ b/source/games/sw/src/coolie.cpp @@ -562,7 +562,7 @@ int SpawnCoolg(short SpriteNum) { // Don't do a ghost every time - if (RANDOM_RANGE(1000) > 700) + if (RANDOM_RANGE(1000) > 700 || Skill < MinEnemySkill - 1) { return(0); } diff --git a/source/games/sw/src/game.h b/source/games/sw/src/game.h index 697655440..8c515e487 100644 --- a/source/games/sw/src/game.h +++ b/source/games/sw/src/game.h @@ -2095,6 +2095,7 @@ extern USERSAVE puser[MAX_SW_PLAYERS_REG]; extern double smoothratio; extern int MoveSkip4, MoveSkip2, MoveSkip8; +extern int MinEnemySkill; #define MASTER_SWITCHING 1 diff --git a/source/games/sw/src/girlninj.cpp b/source/games/sw/src/girlninj.cpp index 582e96f56..59ab2d1e2 100644 --- a/source/games/sw/src/girlninj.cpp +++ b/source/games/sw/src/girlninj.cpp @@ -728,7 +728,7 @@ SetupGirlNinja(short SpriteNum) else { u = SpawnUser(SpriteNum, GIRLNINJA_RUN_R0, s_GirlNinjaRun[0]); - u->Health = 100; + u->Health = (Skill < MinEnemySkill - 1) ? 50 : 100; } u->StateEnd = s_GirlNinjaDie; diff --git a/source/games/sw/src/ninja.cpp b/source/games/sw/src/ninja.cpp index 892f50774..e637fe6ee 100644 --- a/source/games/sw/src/ninja.cpp +++ b/source/games/sw/src/ninja.cpp @@ -1832,6 +1832,10 @@ SetupNinja(short SpriteNum) ANIMATOR DoActorDecide; short pic = sp->picnum; + // Fake some skill settings in case the lower skills are empty. + int RedNinjaHealth = MinEnemySkill <= Skill ? HEALTH_RED_NINJA : HEALTH_NINJA; + if (Skill < MinEnemySkill - 1) sp->pal = 0; + if (TEST(sp->cstat, CSTAT_SPRITE_RESTORE)) { u = User[SpriteNum].Data(); @@ -1853,7 +1857,7 @@ SetupNinja(short SpriteNum) u->Attrib = &InvisibleNinjaAttrib; EnemyDefaults(SpriteNum, &NinjaGreenActionSet, &NinjaPersonality); if (!TEST(sp->cstat, CSTAT_SPRITE_RESTORE)) - u->Health = HEALTH_RED_NINJA; + u->Health = RedNinjaHealth; SET(sp->cstat, CSTAT_SPRITE_TRANSLUCENT); sp->shade = 127; sp->pal = u->spal = PALETTE_PLAYER5; @@ -1881,7 +1885,7 @@ SetupNinja(short SpriteNum) u->Attrib = &NinjaAttrib; EnemyDefaults(SpriteNum, &NinjaRedActionSet, &NinjaPersonality); if (!TEST(sp->cstat, CSTAT_SPRITE_RESTORE)) - u->Health = HEALTH_RED_NINJA; + u->Health = RedNinjaHealth; sp->pal = u->spal = PALETTE_PLAYER3; if (pic == NINJA_CRAWL_R0) { @@ -1906,7 +1910,7 @@ SetupNinja(short SpriteNum) u->Attrib = &NinjaAttrib; EnemyDefaults(SpriteNum, &NinjaSeekerActionSet, &NinjaPersonality); if (!TEST(sp->cstat, CSTAT_SPRITE_RESTORE)) - u->Health = HEALTH_RED_NINJA; + u->Health = RedNinjaHealth; sp->pal = u->spal = PAL_XLAT_LT_TAN; u->Attrib = &NinjaAttrib; } @@ -1915,7 +1919,7 @@ SetupNinja(short SpriteNum) u->Attrib = &NinjaAttrib; EnemyDefaults(SpriteNum, &NinjaGrenadeActionSet, &NinjaPersonality); if (!TEST(sp->cstat, CSTAT_SPRITE_RESTORE)) - u->Health = HEALTH_RED_NINJA; + u->Health = RedNinjaHealth; sp->pal = u->spal = PAL_XLAT_LT_GREY; u->Attrib = &NinjaAttrib; } diff --git a/source/games/sw/src/save.cpp b/source/games/sw/src/save.cpp index efe2be333..a8a17a524 100644 --- a/source/games/sw/src/save.cpp +++ b/source/games/sw/src/save.cpp @@ -1270,6 +1270,7 @@ void GameInterface::SerializeGameState(FSerializer& arc) .Array("bosswasseen", bosswasseen, 3) .Array("BossSpriteNum", BossSpriteNum, 3); arc.Array("tracks", Track, countof(Track)) + ("minenemyskill", MinEnemySkill) ; postSerializePanelSprites(arc); arc.EndObject(); diff --git a/source/games/sw/src/sprite.cpp b/source/games/sw/src/sprite.cpp index bc6a1ec1b..eb7810072 100644 --- a/source/games/sw/src/sprite.cpp +++ b/source/games/sw/src/sprite.cpp @@ -92,6 +92,7 @@ void InitWeaponUzi(PLAYERp); bool FAF_Sector(short sectnum); int MoveSkip4, MoveSkip2, MoveSkip8; +int MinEnemySkill; extern STATE s_CarryFlag[]; extern STATE s_CarryFlagNoDet[]; @@ -1049,7 +1050,8 @@ ActorTestSpawn(SPRITEp sp) } // Skill ranges from -1 (No Monsters) to 3 - if (TEST(sp->extra, SPRX_SKILL) > Skill) + int spawnskill = TEST(sp->extra, SPRX_SKILL); + if (spawnskill > MinEnemySkill || (MinEnemySkill == 0 && spawnskill > Skill)) { // JBF: hack to fix Wanton Destruction's missing Sumos, Serpents, and Zilla on Skill < 2 @@ -1091,23 +1093,44 @@ ActorTestSpawn(SPRITEp sp) } -void PreCacheRipper(void); -void PreCacheRipper2(void); -void PreCacheCoolie(void); -void PreCacheSerpent(void); -void PreCacheGuardian(void); -void PreCacheNinja(void); -void PreCacheSumo(void); -void PreCacheEel(void); -void PreCacheToiletGirl(void); -void PreCacheWashGirl(void); -void PreCacheTrash(void); -void PreCacheBunny(void); -void PreCacheSkel(void); -void PreCacheHornet(void); -void PreCacheSkull(void); -void PreCacheBetty(void); -void PreCachePachinko(void); +int EnemyCheckSkill() +{ + StatIterator it(STAT_DEFAULT); + int maxskill = INT_MAX; + int SpriteNum; + while ((SpriteNum = it.NextIndex()) >= 0) + { + auto sp = &sprite[SpriteNum]; + + switch (sp->picnum) + { + case COOLIE_RUN_R0: + case NINJA_RUN_R0: + case NINJA_CRAWL_R0: + case GORO_RUN_R0: + case 1441: + case COOLG_RUN_R0: + case EEL_RUN_R0: + case SUMO_RUN_R0: + case ZILLA_RUN_R0: + case RIPPER_RUN_R0: + case RIPPER2_RUN_R0: + case SERP_RUN_R0: + case LAVA_RUN_R0: + case SKEL_RUN_R0: + case HORNET_RUN_R0: + case SKULL_R0: + case BETTY_R0: + case GIRLNINJA_RUN_R0: + { + int myskill = sp->extra & SPRX_SKILL; + if (myskill < maxskill) maxskill = myskill; + } + } + } + if (maxskill < 0 || maxskill == INT_MAX) maxskill = 0; + return maxskill; +} bool ActorSpawn(SPRITEp sp) @@ -1789,6 +1812,8 @@ SpriteSetup(void) short i, num; int cz,fz; + MinEnemySkill = EnemyCheckSkill(); + // special case for player PicAnimOff(PLAYER_NINJA_RUN_R0); @@ -1808,6 +1833,8 @@ SpriteSetup(void) // Call my little sprite setup routine first JS_SpriteSetup(); + int minEnemySkill = EnemyCheckSkill(); + StatIterator it(STAT_DEFAULT); while ((SpriteNum = it.NextIndex()) >= 0) {