nuclide/src/gs-entbase/shared/env_sprite.qc

350 lines
9.1 KiB
Plaintext

/*
* 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.
*/
enumflags
{
SPRITE_CHANGED_ORIGIN,
SPRITE_CHANGED_MODELINDEX,
SPRITE_CHANGED_FRAMERATE,
SPRITE_CHANGED_SCALE,
SPRITE_CHANGED_RENDERMODE,
SPRITE_CHANGED_RENDERFX,
SPRITE_CHANGED_RENDERCOLOR,
SPRITE_CHANGED_RENDERAMT,
SPRITE_CHANGED_MATERIAL,
};
enumflags
{
ENVS_STARTON,
ENVS_PLAYONCE
};
/*!QUAKED env_sprite (1 .5 0) (-8 -8 -8) (8 8 8) ENVS_STARTON ENVS_PLAYONCE
# OVERVIEW
A sprite entity manager with fancy overrides.
# KEYS
- "targetname" : Name
- "target" : Target when triggered.
- "killtarget" : Target to kill when triggered.
- "angles" : Sets the pitch, yaw and roll angles of the sprite.
- "model" : Path to the sprite in question.
- "material" : Instead of model, you can set the path of a material/image here.
- "rendercolor" : Color modifier of the sprite.
- "renderamt" : Alpha modifier of the sprite.
- "rendermode" : Render mode of the sprite.
- "framerate" : Rate between frames in seconds.
- "scale" : Scale modifier of the sprite.
# SPAWNFLAGS
- ENVS_STARTON (1) : Start visible.
- ENVS_PLAYONCE (2) : Play once from start to finish, then make invisible.
# NOTES
Only used with an external sprite format, like SPR, SPRHL and SPR32.
# TRIVIA
This entity was introduced in Half-Life (1998).
*/
class env_sprite:NSRenderableEntity
{
public:
void env_sprite(void);
virtual void(bool) SetFramerate;
#ifdef SERVER
virtual void Spawned(void);
virtual void Trigger(entity, triggermode_t);
virtual void EvaluateEntity(void);
virtual float SendEntity(entity,float);
virtual void SpawnKey(string,string);
virtual void NetworkOnce(void);
#else
virtual float predraw(void);
virtual void think(void);
virtual void ReceiveEntity(float,float);
virtual void SetMaxFrame(int);
virtual void SetLoopFlag(bool);
#endif
private:
bool m_iIsShader;
int m_iToggled;
float m_flEffects;
NETWORKED_STRING(m_strMaterial)
NETWORKED_FLOAT(m_flFramerate)
#ifdef CLIENT
int m_iMaxFrame;
bool m_bLoops;
#endif
};
void
env_sprite::env_sprite(void)
{
NETWORKED_DEFAULT(m_strMaterial, __NULL__)
NETWORKED_DEFAULT(m_flFramerate, 10.0f)
NETWORKED_DEFAULT(scale, 1.0f)
m_iIsShader = false;
}
#ifdef SERVER
void
env_sprite::EvaluateEntity(void)
{
EVALUATE_VECTOR(origin, 0, SPRITE_CHANGED_ORIGIN)
EVALUATE_VECTOR(origin, 1, SPRITE_CHANGED_ORIGIN)
EVALUATE_VECTOR(origin, 2, SPRITE_CHANGED_ORIGIN)
EVALUATE_FIELD(modelindex, SPRITE_CHANGED_MODELINDEX)
EVALUATE_FIELD(m_flFramerate, SPRITE_CHANGED_FRAMERATE)
EVALUATE_FIELD(scale, SPRITE_CHANGED_SCALE)
EVALUATE_FIELD(m_iRenderMode, SPRITE_CHANGED_RENDERMODE)
EVALUATE_FIELD(m_iRenderFX, SPRITE_CHANGED_RENDERFX)
EVALUATE_VECTOR(m_vecRenderColor, 0, SPRITE_CHANGED_RENDERCOLOR)
EVALUATE_VECTOR(m_vecRenderColor, 1, SPRITE_CHANGED_RENDERCOLOR)
EVALUATE_VECTOR(m_vecRenderColor, 2, SPRITE_CHANGED_RENDERCOLOR)
EVALUATE_FIELD(m_flRenderAmt, SPRITE_CHANGED_RENDERAMT)
EVALUATE_FIELD(m_strMaterial, SPRITE_CHANGED_MATERIAL)
}
float
env_sprite::SendEntity(entity ePEnt, float flChanged)
{
if (clienttype(ePEnt) != CLIENTTYPE_REAL)
return (0);
if (HasSpawnFlags(ENVS_PLAYONCE))
return (0);
/* Delete it on the client. */
if (m_iToggled == FALSE)
return (0);
/* strings are expensive. */
if (!m_strMaterial)
flChanged &= ~SPRITE_CHANGED_MATERIAL;
WriteByte(MSG_ENTITY, ENT_SPRITE);
WriteFloat(MSG_ENTITY, flChanged);
SENDENTITY_COORD(origin[0], SPRITE_CHANGED_ORIGIN)
SENDENTITY_COORD(origin[1], SPRITE_CHANGED_ORIGIN)
SENDENTITY_COORD(origin[2], SPRITE_CHANGED_ORIGIN)
SENDENTITY_FLOAT(modelindex, SPRITE_CHANGED_MODELINDEX)
SENDENTITY_FLOAT(m_flFramerate, SPRITE_CHANGED_FRAMERATE)
SENDENTITY_FLOAT(scale, SPRITE_CHANGED_SCALE)
SENDENTITY_BYTE(m_iRenderMode, SPRITE_CHANGED_RENDERMODE)
SENDENTITY_BYTE(m_iRenderFX, SPRITE_CHANGED_RENDERFX)
SENDENTITY_COLOR(m_vecRenderColor[0], SPRITE_CHANGED_RENDERCOLOR)
SENDENTITY_COLOR(m_vecRenderColor[1], SPRITE_CHANGED_RENDERCOLOR)
SENDENTITY_COLOR(m_vecRenderColor[2], SPRITE_CHANGED_RENDERCOLOR)
SENDENTITY_COLOR(m_flRenderAmt, SPRITE_CHANGED_RENDERAMT)
SENDENTITY_STRING(m_strMaterial, SPRITE_CHANGED_MATERIAL)
return (1);
}
void
env_sprite::NetworkOnce(void)
{
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_SPRITE);
WriteCoord(MSG_MULTICAST, origin[0]);
WriteCoord(MSG_MULTICAST, origin[1]);
WriteCoord(MSG_MULTICAST, origin[2]);
WriteFloat(MSG_MULTICAST, modelindex);
WriteFloat(MSG_MULTICAST, m_flFramerate);
WriteFloat(MSG_MULTICAST, scale);
WriteByte(MSG_MULTICAST, m_iRenderMode);
WriteByte(MSG_MULTICAST, m_iRenderFX);
WriteFloat(MSG_MULTICAST, m_vecRenderColor[0]);
WriteFloat(MSG_MULTICAST, m_vecRenderColor[1]);
WriteFloat(MSG_MULTICAST, m_vecRenderColor[2]);
WriteFloat(MSG_MULTICAST, m_flRenderAmt);
WriteString(MSG_MULTICAST, m_strMaterial);
msg_entity = this;
multicast(origin, MULTICAST_PVS);
}
/* TODO: Implement state */
void
env_sprite::Trigger(entity act, triggermode_t state)
{
if (HasSpawnFlags(ENVS_PLAYONCE)) {
NetworkOnce();
} else {
m_iToggled = 1 - m_iToggled;
SendFlags = 1;
}
}
void
env_sprite::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "shader":
case "material":
m_strMaterial = strValue;
break;
case "framerate":
m_flFramerate = stof(strValue);
break;
default:
super::SpawnKey(strKey, strValue);
}
}
void
env_sprite::Spawned(void)
{
super::Spawned();
m_iToggled = (HasSpawnFlags(ENVS_STARTON) > 0) ? TRUE : FALSE;
/* how pointless this would be otherwise. */
if (!targetname)
m_iToggled = TRUE;
}
#else
float
env_sprite::predraw(void)
{
if (m_strMaterial == __NULL__) {
return super::predraw();
}
int s = (float)getproperty(VF_ACTIVESEAT);
pSeat = &g_seats[s];
vector vecPlayer = pSeat->m_vecPredictedOrigin;
makevectors(view_angles);
makevectors(vectoangles(origin - vecPlayer));
vector forg = origin + (v_forward * -16);
vector fsize = [64,64];
traceline(origin, vecPlayer, MOVE_WORLDONLY, this);
if (trace_fraction < 1.0)
return (PREDRAW_NEXT);
R_BeginPolygon(m_strMaterial, 1, 0);
R_PolygonVertex(forg + v_right * fsize[0] - v_up * fsize[1],
[1,1], m_vecRenderColor, 1.0);
R_PolygonVertex(forg - v_right * fsize[0] - v_up * fsize[1],
[0,1], m_vecRenderColor, 1.0);
R_PolygonVertex(forg - v_right * fsize[0] + v_up * fsize[1],
[0,0], m_vecRenderColor, 1.0);
R_PolygonVertex(forg + v_right * fsize[0] + v_up * fsize[1],
[1,0], m_vecRenderColor, 1.0);
R_EndPolygon();
addentity(this);
return (PREDRAW_NEXT);
}
void
env_sprite::think(void)
{
if (frame >= (m_iMaxFrame-1)) {
if (m_bLoops == 0) {
Destroy();
return;
} else {
frame = 0;
}
} else {
frame += 1;
}
nextthink = time + (1 / m_flFramerate);
}
void
env_sprite::ReceiveEntity(float flNew, float flChanged)
{
READENTITY_COORD(origin[0], SPRITE_CHANGED_ORIGIN)
READENTITY_COORD(origin[1], SPRITE_CHANGED_ORIGIN)
READENTITY_COORD(origin[2], SPRITE_CHANGED_ORIGIN)
READENTITY_FLOAT(modelindex, SPRITE_CHANGED_MODELINDEX)
READENTITY_FLOAT(m_flFramerate, SPRITE_CHANGED_FRAMERATE)
READENTITY_FLOAT(scale, SPRITE_CHANGED_SCALE)
READENTITY_BYTE(m_iRenderMode, SPRITE_CHANGED_RENDERMODE)
READENTITY_BYTE(m_iRenderFX, SPRITE_CHANGED_RENDERFX)
READENTITY_COLOR(m_vecRenderColor[0], SPRITE_CHANGED_RENDERCOLOR)
READENTITY_COLOR(m_vecRenderColor[1], SPRITE_CHANGED_RENDERCOLOR)
READENTITY_COLOR(m_vecRenderColor[2], SPRITE_CHANGED_RENDERCOLOR)
READENTITY_COLOR(m_flRenderAmt, SPRITE_CHANGED_RENDERAMT)
READENTITY_STRING(m_strMaterial, SPRITE_CHANGED_MATERIAL)
drawmask = MASK_ENGINE;
nextthink = time + (1 / m_flFramerate);
m_iMaxFrame = modelframecount(modelindex);
m_bLoops = 1; /* repeats */
setorigin(this, origin);
}
void
env_sprite::SetMaxFrame(int fr)
{
m_iMaxFrame = fr;
}
void
env_sprite::SetLoopFlag(bool loops)
{
m_bLoops = loops;
}
#endif
void
env_sprite::SetFramerate(bool flag)
{
}
#ifdef CLIENT
void
EnvSprite_ParseEvent(void)
{
env_sprite spr = spawn(env_sprite);
spr.origin[0] = readcoord();
spr.origin[1] = readcoord();
spr.origin[2] = readcoord();
spr.modelindex = readfloat();
spr.m_flFramerate = readfloat();
spr.scale = readfloat();
spr.m_iRenderMode = readbyte();
spr.m_iRenderFX = readbyte();
spr.m_vecRenderColor[0] = readfloat();
spr.m_vecRenderColor[1] = readfloat();
spr.m_vecRenderColor[2] = readfloat();
spr.m_flRenderAmt = readfloat();
spr.m_strMaterial = readstring();
spr.drawmask = MASK_ENGINE;
spr.nextthink = time + (1 / spr.m_flFramerate);
spr.m_iMaxFrame = modelframecount(spr.modelindex);
spr.m_bLoops = 0; /* does not repeat */
setorigin(spr, spr.origin);
}
#endif