env_bubbles: Implementation. Should be complete.
NSIO: Add methods ReadBool(), SaveBool(), and PREDICTED_BOOL macro.
This commit is contained in:
parent
d562e4d742
commit
e64e72d155
8 changed files with 382 additions and 274 deletions
|
@ -132,6 +132,9 @@ Entity_EntityUpdate(float type, float new)
|
|||
case ENT_PROPROPE:
|
||||
prop_rope_readentity(new);
|
||||
break;
|
||||
case ENT_BUBBLES:
|
||||
env_bubbles_ReadEntity(new);
|
||||
break;
|
||||
default:
|
||||
//error(sprintf("Unknown entity type update received. (%d)\n", t));
|
||||
}
|
||||
|
|
|
@ -1,274 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
|
||||
*
|
||||
* 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 ambient_generic (1 1 1) (-8 -8 -8) (8 8 8) AS_ARADIUS AS_SRADIUS AS_MRADIUS AS_LRADIUS AS_SILENT AS_NOTTOGGLED
|
||||
Plays a sound sample of whatever format the engine is configured to support.
|
||||
|
||||
-------- KEYS --------
|
||||
"targetname" : Name
|
||||
"target" : Target when triggered.
|
||||
"killtarget" : Target to kill when triggered.
|
||||
"message" : Sound file to play
|
||||
"volume" : Playback volume from 0.0 to 1.0
|
||||
"pitch" : Playback pitch from 0.0 to 2.0
|
||||
|
||||
-------- SPAWNFLAGS --------
|
||||
AS_ARADIUS : Plays the sound everywhere. Heard by everyone.
|
||||
AS_SRADIUS : Small playback radius.
|
||||
AS_MRADIUS : Medium playback radius.
|
||||
AS_LRADIUS : Large playback radius.
|
||||
AS_SILENT : Start silent, trigger to make it play!
|
||||
AS_NOTTOGGLED : Don't toggle playback. When triggered, only play the sample once.
|
||||
|
||||
-------- NOTES --------
|
||||
If you want it to loop, you have to give the file itself a loop flag.
|
||||
|
||||
-------- TRIVIA --------
|
||||
This entity was introduced in Half-Life (1998).
|
||||
*/
|
||||
|
||||
enumflags
|
||||
{
|
||||
AS_ARADIUS,
|
||||
AS_SRADIUS,
|
||||
AS_MRADIUS,
|
||||
AS_LRADIUS,
|
||||
AS_SILENT,
|
||||
AS_NOTTOGGLED
|
||||
};
|
||||
|
||||
enumflags
|
||||
{
|
||||
AG_INFO,
|
||||
AG_SAMPLE
|
||||
};
|
||||
|
||||
class ambient_generic:NSPointTrigger
|
||||
{
|
||||
string m_strActivePath;
|
||||
string m_strSoundPath;
|
||||
float m_flVolume;
|
||||
float m_flRadius;
|
||||
float m_flPitch;
|
||||
int m_iToggleSwitch;
|
||||
int m_iLoop;
|
||||
|
||||
void(void) ambient_generic;
|
||||
|
||||
/* overrides */
|
||||
virtual void(float) Save;
|
||||
virtual void(string, string) Restore;
|
||||
virtual float(entity, float) SendEntity;
|
||||
virtual void(string, string) SpawnKey;
|
||||
virtual void(void) Respawn;
|
||||
|
||||
virtual void(entity, int) UseNormal;
|
||||
virtual void(entity, int) UseLoop;
|
||||
};
|
||||
|
||||
void
|
||||
ambient_generic::Save(float handle)
|
||||
{
|
||||
SaveString(handle, "activepath", m_strActivePath);
|
||||
SaveString(handle, "soundpath", m_strSoundPath);
|
||||
SaveFloat(handle, "volume", m_flVolume);
|
||||
SaveFloat(handle, "radius", m_flRadius);
|
||||
SaveFloat(handle, "pitch", m_flPitch);
|
||||
SaveInt(handle, "toggleswitch", m_iToggleSwitch);
|
||||
SaveInt(handle, "loop", m_iLoop);
|
||||
super::Save(handle);
|
||||
}
|
||||
|
||||
void
|
||||
ambient_generic::Restore(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "loop":
|
||||
m_iLoop = ReadInt(strValue);
|
||||
break;
|
||||
case "toggleswitch":
|
||||
m_iToggleSwitch = ReadInt(strValue);
|
||||
break;
|
||||
case "pitch":
|
||||
m_flPitch = ReadFloat(strValue);
|
||||
break;
|
||||
case "radius":
|
||||
m_flRadius = ReadFloat(strValue);
|
||||
break;
|
||||
case "volume":
|
||||
m_flVolume = ReadFloat(strValue);
|
||||
break;
|
||||
case "soundpath":
|
||||
m_strSoundPath = ReadString(strValue);
|
||||
break;
|
||||
case "activepath":
|
||||
m_strActivePath = ReadString(strValue);
|
||||
break;
|
||||
default:
|
||||
super::Restore(strKey, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
ambient_generic::SendEntity(entity ePEnt, float fChanged)
|
||||
{
|
||||
if (clienttype(ePEnt) != CLIENTTYPE_REAL) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* only override when we're doing the toggle guff */
|
||||
if (m_iLoop == FALSE) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
WriteByte(MSG_ENTITY, ENT_AMBIENTSOUND);
|
||||
WriteFloat(MSG_ENTITY, fChanged);
|
||||
|
||||
if (fChanged & AG_INFO) {
|
||||
WriteCoord(MSG_ENTITY, origin[0]);
|
||||
WriteCoord(MSG_ENTITY, origin[1]);
|
||||
WriteCoord(MSG_ENTITY, origin[2]);
|
||||
WriteFloat(MSG_ENTITY, m_flVolume);
|
||||
WriteByte(MSG_ENTITY, m_flRadius);
|
||||
WriteFloat(MSG_ENTITY, m_flPitch);
|
||||
}
|
||||
|
||||
/* TODO: work with soundindices? */
|
||||
if (fChanged & AG_SAMPLE) {
|
||||
WriteString(MSG_ENTITY, m_strActivePath);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
ambient_generic::UseNormal(entity act, int state)
|
||||
{
|
||||
sound(this, CHAN_VOICE, m_strActivePath, m_flVolume, m_flRadius, m_flPitch);
|
||||
dprint(sprintf("^2ambient_generic::^3UseNormal^7: %s plays `%s`\n",
|
||||
target, m_strActivePath));
|
||||
}
|
||||
|
||||
void
|
||||
ambient_generic::UseLoop(entity act, int state)
|
||||
{
|
||||
if (m_iToggleSwitch == TRUE) {
|
||||
dprint(sprintf("^2ambient_generic::^3UseLoop^7: %s stops `%s`\n",
|
||||
target, m_strActivePath));
|
||||
m_strActivePath = "common/null.wav";
|
||||
} else {
|
||||
m_strActivePath = m_strSoundPath;
|
||||
dprint(sprintf("^2ambient_generic::^3UseLoop^7: %s plays `%s`\n",
|
||||
target, m_strActivePath));
|
||||
}
|
||||
|
||||
m_iToggleSwitch = 1 - m_iToggleSwitch;
|
||||
SetSendFlags(AG_SAMPLE);
|
||||
}
|
||||
|
||||
void
|
||||
ambient_generic::Respawn(void)
|
||||
{
|
||||
m_strActivePath = m_strSoundPath;
|
||||
|
||||
if (HasSpawnFlags(AS_NOTTOGGLED)) {
|
||||
Trigger = UseNormal;
|
||||
m_iLoop = FALSE;
|
||||
} else {
|
||||
m_iLoop = TRUE;
|
||||
|
||||
/* set our sample up */
|
||||
if (HasSpawnFlags(AS_SILENT)) {
|
||||
m_iToggleSwitch = FALSE;
|
||||
m_strActivePath = "common/null.wav";
|
||||
} else {
|
||||
m_iToggleSwitch = TRUE;
|
||||
m_strActivePath = m_strSoundPath;
|
||||
}
|
||||
|
||||
Trigger = UseLoop;
|
||||
SetSendFlags(AG_SAMPLE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ambient_generic::SpawnKey(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "message":
|
||||
m_strSoundPath = strValue;
|
||||
m_strActivePath = m_strSoundPath;
|
||||
precache_sound(m_strSoundPath);
|
||||
message = __NULL__;
|
||||
break;
|
||||
case "health":
|
||||
m_flVolume = stof(strValue) * 0.1f;
|
||||
health = __NULL__;
|
||||
break;
|
||||
case "volume":
|
||||
m_flVolume = stof(strValue);
|
||||
break;
|
||||
case "pitch":
|
||||
m_flPitch = stof(strValue);
|
||||
break;
|
||||
/* TODO: currently unimplemented */
|
||||
case "preset":
|
||||
case "volstart":
|
||||
case "fadein":
|
||||
case "fadeout":
|
||||
case "pitchstart":
|
||||
case "spinup":
|
||||
case "spindown":
|
||||
case "lfotype":
|
||||
case "lforate":
|
||||
case "lfomodpitch":
|
||||
case "lfomodvol":
|
||||
case "cspinup":
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(strKey, strValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ambient_generic::ambient_generic(void)
|
||||
{
|
||||
super::NSPointTrigger();
|
||||
|
||||
if (!m_strSoundPath) {
|
||||
objerror("ambient_generic: No sound file specified!");
|
||||
}
|
||||
|
||||
if (!m_flVolume) {
|
||||
m_flVolume = 1.0f;
|
||||
}
|
||||
|
||||
// There can be only one
|
||||
if (HasSpawnFlags(AS_ARADIUS)) {
|
||||
m_flRadius = ATTN_NONE;
|
||||
} else if (HasSpawnFlags(AS_SRADIUS)) {
|
||||
m_flRadius = ATTN_IDLE;
|
||||
} else if (HasSpawnFlags(AS_MRADIUS)) {
|
||||
m_flRadius = ATTN_STATIC;
|
||||
} else if (HasSpawnFlags(AS_LRADIUS)) {
|
||||
m_flRadius = ATTN_NORM;
|
||||
} else {
|
||||
m_flRadius = ATTN_STATIC;
|
||||
}
|
||||
|
||||
pvsflags = PVSF_USEPHS;
|
||||
}
|
|
@ -19,6 +19,7 @@ shared/ambient_generic.qc
|
|||
shared/decals.qc
|
||||
shared/spraylogo.qc
|
||||
shared/func_friction.qc
|
||||
shared/env_bubbles.qc
|
||||
shared/env_projectedtexture.qc
|
||||
shared/env_fog_controller.qc
|
||||
shared/light_dynamic.qc
|
||||
|
|
|
@ -54,10 +54,12 @@ class NSIO
|
|||
nonvirtual void(float, string, int) SaveInt;
|
||||
nonvirtual void(float, string, string) SaveString;
|
||||
nonvirtual void(float, string, vector) SaveVector;
|
||||
nonvirtual void(float, string, bool) SaveBool;
|
||||
nonvirtual float(string) ReadFloat;
|
||||
nonvirtual int(string) ReadInt;
|
||||
nonvirtual string(string) ReadString;
|
||||
nonvirtual vector(string) ReadVector;
|
||||
nonvirtual bool(string) ReadBool;
|
||||
|
||||
/* Handle incoming entities input messaging */
|
||||
virtual void(entity, string, string) Input;
|
||||
|
|
|
@ -159,6 +159,12 @@ NSIO::Respawn(void)
|
|||
// Respawn code goes here...
|
||||
}
|
||||
|
||||
void
|
||||
NSIO::SaveBool(float handle, string key, bool value)
|
||||
{
|
||||
if (value)
|
||||
fputs(handle, sprintf("%S \"%f\"\n", key, value));
|
||||
}
|
||||
void
|
||||
NSIO::SaveFloat(float handle, string key, float value)
|
||||
{
|
||||
|
@ -184,6 +190,13 @@ NSIO::SaveVector(float handle, string key, vector value)
|
|||
fputs(handle, sprintf("%S \"%v\"\n", key, value));
|
||||
}
|
||||
|
||||
float
|
||||
NSIO::ReadBool(string strValue)
|
||||
{
|
||||
if (strValue && strValue != "")
|
||||
return stof(strValue);
|
||||
return __NULL__;
|
||||
}
|
||||
float
|
||||
NSIO::ReadFloat(string strValue)
|
||||
{
|
||||
|
|
361
src/gs-entbase/shared/env_bubbles.qc
Normal file
361
src/gs-entbase/shared/env_bubbles.qc
Normal file
|
@ -0,0 +1,361 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2022 Marco Cawthorne <marco@icculus.org>
|
||||
*
|
||||
* 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_bubbles (1 0 0) ? BUBFL_STARTOFF
|
||||
Brush volume that emits rising bubbles.
|
||||
|
||||
-------- KEYS --------
|
||||
"targetname" : Name
|
||||
"density" : Bubble count when it's emitting
|
||||
"frequency" : Emitting frequency in seconds
|
||||
"angles" : Direction of water current
|
||||
"current" : Speed of the water current
|
||||
|
||||
-------- SPAWNFLAGS --------
|
||||
BUBFL_STARTOFF : Start disabled.
|
||||
|
||||
-------- INPUTS --------
|
||||
"Activate" : Turns the entity on
|
||||
"Deactive" : Turns the entity off
|
||||
"Toggle" : Toggles the entity to an on/off state
|
||||
"SetDensity" : Sets the bubble count when it's emitting
|
||||
"SetFrequency" : Sets the emitting frequency in seconds
|
||||
"SetCurrent" : Sets the speed of the water current
|
||||
|
||||
-------- NOTES --------
|
||||
The bubbles emit will pick a random place in the volume (although always at the bottom)
|
||||
and rise up in varying speeds. This means you can only place vertical bubble emitters.
|
||||
|
||||
-------- TRIVIA --------
|
||||
This entity was introduced in Half-Life (1998).
|
||||
*/
|
||||
|
||||
enumflags
|
||||
{
|
||||
BUBBLES_ORIGIN,
|
||||
BUBBLES_ANGLES,
|
||||
BUBBLES_DENSITY,
|
||||
BUBBLES_FREQUENCY,
|
||||
BUBBLES_CURRENT,
|
||||
BUBBLES_ENABLED
|
||||
};
|
||||
|
||||
#define BUBFL_STARTOFF 1
|
||||
|
||||
class
|
||||
env_bubbles:NSPointTrigger
|
||||
{
|
||||
PREDICTED_INT(m_iDensity);
|
||||
PREDICTED_FLOAT(m_flFrequency);
|
||||
PREDICTED_FLOAT(m_flCurrent);
|
||||
PREDICTED_BOOL(m_bEnabled);
|
||||
|
||||
/* spawn values */
|
||||
int m_iSpawnDensity;
|
||||
float m_flSpawnFrequency;
|
||||
float m_flSpawnCurrent;
|
||||
|
||||
void(void) env_bubbles;
|
||||
|
||||
/* overrides */
|
||||
virtual void(string, string) SpawnKey;
|
||||
virtual void(void) Respawn;
|
||||
|
||||
#ifdef SERVER
|
||||
virtual void(float) Save;
|
||||
virtual void(string, string) Restore;
|
||||
virtual void(void) EvaluateEntity;
|
||||
virtual float(entity, float) SendEntity;
|
||||
virtual void(entity, int) Trigger;
|
||||
virtual void(entity, string, string) Input;
|
||||
#else
|
||||
virtual void(void) EmitBubbles;
|
||||
virtual void(float, float) ReceiveEntity;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
env_bubbles::Save(float handle)
|
||||
{
|
||||
SaveInt(handle, "density", m_iDensity);
|
||||
SaveFloat(handle, "frequency", m_flFrequency);
|
||||
SaveFloat(handle, "current", m_flCurrent);
|
||||
SaveBool(handle, "enabled", m_bEnabled);
|
||||
|
||||
SaveInt(handle, "spawn_density", m_iSpawnDensity);
|
||||
SaveFloat(handle, "spawn_frequency", m_flSpawnFrequency);
|
||||
SaveFloat(handle, "spawn_current", m_flSpawnCurrent);
|
||||
|
||||
super::Save(handle);
|
||||
}
|
||||
|
||||
void
|
||||
env_bubbles::Restore(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "density":
|
||||
m_iDensity = ReadInt(strValue);
|
||||
break;
|
||||
case "frequency":
|
||||
m_flFrequency = ReadFloat(strValue);
|
||||
break;
|
||||
case "current":
|
||||
m_flCurrent = ReadFloat(strValue);
|
||||
break;
|
||||
case "enabled":
|
||||
m_bEnabled = ReadBool(strValue);
|
||||
break;
|
||||
case "spawn_density":
|
||||
m_iSpawnDensity = ReadInt(strValue);
|
||||
break;
|
||||
case "spawn_frequency":
|
||||
m_flSpawnFrequency = ReadFloat(strValue);
|
||||
break;
|
||||
case "spawn_current":
|
||||
m_flSpawnCurrent = ReadFloat(strValue);
|
||||
break;
|
||||
default:
|
||||
super::Restore(strKey, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
env_bubbles::Input(entity eAct, string strKey, string strData)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "Activate":
|
||||
Trigger(eAct, TRIG_ON);
|
||||
break;
|
||||
case "Deactivate":
|
||||
Trigger(eAct, TRIG_OFF);
|
||||
break;
|
||||
case "Toggle":
|
||||
Trigger(eAct, TRIG_TOGGLE);
|
||||
break;
|
||||
case "SetDensity":
|
||||
m_iDensity = stoi(strData);
|
||||
break;
|
||||
case "SetFrequency":
|
||||
m_flSpawnFrequency = stof(strData);
|
||||
break;
|
||||
case "SetCurrent":
|
||||
m_flSpawnCurrent = stof(strData);
|
||||
break;
|
||||
default:
|
||||
super::Input(eAct, strKey, strData);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
env_bubbles::Trigger(entity eAct, int iState)
|
||||
{
|
||||
switch (iState) {
|
||||
case TRIG_OFF:
|
||||
m_bEnabled = false;
|
||||
break;
|
||||
case TRIG_ON:
|
||||
m_bEnabled = true;
|
||||
break;
|
||||
default:
|
||||
m_bEnabled = true - m_bEnabled;
|
||||
}
|
||||
}
|
||||
void
|
||||
env_bubbles::EvaluateEntity(void)
|
||||
{
|
||||
if (ATTR_CHANGED(origin))
|
||||
SetSendFlags(BUBBLES_ORIGIN);
|
||||
if (ATTR_CHANGED(angles))
|
||||
SetSendFlags(BUBBLES_ANGLES);
|
||||
if (ATTR_CHANGED(m_iDensity))
|
||||
SetSendFlags(BUBBLES_DENSITY);
|
||||
if (ATTR_CHANGED(m_flFrequency))
|
||||
SetSendFlags(BUBBLES_FREQUENCY);
|
||||
if (ATTR_CHANGED(m_flCurrent))
|
||||
SetSendFlags(BUBBLES_CURRENT);
|
||||
if (ATTR_CHANGED(m_bEnabled))
|
||||
SetSendFlags(BUBBLES_ENABLED);
|
||||
|
||||
SAVE_STATE(origin);
|
||||
SAVE_STATE(angles);
|
||||
SAVE_STATE(m_iDensity);
|
||||
SAVE_STATE(m_flFrequency);
|
||||
SAVE_STATE(m_flCurrent);
|
||||
SAVE_STATE(m_bEnabled);
|
||||
}
|
||||
float
|
||||
env_bubbles::SendEntity(entity ePVSent, float flChanged)
|
||||
{
|
||||
WriteByte(MSG_ENTITY, ENT_BUBBLES);
|
||||
WriteFloat(MSG_ENTITY, flChanged);
|
||||
|
||||
if (flChanged & BUBBLES_ORIGIN) {
|
||||
WriteCoord(MSG_ENTITY, origin[0]);
|
||||
WriteCoord(MSG_ENTITY, origin[1]);
|
||||
WriteCoord(MSG_ENTITY, origin[2]);
|
||||
WriteCoord(MSG_ENTITY, mins[0]);
|
||||
WriteCoord(MSG_ENTITY, mins[1]);
|
||||
WriteCoord(MSG_ENTITY, mins[2]);
|
||||
WriteCoord(MSG_ENTITY, maxs[0]);
|
||||
WriteCoord(MSG_ENTITY, maxs[1]);
|
||||
WriteCoord(MSG_ENTITY, maxs[2]);
|
||||
}
|
||||
|
||||
if (flChanged & BUBBLES_ANGLES) {
|
||||
WriteCoord(MSG_ENTITY, angles[0]);
|
||||
WriteCoord(MSG_ENTITY, angles[1]);
|
||||
WriteCoord(MSG_ENTITY, angles[2]);
|
||||
}
|
||||
|
||||
if (flChanged & BUBBLES_DENSITY)
|
||||
WriteByte(MSG_ENTITY, m_iDensity);
|
||||
if (flChanged & BUBBLES_FREQUENCY)
|
||||
WriteFloat(MSG_ENTITY, m_flFrequency);
|
||||
if (flChanged & BUBBLES_CURRENT)
|
||||
WriteFloat(MSG_ENTITY, m_flCurrent);
|
||||
if (flChanged & BUBBLES_ENABLED)
|
||||
WriteByte(MSG_ENTITY, m_bEnabled);
|
||||
|
||||
return (1);
|
||||
}
|
||||
#else
|
||||
void
|
||||
env_bubbles::EmitBubbles(void)
|
||||
{
|
||||
vector vecPos;
|
||||
|
||||
//if (m_bEnabled)
|
||||
for (int i = 0; i < m_iDensity; i++) {
|
||||
float timer;
|
||||
vecPos[0] = mins[0] + (random() * (maxs[0] - mins[0]));
|
||||
vecPos[1] = mins[1] + (random() * (maxs[1] - mins[1]));
|
||||
vecPos[2] = mins[2];
|
||||
|
||||
env_sprite eBubble = spawn(env_sprite);
|
||||
setorigin(eBubble, vecPos);
|
||||
setmodel(eBubble, "sprites/bubble.spr");
|
||||
eBubble.drawmask = MASK_ENGINE;
|
||||
eBubble.m_vecRenderColor = [1,1,1];
|
||||
eBubble.m_iRenderMode = RM_ADDITIVE;
|
||||
eBubble.m_flRenderAmt = 1.0f;
|
||||
eBubble.movetype = MOVETYPE_FLY;
|
||||
eBubble.velocity[2] = 100 + random(0, 50);
|
||||
|
||||
/* apply current */
|
||||
if (m_flCurrent > 0) {
|
||||
makevectors(eBubble.angles);
|
||||
eBubble.velocity *= v_forward * m_flCurrent;
|
||||
}
|
||||
|
||||
/* destroy the bubble once it exits out the water */
|
||||
timer = (size[2] / eBubble.velocity[2]);
|
||||
eBubble.think = Util_Destroy;
|
||||
eBubble.nextthink = time + timer;
|
||||
}
|
||||
|
||||
nextthink = time + m_flFrequency;
|
||||
}
|
||||
|
||||
void
|
||||
env_bubbles::ReceiveEntity(float is_new, float flChanged)
|
||||
{
|
||||
if (flChanged & BUBBLES_ORIGIN) {
|
||||
origin[0] = readcoord();
|
||||
origin[1] = readcoord();
|
||||
origin[2] = readcoord();
|
||||
mins[0] = readcoord();
|
||||
mins[1] = readcoord();
|
||||
mins[2] = readcoord();
|
||||
maxs[0] = readcoord();
|
||||
maxs[1] = readcoord();
|
||||
maxs[2] = readcoord();
|
||||
setsize(this, mins, maxs);
|
||||
setorigin(this, origin);
|
||||
}
|
||||
|
||||
if (flChanged & BUBBLES_ANGLES) {
|
||||
angles[0] = readcoord();
|
||||
angles[1] = readcoord();
|
||||
angles[2] = readcoord();
|
||||
}
|
||||
|
||||
if (flChanged & BUBBLES_DENSITY)
|
||||
m_iDensity = readbyte();
|
||||
if (flChanged & BUBBLES_FREQUENCY)
|
||||
m_flFrequency = readfloat();
|
||||
if (flChanged & BUBBLES_CURRENT)
|
||||
m_flCurrent = readfloat();
|
||||
if (flChanged & BUBBLES_ENABLED)
|
||||
m_bEnabled = readbyte();
|
||||
|
||||
think = EmitBubbles;
|
||||
nextthink = time + m_flFrequency;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
env_bubbles::SpawnKey(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "density":
|
||||
m_iSpawnDensity = stoi(strValue);
|
||||
break;
|
||||
case "frequency":
|
||||
m_flSpawnFrequency = stof(strValue);
|
||||
break;
|
||||
case "current":
|
||||
m_flSpawnCurrent = stof(strValue);
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(strKey, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
env_bubbles::Respawn(void)
|
||||
{
|
||||
SetModel(GetSpawnModel());
|
||||
SetSolid(SOLID_NOT);
|
||||
SetOrigin(GetSpawnOrigin());
|
||||
SetAngles(GetSpawnAngles());
|
||||
m_iDensity = m_iSpawnDensity;
|
||||
m_flFrequency = m_flSpawnFrequency;
|
||||
m_flCurrent = m_flSpawnCurrent;
|
||||
|
||||
if (spawnflags & BUBFL_STARTOFF)
|
||||
m_bEnabled = false;
|
||||
else
|
||||
m_bEnabled = true;
|
||||
}
|
||||
|
||||
void
|
||||
env_bubbles::env_bubbles(void)
|
||||
{
|
||||
super::NSPointTrigger();
|
||||
}
|
||||
|
||||
#ifdef CLIENT
|
||||
void
|
||||
env_bubbles_ReadEntity(float new)
|
||||
{
|
||||
env_bubbles me = (env_bubbles)self;
|
||||
if (new) {
|
||||
spawnfunc_env_bubbles();
|
||||
}
|
||||
me.ReceiveEntity(new, readfloat());
|
||||
}
|
||||
#endif
|
|
@ -20,6 +20,7 @@
|
|||
#define PREDICTED_VECTOR(x) vector x; vector x ##_net
|
||||
#define PREDICTED_ENT(x) entity x; entity x ##_net
|
||||
#define PREDICTED_STRING(x) string x; string x ##_net
|
||||
#define PREDICTED_BOOL(x) bool x; bool x ##_net
|
||||
|
||||
#define PREDICTED_INT_N(x) int x ##_net
|
||||
#define PREDICTED_FLOAT_N(x) float x ##_net
|
||||
|
|
|
@ -41,5 +41,6 @@ enum
|
|||
ENT_VEH_TANKMORTAR,
|
||||
ENT_VEH_4WHEEL,
|
||||
ENT_PROPROPE,
|
||||
ENT_BUBBLES,
|
||||
ENT_SEPARATOR,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue