env_beam/env_laser: Visual overhaul of env_beam. env_laser now also rebased using my work on env_beam.
This commit is contained in:
parent
0f9439b956
commit
711548465a
9 changed files with 591 additions and 376 deletions
|
@ -35,6 +35,9 @@ Entity_EntityUpdate(float type, float new)
|
|||
case ENT_BEAM:
|
||||
env_beam_ReadEntity(new);
|
||||
break;
|
||||
case ENT_LASER:
|
||||
env_laser_ReadEntity(new);
|
||||
break;
|
||||
case ENT_PHYSICS:
|
||||
NSPhysicsEntity_ReadEntity(new);
|
||||
break;
|
||||
|
@ -118,13 +121,6 @@ Entity_EntityUpdate(float type, float new)
|
|||
case ENT_FOGCONTROLLER:
|
||||
env_fog_controller_readentity(new);
|
||||
break;
|
||||
case ENT_ENVLASER:
|
||||
env_laser l = (env_laser)self;
|
||||
if (new) {
|
||||
spawnfunc_env_laser();
|
||||
}
|
||||
l.ReceiveEntity(new, readfloat());
|
||||
break;
|
||||
case ENT_PARTSYSTEM:
|
||||
info_particle_system ips = (info_particle_system)self;
|
||||
if (new) {
|
||||
|
|
|
@ -11,7 +11,6 @@ client/env_sun.qc
|
|||
client/env_sound.qc
|
||||
client/env_soundscape.qc
|
||||
client/env_particle.qc
|
||||
client/env_laser.qc
|
||||
client/func_lod.qc
|
||||
client/func_dustmotes.qc
|
||||
client/func_dustcloud.qc
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2022 Vera Visions LLC.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
void(float radius, vector texcoordbias) R_EndPolygonRibbon = #0;
|
||||
|
||||
enumflags
|
||||
{
|
||||
ENVLASER_CHANGED_ORIGIN,
|
||||
ENVLASER_CHANGED_ANGLES,
|
||||
ENVLASER_CHANGED_TEXTURE,
|
||||
ENVLASER_CHANGED_ENDTEXTURE,
|
||||
ENVLASER_CHANGED_STATE
|
||||
};
|
||||
|
||||
class env_laser
|
||||
{
|
||||
public:
|
||||
void env_laser(void);
|
||||
|
||||
virtual void ReceiveEntity(float,float);
|
||||
virtual float predraw(void);
|
||||
|
||||
private:
|
||||
int m_iState;
|
||||
string m_strBeamTex;
|
||||
string m_strEndTex;
|
||||
};
|
||||
|
||||
float env_laser::predraw(void)
|
||||
{
|
||||
if (!m_iState)
|
||||
return (PREDRAW_NEXT);
|
||||
|
||||
R_BeginPolygon(m_strBeamTex, 0, 0);
|
||||
R_PolygonVertex(angles, [0,0], [1,1,1], 1.0f);
|
||||
R_PolygonVertex(origin, [0,1], [1,1,1], 1.0f);
|
||||
R_EndPolygonRibbon(2, [1,0]);
|
||||
|
||||
return (PREDRAW_NEXT);
|
||||
}
|
||||
|
||||
void
|
||||
env_laser::ReceiveEntity(float flNew, float flChanged)
|
||||
{
|
||||
if (flChanged & ENVLASER_CHANGED_ORIGIN) {
|
||||
origin[0] = readcoord();
|
||||
origin[1] = readcoord();
|
||||
origin[2] = readcoord();
|
||||
}
|
||||
if (flChanged & ENVLASER_CHANGED_ANGLES) {
|
||||
angles[0] = readcoord();
|
||||
angles[1] = readcoord();
|
||||
angles[2] = readcoord();
|
||||
}
|
||||
if (flChanged & ENVLASER_CHANGED_TEXTURE)
|
||||
m_strBeamTex = sprintf("%s_0.tga", readstring());
|
||||
if (flChanged & ENVLASER_CHANGED_ENDTEXTURE)
|
||||
m_strEndTex = readstring();
|
||||
if (flChanged & ENVLASER_CHANGED_STATE)
|
||||
m_iState = readbyte();
|
||||
|
||||
setorigin(this, origin);
|
||||
}
|
||||
|
||||
void
|
||||
env_laser::env_laser(void)
|
||||
{
|
||||
}
|
|
@ -82,7 +82,6 @@ server/trigger_relay.qc
|
|||
server/env_shooter.qc
|
||||
server/gibshooter.qc
|
||||
server/env_beverage.qc
|
||||
server/env_laser.qc
|
||||
server/item_food.qc
|
||||
server/speaker.qc
|
||||
server/multi_manager.qc
|
||||
|
|
|
@ -1,260 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2022 Vera Visions LLC.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*QUAKED env_laser (1 0 0) (-8 -8 -8) (8 8 8) ENVLAZ_STARTON x x x ENVLAZ_STARTSPARK ENVLAZ_ENDSPARK ENVLAZ_DECALEND
|
||||
Shoots a frickin lazer.
|
||||
|
||||
-------- KEYS --------
|
||||
"targetname" : Name
|
||||
"target" : Target when triggered.
|
||||
"killtarget" : Target to kill when triggered.
|
||||
"texture" : Sprite to use as a texture.
|
||||
"EndSprite" : Sprite to draw at the end of the laser beam impact.
|
||||
"LaserTarget" : Which entity determines the end position.
|
||||
"damage" : Damage-per-second when something passes through.
|
||||
|
||||
-------- NOTES --------
|
||||
Use an info_notnull for a LaserTarget.
|
||||
|
||||
-------- TRIVIA --------
|
||||
This entity was introduced in Half-Life (1998).
|
||||
*/
|
||||
|
||||
enumflags
|
||||
{
|
||||
ENVLASER_CHANGED_ORIGIN,
|
||||
ENVLASER_CHANGED_ANGLES,
|
||||
ENVLASER_CHANGED_TEXTURE,
|
||||
ENVLASER_CHANGED_ENDTEXTURE,
|
||||
ENVLASER_CHANGED_STATE
|
||||
};
|
||||
|
||||
enumflags
|
||||
{
|
||||
ENVLAZ_STARTON,
|
||||
ENVLAZ_2,
|
||||
ENVLAZ_4,
|
||||
ENVLAZ_8,
|
||||
ENVLAZ_STARTSPARK,
|
||||
ENVLAZ_ENDSPARK,
|
||||
ENVLAZ_DECALEND
|
||||
};
|
||||
|
||||
class
|
||||
env_laser:NSPointTrigger
|
||||
{
|
||||
int m_iState;
|
||||
int m_iStateOld;
|
||||
float m_flDPS;
|
||||
string m_strLaserDest;
|
||||
string m_strBeamTex;
|
||||
string m_strEndTex;
|
||||
|
||||
public:
|
||||
void env_laser(void);
|
||||
|
||||
virtual void Save(float);
|
||||
virtual void Restore(string,string);
|
||||
virtual void SpawnKey(string,string);
|
||||
virtual void Respawn(void);
|
||||
virtual void LaserThink(void);
|
||||
virtual void Trigger(entity,int);
|
||||
virtual void EvaluateEntity(void);
|
||||
virtual float SendEntity(entity,float);
|
||||
|
||||
};
|
||||
|
||||
void
|
||||
env_laser::env_laser(void)
|
||||
{
|
||||
pvsflags = PVSF_IGNOREPVS;
|
||||
m_iState = 0i;
|
||||
m_iStateOld = 0i;
|
||||
m_flDPS = 0.0f;
|
||||
m_strLaserDest = __NULL__;
|
||||
m_strBeamTex = __NULL__;
|
||||
m_strEndTex = __NULL__;
|
||||
}
|
||||
|
||||
void
|
||||
env_laser::Save(float handle)
|
||||
{
|
||||
super::Save(handle);
|
||||
SaveInt(handle, "m_iState", m_iState);
|
||||
SaveInt(handle, "m_iStateOld", m_iStateOld);
|
||||
SaveFloat(handle, "m_flDPS", m_flDPS);
|
||||
SaveString(handle, "m_strLaserDest", m_strLaserDest);
|
||||
SaveString(handle, "m_strBeamTex", m_strBeamTex);
|
||||
SaveString(handle, "m_strEndTex", m_strEndTex);
|
||||
}
|
||||
|
||||
void
|
||||
env_laser::Restore(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "m_iState":
|
||||
m_iState = ReadInt(strValue);
|
||||
break;
|
||||
case "m_iStateOld":
|
||||
m_iStateOld = ReadInt(strValue);
|
||||
break;
|
||||
case "m_flDPS":
|
||||
m_flDPS = ReadFloat(strValue);
|
||||
break;
|
||||
case "m_strLaserDest":
|
||||
m_strLaserDest = ReadString(strValue);
|
||||
break;
|
||||
case "m_strBeamTex":
|
||||
m_strBeamTex = ReadString(strValue);
|
||||
break;
|
||||
case "m_strEndTex":
|
||||
m_strEndTex = ReadString(strValue);
|
||||
break;
|
||||
default:
|
||||
super::Restore(strKey, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
env_laser::SpawnKey(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "texture":
|
||||
m_strBeamTex = strValue;
|
||||
precache_model(m_strBeamTex);
|
||||
break;
|
||||
case "EndSprite":
|
||||
m_strEndTex = strValue;
|
||||
precache_model(m_strEndTex);
|
||||
break;
|
||||
case "LaserTarget":
|
||||
m_strLaserDest = strValue;
|
||||
break;
|
||||
case "damage":
|
||||
m_flDPS = stof(strValue);
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(strKey, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
env_laser::Respawn(void)
|
||||
{
|
||||
if (HasSpawnFlags(ENVLAZ_STARTON)) {
|
||||
m_iState = 1;
|
||||
ScheduleThink(LaserThink, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
env_laser::LaserThink(void)
|
||||
{
|
||||
entity t;
|
||||
|
||||
if (!m_iState) {
|
||||
return;
|
||||
} else {
|
||||
ScheduleThink(LaserThink, 0.1f);
|
||||
}
|
||||
|
||||
t = find(world, ::targetname, m_strLaserDest);
|
||||
SetAngles(t.origin);
|
||||
|
||||
if (!t) {
|
||||
print(sprintf("^1env_laser::^3LaserThink^7: %s has no valid target. Aborting\n", targetname));
|
||||
return;
|
||||
}
|
||||
|
||||
traceline(origin, t.origin, FALSE, this);
|
||||
|
||||
if (trace_ent.takedamage) {
|
||||
Damage_Apply(trace_ent, this, rint(m_flDPS), 0, DMG_GENERIC);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
env_laser::Trigger(entity act, int state)
|
||||
{
|
||||
switch (state) {
|
||||
case TRIG_OFF:
|
||||
m_iState = 0;
|
||||
break;
|
||||
case TRIG_ON:
|
||||
m_iState = 1;
|
||||
break;
|
||||
default:
|
||||
m_iState = 1 - m_iState;
|
||||
}
|
||||
|
||||
if (m_iState) {
|
||||
ScheduleThink(LaserThink, 0.0f);
|
||||
} else {
|
||||
ReleaseThink();
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
env_laser::SendEntity(entity ePEnt, float fChanged)
|
||||
{
|
||||
if (clienttype(ePEnt) != CLIENTTYPE_REAL) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
WriteByte(MSG_ENTITY, ENT_ENVLASER);
|
||||
WriteFloat(MSG_ENTITY, fChanged);
|
||||
|
||||
if (fChanged & ENVLASER_CHANGED_ORIGIN) {
|
||||
WriteCoord(MSG_ENTITY, origin[0]);
|
||||
WriteCoord(MSG_ENTITY, origin[1]);
|
||||
WriteCoord(MSG_ENTITY, origin[2]);
|
||||
}
|
||||
if (fChanged & ENVLASER_CHANGED_ANGLES) {
|
||||
WriteCoord(MSG_ENTITY, angles[0]);
|
||||
WriteCoord(MSG_ENTITY, angles[1]);
|
||||
WriteCoord(MSG_ENTITY, angles[2]);
|
||||
}
|
||||
if (fChanged & ENVLASER_CHANGED_TEXTURE) {
|
||||
WriteString(MSG_ENTITY, m_strBeamTex);
|
||||
}
|
||||
if (fChanged & ENVLASER_CHANGED_ENDTEXTURE) {
|
||||
WriteString(MSG_ENTITY, m_strEndTex);
|
||||
}
|
||||
if (fChanged & ENVLASER_CHANGED_STATE) {
|
||||
WriteByte(MSG_ENTITY, m_iState);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
env_laser::EvaluateEntity(void)
|
||||
{
|
||||
/* FIXME: Check our fields for networking */
|
||||
if (ATTR_CHANGED(angles)) {
|
||||
SetSendFlags(ENVLASER_CHANGED_ORIGIN);
|
||||
}
|
||||
if (ATTR_CHANGED(origin)) {
|
||||
SetSendFlags(ENVLASER_CHANGED_ANGLES);
|
||||
}
|
||||
if (m_iState != m_iStateOld) {
|
||||
SetSendFlags(ENVLASER_CHANGED_STATE);
|
||||
m_iStateOld = m_iState;
|
||||
}
|
||||
|
||||
SAVE_STATE(origin);
|
||||
SAVE_STATE(angles);
|
||||
}
|
|
@ -9,6 +9,7 @@ shared/func_friction.qc
|
|||
shared/env_beam.qc
|
||||
shared/env_sprite.qc
|
||||
shared/env_bubbles.qc
|
||||
shared/env_laser.qc
|
||||
shared/env_projectedtexture.qc
|
||||
shared/env_fog_controller.qc
|
||||
shared/light_dynamic.qc
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
|
||||
/*QUAKED env_beam (1 0 0) (-8 -8 -8) (8 8 8) BEAM_STARTON BEAM_TOGGLE BEAM_RANDOMSTRIKE BEAM_RING BEAM_STARTSPARKS BEAM_ENDSPARKS BEAM_DECAL BEAM_SHADESTART BEAM_SHADEEND
|
||||
This entity is incomplete. Purely stub.
|
||||
Controllable beam effect, akin to lightning. Also known as env_lightning.
|
||||
|
||||
-------- KEYS --------
|
||||
"targetname" : Name
|
||||
|
@ -26,17 +26,20 @@ This entity is incomplete. Purely stub.
|
|||
"life" : Lifetime of the beam in seconds.
|
||||
"StrikeTime" : Time in seconds before the beam reactivates.
|
||||
"damage" : Damage per second that's dealt when touching the inner beam.
|
||||
"texture" : Path to the sprite to use in place of a texture.
|
||||
"BoltWidth" : Thickness multiplier. 0-255 range.
|
||||
"NoiseAmplitude" : Amplitude multiplier. 0-255 range.
|
||||
|
||||
-------- SPAWNFLAGS --------
|
||||
BEAM_STARTON : Activate the beam at map start.
|
||||
BEAM_TOGGLE : Beam can now be toggled off, else StrikeTime + life keys take over.
|
||||
BEAM_RANDOMSTRIKE : Use variations in StrikeTime + life keys when set.
|
||||
BEAM_RING : TODO: Instead of a beam, two points will connect into a ring.
|
||||
BEAM_RING : Instead of a beam, two points will connect into a ring.
|
||||
BEAM_STARTSPARKS : TODO: Start of the beam will spark when set.
|
||||
BEAM_ENDSPARKS : TODO: End of the beam will spark when set.
|
||||
BEAM_DECAL : TODO: Presumably leaves decals when sparks hit a surface.
|
||||
BEAM_SHADESTART : TODO: Beam will fade towards the start point when set.
|
||||
BEAM_SHADEEND : TODO: Beam will fade towards the end point when set.
|
||||
BEAM_SHADESTART : Beam will fade towards the start point when set.
|
||||
BEAM_SHADEEND : Beam will fade towards the end point when set.
|
||||
|
||||
-------- TRIVIA --------
|
||||
This entity was introduced in Half-Life (1998).
|
||||
|
@ -44,14 +47,18 @@ This entity was introduced in Half-Life (1998).
|
|||
|
||||
enumflags
|
||||
{
|
||||
BEAM_CHANGED_ORIGIN,
|
||||
BEAM_CHANGED_SPRITE,
|
||||
BEAM_CHANGED_STARTPOS_X,
|
||||
BEAM_CHANGED_STARTPOS_Y,
|
||||
BEAM_CHANGED_STARTPOS_Z,
|
||||
BEAM_CHANGED_ENDPOS_X,
|
||||
BEAM_CHANGED_ENDPOS_Y,
|
||||
BEAM_CHANGED_ENDPOS_Z,
|
||||
BEAM_CHANGED_ACTIVE
|
||||
BEAM_CHANGED_ACTIVE,
|
||||
BEAM_CHANGED_FLAGS,
|
||||
BEAM_CHANGED_COLOR,
|
||||
BEAM_CHANGED_WIDTH,
|
||||
BEAM_CHANGED_AMPLITUDE
|
||||
};
|
||||
|
||||
enumflags
|
||||
|
@ -68,7 +75,7 @@ enumflags
|
|||
};
|
||||
|
||||
class
|
||||
env_beam:NSEntity
|
||||
env_beam:NSRenderableEntity
|
||||
{
|
||||
public:
|
||||
void env_beam(void);
|
||||
|
@ -92,6 +99,13 @@ private:
|
|||
PREDICTED_VECTOR(m_vecStartPos)
|
||||
PREDICTED_VECTOR(m_vecEndPos)
|
||||
PREDICTED_INT(m_iActive)
|
||||
PREDICTED_INT(m_iBeamFlags)
|
||||
PREDICTED_FLOAT(m_flBeamWidth)
|
||||
PREDICTED_FLOAT(m_flAmplitude)
|
||||
|
||||
/* visual fluff */
|
||||
string m_strTexture;
|
||||
PREDICTED_INT(m_iSpriteID)
|
||||
|
||||
#ifdef SERVER
|
||||
string m_strStartEnt;
|
||||
|
@ -113,6 +127,10 @@ env_beam::env_beam(void)
|
|||
m_flLifeTime = 0.0f;
|
||||
m_flStrikeTime = 0.0f;
|
||||
m_iDamage = 0i;
|
||||
m_iBeamFlags = 0i;
|
||||
|
||||
m_strTexture = __NULL__;
|
||||
m_flBeamWidth = 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -124,8 +142,14 @@ env_beam::Respawn(void)
|
|||
SetOrigin(GetSpawnOrigin());
|
||||
m_iValue = 0;
|
||||
|
||||
/* force us to precache the sprite model... and get a modelindex back */
|
||||
m_iSpriteID = getmodelindex(m_strTexture, false);
|
||||
|
||||
if (HasSpawnFlags(BEAM_STARTON))
|
||||
Trigger(this, TRIG_ON);
|
||||
|
||||
/* keep it simple */
|
||||
m_iBeamFlags = spawnflags | BEAM_SHADEEND;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -150,6 +174,18 @@ env_beam::SpawnKey(string strKey, string strValue)
|
|||
case "damage":
|
||||
m_iDamage = ReadInt(strValue);
|
||||
break;
|
||||
case "texture":
|
||||
m_strTexture = ReadString(strValue);
|
||||
break;
|
||||
case "BoltWidth":
|
||||
m_flBeamWidth = ReadFloat(strValue);
|
||||
break;
|
||||
case "NoiseAmplitude":
|
||||
m_flAmplitude = ReadFloat(strValue);
|
||||
break;
|
||||
case "rendercolor":
|
||||
m_vecRenderColor = ReadVector(strValue);
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(strValue, strKey);
|
||||
}
|
||||
|
@ -185,16 +221,13 @@ env_beam::LaunchBeam(void)
|
|||
if (HasSpawnFlags(BEAM_TOGGLE))
|
||||
return;
|
||||
|
||||
/* if we have a specific life time set */
|
||||
if (m_flLifeTime)
|
||||
lifetime = m_flLifeTime;
|
||||
else if (m_flStrikeTime) /* else, we'll just have to take the strike time */
|
||||
lifetime = m_flStrikeTime;
|
||||
|
||||
/* if lifetime is less or equal to 0, it's an infinite beam */
|
||||
if (lifetime <= 0.0f)
|
||||
if (m_flLifeTime <= 0.0f)
|
||||
return;
|
||||
|
||||
/* if we have a specific life time set */
|
||||
lifetime = m_flLifeTime;
|
||||
|
||||
if (HasSpawnFlags(BEAM_RANDOMSTRIKE))
|
||||
lifetime *= random();
|
||||
|
||||
|
@ -210,14 +243,6 @@ env_beam::EndBeam(void)
|
|||
m_iActive = 0i; /* beam is now active */
|
||||
striketime = m_flStrikeTime;
|
||||
|
||||
/* if the strike time is less or equal to 0, don't replay it */
|
||||
if (striketime <= 0.0f)
|
||||
return;
|
||||
|
||||
/* odd behaviour: don't re-strike if we have no life-time set? */
|
||||
if (m_flLifeTime <= 0.0f)
|
||||
return;
|
||||
|
||||
if (HasSpawnFlags(BEAM_RANDOMSTRIKE))
|
||||
striketime *= random();
|
||||
|
||||
|
@ -236,7 +261,7 @@ void
|
|||
env_beam::Trigger(entity act, int state)
|
||||
{
|
||||
/* if toggle isn't enabled, it can only ever get activated */
|
||||
if (HasSpawnFlags(BEAM_TOGGLE) == false) {
|
||||
if (m_flLifeTime > 0 && HasSpawnFlags(BEAM_TOGGLE) == false) {
|
||||
m_iValue = 1;
|
||||
} else {
|
||||
switch (state) {
|
||||
|
@ -294,15 +319,20 @@ env_beam::EvaluateEntity(void)
|
|||
}
|
||||
}
|
||||
|
||||
EVALUATE_FIELD(m_iSpriteID, BEAM_CHANGED_SPRITE)
|
||||
EVALUATE_VECTOR(m_vecStartPos, 0, BEAM_CHANGED_STARTPOS_X)
|
||||
EVALUATE_VECTOR(m_vecStartPos, 1, BEAM_CHANGED_STARTPOS_Y)
|
||||
EVALUATE_VECTOR(m_vecStartPos, 2, BEAM_CHANGED_STARTPOS_Z)
|
||||
|
||||
EVALUATE_VECTOR(m_vecEndPos, 0, BEAM_CHANGED_ENDPOS_X)
|
||||
EVALUATE_VECTOR(m_vecEndPos, 1, BEAM_CHANGED_ENDPOS_Y)
|
||||
EVALUATE_VECTOR(m_vecEndPos, 2, BEAM_CHANGED_ENDPOS_Z)
|
||||
|
||||
EVALUATE_FIELD(m_iActive, BEAM_CHANGED_ACTIVE)
|
||||
EVALUATE_FIELD(m_iBeamFlags, BEAM_CHANGED_FLAGS)
|
||||
EVALUATE_VECTOR(m_vecRenderColor, 0, BEAM_CHANGED_COLOR)
|
||||
EVALUATE_VECTOR(m_vecRenderColor, 1, BEAM_CHANGED_COLOR)
|
||||
EVALUATE_VECTOR(m_vecRenderColor, 2, BEAM_CHANGED_COLOR)
|
||||
EVALUATE_FIELD(m_flBeamWidth, BEAM_CHANGED_WIDTH)
|
||||
EVALUATE_FIELD(m_flAmplitude, BEAM_CHANGED_AMPLITUDE)
|
||||
}
|
||||
|
||||
float
|
||||
|
@ -311,6 +341,7 @@ env_beam::SendEntity(entity ePEnt, float flChanged)
|
|||
WriteByte(MSG_ENTITY, ENT_BEAM);
|
||||
WriteFloat(MSG_ENTITY, flChanged);
|
||||
|
||||
SENDENTITY_INT(m_iSpriteID, BEAM_CHANGED_SPRITE)
|
||||
SENDENTITY_COORD(m_vecStartPos[0], BEAM_CHANGED_STARTPOS_X)
|
||||
SENDENTITY_COORD(m_vecStartPos[1], BEAM_CHANGED_STARTPOS_Y)
|
||||
SENDENTITY_COORD(m_vecStartPos[2], BEAM_CHANGED_STARTPOS_Z)
|
||||
|
@ -318,6 +349,12 @@ env_beam::SendEntity(entity ePEnt, float flChanged)
|
|||
SENDENTITY_COORD(m_vecEndPos[1], BEAM_CHANGED_ENDPOS_Y)
|
||||
SENDENTITY_COORD(m_vecEndPos[2], BEAM_CHANGED_ENDPOS_Z)
|
||||
SENDENTITY_BYTE(m_iActive, BEAM_CHANGED_ACTIVE)
|
||||
SENDENTITY_BYTE(m_iBeamFlags, BEAM_CHANGED_FLAGS)
|
||||
SENDENTITY_BYTE(m_vecRenderColor[0], BEAM_CHANGED_COLOR)
|
||||
SENDENTITY_BYTE(m_vecRenderColor[1], BEAM_CHANGED_COLOR)
|
||||
SENDENTITY_BYTE(m_vecRenderColor[2], BEAM_CHANGED_COLOR)
|
||||
SENDENTITY_BYTE(m_flBeamWidth, BEAM_CHANGED_WIDTH)
|
||||
SENDENTITY_BYTE(m_flAmplitude, BEAM_CHANGED_AMPLITUDE)
|
||||
|
||||
//print(sprintf("S (%x): %v %v %i\n", flChanged, m_vecStartPos, m_vecEndPos, m_iActive));
|
||||
|
||||
|
@ -327,6 +364,7 @@ env_beam::SendEntity(entity ePEnt, float flChanged)
|
|||
void
|
||||
env_beam::ReceiveEntity(float flNew, float flChanged)
|
||||
{
|
||||
READENTITY_INT(m_iSpriteID, BEAM_CHANGED_SPRITE)
|
||||
READENTITY_COORD(m_vecStartPos[0], BEAM_CHANGED_STARTPOS_X)
|
||||
READENTITY_COORD(m_vecStartPos[1], BEAM_CHANGED_STARTPOS_Y)
|
||||
READENTITY_COORD(m_vecStartPos[2], BEAM_CHANGED_STARTPOS_Z)
|
||||
|
@ -334,14 +372,58 @@ env_beam::ReceiveEntity(float flNew, float flChanged)
|
|||
READENTITY_COORD(m_vecEndPos[1], BEAM_CHANGED_ENDPOS_Y)
|
||||
READENTITY_COORD(m_vecEndPos[2], BEAM_CHANGED_ENDPOS_Z)
|
||||
READENTITY_BYTE(m_iActive, BEAM_CHANGED_ACTIVE)
|
||||
READENTITY_BYTE(m_iBeamFlags, BEAM_CHANGED_FLAGS)
|
||||
READENTITY_BYTE(m_vecRenderColor[0], BEAM_CHANGED_COLOR)
|
||||
READENTITY_BYTE(m_vecRenderColor[1], BEAM_CHANGED_COLOR)
|
||||
READENTITY_BYTE(m_vecRenderColor[2], BEAM_CHANGED_COLOR)
|
||||
READENTITY_BYTE(m_flBeamWidth, BEAM_CHANGED_WIDTH)
|
||||
READENTITY_BYTE(m_flAmplitude, BEAM_CHANGED_AMPLITUDE)
|
||||
|
||||
//print(sprintf("R (%x): %v %v %i\n", flChanged, m_vecStartPos, m_vecEndPos, m_iActive));
|
||||
|
||||
drawmask = MASK_ENGINE;
|
||||
setsize(this, [0,0,0], [0,0,0]);
|
||||
setorigin(this, m_vecStartPos);
|
||||
|
||||
/* the sprite has changed, we need to query a new texture */
|
||||
if (flChanged & BEAM_CHANGED_SPRITE) {
|
||||
m_strTexture = spriteframe(modelnameforindex(m_iSpriteID), 0, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
#define BEAM_COUNT 16
|
||||
float
|
||||
pseudorand(float input)
|
||||
{
|
||||
float seed = (float)input % 5.0f;
|
||||
seed += (float)input % 8.0f;
|
||||
seed += (float)input % 4.0f;
|
||||
seed += (float)input % 13.0f;
|
||||
seed += (float)input % 70.0f;
|
||||
|
||||
/* like the engine its random(), never return 0, never return 1 */
|
||||
return bound(0.01, (seed) / 100.0f, 0.99f);
|
||||
}
|
||||
|
||||
static float env_beam_jitlut[BEAM_COUNT] = {
|
||||
0.000000,
|
||||
0.195090,
|
||||
0.382683,
|
||||
0.555570,
|
||||
0.707106,
|
||||
0.831469,
|
||||
0.923879,
|
||||
0.980785,
|
||||
1.000000,
|
||||
0.980786,
|
||||
0.923880,
|
||||
0.831471,
|
||||
0.707108,
|
||||
0.555572,
|
||||
0.382685,
|
||||
0.000000,
|
||||
};
|
||||
|
||||
float
|
||||
env_beam::predraw(void)
|
||||
{
|
||||
|
@ -349,11 +431,77 @@ env_beam::predraw(void)
|
|||
if (!m_iActive)
|
||||
return;
|
||||
|
||||
if (autocvar(r_skipBeams, 0))
|
||||
return;
|
||||
|
||||
/* primitive representation */
|
||||
#if 0
|
||||
R_BeginPolygon("", 0, 0);
|
||||
R_PolygonVertex(m_vecStartPos, [0,1], [0,1,0], 1.0f);
|
||||
R_PolygonVertex(m_vecEndPos, [1,1], [0,1,0], 1.0f);
|
||||
R_EndPolygon();
|
||||
#endif
|
||||
|
||||
if (m_strTexture) {
|
||||
float last_progression = 0.0f;
|
||||
makevectors(g_view.GetCameraAngle());
|
||||
setproperty(VF_ORIGIN, pSeat->m_vecPredictedOrigin);
|
||||
R_BeginPolygon(m_strTexture, DRAWFLAG_ADDITIVE, 0);
|
||||
|
||||
for (float i = 0; i < BEAM_COUNT; i++) {
|
||||
float progression = (i / (BEAM_COUNT-1));
|
||||
vector point;
|
||||
vector jitter;
|
||||
float strength;
|
||||
float a = 1.0f;
|
||||
|
||||
/* our steps from a - b */
|
||||
if (m_iBeamFlags & BEAM_RING) {
|
||||
vector center = m_vecStartPos - (m_vecStartPos - m_vecEndPos) * 0.5f;
|
||||
float length = vlen(m_vecStartPos - m_vecEndPos) * 0.5;
|
||||
|
||||
float theta = 2.0f * M_PI * (i / (BEAM_COUNT-1));
|
||||
vector p = [sin(theta), cos(theta)] * length;
|
||||
|
||||
point = center + p;
|
||||
} else {
|
||||
point[0] = Math_Lerp(m_vecStartPos[0], m_vecEndPos[0], progression);
|
||||
point[1] = Math_Lerp(m_vecStartPos[1], m_vecEndPos[1], progression);
|
||||
point[2] = Math_Lerp(m_vecStartPos[2], m_vecEndPos[2], progression);
|
||||
}
|
||||
|
||||
/* get the direction the beam is 'looking' */
|
||||
makevectors(vectoangles(m_vecEndPos - m_vecStartPos));
|
||||
|
||||
/* nudge it a lil bit up/down left/right from its trajectory */
|
||||
/* these are all randomly chosen constants */
|
||||
jitter = v_right * (pseudorand((4 * time) + i + entnum) - 0.5);
|
||||
jitter += v_up * (pseudorand((4 * time) + i + 64.12 + entnum) - 0.5);
|
||||
jitter += v_right * (pseudorand(100 + (8 * time) + i + entnum) - 0.5);
|
||||
jitter += v_up * (pseudorand(100 + (8 * time) + i + 25.4 + entnum) - 0.5);
|
||||
jitter *= m_flAmplitude;
|
||||
|
||||
/* start/end points get less jittery the closer we get*/
|
||||
jitter *= env_beam_jitlut[i];
|
||||
|
||||
/* apply jitter */
|
||||
point += jitter;
|
||||
|
||||
/* fading flag stuff */
|
||||
if ((i == 0 && m_iBeamFlags & BEAM_SHADESTART) ||
|
||||
(i == BEAM_COUNT && m_iBeamFlags & BEAM_SHADEEND))
|
||||
a = 0.0f;
|
||||
|
||||
R_PolygonVertex(point, [1, 0], m_vecRenderColor / 255, a);
|
||||
|
||||
if (autocvar(cl_showoff, 0))
|
||||
dynamiclight_add(point, 150, m_vecRenderColor/255);
|
||||
|
||||
last_progression = progression;
|
||||
}
|
||||
|
||||
R_EndPolygonRibbon(m_flBeamWidth/8, [-1,0]);
|
||||
}
|
||||
|
||||
return (PREDRAW_NEXT);
|
||||
}
|
||||
|
|
413
src/gs-entbase/shared/env_laser.qc
Normal file
413
src/gs-entbase/shared/env_laser.qc
Normal file
|
@ -0,0 +1,413 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2022 Vera Visions LLC.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*QUAKED env_laser (1 0 0) (-8 -8 -8) (8 8 8) LASER_STARTON x x x LASER_STARTSPARKS LASER_ENDSPARKS LASER_DECAL
|
||||
Controllable laser effect. More or less a stripped-down version of env_beam.
|
||||
|
||||
-------- KEYS --------
|
||||
"targetname" : Name
|
||||
"LaserTarget" : Targetname of the entity that acts as end point for the laser.
|
||||
"damage" : Damage per second that's dealt when touching the inner laser.
|
||||
"texture" : Path to the sprite to use in place of a texture.
|
||||
"BoltWidth" : Thickness multiplier. 0-255 range.
|
||||
"NoiseAmplitude" : Amplitude multiplier. 0-255 range.
|
||||
|
||||
-------- SPAWNFLAGS --------
|
||||
LASER_STARTON : Activate the laser at map start.
|
||||
LASER_STARTSPARKS :Start of the laser will spark when set.
|
||||
LASER_ENDSPARKS : End of the laser will spark when set.
|
||||
LASER_DECAL : TODO: Presumably leaves decals when sparks hit a surface.
|
||||
|
||||
-------- TRIVIA --------
|
||||
This entity was introduced in Half-Life (1998).
|
||||
*/
|
||||
|
||||
enumflags
|
||||
{
|
||||
LASER_CHANGED_SPRITE,
|
||||
LASER_CHANGED_STARTPOS_X,
|
||||
LASER_CHANGED_STARTPOS_Y,
|
||||
LASER_CHANGED_STARTPOS_Z,
|
||||
LASER_CHANGED_ENDPOS_X,
|
||||
LASER_CHANGED_ENDPOS_Y,
|
||||
LASER_CHANGED_ENDPOS_Z,
|
||||
LASER_CHANGED_ACTIVE,
|
||||
LASER_CHANGED_FLAGS,
|
||||
LASER_CHANGED_COLOR,
|
||||
LASER_CHANGED_WIDTH,
|
||||
LASER_CHANGED_AMPLITUDE
|
||||
};
|
||||
|
||||
enumflags
|
||||
{
|
||||
LASER_STARTON,
|
||||
LASER_UNUSED1,
|
||||
LASER_UNUSED2,
|
||||
LASER_UNUSED3,
|
||||
LASER_STARTSPARKS,
|
||||
LASER_ENDSPARKS,
|
||||
LASER_DECAL
|
||||
};
|
||||
|
||||
class
|
||||
env_laser:NSRenderableEntity
|
||||
{
|
||||
public:
|
||||
void env_laser(void);
|
||||
|
||||
#ifdef SERVER
|
||||
virtual void Respawn(void);
|
||||
virtual void SpawnKey(string,string);
|
||||
virtual void EvaluateEntity(void);
|
||||
virtual float SendEntity(entity,float);
|
||||
virtual void Trigger(entity,int);
|
||||
nonvirtual void CastLaser(void);
|
||||
#else
|
||||
virtual float predraw(void);
|
||||
virtual void ReceiveEntity(float,float);
|
||||
#endif
|
||||
|
||||
private:
|
||||
PREDICTED_VECTOR(m_vecEndPos)
|
||||
PREDICTED_INT(m_iActive)
|
||||
PREDICTED_INT(m_iBeamFlags)
|
||||
PREDICTED_FLOAT(m_flBeamWidth)
|
||||
PREDICTED_FLOAT(m_flAmplitude)
|
||||
|
||||
/* visual fluff */
|
||||
string m_strTexture;
|
||||
PREDICTED_INT(m_iSpriteID)
|
||||
|
||||
#ifdef SERVER
|
||||
string m_strEndEnt;
|
||||
float m_iDamage;
|
||||
float m_flTraceTime;
|
||||
#else
|
||||
float m_flSparkTime;
|
||||
#endif
|
||||
};
|
||||
|
||||
void
|
||||
env_laser::env_laser(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
m_strEndEnt = __NULL__;
|
||||
m_iDamage = 0i;
|
||||
m_iBeamFlags = 0i;
|
||||
|
||||
m_strTexture = __NULL__;
|
||||
m_flBeamWidth = 4.0f;
|
||||
#else
|
||||
m_flSparkTime = 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
env_laser::Respawn(void)
|
||||
{
|
||||
SetSize([0,0,0], [0,0,0]);
|
||||
SetOrigin(GetSpawnOrigin());
|
||||
m_iValue = 0;
|
||||
|
||||
/* force us to precache the sprite model... and get a modelindex back */
|
||||
m_iSpriteID = getmodelindex(m_strTexture, false);
|
||||
|
||||
if (HasSpawnFlags(LASER_STARTON))
|
||||
Trigger(this, TRIG_ON);
|
||||
|
||||
/* keep it simple */
|
||||
m_iBeamFlags = spawnflags;
|
||||
}
|
||||
|
||||
void
|
||||
env_laser::SpawnKey(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "LaserTarget":
|
||||
m_strEndEnt = ReadString(strValue);
|
||||
break;
|
||||
case "damage":
|
||||
m_iDamage = ReadInt(strValue);
|
||||
break;
|
||||
case "texture":
|
||||
m_strTexture = ReadString(strValue);
|
||||
break;
|
||||
case "BoltWidth":
|
||||
m_flBeamWidth = ReadFloat(strValue);
|
||||
break;
|
||||
case "NoiseAmplitude":
|
||||
m_flAmplitude = ReadFloat(strValue);
|
||||
break;
|
||||
case "rendercolor":
|
||||
m_vecRenderColor = ReadVector(strValue);
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(strValue, strKey);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
env_laser::CastLaser(void)
|
||||
{
|
||||
traceline(origin, m_vecEndPos, MOVE_NORMAL, this);
|
||||
|
||||
if (trace_fraction >= 1.0)
|
||||
return;
|
||||
|
||||
if (trace_ent.takedamage == DAMAGE_NO)
|
||||
return;
|
||||
|
||||
Damage_Apply(trace_ent, this, m_iDamage, 0, DMG_ELECTRO);
|
||||
m_flTraceTime = time + 1.0f;
|
||||
}
|
||||
|
||||
void
|
||||
env_laser::Trigger(entity act, int state)
|
||||
{
|
||||
switch (state) {
|
||||
case TRIG_OFF:
|
||||
m_iValue = 0;
|
||||
break;
|
||||
case TRIG_ON:
|
||||
m_iValue = 1;
|
||||
break;
|
||||
default:
|
||||
m_iValue = 1 - m_iValue;
|
||||
}
|
||||
|
||||
m_iActive = m_iValue;
|
||||
}
|
||||
|
||||
void
|
||||
env_laser::EvaluateEntity(void)
|
||||
{
|
||||
entity eFind;
|
||||
|
||||
/* only bother updating our start/end pos if we're running */
|
||||
if (m_iActive) {
|
||||
m_vecEndPos = origin;
|
||||
|
||||
if (m_strEndEnt) {
|
||||
eFind = find(world, ::targetname, m_strEndEnt);
|
||||
|
||||
if (eFind) {
|
||||
m_vecEndPos = eFind.origin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_flTraceTime < time) {
|
||||
CastLaser();
|
||||
}
|
||||
|
||||
traceline(origin, m_vecEndPos, MOVE_NORMAL, this);
|
||||
m_vecEndPos = trace_endpos;
|
||||
|
||||
EVALUATE_FIELD(m_iSpriteID, LASER_CHANGED_SPRITE)
|
||||
EVALUATE_VECTOR(origin, 0, LASER_CHANGED_STARTPOS_X)
|
||||
EVALUATE_VECTOR(origin, 1, LASER_CHANGED_STARTPOS_Y)
|
||||
EVALUATE_VECTOR(origin, 2, LASER_CHANGED_STARTPOS_Z)
|
||||
EVALUATE_VECTOR(m_vecEndPos, 0, LASER_CHANGED_ENDPOS_X)
|
||||
EVALUATE_VECTOR(m_vecEndPos, 1, LASER_CHANGED_ENDPOS_Y)
|
||||
EVALUATE_VECTOR(m_vecEndPos, 2, LASER_CHANGED_ENDPOS_Z)
|
||||
EVALUATE_FIELD(m_iActive, LASER_CHANGED_ACTIVE)
|
||||
EVALUATE_FIELD(m_iBeamFlags, LASER_CHANGED_FLAGS)
|
||||
EVALUATE_VECTOR(m_vecRenderColor, 0, LASER_CHANGED_COLOR)
|
||||
EVALUATE_VECTOR(m_vecRenderColor, 1, LASER_CHANGED_COLOR)
|
||||
EVALUATE_VECTOR(m_vecRenderColor, 2, LASER_CHANGED_COLOR)
|
||||
EVALUATE_FIELD(m_flBeamWidth, LASER_CHANGED_WIDTH)
|
||||
EVALUATE_FIELD(m_flAmplitude, LASER_CHANGED_AMPLITUDE)
|
||||
}
|
||||
|
||||
float
|
||||
env_laser::SendEntity(entity ePEnt, float flChanged)
|
||||
{
|
||||
WriteByte(MSG_ENTITY, ENT_LASER);
|
||||
WriteFloat(MSG_ENTITY, flChanged);
|
||||
|
||||
SENDENTITY_INT(m_iSpriteID, LASER_CHANGED_SPRITE)
|
||||
SENDENTITY_COORD(origin[0], LASER_CHANGED_STARTPOS_X)
|
||||
SENDENTITY_COORD(origin[1], LASER_CHANGED_STARTPOS_Y)
|
||||
SENDENTITY_COORD(origin[2], LASER_CHANGED_STARTPOS_Z)
|
||||
SENDENTITY_COORD(m_vecEndPos[0], LASER_CHANGED_ENDPOS_X)
|
||||
SENDENTITY_COORD(m_vecEndPos[1], LASER_CHANGED_ENDPOS_Y)
|
||||
SENDENTITY_COORD(m_vecEndPos[2], LASER_CHANGED_ENDPOS_Z)
|
||||
SENDENTITY_BYTE(m_iActive, LASER_CHANGED_ACTIVE)
|
||||
SENDENTITY_BYTE(m_iBeamFlags, LASER_CHANGED_FLAGS)
|
||||
SENDENTITY_BYTE(m_vecRenderColor[0], LASER_CHANGED_COLOR)
|
||||
SENDENTITY_BYTE(m_vecRenderColor[1], LASER_CHANGED_COLOR)
|
||||
SENDENTITY_BYTE(m_vecRenderColor[2], LASER_CHANGED_COLOR)
|
||||
SENDENTITY_BYTE(m_flBeamWidth, LASER_CHANGED_WIDTH)
|
||||
SENDENTITY_BYTE(m_flAmplitude, LASER_CHANGED_AMPLITUDE)
|
||||
|
||||
//print(sprintf("S (%x): %v %v %i\n", flChanged, origin, m_vecEndPos, m_iActive));
|
||||
|
||||
return (1);
|
||||
}
|
||||
#else
|
||||
void
|
||||
env_laser::ReceiveEntity(float flNew, float flChanged)
|
||||
{
|
||||
READENTITY_INT(m_iSpriteID, LASER_CHANGED_SPRITE)
|
||||
READENTITY_COORD(origin[0], LASER_CHANGED_STARTPOS_X)
|
||||
READENTITY_COORD(origin[1], LASER_CHANGED_STARTPOS_Y)
|
||||
READENTITY_COORD(origin[2], LASER_CHANGED_STARTPOS_Z)
|
||||
READENTITY_COORD(m_vecEndPos[0], LASER_CHANGED_ENDPOS_X)
|
||||
READENTITY_COORD(m_vecEndPos[1], LASER_CHANGED_ENDPOS_Y)
|
||||
READENTITY_COORD(m_vecEndPos[2], LASER_CHANGED_ENDPOS_Z)
|
||||
READENTITY_BYTE(m_iActive, LASER_CHANGED_ACTIVE)
|
||||
READENTITY_BYTE(m_iBeamFlags, LASER_CHANGED_FLAGS)
|
||||
READENTITY_BYTE(m_vecRenderColor[0], LASER_CHANGED_COLOR)
|
||||
READENTITY_BYTE(m_vecRenderColor[1], LASER_CHANGED_COLOR)
|
||||
READENTITY_BYTE(m_vecRenderColor[2], LASER_CHANGED_COLOR)
|
||||
READENTITY_BYTE(m_flBeamWidth, LASER_CHANGED_WIDTH)
|
||||
READENTITY_BYTE(m_flAmplitude, LASER_CHANGED_AMPLITUDE)
|
||||
|
||||
//print(sprintf("R (%x): %v %v %i\n", flChanged, origin, m_vecEndPos, m_iActive));
|
||||
|
||||
drawmask = MASK_ENGINE;
|
||||
setsize(this, [0,0,0], [0,0,0]);
|
||||
setorigin(this, origin);
|
||||
|
||||
/* the sprite has changed, we need to query a new texture */
|
||||
if (flChanged & LASER_CHANGED_SPRITE) {
|
||||
m_strTexture = spriteframe(modelnameforindex(m_iSpriteID), 0, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
#define LASER_COUNT 16
|
||||
|
||||
void FX_Spark(vector pos, vector ang);
|
||||
|
||||
static float env_laser_jitlut[LASER_COUNT] = {
|
||||
0.000000,
|
||||
0.195090,
|
||||
0.382683,
|
||||
0.555570,
|
||||
0.707106,
|
||||
0.831469,
|
||||
0.923879,
|
||||
0.980785,
|
||||
1.000000,
|
||||
0.980786,
|
||||
0.923880,
|
||||
0.831471,
|
||||
0.707108,
|
||||
0.555572,
|
||||
0.382685,
|
||||
0.000000,
|
||||
};
|
||||
|
||||
float
|
||||
env_laser::predraw(void)
|
||||
{
|
||||
/* only draw when active. */
|
||||
if (!m_iActive)
|
||||
return;
|
||||
|
||||
if (autocvar(r_skipBeams, 0))
|
||||
return;
|
||||
|
||||
/* primitive representation */
|
||||
#if 0
|
||||
R_BeginPolygon("", 0, 0);
|
||||
R_PolygonVertex(origin, [0,1], [0,1,0], 1.0f);
|
||||
R_PolygonVertex(m_vecEndPos, [1,1], [0,1,0], 1.0f);
|
||||
R_EndPolygon();
|
||||
#endif
|
||||
|
||||
if (m_strTexture) {
|
||||
float last_progression = 0.0f;
|
||||
makevectors(g_view.GetCameraAngle());
|
||||
setproperty(VF_ORIGIN, pSeat->m_vecPredictedOrigin);
|
||||
R_BeginPolygon(m_strTexture, DRAWFLAG_ADDITIVE, 0);
|
||||
|
||||
for (float i = 0; i < LASER_COUNT; i++) {
|
||||
float progression = (i / (LASER_COUNT-1));
|
||||
vector point;
|
||||
vector jitter;
|
||||
float strength;
|
||||
float a = 1.0f;
|
||||
|
||||
/* our steps from a - b */
|
||||
point[0] = Math_Lerp(origin[0], m_vecEndPos[0], progression);
|
||||
point[1] = Math_Lerp(origin[1], m_vecEndPos[1], progression);
|
||||
point[2] = Math_Lerp(origin[2], m_vecEndPos[2], progression);
|
||||
|
||||
/* get the direction the laser is 'looking' */
|
||||
makevectors(vectoangles(m_vecEndPos - origin));
|
||||
|
||||
/* nudge it a lil bit up/down left/right from its trajectory */
|
||||
/* these are all randomly chosen constants */
|
||||
jitter = v_right * (pseudorand((4 * time) + i + entnum) - 0.5);
|
||||
jitter += v_up * (pseudorand((4 * time) + i + 64.12 + entnum) - 0.5);
|
||||
jitter += v_right * (pseudorand(100 + (8 * time) + i + entnum) - 0.5);
|
||||
jitter += v_up * (pseudorand(100 + (8 * time) + i + 25.4 + entnum) - 0.5);
|
||||
jitter *= m_flAmplitude;
|
||||
|
||||
/* start/end points get less jittery the closer we get*/
|
||||
jitter *= env_laser_jitlut[i];
|
||||
|
||||
/* apply jitter */
|
||||
point += jitter;
|
||||
|
||||
R_PolygonVertex(point, [1, 0], m_vecRenderColor / 255, a);
|
||||
|
||||
if (autocvar(cl_showoff, 0))
|
||||
dynamiclight_add(point, 150, m_vecRenderColor/255);
|
||||
|
||||
last_progression = progression;
|
||||
}
|
||||
|
||||
R_EndPolygonRibbon(m_flBeamWidth/8, [-1,0]);
|
||||
}
|
||||
|
||||
if (m_flSparkTime > time)
|
||||
return (PREDRAW_NEXT);
|
||||
|
||||
if (m_iBeamFlags & (LASER_STARTSPARKS)) {
|
||||
vector dir = vectoangles(origin - m_vecEndPos);
|
||||
makevectors(dir);
|
||||
FX_Spark(origin, -v_forward);
|
||||
}
|
||||
|
||||
if (m_iBeamFlags & (LASER_ENDSPARKS)) {
|
||||
vector dir2 = vectoangles(m_vecEndPos - origin);
|
||||
|
||||
makevectors(dir2);
|
||||
FX_Spark(m_vecEndPos, -v_forward);
|
||||
}
|
||||
|
||||
m_flSparkTime = time + 0.25f;
|
||||
|
||||
return (PREDRAW_NEXT);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CLIENT
|
||||
void
|
||||
env_laser_ReadEntity(float isnew)
|
||||
{
|
||||
env_laser laser = (env_laser)self;
|
||||
float changedflags = readfloat();
|
||||
|
||||
if (isnew)
|
||||
spawnfunc_env_laser();
|
||||
|
||||
laser.ReceiveEntity(isnew, changedflags);
|
||||
}
|
||||
#endif
|
|
@ -31,7 +31,7 @@ enum
|
|||
ENT_DLIGHT,
|
||||
ENT_PROJECTEDTEXTURE,
|
||||
ENT_FOGCONTROLLER,
|
||||
ENT_ENVLASER,
|
||||
ENT_LASER,
|
||||
ENT_PARTSYSTEM,
|
||||
ENT_SPRITE,
|
||||
ENT_SPRAY,
|
||||
|
|
Loading…
Reference in a new issue