Code: Select all
#include <amxmodx>
#include <cstrike>
#include <fakemeta>
#include <hamsandwich>
#include <xs>
#include <zombieplague>
#if (AMXX_VERSION_NUM < 183)
#include <dhudmessage>
#endif
#define PLUGIN_NAME "[ZP] Addon: Hero"
#define PLUGIN_VERSION "1.0"
#define PLUGIN_AUTHOR "Batcon"
#define BIT_VALID(%0,%1) (%0 & (1<<(%1 & 31)))
#define BIT_ADD(%0,%1) (%0 |= (1<<(%1 & 31)))
#define BIT_SUB(%0,%1) (%0 &= ~(1<<(%1 & 31)))
#define BIT_INVERT(%0,%1) (%0 ^= (1<<(%1 & 31)))
#define IsNullEnt(%0) (%0 == -1 || %0 == 0)
#define IsValidEnt(%0) (!IsNullEnt(%0) && pev_valid(%0))
#define FILE_HERO_SETTING "zp_hero.ini"
#define FILE_HERO_LANG "zp_hero.txt"
#define HUD_NOTICE_X 0.6
#define HUD_NOTICE_Y 0.5
#define HUD_NOTICE_C 0, 155, 200
#define HUD_NOTICE_T 2.0
new const MAXBPAMMO[] = { -1, 52, -1, 90, 1, 32, 1, 100, 90, 1, 120, 100, 100, 90, 90, 90, 100, 120,
30, 120, 200, 32, 90, 120, 90, 2, 35, 90, 90, -1, 100 }
#define SLOT_PRIMARY 1
#define SLOT_SECONDARY 2
#define SLOT_KNIFE 3
#define SLOT_GRENADE 4
#define SLOT_C4 5
#define MAX_CLIENTS 32
#define TASK_ICON_ID 64
#define TASK_ICON_DELAY 0.3
#define TASK_AURA_ID 96
#define TASK_AURA_DELAY 0.1
#define AURA_RADIUS 20
// Linux extra offset
#define OFFSET_LINUX_WEAPON 4
#define OFFSET_LINUX_PLAYER 5
// CBasePlayerItem
#define m_pPlayer 41
#define m_pNext 42
#define m_iId 43
// CBasePlayer
#define m_rpgPlayerItems 367
new g_BitUserHero;
new g_sHeroModel[32];
new g_iHeroBody;
new g_iHeroArmor;
new g_iHeroHealth;
new Array:g_aHeroWeapons;
new g_iHeroMinPlayers;
new Array:g_aHeroes;
new g_sHeroModelIcon;
public plugin_init()
{
register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR);
RegisterHam(Ham_Spawn, "player", "CBasePlayer_Spawn_Post", true);
RegisterHam(Ham_Killed, "player", "CBasePlayer_Killed_Post", true);
RegisterHam(Ham_Touch, "weaponbox", "CWeaponBox_Touch", false);
register_dictionary(FILE_HERO_LANG);
register_clcmd("drop", "ClientCmd_Drop");
}
public plugin_cfg()
{
g_aHeroWeapons = ArrayCreate(32,1);
g_aHeroes = ArrayCreate(1,1);
SettingsFile_Load();
}
public plugin_natives()
{
register_native("zp_is_user_hero", "native_is_user_hero", 1);
register_native("zp_make_user_hero", "native_make_user_hero", 1);
}
public native_is_user_hero(pPlayer)
{
return BIT_VALID(g_BitUserHero, pPlayer);
}
public native_make_user_hero(pPlayer)
{
if(!is_user_alive(pPlayer))
return 0;
if(zp_get_user_zombie(pPlayer))
return 0;
if(zp_get_user_survivor(pPlayer))
return 0;
MakeUserHero(pPlayer);
return 1;
}
#if (AMXX_VERSION_NUM < 183)
public client_disconnect(pPlayer)
#else
public client_disconnected(pPlayer)
#endif
{
RemoveUserHero(pPlayer);
remove_task(pPlayer + TASK_ICON_ID);
}
public CBasePlayer_Spawn_Post(pPlayer)
{
if(!BIT_VALID(g_BitUserHero, pPlayer))
return;
RemoveUserHero(pPlayer);
CS_RemoveItemsBySlot(pPlayer, SLOT_PRIMARY);
CS_RemoveItemsBySlot(pPlayer, SLOT_SECONDARY);
CS_RemoveItemsBySlot(pPlayer, SLOT_GRENADE);
CS_RemoveItemsBySlot(pPlayer, SLOT_C4);
}
public CBasePlayer_Killed_Post(pVictim, pAttacker, Gibs)
{
RemoveUserHero(pVictim);
remove_task(pVictim + TASK_ICON_ID);
}
public CWeaponBox_Touch(pWeaponBox, pPlayer)
{
if(!is_user_alive(pPlayer))
return HAM_IGNORED;
if(!BIT_VALID(g_BitUserHero, pPlayer))
return HAM_IGNORED;
return HAM_SUPERCEDE;
}
public ClientCmd_Drop(pPlayer)
{
if(BIT_VALID(g_BitUserHero, pPlayer))
return PLUGIN_HANDLED;
return PLUGIN_CONTINUE;
}
public zp_user_humanized_pre(pPlayer)
{
if(!BIT_VALID(g_BitUserHero, pPlayer))
return;
RemoveUserHero(pPlayer);
CS_RemoveItemsBySlot(pPlayer, SLOT_PRIMARY);
CS_RemoveItemsBySlot(pPlayer, SLOT_SECONDARY);
CS_RemoveItemsBySlot(pPlayer, SLOT_GRENADE);
CS_RemoveItemsBySlot(pPlayer, SLOT_C4);
}
public zp_user_humanized_post(pPlayer, bSurvivor)
{
RemoveUserHero(pPlayer);
remove_task(pPlayer + TASK_ICON_ID);
if(bSurvivor)
return;
if(zp_has_round_started() && ArraySize(g_aHeroes))
set_task(TASK_ICON_DELAY, "Task_Client_DrawIcons", pPlayer + TASK_ICON_ID, _, _, "b");
}
public zp_user_infected_post(pPlayer)
{
RemoveUserHero(pPlayer);
remove_task(pPlayer + TASK_ICON_ID);
}
public zp_round_started(GameModeID)
{
if(GameModeID != MODE_INFECTION)
return;
new Players[MAX_CLIENTS], iPlayersNum;
get_players(Players, iPlayersNum, "a");
if(iPlayersNum < g_iHeroMinPlayers)
return;
new Humans[MAX_CLIENTS], iHumansNum;
new pPlayer;
for(new i; i < iPlayersNum; i++)
{
pPlayer = Players[i];
if(zp_get_user_zombie(pPlayer) || BIT_VALID(g_BitUserHero, pPlayer))
continue;
Humans[iHumansNum] = pPlayer;
iHumansNum++;
}
if(!iHumansNum)
return;
new pHero = Humans[random(iHumansNum)];
MakeUserHero(pHero);
new szUserName[32]; get_user_name(pHero, szUserName, charsmax(szUserName));
set_dhudmessage(HUD_NOTICE_C, HUD_NOTICE_X, HUD_NOTICE_Y, 0, 0.0, HUD_NOTICE_T, 1.0, 0.1);
show_dhudmessage(0, "%L", LANG_PLAYER, "NOTICE_HERO", szUserName);
if(ArraySize(g_aHeroes))
{
for(new i; i < iHumansNum; i++)
{
pPlayer = Humans[i];
if(BIT_VALID(g_BitUserHero, pPlayer))
continue;
set_task(TASK_ICON_DELAY, "Task_Client_DrawIcons", pPlayer + TASK_ICON_ID, _, _, "b");
}
}
}
public Task_Client_DrawIcons(pPlayer)
{
pPlayer -= TASK_ICON_ID;
static pHero;
static Float:vIcon[3];
static Float:vSrc[3];
static Float:vViewOfs[3];
static Float:vEnd[3];
static Float:vDir[3];
static Float:vEndPos[3];
static Float:fDistToWall;
static Float:fDistToHero;
static Float:fScal;
static Float:fFraction;
static iTrace;
iTrace = create_tr2();
pev(pPlayer, pev_origin, vSrc);
pev(pPlayer, pev_view_ofs, vViewOfs);
xs_vec_add(vSrc, vViewOfs, vSrc);
for(new i = 0; i < ArraySize(g_aHeroes); i++)
{
pHero = ArrayGetCell(g_aHeroes, i);
pev(pHero, pev_origin, vEnd);
xs_vec_sub(vEnd, vSrc, vDir);
engfunc(EngFunc_TraceLine, vSrc, vEnd, IGNORE_MONSTERS, 0, iTrace);
get_tr2(iTrace, TR_flFraction, fFraction);
fDistToHero = get_distance_f(vSrc, vEnd);
get_tr2(iTrace, TR_vecEndPos, vEndPos);
fDistToWall = get_distance_f(vSrc, vEndPos) - 10.0;
if(fFraction == 1.0)
{
if(fDistToHero < 256.0)
continue;
fDistToWall -= 30.0;
}
xs_vec_normalize(vDir, vDir);
xs_vec_mul_scalar(vDir, fDistToWall, vIcon);
xs_vec_add(vIcon, vSrc, vIcon);
fScal = 1.0 + fDistToWall / fDistToHero
if(fFraction == 1.0)
vIcon[2] += 36.0;
message_begin(MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, _, pPlayer);
write_byte(TE_SPRITE);
engfunc(EngFunc_WriteCoord, vIcon[0]);
engfunc(EngFunc_WriteCoord, vIcon[1]);
engfunc(EngFunc_WriteCoord, vIcon[2]);
write_short(g_sHeroModelIcon);
write_byte(floatround(fScal));
write_byte(125);
message_end() ;
}
free_tr2(iTrace);
}
public Task_Hero_Aura(pPlayer)
{
pPlayer -= TASK_AURA_ID;
static origin[3]; get_user_origin(pPlayer, origin);
message_begin(MSG_PVS, SVC_TEMPENTITY, origin);
write_byte(TE_DLIGHT);
write_coord(origin[0]);
write_coord(origin[1]);
write_coord(origin[2]);
write_byte(AURA_RADIUS);
write_byte(128);
write_byte(128);
write_byte(128);
write_byte(2);
write_byte(0);
message_end();
}
public MakeUserHero(pPlayer)
{
RemoveUserHero(pPlayer);
CS_RemoveItemsBySlot(pPlayer, SLOT_PRIMARY);
CS_RemoveItemsBySlot(pPlayer, SLOT_SECONDARY);
CS_RemoveItemsBySlot(pPlayer, SLOT_GRENADE);
CS_RemoveItemsBySlot(pPlayer, SLOT_C4);
BIT_ADD(g_BitUserHero, pPlayer);
ArrayPushCell(g_aHeroes, pPlayer);
set_pev(pPlayer, pev_health, float(g_iHeroHealth));
set_pev(pPlayer, pev_max_health, float(g_iHeroHealth));
cs_set_user_armor(pPlayer, g_iHeroArmor, CS_ARMOR_KEVLAR);
zp_override_user_model(pPlayer, g_sHeroModel, true);
set_pev(pPlayer, pev_body, g_iHeroBody);
for(new i, szWeaponName[32], iId; i < ArraySize(g_aHeroWeapons); i++)
{
ArrayGetString(g_aHeroWeapons, i, szWeaponName, charsmax(szWeaponName));
if((iId = zp_get_extra_item_id(szWeaponName)) != -1)
zp_force_buy_extra_item(pPlayer, iId, true);
else if((iId = get_weaponid(szWeaponName)) > 0)
CS_GiveWeapon(pPlayer, szWeaponName, true);
}
set_task(TASK_AURA_DELAY, "Task_Hero_Aura", pPlayer + TASK_AURA_ID, _, _, "b");
}
public RemoveUserHero(pPlayer)
{
if(!BIT_VALID(g_BitUserHero, pPlayer))
return;
BIT_SUB(g_BitUserHero, pPlayer);
for(new i = 0; i < ArraySize(g_aHeroes); i++)
{
if(ArrayGetCell(g_aHeroes, i) == pPlayer)
{
ArrayDeleteItem(g_aHeroes, i);
break;
}
}
remove_task(pPlayer + TASK_AURA_ID);
}
public SettingsFile_Load()
{
new szDirPath[64];
get_localinfo("amxx_configsdir", szDirPath, charsmax(szDirPath));
format(szDirPath, charsmax(szDirPath), "%s/%s", szDirPath, FILE_HERO_SETTING);
if(!file_exists(szDirPath))
{
new szError[100];
formatex(szError, charsmax(szError), "| File '%s' not found.", szDirPath);
set_fail_state(szError);
return;
}
new szBuffer[1024], szKey[64], szValue[960];
new iFile = fopen(szDirPath, "rt");
while(iFile && !feof(iFile))
{
fgets(iFile, szBuffer, charsmax(szBuffer));
if(!szBuffer[0] || szBuffer[0] == '/' || szBuffer[0] == ';')
continue;
strtok(szBuffer, szKey, charsmax(szKey), szValue, charsmax(szValue), '=');
trim(szKey);
trim(szValue);
if(equal(szKey, "HERO MODEL"))
{
copy(g_sHeroModel, charsmax(g_sHeroModel), szValue);
new szModel[96]; format(szModel, charsmax(szModel), "models/player/%s/%s.mdl", szValue, szValue);
engfunc(EngFunc_PrecacheModel, szModel);
}
else if(equal(szKey, "HERO BODY"))
{
g_iHeroBody = str_to_num(szValue);
}
else if(equal(szKey, "HERO ARMOR"))
{
g_iHeroArmor = str_to_num(szValue);
}
else if(equal(szKey, "HERO HEALTH"))
{
g_iHeroHealth = str_to_num(szValue);
}
else if(equal(szKey, "HERO WEAPONS"))
{
while (szValue[0] != 0 && strtok(szValue, szKey, charsmax(szKey), szValue, charsmax(szValue), ','))
{
trim(szKey)
trim(szValue)
ArrayPushString(g_aHeroWeapons, szKey);
}
}
else if(equal(szKey, "HERO ICON"))
{
g_sHeroModelIcon = engfunc(EngFunc_PrecacheModel, szValue);
}
else if(equal(szKey, "HERO MIN PLAYERS"))
{
g_iHeroMinPlayers = str_to_num(szValue);
}
}
if(iFile)
fclose(iFile);
}
stock CS_GiveWeapon(pPlayer, szWeaponName[], bool:bGiveAmmo = false)
{
new pItem = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, szWeaponName));
if(!pev_valid(pItem))
return 0;
ExecuteHamB(Ham_Spawn, pItem);
if(!ExecuteHamB(Ham_AddPlayerItem, pPlayer, pItem))
{
set_pev(pItem, pev_flags, FL_KILLME);
return 0;
}
ExecuteHamB(Ham_Item_AttachToPlayer, pItem, pPlayer);
emit_sound(pPlayer, CHAN_ITEM, "items/gunpickup2.wav", VOL_NORM, ATTN_NORM, 0, PITCH_NORM);
if(bGiveAmmo)
{
new iId = cs_get_weapon_id(pItem);
if(MAXBPAMMO[iId] != -1)
cs_set_user_bpammo(pPlayer, iId, MAXBPAMMO[iId]);
}
return pItem;
}
stock CS_DropItemsBySlot(pPlayer, iSlot)
{
new pItem = get_pdata_cbase(pPlayer, m_rpgPlayerItems + iSlot, OFFSET_LINUX_PLAYER);
if(IsNullEnt(pItem))
return;
new pNext;
new szWeaponName[28];
do
{
pNext = get_pdata_cbase(pItem, m_pNext, OFFSET_LINUX_WEAPON);
if(get_weaponname(get_pdata_int(pItem, m_iId, OFFSET_LINUX_WEAPON), szWeaponName, charsmax(szWeaponName)))
engclient_cmd(pPlayer, "drop", szWeaponName);
}
while((pItem = pNext) > 0)
}
stock CS_RemoveItemsBySlot(pPlayer, iSlot)
{
new pItem = get_pdata_cbase(pPlayer, m_rpgPlayerItems + iSlot, OFFSET_LINUX_PLAYER);
if(IsNullEnt(pItem))
return;
new pNext;
new iId;
do
{
pNext = get_pdata_cbase(pItem, m_pNext, OFFSET_LINUX_WEAPON);
iId = get_pdata_int(pItem, m_iId, OFFSET_LINUX_WEAPON);
if(get_user_weapon(pPlayer) == iId)
ExecuteHamB(Ham_Weapon_RetireWeapon, pItem);
ExecuteHamB(Ham_RemovePlayerItem, pPlayer, pItem);
ExecuteHamB(Ham_Item_Kill, pItem);
set_pev(pPlayer, pev_weapons, pev(pPlayer, pev_weapons) & ~(1<<iId));
cs_set_user_bpammo(pPlayer, iId, 0);
}
while((pItem = pNext) > 0)
}
/* AMXX-Studio Notes - DO NOT MODIFY BELOW HERE
*{\\ rtf1\\ ansi\\ deff0{\\ fonttbl{\\ f0\\ fnil Tahoma;}}\n\\ viewkind4\\ uc1\\ pard\\ lang1049\\ f0\\ fs16 \n\\ par }
*/