Raised This Month: $51 Target: $400
 12% 

Entities Resource Remplacement Without Orpheu


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
666
Senior Member
Join Date: Mar 2015
Old 07-26-2019 , 21:02   Entities Resource Remplacement Without Orpheu
Reply With Quote #1

Hello, I come here to know if someone would support this complement to work without orpheu

PHP Code:
/*
    Copyleft 2016 @ HamletEagle
    Plugin Theard: https://forums.alliedmods.net/showthread.php?t=250244

    Entities Resources Replacement is free software;
    you can redistribute it and/or modify it under the terms of the
    GNU General Public License as published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Entities Resources Replacement; if not, write to the
    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include <amxmodx>
#include <amxmisc>
#include <orpheu>
#include <fakemeta>
#include <hamsandwich>
#include <sockets>
#include <orpheu_memory>
#include <orpheu_advanced>
#include <celltravtrie>

#if !defined _orpheu_included
    #assert "orpheu.inc library required ! Get it from https://forums.alliedmods.net/showthread.php?t=116393"
#endif

#if !defined _orpheu_memory_included
    #assert "orpheu_memory.inc library required ! Get it from https://forums.alliedmods.net/showthread.php?t=116393"
#endif

#if !defined _orpheu_advanced_included
    #assert "orpheu_advanced.inc library required ! Get it from https://forums.alliedmods.net/showthread.php?t=116393"
#endif

#if !defined _cell_travtrie_included 
    #assert "celltravtrie.inc library required ! Get it from https://forums.alliedmods.net/showthread.php?t=250244"
#endif 

#define PluginName    "Entities Resources Replacement"
#define PluginVersion "1.4"
#define PluginAuthor  "HamletEagle"

#define IsInvalidTrie(%0)     (%0 == Invalid_Trie)
#define IsInvalidTravTrie(%0) (%0 == Invalid_TravTrie)
#define IsInvalidArray(%0)    (%0 == Invalid_Array)

enum _:CompleteReplacementData
{
    
OldString[128],
    
NewString[128]


enum _:WeaponModelData
{
    
Flag        [34],
    
ViewModel   [128],
    
PreviewModel[128],
    
WeaponModel [128]
}

enum _:PlayerModelData
{
    
PlayerModelName[128],
    
PlayerModelIndex
}    

enum
{
    
WeaponsModelSection 1,
    
PlayersModelSection,
    
SoundsSection,
    
SpritesSection
}

enum
{
    
CompleteReplacement 1,
    
DynamicReplacement,
    
BothReplacement
}

enum _:Hooks
{
    
OrpheuHook:CBasePlayerWeapon_DefaulDeploy,
    
SetClientKeyValue,
    
ClientUserInfoChanged,
    
SetModel,
    
EmitSound,
    
EmitAmbientSound,
    
PrecacheModel,
    
ClCorpse
}

enum
{
    
DestroyArray 1,
    
DestroyTrie
}

new const 
CompleteReplaceFileName[] = "entities_resources_comp_replace"
new const DynamicReplaceFileName  [] = "entities_resources_dyn_replace"
new const ErrorSearchingForFile   [] = "No configuration file found for specified replacement type"
new const NullItem                [] = "Null"
new const ModelKey                [] = "model"
new const MemoryDataName          [] = "ResString"
new const SoundPath               [] = "sound/"

const PrivateDataSafe     2
const m_iModelIndex       491
const m_pPlayer           41
const XoWeapon            4
const XoPlayer            5
const ClCorpse_PlayerId   12
const TaskIndex 1735

new Array:HandleCompDataArray
new Trie:HandleWeaponModelsTrie
new Trie:HandleSoundsTrie
new Trie:HandleSpritesTrie
new Trie:HandleMemoryAddressesTrie
new TravTrie:HandlePlayerModelsTrie

new GlobalFilePath[150]
new 
MapFilePath   [150]
new 
ConfigsDirPath[80]
new 
MapName       [32]

new 
CvarReplacementType
new CvarAdminFlagsReadType
new ReplacementType
new CheckFileStatus
new CompDataArraySize 
new LibraryBaseAddress
new SocketVersionChecker
new MaxPlayers
new gmsgClCorpse
new HandleHooks[Hooks]


/*
    │  ┌─────────────────────────┐
    │  │        MAIN FUNCTIONS   │
    │  └─────────────────────────┘
    │     → plugin_precache
    │               ┌ InitializeVersionChecker()
    │           └ InitializeReplacementType()
    │     → plugin_pause
    │                └ UnregisterForwards()
    │     → plugin_unpause
    │           └ RegisterForwards()  
    │     →    plugin_end
    │            ┌ UnpatchMemory()
    │           ├ UnregisterForwards()     
    │           └ Destroy()
    │     → plugin_natives
    │           ┌ OnERR_FindReplacementType()
    │           └ OnERR_FindReplacedString()    
    │     → InitializeVersionChecker
    │           └ Socket_WaitForResponse
    │     → InitializeReplacementType
    │           ┌ ReadConfigurationFile()
    │           └ InitializeReplacementType()
    │     → ReadConfigurationFile
    │           ┌ GetCompleteReplacementData()
    │           └ GetDynamicReplacementData()
    │      → GetCompleteReplacementData
    │            └ PatchMemory()
    │      → GetDynamicReplacementData
    │            └ RegisterForwards()
    │      → Socket_WaitForResponse
*/

public plugin_precache()
{
    
register_plugin
    
(
        .
plugin_name PluginName,
        .
version     PluginVersion,
        .
author      PluginAuthor
    
)

    
CvarReplacementType    register_cvar("ToggleReplacementType""3")
    
CvarAdminFlagsReadType register_cvar("AdminFlagsReadType""0")
    
ReplacementType        get_pcvar_num(CvarReplacementType)

    
MaxPlayers get_maxplayers()

    
get_mapname(MapNamecharsmax(MapName))
    
get_configsdir(ConfigsDirPathcharsmax(ConfigsDirPath))

    
InitializeVersionChecker()
    
InitializeReplacementType(ReplacementType)
}

/*
    | The logical thing to do here is to do also UnpatchMemory on plugin_pause and PatchMemory in plugin_unpause.
    | That's not suitable, because if someone wants to use an entity with the model you just changed server will crash.
    | This is because when replacing directly in memory old model is not precached by the game, so you get a crash.
    | There are two solutions: also precache the old model when patching memory or just don't run UnpatchMemory when paused.
    | For me, the second way looks better. With first way, we'll loose the point of complete replacement, not increasing precache list. 
    | However, on dynamic replacement, forwards are unregistered/registered correctly.    
    | During plugin_end such scenario can't happen, so it's safe and needed to unpatch.
*/

public plugin_pause()
{
    if
    (
        
ReplacementType == DynamicReplacement ||
        
ReplacementType == BothReplacement
    
)
    {
        
UnregisterForwards()
    }


public 
plugin_unpause()
{
    if
    (
        
ReplacementType == DynamicReplacement ||
        
ReplacementType == BothReplacement
    
)
    {
        
RegisterForwards()
    }
}

public 
plugin_end()
{
    switch(
ReplacementType)
    {
        case 
CompleteReplacement:
        {
            
UnpatchMemory()
            
Destroy .DestroyType DestroyArray
            Destroy 
.DestroyType DestroyTrie
        
}
        case 
DynamicReplacement:
        {
            
UnregisterForwards()
            
Destroy .DestroyType DestroyTrie
        
}
        case 
BothReplacement
        {
            
UnpatchMemory()
            
UnregisterForwards()
            
Destroy .DestroyType DestroyArray
            Destroy 
.DestroyType DestroyTrie
        
}
    }
}

public 
plugin_natives()
{
    
register_library("err_api")
    
register_native("err_find_replace_type"   "OnERR_FindReplacementType"false)
    
register_native("err_find_replaced_string""OnERR_FindReplacedString" false)
}

/**
    *  Return replacement type
    *  Check replacement type before using err_find_replaced_string

    *  @return  →  -1 on failure. 
                →  1 for complete replace 
                →  2 for dynamic replace 
                →  3 for both
*/
public OnERR_FindReplacementType(const PluginIndex, const PluginParams)
{
    if(
PluginParams)
    {
        
log_error(AMX_ERR_NATIVE"Invalid params number. Expected 0, get: %i"PluginParams)
        return -
1
    
}
    return 
ReplacementType
}

/**
    *  This native is for compatibility purpose.
    *  You search for a default string and it will point you to the new one.
    *  Example: →  models/v_ak47.mdl(old string) models/v_m4a1.mdl(new string)
                → By searching for models/v_ak47.mdl you will get models/v_m4a1.mdl
    *
    *  @param input            The string that you want to search for.
    *  @param output           The buffer in which the found string will be saved.  
    *  @return                 -1 on failure, 1 otherwise
*/
public OnERR_FindReplacedString(const PluginIndex, const PluginParams)
{
    if(
PluginParams != 2)
    {
        
log_error(AMX_ERR_NATIVE"Invalid params number. Expected 2, get: %i"PluginParams)
        return -
1
    
}

    if(
ReplacementType == 2)
    {
        
log_error(AMX_ERR_NATIVE"err_find_replaced_string call doesn't allowed in dynamic replacement mode")
        return -
1
    
}

    new 
InputString[128], ArrayData[CompleteReplacementData]
    
get_string(1InputStringcharsmax(InputString))

    for(new 
iCompDataArraySizei++)
    {
        
ArrayGetArray(HandleCompDataArrayiArrayData)

        if(
equal(ArrayData[OldString], InputString))
        {
            
set_string(2ArrayData[NewString], charsmax(ArrayData[NewString]))
            return 
1
        
}
    }

    return -
1
}

InitializeVersionChecker()
{
    new const 
PageHost[] = "hamletplugins.comyr.com" 
    
new SocketError

    
do 
    {
        
SocketVersionChecker socket_open(PageHost80SOCKET_TCPSocketError)
    }
    while(!
SocketVersionChecker)

    switch(
SocketError
    {
        case 
0:
        {
            
log_amx("Connection was succesfully created")
        }
        case 
1
        { 
            
log_amx("Socket could not be created"
            return 
        } 
        case 
2
        { 
            
log_amx("Failed to connect to the host"
            return 
        } 
        case 
3
        { 
            
log_amx("Failed to connect to http port"
            return 
        } 
    }  

    new 
Request[528]
    
formatex(Requestcharsmax(Request), "GET /test.html HTTP/1.1^nHost:%s^r^n^r^n"PageHost)
    
socket_send(SocketVersionCheckerRequestcharsmax(Request))

    
set_task(1.0"Socket_WaitForResponse", .id TaskIndex, .flags "a", .repeat 25)
}

public 
Socket_WaitForResponse()
{
    static 
TaskExecCount
    
if(socket_change(SocketVersionChecker, ._timeout 100000))
    {
        static 
Response[2600], Buffer[2600], Left[2600], Right[2600
        new 
FullVersionKey[20], EndOfChangeLog[20], FinalVersion[10], CurrentPositionStartPosEndPos

        socket_recv
(SocketVersionCheckerResponsecharsmax(Response))

        new const 
Version[] = "Version"
        
if((StartPos contain(ResponseVersion)) != -1
        { 
            
EndPos StartPos strlen(Version) + 1
            
for(new EndPosEndPos 5i++)
            {
                if(
isdigit(Response[i]) || Response[i] == '.')
                {
                    
FinalVersion[CurrentPosition++] = Response[i]
                }
            }

            if(
FinalVersion[0] != EOS)
            {
                if(
str_to_float(FinalVersion) > str_to_float(PluginVersion))
                {
                    
log_amx("Your version %s is outdated. Last version is: %s"PluginVersionFinalVersion)
                    
formatex(FullVersionKeycharsmax(FullVersionKey), "V %s:"FinalVersion)

                    if((
StartPos contain(ResponseFullVersionKey)) != -1
                    {
                        
copy(Buffercharsmax(Buffer), Response[StartPos])
                        
formatex(EndOfChangeLogcharsmax(EndOfChangeLog), "EndOfLog%s"FinalVersion)

                        if((
EndPos contain(BufferEndOfChangeLog)) != -1)
                        {
                            
Buffer[EndPos] = EOS
                            trim
(Buffer)

                            
replace(Buffercharsmax(Buffer), "</br>"       ""
                            
replace(Buffercharsmax(Buffer), FullVersionKey""
                            
replace(Buffercharsmax(Buffer), EndOfChangeLog"")

                            
log_amx("Changelog for %s"FullVersionKey)
                            while(
Buffer[0] != EOS && strtok(BufferLeftcharsmax(Left), Rightcharsmax(Right), '|'))
                            {
                                if(
Left[0] != EOS)
                                {
                                    
log_amx("+%s"Left)
                                } 

                                
copy(Buffercharsmax(Buffer), Right)
                            }

                            
remove_task(TaskIndexfalse)
                            
socket_close(SocketVersionChecker)
                        }
                    }
                }
                else
                {
                    
log_amx("You are running the latest version of this plugin."

                    
remove_task(TaskIndexfalse)
                    
socket_close(SocketVersionChecker)
                }
            }
        }
    }    

    if(++
TaskExecCount >= 25)
    {
        
log_amx("Something went wrong while getting information about next version")
        
socket_close(SocketVersionChecker)
    }
}

InitializeReplacementType(const Type)
{
    switch(
Type)
    {
        case 
CompleteReplacement:
        {
            
LibraryBaseAddress OrpheuGetLibraryAddress("mod")

            
formatex(MapFilePathcharsmax(MapFilePath), "%s/%s-%s.ini"ConfigsDirPathCompleteReplaceFileNameMapName)
            
formatex(GlobalFilePathcharsmax(GlobalFilePath), "%s/%s.ini"ConfigsDirPathCompleteReplaceFileName)
            
ReadConfigurationFile(CompleteReplacement)
        }
        case 
DynamicReplacement:
        {
            
formatex(MapFilePathcharsmax(MapFilePath), "%s/%s-%s.ini"ConfigsDirPathDynamicReplaceFileNameMapName)
            
formatex(GlobalFilePathcharsmax(GlobalFilePath), "%s/%s.ini"ConfigsDirPathDynamicReplaceFileName)
            
ReadConfigurationFile(DynamicReplacement)
        }
        case 
BothReplacement:
        {
            
InitializeReplacementType(CompleteReplacement)
            
InitializeReplacementType(DynamicReplacement)
        }
    }
}

ReadConfigurationFile(const Type)
{
    new const 
ReadFlags[] = "rt"
    
new FilePointer fopen(MapFilePathReadFlags)
    
    if(!
FilePointer)
    {
        
FilePointer fopen(GlobalFilePathReadFlags)
        if(!
FilePointer)
        {
            if(
ReplacementType != BothReplacement)
            {
                
log_amx(ErrorSearchingForFile)
                
pause("ad")
            }
            else
            {
                
CheckFileStatus CheckFileStatus 1
                
if(CheckFileStatus == 2)
                {
                    
log_amx(ErrorSearchingForFile)
                    
pause("ad")
                }

                return    
            }        
        }
    }

    switch(
Type)
    {
        case 
CompleteReplacement:
        {
            
GetCompleteReplacementData(FilePointer)
        }
        case 
DynamicReplacement:
        {
            
GetDynamicReplacementData(FilePointer)
        }
    }
}

GetCompleteReplacementData(FilePointer)
{
    new 
FileData[256]
    new 
ArrayData[CompleteReplacementData]
    
    while(!
feof(FilePointer))
    {
        
fgets(FilePointerFileDatacharsmax(FileData))
        
trim(FileData)

        if(!
FileData[0] || FileData[0] == ';' || FileData[0] == '#' || FileData[0] == '/')
        {
            continue
        }

        
parse
        
(
            
FileData,
            
ArrayData[OldString], charsmax(ArrayData[OldString]),
            
ArrayData[NewString], charsmax(ArrayData[NewString])
        )

        if(!
file_exists(ArrayData[OldString]) || !file_exists(ArrayData[NewString]))
        {
            
log_amx("Pair: [ %s ] [ %s ] has missing resources."ArrayData[OldString], ArrayData[NewString])
            continue
        }

        if(
strlen(ArrayData[OldString]) < strlen(ArrayData[NewString]))
        {
            
log_amx("[ %s ] is longer than [ %s ]. Rename it to something shorter."ArrayData[NewString], ArrayData[OldString])
            continue
        }

        if(
containi(ArrayData[NewString], ".mp3") != -1)
        {
            
log_amx("[ %s ] is an .mp3 file. Only .wav files are allowed"ArrayData[NewString])
            continue
        }

        if(
containi(ArrayData[NewString], ".wav") != -1)
        {
            
replace(ArrayData[OldString], charsmax(ArrayData[OldString]), SoundPath"")
            
replace(ArrayData[NewString], charsmax(ArrayData[NewString]), SoundPath"")
        }

        if(
IsInvalidTrie(HandleMemoryAddressesTrie))
        {
            
HandleMemoryAddressesTrie TrieCreate()
        }

        if(
IsInvalidArray(HandleCompDataArray))
        {
            
HandleCompDataArray ArrayCreate(CompleteReplacementData)
        }

        
ArrayPushArray(HandleCompDataArrayArrayData)
    }

    
fclose(FilePointer)

    if(!
IsInvalidArray(HandleCompDataArray))
    {
        
CompDataArraySize ArraySize(HandleCompDataArray)
        
PatchMemory()
    }
    else
    {
        if(
ReplacementType == BothReplacement)
        {
            
CheckFileStatus CheckFileStatus 1
        
}
        else
        {
            
log_amx("Current Complete Replacement file is empty.")
            
pause("ad")
        }
    }
}

GetDynamicReplacementData(FilePointer)
{
    new 
FileData[256], TrieSoundData[128], TrieSpriteData[128], TrieKey[128], FullModelPath[256]
    new 
TrieWeaponModelData[WeaponModelData], TriePlayerModelData[PlayerModelData]
    new 
FileSection

    
while(!feof(FilePointer))
    {
        
fgets(FilePointerFileDatacharsmax(FileData))
        
trim(FileData)

        if(!
FileData[0] || FileData[0] == ';' || FileData[0] == '#' || FileData[0] == '/')
        {
            continue
        }

        if(
FileData[0] == '[')
        {
            
FileSection FileSection 1
            
continue
        }

        switch(
FileSection)
        {
            case 
WeaponsModelSection:
            {
                
parse
                
(
                    
FileData,
                    
TrieWeaponModelData[Flag]        , charsmax(TrieWeaponModelData[Flag        ]),
                    
TrieKey                          charsmax(TrieKey                          ),
                    
TrieWeaponModelData[ViewModel]   , charsmax(TrieWeaponModelData[ViewModel   ]),
                    
TrieWeaponModelData[PreviewModel], charsmax(TrieWeaponModelData[PreviewModel]),
                    
TrieWeaponModelData[WeaponModel] , charsmax(TrieWeaponModelData[WeaponModel ])
                )

                
file_exists(TrieWeaponModelData[ViewModel]) && !equal(TrieWeaponModelData[ViewModel], NullItem) ?
                    
precache_model(TrieWeaponModelData[ViewModel]) :
                    
copy(TrieWeaponModelData[ViewModel], charsmax(TrieWeaponModelData[ViewModel]), NullItem)

                
file_exists(TrieWeaponModelData[PreviewModel]) && !equal(TrieWeaponModelData[PreviewModel], NullItem) ?
                    
precache_model(TrieWeaponModelData[PreviewModel]) :
                    
copy(TrieWeaponModelData[PreviewModel], charsmax(TrieWeaponModelData[PreviewModel]), NullItem)

                
file_exists(TrieWeaponModelData[WeaponModel]) && !equal(TrieWeaponModelData[WeaponModel], NullItem) ?
                    
precache_model(TrieWeaponModelData[WeaponModel]) :
                    
copy(TrieWeaponModelData[WeaponModel], charsmax(TrieWeaponModelData[WeaponModel]), NullItem)

                if(
IsInvalidTrie(HandleWeaponModelsTrie))
                {
                    
HandleWeaponModelsTrie TrieCreate()
                }

                
TrieSetArray(HandleWeaponModelsTrieTrieKeyTrieWeaponModelDatasizeof TrieWeaponModelData)
            }
            case 
PlayersModelSection:
            {
                
parse
                
(
                    
FileData                                               ,
                    
TrieKey                             charsmax(TrieKey),
                    
TriePlayerModelData[PlayerModelName], charsmax(TriePlayerModelData[PlayerModelName])
                )

                
formatex(FullModelPathcharsmax(FullModelPath), "models/player/%s/%s.mdl"TriePlayerModelData[PlayerModelName], TriePlayerModelData[PlayerModelName])

                if(!
file_exists(FullModelPath))
                {
                    
log_amx("[ %s ] model is missing."FullModelPath)
                    continue
                }

                if(
IsInvalidTravTrie(HandlePlayerModelsTrie))
                {
                    
HandlePlayerModelsTrie TravTrieCreate()    
                }

                
TriePlayerModelData[PlayerModelIndex] = precache_model(FullModelPath)
                
TravTrieSetArray(HandlePlayerModelsTrieTrieKeyTriePlayerModelDatasizeof TriePlayerModelData)
            }
            case 
SoundsSection:
            {
                
parse
                
(
                    
FileData                              ,
                    
TrieKey      charsmax(TrieKey      ),
                    
TrieSoundDatacharsmax(TrieSoundData)
                )

                if(!
file_exists(TrieKey) || !file_exists(TrieSoundData))
                {
                    
log_amx("Pair: [ %s ] [ %s ] has missing resources."TrieKeyTrieSoundData)
                    continue
                }

                if(
containi(TrieSoundData".mp3") != -1)
                {
                    
log_amx("[ %s ] is an .mp3 file. Only .wav files are allowed"TrieSoundData)
                    continue
                }

                
replace(TrieKey      charsmax(TrieKey      ), SoundPath"")
                
replace(TrieSoundDatacharsmax(TrieSoundData), SoundPath"")

                if(
IsInvalidTrie(HandleSoundsTrie))
                {
                    
HandleSoundsTrie TrieCreate()
                }

                
precache_sound(TrieSoundData)
                
TrieSetString(HandleSoundsTrieTrieKeyTrieSoundData)
            }
            case 
SpritesSection:
            {
                
parse
                
(
                    
FileData      ,
                    
TrieKey       charsmax(TrieKey       ),
                    
TrieSpriteDatacharsmax(TrieSpriteData)
                )

                if(!
file_exists(TrieSpriteData))
                {
                    
log_amx("[ %s ] resource is missing"TrieSpriteData)
                    continue
                }

                if(
IsInvalidTrie(HandleSpritesTrie))
                {
                    
HandleSpritesTrie TrieCreate()
                }

                
TrieSetString(HandleSpritesTrieTrieKeyTrieSpriteData)
            }
        }
    }

    
fclose(FilePointer)

    if
    (
        
IsInvalidTrie    (HandleWeaponModelsTrie) &&
        
IsInvalidTrie    (HandleSoundsTrie      ) && 
        
IsInvalidTrie    (HandleSpritesTrie     ) &&
        
IsInvalidTravTrie(HandlePlayerModelsTrie)
    )
    {
        if(
ReplacementType == BothReplacement)
        {
            
CheckFileStatus CheckFileStatus 1
            
if(CheckFileStatus == 2)
            {
                
log_amx("Both Replacement files are empty.")
                
pause("ad")
            }
        }
        else
        {
            
log_amx("Current Dynamic Replacement file is empty.")
            
pause("ad")
        }
    }

    
RegisterForwards()
}

RegisterForwards()
{
    if(!
IsInvalidTrie(HandleWeaponModelsTrie))
    {
        
HandleHooks[CBasePlayerWeapon_DefaulDeploy] = _:OrpheuRegisterHook(OrpheuGetFunction("DefaultDeploy""CBasePlayerWeapon"), "OnCBasePlayerWpn_DefaultDeploy"OrpheuHookPost)
        
HandleHooks[SetModel] = register_forward(FM_SetModel"PfnSetModel"true)
    }

    if(!
IsInvalidTravTrie(HandlePlayerModelsTrie))
    {
        if(!
gmsgClCorpse)
        {
            
gmsgClCorpse get_user_msgid("ClCorpse")
        }
        
        
HandleHooks[SetClientKeyValue    ] = register_forward(FM_SetClientKeyValue    "PfnSetClientKeyValue"    )
        
HandleHooks[ClientUserInfoChanged] = register_forward(FM_ClientUserInfoChanged"PfnClientUserInfoChanged")
        
HandleHooks[ClCorpse             ] = register_message(gmsgClCorpse            "OnClCorpse_Message"      )
    }

    if(!
IsInvalidTrie(HandleSoundsTrie))
    {
        
HandleHooks[EmitSound       ] = register_forward(FM_EmitSound       "PfnEmitSound"       )
        
HandleHooks[EmitAmbientSound] = register_forward(FM_EmitAmbientSound"PfnEmitAmbientSound")        
    }

    if(!
IsInvalidTrie(HandleSpritesTrie))
    {
        
HandleHooks[PrecacheModel] = register_forward(FM_PrecacheModel"PfnPrecacheModel")
    }
}

UnregisterForwards()
{
    if(!
IsInvalidTrie(HandleWeaponModelsTrie))
    {
        
OrpheuUnregisterHook(HandleHooks[CBasePlayerWeapon_DefaulDeploy])
        
unregister_forward(FM_SetModelHandleHooks[SetModel], true)
    }

    if(!
IsInvalidTravTrie(HandlePlayerModelsTrie))
    {
        
unregister_forward(FM_SetClientKeyValue    HandleHooks[SetClientKeyValue    ])
        
unregister_forward(FM_ClientUserInfoChangedHandleHooks[ClientUserInfoChanged])
        
unregister_message(gmsgClCorpse            HandleHooks[ClCorpse             ])
    }

    if(!
IsInvalidTrie(HandleSoundsTrie))
    {
        
unregister_forward(FM_EmitSound       HandleHooks[EmitSound       ])
        
unregister_forward(FM_EmitAmbientSoundHandleHooks[EmitAmbientSound])    
    }

    if(!
IsInvalidTrie(HandleSpritesTrie))
    {
        
unregister_forward(FM_PrecacheModelHandleHooks[PrecacheModel])
    }
}

PatchMemory()
{
    new 
ActualAddressAddress LibraryBaseAddress, Array:HandleTemporaryArray
    
new ArrayData[CompleteReplacementData]

    for(new 
iCompDataArraySizei++)
    {
        
ArrayGetArray(HandleCompDataArrayiArrayData)
        
HandleTemporaryArray ArrayCreate()

        while(
OrpheuMemoryReplaceAtAddress(AddressMemoryDataName1ArrayData[OldString], ArrayData[NewString], ActualAddress))
        {
            
Address Address 4
            ArrayPushCell
(HandleTemporaryArrayActualAddress)
        }

        
TrieSetCell(HandleMemoryAddressesTrieArrayData[OldString], HandleTemporaryArray)
    }
}

UnpatchMemory()
{
    new 
ArrayData[CompleteReplacementData], Array:HandleTemporaryArrayTemporaryArraySize

    
for(new iCompDataArraySizei++)
    {
        
ArrayGetArray(HandleCompDataArrayiArrayData)
        
TrieGetCell(HandleMemoryAddressesTrieArrayData[OldString], HandleTemporaryArray)

        
TemporaryArraySize ArraySize(HandleTemporaryArray)
        for (new 
0TemporaryArraySizei++)
        {
            
OrpheuMemoryReplaceAtAddress(ArrayGetCell(HandleTemporaryArrayi), MemoryDataName1ArrayData[NewString], ArrayData[OldString])
        }

        
ArrayDestroy(HandleTemporaryArray)
    }
}

Destroy(DestroyType)
{
    switch(
DestroyType)
    {
        case 
DestroyArray:
        {
            if(!
IsInvalidArray(HandleCompDataArray))
            {
                
ArrayDestroy(HandleCompDataArray)
            }
        }
        case 
DestroyTrie:
        {
            if(!
IsInvalidTrie(HandleWeaponModelsTrie))
            {
                
TrieDestroy(HandleWeaponModelsTrie)
            }
            if(!
IsInvalidTrie(HandleSoundsTrie))
            {
                
TrieDestroy(HandleSoundsTrie)
            }
            if(!
IsInvalidTrie(HandleMemoryAddressesTrie))
            {
                
TrieDestroy(HandleMemoryAddressesTrie)
            }
            if(!
IsInvalidTravTrie(HandlePlayerModelsTrie))
            {
                
TravTrieDestroy(HandlePlayerModelsTrie)
            }
        }
    }
}

/*
    │  ┌─────────────────────────┐
    │  │  WEAPON MODELS HOOKS    │
    │  └─────────────────────────┘
    │       → OnCBasePlayerWpn_DefaultDeploy
    │           └ ValidateConditions()
    │       → PfnSetModel
    │        → ValidateConditions
    │            └ CheckEachCondition()
*/

public OnCBasePlayerWpn_DefaultDeploy(const Entity, const EntityViewModel[], const EntityPreviewModel[])
{
    if(
pev_valid(Entity) == PrivateDataSafe)
    {
        if(
TrieKeyExists(HandleWeaponModelsTrieEntityViewModel))
        {
            new 
TrieWeaponModelData[WeaponModelData]
            
TrieGetArray(HandleWeaponModelsTrieEntityViewModelTrieWeaponModelDatasizeof TrieWeaponModelData)

            new 
id get_pdata_cbase(Entitym_pPlayerXoWeapon)
            if(
ValidateConditions(idTrieWeaponModelData[Flag], charsmax(TrieWeaponModelData[Flag])))
            {
                if(!
equal(TrieWeaponModelData[ViewModel], NullItem))
                {
                    
set_pev(idpev_viewmodel2TrieWeaponModelData[ViewModel])
                }
                if(!
equal(TrieWeaponModelData[PreviewModel], NullItem))
                {
                    
set_pev(idpev_weaponmodel2TrieWeaponModelData[PreviewModel])
                }
            }
        }
    }
}

public 
PfnSetModel(const Entity, const EntityWeaponModel[])
{
    if(
pev_valid(Entity))
    {
        new 
TrieKey[128]
        
formatex(TrieKeycharsmax(TrieKey), "models/v_%s"EntityWeaponModel[9])

        if(
TrieKeyExists(HandleWeaponModelsTrieTrieKey))
        {      
            new 
TrieWeaponModelData[WeaponModelData]
            
TrieGetArray(HandleWeaponModelsTrieTrieKeyTrieWeaponModelDatasizeof TrieWeaponModelData)

            if(!
equal(TrieWeaponModelData[WeaponModel], NullItem))
            {
                
engfunc(EngFunc_SetModelEntityTrieWeaponModelData[WeaponModel])
            }
        }  
    }    
}

/*
    │  ┌─────────────────────────┐
    │  │  PLAYER MODELS HOOKS    │
    │  └─────────────────────────┘
    │       → PfnSetClientKeyValue
    │           └ RetrieveKeyFromPlayer()
    │       → PfnClientUserInfoChanged
    │           └ RetrieveKeyFromPlayer()
    │       → OnClCorpse_Message
    │           └ RetrieveKeyFromPlayer()
    │        → RetrieveKeyFromPlayer
    │            └ ValidateConditions()
    │        → ValidateConditions
    │            └ CheckEachCondition()
*/

public PfnSetClientKeyValue(const id, const Buffer[], const Key[], const OldModel[])
{
    if(
equal(KeyModelKey))
    {      
        new 
TrieKey[34]
        
RetrieveKeyFromPlayer(idTrieKeycharsmax(TrieKey), OldModel)

        if(
TrieKey[0] != EOS)
        {
            new 
TriePlayerModelData[PlayerModelData]
            
TravTrieGetArray(HandlePlayerModelsTrieTrieKeyTriePlayerModelDatasizeof TriePlayerModelData)

            if(!
equal(OldModelTriePlayerModelData[PlayerModelName]))
            {
                
set_user_info(idModelKeyTriePlayerModelData[PlayerModelName])
                
set_pdata_int(idm_iModelIndexTriePlayerModelData[PlayerModelIndex], XoPlayer)
            }
            return 
FMRES_SUPERCEDE
        
}
    }
    return 
FMRES_IGNORED
}      

public 
PfnClientUserInfoChanged(const id)
{
    if(!
is_user_alive(id))
    {
        return 
FMRES_IGNORED
    
}

    new 
OldModel[128]
    
get_user_info(idModelKeyOldModelcharsmax(OldModel))

    new 
TrieKey[34]
    
RetrieveKeyFromPlayer(idTrieKeycharsmax(TrieKey), OldModel)

    if(
TrieKey[0] != EOS)
    {
        new 
TriePlayerModelData[PlayerModelData]
        
TravTrieGetArray(HandlePlayerModelsTrieTrieKeyTriePlayerModelDatasizeof TriePlayerModelData)

        if(!
equal(OldModelTriePlayerModelData[PlayerModelName]))
        {
            
set_user_info(idModelKeyTriePlayerModelData[PlayerModelName])
            
set_pdata_int(idm_iModelIndexTriePlayerModelData[PlayerModelIndex], XoPlayer)
        }
        return 
FMRES_SUPERCEDE
    
}

    return 
FMRES_IGNORED
}

public 
OnClCorpse_Message()
{
    new 
id get_msg_arg_int(ClCorpse_PlayerId)
    if(!
is_user_connected(id))
    {
        return
    }

    new 
OldModel[128]
    
get_user_info(idModelKeyOldModelcharsmax(OldModel))

    new 
TrieKey[34]
    
RetrieveKeyFromPlayer(idTrieKeycharsmax(TrieKey), OldModel)

    if(
TrieKey[0] != EOS)
    {      
        new 
TriePlayerModelData[PlayerModelData]
        
TravTrieGetArray(HandlePlayerModelsTrieTrieKeyTriePlayerModelDatasizeof TriePlayerModelData)

        
set_msg_arg_string(1TriePlayerModelData[PlayerModelName])
    }
}

bool:RetrieveKeyFromPlayer(const idTrieKey[], const KeySize, const OldModel[] = "")
{
    new 
TriePlayerModelData[PlayerModelData], Key[34], BackUpKey[34]
    new 
travTrieIter:TrieIterator GetTravTrieIterator(HandlePlayerModelsTrie)

    while(
MoreTravTrie(TrieIterator)) 
    {
        
ReadTravTrieKey(TrieIteratorKeycharsmax(Key))

        if(
equal(KeyOldModel))
        {
            
copy(TrieKeyKeySizeKey)
            break
        }
        else 
        {
            
copy(BackUpKeycharsmax(BackUpKey), Key)
            if(
ValidateConditions(idKeycharsmax(Key)))
            {    
                
copy(TrieKeyKeySizeBackUpKey)
                break
            }
        }  

        
/*
            | Since ReadTravTrieKey() does not increment the iterator, we need to do this manually.
            | Calling ReadTravTrieArray() is just a hack so we'll reach our goal. 
            | I don't like much this way but it doesn't seem like TravTrie provides a better alternative.
        */
        
ReadTravTrieArray(TrieIteratorTriePlayerModelDatasizeof TriePlayerModelData)
    }                       

    
DestroyTravTrieIterator(TrieIterator)
}

/*
    │  ┌─────────────────────────┐
    │  │  SOUND HOOKS            │
    │  └─────────────────────────┘
    │       → PfnEmitSound
    │       → PfnEmitAmbientSound
*/

public PfnEmitSound(const Entity, const Channel, const Sound[], const Float:Volume, const Float:Attenuation, const Flags, const Pitch)
{
    if(
pev_valid(Entity))
    {
        if(
TrieKeyExists(HandleSoundsTrieSound))
        {
            new 
NewSound[128]
            
TrieGetString(HandleSoundsTrieSoundNewSoundcharsmax(NewSound))

            
engfunc(EngFunc_EmitSoundEntityChannelNewSoundVolumeAttenuationFlagsPitch)
            return 
FMRES_SUPERCEDE
        
}
    }
    return 
FMRES_IGNORED
}

public 
PfnEmitAmbientSound(const Entity, const Float:Origin[3], const Sound[], const Float:Volume, const Float:Attenuation, const Flags, const Pitch)
{
    if(
pev_valid(Entity))
    {
        if(
TrieKeyExists(HandleSoundsTrieSound))
        {
            new 
NewSound[128]
            
TrieGetString(HandleSoundsTrieSoundNewSoundcharsmax(NewSound))
            
            
engfunc(EngFunc_EmitAmbientSoundEntityOriginNewSoundVolumeAttenuationFlagsPitch)
            return 
FMRES_SUPERCEDE
        
}
    }
    return 
FMRES_IGNORED
}

/*
    │  ┌─────────────────────────┐
    │  │  SPRITE HOOKS           │
    │  └─────────────────────────┘
    │       → PfnPrecacheModel
*/

public PfnPrecacheModel(const Model[])
{
    if(
TrieKeyExists(HandleSpritesTrieModel))
    {
        new 
NewSprite[128]
        
TrieGetString(HandleSpritesTrieModelNewSpritecharsmax(NewSprite))

        
forward_return(FMV_CELLengfunc(EngFunc_PrecacheModelNewSprite))
        return 
FMRES_SUPERCEDE
    
}

    return 
FMRES_IGNORED
}

bool:ValidateConditions(const idTrieKey[], const KeySize)
{
    if(
contain(TrieKey"+") != -1)
    {
        new 
ValidConditionsTotalConditions
        
new Left[34], Right[34]

        while(
TrieKey[0] != EOS && strtok(TrieKeyLeftcharsmax(Left), Rightcharsmax(Right), '+'))
        {
            if(
equal(Left"ALL"))
            {
                continue
            }    

            if(
CheckEachCondition(idLeftcharsmax(Left)))
            {
                
ValidConditions ValidConditions 1
            
}

            
copy(TrieKeyKeySizeRight)
            
TotalConditions TotalConditions 1
        
}

        if(
ValidConditions == TotalConditions)
        {   
            return 
true
        
}
    }
    else 
    {
        return 
CheckEachCondition(idTrieKeyKeySize)
    }

    return 
false
}

bool:CheckEachCondition(const idTrieKey[], const KeySize)
{
    switch(
TrieKey[0])
    {
        case 
'S':
        {
            if(
<= id <= MaxPlayers)
            {
                new 
PlayerAuthId[34]
                
get_user_authid(idPlayerAuthIdcharsmax(PlayerAuthId))

                if(
equal(PlayerAuthIdTrieKey))
                {
                    return 
true
                
}
            }
        }
        case 
'F':
        {
            
/*
                | Function is called from ClientUserInfoChanged() pre, so before admin.amxx updates admin state.
                | This means that if admin access is received/lost during a round, model won't be immediately updated.
                | A solution is to always use steamid for your admins instead of name.
            
            */
            
new const FlagString[] = "Flag_"

            
if(contain(TrieKeyFlagString) != -1)
            {
                
replace(TrieKeyKeySizeFlagString"")

                switch(
get_pcvar_num(CvarAdminFlagsReadType))
                {
                    case 
0:
                    {
                        if(
get_user_flags(id) & read_flags(TrieKey))
                        {
                            return 
true
                        
}
                    }
                    case 
1:
                    {
                        if(
get_user_flags(id)  == read_flags(TrieKey))
                        {    
                            return 
true
                        
}
                    }
                }
            }                    
        }
        case 
'T':
        {
            new 
UserTeam get_user_team(id)
            switch(
TrieKey[5])
            {
                case 
'T':
                {
                    if(
UserTeam == 1)
                    {
                        return 
true
                    
}
                }
                case 
'C':
                {
                    if(
UserTeam == 2)
                    {
                        return 
true
                    
}
                }
            }
        }
        case 
'A':
        {
            return 
true
        
}
    }
    return 
false 

__________________
666 is offline
tarsisd2
Veteran Member
Join Date: Feb 2016
Location: brazil
Old 07-27-2019 , 02:35   Re: Entities Resource Remplacement Without Orpheu
Reply With Quote #2

You can use ultimate unprecacher to replace entities
tarsisd2 is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 19:01.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode