mirror of
https://github.com/YGGverse/hlsdk-portable.git
synced 2025-01-23 13:14:51 +00:00
Update nuclearbomb
This commit is contained in:
parent
ea13d88e37
commit
5d636b8519
@ -22,322 +22,246 @@
|
||||
#include "items.h"
|
||||
#include "gamerules.h"
|
||||
|
||||
#define SF_BUTTON_DONTMOVE 1
|
||||
#define SF_ROTBUTTON_NOTSOLID 1
|
||||
#define SF_BUTTON_TOGGLE 32 // button stays pushed until reactivated
|
||||
#define SF_BUTTON_SPARK_IF_OFF 64 // button sparks in OFF state
|
||||
#define SF_BUTTON_TOUCH_ONLY 256 // button only fires as a result of USE key.
|
||||
|
||||
//=========================================================
|
||||
// Nuclear bomb
|
||||
//=========================================================
|
||||
|
||||
#define NUKE_CLASSNAME_BUTTON "item_nuclearbomb_button"
|
||||
#define NUKE_CLASSNAME_TIMER "item_nuclearbomb_timer"
|
||||
|
||||
#define NUKE_MODEL_BUTTON "models/nuke_button.mdl"
|
||||
#define NUKE_MODEL_CASE "models/nuke_case.mdl"
|
||||
#define NUKE_MODEL_TIMER "models/nuke_timer.mdl"
|
||||
|
||||
#define NUKE_MIN_HEAR_DIST 192
|
||||
|
||||
//----------------------------------------------
|
||||
// Nuke button
|
||||
//----------------------------------------------
|
||||
class CNukeButton : public CBaseAnimating
|
||||
class CNuclearBombTimer : public CBaseEntity
|
||||
{
|
||||
public:
|
||||
void Spawn(void);
|
||||
void Precache(void);
|
||||
void Precache();
|
||||
void Spawn();
|
||||
void EXPORT NuclearBombTimerThink();
|
||||
void SetNuclearBombTimer(bool on);
|
||||
int ObjectCaps() {return FCAP_DONT_SAVE;}
|
||||
|
||||
BOOL bPlayBombSound;
|
||||
BOOL bBombSoundPlaying;
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS(item_nuclearbomb_button, CNukeButton);
|
||||
LINK_ENTITY_TO_CLASS(item_nuclearbombtimer, CNuclearBombTimer)
|
||||
|
||||
void CNukeButton::Spawn(void)
|
||||
void CNuclearBombTimer::Precache()
|
||||
{
|
||||
Precache();
|
||||
SET_MODEL(ENT(pev), "models/nuke_button.mdl");
|
||||
|
||||
UTIL_SetOrigin(pev, pev->origin);
|
||||
UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0));
|
||||
PRECACHE_MODEL("models/nuke_timer.mdl");
|
||||
PRECACHE_SOUND("common/nuke_ticking.wav");
|
||||
}
|
||||
|
||||
void CNukeButton::Precache(void)
|
||||
void CNuclearBombTimer::Spawn()
|
||||
{
|
||||
Precache();
|
||||
SET_MODEL(ENT(pev), "models/nuke_timer.mdl");
|
||||
pev->solid = SOLID_NOT;
|
||||
UTIL_SetSize(pev, Vector(-16,-16,0), Vector(16,16,32));
|
||||
pev->movetype = MOVETYPE_NONE;
|
||||
UTIL_SetOrigin(pev, pev->origin);
|
||||
if( DROP_TO_FLOOR(ENT( pev ) ) == 0 )
|
||||
{
|
||||
ALERT(at_error, "Nuclear Bomb timer fell out of level at %f,%f,%f\n", pev->origin.x, pev->origin.y, pev->origin.z);
|
||||
UTIL_Remove( this );
|
||||
return;
|
||||
}
|
||||
pev->skin = 0;
|
||||
bPlayBombSound = FALSE;
|
||||
bBombSoundPlaying = FALSE;
|
||||
}
|
||||
|
||||
void CNuclearBombTimer::NuclearBombTimerThink()
|
||||
{
|
||||
if (pev->skin <= 1)
|
||||
pev->skin++;
|
||||
else
|
||||
pev->skin = 0;
|
||||
if (bPlayBombSound)
|
||||
{
|
||||
EMIT_SOUND(ENT(pev), CHAN_BODY, "common/nuke_ticking.wav", 0.75, ATTN_IDLE);
|
||||
bBombSoundPlaying = TRUE;
|
||||
}
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
}
|
||||
|
||||
void CNuclearBombTimer::SetNuclearBombTimer(bool on)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
SetThink(&CNuclearBombTimer::NuclearBombTimerThink);
|
||||
pev->nextthink = gpGlobals->time;
|
||||
bPlayBombSound = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetThink(NULL);
|
||||
pev->nextthink = gpGlobals->time;
|
||||
pev->skin = 3;
|
||||
if (bBombSoundPlaying)
|
||||
{
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_BODY, "common/nuke_ticking.wav", 0.0, 0.0, SND_STOP, PITCH_NORM);
|
||||
bBombSoundPlaying = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CNuclearBombButton : public CBaseEntity
|
||||
{
|
||||
public:
|
||||
void Precache();
|
||||
void Spawn();
|
||||
void SetNuclearBombButton(bool on);
|
||||
int ObjectCaps() {return FCAP_DONT_SAVE;}
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS(item_nuclearbombbutton, CNuclearBombButton)
|
||||
|
||||
void CNuclearBombButton::Precache()
|
||||
{
|
||||
PRECACHE_MODEL("models/nuke_button.mdl");
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
// Nuke timer
|
||||
//----------------------------------------------
|
||||
|
||||
class CNukeTimer : public CBaseAnimating
|
||||
{
|
||||
public:
|
||||
void Spawn(void);
|
||||
void Precache(void);
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS(item_nuclearbomb_timer, CNukeTimer);
|
||||
|
||||
void CNukeTimer::Spawn(void)
|
||||
void CNuclearBombButton::Spawn()
|
||||
{
|
||||
Precache();
|
||||
SET_MODEL(ENT(pev), "models/nuke_timer.mdl");
|
||||
|
||||
SET_MODEL(ENT(pev), "models/nuke_button.mdl");
|
||||
pev->solid = SOLID_NOT;
|
||||
UTIL_SetSize(pev, Vector(-16,-16,0), Vector(16,16,32));
|
||||
pev->movetype = MOVETYPE_NONE;
|
||||
UTIL_SetOrigin(pev, pev->origin);
|
||||
UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0));
|
||||
if( DROP_TO_FLOOR(ENT( pev ) ) == 0 )
|
||||
{
|
||||
ALERT(at_error, "Nuclear Bomb button fell out of level at %f,%f,%f\n", pev->origin.x, pev->origin.y, pev->origin.z);
|
||||
UTIL_Remove( this );
|
||||
return;
|
||||
}
|
||||
pev->skin = 0;
|
||||
}
|
||||
|
||||
void CNukeTimer::Precache(void)
|
||||
void CNuclearBombButton::SetNuclearBombButton(bool on)
|
||||
{
|
||||
PRECACHE_MODEL("models/nuke_timer.mdl");
|
||||
pev->skin = 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
// Nuke case
|
||||
//----------------------------------------------
|
||||
class CNukeCase : public CBaseButton
|
||||
class CNuclearBomb : public CBaseToggle
|
||||
{
|
||||
public:
|
||||
void Precache();
|
||||
void Spawn();
|
||||
void KeyValue(KeyValueData* pkvd);
|
||||
void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value);
|
||||
int ObjectCaps() {return FCAP_ACROSS_TRANSITION | FCAP_IMPULSE_USE;}
|
||||
void UpdateOnRemove();
|
||||
|
||||
virtual int Save(CSave &save);
|
||||
virtual int Restore(CRestore &restore);
|
||||
virtual int Save( CSave &save );
|
||||
virtual int Restore( CRestore &restore );
|
||||
static TYPEDESCRIPTION m_SaveData[];
|
||||
|
||||
static TYPEDESCRIPTION m_SaveData[];
|
||||
|
||||
void KeyValue(KeyValueData *pkvd);
|
||||
|
||||
void Spawn(void);
|
||||
void Precache(void);
|
||||
|
||||
void EXPORT StartupThink(void);
|
||||
void EXPORT CaseThink(void);
|
||||
|
||||
void ButtonActivate();
|
||||
|
||||
int m_initialstate;
|
||||
float m_flWait;
|
||||
float m_flNextTickTime;
|
||||
BOOL m_fCaseOn;
|
||||
|
||||
EHANDLE m_hNukeButton;
|
||||
EHANDLE m_hNukeTimer;
|
||||
|
||||
|
||||
void TurnOn(void);
|
||||
void TurnOff(void);
|
||||
BOOL m_fOn;
|
||||
float m_flLastPush;
|
||||
int m_iPushCount;
|
||||
CNuclearBombTimer* m_pTimer;
|
||||
CNuclearBombButton* m_pButton;
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS(item_nuclearbomb, CNukeCase);
|
||||
LINK_ENTITY_TO_CLASS(item_nuclearbomb, CNuclearBomb)
|
||||
|
||||
TYPEDESCRIPTION CNukeCase::m_SaveData[] =
|
||||
TYPEDESCRIPTION CNuclearBomb::m_SaveData[] =
|
||||
{
|
||||
DEFINE_FIELD(CNukeCase, m_initialstate, FIELD_INTEGER),
|
||||
DEFINE_FIELD(CNukeCase, m_flWait, FIELD_FLOAT),
|
||||
|
||||
DEFINE_FIELD(CNukeCase, m_hNukeButton, FIELD_EHANDLE),
|
||||
DEFINE_FIELD(CNukeCase, m_hNukeTimer, FIELD_EHANDLE),
|
||||
DEFINE_FIELD(CNukeCase, m_flNextTickTime, FIELD_TIME),
|
||||
DEFINE_FIELD(CNukeCase, m_fCaseOn, FIELD_BOOLEAN),
|
||||
|
||||
DEFINE_FIELD(CNuclearBomb, m_fOn, FIELD_BOOLEAN),
|
||||
DEFINE_FIELD(CNuclearBomb, m_flLastPush, FIELD_TIME),
|
||||
DEFINE_FIELD(CNuclearBomb, m_iPushCount, FIELD_INTEGER),
|
||||
};
|
||||
|
||||
IMPLEMENT_SAVERESTORE(CNukeCase, CBaseButton);
|
||||
IMPLEMENT_SAVERESTORE(CNuclearBomb, CBaseToggle)
|
||||
|
||||
void CNukeCase::KeyValue(KeyValueData* pkvd)
|
||||
void CNuclearBomb::Precache()
|
||||
{
|
||||
if (FStrEq(pkvd->szKeyName, "initialstate"))
|
||||
{
|
||||
m_initialstate = atoi(pkvd->szValue);
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else if (FStrEq(pkvd->szKeyName, "wait"))
|
||||
{
|
||||
m_flWait = atof(pkvd->szValue);
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else
|
||||
CBaseEntity::KeyValue(pkvd);
|
||||
PRECACHE_MODEL("models/nuke_case.mdl");
|
||||
UTIL_PrecacheOther("item_nuclearbombtimer");
|
||||
UTIL_PrecacheOther("item_nuclearbombbutton");
|
||||
PRECACHE_SOUND("buttons/button4.wav");
|
||||
PRECACHE_SOUND("buttons/button6.wav");
|
||||
|
||||
m_pTimer = (CNuclearBombTimer*)Create("item_nuclearbombtimer", pev->origin, pev->angles);
|
||||
if (m_pTimer)
|
||||
m_pTimer->SetNuclearBombTimer(m_fOn);
|
||||
m_pButton = (CNuclearBombButton*)Create("item_nuclearbombbutton", pev->origin, pev->angles);
|
||||
if (m_pButton)
|
||||
m_pButton->SetNuclearBombButton(m_fOn);
|
||||
}
|
||||
|
||||
void CNukeCase::Spawn(void)
|
||||
void CNuclearBomb::Spawn()
|
||||
{
|
||||
//
|
||||
// Remove touch button flag, so that it will correctly set
|
||||
// the default "ButtonUse" function pointer in the
|
||||
// CBaseButton::Spawn function.
|
||||
//
|
||||
pev->spawnflags &= ~SF_BUTTON_TOUCH_ONLY;
|
||||
|
||||
// Set toggle spawn flag, to prevent the button
|
||||
// from returning.
|
||||
pev->spawnflags |= SF_BUTTON_TOGGLE;
|
||||
|
||||
|
||||
// Make the button stay on place.
|
||||
m_flWait = -1;
|
||||
|
||||
//
|
||||
// Set model name right now so that it will be precached
|
||||
// from the CBaseButton::Precache and set from
|
||||
// the CBaseButton::Spawn function.
|
||||
//
|
||||
pev->model = ALLOC_STRING(NUKE_MODEL_CASE);
|
||||
|
||||
// Call CBaseButton (baseclass) spawn function.
|
||||
CBaseButton::Spawn();
|
||||
|
||||
pev->movetype = MOVETYPE_FLY;
|
||||
Precache();
|
||||
SET_MODEL(ENT(pev), "models/nuke_case.mdl");
|
||||
pev->solid = SOLID_BBOX;
|
||||
|
||||
UTIL_SetOrigin( pev, pev->origin );
|
||||
UTIL_SetSize( pev, Vector(-16, -16, 0), Vector(16, 16, 36) );
|
||||
|
||||
// Change button sound.
|
||||
pev->noise = ALLOC_STRING("buttons/button4.wav");
|
||||
|
||||
// Setup next tick time (to play tick sound).
|
||||
m_flNextTickTime = gpGlobals->time;
|
||||
|
||||
m_hNukeButton.Set(NULL);
|
||||
m_hNukeTimer.Set(NULL);
|
||||
|
||||
// Adjust angles. In level editor, the case is 90 degrees in
|
||||
// counter clockwise (relative to PI).
|
||||
pev->angles.y = -90;
|
||||
|
||||
SetThink(&CNukeCase::StartupThink);
|
||||
pev->nextthink = gpGlobals->time + 0.1f;
|
||||
}
|
||||
|
||||
void CNukeCase::Precache(void)
|
||||
{
|
||||
CBaseButton::Precache();
|
||||
|
||||
PRECACHE_MODEL(STRING(pev->model));
|
||||
|
||||
PRECACHE_SOUND( "common/nuke_ticking.wav" );
|
||||
|
||||
UTIL_PrecacheOther( NUKE_CLASSNAME_BUTTON );
|
||||
UTIL_PrecacheOther( NUKE_CLASSNAME_TIMER );
|
||||
}
|
||||
|
||||
|
||||
void CNukeCase::StartupThink(void)
|
||||
{
|
||||
pev->nextthink = gpGlobals->time + 0.1f;
|
||||
|
||||
CBaseEntity* pPart = NULL;
|
||||
|
||||
pPart = CBaseEntity::Create(NUKE_CLASSNAME_BUTTON, pev->origin, pev->angles);
|
||||
|
||||
if (pPart)
|
||||
UTIL_SetOrigin(pev, pev->origin);
|
||||
UTIL_SetSize(pev, Vector(-16,-16,0), Vector(16,16,32));
|
||||
pev->movetype = MOVETYPE_NONE;
|
||||
if( DROP_TO_FLOOR(ENT( pev ) ) == 0 )
|
||||
{
|
||||
m_hNukeButton = pPart;
|
||||
ALERT(at_error, "Nuclear Bomb fell out of level at %f,%f,%f\n", pev->origin.x, pev->origin.y, pev->origin.z);
|
||||
UTIL_Remove( this );
|
||||
return;
|
||||
}
|
||||
m_iPushCount = 0;
|
||||
m_flLastPush = gpGlobals->time;
|
||||
}
|
||||
|
||||
// Adjust angles. In level editor, the case is 90 degrees in
|
||||
// counter clockwise (relative to PI).
|
||||
m_hNukeButton->pev->angles.y = -90;
|
||||
void CNuclearBomb::KeyValue(KeyValueData *pkvd)
|
||||
{
|
||||
if( FStrEq( pkvd->szKeyName, "initialstate" ) )
|
||||
{
|
||||
m_fOn = atoi( pkvd->szValue );
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else if( FStrEq( pkvd->szKeyName, "wait" ) )
|
||||
{
|
||||
m_flWait = atof( pkvd->szValue );
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ALERT(at_aiconsole, "ERROR: Failed to create entity with classname %s.\n", NUKE_CLASSNAME_BUTTON);
|
||||
}
|
||||
|
||||
pPart = CBaseEntity::Create(NUKE_CLASSNAME_TIMER, pev->origin, pev->angles);
|
||||
|
||||
if (pPart)
|
||||
{
|
||||
m_hNukeTimer = pPart;
|
||||
|
||||
// Adjust angles. In level editor, the case is 90 degrees in
|
||||
// counter clockwise (relative to PI).
|
||||
m_hNukeTimer->pev->angles.y = -90;
|
||||
}
|
||||
else
|
||||
{
|
||||
ALERT(at_aiconsole, "ERROR: Failed to create entity with classname %s.\n", NUKE_CLASSNAME_TIMER);
|
||||
}
|
||||
|
||||
TurnOn();
|
||||
|
||||
SetThink(&CNukeCase::CaseThink);
|
||||
CBaseToggle::KeyValue(pkvd);
|
||||
}
|
||||
|
||||
void CNukeCase::CaseThink(void)
|
||||
void CNuclearBomb::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
|
||||
{
|
||||
if (m_fCaseOn)
|
||||
if ((m_flWait >= 0 || m_iPushCount <= 0) && m_flWait <= gpGlobals->time - m_flLastPush && ShouldToggle(useType, m_fOn))
|
||||
{
|
||||
if (m_flNextTickTime < gpGlobals->time)
|
||||
const char* sound = NULL;
|
||||
if (m_fOn)
|
||||
{
|
||||
if ( m_hNukeTimer )
|
||||
m_hNukeTimer->pev->skin = ((m_hNukeTimer->pev->skin + 1) % 3);
|
||||
|
||||
CBaseEntity* pPlayer = UTIL_PlayerByIndex( 1 );
|
||||
|
||||
ASSERT( pPlayer != NULL );
|
||||
float volume = 0.0f;
|
||||
float flDist = (pPlayer->pev->origin - pev->origin).Length();
|
||||
|
||||
if (flDist <= NUKE_MIN_HEAR_DIST)
|
||||
{
|
||||
volume = 1.0f - (flDist / (float)NUKE_MIN_HEAR_DIST);
|
||||
ALERT(at_console, "Nuclearbomb volume: %f.\n", volume);
|
||||
}
|
||||
|
||||
EMIT_SOUND(ENT(pev), CHAN_ITEM, "common/nuke_ticking.wav", volume, ATTN_NONE);
|
||||
m_flNextTickTime = gpGlobals->time + 0.05f;
|
||||
m_fOn = FALSE;
|
||||
sound = "buttons/button4.wav";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fOn = TRUE;
|
||||
sound = "buttons/button6.wav";
|
||||
}
|
||||
EMIT_SOUND(ENT(pev), CHAN_VOICE, sound, VOL_NORM, ATTN_NORM);
|
||||
SUB_UseTargets(pActivator, USE_TOGGLE, 0);
|
||||
if (m_pButton)
|
||||
{
|
||||
m_pButton->SetNuclearBombButton(m_fOn);
|
||||
}
|
||||
if (m_pTimer)
|
||||
{
|
||||
m_pTimer->SetNuclearBombTimer(m_fOn);
|
||||
}
|
||||
m_iPushCount++;
|
||||
m_flLastPush = gpGlobals->time;
|
||||
}
|
||||
|
||||
pev->nextthink = gpGlobals->time + 0.1f;
|
||||
}
|
||||
|
||||
void CNukeCase::TurnOn(void)
|
||||
void CNuclearBomb::UpdateOnRemove()
|
||||
{
|
||||
if (m_hNukeButton)
|
||||
m_hNukeButton->pev->skin = 1;
|
||||
|
||||
if (m_hNukeTimer)
|
||||
m_hNukeTimer->pev->skin = 0;
|
||||
|
||||
m_toggle_state = TS_AT_BOTTOM;
|
||||
|
||||
m_flNextTickTime = gpGlobals->time;
|
||||
m_fCaseOn = TRUE;
|
||||
}
|
||||
|
||||
void CNukeCase::TurnOff(void)
|
||||
{
|
||||
if (m_hNukeButton)
|
||||
m_hNukeButton->pev->skin = 0;
|
||||
|
||||
if (m_hNukeTimer)
|
||||
m_hNukeTimer->pev->skin = 3;
|
||||
|
||||
m_toggle_state = TS_AT_TOP;
|
||||
|
||||
m_flNextTickTime = 0.0f;
|
||||
m_fCaseOn = FALSE;
|
||||
|
||||
STOP_SOUND(ENT(pev), CHAN_ITEM, "common/nuke_ticking.wav");
|
||||
}
|
||||
|
||||
//
|
||||
// Starts the button moving "in/up".
|
||||
//
|
||||
void CNukeCase::ButtonActivate(void)
|
||||
{
|
||||
ASSERT(m_toggle_state == TS_AT_BOTTOM);
|
||||
m_toggle_state = TS_AT_TOP;
|
||||
|
||||
EMIT_SOUND(ENT(pev), CHAN_VOICE, STRING(pev->noise), 1, ATTN_NORM);
|
||||
|
||||
TurnOff();
|
||||
|
||||
SUB_UseTargets(m_hActivator, USE_TOGGLE, TS_AT_TOP);
|
||||
|
||||
SetThink( NULL );
|
||||
SetUse( NULL );
|
||||
CBaseToggle::UpdateOnRemove();
|
||||
if (m_pTimer)
|
||||
{
|
||||
UTIL_Remove(m_pTimer);
|
||||
m_pTimer = NULL;
|
||||
}
|
||||
if (m_pButton)
|
||||
{
|
||||
UTIL_Remove(m_pButton);
|
||||
m_pButton = NULL;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user