diff --git a/src/gs-entbase/server.src b/src/gs-entbase/server.src index c8a442ff..626f3f42 100644 --- a/src/gs-entbase/server.src +++ b/src/gs-entbase/server.src @@ -13,6 +13,8 @@ server/info_hint.qc server/button_target.qc server/cycler.qc server/cycler_sprite.qc +server/cycler_weapon.qc +server/cycler_wreckage.qc server/env_fade.qc server/env_hudhint.qc server/env_spark.qc @@ -25,7 +27,15 @@ server/env_model.qc server/game_text.qc server/game_counter.qc server/game_counter_set.qc +server/game_end.qc server/game_player_equip.qc +server/game_player_hurt.qc +server/game_score.qc +server/multisource.qc +server/game_team_master.qc +server/game_team_set.qc +server/game_player_team.qc +server/game_zone_player.qc server/path_corner.qc server/path_track.qc server/func_areaportal.qc @@ -107,7 +117,6 @@ server/func_mortar_field.qc server/monster_furniture.qc server/monster_generic.qc server/monstermaker.qc -server/multisource.qc server/prop_door_rotating.qc server/random_speaker.qc server/random_trigger.qc diff --git a/src/gs-entbase/server/cycler_weapon.qc b/src/gs-entbase/server/cycler_weapon.qc new file mode 100644 index 00000000..41249dff --- /dev/null +++ b/src/gs-entbase/server/cycler_weapon.qc @@ -0,0 +1,32 @@ +/* + * 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 cycler_weapon (1 .5 0) (-8 -8 -8) (8 8 8) +# OVERVIEW +A development entity. When picked up, will display the viewmodel on the activating player. + +# KEYS +- "targetname" : Name +- "model" : Model to display on the player. + +# TRIVIA +This entity was introduced in Half-Life (1998). +*/ +class +cycler_weapon:NSPointTrigger +{ + +}; \ No newline at end of file diff --git a/src/gs-entbase/server/cycler_wreckage.qc b/src/gs-entbase/server/cycler_wreckage.qc new file mode 100644 index 00000000..bd46e3ed --- /dev/null +++ b/src/gs-entbase/server/cycler_wreckage.qc @@ -0,0 +1,52 @@ +/*!QUAKED cycler_wreckage (1 .5 0) (-8 -8 -8) (8 8 8) +# OVERVIEW +A env_sprite with smoke all around it. + +# KEYS +- "targetname" : Name +- "model" : Model to display on the player. +- "scale" : Scale of the sprite. + +# TRIVIA +This entity was introduced in Half-Life (1998). +*/ +class +cycler_wreckage:NSRenderableEntity +{ +public: + void cycler_wreckage(void); + + virtual void Spawned(void); + virtual void OnRemoveEntity(void); + +private: + NSEntity m_eSmoke; +}; + +void +cycler_wreckage::cycler_wreckage(void) +{ + m_eSmoke = __NULL__; +} + +void +cycler_wreckage::Spawned(void) +{ + super::Spawned(); + + if (!m_eSmoke) { + m_eSmoke = NSEntity_SpawnClass("env_smoker", GetOrigin(), [-90.0f, 0.0f, 0.0f]); + m_eSmoke.Input(this, "SetScale", "128"); + m_eSmoke.Input(this, "SetDispersion", "4"); + m_eSmoke.Input(this, "SetDuration", "-1"); + m_eSmoke.Respawn(); + m_eSmoke.ReleaseThink(); + } +} +void +cycler_wreckage::OnRemoveEntity(void) +{ + if (m_eSmoke) { + m_eSmoke.Destroy(); + } +} \ No newline at end of file diff --git a/src/gs-entbase/server/game_end.qc b/src/gs-entbase/server/game_end.qc new file mode 100644 index 00000000..19742273 --- /dev/null +++ b/src/gs-entbase/server/game_end.qc @@ -0,0 +1,50 @@ +/* + * 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 game_end (1 .5 0) (-8 -8 -8) (8 8 8) +# OVERVIEW +Upon being triggered, the intermission secret will commence in multiplayer games. + +# KEYS +- "targetname" : Name +- "master" : Name of the multisource regulating its usage. + +# TRIVIA +This entity was introduced in Half-Life (1998). +*/ +class +game_end:NSEntity +{ +public: + void game_end(void); + + virtual void Trigger(entity, triggermode_t); +}; + +void +game_end::game_end(void) +{ +} + +void +game_end::Trigger(entity activatingEntity, triggermode_t triggerMode) +{ + if (GetMaster() == FALSE) { + return; + } + + g_grMode.IntermissionStart(); +} \ No newline at end of file diff --git a/src/gs-entbase/server/game_player_equip.qc b/src/gs-entbase/server/game_player_equip.qc index ac00539f..3d75c285 100644 --- a/src/gs-entbase/server/game_player_equip.qc +++ b/src/gs-entbase/server/game_player_equip.qc @@ -27,6 +27,13 @@ Entity that emits items when triggered, or upon player spawn (MP-only). - "targetname" : Name - "master" : Team Master +And any weapon or item you want to give to the player, you will list as a key, +with the value being the amount of items of that type. + +For example: + +`"weapon_pistol" "1"` + # SPAWNFLAGS - GPEFL_TRIGGERONLY (1) : See notes. @@ -34,6 +41,7 @@ Entity that emits items when triggered, or upon player spawn (MP-only). When the flag GPEFL_TRIGGERONLY is set, the entity has to be triggered in order to 'give' the activator the item. Otherwise it'll automatically 'give' every client its noted items upon spawning. + However, this only applies to Multiplayer games. In Singleplayer, the entity will only work with GPEFL_TRIGGERONLY being set. diff --git a/src/gs-entbase/server/game_player_hurt.qc b/src/gs-entbase/server/game_player_hurt.qc new file mode 100644 index 00000000..3019a7d6 --- /dev/null +++ b/src/gs-entbase/server/game_player_hurt.qc @@ -0,0 +1,100 @@ +/* + * 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 game_player_hurt (1 .5 0) (-8 -8 -8) (8 8 8) REMOVE +# OVERVIEW +Upon being triggered, the entity will damage/heal the activating player. + +# KEYS +- "targetname" : Name +- "dmg" : Damage value to apply to a player. +- "master" : Name of the multisource regulating its usage. + + +# SPAWNFLAGS +- REMOVE (1) : Remove after being triggered. + +# TRIVIA +This entity was introduced in Half-Life (1998). +*/ +class +game_player_hurt:NSEntity +{ +public: + void game_player_hurt(void); + + virtual void SpawnKey(string, string); + virtual void Save(float); + virtual void Restore(string,string); + virtual void Trigger(entity, triggermode_t); + +private: + int m_iDamage; +}; + +void +game_player_hurt::game_player_hurt(void) +{ + m_iDamage = 0i; +} + +void +game_player_hurt::SpawnKey(string keyName, string setValue) +{ + switch (keyName) { + case "dmg": + m_iDamage = ReadInt(setValue); + break; + default: + super::SpawnKey(keyName, setValue); + } +} + +void +game_player_hurt::Save(float handle) +{ + super::Save(handle); + SaveInt(handle, "m_iDamage", m_iDamage); +} + +void +game_player_hurt::Restore(string strKey, string strValue) +{ + switch (strKey) { + case "m_iDamage": + m_iDamage = ReadInt(strValue); + break; + default: + super::Restore(strKey, strValue); + } +} + +void +game_player_hurt::Trigger(entity activatingEntity, triggermode_t triggerMode) +{ + if (GetMaster() == FALSE) { + return; + } + if (!(activatingEntity.flags & FL_CLIENT)) { + return; + } + + Damage_Apply(activatingEntity, world, m_iDamage, 0, 0); + + if (HasSpawnFlags(1)) { + Destroy(); + } +} \ No newline at end of file diff --git a/src/gs-entbase/server/game_player_team.qc b/src/gs-entbase/server/game_player_team.qc new file mode 100644 index 00000000..4706b7cc --- /dev/null +++ b/src/gs-entbase/server/game_player_team.qc @@ -0,0 +1,77 @@ +/* + * 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 game_player_team (1 .5 0) (-8 -8 -8) (8 8 8) REMOVE KILL GIB +# OVERVIEW +Allows the player to change teams. + +# KEYS +- "targetname" : Name +- "master" : Name of the multisource or game_team_master regulating this entity. +- "target" : Name of the game_team_master that specifies the new team. + +# SPAWNFLAGS +- REMOVE (1) : Will be removed once triggered. +- KILL (2) : Kills the player when activated. +- GIB (4) : Gibs the player when activated. + +# TRIVIA +This entity was introduced in Half-Life (1998). +*/ +class +game_player_team:NSPointTrigger +{ +public: + void game_player_team(void); + + virtual void Trigger(entity, triggermode_t); +}; + +void +game_player_team::game_player_team(void) +{ +} + +void +game_player_team::Trigger(entity entityActivator, triggermode_t state) +{ + NSClientPlayer targetPlayer = __NULL__; + game_team_master toRead = __NULL__; + + if (GetMaster() == FALSE) { + return; + } + + toRead = (game_team_master)GetTargetEntity(); + + if (!toRead) { + NSEntWarning("Unable to find game_team_master named %S", GetTriggerTarget()); + return; + } + + targetPlayer = (NSClientPlayer)entityActivator; + targetPlayer.SetTeam((float)toRead.GetTeamIndex()); + + if (HasSpawnFlags(4) == true) { + Damage_Apply(targetPlayer, targetPlayer, targetPlayer.health + 100i, 0, DMG_SKIP_ARMOR); + } else if (HasSpawnFlags(2) == true) { + Damage_Apply(targetPlayer, targetPlayer, targetPlayer.health, 0, DMG_SKIP_ARMOR); + } + + if (HasSpawnFlags(1)) { + Destroy(); + } +} \ No newline at end of file diff --git a/src/gs-entbase/server/game_score.qc b/src/gs-entbase/server/game_score.qc new file mode 100644 index 00000000..7726b28d --- /dev/null +++ b/src/gs-entbase/server/game_score.qc @@ -0,0 +1,107 @@ +/* + * 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 game_score (1 .5 0) (-8 -8 -8) (8 8 8) NEGATIVE TEAMSCORE +# OVERVIEW +Awards points to the activator when triggered. + +# KEYS +- "targetname" : Name +- "master" : Name of the multisource or game_team_master regulating this entity. +- "points" : Amount of points to add. + +# SPAWNFLAGS +- NEGATIVE (1) : Allow negative values. +- TEAMSCORE (2) : Will affect whole team their score. + +# TRIVIA +This entity was introduced in Half-Life (1998). +*/ +class +game_score:NSPointTrigger +{ +public: + void game_score(void); + + virtual void Save(float); + virtual void Restore(string, string); + virtual void SpawnKey(string, string); + virtual void Trigger(entity, triggermode_t); + +private: + int m_iPoints; +}; + +void +game_score::game_score(void) +{ + m_iPoints = 0i; +} + +void +game_score::Save(float handle) +{ + SaveInt(handle, "m_iPoints", m_iPoints); +} + +void +game_score::Restore(string keyName, string setValue) +{ + switch (keyName) { + case "m_iPoints": + m_iPoints = ReadInt(setValue); + break; + default: + super::Restore(keyName, setValue); + } +} + +void +game_score::SpawnKey(string keyName, string setValue) +{ + switch (keyName) { + case "points": + m_iPoints = ReadInt(setValue); + break; + default: + super::SpawnKey(keyName, setValue); + } +} + +void +game_score::Trigger(entity entityActivator, triggermode_t state) +{ + int toAdd = m_iPoints; + + if (GetMaster() == FALSE) { + return; + } + + /* don't allow negative values. */ + if (HasSpawnFlags(1) == false) { + toAdd = m_iPoints < 0i ? 0i : m_iPoints; + } + + if (HasSpawnFlags(2) == false) { + entityActivator.frags += (float)toAdd; + } else { + int targetTeam = (int)entityActivator.team; + string targetKey = sprintf("teamscore_%i", targetTeam); + int currentPoints = (int)serverkeyfloat(targetKey); + string targetValue = sprintf("%i", currentPoints + toAdd); + forceinfokey(world, targetKey, targetValue); + } +} \ No newline at end of file diff --git a/src/gs-entbase/server/game_team_master.qc b/src/gs-entbase/server/game_team_master.qc new file mode 100644 index 00000000..264fedf6 --- /dev/null +++ b/src/gs-entbase/server/game_team_master.qc @@ -0,0 +1,138 @@ +/* + * 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 game_team_master (1 .5 0) (-8 -8 -8) (8 8 8) REMOVE +# OVERVIEW +Regulates triggers in team based modes. + +# KEYS +- "targetname" : Name +- "master" : Name of the multisource or game_team_master regulating this entity. +- "target" : Name of the entity to trigger. +- "triggerstate" : Desired trigger state. +- "teamindex" : Which team to affect. -1 means none. + +# SPAWNFLAGS +- REMOVE (1) : Will be removed once triggered. + +# TRIVIA +This entity was introduced in Half-Life (1998). +*/ +class +game_team_master:multisource +{ +public: + void game_team_master(void); + + virtual void Save(float); + virtual void Restore(string,string); + virtual void SpawnKey(string, string); + virtual void Input(entity, string, string); + virtual void Trigger(entity, triggermode_t); + + nonvirtual void SetTeamIndex(int); + nonvirtual int GetTeamIndex(void); + +private: + int m_iTeamIndex; + triggermode_t m_iTriggerState; +}; + +void +game_team_master::game_team_master(void) +{ + m_iTeamIndex = 0i; + m_iTriggerState = TRIG_TOGGLE; +} + +void +game_team_master::Save(float handle) +{ + super::Save(handle); + SaveFloat(handle, "m_iTriggerState", m_iTriggerState); + SaveInt(handle, "m_iTeamIndex", m_iTeamIndex); +} + +void +game_team_master::Restore(string keyName, string setValue) +{ + switch (keyName) { + case "m_iTriggerState": + m_iTriggerState = ReadFloat(setValue); + break; + case "m_iTeamIndex": + m_iTeamIndex = ReadInt(setValue); + break; + default: + super::Restore(keyName, setValue); + } +} + +void +game_team_master::SpawnKey(string keyName, string setValue) +{ + switch (keyName) { + case "triggerstate": + m_iTriggerState = ReadInt(setValue); + break; + case "teamindex": + m_iTeamIndex = ReadInt(setValue); + break; + default: + super::SpawnKey(keyName, setValue); + } +} + +void +game_team_master::Trigger(entity entityActivator, triggermode_t state) +{ + if (GetMaster() == FALSE) { + return; + } + + if (m_iTeamIndex != -1i) { + if (entityActivator.team != (float)m_iTeamIndex) { + return; + } + } + + super::Trigger(entityActivator, state); +} + +void +game_team_master::Input(entity entityActivator, string inputName, string dataField) +{ + switch (inputName) { + case "SetTeamIndex": + SetTeamIndex(ReadInt(dataField)); + break; + default: + super::Input(entityActivator, inputName, dataField); + break; + } +} + +void +game_team_master::SetTeamIndex(int newIndex) +{ + m_iTeamIndex = newIndex; +} + +int +game_team_master::GetTeamIndex(void) +{ + return m_iTeamIndex; +} \ No newline at end of file diff --git a/src/gs-entbase/server/game_team_set.qc b/src/gs-entbase/server/game_team_set.qc new file mode 100644 index 00000000..f683f41d --- /dev/null +++ b/src/gs-entbase/server/game_team_set.qc @@ -0,0 +1,67 @@ +/* + * 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 game_team_set (1 .5 0) (-8 -8 -8) (8 8 8) REMOVE +# OVERVIEW +When triggered, will set the target game_team_master's team-index value to the team of the activating player. + +# KEYS +- "targetname" : Name +- "master" : Name of the multisource or game_team_master regulating this entity. +- "target" : The name of the game_team_master we'll be affecting. + +# SPAWNFLAGS +- REMOVE (1) : Will be removed once triggered. + +# TRIVIA +This entity was introduced in Half-Life (1998). +*/ +class +game_team_set:NSPointTrigger +{ +public: + void game_team_set(void); + + virtual void Trigger(entity, triggermode_t); +}; + +void +game_team_set::game_team_set(void) +{ +} + +void +game_team_set::Trigger(entity activatorEntity, triggermode_t state) +{ + game_team_master toChange = __NULL__; + + if (GetMaster() == FALSE) { + return; + } + + toChange = (game_team_master)GetTargetEntity(); + + if (!toChange) { + NSEntWarning("Unable to find game_team_master named %S", GetTriggerTarget()); + return; + } + + toChange.SetTeamIndex((int)activatorEntity.team); + + if (HasSpawnFlags(1)) { + Destroy(); + } +} \ No newline at end of file diff --git a/src/gs-entbase/server/game_zone_player.qc b/src/gs-entbase/server/game_zone_player.qc new file mode 100644 index 00000000..667439a3 --- /dev/null +++ b/src/gs-entbase/server/game_zone_player.qc @@ -0,0 +1,157 @@ +/* + * 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 game_zone_player (1 .5 0) ? +# OVERVIEW +When triggered, will cause players inside/outside this volume to trigger entities. It also has the ability to set game_counter entities to the amount of players inside/outside of the volume. + +# KEYS +- "targetname" : Name +- "intarget" : Target that the players inside this volume will trigger. +- "outtarget" : Target that the players outside this volume will trigger. +- "incount" : Specifies the game_counter which will be set to the 'in' player count. +- "outcount" : Specifies the game_counter which will be set to the 'out' player count. + +# TRIVIA +This entity was introduced in Half-Life (1998). +*/ +class +game_zone_player:NSBrushTrigger +{ +public: + void game_zone_player(void); + + virtual void Save(float); + virtual void Restore(string, string); + virtual void SpawnKey(string, string); + virtual void Respawn(void); + virtual void Trigger(entity, triggermode_t); + +private: + string m_strInTarget; + string m_strOutTarget; + string m_strInCount; + string m_strOutCount; +}; + +void +game_zone_player::game_zone_player(void) +{ + m_strInTarget = __NULL__; + m_strOutTarget = __NULL__; + m_strInCount = __NULL__; + m_strOutCount = __NULL__; +} + +void +game_zone_player::Save(float handle) +{ + super::Save(handle); + + SaveString(handle, "m_strInTarget", m_strInTarget); + SaveString(handle, "m_strOutTarget", m_strOutTarget); + SaveString(handle, "m_strInCount", m_strInCount); + SaveString(handle, "m_strOutCount", m_strOutCount); +} + +void +game_zone_player::Restore(string strKey, string strValue) +{ + switch (strKey) { + case "m_strInTarget": + m_strInTarget = ReadString(strValue); + break; + case "m_strOutTarget": + m_strOutTarget = ReadString(strValue); + break; + case "m_strInCount": + m_strInCount = ReadString(strValue); + break; + case "m_strOutCount": + m_strOutCount = ReadString(strValue); + break; + default: + super::Restore(strKey, strValue); + } +} + +void +game_zone_player::SpawnKey(string keyName, string setValue) +{ + switch (keyName) { + case "intarget": + m_strInTarget = ReadString(setValue); + break; + case "incount": + m_strInCount = ReadString(setValue); + break; + case "outtarget": + m_strOutTarget = ReadString(setValue); + break; + case "outcount": + m_strOutCount = ReadString(setValue); + break; + default: + super::SpawnKey(keyName, setValue); + } +} + +void +game_zone_player::Respawn(void) +{ + InitBrushTrigger(); +} + +void +game_zone_player::Trigger(entity entityActivator, triggermode_t state) +{ + int playersIn = 0i; + int playersOut = 0i; + NSEntity inTarget = (NSEntity)find(world, ::targetname, m_strInTarget); + NSEntity outTarget = (NSEntity)find(world, ::targetname, m_strOutTarget); + + for (other = world; (other = find(other, ::classname, "player"));) { + if (IntersectsWith(other)) { + if (inTarget) { + inTarget.Trigger(other, state); + } + playersIn++; + } else { + if (outTarget) { + outTarget.Trigger(other, state); + } + playersOut++; + } + } + + if (m_strInCount) { + game_counter inCounter = (game_counter)find(world, ::targetname, m_strInCount); + + if (inCounter) { + inCounter.SetCount(playersIn); + inCounter.Trigger(entityActivator, TRIG_TOGGLE); + } + } + + if (m_strOutCount) { + game_counter outCounter = (game_counter)find(world, ::targetname, m_strOutCount); + + if (outCounter) { + outCounter.SetCount(playersIn); + outCounter.Trigger(entityActivator, TRIG_TOGGLE); + } + } +} \ No newline at end of file diff --git a/src/gs-entbase/server/monster_furniture.qc b/src/gs-entbase/server/monster_furniture.qc index d7b2e560..73e59115 100644 --- a/src/gs-entbase/server/monster_furniture.qc +++ b/src/gs-entbase/server/monster_furniture.qc @@ -28,7 +28,7 @@ enumflags /*!QUAKED monster_furniture (1 0 0) (-8 -8 -8) (8 8 8) # OVERVIEW -Decorative, does nothing yet. +A non-solid, decorative, entity. # KEYS - "targetname" : Name diff --git a/src/gs-entbase/server/monster_generic.qc b/src/gs-entbase/server/monster_generic.qc index 2aa21011..ac419aa2 100644 --- a/src/gs-entbase/server/monster_generic.qc +++ b/src/gs-entbase/server/monster_generic.qc @@ -14,9 +14,11 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define MGF_NONSOLID 4 + /*!QUAKED monster_generic (1 0 0) (-8 -8 -8) (8 8 8) x x MGF_NONSOLID # OVERVIEW -Decorative, does nothing yet. +A 'monster' that is able to bleed, speak and follow scripted sequences. # KEYS - "targetname" : Name @@ -29,9 +31,6 @@ Decorative, does nothing yet. # TRIVIA This entity was introduced in Half-Life (1998). */ - -#define MGF_NONSOLID 4 - class monster_generic:NSTalkMonster { diff --git a/src/gs-entbase/server/speaker.qc b/src/gs-entbase/server/speaker.qc index 052777ed..2b410701 100644 --- a/src/gs-entbase/server/speaker.qc +++ b/src/gs-entbase/server/speaker.qc @@ -142,8 +142,7 @@ speaker::Respawn(void) /* force this thing to be networked */ SetModel("models/player.mdl"); SetOrigin(GetSpawnOrigin()); - SetRenderMode(RM_COLOR); - SetRenderAmt(0); + Hide(); if (HasSpawnFlags(SPEAKFL_SILENT) == false) ScheduleThink(Announce, 10.0f); diff --git a/src/gs-entbase/server/trigger_relay.qc b/src/gs-entbase/server/trigger_relay.qc index 23f3f767..8bd02c41 100644 --- a/src/gs-entbase/server/trigger_relay.qc +++ b/src/gs-entbase/server/trigger_relay.qc @@ -90,7 +90,7 @@ trigger_relay::SpawnKey(string strKey, string strValue) { switch (strKey) { case "triggerstate": - m_iTriggerState = stoi(strValue); + m_iTriggerState = ReadInt(strValue); break; default: super::SpawnKey(strKey, strValue); diff --git a/src/gs-entbase/shared/env_smoker.qc b/src/gs-entbase/shared/env_smoker.qc index 83567583..8c642cad 100644 --- a/src/gs-entbase/shared/env_smoker.qc +++ b/src/gs-entbase/shared/env_smoker.qc @@ -199,6 +199,15 @@ env_smoker::Input(entity eAct, string strInput, string strData) case "Use": Trigger(eAct, TRIG_TOGGLE); break; + case "SetScale": + m_flScale = ReadFloat(strData); + break; + case "SetDispersion": + m_flDispersion = ReadFloat(strData); + break; + case "SetDuration": + m_flDuration = ReadFloat(strData); + break; default: super::Input(eAct, strInput, strData); } diff --git a/src/shared/NSEntity.h b/src/shared/NSEntity.h index 75e96dda..d61a1a52 100644 --- a/src/shared/NSEntity.h +++ b/src/shared/NSEntity.h @@ -167,6 +167,12 @@ public: /** Sets the movement velocity of the given entity. */ nonvirtual void SetVelocity(vector); + + /** Adds onto the existing angular velocity. */ + nonvirtual void AddAngularVelocity(vector); + /** Adds onto the existing velocity. */ + nonvirtual void AddVelocity(vector); + /** Overrides the touch function of a the entity to the specified function. As a result Start/EndTouch will be unreliable. */ nonvirtual void SetTouch(void()); @@ -333,8 +339,10 @@ public: nonvirtual entity GetGroundEntity(void); /** Returns if the entity was spawned by the map we're on. */ nonvirtual bool CreatedByMap(void); - /** Returns whether or not we are within the bounds of a given entity. */ + /** Returns whether or not we are fully within the bounds of a given entity. */ nonvirtual bool WithinBounds(entity); + /** Returns whether or not the given entity insersects with us. Like a more lenient WithinBounds(). */ + nonvirtual bool IntersectsWith(entity); /* useful methods, (some) based on Doom 3's API */ /** Plays a sound sample directly onto the entity. @@ -374,4 +382,21 @@ public: /** Finds a free spot of an entity near itself of same size. Extra padding as argument. */ nonvirtual vector GetNearbySpot(void); -}; \ No newline at end of file +}; + +/** Will spawn a given classname in the type of an NSEntity at a given position and angle. */ +NSEntity +NSEntity_SpawnClass(string className, vector spawnOrigin, vector spawnAngles) +{ + entity oldSelf; + NSEntity output = (NSEntity)spawn(); + oldSelf = self; + self = output; + callfunction(strcat("spawnfunc_", className)); + output.m_oldOrigin = spawnOrigin; + output.m_oldAngle = spawnAngles; + output.angles = spawnAngles; + setorigin(output, spawnOrigin); + self = oldSelf; + return output; +} \ No newline at end of file diff --git a/src/shared/NSEntity.qc b/src/shared/NSEntity.qc index da89e25b..d9fd198c 100644 --- a/src/shared/NSEntity.qc +++ b/src/shared/NSEntity.qc @@ -503,6 +503,18 @@ void NSEntity::SetModelindex( float newModelIndex ) { } +void +NSEntity::AddAngularVelocity(vector addVel) +{ + avelocity += addVel; +} + +void +NSEntity::AddVelocity(vector addVel) +{ + velocity += addVel; +} + void NSEntity::AddEffects( float fl ) { effects |= fl; } @@ -790,6 +802,32 @@ void NSEntity::Input( entity eAct, string strInput, string strData ) { velocity += v_right * velAdd[1]; velocity += v_up * velAdd[2]; break; + case "Shockwave": + int c = tokenize(strData); + + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); + WriteByte(MSG_MULTICAST, EV_BEAMCYLINDER); + WriteCoord(MSG_MULTICAST, origin[0]); + WriteCoord(MSG_MULTICAST, origin[1]); + WriteCoord(MSG_MULTICAST, origin[2]); + WriteCoord(MSG_MULTICAST, angles[0]); + WriteCoord(MSG_MULTICAST, stof(argv(1))); + WriteCoord(MSG_MULTICAST, angles[2]); + WriteShort(MSG_MULTICAST, getmodelindex(argv(0))); + WriteByte(MSG_MULTICAST, stof(argv(2))); + WriteByte(MSG_MULTICAST, stof(argv(3))); + WriteByte(MSG_MULTICAST, stof(argv(4))); + WriteByte(MSG_MULTICAST, stof(argv(5))); + WriteByte(MSG_MULTICAST, stof(argv(6))); + WriteByte(MSG_MULTICAST, stof(argv(7))); + WriteByte(MSG_MULTICAST, stof(argv(8))); + WriteByte(MSG_MULTICAST, stof(argv(9))); + WriteByte(MSG_MULTICAST, stof(argv(10))); + WriteByte(MSG_MULTICAST, stof(argv(11))); + + msg_entity = this; + multicast(origin, MULTICAST_PVS); + break; default: NSTrigger::Input( eAct, strInput, strData ); } @@ -895,6 +933,17 @@ bool NSEntity::WithinBounds( entity check ) { return ( true ); } +bool NSEntity::IntersectsWith( entity check ) { + if not ( check.origin[0] >= absmin[0] && check.origin[0] <= absmax[0] ) + return ( false ); + if not ( check.origin[1] >= absmin[1] && check.origin[1] <= absmax[1] ) + return ( false ); + if not ( check.origin[2] >= absmin[2] && check.origin[2] <= absmax[2] ) + return ( false ); + + return ( true ); +} + bool NSEntity::StartSound( string strSample, float channel, float flags, bool broadcast ) { if not ( whichpack( strcat( "sound/", strSample ) ) ) return ( false );