Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 56 additions & 49 deletions TheForceEngine/TFE_DarkForces/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1830,69 +1830,76 @@ namespace TFE_DarkForces
//s_282344 = 34 - dH;
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This diff below looks big but all of the lines from this point to :1844 are unchanged except for the following:

  • I removed the if block that starts on line :1836 and thus all of the code within that block down to :1885 was indented left-ward (hence why the diff looks large). I removed it because we now need to run these calculations regardless of whether head waving is on since these are used for weapon waving.
  • Any assignments to s_headwaveVerticalOffset in this range of code now assign to a new local variable headwaveVerticalOffset (see :1835). I essentially avoid modifying s_headwaveVerticalOffset until I know the head waving is on and needs to be applied since modifying s_headwaveVerticalOffset alters how player projectiles (like lasers from the blaster) are calculated.

// Headwave
// Calculate the head and weapon wave offsets.
s32 xWpnWaveOffset = 0;
s_headwaveVerticalOffset = 0;
if (s_config.headwave && (player->flags & 2))
s32 headwaveVerticalOffset = 0;
fixed16_16 playerSpeed = distApprox(0, 0, s_playerVelX, s_playerVelZ);
if (!moved)
{
playerSpeed = 0;
}
if ((s_playerSector->flags1 & SEC_FLAGS1_ICE_FLOOR) && !s_wearingCleats)
{
playerSpeed = 0;
}

if (playerSpeed != s_playerSpeed)
{
fixed16_16 playerSpeed = distApprox(0, 0, s_playerVelX, s_playerVelZ);
if (!moved)
fixed16_16 speedDelta = playerSpeed - s_playerSpeed;
fixed16_16 maxFrameChange = mul16(FIXED(32), s_deltaTime);

if (speedDelta > maxFrameChange)
{
playerSpeed = 0;
speedDelta = maxFrameChange;
}
if ((s_playerSector->flags1 & SEC_FLAGS1_ICE_FLOOR) && !s_wearingCleats)
else if (speedDelta < -maxFrameChange)
{
playerSpeed = 0;
speedDelta = -maxFrameChange;
}
s_playerSpeed += speedDelta;
}
sinCosFixed((s_curTick & 0xffff) << 7, &s_wpnSin, &s_wpnCos);

if (playerSpeed != s_playerSpeed)
{
fixed16_16 speedDelta = playerSpeed - s_playerSpeed;
fixed16_16 maxFrameChange = mul16(FIXED(32), s_deltaTime);

if (speedDelta > maxFrameChange)
{
speedDelta = maxFrameChange;
}
else if (speedDelta < -maxFrameChange)
{
speedDelta = -maxFrameChange;
}
s_playerSpeed += speedDelta;
}
sinCosFixed((s_curTick & 0xffff) << 7, &s_wpnSin, &s_wpnCos);

fixed16_16 playerSpeedFract = div16(s_playerSpeed, FIXED(32));
s_headwaveVerticalOffset = mul16(mul16(s_wpnCos, PLAYER_HEADWAVE_VERT_SPD), playerSpeedFract);
fixed16_16 playerSpeedFract = div16(s_playerSpeed, FIXED(32));
headwaveVerticalOffset = mul16(mul16(s_wpnCos, PLAYER_HEADWAVE_VERT_SPD), playerSpeedFract);

sinCosFixed((s_curTick & 0xffff) << 6, &s_wpnSin, &s_wpnCos);
xWpnWaveOffset = mul16(playerSpeedFract, s_wpnCos) >> 12;
sinCosFixed((s_curTick & 0xffff) << 6, &s_wpnSin, &s_wpnCos);
xWpnWaveOffset = mul16(playerSpeedFract, s_wpnCos) >> 12;

// Water...
if (s_playerSector->secHeight - 1 >= 0)
// Water...
if (s_playerSector->secHeight - 1 >= 0)
{
if (s_externalVelX || s_externalVelZ)
{
if (s_externalVelX || s_externalVelZ)
{
fixed16_16 externSpd = distApprox(0, 0, s_externalVelX, s_externalVelZ);

// Replace the fractional part with the current time fractional part.
// I think this is meant to add some "randomness" to the headwave while in water.
fixed16_16 speed = externSpd & (~0xffff);
speed |= (s_curTick & 0xffff);
// Then multiply by 16 and take the cosine - this is meant to be a small modification to the weapon motion
// (note that the base multiplier is 128).
sinCosFixed(speed << 4, &s_wpnSin, &s_wpnCos);
// Modify the headwave motion.
s_headwaveVerticalOffset += mul16(s_wpnCos, PLAYER_HEADWAVE_VERT_WATER_SPD);
}
fixed16_16 externSpd = distApprox(0, 0, s_externalVelX, s_externalVelZ);

// Replace the fractional part with the current time fractional part.
// I think this is meant to add some "randomness" to the headwave while in water.
fixed16_16 speed = externSpd & (~0xffff);
speed |= (s_curTick & 0xffff);
// Then multiply by 16 and take the cosine - this is meant to be a small modification to the weapon motion
// (note that the base multiplier is 128).
sinCosFixed(speed << 4, &s_wpnSin, &s_wpnCos);
// Modify the headwave motion.
headwaveVerticalOffset += mul16(s_wpnCos, PLAYER_HEADWAVE_VERT_WATER_SPD);
}
}
setCameraOffset(0, s_headwaveVerticalOffset, 0);

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code below is where the condition was moved to and what ultimately separates the head waving and weapon waving, as well as applying the new setting.

// Apply the weapon motion.
if (s_config.headwave && (player->flags & 2))
{
// If head wave is enabled, store the offset and apply it. This offset also affects projectiles fired by the player so
// we must not store it if head waving is disabled.
s_headwaveVerticalOffset = headwaveVerticalOffset;
setCameraOffset(0, s_headwaveVerticalOffset, 0);
}

PlayerWeapon* weapon = s_curPlayerWeapon;
weapon->xWaveOffset = xWpnWaveOffset; // the x offset has 4 bits of sub-texel precision.
weapon->yWaveOffset = s_headwaveVerticalOffset >> 13; // the y offset is probably the same 4 bits of precision & multiplied by half.
if (TFE_Settings::getHudSettings()->weaponWave)
{
// If weapon wave is enabled, apply the offset.
weapon->xWaveOffset = xWpnWaveOffset; // the x offset has 4 bits of sub-texel precision.
weapon->yWaveOffset = headwaveVerticalOffset >> 13; // the y offset is probably the same 4 bits of precision & multiplied by half.
}

// The moves the player can make are restricted based on whether they are on the floor or not.
if (s_colCurLowestFloor == player->posWS.y)
Expand Down
4 changes: 4 additions & 0 deletions TheForceEngine/TFE_FrontEndUI/frontEndUi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1538,6 +1538,10 @@ namespace TFE_FrontEndUI
ImGui::SetNextItemWidth(196*s_uiScale);
ImGui::SliderInt("Offset Y", &hud->pixelOffset[1], -512, 512);

ImGui::Separator();

ImGui::Checkbox("Weapon Wave", &hud->weaponWave);

if (s_menuRetState != APP_STATE_MENU)
{
TFE_DarkForces::mission_render();
Expand Down
5 changes: 5 additions & 0 deletions TheForceEngine/TFE_Settings/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ namespace TFE_Settings
writeHeader(settings, c_sectionNames[SECTION_HUD]);
writeKeyValue_String(settings, "hudScale", c_tfeHudScaleStrings[s_hudSettings.hudScale]);
writeKeyValue_String(settings, "hudPos", c_tfeHudPosStrings[s_hudSettings.hudPos]);
writeKeyValue_Bool(settings, "weaponWave", s_hudSettings.weaponWave);
writeKeyValue_Float(settings, "scale", s_hudSettings.scale);
writeKeyValue_Int(settings, "pixelOffsetX", s_hudSettings.pixelOffset[0]);
writeKeyValue_Int(settings, "pixelOffsetY", s_hudSettings.pixelOffset[1]);
Expand Down Expand Up @@ -582,6 +583,10 @@ namespace TFE_Settings
{
s_hudSettings.pixelOffset[1] = parseInt(value);
}
else if (strcasecmp("weaponWave", key) == 0)
{
s_hudSettings.weaponWave = parseBool(value);
}
}

void parseSoundSettings(const char* key, const char* value)
Expand Down
2 changes: 2 additions & 0 deletions TheForceEngine/TFE_Settings/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ struct TFE_Settings_Hud
TFE_HudScale hudScale = TFE_HUDSCALE_PROPORTIONAL;
// This setting determines how the left and right corners are calculated, which have an offset of (0,0).
TFE_HudPosition hudPos = TFE_HUDPOS_EDGE;
// This setting determines whether the weapon will wave/bob.
bool weaponWave = true;

// Scale of the HUD, ignored if HudScale is TFE_HUDSCALE_PROPORTIONAL.
f32 scale = 1.0f;
Expand Down