2014-08-04 10:05:55 +00:00
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
//
// Engine Module
//
2004-05-26 08:44:15 +00:00
# include "engine.h"
2004-05-26 05:15:40 +00:00
2004-08-11 12:17:39 +00:00
BOOL CheckForPublic ( const char * publicname ) ;
2015-06-11 14:08:46 +00:00
void CreateDetours ( ) ;
void DestroyDetours ( ) ;
CDetour * LightStyleDetour = NULL ;
2015-10-06 22:10:48 +00:00
HLTypeConversion TypeConversion ;
2004-08-12 04:14:47 +00:00
2004-05-26 05:15:40 +00:00
int AmxStringToEngine ( AMX * amx , cell param , int & len )
{
char * szString = MF_GetAmxString ( amx , param , 0 , & len ) ;
2004-07-06 16:48:20 +00:00
return ALLOC_STRING ( szString ) ;
2004-05-26 05:15:40 +00:00
}
2004-09-08 21:43:50 +00:00
void ClearHooks ( )
2004-08-31 02:05:27 +00:00
{
2006-05-11 07:49:45 +00:00
size_t i ;
2005-07-14 04:50:46 +00:00
2014-08-09 18:30:31 +00:00
for ( i = 0 ; i < Touches . length ( ) ; i + + )
2004-08-31 02:05:27 +00:00
delete Touches [ i ] ;
2014-08-09 18:30:31 +00:00
for ( i = 0 ; i < Impulses . length ( ) ; i + + )
2004-08-31 02:05:27 +00:00
delete Impulses [ i ] ;
2014-08-09 18:30:31 +00:00
for ( i = 0 ; i < Thinks . length ( ) ; i + + )
2004-08-31 02:05:27 +00:00
delete Thinks [ i ] ;
2005-07-14 04:50:46 +00:00
2004-08-31 02:05:27 +00:00
Touches . clear ( ) ;
Impulses . clear ( ) ;
Thinks . clear ( ) ;
}
2004-05-26 05:15:40 +00:00
void OnAmxxAttach ( )
{
pfnTouchForward = 0 ;
pfnThinkForward = 0 ;
PlayerPreThinkForward = 0 ;
PlayerPostThinkForward = 0 ;
ClientKillForward = 0 ;
2013-07-02 22:19:12 +00:00
ClientImpulseForward = 0 ;
2013-07-02 23:00:52 +00:00
CmdStartForward = 0 ;
2004-05-26 05:15:40 +00:00
StartFrameForward = 0 ;
MF_AddNatives ( ent_Natives ) ;
2006-09-01 03:29:27 +00:00
MF_AddNewNatives ( ent_NewNatives ) ;
2004-05-26 05:15:40 +00:00
MF_AddNatives ( engine_Natives ) ;
2006-09-01 03:29:27 +00:00
MF_AddNewNatives ( engine_NewNatives ) ;
2004-05-26 05:15:40 +00:00
MF_AddNatives ( global_Natives ) ;
memset ( glinfo . szLastLights , 0x0 , 128 ) ;
memset ( glinfo . szRealLights , 0x0 , 128 ) ;
glinfo . bCheckLights = false ;
2015-06-11 14:08:46 +00:00
CreateDetours ( ) ;
}
void OnAmxxDetach ( )
{
DestroyDetours ( ) ;
2004-05-26 05:15:40 +00:00
}
void OnPluginsLoaded ( )
{
2015-10-06 22:10:48 +00:00
TypeConversion . init ( ) ;
2004-08-11 12:17:39 +00:00
g_CameraCount = 0 ;
pfnThinkForward = MF_RegisterForward ( " pfn_think " , ET_STOP , FP_CELL , FP_DONE ) ; // done
PlayerPreThinkForward = MF_RegisterForward ( " client_PreThink " , ET_STOP , FP_CELL , FP_DONE ) ; // done
PlayerPostThinkForward = MF_RegisterForward ( " client_PostThink " , ET_STOP , FP_CELL , FP_DONE ) ; // done
ClientKillForward = MF_RegisterForward ( " client_kill " , ET_STOP , FP_CELL , FP_DONE ) ; // done
2013-07-02 22:19:12 +00:00
ClientImpulseForward = MF_RegisterForward ( " client_impulse " , ET_STOP , FP_CELL , FP_CELL , FP_DONE ) ; // done
2013-07-02 23:00:52 +00:00
CmdStartForward = MF_RegisterForward ( " client_cmdStart " , ET_STOP , FP_CELL , FP_DONE ) ; // done
2004-08-11 12:17:39 +00:00
StartFrameForward = MF_RegisterForward ( " server_frame " , ET_IGNORE , FP_DONE ) ; // done
DispatchKeyForward = MF_RegisterForward ( " pfn_keyvalue " , ET_STOP , FP_CELL , FP_DONE ) ; // done
PlaybackForward = MF_RegisterForward ( " pfn_playbackevent " , ET_STOP , FP_CELL , FP_CELL , FP_CELL , FP_FLOAT , FP_ARRAY , FP_ARRAY , FP_FLOAT , FP_FLOAT , FP_CELL , FP_CELL , FP_CELL , FP_CELL , FP_DONE ) ; // done
2005-09-05 22:05:23 +00:00
SpawnForward = MF_RegisterForward ( " pfn_spawn " , ET_STOP , FP_CELL , FP_DONE ) ; // done
2004-08-11 12:17:39 +00:00
pfnTouchForward = MF_RegisterForward ( " pfn_touch " , ET_STOP , FP_CELL , FP_CELL , FP_DONE ) ; // done
VexdTouchForward = MF_RegisterForward ( " vexd_pfntouch " , ET_IGNORE , FP_CELL , FP_CELL , FP_DONE ) ; // done
VexdServerForward = MF_RegisterForward ( " ServerFrame " , ET_IGNORE , FP_DONE ) ; // done
// Reset all standard engine callbacks
// These will be reset through native calls, if need be
g_pFunctionTable - > pfnAddToFullPack = NULL ;
g_pFunctionTable - > pfnKeyValue = NULL ;
if ( CheckForPublic ( " pfn_keyvalue " ) )
g_pFunctionTable - > pfnKeyValue = KeyValue ;
g_pengfuncsTable - > pfnPlaybackEvent = NULL ; // "pfn_playbackevent"
if ( CheckForPublic ( " pfn_playbackevent " ) )
g_pengfuncsTable - > pfnPlaybackEvent = PlaybackEvent ;
g_pFunctionTable - > pfnPlayerPreThink = NULL ; // "client_PreThink"
if ( CheckForPublic ( " client_PreThink " ) )
g_pFunctionTable - > pfnPlayerPreThink = PlayerPreThink ;
2004-08-12 04:21:03 +00:00
g_pFunctionTable_Post - > pfnPlayerPostThink = NULL ; // "client_PostThink"
2004-08-11 12:17:39 +00:00
if ( CheckForPublic ( " client_PostThink " ) )
g_pFunctionTable - > pfnPlayerPostThink = PlayerPostThink_Post ;
g_pFunctionTable - > pfnSpawn = NULL ; // "pfn_spawn"
2004-10-27 19:06:43 +00:00
//if (CheckForPublic("pfn_spawn")) // JGHG: I commented this if out because we always need the Spawn to precache the rocket mdl used with SetView native
g_pFunctionTable - > pfnSpawn = Spawn ;
2004-08-11 12:17:39 +00:00
g_pFunctionTable - > pfnClientKill = NULL ; // "client_kill"
if ( CheckForPublic ( " client_kill " ) )
g_pFunctionTable - > pfnClientKill = ClientKill ;
2013-07-02 23:00:52 +00:00
g_pFunctionTable - > pfnCmdStart = NULL ; // "client_impulse","register_impulse","client_cmdStart"
if ( CheckForPublic ( " client_impulse " ) | | CheckForPublic ( " client_cmdStart " ) )
2004-08-11 12:17:39 +00:00
g_pFunctionTable - > pfnCmdStart = CmdStart ;
g_pFunctionTable - > pfnThink = NULL ; // "pfn_think", "register_think"
if ( CheckForPublic ( " pfn_think " ) )
g_pFunctionTable - > pfnThink = Think ;
g_pFunctionTable - > pfnStartFrame = NULL ; // "server_frame","ServerFrame"
if ( CheckForPublic ( " server_frame " ) )
g_pFunctionTable - > pfnStartFrame = StartFrame ;
if ( CheckForPublic ( " ServerFrame " ) )
g_pFunctionTable - > pfnStartFrame = StartFrame ;
g_pFunctionTable - > pfnTouch = NULL ; // "pfn_touch","vexd_pfntouch"
if ( CheckForPublic ( " pfn_touch " ) )
g_pFunctionTable - > pfnTouch = pfnTouch ;
if ( CheckForPublic ( " vexd_pfntouch " ) )
g_pFunctionTable - > pfnTouch = pfnTouch ;
2004-05-26 05:15:40 +00:00
}
qboolean Voice_SetClientListening ( int iReceiver , int iSender , qboolean bListen )
{
if ( ( plinfo [ iSender ] . iSpeakFlags & SPEAK_MUTED ) ! = 0 ) {
( g_engfuncs . pfnVoice_SetClientListening ) ( iReceiver , iSender , false ) ;
RETURN_META_VALUE ( MRES_SUPERCEDE , false ) ;
}
if ( ( plinfo [ iSender ] . iSpeakFlags & SPEAK_ALL ) ! = 0 ) {
( g_engfuncs . pfnVoice_SetClientListening ) ( iReceiver , iSender , true ) ;
RETURN_META_VALUE ( MRES_SUPERCEDE , true ) ;
}
if ( ( plinfo [ iReceiver ] . iSpeakFlags & SPEAK_LISTENALL ) ! = 0 ) {
( g_engfuncs . pfnVoice_SetClientListening ) ( iReceiver , iSender , true ) ;
RETURN_META_VALUE ( MRES_SUPERCEDE , true ) ;
}
RETURN_META_VALUE ( MRES_IGNORED , bListen ) ;
}
2013-06-15 20:02:24 +00:00
int AddToFullPack_Post ( struct entity_state_s * state , int e , edict_t * ent , edict_t * host , int hostflags , int player , unsigned char * pSet )
2004-05-26 05:15:40 +00:00
{
2016-02-03 16:34:51 +00:00
if ( player & & ent & & ent = = host & & plinfo [ TypeConversion . edict_to_id ( ent ) ] . iViewType ! = CAMERA_NONE )
2015-03-10 15:51:45 +00:00
{
state - > rendermode = kRenderTransTexture ;
state - > renderamt = 100 ;
2004-05-26 05:15:40 +00:00
}
RETURN_META_VALUE ( MRES_IGNORED , 0 ) ;
}
void ClientDisconnect ( edict_t * pEntity )
{
2016-02-03 16:34:51 +00:00
auto id = TypeConversion . edict_to_id ( pEntity ) ;
2004-05-26 05:15:40 +00:00
2015-10-06 22:10:48 +00:00
if ( plinfo [ id ] . iViewType ! = CAMERA_NONE ) // Verify that they were originally in a modified view
2004-08-11 12:17:39 +00:00
{
g_CameraCount - - ;
if ( g_CameraCount < 0 )
g_CameraCount = 0 ;
2004-08-12 04:14:47 +00:00
if ( g_CameraCount = = 0 ) // Reset the AddToFullPack pointer if there's no more cameras in use...
g_pFunctionTable - > pfnAddToFullPack = NULL ;
2004-08-11 12:17:39 +00:00
}
2004-05-26 05:15:40 +00:00
plinfo [ id ] . iSpeakFlags = SPEAK_NORMAL ;
plinfo [ id ] . iViewType = CAMERA_NONE ;
RETURN_META ( MRES_IGNORED ) ;
}
BOOL ClientConnect ( edict_t * pEntity , const char * pszName , const char * pszAddress , char szRejectReason [ 128 ] )
{
2016-02-03 16:34:51 +00:00
auto id = TypeConversion . edict_to_id ( pEntity ) ;
2004-05-26 05:15:40 +00:00
plinfo [ id ] . iSpeakFlags = SPEAK_NORMAL ;
plinfo [ id ] . iViewType = CAMERA_NONE ;
plinfo [ id ] . pViewEnt = NULL ;
RETURN_META_VALUE ( MRES_IGNORED , 0 ) ;
}
void ServerDeactivate ( )
{
memset ( glinfo . szLastLights , 0x0 , 128 ) ;
memset ( glinfo . szRealLights , 0x0 , 128 ) ;
2005-11-26 20:38:58 +00:00
glinfo . bCheckLights = false ;
2004-08-12 04:14:47 +00:00
// Reset all forwarding function tables (so that forwards won't be called before plugins are initialized)
g_pFunctionTable - > pfnAddToFullPack = NULL ;
g_pFunctionTable - > pfnKeyValue = NULL ;
g_pengfuncsTable - > pfnPlaybackEvent = NULL ; // "pfn_playbackevent"
g_pFunctionTable - > pfnPlayerPreThink = NULL ; // "client_PreThink"
2004-08-12 04:21:03 +00:00
g_pFunctionTable_Post - > pfnPlayerPostThink = NULL ; // "client_PostThink"
2004-08-12 04:14:47 +00:00
g_pFunctionTable - > pfnSpawn = NULL ; // "pfn_spawn"
g_pFunctionTable - > pfnClientKill = NULL ; // "client_kill"
g_pFunctionTable - > pfnCmdStart = NULL ; // "client_impulse","register_impulse"
g_pFunctionTable - > pfnThink = NULL ; // "pfn_think", "register_think"
g_pFunctionTable - > pfnStartFrame = NULL ; // "server_frame","ServerFrame"
g_pFunctionTable - > pfnTouch = NULL ; // "pfn_touch","vexd_pfntouch"
2004-06-25 22:51:18 +00:00
2004-09-08 21:43:50 +00:00
ClearHooks ( ) ;
2004-05-26 05:15:40 +00:00
RETURN_META ( MRES_IGNORED ) ;
2004-06-24 07:36:43 +00:00
}
2004-05-26 05:15:40 +00:00
2015-06-11 14:08:46 +00:00
DETOUR_DECL_STATIC2 ( LightStyle , void , int , style , const char * , val ) // void (*pfnLightStyle) (int style, const char* val);
{
DETOUR_STATIC_CALL ( LightStyle ) ( style , val ) ;
2015-05-10 21:21:12 +00:00
if ( ! style & & strcmp ( val , glinfo . szRealLights ) ) {
2017-12-07 17:45:16 +00:00
ke : : SafeStrcpy ( glinfo . szRealLights , sizeof ( glinfo . szRealLights ) , val ) ;
2004-05-26 05:15:40 +00:00
}
2015-06-11 14:08:46 +00:00
if ( glinfo . bCheckLights & & strcmp ( val , glinfo . szLastLights ) )
g_pFunctionTable_Post - > pfnStartFrame = StartFrame_Post ;
}
void StartFrame_Post ( )
{
g_pFunctionTable_Post - > pfnStartFrame = NULL ;
LightStyleDetour - > DisableDetour ( ) ;
LIGHT_STYLE ( 0 , glinfo . szLastLights ) ;
LightStyleDetour - > EnableDetour ( ) ;
2004-05-26 05:15:40 +00:00
RETURN_META ( MRES_IGNORED ) ;
}
2004-08-11 12:17:39 +00:00
BOOL CheckForPublic ( const char * publicname )
{
AMX * amx ;
char blah [ 64 ] ;
strncpy ( blah , publicname , 63 ) ;
int iFunctionIndex ;
int i = 0 ;
// Loop through all running scripts
while ( ( amx = MF_GetScriptAmx ( i + + ) ) ! = NULL )
{
// Scan for public
if ( MF_AmxFindPublic ( amx , blah , & iFunctionIndex ) = = AMX_ERR_NONE )
{
// Public was found.
return TRUE ;
}
}
return FALSE ; // no public found in any loaded script
}
2015-06-11 14:08:46 +00:00
void CreateDetours ( )
{
LightStyleDetour = DETOUR_CREATE_STATIC_FIXED ( LightStyle , ( void * ) ( g_engfuncs . pfnLightStyle ) ) ;
}
void DestroyDetours ( )
{
LightStyleDetour - > Destroy ( ) ;
2017-12-07 17:45:16 +00:00
}