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)
|
||||
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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
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_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
|
||||
|
|
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.
|
||||
|
||||
![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
|
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.
|
||||
*/
|
||||
|
||||
#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
|
|
@ -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. */
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -59,5 +59,6 @@ enum
|
|||
EV_BEAMCYLINDER,
|
||||
EV_MUZZLEFLASH,
|
||||
EV_TRACEDEBUG,
|
||||
EV_ACHIEVEMENT,
|
||||
EV_SEPARATOR
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue