Иконка ресурса

reapi Crossbow 0.1

Нет прав для скачивания
Автор
Vaqtincha
Исходный код
// Copyright © 2020 Vaqtincha

#include <amxmodx>
#include <fakemeta>
#include <reapi>
#include <hamsandwich>
#include <xs>

/**■■■■■■■■■■■■■■■■■■■■■■■■■■■■ CONFIG START ■■■■■■■■■■■■■■■■■■■■■■■■■■■■*/

const WEAPON_MAX_CLIP = 5
const WEAPON_BUY_CLIP = 5
const WEAPON_MAX_AMMO = 15
const Float:WEAPON_RECOIL = 1.4
const Float:WEAPON_MAX_SPEED = 260.0


new const WEAPON_V_MODEL[] = "models/hl_ports/v_crossbow.mdl"
new const WEAPON_W_MODEL[] = "models/hl_ports/w_crossbow.mdl"
new const WEAPON_P_MODEL[] = "models/hl_ports/p_crossbow.mdl"
new const BOLT_MODEL[] = "models/crossbow_bolt.mdl"

new const WEAPON_FIRE_SOUND[] = "weapons/xbow_fire1.wav"


const Float:BOLT_DAMAGE = 120.0
const Float:BOLT_AIR_VELOCITY = 3600.0
const Float:BOLT_KILL_DELAY = 5.0
const Float:BOLT_ANGULAR_VELOCITY = 30.0 // angle speed
#define BOLT_TOUCH_USE_BUTTON


/**■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ CONFIG END ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■*/

// #define PL_DEBUG
#define PL_VERSION "0.1"

const CUSTOM_WEAPON_INDEX = 39752552
const CUSTOM_WEAPON_AMMO_INDEX = 18

const CBasePlayerWeapon_Members:m_bWaitReload = m_Weapon_bSecondarySilencerOn
const CBaseEntity_Members:pLAYER_AMMO_MEMBER_NAME = ammo_57mm


#define BASE_WEAPON_NAME "weapon_p90" // fuck amxx compiler
new const CUSTOM_WEAPON_NAME[] = "weapon_crossbowhl"

new const BASE_ENTITY_CLASSNAME[] = "info_target"
new const CUSTOM_ENTITY_CLASSNAME[] = "bolt"

new const WEAPON_SOUNDS[][] =
{
"weapons/xbow_reload1.wav",
"weapons/xbow_hitbod1.wav",
"weapons/xbow_hitbod2.wav",
"weapons/xbow_hit1.wav"
}

new const Float:g_vecColorTeam[any:TEAM_CT + 1][3] =
{
{ 0.0, 250.0, 0.0 }, // TEAM_UNASSIGNED
{ 250.0, 0.0, 0.0 }, // TEAM_TERRORIST
{ 0.0, 0.0, 250.0 } // TEAM_CT
}

enum crossbow_anims_e
{
CROSSBOW_IDLE1 = 0,
CROSSBOW_IDLE_EMPTY,
CROSSBOW_FIRE1,
CROSSBOW_FIRE_LAST,
CROSSBOW_RELOAD,
CROSSBOW_DRAW,
CROSSBOW_DRAW_SHORT,
CROSSBOW_DRAW_EMPTY
}

enum p90_anims_e
{
P90_IDLE1 = 0,
P90_RELOAD,
P90_DRAW,
P90_SHOOT1,
P90_SHOOT2,
P90_SHOOT3
}

enum
{
GROUP_OP_AND = 0,
GROUP_OP_NAND
}


enum hook_s
{
any:iFunctionId,
szCallback[32],
szClass[32],
bool:bIsPost
}

enum
{
FORWARD_REGISTER,
FORWARD_ENABLE,
FORWARD_DISABLE
}

#define IsHamHook(%1) (g_aHookData[%1][szClass][0] > 0)
#define IsCustomWeapon(%1) (get_entvar(%1, var_impulse) == CUSTOM_WEAPON_INDEX)

#if !defined write_coord_f
#define write_coord_f(%1) engfunc(EngFunc_WriteCoord, %1)
#endif

#define VECTOR_ZERO Float:{0.0, 0.0, 0.0}

new const g_aHookData[][hook_s] =
{
{ RG_CBasePlayer_GiveAmmo, "CBasePlayer_GiveAmmo", "", false },
{ RG_CBasePlayer_AddPlayerItem, "CBasePlayer_AddPlayerItem", "", false },
{ RG_CBasePlayer_OnSpawnEquip, "CBasePlayer_OnSpawnEquip", "", true },
{ RG_CWeaponBox_SetModel, "CWeaponBox_SetModel", "", false },
{ RG_BuyGunAmmo, "BuyGunAmmo", "", false },
{ RG_CSGameRules_RemoveGuns, "CSGameRules_RemoveGuns", "", true },

{ Ham_Item_Holster, "CBasePlayerItem_Holster", BASE_WEAPON_NAME, true },
{ Ham_Item_Deploy, "CBasePlayerItem_Deploy", BASE_WEAPON_NAME, true },
{ Ham_Weapon_PrimaryAttack, "CBasePlayerWeapon_PrimAttack", BASE_WEAPON_NAME, false },
{ Ham_Item_AddToPlayer, "CBasePlayerItem_AddToPlayer", BASE_WEAPON_NAME, true },
{ Ham_Weapon_Reload, "CBasePlayerWeapon_Reload", BASE_WEAPON_NAME, true },
{ Ham_CS_Weapon_SendWeaponAnim, "CBasePlayerWeapon_SendWpnAnim", BASE_WEAPON_NAME, false },
#if !defined PL_DEBUG
{ Ham_CS_Item_CanDrop, "CBasePlayerItem_CanDrop", BASE_WEAPON_NAME, false },
#endif
{ Ham_CS_Item_GetMaxSpeed, "CBasePlayerItem_GetMaxSpeed", BASE_WEAPON_NAME, false }
}

new any:g_hHookHandle[sizeof(g_aHookData)], g_iFwdUpdateClientData

new WeaponIdType:BASE_WEAPON_ID, BASE_WEAPON_AMMO_INDEX, BASE_WEAPON_SLOT = -1, BASE_WEAPON_POSITION
new BASE_WEAPON_AMMO_MAX, BASE_WEAPON_BUY_CLIP, BASE_WEAPON_AMMO_NAME[32]

new bool:g_bActiveItem[MAX_CLIENTS + 1], g_pItem[MAX_CLIENTS + 1], g_pBuyItem[MAX_CLIENTS + 1]
new g_iFallowSprite, g_iModelIndexLaser


// Warmup API
public WarmupStateChanged(bool:bWarmupState)
{
ForwardsState(FORWARD_DISABLE)

if (!bWarmupState)
{
ForwardsState(bWarmupState ? FORWARD_ENABLE : FORWARD_DISABLE)
CSGameRules_RemoveGuns() // remove all bolt entitys

new aPlayers[32], iCount, pPlayer
get_players(aPlayers, iCount, "ah")

for (--iCount; iCount >= 0; iCount--)
{
pPlayer = aPlayers[iCount]
SendWeaponListSpecial(pPlayer, BASE_WEAPON_NAME, BASE_WEAPON_AMMO_MAX, BASE_WEAPON_AMMO_INDEX)

// if (GetCustomItem(pPlayer) != NULLENT)
{
// rg_remove_all_items(pPlayer)
rg_remove_item(pPlayer, CUSTOM_WEAPON_NAME, true)
}
}
}
else
{
ForwardsState(FORWARD_ENABLE)
set_cvar_num("mp_warmup_player_health", 100)
}
}

public WarmupCanHaveItem(const pPlayer, const pItem)
{
return IsCustomWeapon(pItem) ? PLUGIN_CONTINUE : PLUGIN_HANDLED
}

public plugin_precache()
{
precache_model(WEAPON_P_MODEL)
precache_model(WEAPON_V_MODEL)
precache_model(WEAPON_W_MODEL)
precache_model(BOLT_MODEL)

precache_sound(WEAPON_FIRE_SOUND)
ParseSpriteDesc(CUSTOM_WEAPON_NAME)

for (new i = 1; i < sizeof(WEAPON_SOUNDS); i++) {
precache_sound(WEAPON_SOUNDS)
}

g_iFallowSprite = precache_model("sprites/smoke.spr")
g_iModelIndexLaser = g_iFallowSprite
// g_iModelIndexLaser = precache_model("sprites/laserbeam.spr")
}

public client_putinserver(pPlayer)
{
g_bActiveItem[pPlayer] = false
g_pItem[pPlayer] = g_pBuyItem[pPlayer] = NULLENT
}

public plugin_cfg()
{
BASE_WEAPON_ID = rg_get_weapon_info(BASE_WEAPON_NAME, WI_ID)
BASE_WEAPON_AMMO_INDEX = rg_get_weapon_info(BASE_WEAPON_ID, WI_AMMO_TYPE)
BASE_WEAPON_BUY_CLIP = rg_get_weapon_info(BASE_WEAPON_ID, WI_BUY_CLIP_SIZE)
rg_get_weapon_info(BASE_WEAPON_ID, WI_AMMO_NAME, BASE_WEAPON_AMMO_NAME, charsmax(BASE_WEAPON_AMMO_NAME))
}


public plugin_init()
{
register_plugin("Crossbow", PL_VERSION, "Vaqtincha")

ForwardsState(FORWARD_REGISTER)

#if defined PL_DEBUG
ForwardsState(FORWARD_ENABLE)
RegisterHookChain(RG_CBasePlayer_UseEmpty, "CBasePlayer_UseEmpty", .post = true)
#endif
}

public CBasePlayer_UseEmpty(const pPlayer)
{
if (get_viewent(pPlayer) == pPlayer)
{
new pEntity = NULLENT
while ((pEntity = rg_find_ent_by_class(pEntity, CUSTOM_ENTITY_CLASSNAME)))
{
if (get_entvar(pEntity, var_owner) == pPlayer && get_entvar(pEntity, var_movetype) == MOVETYPE_FLY)
{
engset_view(pPlayer, pEntity)
return
}
}
}

engset_view(pPlayer, pPlayer)
}

public UpdateClientData(const pPlayer, const sendweapons, const CD_Handle)
{
if (g_bActiveItem[pPlayer] && sendweapons) {
set_cd(CD_Handle, CD_flNextAttack, get_gametime() + 0.1)
}
}

public CSGameRules_RemoveGuns()
{
new pEntity = NULLENT
while ((pEntity = rg_find_ent_by_class(pEntity, CUSTOM_ENTITY_CLASSNAME)))
{
RemoveEntity(pEntity)
}
}

public CWeaponBox_SetModel(const pWeaponBox, const szModel[])
{
if (pWeaponBox <= 0)
return

new pWeapon = GetWeaponBoxWeapon(pWeaponBox)
if (pWeapon > 0 && IsCustomWeapon(pWeapon))
{
if (get_member(pWeapon, m_bWaitReload))
set_entvar(pWeaponBox, var_body, 1)

// if (get_member(pWeaponBox, m_WeaponBox_rgAmmo, 1)) // for other regamedll
if (get_member(pWeaponBox, m_WeaponBox_rgAmmo, BASE_WEAPON_AMMO_INDEX))
set_entvar(pWeaponBox, var_sequence, 1) // has backpack ammo

SetHookChainArg(2, ATYPE_STRING, WEAPON_W_MODEL)
}
}

public BuyGunAmmo(const pPlayer, const pItem, const bool:blinkMoney)
{
g_pBuyItem[pPlayer] = pItem > 0 && IsCustomWeapon(pItem) ? pItem : NULLENT
}

public CBasePlayer_OnSpawnEquip(const pPlayer, bool:addDefault, bool:equipGame)
{
if (/* !get_member(pPlayer, m_bJustConnected) && */ GetCustomItem(pPlayer) == NULLENT)
{
GiveItem(pPlayer)
}
}

public CBasePlayer_AddPlayerItem(const pPlayer, const pItem)
{
g_pItem[pPlayer] = pItem > 0 && IsCustomWeapon(pItem) ? pItem : NULLENT
}


public CBasePlayer_GiveAmmo(const pPlayer, const iAmount, const szName[], const iMax)
{
if (!szName[0] || iAmount < 1 || !equali(szName, BASE_WEAPON_AMMO_NAME[5]) || !is_user_alive(pPlayer))
return HC_CONTINUE

if (!is_nullent(g_pBuyItem[pPlayer]) && iMax == WEAPON_MAX_AMMO && iAmount == BASE_WEAPON_BUY_CLIP) // buy ammo
{
SetHookChainReturn(ATYPE_INTEGER, GiveAmmo(pPlayer, g_pBuyItem[pPlayer], WEAPON_BUY_CLIP, iMax))
g_pBuyItem[pPlayer] = NULLENT
return HC_SUPERCEDE
}

if (!is_nullent(g_pItem[pPlayer])) // touch ammo (weaponbox)
{
SetHookChainReturn(ATYPE_INTEGER, GiveAmmo(pPlayer, g_pItem[pPlayer], iAmount, iMax))
g_pItem[pPlayer] = NULLENT
return HC_SUPERCEDE
}

return HC_CONTINUE
}

public CBasePlayerWeapon_SendWpnAnim(const pWeapon, const iAnim, const skiplocal)
{
if (pWeapon <= 0 || !IsCustomWeapon(pWeapon))
return HAM_IGNORED

new pPlayer = get_member(pWeapon, m_pPlayer)

if (pPlayer <= 0)
return HAM_IGNORED

switch (iAnim)
{
case P90_IDLE1:
{
set_member(pWeapon, m_bWaitReload, false)
SendWeaponAnim(pPlayer, get_member(pWeapon, m_Weapon_iClip) > 0 ? CROSSBOW_IDLE1 : CROSSBOW_IDLE_EMPTY)
}
case P90_RELOAD:
{
set_member(pWeapon, m_bWaitReload, true)
SendWeaponAnim(pPlayer, CROSSBOW_RELOAD)
set_member(pPlayer, m_flNextAttack, 2.7)

SetThink(pWeapon, "DelayIdleSetThink")
set_entvar(pWeapon, var_nextthink, get_gametime() + 0.1)
}
}

return HAM_SUPERCEDE
}

public CBasePlayerItem_CanDrop(const pItem)
{
if (pItem <= 0 || !IsCustomWeapon(pItem))
return HAM_IGNORED

SetHamReturnInteger(false)
return HAM_SUPERCEDE
}


public CBasePlayerItem_GetMaxSpeed(const pItem)
{
SetHamReturnFloat(WEAPON_MAX_SPEED)
return HAM_SUPERCEDE
}

public CBasePlayerItem_AddToPlayer(const pItem, const pPlayer)
{
if (pItem <= 0 || !is_user_alive(pPlayer))
return HAM_IGNORED

// def weapon info cache
if (BASE_WEAPON_AMMO_MAX == 0)
BASE_WEAPON_AMMO_MAX = rg_get_iteminfo(pItem, ItemInfo_iMaxAmmo1)
if (BASE_WEAPON_SLOT == -1)
BASE_WEAPON_SLOT = rg_get_iteminfo(pItem, ItemInfo_iSlot)
if (BASE_WEAPON_POSITION == 0)
BASE_WEAPON_POSITION = rg_get_iteminfo(pItem, ItemInfo_iPosition)

if (IsCustomWeapon(pItem))
{
set_member(pItem, m_Weapon_iPrimaryAmmoType, CUSTOM_WEAPON_AMMO_INDEX)

if (!get_member(pItem, m_Weapon_iPlayEmptySound)) // first pickup
{
set_member(pItem, m_Weapon_iPrimaryAmmoType, CUSTOM_WEAPON_AMMO_INDEX)
set_member(pItem, m_bWaitReload, true)
}

SendWeaponListSpecial(pPlayer, CUSTOM_WEAPON_NAME, WEAPON_MAX_AMMO, CUSTOM_WEAPON_AMMO_INDEX)
}
else
{
SendWeaponListSpecial(pPlayer, BASE_WEAPON_NAME, BASE_WEAPON_AMMO_MAX, BASE_WEAPON_AMMO_INDEX)
}

return HAM_IGNORED
}

public DelayIdleSetThink(const pWeapon)
{
if (!is_nullent(pWeapon))
{
set_member(pWeapon, m_Weapon_flTimeWeaponIdle, 2.7)
SetThink(pWeapon, "")
set_entvar(pWeapon, var_nextthink, -1.0)
}
}

public CBasePlayerItem_Deploy(const pItem)
{
if (pItem <= 0 || !IsCustomWeapon(pItem))
{
return HAM_IGNORED
}

new pPlayer = get_member(pItem, m_pPlayer)

if (pPlayer <= 0)
return HAM_IGNORED

if (get_member(pItem, m_Weapon_iClip) < 1)
{
SendWeaponAnim(pPlayer, CROSSBOW_DRAW_EMPTY)
}
else if (get_member(pItem, m_bWaitReload))
{
SendWeaponAnim(pPlayer, CROSSBOW_DRAW)
set_member(pItem, m_Weapon_flNextPrimaryAttack, 2.1)
set_member(pPlayer, m_flNextAttack, 2.1)
set_member(pItem, m_Weapon_flTimeWeaponIdle, 2.15)
}
else
{
SendWeaponAnim(pPlayer, CROSSBOW_DRAW_SHORT)
set_member(pItem, m_Weapon_flNextPrimaryAttack, 0.60)

set_member(pPlayer, m_flNextAttack, 0.60)
}

set_entvar(pPlayer, var_viewmodel, WEAPON_V_MODEL)
set_entvar(pPlayer, var_weaponmodel, WEAPON_P_MODEL)

// rg_set_iteminfo(pItem, ItemInfo_iId, 99)
// set_member(pPlayer, m_szAnimExtention, "rifle")

g_bActiveItem[pPlayer] = true

return HAM_IGNORED
}

public CBasePlayerItem_Holster(const pItem)
{
if (pItem > 0 && IsCustomWeapon(pItem))
{
g_bActiveItem[get_member(pItem, m_pPlayer)] = false

// rg_set_iteminfo(pItem, ItemInfo_iId, BASE_WEAPON_ID)
}
}

public CBasePlayerWeapon_Reload(const pWeapon) // hack :D
{
if (pWeapon <= 0 || !IsCustomWeapon(pWeapon) || get_member(pWeapon, m_Weapon_fInReload))
return HAM_IGNORED

new pPlayer = get_member(pWeapon, m_pPlayer)

if (pPlayer > 0 && !get_member(pPlayer, PLAYER_AMMO_MEMBER_NAME))
{
set_member(pPlayer, PLAYER_AMMO_MEMBER_NAME, get_member(pPlayer, m_rgAmmo, get_member(pWeapon, m_Weapon_iPrimaryAmmoType)))
}

return HAM_IGNORED
}

public CBasePlayerWeapon_PrimAttack(const pWeapon)
{
if (pWeapon <= 0 || !IsCustomWeapon(pWeapon))
return HAM_IGNORED

static iClip, Float:vecPunchAngle[3]

if ((iClip = get_member(pWeapon, m_Weapon_iClip)) <= 0)
{
ExecuteHam(Ham_Weapon_PlayEmptySound, pWeapon)
set_member(pWeapon, m_Weapon_flNextPrimaryAttack, 0.6)
return HAM_SUPERCEDE
}

new pPlayer = get_member(pWeapon, m_pPlayer)

if (pPlayer <= 0)
{
return HAM_IGNORED
}

if (BoltShot(pPlayer) == NULLENT)
return HAM_SUPERCEDE

--iClip

rg_set_animation(pPlayer, PLAYER_ATTACK1)
SendWeaponAnim(pPlayer, iClip == 0 ? CROSSBOW_FIRE_LAST : CROSSBOW_FIRE1)

set_member(pWeapon, m_Weapon_iClip, iClip)
set_member(pWeapon, m_bWaitReload, true)
set_member(pWeapon, m_Weapon_flNextPrimaryAttack, iClip == 0 ? 0.7 : 1.75)
set_member(pWeapon, m_Weapon_flTimeWeaponIdle, 1.8)

emit_sound(pPlayer, CHAN_WEAPON, WEAPON_FIRE_SOUND, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)

get_entvar(pPlayer, var_punchangle, vecPunchAngle)
vecPunchAngle[0] -= WEAPON_RECOIL
set_entvar(pPlayer, var_punchangle, vecPunchAngle)

return HAM_SUPERCEDE
}

// =================================== Bolt ==============================================
public CBaseEntity_Touch(const pEntity, const pToucher)
{
if (is_nullent(pEntity))
return

new Float:vecDir[3], Float:vecVelocity[3], Float:vecOrigin[3], Float:vecEnd[3]
new Float:flKillTime = BOLT_KILL_DELAY, Float:flDamage = BOLT_DAMAGE
new pOwner = get_entvar(pEntity, var_owner)

if (!is_user_connected(pOwner))
{
flKillTime = 0.1
goto ForceKill
}

get_entvar(pEntity, var_velocity, vecVelocity)
xs_vec_normalize(vecVelocity, vecDir)
get_entvar(pEntity, var_origin, vecOrigin)

for (new i = 0; i < 3; i++)
{
vecVelocity = vecOrigin - vecDir * 12.0
vecEnd = vecOrigin + vecDir * 50.0
}

/* if (is_user_alive(pToucher) && !rg_is_player_can_takedamage(pToucher, pOwner))
{
return
} */

SetTouch(pEntity, "")

new pTracehandle = create_tr2()

get_entvar(pEntity, var_oldorigin, vecOrigin)
engfunc(EngFunc_TraceLine, vecOrigin, vecEnd, DONT_IGNORE_MONSTERS, pOwner, pTracehandle)

if (!is_nullent(pToucher) && get_entvar(pToucher, var_takedamage))
{
new Float:flFraction
flKillTime = 0.2

get_tr2(pTracehandle, TR_flFraction, flFraction)

if (flFraction != 1.0)
{
new iHitGroup = get_tr2(pTracehandle, TR_iHitgroup)

if (any:HITGROUP_HEAD <= iHitGroup <= any:HITGROUP_STOMACH)
flDamage *= 2
else if (iHitGroup == any:HITGROUP_SHIELD)
flDamage = 0.0 // already in CBasePlayer::TraceAttack

rg_multidmg_clear()
ExecuteHam(Ham_TraceAttack, pToucher, pOwner, flDamage, vecDir, pTracehandle, DMG_BULLET | DMG_NEVERGIB)
rg_multidmg_apply(pEntity, pOwner)

if (flDamage != 0.0)
emit_sound(pEntity, CHAN_BODY, random(1) ? "weapons/xbow_hitbod1.wav" : "weapons/xbow_hitbod2.wav", VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
}
#if defined PL_DEBUG
get_tr2(pTracehandle, TR_vecEndPos, vecEnd)
ShowLine(pOwner, vecOrigin, vecEnd, flDamage != 0.0 ? {0, 250, 0} : {225, 0, 0})
client_print(pOwner, print_chat, "iHitgroup %i flFraction %f", get_tr2(pTracehandle, TR_iHitgroup), flFraction)
#endif
}
else if (FClassnameIs(pToucher, "worldspawn") || get_entvar(pToucher, var_solid) == SOLID_BSP)
{
if (pToucher > 0 && !(get_entvar(pToucher, var_flags) & FL_WORLDBRUSH))
{
flKillTime = 0.2
}

// if (UTIL_PointContents(pev->origin) != CONTENTS_WATER)
// {
// UTIL_Sparks( pev->origin )
// }

emit_sound(pEntity, CHAN_BODY, "weapons/xbow_hit1.wav", random_float(0.40, 0.60), ATTN_NORM, 0, 98 + random_num(0, 7))

get_tr2(pTracehandle, TR_vecEndPos, vecEnd)
UTIL_DecalTrace(vecEnd)
}

free_tr2(pTracehandle)

/* if (FClassnameIs(pToucher, CUSTOM_ENTITY_CLASSNAME))
{
flKillTime = 0.1
set_entvar(pToucher, var_nextthink, get_gametime() + flKillTime)
}
else */
{
set_entvar(pEntity, var_solid, SOLID_NOT)
set_entvar(pEntity, var_movetype, MOVETYPE_NONE)

engfunc(EngFunc_SetOrigin, pEntity, vecVelocity)

set_entvar(pEntity, var_avelocity, VECTOR_ZERO)
set_entvar(pEntity, var_velocity, VECTOR_ZERO)
}

#if defined BOLT_TOUCH_USE_BUTTON
if (FClassnameIs(pToucher, "func_button") && !(get_entvar(pToucher, var_spawnflags) & SF_BUTTON_TOUCH_ONLY))
{
ExecuteHam(Ham_Use, pToucher, pOwner, pOwner, USE_SET, 1.0)
}
#endif

#if defined PL_DEBUG
if (get_viewent(pOwner) == pEntity)
{
engset_view(pOwner, pOwner)
}
#endif

ForceKill:
if (flKillTime < 0.5)
set_entvar(pEntity, var_impulse, DEAD_DEAD)

set_entvar(pEntity, var_nextthink, get_gametime() + flKillTime)
}

public BubbleThink(const pEntity)
{
if (pEntity <= 0)
return

if (get_entvar(pEntity, var_waterlevel) != 0)
{
// UTIL_BubbleTrail( pev->origin - pev->velocity * 0.1, pev->origin, 1 );
}

set_entvar(pEntity, var_nextthink, get_gametime() + 0.1)
}

public FadeThink(const pEntity)
{
if (pEntity <= 0)
return

static Float:renderamt

if ((renderamt = get_entvar(pEntity, var_renderamt)) > 10.0)
{
set_entvar(pEntity, var_renderamt, renderamt - 15.0)
set_entvar(pEntity, var_nextthink, get_gametime() + 0.2)
}
else
{
RemoveEntity(pEntity)
}
}

RemoveEntity(const pEntity)
{
set_entvar(pEntity, var_owner, 0)
set_entvar(pEntity, var_flags, FL_KILLME)
SetThink(pEntity, "")
set_entvar(pEntity, var_nextthink, -1.0)
// engfunc(EngFunc_RemoveEntity, pEntity) // FL_KILLME
}

public RemoveThink(const pEntity)
{
if (!is_nullent(pEntity))
{
if (get_entvar(pEntity, var_impulse) == DEAD_DEAD)
{
RemoveEntity(pEntity)
}
else
{
SetRendering(pEntity, kRenderTransAlpha)
SetThink(pEntity, "FadeThink")
set_entvar(pEntity, var_nextthink, get_gametime() + 0.1)
}
}
}

BoltCreate()
{
new pEntity = rg_create_entity(BASE_ENTITY_CLASSNAME)

if (is_nullent(pEntity))
return NULLENT

set_entvar(pEntity, var_classname, CUSTOM_ENTITY_CLASSNAME)
set_entvar(pEntity, var_solid, SOLID_BBOX)
set_entvar(pEntity, var_movetype, MOVETYPE_FLY)

set_entvar(pEntity, var_groupinfo, (1 << 1))
engfunc(EngFunc_SetGroupMask, 0, GROUP_OP_NAND)

engfunc(EngFunc_SetModel, pEntity, BOLT_MODEL)
engfunc(EngFunc_SetSize, pEntity, VECTOR_ZERO, VECTOR_ZERO)

// SetThink(pEntity, "BubbleThink")
// set_entvar(pEntity, var_nextthink, get_gametime() + 0.1)

return pEntity
}

BoltShot(const pPlayer)
{
new pEntity = BoltCreate()

if (pEntity == NULLENT)
return NULLENT

new Float:vecVAngle[3], Float:vecPunchangle[3], Float:vecForward[3],
Float:anglesAim[3], Float:vecAVelocity[3], Float:vecDir[3], Float:vecSrc[3]

SetTouch(pEntity, "CBaseEntity_Touch")
SetThink(pEntity, "RemoveThink")

get_entvar(pPlayer, var_v_angle, vecVAngle)
get_entvar(pPlayer, var_punchangle, vecPunchangle)
xs_vec_add(vecVAngle, vecPunchangle, anglesAim)
engfunc(EngFunc_MakeVectors, anglesAim)
anglesAim[0] = -anglesAim[0]
global_get(glb_v_forward, vecForward)

new Float:flVelocity = BOLT_AIR_VELOCITY
new iTeam = get_member(pPlayer, m_iTeam)

if (get_entvar(pPlayer, var_waterlevel) >= 3)
{
flVelocity /= 2.5
}
#if defined PL_DEBUG
if (get_entvar(pPlayer, var_button) & IN_ATTACK2)
{
flVelocity = 80.0 // very slow
FollowEntity(pEntity) // debug
SetRendering(pEntity, kRenderNormal, kRenderFxGlowShell, g_vecColorTeam[random(sizeof(g_vecColorTeam))], 10.0)
}
else
#endif
{
SetRendering(pEntity, kRenderNormal, kRenderFxGlowShell, g_vecColorTeam[iTeam], 10.0)
}

xs_vec_mul_scalar(vecForward, flVelocity, vecDir)
vecSrc = GetGunPosition(pPlayer)
engfunc(EngFunc_SetOrigin, pEntity, vecSrc)
set_entvar(pEntity, var_oldorigin, vecSrc)
set_entvar(pEntity, var_angles, anglesAim)
set_entvar(pEntity, var_velocity, vecDir)
set_entvar(pEntity, var_speed, flVelocity)
vecAVelocity[2] = BOLT_ANGULAR_VELOCITY // angle speed
set_entvar(pEntity, var_avelocity, vecAVelocity)

set_entvar(pEntity, var_owner, pPlayer)
set_entvar(pEntity, var_team, iTeam) // TODO: team check on touch
set_entvar(pEntity, var_nextthink, get_gametime() + BOLT_KILL_DELAY + 15.0)

return pEntity
}

GiveItem(const pPlayer)
{
new pWeapon = rg_give_custom_item(pPlayer, BASE_WEAPON_NAME, GT_DROP_AND_REPLACE, CUSTOM_WEAPON_INDEX)

if (!is_nullent(pWeapon))
{
rg_set_iteminfo(pWeapon, ItemInfo_iMaxClip, WEAPON_MAX_CLIP)
rg_set_iteminfo(pWeapon, ItemInfo_iMaxAmmo1, WEAPON_MAX_AMMO)
rg_set_iteminfo(pWeapon, ItemInfo_iFlags, ITEM_FLAG_EXHAUSTIBLE)
rg_set_iteminfo(pWeapon, ItemInfo_pszName, CUSTOM_WEAPON_NAME)

set_member(pWeapon, m_Weapon_iClip, WEAPON_MAX_CLIP)
// set_member(pWeapon, m_Weapon_bHasSecondaryAttack, true)
set_entvar(pWeapon, var_classname, CUSTOM_WEAPON_NAME)

GiveAmmo(pPlayer, pWeapon, WEAPON_MAX_AMMO, WEAPON_MAX_AMMO)

return pWeapon
}

return NULLENT
}

GiveAmmo(const pPlayer, const pItem, const iAmount, const iMax)
{
new ammoType = get_member(pItem, m_Weapon_iPrimaryAmmoType)

if (get_member(pPlayer, m_rgAmmo, ammoType) >= iMax)
{
return ammoType
}

new iAdd = min(iAmount, iMax - get_member(pPlayer, m_rgAmmo, ammoType))
if (iAdd < 1)
{
return ammoType
}

set_member(pPlayer, m_rgAmmo, get_member(pPlayer, m_rgAmmo, ammoType) + iAdd, ammoType)
SendAmmoPickup(pPlayer, ammoType, iAdd)

return ammoType
}

SendWeaponListSpecial(const pPlayer, const szName[], const iMaxAmmo, const iAmmoType)
{
static iMsgIdWeaponList

if (iMsgIdWeaponList > 0 || (iMsgIdWeaponList = get_user_msgid("WeaponList")) > 0)
{
message_begin(MSG_ONE, iMsgIdWeaponList, .player = pPlayer)
write_string(szName)
write_byte(iAmmoType) // iPrimaryAmmoType
write_byte(iMaxAmmo) // iMaxAmmo1
write_byte(-1) // iSecondaryAmmoType
write_byte(-1) // iMaxAmmo2
write_byte(BASE_WEAPON_SLOT) // iSlot
write_byte(BASE_WEAPON_POSITION)// iPosition
write_byte(any:BASE_WEAPON_ID) // iId
write_byte(0) // iFlags
message_end()
}
}

ForwardsState(const iState)
{
for (new i = 0; i < sizeof(g_aHookData); i++)
{
if (IsHamHook(i))
{
switch(iState)
{
case FORWARD_REGISTER: DisableHamForward(g_hHookHandle = any:RegisterHam(g_aHookData[iFunctionId], g_aHookData[szClass], g_aHookData[szCallback], g_aHookData[bIsPost]))
case FORWARD_ENABLE: EnableHamForward(g_hHookHandle)
case FORWARD_DISABLE: DisableHamForward(g_hHookHandle)
}
}
else
{
switch(iState)
{
case FORWARD_REGISTER: DisableHookChain(g_hHookHandle = any:RegisterHookChain(g_aHookData[iFunctionId], g_aHookData[szCallback], g_aHookData[bIsPost]))
case FORWARD_ENABLE: EnableHookChain(g_hHookHandle)
case FORWARD_DISABLE: DisableHookChain(g_hHookHandle)
}
}
}

if (iState == FORWARD_ENABLE && !g_iFwdUpdateClientData)
g_iFwdUpdateClientData = register_forward(FM_UpdateClientData, "UpdateClientData", true)
else if (iState == FORWARD_DISABLE && g_iFwdUpdateClientData)
unregister_forward(FM_UpdateClientData, g_iFwdUpdateClientData, true)
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

stock GetWeaponBoxWeapon(const pWeaponBox)
{
for (new pWeapon, InventorySlotType:i = PRIMARY_WEAPON_SLOT; i <= C4_SLOT; i++)
{
if (i != KNIFE_SLOT && !is_nullent((pWeapon = get_member(pWeaponBox, m_WeaponBox_rgpPlayerItems, i)))) {
return pWeapon
}
}

return NULLENT
}

stock GetCustomItem(const pPlayer)
{
for (new InventorySlotType:iSlot = PRIMARY_WEAPON_SLOT, pItem; iSlot <= C4_SLOT; iSlot++)
{
if (iSlot == KNIFE_SLOT)
continue

pItem = get_member(pPlayer, m_rgpPlayerItems, iSlot)

while (!is_nullent(pItem))
{
if (get_entvar(pItem, var_impulse) == CUSTOM_WEAPON_INDEX)
{
return pItem
}

pItem = get_member(pItem, m_pNext)
}
}

return NULLENT
}

stock Float:GetGunPosition(const pPlayer)
{
new Float:vecOrigin[3], Float:vecViewOfs[3], Float:vecOutput[3]
get_entvar(pPlayer, var_origin, vecOrigin)
get_entvar(pPlayer, var_view_ofs, vecViewOfs)
xs_vec_add(vecOrigin, vecViewOfs, vecOutput)

return vecOutput
}

stock bool:parseSpriteDesc(const szClassname[])
{
new szSpriteDesc[64], szLineData[128], szSprite[32], pFile
formatex(szSpriteDesc, charsmax(szSpriteDesc), "sprites/%s.txt", szClassname)

if (!(pFile = fopen(szSpriteDesc, "rt")))
return false

precache_generic(szSpriteDesc)

while(!feof(pFile))
{
fgets(pFile, szLineData, charsmax(szLineData))
trim(szLineData)

if ((parse(szLineData, 1, 0, 1, 0, szSprite, charsmax(szSprite), 1, 0, 1, 0, 1, 0, 1, 0)
) == 7)
{
formatex(szSpriteDesc, charsmax(szSpriteDesc), "sprites/%s.spr", szSprite)
server_print("szSpriteDesc %s", szSpriteDesc)
precache_generic(szSpriteDesc)
}
}

fclose(pFile)
return true
}

stock SetRendering(const pEntity, const render = kRenderNormal, const fx = kRenderFxNone, const Float:color[] = {255.0, 255.0, 255.0}, const Float:amount = 255.0)
{
set_entvar(pEntity, var_rendermode, render)
set_entvar(pEntity, var_renderfx, fx)
set_entvar(pEntity, var_rendercolor, color)
set_entvar(pEntity, var_renderamt, amount)
}

stock ShowLine(pPlayer, Float:vecSrc[3], Float:vecEnd[3], Color[3])
{
// message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
message_begin(MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, .player = pPlayer)
write_byte(TE_BEAMPOINTS)
write_coord_f(vecSrc[0])
write_coord_f(vecSrc[1])
write_coord_f(vecSrc[2])
write_coord_f(vecEnd[0])
write_coord_f(vecEnd[1])
write_coord_f(vecEnd[2])
write_short(g_iModelIndexLaser)
write_byte(1) // starting frame
write_byte(0) // frame rate in 0.1's
write_byte(100) // life in 0.1's
write_byte(3) // line width in 0.1's
write_byte(0) // noise amplitude in 0.01's
write_byte(Color[0]) // r
write_byte(Color[1]) // g
write_byte(Color[2]) // b
write_byte(255) // brightness
write_byte(0) // scroll speed in 0.1's
message_end()
}

stock UTIL_DecalTrace(const Float:vecOrigin[3])
{
static iWorldDecal

if (!iWorldDecal)
{
new const szDecals[][] = { "{shot1", "{shot2", "{shot3", "{shot4", "{shot5" }

for (new i = 0, iDecal; i < sizeof(szDecals); i++)
{
if ((iDecal = engfunc(EngFunc_DecalIndex, szDecals)) != -1)
{
iWorldDecal = iDecal
break;
}
}
}

if (iWorldDecal)
{
engfunc(EngFunc_MessageBegin, MSG_PAS, SVC_TEMPENTITY, vecOrigin, 0)
write_byte(TE_WORLDDECAL)
write_coord_f(vecOrigin[0])
write_coord_f(vecOrigin[1])
write_coord_f(vecOrigin[2])
write_byte(iWorldDecal)
message_end()
}
}

stock FollowEntity(const pEntity)
{
message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
write_byte(TE_BEAMFOLLOW)
write_short(pEntity)
write_short(g_iFallowSprite)
write_byte(12) // life
write_byte(2) // line width
write_byte(220) // r
write_byte(220) // g
write_byte(220) // b
write_byte(90) // brightness
message_end()
}

stock SendAmmoPickup(const pPlayer, const ammoType, const iCount)
{
static gmsgAmmoPickup

if ((gmsgAmmoPickup || (gmsgAmmoPickup = get_user_msgid("AmmoPickup"))))
{
message_begin(MSG_ONE, gmsgAmmoPickup, .player = pPlayer)
write_byte(ammoType)
write_byte(iCount)
message_end()
}
}

stock SendWeaponAnim(const pPlayer, const iAnimNum, bool:bSkipLocal = false)
{
new aPlayers[32], iCount, pClient
get_players(aPlayers, iCount, "ch") // skip bot's & hltv

for (--iCount; iCount >= 0; iCount--)
{
pClient = aPlayers[iCount]

if ((!bSkipLocal && pPlayer == pClient)
|| (get_entvar(pClient, var_iuser2) == pPlayer && get_entvar(pClient, var_iuser1) == OBS_IN_EYE))
{
set_entvar(pClient, var_weaponanim, iAnimNum)

message_begin(MSG_ONE, SVC_WEAPONANIM, .player = pClient)
write_byte(iAnimNum)
write_byte(0)
message_end()
}
}
}
Требования
ReAPI, Amx Mod X 1.8.3, Amx Mod X 1.9.0
Требование ReAPI
Да
Поддержка русского языка
Да
Совместимость
  1. REHLDS
Сверху Снизу