2022-12-17 13:32:43 +01:00
|
|
|
/***
|
2013-08-30 13:34:05 -07:00
|
|
|
*
|
|
|
|
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
|
|
|
*
|
|
|
|
* This product contains software technology licensed from Id
|
|
|
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
|
|
|
* All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Use, distribution, and modification of this source code and/or resulting
|
|
|
|
* object code is restricted to non-commercial enhancements to products from
|
|
|
|
* Valve LLC. All other use, distribution, or modification is prohibited
|
|
|
|
* without written permission from Valve LLC.
|
|
|
|
*
|
|
|
|
****/
|
|
|
|
|
|
|
|
#include "extdll.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "cbase.h"
|
|
|
|
#include "monsters.h"
|
|
|
|
#include "weapons.h"
|
|
|
|
#include "player.h"
|
|
|
|
#include "gamerules.h"
|
|
|
|
|
2024-08-28 14:21:38 +02:00
|
|
|
// If you want the "legacy" controls where primary attack is "throw first charge / detonate" and secondary attack is
|
|
|
|
// "throw extra" charge, simply comment this define.
|
|
|
|
#define MODERN_SATCHEL_CONTROLS
|
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
class CSatchelCharge : public CGrenade
|
|
|
|
{
|
2021-03-05 23:07:22 +01:00
|
|
|
void Spawn() override;
|
|
|
|
void Precache() override;
|
|
|
|
void BounceSound() override;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
void EXPORT SatchelSlide(CBaseEntity* pOther);
|
2021-03-05 20:54:33 +01:00
|
|
|
void EXPORT SatchelThink();
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
public:
|
2021-03-05 20:54:33 +01:00
|
|
|
void Deactivate();
|
2013-08-30 13:34:05 -07:00
|
|
|
};
|
2021-11-28 16:54:48 +01:00
|
|
|
LINK_ENTITY_TO_CLASS(monster_satchel, CSatchelCharge);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
//=========================================================
|
2021-11-28 16:54:48 +01:00
|
|
|
// Deactivate - do whatever it is we do to an orphaned
|
2013-08-30 13:34:05 -07:00
|
|
|
// satchel when we don't want it in the world anymore.
|
|
|
|
//=========================================================
|
2021-03-05 20:54:33 +01:00
|
|
|
void CSatchelCharge::Deactivate()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
pev->solid = SOLID_NOT;
|
2021-11-28 16:54:48 +01:00
|
|
|
UTIL_Remove(this);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-29 20:31:17 +01:00
|
|
|
void CSatchelCharge::Spawn()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
Precache();
|
2013-08-30 13:34:05 -07:00
|
|
|
// motor
|
|
|
|
pev->movetype = MOVETYPE_BOUNCE;
|
|
|
|
pev->solid = SOLID_BBOX;
|
|
|
|
|
|
|
|
SET_MODEL(ENT(pev), "models/w_satchel.mdl");
|
|
|
|
//UTIL_SetSize(pev, Vector( -16, -16, -4), Vector(16, 16, 32)); // Old box -- size of headcrab monsters/players get blocked by this
|
2021-11-28 16:54:48 +01:00
|
|
|
UTIL_SetSize(pev, Vector(-4, -4, -4), Vector(4, 4, 4)); // Uses point-sized, and can be stepped over
|
|
|
|
UTIL_SetOrigin(pev, pev->origin);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
SetTouch(&CSatchelCharge::SatchelSlide);
|
|
|
|
SetUse(&CSatchelCharge::DetonateUse);
|
|
|
|
SetThink(&CSatchelCharge::SatchelThink);
|
2013-08-30 13:34:05 -07:00
|
|
|
pev->nextthink = gpGlobals->time + 0.1;
|
|
|
|
|
|
|
|
pev->gravity = 0.5;
|
|
|
|
pev->friction = 0.8;
|
|
|
|
|
|
|
|
pev->dmg = gSkillData.plrDmgSatchel;
|
|
|
|
// ResetSequenceInfo( );
|
|
|
|
pev->sequence = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
void CSatchelCharge::SatchelSlide(CBaseEntity* pOther)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
entvars_t* pevOther = pOther->pev;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
// don't hit the guy that launched this grenade
|
2021-11-28 16:54:48 +01:00
|
|
|
if (pOther->edict() == pev->owner)
|
2013-08-30 13:34:05 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
// pev->avelocity = Vector (300, 300, 300);
|
2021-11-28 16:54:48 +01:00
|
|
|
pev->gravity = 1; // normal gravity now
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
// HACKHACK - On ground isn't always set, so look for ground underneath
|
|
|
|
TraceResult tr;
|
2021-11-28 16:54:48 +01:00
|
|
|
UTIL_TraceLine(pev->origin, pev->origin - Vector(0, 0, 10), ignore_monsters, edict(), &tr);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (tr.flFraction < 1.0)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// add a bit of static friction
|
|
|
|
pev->velocity = pev->velocity * 0.95;
|
|
|
|
pev->avelocity = pev->avelocity * 0.9;
|
|
|
|
// play sliding sound, volume based on velocity
|
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
if ((pev->flags & FL_ONGROUND) == 0 && pev->velocity.Length2D() > 10)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
BounceSound();
|
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
StudioFrameAdvance();
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-29 20:31:17 +01:00
|
|
|
void CSatchelCharge::SatchelThink()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
StudioFrameAdvance();
|
2013-08-30 13:34:05 -07:00
|
|
|
pev->nextthink = gpGlobals->time + 0.1;
|
|
|
|
|
|
|
|
if (!IsInWorld())
|
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
UTIL_Remove(this);
|
2013-08-30 13:34:05 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pev->waterlevel == 3)
|
|
|
|
{
|
|
|
|
pev->movetype = MOVETYPE_FLY;
|
|
|
|
pev->velocity = pev->velocity * 0.8;
|
|
|
|
pev->avelocity = pev->avelocity * 0.9;
|
|
|
|
pev->velocity.z += 8;
|
|
|
|
}
|
|
|
|
else if (pev->waterlevel == 0)
|
|
|
|
{
|
|
|
|
pev->movetype = MOVETYPE_BOUNCE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pev->velocity.z -= 8;
|
2021-11-28 16:54:48 +01:00
|
|
|
}
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-29 20:31:17 +01:00
|
|
|
void CSatchelCharge::Precache()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
PRECACHE_MODEL("models/grenade.mdl");
|
|
|
|
PRECACHE_SOUND("weapons/g_bounce1.wav");
|
|
|
|
PRECACHE_SOUND("weapons/g_bounce2.wav");
|
|
|
|
PRECACHE_SOUND("weapons/g_bounce3.wav");
|
|
|
|
}
|
|
|
|
|
2021-11-29 20:31:17 +01:00
|
|
|
void CSatchelCharge::BounceSound()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
switch (RANDOM_LONG(0, 2))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
case 0:
|
|
|
|
EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/g_bounce1.wav", 1, ATTN_NORM);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/g_bounce2.wav", 1, ATTN_NORM);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/g_bounce3.wav", 1, ATTN_NORM);
|
|
|
|
break;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
LINK_ENTITY_TO_CLASS(weapon_satchel, CSatchel);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
// CALLED THROUGH the newly-touched weapon's instance. The existing player weapon is pOriginal
|
|
|
|
//=========================================================
|
2021-11-28 16:54:48 +01:00
|
|
|
bool CSatchel::AddDuplicate(CBasePlayerItem* pOriginal)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2024-08-28 14:20:42 +02:00
|
|
|
CSatchel* pSatchel = nullptr;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
#ifdef CLIENT_DLL
|
2021-11-28 16:54:48 +01:00
|
|
|
if (bIsMultiplayer())
|
2013-08-30 13:34:05 -07:00
|
|
|
#else
|
2021-11-28 16:54:48 +01:00
|
|
|
if (g_pGameRules->IsMultiplayer())
|
2013-08-30 13:34:05 -07:00
|
|
|
#endif
|
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
pSatchel = (CSatchel*)pOriginal;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2024-08-28 14:20:42 +02:00
|
|
|
if (pOriginal->m_pPlayer == NULL)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
int nSatchelsInPocket = pSatchel->m_pPlayer->m_rgAmmo[pSatchel->PrimaryAmmoIndex()];
|
|
|
|
int nNumSatchels = 0;
|
|
|
|
CBaseEntity* pLiveSatchel = NULL;
|
|
|
|
|
|
|
|
while ((pLiveSatchel = UTIL_FindEntityInSphere(pLiveSatchel, pOriginal->m_pPlayer->pev->origin, 4096)) != NULL)
|
|
|
|
{
|
|
|
|
if (FClassnameIs(pLiveSatchel->pev, "monster_satchel"))
|
|
|
|
{
|
|
|
|
if (pLiveSatchel->pev->owner == pOriginal->m_pPlayer->edict())
|
|
|
|
{
|
|
|
|
nNumSatchels++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pSatchel->m_chargeReady != 0 && (nSatchelsInPocket + nNumSatchels) >= SATCHEL_MAX_CARRY)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// player has some satchels deployed. Refuse to add more.
|
2021-11-19 13:43:33 +01:00
|
|
|
return false;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
return CBasePlayerWeapon::AddDuplicate(pOriginal);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
//=========================================================
|
2022-07-22 19:01:05 +02:00
|
|
|
void CSatchel::AddToPlayer(CBasePlayer* pPlayer)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
m_chargeReady = 0; // this satchel charge weapon now forgets that any satchels are deployed by it.
|
2022-07-22 19:01:05 +02:00
|
|
|
CBasePlayerWeapon::AddToPlayer(pPlayer);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
void CSatchel::Spawn()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
Precache();
|
2013-08-30 13:34:05 -07:00
|
|
|
m_iId = WEAPON_SATCHEL;
|
|
|
|
SET_MODEL(ENT(pev), "models/w_satchel.mdl");
|
|
|
|
|
|
|
|
m_iDefaultAmmo = SATCHEL_DEFAULT_GIVE;
|
2021-11-28 16:54:48 +01:00
|
|
|
|
|
|
|
FallInit(); // get ready to fall down.
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-05 20:54:33 +01:00
|
|
|
void CSatchel::Precache()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
PRECACHE_MODEL("models/v_satchel.mdl");
|
|
|
|
PRECACHE_MODEL("models/v_satchel_radio.mdl");
|
|
|
|
PRECACHE_MODEL("models/w_satchel.mdl");
|
|
|
|
PRECACHE_MODEL("models/p_satchel.mdl");
|
|
|
|
PRECACHE_MODEL("models/p_satchel_radio.mdl");
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
UTIL_PrecacheOther("monster_satchel");
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
bool CSatchel::GetItemInfo(ItemInfo* p)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
p->pszName = STRING(pev->classname);
|
|
|
|
p->pszAmmo1 = "Satchel Charge";
|
|
|
|
p->iMaxAmmo1 = SATCHEL_MAX_CARRY;
|
|
|
|
p->pszAmmo2 = NULL;
|
|
|
|
p->iMaxAmmo2 = -1;
|
|
|
|
p->iMaxClip = WEAPON_NOCLIP;
|
|
|
|
p->iSlot = 4;
|
|
|
|
p->iPosition = 1;
|
|
|
|
p->iFlags = ITEM_FLAG_SELECTONEMPTY | ITEM_FLAG_LIMITINWORLD | ITEM_FLAG_EXHAUSTIBLE;
|
|
|
|
p->iId = m_iId = WEAPON_SATCHEL;
|
|
|
|
p->iWeight = SATCHEL_WEIGHT;
|
|
|
|
|
2021-11-28 15:32:26 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
//=========================================================
|
2021-11-19 14:31:11 +01:00
|
|
|
bool CSatchel::IsUseable()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()] > 0)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// player is carrying some satchels
|
2021-11-19 13:45:16 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (m_chargeReady != 0)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// player isn't carrying any satchels, but has some out
|
2021-11-19 13:45:16 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-19 13:43:33 +01:00
|
|
|
return false;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-19 14:31:11 +01:00
|
|
|
bool CSatchel::CanDeploy()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()] > 0)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// player is carrying some satchels
|
2021-11-19 13:45:16 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (m_chargeReady != 0)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// player isn't carrying any satchels, but has some out
|
2021-11-19 13:45:16 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-19 13:43:33 +01:00
|
|
|
return false;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
bool CSatchel::Deploy()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1.0;
|
2021-03-09 16:55:57 +01:00
|
|
|
//m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
|
|
|
|
|
2021-11-19 14:40:35 +01:00
|
|
|
bool result;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (0 != m_chargeReady)
|
|
|
|
result = DefaultDeploy("models/v_satchel_radio.mdl", "models/p_satchel_radio.mdl", SATCHEL_RADIO_DRAW, "hive");
|
2013-08-30 13:34:05 -07:00
|
|
|
else
|
2021-11-28 16:54:48 +01:00
|
|
|
result = DefaultDeploy("models/v_satchel.mdl", "models/p_satchel.mdl", SATCHEL_DRAW, "trip");
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-03-09 16:55:57 +01:00
|
|
|
if (result)
|
|
|
|
{
|
|
|
|
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2;
|
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2021-03-09 16:55:57 +01:00
|
|
|
return result;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-10-21 14:00:29 +02:00
|
|
|
void CSatchel::Holster()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
|
2021-11-28 16:54:48 +01:00
|
|
|
|
|
|
|
if (0 != m_chargeReady)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
SendWeaponAnim(SATCHEL_RADIO_HOLSTER);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
SendWeaponAnim(SATCHEL_DROP);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM);
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (0 == m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] && 0 == m_chargeReady)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-12-02 13:49:56 +01:00
|
|
|
m_pPlayer->ClearWeaponBit(m_iId);
|
2021-11-28 16:54:48 +01:00
|
|
|
SetThink(&CSatchel::DestroyItem);
|
2013-08-30 13:34:05 -07:00
|
|
|
pev->nextthink = gpGlobals->time + 0.1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CSatchel::PrimaryAttack()
|
|
|
|
{
|
2024-08-28 14:21:38 +02:00
|
|
|
#ifdef MODERN_SATCHEL_CONTROLS
|
|
|
|
// we're reloading, don't allow fire
|
|
|
|
if (m_chargeReady != 2)
|
|
|
|
{
|
|
|
|
Throw();
|
|
|
|
}
|
|
|
|
#else
|
2013-08-30 13:34:05 -07:00
|
|
|
switch (m_chargeReady)
|
|
|
|
{
|
2021-11-29 20:55:01 +01:00
|
|
|
case 0:
|
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
Throw();
|
|
|
|
}
|
|
|
|
break;
|
2021-11-29 20:55:01 +01:00
|
|
|
case 1:
|
|
|
|
{
|
2024-08-28 14:21:38 +02:00
|
|
|
Detonate();
|
2013-08-30 13:34:05 -07:00
|
|
|
break;
|
2021-11-28 16:54:48 +01:00
|
|
|
}
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
case 2:
|
|
|
|
// we're reloading, don't allow fire
|
|
|
|
{
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2024-08-28 14:21:38 +02:00
|
|
|
#endif
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-05 20:54:33 +01:00
|
|
|
void CSatchel::SecondaryAttack()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2024-08-28 14:21:38 +02:00
|
|
|
#ifdef MODERN_SATCHEL_CONTROLS
|
|
|
|
if (m_chargeReady == 1)
|
|
|
|
{
|
|
|
|
Detonate();
|
|
|
|
}
|
|
|
|
#else
|
2021-11-28 16:54:48 +01:00
|
|
|
if (m_chargeReady != 2)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
Throw();
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
2024-08-28 14:21:38 +02:00
|
|
|
#endif
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-05 20:54:33 +01:00
|
|
|
void CSatchel::Throw()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (0 != m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType])
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
Vector vecSrc = m_pPlayer->pev->origin;
|
|
|
|
|
|
|
|
Vector vecThrow = gpGlobals->v_forward * 274 + m_pPlayer->pev->velocity;
|
|
|
|
|
|
|
|
#ifndef CLIENT_DLL
|
2021-11-28 16:54:48 +01:00
|
|
|
CBaseEntity* pSatchel = Create("monster_satchel", vecSrc, Vector(0, 0, 0), m_pPlayer->edict());
|
2013-08-30 13:34:05 -07:00
|
|
|
pSatchel->pev->velocity = vecThrow;
|
|
|
|
pSatchel->pev->avelocity.y = 400;
|
|
|
|
|
|
|
|
m_pPlayer->pev->viewmodel = MAKE_STRING("models/v_satchel_radio.mdl");
|
|
|
|
m_pPlayer->pev->weaponmodel = MAKE_STRING("models/p_satchel_radio.mdl");
|
|
|
|
#else
|
2021-11-28 16:54:48 +01:00
|
|
|
LoadVModel("models/v_satchel_radio.mdl", m_pPlayer);
|
2013-08-30 13:34:05 -07:00
|
|
|
#endif
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
SendWeaponAnim(SATCHEL_RADIO_DRAW);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
// player "shoot" animation
|
2021-11-28 16:54:48 +01:00
|
|
|
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
m_chargeReady = 1;
|
2021-11-28 16:54:48 +01:00
|
|
|
|
2013-08-30 13:34:05 -07:00
|
|
|
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--;
|
|
|
|
|
|
|
|
m_flNextPrimaryAttack = GetNextAttackDelay(1.0);
|
|
|
|
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-08-28 14:21:38 +02:00
|
|
|
void CSatchel::Detonate()
|
|
|
|
{
|
|
|
|
SendWeaponAnim(SATCHEL_RADIO_FIRE);
|
|
|
|
|
|
|
|
edict_t* pPlayer = m_pPlayer->edict();
|
|
|
|
|
|
|
|
CBaseEntity* pSatchel = NULL;
|
|
|
|
|
|
|
|
while ((pSatchel = UTIL_FindEntityInSphere(pSatchel, m_pPlayer->pev->origin, 4096)) != NULL)
|
|
|
|
{
|
|
|
|
if (FClassnameIs(pSatchel->pev, "monster_satchel"))
|
|
|
|
{
|
|
|
|
if (pSatchel->pev->owner == pPlayer)
|
|
|
|
{
|
|
|
|
pSatchel->Use(m_pPlayer, m_pPlayer, USE_ON, 0);
|
|
|
|
m_chargeReady = 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_chargeReady = 2;
|
|
|
|
m_flNextPrimaryAttack = GetNextAttackDelay(0.5);
|
|
|
|
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5;
|
|
|
|
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-05 20:54:33 +01:00
|
|
|
void CSatchel::WeaponIdle()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase())
|
2013-08-30 13:34:05 -07:00
|
|
|
return;
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
switch (m_chargeReady)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
case 0:
|
2021-11-28 16:54:48 +01:00
|
|
|
SendWeaponAnim(SATCHEL_FIDGET1);
|
2013-08-30 13:34:05 -07:00
|
|
|
// use tripmine animations
|
2021-11-28 16:54:48 +01:00
|
|
|
strcpy(m_pPlayer->m_szAnimExtention, "trip");
|
2013-08-30 13:34:05 -07:00
|
|
|
break;
|
|
|
|
case 1:
|
2021-11-28 16:54:48 +01:00
|
|
|
SendWeaponAnim(SATCHEL_RADIO_FIDGET1);
|
2013-08-30 13:34:05 -07:00
|
|
|
// use hivehand animations
|
2021-11-28 16:54:48 +01:00
|
|
|
strcpy(m_pPlayer->m_szAnimExtention, "hive");
|
2013-08-30 13:34:05 -07:00
|
|
|
break;
|
|
|
|
case 2:
|
2021-11-28 16:54:48 +01:00
|
|
|
if (0 == m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType])
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
m_chargeReady = 0;
|
|
|
|
RetireWeapon();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef CLIENT_DLL
|
|
|
|
m_pPlayer->pev->viewmodel = MAKE_STRING("models/v_satchel.mdl");
|
|
|
|
m_pPlayer->pev->weaponmodel = MAKE_STRING("models/p_satchel.mdl");
|
|
|
|
#else
|
2021-11-28 16:54:48 +01:00
|
|
|
LoadVModel("models/v_satchel.mdl", m_pPlayer);
|
2013-08-30 13:34:05 -07:00
|
|
|
#endif
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
SendWeaponAnim(SATCHEL_DRAW);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
// use tripmine animations
|
2021-11-28 16:54:48 +01:00
|
|
|
strcpy(m_pPlayer->m_szAnimExtention, "trip");
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
m_flNextPrimaryAttack = GetNextAttackDelay(0.5);
|
|
|
|
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5;
|
|
|
|
m_chargeReady = 0;
|
|
|
|
break;
|
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat(m_pPlayer->random_seed, 10, 15); // how long till we do this again.
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
// DeactivateSatchels - removes all satchels owned by
|
|
|
|
// the provided player. Should only be used upon death.
|
|
|
|
//
|
|
|
|
// Made this global on purpose.
|
|
|
|
//=========================================================
|
2021-11-28 16:54:48 +01:00
|
|
|
void DeactivateSatchels(CBasePlayer* pOwner)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
edict_t* pFind;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
pFind = FIND_ENTITY_BY_CLASSNAME(NULL, "monster_satchel");
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
while (!FNullEnt(pFind))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
CBaseEntity* pEnt = CBaseEntity::Instance(pFind);
|
|
|
|
CSatchelCharge* pSatchel = (CSatchelCharge*)pEnt;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (pSatchel)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (pSatchel->pev->owner == pOwner->edict())
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
pSatchel->Deactivate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
pFind = FIND_ENTITY_BY_CLASSNAME(pFind, "monster_satchel");
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
}
|