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

Created 3 years ago2021-01-13 21:05:33 UTC by Solokiller Solokiller

Posted 2 years ago2021-10-21 12:49:45 UTC Post #345987
Yeah but they haven't been active for a while.
Posted 2 years ago2021-11-14 18:52:17 UTC Post #346059
I've been working to add a few new systems to the Unified SDK to make modding easier to do through configuration files instead of relying on hard-coded settings so much.

Here are most of them in action:
User posted image
These are all of the systems i've added, though some are not entirely finished:

String pool

This replaces the engine's ALLOC_STRING engine function, and changes behavior to allocate memory once per string, so calling it multiple times with the same string doesn't allocate more memory. Very efficient, this change also frees up a little memory in the engine's available memory pool.

It also no longer performs escape character parsing which required game_text to be changed to perform this parsing by itself. This behavior was inconsistent and could cause difficult to debug problems otherwise.

Better support for writing code that works on both client and server

The server's engine functions interface now has better support on the client which makes it easier to write code that works on both sides.

This also includes helper functions like Con_Printf which will unconditionally print to the console, and supports all of printf's format options (the engine's version is limited to C89 printf options).

Access to the engine's filesystem

The engine has a filesystem interface used to load files from game and mod directories. I've provided access to it, as well as a couple helper functions to easily load files without the risk of leaking memory.

You can use this to load files from the mod directory only if needed, for example server configuration files should never load from other directories to prevent custom and downloaded content from overriding it. Conversely you can also load files from all of those directories if needed, such as map configuration files.

Support for creating console variables and commands using unified syntax on client and server

The server requires you to create cvars whereas the client has the engine create them for you; i've created an abstraction that does this for you. This abstraction also prepends an sv_ or cl_ prefix automatically so you can have the same variables and commands on both sides.

You can set variables created this way using the new command line syntax :command_name command_value or :(sv_|cl_)command_name command_value.
If specified without the prefix it will apply to both the server and client versions. This also works properly for server variables which the engine will not initialize from the command line if you launch a listen server manually through the main menu.

Command functions can also be object methods by using a lambda to wrap it:
g_ConCommands.CreateCommand("my_command", [this](const auto& args) { MyCommandHandler(args); });

void MyClass::MyCommandHandler(const CCommandArgs& args)
{
    Con_Printf("%d arguments:\n", args.Count());

    for (int i = 0; i < args.Count(); ++i)
    {
        Con_Printf("d\n", args.Argument(i)));
    }
}
CCommandArgs is a thin wrapper around engine functions that makes it easier to work with commands by indicating which functions are available in all libraries.

Improved logging

I've added the spdlog library and set up the functionality to create loggers for subsystems. This allows you to log output with more control over how much is visible and what kind of output it is. As you can see in the screenshot above you can easily distinguish which system is logging something, and what kind of information it is.

This system loads settings from a configuration file. You can specify default logger settings so you can enable more debug output for all loggers, or even disable them all. You can also configure each logger individually.

There are console commands to list all of the loggers that exist, as well as to manually change the log level at runtime.

Angelscript-based scripting functionality

Bare bones Angelscript support has been added. The creation of script engines, contexts and modules is provided with error reporting for failure, as well as engine message logging, exception logging and proper handling for C++ exceptions including problematic behavior regarding longjmp (essentially C's version of exceptions), which could put the game engine or the script engine in an invalid state otherwise (note that longjmp does not seem to be caught by catch-all statements in VS2019, this used to happen in VS2012 but fail-safe logic should prevent the problem from occurring).

There is currently no scripting support for plugins and map scripts, but it's something i'd like to add if there's interest.

JSON-based configuration files

I've added support for loading JSON configuration files and parsing them. Error handling is done for you so if there's invalid JSON it'll be reported automatically.

I've also added JSON Schema-based extended error reporting for debugging purposes. This provides additional information when needed to indicate which part of the given JSON is invalid. It's only enabled with a debug cvar since it adds a lot of overhead.

Here's an example of the errors it will log (given an array instead of an object):
[startup] [error] Error validating JSON "/Defaults" with value "[{"LogLevel":"trace"}]": unexpected instance type
The JSON schemas can also be written to a file and used as input to tools that can generate JSON editors. This makes it easier to edit JSON and shows what kind of options you have.

I've also allowed the use of comments in JSON. This is a non-standard extension to the format, but is supported in most JSON libraries and the benefits are too good to ignore.

Game configuration files

Building on JSON support, there is a system for loading game configuration files. These are files that contain configuration data that needs to be applied every time a new map is loaded. This replaces server.cfg, listenserver.cfg and map change cfg files, which are mostly handled by the engine.

Additionally maps can have a config file as well. A file called cfg/maps/<mapname>.json will be loaded if the map with that name is started.

Here's an example of such a file used to configure the server for a new map:
{
    "Includes": [
        "cfg/shared.json"
    ],
    "Sections": [
        {
            "Name": "Echo",
            "Message": "Hello World!"
        },
        {
            //Commands to configure multiplayer server
            "Name": "Commands",
            "Condition": "Multiplayer",
            "Commands": [
                "echo Hello World from command!",
                // disable autoaim
                "sv_aim 0",
                // player bounding boxes (collisions, not clipping)
                "sv_clienttrace 3.5",
                // disable clients' ability to pause the server
                "pausable 0",
                // maximum client movement speed
                "sv_maxspeed 270",
                // load ban files"
                "exec listip.cfg",
                "exec banned.cfg"
            ]
        }
    ]
}
The Includes value is a list of files to include before the current one, and makes sharing settings between servers and maps very easy. You could for instance make a map series where each map includes a file that contains the shared configuration before changing some for specific maps.

Here are the contents of the included file:
{
    "Sections": [
        {
            "Name": "Echo",
            "Message": "Hello World from shared.json!"
        }
    ]
}
The Sections value is a list of section objects that apply to the game. Each section can have a condition associated with it evaluated at load time to determine whether the section should be used or not.

This condition is evaluated using Angelscript by wrapping it in a function:
bool Evaluate()
{
    return condition;
}
To prevent abuse this evaluation will time out after 1 second, so the server won't lock up due to some clever infinite loop trick.

There are currently only two conditions to check: Singleplayer and Multiplayer. I plan to expand on this with gamemode detection (deathmatch, coop, teamplay, etc) as well as checking the map name and the value of cvars.

The Echo section simply prints the message to the console, useful for debugging to see if your file is getting loaded properly.

The Commands section provides the same functionality as the cfg files this system replaces. It lets you provide a list of console commands to execute.
For security purposes map config files are checked against a whitelist to limit the commands that can be executed. This prevents maps from doing things like changing the RCON password or the listen server host's name.

This whitelist is loaded from another JSON file:
[
    "sv_gravity"
]
So server operators can manage this whitelist themselves if needed.

Though the configuration files for servers, maps and map changes are currently identical they are actually defined separately. Some will get sections exclusive to one or two of them in which case trying to use them in a format that doesn't have them will cause an error to be logged the console, but otherwise it will continue loading the file.
With this stuff implemented i can get to work implementing skill.json functionality and its map-specific equivalent. There are also a few changes needed to support things like Xen aliens fighting with Race X aliens (they're treated as allies by the game's code). Black ops have the same problem when it comes to fighting human military types (also allies).

I've also been updating the other SDKs to include bug fixes and improvements. There are some mistakes i made in Opposing Force that should be merged into any other projects that use that code.

There isn't much more work to do before a first release can happen. Since this is a lot of work i'll be doing an alpha release first to get some feedback, then at least one beta before a full release can be done.

That's all for now, feedback and suggestions are always welcome.
Posted 2 years ago2021-11-28 20:14:56 UTC Post #346079
@Solokiller

In regards to scripting, and assuming scripting allows for creating custom monsters and entities, I believe this could definitely be a plus.

For example, Garry's mod provides a Lua API which allows clients to override the game's default behavior. This mainly has the following advantages for clients:
  • Hide internal game code complexity
  • Reuse custom entities in multiple projects (No need to recompile)
  • Easier way to manage modularity (Depends on script language used)
  • Abstraction over game update (No need to recompile or merge changes in code base)
  • Write minimal code
In addition, this would probably encourage more people to contribute to a common SDK rather than maintaining a fork separately.

On developer side, the following must be taken in consideration:
  • Maintenance of script library (Additional work)
  • Ensure scripted language updates do not break client scripts (Unit tests)
  • Require to manage a wiki for clients and update documentation
Posted 2 years ago2021-11-29 12:45:42 UTC Post #346080
In regards to scripting, and assuming scripting allows for creating custom monsters and entities, I believe this could definitely be a plus.
Yeah that's certainly a possibility. I implemented custom entity/NPC/weapon support in Sven Co-op using Angelscript before.

I worked out some of the details for a scripting system last week. Since this is derived from Sven Co-op's scripting system (aka "previous system") i'll be comparing it to that. Note that this is all conceptual, i haven't written any code for this yet so it could change if it's not feasible.

Plugins and map scripts are virtually identical, unlike the previous system (somebody should update that page though, custom entities have been allowed in plugins for a long time now). The only difference is how long scripts stay loaded for.
Plugins normally get loaded on server startup and stay loaded until the server shuts down, unless the scripts are explicitly unloaded or reloaded.

Map scripts are loaded when a map references them, and are unloaded if the next map does not reference it. Some option to keep a script loaded regardless by extending its lifetime is required so you can have for example a script that runs in the background of every map, like a stat tracker or something.

The simplest way to do this is to use the configuration file system to list a script for use in multiple maps, or every map by listing it in the server config file. Then it'd just be a plugin loaded as a map script, with the option to conditionally include it using the Condition key.

One of the problems that popped up was that multiple scripts would be written to be the main script, with initialization code in the automatically called functions MapInit, MapActivate, MapStart and PluginInit. So if you then included multiple scripts those functions would conflict with each-other.

To solve this problem each script listed in the config file, and each script referenced by trigger_script would be loaded into its own Angelscript module. A module is basically a C++ library in terms of scope, so these API functions wouldn't conflict unless you mark them as shared.

In the previous system shared entities weren't allowed because it could interfere with the reloading of plugins. If you have a script that defines something as shared, include it in 2 or more plugins, change the shared code and then reload one of the plugins it'll fail to load because the shared code is now different.

I'd flip this behavior on its head now. Allow shared stuff, even between plugins and map scripts, but disallow making API functions shared to prevent one script from monopolizing them.

This approach makes it much easier to design things like AFB, which is a plugin manager written in Angelscript. To work around the lack of shared entities you have to add your script to a function to initialize the system: https://github.com/Zode/AFBase/blob/acd7ba7e1248538d9b660638915dc91a7da59deb/scripts/plugins/AFBaseExpansions.as

With shared entities each plugin can be its own module, referencing a shared Plugin class. Plugins then need only register their plugin class, which the plugin manager can query from the shared code to manage each plugin instance.

Such registration can be automated to this point:
AFBRegister register(@MyAFBPluginClass());
The AFBRegister class registers the plugin in its constructor and unregisters it in its destructor, thus tying the plugin lifetime to that of its containing module. You won't even need to write a PluginInit function anymore. AFBRegister would be a shared class.

The API functions should also be improved, there are too many of them. Each module should get exactly 2 of them: an init and shutdown function. Everything else should be event-driven:
void ScriptInit()
{
    //Called when the script is first loaded.
    //Subscribe to the MapInit event. All events define a unique event type associated with it, even if they don't have any data or methods.
    Events.GetEvent<MapInitEvent>().Subscribe(@MapInit);
}

void ScriptShutdown()
{
    //Called when the script is about to be discarded/unloaded.
    //Don't need to manually free event handlers because they'll be removed automatically, but it can be done manually like this.
    Events.RemoveAllEventHandlersFromCallingModule();
}

//All event handlers follow the same structure: void return type, one parameter taking the event by handle.
void MapInit(MapInitEvent@ event)
{
    //Called when the map is starting for any reason, map scripts could be in the process of being loaded right now, so inter-module communication isn't advised at this time.

    //Equivalent to Source's logic_auto outputs: https://developer.valvesoftware.com/wiki/Logic_auto
    switch (event.InitType)
    {
    case MapInitType::NewGame:
        //The map is being loaded for the first time, like when the map or changelevel console commands are used.
        break;
    case MapInitType::LoadGame:
        //The map is being loaded from a save game, which means the player is loading a save game or a map is being returned to through a trigger_changelevel.
        break;
    case MapInitType::NewRound:
        //For game modes that use round-based gameplay, a new round is starting.
        break;

    //More types if needed.
    }
}
The event system replaces hooks and allows for compile-time compatibility checking of events. The previous system had to rely on variable parameters because hooks could have any number of parameters, so you could technically pass in an integer into a function that's expecting a function handle. You'd get an error at runtime, so it's not as obvious that you've made a mistake.

On the C++ side you'd publish events like this:
Events.GetEvent<MapInitEvent>().Publish(MapInitType::NewGame);
This would then internally create the event object:
//Curiously Recurring Template Pattern-based base class
template<typename TEvent>
class Event
{
public:
    //Reference counting code omitted for brevity.

    template<typename... Args>
    void Publish(Args&&... args)
    {
        //Event is created with reference count 1, ownership transferred to smart pointer.
        //Event constructor is invoked with template parameters.
        as::SmartPtr event{new TEvent{std::forward<Args>(args)...}};

        //Event handlers are tracked by the Events global and will invoke all handlers.
        Events.PublishEvent(event.Get());

        //Smart pointer releases event, usually destroys it if no script holds on to it.
    }
};

class EventSystem
{
public:
    template<typename TEvent>
    void PublishEvent(TEvent* event)
    {
        //Probably a std::unordered_map<std::reference_wrapper<type_info>, as::SmartPtr<asITypeInfo>>.
        asITypeInfo* type = GetScriptTypeFromCppType<TEvent>();

        if (!type)
        {
            return;
        }

        auto context = ...;

        //Finds or creates the list of handlers for this event type.
        const std::vector<as::SmartPtr<asIScriptFunction>>& handlers = GetEventHandlersForType(type);

        for (const auto& function : handlers)
        {
            //Context setup and error handling omitted for brevity.
            context->SetArgObject(0, event);
            context->Execute();
        }
    }
};
Custom entities require a fair bit of work to support. You need to expose the class you want custom entities to inherit from, expose the API to call base class implementations (e.g. calling CBaseMonster::Killed from your NPC's Killed method) and you need to write a wrapper that forwards calls to the script for any virtual functions it has.

The C++ side also needs to support custom entity creation by implementing the custom function. I haven't quite figured out how to save and load them since the save game system doesn't use custom. I could hack it by saving custom entities to have the custom class, and then saving the actual classname separately. That solves the problem, but there is still the issue of scripts changing the custom entity implementation.

One map could have a script A.as that defines a custom entity foo, and the next map could have a script B.as that also defines a custom entity foo. When such an entity is transitioned between maps its composition can change dramatically, including changing base classes.

Custom weapons could be restored as an NPC for example, and the pointer to the weapon would now be invalid since CBasePlayerWeapon* isn't compatible with CBaseMonster*. There are no safeguards in the save game system against this and it would take some doing to support it, so the initial version of the scripting system wouldn't be able to support it.

Custom entity support thus needs to be disabled in singleplayer with an error message in the console if you try to register them anyway (since saving the game and loading it would make it disappear).

I'll work this out more once i've completed work on the first version of the unified SDK. There's still a lot of work left to be done in all of the existing repositories to clean things up.
Posted 2 years ago2021-11-29 12:58:16 UTC Post #346081
Regarding the work being done on Half-Life Updated at the moment: i'd like to thank malortie for helping to clean things up and fix bugs, it's really helping to make the SDK better.

I've completely eliminated the use of Windows headers in game code now, only 2 files still use it: inputw32.cpp (for raw input and mouse threading, which i'd like to convert to std::thread and related types) and interface.cpp (for loading dlls at runtime).

This has cut down on compile time some more. I've also reworked a ton of code to properly convert between bool and other types which should make it easier to tell when something's a true/false value or not.

I've switched the C++ language version from C++14 to C++17 which provides some useful additions like inline global variables.

I've enabled clang-tidy as part of the code analysis feature in Visual Studio, so you'll get more warnings now. A fair number of warnings are being shown because of the SDK's tendency to include headers only in source files so there are false positives, i'm going to try to fix those as much as i can.

Clang-tidy is configured through a configuration file in the root of the repository, i'm going to systematically enable more of those as i work through the remaining warnings.

I've also added a clang-format configuration file to the root of the repository which Visual Studio uses to format files. This ensures that formatting files is done consistently rather than depending on individual developers' text editor settings, but i'm still working out the kinks in the settings. The issue for this change provides more information on how it works, and how to mass-format all files: https://github.com/SamVanheer/halflife-updated/issues/84

I've been doing lots of code cleanup as well, removing duplicate forward declarations, using inline to avoid the need to declare globals as extern separately and otherwise improving the quality of the code.

The long-term goal is to have 0 warnings at the highest warning settings with as many clang-tidy warnings enabled as possible to enforce stricter and more correct code.

Note that due to recent changes existing save games will not work with newer updated builds. If you update your fork to include these changes, or if you use the next pre-built libraries you'll need to delete the save games to prevent problems from cropping up.
Posted 2 years ago2021-12-01 16:53:01 UTC Post #346091
I've got a question for anybody using Half-Life Updated: does anybody still use the Visual Studio 2017 project files?

The system requirements for Visual Studio 2019 are almost identical to that of 2017, mainly differing in the minimum version of Windows 10 required and the recommended amount of RAM:
https://docs.microsoft.com/en-us/visualstudio/releases/2017/vs2017-system-requirements-vs
https://docs.microsoft.com/en-us/visualstudio/releases/2019/system-requirements

VS 2019 is also more flexible in how much disk space is required due to its different approach to installing it, but that's about it.

If nobody has need for it then i'll remove the 2017 project files. This will simplify development a bit and allows certain newer features to be used (like C++20).

The VS 2019 project files should work out of the box with VS 2022 (it will upgrade the files on first open), so there is no need to maintain a separate set of files for now.

In the long run once the Half-Life Unified SDK has been released it might be easier to use that as a base instead since it will encompass Half-Life Updated, Half-Life Opposing Force: Updated and Half-Life: Blue Shift Updated. At that point i'd prefer to archive the older repositories to focus on developing that version of the SDK instead.

It uses CMake so there is no problem with supporting different versions of Visual Studio, although this does require users to learn to use CMake. I can cover the basics in a tutorial which should get people going, but it does add an additional barrier to new modders.

On the flip side it does automate things that have to be done manually, like setting up the copying of game libraries to the mod directory so there are benefits to using it.

On that note: to use the CMake version of Half-Life Updated you currently have to build the INSTALL target to deploy the libraries, which might be a bit cumbersome and annoying. Visual Studio won't build this target if you try to run a project that needs to be rebuilt and instead launches an older version.

I can change this to instead deploy them when building the projects themselves, if this is something that's considered preferable i'll make it do that.

Some people have asked to make certain new features in the Unified SDK optional, like Angelscript for example. I've been pondering how feasible this is and i think i can make it work, although certain features that depend on such features will not work as well if it's disabled (e.g. conditional cfg files wouldn't work).

I'd like to get people's opinions on the matter before i make any decisions.
Posted 2 years ago2021-12-01 18:52:39 UTC Post #346092
@Solokiller

Personally, I've already removed VS17 projects from my Spirinity fork. I've got about 4 friends using my repo and they are all working on VS19, and I'm working on VS22 preview.

I'm not that sure about the removal/replacement of v141_xp tools but VS17 project files are probably lying there, unused.

About the CMake, using it could maybe add an additional barrier, but it could also encourage people to learn using CMake, so they could use this "skill" in other projects, too. Apart from that; it would also help to maintain cross-platforming and save from adding new files and build settings into particular projects one by one. So I'd personally side with CMake.

Lastly, making features optional generally give good results bacause some people want lightweight mod without the new asthethisc and concepts. So I'd say It'd be neat to give it a try.
FranticDreamer FranticDreamerR.I.P. Benny Harvey. Miss you big man. Gone but not forgotten.
Posted 2 years ago2021-12-01 19:29:43 UTC Post #346093
I stopped using the VS2017 project files last year. I haven't seen anybody use them lately.
On that note: to use the CMake version of Half-Life Updated you currently have to build the INSTALL target to deploy the libraries, which might be a bit cumbersome and annoying.
Not a problem for me, though I imagine it'd be a bit confusing/frustrating to beginners.
Admer456 Admer456If it ain't broken, don't fox it!
Posted 2 years ago2021-12-01 21:22:30 UTC Post #346094
For me, personally, the most important thing is to have something that's as close to the original, unmodified Half-Life SDK code as possible, while still being usable with VS 2019 or later. Whether that be through a VS 2019 project file or CMake doesn't really matter to me.
Dr. Orange Dr. OrangeSource good.
Posted 2 years ago2021-12-02 06:32:45 UTC Post #346097
I also only use vs2019+
The vs2017 can be removed.

Thanks Solo, you are doing a great job.
Posted 2 years ago2021-12-04 20:33:23 UTC Post #346105
The project changes have been discussed in a few places the past few days, you can see some of these discussions here:
https://knockout.chat/thread/30908/1#post-1091521 (next page has the replies)

More discussions also took place on the TWHL and Half-Life Creations Discord servers.

The feedback has universally shown that nobody uses the VS 2017 projects anymore, so i'm going to remove those from all repositories.

Once the Unified SDK has been released i'm going to archive Half-Life Updated, Half-Life Opposing Force: Updated, Half-Life: Blue Shift Updated and Half-Life Updated CMake.

Projects made using these repositories will still work as before and will still be able to pull all changes made. Archiving a repository makes it read-only and adds a banner informing visitors that's it's been archived. No new issues or pull requests can be made and you will no longer be able comment on anything.

The Unified SDK provides all of the functionality that these projects have all in one SDK with a better workflow. It also solves some common tasks like changing HUD colors (easily done programmatically and through map entities, and will also be possible through configuration files and scripting) and integrating Opposing Force weapons and NPCs so there is no reason to continue using the other projects.

It does require knowledge of CMake but that's not a terribly difficult thing to learn. The project uses modern CMake so it's not an overly complicated thing to learn and use, and most of the time you're only going to be adding new headers and source files which is trivially easy to do.

Existing Github issues will be transferred to the Unified SDK repository to continue work on them there.

The first order of business now is merging all changes into the other repositories and fixing any issues that crop up. Once that's done i can get the Unified SDK to a releasable state. A final release of all of the Updated projects will be done to ensure that changes made to configuration files are available for use, and then the repositories will be archived and will direct users to the Unified SDK repository instead through the description. Further development will be done with that repository the same way it's been done before.

After that's all done i'd like to merge as many of the improvements i made to Enhanced Half-Life into this project as well, as well as the improved weapon class management from the better weapons repository (which will also be archived and eventually removed). I'm also going to review the changes i made to HLEnhanced to see what i can merge from that.

I'm also going to look at integrating an improved version of Condition Zero: Deleted Scenes' trigger_sequence entity. If Angelscript by itself is not good enough to manage such scripting functionality then providing a means of doing so through both entity and scripting means would be useful. It is likely that scripting will be sufficient given how the entity is implemented: https://github.com/SamVanheer/czeror-sdk/blob/1e732141e5823fa69596de388a269c1ba34a33b7/dlls/CTriggerSequence.cpp#L270-L371

This will allow the archiving of the Deleted Scenes SDK which only contains this entity and nothing else from Deleted Scenes. A full Deleted Scenes SDK would take a fair bit of work and i'm not so sure about making that. I'd prefer to add it to the Unified SDK instead as an optional component to make it easier to work with, but that's something i'm going to wait to decide on until after work on Half-Life campaign support is complete.

All in all, this will see the merging of these projects into a single project:
  • Half-Life Updated
  • Half-Life: Opposing Force Updated
  • Half-Life: Blue Shift Updated
  • Half-Life Updated CMake
  • HLEnhanced
  • Enhanced Half-Life
  • Half-Life Better Weapons
  • Condition Zero: Deleted Scenes SDK
After this point the goal will be to continue fixing compiler warnings, enabling and fixing clang-tidy warnings, cleaning up code, fixing bugs and improving SDK functionality.

I would like to ask that all contributors hold off on making more pull requests for now until i can get this all sorted out. I'm not certain how long it will take to complete the remaining work, but hopefully it should be done in a few weeks time at the most.

I've made the Half-Life Unified SDK repository visible. If needed pull requests can be made on that repository instead.

Note that this is a work in progress project, i haven't yet had the chance to review the requirements for a clean git clone and CMake setup. While everything should work fine there may be problems i'm not aware of right now. Once the work on the to-be-archived repositories is complete i can focus on finishing the first release of this project.

That's all for now, i'd like to thank everybody that gave feedback and to those contributing to development. Hopefully we can get a first version of the Unified SDK released before the end of the year. I'm very interested to hear what people have to say about it.
Posted 2 years ago2021-12-25 19:26:20 UTC Post #346160

Progress update

The VS 2017 project files have been removed from all repositories.

I've fixed a few more bugs that slipped in during some of the overhauls. One of the biggest is a change to the Vector type that changed how the GCC compiler optimized passing vectors by value. This change broke compatibility with the particle manager library, which ships as part of the game.

To fix the issue i've re-implemented the library in the client library. I've also fixed a couple bugs in it, such as memory leaks and a use-after-free issue. Because it's now implemented in the client it is no longer possible for players to cheat by deleting the particleman library.

All changes have been merged into the following repositories:
  • Half-Life: Opposing Force Updated
  • Half-Life: Blue Shift Updated
  • Condition Zero Deleted Scenes SDK
The Deleted Scenes SDK also received an implementation of the material system used by that game. Nothing is actually using the material system, but the implementation is now available for use if anybody wants it. It's unlikely that it will work without further modifications. I plan to implement a new material system in the Unified SDK at some point that will provide this functionality in a better way.

This system was partially implemented already (i needed parts of it for something years back), so i've finished it to get the work out of the way.

I've also fixed a mistake i made in the DS SDK where CTriggerChangeKeyValue didn't increment a variable used to keep track of how many keyvalues had been initialized already.

The DS SDK will be archived along with the others when the Unified SDK is set to become the new default SDK for use.

I forgot about the halflife-fog repository, which will also be integrated into the Unified SDK. It implements OpenGL-based fog effects. Deleted Scenes also has fog so whichever implementation of those two and any alternates provided by the community is best will be used.

Most of the changes made to Half-Life Updated have been merged into Half-Life Updated CMake. A few changes remain, then i can focus on merging the changes into the Unified SDK.

I'd also like to thank suXinjke, vasiavasiavasia95, malortie and Shepard for helping to get everything ready.

Discord channel

The TWHL server channel #sharplife has been renamed to #unified-sdk. It serves as a channel to discuss anything related to Half-Life Updated, Half-Life Unified SDK and Half-Life Asset Manager.

Status of SharpLife

Several people have asked about SharpLife, what its status is.

This project is on indefinite hold since its scope is much, much bigger than anything else i'm working on right now.

Whereas these SDKs are about improving game code, re-implementing some engine functionality and improving the quality of the code, SharpLife is about making a whole new engine. Such an endeavor is much more difficult and requires more time and experience to accomplish.

At this time i'd like to focus on improving these SDKs and finishing Half-Life Asset Manager. Perhaps after that i might work on SharpLife again, or attempt a C++-based version of the concept, but that's not something i'd like to decide right now. It's likely that this won't even be possible for several years given the amount of work that's left to be done for current projects.

The goal behind using C# was to make it easier to use for modders with little (C++) programming experience, but if an Angelscript-based scripting system can be used to handle game code (entities et al) then this isn't really necessary. The performance-critical parts can be implemented in C++ and the rest in Angelscript, or C# if such a combination is feasible.

The two languages are fairly similar to one another so it will likely come down to how easy they are to use in such a situation. That's not to say that i've done any research on the feasibility of using either, it's nothing more than an idea at this time. Perhaps with the right abstractions the language used can be swapped out much like Source's scripting system supports multiple implementations, but that would require a fair amount of work either way.

I'd advise against getting hyped up for any of this stuff since it's years away from even starting development, assuming such a thing will ever be done at all.

Immediate future of Unified SDK

As i said in the previous post, once work on the now-obsolete repositories is done the Unified SDK will get some cleanup work done. There are a lot of things i'd like to do but i don't want to make any promises before i know what's actually possible (both technically and legally). There is a list of planned upgrades on the repository you can check to see what's going to be done sooner or later: https://github.com/SamVanheer/halflife-unified-sdk/projects/3

Most planned upgrades concern improving boilerplate code that involve supporting multiple games within a single codebase. The goal is to allow you to play any Half-Life 1 PC game's campaign through the Unified SDK without having to make code changes. To make this work, some features like global model replacement are needed. Those features in turn need models to support this, namely viewmodels for each game's hand models. I haven't had time to check for the existence of such models though i have seen some used.

If anybody knows of viewmodels for the Opposing Force-exclusive weapons that use HEV and security guard hands, that would be a big help. Ideally both low definition and high definition versions should be used for consistency with the HD models setting, but i'll take what i can get.

It's important to remember that such models must be available under a license that allows redistribution with mods. This is to avoid scenarios where mods based on the Unified SDK suddenly need to remove files due to a copyright claim.

Right now i need to do a lot of merging of code into the Unified SDK, so it'll be some time before everything is synchronized. Once it's done i'll make another post to announce the archiving of all obsolete repositories. All remaining open issues will be moved to the Unified SDK repository at that time.

That should be just about everything for now.
Posted 2 years ago2022-01-11 19:17:53 UTC Post #346194

Progress update for 11/01/2022

All changes have been merged into Half-Life Updated CMake and the Unified SDK, and all problems preventing compilation on Linux have been resolved.

Shepard has set up Continuous Integration to automatically build the SDK on Windows and Linux. This is currently used only to automatically determine if the SDK successfully builds on both platforms, but in the future it could be used to automatically provide the latest versions of both the client and server libraries on both platforms.

You can see the CI builds in action here: https://github.com/SamVanheer/halflife-unified-sdk/actions

A badge has been added to the readme to show if builds are succeeding or failing.

All pending pull requests have been merged in on all repositories and all issues have either been resolved, transferred to the Unified SDK repository or closed with the sole exception of an issue tracking a problem with the Half-Life Updated game package which i'll be putting up soon.

I've rewritten the scripts used to create those game packages as well as the game install scripts to use PowerShell instead of batch scripts. PoiwerShell syntax is easier to work with, common commands are easier to recognize and use and most importantly it's cross-platform.

These scripts should work on Linux which will make it easier to create Linux versions of game packages and to install content from other games. Unfortunately PowerShell 7 - which is the cross-platform version - isn't available on Windows 7 which is still supported by this SDK so the scripts are required to work in both PowerShell 5.1 (Windows only) and PowerShell 7. This isn't a problem since the scripts don't rely on any features exclusive to either version but some script code is a bit more verbose as a result (mostly Join-Path usages).

To make the scripts easier to work with the boilerplate logic is separate from game-specific parts, this makes it easier to tell which parts require modifying. It's also been redesigned to support copying content from multiple games which the Unified SDK requires.

malortie has been hard at work creating updated models for the Unified SDK. Low definition and high definition versions of each view model for each set of hands (HEV, PCV and guard) will be included to support using all weapons in any mod. Additionally a third person player model ("player.mdl", used to trace attacks directed at players) for Barney has also been created to match the models used in Half-Life and Opposing Force.

Right now i need to test Half-Life Updated, Opposing Force Updated and Blue Shift Updated's singleplayer campaigns to see if anything is broken. Any issues that crop up that didn't already exist will be fixed to ensure that these repositories contain a relatively stable codebase.

Once that's done i'll put together beta packages for each of the 3 repositories. I'd like to run some tests in multiplayer to make sure nothing is broken there (e.g. broken game mode or friendly fire issues) so if anybody's interested we can organize some tests. I'm going to add basic bot support (bots that just stand in place, no AI) to run some tests in isolation but some game modes require more than that.

Only Half-Life and Opposing Force Updated need multiplayer testing since Blue Shift multiplayer is identical to Half-Life (and the game isn't meant to be played in multiplayer), and Opposing Force multiplayer differs mainly in the existence of the Capture The Flag game mode, so ideally multiplayer testing involves first testing Half-Life deathmatch, teamplay and then the Opposing Force versions before testing CTF.

Once this is all done and all issues have been resolved then a full 1.0.0 release will be done for each Updated repository and each repository will then be archived. The Half-Life Updated CMake repository will be removed entirely after this, since it's no longer useful at that point.

This entire process will probably take a week or 2 to complete depending on whether any bugs crop up.

For now i'd like to thank everybody who contributed to the development of these projects and getting the Unified SDK up and running, and i hope to have a first version of the SDK available for use soon, but we'll see about that after this work is all done.
Posted 2 years ago2022-01-21 18:46:35 UTC Post #346215

Half-Life 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-beta007
Half-Life: Opposing Force Updated: https://github.com/SamVanheer/halflife-op4-updated/releases/tag/HLOP4U-V1.0.0-beta003
Half-Life: Blue Shift Updated: https://github.com/SamVanheer/halflife-bs-updated/releases/tag/HLBSU-V1.0.0-beta004

Notable changes:
  • Fixed models stuttering due to client side interpolation
  • Rewrote installation scripts to use PowerShell
  • Added support for adding 64 weapons
  • Removed VS2017 projects
  • Cleaned up the codebase to remove unused code
  • Enabled clang-tidy code analysis rules
  • Added clang-format configuration file to share code formatting settings with other developers
  • Formatted the codebase to use a consistent style (easier to read and search in)
  • See the full changelog for 100+ changes
This beta will be used to test multiplayer functionality, after which a full release of V1.0.0 will be made available. This will be the last update released for the Updated projects, after which development will shift to the Half-Life Unified SDK.
Posted 2 years ago2022-01-31 20:04:04 UTC Post #346243

Progress update for 31/01/2022

Shepard and I did a multiplayer test last week and found a number of issues. Most of them are related to weapon prediction but there are also a few other issues that still need looking into. Opposing Force CTF has a number of bugs that still need to be fixed but it's going pretty well.

I'm confident that the next multiplayer test will show that all games are ready for a full release, but we'll have to wait and see.

malortie has been creating updated models that include animations from all 3 games to ensure that scripted sequences work properly across all games using the same model files. This will make it easier to make mods that reference animations specific to individual games.

Half-Life Unified SDK progress

Shepard and I have fine-tuned the Continuous Integration configuration to speed up automated builds as much as possible. I've added precompiled headers to the client and server projects to dramatically speed up the build times for both projects.

The entire Unified SDK solution builds in 30 seconds on my machine now, whereas before it took 2 minutes when nothing else is using the computer's resources. When you're doing things in the background it could easily take 5-10 minutes before whereas now it isn't impacted nearly as much since Visual Studio uses fewer CPU cores to compile everything.

Github CI builds meanwhile are nearly twice as fast as before, from ~9 minutes to ~5.

These are full builds, not partial builds which you'll be doing most often during development. Partial builds are faster than full builds so this makes it much easier to iterate on your code's design.

I've also cleaned up commonly used headers to simplify header inclusions a bit. You no longer need to include extdll.h and util.h before including cbase.h and many other common headers are also included in cbase.h which means you'll get access to common entity classes like CSprite right off the bat.

I've also added a new debug-only feature to help diagnose incorrect usage of SetThink, SetUse, SetTouch and SetBlocked. If you try to set one of these to a function pointer that does not belong to the class hierarchy of the entity that you're setting the function on you'll get an error message in the console warning you about it. Setting a function incorrectly can cause strange bugs and crashes so this will help a lot.

The continued focus on code cleanup and speeding up build times should make for a better SDK to work with that hopefully takes up less disk space as well (Visual Studio Intellisense generates database files with sizes measured in gigabytes). In the past i've noticed that precompiled headers cut down on the amount of disk space used by Intellisense so that should help.

I've also configured the third party library Git submodules to be included using shallow clones which should reduce the amount of bandwidth and disk space required to download and store those dependencies.

Also note that work that was added to projects like HLEnhanced will mostly be integrated into this one at some point. This also includes the work i've previously mentioned for Enhanced Half-Life, but like all things it will take time to do so. Some of these features are breaking changes, and i want to set up proper procedures for handling those before i start changing things. I will go into more detail on the plans for that later on.

Until the Updated projects are complete there won't be much progress on the Unified SDK. With the way things are going right now it'll probably take another week or 2 to finish those up. Once that's all done we can look at where to go next.

That's all for now. I'd like to thank everybody that's been helping out on these projects, and hopefully we can put the Updated projects to bed sooner rather than later.
Posted 2 years ago2022-02-01 08:05:30 UTC Post #346244
Thanks for the great update. I really like this project. 🙂
Posted 2 years ago2022-02-02 20:25:08 UTC Post #346245
I've also added a new debug-only feature to help diagnose incorrect usage of SetThink, SetUse, SetTouch and SetBlocked. If you try to set one of these to a function pointer that does not belong to the class hierarchy of the entity that you're setting the function on you'll get an error message in the console warning you about it. Setting a function incorrectly can cause strange bugs and crashes so this will help a lot.
Where is that change? I couldn't see anything obvious in the most recent commit messages.
Posted 2 years ago2022-02-02 20:37:34 UTC Post #346246
Posted 2 years ago2022-02-05 20:35:27 UTC Post #346252
@fresco Thanks for the compliments :)

@tschumann As Admer said it's in that commit.

I think i'm just about done with fixing Opposing Force CTF issues. A lot of problems with Half-Life multiplayer have also been fixed, in addition to a couple nice-to-have issues. I've got a couple more things to check out, but i think it's almost time to run another test.
Posted 2 years ago2022-02-11 17:22:05 UTC Post #346273

Half-Life 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-beta008
Half-Life: Opposing Force Updated: https://github.com/SamVanheer/halflife-op4-updated/releases/tag/HLOP4U-V1.0.0-beta004
Half-Life: Blue Shift Updated: https://github.com/SamVanheer/halflife-bs-updated/releases/tag/HLBSU-V1.0.0-beta005

Notable changes for all games:
  • Fixed some weapon prediction bugs
  • Fixed chat text sometimes using the wrong color
  • Fixed explosions going through walls sometimes
  • Fixed tripmine beams showing up in the wrong position sometimes and duplicating after level changes
Notable changes for Opposing Force:
  • Finished implementing Capture The Flag gamemode
  • Fixed player info bar in CTF gamemode showing incorrect health for dead players
This beta will be used to test multiplayer functionality, after which a full release of V1.0.0 will be made available. This will be the last update released for the Updated projects, after which development will shift to the Half-Life Unified SDK.
Posted 2 years ago2022-02-12 12:11:32 UTC Post #346275
I will be hosting a listen server to test first Half-Life Updated multiplayer (deathmatch and teamplay), and then Opposing Force Updated multiplayer (deathmatch, teamplay and capture the flag). We'll switch mods to test Opposing Force.

The goal is to make sure that there are no game-breaking bugs, no egregious visual and/or sound bugs like infinitely looping animations and sounds and that all game mode work as intended.

To participate in this test you'll need to install Half-Life Updated and Half-Life: Opposing Force Updated in the directories specified in the installation instructions for both mods.

Note that there might be problems with the PowerShell scripts used to install game content. You don't need that content to participate in the tests, so you can skip running the scripts.

I will be replacing those scripts with C# scripts as i initially wanted to which should fix those problems. A separate beta will be released for that later on, which will include any other fixes if today's test shows there is a need.

The IP for the server is <server no longer up>. I'll be putting the server up a bit before the test starts. The server will need to be restarted to test Opposing Force.

The test will start at 4 PM GMT +1 (UTC +1). That's in 2 hours and 50 minutes.
Posted 2 years ago2022-03-06 18:30:59 UTC Post #346325

Progress update for 06/3/2022

I've released a beta version of a C# library meant to aid in the writing of the install scripts as well as other tasks that will come up during the Unified SDK's development: https://github.com/SamVanheer/HalfLife.UnifiedSdk-CSharp

The HalfLife.UnifiedSdk.Utilities library contains utility functionality for opening, analyzing, modifying, converting and upgrading Half-Life 1 maps made for the GoldSource engine.

This library uses the Sledge.Formats.Bsp and Sledge.Formats.Map libraries to load .rmf, .map, .bsp and .ent files. Many thanks to Penguinboy for creating these libraries and updating them to support the loading of Blue Shift BSP files.

Note that Sven Co-op uses a modified BSP format. Trying to use this library with those files might not work and could cause crashes and data corruption.

The provided functionality replaces the BlueShiftBSPConverter and ripent tools currently used to install content. Along with the standard ZipFile API provided as part of the .NET runtime replacing the use of the 7zip tool this eliminates the use of platform-specific tools in all scripts.

In theory this will allow the scripts to run on Windows 7 SP1 and newer, modern Linux distributions and macOS 10.15 and newer. They will work on both 32 and 64 bit platforms since there are no architecture-specific dependencies.

Consult the .NET 6 supported operating systems documentation for more information about which platforms are supported: https://github.com/dotnet/core/blob/main/release-notes/6.0/supported-os.md

In short, this library allows you to manipulate the entity data contained in maps and map source files. You can search through maps for occurrences of entities, keyvalues, entity setups ranging anywhere from a simple trigger to complex setups involving hundreds or even thousands of entities, anything you can think of and more.

You can also modify the entity data. You can add, remove and modify keyvalues and add and remove entities programmatically.

This library is powerful enough to write scripts that can convert maps from one GoldSource engine game to another, for example you could convert a Day of Defeat map to Counter-Strike with this.

Also provided with the library is a tool to help automate the upgrading of maps from an older version of a game to a newer version. This tool is intended to be used to upgrade original Half-Life 1, Opposing Force and Blue Shift maps to the Unified SDK, and then upgrade all maps automatically to newer versions of the SDK whenever breaking changes are made.

This upgrade process should hopefully work on both BSP files as well as map source files. There is currently no support for modifying .jmf files (J.A.C.K. map source files) but hopefully full support can be added to Sledge.Formats.Map someday.

Unfortunately there is no cross-platform means of locating Half-Life installations programmatically. On Windows you can use this helper function:
var halfLifeDirectory = SteamUtilities.TryGetModInstallPath() ?? throw new InvalidOperationException("Steam or Half-Life isn't installed");
On Windows Steam writes a few registry keys, one of which contains the install location of Half-Life. On Linux it's up to the user to provide the location, so the install scripts will use the script's location as a starting point.

Here are some examples of scripts i've written to test the library. These scripts are executed using dotnet script.

This script counts the number of human grunts that exist in Half-Life games:
#r "nuget: HalfLife.UnifiedSdk.Utilities, 0.1.0"

#nullable enable

using HalfLife.UnifiedSdk.Utilities.Entities;
using HalfLife.UnifiedSdk.Utilities.Games;
using HalfLife.UnifiedSdk.Utilities.Maps;
using HalfLife.UnifiedSdk.Utilities.Tools;

var counts = MapFormats.EnumerateMapsWithExtension("bsp",
    "C:/Program Files (x86)/Steam/steamapps/common/Half-Life/valve/maps",
    "C:/Program Files (x86)/Steam/steamapps/common/Half-Life/gearbox/maps",
    "C:/Program Files (x86)/Steam/steamapps/common/Half-Life/bshift/maps")
    .WhereIsCampaignMap()
    .GroupBy(m => m.FileName, m => m.Entities.OfClass("monster_human_grunt").Count()
        + m.Entities
            .OfClass("monstermaker")
            .WhereString("monstertype", "monster_human_grunt")
            .Select(e => e.GetInteger("monstercount"))
            .Sum())
    .ToList();

var countsByGame = counts.GroupBy(c => Path.GetFileName(Path.GetDirectoryName(Path.GetDirectoryName(c.Key))));

foreach (var game in countsByGame)
{
    Console.WriteLine("{0} human grunts in {1}", game.Sum(g => g.Sum()), game.Key);
}
Output:
174 human grunts in valve
0 human grunts in gearbox
81 human grunts in bshift
This script counts both the actual grunt entities as well as monstermaker entities that spawn them, and counts the number of them it spawns. It doesn't account for infinitely spawning makers, but that's an easy thing to add. (Opposing Force has none because it uses a different entity)

Here's an example of how a map can be upgraded:
static void ReplaceWorldItems(Map map, Entity entity)
{
    //Convert world_items entities to their respective entities
    if (entity.ClassName == "world_items")
    {
        switch (entity.GetInteger("type"))
        {
        case 42:
            entity.ClassName = "item_antidote";
            entity.Remove("type");
            break;

        case 43:
            //Remove security items (no purpose, and has been removed from the codebase)
            map.Entities.Remove(entity);
            break;

        case 44:
            entity.ClassName = "item_battery";
            entity.Remove("type");
            break;

        case 45:
            entity.ClassName = "item_suit";
            entity.Remove("type");
            break;
        }
    }
}

static void UpgradeWorldItems(MapUpgradeContext context)
{
    foreach (var entity in context.Map.Entities)
    {
        ReplaceWorldItems(context.Map, entity);
    }
}

static readonly string BaseDirectory = "./upgrade";

var unifiedSdk100UpgradeAction = new MapUpgradeAction(new SemVersion(1, 0, 0));
unifiedSdk100UpgradeAction.Upgrading += UpgradeWorldItems;

var upgradeTool = new MapUpgradeTool(unifiedSdk100UpgradeAction);

var map = MapFormats.Deserialize(Path.Combine(BaseDirectory, "c1a0d.bsp"));

upgradeTool.Upgrade(new MapUpgrade(map));

Console.WriteLine($"Upgraded map to {upgradeTool.GetVersion(map)}");

using (var file = File.Open(Path.Combine(BaseDirectory, "c1a0d_new.bsp"), FileMode.Create, FileAccess.Write))
{
    map.Serialize(file);
}
This will upgrade maps to replace world_items with the entity it normally spawns, while removing item_security altogether since it's an obsolete entity.

You can also get a list of Valve games running on the GoldSource engine and the official maps they have to help automate certain tasks.

Here's a script to get a list of all mods installed in the Half-Life directory:
foreach (var modDirectory in ModUtilities.EnumerateMods(HalfLifeDirectory).Except(ValveGames.GoldSourceGames.Select(g => g.ModDirectory)))
{
    Console.WriteLine($"Found mod {modDirectory}");

    if (ModUtilities.TryLoadLiblist(HalfLifeDirectory, modDirectory) is { } liblist)
    {
        Console.WriteLine($"Mod is called {liblist.Game ?? "not listed"}");
    }
}
In my case it outputs this:
Found mod czeror-sdk
Mod is called Condition-Zero: Deleted Scenes SDK
Found mod ehl
Mod is called Enhanced Half-Life
Found mod halflife-pr
Mod is called Half-Life PR
Found mod halflife-updated-cmake
Mod is called Half-Life Updated CMake
Found mod halflife_bs_updated
Mod is called Half-Life: Blue Shift Updated
Found mod halflife_op4_updated
Mod is called Half-Life: Opposing Force Updated
Found mod halflife_updated
Mod is called Half-Life Updated
Found mod hlenhanced
Mod is called Half-Life Enhanced
Found mod hlu
Mod is called Half-Life Unified SDK
Found mod scriptablemod
Mod is called Half-Life Scriptable Mod
Continued in next post --->
Posted 2 years ago2022-03-06 18:31:08 UTC Post #346326
Continued from previous post <---

Progress on Half-Life Updated

The previous test we did showed some more problems with the weapon prediction code. I've fixed as many issues as i can there, unless the next test shows more issues that can be fixed in a reasonable amount of time i'd consider that done.

I've also fixed some other issues such as hand grenades remaining primed when unequipped or dropped, and Opposing Force crashing on map load. I think this fixes an issue that prevented the CTF test from continuing, but i'm going to run some more tests to be sure about that.

Once i'm satisfied with those tests i'll schedule another beta test. Hopefully this'll be the last one.

Many thanks to malortie and Shepard for helping with the previous test.

Progress on Half-Life Unified SDK

malortie has continued working on updating the models and has made good progress streamlining the assets and asset sources. This will make it easier to make maps that use models and animations specific to one of the Half-Life 1 games without having to use model replacement.

I've also added a Visual Studio hint file to stop Intellisense from giving false positives about some macros used in code: https://github.com/SamVanheer/halflife-unified-sdk/commit/5a101fea5d3415b7a04b52d0ac9c90461d0e4948

This eliminates the green squiggles seen under code like LINK_ENTITY_TO_CLASS and allows you to use Go to Definition on Save and Restore methods and gets rid of the visual noise those warnings show in the editor, making it easier to find code that is actually in need of attention.

I'll be done with the tests for Half-Life Updated pretty soon, once that's done i'll get to work completing some tasks for the Unified SDK. Things should start progressing faster now that all of this work has been done, so hopefully i can start setting up dev builds and stuff soon.

That's all for now, i'd like to thank everybody who has been helping to test and fix Half-Life Updated and get the Unified SDK off the ground. I really appreciate it.
Posted 2 years ago2022-03-14 14:09:22 UTC Post #346344
@SourceSkyBoxer Thanks, you stay healthy too!
Posted 2 years ago2022-03-14 14:24:44 UTC Post #346345

Half-Life 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-beta009
Half-Life: Opposing Force Updated: https://github.com/SamVanheer/halflife-op4-updated/releases/tag/HLOP4U-V1.0.0-beta005
Half-Life: Blue Shift Updated: https://github.com/SamVanheer/halflife-bs-updated/releases/tag/HLBSU-V1.0.0-beta006

Notable changes for all games:
  • Fixed chainsaw hornetgun sounds and mostly fixed hornetgun not playing firing animation
  • Fixed Gauss charge sound not always being reset
  • Show pickup icons in HUD for all weapons (except when spawning with weapons)
  • Fixed picking up weapons that give free/regenerating ammo sometimes showing weapon icon as red
  • Fixed hand grenades staying primed when switching away or dropping the weapon
  • Fixed event code crashing if weapon prediction is disabled
  • Automatically switch away from exhaustible weapons that have no ammo left (even in singleplayer)
  • Fixed controlling a func_tank with empty weapon deploying invisible weapon when stopping control (now switches to next best weapon)
  • Fixed m_rawinput changes not taking effect if a new map has started and less time has passed than on any previous map or if weapon prediction is disabled
  • Fixed Osprey not interpolating
  • Rewrote the installation and packing scripts to use C#
Notable changes for Opposing Force:
  • Fixed game crashing when loading map due to null scoreboard pointer
  • Fixed pipe wrench big swing attack not cancelling when the wrench is unequipped
  • Fixed player saytext color being incorrect in deathmatch games
  • Fixed TeamInfo message being sent to wrong player when initializing player hud in CTF gamemode
This beta will be used to test multiplayer functionality, after which a full release of V1.0.0 will be made available.

Please take a moment to read the About page if are thinking of copying dlls around manually.

This is the first release to use the C# install scripts. I have tested the scripts on a new Windows 10 installation, so i'm fairly confident that the instructions cover all of the required dependencies and steps needed to run them. If you encounter any issues please don't hesitate to let me know.

The install scripts are a bit different from previous ones: all singleplayer and training maps are now copied, maps that require Ripent patching are automatically updated. Blue Shift maps are converted automatically.

Node graph files in the mod directory for official maps copied to the mod are deleted if they exist to avoid problems with incorrect node graph files and to force them to regenerate. this was done as an installation step rather than a node graph version change because the node graph code itself has not changed and thus should not require a version change.

The packing script will automatically pack the contents of modname_hd, modname_lv and modname_language directories if they exist (where language is a language listed here in the API language code column, except for english since that's the default).

For more information on editing, running and debugging C# scripts, see this wiki page: https://github.com/SamVanheer/halflife-unified-sdk/wiki/Setting-up-and-using-dotnet-script

HalfLife.UnifiedSdk.Utilities updates

I've updated the C# utility library to include the latest version of the Sledge.Formats.Bsp library, as well as made sure all maps are written in the standard BSP format rather than the Blue Shift BSP format. I've also added utility functionality to get the list of languages supported by Steam for use in automating the management of language-specific mod directories, as well as constants to manage content directories such as modname_hd.
Posted 1 year ago2022-03-30 13:28:25 UTC Post #346388
@BAJIET

You're welcome :)

@SourceSkyBoxer

Glad to see you were able to solve your problems.
Posted 1 year ago2022-04-03 14:58:37 UTC Post #346395

Half-Life 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-beta010
Half-Life: Opposing Force Updated: https://github.com/SamVanheer/halflife-op4-updated/releases/tag/HLOP4U-V1.0.0-beta006
Half-Life: Blue Shift Updated: https://github.com/SamVanheer/halflife-bs-updated/releases/tag/HLBSU-V1.0.0-beta007

Notable changes for all games:
  • Fixed (Black Ops) Osprey crashing if it has no valid target
  • Fixed (Black Ops) Osprey teleporting to world origin if it isn't moving at all
  • Fixed (Black Ops) Osprey and (Black Ops) Apache not firing trigger targets
  • Fixed (Black Ops) Osprey engine damage effects showing on wrong engine
  • Pass director stufftext commands to filtered client command function
  • Fixed RPG sometimes getting stuck unable to reload
  • Fixed Tentacle not interpolating
  • Fixed node graphs being loaded from search paths other than GAME path (caused the wrong graph from vanilla HL to load sometimes)
  • Fixed momentary_door restarting movement sound repeatedly when moving back to starting position
  • Deleted Makefiles and libraries for MacOS X (Half-Life 1 is 32 bit, no longer supported by MacOS)
Notable changes for Opposing Force:
  • Fixed Otis Using Barney Voice Lines
This beta will be used to test multiplayer functionality, after which a full release of V1.0.0 will be made available.

Please take a moment to read the About page if are thinking of copying dlls around manually.

I've also added a new page to each repository's wiki containing a full changelog of all changes that have been made, excluding changes that involve bugs introduced in alpha and beta builds of these projects. These changelogs represent all changes from the original games to V1.0.0.

I'm going to tidy up the wiki a bit by adding links to the pages to more easily navigate everywhere, and add additional links to releases and project descriptions so people can find this information more easily.

Utility projects

The SDK's utility projects have been upgraded to compile with Visual Studio 2019. All projects with the exception of smdlexp (3DS Max plugin) compile and - with the exception of the procinfo library - run now, although some aren't very useful.

All projects are now 100% compiled as C++ which helps catch some problems that are permitted in C. I've also refactored the code a bit to eliminate redundant code.

The CMake version has more work done to eliminate redundant code.

Thanks to fel1x-developer for helping with this.

Progress on Half-Life Unified SDK

I've reworked the JSON loading code a bit so user code doesn't need to manage the creation of JSON validators anymore. This simplifies the code a bit and delegates the responsibility to the JSON system. Validators are only created if validation is enabled, which helps to cut down on memory usage and startup time cost.

More work is planned for the JSON system to eliminate differences between validation enabled and disabled modes.
Posted 1 year ago2022-04-03 17:30:56 UTC Post #346396
Wow Solokiller, this is insane. Amazing work you're doing here. I've only skimmed through the posts, but I had a question:

In WON, there was a hit sound when you shoot humans / aliens with a bullet, but in steam that is no longer there. Sven Coop actually added this back. Is this something you've added in this unified SDK? If not, do you know anything about it? As well as making the crosshair similar to the WON crosshairs? I know the crosshair part is kind of off topic from the SDK though.
awkook awkookaka vhetutor
Posted 1 year ago2022-04-03 17:56:33 UTC Post #346397
In WON, there was a hit sound when you shoot humans / aliens with a bullet, but in steam that is no longer there. Sven Coop actually added this back. Is this something you've added in this unified SDK? If not, do you know anything about it?
In SDK 2.2 the code to handle bullets was split into a monster-only and a player-only version. The monster-only version still has the hit sound code:
https://github.com/SamVanheer/Half-Life-Tools-Backup/blame/10b7ac15af91e50dad170af48bf77dcdf18dadf6/src/dlls/combat.cpp#L1456

The player-only one does not:
https://github.com/SamVanheer/Half-Life-Tools-Backup/blame/10b7ac15af91e50dad170af48bf77dcdf18dadf6/src/dlls/combat.cpp#L1551-L1553

The sounds are played on the client side for players:
https://github.com/SamVanheer/Half-Life-Tools-Backup/blob/10b7ac15af91e50dad170af48bf77dcdf18dadf6/src/cl_dll/ev_hldm.cpp#L413-L418

But since the client doesn't know what exactly is getting hit it can only handle sounds properly for players and the world:
https://github.com/SamVanheer/Half-Life-Tools-Backup/blob/10b7ac15af91e50dad170af48bf77dcdf18dadf6/src/cl_dll/ev_hldm.cpp#L115-L151

For reference, the server's version:
https://github.com/SamVanheer/Half-Life-Tools-Backup/blob/10b7ac15af91e50dad170af48bf77dcdf18dadf6/src/dlls/sound.cpp#L1646-L1651

Fixing this properly is impossible since the client can't just ask the entity like the server does. You could send the relevant information to clients using user variables (iuser) but there are only so many of those.
As well as making the crosshair similar to the WON crosshairs?
What's different about the crosshairs? Are you talking about sv_aim or something else?
Posted 1 year ago2022-04-03 20:33:03 UTC Post #346398
Steam Crosshair: https://i.imgur.com/017TOla.png
WON Crosshair: https://i.imgur.com/Q6EdEfp.png

The steam one seems to be thicker. Idk if it's just modifying the hud.txt file, but that's one of the differences between them.

And so for the sound then it would require a big rework or something. I wonder how Sven Coop achieved this. I'm just looking for the most nostalgia way to play half life for myself lol
awkook awkookaka vhetutor
Posted 1 year ago2022-04-03 21:41:04 UTC Post #346399
This seems to be caused by differences in how the sprite texture is blended before being uploaded. If you switch to the D3D renderer in WON it'll do the same thing.
And so for the sound then it would require a big rework or something. I wonder how Sven Coop achieved this. I'm just looking for the most nostalgia way to play half life for myself lol
They probably added the hit sound on the server sound, or they added a new variable sent to the client to let it pick the right sound (they have engine access, so they can do that).
Posted 1 year ago2022-04-03 21:57:31 UTC Post #346400
If you switch to the D3D renderer in WON it'll do the same thing.
I was rendering the WON version just now in OpenGL, which is what I use on Steam too. Hmm. Sven Coop also uses the WON style crosshair lol.
awkook awkookaka vhetutor
Posted 1 year ago2022-04-04 16:10:48 UTC Post #346401
I've updated the project descriptions, wikis and releases for Half-Life Updated, Half-Life: Opposing Force Updated and Half-Life: Blue Shift Updated to include links to the main wiki page, as well as a sidebar and footer, both of which contain navigation links for all three projects.
Redundant pages have been removed from the wiki and the About page has been moved to the Home page (default page).

Each wiki has the same sidebar, so you'll jump around these wikis when clicking on the project-specific links.

I hope all of this will make it easier for people to see what these projects are about and what you can and cannot do with them.

This page is now your starting point to learn about these projects: https://github.com/SamVanheer/halflife-updated/wiki

Note that once these projects are finished and the repositories are read-only i'll be making a version of this page on the Unified SDK wiki that will become the new hub for that project. It'll refer back to these projects, but won't have navigation going back because it'll have everything these projects have.

Some old links will no longer work but you should be automatically redirected to the Home page.

Also note that for older releases the instructions are no longer correct. Due to the switch first to PowerShell and then to C# the instructions are not correct for those releases. Since the changes only deal with running install scripts to copy maps this isn't important enough to keep old versions available for.

I've also added tags to all 3 projects to make them easier to find them when searching Github by topic.
Posted 1 year ago2022-04-04 19:10:06 UTC Post #346402
In SDK 2.2 the code to handle bullets was split into a monster-only and a player-only version. The monster-only version still has the hit sound code:
https://github.com/SamVanheer/Half-Life-Tools-Backup/blame/10b7ac15af91e50dad170af48bf77dcdf18dadf6/src/dlls/combat.cpp#L1456

The player-only one does not:
https://github.com/SamVanheer/Half-Life-Tools-Backup/blame/10b7ac15af91e50dad170af48bf77dcdf18dadf6/src/dlls/combat.cpp#L1551-L1553

The sounds are played on the client side for players:
https://github.com/SamVanheer/Half-Life-Tools-Backup/blob/10b7ac15af91e50dad170af48bf77dcdf18dadf6/src/cl_dll/ev_hldm.cpp#L413-L418

But since the client doesn't know what exactly is getting hit it can only handle sounds properly for players and the world:
https://github.com/SamVanheer/Half-Life-Tools-Backup/blob/10b7ac15af91e50dad170af48bf77dcdf18dadf6/src/cl_dll/ev_hldm.cpp#L115-L151

For reference, the server's version:
https://github.com/SamVanheer/Half-Life-Tools-Backup/blob/10b7ac15af91e50dad170af48bf77dcdf18dadf6/src/dlls/sound.cpp#L1646-L1651
I was reading the code for this Solo, and in both cases for monster and player, they both have this line inside of the if (iDamage) statement
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);

And it looks like both methods have similar input variables, so how come the player method can call TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); in the if (iDamage) statement, but not in the switch statement in the case of BULLET_PLAYER_9MM?
awkook awkookaka vhetutor
Posted 1 year ago2022-04-04 19:26:10 UTC Post #346403
iDamage is used to pass a custom damage value to FireBulletsPlayer. None of the weapons do that, so that code never gets executed. As for why it plays sounds, that's probably a leftover because nobody realized it was still there. Since nothing actually causes that code to execute nobody noticed.

There are several cases of unfinished pieces of code, leftover stuff and simple mistakes all made during the SDK 2.0 period, so this is just another one of those.
Posted 1 year ago2022-04-04 19:46:26 UTC Post #346404
What happens with the traceresult at this line https://github.com/SamVanheer/Half-Life-Tools-Backup/blame/10b7ac15af91e50dad170af48bf77dcdf18dadf6/src/dlls/combat.cpp#L1534 ? That doesn't figure out what was hit? Does it not modify the tr variable?
awkook awkookaka vhetutor
Posted 1 year ago2022-04-04 19:52:49 UTC Post #346405
What happens with the traceresult at this line https://github.com/SamVanheer/Half-Life-Tools-Backup/blame/10b7ac15af91e50dad170af48bf77dcdf18dadf6/src/dlls/combat.cpp#L1534 ? That doesn't figure out what was hit? Does it not modify the tr variable?
The function does modify the trace result. The last parameter passed in is a pointer to the result variable which the trace result is stored in. It's used to determine which entity to deal damage to.
Posted 1 year ago2022-04-04 19:56:42 UTC Post #346406
I did see that it was a pointer, and so then if it correctly does the traceresult, you can call TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); inside the switch statement, no? All the appropriate variables are needed for the call, the traceresult knows the entity that was hit

I know there's something I'm not understanding about how this engine works... is EV_HLDM.CPP where client processing happens? Why is it called HLDM if so?
awkook awkookaka vhetutor
Posted 1 year ago2022-04-04 20:40:39 UTC Post #346407
I did see that it was a pointer, and so then if it correctly does the traceresult, you can call TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); inside the switch statement, no? All the appropriate variables are needed for the call, the traceresult knows the entity that was hit
You can, but the client is playing sounds as well so you'll end up playing them twice.
I know there's something I'm not understanding about how this engine works... is EV_HLDM.CPP where client processing happens? Why is it called HLDM if so?
It's called that because the client side code was added for multiplayer. It was originally server only, but to compensate for lag it was moved to the client. Half-Life multiplayer is Half-Life Deathmatch, hence HLDM.
Posted 1 year ago2022-04-04 20:47:53 UTC Post #346408
You can, but the client is playing sounds as well so you'll end up playing them twice.
But the bullet hit flesh sound doesn't play either way, it's never called, so if you call TEXTURETYPE_PlaySound it will play the correct flesh hit sound?
awkook awkookaka vhetutor
Posted 1 year ago2022-04-04 21:18:13 UTC Post #346409
But the bullet hit flesh sound doesn't play either way, it's never called, so if you call TEXTURETYPE_PlaySound it will play the correct flesh hit sound?
The client is playing a sound, it's just not the flesh sound. If it can't identify the surface type it defaults to concrete:
https://github.com/SamVanheer/Half-Life-Tools-Backup/blob/10b7ac15af91e50dad170af48bf77dcdf18dadf6/src/cl_dll/ev_hldm.cpp#L155-L160
Posted 1 year ago2022-04-05 01:36:02 UTC Post #346410
So that EV_HLDM.cpp file is where client sounds get rendered even in singleplayer?
awkook awkookaka vhetutor
Posted 1 year ago2022-04-05 09:31:05 UTC Post #346412
Yes, the same code is used in singleplayer and multiplayer.

But there are other places were sounds are played, like studio event 5004:
https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/cl_dll/entity.cpp#L369-L372
Posted 1 year ago2022-04-06 18:20:44 UTC Post #346413

New JSON-based skill configuration system

I've implemented the JSON-based skill configuration system i've talked about before.

This replaces skill.cfg entirely and removes the hard-coded values used in multiplayer. It eliminates the need to define, register and synchronize cvars and variables in the skilldata_t struct while also allowing you to change the values in real-time (except in those cases where the values are cached, like an NPC's health for example).

Support for conditional values is present to allow for multiplayer-only values.

See the documentation page for more information and a comparison between the old and new systems: https://github.com/SamVanheer/halflife-unified-sdk/wiki/Skill-configuration-system
Posted 1 year ago2022-04-07 14:18:46 UTC Post #346414

Small addendum for the new skill system

I've removed the sk_ prefix from all skill variables. This prefix was only needed because the values were stored in cvars. Removing this removes the visual noise and repetition, and also reduces memory usage a bit (not by any significant amount). Variables that now start with a number have been renamed, in all cases this meant swapping the words in the name from numbermm_bullet to bullet_numbermm.

Only the value for the current skill level is now stored in-memory. The skill file is reloaded on map start anyway and the skill level cannot be changed without restarting the map (or using sk_reload after changing the skill level) so storing this information was pointless and wasteful.

The sk_set command no longer takes a skill level parameter and the sk_find command now prints the value for each variable it finds.

And finally variable names are now parsed using the same regular expression used by the JSON schema to validate the input so the behavior is consistent with validation on and off. This also simplifies the logic for parsing names.

I think that's just about everything needed for skill variables for now.
Posted 1 year ago2022-04-10 11:34:22 UTC Post #346420

Skill2Json tool release

I've released a beta version of a new tool called Skill2Json. This tool converts original Half-Life skill.cfg files to the Unified SDK's skill.json format.

Download here: https://github.com/SamVanheer/HalfLife.UnifiedSdk-CSharp/releases/tag/Tools-v0.1.0

See the readme for more information: https://github.com/SamVanheer/HalfLife.UnifiedSdk-CSharp#halflife-unified-sdk-csharp-tools

HalfLife.UnifiedSdk.Utilities

This library now has a Tokenizer struct that can extract tokens out of text just like the game's COM_Parse function. I haven't published a new version on Nuget yet since i'm probably adding more to the library soon.
Posted 1 year ago2022-05-05 14:58:43 UTC Post #346494

Half-Life 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-beta011
Half-Life: Opposing Force Updated: https://github.com/SamVanheer/halflife-op4-updated/releases/tag/HLOP4U-V1.0.0-beta007
Half-Life: Blue Shift Updated: https://github.com/SamVanheer/halflife-bs-updated/releases/tag/HLBSU-V1.0.0-beta008

Changes for all games:
  • Fixed node graphs being loaded from search paths other than GAMECONFIG path (properly this time)
  • Fixed node graphs being loaded with a null byte appended
  • Fixed "fullupdate" call making a HUD disappear
  • Fixed STL Algorithm Header Errors When Included with Platform.h
Changes for Opposing Force:
  • Fixed not being able to open team menu after a full CTF round has been played
  • Fixed npc_gonome trying to play non-existent sounds
  • Fixed monster_tentacle missing spawnflag 64 (different model option)
I've tested Opposing Force CTF using multiple clients on a LAN. Everything seems to be working fine, so i'm fairly certain that this will be the last beta release before the full release.
Posted 1 year ago2022-05-14 16:22:25 UTC Post #346518

Half-Life: Opposing Force Updated beta released

A Half-Life: Opposing Force Updated beta has been released: https://github.com/SamVanheer/halflife-op4-updated/releases/tag/HLOP4U-V1.0.0-beta008

Changes:
  • Fixed typo in shephard player model name
  • Fixed clients not getting ScoreInfo message for new players immediately in CTF
  • Fixed crashes when GetClientColor returns null in CTF
Thanks to Shepard for helping test this and uncovering these issues.
Posted 1 year 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 year 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.