#include <amxmodx>
#include <cstrike>
#include <fakemeta>
#include <fakemeta_util>
#include <engine>
#include <hamsandwich>
#define PLUGIN "Deception"
#define AUTHOR "joaquimandrade e luciaandrade"
#define VERSION "1.0"
new msgBarTimeIndex
new Array:bodies
new BodyUser[33 char]
new LastBodyWatched[33 char]
new Float:BodiesTimeCounter[33]
new DeceptedPlayer[33 char]
new bool:changedModel[33 char]
const ModelLen = 40
new Float:SuspectGaitSequences[] = {6.0,4.0}
new Float:PreviousGaitSequence[33]
new Ham:HamWeaponEvents[] = {Ham_Weapon_PrimaryAttack,Ham_Weapon_SecondaryAttack,Ham_Weapon_Reload}
new MaxPlayers
new const CvarDeceptionCamouflageTimeDft[] = "2"
new CvarDeceptionCamouflageTime
new CamouflageTime
new Float:CamouflageMaxDistance = 150.0
new Float:DetectionMaxDistance = 800.0
enum MLData
{
CamouflagedStart,
CamouflagedEnd
}
new MLStrings[MLData][] = {"DECEPTION_CAMOUFLAGE_START","DECEPTION_CAMOUFLAGE_END"}
new const Dictionary[] = "deception.txt"
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
register_forward(FM_CmdStart,"FMCmdStart");
RegisterHam(Ham_Killed,"player","playerKilled",1)
register_message(get_user_msgid("ClCorpse"),"message_clcorpse")
register_event("HLTV","newRound","a","1=0","2=0")
RegisterHam(Ham_TraceAttack,"player","playerAttacked")
new weaponName[24];
get_weaponname(1,weaponName,charsmax (weaponName));
for(new i=0;i<sizeof HamWeaponEvents;i++)
RegisterHam(HamWeaponEvents[i],weaponName,"weaponUse");
for (new i=3, LastWeapon=30; i<=LastWeapon; i++)
{
get_weaponname (i,weaponName,charsmax(weaponName));
for(new i=0;i<sizeof HamWeaponEvents;i++)
RegisterHam(HamWeaponEvents[i],weaponName,"weaponUse");
}
RegisterHam(Ham_Use,"grenade","grenadeUse")
register_forward(FM_SetClientKeyValue,"fw_SetClientKeyValue");
CvarDeceptionCamouflageTime = register_cvar("deception_camouflage_time",CvarDeceptionCamouflageTimeDft)
CamouflageTime = clamp(get_pcvar_num(CvarDeceptionCamouflageTime),1,5)
MaxPlayers = get_maxplayers()
register_dictionary(Dictionary)
}
public grenadeUse(id, idcaller, idactivator, use_type, Float:value)
{
checkIfIsBeingWatched(idactivator)
}
checkIfIsBeingWatched(id)
{
if(DeceptedPlayer{id} && (1<=id<=MaxPlayers))
{
new CsTeams:team = cs_get_user_team(id);
new Float:origin[3]
entity_get_vector(id,EV_VEC_origin,origin)
for(new i=1,CsTeams:teamViewer;i<=MaxPlayers;i++)
{
if(is_user_alive(i))
{
teamViewer = cs_get_user_team(i);
if(team != teamViewer)
{
if(fm_is_ent_visible_maxdistance(i,id,.maxdistance = DetectionMaxDistance) && is_in_viewcone(i,origin))
{
if(is_user_connected(DeceptedPlayer{id}))
{
checkRestoreModel(DeceptedPlayer{id})
}
DeceptedPlayer{id} = 0
doRestoreModel(id)
client_print(id,print_chat,"%L",id,MLStrings[CamouflagedEnd])
return true;
}
}
}
}
}
return false
}
public weaponUse(weaponID)
{
checkIfIsBeingWatched(pev(weaponID,pev_owner))
}
doRestoreModel(id)
{
changedModel{id} = false
dllfunc(DLLFunc_ClientUserInfoChanged,id,engfunc(EngFunc_GetInfoKeyBuffer,id));
}
checkRestoreModel(id)
{
if(changedModel{id})
{
doRestoreModel(id)
}
}
public plugin_cfg()
{
bodies = ArrayCreate()
msgBarTimeIndex = get_user_msgid("BarTime")
}
addBody(id)
{
ArrayPushCell(bodies,id)
}
removeBody(id)
{
for(new i=0;i<ArraySize(bodies);i++)
{
if(id == ArrayGetCell(bodies,i))
{
ArrayDeleteItem(bodies,i)
break;
}
}
}
public client_disconnect(id)
{
removeBody(id)
changedModel{id} = false
}
public newRound()
{
ArrayClear(bodies);
new newArray[33 char]
BodyUser = newArray
new otherArray[33 char]
DeceptedPlayer = otherArray
new bool:anotherArray[33 char]
changedModel = anotherArray
CamouflageTime = clamp(get_pcvar_num(CvarDeceptionCamouflageTime),1,5)
}
public message_clcorpse()
{
removeBody(get_msg_arg_int(12))
}
public playerKilled(id,idattacker, shouldgib)
{
addBody(id)
checkIfIsBeingWatched(id)
}
public playerAttacked(id, idattacker, Float:damage, Float:direction[3], tracehandle, damagebits)
{
checkIfIsBeingWatched(id)
}
public FMCmdStart(id,uc_handle,random_seed)
{
if(!DeceptedPlayer{id})
{
if((get_uc(uc_handle,UC_Buttons) & IN_USE) )
{
static Float:start[3], Float:view_ofs[3], Float:dest[3]
pev(id, pev_origin, start);
pev(id, pev_view_ofs, view_ofs);
xs_vec_add(start, view_ofs, start);
pev(id, pev_v_angle, dest);
engfunc(EngFunc_MakeVectors, dest);
global_get(glb_v_forward, dest);
xs_vec_mul_scalar(dest, CamouflageMaxDistance, dest);
xs_vec_add(start, dest, dest);
new watchingBody
for(new i=0, body, bodyUser, hit ;i<ArraySize(bodies);i++)
{
body = ArrayGetCell(bodies,i)
bodyUser = BodyUser{body}
if((!bodyUser || (bodyUser == id)) && (cs_get_user_team(id) != cs_get_user_team(body)))
{
engfunc ( EngFunc_TraceModel, start, dest, HULL_POINT, body ,0)
hit = get_tr2(0, TR_pHit);
if(hit == body)
{
watchingBody = body
break;
}
}
}
if(watchingBody)
{
if(LastBodyWatched{id} == watchingBody)
{
if(!increaseBodyWatchCounter(id,watchingBody))
{
LastBodyWatched{id} = 0
BodyUser{watchingBody} = 0;
}
}
else
{
if(LastBodyWatched{id})
{
resetBodyWatchCounter(id,LastBodyWatched{id});
BodyUser{LastBodyWatched{id}} = 0
}
LastBodyWatched{id} = watchingBody
}
}
else if(LastBodyWatched{id})
{
resetBodyWatchCounter(id,LastBodyWatched{id});
BodyUser{LastBodyWatched{id}} = 0
LastBodyWatched{id} = 0
}
}
else if(LastBodyWatched{id})
{
resetBodyWatchCounter(id,LastBodyWatched{id});
BodyUser{LastBodyWatched{id}} = 0
LastBodyWatched{id} = 0
}
}
}
increaseBodyWatchCounter(id,body)
{
new Float:startTime = BodiesTimeCounter[body]
if(!startTime)
{
BodiesTimeCounter[body] = get_gametime()
message_begin(MSG_ONE_UNRELIABLE, msgBarTimeIndex, _, id)
write_short(CamouflageTime)
message_end()
}
else
{
new Float:timeTaken = get_gametime() - startTime;
if(timeTaken >= float(CamouflageTime) )
{
BodiesTimeCounter[body] = 0.0
if(is_user_connected(body))
{
DeceptedPlayer{id} = body;
static modelPlayer[ModelLen]
static modelBody[ModelLen]
cs_get_user_model(id,modelPlayer,ModelLen-1)
cs_get_user_model(body,modelBody,ModelLen-1)
changedModel{id} = true;
changedModel{body} = true;
set_user_model(body,modelPlayer)
set_user_model(id,modelBody)
removeBody(body)
client_print(id,print_chat,"%L",id,MLStrings[CamouflagedStart])
}
return false;
}
}
return true;
}
resetBodyWatchCounter(id,body)
{
BodiesTimeCounter[body] = 0.0
message_begin(MSG_ONE_UNRELIABLE, msgBarTimeIndex, _, id)
write_short(0)
message_end()
}
public client_PreThink(id)
{
if(DeceptedPlayer{id})
{
new Float:newSequence
pev(id,pev_gaitsequence,newSequence)
if(PreviousGaitSequence[id] != newSequence)
{
for(new i=0;i<sizeof SuspectGaitSequences;i++)
{
if(newSequence == SuspectGaitSequences[i])
{
if(checkIfIsBeingWatched(id))
PreviousGaitSequence[id] = 0.0
break;
}
}
PreviousGaitSequence[id] = newSequence
}
}
}
set_user_model(id,model[])
{
engfunc(EngFunc_SetClientKeyValue,id,engfunc(EngFunc_GetInfoKeyBuffer,id),"model",model)
}
public fw_SetClientKeyValue(id,const infobuffer[],const key[])
{
return equal(key,"model") && changedModel{id} ? FMRES_SUPERCEDE : FMRES_IGNORED
}
bool:fm_is_ent_visible_maxdistance(index, entity,ignoremonsters = 0,Float:maxdistance)
{
new Float:start[3], Float:dest[3];
pev(index, pev_origin, start);
pev(index, pev_view_ofs, dest);
xs_vec_add(start, dest, start);
pev(entity, pev_origin, dest);
if(vector_distance(start,dest) <= maxdistance)
{
engfunc(EngFunc_TraceLine, start, dest, ignoremonsters, index, 0);
new Float:fraction;
get_tr2(0, TR_flFraction, fraction);
if (fraction == 1.0 || get_tr2(0, TR_pHit) == entity)
return true
}
return false;
}