diff --git a/src/server/gamerules.qc b/src/server/gamerules.qc index 80a8335..6fc0ae8 100644 --- a/src/server/gamerules.qc +++ b/src/server/gamerules.qc @@ -167,26 +167,26 @@ TFCGameRules::ImpulseCommand(NSClient bp, float num) case 101: player pl = (player)bp; if (cvar("sv_cheats") > 0) { - Weapons_AddItem(pl, WEAPON_CROWBAR, -1); - Weapons_AddItem(pl, WEAPON_MEDKIT, -1); - Weapons_AddItem(pl, WEAPON_KNIFE, -1); - Weapons_AddItem(pl, WEAPON_WRENCH, -1); - Weapons_AddItem(pl, WEAPON_UMBRELLA, -1); - Weapons_AddItem(pl, WEAPON_SBS, -1); - Weapons_AddItem(pl, WEAPON_SNIPER, -1); - Weapons_AddItem(pl, WEAPON_TRANQUIL, -1); - Weapons_AddItem(pl, WEAPON_RAILGUN, -1); - Weapons_AddItem(pl, WEAPON_AUTORIFLE, -1); - Weapons_AddItem(pl, WEAPON_DBS, -1); - Weapons_AddItem(pl, WEAPON_NAILGUN, -1); - Weapons_AddItem(pl, WEAPON_GLAUNCHER, -1); - Weapons_AddItem(pl, WEAPON_SUPERNAIL, -1); - Weapons_AddItem(pl, WEAPON_FLAMER, -1); - Weapons_AddItem(pl, WEAPON_RPG, -1); - Weapons_AddItem(pl, WEAPON_PIPEBOMB, -1); - Weapons_AddItem(pl, WEAPON_ASSCAN, -1); - Weapons_AddItem(pl, WEAPON_INCENDIARY, -1); - Weapons_AddItem(pl, WEAPON_GRAPPLE, -1); + Weapons_AddItem(pl, WEAPON_CROWBAR, -1); + Weapons_AddItem(pl, WEAPON_MEDKIT, -1); + Weapons_AddItem(pl, WEAPON_KNIFE, -1); + Weapons_AddItem(pl, WEAPON_WRENCH, -1); + Weapons_AddItem(pl, WEAPON_UMBRELLA, -1); + Weapons_AddItem(pl, WEAPON_SBS, -1); + Weapons_AddItem(pl, WEAPON_SNIPER, -1); + Weapons_AddItem(pl, WEAPON_TRANQUIL, -1); + Weapons_AddItem(pl, WEAPON_RAILGUN, -1); + Weapons_AddItem(pl, WEAPON_AUTORIFLE, -1); + Weapons_AddItem(pl, WEAPON_DBS, -1); + Weapons_AddItem(pl, WEAPON_NAILGUN, -1); + Weapons_AddItem(pl, WEAPON_GLAUNCHER, -1); + Weapons_AddItem(pl, WEAPON_SUPERNAIL, -1); + Weapons_AddItem(pl, WEAPON_FLAMER, -1); + Weapons_AddItem(pl, WEAPON_RPG, -1); + Weapons_AddItem(pl, WEAPON_PIPEBOMB, -1); + Weapons_AddItem(pl, WEAPON_ASSCAN, -1); + Weapons_AddItem(pl, WEAPON_INCENDIARY, -1); + Weapons_AddItem(pl, WEAPON_GRAPPLE, -1); } break; default: @@ -199,43 +199,9 @@ TFCGameRules::ImpulseCommand(NSClient bp, float num) void TFCGameRules::InitPostEnts(void) { - int team_count = 0i; - entity e = __NULL__; - super::InitPostEnts(); - /* populate the serverinfo field with the teams we have on the map */ - e = find(world, ::classname, "info_teamspawn_blue"); - if (e) { - team_count += 1; - forceinfokey(world, sprintf("team_%i", team_count), "Blue"); - forceinfokey(world, sprintf("teamscore_%i", team_count), "0"); - g_tfcHasBlueTeam = true; - } - - e = find(world, ::classname, "info_teamspawn_red"); - if (e) { - team_count += 1; - forceinfokey(world, sprintf("team_%i", team_count), "Red"); - forceinfokey(world, sprintf("teamscore_%i", team_count), "0"); - g_tfcHasRedTeam = true; - } - - e = find(world, ::classname, "info_teamspawn_green"); - if (e) { - team_count += 1; - forceinfokey(world, sprintf("team_%i", team_count), "Green"); - forceinfokey(world, sprintf("teamscore_%i", team_count), "0"); - g_tfcHasGreenTeam = true; - } - - e = find(world, ::classname, "info_teamspawn_yellow"); - if (e) { - team_count += 1; - forceinfokey(world, sprintf("team_%i", team_count), "Yellow"); - forceinfokey(world, sprintf("teamscore_%i", team_count), "0"); - g_tfcHasYellowTeam = true; - } - - forceinfokey(world, "teams", itos(team_count)); + /* rename the team spawns. */ + info_player_teamspawn::RenameTeamSpawns(); + info_tfdetect::Setup(); } diff --git a/src/server/info_player_teamspawn.qc b/src/server/info_player_teamspawn.qc index 1433498..98df156 100644 --- a/src/server/info_player_teamspawn.qc +++ b/src/server/info_player_teamspawn.qc @@ -14,40 +14,55 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -class info_player_teamspawn:NSRenderableEntity +class info_player_teamspawn:NSSpawnPoint { void(void) info_player_teamspawn; + + virtual void SpawnKey(string, string); + + nonvirtual void RenameTeamSpawns(void); }; void info_player_teamspawn::info_player_teamspawn(void) { - int team = 1; - for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) { - switch (argv(i)) { - case "team_no": - team = stoi(argv(i+1)); + +} + +void +info_player_teamspawn::SpawnKey(string keyName, string setValue) +{ + switch (keyName) { + case "team_no": + team = ReadInt(setValue); + break; + default: + super::SpawnKey(keyName, setValue); + } +} + +void +info_player_teamspawn::RenameTeamSpawns(void) +{ + for (entity e = world; (e = find(e, ::classname, "info_player_teamspawn"));) { + info_player_teamspawn findSpawn = (info_player_teamspawn)e; + + switch (findSpawn.team) { + case 1: + e.classname = "info_teamspawn_blue"; break; - default: + case 2: + e.classname = "info_teamspawn_red"; + break; + case 3: + e.classname = "info_teamspawn_yellow"; + break; + case 4: + e.classname = "info_teamspawn_green"; break; } } - switch (team) { - case 1: - classname = "info_teamspawn_blue"; - break; - case 2: - classname = "info_teamspawn_red"; - break; - case 3: - classname = "info_teamspawn_yellow"; - break; - case 4: - classname = "info_teamspawn_green"; - break; - } - botinfo = BOTINFO_SPAWNPOINT; } diff --git a/src/server/info_tfdetect.qc b/src/server/info_tfdetect.qc new file mode 100644 index 0000000..0b4714d --- /dev/null +++ b/src/server/info_tfdetect.qc @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2024 Marco Cawthorne + * + * 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. + */ + +typedef enum +{ + TFDFL_CIVILIANONLY = -1, + TFDFL_NONE = 0, + TFDFL_NOSCOUNT = 1, + TFDFL_NOSNIPER = 2, + TFDFL_NOSOLDIER = 4, + TFDFL_NODEMOMAN = 8, + TFDFL_NOMEDIC = 16, + TFDFL_NOHEAVY = 32, + TFDFL_NOPYRO = 64, + TFDFL_NORANDOM = 128, + TFDFL_NOSPY = 256, + TFDFL_NOENGINEER = 512, +} tfdetectTeamFlags_t; + +/*QUAKED info_tfdetect (0 0 0.8) (-16 -16 -16) (16 16 16) +# OVERVIEW + +# KEYS +- "broadcast" : ??? +- "number_of_teams" : Number of teams. +- "team1_name" : Name of team blue. +- "team2_name" : Name of team red. +- "team3_name" : Name of team yellow. +- "team4_name" : Name of team green. +- "impulse" : Game settings field. +- "message" : commands to insert into the server console. +- "maxammo_shells" : Blue team flags bitfield. +- "maxammo_nails" : Red team flags bitfield. +- "maxammo_rockets" : Yellow team flags bitfield. +- "maxammo_cells" : Green team flags bitfield. +- "ammo_medikit" : Blue team max player count. +- "ammo_detpack" : Red team max player count. +- "maxammo_medikit" : Yellow team max player count. +- "maxammo_detpack" : Green team max player count. +- "team1_allies" : Blue team ally bitfield. +- "team2_allies" : Red team ally bitfield. +- "team3_allies" : Yellow team ally bitfield. +- "team4_allies" : Green team ally bitfield. + +# NOTES + + +# TRIVIA +This entity was introduced in Team Fortress (1996). +*/ +class +info_tfdetect:NSPointTrigger +{ +public: + void info_tfdetect(void); + + virtual void SpawnKey(string, string); + virtual void Respawn(void); + + nonvirtual void Setup(void); + +private: + string m_strTeam1Name; + string m_strTeam2Name; + string m_strTeam3Name; + string m_strTeam4Name; + string m_strLocalCommand; + + tfdetectTeamFlags_t m_bfTeam1Flags; + tfdetectTeamFlags_t m_bfTeam2Flags; + tfdetectTeamFlags_t m_bfTeam3Flags; + tfdetectTeamFlags_t m_bfTeam4Flags; +}; + +void +info_tfdetect::info_tfdetect(void) +{ + m_strTeam1Name = "Blue"; + m_strTeam2Name = "Red"; + m_strTeam3Name = "Yellow"; + m_strTeam4Name = "Green"; + m_strLocalCommand = ""; + m_bfTeam1Flags = TFDFL_NONE; + m_bfTeam2Flags = TFDFL_NONE; + m_bfTeam3Flags = TFDFL_NONE; + m_bfTeam4Flags = TFDFL_NONE; +} + +void +info_tfdetect::SpawnKey(string keyName, string setValue) +{ + switch (keyName) { + case "team1_name": + m_strTeam1Name = ReadString(setValue); + break; + case "team2_name": + m_strTeam2Name = ReadString(setValue); + break; + case "team3_name": + m_strTeam3Name = ReadString(setValue); + break; + case "team4_name": + m_strTeam4Name = ReadString(setValue); + break; + case "message": + m_strLocalCommand = ReadString(setValue); + break; + case "maxammo_shells": + m_bfTeam1Flags = ReadFloat(setValue); + break; + case "maxammo_nails": + m_bfTeam2Flags = ReadFloat(setValue); + break; + case "maxammo_rockets": + m_bfTeam3Flags = ReadFloat(setValue); + break; + case "maxammo_cells": + m_bfTeam4Flags = ReadFloat(setValue); + break; + default: + super::SpawnKey(keyName, setValue); + } +} + +void +info_tfdetect::Respawn(void) +{ + +} + +void +info_tfdetect::Setup(void) +{ + int team_count = 0i; + entity e = __NULL__; + info_tfdetect globalTFD = (info_tfdetect)find(world, ::classname, "info_tfdetect"); + + /* populate the serverinfo field with the teams we have on the map */ + e = find(world, ::classname, "info_teamspawn_blue"); + if (e) { + team_count += 1; + forceinfokey(world, sprintf("team_%i", team_count), "Blue"); + forceinfokey(world, sprintf("teamscore_%i", team_count), "0"); + g_tfcHasBlueTeam = true; + } + + e = find(world, ::classname, "info_teamspawn_red"); + if (e) { + team_count += 1; + forceinfokey(world, sprintf("team_%i", team_count), "Red"); + forceinfokey(world, sprintf("teamscore_%i", team_count), "0"); + g_tfcHasRedTeam = true; + } + + e = find(world, ::classname, "info_teamspawn_green"); + if (e) { + team_count += 1; + forceinfokey(world, sprintf("team_%i", team_count), "Green"); + forceinfokey(world, sprintf("teamscore_%i", team_count), "0"); + g_tfcHasGreenTeam = true; + } + + e = find(world, ::classname, "info_teamspawn_yellow"); + if (e) { + team_count += 1; + forceinfokey(world, sprintf("team_%i", team_count), "Yellow"); + forceinfokey(world, sprintf("teamscore_%i", team_count), "0"); + g_tfcHasYellowTeam = true; + } + forceinfokey(world, "teams", itos(team_count)); + + if (!globalTFD) { + NSLog("No info_tfdetect in level."); + forceinfokey(world, "teamflags_1", "0"); + forceinfokey(world, "teamflags_2", "0"); + forceinfokey(world, "teamflags_3", "0"); + forceinfokey(world, "teamflags_4", "0"); + return; + } + + forceinfokey(world, "team_1", globalTFD.m_strTeam1Name); + forceinfokey(world, "team_2", globalTFD.m_strTeam2Name); + forceinfokey(world, "team_3", globalTFD.m_strTeam3Name); + forceinfokey(world, "team_4", globalTFD.m_strTeam4Name); + + forceinfokey(world, "teamflags_1", ftos(globalTFD.m_bfTeam1Flags)); + forceinfokey(world, "teamflags_2", ftos(globalTFD.m_bfTeam1Flags)); + forceinfokey(world, "teamflags_3", ftos(globalTFD.m_bfTeam1Flags)); + forceinfokey(world, "teamflags_4", ftos(globalTFD.m_bfTeam1Flags)); + + /* the evil localcmd feature of this entity. */ + if (m_strLocalCommand) { + localcmd(m_strLocalCommand); + localcmd("\n"); + } +} \ No newline at end of file diff --git a/src/server/item_armor.qc b/src/server/item_armor.qc index 580e558..7ff6e49 100644 --- a/src/server/item_armor.qc +++ b/src/server/item_armor.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Marco Cawthorne + * Copyright (c) 2022-2024 Marco Cawthorne * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,63 +14,67 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/*QUAKED item_armor1 (0 0 0.8) (-16 -16 0) (16 16 56) - -TEAM FORTRESS/QUAKE (1996) ENTITY - -Armor pickup, which will also replenish metal. -It has a 100 points. - --------- KEYS -------- -"targetname" : Name -"areaname" : Name of the specified area -"team_no" : Which team can pick up the armor (0 = all) -"respawn_delay" : Time it takes to respawn after having been picked up -*/ - -/*QUAKED item_armor2 (0 0 0.8) (-16 -16 0) (16 16 56) - -TEAM FORTRESS/QUAKE (1996) ENTITY - -Armor pickup, which will also replenish metal -It has a 150 points. - --------- KEYS -------- -"targetname" : Name -"areaname" : Name of the specified area -"team_no" : Which team can pick up the armor (0 = all) -"respawn_delay" : Time it takes to respawn after having been picked up -*/ - -/*QUAKED item_armor3 (0 0 0.8) (-16 -16 0) (16 16 56) - -TEAM FORTRESS/QUAKE (1996) ENTITY - -Armor pickup, which will also replenish metal -It has a 200 points. - --------- KEYS -------- -"targetname" : Name -"areaname" : Name of the specified area -"team_no" : Which team can pick up the armor (0 = all) -"respawn_delay" : Time it takes to respawn after having been picked up -*/ - class -item_armor:NSRenderableEntity +TFCArmor:NSRenderableEntity { float m_flRespawnDelay; int m_iTeamUses; + int m_iArmorValue; - void(void) item_armor; + void(void) TFCArmor; virtual void(entity) Touch; virtual void(void) Respawn; + virtual void(void) Spawned; virtual void(string,string) SpawnKey; }; void -item_armor::Touch(entity eToucher) +TFCArmor::TFCArmor(void) +{ + m_flRespawnDelay = 0.0f; + m_iTeamUses = 0i; + m_iArmorValue = 0i; +} + +void +TFCArmor::SpawnKey(string keyName, string setValue) +{ + switch (keyName) { + case "armorvalue": + m_iArmorValue = ReadInt(setValue); + break; + case "team_no": + m_iTeamUses = ReadInt(setValue); + break; + case "respawn_delay": + m_flRespawnDelay = ReadFloat(setValue); + break; + default: + super::SpawnKey(keyName, setValue); + } +} + +void +TFCArmor::Spawned(void) +{ + super::Spawned(); + Sound_Precache("item_armor_tfc.pickup"); +} + +void +TFCArmor::Respawn(void) +{ + SetModel(GetSpawnModel()); + SetSize([-16,-16,0], [16,16,56]); + SetSolid(SOLID_TRIGGER); + SetOrigin(GetSpawnOrigin()); + DropToFloor(); + botinfo = BOTINFO_ARMOR; +} + +void +TFCArmor::Touch(entity eToucher) { if (eToucher.classname != "player") { return; @@ -91,22 +95,7 @@ item_armor::Touch(entity eToucher) /* get remaining points */ ap = pl.m_iMaxArmor - pl.armor; - - /* get the total points the armor can give */ - switch (classname) { - case "item_armor1": - tp = 100; - break; - case "item_armor2": - tp = 150; - break; - case "item_armor3": - tp = 200; - break; - default: - print("^1item_armor: unknown armor type\n"); - return; - } + tp = m_iArmorValue; /* if that's all we can give... */ if (ap > tp) { @@ -127,75 +116,3 @@ item_armor::Touch(entity eToucher) Disappear(); ScheduleThink(Respawn, m_flRespawnDelay); } - -void -item_armor::SpawnKey(string strKey, string strValue) -{ - switch (strKey) { - case "team_no": - m_iTeamUses = stoi(strValue); - break; - case "respawn_delay": - m_flRespawnDelay = stof(strValue); - break; - default: - super::SpawnKey(strKey, strValue); - } -} - -void -item_armor::Respawn(void) -{ - /* get the total points the armor can give */ - switch (classname) { - case "item_armor1": - SetModel("models/g_armor.mdl"); - break; - case "item_armor2": - SetModel("models/y_armor.mdl"); - break; - case "item_armor3": - SetModel("models/r_armor.mdl"); - break; - default: - print("^1item_armor: unknown armor type\n"); - Destroy(); - return; - } - - SetSize([-16,-16,0], [16,16,56]); - SetSolid(SOLID_TRIGGER); - SetOrigin(GetSpawnOrigin()); - DropToFloor(); - botinfo = BOTINFO_ARMOR; -} - -void -item_armor::item_armor(void) -{ - Sound_Precache("item_armor_tfc.pickup"); -} - -void -item_armor1(void) -{ - precache_model("models/g_armor.mdl"); - spawnfunc_item_armor(); - self.classname = "item_armor1"; -} - -void -item_armor2(void) -{ - precache_model("models/y_armor.mdl"); - spawnfunc_item_armor(); - self.classname = "item_armor2"; -} - -void -item_armor3(void) -{ - precache_model("models/r_armor.mdl"); - spawnfunc_item_armor(); - self.classname = "item_armor3"; -} diff --git a/src/server/progs.src b/src/server/progs.src index df8ae2e..4618bad 100644 --- a/src/server/progs.src +++ b/src/server/progs.src @@ -38,6 +38,7 @@ info_player_teamspawn.qc item_tfgoal.qc info_tfgoal.qc info_areadef.qc +info_tfdetect.qc item_armor.qc item_healthkit.qc nades.qc diff --git a/src/shared/w_nailgun.qc b/src/shared/w_nailgun.qc index 9789001..852f6ac 100644 --- a/src/shared/w_nailgun.qc +++ b/src/shared/w_nailgun.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020 Marco Cawthorne + * Copyright (c) 2016-2024 Marco Cawthorne * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -80,7 +80,7 @@ w_nailgun_shootnail(player pl) /* impact per bullet */ if (trace_ent.iBleeds == 0) { DecalGroups_Place("Impact.Shot", trace_endpos + (v_forward * -2)); - SurfData_Impact(trace_ent, trace_surfaceflagsi, trace_endpos, trace_plane_normal); + SurfData_Impact(trace_ent, trace_endpos, trace_plane_normal); } if (trace_ent.takedamage == DAMAGE_YES) { Damage_Apply(trace_ent, self.owner, 9, WEAPON_NAILGUN, DMG_BULLET); diff --git a/src/shared/w_supernail.qc b/src/shared/w_supernail.qc index 3c0ff2c..cbd7cd6 100644 --- a/src/shared/w_supernail.qc +++ b/src/shared/w_supernail.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020 Marco Cawthorne + * Copyright (c) 2016-2024 Marco Cawthorne * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -83,7 +83,7 @@ w_supernail_shootnail(player pl) /* impact per bullet */ if (trace_ent.iBleeds == 0) { DecalGroups_Place("Impact.BigShot", trace_endpos + (v_forward * -2)); - SurfData_Impact(trace_ent, trace_surfaceflagsi, trace_endpos, trace_plane_normal); + SurfData_Impact(trace_ent, trace_endpos, trace_plane_normal); } if (trace_ent.takedamage == DAMAGE_YES) { Damage_Apply(trace_ent, self.owner, 14, WEAPON_NAILGUN, DMG_BULLET); diff --git a/zpak001.pk3dir/def/armor.def b/zpak001.pk3dir/def/armor.def new file mode 100644 index 0000000..d7ac014 --- /dev/null +++ b/zpak001.pk3dir/def/armor.def @@ -0,0 +1,23 @@ +entityDef item_armor1 +{ + spawnclass TFCArmor + model "models/g_armor.mdl" + armorvalue "100" + snd_pickup "item_armor_tfc.pickup" +} + +entityDef item_armor2 +{ + spawnclass TFCArmor + model "models/y_armor.mdl" + armorvalue "150" + snd_pickup "item_armor_tfc.pickup" +} + +entityDef item_armor3 +{ + spawnclass TFCArmor + model "models/r_armor.mdl" + armorvalue "200" + snd_pickup "item_armor_tfc.pickup" +} \ No newline at end of file diff --git a/zpak001.pk3dir/def/spawns.def b/zpak001.pk3dir/def/spawns.def new file mode 100644 index 0000000..07ed426 --- /dev/null +++ b/zpak001.pk3dir/def/spawns.def @@ -0,0 +1,44 @@ +entityDef info_player_start +{ + editor_mins "-16 -16 -36" + editor_maxs "16 16 36" + editor_description "Singleplayer Spawn" + + spawnclass NSSpawnPoint +} + +entityDef info_teamspawn_blue +{ + editor_mins "-16 -16 -36" + editor_maxs "16 16 36" + editor_description "Blue Team Spawn" + + spawnclass NSSpawnPoint +} + +entityDef info_teamspawn_red +{ + editor_mins "-16 -16 -36" + editor_maxs "16 16 36" + editor_description "Red Team Spawn" + + spawnclass NSSpawnPoint +} + +entityDef info_teamspawn_green +{ + editor_mins "-16 -16 -36" + editor_maxs "16 16 36" + editor_description "Yellow Team Spawn" + + spawnclass NSSpawnPoint +} + +entityDef info_teamspawn_yellow +{ + editor_mins "-16 -16 -36" + editor_maxs "16 16 36" + editor_description "Yellow Team Spawn" + + spawnclass NSSpawnPoint +} \ No newline at end of file