You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
352 lines
8.1 KiB
352 lines
8.1 KiB
8 years ago
|
/***
|
||
|
*
|
||
|
* 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 "schedule.h"
|
||
|
#include "nodes.h"
|
||
|
#include "effects.h"
|
||
|
#include "decals.h"
|
||
|
#include "soundent.h"
|
||
|
#include "game.h"
|
||
|
#include "xenspit.h"
|
||
|
|
||
|
LINK_ENTITY_TO_CLASS(xensmallspit, CXenSmallSpit);
|
||
|
|
||
|
TYPEDESCRIPTION CXenSmallSpit::m_SaveData[] =
|
||
|
{
|
||
|
DEFINE_FIELD(CXenSmallSpit, m_iTrail, FIELD_INTEGER),
|
||
|
DEFINE_FIELD(CXenSmallSpit, m_flCycle, FIELD_FLOAT),
|
||
|
DEFINE_FIELD(CXenSmallSpit, m_pBeam, FIELD_CLASSPTR),
|
||
|
DEFINE_FIELD(CXenSmallSpit, m_vecOldVelocity, FIELD_VECTOR),
|
||
|
};
|
||
|
|
||
|
IMPLEMENT_SAVERESTORE(CXenSmallSpit, CBaseEntity);
|
||
|
|
||
|
void CXenSmallSpit::Spawn(void)
|
||
|
{
|
||
|
Precache();
|
||
|
|
||
|
pev->movetype = MOVETYPE_FLY;
|
||
|
pev->classname = MAKE_STRING("xensmallspit");
|
||
|
|
||
|
pev->solid = SOLID_BBOX;
|
||
|
pev->rendermode = kRenderTransAdd;
|
||
|
pev->renderamt = 255;
|
||
|
|
||
|
SET_MODEL(ENT(pev), "sprites/hotglow.spr");
|
||
|
pev->frame = 0;
|
||
|
pev->scale = 0.5;
|
||
|
pev->gravity = 0;
|
||
|
pev->dmg = gSkillData.plrDmgGauss;
|
||
|
|
||
|
UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0));
|
||
|
|
||
|
// trail
|
||
|
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
|
||
|
WRITE_BYTE( TE_BEAMFOLLOW );
|
||
|
WRITE_SHORT( entindex() ); // entity
|
||
|
WRITE_SHORT( m_iTrail ); // model
|
||
|
WRITE_BYTE( 10 ); // life
|
||
|
WRITE_BYTE( 4 ); // width
|
||
|
WRITE_BYTE( 161 ); // r, g, b
|
||
|
WRITE_BYTE( 188 ); // r, g, b
|
||
|
WRITE_BYTE( 0 ); // r, g, b
|
||
|
WRITE_BYTE( 128 ); // brightness
|
||
|
|
||
|
MESSAGE_END();
|
||
|
|
||
|
m_pBeam = NULL;
|
||
|
m_pParent = NULL;
|
||
|
}
|
||
|
|
||
|
void CXenSmallSpit::Precache()
|
||
|
{
|
||
|
PRECACHE_MODEL("sprites/hotglow.spr");
|
||
|
|
||
|
m_iTrail = PRECACHE_MODEL("sprites/laserbeam.spr");
|
||
|
|
||
|
PRECACHE_MODEL("sprites/laserbeam.spr");
|
||
|
}
|
||
|
|
||
|
CXenSmallSpit* CXenSmallSpit::ShootStraight(entvars_t *pevOwner, Vector vecStart, Vector vecAngles, Vector vecVelocity)
|
||
|
{
|
||
|
CXenSmallSpit *pSpit = GetClassPtr((CXenSmallSpit *)NULL);
|
||
|
pSpit->Spawn();
|
||
|
|
||
|
UTIL_SetOrigin(pSpit->pev, vecStart);
|
||
|
pSpit->pev->angles = vecAngles;
|
||
|
pSpit->pev->velocity = vecVelocity;
|
||
|
pSpit->pev->owner = ENT(pevOwner);
|
||
|
pSpit->m_vecOldVelocity = vecVelocity;
|
||
|
|
||
|
pSpit->m_flCycle = 0.0f;
|
||
|
pSpit->m_pParent = NULL;
|
||
|
|
||
|
pSpit->SetThink(&CXenSmallSpit::StraightThink);
|
||
|
pSpit->pev->nextthink = gpGlobals->time + 0.01;
|
||
|
|
||
|
return pSpit;
|
||
|
}
|
||
|
|
||
|
CXenSmallSpit* CXenSmallSpit::ShootCycle(entvars_t *pevOwner, Vector vecStart, Vector vecAngles, Vector vecVelocity, CBaseEntity* pParent, float flCycle)
|
||
|
{
|
||
|
CXenSmallSpit *pSpit = GetClassPtr((CXenSmallSpit *)NULL);
|
||
|
pSpit->Spawn();
|
||
|
|
||
|
UTIL_SetOrigin(pSpit->pev, vecStart);
|
||
|
pSpit->pev->angles = vecAngles;
|
||
|
pSpit->pev->velocity = vecVelocity;
|
||
|
pSpit->pev->owner = ENT(pevOwner);
|
||
|
pSpit->m_vecOldVelocity = vecVelocity;
|
||
|
|
||
|
pSpit->m_flCycle = flCycle;
|
||
|
pSpit->m_pParent = pParent;
|
||
|
|
||
|
pSpit->SetThink(&CXenSmallSpit::CycleThink);
|
||
|
pSpit->pev->nextthink = gpGlobals->time + 0.01;
|
||
|
|
||
|
return pSpit;
|
||
|
}
|
||
|
|
||
|
void CXenSmallSpit::Touch(CBaseEntity *pOther)
|
||
|
{
|
||
|
if (m_pParent != NULL)
|
||
|
return;
|
||
|
|
||
|
if (FClassnameIs(pOther->pev, STRING(pev->classname)))
|
||
|
return;
|
||
|
|
||
|
// ALERT(at_console, " CXenSmallSpit::Touch START\n");
|
||
|
|
||
|
TraceResult tr;
|
||
|
|
||
|
RadiusDamage(pev->origin, pev, pev, pev->dmg, 80, CLASS_NONE, DMG_POISON | DMG_ALWAYSGIB);
|
||
|
|
||
|
if (!pOther->pev->takedamage)
|
||
|
{
|
||
|
// make a splat on the wall
|
||
|
UTIL_TraceLine(pev->origin, pev->origin + pev->velocity * 10, dont_ignore_monsters, ENT(pev), &tr);
|
||
|
UTIL_DecalTrace(&tr, DECAL_SMALLSCORCH1 + RANDOM_LONG(0, 2));
|
||
|
}
|
||
|
|
||
|
if (m_pBeam)
|
||
|
{
|
||
|
UTIL_Remove(m_pBeam);
|
||
|
m_pBeam = NULL;
|
||
|
}
|
||
|
|
||
|
// light.
|
||
|
MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin);
|
||
|
WRITE_BYTE(TE_DLIGHT);
|
||
|
WRITE_COORD(pev->origin.x); // X
|
||
|
WRITE_COORD(pev->origin.y); // Y
|
||
|
WRITE_COORD(pev->origin.z); // Z
|
||
|
WRITE_BYTE(8); // radius * 0.1
|
||
|
WRITE_BYTE(161); // r
|
||
|
WRITE_BYTE(188); // g
|
||
|
WRITE_BYTE(0); // b
|
||
|
WRITE_BYTE(10); // time * 10
|
||
|
WRITE_BYTE(2); // decay * 0.1
|
||
|
MESSAGE_END();
|
||
|
|
||
|
m_pParent = NULL;
|
||
|
|
||
|
SetThink(&CXenSmallSpit::SUB_Remove);
|
||
|
SetTouch(NULL);
|
||
|
pev->nextthink = gpGlobals->time;
|
||
|
|
||
|
// ALERT(at_console, " CXenSmallSpit::Touch END\n");
|
||
|
}
|
||
|
|
||
|
void CXenSmallSpit::StraightThink(void)
|
||
|
{
|
||
|
pev->nextthink = gpGlobals->time + 0.01f;
|
||
|
|
||
|
m_flCycle += 0.02f;
|
||
|
|
||
|
if (m_flCycle >= 1)
|
||
|
m_flCycle = 0;
|
||
|
|
||
|
pev->velocity.z = m_vecOldVelocity.z + sin(m_flCycle * 2 * M_PI) * 16;
|
||
|
}
|
||
|
|
||
|
void CXenSmallSpit::CycleThink(void)
|
||
|
{
|
||
|
pev->nextthink = gpGlobals->time + 0.01f;
|
||
|
|
||
|
m_flCycle += 0.02f;
|
||
|
|
||
|
if (m_flCycle >= 1)
|
||
|
m_flCycle = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
LINK_ENTITY_TO_CLASS(xenlargespit, CXenLargeSpit);
|
||
|
|
||
|
TYPEDESCRIPTION CXenLargeSpit::m_SaveData[] =
|
||
|
{
|
||
|
DEFINE_FIELD(CXenLargeSpit, m_iChildCount, FIELD_INTEGER),
|
||
|
DEFINE_ARRAY(CXenLargeSpit, m_pChildren, FIELD_CLASSPTR, XENSPIT_MAX_PROJECTILES),
|
||
|
};
|
||
|
|
||
|
IMPLEMENT_SAVERESTORE(CXenLargeSpit, CBaseEntity);
|
||
|
|
||
|
|
||
|
void CXenLargeSpit::Spawn(void)
|
||
|
{
|
||
|
Precache();
|
||
|
|
||
|
pev->movetype = MOVETYPE_FLY;
|
||
|
pev->classname = MAKE_STRING("xenlargespit");
|
||
|
|
||
|
pev->solid = SOLID_BBOX;
|
||
|
pev->rendermode = kRenderTransAdd;
|
||
|
pev->renderamt = 255;
|
||
|
|
||
|
SET_MODEL(ENT(pev), "sprites/glow02.spr");
|
||
|
pev->frame = 0;
|
||
|
pev->scale = 0.5;
|
||
|
pev->gravity = 0;
|
||
|
pev->dmg = gSkillData.plrDmgGauss;
|
||
|
|
||
|
pev->renderamt = 0;
|
||
|
|
||
|
UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0));
|
||
|
|
||
|
for (int i = 0; i < XENSPIT_MAX_PROJECTILES; i++)
|
||
|
m_pChildren[i] = NULL;
|
||
|
}
|
||
|
|
||
|
void CXenLargeSpit::Precache()
|
||
|
{
|
||
|
PRECACHE_MODEL("sprites/glow02.spr");
|
||
|
}
|
||
|
|
||
|
CXenLargeSpit* CXenLargeSpit::Shoot(entvars_t *pevOwner, Vector vecStart, Vector vecAngles, Vector vecVelocity)
|
||
|
{
|
||
|
CXenLargeSpit *pSpit = GetClassPtr((CXenLargeSpit *)NULL);
|
||
|
pSpit->Spawn();
|
||
|
|
||
|
UTIL_SetOrigin(pSpit->pev, vecStart);
|
||
|
pSpit->pev->angles = vecAngles;
|
||
|
pSpit->pev->velocity = vecVelocity;
|
||
|
pSpit->pev->owner = ENT(pevOwner);
|
||
|
|
||
|
pSpit->SetThink(&CXenLargeSpit::CycleThink);
|
||
|
pSpit->pev->nextthink = gpGlobals->time + 0.01;
|
||
|
|
||
|
return pSpit;
|
||
|
}
|
||
|
|
||
|
void CXenLargeSpit::Touch(CBaseEntity *pOther)
|
||
|
{
|
||
|
// ALERT(at_console, " CXenLargeSpit::Touch START\n");
|
||
|
|
||
|
float damage = max(pev->dmg, pev->dmg * m_iChildCount);
|
||
|
|
||
|
RadiusDamage(pev->origin, pev, pev, damage, 110, CLASS_NONE, DMG_POISON | DMG_ALWAYSGIB);
|
||
|
|
||
|
TraceResult tr;
|
||
|
|
||
|
if (!pOther->pev->takedamage)
|
||
|
{
|
||
|
// make a splat on the wall
|
||
|
UTIL_TraceLine(pev->origin, pev->origin + pev->velocity * 10, dont_ignore_monsters, ENT(pev), &tr);
|
||
|
UTIL_DecalTrace(&tr, DECAL_SMALLSCORCH1 + RANDOM_LONG(0, 2));
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < m_iChildCount; i++)
|
||
|
{
|
||
|
if (m_pChildren[i])
|
||
|
{
|
||
|
UTIL_Remove(m_pChildren[i]);
|
||
|
m_pChildren[i] = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_iChildCount = 0;
|
||
|
|
||
|
// light.
|
||
|
MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin);
|
||
|
WRITE_BYTE(TE_DLIGHT);
|
||
|
WRITE_COORD(pev->origin.x); // X
|
||
|
WRITE_COORD(pev->origin.y); // Y
|
||
|
WRITE_COORD(pev->origin.z); // Z
|
||
|
WRITE_BYTE(12); // radius * 0.1
|
||
|
WRITE_BYTE(161); // r
|
||
|
WRITE_BYTE(188); // g
|
||
|
WRITE_BYTE(0); // b
|
||
|
WRITE_BYTE(10); // time * 10
|
||
|
WRITE_BYTE(2); // decay * 0.1
|
||
|
MESSAGE_END();
|
||
|
|
||
|
SetThink(&CXenLargeSpit::SUB_Remove);
|
||
|
SetTouch(NULL);
|
||
|
pev->nextthink = gpGlobals->time + 0.1f;
|
||
|
|
||
|
// ALERT(at_console, " CXenLargeSpit::Touch START\n");
|
||
|
}
|
||
|
|
||
|
void CXenLargeSpit::CycleThink(void)
|
||
|
{
|
||
|
pev->nextthink = gpGlobals->time + 0.1f;
|
||
|
|
||
|
Vector src, forward, right, up, cross;
|
||
|
|
||
|
forward = pev->velocity.Normalize();
|
||
|
|
||
|
Vector horizontal = Vector(pev->velocity.x, pev->velocity.y, 0).Normalize();
|
||
|
Vector direction = forward;
|
||
|
|
||
|
float flDot = DotProduct(direction, horizontal);
|
||
|
if (flDot < 0.5)
|
||
|
cross = Vector(1, 0, 0);
|
||
|
else
|
||
|
cross = Vector(0, 0, 1);
|
||
|
|
||
|
right = CrossProduct(direction, cross);
|
||
|
up = CrossProduct(right, direction);
|
||
|
|
||
|
for (int i = 0; i < m_iChildCount; i++)
|
||
|
{
|
||
|
CXenSmallSpit* pSpit = (CXenSmallSpit*)m_pChildren[i];
|
||
|
if (pSpit)
|
||
|
{
|
||
|
float cs, sn, dist;
|
||
|
cs = cos(pSpit->m_flCycle * 2 * M_PI);
|
||
|
sn = sin(pSpit->m_flCycle * 2 * M_PI);
|
||
|
dist = max(2, 2 * m_iChildCount);
|
||
|
|
||
|
// ALERT(at_console, "cs: %.2f. sn: %.2f\n", cs, sn);
|
||
|
|
||
|
Vector target = (right * cs * dist) + (up * sn * dist);
|
||
|
|
||
|
src = pev->origin + target * -2;
|
||
|
pSpit->pev->origin = src;
|
||
|
pSpit->pev->velocity = pev->velocity;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|