The best anti-crash is using 1 player model for all player models. This will save you resources precached and avoid crashes on multiple model changes.
Here i will teach you how to use 1 Model and than play with Sub-Models. On plugin you will play with pev_body.
First on Model.
1. Create a Folder to gather all the player models.
2. Decompile all your models into that folder
3. Edit QC file of your main model
Code:
//reference mesh(es)
$bodygroup "studio"
{
studio "model1"
studio "model2"
studio "model3"
studio "model4"
}
4. Compile the model & it's done
Crucial Information:
- The model1/2/etc that we use on bodygroup can be named whatever you want but it must be the name of the main SMD file of the sub-model.
- Your models must be 1 Part only (unless the second part is the bomb/defuse). If your model is divided into several parts it won't work (at least i don't know how to make it work)
After everything is done properly you will have one player model with several sub-models. Now we can go to the plugin part.
Code:
#include <amxmodx>
#include <hamsandwich>
#include <fakemeta>
#include <cstrike>
#include <cl_buy>
#define TASKID 4256
#define MODEL_TASK 8425
new g_szModelName[] = "my_multimodel"
new g_iBody[33]
public plugin_init()
{
RegisterHam(Ham_AddPlayerItem, "player", "Player__AddPlayerItem", true)
RegisterHam(Ham_Spawn, "player", "Player__Spawn", true)
register_forward(FM_SetClientKeyValue, "Fw__SetClientKeyValue")
register_forward(FM_ClientUserInfoChanged, "Fw__ClientUserInfoChanged")
}
public plugin_precache()
{
new szPlayerModel[64]
formatex(szPlayerModel, charsmax(szPlayerModel), "models/player/%s/%s.mdl", g_szModelName, g_szModelName)
if(file_exists(szPlayerModel))
engfunc(EngFunc_PrecacheModel, szPlayerModel)
}
public client_putinserver(id)
g_iBody[id] = 0
public Player__AddPlayerItem(id , iWeapon)
{
if(cs_get_weapon_id(iWeapon) == CSW_C4)
set_pev(id, pev_body, g_iBody[id])
}
// You can remove this if players can't buy on your server, including Task__FixBody function
public client_buy(id, iItem)
{
if(iItem == CSW_DEFUSER && !cs_get_user_defuse(id))
set_task(0.5, "Task__FixBody", id + TASKID)
}
public Task__FixBody(id)
{
id -= TASKID
if(is_user_alive(id))
set_pev(id, pev_body, g_iBody[id])
}
public Player__Spawn(id)
{
if(is_user_alive(id))
{
static currentmodel[32]
engfunc(EngFunc_InfoKeyValue, engfunc(EngFunc_GetInfoKeyBuffer, id), "model", currentmodel, charsmax(currentmodel))
if(!equal(currentmodel, g_szModelName))
set_task(random_float(0.1, 2.9), "Task__SetModel", id + MODEL_TASK)
/* Example:
g_iBody[id] = cs_get_user_team(id) == CS_TEAM_CT ? 0 : 1
You should set body on spawn & on events where you would change the player model. Like Zombie Plague infection
After changing g_iBody you must change pev_body.
The reason we are using g_iBody is because we need to store the information for when a player buys defuse kit or gets a bomb
because that will mess with pev_body. So we either do this or a looping task to check the pev_body value. This way is better.
*/
}
}
public Task__SetModel(id)
{
id -= MODEL_TASK
if(is_user_alive(id))
{
engfunc(EngFunc_SetClientKeyValue, id, engfunc(EngFunc_GetInfoKeyBuffer, id), "model", g_szModelName)
set_pev(id, pev_body, g_iBody[id])
}
}
public Fw__SetClientKeyValue(id, const infobuffer[], const key[])
{
if(equal(key, "model") && !equal(infobuffer, g_szModelName))
return FMRES_SUPERCEDE
return FMRES_IGNORED
}
public Fw__ClientUserInfoChanged(id)
{
static currentmodel[32]
engfunc(EngFunc_InfoKeyValue, engfunc(EngFunc_GetInfoKeyBuffer, id), "model", currentmodel, charsmax(currentmodel))
if(!equal(currentmodel, g_szModelName))
engfunc(EngFunc_SetClientKeyValue, id, engfunc(EngFunc_GetInfoKeyBuffer, id), "model", g_szModelName)
return FMRES_IGNORED
}
In that code you already change the player model, all you need to do is manipulate the g_iBody[index] and set the pev_body when you need to. You can also create a models menu.
The client_buy forward can be found
here. You don't need to use it if your server doesn't allow the player to buy a defuse kit.
The bomb part should remain for safety since if a player gets the bomb it will change his pev_body.
Also you must NOT use plugins that use the cs_set_user_defuse native.
__________________