Progress on the Unified SDK
SDK Changes
- Fixed mouse movement during map load affecting initial view angles (caused the player to look to the side instead of straight ahead)
- Set
monster_rosenberg
model to correct default (was still using scientist.mdl
)
- Overhauled entity classification system (see below)
- Implemented
is_player_ally
keyvalue
- Fire
monstermaker
target after NPC spawning is done instead of after NPC creation and before spawning
- Re-implemented
UTIL_FindEntityBy*
functions to avoid calling engine function (see below)
- Implemented wildcard matching for entity classname, targetname & target searches
- Implemented
point_teleport
- Added
initial_capacity
keyvalue to Osprey NPCs to allow specifying how many grunts/assassins to deploy instead of relying on existing NPCs in the map to influence calculations (max 24)
- Implemented targeting laser in all
func_tank
entities
- Fixed
func_tank
entities not returning player weapon control when killtargeted
- Prevent engine precache limit from being reached (game will no longer tell engine to precache a resource if doing so would cause the limit to be exceeded)
- Implemented target selector support for target, killtarget & point_teleport (see below)
- Always store activator on delay trigger to allow access to initial activator entity in delayed trigger setups
- Ensure turret NPCs finish dying so they don't keep running dying logic forever if killed during first activation
- Fire Death trigger condition when turret NPCs are destroyed
- Install additional 32 bit Linux dependencies when running Linux CI (needed because Github Actions has updated its default Linux environment)
- Implemented Counter-Strike style
env_fog
- Play hud & geiger sounds on unique channels to avoid preempting game sounds (geiger used to cause sounds to cut out)
Asset changes
- Add default entity classifications config file
- Added new keyvalues to fgd
- Added
point_teleport
and env_fog
entities to fgd
- Cleaned up fgd a bit to remove non-existent functionaltiy and properly hint to level editor how to use certain keyvalues
- Added source files for
class_signs.wad
(contains textures stating NPC names)
- Added
zoo_npcs
map
- Added Half-Life Uplink demo sentences & titles entries
C# Changes
- Fixed flare sprites in
c4a3
(Nihilanth boss battle death script) using wrong render mode
- Fixed grunt on stretcher holding gun in
of1a1
(Opposing Force "Welcome To Black Mesa" map)
- Clear
model
keyvalue for monster_rosenberg
(defaults to correct model in code now)
- Copy Uplink maps from
valve_uplink
directory
Entity classification changes
The entity classification system has been redesigned for comfort and utility. Previously this was a hard-coded table defining the relationship between entity classifications.
You can think of a classification as a faction. The
human_passive
classification (Black Mesa scientists) fears
human_military
(Human Grunts) and will run away from them.
human_military
dislikes
human_passive
and will attack them.
This is now defined in a configuration file:
{
// Class none is always added and should only have relationship "none" (default) to all classes.
"none": {},
"machine": {
"Relationships": {
"player": "dislike",
"human_passive": "dislike",
"human_military": "none",
"alien_military": "dislike",
"alien_passive": "dislike",
"alien_monster": "dislike",
"alien_prey": "dislike",
"alien_predator": "dislike",
"player_ally": "dislike",
"player_bioweapon": "dislike",
"alien_bioweapon": "dislike",
"human_military_ally": "dislike",
"race_x": "dislike"
}
},
"player": {
"Relationships": {
"machine": "dislike",
"human_military": "dislike",
"alien_military": "dislike",
"alien_passive": "dislike",
"alien_monster": "dislike",
"alien_prey": "dislike",
"alien_predator": "dislike",
"player_bioweapon": "dislike",
"alien_bioweapon": "dislike",
"race_x": "dislike"
}
},
"human_passive": {
"Relationships": {
"player": "ally",
"human_passive": "ally",
"human_military": "hate",
"alien_military": "hate",
"alien_monster": "hate",
"alien_prey": "dislike",
"alien_predator": "dislike",
"player_ally": "ally",
"human_military_ally": "dislike",
"race_x": "hate"
}
},
// More classifications here
}
As usual it can be overridden on a per-map basis, though it only supports a single file per map.
The default classification used by NPCs now uses these names instead of a hard-coded index.
Notable changes to existing classifications:
- added
alien_flora
classification for Xen trees and large spores (replaces CLASS_BARNACLE
which wasn't used by barnacles and was never used because it would cause the class table to be accessed out of bounds)
- Added
IsMachine
method to determine whether an entity is a machine of some kind (e.g. Osprey, turrets)
- Added
IsBioWeapon
method to determine whether an entity is a bioweapon of some kind (e.g. Snarks, Penguins, Hornets)
- Changed
RadiusDamage
and FlameDamage
methods to take ignore class as last parameter to allow it to be defaulted to "none"
- Changed squad monster code to use
CanRecruit
function to determine whether a candidate entity can be recruited into the current squad monster's squad
- Changed human grunts, allied human grunts and shock trooper squad dialogue to only identify enemies as monsters if they have alien gibs (previously entities that are not players, player allies, human passive or machines were considered to be monsters)
- Changed Snarks and Penguins to change their classification when they update their enemy instead of doing so when their classification is requested (avoids possible recursion). They will not do so if they are using a custom classification.
Two new keyvalues have been added:
classification
: If defined, changes the NPC's classification to the specified class (must be one named in the map's classification config file). The new entity templates feature can be used to apply this to every instance of a specific type of NPC in a map. The new target selector feature (see below) can be used to change the player's classification.
is_player_ally
: Has three possible values: Default, No and Yes. Default uses the relationship from the NPC's class to the player's class defined in the map's classification config file. No equals dislike
(will attack), Yes equals ally
.
The classification system changes are not done yet. More work is needed before it works as intended but this covers the majority of the work required.
Entity lookup changes
The functions used to look up entities by classname, targetname and target have been re-implemented in game code. Previously they asked the engine to find entities.
Doing so makes these functions more efficient, not only by eliminating a function pointer call but also because the engine uses an inefficient lookup method. Every time the engine is asked it first looks up the address of the variable used to perform comparisons which slows things down.
The new implementation uses a callback to indicate which variable to use. Analysis of compiled release builds shows that the callback does not exist at all so there is no overhead involved with selecting the variable anymore.
In addition these functions now accept wildcards just like source. So you can for instance trigger all entities that start with a specific prefix:
"target" "class_sprite_*"
Just like Source it only accepts wildcards at the end.
It is now also possible to use target selectors in some cases. For example you can kill the activator of a trigger like this:
"killtarget" "!activator"
Unfortunately some entities don't pass activators along properly, like
trigger_relay
which passes itself instead.
Two target selectors are supported:
!activator
: The entity that started the current trigger execution
!caller
: The last entity in the trigger execution chain
Teleport entities changes
trigger_teleport
now has a
fire_on_teleport
target fired whenever it teleports an entity. Useful for triggering effects and whatnot.
The new
point_teleport
entity can be used to teleport a targeted entity to the
point_teleport
entity's position. To teleport the entity that activated it (like a player pressing a button that triggers the teleport entity) the
!activator
target selector can be used.
It also has a
fire_on_teleport
keyvalue.
func_tank changes
All tank entities now correctly restore the player's weapon if they are killtargeted. Previously this left the player in an invalid state where the weapon HUD was disabled.
Tanks now also have a target laser visible only to the player that is currently using it.
This laser is enabled only if turned on with the
enable_target_laser
keyvalue and can use a designer-configured sprite, width and color.
env_fog
Counter-Strike's
env_fog
entity has been implemented here as well. This entity allows the addition of fog with configurable density, start and stop distances, color and the option to also affect the skybox.
The TWHL and VDC wikis have been updated to include missing keyvalues and spawnflags for this entity.
Note that fog only renders when using the OpenGL renderer. This uses the engine's fog rendering code, not custom OpenGL code.
Hud & geiger sound changes
HUD sounds (weapon selection HUD & chat text) now play on a dedicated sound channel, as do geiger sounds. Previously these played on the player's item channel which is also used for things like weapon reloading. Since the geiger plays very often when near a radiation source it kept cutting off the sounds. This is no longer the case.
--> Continued in next post