diff --git a/source/rr/src/actors.cpp b/source/rr/src/actors.cpp index 0946c358a..3c56ce9b5 100644 --- a/source/rr/src/actors.cpp +++ b/source/rr/src/actors.cpp @@ -1184,7 +1184,7 @@ ACTOR_STATIC void G_MovePlayers(void) { pSprite->extra = pPlayer->max_player_health; pSprite->cstat = 257; - if (!RR) + if (!RR && !WW2GI) pPlayer->inv_amount[GET_JETPACK] = 1599; } @@ -1801,6 +1801,20 @@ ACTOR_STATIC void G_MoveStandables(void) } else if (!RR && pSprite->picnum == TRIPBOMB) { + int const tripBombMode = Gv_GetVarByLabel("TRIPBOMB_CONTROL", TRIPBOMB_TRIPWIRE, -1, -1); + if(tripBombMode & TRIPBOMB_TIMER) + { + // we're on a timer.... + if (pSprite->extra >= 0) + { + pSprite->extra--; + if (pSprite->extra == 0) + { + T3(spriteNum) = 16; + A_PlaySound(LASERTRIP_ARMING,spriteNum); + } + } + } if (T3(spriteNum) > 0) { T3(spriteNum)--; @@ -1871,6 +1885,8 @@ ACTOR_STATIC void G_MoveStandables(void) actor[spriteNum].lastv.x = hitDist; pSprite->ang = oldAng; + if (tripBombMode & TRIPBOMB_TRIPWIRE) + { // we're on a trip wire //int16_t cursectnum; @@ -1896,6 +1912,7 @@ ACTOR_STATIC void G_MoveStandables(void) //if (cursectnum < 0) // break; } + } T1(spriteNum)++; @@ -1906,7 +1923,7 @@ ACTOR_STATIC void G_MoveStandables(void) setsprite(spriteNum,(vec3_t *)pSprite); T4(spriteNum) = T3(spriteNum) = 0; - if (hitSprite >= 0) + if (hitSprite >= 0 && (tripBombMode & TRIPBOMB_TRIPWIRE)) { T3(spriteNum) = 13; A_PlaySound(LASERTRIP_ARMING,spriteNum); @@ -1934,7 +1951,7 @@ ACTOR_STATIC void G_MoveStandables(void) setsprite(spriteNum, (vec3_t *) pSprite); // if( Actor[i].lastvx != x && lTripBombControl & TRIPBOMB_TRIPWIRE) - if (actor[spriteNum].lastv.x != hitDist) + if (actor[spriteNum].lastv.x != hitDist && (tripBombMode & TRIPBOMB_TRIPWIRE)) { T3(spriteNum) = 13; A_PlaySound(LASERTRIP_ARMING, spriteNum); diff --git a/source/rr/src/cheats.cpp b/source/rr/src/cheats.cpp index 8b0580be1..ecfd7e020 100644 --- a/source/rr/src/cheats.cpp +++ b/source/rr/src/cheats.cpp @@ -185,6 +185,43 @@ void G_SetupCheats(void) Bstrcpy(CheatStrings[39], "van"); } } + if (WW2GI) + { +#if 0 + // WWII GI's original cheat prefix temporarily disabled because W conflicts with WSAD movement + CheatKeys[0] = CheatKeys[1] = sc_W; +#else + CheatKeys[0] = sc_G; + CheatKeys[1] = sc_I; +#endif + + Bstrcpy(CheatStrings[0], "2god"); + Bstrcpy(CheatStrings[1], "2blood"); + Bstrcpy(CheatStrings[2], "2level###"); + Bstrcpy(CheatStrings[3], "2coords"); + Bstrcpy(CheatStrings[4], "2view"); + Bstrcpy(CheatStrings[5], ""); + Bstrcpy(CheatStrings[7], ""); + Bstrcpy(CheatStrings[8], ""); + Bstrcpy(CheatStrings[9], "2rate"); + Bstrcpy(CheatStrings[10], "2skill"); + Bstrcpy(CheatStrings[11], ""); + Bstrcpy(CheatStrings[12], ""); + Bstrcpy(CheatStrings[13], ""); + Bstrcpy(CheatStrings[16], "2matt"); + Bstrcpy(CheatStrings[17], "2showmap"); + Bstrcpy(CheatStrings[18], "2ryan"); + Bstrcpy(CheatStrings[19], ""); + Bstrcpy(CheatStrings[20], "2clip"); + Bstrcpy(CheatStrings[21], "2weapons"); + Bstrcpy(CheatStrings[22], "2inventory"); + Bstrcpy(CheatStrings[23], ""); + Bstrcpy(CheatStrings[24], "2debug"); + Bstrcpy(CheatStrings[26], "2cgs"); + + Bstrcpy(g_gametypeNames[0], "GI Match (Spawn)"); + Bstrcpy(g_gametypeNames[2], "GI Match (No Spawn)"); + } else if (NAM) { CheatKeys[0] = sc_N; diff --git a/source/rr/src/gamevars.cpp b/source/rr/src/gamevars.cpp new file mode 100644 index 000000000..b11f230aa --- /dev/null +++ b/source/rr/src/gamevars.cpp @@ -0,0 +1,852 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 2016 EDuke32 developers and contributors + +This file is part of EDuke32. + +EDuke32 is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License version 2 +as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +//------------------------------------------------------------------------- + +#include "duke3d.h" +#include "menus.h" +#include "savegame.h" + +#include "vfs.h" + +#define gamevars_c_ + +gamevar_t aGameVars[MAXGAMEVARS]; +int32_t g_gameVarCount = 0; + +// pointers to weapon gamevar data +intptr_t *aplWeaponClip[MAX_WEAPONS]; // number of items in magazine +intptr_t *aplWeaponFireDelay[MAX_WEAPONS]; // delay to fire +intptr_t *aplWeaponFireSound[MAX_WEAPONS]; // Sound made when firing (each time for automatic) +intptr_t *aplWeaponFlags[MAX_WEAPONS]; // Flags for weapon +intptr_t *aplWeaponFlashColor[MAX_WEAPONS]; // Muzzle flash color +intptr_t *aplWeaponHoldDelay[MAX_WEAPONS]; // delay after release fire button to fire (0 for none) +intptr_t *aplWeaponInitialSound[MAX_WEAPONS]; // Sound made when weapon starts firing. zero for no sound +intptr_t *aplWeaponReload[MAX_WEAPONS]; // delay to reload (include fire) +intptr_t *aplWeaponShoots[MAX_WEAPONS]; // what the weapon shoots +intptr_t *aplWeaponShotsPerBurst[MAX_WEAPONS]; // number of shots per 'burst' (one ammo per 'burst') +intptr_t *aplWeaponSound2Sound[MAX_WEAPONS]; // Alternate sound sound ID +intptr_t *aplWeaponSound2Time[MAX_WEAPONS]; // Alternate sound time +intptr_t *aplWeaponSpawn[MAX_WEAPONS]; // the item to spawn +intptr_t *aplWeaponSpawnTime[MAX_WEAPONS]; // the frame at which to spawn an item +intptr_t *aplWeaponTotalTime[MAX_WEAPONS]; // The total time the weapon is cycling before next fire. +intptr_t *aplWeaponWorksLike[MAX_WEAPONS]; // What original the weapon works like + + +// Frees the memory for the *values* of game variables and arrays. Resets their +// counts to zero. Call this function as many times as needed. +// +// Returns: old g_gameVarCount | (g_gameArrayCount<<16). +int Gv_Free(void) +{ + for (auto &gameVar : aGameVars) + { + if (gameVar.flags & GAMEVAR_USER_MASK) + ALIGNED_FREE_AND_NULL(gameVar.pValues); + gameVar.flags |= GAMEVAR_RESET; + } + + EDUKE32_STATIC_ASSERT(MAXGAMEVARS < 32768); + int const varCount = g_gameVarCount; + g_gameVarCount = 0; + + hash_init(&h_gamevars); + + return varCount; +} + +// Calls Gv_Free() and in addition frees the labels of all game variables and +// arrays. +// Only call this function at exit +void Gv_Clear(void) +{ + Gv_Free(); + + // Now, only do work that Gv_Free() hasn't done. + for (auto & gameVar : aGameVars) + DO_FREE_AND_NULL(gameVar.szLabel); +} + +int Gv_ReadSave(buildvfs_kfd kFile) +{ + char tbuf[12]; + + if (kread(kFile, tbuf, 12)!=12) goto corrupt; + if (Bmemcmp(tbuf, "BEG: EDuke32", 12)) { OSD_Printf("BEG ERR\n"); return 2; } + + Gv_Free(); // nuke 'em from orbit, it's the only way to be sure... + + if (kdfread_LZ4(&g_gameVarCount,sizeof(g_gameVarCount),1,kFile) != 1) goto corrupt; + for (bssize_t i=0; i= MAXGAMEVARS)) + { + g_errorCnt++; + C_ReportError(-1); + initprintf("%s:%d: error: too many gamevars!\n",g_scriptFileName,g_lineNumber); + return; + } + + if (EDUKE32_PREDICT_FALSE(Bstrlen(pszLabel) > (MAXVARLABEL-1))) + { + g_errorCnt++; + C_ReportError(-1); + initprintf("%s:%d: error: variable name `%s' exceeds limit of %d characters.\n",g_scriptFileName,g_lineNumber,pszLabel, MAXVARLABEL); + return; + } + + int gV = hash_find(&h_gamevars,pszLabel); + + if (gV >= 0 && !(aGameVars[gV].flags & GAMEVAR_RESET)) + { + // found it... + if (EDUKE32_PREDICT_FALSE(aGameVars[gV].flags & (GAMEVAR_PTR_MASK))) + { + C_ReportError(-1); + initprintf("%s:%d: warning: cannot redefine internal gamevar `%s'.\n",g_scriptFileName,g_lineNumber,label+(g_labelCnt<<6)); + return; + } + else if (EDUKE32_PREDICT_FALSE(!(aGameVars[gV].flags & GAMEVAR_SYSTEM))) + { + // it's a duplicate in error + g_warningCnt++; + C_ReportError(WARNING_DUPLICATEDEFINITION); + return; + } + } + + if (gV == -1) + gV = g_gameVarCount; + + // If it's a user gamevar... + if ((aGameVars[gV].flags & GAMEVAR_SYSTEM) == 0) + { + // Allocate and set its label + if (aGameVars[gV].szLabel == NULL) + aGameVars[gV].szLabel = (char *)Xcalloc(MAXVARLABEL,sizeof(uint8_t)); + + if (aGameVars[gV].szLabel != pszLabel) + Bstrcpy(aGameVars[gV].szLabel,pszLabel); + + // and the flags + aGameVars[gV].flags=dwFlags; + + // only free if per-{actor,player} + if (aGameVars[gV].flags & GAMEVAR_USER_MASK) + ALIGNED_FREE_AND_NULL(aGameVars[gV].pValues); + } + + // if existing is system, they only get to change default value.... + aGameVars[gV].defaultValue = lValue; + aGameVars[gV].flags &= ~GAMEVAR_RESET; + + if (gV == g_gameVarCount) + { + // we're adding a new one. + hash_add(&h_gamevars, aGameVars[gV].szLabel, g_gameVarCount++, 0); + } + + // Set initial values. (Or, override values for system gamevars.) + if (aGameVars[gV].flags & GAMEVAR_PERPLAYER) + { + if (!aGameVars[gV].pValues) + { + aGameVars[gV].pValues = (intptr_t *) Xaligned_alloc(PLAYER_VAR_ALIGNMENT, MAXPLAYERS * sizeof(intptr_t)); + Bmemset(aGameVars[gV].pValues, 0, MAXPLAYERS * sizeof(intptr_t)); + } + for (bssize_t j=MAXPLAYERS-1; j>=0; --j) + aGameVars[gV].pValues[j]=lValue; + } + else if (aGameVars[gV].flags & GAMEVAR_PERACTOR) + { + if (!aGameVars[gV].pValues) + { + aGameVars[gV].pValues = (intptr_t *) Xaligned_alloc(ACTOR_VAR_ALIGNMENT, MAXSPRITES * sizeof(intptr_t)); + Bmemset(aGameVars[gV].pValues, 0, MAXSPRITES * sizeof(intptr_t)); + } + for (bssize_t j=MAXSPRITES-1; j>=0; --j) + aGameVars[gV].pValues[j]=lValue; + } + else aGameVars[gV].global = lValue; +} + +static int Gv_GetVarIndex(const char *szGameLabel) +{ + int const gameVar = hash_find(&h_gamevars,szGameLabel); + + if (EDUKE32_PREDICT_FALSE((unsigned)gameVar >= MAXGAMEVARS)) + { + OSD_Printf(OSD_ERROR "Gv_GetVarIndex(): INTERNAL ERROR: couldn't find gamevar %s!\n", szGameLabel); + return 0; + } + + return gameVar; +} + +static FORCE_INLINE int __fastcall getvar__(int const gameVar, int const spriteNum, int const playerNum) +{ + auto const &var = aGameVars[gameVar & (MAXGAMEVARS-1)]; + + int returnValue = 0; + int const varFlags = var.flags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK); + + if (!varFlags) returnValue = var.global; + else if (varFlags == GAMEVAR_PERACTOR) + returnValue = var.pValues[spriteNum & (MAXSPRITES-1)]; + else if (varFlags == GAMEVAR_PERPLAYER) + returnValue = var.pValues[playerNum & (MAXPLAYERS-1)]; + else switch (varFlags & GAMEVAR_PTR_MASK) + { + case GAMEVAR_RAWQ16PTR: + case GAMEVAR_INT32PTR: returnValue = *(int32_t *)var.global; break; + case GAMEVAR_INT16PTR: returnValue = *(int16_t *)var.global; break; + case GAMEVAR_Q16PTR: returnValue = fix16_to_int(*(fix16_t *)var.global); break; + } + + return NEGATE_ON_CONDITION(returnValue, gameVar & GV_FLAG_NEGATIVE); +} + +int __fastcall Gv_GetVar(int const gameVar, int const spriteNum, int const playerNum) { return getvar__(gameVar, spriteNum, playerNum); } +int __fastcall Gv_GetVar(int const gameVar) { return getvar__(gameVar, vm.spriteNum, vm.playerNum); } + +void __fastcall Gv_GetManyVars(int const numVars, int32_t * const outBuf) +{ + for (native_t j = 0; j < numVars; ++j) + outBuf[j] = getvar__(*insptr++, vm.spriteNum, vm.playerNum); +} + +static FORCE_INLINE void __fastcall setvar__(int const gameVar, int const newValue, int const spriteNum, int const playerNum) +{ + gamevar_t &var = aGameVars[gameVar]; + int const varFlags = var.flags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK); + + if (!varFlags) var.global=newValue; + else if (varFlags == GAMEVAR_PERACTOR) + var.pValues[spriteNum & (MAXSPRITES-1)] = newValue; + else if (varFlags == GAMEVAR_PERPLAYER) + var.pValues[playerNum & (MAXPLAYERS-1)] = newValue; + else switch (varFlags & GAMEVAR_PTR_MASK) + { + case GAMEVAR_RAWQ16PTR: + case GAMEVAR_INT32PTR: *((int32_t *)var.global) = (int32_t)newValue; break; + case GAMEVAR_INT16PTR: *((int16_t *)var.global) = (int16_t)newValue; break; + case GAMEVAR_Q16PTR: *(fix16_t *)var.global = fix16_from_int((int16_t)newValue); break; + } + return; +} + +void __fastcall Gv_SetVar(int const gameVar, int const newValue) { setvar__(gameVar, newValue, vm.spriteNum, vm.playerNum); } +void __fastcall Gv_SetVar(int const gameVar, int const newValue, int const spriteNum, int const playerNum) +{ + setvar__(gameVar, newValue, spriteNum, playerNum); +} + +int Gv_GetVarByLabel(const char *szGameLabel, int const defaultValue, int const spriteNum, int const playerNum) +{ + int const gameVar = hash_find(&h_gamevars, szGameLabel); + return EDUKE32_PREDICT_TRUE(gameVar >= 0) ? Gv_GetVar(gameVar, spriteNum, playerNum) : defaultValue; +} + +static intptr_t *Gv_GetVarDataPtr(const char *szGameLabel) +{ + int const gameVar = hash_find(&h_gamevars, szGameLabel); + + if (EDUKE32_PREDICT_FALSE((unsigned)gameVar >= MAXGAMEVARS)) + return NULL; + + gamevar_t &var = aGameVars[gameVar]; + + if (var.flags & (GAMEVAR_USER_MASK | GAMEVAR_PTR_MASK)) + return var.pValues; + + return &(var.global); +} + +void Gv_ResetSystemDefaults(void) +{ + // call many times... + char aszBuf[64]; + + //AddLog("ResetWeaponDefaults"); + + for (int weaponNum = 0; weaponNum < MAX_WEAPONS; ++weaponNum) + { + for (int playerNum = 0; playerNum < MAXPLAYERS; ++playerNum) + { + Bsprintf(aszBuf, "WEAPON%d_CLIP", weaponNum); + aplWeaponClip[weaponNum][playerNum] = Gv_GetVarByLabel(aszBuf, 0, -1, playerNum); + Bsprintf(aszBuf, "WEAPON%d_RELOAD", weaponNum); + aplWeaponReload[weaponNum][playerNum] = Gv_GetVarByLabel(aszBuf, 0, -1, playerNum); + Bsprintf(aszBuf, "WEAPON%d_FIREDELAY", weaponNum); + aplWeaponFireDelay[weaponNum][playerNum] = Gv_GetVarByLabel(aszBuf, 0, -1, playerNum); + Bsprintf(aszBuf, "WEAPON%d_TOTALTIME", weaponNum); + aplWeaponTotalTime[weaponNum][playerNum] = Gv_GetVarByLabel(aszBuf, 0, -1, playerNum); + Bsprintf(aszBuf, "WEAPON%d_HOLDDELAY", weaponNum); + aplWeaponHoldDelay[weaponNum][playerNum] = Gv_GetVarByLabel(aszBuf, 0, -1, playerNum); + Bsprintf(aszBuf, "WEAPON%d_FLAGS", weaponNum); + aplWeaponFlags[weaponNum][playerNum] = Gv_GetVarByLabel(aszBuf, 0, -1, playerNum); + Bsprintf(aszBuf, "WEAPON%d_SHOOTS", weaponNum); + aplWeaponShoots[weaponNum][playerNum] = Gv_GetVarByLabel(aszBuf, 0, -1, playerNum); + if ((unsigned)aplWeaponShoots[weaponNum][playerNum] >= MAXTILES) + aplWeaponShoots[weaponNum][playerNum] = 0; + Bsprintf(aszBuf, "WEAPON%d_SPAWNTIME", weaponNum); + aplWeaponSpawnTime[weaponNum][playerNum] = Gv_GetVarByLabel(aszBuf, 0, -1, playerNum); + Bsprintf(aszBuf, "WEAPON%d_SPAWN", weaponNum); + aplWeaponSpawn[weaponNum][playerNum] = Gv_GetVarByLabel(aszBuf, 0, -1, playerNum); + Bsprintf(aszBuf, "WEAPON%d_SHOTSPERBURST", weaponNum); + aplWeaponShotsPerBurst[weaponNum][playerNum] = Gv_GetVarByLabel(aszBuf, 0, -1, playerNum); + Bsprintf(aszBuf, "WEAPON%d_WORKSLIKE", weaponNum); + aplWeaponWorksLike[weaponNum][playerNum] = Gv_GetVarByLabel(aszBuf, 0, -1, playerNum); + Bsprintf(aszBuf, "WEAPON%d_INITIALSOUND", weaponNum); + aplWeaponInitialSound[weaponNum][playerNum] = Gv_GetVarByLabel(aszBuf, 0, -1, playerNum); + Bsprintf(aszBuf, "WEAPON%d_FIRESOUND", weaponNum); + aplWeaponFireSound[weaponNum][playerNum] = Gv_GetVarByLabel(aszBuf, 0, -1, playerNum); + Bsprintf(aszBuf, "WEAPON%d_SOUND2TIME", weaponNum); + aplWeaponSound2Time[weaponNum][playerNum] = Gv_GetVarByLabel(aszBuf, 0, -1, playerNum); + Bsprintf(aszBuf, "WEAPON%d_SOUND2SOUND", weaponNum); + aplWeaponSound2Sound[weaponNum][playerNum] = Gv_GetVarByLabel(aszBuf, 0, -1, playerNum); + Bsprintf(aszBuf, "WEAPON%d_FLASHCOLOR", weaponNum); + aplWeaponFlashColor[weaponNum][playerNum] = Gv_GetVarByLabel(aszBuf, 0, -1, playerNum); + } + } + + g_aimAngleVarID = Gv_GetVarIndex("AUTOAIMANGLE"); + g_angRangeVarID = Gv_GetVarIndex("ANGRANGE"); + g_returnVarID = Gv_GetVarIndex("RETURN"); + g_weaponVarID = Gv_GetVarIndex("WEAPON"); + g_worksLikeVarID = Gv_GetVarIndex("WORKSLIKE"); + g_zRangeVarID = Gv_GetVarIndex("ZRANGE"); + + //AddLog("EOF:ResetWeaponDefaults"); +} + +// Will set members that were overridden at CON translation time to 1. +// For example, if +// gamevar WEAPON1_SHOOTS 2200 GAMEVAR_PERPLAYER +// was specified at file scope, g_weaponOverridden[1].Shoots will be 1. +weapondata_t g_weaponOverridden[MAX_WEAPONS]; + +static weapondata_t weapondefaults[MAX_WEAPONS] = { + /* + WorksLike, Clip, Reload, FireDelay, TotalTime, HoldDelay, + Flags, + Shoots, SpawnTime, Spawn, ShotsPerBurst, InitialSound, FireSound, Sound2Time, Sound2Sound, + FlashColor + */ + { + KNEE_WEAPON__STATIC, 0, 30, 7, 14, 14, + WEAPON_RANDOMRESTART | WEAPON_AUTOMATIC, + KNEE__STATIC, 0, 0, 0, 0, 0, 0, + 0 + }, + + { + PISTOL_WEAPON, 20, 50, 2, 5, 0, + WEAPON_AUTOMATIC | WEAPON_HOLSTER_CLEARS_CLIP, + SHOTSPARK1__STATIC, 2, SHELL__STATIC, 0, 0, PISTOL_FIRE__STATIC, 0, 0, + 255+(95<<8) + }, + + { + SHOTGUN_WEAPON__STATIC, 0, 13, 4, 31, 0, + WEAPON_CHECKATRELOAD, + SHOTGUN__STATIC, 24, SHOTGUNSHELL__STATIC, 7, 0, SHOTGUN_FIRE__STATIC, 15, SHOTGUN_COCK__STATIC, + 255+(95<<8) + }, + + { + CHAINGUN_WEAPON__STATIC, 0, 30, 1, 12, 10, + WEAPON_AUTOMATIC | WEAPON_FIREEVERYTHIRD | WEAPON_AMMOPERSHOT, + CHAINGUN__STATIC, 0, SHELL__STATIC, 0, 0, CHAINGUN_FIRE__STATIC, 0, 0, + 255+(95<<8) + }, + + { + RPG_WEAPON__STATIC, 0, 30, 4, 20, 0, + 0, + RPG__STATIC, 0, 0, 0, 0, 0, 0, 0, + 255+(95<<8) + }, + + { + HANDBOMB_WEAPON__STATIC, 0, 30, 6, 19, 12, + WEAPON_THROWIT, + HEAVYHBOMB__STATIC, 0, 0, 0, 0, 0, 0, + 0 + }, + + { + SHRINKER_WEAPON__STATIC, 0, 0, 10, 30, 0, + WEAPON_GLOWS, + SHRINKER__STATIC, 0, 0, 0, SHRINKER_FIRE__STATIC, 0, 0, 0, + 176+(252<<8)+(120<<16) + }, + + { + DEVISTATOR_WEAPON__STATIC, 0, 30, 2, 5, 5, + WEAPON_FIREEVERYOTHER, + RPG__STATIC, 0, 0, 2, CAT_FIRE__STATIC, 0, 0, 0, + 255+(95<<8) + }, + + { + TRIPBOMB_WEAPON__STATIC, 0, 30, 3, 16, 0, + WEAPON_STANDSTILL, + HANDHOLDINGLASER__STATIC, 0, 0, 0, 0, 0, 0, + 0 + }, + + { + FREEZE_WEAPON__STATIC, 0, 0, 3, 5, 0, + WEAPON_FIREEVERYOTHER, + FREEZEBLAST__STATIC, 0, 0, 0, CAT_FIRE__STATIC, CAT_FIRE__STATIC, 0, 0, + 72+(88<<8)+(140<<16) + }, + + { + HANDREMOTE_WEAPON__STATIC, 0, 30, 2, 10, 0, + WEAPON_BOMB_TRIGGER | WEAPON_NOVISIBLE, + 0, 0, 0, 0, 0, 0, 0, + 0 + }, + + { + GROW_WEAPON__STATIC, 0, 0, 3, 30, 0, + WEAPON_GLOWS, + GROWSPARK__STATIC, 0, 0, 0, EXPANDERSHOOT__STATIC, EXPANDERSHOOT__STATIC, 0, 0, + 216+(52<<8)+(20<<16) + }, +}; + +// KEEPINSYNC with what is contained above +// XXX: ugly +static int32_t G_StaticToDynamicTile(int32_t const tile) +{ + switch (tile) + { +#ifndef EDUKE32_STANDALONE + case CHAINGUN__STATIC: return CHAINGUN; + case FREEZEBLAST__STATIC: return FREEZEBLAST; + case GROWSPARK__STATIC: return GROWSPARK; + case HANDHOLDINGLASER__STATIC: return HANDHOLDINGLASER; + case HEAVYHBOMB__STATIC: return HEAVYHBOMB; + case KNEE__STATIC: return KNEE; + case RPG__STATIC: return RPG; + case SHELL__STATIC: return SHELL; + case SHOTGUNSHELL__STATIC: return SHOTGUNSHELL; + case SHOTGUN__STATIC: return SHOTGUN; + case SHOTSPARK1__STATIC: return SHOTSPARK1; + case SHRINKER__STATIC: return SHRINKER; +#endif + default: return tile; + } +} + +static int32_t G_StaticToDynamicSound(int32_t const sound) +{ + switch (sound) + { +#ifndef EDUKE32_STANDALONE + case CAT_FIRE__STATIC: return CAT_FIRE; + case CHAINGUN_FIRE__STATIC: return CHAINGUN_FIRE; + case EJECT_CLIP__STATIC: return EJECT_CLIP; + case EXPANDERSHOOT__STATIC: return EXPANDERSHOOT; + case INSERT_CLIP__STATIC: return INSERT_CLIP; + case PISTOL_FIRE__STATIC: return PISTOL_FIRE; + case SELECT_WEAPON__STATIC: return SELECT_WEAPON; + case SHOTGUN_FIRE__STATIC: return SHOTGUN_FIRE; + case SHOTGUN_COCK__STATIC: return SHOTGUN_COCK; + case SHRINKER_FIRE__STATIC: return SHRINKER_FIRE; +#endif + default: return sound; + } +} + +// Initialize WEAPONx_* gamevars. Since for Lunatic, they reside on the C side, +// they're set directly. In C-CON, a new CON variable is defined together with +// its initial value. +#ifdef LUNATIC +# define ADDWEAPONVAR(Weapidx, Membname) do { \ + int32_t j; \ + for (j=0; j=0; i--) + { + Bsprintf(aszBuf, "WEAPON%d_CLIP", i); + aplWeaponClip[i] = Gv_GetVarDataPtr(aszBuf); + + if (!aplWeaponClip[i]) + { + initprintf("ERROR: NULL weapon! WTF?! %s\n", aszBuf); + // Bexit(EXIT_SUCCESS); + G_Shutdown(); + } + + Bsprintf(aszBuf, "WEAPON%d_RELOAD", i); + aplWeaponReload[i] = Gv_GetVarDataPtr(aszBuf); + Bsprintf(aszBuf, "WEAPON%d_FIREDELAY", i); + aplWeaponFireDelay[i] = Gv_GetVarDataPtr(aszBuf); + Bsprintf(aszBuf, "WEAPON%d_TOTALTIME", i); + aplWeaponTotalTime[i] = Gv_GetVarDataPtr(aszBuf); + Bsprintf(aszBuf, "WEAPON%d_HOLDDELAY", i); + aplWeaponHoldDelay[i] = Gv_GetVarDataPtr(aszBuf); + Bsprintf(aszBuf, "WEAPON%d_FLAGS", i); + aplWeaponFlags[i] = Gv_GetVarDataPtr(aszBuf); + Bsprintf(aszBuf, "WEAPON%d_SHOOTS", i); + aplWeaponShoots[i] = Gv_GetVarDataPtr(aszBuf); + Bsprintf(aszBuf, "WEAPON%d_SPAWNTIME", i); + aplWeaponSpawnTime[i] = Gv_GetVarDataPtr(aszBuf); + Bsprintf(aszBuf, "WEAPON%d_SPAWN", i); + aplWeaponSpawn[i] = Gv_GetVarDataPtr(aszBuf); + Bsprintf(aszBuf, "WEAPON%d_SHOTSPERBURST", i); + aplWeaponShotsPerBurst[i] = Gv_GetVarDataPtr(aszBuf); + Bsprintf(aszBuf, "WEAPON%d_WORKSLIKE", i); + aplWeaponWorksLike[i] = Gv_GetVarDataPtr(aszBuf); + Bsprintf(aszBuf, "WEAPON%d_INITIALSOUND", i); + aplWeaponInitialSound[i] = Gv_GetVarDataPtr(aszBuf); + Bsprintf(aszBuf, "WEAPON%d_FIRESOUND", i); + aplWeaponFireSound[i] = Gv_GetVarDataPtr(aszBuf); + Bsprintf(aszBuf, "WEAPON%d_SOUND2TIME", i); + aplWeaponSound2Time[i] = Gv_GetVarDataPtr(aszBuf); + Bsprintf(aszBuf, "WEAPON%d_SOUND2SOUND", i); + aplWeaponSound2Sound[i] = Gv_GetVarDataPtr(aszBuf); + Bsprintf(aszBuf, "WEAPON%d_FLASHCOLOR", i); + aplWeaponFlashColor[i] = Gv_GetVarDataPtr(aszBuf); + } +} + +void Gv_RefreshPointers(void) +{ + aGameVars[Gv_GetVarIndex("COOP")].global = (intptr_t)&ud.coop; + aGameVars[Gv_GetVarIndex("FFIRE")].global = (intptr_t)&ud.ffire; + aGameVars[Gv_GetVarIndex("LEVEL")].global = (intptr_t)&ud.level_number; + aGameVars[Gv_GetVarIndex("MARKER")].global = (intptr_t)&ud.marker; + aGameVars[Gv_GetVarIndex("MONSTERS_OFF")].global = (intptr_t)&ud.monsters_off; + aGameVars[Gv_GetVarIndex("MULTIMODE")].global = (intptr_t)&ud.multimode; + aGameVars[Gv_GetVarIndex("RESPAWN_INVENTORY")].global = (intptr_t)&ud.respawn_inventory; + aGameVars[Gv_GetVarIndex("RESPAWN_ITEMS")].global = (intptr_t)&ud.respawn_items; + aGameVars[Gv_GetVarIndex("RESPAWN_MONSTERS")].global = (intptr_t)&ud.respawn_monsters; + aGameVars[Gv_GetVarIndex("VOLUME")].global = (intptr_t)&ud.volume_number; +} +#endif diff --git a/source/rr/src/player.cpp b/source/rr/src/player.cpp index bbe1b211c..7ea3b35ac 100644 --- a/source/rr/src/player.cpp +++ b/source/rr/src/player.cpp @@ -211,8 +211,14 @@ static int A_FindTargetSprite(const spritetype *pSprite, int projAng, int projec int const spriteAng = pSprite->ang; - int const isShrinker = (!RR && pSprite->picnum == APLAYER && g_player[playerNum].ps->curr_weapon == SHRINKER_WEAPON); - int const isFreezer = (!RR && pSprite->picnum == APLAYER && g_player[playerNum].ps->curr_weapon == FREEZE_WEAPON); + int isShrinker = (!RR && pSprite->picnum == APLAYER && g_player[playerNum].ps->curr_weapon == SHRINKER_WEAPON); + int isFreezer = (!RR && pSprite->picnum == APLAYER && g_player[playerNum].ps->curr_weapon == FREEZE_WEAPON); + + if (WW2GI) + { + isShrinker = (pSprite->picnum == APLAYER && PWEAPON(playerNum, g_player[playerNum].ps->curr_weapon, WorksLike) == SHRINKER_WEAPON); + isFreezer = (pSprite->picnum == APLAYER && PWEAPON(playerNum, g_player[playerNum].ps->curr_weapon, WorksLike) == FREEZE_WEAPON); + } vec2_t const d1 = { sintable[(spriteAng + 512 - projAng) & 2047], sintable[(spriteAng - projAng) & 2047] }; vec2_t const d2 = { sintable[(spriteAng + 512 + projAng) & 2047], sintable[(spriteAng + projAng) & 2047] }; @@ -1212,7 +1218,7 @@ growspark_rr: pReturn->extra >>= 2; } } - else if (g_player[playerNum].ps->curr_weapon == DEVISTATOR_WEAPON) + else if ((WW2GI ? PWEAPON(playerNum, g_player[playerNum].ps->curr_weapon, WorksLike) : g_player[playerNum].ps->curr_weapon) == DEVISTATOR_WEAPON) { pReturn->extra >>= 2; pReturn->ang += 16 - (krand2() & 31); @@ -1272,8 +1278,17 @@ growspark_rr: if (placeMine == 1) { + int const tripBombMode = Gv_GetVarByLabel("TRIPBOMB_CONTROL", TRIPBOMB_TRIPWIRE, -1, -1); int const spawnedSprite = A_InsertSprite(hitData.sect, hitData.pos.x, hitData.pos.y, hitData.pos.z, TRIPBOMB, -16, 4, 5, shootAng, 0, 0, spriteNum, 6); + if (tripBombMode & TRIPBOMB_TIMER) + { + int32_t lLifetime = Gv_GetVarByLabel("STICKYBOMB_LIFETIME", NAM_GRENADE_LIFETIME, -1, playerNum); + int32_t lLifetimeVar + = Gv_GetVarByLabel("STICKYBOMB_LIFETIME_VAR", NAM_GRENADE_LIFETIME_VAR, -1, playerNum); + // set timer. blows up when at zero.... + sprite[spawnedSprite].extra = lLifetime + mulscale14(krand2(), lLifetimeVar) - lLifetimeVar; + } sprite[spawnedSprite].hitag = spawnedSprite; A_PlaySound(LASERTRIP_ONWALL, spawnedSprite); sprite[spawnedSprite].xvel = -20; @@ -1285,7 +1300,7 @@ growspark_rr: actor[spawnedSprite].t_data[5] = sprite[spawnedSprite].ang = wallAng; - if (playerNum >= 0) + if (!WW2GI && playerNum >= 0) pPlayer->ammo_amount[TRIPBOMB_WEAPON]--; return spawnedSprite; @@ -1585,6 +1600,8 @@ static int P_DisplayKnee(int kneeShade) static int P_DisplayKnuckles(int knuckleShade) { + if (WW2GI) + return 0; const DukePlayer_t *const pPlayer = g_player[screenpeek].ps; if (pPlayer->knuckle_incs == 0) @@ -1606,6 +1623,99 @@ static int P_DisplayKnuckles(int knuckleShade) return 1; } +// Set C-CON's WEAPON and WORKSLIKE gamevars. +void P_SetWeaponGamevars(int playerNum, const DukePlayer_t * const pPlayer) +{ + if (!WW2GI) + return; + Gv_SetVar(g_weaponVarID, pPlayer->curr_weapon, pPlayer->i, playerNum); + Gv_SetVar(g_worksLikeVarID, + ((unsigned)pPlayer->curr_weapon < MAX_WEAPONS) ? PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) : -1, + pPlayer->i, playerNum); +} + +static void P_FireWeapon(int playerNum) +{ + auto const pPlayer = g_player[playerNum].ps; + + if (PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) != KNEE_WEAPON) + pPlayer->ammo_amount[pPlayer->curr_weapon]--; + + if (PWEAPON(playerNum, pPlayer->curr_weapon, FireSound) > 0) + A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, FireSound), pPlayer->i); + + P_SetWeaponGamevars(playerNum, pPlayer); + // OSD_Printf("doing %d %d %d\n",PWEAPON(snum, p->curr_weapon, Shoots),p->curr_weapon,snum); + A_Shoot(pPlayer->i, PWEAPON(playerNum, pPlayer->curr_weapon, Shoots)); + + for (bssize_t burstFire = PWEAPON(playerNum, pPlayer->curr_weapon, ShotsPerBurst) - 1; burstFire > 0; --burstFire) + { + A_Shoot(pPlayer->i, PWEAPON(playerNum, pPlayer->curr_weapon, Shoots)); + + if (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_AMMOPERSHOT) + { + pPlayer->ammo_amount[pPlayer->curr_weapon]--; + } + } + + if (!(PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_NOVISIBLE)) + { +#ifdef POLYMER + spritetype *s = &sprite[pPlayer->i]; + int32_t x = ((sintable[(s->ang + 512) & 2047]) >> 7), y = ((sintable[(s->ang) & 2047]) >> 7); + + s->x += x; + s->y += y; + G_AddGameLight(0, pPlayer->i, PHEIGHT, 8192, PWEAPON(playerNum, pPlayer->curr_weapon, FlashColor), + PR_LIGHT_PRIO_MAX_GAME); + actor[pPlayer->i].lightcount = 2; + s->x -= x; + s->y -= y; +#endif // POLYMER + pPlayer->visibility = 0; + } + + if (/*!(PWEAPON(playerNum, p->curr_weapon, Flags) & WEAPON_CHECKATRELOAD) && */ + PWEAPON(playerNum, pPlayer->curr_weapon, Reload) > PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime) && pPlayer->ammo_amount[pPlayer->curr_weapon] > 0 + && (PWEAPON(playerNum, pPlayer->curr_weapon, Clip)) && (((pPlayer->ammo_amount[pPlayer->curr_weapon]%(PWEAPON(playerNum, pPlayer->curr_weapon, Clip)))==0))) + { + pPlayer->kickback_pic = PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime); + } + + if (PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) != KNEE_WEAPON) + P_CheckWeapon(pPlayer); +} + +static void P_DoWeaponSpawn(int playerNum) +{ + auto const pPlayer = g_player[playerNum].ps; + + // NOTE: For the 'Spawn' member, 0 means 'none', too (originally so, + // i.e. legacy). The check for <0 was added to the check because mod + // authors (rightly) assumed that -1 is the no-op value. + if (PWEAPON(playerNum, pPlayer->curr_weapon, Spawn) <= 0) // <=0 : AMC TC beta/RC2 has WEAPONx_SPAWN -1 + return; + + int newSprite = A_Spawn(pPlayer->i, PWEAPON(playerNum, pPlayer->curr_weapon, Spawn)); + + if ((PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_SPAWNTYPE2)) + { + // like shotgun shells + sprite[newSprite].ang += 1024; + A_SetSprite(newSprite,CLIPMASK0); + sprite[newSprite].ang += 1024; + } + else if ((PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_SPAWNTYPE3)) + { + // like chaingun shells + sprite[newSprite].ang += 1024; + sprite[newSprite].ang &= 2047; + sprite[newSprite].xvel += 32; + sprite[newSprite].z += (3<<8); + A_SetSprite(newSprite,CLIPMASK0); + } +} + void P_DisplayScuba(void) { if (g_player[screenpeek].ps->scuba_on) @@ -1762,7 +1872,10 @@ void P_DisplayWeapon(void) weaponX -= 58 + pPlayer->weapon_ang; weaponYOffset -= (pPlayer->hard_landing << 3); - currentWeapon = (pPlayer->last_weapon >= 0) ? pPlayer->last_weapon : pPlayer->curr_weapon; + if (WW2GI) + currentWeapon = PWEAPON(screenpeek, (pPlayer->last_weapon >= 0) ? pPlayer->last_weapon : pPlayer->curr_weapon, WorksLike); + else + currentWeapon = (pPlayer->last_weapon >= 0) ? pPlayer->last_weapon : pPlayer->curr_weapon; hudweap.gunposy = weaponYOffset; hudweap.lookhoriz = weaponY; hudweap.cur = currentWeapon; @@ -2415,9 +2528,19 @@ void P_DisplayWeapon(void) if (*weaponFrame > 0) { - if (*weaponFrame < 8) + int totalTime; + if (*weaponFrame < (WW2GI ? (totalTime = PWEAPON(screenpeek, pPlayer->curr_weapon, TotalTime)) : 8)) G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 164, (weaponY << 1) + 176 - weaponYOffset, RPGGUN + ((*weaponFrame) >> 1), weaponShade, weaponBits, weaponPal); + else if (WW2GI) + { + totalTime = PWEAPON(screenpeek, pPlayer->curr_weapon, TotalTime); + int const reloadTime = PWEAPON(screenpeek, pPlayer->curr_weapon, Reload); + + weaponYOffset -= (*weaponFrame < ((reloadTime - totalTime) / 2 + totalTime)) + ? 10 * ((*weaponFrame) - totalTime) // down + : 10 * (reloadTime - (*weaponFrame)); // up + } } G_DrawWeaponTileWithID(currentWeapon, weaponX + 164, (weaponY << 1) + 176 - weaponYOffset, RPGGUN, weaponShade, @@ -2427,6 +2550,41 @@ void P_DisplayWeapon(void) case SHOTGUN_WEAPON__STATIC: weaponX -= 8; + if (WW2GI) + { + int const totalTime = PWEAPON(screenpeek, pPlayer->curr_weapon, TotalTime); + int const reloadTime = PWEAPON(screenpeek, pPlayer->curr_weapon, Reload); + + if (*weaponFrame > 0) + weaponYOffset -= sintable[(*weaponFrame)<<7]>>12; + + if (*weaponFrame > 0 && doAnim) + weaponX += 1-(rand()&3); + + if (*weaponFrame == 0) + { + G_DrawWeaponTileWithID(currentWeapon, weaponX + 146 - halfLookAng, weaponY + 202 - weaponYOffset, + SHOTGUN, weaponShade, weaponBits, weaponPal); + } + else if (*weaponFrame <= totalTime) + { + G_DrawWeaponTileWithID(currentWeapon, weaponX + 146 - halfLookAng, weaponY + 202 - weaponYOffset, + SHOTGUN + 1, weaponShade, weaponBits, weaponPal); + } + // else we are in 'reload time' + else + { + weaponYOffset -= (*weaponFrame < ((reloadTime - totalTime) / 2 + totalTime)) + ? 10 * ((*weaponFrame) - totalTime) // D + : 10 * (reloadTime - (*weaponFrame)); // U + + G_DrawWeaponTileWithID(currentWeapon, weaponX + 146 - halfLookAng, weaponY + 202 - weaponYOffset, + SHOTGUN, weaponShade, weaponBits, weaponPal); + } + + break; + } + switch (*weaponFrame) { case 1: @@ -2505,6 +2663,83 @@ void P_DisplayWeapon(void) weaponX += 1-(rand()&3); } + if (WW2GI) + { + int const totalTime = PWEAPON(screenpeek, pPlayer->curr_weapon, TotalTime); + int const reloadTime = PWEAPON(screenpeek, pPlayer->curr_weapon, Reload); + + if (*weaponFrame == 0) + { + G_DrawWeaponTileWithID(currentWeapon, weaponX + 178 - halfLookAng,weaponY+233-weaponYOffset, + CHAINGUN+1,weaponShade,weaponBits,weaponPal); + } + else if (*weaponFrame <= totalTime) + { + G_DrawWeaponTileWithID(currentWeapon, weaponX + 188 - halfLookAng,weaponY+243-weaponYOffset, + CHAINGUN+2,weaponShade,weaponBits,weaponPal); + } + // else we are in 'reload time' + // divide reload time into fifths.. + // 1) move weapon up/right, hand on clip (CHAINGUN - 17) + // 2) move weapon up/right, hand removing clip (CHAINGUN - 18) + // 3) hold weapon up/right, hand removed clip (CHAINGUN - 19) + // 4) hold weapon up/right, hand inserting clip (CHAINGUN - 18) + // 5) move weapon down/left, clip inserted (CHAINGUN - 17) + else + { + int iFifths = (reloadTime - totalTime) / 5; + if (iFifths < 1) + iFifths = 1; + + if (*weaponFrame < iFifths + totalTime) + { + // first segment + int const weaponOffset = 80 - 10 * (totalTime + iFifths - (*weaponFrame)); + weaponYOffset += weaponOffset; + weaponX += weaponOffset; + G_DrawWeaponTileWithID(currentWeapon, weaponX + 168 - halfLookAng, weaponY + 260 - weaponYOffset, CHAINGUN - 17, + weaponShade, weaponBits, weaponPal); + } + else if (*weaponFrame < (iFifths * 2 + totalTime)) + { + // second segment + weaponYOffset += 80; // D + weaponX += 80; + G_DrawWeaponTileWithID(currentWeapon, weaponX + 168 - halfLookAng, weaponY + 260 - weaponYOffset, CHAINGUN - 18, + weaponShade, weaponBits, weaponPal); + } + else if (*weaponFrame < (iFifths * 3 + totalTime)) + { + // third segment + // up + weaponYOffset += 80; + weaponX += 80; + G_DrawWeaponTileWithID(currentWeapon, weaponX + 168 - halfLookAng, weaponY + 260 - weaponYOffset, CHAINGUN - 19, + weaponShade, weaponBits, weaponPal); + } + else if (*weaponFrame < (iFifths * 4 + totalTime)) + { + // fourth segment + // down + weaponYOffset += 80; // D + weaponX += 80; + G_DrawWeaponTileWithID(currentWeapon, weaponX + 168 - halfLookAng, weaponY + 260 - weaponYOffset, CHAINGUN - 18, + weaponShade, weaponBits, weaponPal); + } + else + { + // up and left + int const weaponOffset = 10 * (reloadTime - (*weaponFrame)); + weaponYOffset += weaponOffset; // U + weaponX += weaponOffset; + G_DrawWeaponTileWithID(currentWeapon, weaponX + 168 - halfLookAng, weaponY + 260 - weaponYOffset, CHAINGUN - 17, + weaponShade, weaponBits, weaponPal); + } + } + + break; + } + switch (*weaponFrame) { case 0: @@ -2584,21 +2819,21 @@ void P_DisplayWeapon(void) weaponShade, weaponBits, weaponPal); } - else if ((*weaponFrame) < (NAM ? 38 : 23)) + else if ((*weaponFrame) < (WW2GI ? PWEAPON(screenpeek, PISTOL_WEAPON, Reload) - 12 : (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) < (NAM ? 44 : 25)) + else if ((*weaponFrame) < (WW2GI ? PWEAPON(screenpeek, PISTOL_WEAPON, Reload) - 6 : (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) < (NAM ? 50 : 27)) + else if ((*weaponFrame) < (WW2GI ? PWEAPON(screenpeek, PISTOL_WEAPON, Reload) : (NAM ? 50 : 27))) G_DrawWeaponTileWithID(currentWeapon, 194 - (pPlayer->look_ang >> 1), weaponY + 235 - weaponYOffset, FIRSTGUN + 5, weaponShade, weaponBits, weaponPal); @@ -2611,13 +2846,45 @@ void P_DisplayWeapon(void) if (*weaponFrame >= ARRAY_SIZE(pipebombFrames)) break; + if (WW2GI && *weaponFrame >= PWEAPON(screenpeek, pPlayer->curr_weapon, TotalTime)) + break; + if (*weaponFrame) { - if (*weaponFrame < 7) weaponYOffset -= 10 * (*weaponFrame); // D - else if (*weaponFrame < 12) weaponYOffset += 20 * ((*weaponFrame) - 10); // U - else if (*weaponFrame < 20) weaponYOffset -= 9 * ((*weaponFrame) - 14); // D + if (WW2GI) + { + int const fireDelay = PWEAPON(screenpeek, pPlayer->curr_weapon, FireDelay); + int const totalTime = PWEAPON(screenpeek, pPlayer->curr_weapon, TotalTime); - weaponYOffset += 10; + if (*weaponFrame <= fireDelay) + { + // it holds here + weaponYOffset -= 5 * (*weaponFrame); // D + } + else if (*weaponFrame < ((totalTime - fireDelay) / 2 + fireDelay)) + { + // up and left + int const weaponOffset = (*weaponFrame) - fireDelay; + weaponYOffset += 10 * weaponOffset; // U + weaponX += 80 * weaponOffset; + } + else if (*weaponFrame < totalTime) + { + // start high + weaponYOffset += 240; + weaponYOffset -= 12 * ((*weaponFrame) - fireDelay); // D + // move left + weaponX += 90 - 5 * (totalTime - (*weaponFrame)); + } + } + else + { + if (*weaponFrame < 7) weaponYOffset -= 10 * (*weaponFrame); // D + else if (*weaponFrame < 12) weaponYOffset += 20 * ((*weaponFrame) - 10); // U + else if (*weaponFrame < 20) weaponYOffset -= 9 * ((*weaponFrame) - 14); // D + + weaponYOffset += 10; + } } G_DrawWeaponTileWithID(currentWeapon, weaponX + 190 - halfLookAng, weaponY + 260 - weaponYOffset, @@ -2639,6 +2906,55 @@ void P_DisplayWeapon(void) break; case DEVISTATOR_WEAPON__STATIC: + if (WW2GI) + { + if (*weaponFrame) + { + int32_t const totalTime = PWEAPON(screenpeek, pPlayer->curr_weapon, TotalTime); + int32_t const reloadTime = PWEAPON(screenpeek, pPlayer->curr_weapon, Reload); + + if (*weaponFrame < totalTime) + { + int const tileOffset = ksgn((*weaponFrame) >> 2); + + if (pPlayer->ammo_amount[pPlayer->curr_weapon] & 1) + { + G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 30 - halfLookAng, weaponY + 240 - weaponYOffset, + DEVISTATOR, weaponShade, weaponBits | 4, weaponPal); + G_DrawWeaponTileWithID(currentWeapon, weaponX + 268 - halfLookAng, weaponY + 238 - weaponYOffset, + DEVISTATOR + tileOffset, -32, weaponBits, weaponPal); + } + else + { + G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 30 - halfLookAng, weaponY + 240 - weaponYOffset, + DEVISTATOR + tileOffset, -32, weaponBits | 4, weaponPal); + G_DrawWeaponTileWithID(currentWeapon, weaponX + 268 - halfLookAng, weaponY + 238 - weaponYOffset, DEVISTATOR, + weaponShade, weaponBits, weaponPal); + } + } + // else we are in 'reload time' + else + { + weaponYOffset -= (*weaponFrame < ((reloadTime - totalTime) / 2 + totalTime)) + ? 10 * ((*weaponFrame) - totalTime) + : 10 * (reloadTime - (*weaponFrame)); + + G_DrawWeaponTileWithID(currentWeapon, weaponX + 268 - halfLookAng, weaponY + 238 - weaponYOffset, DEVISTATOR, + weaponShade, weaponBits, weaponPal); + G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 30 - halfLookAng, weaponY + 240 - weaponYOffset, DEVISTATOR, + weaponShade, weaponBits | 4, weaponPal); + } + } + else + { + G_DrawWeaponTileWithID(currentWeapon, weaponX + 268 - halfLookAng, weaponY + 238 - weaponYOffset, DEVISTATOR, + weaponShade, weaponBits, weaponPal); + G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 30 - halfLookAng, weaponY + 240 - weaponYOffset, DEVISTATOR, + weaponShade, weaponBits | 4, weaponPal); + } + break; + } + if (*weaponFrame > 0) { static uint8_t const devastatorFrames[] = { 0, 4, 12, 24, 12, 4, 0 }; @@ -2706,6 +3022,65 @@ void P_DisplayWeapon(void) weaponX += 28; weaponY += 18; + if (WW2GI) + { + if (*weaponFrame == 0) + { + // the 'at rest' display + if (currentWeapon == GROW_WEAPON) + { + G_DrawWeaponTileWithID(currentWeapon, weaponX + 188 - halfLookAng, weaponY + 240 - weaponYOffset, SHRINKER - 2, + weaponShade, weaponBits, weaponPal); + break; + } + else if (pPlayer->ammo_amount[currentWeapon] > 0) + { + G_DrawWeaponTileUnfadedWithID(currentWeapon << 1, weaponX + 184 - halfLookAng, weaponY + 240 - weaponYOffset, SHRINKER + 2, + 16 - (sintable[pPlayer->random_club_frame & 2047] >> 10), weaponBits, 0); + G_DrawWeaponTileWithID(currentWeapon, weaponX + 188 - halfLookAng, weaponY + 240 - weaponYOffset, SHRINKER, + weaponShade, weaponBits, weaponPal); + break; + } + } + else + { + // the 'active' display. + if (doAnim) + { + weaponX += rand() & 3; + weaponYOffset += rand() & 3; + } + + int const totalTime = PWEAPON(screenpeek, pPlayer->curr_weapon, TotalTime); + int const reloadTime = PWEAPON(screenpeek, pPlayer->curr_weapon, Reload); + + if (*weaponFrame < totalTime) + { + if (*weaponFrame >= PWEAPON(screenpeek, pPlayer->curr_weapon, FireDelay)) + { + // after fire time. + // lower weapon to reload cartridge (not clip) + weaponYOffset -= (currentWeapon == GROW_WEAPON ? 15 : 10) * (totalTime - (*weaponFrame)); + } + } + // else we are in 'reload time' + else + { + weaponYOffset -= (*weaponFrame < ((reloadTime - totalTime) / 2 + totalTime)) + ? (currentWeapon == GROW_WEAPON ? 5 : 10) * ((*weaponFrame) - totalTime) // D + : 10 * (reloadTime - (*weaponFrame)); // U + } + } + + G_DrawWeaponTileUnfadedWithID(currentWeapon << 1, weaponX + 184 - halfLookAng, weaponY + 240 - weaponYOffset, + SHRINKER + 3 + ((*weaponFrame) & 3), -32, weaponBits, currentWeapon == GROW_WEAPON ? 2 : 0); + + G_DrawWeaponTileWithID(currentWeapon, weaponX + 188 - halfLookAng, weaponY + 240 - weaponYOffset, + SHRINKER + (currentWeapon == GROW_WEAPON ? -1 : 1), weaponShade, weaponBits, weaponPal); + + break; + } + if ((*weaponFrame) > 0) { if (doAnim) @@ -3924,16 +4299,18 @@ static int32_t P_DoCounters(int playerNum) } A_PlaySound(soundId, pPlayer->i); } - else if (totalclock > 1024) - if (playerNum == screenpeek || GTFLAGS(GAMETYPE_COOPSOUND)) - { - if (rand()&1) - A_PlaySound(DUKE_CRACK,pPlayer->i); - else A_PlaySound(DUKE_CRACK2,pPlayer->i); - } + else if (!WW2GI) + { + if (totalclock > 1024) + if (playerNum == screenpeek || GTFLAGS(GAMETYPE_COOPSOUND)) + { + if (rand()&1) + A_PlaySound(DUKE_CRACK,pPlayer->i); + else A_PlaySound(DUKE_CRACK2,pPlayer->i); + } - if (!RR) - A_PlaySound(DUKE_CRACK_FIRST,pPlayer->i); + A_PlaySound(DUKE_CRACK_FIRST, pPlayer->i); + } } else if (pPlayer->knuckle_incs == 22 || TEST_SYNC_KEY(g_player[playerNum].inputBits->bits, SK_FIRE)) pPlayer->knuckle_incs=0; @@ -3952,7 +4329,7 @@ int16_t WeaponPickupSprites[MAX_WEAPONS] = { KNEE__STATIC, FIRSTGUNSPRITE__STATI void P_DropWeapon(int const playerNum) { DukePlayer_t *const pPlayer = g_player[playerNum].ps; - int const currentWeapon = pPlayer->curr_weapon; + int const currentWeapon = WW2GI ? PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) : pPlayer->curr_weapon; if (RRRA && (g_netServer || numplayers > 1)) { @@ -3990,7 +4367,7 @@ void P_DropWeapon(int const playerNum) } } - if ((unsigned)currentWeapon >= MAX_WEAPONS) + if (currentWeapon == KNEE_WEAPON || (unsigned)currentWeapon >= MAX_WEAPONS) return; if (krand2() & 1) @@ -4137,15 +4514,6 @@ void P_SelectNextInvItem(DukePlayer_t *pPlayer) pPlayer->inven_icon = ICON_NONE; } -// Set C-CON's WEAPON and WORKSLIKE gamevars. -void P_SetWeaponGamevars(int playerNum, const DukePlayer_t * const pPlayer) -{ - Gv_SetVar(g_weaponVarID, pPlayer->curr_weapon, pPlayer->i, playerNum); - Gv_SetVar(g_worksLikeVarID, - ((unsigned)pPlayer->curr_weapon < MAX_WEAPONS) ? PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) : -1, - pPlayer->i, playerNum); -} - void P_CheckWeapon(DukePlayer_t *pPlayer) { int playerNum; @@ -4571,9 +4939,10 @@ static void P_ProcessWeapon(int playerNum) } } #undef WEAPON2_CLIP - if (pPlayer->curr_weapon == SHRINKER_WEAPON || pPlayer->curr_weapon == GROW_WEAPON + if (WW2GI ? PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_GLOWS : + (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))) + || (RRRA && (pPlayer->curr_weapon == KNEE_WEAPON || pPlayer->curr_weapon == SLINGBLADE_WEAPON)))) { pPlayer->random_club_frame += 64; // Glowing @@ -4627,19 +4996,23 @@ static void P_ProcessWeapon(int playerNum) P_SetWeaponGamevars(playerNum, pPlayer); if (VM_OnEvent(EVENT_FIRE, pPlayer->i, playerNum) == 0) { - switch (DYNAMICWEAPONMAP(pPlayer->curr_weapon)) + switch (DYNAMICWEAPONMAP(WW2GI ? PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) : pPlayer->curr_weapon)) { case HANDBOMB_WEAPON__STATIC: pPlayer->hbomb_hold_delay = 0; if (pPlayer->ammo_amount[pPlayer->curr_weapon] > 0) { (*weaponFrame) = 1; + if (WW2GI && PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0) + A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i); } break; case HANDREMOTE_WEAPON__STATIC: pPlayer->hbomb_hold_delay = 0; (*weaponFrame) = 1; + if (WW2GI && PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0) + A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i); break; case PISTOL_WEAPON__STATIC: @@ -4647,6 +5020,8 @@ static void P_ProcessWeapon(int playerNum) { pPlayer->ammo_amount[PISTOL_WEAPON]--; (*weaponFrame) = 1; + if (WW2GI && PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0) + A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i); } break; @@ -4654,6 +5029,8 @@ static void P_ProcessWeapon(int playerNum) if (pPlayer->ammo_amount[SHOTGUN_WEAPON] > 0 && pPlayer->random_club_frame == 0) { (*weaponFrame) = 1; + if (WW2GI && PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0) + A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i); } break; @@ -4706,6 +5083,10 @@ static void P_ProcessWeapon(int playerNum) pPlayer->pos.z = pPlayer->opos.z; pPlayer->vel.z = 0; (*weaponFrame) = 1; + if (WW2GI && PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0) + { + A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i); + } } } break; @@ -4714,7 +5095,10 @@ static void P_ProcessWeapon(int playerNum) if (pPlayer->ammo_amount[SHRINKER_WEAPON] > 0) { (*weaponFrame) = 1; - A_PlaySound(SHRINKER_FIRE, pPlayer->i); + if (!WW2GI) + A_PlaySound(SHRINKER_FIRE, pPlayer->i); + else if (PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0) + A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i); } break; @@ -4722,16 +5106,24 @@ static void P_ProcessWeapon(int playerNum) if (pPlayer->ammo_amount[GROW_WEAPON] > 0) { (*weaponFrame) = 1; - A_PlaySound(RR ? 431 : EXPANDERSHOOT, pPlayer->i); + if (!WW2GI) + A_PlaySound(RR ? 431 : EXPANDERSHOOT, pPlayer->i); + else if (PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0) + A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i); } break; case FREEZE_WEAPON__STATIC: - if (pPlayer->ammo_amount[FREEZE_WEAPON] > 0) + if (pPlayer->ammo_amount[pPlayer->curr_weapon] > 0) { (*weaponFrame) = 1; if (!RR) - A_PlaySound(CAT_FIRE, pPlayer->i); + { + if (!WW2GI) + A_PlaySound(CAT_FIRE, pPlayer->i); + else if (PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0) + A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i); + } } break; @@ -4740,6 +5132,8 @@ static void P_ProcessWeapon(int playerNum) if (pPlayer->ammo_amount[pPlayer->curr_weapon] > 0) { (*weaponFrame) = 1; + if (WW2GI && PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0) + A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i); } break; @@ -4749,7 +5143,12 @@ static void P_ProcessWeapon(int playerNum) (*weaponFrame) = 1; pPlayer->hbomb_hold_delay = !pPlayer->hbomb_hold_delay; if (!RR) - A_PlaySound(CAT_FIRE, pPlayer->i); + { + if (!WW2GI) + A_PlaySound(CAT_FIRE, pPlayer->i); + else if (PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0) + A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i); + } } break; @@ -4765,6 +5164,8 @@ static void P_ProcessWeapon(int playerNum) if (pPlayer->quick_kick == 0) { (*weaponFrame) = 1; + if (WW2GI && PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0) + A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i); } break; @@ -5375,6 +5776,186 @@ static void P_ProcessWeapon(int playerNum) break; } } + else if (WW2GI) + { + if (PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) == HANDBOMB_WEAPON) + { + if (PWEAPON(playerNum, pPlayer->curr_weapon, HoldDelay) && ((*weaponFrame) == PWEAPON(playerNum, pPlayer->curr_weapon, FireDelay)) && TEST_SYNC_KEY(playerBits, SK_FIRE)) + { + pPlayer->rapid_fire_hold = 1; + return; + } + + if (++(*weaponFrame) == PWEAPON(playerNum, pPlayer->curr_weapon, HoldDelay)) + { + pPlayer->ammo_amount[pPlayer->curr_weapon]--; + + int pipeBombType; + int pipeBombZvel; + int pipeBombFwdVel; + + if (pPlayer->on_ground && TEST_SYNC_KEY(playerBits, SK_CROUCH)) + { + pipeBombFwdVel = 15; + pipeBombZvel = (fix16_to_int(pPlayer->q16horiz + pPlayer->q16horizoff - F16(100)) * 20); + } + else + { + pipeBombFwdVel = 140; + pipeBombZvel = -512 - (fix16_to_int(pPlayer->q16horiz + pPlayer->q16horizoff - F16(100)) * 20); + } + + int pipeSpriteNum = A_InsertSprite(pPlayer->cursectnum, + pPlayer->pos.x+(sintable[(fix16_to_int(pPlayer->q16ang)+512)&2047]>>6), + pPlayer->pos.y+(sintable[fix16_to_int(pPlayer->q16ang)&2047]>>6), + pPlayer->pos.z,PWEAPON(playerNum, pPlayer->curr_weapon, Shoots),-16,9,9, + fix16_to_int(pPlayer->q16ang),(pipeBombFwdVel+(pPlayer->hbomb_hold_delay<<5)),pipeBombZvel,pPlayer->i,1); + + int pipeLifeTime = Gv_GetVarByLabel("GRENADE_LIFETIME", NAM_GRENADE_LIFETIME, -1, playerNum); + int pipeLifeVariance = Gv_GetVarByLabel("GRENADE_LIFETIME_VAR", NAM_GRENADE_LIFETIME_VAR, -1, playerNum); + sprite[pipeSpriteNum].extra = pipeLifeTime + + mulscale14(krand2(), pipeLifeVariance) + - pipeLifeVariance; + + if (pipeBombFwdVel == 15) + { + sprite[pipeSpriteNum].yvel = 3; + sprite[pipeSpriteNum].z += ZOFFSET3; + } + + if (A_GetHitscanRange(pPlayer->i) < 512) + { + sprite[pipeSpriteNum].ang += 1024; + sprite[pipeSpriteNum].zvel /= 3; + sprite[pipeSpriteNum].xvel /= 3; + } + + pPlayer->hbomb_on = 1; + } + else if ((*weaponFrame) < PWEAPON(playerNum, pPlayer->curr_weapon, HoldDelay) && TEST_SYNC_KEY(playerBits, SK_FIRE)) + pPlayer->hbomb_hold_delay++; + else if ((*weaponFrame) > PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime)) + { + (*weaponFrame) = 0; + P_CheckWeapon(pPlayer); + } + } + else if (PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) == HANDREMOTE_WEAPON) + { + if (++(*weaponFrame) == PWEAPON(playerNum, pPlayer->curr_weapon, FireDelay)) + { + if (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_BOMB_TRIGGER) + pPlayer->hbomb_on = 0; + + if (PWEAPON(playerNum, pPlayer->curr_weapon, Shoots) != 0) + { + if (!(PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_NOVISIBLE)) + { + lastvisinc = (int32_t) totalclock+32; + pPlayer->visibility = 0; + } + + P_SetWeaponGamevars(playerNum, pPlayer); + A_Shoot(pPlayer->i, PWEAPON(playerNum, pPlayer->curr_weapon, Shoots)); + } + } + + if ((*weaponFrame) >= PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime)) + { + (*weaponFrame) = 0; + if (pPlayer->ammo_amount[HANDBOMB_WEAPON] > 0) + P_AddWeapon(pPlayer, HANDBOMB_WEAPON); + else P_CheckWeapon(pPlayer); + } + } + else + { + // the basic weapon... + (*weaponFrame)++; + + if (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_CHECKATRELOAD) + { + if (*weaponFrame >= PWEAPON(playerNum, pPlayer->curr_weapon, Reload)) + P_CheckWeapon(pPlayer); + } + + if (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_STANDSTILL + && *weaponFrame < (PWEAPON(playerNum, pPlayer->curr_weapon, FireDelay)+1)) + { + pPlayer->pos.z = pPlayer->opos.z; + pPlayer->vel.z = 0; + } + + if (*weaponFrame == PWEAPON(playerNum, pPlayer->curr_weapon, Sound2Time)) + if (PWEAPON(playerNum, pPlayer->curr_weapon, Sound2Sound) > 0) + A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, Sound2Sound),pPlayer->i); + + if (*weaponFrame == PWEAPON(playerNum, pPlayer->curr_weapon, SpawnTime)) + P_DoWeaponSpawn(playerNum); + + if (*weaponFrame == PWEAPON(playerNum, pPlayer->curr_weapon, FireDelay)) + P_FireWeapon(playerNum); + + if (*weaponFrame > PWEAPON(playerNum, pPlayer->curr_weapon, FireDelay) + && *weaponFrame < PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime)) + { + if (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_AUTOMATIC) + { + if (TEST_SYNC_KEY(playerBits, SK_FIRE) == 0) + *weaponFrame = PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime); + if (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_FIREEVERYTHIRD) + { + if (((*(weaponFrame))%3) == 0) + { + P_FireWeapon(playerNum); + P_DoWeaponSpawn(playerNum); + } + } + if (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_FIREEVERYOTHER) + { + P_FireWeapon(playerNum); + P_DoWeaponSpawn(playerNum); + } + } + } + else if (*weaponFrame >= PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime)) + { + if (PWEAPON(playerNum, pPlayer->curr_weapon, Reload) > PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime) && pPlayer->ammo_amount[pPlayer->curr_weapon] > 0 + && PWEAPON(playerNum, pPlayer->curr_weapon, Clip) && pPlayer->ammo_amount[pPlayer->curr_weapon] % PWEAPON(playerNum, pPlayer->curr_weapon, Clip) == 0) + { + int const weaponReloadTime = PWEAPON(playerNum, pPlayer->curr_weapon, Reload) + - PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime); + + if ((*weaponFrame) == (PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime)+1)) + { + A_PlaySound(EJECT_CLIP, pPlayer->i); + } + else if ((*weaponFrame) == + (PWEAPON(playerNum, pPlayer->curr_weapon, Reload) - (weaponReloadTime / 3))) + { + A_PlaySound(INSERT_CLIP, pPlayer->i); + } + if ((*weaponFrame) >= (PWEAPON(playerNum, pPlayer->curr_weapon, Reload))) + { + *weaponFrame = 0; + } + } + else + { + if (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_AUTOMATIC) + { + if (TEST_SYNC_KEY(playerBits, SK_FIRE)) + { + *weaponFrame = + (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_RANDOMRESTART) ? 1 + (krand2() & 3) : 1; + } + else *weaponFrame = 0; + } + else *weaponFrame = 0; + } + } + } + } else { switch (DYNAMICWEAPONMAP(pPlayer->curr_weapon)) @@ -6932,7 +7513,7 @@ check_enemy_sprite: P_UpdatePosWhenViewingCam(pPlayer); P_DoCounters(playerNum); - if (pPlayer->curr_weapon == HANDREMOTE_WEAPON) + if ((WW2GI ? PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) : pPlayer->curr_weapon) == HANDREMOTE_WEAPON) P_ProcessWeapon(playerNum); return; diff --git a/source/rr/src/premap.cpp b/source/rr/src/premap.cpp index 8359cd266..cf6f4e28c 100644 --- a/source/rr/src/premap.cpp +++ b/source/rr/src/premap.cpp @@ -1956,13 +1956,14 @@ end_vol4a: { for (bssize_t weaponNum = 0; weaponNum < MAX_WEAPONS; weaponNum++) { - if (weaponNum == PISTOL_WEAPON) + auto const worksLike = WW2GI ? PWEAPON(0, weaponNum, WorksLike) : weaponNum; + if (worksLike == PISTOL_WEAPON) { pPlayer->curr_weapon = weaponNum; pPlayer->gotweapon |= (1 << weaponNum); pPlayer->ammo_amount[weaponNum] = min(pPlayer->max_ammo_amount[weaponNum], 48); } - else if (weaponNum == KNEE_WEAPON || (!RR && weaponNum == HANDREMOTE_WEAPON) || (RRRA && weaponNum == SLINGBLADE_WEAPON)) + else if (worksLike == KNEE_WEAPON || (!RR && worksLike == HANDREMOTE_WEAPON) || (RRRA && worksLike == SLINGBLADE_WEAPON)) { pPlayer->gotweapon |= (1 << weaponNum); if (RRRA) diff --git a/source/rr/src/sbar.cpp b/source/rr/src/sbar.cpp index a3c31c67e..64e810707 100644 --- a/source/rr/src/sbar.cpp +++ b/source/rr/src/sbar.cpp @@ -604,8 +604,12 @@ static int32_t G_GetInvOn(const DukePlayer_t *p) return 0x80000000; } -static inline void rotatesprite_althud(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, int8_t dashade, uint8_t dapalnum, int32_t dastat) +static int32_t G_GetMorale(int32_t p_i, int32_t snum) { + return Gv_GetVarByLabel("PLR_MORALE", -1, p_i, snum); +} + +static inline void rotatesprite_althud(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, int8_t dashade, uint8_t dapalnum, int32_t dastat){ if (videoGetRenderMode() >= REND_POLYMOST && althud_shadows) rotatesprite_(sbarx(sx+1), sbary(sy+1), z, a, picnum, 127, 4, dastat + POLYMOSTTRANS2, 0, 0, 0, 0, xdim - 1, ydim - 1); rotatesprite_(sbarx(sx), sbary(sy), z, a, picnum, dashade, dapalnum, dastat, 0, 0, 0, 0, xdim - 1, ydim - 1); @@ -808,7 +812,13 @@ void G_DrawStatusBar(int32_t snum) } rotatesprite_althud(62, hudoffset-25, sb15h, 0, SHIELD, 0, 0, 10+16+256); - G_DrawAltDigiNum(105, -(hudoffset-22), p->inv_amount[GET_SHIELD], -16, 10+16+256); + + { + int32_t lAmount = G_GetMorale(p->i, snum); + if (lAmount == -1) + lAmount = p->inv_amount[GET_SHIELD]; + G_DrawAltDigiNum(105, -(hudoffset-22), lAmount, -16, 10+16+256); + } if (ammo_sprites[p->curr_weapon] >= 0) { @@ -844,6 +854,8 @@ void G_DrawStatusBar(int32_t snum) G_DrawInvNum(-(284-30-o), 0, hudoffset-6-3, (uint8_t) i, 0, 10+permbit+256); + if (!WW2GI) + { if (j > 0) { if (videoGetRenderMode() >= REND_POLYMOST && althud_shadows) @@ -856,6 +868,7 @@ void G_DrawStatusBar(int32_t snum) minitextshade(284-30-o+1, hudoffset-20-3+1, "Off", 127, 4, POLYMOSTTRANS+orient+ROTATESPRITE_MAX); minitext(284-30-o, hudoffset-20-3, "Off", 2, orient+ROTATESPRITE_MAX); } + } if (p->inven_icon >= ICON_SCUBA) { @@ -981,10 +994,13 @@ void G_DrawStatusBar(int32_t snum) G_DrawInvNum(284-30-o, yofssh, 200-6, (uint8_t) i, 0, orient&~16); + if (!WW2GI) + { if (j > 0) minitext(288-30-o, 180, GStrings("OPTVAL_ON"), 0, orient); else if ((uint32_t) j != 0x80000000) minitext(284-30-o, 180, GStrings("OPTVAL_OFF"), 2, orient); + } if (p->inven_icon >= ICON_SCUBA) minitext(284-35-o, 180, GStrings("OPTVAL_AUTO"), 2, orient); @@ -1024,7 +1040,9 @@ void G_DrawStatusBar(int32_t snum) } { - int32_t lAmount = p->inv_amount[GET_SHIELD]; + int32_t lAmount = G_GetMorale(p->i, snum); + if (lAmount == -1) + lAmount = p->inv_amount[GET_SHIELD]; if (sbar.inv_amount[GET_SHIELD] != lAmount) { sbar.inv_amount[GET_SHIELD] = lAmount; @@ -1045,6 +1063,8 @@ void G_DrawStatusBar(int32_t snum) sbar.ammo_amount[i] = p->ammo_amount[i]; if (i < 9) u |= ((2<refresh_inventory) + if (WW2GI && pPlayer->refresh_inventory) playerBits |= BIT(SK_INV_LEFT); // emulate move left... - if (pPlayer->newowner == -1 && (TEST_SYNC_KEY(playerBits, SK_INV_LEFT) || TEST_SYNC_KEY(playerBits, SK_INV_RIGHT))) + if (pPlayer->newowner == -1 && (TEST_SYNC_KEY(playerBits, SK_INV_LEFT) || TEST_SYNC_KEY(playerBits, SK_INV_RIGHT)) || (!WW2GI && pPlayer->refresh_inventory)) { pPlayer->invdisptime = GAMETICSPERSEC*2;