Half-Life Updated (custom SDK) Created 1 year ago2021-01-13 21:05:33 UTC by Solokiller Solokiller

Created 1 year ago2021-01-13 21:05:33 UTC by Solokiller Solokiller

Posted 4 months ago2022-05-14 16:23:06 UTC Post #346519

Progress on Half-Life Unified SDK

A fair amount of work has been done in recent weeks. These are the highlights:
  • Simplified the logging system to remove the need to create loggers in PostInitialize in some game systems
  • Added file logging with configuration support in logging.json
  • Added IGameSystem interface to help simplify how various systems are initialized and shut down
  • Bunch of code cleanup including removal of redundant forward declarations and extern keyword, removing duplicated code and more
  • Added IMPLEMENT_CUSTOM_SCHEDULES and DECLARE_COMMAND macros to Visual Studio hint file so Intellisense stops showing green squiggles under usages
  • Reworked how client commands are handled on the server side to use a map of commands. Commands can be registered and unregistered at any time, this is done for gamemode-specific commands to simplify command handling
  • Changed how weapon selection is handled to use a proper named client command (previously any weapon_* command was interpreted as a weapon selection command)
  • Added virtual destructor to CGameRules so the destructor runs properly
  • Re-implemented the spectator client command to function outside of the CTF gamemode. This command was made unavailable due to Opposing Force using an older version of the SDK as a base which didn't support spectator mode in all game modes. Opposing Force Updated does this for consistency with the original game, the Unified SDK allows the use of this mode in all game modes just like the Half-Life SDK does (even in singleplayer)
  • The hud color is now saved and restored, allowing it to persist between levels
  • Fixed some Opposing Force code sending ScoreInfo messages with incorrect contents causing a fatal error (Opposing Force doesn't send the player class and team index values because it uses a different method of team-based gameplay)
  • Reworked how the health and model values are set to allow mappers to set custom values for both. Entities now initialize these in OnCreate, if a mapper-provided value exists it will be overridden in DispatchKeyValue. All code uses pev->model now to support custom models, although some edge cases may exist
  • Removed NPC voice pitch restore hack (initial pitch value is set in OnCreate now)
  • Added global model replacement support. This feature lets you globally change references to a model to use another model instead. This does not apply to models used by the engine since those references cannot be changed
  • The PRECACHE_SOUND macro has been removed, either CBaseEntity::PrecacheSound (for entities) or UTIL_PrecacheSound (for global precaching) should be used instead, or g_engfuncs.PfnPrecacheSound if you need to precache a sound unaffected by global model replacement
  • The SET_MODEL macro has been removed, CBaseEntity::SetModel should be used instead
  • Weapons store off the world, view and player models they use to properly precache and restore these models as well as to adjust the active weapon model when changing levels (not intended for use outside of these use cases, but can be made more robust if necessary)
  • Fixed weapon_eagle saving and restoring booleans as integers
  • The player's hud color and suit light type (flashlight or nightvision) can be configured from a configuration file now as well as through an entity and the console
  • Simplified how game configurations are loaded by merging the data apply step into the parse step (more efficient, easier to use, less confusing)
The work that's been done brings us much closer to allowing one to play all 3 games without requiring either code changes or swapping out files.

I've recorded a short video that shows the Half-Life => Opposing Force => Blue Shift transition when changing maps:
The first map has this configuration file:
{
    "Sections": [
        {
            "Name": "HudColor",
            "Color": "255 160 0"
        },
        {
            "Name": "SuitLightType",
            "Type": "flashlight"
        }
    ]
}
These are the default values as well.

The second map has this:
{
    "Sections": [
        {
            "Name": "HudColor",
            "Color": "0 160 0"
        },
        {
            "Name": "SuitLightType",
            "Type": "nightvision"
        },
        {
            "Name": "GlobalModelReplacement",
            "FileName": "cfg/maps/Op4ModelReplacement.json"
        }
    ]
}
This configures the HUD color to Opposing Force green, the suit light type to night vision and it uses the Opposing Force model replacement file, which looks like this:
{
    "models/v_9mmar.mdl": "models/op4/v_9mmar.mdl",
    "models/v_9mmhandgun.mdl": "models/op4/v_9mmhandgun.mdl",
    "models/v_357.mdl": "models/op4/v_357.mdl",
    "models/v_chub.mdl": "models/op4/v_chub.mdl",
    "models/v_crossbow.mdl": "models/op4/v_crossbow.mdl",
    "models/v_crowbar.mdl": "models/op4/v_crowbar.mdl",
    "models/v_desert_eagle.mdl": "models/op4/v_desert_eagle.mdl",
    "models/v_displacer.mdl": "models/op4/v_displacer.mdl",
    "models/v_egon.mdl": "models/op4/v_egon.mdl",
    "models/v_gauss.mdl": "models/op4/v_gauss.mdl",
    "models/v_grenade.mdl": "models/op4/v_grenade.mdl",
    "models/v_hgun.mdl": "models/op4/v_hgun.mdl",
    "models/v_knife.mdl": "models/op4/v_knife.mdl",
    "models/v_m40a1.mdl": "models/op4/v_m40a1.mdl",
    "models/v_penguin.mdl": "models/op4/v_penguin.mdl",
    "models/v_pipe_wrench.mdl": "models/op4/v_pipe_wrench.mdl",
    "models/v_rpg.mdl": "models/op4/v_rpg.mdl",
    "models/v_satchel.mdl": "models/op4/v_satchel.mdl",
    "models/v_satchel_radio.mdl": "models/op4/v_satchel_radio.mdl",
    "models/v_saw.mdl": "models/op4/v_saw.mdl",
    "models/v_shock.mdl": "models/op4/v_shock.mdl",
    "models/v_shotgun.mdl": "models/op4/v_shotgun.mdl",
    "models/v_spore_launcher.mdl": "models/op4/v_spore_launcher.mdl",
    "models/v_squeak.mdl": "models/op4/v_squeak.mdl",
    "models/v_tripmine.mdl": "models/op4/v_tripmine.mdl"
}
The third map uses this:
{
    "Sections": [
        {
            "Name": "HudColor",
            "Color": "95 95 255"
        },
        {
            "Name": "SuitLightType",
            "Type": "flashlight"
        },
        {
            "Name": "GlobalModelReplacement",
            "FileName": "cfg/maps/BlueShiftModelReplacement.json"
        }
    ]
}
Same thing as Opposing Force.

Config files can be included in other config files so a single file can be used to configure entire map packs pretty easily. The server config file can also do all of this so you can use that to configure a mod's default values.

The CTF game mode is the big exception since that still uses hard-coded values. Ideally those will also be configurable at some point.
Posted 4 months ago2022-05-14 16:23:12 UTC Post #346520

Remaining work for Half-Life Unified SDK V1.0.0

  • Replacing sounds (for footstep sounds which differ in Opposing Force), requires client side support which is difficult to provide since it involves the client loading replacement map files
  • Replacing HUD sprites (for Opposing Force which uses a digital-like effect on sprites), requires client side support, could hit engine HUD sprite limit. Might need to be delayed until the UI can be reworked to no longer depend on sprites
  • Replacing the engine's music playback system with one that won't stop playing after level changes. Could be complicated to implement properly since there's no easy way to tell when the client disconnects from a server
I'm considering leaving these features for V2.0.0 so as to focus on stabilizing V1.0.0 and getting it released. V2.0.0 would then be released as soon as it's done so there might be a small amount of time in-between, it's impossible to predict.

Other work that's needed for V1.0.0:
  • Get the assets repository up and running, include all versions of the install scripts in it (add, commit, remove so it's in the history). This repo will contain all of the map, model, etc sources as well as any script code used in the game. A script or tool to copy the scripts from the assets repo to the game installation will be needed to streamline the development process (possibly a filesystem watcher that auto-copies files)
  • Integrate malortie's work into the game installation
  • Update packing script to use a timestamp-based naming scheme (PackageName-YYYY-MM-DD-Revision.zip where Revision is the N'th package that's been made) to make it easier to distribute
I've considered putting the game installation in version control but the available options are bad at storing binary data. For example HLEnhanced has 133 commits and has a size of over 1 GB. The Unified SDK's binaries are twice the size of HLEnhanced so the repository would quickly grow in size to eat up a lot of disk space. Git wasn't made for this, and you can't really bend it to work that way without using risky Git commands. And even if you do that you won't be able to pull changes if you wipe the history (Git will see it as essentially an unrelated branch).

Git LFS isn't an option either. Github's data limits for free accounts is 1 GB storage and 1 GB download bandwidth per month. This project alone would quickly use up the storage space and a single multiplayer playtest could use up that bandwidth as well.

Perforce is stated as being able to do this, but as i understand it it works pretty much like Git LFS and there is no free hosting option for any kind of version control that will host files of this size.

So instead i've opted to use a strategy similar to what i've done with the Half-Life Updated projects: package the installation and upload it on the releases page. Old dev releases will be pruned regularly, full releases will stay. It might be possible to automate this so that executing a script packages the installation and auto-uploads it to Github but i haven't looked into that yet.

I would also like to reiterate that this SDK is not ready for development use yet. Once V1.0.0 has been released i will be switching the repository's setup a bit so the master branch tracks full releases so that it always represents the latest stable build, with an unstable dev branch and feature branches that branch off from the dev branch. This will make it easier to make mods with this SDK without accidentally cloning an unstable version.

Note that because some work involves making breaking changes future updates are unlikely to be easy to merge in. It's unlikely that you'll be able to pull V2.0.0 on top of a modified V1.0.0 and expect everything to work. Unfortunately this is the difficulty in making an SDK that is available early while also solving big problems. The alternative is keeping it private or labeling it unstable the entire time which only complicates things.

I'd like to thank malortie for updating all of the models to work with this SDK. He's been doing a lot of good work and this SDK would not be complete without him.

I'd also like to thank Penguinboy for fixing a performance issue with the skill name regular expression which dramatically slowed down map loading. This fix really helped.
Posted 2 months ago2022-07-17 12:44:43 UTC Post #346728

Progress on Half-Life Unified SDK

Make sure to read the wiki for more information.

It's been a while since the last update. I've been busy with real life stuff so i haven't had much time to work on stuff, but there has been progress.

First off, i'd like to make it absolutely clear that this SDK is not ready for use yet. You shouldn't be trying to use it to make mods at this point. It also doesn't change any engine limits.

malortie has done a lot of good work updating and improving models. Related models are now consistent with each-other and are more flexible to use. He's also been improving the studiomdl compiler with important changes.

A lot of small fixes and improvements have been made to the game's code:
  • Lots of fixes and changes for work-in-progress stuff, to be expected
  • Minor code cleanup
  • delta.lst and liblist.gam are now installed to the mod directory. This means you'll have to edit these files and commit them in the source code repository. The files are closely related to the game's code, that's why they're here.
  • renamed hl library to server
  • Updated third party dependencies
  • Added .natvis config file to allow the Visual Studio debugger to show the contents of certain string_t variables like the entity's classname, netname, targetname, target. In the future i plan to change string_t to a struct to allow this to work for all instances of string_t, but i need to test that this works on all platforms
  • Enabled modernize-use-bool-literals Clang-tidy check
  • Improved game config loader to detect the use of different search paths to bypass single include detection
  • Reworked the client command registry to avoid the use of global variables. Commands that exist for the duration of the server's existence have their lifetime managed by the registry, others are managed by an object with automatic lifetime
  • Client command names are required to be lowercase and contain only alphabetic characters and _
  • Added constants for checking if a server is running in listen or dedicated mode to allow config files to check for it
  • Removed unused trigger_changelevel code (left over from Quake 1)
  • Added special targetname fired when players are activated (happens when they've fully spawned after connecting or map change)
  • OpenGL is no longer needed for linking, which simplifies Linux setup a bit
  • Changed minimum required version of CMake to 2.23
  • Github CI builds now provide artifacts containing the contents of the CMake install command to ensure that everything needed is included
  • Linux builds no longer enable DWARF debug info for all build configurations, which dramatically reduces the size of CI artifacts
  • spdlog log output now adds the short library prefix to console log output to make it clear where it's coming from (useful for code used in both client and server)
  • Added CMake option to enable developer mode (-dev command line parameter). This enables cheats, the console, sets developer to 1 and most importantly allows more console log output to be seen during startup. Most of this parameter's behavior was already provided with other options, but the early logging behavior is exclusive to this parameter
  • Reworked game title drawing to allow the use of all three games' titles. I've combined the sprites into a single HUD sprite, and the Opposing Force version uses both the Half-Life and Opposing Force sections at the same time. This greatly simplifies the logic for drawing this title, but it's still temporary since the UI needs a rewrite at some point. It will work fine for custom maps as well, but only those three titles are supported. The gametitle worldspawn keyvalue has been changed from a boolean to a string to allow selection of this title. In the future i'd like to make this flexible enough to allow for custom titles, but that's not happening any time soon.
  • Merged sentences.txt for all three games together. There are too many sentences to have them all co-exist, so i've commented out some of the scripted dialogue. I've also increased the server-only sentence group limit from 200 to 1536 to match the engine's sentence limit. Both limits will be going away with a new feature, see below.

Major changes

New music system

I've implemented a new music playback system using OpenAL. This provides the same functionality as the engine's version (minus the ability to open the CD tray) and does not stop playing on map change. It also supports Ogg files.

trigger_cdaudio and target_cdaudio have been removed, replaced by ambient_music. This entity allows you to play music for a single player or all players, allows you to loop, fade out and stop music and play music for players in a certain radius.

The existing soundtracks for each game are now copied to the mod installation and are renamed to allow them to co-exist. Existing maps are upgraded to use the new entity.

This does not replace the engine's music system. That's still there and is used to play gamestartup.mp3. Servers can also still issue commands to the original system so multiple songs could be playing at the same time. There's nothing i can do about that.

On Windows OpenAL is installed to the cl_dlls directory and located by way of delay loading. On Linux the existing OpenAL library is used, which is the version provided by the Steam runtime. Miles Sound System (used by the engine to play music) uses OpenAL so that dependency is already locked in. OpenAL is backwards compatible with a stable API so this shouldn't be a problem.

This video shows the music system in action:

Project configuration changes

Windows and Linux require the use of a toolchain file now. This is needed to enforce the use of the right compiler on Linux and to enable the use of vcpkg.

Vcpkg is a package manager used to automate the process of setting up third party dependencies. It downloads, builds and installs dependencies to enable them to be used in the project. This process occurs when you configure or generate the build files with CMake, so this slows things down a bit there. On the other hand it is no longer necessary to rebuild dependencies as part of the project which speeds things up compared to before.

Not all dependencies are acquired through vcpkg. One of them isn't available at all, another is outdated. I may contribute to those projects to get things moving on that end.

Continuous integration builds cache vcpkg artifacts, which means it doesn't have to rebuild all of them like it did before. This speeds up CI builds which is great.

Project info overlay

To help with development, bug reporting and debugging i've added an in-game overlay to show information about the project's build state:
User posted image
For Pre-Alpha and Alpha builds this is enabled by default to make it obvious that this is a development build.

More information here.

Removal of support for low resolutions

Historically Half-Life has had special support for resolutions below 640x480 in the form of smaller HUD sprites and some UI elements being smaller.

I've removed this support because it doubles the amount of sprites needed for the HUD, the results appear near identical and modern systems don't even allow a resolution that low.

Only the use of command line parameters allows the game to be forced into such a low resolution, which isn't very useful and not worth providing special support for.

The game will still work and display the UI at those resolutions but it might not perfectly fit the screen.

I'm hopeful that the UI can be rewritten altogether, which makes the use of sprites and hud.txt unnecessary but that's too much work for V1.0.0.

Changes in HalfLife.UnifiedSdk-CSharp

The packager, asset synchronizer, installer have been ported from dotnet script to become full fledged executables. They are part of this repository now.

Many improvements have been made to these tools. Ripent .ent files are no longer used to update maps, instead all changes are done exclusively through the map upgrade tool.

The packager now handles the including of additional mod directories (_addon, _hd, etc) through the configuration file to avoid hardcoding anything and allowing complete control.

Package names have the format PackageName-yyyy-MM-dd-HH-mm-ss.zip. When needed pre-alpha builds are uploaded to the main repository's releases page. As noted on the main wiki page this project uses standard terms for releases. Pre-alpha builds are not ready to be used for mod development and regular play.

A new tool has been added to upgrade maps separately from the installer, allowing the conversion of custom maps. You'll have to specify which game the map is from, it will then convert the map according to the rules for that game.

Many upgrades have been added to automate the conversion of maps that use models that malortie has updated.

The documentation for all of these tools is available on the wiki (see the sidebar): https://github.com/SamVanheer/halflife-unified-sdk/wiki

Continued in next post ==>
Posted 2 months ago2022-07-17 12:44:48 UTC Post #346729
<== Continued from previous post

Assets repository

The assets repository is up and running: https://github.com/SamVanheer/halflife-unified-sdk-assets

The AssetSynchronizer tool is used to automate the copying of files from this repository to the mod installation. This happens locally, so you'll need everything set up on your computer. To prevent accidental removal of the entire mod installation this tool does not delete files, though it does overwrite them without warning. Always make backups of everything you have.

Remaining work to be done

This is roughly the work that needs to be done now to finish V1.0.0:
  • Merge pull requests into repository (in progress)
  • Update project info overlay to use Pre-Alpha terms for dev builds (done)
  • Fix game title not showing up at the start of campaigns (requires temporary workaround since the UI code will be rewritten) (done)
  • Implement new sentence playback system (OpenAL + convert sentences.txt to JSON), add all sentences
  • Update changelog to include all changes
  • Review all changes
  • First alpha build
  • Stress test the three campaigns and fix issues that show up
  • First beta build
This is going to take some time, the sentences system will probably take up most of it. I've already got the experience needed from upgrading Quake to use OpenAL so it's mostly building a system for sentences specifically, but i can't say how much that'll take.

I will be converting sentences.txt to JSON to simplify this a bit (the file needs a different name anyway to stop the engine from trying to load it). A tool will be needed to convert the file automatically as well. Fortunately this is a straightforward task. Note that the actual sentence contents won't be converted to a complicated JSON data structure, it'll remain as a single string of text.

For future releases this is the work needed at minimum to provide full support for playing each campaign as it was originally designed:
  • Networking system to transfer data as needed (contents of sentences.json and replacement maps). I have a prototype system that sets up the connection and that syncs it with the engine's connection (player leaves -> connection terminates, etc) but it needs more work to do this stuff and there are edge cases that need covering
  • Global sound replacement (for footsteps, so it has to be client side as well)
  • Global sentence replacement (for dialogue that references the player character, mostly pre-disaster, Barney and Scientist dialogue)
  • New UI (HUD and VGUI1 code needs replacing). I need to investigate what the best option here is. VGUI2 might be useful but technically violates the Source SDK license, an HTML-based approach could be very useful if it's practical to do but i need to experiment. Moving away from HUD sprites is important since that has a bunch of limitations (sprites count as models, overall limit of 256 HUD sprites, limited palette).
  • Opposing Force HUD sprites need a version that removes the scanline effect. IIRC this affects only the weapon and night vision icons, but i haven't made a complete list. I don't know how much work is needed for this to be done, perhaps the effect is easy to reverse, perhaps not
Ideally i'd finish all of this before doing a V1.0.0 release, but the risk of feature creep setting in and V1.0.0 never releasing is too high. I also need to work on HLAM to finish a bunch of stuff there so i want to focus on that after V1.0.0 is out.

I will be releasing new betas for the three Updated projects soon once i've fixed a couple more things on that end.

See also the Half-Life Asset Manager thread for a status update about that.

I'd like to thank malortie for his continued work on the game's assets and studiomdl. Your work has been invaluable.

Thanks to everybody else that has helped out with development and testing. I really appreciate it.

Until next time.
Posted 1 month ago2022-08-06 14:01:17 UTC Post #346761

Half-Life Updated Updated betas released

Half-Life Updated, Half-Life: Opposing Force Updated and Half-Life: Blue Shift Updated betas have been released:
Half-Life Updated: https://github.com/SamVanheer/halflife-updated/releases/tag/HLU-V1.0.0-beta12
Half-Life: Opposing Force Updated: https://github.com/SamVanheer/halflife-op4-updated/releases/tag/HLOP4U-V1.0.0-beta009
Half-Life: Blue Shift Updated: https://github.com/SamVanheer/halflife-bs-updated/releases/tag/HLBSU-V1.0.0-beta009

Notable changes for all games:
  • Reset server's client FOV value so loading save games restores FOV correctly with weapon prediction disabled
  • Fixed players not being given exhaustible weapons when they get the ammo for them (e.g. giving Hand Grenade ammo now gives weapon_handgrenade)
  • Fixed weapon deploy animations and body values not working correctly in several cases
  • Cleaned up weapons code a bit (Note: some code has been moved which could break mods, make sure to double check these changes in your mod if you merge them in)
  • Updated smdlexp to use 3DS Max 2023 SDK (Note: this is a direct upgrade, there are versions of this plugin that have had more bug fixes applied. See here for an up-to-date plugin(for 3DS Max 2022))
  • Added sensible error messages to prevent this plugin from being compiled incorrectly
  • Added keyvalue allow_item_dropping to control whether NPCs can drop items. Note that level editors may not apply this keyvalue correctly to existing maps so you will need to double check NPC entities
  • env_sound effects are now restored correctly and reset to 0 when changing maps. They do not persist when going back and forth between level changes due to engine limitations
  • Added fixes from Marphy Black's Half-Life Fact Fixes
  • Added fgd files for each game to their respective code repositories
Notable changes for Opposing Force:
  • Fixed Gonome calculating gut throw direction incorrectly
  • Fixed info_ctfspawn_pickup not being called info_ctfspawn_powerup
  • Fixed human grunts being able to drop weapons in the intro map

Progress on Half-Life Unified SDK

  • smdlexp (StudioModel exporter) 3DS Max plugin is now a separate CMake project to avoid the need for special handling since it requires a third party SDK to be installed. This plugin has to be compiled as 64 bit unlike all other tools which were designed for 32 bit compilation only
  • libstdc++ is now linked statically on Linux to prevent problems when users do not have a C++20-capable version installed (Thanks a1batross)

EASTL library

I've added the EASTL library as a dependency. This is a static library maintained by Electronic Arts containing various helper classes and functions for use in games. The intended use of this library is to allow for safer and more efficient string and container usage.

For example a common task is to format a filename before opening the file. The SDK typically does this using a stack buffer which means the filename has a limited size. Modern C++ code does this using either std::string or std::filesystem::path, but both of those use dynamic memory allocation.

EASTL provides a special class called fixed_string that can be used to optimize this out. fixed_string uses a fixed size buffer to store the string, optionally allocating memory if the string is too large. Most filenames handled by this game have to abide by path size limitations from long ago: 260 characters. So using a fixed_string with that as its internal buffer size can eliminate a lot of dynamic memory allocations.

Another example is fixed_vector. It works pretty much just like fixed_string in that it has an internal buffer. For cases where most arrays have a known maximum with a few outliers this can cut down on a lot of memory allocations, like for example the words in a sentence parsed from sentences.txt.

The engine has a hard limit of 32 words, so in virtually all cases a fixed_vector with that size won't allocate additional memory, but new sentences can have more words and will allocate.

The long term goal is to use EASTL containers everywhere when it improves performance. String operations that currently use stack buffers will use fixed_string instead to eliminate string truncation problems (aka strings too large to fit in the stack buffer). You can see some compiler warnings about this here.

Uses of STL unordered containers will be replaced as needed since those are known to have worse performance than existing open source versions.

Progress on new sentences system

I've been working on the new sentences system to get that done. Sentence playback is fully functional, but time compression doesn't chop up the sound sample at the exact same boundaries as the original code and reverb and delay effects aren't implemented yet.

Implementing this system required me to implement virtually everything needed for regular sound playback as well. With the exception of looping sounds that's all working now as well, but it isn't being used because it relies on the map-specific precache calls to know which sound index maps to a filename.

Since it isn't needed for V1.0.0 i'm not planning to add support for that, but once the networking system has been implemented using this sound system for everything should be straightforward to implement.

I've also decided to leave the conversion to JSON for later. The engine ignores sentences if it reaches the limit so having an easy way to compare them both by switching back to the original code is useful for now.

Remaining work to be done

  • Merge pull requests into repository (in progress, all pull requests in Updated repos are merged)
  • Implement new sentence playback system, add all sentences (90% complete)
  • Review malortie's work and provide feedback
  • Update changelog to include all changes
  • Review all changes
  • First alpha build
  • Stress test the three campaigns and fix issues that show up
  • First beta build
Many thanks to a1batross, FreeSlave, Ronin4862 and malortie for their continued contributions to these projects. I really appreciate it.
Posted 1 week ago2022-09-17 16:35:01 UTC Post #346885

Progress on Half-Life Unified SDK

Make sure to read the wiki for more information.

There's been quite a bit of work done in the last month and a half.

SDK code changes

  • All open pull requests have been merged in
  • The new OpenAL-based sentences system has been implemented
  • Music now stops playing when disconnecting from servers, when starting a new map using the map command or when loading save games
  • Reworked the model replacement code to be more generic to allow its use for the other replacement systems. The work done also makes implementing per-entity versions of all replacement systems very easy
  • Added global sound replacement with client-side player movement sound replacement support (to replace footstep sounds)
  • Added global sentence replacement. This can replace individual sentences as well as sentence groups (to replace entire sets of responses, sets of randomly selected sentences, etc. Depends on how entities use them)
  • Updated all new code to use a consistent naming style
  • Updated new files to use better names to reflect their content more closely
  • Updated JSON library to 3.11.2
  • Updated JSON schema validator to latest commit
  • Added fmtlib as a direct dependency. fmt::format is now the way to format strings safely, std::format will not be used since it isn't available everywhere yet and will likely suffer from the same problems as other standardized APIs (can't be updated due to backward compatibility)
  • Updated EASTL to use a local port that uses the latest commit to allow it to compile when using GCC
  • Added helper commands for debugging maps, like infinite air, armor, finding entities based on classname or targetname, triggering them
  • Reworked UTIL_dtos1-4 to a single function UTIL_ToString that converts an integer value to a string without allocating memory
  • Reworked Visual Studio natvis configuration to use intrinsic functions to allow string_t values to be displayed immediately, instead of requiring manual evaluation. This allows for faster debugging
  • Added entity info hud to display the classname of the entity you're looking at as well as its health. The color of the values is determined by the entity's relationship with the player:
    • white: no relationship
    • blue: friendly
    • red: hostile
  • Talk monsters now only treat other talk monsters as potential friends to avoid monsters trying to talk to random nearby entities and crashing as a result
  • Removed obsolete Quake code used to handle the cloak powerup (doesn't exist here)
  • Renamed VModEnable client command to vmodenable adhere to new client command naming rules
  • Defined dummy vmodenable client command to silence console errors in singleplayer
  • Removed superfluous Random value from monster_otis bodystate keyvalue (was equivalent to Holstered)
  • Use proper constants for all uses of GetBodygroup and SetBodygroup
  • Reworked animation body groups for NPCs that use new submodel structure. This is to make weapon submodels more consistent across the board
  • Added new game icon to the game installation to display in the program title bar, in the task bar and in the Steam library

C# tool code changes

  • Reworked the Utilities library to reduce the number of C# objects created by merging the entity and map APIs with the provider-specific types. For any given map this reduces the number of objects created by 1/3rd
  • Added events to allow listening to entity creation, removal, keyvalue changes and keyvalue removal
  • Added diagnostics system to enable verbose logging of all changes made to a map
  • Added command line option --diagnostics-level to the Installer and MapUpgrader tools to enable diagnostics output to show what is changed in a map

Asset changes

  • Merged sentences.txt for all three games into a single one containing all unique sentences
  • Added global sound and sentence replacement files for Opposing Force and Blue Shift
  • Added source files for new game icons
  • Added more assets to PackageManifest.json to ensure game installations contain everything needed to run the game

New sentences system

The new sentences system has been fully implemented:
Although there are still a few kinks to work out it's pretty much all there.

You can also hear footstep sound replacement in Opposing Force and sentence replacement when interacting with scientists and Barneys in Blue Shift.

The new system changes some limits:
  • Maximum number of sentences: was 1536, now 65535, can be further raised by changing the network message used to send them to the client but this will increase bandwidth usage
  • Maximum number of sentence groups: was 200, now unlimited
  • Maximum number of words in a sentences: was 32, now unlimited
  • Maximum sentence name length: was 15 ASCII characters, now unlimited but warns if it exceeds 31
  • Maximum number of unique sounds: was 1024, now unlimited
  • Maximum sentence line length: was 511 characters, now unlimited
  • Maximum number of concurrent sounds of all kinds (static, dynamic, ambient): was 128, now unlimited
Sentences are now paused when the game is paused and will not be cut off.

There are console commands to play sounds to test them out. You can optionally specify volume, attenuation and pitch although attenuation isn't very useful since the sounds always play on your local player entity.

There is a cvar to toggle between the old and new sound systems, although this only works for the first 1536 sentences listed in the file.

I've also implemented sound effects using OpenAL's EFX API which is the successor to EAX. It uses almost identical parameters but since the original implementation used software mixing and fixed position 3D sound sources the results aren't identical.

Half-Life, like Quake, uses software mixing regardless of which audio API is used to actually play it. This means distance calculations are done before the audio is sent to the EAX 3D sound sources.

To avoid duplicating distance effects Half-Life has 4 3D sources placed around the player. If you imagine a box 2x2 units wide and long centered on the player, the sources are placed at the corners of the box:
Image not to scaleImage not to scale
The new sentences system lets OpenAL handle distance calculations so sound sources are handled properly by the EFX extension, so the sound effects are working properly, but sound different from the original effects.

The effects do sound correct in-game but it's always going to be different.

Regular sound playback is also fully supported, the only thing preventing its full use is that the sound precache list can't yet be sent to the client to map sound indices back to filenames.

Improved natvis debug configuration

When viewing an entity in the Visual Studio debugger you can now see certain string values directly:
User posted image
In the future i'd like to turn string_t into a strong type (as opposed to a typedef which is treated as its underlying type) to allow this to work for all of them, but i need to make sure this doesn't cause problems before i can do that.

Entity info

This feature was added for debugging purposes, as well as to show how to implement this kind of feature.
User posted image
More information can be found here: https://github.com/SamVanheer/halflife-unified-sdk/wiki/Hud-Entity-Info

New game icon

The new icon is the default Half-Life icon, modified to include the base colors from all three games (shown enlarged here):
User posted image
In the Steam library:
User posted image

Diagnostics output in Installer

Here's an example of the diagnostics output from the Installer:
User posted image
Because there is an upgrade that alters the angles of every entity there is an additional diagnostics level that filters those changes out. Otherwise the amount of log output would dramatically increase.

Continued in next post ==>
Posted 1 week ago2022-09-17 16:35:37 UTC Post #346886
<== Continued from previous post

New UI: preliminary research

I've been looking into RmlUi a bit more. There has been work done recently to refactor its render backend which would make it easier to integrate in a Half-Life mod.

I see two possible implementations: The second option is probably more efficient but means dropping Software mode support. To prevent users from reporting this as a bug i'd have to add a forced quit command when the engine is started in Software mode (IsHardware() returns 0).

The best of both worlds is to use OpenGL when the engine is loaded in OpenGL mode and the VGUI1 workaround in all other modes (D3D mode returns 2, though it obviously won't ever do that now since it was removed).

This work is planned for RmlUi 5.0 (currently at 4.4) with no ETA so i don't expect to be doing this any time soon.

In the meantime i can make a standalone test program to see how feasible it is to make a HUD with it. That's a quick way to determine if the library is an option here at all.

I'm not planning to add a new UI in V1.0.0 so it's not a big deal if it takes time. I've given them some feedback on CMake modernization they want to do to help them along.

I've also looked into how VGUI1 and VGUI2 handle TGA loading. Both use the same backend that boils down to glGenTextures and glTexImage2D calls, it doesn't pass through the engine's texture loading routines which handle loading, filtering, resampling and rescaling.

VGUI1 supports very large textures (134,217,727 RGBA32 pixels max) but doesn't free the main RAM buffer. VGUI2 limits textures to 256 x 256 pixels but doesn't keep a buffer allocated.

All backends support 24 and 32 bit uncompressed TGA with no custom origin coordinates (only game.tga and game_big.tga use a non-default origin, and game_big.tga can probably be changed since it's used by Steam and not the game), so sticking to that format will work regardless of which option we use.

This means we'll need a tool to take the sprites and convert them to TGA. For animated sprites we'll need a framework-specific solution: RmUi has sprite sheets (single large texture divided into rectangles for each frame) but VGUI1 and 2 don't have a built-in feature so that'll require splitting frames into separate textures either at the file level (filename0.tga, filename1.tga, etc) or at file load time.

Either way a separate file is needed to specify animation frames. It is possible to just use sprites here if we handle loading ourselves but i'd like to get away from the limitations of the sprite format (256 colors for all frames combined, variable framerate sprite frames which aren't supported by the engine anyway, etc).

Some other container format could work, even Source vtf might work here but i'd prefer to keep things simple and RmlUi has its way of specifying sprites already.

Only once a decision has been made on where to take the UI can i figure out how to deal with the Opposing Force image replacement problem. This depends on the UI framework since the manner in which images are referenced differs between them.

Regardless, the actual directory structure will likely be:
  • mod directory
    • gfx
      • ui
        • op4
The default UI will go in the ui directory, with Opposing Force-specific UI images going in a subdirectory, matching the structure used for other file replacements already in use.

The choice of framework will also influence how other UI-related issues will be handled, so there isn't much to gain from discussing that now.

Remaining work to be done

  • Merge pull requests into repository (done)
  • Implement new sentence playback system, add all sentences (done)
  • Review malortie's work and provide feedback (done)
  • Global sound replacement (done)
  • Global sentence replacement (done)
  • Rework the client command registry to eliminate use of shared pointers
  • Rework game configuration system to no longer rely on std::any to harden the API against incorrect use
  • Update Packager tool to provide list of files not included in the package to spot missing files more easily
  • Update changelog to include all changes
  • Write documentation for all new features (partially complete)
  • Investigate making the wiki accessible for pull requests to allow direct modification or make the wiki part of the repository Vcpkg does this, albeit for their website)
  • Review all changes
  • First alpha build
  • Stress test the three campaigns and fix issues that show up
  • First beta build
Work expected to be needed in the future (in no particular order):
  • Networking system (transfer contents of replacement files, precache lists, possibly other immutable data): work in progress
  • New UI (including HUD image replacement for Opposing Force): being researched
  • Versions of Opposing Force-only HUD images that have the scanline effect removed: some preliminary research done, needs more investigation
  • A way to start all three campaigns from the main menu. Probably the same solution as used in Condition Zero Deleted Scenes (menu button that starts a map that opens an SDK-level menu that enables campaign and training selection). Depends on the new UI
  • Unknown unknowns
There has also been more work done on the Updated projects with bug fixes and improvements which i'll list when i release the next set of beta builds. I need to investigate a couple more things before i can do that.

Many thanks to a1batross, hammermaps, Shepard, BryanHaley, Ronin4862 and malortie for helping to get this project much closer to its first release. I couldn't have done this without you.
You must be logged in to post a response.