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:
parent
4790e9d230
commit
bf705a9e31
19 changed files with 1165 additions and 37 deletions
|
@ -51,6 +51,10 @@ Entity_EntityUpdate(float type, float new)
|
||||||
NSENTITY_READENTITY(NSTalkMonster, new)
|
NSENTITY_READENTITY(NSTalkMonster, new)
|
||||||
self.customphysics = Empty;
|
self.customphysics = Empty;
|
||||||
break;
|
break;
|
||||||
|
case ENT_SPEAKER:
|
||||||
|
NSENTITY_READENTITY(speaker, new)
|
||||||
|
self.customphysics = Empty;
|
||||||
|
break;
|
||||||
case ENT_VEHICLE:
|
case ENT_VEHICLE:
|
||||||
NSENTITY_READENTITY(NSVehicle, new)
|
NSENTITY_READENTITY(NSVehicle, new)
|
||||||
break;
|
break;
|
||||||
|
@ -122,6 +126,9 @@ Entity_EntityUpdate(float type, float new)
|
||||||
case ENT_FOGCONTROLLER:
|
case ENT_FOGCONTROLLER:
|
||||||
NSENTITY_READENTITY(env_fog_controller, new)
|
NSENTITY_READENTITY(env_fog_controller, new)
|
||||||
break;
|
break;
|
||||||
|
case ENT_CASCADELIGHT:
|
||||||
|
NSENTITY_READENTITY(env_cascade_light, new)
|
||||||
|
break;
|
||||||
case ENT_PARTSYSTEM:
|
case ENT_PARTSYSTEM:
|
||||||
NSENTITY_READENTITY(info_particle_system, new)
|
NSENTITY_READENTITY(info_particle_system, new)
|
||||||
break;
|
break;
|
||||||
|
@ -140,6 +147,9 @@ Entity_EntityUpdate(float type, float new)
|
||||||
case ENT_WAYPOINT:
|
case ENT_WAYPOINT:
|
||||||
NSENTITY_READENTITY(info_waypoint, new)
|
NSENTITY_READENTITY(info_waypoint, new)
|
||||||
break;
|
break;
|
||||||
|
case ENT_INSTRUCTOR:
|
||||||
|
NSENTITY_READENTITY(env_instructor_hint, new)
|
||||||
|
break;
|
||||||
case ENT_PUSH:
|
case ENT_PUSH:
|
||||||
NSENTITY_READENTITY(trigger_push, new)
|
NSENTITY_READENTITY(trigger_push, new)
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -165,6 +165,13 @@ EV_TraceDebug(void)
|
||||||
traceRep.angles = endOrg;
|
traceRep.angles = endOrg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EV_Achievement(void)
|
||||||
|
{
|
||||||
|
string eventName = readstring();
|
||||||
|
NSLog("EV_Achievement: %S", eventName);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Event_Parse(float type)
|
Event_Parse(float type)
|
||||||
{
|
{
|
||||||
|
@ -240,6 +247,9 @@ Event_Parse(float type)
|
||||||
case EV_TRACEDEBUG:
|
case EV_TRACEDEBUG:
|
||||||
EV_TraceDebug();
|
EV_TraceDebug();
|
||||||
break;
|
break;
|
||||||
|
case EV_ACHIEVEMENT:
|
||||||
|
EV_Achievement();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
error(sprintf("event id %d not recognized. abort immediately.\n", type));
|
error(sprintf("event id %d not recognized. abort immediately.\n", type));
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,12 +103,12 @@ server/trigger_once.qc
|
||||||
server/trigger_multiple.qc
|
server/trigger_multiple.qc
|
||||||
server/trigger_teleport.qc
|
server/trigger_teleport.qc
|
||||||
server/trigger_playerfreeze.qc
|
server/trigger_playerfreeze.qc
|
||||||
|
server/trigger_monsterjump.qc
|
||||||
server/trigger_relay.qc
|
server/trigger_relay.qc
|
||||||
server/env_shooter.qc
|
server/env_shooter.qc
|
||||||
server/gibshooter.qc
|
server/gibshooter.qc
|
||||||
server/env_beverage.qc
|
server/env_beverage.qc
|
||||||
server/item_food.qc
|
server/item_food.qc
|
||||||
server/speaker.qc
|
|
||||||
server/multi_manager.qc
|
server/multi_manager.qc
|
||||||
server/momentarybase.qc
|
server/momentarybase.qc
|
||||||
server/momentary_rot_button.qc
|
server/momentary_rot_button.qc
|
||||||
|
|
|
@ -30,3 +30,14 @@ If you don't want this entity to have collision, consider using func_detail_illu
|
||||||
# TRIVIA
|
# TRIVIA
|
||||||
This entity was introduced in Quake II (1997).
|
This entity was introduced in Quake II (1997).
|
||||||
*/
|
*/
|
||||||
|
class
|
||||||
|
func_detail:info_null
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void func_detail(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
func_detail::func_detail(void)
|
||||||
|
{
|
||||||
|
}
|
|
@ -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.
|
If you want this entity to have collision, consider using func_detail.
|
||||||
|
|
||||||
# TRIVIA
|
# 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)
|
||||||
|
{
|
||||||
|
}
|
|
@ -27,3 +27,14 @@ worldspawn upon compile.
|
||||||
# TRIVIA
|
# TRIVIA
|
||||||
This entity was introduced in Quake II (1997).
|
This entity was introduced in Quake II (1997).
|
||||||
*/
|
*/
|
||||||
|
class
|
||||||
|
func_group:info_null
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void func_group(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
func_group::func_group(void)
|
||||||
|
{
|
||||||
|
}
|
|
@ -168,9 +168,15 @@ light::SpawnKey(string strKey, string strValue)
|
||||||
case "_cone":
|
case "_cone":
|
||||||
case "_cone2":
|
case "_cone2":
|
||||||
case "_sky":
|
case "_sky":
|
||||||
case "pitch":
|
|
||||||
case "_light":
|
case "_light":
|
||||||
break;
|
break;
|
||||||
|
/* mostly for light_environment */
|
||||||
|
case "pitch":
|
||||||
|
angles[0] = ReadFloat(strValue);
|
||||||
|
break;
|
||||||
|
case "sunangle":
|
||||||
|
angles[1] = ReadFloat(strValue);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
super::SpawnKey(strKey, strValue);
|
super::SpawnKey(strKey, strValue);
|
||||||
}
|
}
|
||||||
|
@ -236,9 +242,22 @@ light::Trigger(entity act, triggermode_t state)
|
||||||
}
|
}
|
||||||
|
|
||||||
CLASSEXPORT(light_spot, light)
|
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)
|
/*!QUAKED light_surface (0 1 0) (-8 -8 -8) (8 8 8)
|
||||||
|
# OVERVIEW
|
||||||
Material property modifier related to lighting.
|
Material property modifier related to lighting.
|
||||||
|
|
||||||
# KEYS
|
# KEYS
|
||||||
|
|
|
@ -87,11 +87,3 @@ CLASSEXPORT(func_dustmotes, info_null)
|
||||||
CLASSEXPORT(env_soundscape, info_null)
|
CLASSEXPORT(env_soundscape, info_null)
|
||||||
CLASSEXPORT(env_cubemap, info_null)
|
CLASSEXPORT(env_cubemap, info_null)
|
||||||
CLASSEXPORT(sky_camera, info_null)
|
CLASSEXPORT(sky_camera, info_null)
|
||||||
|
|
||||||
void
|
|
||||||
env_glow(void)
|
|
||||||
{
|
|
||||||
if (self.model) {
|
|
||||||
precache_model(self.model);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
115
src/gs-entbase/server/trigger_monsterjump.qc
Normal file
115
src/gs-entbase/server/trigger_monsterjump.qc
Normal 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);
|
||||||
|
}
|
|
@ -15,12 +15,14 @@ shared/env_glow.qc
|
||||||
shared/env_projectedtexture.qc
|
shared/env_projectedtexture.qc
|
||||||
shared/env_fog.qc
|
shared/env_fog.qc
|
||||||
shared/env_fog_controller.qc
|
shared/env_fog_controller.qc
|
||||||
|
shared/env_cascade_light.qc
|
||||||
shared/env_smoker.qc
|
shared/env_smoker.qc
|
||||||
shared/env_muzzleflash.qc
|
shared/env_muzzleflash.qc
|
||||||
//shared/env_fire.qc
|
//shared/env_fire.qc
|
||||||
shared/env_steam.qc
|
shared/env_steam.qc
|
||||||
shared/env_shockwave.qc
|
shared/env_shockwave.qc
|
||||||
shared/light_dynamic.qc
|
shared/light_dynamic.qc
|
||||||
|
shared/logic_achievement.qc
|
||||||
shared/func_monitor.qc
|
shared/func_monitor.qc
|
||||||
shared/func_illusionary.qc
|
shared/func_illusionary.qc
|
||||||
shared/func_ladder.qc
|
shared/func_ladder.qc
|
||||||
|
@ -31,6 +33,7 @@ shared/trigger_camera.qc
|
||||||
shared/trigger_gravity.qc
|
shared/trigger_gravity.qc
|
||||||
shared/info_particle_system.qc
|
shared/info_particle_system.qc
|
||||||
shared/info_waypoint.qc
|
shared/info_waypoint.qc
|
||||||
|
shared/env_instructor_hint.qc
|
||||||
shared/prop_physics_multiplayer.qc
|
shared/prop_physics_multiplayer.qc
|
||||||
shared/prop_vehicle_driveable.qc
|
shared/prop_vehicle_driveable.qc
|
||||||
shared/point_spotlight.qc
|
shared/point_spotlight.qc
|
||||||
|
@ -39,4 +42,5 @@ shared/func_conveyor.qc
|
||||||
shared/prop_rope.qc
|
shared/prop_rope.qc
|
||||||
shared/phys_rope.qc
|
shared/phys_rope.qc
|
||||||
shared/worldspawn.qc
|
shared/worldspawn.qc
|
||||||
|
shared/speaker.qc
|
||||||
#endlist
|
#endlist
|
||||||
|
|
304
src/gs-entbase/shared/env_cascade_light.qc
Normal file
304
src/gs-entbase/shared/env_cascade_light.qc
Normal 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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
# 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
|
365
src/gs-entbase/shared/env_instructor_hint.qc
Normal file
365
src/gs-entbase/shared/env_instructor_hint.qc
Normal 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
|
156
src/gs-entbase/shared/logic_achievement.qc
Normal file
156
src/gs-entbase/shared/logic_achievement.qc
Normal 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
|
|
@ -14,6 +14,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef SERVER
|
||||||
enumflags
|
enumflags
|
||||||
{
|
{
|
||||||
SPEAKFL_SILENT
|
SPEAKFL_SILENT
|
||||||
|
@ -33,6 +34,7 @@ string g_speaker_hlpresets[] = {
|
||||||
"!C3A1_",
|
"!C3A1_",
|
||||||
"!C3A2_"
|
"!C3A2_"
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/*!QUAKED speaker (1 0 0) (-8 -8 -8) (8 8 8)
|
/*!QUAKED speaker (1 0 0) (-8 -8 -8) (8 8 8)
|
||||||
# OVERVIEW
|
# OVERVIEW
|
||||||
|
@ -70,6 +72,7 @@ speaker:NSTalkMonster
|
||||||
public:
|
public:
|
||||||
void speaker(void);
|
void speaker(void);
|
||||||
|
|
||||||
|
#ifdef SERVER
|
||||||
/* overrides */
|
/* overrides */
|
||||||
virtual void Save(float);
|
virtual void Save(float);
|
||||||
virtual void Restore(string,string);
|
virtual void Restore(string,string);
|
||||||
|
@ -79,18 +82,32 @@ public:
|
||||||
|
|
||||||
nonvirtual void Announce(void);
|
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:
|
private:
|
||||||
|
|
||||||
string m_strSentence;
|
string m_strSentence;
|
||||||
float m_flVolume;
|
float m_flVolume;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
speaker::speaker(void)
|
speaker::speaker(void)
|
||||||
{
|
{
|
||||||
|
#ifdef SERVER
|
||||||
m_strSentence = __NULL__;
|
m_strSentence = __NULL__;
|
||||||
m_flVolume = 1.0f;
|
m_flVolume = 1.0f;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SERVER
|
||||||
void
|
void
|
||||||
speaker::Save(float handle)
|
speaker::Save(float handle)
|
||||||
{
|
{
|
||||||
|
@ -139,10 +156,7 @@ speaker::SpawnKey(string strKey, string strValue)
|
||||||
void
|
void
|
||||||
speaker::Respawn(void)
|
speaker::Respawn(void)
|
||||||
{
|
{
|
||||||
/* force this thing to be networked */
|
|
||||||
SetModel("models/player.mdl");
|
|
||||||
SetOrigin(GetSpawnOrigin());
|
SetOrigin(GetSpawnOrigin());
|
||||||
Hide();
|
|
||||||
|
|
||||||
if (HasSpawnFlags(SPEAKFL_SILENT) == false)
|
if (HasSpawnFlags(SPEAKFL_SILENT) == false)
|
||||||
ScheduleThink(Announce, 10.0f);
|
ScheduleThink(Announce, 10.0f);
|
||||||
|
@ -173,3 +187,42 @@ speaker::Trigger(entity eAct, triggermode_t foo)
|
||||||
{
|
{
|
||||||
ScheduleThink(Announce, 0.0f);
|
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
|
|
@ -381,6 +381,8 @@ public:
|
||||||
|
|
||||||
/** Returns TRUE if 'enemy' should be considered a valid target for killing */
|
/** Returns TRUE if 'enemy' should be considered a valid target for killing */
|
||||||
nonvirtual bool IsValidEnemy(entity);
|
nonvirtual bool IsValidEnemy(entity);
|
||||||
|
/** Returns TRUE if the monster is currently on route to a position. */
|
||||||
|
virtual bool IsOnRoute(void);
|
||||||
|
|
||||||
/* sequences */
|
/* sequences */
|
||||||
/** Internal use only. Called when a sequence is done. */
|
/** Internal use only. Called when a sequence is done. */
|
||||||
|
|
|
@ -646,6 +646,12 @@ NSMonster::IsValidEnemy(entity enny)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
NSMonster::IsOnRoute(void)
|
||||||
|
{
|
||||||
|
return (m_iNodes || m_pathTarget) && (GetState() == MONSTER_IDLE || GetState() == MONSTER_ALERT) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
NSMonster_TraceAgainsTarget(NSMonster monster, NSEntity target)
|
NSMonster_TraceAgainsTarget(NSMonster monster, NSEntity target)
|
||||||
{
|
{
|
||||||
|
@ -1258,12 +1264,11 @@ NSMonster::RouteEnded(void)
|
||||||
void
|
void
|
||||||
NSMonster::WalkRoute(void)
|
NSMonster::WalkRoute(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* we're busy shooting at something, don't walk */
|
/* we're busy shooting at something, don't walk */
|
||||||
if (GetState() == MONSTER_AIMING && m_eEnemy) {
|
if (GetState() == MONSTER_AIMING && m_eEnemy) {
|
||||||
input_angles = vectoangles(m_eEnemy.origin - origin);
|
input_angles = vectoangles(m_eEnemy.origin - origin);
|
||||||
input_angles[0] = input_angles[2] = 0;
|
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 = GetRouteDirection();
|
||||||
input_angles[0] = input_angles[2] = 0;
|
input_angles[0] = input_angles[2] = 0;
|
||||||
input_movevalues = GetRouteMovevalues() * m_flSequenceSpeed;
|
input_movevalues = GetRouteMovevalues() * m_flSequenceSpeed;
|
||||||
|
@ -1548,8 +1553,30 @@ NSMonster::Touch(entity eToucher)
|
||||||
|
|
||||||
if (autocvar(pm_pushMonsters, 0))
|
if (autocvar(pm_pushMonsters, 0))
|
||||||
if (eToucher.movetype == MOVETYPE_WALK) {
|
if (eToucher.movetype == MOVETYPE_WALK) {
|
||||||
if (eToucher.absmin[2] < origin[2])
|
if (eToucher.absmin[2] < origin[2]) {
|
||||||
velocity = normalize(eToucher.origin - origin) * -128;
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -308,6 +308,9 @@ NSTalkMonster::Speak(string sentence)
|
||||||
void
|
void
|
||||||
NSTalkMonster::TalkPlayerGreet(void)
|
NSTalkMonster::TalkPlayerGreet(void)
|
||||||
{
|
{
|
||||||
|
if (HasSpawnFlags(MSF_GAG))
|
||||||
|
return;
|
||||||
|
|
||||||
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -336,10 +339,12 @@ NSTalkMonster::TalkPlayerGreet(void)
|
||||||
void
|
void
|
||||||
NSTalkMonster::TalkPlayerIdle(void)
|
NSTalkMonster::TalkPlayerIdle(void)
|
||||||
{
|
{
|
||||||
|
if (HasSpawnFlags(MSF_GAG))
|
||||||
|
return;
|
||||||
|
|
||||||
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
||||||
return;
|
return;
|
||||||
if (HasSpawnFlags(MSF_PREDISASTER))
|
|
||||||
return;
|
|
||||||
if (m_flNextSentence > time)
|
if (m_flNextSentence > time)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -366,10 +371,12 @@ NSTalkMonster::TalkPlayerIdle(void)
|
||||||
void
|
void
|
||||||
NSTalkMonster::TalkPlayerAsk(void)
|
NSTalkMonster::TalkPlayerAsk(void)
|
||||||
{
|
{
|
||||||
|
if (HasSpawnFlags(MSF_GAG))
|
||||||
|
return;
|
||||||
|
|
||||||
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
||||||
return;
|
return;
|
||||||
if (HasSpawnFlags(MSF_PREDISASTER))
|
|
||||||
return;
|
|
||||||
if (m_flNextSentence > time)
|
if (m_flNextSentence > time)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -391,6 +398,9 @@ NSTalkMonster::TalkPlayerAsk(void)
|
||||||
void
|
void
|
||||||
NSTalkMonster::TalkPlayerWounded1(void)
|
NSTalkMonster::TalkPlayerWounded1(void)
|
||||||
{
|
{
|
||||||
|
if (HasSpawnFlags(MSF_GAG))
|
||||||
|
return;
|
||||||
|
|
||||||
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -417,6 +427,9 @@ NSTalkMonster::TalkPlayerWounded1(void)
|
||||||
void
|
void
|
||||||
NSTalkMonster::TalkPlayerWounded2(void)
|
NSTalkMonster::TalkPlayerWounded2(void)
|
||||||
{
|
{
|
||||||
|
if (HasSpawnFlags(MSF_GAG))
|
||||||
|
return;
|
||||||
|
|
||||||
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -444,6 +457,9 @@ NSTalkMonster::TalkPlayerWounded2(void)
|
||||||
void
|
void
|
||||||
NSTalkMonster::TalkPlayerWounded3(void)
|
NSTalkMonster::TalkPlayerWounded3(void)
|
||||||
{
|
{
|
||||||
|
if (HasSpawnFlags(MSF_GAG))
|
||||||
|
return;
|
||||||
|
|
||||||
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -468,6 +484,9 @@ NSTalkMonster::TalkPlayerWounded3(void)
|
||||||
void
|
void
|
||||||
NSTalkMonster::TalkPanic(void)
|
NSTalkMonster::TalkPanic(void)
|
||||||
{
|
{
|
||||||
|
if (HasSpawnFlags(MSF_GAG))
|
||||||
|
return;
|
||||||
|
|
||||||
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -519,6 +538,9 @@ NSTalkMonster::TalkDenyFollow(void)
|
||||||
void
|
void
|
||||||
NSTalkMonster::Touch(entity eToucher)
|
NSTalkMonster::Touch(entity eToucher)
|
||||||
{
|
{
|
||||||
|
if (eToucher == world)
|
||||||
|
return;
|
||||||
|
|
||||||
if (eToucher == m_eFollowing) {
|
if (eToucher == m_eFollowing) {
|
||||||
makevectors(eToucher.angles);
|
makevectors(eToucher.angles);
|
||||||
velocity = v_forward * 250.0f;
|
velocity = v_forward * 250.0f;
|
||||||
|
@ -634,23 +656,35 @@ NSTalkMonster::FollowPlayer(void)
|
||||||
void
|
void
|
||||||
NSTalkMonster::PanicFrame(void)
|
NSTalkMonster::PanicFrame(void)
|
||||||
{
|
{
|
||||||
|
float bestYaw = 0.0f;
|
||||||
|
float best_fraction = 0.0f;
|
||||||
|
float secondBest = 0.0f;
|
||||||
|
|
||||||
m_iFlags |= MONSTER_METPLAYER;
|
m_iFlags |= MONSTER_METPLAYER;
|
||||||
input_movevalues = [240, 0, 0];
|
input_movevalues = [240, 0, 0];
|
||||||
|
|
||||||
if (m_flTraceTime < time) {
|
if (m_flTraceTime < time) {
|
||||||
traceline(origin, origin + (v_forward * 64), FALSE, this);
|
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_fraction < 1.0f) {
|
if (trace_startsolid) {
|
||||||
m_flChangePath = 0.0f;
|
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)
|
if (m_flNextSentence > time)
|
||||||
return;
|
return;
|
||||||
|
@ -1112,7 +1146,7 @@ NSTalkMonster_ParseSentence(void)
|
||||||
ent = findfloat(world, entnum, e);
|
ent = findfloat(world, entnum, e);
|
||||||
|
|
||||||
if (ent) {
|
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);
|
NSMonster_Log("^3 NSTalkMonster_ParseSentence ^7: Entity %d not a NSTalkMonster!", e);
|
||||||
else {
|
else {
|
||||||
targ = (NSTalkMonster)ent;
|
targ = (NSTalkMonster)ent;
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -25,6 +25,7 @@ typedef enum
|
||||||
ENT_PHYSICS, /**< of type NSPhysicsEntity */
|
ENT_PHYSICS, /**< of type NSPhysicsEntity */
|
||||||
ENT_MONSTER, /**< of type NSMonster */
|
ENT_MONSTER, /**< of type NSMonster */
|
||||||
ENT_TALKMONSTER, /**< of type NSTalkMonster */
|
ENT_TALKMONSTER, /**< of type NSTalkMonster */
|
||||||
|
ENT_SPEAKER, /**< of type speaker */
|
||||||
ENT_PLAYER, /**< of type NSClientPlayer */
|
ENT_PLAYER, /**< of type NSClientPlayer */
|
||||||
ENT_WEAPON, /**< of type NSWeapon */
|
ENT_WEAPON, /**< of type NSWeapon */
|
||||||
ENT_SPECTATOR, /**< of type NSClientSpectator */
|
ENT_SPECTATOR, /**< of type NSClientSpectator */
|
||||||
|
@ -37,8 +38,9 @@ typedef enum
|
||||||
ENT_PROJECTEDTEXTURE, /**< of type env_projectedtexture */
|
ENT_PROJECTEDTEXTURE, /**< of type env_projectedtexture */
|
||||||
ENT_SPOTLIGHT, /**< of type point_spotlight */
|
ENT_SPOTLIGHT, /**< of type point_spotlight */
|
||||||
ENT_FOG, /*<< of type env_fog */
|
ENT_FOG, /*<< of type env_fog */
|
||||||
ENT_STEAM,
|
ENT_STEAM, /*<< of type env_steam */
|
||||||
ENT_FOGCONTROLLER, /**< of type env_fog_controller */
|
ENT_FOGCONTROLLER, /**< of type env_fog_controller */
|
||||||
|
ENT_CASCADELIGHT, /*<< of type env_cascade_light */
|
||||||
ENT_LASER, /**< of type env_laser */
|
ENT_LASER, /**< of type env_laser */
|
||||||
ENT_PARTSYSTEM, /**< of type info_particle_system */
|
ENT_PARTSYSTEM, /**< of type info_particle_system */
|
||||||
ENT_SPRITE, /**< of type env_sprite */
|
ENT_SPRITE, /**< of type env_sprite */
|
||||||
|
@ -56,6 +58,7 @@ typedef enum
|
||||||
ENT_BUBBLES, /**< of type env_bubbles */
|
ENT_BUBBLES, /**< of type env_bubbles */
|
||||||
ENT_CONVEYOR, /**< of type func_conveyor */
|
ENT_CONVEYOR, /**< of type func_conveyor */
|
||||||
ENT_WAYPOINT, /**< of type info_waypoint */
|
ENT_WAYPOINT, /**< of type info_waypoint */
|
||||||
|
ENT_INSTRUCTOR, /**< of type env_instructor_hint */
|
||||||
ENT_PUSH, /**< of type trigger_push */
|
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. */
|
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;
|
} entupdate_t;
|
||||||
|
|
|
@ -59,5 +59,6 @@ enum
|
||||||
EV_BEAMCYLINDER,
|
EV_BEAMCYLINDER,
|
||||||
EV_MUZZLEFLASH,
|
EV_MUZZLEFLASH,
|
||||||
EV_TRACEDEBUG,
|
EV_TRACEDEBUG,
|
||||||
|
EV_ACHIEVEMENT,
|
||||||
EV_SEPARATOR
|
EV_SEPARATOR
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue