speaker: now shared between client/server game

NSTalkMonster: Remove game specific PREDISASTER flag from the code, implement GAG instead
New entities: env_cascade_light (wip), logic_achievement, env_instructor_hint (wip)
This commit is contained in:
Marco Cawthorne 2023-11-15 09:52:11 -08:00
parent 4790e9d230
commit bf705a9e31
Signed by: eukara
GPG key ID: CE2032F0A2882A22
19 changed files with 1165 additions and 37 deletions

View file

@ -51,6 +51,10 @@ Entity_EntityUpdate(float type, float new)
NSENTITY_READENTITY(NSTalkMonster, new)
self.customphysics = Empty;
break;
case ENT_SPEAKER:
NSENTITY_READENTITY(speaker, new)
self.customphysics = Empty;
break;
case ENT_VEHICLE:
NSENTITY_READENTITY(NSVehicle, new)
break;
@ -122,6 +126,9 @@ Entity_EntityUpdate(float type, float new)
case ENT_FOGCONTROLLER:
NSENTITY_READENTITY(env_fog_controller, new)
break;
case ENT_CASCADELIGHT:
NSENTITY_READENTITY(env_cascade_light, new)
break;
case ENT_PARTSYSTEM:
NSENTITY_READENTITY(info_particle_system, new)
break;
@ -140,6 +147,9 @@ Entity_EntityUpdate(float type, float new)
case ENT_WAYPOINT:
NSENTITY_READENTITY(info_waypoint, new)
break;
case ENT_INSTRUCTOR:
NSENTITY_READENTITY(env_instructor_hint, new)
break;
case ENT_PUSH:
NSENTITY_READENTITY(trigger_push, new)
break;

View file

@ -165,6 +165,13 @@ EV_TraceDebug(void)
traceRep.angles = endOrg;
}
void
EV_Achievement(void)
{
string eventName = readstring();
NSLog("EV_Achievement: %S", eventName);
}
void
Event_Parse(float type)
{
@ -240,6 +247,9 @@ Event_Parse(float type)
case EV_TRACEDEBUG:
EV_TraceDebug();
break;
case EV_ACHIEVEMENT:
EV_Achievement();
break;
default:
error(sprintf("event id %d not recognized. abort immediately.\n", type));
}

View file

@ -103,12 +103,12 @@ server/trigger_once.qc
server/trigger_multiple.qc
server/trigger_teleport.qc
server/trigger_playerfreeze.qc
server/trigger_monsterjump.qc
server/trigger_relay.qc
server/env_shooter.qc
server/gibshooter.qc
server/env_beverage.qc
server/item_food.qc
server/speaker.qc
server/multi_manager.qc
server/momentarybase.qc
server/momentary_rot_button.qc

View file

@ -30,3 +30,14 @@ If you don't want this entity to have collision, consider using func_detail_illu
# TRIVIA
This entity was introduced in Quake II (1997).
*/
class
func_detail:info_null
{
public:
void func_detail(void);
};
void
func_detail::func_detail(void)
{
}

View file

@ -29,5 +29,16 @@ except that it does not use an entity slot or require custom materials.
If you want this entity to have collision, consider using func_detail.
# TRIVIA
This entity was introduced in Quake II (1997).
This entity was introduced in ericw-tools (2017).
*/
class
func_detail_illusionary:info_null
{
public:
void func_detail_illusionary(void);
};
void
func_detail_illusionary::func_detail_illusionary(void)
{
}

View file

@ -27,3 +27,14 @@ worldspawn upon compile.
# TRIVIA
This entity was introduced in Quake II (1997).
*/
class
func_group:info_null
{
public:
void func_group(void);
};
void
func_group::func_group(void)
{
}

View file

@ -168,9 +168,15 @@ light::SpawnKey(string strKey, string strValue)
case "_cone":
case "_cone2":
case "_sky":
case "pitch":
case "_light":
break;
/* mostly for light_environment */
case "pitch":
angles[0] = ReadFloat(strValue);
break;
case "sunangle":
angles[1] = ReadFloat(strValue);
break;
default:
super::SpawnKey(strKey, strValue);
}
@ -236,9 +242,22 @@ light::Trigger(entity act, triggermode_t state)
}
CLASSEXPORT(light_spot, light)
CLASSEXPORT(light_environment, light)
class
light_environment:light
{
public:
void light_environment(void);
};
void
light_environment::light_environment(void)
{
}
/*!QUAKED light_surface (0 1 0) (-8 -8 -8) (8 8 8)
# OVERVIEW
Material property modifier related to lighting.
# KEYS

View file

@ -87,11 +87,3 @@ CLASSEXPORT(func_dustmotes, info_null)
CLASSEXPORT(env_soundscape, info_null)
CLASSEXPORT(env_cubemap, info_null)
CLASSEXPORT(sky_camera, info_null)
void
env_glow(void)
{
if (self.model) {
precache_model(self.model);
}
}

View file

@ -0,0 +1,115 @@
/*
* Copyright (c) 2023 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 trigger_monsterjump (.5 .5 .5) ?
# OVERVIEW
When monsters touch this volume, they will be forced to jump.
# KEYS
- "targetname" : Name
- "target" : Target when triggered.
- "speed" : Speed of the jump.
- "height" : Height of the jump.
# TRIVIA
This entity was introduced in Quake (1996).
*/
class
trigger_monsterjump:NSBrushTrigger
{
public:
void trigger_monsterjump(void);
virtual void Respawn(void);
virtual void Touch(entity);
virtual void Save(float);
virtual void Restore(string,string);
virtual void SpawnKey(string,string);
private:
float m_flSpeed;
float m_flHeight;
};
void
trigger_monsterjump::trigger_monsterjump(void)
{
m_flSpeed = 0.0f;
m_flHeight = 0.0f;
}
void
trigger_monsterjump::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "speed":
m_flSpeed = ReadFloat(strValue);
break;
case "height":
m_flHeight = ReadFloat(strValue);
break;
default:
super::SpawnKey(strKey, strValue);
}
}
void
trigger_monsterjump::Save(float handle)
{
super::Save(handle);
SaveFloat(handle, "m_flSpeed", m_flSpeed);
SaveFloat(handle, "m_flHeight", m_flHeight);
}
void
trigger_monsterjump::Restore(string strKey, string strValue)
{
switch (strKey) {
case "m_flSpeed":
m_flSpeed = ReadFloat(strValue);
break;
case "m_flHeight":
m_flHeight = ReadFloat(strValue);
break;
default:
super::Restore(strKey, strValue);
}
}
void
trigger_monsterjump::Respawn(void)
{
InitBrushTrigger();
}
void
trigger_monsterjump::Touch(entity touchingEntity)
{
vector targetVelocity = g_vec_null;
if (!touchingEntity.flags & FL_MONSTER) {
return;
}
if (GetMaster(touchingEntity) == false) {
return;
}
NSMonster theMonster = (NSMonster)touchingEntity;
targetVelocity = theMonster.GetForward() * m_flSpeed;
targetVelocity[2] += m_flHeight;
theMonster.SetVelocity(targetVelocity);
}

View file

@ -15,12 +15,14 @@ shared/env_glow.qc
shared/env_projectedtexture.qc
shared/env_fog.qc
shared/env_fog_controller.qc
shared/env_cascade_light.qc
shared/env_smoker.qc
shared/env_muzzleflash.qc
//shared/env_fire.qc
shared/env_steam.qc
shared/env_shockwave.qc
shared/light_dynamic.qc
shared/logic_achievement.qc
shared/func_monitor.qc
shared/func_illusionary.qc
shared/func_ladder.qc
@ -31,6 +33,7 @@ shared/trigger_camera.qc
shared/trigger_gravity.qc
shared/info_particle_system.qc
shared/info_waypoint.qc
shared/env_instructor_hint.qc
shared/prop_physics_multiplayer.qc
shared/prop_vehicle_driveable.qc
shared/point_spotlight.qc
@ -39,4 +42,5 @@ shared/func_conveyor.qc
shared/prop_rope.qc
shared/phys_rope.qc
shared/worldspawn.qc
shared/speaker.qc
#endlist

View file

@ -0,0 +1,304 @@
/*
* Copyright (c) 2023 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
{
ENVCASLIGHT_CHANGED_ACTIVE,
ENVCASLIGHT_CHANGED_ANGLE_X,
ENVCASLIGHT_CHANGED_ANGLE_Y,
ENVCASLIGHT_CHANGED_ANGLE_Z,
ENVCASLIGHT_CHANGED_COLOR_X,
ENVCASLIGHT_CHANGED_COLOR_Y,
ENVCASLIGHT_CHANGED_COLOR_Z,
ENVCASLIGHT_CHANGED_DISTANCE,
};
/*!QUAKED env_cascade_light (1 .5 0) (-8 -8 -8) (8 8 8)
# OVERVIEW
Shadowmapped outdoor lighting entity.
![Shadows cast by an env_cascade_light](@ref Documentation/Entities/env_cascade_light.png)
# KEYS
- "targetname" : Name
- "color" : Color of the sun light. Three space separated 0-255 based values.
- "maxshadowdistance" : Maximum shadow distance from the camera.
- "uselightenvangles" : When set to 1, the angles are taken from the light_environment in the map.
- "StartDisabled" : Entity will have to be enabled in order to work when set to 1.
# INPUTS
- "SetAngles" : Sets the light angle.
- "LightColor" : Sets the light color. Three space separated 0-255 based values.
- "Enable" : Enable the entity.
- "Disable" : Disable the entity.
- "Toggle" : Toggles between enabled/disabled states.
# TRIVIA
This entity was introduced in Counter-Strike: Global Offensive (2012).
*/
class
env_cascade_light:NSPointTrigger
{
public:
void env_cascade_light(void);
#ifdef SERVER
virtual float SendEntity(entity,float);
virtual void EvaluateEntity(void);
virtual void Trigger(entity, triggermode_t);
virtual void Respawn(void);
virtual void Save(float);
virtual void Restore(string,string);
virtual void SpawnKey(string,string);
virtual void Input(entity, string, string);
#endif
#ifdef CLIENT
virtual void OnRemoveEntity(void);
virtual void ReceiveEntity(float,float);
virtual void RendererRestarted(void);
#endif
private:
NETWORKED_BOOL(m_bLightActive)
NETWORKED_VECTOR(m_vecLightColor)
NETWORKED_FLOAT(m_flShadowDistance)
#ifdef CLIENT
float m_lightHandle;
#else
bool m_bUseEnvAngles;
#endif
};
void
env_cascade_light::env_cascade_light(void)
{
#ifdef SERVER
m_vecLightColor = [1.0, 1.0, 1.0];
m_bLightActive = true;
m_flShadowDistance = 512.0f;
#endif
}
#ifdef SERVER
void
env_cascade_light::SpawnKey(string keyName, string setValue)
{
switch (keyName) {
case "color":
m_vecLightColor = ReadVector(setValue) / 255;
break;
case "maxshadowdistance":
m_flShadowDistance = ReadFloat(setValue);
break;
case "uselightenvangles":
m_bUseEnvAngles = ReadBool(setValue);
break;
case "StartDisabled":
m_bLightActive = ReadBool(setValue) == true ? false : true;
break;
default:
super::SpawnKey(keyName, setValue);
}
}
void
env_cascade_light::Respawn(void)
{
InitPointTrigger();
pvsflags = PVSF_IGNOREPVS;
}
void
env_cascade_light::Save(float handle)
{
super::Save(handle);
SaveBool(handle, "m_bLightActive", m_bLightActive);
SaveVector(handle, "m_vecLightColor", m_vecLightColor);
SaveFloat(handle, "m_flShadowDistance", m_flShadowDistance);
SaveBool(handle, "m_bUseEnvAngles", m_bUseEnvAngles);
}
void
env_cascade_light::Restore(string keyName, string setValue)
{
switch (keyName) {
case "m_bLightActive":
m_bLightActive = ReadBool(setValue);
break;
case "m_vecLightColor":
m_vecLightColor = ReadVector(setValue);
break;
case "m_flShadowDistance":
m_flShadowDistance = ReadFloat(setValue);
break;
case "m_bUseEnvAngles":
m_bUseEnvAngles = ReadBool(setValue);
break;
default:
super::Restore(keyName, setValue);
}
}
void
env_cascade_light::Input(entity activatingEntity, string keyName, string setValue)
{
switch (keyName) {
case "Enable":
m_bLightActive = false;
break;
case "Disable":
m_bLightActive = true;
break;
case "Toggle":
m_bLightActive = !m_bLightActive;
break;
case "SetAngles":
angles = stov(setValue);
break;
case "LightColor":
m_vecLightColor = stov(setValue) / 255;
break;
default:
super::Input(activatingEntity, keyName, setValue);
}
}
void
env_cascade_light::Trigger(entity activatingEntity, triggermode_t triggerState)
{
switch (triggerState) {
case TRIG_OFF:
m_bLightActive = (false);
break;
case TRIG_ON:
m_bLightActive = (true);
break;
default:
m_bLightActive = (true - m_bLightActive);
}
}
void
env_cascade_light::EvaluateEntity(void)
{
if (m_bUseEnvAngles == true) {
light envLight = (light)find(world, ::classname, "light_environment");
if (!envLight) {
error("env_cascade_light unable to find light_environment.\n");
return;
}
makevectors(envLight.GetAngles());
angles = vectoangles(v_forward * -1);
}
//angles[0] = sin(time) * 180.0f;
//angles[1] = sin(time*2) * 180.0f;
EVALUATE_FIELD(m_bLightActive, ENVCASLIGHT_CHANGED_ACTIVE)
EVALUATE_VECTOR(angles, 0, ENVCASLIGHT_CHANGED_ANGLE_X)
EVALUATE_VECTOR(angles, 1, ENVCASLIGHT_CHANGED_ANGLE_Y)
EVALUATE_VECTOR(angles, 2, ENVCASLIGHT_CHANGED_ANGLE_Z)
EVALUATE_VECTOR(m_vecLightColor, 0, ENVCASLIGHT_CHANGED_COLOR_X)
EVALUATE_VECTOR(m_vecLightColor, 1, ENVCASLIGHT_CHANGED_COLOR_Y)
EVALUATE_VECTOR(m_vecLightColor, 2, ENVCASLIGHT_CHANGED_COLOR_Z)
EVALUATE_FIELD(m_flShadowDistance, ENVCASLIGHT_CHANGED_DISTANCE)
}
float
env_cascade_light::SendEntity(entity ePVEnt, float flChanged)
{
if (m_bLightActive == false)
return (0);
WriteByte(MSG_ENTITY, ENT_CASCADELIGHT);
WriteFloat(MSG_ENTITY, flChanged);
SENDENTITY_BYTE(m_bLightActive, ENVCASLIGHT_CHANGED_ACTIVE)
SENDENTITY_COORD(angles[0], ENVCASLIGHT_CHANGED_ANGLE_X)
SENDENTITY_COORD(angles[1], ENVCASLIGHT_CHANGED_ANGLE_Y)
SENDENTITY_COORD(angles[2], ENVCASLIGHT_CHANGED_ANGLE_Z)
SENDENTITY_COLOR(m_vecLightColor[0], ENVCASLIGHT_CHANGED_COLOR_X)
SENDENTITY_COLOR(m_vecLightColor[1], ENVCASLIGHT_CHANGED_COLOR_Y)
SENDENTITY_COLOR(m_vecLightColor[2], ENVCASLIGHT_CHANGED_COLOR_Z)
SENDENTITY_FLOAT(m_flShadowDistance, ENVCASLIGHT_CHANGED_DISTANCE)
return (1);
}
#else
void
env_cascade_light::OnRemoveEntity(void)
{
/* this tells the engine to re-use this for a later light */
dynamiclight_set(m_lightHandle, LFIELD_RADIUS, 0);
m_lightHandle = 0;
}
void
env_cascade_light::LightChanged(float flFlags)
{
bool updateAngle = false;
bool updateColor = false;
updateAngle |= (flFlags & ENVCASLIGHT_CHANGED_ANGLE_X) ? true : false;
updateAngle |= (flFlags & ENVCASLIGHT_CHANGED_ANGLE_Y) ? true : false;
updateAngle |= (flFlags & ENVCASLIGHT_CHANGED_ANGLE_Z) ? true : false;
updateColor |= (flFlags & ENVCASLIGHT_CHANGED_COLOR_X) ? true : false;
updateColor |= (flFlags & ENVCASLIGHT_CHANGED_COLOR_Y) ? true : false;
updateColor |= (flFlags & ENVCASLIGHT_CHANGED_COLOR_Z) ? true : false;
if (updateAngle) {
dynamiclight_set(m_lightHandle, LFIELD_ANGLES, angles);
}
if (updateColor) {
dynamiclight_set(m_lightHandle, LFIELD_COLOUR, m_vecLightColor);
}
}
void
env_cascade_light::ReceiveEntity(float flNew, float flChanged)
{
READENTITY_BYTE(m_bLightActive, ENVCASLIGHT_CHANGED_ACTIVE)
READENTITY_COORD(angles[0], ENVCASLIGHT_CHANGED_ANGLE_X)
READENTITY_COORD(angles[1], ENVCASLIGHT_CHANGED_ANGLE_Y)
READENTITY_COORD(angles[2], ENVCASLIGHT_CHANGED_ANGLE_Z)
READENTITY_COLOR(m_vecLightColor[0], ENVCASLIGHT_CHANGED_COLOR_X)
READENTITY_COLOR(m_vecLightColor[1], ENVCASLIGHT_CHANGED_COLOR_Y)
READENTITY_COLOR(m_vecLightColor[2], ENVCASLIGHT_CHANGED_COLOR_Z)
READENTITY_FLOAT(m_flShadowDistance, ENVCASLIGHT_CHANGED_DISTANCE)
if (flNew) {
RendererRestarted();
} else {
LightChanged(flChanged);
}
}
void
env_cascade_light::RendererRestarted(void)
{
OnRemoveEntity();
m_lightHandle = dynamiclight_spawnstatic(origin, m_flShadowDistance, m_vecLightColor);
dynamiclight_set(m_lightHandle, LFIELD_FLAGS, LFLAG_ORTHOSUN | LFLAG_SHADOWMAP | LFLAG_REALTIMEMODE);
LightChanged(0xFFFFFF);
}
#endif

View file

@ -0,0 +1,365 @@
/*
* Copyright (c) 2023 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
{
ENVINSTRUCTOR_CHANGED_ORIGIN,
ENVINSTRUCTOR_CHANGED_IMAGE,
ENVINSTRUCTOR_CHANGED_IMAGE_OFF,
ENVINSTRUCTOR_CHANGED_TEXT,
ENVINSTRUCTOR_CHANGED_TEXT_COLOR,
ENVINSTRUCTOR_CHANGED_TIMEOUT,
ENVINSTRUCTOR_CHANGED_OFFSET,
ENVINSTRUCTOR_CHANGED_STATE
};
/*!QUAKED env_instructor_hint (0 1 0) (-8 -8 -8) (8 8 8)
# OVERVIEW
Used to display hints throughout the environment.
# KEYS
- "targetname" : Name
- "hint_caption" : Text of your hint.
- "hint_color" : Color tint of your text.
- "hint_icon_onscreen" : Icon to use when the hint is visible.
- "hint_icon_offscreen" : Icon to use when the hint is out of view.
- "hint_binding" : Name of the command that we'll display a key/button for.
- "hint_nooffscreen" : When 1, will not show an off-screen hint at all.
- "hint_target" : Hint will be displayed at the named entity.
- "hint_static" : When 0, follows the entity specified in `hint_target`. Will be displayed on the heads-up-display otherwise.
- "hint_allow_nodraw_target" : When 0, will stop rendering if the `hint_target` becomes invisible.
- "hint_forcecaption" : When 1, will show the hint even if it's obscured by a wall.
- "hint_icon_offset" : Height offset at which the hint will be displayed in-world.
- "hint_pulseoption" : Speed at which the icon pulses in size. 0 is none, 3 is very fast.
- "hint_alphaoption" : Speed at which the icon pulses in transparency. 0 is none, 3 is very fast.
- "hint_shakeoption" : Strength at which the icon shakes. 0 is none, 2 is wide.
- "hint_timeout" : Time until the hint stops showing. When 0, needs to be triggered to be disabled.
- "hint_range" : Visible range of the hint in world units.
- "hint_auto_start" : When set to 0, the entity no longer has to be triggered to show, line-of-sight will be enough.
- "hint_display_limit" : Number of times this hint can be shown.
# INPUTS
- "Enable" : Enable the entity.
- "Disable" : Disable the entity.
- "Toggle" : Toggles between enabled/disabled states.
# TRIVIA
This entity was introduced in Left 4 Dead 2 (2009).
*/
class
env_instructor_hint:NSPointTrigger
{
public:
void env_instructor_hint(void);
#ifdef SERVER
virtual void Respawn(void);
virtual void SpawnKey(string,string);
virtual void Save(float);
virtual void Restore(string,string);
virtual void Input(entity,string,string);
virtual void Trigger(entity, triggermode_t);
virtual void EvaluateEntity(void);
virtual float SendEntity(entity,float);
#endif
#ifdef CLIENT
virtual void ReceiveEntity(float, float);
virtual void postdraw(void);
#endif
private:
PREDICTED_STRING(m_strIcon)
PREDICTED_STRING(m_strIconOff)
PREDICTED_STRING(m_strText)
PREDICTED_VECTOR(m_vecTextColor)
PREDICTED_BOOL(m_bEnabled)
NETWORKED_FLOAT(m_flTimeOut)
NETWORKED_FLOAT(m_flOffset)
#ifdef CLIENT
bool m_bOldHintState;
float m_flHintTime;
#endif
};
void
env_instructor_hint::env_instructor_hint(void)
{
m_strIcon =
m_strIconOff =
m_strText = __NULL__;
m_vecTextColor = [1,1,1];
m_flTimeOut = 0.0f;
m_flOffset = 0.0f;
}
#ifdef SERVER
void
env_instructor_hint::Respawn(void)
{
InitPointTrigger();
m_bEnabled = false;
}
void
env_instructor_hint::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "hint_icon_onscreen":
m_strIcon = strValue;
break;
case "hint_icon_offscreen":
m_strIconOff = strValue;
break;
case "hint_caption":
m_strText = strValue;
break;
case "hint_color":
m_vecTextColor = ReadVector(strValue) / 255;
break;
case "hint_timeout":
m_flTimeOut = ReadFloat(strValue);
break;
case "hint_icon_offset":
m_flOffset = ReadFloat(strValue);
break;
default:
super::SpawnKey(strKey, strValue);
}
}
void
env_instructor_hint::Save(float handle)
{
super::Save(handle);
SaveString(handle, "m_strIcon", m_strIcon);
SaveString(handle, "m_strIconOff", m_strIconOff);
SaveString(handle, "m_strText", m_strText);
SaveVector(handle, "m_vecTextColor", m_vecTextColor);
SaveFloat(handle, "m_flTimeOut", m_flTimeOut);
SaveFloat(handle, "m_flOffset", m_flOffset);
}
void
env_instructor_hint::Restore(string strKey, string strValue)
{
switch (strKey) {
case "m_strIcon":
m_strIcon = ReadString(strValue);
break;
case "m_strIconOff":
m_strIconOff = ReadString(strValue);
break;
case "m_strText":
m_strText = ReadString(strValue);
break;
case "m_vecTextColor":
m_vecTextColor = ReadVector(strValue);
break;
case "m_flTimeOut":
m_flTimeOut = ReadFloat(strValue);
break;
case "m_flOffset":
m_flOffset = ReadFloat(strValue);
break;
default:
super::Restore(strKey, strValue);
}
}
void
env_instructor_hint::Trigger(entity act, triggermode_t state)
{
switch (state) {
case TRIG_OFF:
m_bEnabled = false;
break;
case TRIG_ON:
m_bEnabled = true;
break;
default:
m_bEnabled = m_bEnabled ? false : true;
}
}
void
env_instructor_hint::Input(entity eAct, string strInput, string strData)
{
switch (strInput) {
case "Enable":
Trigger(eAct, TRIG_ON);
break;
case "Disable":
Trigger(eAct, TRIG_OFF);
break;
case "Toggle":
Trigger(eAct, TRIG_TOGGLE);
break;
default:
super::Input(eAct, strInput, strData);
}
}
void
env_instructor_hint::EvaluateEntity(void)
{
EVALUATE_VECTOR(origin, 0, ENVINSTRUCTOR_CHANGED_ORIGIN)
EVALUATE_VECTOR(origin, 1, ENVINSTRUCTOR_CHANGED_ORIGIN)
EVALUATE_VECTOR(origin, 2, ENVINSTRUCTOR_CHANGED_ORIGIN)
EVALUATE_FIELD(m_strIcon, ENVINSTRUCTOR_CHANGED_IMAGE)
EVALUATE_FIELD(m_strIconOff, ENVINSTRUCTOR_CHANGED_IMAGE_OFF)
EVALUATE_FIELD(m_strText, ENVINSTRUCTOR_CHANGED_TEXT)
EVALUATE_VECTOR(m_vecTextColor, 0, ENVINSTRUCTOR_CHANGED_TEXT_COLOR)
EVALUATE_VECTOR(m_vecTextColor, 1, ENVINSTRUCTOR_CHANGED_TEXT_COLOR)
EVALUATE_VECTOR(m_vecTextColor, 2, ENVINSTRUCTOR_CHANGED_TEXT_COLOR)
EVALUATE_FIELD(m_flTimeOut, ENVINSTRUCTOR_CHANGED_TIMEOUT)
EVALUATE_FIELD(m_flOffset, ENVINSTRUCTOR_CHANGED_OFFSET)
EVALUATE_FIELD(m_bEnabled, ENVINSTRUCTOR_CHANGED_STATE)
pvsflags = PVSF_IGNOREPVS;
}
float
env_instructor_hint::SendEntity(entity ePEnt, float flChanged)
{
WriteByte(MSG_ENTITY, ENT_INSTRUCTOR);
WriteFloat(MSG_ENTITY, flChanged);
SENDENTITY_COORD(origin[0], ENVINSTRUCTOR_CHANGED_ORIGIN)
SENDENTITY_COORD(origin[1], ENVINSTRUCTOR_CHANGED_ORIGIN)
SENDENTITY_COORD(origin[2], ENVINSTRUCTOR_CHANGED_ORIGIN)
SENDENTITY_STRING(m_strIcon, ENVINSTRUCTOR_CHANGED_IMAGE)
SENDENTITY_STRING(m_strIconOff, ENVINSTRUCTOR_CHANGED_IMAGE_OFF)
SENDENTITY_STRING(m_strText, ENVINSTRUCTOR_CHANGED_TEXT)
SENDENTITY_COORD(m_vecTextColor[0], ENVINSTRUCTOR_CHANGED_TEXT_COLOR)
SENDENTITY_COORD(m_vecTextColor[1], ENVINSTRUCTOR_CHANGED_TEXT_COLOR)
SENDENTITY_COORD(m_vecTextColor[2], ENVINSTRUCTOR_CHANGED_TEXT_COLOR)
SENDENTITY_FLOAT(m_flTimeOut, ENVINSTRUCTOR_CHANGED_TIMEOUT)
SENDENTITY_FLOAT(m_flOffset, ENVINSTRUCTOR_CHANGED_OFFSET)
SENDENTITY_BYTE(m_bEnabled, ENVINSTRUCTOR_CHANGED_STATE)
return true;
}
#endif
#ifdef CLIENT
void
env_instructor_hint::ReceiveEntity(float flNew, float flChanged)
{
READENTITY_COORD(origin[0], ENVINSTRUCTOR_CHANGED_ORIGIN)
READENTITY_COORD(origin[1], ENVINSTRUCTOR_CHANGED_ORIGIN)
READENTITY_COORD(origin[2], ENVINSTRUCTOR_CHANGED_ORIGIN)
READENTITY_STRING(m_strIcon, ENVINSTRUCTOR_CHANGED_IMAGE)
READENTITY_STRING(m_strIconOff, ENVINSTRUCTOR_CHANGED_IMAGE_OFF)
READENTITY_STRING(m_strText, ENVINSTRUCTOR_CHANGED_TEXT)
READENTITY_COORD(m_vecTextColor[0], ENVINSTRUCTOR_CHANGED_TEXT_COLOR)
READENTITY_COORD(m_vecTextColor[1], ENVINSTRUCTOR_CHANGED_TEXT_COLOR)
READENTITY_COORD(m_vecTextColor[2], ENVINSTRUCTOR_CHANGED_TEXT_COLOR)
READENTITY_FLOAT(m_flTimeOut, ENVINSTRUCTOR_CHANGED_TIMEOUT)
READENTITY_FLOAT(m_flOffset, ENVINSTRUCTOR_CHANGED_OFFSET)
READENTITY_BYTE(m_bEnabled, ENVINSTRUCTOR_CHANGED_STATE)
setorigin(this, origin);
if (m_bEnabled != m_bOldHintState) {
m_flHintTime = m_flTimeOut;
}
m_bOldHintState = m_bEnabled;
}
void
env_instructor_hint::postdraw(void)
{
bool visible = false;
bool inView = false;
vector positionValues;
if (!m_bEnabled)
return;
if (m_flHintTime <= 0.0f)
return;
/* calculation for the edge positions */
{
vector delta;
vector p2 = g_view.GetCameraOrigin();
vector ang = g_view.GetCameraAngle();
vector outputValue;
float leftValue;
float upValue;
makevectors(ang);
delta = normalize (origin - p2);
leftValue = delta * v_right;
upValue = delta * -v_up;
positionValues[0] = (delta * v_forward);
positionValues[1] = (leftValue + 1.0f) * 0.5f;
positionValues[2] = (upValue + 1.0f) * 0.5f;
if (fabs(leftValue) > fabs(upValue)) {
/* clamp leftvalue */
if (positionValues[1] > 0.5)
positionValues[1] = 1.0f;
else
positionValues[1] = 0.0f;
} else {
/* clamp upvalue */
if (positionValues[2] > 0.5)
positionValues[2] = 1.0f;
else
positionValues[2] = 0.0f;
}
/* within field of view... */
if (positionValues[0] > (g_view.GetAFOV()/180)) {
traceline(p2, origin, MOVE_WORLDONLY, self);
/* totally visible */
if (trace_fraction == 1.0) {
visible = true;
}
inView = true;
}
}
vector iconPos;
vector textPos;
vector hintPos;
float textLength = Font_StringWidth(m_strText, true, FONT_CON);
float sideOffset = textLength + 64.0f;
float a = (visible == false) ? 0.25 : 1.0f;
a = 1.0f;
/* in-world position of the center */
hintPos = project(origin + [0, m_flOffset]) - [(textLength * 0.5f), 0];
if (inView == false) {
hintPos[0] = Math_Lerp(32.0f, video_res[0] - sideOffset, positionValues[1]);
hintPos[1] = Math_Lerp(32.0f, video_res[1] - 32.0f, positionValues[2]);
}
/* draw the thing */
iconPos = hintPos - [32, 32];
textPos = hintPos + [48.0f, 0];
drawpic(iconPos, m_strIcon, [64, 64], [1,1,1], a);
Font_DrawText_RGBA(textPos + [1,1], m_strText, [0,0,0], a, FONT_CON);
Font_DrawText_RGBA(textPos, m_strText, m_vecTextColor, a, FONT_CON);
m_flHintTime -= clframetime;
}
#endif

View file

@ -0,0 +1,156 @@
/*
* Copyright (c) 2023 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.
*/
#ifdef SERVER
/*!QUAKED logic_achievement (0.3 0.1 0.6) (-8 -8 -8) (8 8 8)
# OVERVIEW
Unlocks achievements or aids in the progression of them.
# KEYS
- "targetname" : Name
- "AchievementEvent" : Identifier of the achievement.
- "StartDisabled" : Entity will have to be enabled in order to work when set to 1.
# INPUTS
- "FireEvent" : Triggers the achievement.
- "Enable" : Enable the entity.
- "Disable" : Disable the entity.
- "Toggle" : Toggles between enabled/disabled states.
# OUTPUTS
- "OnFired" : Triggered when the 'FireEvent' is received.
# NOTES
Ensure to prefix the value of the `AchievementEvent` key with `ACHIEVEMENT_EVENT_`. For example, if you are using SteamWorks and have your achievement on there named `FOOBAR` then you want the value to be `ACHIEVEMENT_EVENT_FOOBAR`.
# TRIVIA
This entity was introduced in The Orange Box (2007) for Xbox 360.
*/
class
logic_achievement:NSPointTrigger
{
public:
void logic_achievement(void);
/** overrides */
virtual void Save(float);
virtual void Restore(string, string);
virtual void SpawnKey(string, string);
virtual void Spawned(void);
virtual void Respawn(void);
virtual void Input(entity, string, string);
virtual void Trigger(entity, triggermode_t);
nonvirtual void CallEvent(entity);
private:
string m_strAchievementEvent;
string m_strOnFired;
};
void
logic_achievement::logic_achievement(void)
{
m_strAchievementEvent = __NULL__;
m_strOnFired = __NULL__;
}
void
logic_achievement::Save(float handle)
{
SaveString(handle, "m_strAchievementEvent", m_strAchievementEvent);
SaveString(handle, "m_strOnFired", m_strOnFired);
}
void
logic_achievement::Restore(string keyName, string setValue)
{
switch (keyName) {
case "m_strAchievementEvent":
m_strAchievementEvent = ReadString(setValue);
break;
case "m_strOnFired":
m_strOnFired = ReadString(setValue);
break;
default:
super::Restore(keyName, setValue);
}
}
void
logic_achievement::SpawnKey(string keyName, string setValue)
{
switch (keyName) {
case "AchievementEvent":
m_strAchievementEvent = ReadString(setValue);
break;
case "OnFired":
m_strOnFired = PrepareOutput(m_strOnFired, setValue);
break;
default:
super::SpawnKey(keyName, setValue);
}
}
void
logic_achievement::Spawned(void)
{
super::Spawned();
if (m_strOnFired)
m_strOnFired = CreateOutput(m_strOnFired);
}
void
logic_achievement::Respawn(void)
{
InitPointTrigger();
}
void
logic_achievement::Input(entity activatorEntity, string inputName, string dataField)
{
switch (inputName) {
case "FireEvent":
CallEvent(activatorEntity);
break;
default:
super::Input(activatorEntity, inputName, dataField);
}
}
void
logic_achievement::Trigger(entity activatorEntity, triggermode_t state)
{
CallEvent(activatorEntity);
}
void
logic_achievement::CallEvent(entity targetPlayer)
{
if (m_bEnabled == false) {
return;
}
UseOutput(targetPlayer, m_strOnFired);
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_ACHIEVEMENT);
WriteString(MSG_MULTICAST, m_strAchievementEvent);
msg_entity = targetPlayer;
multicast([0,0,0], MULTICAST_ONE_R);
}
#endif

View file

@ -14,6 +14,7 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef SERVER
enumflags
{
SPEAKFL_SILENT
@ -33,6 +34,7 @@ string g_speaker_hlpresets[] = {
"!C3A1_",
"!C3A2_"
};
#endif
/*!QUAKED speaker (1 0 0) (-8 -8 -8) (8 8 8)
# OVERVIEW
@ -69,7 +71,8 @@ speaker:NSTalkMonster
{
public:
void speaker(void);
#ifdef SERVER
/* overrides */
virtual void Save(float);
virtual void Restore(string,string);
@ -79,18 +82,32 @@ public:
nonvirtual void Announce(void);
virtual void EvaluateEntity(void);
virtual float SendEntity(entity,float);
#endif
#ifdef CLIENT
virtual void ReceiveEntity(float, float);
#endif
#ifdef SERVER
private:
string m_strSentence;
float m_flVolume;
#endif
};
void
speaker::speaker(void)
{
#ifdef SERVER
m_strSentence = __NULL__;
m_flVolume = 1.0f;
#endif
}
#ifdef SERVER
void
speaker::Save(float handle)
{
@ -139,10 +156,7 @@ speaker::SpawnKey(string strKey, string strValue)
void
speaker::Respawn(void)
{
/* force this thing to be networked */
SetModel("models/player.mdl");
SetOrigin(GetSpawnOrigin());
Hide();
if (HasSpawnFlags(SPEAKFL_SILENT) == false)
ScheduleThink(Announce, 10.0f);
@ -173,3 +187,42 @@ speaker::Trigger(entity eAct, triggermode_t foo)
{
ScheduleThink(Announce, 0.0f);
}
void
speaker::EvaluateEntity(void)
{
EVALUATE_VECTOR(origin, 0, MONFL_CHANGED_ORIGIN_X)
EVALUATE_VECTOR(origin, 1, MONFL_CHANGED_ORIGIN_Y)
EVALUATE_VECTOR(origin, 2, MONFL_CHANGED_ORIGIN_Z)
}
/* Make sure StartFrame calls this */
float
speaker::SendEntity(entity ePEnt, float flChanged)
{
if (clienttype(ePEnt) != CLIENTTYPE_REAL)
return (0);
WriteByte(MSG_ENTITY, ENT_SPEAKER);
/* broadcast how much data is expected to be read */
WriteFloat(MSG_ENTITY, flChanged);
SENDENTITY_COORD(origin[0], MONFL_CHANGED_ORIGIN_X)
SENDENTITY_COORD(origin[1], MONFL_CHANGED_ORIGIN_Y)
SENDENTITY_COORD(origin[2], MONFL_CHANGED_ORIGIN_Z)
return (1);
}
#endif
#ifdef CLIENT
void
speaker::ReceiveEntity(float flNew, float flChanged)
{
READENTITY_COORD(origin[0], MONFL_CHANGED_ORIGIN_X)
READENTITY_COORD(origin[1], MONFL_CHANGED_ORIGIN_Y)
READENTITY_COORD(origin[2], MONFL_CHANGED_ORIGIN_Z)
SetOrigin(origin);
}
#endif

View file

@ -381,6 +381,8 @@ public:
/** Returns TRUE if 'enemy' should be considered a valid target for killing */
nonvirtual bool IsValidEnemy(entity);
/** Returns TRUE if the monster is currently on route to a position. */
virtual bool IsOnRoute(void);
/* sequences */
/** Internal use only. Called when a sequence is done. */

View file

@ -646,6 +646,12 @@ NSMonster::IsValidEnemy(entity enny)
return true;
}
bool
NSMonster::IsOnRoute(void)
{
return (m_iNodes || m_pathTarget) && (GetState() == MONSTER_IDLE || GetState() == MONSTER_ALERT) ? true : false;
}
static bool
NSMonster_TraceAgainsTarget(NSMonster monster, NSEntity target)
{
@ -1258,12 +1264,11 @@ NSMonster::RouteEnded(void)
void
NSMonster::WalkRoute(void)
{
/* we're busy shooting at something, don't walk */
if (GetState() == MONSTER_AIMING && m_eEnemy) {
input_angles = vectoangles(m_eEnemy.origin - origin);
input_angles[0] = input_angles[2] = 0;
} else if ((m_iNodes || m_pathTarget) && (GetState() == MONSTER_IDLE || GetState() == MONSTER_ALERT)) {
} else if (IsOnRoute()) {
input_angles = GetRouteDirection();
input_angles[0] = input_angles[2] = 0;
input_movevalues = GetRouteMovevalues() * m_flSequenceSpeed;
@ -1548,8 +1553,30 @@ NSMonster::Touch(entity eToucher)
if (autocvar(pm_pushMonsters, 0))
if (eToucher.movetype == MOVETYPE_WALK) {
if (eToucher.absmin[2] < origin[2])
velocity = normalize(eToucher.origin - origin) * -128;
if (eToucher.absmin[2] < origin[2]) {
float bestYaw = 0.0f;
float best_fraction = 0.0f;
vector bestPos = g_vec_null;
for (float yaw = angles[1]; yaw < (angles[1] + 360.0f); yaw += 1.0f) {
makevectors([0, yaw, 0]);
tracebox(origin, mins, maxs, origin + (v_forward * 128.0f), FALSE, this);
if (trace_startsolid) {
bestYaw = random(0, 360);
break;
}
if (trace_fraction > best_fraction) {
best_fraction = trace_fraction;
bestYaw = yaw;
bestPos = trace_endpos;
}
}
RouteToPosition(bestPos);
m_flSequenceSpeed = GetWalkSpeed();
}
}
}

View file

@ -308,6 +308,9 @@ NSTalkMonster::Speak(string sentence)
void
NSTalkMonster::TalkPlayerGreet(void)
{
if (HasSpawnFlags(MSF_GAG))
return;
if (m_iSequenceState != SEQUENCESTATE_NONE)
return;
@ -336,10 +339,12 @@ NSTalkMonster::TalkPlayerGreet(void)
void
NSTalkMonster::TalkPlayerIdle(void)
{
if (HasSpawnFlags(MSF_GAG))
return;
if (m_iSequenceState != SEQUENCESTATE_NONE)
return;
if (HasSpawnFlags(MSF_PREDISASTER))
return;
if (m_flNextSentence > time)
return;
@ -366,10 +371,12 @@ NSTalkMonster::TalkPlayerIdle(void)
void
NSTalkMonster::TalkPlayerAsk(void)
{
if (HasSpawnFlags(MSF_GAG))
return;
if (m_iSequenceState != SEQUENCESTATE_NONE)
return;
if (HasSpawnFlags(MSF_PREDISASTER))
return;
if (m_flNextSentence > time)
return;
@ -391,6 +398,9 @@ NSTalkMonster::TalkPlayerAsk(void)
void
NSTalkMonster::TalkPlayerWounded1(void)
{
if (HasSpawnFlags(MSF_GAG))
return;
if (m_iSequenceState != SEQUENCESTATE_NONE)
return;
@ -417,6 +427,9 @@ NSTalkMonster::TalkPlayerWounded1(void)
void
NSTalkMonster::TalkPlayerWounded2(void)
{
if (HasSpawnFlags(MSF_GAG))
return;
if (m_iSequenceState != SEQUENCESTATE_NONE)
return;
@ -444,6 +457,9 @@ NSTalkMonster::TalkPlayerWounded2(void)
void
NSTalkMonster::TalkPlayerWounded3(void)
{
if (HasSpawnFlags(MSF_GAG))
return;
if (m_iSequenceState != SEQUENCESTATE_NONE)
return;
@ -468,6 +484,9 @@ NSTalkMonster::TalkPlayerWounded3(void)
void
NSTalkMonster::TalkPanic(void)
{
if (HasSpawnFlags(MSF_GAG))
return;
if (m_iSequenceState != SEQUENCESTATE_NONE)
return;
@ -519,6 +538,9 @@ NSTalkMonster::TalkDenyFollow(void)
void
NSTalkMonster::Touch(entity eToucher)
{
if (eToucher == world)
return;
if (eToucher == m_eFollowing) {
makevectors(eToucher.angles);
velocity = v_forward * 250.0f;
@ -634,23 +656,35 @@ NSTalkMonster::FollowPlayer(void)
void
NSTalkMonster::PanicFrame(void)
{
float bestYaw = 0.0f;
float best_fraction = 0.0f;
float secondBest = 0.0f;
m_iFlags |= MONSTER_METPLAYER;
input_movevalues = [240, 0, 0];
if (m_flTraceTime < time) {
traceline(origin, origin + (v_forward * 64), FALSE, this);
if (trace_fraction < 1.0f) {
m_flChangePath = 0.0f;
for (float yaw = -180.0f; yaw < 180.0f; yaw += 1.0f) {
makevectors([0, yaw, 0]);
tracebox(origin, mins, maxs, origin + (v_forward * 1024), FALSE, this);
if (trace_startsolid) {
bestYaw = random(0, 360);
break;
}
if (trace_fraction > best_fraction) {
best_fraction = trace_fraction;
bestYaw = yaw;
}
}
m_flTraceTime = time + 0.5f;
angles[1] = Math_FixDelta(bestYaw + random(-25, 25));
input_angles[1] = angles[1];
v_angle[1] = angles[1];
m_flTraceTime = time + 0.5f + random();
}
if (m_flChangePath < time) {
input_angles[1] -= 180 + ((random() - 0.5) * 90);
input_angles[1] = Math_FixDelta(input_angles[1]);
m_flChangePath = time + floor(random(2,10));
}
if (m_flNextSentence > time)
return;
@ -1112,7 +1146,7 @@ NSTalkMonster_ParseSentence(void)
ent = findfloat(world, entnum, e);
if (ent) {
if (ent.classname != "NSTalkMonster" && ent.classname != "ambient_generic")
if (ent.classname != "speaker" && ent.classname != "NSTalkMonster" && ent.classname != "ambient_generic")
NSMonster_Log("^3 NSTalkMonster_ParseSentence ^7: Entity %d not a NSTalkMonster!", e);
else {
targ = (NSTalkMonster)ent;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2022 Vera Visions LLC.
* Copyright (c) 2016-2023 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
@ -25,6 +25,7 @@ typedef enum
ENT_PHYSICS, /**< of type NSPhysicsEntity */
ENT_MONSTER, /**< of type NSMonster */
ENT_TALKMONSTER, /**< of type NSTalkMonster */
ENT_SPEAKER, /**< of type speaker */
ENT_PLAYER, /**< of type NSClientPlayer */
ENT_WEAPON, /**< of type NSWeapon */
ENT_SPECTATOR, /**< of type NSClientSpectator */
@ -37,8 +38,9 @@ typedef enum
ENT_PROJECTEDTEXTURE, /**< of type env_projectedtexture */
ENT_SPOTLIGHT, /**< of type point_spotlight */
ENT_FOG, /*<< of type env_fog */
ENT_STEAM,
ENT_STEAM, /*<< of type env_steam */
ENT_FOGCONTROLLER, /**< of type env_fog_controller */
ENT_CASCADELIGHT, /*<< of type env_cascade_light */
ENT_LASER, /**< of type env_laser */
ENT_PARTSYSTEM, /**< of type info_particle_system */
ENT_SPRITE, /**< of type env_sprite */
@ -56,6 +58,7 @@ typedef enum
ENT_BUBBLES, /**< of type env_bubbles */
ENT_CONVEYOR, /**< of type func_conveyor */
ENT_WAYPOINT, /**< of type info_waypoint */
ENT_INSTRUCTOR, /**< of type env_instructor_hint */
ENT_PUSH, /**< of type trigger_push */
ENT_SEPARATOR, /**< This is a separator. This separator is used by you to add game-specific networked entities. When declaring your own entity-update types, you want the first value to equal ENT_SEPARATOR at all times to ensure you'll not be overriding existing slots. */
} entupdate_t;

View file

@ -59,5 +59,6 @@ enum
EV_BEAMCYLINDER,
EV_MUZZLEFLASH,
EV_TRACEDEBUG,
EV_ACHIEVEMENT,
EV_SEPARATOR
};