untyped globalize_all_functions struct { table < entity, array< void functionref( entity weapon, WeaponPrimaryAttackParams attackParams, var ammoUsed ) > > weaponCallbacks table < string, array< void functionref( entity weapon, WeaponPrimaryAttackParams attackParams, var ammoUsed ) > > weaponClassCallbacks table < string, array< void functionref( entity weapon, WeaponPrimaryAttackParams attackParams, var ammoUsed ) > > ownerClassCallbacks bool clearThreadRunning = false // Only used on client } file void function WeaponFireCallbacks_AddCallbackOnWeaponFired( entity weapon, void functionref( entity weapon, WeaponPrimaryAttackParams attackParams, var ammoUsed ) callback ) { if ( !IsValid( weapon ) ) return if ( weapon in file.weaponCallbacks ) file.weaponCallbacks[weapon].append( callback ) else file.weaponCallbacks[weapon] <- [callback] #if SERVER AddEntityDestroyedCallback( weapon, WeaponFireCallbacks_HandleWeaponDestroyed ) #else // Per-entity destroyed callbacks don't exist on client. Client needs to clear invalid keys periodically. if ( !file.clearThreadRunning ) thread ClearInvalidWeaponsThread() #endif } void function WeaponFireCallbacks_AddCallbackOnWeaponClassFired( string weaponClass, void functionref( entity weapon, WeaponPrimaryAttackParams attackParams, var ammoUsed ) callback ) { if ( weaponClass in file.weaponClassCallbacks ) file.weaponClassCallbacks[weaponClass].append( callback ) else file.weaponClassCallbacks[weaponClass] <- [callback] } void function WeaponFireCallbacks_RemoveCallbackOnWeaponClassFired( string weaponClass, void functionref( entity weapon, WeaponPrimaryAttackParams attackParams, var ammoUsed ) callback ) { if ( weaponClass in file.weaponClassCallbacks ) { file.weaponClassCallbacks[weaponClass].fastremovebyvalue( callback ) if ( file.weaponClassCallbacks[weaponClass].len() == 0 ) delete file.weaponClassCallbacks[weaponClass] } } void function WeaponFireCallbacks_AddCallbackOnOwnerClassFired( string ownerClass, void functionref( entity weapon, WeaponPrimaryAttackParams attackParams, var ammoUsed ) callback ) { if ( ownerClass in file.ownerClassCallbacks ) file.ownerClassCallbacks[ownerClass].append( callback ) else file.ownerClassCallbacks[ownerClass] <- [callback] } void function WeaponFireCallbacks_RemoveCallbackOnOwnerClassFired( string ownerClass, void functionref( entity weapon, WeaponPrimaryAttackParams attackParams, var ammoUsed ) callback ) { if ( ownerClass in file.ownerClassCallbacks ) { file.ownerClassCallbacks[ownerClass].fastremovebyvalue( callback ) if ( file.ownerClassCallbacks[ownerClass].len() == 0 ) delete file.ownerClassCallbacks[ownerClass] } } function WeaponFireCallbacks_HandleWeaponDestroyed( weapon ) { entity w = expect entity( weapon ) if ( w in file.weaponCallbacks ) delete file.weaponCallbacks[w] } #if CLIENT void function ClearInvalidWeaponsThread() { file.clearThreadRunning = true while( file.weaponCallbacks.len() > 0 ) { array< entity > invalidList = [] foreach( key, callback in file.weaponCallbacks ) { if ( !IsValid( key ) ) invalidList.append( key ) } foreach( w in invalidList ) delete file.weaponCallbacks[w] wait 1.0 // Some arbitrary number that isn't WaitFrame(), don't need to run this very often } file.clearThreadRunning = false } #endif void function WeaponFireCallbacks_OnWeaponFired( entity weapon, WeaponPrimaryAttackParams attackParams, var ammoUsed ) { if ( weapon in file.weaponCallbacks ) { array< void functionref( entity weapon, WeaponPrimaryAttackParams attackParams, var ammoUsed ) > callbacks = file.weaponCallbacks[weapon] foreach ( callback in callbacks ) callback( weapon, attackParams, ammoUsed ) } string weaponClass = weapon.GetWeaponClassName() if ( weaponClass in file.weaponClassCallbacks ) { array< void functionref( entity weapon, WeaponPrimaryAttackParams attackParams, var ammoUsed ) > callbacks = file.weaponClassCallbacks[weaponClass] foreach ( callback in callbacks ) callback( weapon, attackParams, ammoUsed ) } entity owner = weapon.GetWeaponOwner() if ( !IsValid( owner ) ) return string ownerClass = owner.GetClassName() if ( ownerClass in file.ownerClassCallbacks ) { array< void functionref( entity weapon, WeaponPrimaryAttackParams attackParams, var ammoUsed ) > callbacks = file.ownerClassCallbacks[ownerClass] foreach ( callback in callbacks ) callback( weapon, attackParams, ammoUsed ) } } var function WeaponFireCallbacks_OnWeaponPrimaryAttack( entity weapon, WeaponPrimaryAttackParams attackParams ) { weapon.EmitWeaponNpcSound( LOUD_WEAPON_AI_SOUND_RADIUS_MP, 0.2 ) var result = weapon.FireWeaponBullet( attackParams.pos, attackParams.dir, 1, weapon.GetWeaponDamageFlags() ) if ( result == 0 ) return 0 WeaponFireCallbacks_OnWeaponFired( weapon, attackParams, result ) return result } #if SERVER var function WeaponFireCallbacks_OnWeaponNpcPrimaryAttack( entity weapon, WeaponPrimaryAttackParams attackParams ) { weapon.EmitWeaponNpcSound( LOUD_WEAPON_AI_SOUND_RADIUS_MP, 0.2 ) var result = weapon.FireWeaponBullet( attackParams.pos, attackParams.dir, 1, weapon.GetWeaponDamageFlags() ) if ( result == 0 ) return 0 WeaponFireCallbacks_OnWeaponFired( weapon, attackParams, result ) return result } #endif