Half-Life Enhanced Created 1 year ago2016-07-15 18:57:29 UTC by Solokiller Solokiller

Created 1 year ago2016-07-15 18:57:29 UTC by Solokiller Solokiller

Posted 1 year ago2017-01-08 23:04:39 UTC Post #332990
Good job, why not use with CEF from Steam directory?
If your webview of ingame need to get support of webgl!
Posted 1 year ago2017-01-08 23:07:37 UTC Post #332991
This is the engine's CEF implementation, all i did was backport Source 2013's version to work with this.
Posted 1 year ago2017-01-08 23:07:43 UTC Post #332992
Now the whole Black Mesa facility can browse TWHL! Great job!
Shepard62700FR Shepard62700FRHalf-Cat is watching...
Posted 1 year ago2017-01-08 23:27:32 UTC Post #332993
Lovely, but... what are the uses of this? Other than people spamming even more through MOTD?
Posted 1 year ago2017-01-09 11:04:15 UTC Post #332995
Perhaps one could program in a button in-game, place it over a computer, and when you press use on it a browser window would pop up?
Dr. Orange Dr. OrangeBoth a fruit and a color
Posted 1 year ago2017-01-09 11:34:00 UTC Post #332996
In one of my projects, we have a fake operating system that allow you to read text files (.txt). Some of them have inline HTML code such as <em> for italic, <strong> for bold, etc... Having this would allow us to remove our HTML to VGUI1 parser, support more HTML elements and have the same rendering as a web browser would.

As for the spamming issue, I think we can do like Source : implement a client CVAR that toggle off HTML MOTD.
Shepard62700FR Shepard62700FRHalf-Cat is watching...
Posted 1 year ago2017-01-09 12:37:00 UTC Post #332997
As Shepard said, providing a way to disable HTML MOTDs is a good idea. A CVAR that either disables the MOTD outright or forces it to fall back to the text based version (or choose between all 3 options) could be added.

@DR. Orange:
That's possible, but there is no way to interact with the game from the browser. Valve designed it to be a one way street, there doesn't seem to be any way to hook in Javascript callbacks.

As long as it just lets you read stuff it should be fine. You can get and set cookies, but i'm not seeing any JS stuff in there.
Posted 1 year ago2017-01-09 17:18:38 UTC Post #333005
I've committed the code needed to use the new HTML code, and will be committing the MOTD class when i'm confident that it's ready for use.

I'll elaborate on the changes needed to make this work, which also affects the rest of the VGUI2 codebase. This is all programmer talk, so you can just ignore this if you're not interested.

I've had to change where the KeyValues class gets its memory from. Source 2006 allocates memory from the IKeyValuesSystem instance returned by KeyValuesSystem(). In GoldSource KeyValues gets its memory from IKeyValues, which is exposed by the VGUI2 library.

This was a problem because the name of each KeyValues instance comes from a memory pool implemented by VGUI2, and is stored as a symbol, not a string. These symbols are compared as integers, so because they were using different pools the values didn't match up.
The symbols are actually indices into the memory pool's list, so you'd actually end up with random matches instead.

Because of this, VGUI2's message dispatch system was failing to properly trigger message callbacks, like for instance the message dispatched when you press the mouse.

That wasn't the only problem. The KeyValues class itself is also allocated from a memory pool provided by IKeyValues, and it is designed to allocate sizeof( KeyValues ) chunks. Unfortunately, Source 2006's KeyValues is 20 bytes larger than GoldSource's (24 bytes), due to changing how strings are stored and supporting escape sequence parsing.
Because the client is initialized too late, there is no way to communicate the different size to VGUI2, so allocations returned NULL, and caused crashes.

So i converted it to GoldSource's KeyValues class, fixing some issues that exist in that version in the process. I also provided cross-platform wide character support, which Source 2006 lacks, and made sure that no memory leaks can occur when changing the data type stored by a KeyValues object.

KeyValues now works on both the client and the server, but can never share the same KeyValues objects from one set of libraries because VGUI2's allocator is unavailable on servers. If you use KeyValues in your own projects, you'll need to provide an IKeyValuesSystem* keyvalues() function to make it work, and you'll need the client's workaround that wraps it to call into IKeyValues.

The HTML class might need some code removed in order to match up with GoldSource's version, not sure about that. It seems to be working pretty well, aside from cursor positions being slightly off.

I've also sent another email to Valve asking if the reported issues will be dealt with or not, and whether there is any way to fix them ourselves if they won't fix it.
Posted 1 year ago2017-01-09 20:00:16 UTC Post #333008
Got a response from Alfred:

Hi Sam, we are in a maintenance mode for the GoldSrc engine at this time, only fixing critical vulnerabilities when reported.
  • Alfred
Posted 1 year ago2017-01-09 21:26:58 UTC Post #333012
So... They're not going to respond to any of your tickets then?
Instant Mix Instant MixTitle commitment issues
Posted 1 year ago2017-01-09 21:40:12 UTC Post #333013
If they were going to do anything they'd have done it by now.
Posted 1 year ago2017-02-04 10:21:44 UTC Post #333192
I just pushed out a repository containing a framework i spent this past week developing: https://github.com/SamVanheer/DataMappingXML

I made this to make data mappings easier, it should replace HLE's version as well since it removes tons of boilerplate. The data descriptor code in HLE currently requires explicit use of types and array specifiers:
DEFINE_FIELD( m_toggle_state, FIELD_INTEGER ),
DEFINE_FIELD( m_flActivateFinished, FIELD_TIME ),
DEFINE_FIELD( m_flMoveDistance, FIELD_FLOAT ),
This framework will reduce that to:
DEFINE_FIELD( m_toggle_state ),
DEFINE_FIELD( m_flActivateFinished ),
DEFINE_FIELD( m_flMoveDistance ),
DEFINE_FIELD( m_vecPosition1 ),
DEFINE_FIELD( m_vecAngle1 ),
DEFINE_FIELD( m_hActivator ),
DEFINE_FIELD( m_hOldEnemy ),
Along with supporting dynamic arrays, the ability to specify public names to use to set keyvalues directly as before, and support for pointer types, this will increase the power of the data mapping framework a lot.

I didn't actually develop this for HLE, i made it to simplify the task of mapping XML to C++ code:


This is mapped onto a set of C++ classes and ends up looking like this:
Class "CXMLAPI":
Field: EMBEDDED globals(m_Globals):
Class "CXMLGlobalField":
Field: STD_STRING type(m_szType):
Field: STD_STRING name(m_szName):
Field: STD_STRING namespace(m_szNamespace):

So the CXMLAPI class has a vector of CXMLGlobalField objects. The globals node is the vector itself, global_field is the type to create/initialize. It can recursively initialize entire data structures like this with 1 line of code:
auto pAPI = static_cast<as_api::CXMLAPI*>( dm::CreateTypeFromXML( root, as_api::DataTypeDictionary() ) );
Good use of metaprogramming allows static verification of types, checking if a type exists and/or is the same as another, etc. If you try to expose a field that isn't compatible it'll statically assert as well.

I also added in additional metadata to iterate over entire class hierarchies, count inheritance depth and do other cool (but presently unnecessary) stuff.

As for why i needed XML parsing, i've been working on a tool that uses libClang to parse an entire codebase to generate metadata for it.

Specifically, the tool will generate a database of all enumerations, functions, globals and classes that need to be exposed to Angelscript. It then uses the Mustache templating library to output code that can register the API for it.

It will be able to generate wrappers for strings automatically, will eventually detect when inout parameters are in use to wrap those as well, and will also be able to extract Doxygen documentation, generate C++ wrapper classes and Angelscript base classes for custom entities, and do pretty much everything else i've been doing manually so far.

Basically it's a wonder tool that does (almost) everything.

The XML parsing will come in handy down the road because the Doxygen documentation will be extracted as XML and will need processing to transform it to the Angelscript variant, then it will be output as 1 big XML file that another program can consume to generate the actual documentation.

This will allow you to generate HTML, XML, JSON, or any other file format that lets you store this documentation. You could even convert it to a bunch of images if you wanted to.

This is an immense improvement over the old way of doing this, which involves a lot of tedious manual exposing of API functionality, writing wrappers and base classes, and writing documentation manually to supplement the API. All of which is error prone.

The tool is nowhere near done, since i've been a little busy trying to convince Valve to open source the engine, writing free alternatives to licensed code, etc. Hopefully i can get it finished now, after the data mapping tool is finished.
Posted 1 year ago2017-02-04 10:54:13 UTC Post #333332
A good chunk of the main CMakeLists file has been rewritten and refactored to deal with some issues:
  • Moved source & include file management to a separate file
  • Moved MSVC runtime management to a separate file
  • Cleaned up include path settings
  • Removed unnecessary hacks for Linux libraries that broke builds
  • Fixed VGUI1 library no longer linking (unknown cause), now properly links with target file. Added symlink to Travis build to use correct file
  • Removed unused preprocessor definitions (QUIVER, QUAKE2, etc)
  • Corrected library dependencies so the server library will load correctly
  • Updated Angelscript & AngelscriptUtils Linux libs to latest version (was missing stuff)
  • SQL shared libraries are now copied to the game directory when CMake is ran, instead of when you first compile. This prevents CMake generation from failing due to missing libraries
Some more cleanup is to be expected, there are multiple copies of some libraries that aren't needed. Workarounds for Travis linking to SDL2 can be removed and replaced with symlinks as well.

I'd like to move the library definitions for the client and server to their respective main directories, game/client and game/server.

Ideally all source code will be moved to /src to tidy the main directory as well, but that'll be a huge movement operation. Git can handle that, but it will make porting mods a bit harder. It will have to wait until the VGUI2 branch is merged in.

I've made more progress on the Angelscript generator tool as well. I've added support for XML configuration files to allow you to specify the API through that, allowing built-in types (e.g. size_t) to be exposed as well.

More work is still required to complete the generation process, but so far it looks good.

Once completed i can replace the manual generation with annotations, then i can rework some of the core base classes and expose those as well. With that done adding stuff should be easy enough. Add to that automatic generation of base classes for class extensions and Angelscript API development will be very easy for anyone to pick up.

The tool requires the use of a command database generated by CMake, which only works when generating with Unix Makefiles. That generator did not work with HLE because it relies on Cygwin linking rules, which uses .a files for import libraries. SDL2, SQLite and MariaDB do not come with a .a file for use with Cygwin, so i had to disable the use of those libraries when generating the database.
Posted 1 year ago2017-02-05 21:51:58 UTC Post #333354
I took a break from working on the usual and made a branch to port all utility programs in /utils to CMake. That in itself wasn't so hard, but some projects wouldn't compile so i had to fix them. With 2 exceptions (3DS max exporter and Server Control) they now all compile, though there is still a lot of work to do there.

Making the tools cross platform requires a fair amount of work, with one tool using MFC (which doesn't work because of library changes).

So far all tools have been moved from GLAux (obsolete OpenGL library) and GLUT to SDL2 for OpenGL drawing, removing both dependencies and completing the conversion suggested in the readme in the repo. I've also converted some of them to C++ to make things easier, exposing some issues in the progress.
Nothing that's hard to fix, but definitely needed in any case.

Hopefully when all these tools are ported over the duplicate code (mathlib) can be removed and made cleaner, though most of these tools have been obsolete for a long time (e.g. map compiler tools).

The Server Control tool looks most interesting, and simultaneously is probably completely non-functional. Modern RCON tools have superseded it since those are cross-platform. I think about half of these tools can be replaced with other tools altogether for the same reason.

I also realized that Half-Life is apparently using an SDL2 version that you can't find anywhere online. 1.3.0 doesn't appear to actually exist and isn't compatible with either 2.0.0 (which the Linux version seems to be) or the last version before that.
It isn't really an issue since all the required files are there, but it would be easier if the distribution were available standalone as well.
Posted 1 year ago2017-02-05 22:10:42 UTC Post #333355
Damn, thats nasty in a good way !
Posted 1 year ago2017-02-06 19:17:32 UTC Post #333367
The code i've had to fix is nasty, the fixes make things a bit better.

I've fixed the majority of the warnings up to warning level 4, 47 remain and aren't terribly bad. The ServerCtrl program compiles now though it will not work due to the aforementioned issues. That just leaves the 3DS Max exporter which i've disabled due to not having the headers for it.

All code has been converted to C++, which exposed relatively few issues. There's tons of global state to make anyone cry, but i won't be fixing those (yet). I'll probably replace the older tools with the latest version's code, then rework that if needed. That won't be any time soon though.

I've tried that before with CSG and got pretty far before giving up, this code just isn't easily redesigned.
I'll have to get back to VGUI2 & the API generator and get both done so i can get all branches merged in and updated. With that done i can start making progress in other areas.
Posted 1 year ago2017-03-03 12:17:33 UTC Post #333835
I've been doing some work on VGUI2, specifically reworking the existing Hud code to make it more flexible and to allow for multiple Huds.
In doing so i've removed the global list of elements, since it was counter-intuitive with the concept of multiple Huds.

I've also implemented a way to dispatch network messages to the right Hud at runtime. This has the side-effect of removing the need for the DECLARE_MESSAGE macro, which defines wrapper functions that forward to the object that it belongs to.
This means there is no longer any overhead to look up a Hud element to dispatch to it. The only overhead is in the message handler lookup, which uses a binary tree so it's relatively fast. It also makes it easier to dispatch to Angelscript when that gets added.

I also made it possible for message handlers to return void instead of bool. All but one existing function returned true in all cases anyway, so this simplifies things a bit more. The engine ignores the return value anyway, so it matters little.

I found a problem in Valve's container classes while working on this (cost me a few hours) so i'll be dealing with that next.
Posted 1 year ago2017-03-31 09:07:32 UTC Post #334167
I fixed a couple uses of magic numbers in monster code, nothing major since it didn't really break anything. I did a sweep for other magic number uses and found nothing, so it's pretty good.

One case was in the Alien Slave's disabled ally resurrection code (sets WaitTillSeen flag), the other in the Tripmine's Spawn method to check whether to instantly turn on.

I'll try to get some small stuff done today, then commit new binaries to the game repository.
Posted 1 year ago2017-03-31 11:54:55 UTC Post #334170
Ooooh man, this gonna be great... :crowbar:
Posted 1 year ago2017-03-31 17:47:40 UTC Post #334176
Some more changes:
  • Weapons have some new frame callbacks backported from Source, these can be used to update weapons at times that were previously impossible.
  • The Hornet Gun and Shock Rifle will now regenerate their ammo in real time while holstered. Uses the above callbacks.
  • Custom entity base classes are marked abstract to prevent bugs when the class is accidentally instantiated on its own.
  • The CSoundEnt class has been refactored. I've cleaned up the syntax, changed #defines to enums when applicable, increased the maximum number of world sounds from 64 to 1024 (largely eliminating "Free Sound List is full!" console messages), added some asserts to perform sanity checks, and simplified some local variable uses to make the code easier to read and safer to use.
  • CBaseEntity::m_pGoalEnt has been changed from CBaseEntity* to EHANDLE, eliminating crashes when the goal ent is killtargeted while an entity is moving to it (e.g. track train moving to path_track that is killed). Renamed to m_hGoalEnt to reflect new type. COsprey's m_pGoalEnt has been removed and replaced with m_hGoalEnt (variable shadowing issue).
Basically you can now +use stuff while shooting and reloading, like HL2.
This will be most useful for mappers once some kind of map specific configuration can be added.
Posted 1 year ago2017-03-31 20:01:54 UTC Post #334178
Great work.
Posted 1 year ago2017-04-01 03:22:16 UTC Post #334182
For some reasons I find reading your changelogs or commits very enjoyable.
I was curious about one thing: do you use a particular coding style or code practice guideline (like a book or something)? I know for example there is a book explaining that function bodies should fit within the screen's height, or that there should not be more than one nesting within the same function.
Posted 1 year ago2017-04-01 09:00:39 UTC Post #334184
My code style is largely based on Valve's from the Source engine. Variable naming, class names, use of globals, CreateInterface, it all comes from the SDK.

I did make some changes, like using i instead of n for numbers, so it looks like this:
class CEngine //Class names start with C
class C_Engine //Client side versions of server classes (networked entities, etc) start with C_
class IBaseInterface //Interfaces start with I
class CBaseEntity //Base/abstract classes start with CBase
int m_iNumber; //Class members start with m_ (member), integers of all sizes start with i
unsigned int m_uiNumber; //Unsigned integers of all sizes start with ui
bool m_bBoolean; //Booleans start with b
float m_flFloat; //Floating point numbers start with fl

Valve's code style is based on Microsoft's (Newell and Harrington came from Microsoft), which is in turn based on Hungarian Notation: https://en.wikipedia.org/wiki/Hungarian_notation

As far as nesting goes, i'll usually try to refactor loops into functions if needed, separate larger functions out into smaller ones if they grow too large.

If i spot the same code multiple times i'll refactor it, for example code to convert radians to degrees would be refactored into inline constexpr functions (possibly templated as well) if i were to write it today.

For code practices i try to follow established principles like SOLID (https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)), Don't Repeat Yourself (DRY), and more listed here: https://en.wikipedia.org/wiki/Category:Programming_principles.

For patterns, i'll use some of these when applicable:

That last one is presented as an object oriented pattern in the article, but also applies on a larger scale, like game engine design. For instance, during map loading you'll change from one state to another (about to start loading map, loading map, loaded map, spawning entities, spawned entities, starting physics simulation, starting main loop, frame started, frame ended)

You can find more of these listed here: https://en.wikipedia.org/wiki/Software_design_pattern.

I have a bit of a leg up on most people because i have some kind of above-average memory recall that lets me memorize a codebase and use that to see the bigger picture more easily. It's part of the reason why i tend to write essay length posts, because i try to sum up all the changes that are made.

To give you an example of how i can put that to use, the reason i'm adding getters and setters for entvars_t members in CBaseEntity is so that in the event that we ever get an open source engine we can remove entvars_t altogether without requiring massive amounts of changing on the spot.
You'd change where the variables are declared, update some metadata tables and you're done.

I'm planning years into the future which requires me to take into account which changes will be needed, where they'll be needed and why.

And as you may have noticed, it also makes me go off on tangents for a bit for what must seem like unrelated things :P
Posted 1 year ago2017-04-01 13:44:02 UTC Post #334186
That's really interesting! I'll learn more on the principles you mentioned.
I recently went to a PHP conference about Extremely Defensive PHP. It described some coding guidelines, some of them were to make objects immutable whenever possible and avoid the use of setters.
We did not actually have a speaker, we just watched a video. :P https://www.youtube.com/watch?v=8d2AtAGJPno
It's not the exact same video but I believe it's the same guy talking about the same thing with the same slides.
Posted 1 year ago2017-04-01 15:30:09 UTC Post #334192
Making objects immutable is necessary in PHP because as the speaker said, the objects are references.
In C++ you have more control over this, so you can have a mutable DateTime class that doesn't experience the same issues, provided you use instances that have automatic lifetime, meaning you don't store pointers to the instance, you store the actual instance.

This is still important for larger objects that you would store references to using something like shared_ptr, but it depends on the language and the use case. C++ gives you the power to control it, but it also gives you the responsibility to do it right.

Sometimes doing it wrong may be needed, if your use case requires a synchronized data set shared between objects then using immutable objects is the wrong way to go.

In C++ you can enforce immutability with the keyword const, though you can still bypass it using either const_cast or using pointer cast tricks, but you have to try to break the code to do that.

The speaker makes some good points, but as always, there are exceptions to all rules. Just as long as you don't blindly apply principles, practices and patterns and consider the effects they will have you should be good.

You'll learn what works and what doesn't with experience, so code you write in your first year won't measure up to what you write in your fifth, but that never really goes away. A year from now i'll think i was stupid doing things a particular way today.
Posted 1 year ago2017-04-01 18:13:31 UTC Post #334193
Some more changes:
  • Added a missing think function for CBloodSplat to the data descriptor (save/restore issue)
  • Replaced most uses of GetClassPtr with UTIL_CreateNamedEntity.
This makes the uses a bit less verbose, since they had to set the classname manually, which was error prone and wasn't easily noticeable (only one such case existed: crossbow bolts are named "crossbow_bolt", but were named "bolt" by usage). This has the added effect of calling through to the engine every time, which lets Metamod/AMXMod hook into it. All entities that were previously not linked to their name have been updated.
  • Updated direct uses of pev->classname to use either GetClassname or SetClassname, depending on their usage.
  • Removed FClassnameIs: all uses have been updated to use CBaseEntity::ClassnameIs, making these obsolete.
I'm currently looking into what it would take to implement some of the OP4 monsters, looks like the relationship table needs updating. To avoid headaches in the future (take a look at this: https://github.com/ValveSoftware/halflife/blob/5d761709a31ce1e71488f2668321de05f791b405/dlls/monsters.cpp#L2195) i'm going to replace this with a more dynamic approach that removes the hardcoded set of classes and uses a list created once per map.

This means you will be able to define your own classes and relationships between other classes. There should be no additional runtime overhead (aside from memory usage) once the entity has spawned, so it's a win-win situation.
Posted 1 year ago2017-04-04 23:08:05 UTC Post #334227
So i've spent a few days putting together the new classification and relationship system. Before i change everything, i'd like to ask for some input to see if what i've come up with is good, whether it makes sense.

The current system works like this:
Entities return their classification, which is looked up in a matrix to see what its relationship to another classification is (see https://github.com/ValveSoftware/halflife/blob/5d761709a31ce1e71488f2668321de05f791b405/dlls/monsters.cpp#L2195) for the matrix).
Completely hardcoded, and the CLASS_IGNORE classification (value 99) will actually read incorrect entries, if not past the end of the array.
Entities can override relationships by overriding IRelationship.

The new system works like this:
On map start, all classes are cleared, and the "NONE" class is created, which is the default for all entities if their requested class does not exist.
CMap initializes the classes to the current defaults, mirroring the current setup.
A classification can be created by at minimum specifying a unique name for it. You can optionally specify the default relationship to fall back on if no explicit relationship is specified, both between the source and target, and the target and source.

What this means is that the following logic is used:
If a relationship from source to target exists, use that relationship (e.g. human passive (scientists) hates human military (grunts)).

If a bidirectional check was requested, and a relationship from target to source exists, use that relationship (e.g. human military dislikes human passive).

If a default target relationship for target is defined, use that relationship (e.g. "IGNORE" has a default target relationship R_NO).

Otherwise, use the default source relationship for source (defaults to "No relationship") (e.g. "INSECT" has a default source relationship R_FR ("Fear")).

The result is that Insects ignore the "IGNORE" class without having to override its default source relationship of "R_FR", which lets you finetune relationships easily. E.g. Human military are feared by default because reasons.

Relationships themselves are established by either defining a unidirectional relationship source->target or a bidirectional relationship source<->target. A bidirectional relationship can be manually created as well, the option is a convenience.

Classifications and relationships can be removed as well.

In addition, i'm also considering adding a way to add aliases to redirect existing classifications to others, for instance mapping human military to human passive so they share relationships and act as though they have the same classification.

This covers the features themselves, and the C++ side of things.

Map configs, when they're added will have the option of controlling these classes as well. Configs will use the KeyValues file format, which allows for structured definitions in the same file.
I'm considering this syntax:
reset 1 //Reset classifications first. If omitted, treated as though reset 0 were present

"class" "HUMAN_PASSIVE" //Short syntax, define class with defaults
//Long syntax, define class with options
"defaultSourceRelationship" "R_NM" //Attack everybody by default. If omitted, defaults to R_NO
"defaultTargetRelationship" "R_NM" //All other classes will attack this class by default. If omitted, no such default is used, they will use their own defaultSourceRelationship

"target" "HUMAN_PASSIVE"
"relationship" "R_FR" //Grunts fear scientists. They will run in fear
"biDirectional" "0" //If 1, this relationship is also established between HUMAN_PASSIVE and HUMAN_MILITARY (scientists fear grunts). If omitted, defaults to 0

"relationship" "R_AL" //Grunts are allied to eachother. If not specified, grunts will kill eachother

//Possible syntax for aliasing. Alias the PLAYER class to HUMAN_MILITARY
"name" "PLAYER"
This configuration wipes all classifications, defines HUMAN_PASSIVE with defaults (no relationship to any classes), and the HUMAN_MILITARY class which will try to kill everything except HUMAN_PASSIVE.

Players will have the same relationships as HUMAN_MILITARY, making everybody except HUMAN_MILTARY attack them, and enabling them to attack everybody except HUMAN_MILITARY (if relationship rules were to control the damage filter).

Angelscript will have callbacks that are invoked both before and after this config is parsed, allowing it to both set defaults, and override map configs. It has methods that are equivalent to the above config:
pClassifications.AddClassification( "HUMAN_MILITARY", R_NM, R_NM );
pClassifications.AddRelationship( "HUMAN_MILTARY", "HUMAN_PASSIVE", R_FR );
pClassifications.AddAlias( "PLAYER", "HUMAN_MILITARY" );
That should just about cover it. Existing entity methods are changed as follows:
virtual int Classify() -> virtual EntityClassification_t GetClassification()
virtual int IRelationship( CBaseEntity* pOther ) -> virtual Relationship Relationship( CBaseEntity* pOther )
EntityClassification_t Classify()
In addition, the classification can be overridden on a per-entity basis by mappers. Classify() takes care of that, and methods to get both the original and overridden classification are available.

Since this relies on mapping strings to Ids, there may be a need to cache these values, so the new setup is designed with that in mind. If caching were implemented, entities need only inform CBaseEntity if they require it to be disabled if they dynamically change their class.

An arbitrary maximum number of classifications is defined at 255, but unless there are memory usage or networking issues the limit can be increased to a few billion.
Posted 1 year ago2017-04-04 23:43:57 UTC Post #334228
Cheers! I'm fairly new to C++, so parts of what you're saying look a bit complicated to me but definitely useful as well. Hopefully I'll be able get better with C++ soon.

As for the new classification system, I assume that, by "class", you mean an NPC relationship class (and not the broad OO meaning)?
The system looks modular and simple, although I'm not sure where CMap, whatever it is, will get the default relationships from?
Posted 1 year ago2017-04-04 23:52:13 UTC Post #334229
Yes, i mean the NPC relationship. CMap is a class whose purpose is managing the per-map state. It will take the current relationship matrix and define it using the new API.
Posted 1 year ago2017-04-05 12:25:28 UTC Post #334233
Good to gather friends along gameplay, as seen in Operation Na-Pali!!
Posted 1 year ago2017-04-05 13:01:29 UTC Post #334234
I've never played it before, what are the similarities?

I just finished integrating the new system and ran some tests. I swapped the scientist and grunt classes, scientists now fear me while grunts are friendly, though i can't get them to follow me.
I also set grunts to be their own nemesis and loaded c1a3b (We've Got Hostiles surface with the Osprey), the grunts were out for eachother's blood. They seemed to be a big fan of kicking eachother and throwing grenades.

Monstermakers have a separate keyvalue to override their target monsters, so the makers themselves can be left unchanged and avoid being targeted for no reason.

So now i get to test it and find ways to break it, and finish up integrating it. I'll have to make sure it save/restores this stuff properly as well.
Posted 1 year ago2017-04-05 18:39:26 UTC Post #334235
I've never played it before, what are the similarities?
ONP is a Unreal Tournament mod, quite old. In the game you encounter natives from the planet (the Nali) that, unless you use them, act like neutral. If you use them you can give them orders and act like enemies to other npcs. It´s quite long since I don´t play this mod (almost 8 years) but I remember that. :)
Posted 1 year ago2017-04-06 21:08:05 UTC Post #334255
So they're like recruitable NPCs? That's not quite what this update does, but very similar.

I've committed the classification changes, i'll write a wiki entry tomorrow for that. I've also committed new debug binaries, an update to the fgd and a test map called test_classification_override that spawns a scientist with HUMAN_MILITARY classification, and 2 monstermakers that spawn grunts and scientists, grunts with HUMAN_PASSIVE and scientists with HUMAN_MILITARY.
The grunts will attack the scientists but not you.

The NPC follow code does not account for relationships so you can still get scientists to follow you, while grunts won't follow you.

With this update done, i can get the vgui2 branch to a point where it can be merged in, allowing the use of KeyValues and other very useful Source SDK stuff. I'll be using that class to implement map configs, which lets you control the classifications on a per-map basis.

KeyValues is a very flexible file format, and because we have the source code for the parser, we can have special tokens to make life easier. The parser comes with support for the #include token, which adds keys from another file to the file in question.
While it doesn't let you overwrite keys from the included file, it does let you share keys easily, so you could have a file that defines the base for your map series, and have map specific additions.

See the VDC page for more information: https://developer.valvesoftware.com/wiki/KeyValues_class
Note that this covers the current Source SDK version, which is quite different. Escape sequence parsing had to be disabled due to GoldSource's version not having it, which forced its removal due to it changing the size of the class.
The #base token does not exist in this version either, and #include is only handled if it is encountered as a top level token (outside any section defined by '{' and '}').
Conditional inclusion isn't included either, but that can be added if needed.
Having the source code makes a lot of things possible here.

I'm considering moving all configuration files over to KeyValues since it's much more flexible, it would also force engine level configs to be deprecated so game code would have complete control over the execution of every config file. It would also be more consistent than having both cfg and KeyValues configuration files, though the execution time of some configs may be impossible to replicate.

Note that once this is done, HLEnhanced will no longer function under any other engine build unless that build provides the same libraries (tier0, etc) and exports (KeyValues memory manager, etc). This effectively locks it to the current Steam build.

Some more bug fixes:
  • The sniper rifle didn't change its zoomed in crosshair to regular if the magazine was emptied and the gun was then automatically reloaded. Its behavior now matches the crossbow in that reloading always zooms out if the player has ammo, even if the magazine is full.
  • The crossbow didn't use the user defined (weapon_info file) ammo type to check if it could reload.
  • The 357's crosshairs were inverted if playing a multiplayer game with maxplayers 1. This is due to the client determining whether the game is multiplayer by checking the number of players, which differs from the server's method of using gamerules. The client is now told whether they have connected to a multiplayer server or not. Various other weapons related settings used the same check, and will now behave properly on the client side (none appeared to have any bugs, due to most checks being server only).
Posted 1 year ago2017-04-06 21:31:05 UTC Post #334256
This effectively locks it to the current Steam build.
Oh. :(
Posted 1 year ago2017-04-07 09:47:43 UTC Post #334262
There's nothing i can do about that, Valve needs to open source their stuff so people can include the essentials needed to make things compatible.

I've refactored the new Hud code so shared state is tracked separately, so it's pretty close to fully supporting multiple Huds. It won't be ready just yet, but the base Hud code is pretty much done now.

The way it works now is you have a global CHud instance that stores and updates the shared state, it also stores the current Hud and updates it accordingly. Each Hud has elements that track their owning Hud and access the shared state as needed.

Ultimately the goal is that each Hud has elements that do all the work of drawing stuff on-screen. The Viewport, which is VGUI1 at this point, should be integrated into the Hud elements. Right now it's a mishmash of Hud elements for the older stuff (health, ammo, weapons, etc), while newer stuff like the scoreboard is VGUI1.
Games like Counter-Strike use VGUI2 for that, further compounding the mess.

So the idea is that Hud elements use VGUI1 or VGUI2 in a mostly transparent way, so you can flip a switch and make it use the other version with few code changes. The viewport class would mostly disappear as a result, since its job is to manage the Hud just like CHud and CBaseHud do, only in a slightly different way.

With all of that stuff integrated and updated to support VGUI2 it should all work nicely without being a headache to deal with. Unfortunately, that will take a bit more time to finish. Ideally i'd do this first, but i'd have to refactor so much stuff that i'd be working solely on that for weeks, and i'd like to get some other stuff finished first.

So i'll be merging the vgui2 branch into master now, finish up on those things first, then get back to VGUI2.
Once the merge is done, i'll do these things:
  • Implement map config support: KeyValues based map config, maps/<mapname>.txt is the config, gets loaded once, processed once to set cvars, entity classifications, etc, in the future things like player inventory can be pulled from this as well.
  • Replace std::unordered_map and std::vector combos with CUtlDict (performance improvement, simpler API).
  • See if adding CUtlVector to save/restore is an option, would make things easier (multi_manager/multisource with theoretically infinite targets, CUtlVector weapon list, etc). Probably requires custom save/restore function support though. I doubt i can do this easily, but it merits investigation to confirm.
  • Update client side FOV properly so crosshairs are updated properly during weapon switch, currently broken when switching between zoomed in weapon and weapon with zoom support.
  • Make sv_cheats be checked in real-time. Only possible for game code, engine caches value like game code currently does. Damn you Valve.
  • Prevent NPC dropped weapons from respawning in multiplayer.
  • Geiger sound overrides crowbar hit sounds.
Then it's off to writing the wiki entry for entity classifications. I'm hoping to do this all today, then i can get back to VGUI2, maybe get it done soon enough to at least get multiple Hud support fully functional.
Posted 1 year ago2017-04-07 14:30:08 UTC Post #334264
Wow! your project is getting better and better. I can hardly wait till it's finished and completely playable once that's the case I will say good bye to opfor.dll and we use yours instead and expand upon it..

The fact that you add opfor monsters as well is amazing let me know if you need proper ai behavior patterns for the other monsters.. 1 of my coder managed to replicate their ai code almost perfectly - voltigore, Vortigaunt even the panther eye etc and that in better quality than it used to be in raven city sdk if you're familiar with that ancient mod project. It might save you and my coder some time for the future.

Our plan was it to get a spirit opfor version out including many other goddies such as female scientists fully voice acted. Construction workers and the cut hl1 monsters etc. but then we discovered your project and put our plans on hold.
Posted 1 year ago2017-04-07 19:35:30 UTC Post #334267
The Op4 monsters will behave as they did in the original because i'll be pulling their original code out of the game library, so i won't need any help with that. Thanks for the offer though :)

I made some progress:
  • Successfully merged vgui2 into master
  • Implemented map configs with cvar & entity classifications support, no whitelist for cvars so it can be used to set rcon passwords atm.
  • Implemented server config using the map config code, will need some refactoring and support for post-map config execution code so servers can enforce changes. I'll probably refactor the map & server config code to store a list of configs, then execute them in order when needed. That way you can add more configs that are processed at the right time. I doubt there's any need, but it will clean up the code a bit.
  • sv_cheats now checked in realtime.
  • NPC weapons no longer respawn.
I couldn't fix the geiger counter sound issue because i can't easily play sounds on different channels on the client side. I found a way to get an object that lets me do so, but, well, i'll quote myself:
i can probably get systemwrapper if i use vgui2 to get the demo player dialog, it stores a pointer to it
from there, i can access its interface and query for enginewrapper
to get a function that lets me play sounds with a user defined channel
this is bullshit man
So i'm leaving that bug for the time being.
The FOV issue seems to be a bug that i caused, so i'm tracking down which change caused it to see if i can just fix it by reverting a change.

I've written wiki pages for the new features:
Posted 1 year ago2017-04-29 10:04:53 UTC Post #334676
Posted 1 year ago2017-06-18 14:58:46 UTC Post #335576
I'm sure some people have noticed that i've been quiet on what i've been working on these past few weeks. That's because i've been working on some Angelscript stuff, and it's pretty close to getting finished.

First off, i dusted off my prototype Angelscript IDE and upgraded it a bit.
Initially it was just a simple text editor with script compilation & error reporting support.
It would let you load a file that contains a configuration output by one of Angelscript's helper functions to get a hold of its API so it could compile scripts, but it was rather limited in what it could do.

So a few weeks ago i started working on it again. First thing i did was to upgrade it to use CMake (as is tradition), including porting the project to use Qt5 (previously Qt4). Qt is a cross-platform GUI library, and it has CMake support so it was actually pretty easy.
I also updated it to use the AngelscriptUtils library for utility code.

A whole lot of refactoring and cleanup later, i also implemented basic syntax highlight support (regular expression matching, not quite perfect), asynchronous compilation (so the UI doesn't freeze) and advanced configuration support through the use of scripts.

It's still far from finished, but it was able to compile a complicated Sven Co-op script pack, so it's working pretty well so far. Eventually it'll be able to do everything you expect an IDE to do, but i don't have time to implement all of it right now.

You can download the latest release here: https://github.com/SamVanheer/AngelscriptIDE/releases

This relates to HLEnhanced because it has Angelscript support. I said in the past that i was going to write a code generator to handle that stuff automatically, which is part of the reason why i haven't exposed a bigger API.

And that brings me to my next project.

I just pushed 2 repositories on Github that contain what i've been working on for the past week and a half: a code generator (almost fully generic, has a few Angelscript references left in it) and an Angelscript code generator geared towards generating the code that registers the Angelscript API.

The basic idea behind this is to collect data from a project like HLEnhanced, translate it into its destination form, and then generate the resulting code.

The CodeGenerator library handles all of the grunt work, while the AngelscriptAPIGenerator program handles the nitty gritty details involving translation and generation.

This probably sounds pretty boring, so how about an example?

This is a function that is part of my test project:
* @brief TestFunction
* @param[ in ] input Input
* @param[ out ] output Output
* @return Value
int TestFunction( const Few& input, Few* output );
And this is the template used to specify the generated file:
#include <string>

#include <angelscript.h>

#include "{{&.}}"

void RegisterScriptAPI( asIScriptEngine& scriptEngine )
const std::string szOldNS = scriptEngine.GetDefaultNamespace();

{{! This reduces the number of namespace changes }}
scriptEngine.SetDefaultNamespace( "{{as.ns}}" );

	"{{#return_type}}{{> vardecl }}{{/return_type}} {{as.name}}("
		"{{> paramdecl}} {{as.name}}{{^last}},{{/last}}"
	asFUNCTION( {{cpp.ns}}::{{cpp.name}} ),


scriptEngine.SetDefaultNamespace( szOldNS.c_str() );


It gets turned into this:
#include <string>

#include <angelscript.h>

#include "Test1.h"

void RegisterScriptAPI( asIScriptEngine& scriptEngine )
const std::string szOldNS = scriptEngine.GetDefaultNamespace();

scriptEngine.SetDefaultNamespace( "Foo" );

	"int TestFunction("
		"const Foo::Few& in input,"
		"Foo::Few@ output"
	asFUNCTION( Foo::TestFunction ),

scriptEngine.SetDefaultNamespace( szOldNS.c_str() );


I've omitted parts of it since it would be far too large, but you get the idea.

Basically this will automate the entire process of registering the API. Handling for wrappers can be done automatically or using annotations that tell the generator where to look.

Eventually documentation will also be generated automatically. The documentation that you see above the function is extracted and formatted as XML:
<Function file="C:/Users/Sam/Documents/Programs/C++_Programs/AngelscriptAPIGenerator/test/test_sources/src/..\Test1.h" line="64" column="5">
<Declaration>int TestFunction(const Foo::Few &amp;input, Foo::Few *output)</Declaration>
	<Para> TestFunction
		<Direction isExplicit="1">in</Direction>
			<Para> Input     </Para>
		<Direction isExplicit="1">out</Direction>
			<Para> Output        </Para>
	<Para> Value</Para>

Once a translation is performed on this, it will provide Angelscript documentation as well. And because it's Doxygen standard documentation, the same tools that can take Doxygen documentation can also be used as a basis for Angelscript documentation.

The same information can also be used to generate wrapper classes for custom entity support.

So once this is done, it'll automate the vast majority of Angelscript development. You can just include a couple generation calls in your CMake setup and it autogenerates everything when you click on Build.

There's still a bit of work left to be done before that's possible, but most of it is already there.

I'm sure this all looks like Chinese to most of you, but i felt like explaining how this works. It was pretty fun (and frustrating!) to work on, but it's worth the effort in the end.
Posted 9 months ago2017-08-25 18:21:26 UTC Post #337049
Some minor updates have been applied:
  • GCC 7 support
  • AppVeyor & Travis configs have been updated to match recent changes to their virtual machines
  • Removed unused VGUI class ControlConfigPanel
  • Fixed CString::FindLastNotOf not using the compare parameter as it should
  • Fixed a whole bunch of warnings emitted by MSVC and GCC at the highest warning level
  • Set the warning level to 4 and treat warnings as errors for client, hl, tier1 and vgui2_controls projects. This catches many problems automatically
  • Recompiled the Windows MariaDB library with PDB generation enabled to fix warnings in debug builds due to missing debug data. Also set the server library to link with networking libraries to ensure that new dependencies are resolved. See https://github.com/SamVanheer/HLEnhanced/wiki/Compiling-MariaDB-for-HLEnhanced for instructions on building MariaDB in similar fashion if needed
All projects now compile with no warnings using MSVC and GCC, Clang emits some warnings, but since it's only used for Mac it's not an immediate issue. I can fix the remaining warnings easily enough if needed.

I've also been planning to add a new feature that should deal with some hardcoded features being impossible to extend/modify/disable/remove. I've written up a description for how it should work here: https://github.com/SamVanheer/HLEnhanced/wiki/Entity-class-properties

This is not final, and if anybody has suggestions or ideas i'd be happy to hear them.

The idea behind this is to remove most if not all of the hardcoded behavior, such as the example shown with the Barnacle Grapple. This would give you much greater control over gameplay than has previously been possible.

To avoid cluttering the codebase with file parsers and data structures all existing features that currently use KeyValues and are fully implemented in game code will be transitioned to XML as well.

It should use the same basic syntax as entity class properties, though specific tags may be used, such as a cvar tag for map configs that set specific cvars.

To give a simple example, you could use this to globally alter the default setting for barnacle grapple interaction to make every entity attachable and pullable. You could pull doors, breakables, etc, though i can't promise the engine won't kill itself when that happens :P
Posted 9 months ago2017-08-25 20:20:53 UTC Post #337054
This idea sounds a lot like Doom 3 scripting - engine has a base framework for entities and you write the logic in .script file, which is simply a text file with basic C++ syntax and tags. I don't know which parts of the engine code are responsible for calling scripts and their syntax though, but they're stripped down C++.

Bringing similar system to GoldSource would be really neat. Checking Doom 3 sources might show you how id did it, I'll have to check the code when I'll have more time and post if I find something.
Posted 9 months ago2017-08-26 07:18:53 UTC Post #337063
I looked at Doom 3 scripting and it's closer to Angelscript than what i'm suggesting here. This system is purely for configuration, no actual logic is used here.
The actual logic would be implemented in either C++ or Angelscript, but it would use the property values instead of hardcoded ones.

For example, the Grapple uses this code to determine which surfaces it can attach to: https://github.com/SamVanheer/HLEnhanced/blob/master/game/shared/entities/weapons/CBarnacleGrappleTip.cpp#L253

With properties it would look more like this:
auto pProps = this->GetProp( "textures" );
if( pProps )
for( auto pTex = pProps->GetFirstSubValue(); pTex; pTex = pTex->GetNextValue() )
if( glob_match( pTex->GetString( "texture" ), pTexture->name ) )
bIsFixed = true;
You'd query the entity's properties for the textures property, then iterate over its child values to find a matching texture name, if any.
Posted 9 months ago2017-08-27 19:17:15 UTC Post #337109
So it'd be more like: entity is defined in dll. It's base definition, tags, parts of code that won't really need to be configurable are hardcoded. Parts that would be configurable will be in the the xml - functions and calls allowing the code from xml to be read and executed would be hardcoded as well.

I guess there is a way to code in some framework that'd search for xml files and execute code stored in them. This'll be longer and probably harder to code, but it'd be less tedious than writing code for it on every entity.
Posted 9 months ago2017-08-27 20:04:53 UTC Post #337113
There won't be any code in XML, it's purely for configuration. Angelscript would be used for actual code if extensibility is needed.
Posted 9 months ago2017-08-27 23:34:13 UTC Post #337118
And can I ask about Angelscript with vgui? I thought in game with gui like CStrike Team selector or Buy screen can load from our map into Sven Coop or Angelscript mod. I am asking about gui into game. But they say no support. Do you plan gui into in-game with Angelscript? Is it possible?
Posted 9 months ago2017-08-28 05:31:13 UTC Post #337125
Eventually there'll be client side scripting that will include the ability to make VGUI2 widgets. That'll take some doing though. To implement this properly engine level support is needed, so i'd either need some workarounds or engine access.
Posted 9 months ago2017-08-28 07:16:21 UTC Post #337130
Hopefully you can get success if vgui2 widgets load from Angelscript.
Posted 9 months ago2017-09-01 07:50:40 UTC Post #337207
We just had a discussion in Gitter about implementing a form of parenting, there may be a way to do Source style parenting where the physics code uses relative origins and updates positions more smoothly:

Basically, all physics is disabled for entities and physics is handled in StartFrame instead, which is called right at the start of physics calls: https://github.com/id-Software/Quake/blob/bf4ac424ce754894ac8f1dae6a3981954bc9852d/QW/server/sv_phys.c#L893

SV_ProgStartFrame is gEntityInterface.pfnStartFrame() in GoldSource, and would let us run the physics code ourselves.
We can reimplement the physics code easily enough (mostly the same as Quake), directly call CBaseEntity methods (slightly more efficient than using function pointers that wrap CBaseEntity calls), fix some bugs in the physics code and add more features if needed (custom physics calls).

Most importantly, this'll let us rework how movement works by letting us use relative origins with parents to map the coordinates to. It should allow for smooth parenting in this engine, though we won't know for sure if this will work until we try it.

Other parts of the engine may rely on the physics settings (e.g. tracelines) so we'd have to reimplement those as well, and there's no easy way to get the model data in the server without relying on workarounds that may or may not work after engine updates.

I'd have to reimplement most of the physics code to do this fully, though it would make life a lot easier when dealing with bugs or missing features.
Posted 9 months ago2017-09-01 10:58:01 UTC Post #337210
Source style parenting on GS would be really neat. Looks like the list of what could be enhanced in the engine is still growing...
Posted 9 months ago2017-09-01 10:58:52 UTC Post #337211
That sounds great! Hope it works out.
Strider StriderTuned to a dead channel.
You must be logged in to post a response.