Roman Chistokhodov
5 years ago
2 changed files with 632 additions and 0 deletions
@ -0,0 +1,631 @@
@@ -0,0 +1,631 @@
|
||||
#include "extdll.h" |
||||
#include "util.h" |
||||
#include "cbase.h" |
||||
#include "effects.h" |
||||
#include "weapons.h" |
||||
#include "explode.h" |
||||
#include "monsters.h" |
||||
#include "player.h" |
||||
#include "soundent.h" |
||||
|
||||
class CMortarShell : public CGrenade |
||||
{ |
||||
public: |
||||
void Precache(); |
||||
void BurnThink(); |
||||
void MortarExplodeTouch(CBaseEntity *pOther); |
||||
void Spawn(); |
||||
void FlyThink(); |
||||
int Save(CSave &save); |
||||
int Restore(CRestore &restore); |
||||
static CMortarShell *CreateMortarShell(Vector p_VecOrigin, Vector p_VecAngles, CBaseEntity *pOwner, int velocity); |
||||
|
||||
static TYPEDESCRIPTION m_SaveData[]; |
||||
int m_iTrail; |
||||
BOOL m_iSoundedOff; |
||||
float m_flIgniteTime; |
||||
float m_velocity; |
||||
}; |
||||
|
||||
LINK_ENTITY_TO_CLASS(mortar_shell, CMortarShell) |
||||
|
||||
TYPEDESCRIPTION CMortarShell::m_SaveData[] = |
||||
{ |
||||
DEFINE_FIELD(CMortarShell, m_velocity, FIELD_FLOAT), |
||||
DEFINE_FIELD(CMortarShell, m_flIgniteTime, FIELD_FLOAT), |
||||
DEFINE_FIELD(CMortarShell, m_iSoundedOff, FIELD_BOOLEAN), |
||||
}; |
||||
|
||||
IMPLEMENT_SAVERESTORE(CMortarShell, CGrenade) |
||||
|
||||
void CMortarShell::Precache() |
||||
{ |
||||
PRECACHE_MODEL("models/mortarshell.mdl"); |
||||
m_iTrail = PRECACHE_MODEL("sprites/wep_smoke_01.spr"); |
||||
PRECACHE_SOUND("weapons/ofmortar.wav"); |
||||
} |
||||
|
||||
void CMortarShell::Spawn() |
||||
{ |
||||
Precache(); |
||||
SET_MODEL(ENT(pev), "models/mortarshell.mdl"); |
||||
UTIL_SetSize(pev, g_vecZero, g_vecZero); |
||||
|
||||
pev->solid = SOLID_BBOX; |
||||
pev->movetype = MOVETYPE_BOUNCE; |
||||
pev->classname = MAKE_STRING("mortar_shell"); |
||||
SetThink(&CMortarShell::BurnThink); |
||||
SetTouch(&CMortarShell::MortarExplodeTouch); |
||||
|
||||
pev->dmg = gSkillData.plrDmgRPG*2; |
||||
pev->nextthink = gpGlobals->time + 0.1; |
||||
m_flIgniteTime = gpGlobals->time; |
||||
m_iSoundedOff = FALSE; |
||||
} |
||||
|
||||
void CMortarShell::MortarExplodeTouch(CBaseEntity *pOther) |
||||
{ |
||||
TraceResult tr; |
||||
Vector vecSpot; |
||||
|
||||
pev->model = iStringNull;//invisible
|
||||
pev->solid = SOLID_NOT;// intangible
|
||||
|
||||
pev->takedamage = DAMAGE_NO; |
||||
|
||||
vecSpot = pev->origin + Vector( 0, 0, 8 ); |
||||
UTIL_TraceLine( vecSpot, vecSpot + Vector( 0, 0, -40 ), ignore_monsters, dont_ignore_glass, ENT(pev), &tr ); |
||||
|
||||
// Pull out of the wall a bit
|
||||
if( tr.flFraction != 1.0 ) |
||||
{ |
||||
pev->origin = tr.vecEndPos + ( tr.vecPlaneNormal * ( pev->dmg - 24 ) * 0.6 ); |
||||
} |
||||
|
||||
int iContents = UTIL_PointContents( pev->origin ); |
||||
|
||||
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin ); |
||||
WRITE_BYTE( TE_EXPLOSION ); // This makes a dynamic light and the explosion sprites/sound
|
||||
WRITE_COORD( pev->origin.x ); // Send to PAS because of the sound
|
||||
WRITE_COORD( pev->origin.y ); |
||||
WRITE_COORD( pev->origin.z ); |
||||
if( iContents != CONTENTS_WATER ) |
||||
{ |
||||
WRITE_SHORT( g_sModelIndexFireball ); |
||||
} |
||||
else |
||||
{ |
||||
WRITE_SHORT( g_sModelIndexWExplosion ); |
||||
} |
||||
WRITE_BYTE( (pev->dmg - 50) * 5); // scale * 10
|
||||
WRITE_BYTE( 10 ); // framerate
|
||||
WRITE_BYTE( TE_EXPLFLAG_NONE ); |
||||
MESSAGE_END(); |
||||
|
||||
CSoundEnt::InsertSound( bits_SOUND_COMBAT, pev->origin, NORMAL_EXPLOSION_VOLUME, 3.0 ); |
||||
entvars_t *pevOwner; |
||||
if( pev->owner ) |
||||
pevOwner = VARS( pev->owner ); |
||||
else |
||||
pevOwner = NULL; |
||||
|
||||
pev->owner = NULL; // can't traceline attack owner if this is set
|
||||
|
||||
RadiusDamage( pev, pevOwner, pev->dmg, CLASS_NONE, DMG_BLAST ); |
||||
|
||||
if( RANDOM_FLOAT( 0, 1 ) < 0.5 ) |
||||
{ |
||||
UTIL_DecalTrace( &tr, 11 ); |
||||
} |
||||
else |
||||
{ |
||||
UTIL_DecalTrace( &tr, 12 ); |
||||
} |
||||
|
||||
switch( RANDOM_LONG( 0, 2 ) ) |
||||
{ |
||||
case 0: |
||||
EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/debris1.wav", 0.55, ATTN_NORM ); |
||||
break; |
||||
case 1: |
||||
EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/debris2.wav", 0.55, ATTN_NORM ); |
||||
break; |
||||
case 2: |
||||
EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/debris3.wav", 0.55, ATTN_NORM ); |
||||
break; |
||||
} |
||||
|
||||
pev->effects |= EF_NODRAW; |
||||
SetThink( &CGrenade::Smoke ); |
||||
pev->velocity = g_vecZero; |
||||
pev->nextthink = gpGlobals->time + 0.3; |
||||
|
||||
if( iContents != CONTENTS_WATER ) |
||||
{ |
||||
int sparkCount = RANDOM_LONG( 0, 3 ); |
||||
for( int i = 0; i < sparkCount; i++ ) |
||||
Create( "spark_shower", pev->origin, tr.vecPlaneNormal, NULL ); |
||||
} |
||||
} |
||||
|
||||
|
||||
void CMortarShell::BurnThink() |
||||
{ |
||||
UTIL_VecToAngles(pev->velocity); |
||||
pev->angles = pev->velocity; |
||||
|
||||
MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin); |
||||
WRITE_BYTE(110); |
||||
WRITE_COORD(pev->origin.x); |
||||
WRITE_COORD(pev->origin.y); |
||||
WRITE_COORD(pev->origin.z); |
||||
WRITE_COORD(0); |
||||
WRITE_COORD(0); |
||||
WRITE_COORD(1); |
||||
WRITE_SHORT(m_iTrail); |
||||
WRITE_BYTE(1); |
||||
WRITE_BYTE(12); |
||||
WRITE_BYTE(120); |
||||
MESSAGE_END(); |
||||
|
||||
if(!((m_flIgniteTime + 0.2) >= gpGlobals->time)) |
||||
SetThink(&CMortarShell::FlyThink); |
||||
|
||||
pev->nextthink = gpGlobals->time + 0.01; |
||||
} |
||||
|
||||
void CMortarShell::FlyThink() |
||||
{ |
||||
pev->angles = UTIL_VecToAngles(pev->velocity); |
||||
pev->angles.x -= 90; |
||||
|
||||
if(pev->velocity.z < 20 && !m_iSoundedOff) |
||||
{ |
||||
m_iSoundedOff = TRUE; |
||||
EMIT_SOUND_DYN(ENT(pev), 2, "weapons/ofmortar.wav", 1, 0, 0, 100); |
||||
} |
||||
|
||||
pev->nextthink = gpGlobals->time + 0.1; |
||||
} |
||||
|
||||
CMortarShell *CMortarShell::CreateMortarShell(Vector p_VecOrigin, Vector p_VecAngles, CBaseEntity *pOwner, int velocity) |
||||
{ |
||||
CMortarShell *rocket = GetClassPtr( (CMortarShell *)NULL ); |
||||
rocket->Spawn(); |
||||
|
||||
rocket->pev->gravity = 1; |
||||
UTIL_SetOrigin( rocket->pev, p_VecOrigin ); |
||||
rocket->pev->angles = UTIL_VecToAngles(p_VecAngles); |
||||
UTIL_MakeVectors(p_VecAngles); |
||||
rocket->pev->velocity = rocket->pev->velocity - gpGlobals->v_forward * velocity; |
||||
if (pOwner) |
||||
rocket->pev->owner = ENT(pOwner->pev); |
||||
|
||||
return rocket; |
||||
} |
||||
|
||||
#define SF_MORTAR_ACTIVE (1 << 0) |
||||
#define SF_MORTAR_LINE_OF_SIGHT (1 << 4) |
||||
#define SF_MORTAR_CAN_CONTROL (1 << 5) |
||||
|
||||
class COp4Mortar : public CBaseMonster |
||||
{ |
||||
public: |
||||
void Spawn(); |
||||
virtual int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); |
||||
virtual void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); |
||||
void Precache(); |
||||
void KeyValue(KeyValueData *pvkd); |
||||
void UpdatePosition(float direction, int controller); |
||||
void AIUpdatePosition(); |
||||
virtual int Save(CSave &save); |
||||
virtual int Restore(CRestore &restore); |
||||
CBaseEntity *FindTarget(); |
||||
void MortarThink(); |
||||
static TYPEDESCRIPTION m_SaveData[]; |
||||
int ObjectCaps() { return 0; } |
||||
|
||||
float m_FireDelay; |
||||
BOOL m_tracking; |
||||
float m_minRange; |
||||
float m_maxRange; |
||||
float m_lastupdate; |
||||
float m_zeroYaw; |
||||
float m_lastFire; |
||||
float m_trackDelay; |
||||
float m_flExplodeTime; |
||||
int m_hmax; |
||||
int m_hmin; |
||||
int d_x; |
||||
int d_y; |
||||
int m_velocity; |
||||
int m_iEnemyType; |
||||
int m_iUpdateTime; |
||||
Vector m_vGunAngle; |
||||
Vector m_vIdealGunVector; |
||||
Vector m_vIdealGunAngle; |
||||
}; |
||||
|
||||
LINK_ENTITY_TO_CLASS(op4mortar, COp4Mortar) |
||||
|
||||
TYPEDESCRIPTION COp4Mortar::m_SaveData[] = |
||||
{ |
||||
DEFINE_FIELD( COp4Mortar, m_tracking, FIELD_BOOLEAN ), |
||||
DEFINE_FIELD( COp4Mortar, m_FireDelay, FIELD_FLOAT ), |
||||
DEFINE_FIELD( COp4Mortar, m_minRange, FIELD_FLOAT), |
||||
DEFINE_FIELD( COp4Mortar, m_maxRange, FIELD_FLOAT ), |
||||
DEFINE_FIELD( COp4Mortar, m_lastFire, FIELD_FLOAT), |
||||
DEFINE_FIELD( COp4Mortar, m_trackDelay, FIELD_FLOAT ), |
||||
DEFINE_FIELD( COp4Mortar, m_hmax, FIELD_INTEGER ), |
||||
DEFINE_FIELD( COp4Mortar, m_hmin, FIELD_INTEGER ), |
||||
DEFINE_FIELD( COp4Mortar, m_velocity, FIELD_INTEGER ), |
||||
DEFINE_FIELD( COp4Mortar, m_iEnemyType, FIELD_INTEGER ), |
||||
DEFINE_FIELD( COp4Mortar, m_vGunAngle, FIELD_VECTOR ), |
||||
DEFINE_FIELD(COp4Mortar, m_lastupdate, FIELD_FLOAT), |
||||
}; |
||||
|
||||
IMPLEMENT_SAVERESTORE( COp4Mortar, CBaseMonster ) |
||||
|
||||
|
||||
void COp4Mortar::Precache() |
||||
{ |
||||
PRECACHE_MODEL("models/mortar.mdl"); |
||||
PRECACHE_SOUND("weapons/mortarhit.wav"); |
||||
PRECACHE_SOUND("player/pl_grate1.wav"); |
||||
UTIL_PrecacheOther("mortar_shell"); |
||||
} |
||||
|
||||
void COp4Mortar::Spawn() |
||||
{ |
||||
float angle; |
||||
|
||||
Precache(); |
||||
UTIL_SetOrigin(pev, pev->origin); |
||||
SET_MODEL(ENT(pev), "models/mortar.mdl"); |
||||
|
||||
pev->sequence = LookupSequence("idle"); |
||||
ResetSequenceInfo(); |
||||
pev->frame = 0; |
||||
pev->framerate = 1; |
||||
m_tracking = FALSE; |
||||
m_lastupdate = gpGlobals->time + 0.5; |
||||
m_vGunAngle = Vector(0,0,0); |
||||
m_iUpdateTime = 0; |
||||
|
||||
if(m_FireDelay < 0.5) |
||||
m_FireDelay = 5; |
||||
|
||||
if(m_minRange == 0) |
||||
m_minRange = 128; |
||||
|
||||
if(m_maxRange == 0) |
||||
m_maxRange = 3072; |
||||
|
||||
InitBoneControllers(); |
||||
angle = pev->angles.y + 180; |
||||
|
||||
m_zeroYaw = UTIL_AngleMod(angle); |
||||
m_hEnemy = NULL; |
||||
|
||||
if (pev->spawnflags & SF_MORTAR_ACTIVE) |
||||
SetThink(&COp4Mortar::MortarThink); |
||||
else |
||||
SetThink(NULL); |
||||
|
||||
m_flExplodeTime = gpGlobals->time + 5; |
||||
|
||||
pev->nextthink = gpGlobals->time + 0.01; |
||||
} |
||||
|
||||
void COp4Mortar::UpdatePosition(float direction, int controller) |
||||
{ |
||||
if(m_vGunAngle.y > 90) |
||||
m_vGunAngle.y = 90; |
||||
|
||||
if(m_vGunAngle.y < -90) |
||||
m_vGunAngle.y = -90; |
||||
|
||||
if(m_vGunAngle.x > 90) |
||||
m_vGunAngle.x = 90; |
||||
|
||||
if(m_vGunAngle.x < 0) |
||||
m_vGunAngle.x = 0; |
||||
|
||||
if(controller == 1) |
||||
m_vGunAngle.y += direction/2; |
||||
else |
||||
m_vGunAngle.x += direction/2; |
||||
|
||||
if(m_iUpdateTime >= 15) |
||||
{ |
||||
EMIT_SOUND_DYN(ENT(pev), 2, "player/pl_grate1.wav", 1, 0.8, 0, 100); |
||||
m_iUpdateTime = 0; |
||||
} |
||||
|
||||
SetBoneController(1, m_vGunAngle.y); |
||||
SetBoneController(0, m_vGunAngle.x); |
||||
|
||||
m_lastupdate = gpGlobals->time + 0.1; |
||||
m_iUpdateTime++; |
||||
} |
||||
|
||||
void COp4Mortar::MortarThink() |
||||
{ |
||||
Vector pos, angle, vecTarget; |
||||
|
||||
if(m_fSequenceFinished) |
||||
{ |
||||
if(pev->sequence != LookupSequence("idle")) |
||||
{ |
||||
pev->frame = 0; |
||||
pev->sequence = LookupSequence("idle"); |
||||
ResetSequenceInfo(); |
||||
} |
||||
} |
||||
|
||||
DispatchAnimEvents(); |
||||
StudioFrameAdvance(); |
||||
|
||||
pev->nextthink = gpGlobals->time + 0.1; |
||||
|
||||
if(pev->spawnflags & SF_MORTAR_ACTIVE) |
||||
{ |
||||
if(m_hEnemy == 0 || !m_hEnemy->IsAlive()) |
||||
{ |
||||
m_hEnemy = FindTarget(); |
||||
} |
||||
} |
||||
|
||||
if(m_hEnemy) |
||||
{ |
||||
vecTarget = Vector( m_hEnemy->pev->origin.x, m_hEnemy->pev->origin.y, m_hEnemy->pev->absmax.z); |
||||
|
||||
if((pev->origin - m_hEnemy->pev->origin).Length() <= m_maxRange) |
||||
{ |
||||
GetAttachment(0, pos, angle); |
||||
|
||||
m_vIdealGunVector = VecCheckThrow(pev, pos, vecTarget, 700, 1); |
||||
m_vIdealGunVector.x =- m_vIdealGunVector.x; |
||||
m_vIdealGunVector.y =- m_vIdealGunVector.y; |
||||
|
||||
m_vIdealGunAngle = UTIL_VecToAngles(m_vIdealGunVector); |
||||
|
||||
m_trackDelay = gpGlobals->time; |
||||
} |
||||
AIUpdatePosition(); |
||||
} |
||||
|
||||
if(m_hEnemy != 0 && gpGlobals->time - m_lastFire > 5 && (m_hEnemy->pev->origin - pev->origin).Length() > 710) |
||||
{ |
||||
EMIT_SOUND_DYN(ENT(pev), 2, "weapons/mortarhit.wav", 1, 0.8, 0, 100); |
||||
UTIL_ScreenShake(pev->origin, 12, 100, 2, 1000); |
||||
|
||||
float speed = m_vIdealGunVector.Length(); |
||||
|
||||
angle = m_vIdealGunAngle; |
||||
|
||||
if(speed > 0) |
||||
{ |
||||
if(CMortarShell::CreateMortarShell(pev->origin, angle, this, floor(speed))) |
||||
{ |
||||
pev->frame = 0; |
||||
pev->sequence = LookupSequence("fire"); |
||||
ResetSequenceInfo(); |
||||
m_lastFire = gpGlobals->time; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
CBaseEntity *COp4Mortar::FindTarget() |
||||
{ |
||||
CBaseEntity *pPlayer; |
||||
Vector BarretEnd; |
||||
Vector BarretAngle; |
||||
Vector targetPosition; |
||||
TraceResult tr; |
||||
CBaseEntity *pIdealTarget; |
||||
|
||||
if((pPlayer = UTIL_FindEntityByClassname(0, "player")) == NULL ) |
||||
return NULL; |
||||
|
||||
m_pLink = 0; |
||||
|
||||
GetAttachment(0, BarretEnd, BarretAngle); |
||||
|
||||
float dist = (pPlayer->pev->origin - pev->origin).Length(); |
||||
|
||||
if(pPlayer->IsAlive()) |
||||
{ |
||||
if(m_maxRange >= dist) |
||||
{ |
||||
targetPosition = pPlayer->pev->origin + pev->view_ofs; |
||||
UTIL_TraceLine(BarretEnd, targetPosition, ignore_monsters, dont_ignore_glass, ENT(pev), &tr); |
||||
|
||||
if((!(pev->spawnflags & SF_MORTAR_LINE_OF_SIGHT) || tr.pHit == ENT(pPlayer->pev)) && !m_iEnemyType) |
||||
{ |
||||
pIdealTarget = pPlayer; |
||||
} |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
pIdealTarget = NULL; |
||||
} |
||||
|
||||
return pIdealTarget; |
||||
} |
||||
|
||||
int COp4Mortar::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) |
||||
{ |
||||
return CBaseMonster::TakeDamage(pevInflictor, pevAttacker, 0, bitsDamageType); |
||||
} |
||||
|
||||
void COp4Mortar::KeyValue(KeyValueData *pvkd) |
||||
{ |
||||
if(strcmp(pvkd->szKeyName, "m_hmax")) |
||||
{ |
||||
m_hmax = atoi(pvkd->szValue); |
||||
pvkd->fHandled = 1; |
||||
} |
||||
else if(strcmp(pvkd->szKeyName, "m_hmin")) |
||||
{ |
||||
m_hmin = atoi(pvkd->szValue); |
||||
pvkd->fHandled = 1; |
||||
} |
||||
else if(strcmp(pvkd->szKeyName, "mortar_velocity")) |
||||
{ |
||||
m_velocity = atoi(pvkd->szValue); |
||||
pvkd->fHandled = 1; |
||||
} |
||||
else if(strcmp(pvkd->szKeyName, "mindist")) |
||||
{ |
||||
m_minRange = atoi(pvkd->szValue); |
||||
pvkd->fHandled = 1; |
||||
} |
||||
else if(strcmp(pvkd->szKeyName, "maxdist")) |
||||
{ |
||||
m_maxRange = atoi(pvkd->szValue); |
||||
pvkd->fHandled = 1; |
||||
} |
||||
else if(strcmp(pvkd->szKeyName, "enemytype")) |
||||
{ |
||||
m_iEnemyType = atoi(pvkd->szValue); |
||||
pvkd->fHandled = 1; |
||||
} |
||||
else if(strcmp(pvkd->szKeyName, "firedelay")) |
||||
{ |
||||
m_FireDelay = atoi(pvkd->szValue); |
||||
pvkd->fHandled = 1; |
||||
} |
||||
else |
||||
{ |
||||
CBaseToggle::KeyValue(pvkd); |
||||
} |
||||
} |
||||
|
||||
void COp4Mortar::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) |
||||
{ |
||||
SetThink(NULL); |
||||
|
||||
if((pev->spawnflags & SF_MORTAR_CAN_CONTROL) && (pActivator->pev->origin - pev->origin).Length() < 170) |
||||
{ |
||||
EMIT_SOUND_DYN(ENT(pev), 2, "weapons/mortarhit.wav", 1, 0, 0, 100); |
||||
UTIL_ScreenShake(pev->origin, 12, 100, 2, 1000); |
||||
|
||||
Vector pos, angle; |
||||
GetAttachment(0, pos, angle); |
||||
angle = m_vGunAngle; |
||||
float anglemod = pev->angles.y + m_vGunAngle.y; |
||||
|
||||
angle.y = UTIL_AngleMod(anglemod); |
||||
|
||||
if((CMortarShell::CreateMortarShell(pos, angle, this, 2000 - (m_vGunAngle.x * 12.25))) != NULL) |
||||
{ |
||||
pev->frame = 0; |
||||
pev->sequence = LookupSequence("fire"); |
||||
ResetSequenceInfo(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
void COp4Mortar::AIUpdatePosition() |
||||
{ |
||||
if(m_hEnemy != 0 && (m_hEnemy->pev->origin - pev->origin).Length() < 710) |
||||
return; |
||||
|
||||
if(m_vIdealGunAngle.x == 270 && m_vIdealGunAngle.y == 0) |
||||
{ |
||||
m_vIdealGunAngle.x = 0; |
||||
m_vIdealGunAngle.y = 0; |
||||
} |
||||
|
||||
if(m_vIdealGunAngle.x <= 0) |
||||
m_vIdealGunAngle.x = 0; |
||||
|
||||
if(m_vIdealGunAngle.x > 90) |
||||
m_vIdealGunAngle.x = 90; |
||||
|
||||
if(m_vIdealGunAngle.y > 165 && m_vIdealGunAngle.y < 270) |
||||
m_vIdealGunAngle.y = -90; |
||||
|
||||
else if(m_vIdealGunAngle.y > 90 && m_vIdealGunAngle.y < 165) |
||||
m_vIdealGunAngle.y = 90; |
||||
|
||||
|
||||
SetBoneController(0, m_vIdealGunAngle.x); |
||||
SetBoneController(1, m_vIdealGunAngle.y); |
||||
|
||||
m_vGunAngle = m_vIdealGunAngle; |
||||
} |
||||
|
||||
//========================================================
|
||||
// COp4MortarController
|
||||
//========================================================
|
||||
|
||||
class COp4MortarController : public CBaseToggle |
||||
{ |
||||
public: |
||||
void Spawn(); |
||||
int Restore(CRestore &restore); |
||||
int Save(CSave &save); |
||||
void KeyValue(KeyValueData *pvkd); |
||||
void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); |
||||
int ObjectCaps() { return FCAP_CONTINUOUS_USE; } |
||||
|
||||
static TYPEDESCRIPTION m_SaveData[]; |
||||
float m_direction; |
||||
float m_lastpush; |
||||
int m_controller; |
||||
}; |
||||
|
||||
LINK_ENTITY_TO_CLASS(func_op4mortarcontroller, COp4MortarController) |
||||
|
||||
TYPEDESCRIPTION COp4MortarController::m_SaveData[] = |
||||
{ |
||||
DEFINE_FIELD(COp4MortarController, m_controller, FIELD_INTEGER), |
||||
DEFINE_FIELD(COp4MortarController, m_direction, FIELD_INTEGER), |
||||
}; |
||||
|
||||
IMPLEMENT_SAVERESTORE( COp4MortarController, CBaseToggle ) |
||||
|
||||
void COp4MortarController::Spawn() |
||||
{ |
||||
pev->solid = SOLID_NOT; |
||||
pev->movetype = MOVETYPE_PUSH; |
||||
UTIL_SetOrigin(pev, pev->origin); |
||||
|
||||
SET_MODEL(ENT(pev), STRING(pev->model)); |
||||
m_direction = -1; |
||||
m_lastpush = gpGlobals->time; |
||||
} |
||||
|
||||
void COp4MortarController::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) |
||||
{ |
||||
if(gpGlobals->time - m_lastpush > 0.5) |
||||
m_direction = -m_direction; |
||||
|
||||
CBaseEntity* ent = UTIL_FindEntityByTargetname(NULL, STRING(pev->target)); |
||||
if (ent) { |
||||
if (FClassnameIs(ent->pev, "op4mortar")) { |
||||
COp4Mortar *Mortar = (COp4Mortar*)ent; |
||||
Mortar->UpdatePosition(m_direction, m_controller); |
||||
} else { |
||||
ALERT(at_console, "Found %s, but it's not op4mortar!\n", STRING(pev->target)); |
||||
} |
||||
} |
||||
|
||||
m_lastpush = gpGlobals->time; |
||||
} |
||||
|
||||
void COp4MortarController::KeyValue(KeyValueData *pvkd) |
||||
{ |
||||
if(FStrEq(pvkd->szKeyName, "mortar_axis")) |
||||
{ |
||||
m_controller = atoi(pvkd->szValue); |
||||
pvkd->fHandled = 1; |
||||
} |
||||
else |
||||
CBaseToggle::KeyValue(pvkd); |
||||
} |
Loading…
Reference in new issue