Add NAM/NAPALM support

Big thanks to NY00123 for his NAM.EXE reconstruction work
This commit is contained in:
nukeykt 2019-06-09 00:29:30 +09:00 committed by Christoph Oelckers
parent 75d2e81e98
commit eafeb27996
11 changed files with 203 additions and 46 deletions

View file

@ -3913,6 +3913,8 @@ ACTOR_STATIC void G_MoveActors(void)
if (g_mineCartCnt)
G_MoveMineCart();
int bBoom = 0;
if (RRRA)
{
int spriteNum = headspritestat[117];
@ -5793,7 +5795,18 @@ ACTOR_STATIC void G_MoveActors(void)
}
DETONATEB:
if (!NAM)
bBoom = 0;
if ((detonatePlayer >= 0 && g_player[detonatePlayer].ps->hbomb_on == 0) || pData[3] == 1)
bBoom = 1;
if (NAM && pSprite->picnum == HEAVYHBOMB)
{
pSprite->extra--;
if (pSprite->extra <= 0)
bBoom = 1;
}
if (bBoom)
{
pData[4]++;

View file

@ -139,6 +139,9 @@ const uint8_t CheatFunctionIDs[NUMCHEATS] =
CHEAT_COORDS,
CHEAT_DEBUG,
};
char const * const g_NAMMattCheatQuote = "Matt Saettler. matts@seanet.com";
void G_SetupCheats(void)
{
if (RR)
@ -176,6 +179,38 @@ void G_SetupCheats(void)
Bstrcpy(CheatStrings[39], "van");
}
}
else if (NAM)
{
CheatKeys[0] = sc_N;
CheatKeys[1] = sc_V;
Bstrcpy(CheatStrings[0], "acaleb");
Bstrcpy(CheatStrings[1], "ablood");
Bstrcpy(CheatStrings[2], "alevel###");
Bstrcpy(CheatStrings[3], "acoords");
Bstrcpy(CheatStrings[4], "aview");
Bstrcpy(CheatStrings[5], "<RESERVED>");
Bstrcpy(CheatStrings[7], "<RESERVED>");
Bstrcpy(CheatStrings[8], "<RESERVED>");
Bstrcpy(CheatStrings[9], "arate");
Bstrcpy(CheatStrings[10], "askill");
Bstrcpy(CheatStrings[11], "<RESERVED>");
Bstrcpy(CheatStrings[12], "ahyper");
Bstrcpy(CheatStrings[13], "<RESERVED>");
Bstrcpy(CheatStrings[16], "amatt");
Bstrcpy(CheatStrings[17], "ashowmap");
Bstrcpy(CheatStrings[18], "agod");
Bstrcpy(CheatStrings[19], "<RESERVED>");
Bstrcpy(CheatStrings[20], "aclip");
Bstrcpy(CheatStrings[21], "aweapons");
Bstrcpy(CheatStrings[22], "ainventory");
Bstrcpy(CheatStrings[23], "<RESERVED>");
Bstrcpy(CheatStrings[24], "adebug");
Bstrcpy(CheatStrings[26], "acgs");
Bstrcpy(g_gametypeNames[0], "GruntMatch (Spawn)");
Bstrcpy(g_gametypeNames[2], "GruntMatch (No Spawn)");
}
}
static void doinvcheat(DukePlayer_t * const pPlayer, int32_t invidx, int32_t defaultnum)
@ -624,7 +659,15 @@ void G_DoCheats(void)
return;
case CHEAT_TODD:
P_DoQuote(QUOTE_CHEAT_TODD, pPlayer);
if (NAM)
{
Bstrcpy(apStrings[QUOTE_RESERVED4], g_NAMMattCheatQuote);
P_DoQuote(QUOTE_RESERVED4, pPlayer);
}
else
{
P_DoQuote(QUOTE_CHEAT_TODD, pPlayer);
}
end_cheat(pPlayer);
return;

View file

@ -269,6 +269,18 @@ void G_CheckCommandLine(int32_t argc, char const * const * argv)
i++;
continue;
}
if (!Bstrcasecmp(c+1, "nam"))
{
g_gameType = GAMEFLAG_NAM;
i++;
continue;
}
if (!Bstrcasecmp(c+1, "napalm"))
{
g_gameType = GAMEFLAG_NAM|GAMEFLAG_NAPALM;
i++;
continue;
}
if (!Bstrcasecmp(c+1, "setup"))
{
g_commandSetup = TRUE;

View file

@ -38,9 +38,9 @@ const char *g_gameNamePtr = NULL;
// grp/con handling
static const char *defaultconfilename = "GAME.CON";
static const char *defaultgamegrp[GAMECOUNT] = { "DUKE3D.GRP", "REDNECK.GRP", "REDNECK.GRP" };
static const char *defaultdeffilename[GAMECOUNT] = { "duke3d.def", "rr.def", "rrra.def" };
//static const char *defaultgameconfilename[GAMECOUNT] = { "GAME.CON", "GAME.CON", "GAME.CON" };
static const char *defaultgamegrp[GAMECOUNT] = { "DUKE3D.GRP", "REDNECK.GRP", "REDNECK.GRP", "NAM.GRP", "NAPALM.GRP" };
static const char *defaultdeffilename[GAMECOUNT] = { "duke3d.def", "rr.def", "rrra.def", "nam.def", "napalm.grp" };
static const char *defaultgameconfilename[GAMECOUNT] = { "GAME.CON", "GAME.CON", "GAME.CON", "NAM.CON", "NAPALM.CON" };
// g_grpNamePtr can ONLY point to a malloc'd block (length BMAX_PATH)
char *g_grpNamePtr = NULL;
@ -83,12 +83,11 @@ const char *G_DefaultDefFile(void)
}
const char *G_DefaultConFile(void)
{
#if 0
if (DUKE && testkopen(defaultgameconfilename[GAME_DUKE],0))
/*if (DUKE && testkopen(defaultgameconfilename[GAME_DUKE],0))
return defaultgameconfilename[GAME_DUKE];
else if (WW2GI && testkopen(defaultgameconfilename[GAME_WW2GI],0))
return defaultgameconfilename[GAME_WW2GI];
else if (NAPALM)
else */if (NAPALM)
{
if (!testkopen(defaultgameconfilename[GAME_NAPALM],0))
{
@ -108,7 +107,6 @@ const char *G_DefaultConFile(void)
else
return defaultgameconfilename[GAME_NAM];
}
#endif
return defaultconfilename;
}
@ -539,7 +537,6 @@ static void G_AddSteamPaths(const char *basepath)
addsearchpath_user(buf, SEARCHPATH_REMOVE);
#endif
#if 0
// NAM (Steam)
#if defined EDUKE32_OSX
Bsnprintf(buf, sizeof(buf), "%s/steamapps/common/Nam/Nam.app/Contents/Resources/Nam.boxer/C.harddisk/NAM", basepath);
@ -548,6 +545,7 @@ static void G_AddSteamPaths(const char *basepath)
#endif
addsearchpath_user(buf, SEARCHPATH_NAM);
#if 0
// WWII GI (Steam)
Bsnprintf(buf, sizeof(buf), "%s/steamapps/common/World War II GI/WW2GI", basepath);
addsearchpath_user(buf, SEARCHPATH_WW2GI);
@ -856,7 +854,6 @@ void G_AddSearchPaths(void)
addsearchpath_user(buf, SEARCHPATH_RRRA);
}
#if 0
// NAM (Steam)
bufsize = sizeof(buf);
if (G_ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 329650)", "InstallLocation", buf, &bufsize))
@ -868,6 +865,7 @@ void G_AddSearchPaths(void)
addsearchpath_user(buf, SEARCHPATH_NAM);
}
#if 0
// WWII GI (Steam)
bufsize = sizeof(buf);
if (G_ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 376750)", "InstallLocation", buf, &bufsize))
@ -887,6 +885,9 @@ void G_CleanupSearchPaths(void)
{
removesearchpaths_withuser(SEARCHPATH_REMOVE);
if (!NAM)
removesearchpaths_withuser(SEARCHPATH_NAM);
if (!RRRA)
removesearchpaths_withuser(SEARCHPATH_RRRA);

View file

@ -25,13 +25,13 @@ extern int g_useCwd;
#endif
#define GAMEFLAG_DUKE 0x00000001
#define GAMEFLAG_RR 0x00000002
#define GAMEFLAG_RRRA 0x00000004
//#define GAMEFLAG_NAM 0x00000002
//#define GAMEFLAG_NAPALM 0x00000004
#define GAMEFLAG_NAM 0x00000002
#define GAMEFLAG_NAPALM 0x00000004
//#define GAMEFLAG_WW2GI 0x00000008
#define GAMEFLAG_ADDON 0x00000010
#define GAMEFLAG_SHAREWARE 0x00000020
#define GAMEFLAG_RR 0x00000040
#define GAMEFLAG_RRRA 0x00000080
//#define GAMEFLAG_DUKEBETA 0x00000060 // includes 0x20 since it's a shareware beta
//#define GAMEFLAG_IONMAIDEN 0x00000080
//#define GAMEFLAG_STANDALONE 0x00000100
@ -45,8 +45,8 @@ extern int g_addonNum;
#define DUKE (g_gameType & GAMEFLAG_DUKE)
#define RR (g_gameType & GAMEFLAG_RR)
#define RRRA (g_gameType & GAMEFLAG_RRRA)
//#define NAM (g_gameType & GAMEFLAG_NAM)
//#define NAPALM (g_gameType & GAMEFLAG_NAPALM)
#define NAM (g_gameType & GAMEFLAG_NAM)
#define NAPALM (g_gameType & GAMEFLAG_NAPALM)
//#define WW2GI (g_gameType & GAMEFLAG_WW2GI)
//#define NAM_WW2GI (g_gameType & (GAMEFLAG_NAM|GAMEFLAG_WW2GI))
#define SHAREWARE (g_gameType & GAMEFLAG_SHAREWARE)
@ -57,8 +57,8 @@ enum Games_t {
GAME_DUKE = 0,
GAME_RR,
GAME_RRRA,
//GAME_NAM,
//GAME_NAPALM,
GAME_NAM,
GAME_NAPALM,
//GAME_WW2GI,
GAMECOUNT
};
@ -78,8 +78,9 @@ enum instpath_t {
enum searchpathtypes_t {
SEARCHPATH_REMOVE = 1<<0,
SEARCHPATH_RR = 1<<1,
SEARCHPATH_RRRA = 1<<2,
SEARCHPATH_NAM = 1<<1,
SEARCHPATH_RR = 1<<2,
SEARCHPATH_RRRA = 1<<3,
};
typedef enum basepal_ {

View file

@ -169,7 +169,7 @@ static int32_t G_OpenDemoRead(int32_t g_whichDemo) // 0 = mine
Bstrncpy(g_player[i].user_name, demoHeader.user_name[i], 32);
}
if (DUKE && demoHeader.version == 117)
if (!RR && demoHeader.version == 117)
{
int32_t autoRun;
kread(g_demo_recFilePtr, &autoRun, sizeof(int32_t));

View file

@ -82,7 +82,7 @@ int32_t vote_map = -1, vote_episode = -1;
int32_t g_Debug = 0;
const char *defaultrtsfilename[GAMECOUNT] = { "DUKE.RTS", "REDNECK.RTS", "REDNECK.RTS" };
const char *defaultrtsfilename[GAMECOUNT] = { "DUKE.RTS", "REDNECK.RTS", "REDNECK.RTS", "NAM.RTS", "NAPALM.RTS" };
int32_t g_Shareware = 0;
@ -121,6 +121,20 @@ const char *G_DefaultRtsFile(void)
{
if (DUKE)
return defaultrtsfilename[GAME_DUKE];
else if (NAPALM)
{
if (!testkopen(defaultrtsfilename[GAME_NAPALM],0) && testkopen(defaultrtsfilename[GAME_NAM],0))
return defaultrtsfilename[GAME_NAM]; // NAM/NAPALM Sharing
else
return defaultrtsfilename[GAME_NAPALM];
}
else if (NAM)
{
if (!testkopen(defaultrtsfilename[GAME_NAM],0) && testkopen(defaultrtsfilename[GAME_NAPALM],0))
return defaultrtsfilename[GAME_NAPALM]; // NAM/NAPALM Sharing
else
return defaultrtsfilename[GAME_NAM];
}
else if (RR)
return defaultrtsfilename[GAME_RR];
@ -2698,7 +2712,7 @@ rrbloodpool_fallthrough:
pSprite->y = sprite[spriteNum].y + (sintable[shellAng & 2047] >> 7);
pSprite->shade = -8;
if (pSprite->yvel == 1)
if (NAM)
{
pSprite->ang = shellAng + 512;
pSprite->xvel = 30;

View file

@ -64,8 +64,8 @@ static internalgrpinfo_t const internalgrpfiles[] =
// { "Duke!ZONE II (1.3D)", DZ2_13_CRC, 26135388, GAMEFLAG_DUKE|GAMEFLAG_ADDON, DUKE13_CRC, "DZ-GAME.CON", NULL},
{ "Duke!ZONE II", DZ2_PP_CRC, 44100411, GAMEFLAG_DUKE|GAMEFLAG_ADDON, DUKE15_CRC, "DZ-GAME.CON", NULL},
{ "Duke!ZONE II", (int32_t) 0x1E9516F1, 3186656, GAMEFLAG_DUKE|GAMEFLAG_ADDON, DUKE15_CRC, "DZ-GAME.CON", NULL},
//{ "NAM", NAM_CRC, 43448927, GAMEFLAG_NAM, 0, NULL, NULL},
//{ "NAPALM", NAPALM_CRC, 44365728, GAMEFLAG_NAM|GAMEFLAG_NAPALM, 0, NULL, NULL},
{ "NAM", NAM_CRC, 43448927, GAMEFLAG_NAM, 0, NULL, NULL},
{ "NAPALM", NAPALM_CRC, 44365728, GAMEFLAG_NAM|GAMEFLAG_NAPALM, 0, NULL, NULL},
//{ "WWII GI", WW2GI_CRC, 77939508, GAMEFLAG_WW2GI, 0, NULL, NULL},
//{ "Platoon Leader", PLATOONL_CRC, 37852572, GAMEFLAG_WW2GI|GAMEFLAG_ADDON, WW2GI_CRC, "PLATOONL.DEF", NULL},
{ "Redneck Rampage", RR_CRC, 141174222, GAMEFLAG_RR, 0, NULL, NULL },
@ -84,6 +84,8 @@ static void LoadList(const char * filename)
scriptfile_addsymbolvalue("GAMEFLAG_DUKE", GAMEFLAG_DUKE);
scriptfile_addsymbolvalue("GAMEFLAG_ADDON", GAMEFLAG_DUKE|GAMEFLAG_ADDON);
scriptfile_addsymbolvalue("GAMEFLAG_NAM", GAMEFLAG_NAM);
scriptfile_addsymbolvalue("GAMEFLAG_NAPALM", GAMEFLAG_NAM|GAMEFLAG_NAPALM);
scriptfile_addsymbolvalue("GAMEFLAG_RR", GAMEFLAG_RR);
scriptfile_addsymbolvalue("GAMEFLAG_RRRA", GAMEFLAG_RR|GAMEFLAG_RRRA);
scriptfile_addsymbolvalue("DUKE15_CRC", DUKE15_CRC);

View file

@ -1882,6 +1882,14 @@ void Menu_Init(void)
//MF_Minifont.emptychar.y <<= 1;
ME_SOUND_DUKETALK.name = "Leonard Talk:";
}
else if (NAPALM)
{
ME_SOUND_DUKETALK.name = "NAPALM Talk:";
}
else if (NAM)
{
ME_SOUND_DUKETALK.name = "NAM Talk:";
}
// prepare shareware
if (VOLUMEONE)

View file

@ -1330,7 +1330,7 @@ growspark_rr:
if (playerNum >= 0)
{
if (GetAutoAimAng(spriteNum, playerNum, projecTile, ZOFFSET6, 0, &startPos, 768, &Zvel, &shootAng) < 0)
if (NAM || GetAutoAimAng(spriteNum, playerNum, projecTile, ZOFFSET6, 0, &startPos, 768, &Zvel, &shootAng) < 0)
Zvel = fix16_to_int(F16(100) - pPlayer->q16horiz - pPlayer->q16horizoff) * 98;
}
else if (pSprite->statnum != STAT_EFFECTOR)
@ -2584,21 +2584,21 @@ void P_DisplayWeapon(void)
weaponShade, weaponBits, weaponPal);
}
else if ((*weaponFrame) < 23)
else if ((*weaponFrame) < (NAM ? 38 : 23))
{
G_DrawWeaponTileWithID(currentWeapon << 2, 184 - (pPlayer->look_ang >> 1), weaponY + 235 - weaponYOffset,
FIRSTGUN + 8, weaponShade, weaponBits, weaponPal);
G_DrawWeaponTileWithID(currentWeapon, 224 - (pPlayer->look_ang >> 1), weaponY + 210 - weaponYOffset, FIRSTGUN + 5,
weaponShade, weaponBits, weaponPal);
}
else if ((*weaponFrame) < 25)
else if ((*weaponFrame) < (NAM ? 44 : 25))
{
G_DrawWeaponTileWithID(currentWeapon << 2, 164 - (pPlayer->look_ang >> 1), weaponY + 245 - weaponYOffset,
FIRSTGUN + 8, weaponShade, weaponBits, weaponPal);
G_DrawWeaponTileWithID(currentWeapon, 224 - (pPlayer->look_ang >> 1), weaponY + 220 - weaponYOffset, FIRSTGUN + 5,
weaponShade, weaponBits, weaponPal);
}
else if ((*weaponFrame) < 27)
else if ((*weaponFrame) < (NAM ? 50 : 27))
G_DrawWeaponTileWithID(currentWeapon, 194 - (pPlayer->look_ang >> 1), weaponY + 235 - weaponYOffset, FIRSTGUN + 5,
weaponShade, weaponBits, weaponPal);
@ -4624,7 +4624,22 @@ static void P_ProcessWeapon(int playerNum)
}
}
}
#define WEAPON2_CLIP 20
if (NAM && TEST_SYNC_KEY(playerBits, SK_HOLSTER))
{
if (pPlayer->curr_weapon == PISTOL_WEAPON)
{
if (pPlayer->ammo_amount[PISTOL_WEAPON] > WEAPON2_CLIP)
{
// throw away the remaining clip
pPlayer->ammo_amount[PISTOL_WEAPON] -= pPlayer->ammo_amount[PISTOL_WEAPON] % WEAPON2_CLIP;
(*weaponFrame) = 3;
playerBits &= ~BIT(SK_FIRE);
}
return;
}
}
#undef WEAPON2_CLIP
if (pPlayer->curr_weapon == SHRINKER_WEAPON || pPlayer->curr_weapon == GROW_WEAPON
|| (RR && (pPlayer->curr_weapon == TRIPBOMB_WEAPON || pPlayer->curr_weapon == BOWLINGBALL_WEAPON))
|| (RRRA && (pPlayer->curr_weapon == KNEE_WEAPON || pPlayer->curr_weapon == SLINGBLADE_WEAPON)))
@ -5461,6 +5476,9 @@ static void P_ProcessWeapon(int playerNum)
pPlayer->pos.y+(sintable[fix16_to_int(pPlayer->q16ang)&2047]>>6),
pPlayer->pos.z,HEAVYHBOMB,-16,9,9,
fix16_to_int(pPlayer->q16ang),(pipeBombFwdVel+(pPlayer->hbomb_hold_delay<<5)),pipeBombZvel,pPlayer->i,1);
if (NAM)
sprite[pipeSpriteNum].extra = mulscale(krand2(), 30, 14)+90;
if (pipeBombFwdVel == 15)
{
@ -5483,9 +5501,17 @@ static void P_ProcessWeapon(int playerNum)
else if ((*weaponFrame) > 19)
{
(*weaponFrame) = 0;
pPlayer->weapon_pos = WEAPON_POS_RAISE;
pPlayer->curr_weapon = HANDREMOTE_WEAPON;
pPlayer->last_weapon = -1;
if (NAM)
{
// don't change to remote when in NAM: grenades are timed
P_CheckWeapon(pPlayer);
}
else
{
pPlayer->weapon_pos = WEAPON_POS_RAISE;
pPlayer->curr_weapon = HANDREMOTE_WEAPON;
pPlayer->last_weapon = -1;
}
}
break;
@ -5498,9 +5524,11 @@ static void P_ProcessWeapon(int playerNum)
if ((*weaponFrame) == 10)
{
(*weaponFrame) = 0;
if (pPlayer->ammo_amount[HANDBOMB_WEAPON] > 0)
/// WHAT THE HELL DOES THIS DO....?????????????
int weapon = NAM ? TRIPBOMB_WEAPON : HANDBOMB_WEAPON;
if (pPlayer->ammo_amount[weapon] > 0)
{
P_AddWeapon(pPlayer, HANDBOMB_WEAPON);
P_AddWeapon(pPlayer, weapon);
}
else
{
@ -5525,7 +5553,7 @@ static void P_ProcessWeapon(int playerNum)
if (++(*weaponFrame) >= 5)
{
if (pPlayer->ammo_amount[PISTOL_WEAPON] <= 0 || (pPlayer->ammo_amount[PISTOL_WEAPON]%12))
if (pPlayer->ammo_amount[PISTOL_WEAPON] <= 0 || (pPlayer->ammo_amount[PISTOL_WEAPON]%(NAM ? 20 : 12)))
{
(*weaponFrame) = 0;
P_CheckWeapon(pPlayer);
@ -5544,7 +5572,7 @@ static void P_ProcessWeapon(int playerNum)
}
}
if ((*weaponFrame) == 27)
if ((*weaponFrame) == (NAM ? 50 : 27))
{
(*weaponFrame) = 0;
P_CheckWeapon(pPlayer);
@ -5643,9 +5671,16 @@ static void P_ProcessWeapon(int playerNum)
break;
case GROW_WEAPON__STATIC:
if ((*weaponFrame) > 3)
if ((!NAM && (*weaponFrame) > 3) || (NAM && ++(*weaponFrame) == 3))
{
(*weaponFrame) = 0;
if (NAM)
{
(*weaponFrame)++;
if (pPlayer->ammo_amount[GROW_WEAPON] <= 1)
(*weaponFrame) = 0;
}
else
(*weaponFrame) = 0;
if (screenpeek == playerNum)
{
pus = 1;
@ -5660,21 +5695,49 @@ static void P_ProcessWeapon(int playerNum)
lastvisinc = (int32_t)totalclock + 32;
P_CheckWeapon(pPlayer);
}
else
else if (!NAM)
{
(*weaponFrame)++;
}
if (NAM && (*weaponFrame) > 30)
{
// reload now...
(*weaponFrame) = 0;
pPlayer->visibility = 0;
flashColor = 216+(52<<8)+(20<<16);
lastvisinc = totalclock + 32;
P_CheckWeapon(pPlayer);
P_CheckWeapon(pPlayer);
}
break;
case SHRINKER_WEAPON__STATIC:
if ((*weaponFrame) > 10)
if ((!NAM && (*weaponFrame) > 10) || (NAM && (*weaponFrame) == 10))
{
(*weaponFrame) = 0;
if (NAM)
{
// fire now, but wait for reload...
(*weaponFrame)++;
}
else
(*weaponFrame) = 0;
pPlayer->ammo_amount[SHRINKER_WEAPON]--;
A_Shoot(pPlayer->i, SHRINKER);
if (!NAM)
{
pPlayer->visibility = 0;
flashColor = 176+(252<<8)+(120<<16);
lastvisinc = totalclock + 32;
P_CheckWeapon(pPlayer);
}
}
else if (NAM && (*weaponFrame) > 30)
{
(*weaponFrame) = 0;
pPlayer->visibility = 0;
flashColor = 176+(252<<8)+(120<<16);
lastvisinc = (int32_t)totalclock + 32;

View file

@ -2464,9 +2464,9 @@ void G_BonusScreen(int32_t bonusonly)
if (g_mapInfo[G_LastMapInfoIndex()].designertime)
{
// EDuke 2.0 / NAM source suggests "Green Beret's Time:"
if (!RR)
if (DUKE)
gametext(10, yy+9, "3D Realms' Time:");
else
else if (RR)
menutext(30, yy, "Xatrix Time:");
yy+=yystep;
}
@ -2529,9 +2529,9 @@ void G_BonusScreen(int32_t bonusonly)
if (g_mapInfo[G_LastMapInfoIndex()].designertime)
{
G_PrintDesignerTime();
if (!RR)
if (DUKE)
gametext_number((320>>2)+71, yy+9, tempbuf);
else
else if (RR)
menutext(191, yy, tempbuf);
yy+=yystep;
}