Vous êtes sur la page 1sur 9

/*

Copyleft 2015 @ 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 <orpheu_memory>
#include <orpheu_advanced>
#include <fakemeta>
#include <hamsandwich>
#include <celltravtrie>
#include <sockets>

#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.3"
#define PluginAuthor "HamletEagle"

/*
| Handle replacement type cvar
|
| 1: complete replacement turned on
| 2: dynamic replacement turned on
| 3: both replacement turned on
*/
new CvarReplacementType
new ReplacementType

enum _:StringData
{
OldString[128],
NewString[128]
}

enum _:WeaponsData
{
WeaponIdentifier[100],
vModel[128],
pModel[128],
wModel[128]
}

enum _:ModelsData
{
ModelName[128],
ModelIndex
}

enum
{
WeaponsModelSection = 1,
PlayersModelSection,
SoundsSection
}

enum
{
DestroyArray = 1,
DestroyTrie
}

enum _:FakemetaHooks
{
SetClientKeyValue,
ClientUserInfoChanged,
SetModel,
EmitSound,
EmitAmbientSound
}

new HandlePfnHooks[FakemetaHooks]

const m_iModelIndex = 491


const m_pPlayer = 41
const XoWeapon = 4
const XoPlayer = 5
const PrivateDataSafe = 2
const TaskIndex = 1735

new const NullItem[] = "Null"


new const CompletelReplaceFileName[] = "entities_resources_comp_replace"
new const DynamicReplaceFileName[] = "entities_resources_dyn_replace"
new const ModelKey[] = "model"
new const Sound[] = "sound/"

new Array:ArrayStrings
new Trie:TrieWeaponModels
new Trie:TrieSounds
new Trie:TrieMemoryAddresses
new TravTrie:TriePlayerModels

new LibraryBaseAddress
new StringsArraySize
new CheckFileStatus
new MaxPlayers
new MessageClCorpse
new ClCorpseRegisterIndex
new SocketResourcesReplacement
new CvarAdminFlagsReadType

new OrpheuHook:CBasePlayerWeapon_DefaulDeploy

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

/*

MAIN FUNCTIONS

plugin_precache
InitializeCompleteReplacement()
InitializeDynamicReplacement()
InitializeVersionChecker()
ReadConfigurationFile()
InitializeCompleteReplacement
InitializeDynamicReplacement
RegisterForwards()
InitializeVersionChecker
WaitForResponse()
ReadConfigurationFile
GetDataFromFirstFile()
CheckResources()
GetFilePointer()
GetDataFromSecondFile()
plugin_natives
FindReplaceType()
FindReplacedString()
plugin_pause
UnregisterForwards()
UnpatchMemory()
plugin_unpause
RegisterForwards()
PatchMemory()
plugin_end
UnpatchMemory()
UnregisterForwards()
Destroy()
*/

/*

WEAPON MODELS HOOKS

OnDefaultDeploy
ProcessFullKey()
CheckCondition()
PfnSetModel
*/

public OnDefaultDeploy(Ent, const vMdl[], const pMdl[])


{
if(pev_valid(Ent) == PrivateDataSafe && TrieKeyExists(TrieWeaponModels,
vMdl))
{
new TrieWeaponData[WeaponsData], id, bool:ReplaceModel
TrieGetArray(TrieWeaponModels, vMdl, TrieWeaponData, sizeof
TrieWeaponData)

id = get_pdata_cbase(Ent, m_pPlayer, XoWeapon)

if(contain(TrieWeaponData[WeaponIdentifier], "+") != -1)


{
//Additive conditions were found, process each of them and check
if true
if(ProcessFullKey(id, TrieWeaponData[WeaponIdentifier],
charsmax(TrieWeaponData[WeaponIdentifier])))
{
ReplaceModel = true
}
}
else
{
//A single condition was found, process it
if(CheckCondition(id, TrieWeaponData[WeaponIdentifier],
charsmax(TrieWeaponData[WeaponIdentifier])))
{
ReplaceModel = true
}
}
if(ReplaceModel)
{
if(!equal(TrieWeaponData[vModel], NullItem))
{
set_pev(id, pev_viewmodel2, TrieWeaponData[vModel])
}
if(!equal(TrieWeaponData[pModel], NullItem))
{
set_pev(id, pev_weaponmodel2, TrieWeaponData[pModel])
}
}
}
}

public PfnSetModel(Ent, const Model[])


{
if(pev_valid(Ent))
{
new TrieKey[128]
formatex(TrieKey, charsmax(TrieKey), "%ss/v_%s", ModelKey, Model[9])
if(TrieKeyExists(TrieWeaponModels, TrieKey))
{
new TrieWeaponData[WeaponsData]
TrieGetArray(TrieWeaponModels, TrieKey, TrieWeaponData,
charsmax(TrieWeaponData))

if(!equal(TrieWeaponData[wModel], NullItem))
{
engfunc(EngFunc_SetModel, Ent, TrieWeaponData[wModel])
}
}
}
}

/*

PLAYER MODELS HOOKS

PfnSetClientKeyValue
GetCorrectKey()
ProcessFullKey
CheckCondition()
PfnClientUserInfoChanged()
GetCorrectKey
ProcessFullKey
CheckCondition()
OnClCorpse_Message
GetCorrectKey()
ProcessFullKey
CheckCondition()
*/

public PfnSetClientKeyValue(id, const Buffer[], const Key[], const Value[])


{
if(equal(Key, ModelKey))
{
new TrieKey[100]
GetCorrectKey(id, TrieKey, charsmax(TrieKey), Value)

if(TrieKey[0] != EOS)
{
new TrieModelData[ModelsData]
TravTrieGetArray(TriePlayerModels, TrieKey, TrieModelData, sizeof
TrieModelData)

if(!equal(Value, TrieModelData[ModelName]))
{
set_user_info(id, ModelKey, TrieModelData[ModelName])
set_pdata_int(id, m_iModelIndex, TrieModelData[ModelIndex],
XoPlayer)
}
return FMRES_SUPERCEDE
}
}
return FMRES_IGNORED
}

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

new CurrentModel[128]; get_user_info(id, ModelKey, CurrentModel,


charsmax(CurrentModel))
new TrieKey[100]; GetCorrectKey(id, TrieKey, charsmax(TrieKey), CurrentModel)

if(TrieKey[0] != EOS)
{
new TrieModelData[ModelsData]
TravTrieGetArray(TriePlayerModels, TrieKey, TrieModelData, sizeof
TrieModelData)

if(!equal(CurrentModel, TrieModelData[ModelName]))
{
set_user_info(id, ModelKey, TrieModelData[ModelName])
set_pdata_int(id, m_iModelIndex, TrieModelData[ModelIndex],
XoPlayer)
}
return FMRES_SUPERCEDE
}
return FMRES_IGNORED
}

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

new CurrentModel[128]; get_user_info(id, ModelKey, CurrentModel,


charsmax(CurrentModel))
new TrieKey[100]; GetCorrectKey(id, TrieKey, charsmax(TrieKey), CurrentModel)

if(TrieKey[0] != EOS)
{
new TrieModelData[ModelsData]
TravTrieGetArray(TriePlayerModels, TrieKey, TrieModelData, sizeof
TrieModelData)

set_msg_arg_string(1, TrieModelData[ModelName])
}
}

bool:GetCorrectKey(id, FullKey[], KeySize, const OldModel[] = "")


{
new Data[ModelsData], Key[100], BackUpKey[100]
new travTrieIter:TrieIter = GetTravTrieIterator(TriePlayerModels)

while(MoreTravTrie(TrieIter))
{
ReadTravTrieKey(TrieIter, Key, charsmax(Key))

if(equal(Key, OldModel))
{
copy(FullKey, KeySize, Key)
break
}
else
{
copy(BackUpKey, charsmax(BackUpKey), Key)
if(contain(Key, "+") != -1)
{
if(ProcessFullKey(id, Key, charsmax(Key)))
{
copy(FullKey, KeySize, BackUpKey)
break
}
}
else
{
if(CheckCondition(id, Key, charsmax(Key)))
{
copy(FullKey, KeySize, BackUpKey)
break
}
}
}
ReadTravTrieArray(TrieIter, Data, sizeof Data) //Hack, only to
increment the iterator
}

DestroyTravTrieIterator(TrieIter)
}

ProcessFullKey(id, Key[], Size)


{
new ValidConditions, TotalConditions, Left[100], Right[100]
while(Key[0] != EOS && strtok(Key, Left, charsmax(Left), Right,
charsmax(Right), '+'))
{
if(equal(Left, "ALL")) //ALL flag can't be used in combination with any
other flag
{
continue
}

if(CheckCondition(id, Left, charsmax(Left)))


{
ValidConditions = ValidConditions + 1
}

copy(Key, Size, Right)


TotalConditions = TotalConditions + 1
}

if(ValidConditions == TotalConditions)
{
return true
}
return false
}
bool:CheckCondition(id, Condition[], ConditionSize)
{
switch(Condition[0])
{
case 'S':
{
if(1 <= id <= MaxPlayers)
{
new PlayerAuthId[35]; get_user_authid(id, PlayerAuthId,
charsmax(PlayerAuthId))
if(equal(PlayerAuthId, Condition))
{
return true
}
}
}
case 'F':
{
if(contain(Condition, "Flag_") != -1)
{
replace(Condition, ConditionSize, "Flag_", "")

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

/*

SOUND HOOKS

PfnEmitSound
PfnEmitAmbientSound
*/

public PfnEmitSound(Ent, Channel, const Sound[], Float:Volume, Float:Attenuation,


Flags, Pitch)
{
if(pev_valid(Ent) && TrieKeyExists(TrieSounds, Sound))
{
new NewSound[128]
TrieGetString(TrieSounds, Sound, NewSound, charsmax(NewSound))
engfunc(EngFunc_EmitSound, Ent, Channel, NewSound, Volume, Attenuation,
Flags, Pitch)
return FMRES_SUPERCEDE
}
return FMRES_IGNORED
}

public PfnEmitAmbientSound(Ent, Float:Origin[3], const Sound[], Float:Volume,


Float:Attenuation, Flags, Pitch)
{
if(pev_valid(Ent) && TrieKeyExists(TrieSounds, Sound))
{
new NewSound[128]
TrieGetString(TrieSounds, Sound, NewSound, charsmax(NewSound))
engfunc(EngFunc_EmitAmbientSound, Ent, Origin, NewSound, Volume,
Attenuation, Flags, Pitch)
return FMRES_SUPERCEDE
}
return FMRES_IGNORED
}