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 1 month 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 1 month 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.
You must be logged in to post a response.