From 92d14a6fd33645bd095dd48efccc2edeba45bcf3 Mon Sep 17 00:00:00 2001 From: Giegue Date: Sat, 29 Apr 2023 01:58:47 -0300 Subject: [PATCH] Update extra AMXX plugins. --- extra/valve/README.md | 21 +++ extra/valve/bin/hl_extra_keyvalues.amxx | Bin 0 -> 4080 bytes extra/valve/bin/hl_soundlist.amxx | Bin 0 -> 4415 bytes extra/valve/src/hl_extra_keyvalues.sma | 232 ++++++++++++++++++++++++ extra/valve/src/hl_soundlist.sma | 204 +++++++++++++++++++++ 5 files changed, 457 insertions(+) create mode 100644 extra/valve/bin/hl_extra_keyvalues.amxx create mode 100644 extra/valve/bin/hl_soundlist.amxx create mode 100644 extra/valve/src/hl_extra_keyvalues.sma create mode 100644 extra/valve/src/hl_soundlist.sma diff --git a/extra/valve/README.md b/extra/valve/README.md index 1b063f8..171cff3 100644 --- a/extra/valve/README.md +++ b/extra/valve/README.md @@ -17,3 +17,24 @@ MonsterMod monsters are hacked "func_wall"'s with simulated AI. Because of this, In simple terms, this plugin acts as a "bridge" to help Half-Life and MonsterMod communicate with each other. With this plugin, HL and MM monsters can "see" and interact with each other, and will react accordingly. Without this plugin, HL and MM monsters will be "invisible" to each other. + +#### Soundlist + +This plugin allows you to use the "soundlist" keyvalue in HL monsters to individually replace monster sounds. Path starts from `sound/MAPNAME`. Use `../` to go to the previous directory if needed. + +The plugin can work standalone, meaning it can be used without MonsterMod. + +#### Extra Keyvalues + +**"Bridge Plugin" is REQUIRED for this add-on to work** + +This plugin allows you use the following keyvalues on HL monsters: + +- classify +- is_player_ally *(non-monstermaker entities)* +- bloodcolor +- respawn_as_playerally *(monstermaker entity)* + +The plugin also adds a 5th keyvalue, **"use_monstermod"**. When reading entities from the BSP file, if MonsterMod finds an entity that already exists in the game, it will stick to the game entity and ignore it. By setting this keyvalue to "1", it will explicity use MonsterMod for this entity. + +This is useful when, for example, you are trying to spawn a Pit Drone from a monstermaker. HL does not recognize monster_pitdrone, but MonsterMod does. By redirecting the entity to MonsterMod, Pit Drones will spawn from this monstermaker. diff --git a/extra/valve/bin/hl_extra_keyvalues.amxx b/extra/valve/bin/hl_extra_keyvalues.amxx new file mode 100644 index 0000000000000000000000000000000000000000..1a8e8fa62e1865beb119e18349b72a48f7064fc9 GIT binary patch literal 4080 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 literal 0 HcmV?d00001 diff --git a/extra/valve/bin/hl_soundlist.amxx b/extra/valve/bin/hl_soundlist.amxx new file mode 100644 index 0000000000000000000000000000000000000000..b2fb6cbbfe1493a8b26a24e4fec025584a421276 GIT binary patch literal 4415 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 Ff|sFl3L*di literal 0 HcmV?d00001 diff --git a/extra/valve/src/hl_extra_keyvalues.sma b/extra/valve/src/hl_extra_keyvalues.sma new file mode 100644 index 0000000..3b6ab21 --- /dev/null +++ b/extra/valve/src/hl_extra_keyvalues.sma @@ -0,0 +1,232 @@ +#pragma semicolon 1 + +#include +#include +#include +#include + +const bits_MEMORY_SPAWN = ( 1 << 1 ); + +const BLOOD_COLOR_BLUE = 211; +const BLOOD_COLOR_PINK = 147; +const BLOOD_COLOR_WHITE = 11; +const BLOOD_COLOR_ORANGE = 231; +const BLOOD_COLOR_BLACK = 49; // not 100% black but close enough +const BLOOD_COLOR_DARKGREEN = 181; // GREEN is aliased to YELLOW, use custom name + +public plugin_init() +{ + register_plugin( "HL-MONSTER Extra Keyvalues", "1.0", "Giegue" ); + + /* CLASSIFY */ + // HACK: since Ham_Spawn won't work, this should do as an alternative + RegisterHam( Ham_SetObjectCollisionBox, "monster_headcrab", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_babycrab", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_bullchicken", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_barnacle", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_bigmomma", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_houndeye", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_alien_slave", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_alien_controller", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_alien_grunt", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_zombie", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_ichthyosaur", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_human_grunt", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_human_assassin", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_barney", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_gman", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_scientist", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_sentry", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_snark", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_miniturret", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_turret", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_apache", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_osprey", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_gargantua", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_nihilanth", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_tentacle", "MonsterSpawn_Post", 1 ); + + /* BLOODCOLOR */ + RegisterHam( Ham_BloodColor, "monster_headcrab", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_babycrab", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_bullchicken", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_barnacle", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_bigmomma", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_houndeye", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_alien_slave", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_alien_controller", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_alien_grunt", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_zombie", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_ichthyosaur", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_human_grunt", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_human_assassin", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_barney", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_gman", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_scientist", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_sentry", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_snark", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_miniturret", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_turret", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_apache", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_osprey", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_gargantua", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_nihilanth", "MonsterBlood" ); + RegisterHam( Ham_BloodColor, "monster_tentacle", "MonsterBlood" ); + + // "use_monstermod" keyvalue + register_cvar( "_hl_explicit", "1" ); +} + +public plugin_precache() +{ + register_forward( FM_KeyValue, "ScanKeys" ); +} + +public ScanKeys( entid, kvd_handle ) +{ + if (is_valid_ent(entid)) + { + static classname[ 33 ], keyname[ 33 ], value[ 128 ]; + get_kvd( kvd_handle, KV_ClassName, classname, charsmax( classname ) ); + + // Monsters + if ( equal( classname, "monster_", 8 ) ) + { + get_kvd( kvd_handle, KV_KeyName, keyname, charsmax( keyname ) ); + get_kvd( kvd_handle, KV_Value, value, charsmax( value ) ); + + // Classification override + if ( equal( keyname, "classify" ) ) + entity_set_int( entid, EV_INT_iuser4, str_to_num( value ) ); + + // Allied monster + if ( equal( keyname, "is_player_ally" ) ) + { + if ( str_to_num( value ) ) + entity_set_int( entid, EV_INT_iuser4, 11 ); // CLASS_PLAYER_ALLY + } + + // Custom blood color + if ( equal( keyname, "bloodcolor" ) ) + { + switch ( str_to_num( value ) ) + { + case -1: entity_set_int( entid, EV_INT_iuser3, DONT_BLEED ); + // 0 = Monster Default + case 1: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_RED ); + case 2: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_YELLOW ); + case 3: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_BLUE ); + case 4: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_PINK ); + case 5: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_WHITE ); + case 6: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_ORANGE ); + case 7: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_BLACK ); + case 8: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_DARKGREEN ); + } + } + + // Redirect entity to MonsterMod + if ( equal( keyname, "use_monstermod" ) ) + { + if ( str_to_num( value ) ) + { + // MonsterMod will inherit this entity, remove it from here + remove_entity( entid ); + return FMRES_SUPERCEDE; + } + } + + return FMRES_IGNORED; + } + // Monster Makers + else if ( equal( classname, "monstermaker" ) ) + { + get_kvd( kvd_handle, KV_KeyName, keyname, charsmax( keyname ) ); + get_kvd( kvd_handle, KV_Value, value, charsmax( value ) ); + + // Classification override + if ( equal( keyname, "classify" ) ) + entity_set_int( entid, EV_INT_iuser4, str_to_num( value ) ); + + // Allied monster + if ( equal( keyname, "respawn_as_playerally" ) ) + { + if ( str_to_num( value ) ) + entity_set_int( entid, EV_INT_iuser4, 11 ); // CLASS_PLAYER_ALLY + } + + // Custom blood color + if ( equal( keyname, "bloodcolor" ) ) + { + switch ( str_to_num( value ) ) + { + case -1: entity_set_int( entid, EV_INT_iuser3, DONT_BLEED ); + // 0 = Monster Default + case 1: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_RED ); + case 2: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_YELLOW ); + case 3: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_BLUE ); + case 4: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_PINK ); + case 5: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_WHITE ); + case 6: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_ORANGE ); + case 7: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_BLACK ); + case 8: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_DARKGREEN ); + } + } + + // Redirect entity to MonsterMod + if ( equal( keyname, "use_monstermod" ) ) + { + if ( str_to_num( value ) ) + { + // MonsterMod will inherit this entity, remove it from here + remove_entity( entid ); + return FMRES_IGNORED; // not a typo, must not supercede or it will crash + } + } + + return FMRES_IGNORED; + } + } + + return FMRES_IGNORED; +} + +public MonsterSpawn_Post( entity ) +{ + // Why is it called 3 times? Restrict this to only once + if ( !( entity_get_int( entity, EV_INT_impulse ) & bits_MEMORY_SPAWN ) ) + { + // monstermaker sets owner after monster spawn, wait next frame + set_task( 0.000001, "MakerSpawn_Post", entity ); + + entity_set_int( entity, EV_INT_impulse, entity_get_int( entity, EV_INT_impulse ) | bits_MEMORY_SPAWN ); + } +} + +public MakerSpawn_Post( entity ) +{ + if ( is_valid_ent( entity ) ) + { + static owner; + owner = entity_get_edict( entity, EV_ENT_owner ); + if ( owner ) + { + // pass parent configurations to child entity + entity_set_int( entity, EV_INT_iuser4, entity_get_int( owner, EV_INT_iuser4 ) ); // classify + entity_set_int( entity, EV_INT_iuser3, entity_get_int( owner, EV_INT_iuser3 ) ); // bloodcolor + } + } +} + +public MonsterBlood( entity ) +{ + static newBlood; + newBlood = entity_get_int( entity, EV_INT_iuser3 ); + + if ( newBlood ) + { + SetHamReturnInteger( newBlood ); + return HAM_OVERRIDE; + } + + return HAM_IGNORED; +} diff --git a/extra/valve/src/hl_soundlist.sma b/extra/valve/src/hl_soundlist.sma new file mode 100644 index 0000000..3fb08e4 --- /dev/null +++ b/extra/valve/src/hl_soundlist.sma @@ -0,0 +1,204 @@ +#pragma semicolon 1 + +#include +#include +#include +#include + +const bits_MEMORY_SOUNDLIST = ( 1 << 3 ); +new Trie:m_Sounds; + +public plugin_init() +{ + register_plugin( "HL-MONSTER Soundlist", "1.0", "Giegue" ); + + /* STOP DUPLICATING CODE FFS */ + RegisterHam( Ham_SetObjectCollisionBox, "monster_headcrab", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_babycrab", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_bullchicken", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_barnacle", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_bigmomma", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_houndeye", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_alien_slave", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_alien_controller", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_alien_grunt", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_zombie", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_ichthyosaur", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_human_grunt", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_human_assassin", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_barney", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_gman", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_scientist", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_sentry", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_snark", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_miniturret", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_turret", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_apache", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_osprey", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_gargantua", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_nihilanth", "MonsterSpawn_Post", 1 ); + RegisterHam( Ham_SetObjectCollisionBox, "monster_tentacle", "MonsterSpawn_Post", 1 ); +} + +public plugin_end() +{ + if ( m_Sounds ) + TrieDestroy( m_Sounds ); +} + +// has to be in precache or it won't work +public plugin_precache() +{ + // check individual monster soundlists + register_forward( FM_KeyValue, "ScanSL" ); +} + +public ScanSL( entid, kvd_handle ) +{ + if (is_valid_ent(entid)) + { + static classname[ 33 ], keyname[ 33 ], value[ 128 ]; + get_kvd( kvd_handle, KV_ClassName, classname, charsmax( classname ) ); + + // Monsters + if ( equal( classname, "monster_", 8 ) ) + { + get_kvd( kvd_handle, KV_KeyName, keyname, charsmax( keyname ) ); + get_kvd( kvd_handle, KV_Value, value, charsmax( value ) ); + + // Individual sound replacement + if ( equal( keyname, "soundlist" ) ) + { + ProcessSoundList( entid, value ); + } + + return FMRES_IGNORED; + } + // Monster Makers + else if ( equal( classname, "monstermaker" ) ) + { + get_kvd( kvd_handle, KV_KeyName, keyname, charsmax( keyname ) ); + get_kvd( kvd_handle, KV_Value, value, charsmax( value ) ); + + // Children sound list + if ( equal( keyname, "soundlist" ) ) + { + ProcessSoundList( entid, value ); + } + + return FMRES_IGNORED; + } + } + + return FMRES_IGNORED; +} + +public ProcessSoundList( entity, const filename[] ) +{ + // First time? + if ( !m_Sounds ) + m_Sounds = TrieCreate(); + + new fullPath[ 129 ]; + + new mapName[ 33 ], pFile; + get_mapname( mapName, charsmax( mapName ) ); + + // path always starts from sound/[MAPNAME] (SC behaviour) + formatex( fullPath, charsmax( fullPath ), "sound/%s/%s", mapName, filename ); + pFile = fopen( fullPath, "r" ); + if ( pFile ) + { + new line[ 258 ], soundSrc[ 129 ], soundDest[ 129 ]; + + while ( fgets( pFile, line, charsmax( line ) ) ) + { + // Replace newlines + replace_all( line, charsmax( line ), "^n", "" ); + + // Ignore blank lines + if ( !line[ 0 ] ) continue; + + // source --> destination + parse( line, soundSrc, charsmax( soundSrc ), soundDest, charsmax( soundDest ) ); + + // Precache destination sound + // HACK: precache_sound outside of plugin_precache + engfunc( EngFunc_PrecacheSound, soundDest ); + + // HACK: prepend the entityID at the beginning of the soundSrc for later identification + format( soundSrc, charsmax( soundSrc ), "%i#%s", entity, soundSrc ); + + TrieSetString( m_Sounds, soundSrc, soundDest ); + entity_set_int( entity, EV_INT_impulse, entity_get_int( entity, EV_INT_impulse ) | bits_MEMORY_SOUNDLIST ); + } + + fclose( pFile ); + + // file could be empty + if ( TrieGetSize( m_Sounds ) ) + { + register_forward( FM_EmitSound, "ReplaceSound" ); + } + } +} + +public ReplaceSound( entity, channel, const sample[], Float:volume, Float:attn, flags, pitch ) +{ + static newSound[ 129 ]; + + // replace monster sound? + if ( entity_get_int( entity, EV_INT_impulse ) & bits_MEMORY_SOUNDLIST ) + { + // get entityID + static owner, entid; + owner = entity_get_edict( entity, EV_ENT_owner ); + if ( owner ) + entid = owner; + else + entid = entity; + + // get sound + static searchSound[ 129 ]; + formatex( searchSound, charsmax( searchSound ), "%i#%s", entid, sample ); + + // if found, stick to that one + if ( TrieGetString( m_Sounds, searchSound, newSound, charsmax( newSound ) ) ) + { + // emit new sound and supercede this one + emit_sound( entity, channel, newSound, volume, attn, flags, pitch ); + return FMRES_SUPERCEDE; + } + } + + return FMRES_IGNORED; +} + +/* extra_keyvalues.sma duplication */ +public MonsterSpawn_Post( entity ) +{ + // monstermaker sets owner after monster spawn, wait next frame + set_task( 0.000001, "MakerSpawn_Post", entity ); +} + +public MakerSpawn_Post( entity ) +{ + if ( is_valid_ent( entity ) ) + { + static owner; + owner = entity_get_edict( entity, EV_ENT_owner ); + if ( owner ) + { + // monstermaker has soundlist defined? + if ( entity_get_int( owner, EV_INT_impulse ) & bits_MEMORY_SOUNDLIST ) + { + // 3 time call + if ( !( entity_get_int( entity, EV_INT_impulse ) & bits_MEMORY_SOUNDLIST ) ) + { + // this monster is to use sound replacements + entity_set_int( entity, EV_INT_impulse, entity_get_int( entity, EV_INT_impulse ) | bits_MEMORY_SOUNDLIST ); + } + } + } + } +}