I've fixed some issues with the weapons code, in order of resolution:
The ammo_* variables in CBaseEntity have been removed. All code now directly references CBasePlayer::m_rgAmmo's values for ammo in both the server and client versions. This fixes some prediction issues where code wasn't referencing an ammo_* variable.
TabulateAmmo has been removed since it no longer did anything, which simplifies some code as well since it no longer has to synchronize values.
Spore ammo is now networked as well in vuser4[ 0 ].
The M249 now tracks the reload time using the weapon time base, which is now networked to fix animation glitches.
The Pipe Wrench now networks its big swing state to prevent animation glitches from happening due to the server's animation being forced onto the client. That can happen if the client is ahead of the server by a few frames, networking that state ensures that the client stays in sync.
There are still glitches, but i can't fix them because they happen as a result of how the prediction system works.
When there is a certain amount of ping (noticeable at 100+) it starts to skip weapon attacks if they have a short interval. For example, the Glock and Desert Eagle can end up skipping animations and sound effects. I've experienced extreme cases where the weapon no longer predicts any attacks for whole seconds.
This happens in vanilla HL as well, and is a consequence of the engine rewinding frames, and skipping over some moments in the process. It might be happening because the engine only stores up to 64 frames worth of data to rewind, so if you have a high ping it can forget data.
Additionally, melee weapons don't predict hits on the client, so they'll play a miss animation first, then switch to a hit animation when the server data gets processed. The more ping you have, the more visible this will become.
I might be able to add hit detection to the client, but it might make things worse in competitive games if the client predicts a hit that ends up missing.
I've got some stuff planned for the near future, so i'll elaborate a bit on those:
I'm going to rework the save/restore code to separate the engine and server save/restore versions. Currently, the engine asks the server to handle the saving and restoring of some data, which requires the code to remain compatible with the engine's TYPEDESCRIPTION data.
By separating it, i can completely rewrite the server's code if needed. I'm going to take advantage of this to add new fields to TYPEDESCRIPTION.
For starters, you'll be able to add fields that will be automatically initialized by DispatchKeyValue. For example, if you have a float that is initialized like this:
if( FStrEq( "my_keyvalue", pkvd->szKeyName ) )
m_flKeyValue = atof( pkvd->szValue );
pkvd->fHandled = true;
You'll be able to automatically have it be initialized by adding it to the datadesc like this:
DEFINE_KEYFIELD( m_flKeyValue, FIELD_FLOAT, "my_keyvalue" )
This will add the field to save it and initialize it. There will also be an optional parameter to disable saving:
DEFINE_KEYFIELD( m_flKeyValue, FIELD_FLOAT, "my_keyvalue", false )
I'm not 100% sure i can add this optional parameter, i'll have to do some macro magic to make this work.
Second, Think, Use, Touch and Blocked functions will be stored in the datadesc as well. Currently, these functions need the EXPORT keyword to dllexport the symbols so the engine can look them up. This requires the use of platform specific code since different platforms have different name mangling rules. It's also more expensive since it routes through the engine, and represents a 32 bit dependency that has caused problems in the past. You can't compile the game for 64 bit without breaking support for the engine's function lookup.
This will remove that dependency, and centralize all metadata for entities in one place. You'll be able to look up any functions registered in the datadesc, though i might not store the type of the function, since it should be type safe by design, and supporting more function types in the future requires an abstract design.
This also means that you'll be able to look up any entity's keyvalues by name as long as it's in the datadesc. I'll also add a way to define fields that are neither automatically initialized nor save/restored to allow it to be used for purely metadata storage for a variable.
I can probably add 64 bit data type support as well.
Those who are familiar with Source will notice that some of this is also available in that, and has similar names. That's intentional to make it easier to understand. I came up with these ideas in response to problems i encountered, which also happens to be what Valve did. Rather than name it differently for the same of being different, i'm keeping them similar to make it easier to find information on the subject.
The aforementioned client side redesign for predicted entities will happen sometime after this. I think i might be able to completely replace the engine's temporary entity system. From what i can tell, the effects API is used by the engine as well, and uses the same object instance.
This means that i might be able to swap out the functions with my own, and control the list of entities. That will allow me to control the number of temporary entities, how they're allocated, and how they're designed. The engine accesses some member variables, so that limits things a bit, but as long as the beginning of the base class has the same layout, it should be fine.
This will hopefully allow me to better control temporary entities, sidestep the overflow issues and possibly even use a common interface for some temporary effects for the server and client versions.
There are still limits in the engine regarding the number of visible entities and beams, but this should make things a bit easier to work with.
It'll take some more research and experimentation, but based on what i've seen so far this is perfectly possible.
After that i'll return to monster code updates, there's still much to do there. I'll probably do some smaller stuff here and there if i find anything that needs doing.
On another note, last week i made a small test project to try out an idea i had. I figured that you could create a new engine that runs as a mod under GoldSource, so i set out to figure out how to do this. It took a few hours, but i got it to work.
The engine i made is pretty minimal, all it does is hijack the client or server and run itself, then hides the engine window and creates its own. It also extracts the command line and has support for console commands, cvars and command execution. This code is based on Quake, which is why the readme and GNU license for it is included.
You can check out the code here: https://github.com/SamVanheer/PrototypeEngine
I hope this will prove useful to anyone wanting to create an engine that runs under GoldSource as some form of enhanced GoldSource engine. It would take a lot of work, probably a year or more, but you can probably replicate the engine's features and use the engine's access to Steamworks to implement master server support and authentication. The engine itself authenticates the local user before loading game libraries, so you cannot run this if you don't own a copy of Half-Life that can run mods.
Note that i currently cannot legally tell you how to access Steamworks, since i haven't received word from Valve on the matter. You'll have to figure that out on your own.
Remember that Quake's license requires your work to be open sourced, so if you don't want to do that, you'll need to remove any Quake code that's being used. Currently, only the code in the console directory uses Quake code, so it's easy enough to remove.