// #define SET_MODELINDEX
#define MAX_MODEL_LEN 64
#define MAX_PATH_LEN 128
#define MAX_PLAYERS 32
#define MAX_BUFFER_LEN MAX_MODEL_LEN + MAX_MODEL_LEN
#include <amxmodx>
#include <fakemeta>
#include <reapi>
#include <hamsandwich>
#define VERSION "0.0.2"
#define UserValidTeam(%1) (TEAM_TERRORIST <= get_member(%1, m_iTeam) <= TEAM_CT)
#define AllocString(%1) engfunc(EngFunc_AllocString,%1)
#define SetModel(%1,%2) engfunc(EngFunc_SetModel,%1,%2)
#define IsPlayer(%1) (1 <= %1 <= g_iMaxPlayers)
#define SetUserModeled(%1) g_bModeled |= 1<<(%1 & 31)
#define SetUserNotModeled(%1) g_bModeled &= ~( 1<<(%1 & 31))
#define IsUserModeled(%1) (g_bModeled & 1<<(%1 & 31))
#define SetUserConnected(%1) g_bConnected |= 1<<(%1 & 31)
#define SetUserNotConnected(%1) g_bConnected &= ~( 1<<(%1 & 31))
#define IsUserConnected(%1) (g_bConnected & 1<<(%1 & 31))
const ClCorpse_ModelName = 1
const ClCorpse_PlayerID = 12
const g_ulModelIndexPlayer = 491
new const MODEL[] = "model"
new const g_szMapEntitys[][] = {"cycler_sprite", "cycler", "armoury_entity"}
new const g_szDefaultModels[][] = {"", "urban", "terror", "leet", "arctic",
"gsg9", "gign", "sas", "guerilla", "vip", "militia", "spetsnaz"
}
new const g_szWeaponNames[CSW_P90+1][] = {"","p228","","scout","hegrenade","xm1014","c4","mac10",
"aug","smokegrenade","elite","fiveseven","ump45","sg550","galil","famas","usp","glock18","awp",
"mp5navy","m249","m3","m4a1","tmp","g3sg1","flashbang","deagle","sg552","ak47","knife","p90"
}
new g_iWeaponIds[CSW_P90+1]
new Trie:g_tDefaultModels, Trie:g_tModelIndexes, Trie:g_tMapModels
new Trie:g_tViewModels, Trie:g_tWeaponModels, Trie:g_tWorldModels
new g_bConnected, g_bModeled, g_iMaxPlayers, bool:g_bPlayerModels
new g_szCurrentModel[MAX_PLAYERS+1][MAX_MODEL_LEN]
public plugin_init()
{
register_plugin("Models Replacement", VERSION, "ConnorMcLeod | Vaqtincha")
if(g_bPlayerModels)
{
register_forward(FM_SetClientKeyValue, "SetClientKeyValue_Pre", 0)
register_message(get_user_msgid("ClCorpse"), "Message_ClCorpse")
}
if(g_tWorldModels)
{
register_forward(FM_SetModel, "SetModel_Pre", 0)
}
if(g_tMapModels)
{
SetMapModels()
}
g_iMaxPlayers = get_maxplayers()
}
public plugin_precache()
{
new szConfigFile[MAX_PATH_LEN]
get_localinfo("amxx_configsdir", szConfigFile, charsmax(szConfigFile))
add(szConfigFile, charsmax(szConfigFile), "/models_replacement.ini")
if(file_exists(szConfigFile))
{
new iFile = fopen(szConfigFile, "rt")
if(!iFile)
{
set_fail_state("[MODELS_REPLACEMENT] ERROR: Failed reading file!")
return
}
new szDatas[MAX_BUFFER_LEN + 10], szWeaponClass[32], iId, c
new szOldModel[MAX_MODEL_LEN], szNewModel[MAX_MODEL_LEN]
new Trie:tRegisterWeaponDeploy = TrieCreate()
new Trie:tWeaponsIds = TrieCreate()
g_tModelIndexes = TrieCreate()
g_tDefaultModels = TrieCreate()
for(new i = 1; i<sizeof(g_szDefaultModels); i++)
{
TrieSetCell(g_tDefaultModels, g_szDefaultModels, i)
}
for(new i = CSW_P228; i <= CSW_P90; i++)
{
TrieSetCell(tWeaponsIds, g_szWeaponNames, g_iWeaponIds)
}
while(!feof(iFile))
{
fgets(iFile, szDatas, charsmax(szDatas))
trim(szDatas)
if(!(c = szDatas[0]) || c == ';' || c == '#')
{
continue
}
if(parse(szDatas, szOldModel, charsmax(szOldModel), szNewModel, charsmax(szNewModel)) != 2)
{
continue
}
if(!szOldModel[0] || !szNewModel[0] || equal(szNewModel, szOldModel))
{
continue
}
if(TrieKeyExists(g_tDefaultModels, szOldModel))
{
if(PrecachePlayerModel(szNewModel))
{
TrieSetString(g_tDefaultModels, szOldModel, szNewModel)
g_bPlayerModels = true
}
}else{
if(((c = szOldModel[0]) == 'p' || c == 'v' ) && szOldModel[1] == '_')
{
if(equal(szOldModel[2], "mp5", 3))
{
copy(szWeaponClass, charsmax(szWeaponClass), "weapon_mp5navy")
}else{
formatex(szWeaponClass, charsmax(szWeaponClass), "weapon_%s", szOldModel[2])
}
if(!TrieGetCell(tWeaponsIds, szWeaponClass[7], iId))
{
server_print("[MODELS_REPLACEMENT] WARNING: Invalid weapon class ^"%s^" will be skipped!", szWeaponClass)
continue
}
if(!TrieKeyExists(tRegisterWeaponDeploy, szWeaponClass))
{
TrieSetCell
(
tRegisterWeaponDeploy,
szWeaponClass,
RegisterHam(Ham_Item_Deploy, szWeaponClass, "ItemDeploy_Post", true)
)
}
format(szNewModel, charsmax(szNewModel), "models/%s.mdl", szNewModel)
if(c == 'v')
{
if(!g_tViewModels)
{
g_tViewModels = TrieCreate()
}
if(PrecacheWeaponModel(szNewModel))
{
TrieSetCell(g_tViewModels, szWeaponClass, AllocString(szNewModel))
}
}else{
if(!g_tWeaponModels)
{
g_tWeaponModels = TrieCreate()
}
if(PrecacheWeaponModel(szNewModel))
{
TrieSetCell(g_tWeaponModels, szWeaponClass, AllocString(szNewModel))
}
}
}else{
format(szOldModel, charsmax(szOldModel), "models/%s.mdl", szOldModel)
format(szNewModel, charsmax(szNewModel), "models/%s.mdl", szNewModel)
if(c == 'w')
{
if(!g_tWorldModels)
{
g_tWorldModels = TrieCreate()
}
else if(TrieKeyExists(g_tWorldModels, szOldModel))
{
continue
}
if(PrecacheWeaponModel(szNewModel))
{
TrieSetString(g_tWorldModels, szOldModel, szNewModel)
}
}
}
if(!g_tMapModels)
{
g_tMapModels = TrieCreate()
}
if(PrecacheWeaponModel(szNewModel))
{
TrieSetString(g_tMapModels, szOldModel, szNewModel)
}
}
}
fclose(iFile)
TrieDestroy(tRegisterWeaponDeploy)
TrieDestroy(tWeaponsIds)
}else{
new iFile = fopen(szConfigFile, "w")
if(!iFile)
{
set_fail_state("[MODELS_REPLACEMENT] ERROR: Failed creating file!")
return
}
fputs(iFile, "^n; Format: ^"old model^" ^"new model^" (without 'models/' & '.mdl')^n;^n; Examples:^n")
fputs(iFile, "^n; ^"arctic^" ^"vip^"^n; ^"chick^" ^"winebottle^"")
fputs(iFile, "^n; ^"v_awp^" ^"custom/v_awp^"^n; ^"p_awp^" ^"custom/p_awp^"^n; ^"w_awp^" ^"custom/w_awp^"")
fclose(iFile)
}
}
public client_putinserver(id)
{
if(!is_user_hltv(id))
{
SetUserConnected(id)
}
}
public client_disconnected(id)
{
SetUserNotModeled(id)
SetUserNotConnected(id)
}
public ItemDeploy_Post(wEnt)
{
if(wEnt <= 0)
{
return
}
new id = get_member(wEnt, m_pPlayer)
if(IsPlayer(id))
{
new iszNewModel, szWeaponClass[32]
set_entvar(wEnt, var_classname, szWeaponClass, charsmax(szWeaponClass))
if(g_tViewModels && TrieGetCell(g_tViewModels, szWeaponClass, iszNewModel))
{
set_entvar(id, var_viewmodel, iszNewModel)
}
if(g_tWeaponModels && TrieGetCell(g_tWeaponModels, szWeaponClass, iszNewModel))
{
set_entvar(id, var_weaponmodel, iszNewModel)
}
}
}
public SetModel_Pre(iEnt, const szModel[])
{
/* if(!pev_valid(iEnt))
{
return FMRES_IGNORED
} */
new szNewModel[MAX_MODEL_LEN]
if(TrieGetString(g_tWorldModels, szModel, szNewModel, charsmax(szNewModel)))
{
SetModel(iEnt, szNewModel)
return FMRES_SUPERCEDE
}
return FMRES_IGNORED
}
public SetClientKeyValue_Pre(id, const szInfoBuffer[], const szKey[], const szValue[])
{
if(!equal(szKey, MODEL) || !IsUserConnected(id) || !UserValidTeam(id))
{
return FMRES_IGNORED
}
new szSupposedModel[MAX_MODEL_LEN]
if(TrieGetString(g_tDefaultModels, szValue, szSupposedModel, charsmax(szSupposedModel)))
{
if(szSupposedModel[0])
{
if(!IsUserModeled(id) || !equal(g_szCurrentModel[id], szSupposedModel) || !equal(szValue, szSupposedModel))
{
copy(g_szCurrentModel[id], MAX_MODEL_LEN-1, szSupposedModel)
SetUserModeled(id)
set_user_info(id, MODEL, szSupposedModel)
#if defined SET_MODELINDEX
new iModelIndex
TrieGetCell(g_tModelIndexes, szSupposedModel, iModelIndex)
// set_pev(id, pev_modelindex, iModelIndex); // is this needed ?
set_member(id, m_modelIndexPlayer, iModelIndex)
#endif
return FMRES_SUPERCEDE
}
}
if(IsUserModeled(id))
{
SetUserNotModeled(id)
g_szCurrentModel[id][0] = 0
}
}
return FMRES_IGNORED
}
public Message_ClCorpse()
{
new id = get_msg_arg_int(ClCorpse_PlayerID)
if(IsUserModeled(id))
{
set_msg_arg_string(ClCorpse_ModelName, g_szCurrentModel[id])
}
}
public plugin_end()
{
if(g_tModelIndexes)
{
TrieDestroy(g_tModelIndexes)
}
if(g_tViewModels)
{
TrieDestroy(g_tViewModels)
}
if(g_tWeaponModels)
{
TrieDestroy(g_tWeaponModels)
}
if(g_tWorldModels)
{
TrieDestroy(g_tWorldModels)
}
if(g_tMapModels)
{
TrieDestroy(g_tMapModels)
}
}
SetMapModels()
{
new iEnt = FM_NULLENT
new szSupposedModel[MAX_MODEL_LEN], szModel[MAX_MODEL_LEN]
for(new i = 0; i <sizeof(g_szMapEntitys); i++)
{
while((iEnt = engfunc(EngFunc_FindEntityByString, iEnt, "classname", g_szMapEntitys)))
{
get_entvar(iEnt, var_model, szModel, charsmax(szModel));
if(TrieGetString(g_tMapModels, szModel, szSupposedModel, charsmax(szSupposedModel)))
{
SetModel(iEnt, szSupposedModel)
}
}
}
}
PrecacheWeaponModel(const szModel[])
{
new szMsg[MAX_MODEL_LEN + 64]
if(!file_exists(szModel))
{
formatex(szMsg, charsmax(szMsg), "[MODELS_REPLACEMENT] ERROR: Model ^"%s^" not found!", szModel)
set_fail_state(szMsg)
return 0
}
precache_model(szModel)
return 1
}
PrecachePlayerModel(const szModel[])
{
if(TrieKeyExists(g_tModelIndexes, szModel) || TrieKeyExists(g_tDefaultModels, szModel))
{
return 1
}
new szFileToPrecache[64], szMsg[MAX_MODEL_LEN + 64]
formatex(szFileToPrecache, charsmax(szFileToPrecache), "models/player/%s/%s.mdl", szModel, szModel)
if(!file_exists(szFileToPrecache))
{
formatex(szMsg, charsmax(szMsg), "[MODELS_REPLACEMENT] ERROR: Player model ^"%s^" not found!", szFileToPrecache)
set_fail_state(szMsg)
return 0
}
TrieSetCell(g_tModelIndexes, szModel, precache_model(szFileToPrecache))
formatex(szFileToPrecache, charsmax(szFileToPrecache), "models/player/%s/%st.mdl", szModel, szModel)
if(file_exists(szFileToPrecache))
{
precache_model(szFileToPrecache)
return 1
}
formatex(szFileToPrecache, charsmax(szFileToPrecache), "models/player/%s/%sT.mdl", szModel, szModel)
if(file_exists(szFileToPrecache))
{
precache_model(szFileToPrecache)
return 1
}
return 1
}