Progress on the Unified SDK
Release candidate 3 is now available: https://github.com/SamVanheer/halflife-unified-sdk/releases/tag/UNIFIED-V1.0.0-RC003SDK Changes
- Reworked tripmine entities to use separate world model
- Don't allow executing sv_addbot with no parameters
- Added
ITEM_FLAG_SELECTONEMPTY
flag to weapons that regenerate ammo to always be selectable and never show as red in hud history - Truncate yaw using cast to int instead of floor to match engine behavior (fixes NPC navigation in some maps)
- Fixed
ambient_music
not being triggerable in radius mode - Added keyvalues to set barney & otis corpse bodygroups
- Fixed code analysis warnings when combining format result with string_view in ternary
- Speed up
sv_load_all_maps
, automatically load first map & print more info, more consistent and robust behavior and addedstop_loading_all_maps
command to stop this process - Build portable binaries and workaround gcc bug to allow the Linux version to run on architectures that are missing the C++ runtime version used by the game and to avoid problems with
std::regex
- Additional fix for op4loader sound looping bug to stop looping when the NPC is removed
- Boosted volume to match original engine by multiplying by **8**
C# Changes
- Adjusted
MaxRange
(far Z clipping plane) inc2a2a
to fix graphical issues - Fixed Alien Slaves in
ba_canal1
waiting for 5 seconds before attacking - Added upgrades to fix issues with barney, otis & scientists in specific levels (skin color & equipped weapons and items)
- Don't delete node graphs, update timestamps instead so graphs will be loaded from disk
- Updated third party dependencies and updated BSPToObj to account for changes in the vertex order used by Sledge library
- Add upgrade for
bell1.wav
sound and pitch so the bell sound sounds like it does in the original game
Asset Changes
- Added separate tripmine world model
- Added scientist_cower models
- Reverted changes made to viewmodel animations to match the original games
- Updated test maps to account for code changes
- Fixed HEV suit sentences playing in Opposing Force and Blue Shift
- Changed event id for sounds played by scientists that shouldn't affect the mouth so scientists don't "talk" when a beep sound plays
- Add polygons to loader accordion spine
- Added
hlu_technology_demonstration
map (unfinished, only contains a zoo of various NPCs and NPC models at this time)
Framerate issues in the GoldSource engine
Some people have reported issues that occur when playing at high framerates (100+ FPS) or when using cvars likehost_framerate
to manipulate the framerate to run very high.This game was developed on machines that ran the game at about 20-30 FPS and everything was designed around that. The engine doesn't compensate for high framerates correctly in some cases and some game code also lacks proper compensation. Some of these issues have been fixed but the game will never work properly at high framerates because the render framerate is tied to the simulation framerate.
The engine was also designed to run at a maximum of 72 FPS, as seen in Quake 1's source code: https://github.com/id-Software/Quake/blob/bf4ac424ce754894ac8f1dae6a3981954bc9852d/WinQuake/host.c#L494-L522
GoldSource lacks this limiter but it still won't work properly. The recommended framerate is either 30 or 60 FPS. 100 FPS generally works but in specific cases like elevators there might be glitches like NPCs taking damage, dying or getting gibbed due to getting stuck. Higher framerates will be more prone to glitches.
Modern engines typically lock framerates or decouple the simulation framerate from the render framerate to avoid these issues, unfortunately this can't be fixed in a mod without re-implementing the entire physics engine.
NPC navigation issues
Users reported NPCs having problems navigating in specific areas. Known occurences includeWe've Got Hostiles
in the area after the first elevator and a soft-lock that sometimes occurs in Lambda Core
level A, where the scientist holding the shotgun fails to move to the button to open the door.This was caused by an engine function that was re-implemented in game code to allow for better optimizations.
The faulty code looked like this:
float VectorToYaw(const Vector& forward)
{
if (forward[1] == 0 && forward[0] == 0)
{
return 0;
}
float yaw = atan2(forward[1], forward[0]) * 180 / PI;
if (yaw < 0)
{
yaw += 360;
}
return yaw;
}
The fixed code looks like this:
float VectorToYaw(const Vector& forward)
{
if (forward[1] == 0 && forward[0] == 0)
{
return 0;
}
float yaw = static_cast<int>(atan2(forward[1], forward[0]) * 180 / PI);
if (yaw < 0)
{
yaw += 360;
}
return yaw;
}
The lack of a cast to int caused yaw angles to be calculated slightly differently compared to the engine.Casting to int and then back to float causes the value to be rounded. The exact behavior is compiler-specific, in Microsoft's case this is equivalent to calling
std::round
: https://learn.microsoft.com/en-us/cpp/c-language/conversions-from-floating-point-types?view=msvc-170Without the cast no rounding is performed and yaw angles will be slightly off, in some edge cases like those mentioned above this can cause NPCs to get stuck.
Finding the cause of this is 99% finding a reproducible case of the problem happening. The
Lambda Core
occurrence didn't always happen, but the We've Got Hostiles
one did.Once that was found it was a simple matter of using version control to pinpoint which change introduced the problem and then finding the exact line of code. Comparing against the engine's version showed the missing cast.
This bug highlights the importance of being precise when recreating existing functionality, as well as making good use of version control. Without version control finding the cause would've been a lot harder.
sv_load_all_maps command
Thesv_load_all_maps
command has been modified a bit to deal with an engine bug that causes the game to crash or shutdown partway through loading all maps.This command is mainly intended to be used to automate generation of node graphs but it can be used to gather error logs for each maps as well, or to automate testing of scripting systems using map-specific scripts if your mod has that.
A related command called
sv_stop_loading_all_maps
has been added to stop this process if necessary.
Node graphs
Node graphs are now bundled with mod installations instead of requiring them to be generated when a map is first loaded. This should make the first-time experience a lot smoother.New repositories in the TWHL Community Github organization
A few new repositories have been added:- HalfLifeSDKHistory: Contains each Half-Life 1 SDK release's source code as individual commits to allow viewing changes made in each update. There are also branches for the multiplayer version (lacks AI code) and a branch showing the difference between the singleplayer and multiplayer versions
- OldValveReleases: Contains modding files released by Valve, mostly old SDKs
- SlackillerDownloads: Contains files hosted on the old Slackiller modding website
- VHLT-V34: Contains the source code for VHLT V34 along with branches that remove disabled code paths for easier viewing. Also includes a copy of the VHLT V34 tools for completeness sake