Update extra AMXX plugins.

This commit is contained in:
Giegue
2023-04-29 01:58:47 -03:00
parent ba9414ea6e
commit 92d14a6fd3
5 changed files with 457 additions and 0 deletions

View File

@@ -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.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,232 @@
#pragma semicolon 1
#include <amxmodx>
#include <engine>
#include <fakemeta>
#include <hamsandwich>
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;
}

View File

@@ -0,0 +1,204 @@
#pragma semicolon 1
#include <amxmodx>
#include <engine>
#include <fakemeta>
#include <hamsandwich>
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 );
}
}
}
}
}