diff --git a/base/manifest.fmf b/base/manifest.fmf new file mode 100644 index 00000000..0de042b5 --- /dev/null +++ b/base/manifest.fmf @@ -0,0 +1,13 @@ +FTEMANIFEST 1 +NAME "Test Game" +GAME base +BASEGAME platform +BASEGAME base + +// you don't really want to change these +RTCBROKER master.frag-net.com:27950 +PROTOCOLNAME "Nuclide" +MAINCONFIG nuclide.cfg +DOWNLOADSURL "" + +-exec platform_default.cfg diff --git a/base/src/server/progs.src b/base/src/server/progs.src index 41f5a55b..8fceff31 100644 --- a/base/src/server/progs.src +++ b/base/src/server/progs.src @@ -10,6 +10,7 @@ ../../../src/shared/fteextensions.qc ../../../src/shared/defs.h ../../../src/server/defs.h +../../../src/botlib/botinfo.h ../../../src/gs-entbase/server.src ../../../src/gs-entbase/shared.src diff --git a/build_game.sh b/build_game.sh index e0a3ffb8..d0da0043 100755 --- a/build_game.sh +++ b/build_game.sh @@ -11,6 +11,10 @@ safe_copy() radiant_build() { + if [ "$SKIP_RADIANT" = "1" ]; then + exit 0 + fi + ./make_mapdef.sh "$1" # copy files over to RADIANT diff --git a/src/botlib/bot.h b/src/botlib/NSBot.h similarity index 98% rename from src/botlib/bot.h rename to src/botlib/NSBot.h index a56e7304..af6884d1 100644 --- a/src/botlib/bot.h +++ b/src/botlib/NSBot.h @@ -39,7 +39,7 @@ typedef enum BOT_STATE_FLEEING /**< this is for when the AI should just get as far away as possible */ } botstate_t; -/** Base class for the Bot AI. +/** A virtual multiplayer opponent. Base class for all bots. */ class NSBot:player { diff --git a/src/botlib/bot.qc b/src/botlib/NSBot.qc similarity index 96% rename from src/botlib/bot.qc rename to src/botlib/NSBot.qc index 4f64e1d2..52d99979 100644 --- a/src/botlib/bot.qc +++ b/src/botlib/NSBot.qc @@ -193,8 +193,7 @@ NSBot::CheckRoute(void) /* we're inside the radius */ if (flDist <= flRadius) { - NSLog("^2NSBot::^3CheckRoute^7: " \ - "%s reached node\n", this.targetname); + BotEntLog("%s reached node", this.netname); m_iCurNode--; /* if we're inside an actual node (not a virtual one */ @@ -218,8 +217,7 @@ NSBot::CheckRoute(void) /* can we walk directly to our target destination? */ if (trace_fraction == 1.0) { - print("^2NSBot::^3CheckRoute^7: " \ - "Walking directly to last node\n"); + BotEntLog("Walking directly to last node."); m_iCurNode = -1; } } @@ -245,7 +243,7 @@ NSBot::CheckRoute(void) /* after one second, also give up the route */ if (m_flNodeGiveup >= 1.0f || m_iCurNode <= BOTROUTE_END) { - print("taking too long! giving up!\n"); + BotEntLog("Taking too long! Giving up!"); RouteClear(); } else if (m_flNodeGiveup >= 0.5f) { /* attempt a jump after half a second */ @@ -279,7 +277,7 @@ NSBot::RunAI(void) input_angles = [0,0,0]; /* attempt to respawn when dead */ - if (IsDead() == true) { + if (IsDead() == true || health <= 0) { RouteClear(); WeaponAttack(); SetEnemy(__NULL__); @@ -294,7 +292,7 @@ NSBot::RunAI(void) if (!m_iNodes && autocvar_bot_aimless == 0) { CreateObjective(); - NSLog("NSBot::RunAI: %s is calculating first bot route", + BotEntLog("%S is calculating first bot route", this.netname); /* our route probably has not been processed yet */ @@ -430,14 +428,12 @@ NSBot::RunAI(void) if (m_eTarget && enemyVisible && m_flEnemyDist < 256) { /* we are far away, inch closer */ aimPos = m_eTarget.origin; - //printf("going to target\n"); } else { goRoute = true; } } else if (m_wtWeaponType == WPNTYPE_THROW) { if ((m_eTarget && enemyVisible && !enemyDistant) && m_flEnemyDist < 512) { aimPos = m_eTarget.origin; - //printf("going to target\n"); } else { goRoute = true; } @@ -448,10 +444,8 @@ NSBot::RunAI(void) if (goRoute) { if (m_iCurNode <= BOTROUTE_DESTINATION) { aimPos = m_vecLastNode; - //printf("going to last node\n"); } else { aimPos = m_pRoute[m_iCurNode].dest; - //printf("going to next node\n"); } } else { RouteClear(); @@ -511,7 +505,7 @@ NSBot::PostFrame(void) /* we've picked something new up */ if (m_iOldItems != g_items) { Weapons_SwitchBest(this); - print(sprintf("%s is now using %s (%d)\n", netname, g_weapons[activeweapon].name, activeweapon)); + BotEntLog("%S is now using %S (%d)", netname, g_weapons[activeweapon].name, activeweapon); m_iOldItems = g_items; } #endif @@ -553,7 +547,7 @@ bot_spawner_think(void) int minClientsCvar = (int)cvar("bot_minClients"); /* if -1, we are not managing _anything_ */ - if (minClientsCvar == -1) { + if (minClientsCvar == -1i) { self.nextthink = time + 5.0f; return; } diff --git a/src/botlib/bot_combat.qc b/src/botlib/bot_combat.qc index f3af9d2c..df03cfc7 100644 --- a/src/botlib/bot_combat.qc +++ b/src/botlib/bot_combat.qc @@ -169,7 +169,7 @@ BotLib_Alert(vector pos, float radius, float t) continue; /* we've heard a noise. investigate the location */ - print(sprintf("bot alerted by noise at %v\n", pos)); + BotLog("Bot %S (%d) alerted by noise at %v", f.netname, num_for_edict(f), pos); f.RouteClear(); f.RouteToPosition(pos); } diff --git a/src/botlib/cvar.h b/src/botlib/cvar.h deleted file mode 100644 index 1f2c06da..00000000 --- a/src/botlib/cvar.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 - * 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. -*/ - -var int autocvar_bot_aimless = FALSE; - -var int autocvar_nav_linksize = 256; -var int autocvar_nav_radius = 8; - -var bool autocvar_bot_crouch = false; -var bool autocvar_bot_walk = false; -var bool autocvar_bot_stop = false; -var bool autocvar_bot_dont_shoot = false; - -var bool autocvar_bot_join_after_player = false; -var float autocvar_bot_join_delay = 0.0f; -var int autocvar_bot_quota = 0i; -var string autocvar_bot_quota_mode = "normal"; -var string autocvar_bot_chatter = "normal"; - -typedef enum -{ - BOTSKILL_EASY = 1, - BOTSKILL_MEDIUM, - BOTSKILL_HARD -} botskill_t; - -var botskill_t autocvar_bot_skill = BOTSKILL_MEDIUM; - -var string autocvar_bot_prefix = ""; diff --git a/src/botlib/defs.h b/src/botlib/defs.h index 79d7186b..30556043 100644 --- a/src/botlib/defs.h +++ b/src/botlib/defs.h @@ -14,10 +14,85 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "bot.h" -#include "botinfo.h" -#include "cvar.h" -#include "profiles.h" - +#include "NSBot.h" vector Route_SelectDestination( NSBot target ); + +var int autocvar_bot_aimless = FALSE; + +var int autocvar_nav_linksize = 256; +var int autocvar_nav_radius = 8; + +var bool autocvar_bot_crouch = false; +var bool autocvar_bot_walk = false; +var bool autocvar_bot_stop = false; +var bool autocvar_bot_dont_shoot = false; + +var bool autocvar_bot_join_after_player = false; +var float autocvar_bot_join_delay = 0.0f; +var int autocvar_bot_quota = 0i; +var string autocvar_bot_quota_mode = "normal"; +var string autocvar_bot_chatter = "normal"; +var bool autocvar_bot_developer = false; + +void +_BotLog(string functionName, string msg) +{ + print(sprintf("%f ^xF05%s ^7: %s\n", time, functionName, msg)); +} + +/** Logs an bot system specific log message. + The console variable `bot_developer` has to be `1` for them to be visible. + +@param description(...) contains a formatted string containing a description. */ +#define BotLog(...) if (autocvar_bot_developer) _BotLog(__FUNC__, sprintf(__VA_ARGS__)) + +void +_BotEntLog(string className, string functionName, float edictNum, string warnMessage) +{ + print(sprintf("%f ^xF05%s (id: %d) ^7: %s\n", time, functionName, edictNum, warnMessage)); +} + +/** Logs an bot specific entity class log message. + The console variable `bot_developer` has to be `1` for them to be visible. + +@param description(...) contains a formatted string containing a description. */ +#define BotEntLog(...) if (autocvar_bot_developer) _BotEntLog(classname, __FUNC__, num_for_edict(this), sprintf(__VA_ARGS__)) + +typedef enum +{ + BOTSKILL_EASY = 1, + BOTSKILL_MEDIUM, + BOTSKILL_HARD +} botskill_t; + +var botskill_t autocvar_bot_skill = BOTSKILL_MEDIUM; + +var string autocvar_bot_prefix = ""; + +/* BotScript + script/bots.txt + + Listing of various bot profiles + where infokeys can be set and interpreted + by the game-logic at will. + + The `name` keys has to _always_ be present. + The `funname` key is optional. + + Name acts as both an identifier as well + as a nickname when `funname` is not present. + + Anything else is considered to be extra. +*/ + +typedef struct +{ + string m_strName; + string m_strNetName; + string m_strExtra; +} botScript_t; + +#define BOTSCRIPT_MAX 32 +botScript_t g_bots[BOTSCRIPT_MAX]; +var int g_botScriptCount; \ No newline at end of file diff --git a/src/botlib/include.src b/src/botlib/include.src index f08b4660..e6ee6691 100644 --- a/src/botlib/include.src +++ b/src/botlib/include.src @@ -3,7 +3,7 @@ #includelist defs.h profiles.qc -bot.qc +NSBot.qc bot_chat.qc bot_combat.qc route.qc diff --git a/src/botlib/profiles.h b/src/botlib/profiles.h deleted file mode 100644 index 3c4e4ed9..00000000 --- a/src/botlib/profiles.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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. -*/ - -/* BotScript - script/bots.txt - - Listing of various bot profiles - where infokeys can be set and interpreted - by the game-logic at will. - - The `name` keys has to _always_ be present. - The `funname` key is optional. - - Name acts as both an identifier as well - as a nickname when `funname` is not present. - - Anything else is considered to be extra. -*/ - -typedef struct -{ - string m_strName; - string m_strNetName; - string m_strExtra; -} botScript_t; - -#define BOTSCRIPT_MAX 32 -botScript_t g_bots[BOTSCRIPT_MAX]; -var int g_botScriptCount; \ No newline at end of file diff --git a/src/botlib/profiles.qc b/src/botlib/profiles.qc index 1bbe4524..8b4d26e1 100644 --- a/src/botlib/profiles.qc +++ b/src/botlib/profiles.qc @@ -29,7 +29,7 @@ Bot_ExistsInServer(string botName) } bool -Bot_AddBot_f(string botName) +Bot_AddBot_f(string botName, float teamValue, float spawnDelay, string newName) { int extraCount = 0i; int foundID = -1i; @@ -43,7 +43,7 @@ Bot_AddBot_f(string botName) } if (!g_nodes_present) { - print("^1BotScript_Add^7: Can't add bot. No waypoints.\n"); + NSError("Can't add bot. No nodes."); return (false); } @@ -56,7 +56,7 @@ Bot_AddBot_f(string botName) } if (foundID == -1i) { - print("^1BotScript_Add^7: Named profile not found.\n"); + NSError("Named profile %S not found.", botName); return (false); } @@ -64,7 +64,7 @@ Bot_AddBot_f(string botName) self = spawnclient(); if (!self) { - print("^1BotScript_Add^7: Can't add bot. Server is full\n"); + NSError("Unable to add bot. Server is full."); self = oldSelf; return (false); } @@ -111,11 +111,11 @@ BotProfile_AddRandom(void) /* every bot exists already */ if (spawnBot == -1i) { - print("^1BotProfile_AddRandom^7: Not enough profiles available.\n"); + NSError("Not enough profiles available."); return (false); } - Bot_AddBot_f(g_bots[spawnBot].m_strName); + Bot_AddBot_f(g_bots[spawnBot].m_strName, 0, 0.0f, __NULL__); return (true); } @@ -127,6 +127,8 @@ BotProfile_Init(void) botScript_t currentDef; int braceDepth = 0i; + InitStart(); + currentDef.m_strName = ""; currentDef.m_strNetName = ""; currentDef.m_strExtra = ""; @@ -140,6 +142,7 @@ BotProfile_Init(void) botScript = fopen("scripts/bots.txt", FILE_READ); if (botScript < 0) { + NSError("Missing file scripts/bots.txt"); return; } @@ -197,14 +200,15 @@ BotProfile_Init(void) } fclose(botScript); - print(sprintf("%i bots parsed\n", g_botScriptCount)); + NSLog("...%i bots parsed.", g_botScriptCount); + InitEnd(); } void Bot_ListBotProfiles_f(void) { if (!g_botScriptCount) { - print("no bot profiles found.\n"); + NSError("No bot profiles available."); return; } diff --git a/src/botlib/route.qc b/src/botlib/route.qc index 01db0844..28eb94d8 100644 --- a/src/botlib/route.qc +++ b/src/botlib/route.qc @@ -169,7 +169,7 @@ Route_SelectDestination(NSBot target) if (rules.IsTeamplay()) { /* we have the goal item, so capture it */ if (target.flags & FL_GOALITEM) { - print(sprintf("%s going for capture\n", target.netname)); + BotLog("%s going for capture", target.netname); dest = Route_SelectNearestTeam(BOTINFO_TEAM_GOALCAPTURE, target.origin, target.team); /* we may have to go to our teams' goal item then */ @@ -177,7 +177,7 @@ Route_SelectDestination(NSBot target) dest = Route_SelectNearestTeam(BOTINFO_TEAM_GOALITEM, target.origin, target.team); } } else { - print(sprintf("%s hunting for goal item\n", target.netname)); + BotLog("%s hunting for goal item", target.netname); dest = Route_SelectNearestEnemyTeam(BOTINFO_TEAM_GOALITEM, target.origin, target.team); } @@ -187,13 +187,12 @@ Route_SelectDestination(NSBot target) } /* by now, they need something else to do involving goal items probably */ - - print(sprintf("%s can't figure out where to go for the goal\n", target.netname)); + BotLog("%s can't figure out where to go for the goal", target.netname); } /* if we're low on health, look for health items */ if (target.health < 50) { - print(sprintf("%s going for health\n", target.netname)); + BotLog("%s going for health", target.netname); dest = Route_SelectNearest(BOTINFO_HEALTH, target.origin, target.m_vecLastPOI); if (dest != __NULL__) { @@ -201,13 +200,13 @@ Route_SelectDestination(NSBot target) return dest.origin + [0,0,32]; } - print(sprintf("%s can't figure out where to go for health\n", target.netname)); + BotLog("%s can't figure out where to go for health", target.netname); } /* armor is always a good idea to have */ if (random() < 0.25) if (target.armor < 50) { - print(sprintf("%s going for armor\n", target.netname)); + BotLog("%s going for armor", target.netname); dest = Route_SelectNearest(BOTINFO_ARMOR, target.origin, target.m_vecLastPOI); if (dest != __NULL__) { @@ -215,13 +214,13 @@ Route_SelectDestination(NSBot target) return dest.origin + [0,0,32]; } - print(sprintf("%s can't figure out where to go for armor\n", target.netname)); + BotLog("%s can't figure out where to go for armor", target.netname); } /* go for ammo, or weapon */ if (random() < 0.25) if (!dest) { - print(sprintf("%s going for ammo/weapon\n", target.netname)); + BotLog("%s going for ammo/weapon", target.netname); if (random() < 0.5) dest = Route_SelectFarthest(BOTINFO_WEAPON, target.origin, target.m_vecLastPOI); @@ -233,7 +232,7 @@ Route_SelectDestination(NSBot target) return dest.origin + [0,0,32]; } - print(sprintf("%s can't figure out where to go for ammo/weapon\n", target.netname)); + BotLog("%s can't figure out where to go for ammo/weapon", target.netname); } if (random() < 0.25) @@ -255,7 +254,7 @@ Route_SelectDestination(NSBot target) } /* if all else fails... select a random spot */ - print(sprintf("%s found nothing, going for random PoI\n", target.netname)); + BotLog("%s found nothing, going for random PoI", target.netname); dest = Route_SelectRandomSpot(); target.m_eDestination = dest; return (dest.origin); diff --git a/src/botlib/way.qc b/src/botlib/way.qc index 07c82519..935e5483 100644 --- a/src/botlib/way.qc +++ b/src/botlib/way.qc @@ -234,7 +234,7 @@ Way_SetRadius(int iID, float flRadValue) } void -Way_FlagJump(void) +Way_LinkFlag(int linkFlag) { if (g_waylink_status == 0) { g_way1 = Way_FindClosestNode(self.origin); @@ -256,41 +256,7 @@ Way_FlagJump(void) Way_LinkNodes(&g_pWaypoints[g_way1], &g_pWaypoints[g_way2]); for (int b = 0i; b < g_pWaypoints[g_way1].m_numNeighbours; b++) { if (g_pWaypoints[g_way1].m_pNeighbour[b].m_iNode == g_way2) { - g_pWaypoints[g_way1].m_pNeighbour[b].m_iFlags |= LF_JUMP; - env_message_single(self, "^2Jump-linked the two points!\n"); - } - } - } else { - env_message_single(self, "^1Failed to link, the two points are the same!\n"); - } - g_way1 = g_way2 = -1; - } -} - -void -Way_FlagCrouch(void) -{ - if (g_waylink_status == 0) { - g_way1 = Way_FindClosestNode(self.origin); - - if (g_way1 == -1i) - return; - - g_waylink_status = 1; - env_message_single(self, "^2Selected first waypoint!\n"); - } else if (g_waylink_status == 1) { - g_way2 = Way_FindClosestNode(self.origin); - - if (g_way2 == -1i) - return; - - g_waylink_status = 0; - - if (g_way1 != g_way2) { - Way_LinkNodes(&g_pWaypoints[g_way1], &g_pWaypoints[g_way2]); - for (int b = 0i; b < g_pWaypoints[g_way1].m_numNeighbours; b++) { - if (g_pWaypoints[g_way1].m_pNeighbour[b].m_iNode == g_way2) { - g_pWaypoints[g_way1].m_pNeighbour[b].m_iFlags |= LF_CROUCH; + g_pWaypoints[g_way1].m_pNeighbour[b].m_iFlags |= linkFlag; env_message_single(self, "^2Crouch-linked the two points!\n"); } } @@ -301,108 +267,6 @@ Way_FlagCrouch(void) } } -void -Way_FlagWalk(void) -{ - if (g_waylink_status == 0) { - g_way1 = Way_FindClosestNode(self.origin); - - if (g_way1 == -1i) - return; - - g_waylink_status = 1; - env_message_single(self, "^2Selected first waypoint!\n"); - } else if (g_waylink_status == 1) { - g_way2 = Way_FindClosestNode(self.origin); - - if (g_way2 == -1i) - return; - - g_waylink_status = 0; - - if (g_way1 != g_way2) { - Way_LinkNodes(&g_pWaypoints[g_way1], &g_pWaypoints[g_way2]); - for (int b = 0i; b < g_pWaypoints[g_way1].m_numNeighbours; b++) { - if (g_pWaypoints[g_way1].m_pNeighbour[b].m_iNode == g_way2) { - g_pWaypoints[g_way1].m_pNeighbour[b].m_iFlags |= LF_WALK; - env_message_single(self, "^2Walk-linked the two points!\n"); - } - } - } else { - env_message_single(self, "^1Failed to link, the two points are the same!\n"); - } - g_way1 = g_way2 = -1; - } -} - -void -Way_FlagAim(void) -{ - if (g_waylink_status == 0) { - g_way1 = Way_FindClosestNode(self.origin); - - if (g_way1 == -1i) - return; - - g_waylink_status = 1; - env_message_single(self, "^2Selected first waypoint!\n"); - } else if (g_waylink_status == 1) { - g_way2 = Way_FindClosestNode(self.origin); - - if (g_way2 == -1i) - return; - - g_waylink_status = 0; - - if (g_way1 != g_way2) { - Way_LinkNodes(&g_pWaypoints[g_way1], &g_pWaypoints[g_way2]); - for (int b = 0i; b < g_pWaypoints[g_way1].m_numNeighbours; b++) { - if (g_pWaypoints[g_way1].m_pNeighbour[b].m_iNode == g_way2) { - g_pWaypoints[g_way1].m_pNeighbour[b].m_iFlags |= LF_AIM; - env_message_single(self, "^2Aim-linked the two points!\n"); - } - } - } else { - env_message_single(self, "^1Failed to link, the two points are the same!\n"); - } - g_way1 = g_way2 = -1; - } -} - -void -Way_FlagUse(void) -{ - if (g_waylink_status == 0) { - g_way1 = Way_FindClosestNode(self.origin); - - if (g_way1 == -1i) - return; - - g_waylink_status = 1; - env_message_single(self, "^2Selected first waypoint!\n"); - } else if (g_waylink_status == 1) { - g_way2 = Way_FindClosestNode(self.origin); - - if (g_way2 == -1i) - return; - - g_waylink_status = 0; - - if (g_way1 != g_way2) { - Way_LinkNodes(&g_pWaypoints[g_way1], &g_pWaypoints[g_way2]); - for (int b = 0i; b < g_pWaypoints[g_way1].m_numNeighbours; b++) { - if (g_pWaypoints[g_way1].m_pNeighbour[b].m_iNode == g_way2) { - g_pWaypoints[g_way1].m_pNeighbour[b].m_iFlags |= LF_USER; - env_message_single(self, "^2Use-linked the two points!\n"); - } - } - } else { - env_message_single(self, "^1Failed to link, the two points are the same!\n"); - } - g_way1 = g_way2 = -1; - } -} - void Way_Unlink(void) { @@ -631,8 +495,7 @@ Way_DrawDebugInfo(void) } int iNearest = Way_FindClosestNode(self.origin); - makevectors(self.v_angle); - R_BeginPolygon("", 0, 0); + makevectors([-90, 0, 0]); for (int i = 0i; i < g_iWaypoints; i++) { waypoint_t *w = g_pWaypoints + i; @@ -643,10 +506,24 @@ Way_DrawDebugInfo(void) rgb = [0,1,0]; } - R_PolygonVertex(org + v_right * 4 - v_up * 4, [1,1], rgb, 1); - R_PolygonVertex(org - v_right * 4 - v_up * 4, [0,1], rgb, 1); - R_PolygonVertex(org - v_right * 4 + v_up * 4, [0,0], rgb, 1); - R_PolygonVertex(org + v_right * 4 + v_up * 4, [1,0], rgb, 1); + R_BeginPolygon("", 0, 0); + R_PolygonVertex(org + v_right * 2 - v_up * 2, [1,1], rgb, 1); + R_PolygonVertex(org - v_right * 2 - v_up * 2, [0,1], rgb, 1); + R_EndPolygon(); + + R_BeginPolygon("", 0, 0); + R_PolygonVertex(org - v_right * 2 - v_up * 2, [0,1], rgb, 1); + R_PolygonVertex(org - v_right * 2 + v_up * 2, [0,0], rgb, 1); + R_EndPolygon(); + + R_BeginPolygon("", 0, 0); + R_PolygonVertex(org - v_right * 2 + v_up * 2, [0,0], rgb, 1); + R_PolygonVertex(org + v_right * 2 + v_up * 2, [1,0], rgb, 1); + R_EndPolygon(); + + R_BeginPolygon("", 0, 0); + R_PolygonVertex(org + v_right * 2 + v_up * 2, [1,0], rgb, 1); + R_PolygonVertex(org + v_right * 2 - v_up * 2, [1,1], rgb, 1); R_EndPolygon(); } @@ -707,6 +584,9 @@ Way_DrawDebugInfo(void) R_EndPolygon(); } + /* spheres need view angle */ + makevectors(self.v_angle); + R_BeginPolygon("", 0, 0); for (int i = 0i; i < g_iWaypoints; i++) { vector rgb; @@ -814,20 +694,8 @@ Way_Cmd(void) g_pWaypoints[i].m_vecOrigin[2] *= -1; } break; - case "linkjump": - Way_FlagJump(); - break; - case "linkcrouch": - Way_FlagCrouch(); - break; - case "linkwalk": - Way_FlagWalk(); - break; - case "linkaim": - Way_FlagAim(); - break; - case "linkuse": - Way_FlagUse(); + case "flag": + Way_LinkFlag(stoi(argv(2))); break; case "unlink1": Way_Unlink(); diff --git a/src/client/NSInteractiveSurface.qc b/src/client/NSInteractiveSurface.qc index 291c94b9..97634aa3 100644 --- a/src/client/NSInteractiveSurface.qc +++ b/src/client/NSInteractiveSurface.qc @@ -268,7 +268,7 @@ NSInteractiveSurface::NSInteractiveSurface(void) m_flScale = 0.25f; m_flUseDistance = 64; m_strSurfaceMat = sprintf("UISurface%d", num_for_edict(this)); - print(sprintf("Surface mat: %S\n", m_strSurfaceMat)); + EntLog("UI surface material: %S\n", m_strSurfaceMat); drawmask = MASK_ENGINE; m_bCached = false; isCSQC = true; diff --git a/src/client/NSRadar.qc b/src/client/NSRadar.qc index c2acbf30..9f411ef4 100644 --- a/src/client/NSRadar.qc +++ b/src/client/NSRadar.qc @@ -302,8 +302,7 @@ NSRadar::InitFromHLTVScript(string fileName) r_uploadimage("overview", width, height, (void *)imgData); memfree(imgData); newRadar.m_strMaterial = "overview"; - - print("Overview loaded.\n"); + NSLog("Map overview available."); return newRadar; } @@ -369,7 +368,6 @@ NSRadar::InitFromSourceHLTVScript(string fileName) vector imageSize = drawgetimagesize(newRadar.m_strMaterial); imageSize *= newRadar.m_flScale; newRadar.CalculateVerticesSource(imageSize[0], imageSize[1]); - - print("Overview loaded.\n"); + NSLog("Map overview available."); return newRadar; } \ No newline at end of file diff --git a/src/client/cmd.qc b/src/client/cmd.qc index b7827f40..60138c3c 100644 --- a/src/client/cmd.qc +++ b/src/client/cmd.qc @@ -207,14 +207,14 @@ CMD_ListTitles(void) int i = 0i; for (i = 0; i < g_titles_count; i++) { - print(sprintf("%s, (x: %d, y: %d)\n", - g_titles[i].m_strName, g_titles[i].m_flPosX, g_titles[i].m_flPosY)); - print(sprintf("\teffect: %i, fade-in: %f, fade-out: %f\n", - g_titles[i].m_iEffect, g_titles[i].m_flFadeIn, g_titles[i].m_flFadeOut)); - print(sprintf("\thold-time: %f, fx-time: %f\n", - g_titles[i].m_flHoldTime, g_titles[i].m_flFXTime)); - print(sprintf("\tcolor 1: %v, color 2: %v\n", - g_titles[i].m_vecColor1, g_titles[i].m_vecColor2)); + printf("%s, (x: %d, y: %d)\n", + g_titles[i].m_strName, g_titles[i].m_flPosX, g_titles[i].m_flPosY); + printf("\teffect: %i, fade-in: %f, fade-out: %f\n", + g_titles[i].m_iEffect, g_titles[i].m_flFadeIn, g_titles[i].m_flFadeOut); + printf("\thold-time: %f, fx-time: %f\n", + g_titles[i].m_flHoldTime, g_titles[i].m_flFXTime); + printf("\tcolor 1: %v, color 2: %v\n", + g_titles[i].m_vecColor1, g_titles[i].m_vecColor2); } print(sprintf("\t%i total titles loaded\n", g_titles_count)); } @@ -226,12 +226,12 @@ CMD_ListModelFramegroups(void) float modelIndex = getmodelindex(modelName); string temp = ""; - print(sprintf("// model: %S\n", modelName)); + printf("// model: %S\n", modelName); print("typedef enum {\n"); for (int i = 0; i < modelframecount(modelIndex); i++) { temp = frametoname(modelIndex, i); - print(sprintf("\t%s = %i,\n", strtoupper(temp), i)); + printf("\t%s = %i,\n", strtoupper(temp), i); } print("} framegroups_e;\n"); } @@ -271,7 +271,7 @@ Cmd_Parse(string sCMD) case "listServerSoundDef": localcmd("sv listSoundDef\n"); break; - case "cleardecals": + case "clearDecals": CMD_Cleardecals(); break; case "testPointLight": @@ -437,28 +437,28 @@ Cmd_Parse(string sCMD) localcmd(sprintf("sv addBot %s\n", argv(1))); break; case "killAllBots": - localcmd(sprintf("sv killAllBots %s\n", argv(1))); + localcmd("sv killAllBots\n"); break; case "resetAllBotsGoals": - localcmd(sprintf("sv resetAllBotsGoals %s\n", argv(1))); + localcmd("sv resetAllBotsGoals\n"); break; case "killClass": localcmd(sprintf("sv killClass %s\n", argv(1))); break; case "killMovables": - localcmd(sprintf("sv killMovables %s\n", argv(1))); + localcmd("sv killMovables\n"); break; case "trigger": localcmd(sprintf("sv trigger %s\n", argv(1))); break; case "input": - localcmd(sprintf("sv input %s\n", argv(1))); + localcmd(sprintf("sv input %s %s %s\n", argv(1), argv(2), argv(3))); break; case "listBotProfiles": - localcmd(sprintf("sv listBotProfiles %s\n", argv(1))); + localcmd("sv listBotProfiles\n"); break; case "listTargets": - localcmd(sprintf("sv listTargets %s\n", argv(1))); + localcmd("sv listTargets\n"); break; case "teleport": localcmd(sprintf("sv teleport %s\n", argv(1))); @@ -467,12 +467,35 @@ Cmd_Parse(string sCMD) localcmd(sprintf("sv teleportToClass %s\n", argv(1))); break; case "respawnEntities": - localcmd(sprintf("sv respawnEntities %s\n", argv(1))); + localcmd("sv respawnEntities\n"); break; - case "spawn": + case "spawnDef": localcmd(sprintf("sv spawn %s\n", argv(1))); break; + + case "nodeAdd": + localcmd(sprintf("sv way addsingle %s\n", argv(1))); + break; + case "nodeDel": + localcmd(sprintf("sv way delete %s\n", argv(1))); + break; + case "nodeFlags": + localcmd(sprintf("sv way link %s\n", argv(1))); + break; + case "nodeLink": + localcmd(sprintf("sv way connect1 %s\n", argv(1))); + break; + case "nodeRadius": + localcmd(sprintf("sv way radius %s\n", argv(1))); + break; + case "nodeOffset": + localcmd(sprintf("sv way move %s\n", argv(1))); + break; + case "nodeUnlink": + localcmd(sprintf("sv way unlink1 %s\n", argv(1))); + break; + default: return (false); } @@ -489,7 +512,7 @@ Register our commands for Nuclide void Cmd_Init(void) { - print("--------- Initializing Cmds ----------\n"); + InitStart(); /* developer/debug commands */ registercommand("listFramegroups"); @@ -512,10 +535,19 @@ Cmd_Init(void) registercommand("teleport"); registercommand("teleportToClass"); registercommand("respawnEntities"); - registercommand("spawn"); + registercommand("spawnDef"); registercommand("listBotProfiles"); - registercommand("cleardecals"); + /* nav editing */ + registercommand("nodeAdd"); + registercommand("nodeDel"); + registercommand("nodeFlags"); + registercommand("nodeLink"); + registercommand("nodeRadius"); + registercommand("nodeOffset"); + registercommand("nodeUnlink"); + + registercommand("clearDecals"); registercommand("testLight"); registercommand("testPointLight"); registercommand("getpos"); @@ -586,4 +618,6 @@ Cmd_Init(void) registercommand("-menu_left"); registercommand("+menu_right"); registercommand("-menu_right"); + + InitEnd(); } diff --git a/src/client/defs.h b/src/client/defs.h index 0d29fa7e..93512370 100644 --- a/src/client/defs.h +++ b/src/client/defs.h @@ -175,6 +175,7 @@ void View_PlayAnimation(int); void View_EnableViewmodel(void); void View_DisableViewmodel(void); +void View_SetViewmodelSkin(float); /** Draws a non-filled rectangle with a specified outline. */ void drawrect(vector pos, vector sz, float thickness, vector rgb, float al, optional float dfl) diff --git a/src/client/detailtex.qc b/src/client/detailtex.qc index 29d2bc82..98f8b736 100644 --- a/src/client/detailtex.qc +++ b/src/client/detailtex.qc @@ -74,12 +74,10 @@ DetailTex_Reload(void) if (!autocvar(r_detailtextures, 0, "High-res detail texture overlays for selected maps")) return; - print("--------- Initializing DetailTex ----------\n"); - fh = fopen(strcat("maps/", mapname, "_detail.txt"), FILE_READ); if (fh < 0) { - print(sprintf("DeailTex definition not found for %s.\n", mapname)); + NSError("DeailTex definition missing for %s.", mapname); return; } @@ -93,7 +91,7 @@ DetailTex_Reload(void) n++; } - print(sprintf("DeailTex initialized with %i entries.\n", n)); + NSLog("DeailTex initialized with %i entries.", n); fclose(fh); g_detail_initialized = 1; } diff --git a/src/client/efx.qc b/src/client/efx.qc index 705b4a4e..6c33aa9d 100644 --- a/src/client/efx.qc +++ b/src/client/efx.qc @@ -96,7 +96,8 @@ EFX_Load(string efx_file) g_efx_name = (string *)memrealloc(g_efx_name, sizeof(string), i, g_efx_count); #else if (g_efx_count > EFXDATA_MAX) { - error(sprintf("EFX_Load: Reached EFXDATA_MAX (%d)\n", EFXDATA_MAX)); + NSError("EFX_Load: Reached EFXDATA_MAX (%d)", EFXDATA_MAX); + return (0); } #endif @@ -210,7 +211,7 @@ EFX_Load(string efx_file) } } - print(sprintf("parsed EFXDef file %s\n", efx_file)); + NSLog("parsed EFXDef file %S", efx_file); fclose(fh); return i; } @@ -318,7 +319,7 @@ EFX_UpdateListener(NSView playerView) } g_flEFXTime += clframetime; #else - NSLog("EFX_UpdateListener: Changed style to %s (%i)", + SndLog("Changed style to %s (%i)", g_efx_name[g_iEFX], g_iEFX); old_dsp = g_iEFX; @@ -332,14 +333,14 @@ EFX_Init(void) int efx_default; int efx_underwater; - print("--------- Initializing EFXDefs ----------\n"); + InitStart(); #ifndef EFXDATA_DYNAMIC g_efx = (reverbinfo_t *)memalloc(sizeof(reverbinfo_t) * EFXDATA_MAX); g_efx_name = (string *)memalloc(sizeof(string) * EFXDATA_MAX); - print(sprintf("allocated %d bytes for EFXDefs.\n", (sizeof(string) * EFXDATA_MAX) + (sizeof(reverbinfo_t) * EFXDATA_MAX))); + NSLog("...allocated %d bytes for EFXDefs.", (sizeof(string) * EFXDATA_MAX) + (sizeof(reverbinfo_t) * EFXDATA_MAX)); #else - print("dynamic allocation for EFXDefs enabled.\n"); + NSLog("...dynamic allocation for EFXDefs enabled."); #endif efx_default = EFX_Load("default"); @@ -354,6 +355,7 @@ EFX_Init(void) setup_reverb(12, &g_efx[g_iEFX], sizeof(reverbinfo_t)); setup_reverb(10, &g_efx[efx_underwater], sizeof(reverbinfo_t)); + InitEnd(); } void diff --git a/src/client/entities.qc b/src/client/entities.qc index fe637766..8fdcb76c 100644 --- a/src/client/entities.qc +++ b/src/client/entities.qc @@ -236,7 +236,6 @@ void Entities_RendererRestarted(void) { int c = 0; - print("--------- Reloading Entity Resources ----------\n"); for (entity b = world; (b = findfloat(b, ::isCSQC, TRUE));) { NSEntity pf = (NSEntity) b; @@ -244,5 +243,5 @@ Entities_RendererRestarted(void) c++; } - print(sprintf("resource reload called on %i entities\n", c)); + NSLog("...resource reload called on %i entities", c); } diff --git a/src/client/entry.qc b/src/client/entry.qc index 170bfe3c..b2db52ac 100644 --- a/src/client/entry.qc +++ b/src/client/entry.qc @@ -35,9 +35,9 @@ Also called when map changes happen. void CSQC_Init(float apilevel, string enginename, float engineversion) { - print("--------- Initializing Client Game ----------\n"); - print("Built: " __DATE__ " " __TIME__"\n"); - print("QCC: " __QCCVER__ "\n"); + InitPrint("Initializing Client Game"); + NSLog("Built: %s %s", __DATE__, __TIME__); + NSLog("QCC: %s", __QCCVER__); for (int i = 0; i < 4; i++) { g_viewSeats[i] = spawn(NSView); @@ -90,7 +90,7 @@ CSQC_Init(float apilevel, string enginename, float engineversion) Sound_Precache("Player.WeaponSelectionClose"); /* end msg */ - print("Client game initialized.\n"); + NSLog("Client game initialized."); /* because the engine will do really bad hacks to our models otherwise. e.g. R6284 */ cvar_set("r_fullbrightSkins", "0"); @@ -108,7 +108,7 @@ somewhere in csprogs.dat to ensure their resources are reloaded properly. void CSQC_RendererRestarted(string rstr) { - print("--------- Reloading Graphical Resources ----------\n"); + InitStart(); /* Fonts */ Font_Load("fonts/font16.font", FONT_16); @@ -146,8 +146,7 @@ CSQC_RendererRestarted(string rstr) g_shellchromeshader = shaderforname("shellchrome", sprintf("{\ndeformVertexes bulge 1.25 1.25 0\n{\nmap %s\ntcMod scroll -0.1 0.1\ntcGen environment\nrgbGen entity\n}\n}", "textures/sfx/reflection.tga")); g_shellchromeshader_cull = shaderforname("shellchrome2", sprintf("{\ncull back\ndeformVertexes bulge 1.5 1.5 0\n{\nmap %s\ntcMod scroll -0.1 0.1\ntcGen environment\nrgbGen entity\n}\n}", "textures/sfx/reflection.tga")); - /* end msg */ - print("Graphical resources reloaded\n"); + InitEnd(); } /** Always call this instead of renderscene(); ! @@ -548,7 +547,8 @@ ourselves if need be. void CSQC_WorldLoaded(void) { - print("--------- Initializing Client World ----------\n"); + InitStart(); + //DetailTex_Init(); /* Primarily for the flashlight */ @@ -567,11 +567,11 @@ CSQC_WorldLoaded(void) break; } if (strTokenized != "{") { - print("^1[WARNING] ^7Bad entity data\n"); + NSWarning("Bad entity data"); break; } if (!Entities_ParseLump()) { - print("^1[WARNING] ^7Bad entity data\n"); + NSWarning("Bad entity data"); break; } } @@ -586,7 +586,7 @@ CSQC_WorldLoaded(void) /* wad files will most likely have loaded now */ DecalGroups_Precache(); - print("Client world initialized.\n"); + InitEnd(); } /** Called when a server tells us an active entity gets removed. @@ -626,12 +626,12 @@ that is the last thing that will be called. void CSQC_Shutdown(void) { - print("--------- Shutting Client Game ----------\n"); + InitPrint("Shutting Client Game"); Decal_Shutdown(); Sentences_Shutdown(); Titles_Shutdown(); Sound_Shutdown(); PropData_Shutdown(); EFX_Shutdown(); - print("Client game shutdown.\n"); + NSLog("Client game shutdown."); } diff --git a/src/client/fade.qc b/src/client/fade.qc index 199e6e73..0bf5acb9 100644 --- a/src/client/fade.qc +++ b/src/client/fade.qc @@ -53,16 +53,15 @@ Fade_Update (int x, int y, int w, int h) if (pSeat->m_iFadeActive == FALSE) { return; } + pSeat->m_flFadeAlpha = 1.0f; + if (pSeat->m_flFadeStyle & EVF_FADEDROM) { - pSeat->m_flFadeAlpha = 1.0f; if (pSeat->m_flFadeTime > pSeat->m_flFadeDuration) { pSeat->m_flFadeAlpha -= (pSeat->m_flFadeTime - pSeat->m_flFadeDuration) * (1.0 / pSeat->m_flFadeHold); } } else { if (pSeat->m_flFadeTime < pSeat->m_flFadeDuration) { pSeat->m_flFadeAlpha = pSeat->m_flFadeTime * (1.0 / pSeat->m_flFadeDuration); - } else { - pSeat->m_flFadeAlpha = (pSeat->m_flFadeTime - pSeat->m_flFadeDuration) * (1.0 / pSeat->m_flFadeHold); } } diff --git a/src/client/font.qc b/src/client/font.qc index 88818834..6998f0db 100644 --- a/src/client/font.qc +++ b/src/client/font.qc @@ -76,14 +76,14 @@ Font_Load(string strFile, font_s &fntNew) } fclose(fileFont); } else { - error(sprintf("cannot load font file %s!", strFile)); + NSError("Missing file %s", strFile); } if (!fntNew.iScaleX || !fntNew.iScaleY) { - error(sprintf("no valid size defined for %s!", strFile)); + NSError("Invalid size defined for %s", strFile); } - print(sprintf("loaded font definition for %s\n", strFile)); + NSLog("Loaded font definition for %s", strFile); if (strRenderSize != "") { fntNew.iID = (int)loadfont("", strFontPath, strRenderSize, -1, 0, 0); diff --git a/src/client/shake.qc b/src/client/shake.qc index ffa784a5..fda44bf7 100644 --- a/src/client/shake.qc +++ b/src/client/shake.qc @@ -14,15 +14,29 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define SHAKE_YAW_DEGREES 5.0f +#define SHAKE_YAW_HERTZ 15.0f +#define SHAKE_PITCH_DEGREES 5.0f +#define SHAKE_PITCH_HERTZ 5.0f +#define SHAKE_ROLL_DEGREES 5.0f +#define SHAKE_ROLL_HERTZ 5.0f + void Shake_Update(NSClientPlayer pl) { if (pSeat->m_flShakeDuration > 0.0) { + float shakeMultiplier = (pSeat->m_flShakeDuration / pSeat->m_flShakeTime); + float sineWave1 = (sin(time * SHAKE_PITCH_HERTZ) * SHAKE_PITCH_DEGREES) * shakeMultiplier; + float sineWave2 = (sin(time * SHAKE_YAW_HERTZ) * SHAKE_YAW_DEGREES) * shakeMultiplier; + float sineWave3 = (sin(time * SHAKE_ROLL_HERTZ) * SHAKE_ROLL_DEGREES) * shakeMultiplier; vector vecShake = [0,0,0]; - vecShake[0] += random() * 3; - vecShake[1] += random() * 3; - vecShake[2] += random() * 3; - pl.punchangle += (vecShake * pSeat->m_flShakeAmp) * (pSeat->m_flShakeDuration / pSeat->m_flShakeTime); + vecShake[0] += random() * 1.5; + vecShake[1] += random() * 1.5; + vecShake[2] += random() * 1.5; + vecShake[0] += sineWave1; + vecShake[1] += sineWave2; + vecShake[2] += sineWave3; + pl.punchangle += (vecShake * pSeat->m_flShakeAmp) * shakeMultiplier; pSeat->m_flShakeDuration -= clframetime; } } diff --git a/src/client/sky.qc b/src/client/sky.qc index 01929f4f..d664dc08 100644 --- a/src/client/sky.qc +++ b/src/client/sky.qc @@ -39,6 +39,6 @@ Sky_Update(int force) return; localcmd(sprintf("sky \"%s\"\n", skyPath)); - print(sprintf("sky update applying %s.\n", skyPath)); + NSLog("sky update applying %s.", skyPath); } } diff --git a/src/client/titles.qc b/src/client/titles.qc index 058b0569..fb26a9e6 100644 --- a/src/client/titles.qc +++ b/src/client/titles.qc @@ -121,14 +121,15 @@ Titles_Init(void) int braced; int id = 0; - print("--------- Initializing TitlesDef ----------\n"); + InitStart(); Titles_Shutdown(); fs_titles = fopen("titles.txt", FILE_READ); if (fs_titles < 0) { - print("^1could NOT load titles.txt\n"); + NSError("missing titles.txt"); + InitEnd(); return; } @@ -165,7 +166,7 @@ Titles_Init(void) } } - print(sprintf("read %i titleDefs (%i bytes).\n", g_titles_count, sizeof(titles_t) * g_titles_count)); + NSLog("read %i titleDefs (%i bytes).", g_titles_count, sizeof(titles_t) * g_titles_count); g_titles = memalloc(sizeof(titles_t) * g_titles_count); fseek(fs_titles, 0); @@ -256,6 +257,8 @@ Titles_Init(void) } } fclose(fs_titles); + + InitEnd(); } diff --git a/src/client/view.qc b/src/client/view.qc index edba7c80..b423f56e 100644 --- a/src/client/view.qc +++ b/src/client/view.qc @@ -127,6 +127,8 @@ View_ForceChange(player pl, int targetWeapon) View_ClearEvents(); View_DisableViewmodel(); View_SetMuzzleflash(0); + m_eViewModel.frame1time = 0.0f; + m_eViewModelL.frame1time = 0.0f; } /* @@ -286,7 +288,7 @@ View_DrawViewModel(void) #endif /* only draw the model when it's 'enabled'... */ - if (m_eViewModel.alpha != 0.0f) { + if (m_eViewModel.IsHidden() == false) { setorigin(m_eViewModel, m_eViewModel.origin); setorigin(m_eViewModelL, m_eViewModel.origin); @@ -359,15 +361,26 @@ View_GetAnimation(void) void View_EnableViewmodel(void) { - pSeat->m_eViewModel.alpha = - pSeat->m_eViewModelL.alpha = 1.0f; + NSRenderableEntity viewModel; + viewModel = (NSRenderableEntity)pSeat->m_eViewModel; + viewModel.Show(); + viewModel = (NSRenderableEntity)pSeat->m_eViewModelL; + viewModel.Show(); } void View_DisableViewmodel(void) { - pSeat->m_eViewModel.alpha = - pSeat->m_eViewModelL.alpha = 0.0f; - pSeat->m_eViewModel.frame1time = - pSeat->m_eViewModelL.frame1time = 0.0f; + NSRenderableEntity viewModel; + viewModel = (NSRenderableEntity)pSeat->m_eViewModel; + viewModel.Hide(); + viewModel = (NSRenderableEntity)pSeat->m_eViewModelL; + viewModel.Hide(); +} + +void +View_SetViewmodelSkin(float skinValue) +{ + pSeat->m_eViewModel.skin = + pSeat->m_eViewModelL.skin = skinValue; } diff --git a/src/client/way.qc b/src/client/way.qc index cd0eb0ac..4103f539 100644 --- a/src/client/way.qc +++ b/src/client/way.qc @@ -112,7 +112,7 @@ Way_Init(void) "3.\tFlag ^1WALK^7 (2 steps)\n" \ "4.\tFlag ^4AIM^7 (2 steps)\n" \ "5.\tFlag ^4USE^7 (2 steps)\n" \ - "\n" \ + "6.\tFlag ^6HAZARDOUS^7 (2 steps)\n" \ "\n" \ "\n" \ "9.\tBack\n"; @@ -293,19 +293,22 @@ WAY_FLAGS(int n) { switch (n) { case 1: - localcmd("sv way linkjump\n"); + localcmd("sv way flag 2\n"); break; case 2: - localcmd("sv way linkcrouch\n"); + localcmd("sv way flag 4\n"); break; case 3: - localcmd("sv way linkwalk\n"); + localcmd("sv way flag 16\n"); break; case 4: - localcmd("sv way linkaim\n"); + localcmd("sv way flag 32\n"); break; case 5: - localcmd("sv way linkuse\n"); + localcmd("sv way flag 64\n"); + break; + case 6: + localcmd("sv way flag 128\n"); break; case 9: Textmenu_Call("WAY_MENU"); diff --git a/src/gs-entbase/client/env_cubemap.qc b/src/gs-entbase/client/env_cubemap.qc index ffc5e905..a5e119ec 100644 --- a/src/gs-entbase/client/env_cubemap.qc +++ b/src/gs-entbase/client/env_cubemap.qc @@ -94,7 +94,7 @@ CMap_Shoot(void) string strReflectcube; if (self.owner) { env_cubemap tmp = (env_cubemap) self.owner; - print("^3Cubemap processing...\n"); + NSLog("Generating cubemap '%v' (%dx%d)", g_vecCubePos, g_dCubeSize, g_dCubeSize); g_vecCubePos = tmp.origin; g_dCubeSize = (float)tmp.m_iSize; @@ -114,7 +114,7 @@ CMap_Shoot(void) self.think = CMap_Check; self.nextthink = time + 0.25f; } else { - print("^2Cubemaps done...\n"); + NSLog("Generating level cubemaps done."); localcmd("r_skipEnvmap 0\n"); localcmd("vid_reload\n"); g_iCubeProcess = FALSE; @@ -161,7 +161,8 @@ CMap_Build(void) localcmd("r_hdr_irisadaptation 0\n"); localcmd("r_postprocshader \"\"0\n"); localcmd("r_skipEnvmap 1\n"); - print("^4Building cubemaps...\n"); + + NSLog("Building cubemaps...\n"); g_eCubeCycle = spawn(); g_eCubeCycle.owner = find(world, classname, "env_cubemap"); diff --git a/src/gs-entbase/client/env_sound.qc b/src/gs-entbase/client/env_sound.qc index 02509832..f8606196 100644 --- a/src/gs-entbase/client/env_sound.qc +++ b/src/gs-entbase/client/env_sound.qc @@ -99,7 +99,7 @@ env_sound::SpawnKey(string strField, string strKey) int efx_alias = stoi(strKey); if (efx_alias >= g_hlefx.length) { - NSEntWarning("invalid roomtype!"); + EntWarning("invalid roomtype!"); m_iRoomType = 0; } else m_iRoomType = EFX_Load(g_hlefx[efx_alias]); diff --git a/src/gs-entbase/server/cycler.qc b/src/gs-entbase/server/cycler.qc index ba439d75..6b4b214c 100644 --- a/src/gs-entbase/server/cycler.qc +++ b/src/gs-entbase/server/cycler.qc @@ -67,5 +67,6 @@ cycler::Pain(void) } else { SetFrame(GetFrame() + 1); } + SetHealth(9999); } diff --git a/src/gs-entbase/server/cycler_sprite.qc b/src/gs-entbase/server/cycler_sprite.qc index 973cac19..359d0835 100644 --- a/src/gs-entbase/server/cycler_sprite.qc +++ b/src/gs-entbase/server/cycler_sprite.qc @@ -16,7 +16,7 @@ /*!QUAKED cycler_sprite (1 0 0) (-8 -8 -8) (8 8 8) # OVERVIEW -Decorative, does nothing yet. +Decorative sprite cycler. # KEYS - "targetname" : Name @@ -24,6 +24,7 @@ Decorative, does nothing yet. - "killtarget" : Target to kill when triggered. - "angles" : Sets the pitch, yaw and roll angles of the model. - "model" : Model file that will be displayed by the entity. +- "framerate" : TODO: Frame rate of the sprite, in frames per second. # TRIVIA This entity was introduced in Half-Life (1998). diff --git a/src/gs-entbase/server/env_physexplosion.qc b/src/gs-entbase/server/env_physexplosion.qc index 269b70a5..38f8e61c 100644 --- a/src/gs-entbase/server/env_physexplosion.qc +++ b/src/gs-entbase/server/env_physexplosion.qc @@ -142,7 +142,7 @@ env_physexplosion::TriggerExplosion(void) physEnt = (NSPhysicsEntity)find(world, ::targetname, m_strTargetEntity); if (!physEnt) { - NSEntWarning("Target set, but not found!"); + EntWarning("Target set, but not found!"); return; } diff --git a/src/gs-entbase/server/env_render.qc b/src/gs-entbase/server/env_render.qc index 95e90ecc..a26965e7 100644 --- a/src/gs-entbase/server/env_render.qc +++ b/src/gs-entbase/server/env_render.qc @@ -97,22 +97,22 @@ env_render::Trigger(entity act, triggermode_t state) (e = find(e, ::targetname, target));) { NSRenderableEntity trigger = (NSRenderableEntity)e; - NSLog("^2env_render::^3Trigger^7: with spawnflags %d", spawnflags); - NSLog("\tTarget: %s", target); + EntLog("Triggering with spawnflags %d", spawnflags); + EntLog("\tTarget: %s", target); if (!HasSpawnFlags(SF_NORENDERMODE)) { - NSLog("\tMode change from %d to %d", trigger.m_iRenderMode, m_iRenderMode); + EntLog("\tMode change from %d to %d", trigger.m_iRenderMode, m_iRenderMode); trigger.SetRenderMode(m_iRenderMode); } if (!HasSpawnFlags(SF_NORENDERCOLOR)) { - NSLog("\tColor change from %v to %v", trigger.m_vecRenderColor, m_vecRenderColor); + EntLog("\tColor change from %v to %v", trigger.m_vecRenderColor, m_vecRenderColor); trigger.SetRenderColor(m_vecRenderColor); } if (!HasSpawnFlags(SF_NORENDERAMT)) { - NSLog("\tAmt change from %d to %d", trigger.m_flRenderAmt, m_flRenderAmt); + EntLog("\tAmt change from %d to %d", trigger.m_flRenderAmt, m_flRenderAmt); trigger.SetRenderAmt(m_flRenderAmt); } if (!HasSpawnFlags(SF_NORENDERFX)) { - NSLog("\tFX change from %d to %d", trigger.m_iRenderFX, m_iRenderFX); + EntLog("\tFX change from %d to %d", trigger.m_iRenderFX, m_iRenderFX); trigger.SetRenderFX(m_iRenderFX); } } diff --git a/src/gs-entbase/server/func_breakable.qc b/src/gs-entbase/server/func_breakable.qc index 14ed1f67..a5f46879 100644 --- a/src/gs-entbase/server/func_breakable.qc +++ b/src/gs-entbase/server/func_breakable.qc @@ -23,7 +23,7 @@ enumflags enum { - BREAKMT_GLASS, + BREAKMT_GLASS = 0, BREAKMT_WOOD, BREAKMT_METAL, BREAKMT_FLESH, @@ -161,9 +161,9 @@ func_breakable::func_breakable(void) /* func_breakable defaults to glass */ if (classname == "func_breakable") { - material = 0; + material = BREAKMT_GLASS; } else { - material = 1; + material = BREAKMT_WOOD; } } @@ -176,6 +176,7 @@ func_breakable::Save(float handle) SaveFloat(handle, "m_flExplodeRad", m_flExplodeRad); SaveString(handle, "m_strBreakSpawn", m_strBreakSpawn); SaveBool(handle, "m_bCanTouch", m_bCanTouch); + SaveFloat(handle, "material", material); } void @@ -197,6 +198,9 @@ func_breakable::Restore(string strKey, string strValue) case "m_bCanTouch": m_bCanTouch = ReadBool(strValue); break; + case "material": + material = ReadFloat(strValue); + break; default: super::Restore(strKey, strValue); } @@ -207,7 +211,7 @@ func_breakable::SpawnKey(string strKey, string strValue) { switch (strKey) { case "material": - material = stof(strValue); + material = ReadFloat(strValue); break; case "explodemagnitude": m_flExplodeMag = stof(strValue); @@ -218,7 +222,7 @@ func_breakable::SpawnKey(string strKey, string strValue) if (oid >= funcbreakable_objtable.length) { m_strBreakSpawn = ""; - NSEntWarning("spawnobject %i out of bounds", oid); + EntWarning("spawnobject %i out of bounds", oid); } else { m_strBreakSpawn = funcbreakable_objtable[oid]; } @@ -288,8 +292,9 @@ func_breakable::Pain(void) painSound = GetSurfaceData(SURFDATA_SND_BULLETIMPACT); - if (painSound) + if (painSound) { StartSoundDef(painSound, CHAN_VOICE, true); + } } @@ -354,16 +359,17 @@ func_breakable::Death(void) vector vecDir = vectoangles(WorldSpaceCenter() - g_dmg_vecLocation); string sndBreak = GetSurfaceData(SURFDATA_SND_BREAK); string breakModel = GetPropData(PROPINFO_BREAKMODEL); + int gibCount = (int)bound(5, vlen(size) / 10, 32); if (breakModel != "") - BreakModel_Spawn(absmin, absmax, vecDir, g_dmg_iDamage * 2.5, vlen(size) / 10, breakModel); + BreakModel_Spawn(absmin, absmax, vecDir, g_dmg_iDamage * 2.5, gibCount, breakModel); else - NSLog("func_breakable (%s) does not have a propdata break model", funcbreakable_surftable[material]); + EntLog("func_breakable (%s) does not have a propdata break model", funcbreakable_surftable[material]); if (sndBreak != "") StartSoundDef(sndBreak, CHAN_BODY, true); else - NSLog("func_breakable (%s) does not have a surfaceproperty for break", funcbreakable_surftable[material]); + EntLog("func_breakable (%s) does not have a surfaceproperty for break", funcbreakable_surftable[material]); Disappear(); SetTakedamage(DAMAGE_NO); diff --git a/src/gs-entbase/server/func_guntarget.qc b/src/gs-entbase/server/func_guntarget.qc index abe7b6f0..1716676e 100644 --- a/src/gs-entbase/server/func_guntarget.qc +++ b/src/gs-entbase/server/func_guntarget.qc @@ -148,7 +148,7 @@ func_guntarget::Move(void) node = (path_corner)find(world, ::targetname, target); if (!node) { - NSEntWarning("node %s for %s not found!", target, targetname); + EntWarning("node %s for %s not found!", target, targetname); return; } @@ -172,7 +172,7 @@ func_guntarget::NextPath(void) { path_corner node; - NSLog("^2func_guntarget::^3NextPath^7: Talking to current target %s... ", target); + EntLog("Talking to current target %s... ", target); node = (path_corner)find(world, ::targetname, target); if (!node) { diff --git a/src/gs-entbase/server/func_plat.qc b/src/gs-entbase/server/func_plat.qc index ab066ea8..2b643755 100644 --- a/src/gs-entbase/server/func_plat.qc +++ b/src/gs-entbase/server/func_plat.qc @@ -62,6 +62,7 @@ public: virtual void Save(float); virtual void Restore(string,string); virtual void Trigger(entity, triggermode_t); + virtual void Input(entity, string, string); virtual void Respawn(void); virtual void SpawnKey(string,string); virtual void Spawned(void); @@ -234,6 +235,21 @@ func_plat::Respawn(void) } } +void +func_plat::Input(entity entityActivator, string inputName, string dataField) +{ + switch (inputName) { + case "GoUp": + MoveToPosition(GetMoverPosition1(), m_flSpeed); + break; + case "GoDown": + MoveToPosition(GetMoverPosition2(), m_flSpeed); + break; + default: + super::Input(entityActivator, inputName, dataField); + } +} + void func_plat::Trigger(entity act, triggermode_t state) { diff --git a/src/gs-entbase/server/func_pushable.qc b/src/gs-entbase/server/func_pushable.qc index 7fac27fa..ded28148 100644 --- a/src/gs-entbase/server/func_pushable.qc +++ b/src/gs-entbase/server/func_pushable.qc @@ -180,7 +180,7 @@ func_pushable::Respawn(void) if (!m_eCollBox) { m_eCollBox = spawn(); m_eCollBox.classname = "func_pushable_bbox"; - m_eCollBox.solid = SOLID_BBOX; + m_eCollBox.solid = SOLID_TRIGGER; m_eCollBox.owner = this; setsize(m_eCollBox, -(size/2) * 0.9f, (size/2) * 0.9f); setorigin(m_eCollBox, WorldSpaceCenter()); @@ -229,7 +229,7 @@ func_pushable::customphysics(void) if (modelindex == 0) { m_eCollBox.solid = SOLID_NOT; } else { - m_eCollBox.solid = SOLID_BBOX; + m_eCollBox.solid = SOLID_TRIGGER; } wasMoving = m_bIsMoving; diff --git a/src/gs-entbase/server/func_trackchange.qc b/src/gs-entbase/server/func_trackchange.qc index 1e03f919..78904f6e 100644 --- a/src/gs-entbase/server/func_trackchange.qc +++ b/src/gs-entbase/server/func_trackchange.qc @@ -142,10 +142,10 @@ func_trackchange::MoverStartsMoving(void) ourTrain.SetVelocity(GetVelocity()); ourTrain.SetAngularVelocity(GetAngularVelocity()); ourTrain.ScheduleThink(ClearVelocity, 100.0f); - print(sprintf("Changing %s to have no target\n", m_strTrainName)); - print(sprintf("%v %v\n", GetVelocity(), GetAngularVelocity())); + EntLog("Changing %s to have no target.", m_strTrainName); + EntLog("Velocity: %v; Angular Velocity: %v", GetVelocity(), GetAngularVelocity()); } else { - print(sprintf("No train to go with trackchange %s\n", targetname)); + EntLog("No train to go with trackchange %S", targetname); } } @@ -159,13 +159,13 @@ func_trackchange::MoverFinishesMoving(void) ourTrain.ClearVelocity(); if (GetMoverState() == MOVER_POS1) { - print(sprintf("Changing %s from %s to %s\n", m_strTrainName, m_strBottomTrack, m_strTopTrack)); + EntLog("Changing %S from %S to %S", m_strTrainName, m_strBottomTrack, m_strTopTrack); ourTrain.target = m_strTopTrack; } else { - print(sprintf("Changing %s from %s to %s\n", m_strTrainName, m_strBottomTrack, m_strBottomTrack)); + EntLog("Changing %S from %S to %S", m_strTrainName, m_strBottomTrack, m_strBottomTrack); ourTrain.target = m_strBottomTrack; } } else { - print(sprintf("No train to go with trackchange %s\n", targetname)); + EntLog("No train to go with trackchange %S", targetname); } } \ No newline at end of file diff --git a/src/gs-entbase/server/func_tracktrain.qc b/src/gs-entbase/server/func_tracktrain.qc index 21848215..58317c1d 100644 --- a/src/gs-entbase/server/func_tracktrain.qc +++ b/src/gs-entbase/server/func_tracktrain.qc @@ -110,6 +110,7 @@ public: nonvirtual vector GetTrainPivotPoint(bool); nonvirtual void RenderDebugInfo(void); + nonvirtual bool ControlCheck(entity); /* overrides */ virtual void Blocked(entity); @@ -304,14 +305,14 @@ func_tracktrain::RenderDebugInfo(void) /* line to the next node forward (green) */ if (eNode) { - eNode = eNode.GetPathTargetEntity(); + eNode = (path_track)eNode.GetPathTargetEntity(); if (eNode) { R_BeginPolygon("", 0, 0); R_PolygonVertex(oldNode.GetOrigin() + [0,0, m_flHeight], [0,1], [0,0.75,0], 1.0); R_PolygonVertex(eNode.GetOrigin() + [0,0, m_flHeight], [1,1], [0,0.75,0], 1.0); R_EndPolygon(); oldNode = eNode; - eNode = eNode.GetPathTargetEntity(); + eNode = (path_track)eNode.GetPathTargetEntity(); if (eNode) { R_BeginPolygon("", 0, 0); @@ -336,7 +337,7 @@ func_tracktrain::RenderDebugInfo(void) oldNode = eNode; if (eNode) { - eNode = eNode.GetSelfTargetEntity(); + eNode = (path_track)eNode.GetSelfTargetEntity(); if (eNode) { /* line to the next node forward (green) */ @@ -346,7 +347,7 @@ func_tracktrain::RenderDebugInfo(void) R_EndPolygon(); oldNode = eNode; - eNode = eNode.GetSelfTargetEntity(); + eNode = (path_track)eNode.GetSelfTargetEntity(); if (eNode) { R_BeginPolygon("", 0, 0); @@ -674,13 +675,13 @@ func_tracktrain::PathMoveBack(void) flTravelTime = (vlen(vecVelocity) / travelSpeed); if (flTravelTime <= 0.0) { - NSVehicle_Log("^1func_tracktrain::^3PathMoveBack^7: Distance short, teleporting next."); + NSVehicle_Log("^Distance short, teleporting next."); ScheduleThink(_PathArrivedBack, 0.0f); SetVelocity([1,1,1]); return; } - NSVehicle_Log("^1func_tracktrain::^3PathMoveBack^7: Changing velocity from '%v' to '%v'", GetVelocity(), vecVelocity); + NSVehicle_Log("Changing velocity from '%v' to '%v'", GetVelocity(), vecVelocity); SetVelocity(vecVelocity * (1 / flTravelTime)); _SoundMove(); @@ -873,8 +874,6 @@ func_tracktrain::PathClear(void) void func_tracktrain::Trigger(entity act, triggermode_t state) { - breakpoint(); - switch (state) { case TRIG_ON: PathMoveForward(); @@ -898,7 +897,7 @@ func_tracktrain::_AfterSpawn(void) path_track nodeAhead; /* get the first target */ - targetNode = GetTrackNodeForward(); + targetNode = (path_track)GetTrackNodeForward(); /* unpossible */ if (!targetNode || HasTriggerTarget() == false) { @@ -914,7 +913,7 @@ func_tracktrain::_AfterSpawn(void) /* face the train towards the next target. while it may be tempting to use GetPathTargetEntity() here, that node may be disabled. so look manually. */ - nodeAhead = find(world, ::targetname, targetNode.target); + nodeAhead = (path_track)find(world, ::targetname, targetNode.target); /* node found. */ if (nodeAhead) { diff --git a/src/gs-entbase/server/func_train.qc b/src/gs-entbase/server/func_train.qc index fcb8af26..c6db9c23 100644 --- a/src/gs-entbase/server/func_train.qc +++ b/src/gs-entbase/server/func_train.qc @@ -203,7 +203,7 @@ void func_train::SoundMove(void) { if (m_strMoveSnd) { - Sound_Play(this, CHAN_VOICE, m_strMoveSnd); + StartSoundDef(m_strMoveSnd, CHAN_VOICE, true); } } @@ -211,7 +211,7 @@ void func_train::SoundStop(void) { if (m_strStopSnd) { - Sound_Play(this, CHAN_BODY, m_strStopSnd); + StartSoundDef(m_strStopSnd, CHAN_BODY, true); } if (m_strMoveSnd) { @@ -248,7 +248,7 @@ func_train::PathMove(void) } SoundMove(); - NSLog("Travelling at %f up/s", m_flSpeed); + EntLog("Travelling at %f up/s", m_flSpeed); SetVelocity(vecVelocity * (1 / flTravelTime)); ScheduleThink(PathNext, flTravelTime); @@ -266,9 +266,9 @@ func_train::PathDone(void) } if (HasTargetname()) { - NSLog("func_train (id %d, name %S): Touched base with path_corner %S", num_for_edict(this), targetname, target); + EntLog("func_train (id %d, name %S): Touched base with path_corner %S", num_for_edict(this), targetname, target); } else { - NSLog("func_train (id %d): Touched base with path_corner %S", num_for_edict(this), target); + EntLog("func_train (id %d): Touched base with path_corner %S", num_for_edict(this), target); } /* fire the path_corners' target */ @@ -290,7 +290,7 @@ func_train::PathNext(void) /* a little more serious, but we don't want to break the map. */ if (eNode == __NULL__) { - print(sprintf("func_tracktrain (id %d) target %S does not exist.\n", num_for_edict(this), target)); + NSError("func_tracktrain (id %d) target %S does not exist.", num_for_edict(this), target); return; } diff --git a/src/gs-entbase/server/game_counter.qc b/src/gs-entbase/server/game_counter.qc index a324658d..68e29b23 100644 --- a/src/gs-entbase/server/game_counter.qc +++ b/src/gs-entbase/server/game_counter.qc @@ -123,7 +123,7 @@ game_counter::Respawn(void) void game_counter::SetCount(int value) { - NSLog("%s's count set to %i", targetname, value); + EntLog("%s's count set to %i", targetname, value); m_iCounted = value; } @@ -139,13 +139,13 @@ game_counter::Trigger(entity act, triggermode_t state) if (GetMaster(act) == FALSE) return; - NSLog("%s's incremented by 1", targetname); + EntLog("%s's incremented by 1", targetname); m_iCounted++; if (m_iCounted < m_iMaxCount) return; - NSLog("%s's triggering %s", targetname, target); + EntLog("%s's triggering %s", targetname, target); //print(sprintf("%s %s %i %i\n", classname, targetname, m_iCounted, m_iMaxCount )); //error(sprintf("%s %i %i\n", act.classname, m_iCounted, m_iMaxCount )); UseTargets(act, TRIG_TOGGLE, m_flDelay); diff --git a/src/gs-entbase/server/game_counter_set.qc b/src/gs-entbase/server/game_counter_set.qc index 94bbf956..c325b5c9 100644 --- a/src/gs-entbase/server/game_counter_set.qc +++ b/src/gs-entbase/server/game_counter_set.qc @@ -101,7 +101,7 @@ game_counter_set::Trigger(entity act, triggermode_t state) if (GetMaster(act) == FALSE) return; - NSLog("%s's manipulating %s to be %i", targetname, target, m_iCount); + EntLog("%s's manipulating %s to be %i", targetname, target, m_iCount); /* apply the value to all the relevant game_counter entities */ for (entity f = world; (f = find(f, ::targetname, target));) { diff --git a/src/gs-entbase/server/game_player_equip.qc b/src/gs-entbase/server/game_player_equip.qc index 3d75c285..2123f1e3 100644 --- a/src/gs-entbase/server/game_player_equip.qc +++ b/src/gs-entbase/server/game_player_equip.qc @@ -139,8 +139,7 @@ game_player_equip::SpawnUnit(string cname, vector org) unit.nextthink = time; unit.real_owner = this; setorigin(unit, org); - NSLog("^2game_player_equip::^3Trigger^7: Spawning %s", - cname); + EntLog("Spawning %s", cname); } void @@ -150,7 +149,7 @@ game_player_equip::Trigger(entity act, triggermode_t state) string cname; if (!(act.flags & FL_CLIENT)) { - print("^1game_player_equip^7::^1Trigger: Activator not a client!\n"); + EntError("Activator %S not a client!", act.classname); return; } diff --git a/src/gs-entbase/server/game_player_team.qc b/src/gs-entbase/server/game_player_team.qc index 4688699a..3a4eaa9f 100644 --- a/src/gs-entbase/server/game_player_team.qc +++ b/src/gs-entbase/server/game_player_team.qc @@ -58,7 +58,7 @@ game_player_team::Trigger(entity entityActivator, triggermode_t state) toRead = (game_team_master)GetTargetEntity(); if (!toRead) { - NSEntWarning("Unable to find game_team_master named %S", GetTriggerTarget()); + EntWarning("Unable to find game_team_master named %S", GetTriggerTarget()); return; } diff --git a/src/gs-entbase/server/game_team_set.qc b/src/gs-entbase/server/game_team_set.qc index 470ec4fa..e12a5681 100644 --- a/src/gs-entbase/server/game_team_set.qc +++ b/src/gs-entbase/server/game_team_set.qc @@ -55,7 +55,7 @@ game_team_set::Trigger(entity activatorEntity, triggermode_t state) toChange = (game_team_master)GetTargetEntity(); if (!toChange) { - NSEntWarning("Unable to find game_team_master named %S", GetTriggerTarget()); + EntWarning("Unable to find game_team_master named %S", GetTriggerTarget()); return; } diff --git a/src/gs-entbase/server/logic_auto.qc b/src/gs-entbase/server/logic_auto.qc index ca0ca6ec..07d1db42 100644 --- a/src/gs-entbase/server/logic_auto.qc +++ b/src/gs-entbase/server/logic_auto.qc @@ -234,7 +234,7 @@ logic_auto::Processing(void) UseOutput(this, m_strOnBackgroundMap); if (HasSpawnFlags(LOGICAUTO_USEONCE)) { - NSLog("^2logic_auto::^3Processing ^7: %s triggerer removed self", target); + EntLog("%S triggerer removed self", target); Destroy(); } } diff --git a/src/gs-entbase/server/logic_case.qc b/src/gs-entbase/server/logic_case.qc index b6da27c3..3c570df0 100644 --- a/src/gs-entbase/server/logic_case.qc +++ b/src/gs-entbase/server/logic_case.qc @@ -491,13 +491,13 @@ logic_case::Input(entity activatorEntity, string inputName, string dataField) void logic_case::PickRandom(entity activatorEntity) { - NSEntWarning("Not implemented."); + EntWarning("Not implemented."); } void logic_case::PickRandomShuffle(entity activatorEntity) { - NSEntWarning("Not implemented."); + EntWarning("Not implemented."); } void diff --git a/src/gs-entbase/server/logic_timer.qc b/src/gs-entbase/server/logic_timer.qc index a6ff41a9..21942c2a 100644 --- a/src/gs-entbase/server/logic_timer.qc +++ b/src/gs-entbase/server/logic_timer.qc @@ -243,13 +243,13 @@ logic_timer::Input(entity activatorEntity, string inputName, string dataField) if (nextthink <= 0.0) nextthink += stof(dataField); else - NSEntWarning("AddToTimer when inactive!"); + EntWarning("AddToTimer when inactive!"); break; case "SubtractFromTimer": if (nextthink <= 0.0) nextthink -= stof(dataField); else - NSEntWarning("SubtractFromTimer when inactive!"); + EntWarning("SubtractFromTimer when inactive!"); break; default: diff --git a/src/gs-entbase/server/math_counter.qc b/src/gs-entbase/server/math_counter.qc new file mode 100644 index 00000000..84c9300b --- /dev/null +++ b/src/gs-entbase/server/math_counter.qc @@ -0,0 +1,11 @@ +class +math_counter:NSPointTrigger +{ + void math_counter(void); +}; + +void +math_counter::math_counter(void) +{ + +} \ No newline at end of file diff --git a/src/gs-entbase/server/monstermaker.qc b/src/gs-entbase/server/monstermaker.qc index 4e54b0b4..a14746d9 100644 --- a/src/gs-entbase/server/monstermaker.qc +++ b/src/gs-entbase/server/monstermaker.qc @@ -168,35 +168,13 @@ monstermaker::TurnOff(void) void monstermaker::TurnOn(void) { - ScheduleThink(Spawner, m_flDelay); + ScheduleThink(Spawner, 0.0f); m_iValue = 1; } void monstermaker::Spawner(void) { - static void monstermaker_spawnunit(void) { - /* these will get overwritten by the monster spawnfunction */ - vector neworg = self.origin; - vector newang = self.angles; - string tname = self.netname; - - /* prevent us from being deleted by callfunction() */ - self.spawnflags |= MSF_MULTIPLAYER; - - /* become the classname assigned */ - NSMonster t = (NSMonster)self; - callfunction(self.classname); - - /* apply the saved values back */ - t.origin = t.m_oldOrigin = neworg; - t.angles = t.m_oldAngle = newang; - t.targetname = tname; - - /* spawn anew */ - t.Respawn(); - } - int c = 0; /* look and count the buggers that are still around */ @@ -222,32 +200,33 @@ monstermaker::Spawner(void) return; } - if (isfunction(strcat("spawnfunc_", m_strMonster))) { - entity unit = spawn(); - unit.classname = strcat("spawnfunc_", m_strMonster); - unit.netname = m_strChildName; - unit.think = monstermaker_spawnunit; - unit.nextthink = time + 0.1f; - unit.real_owner = this; - NSLog("^2monstermaker::^3Trigger^7: Spawning %s", m_strMonster); - setorigin(unit, origin); - unit.angles = angles; - m_iMonsterSpawned++; + NSEntity unit = Entity_CreateClass(m_strMonster); - if (target) { - UseTargets(this, TRIG_TOGGLE, 0.0f); - } - - /* inherit the monsterclip flag */ - if (HasSpawnFlags(MMF_MONSTERCLIP)) { - unit.spawnflags |= MSF_MONSTERCLIP; - } - } else { - NSLog("^1monstermaker::^3Trigger^7: cannot call spawnfunction for %s", m_strMonster); + if (!unit) { + EntError("Cannot call spawnfunction for %s", m_strMonster); Destroy(); return; } + unit.real_owner = this; + EntLog("Spawning %s", m_strMonster); + unit.SetOrigin(GetOrigin()); + unit.SetAngles(GetAngles()); + unit.m_oldOrigin = GetOrigin(); + unit.m_oldAngle = GetAngles(); + unit.targetname = m_strChildName; + + m_iMonsterSpawned++; + + if (target) { + UseTargets(this, TRIG_TOGGLE, 0.0f); + } + + /* inherit the monsterclip flag */ + if (HasSpawnFlags(MMF_MONSTERCLIP)) { + unit.spawnflags |= MSF_MONSTERCLIP; + } + /* shut off for good when we've spawned all we ever wanted */ if ((m_iTotalMonsters > 0) && m_iMonsterSpawned >= m_iTotalMonsters) { ReleaseThink(); diff --git a/src/gs-entbase/server/multi_manager.qc b/src/gs-entbase/server/multi_manager.qc index 2c7e7c8f..4d894636 100644 --- a/src/gs-entbase/server/multi_manager.qc +++ b/src/gs-entbase/server/multi_manager.qc @@ -294,8 +294,8 @@ multi_manager::Trigger(entity act, triggermode_t state) entity eFind = find(world, ::targetname, wow.target); - NSLog("^2%s::^3Trigger^7: %s (%s)", - this.classname, wow.target, eFind.classname); + EntLog("Triggering %S (%S)", + wow.target, eFind.classname); wow.m_iValue = TRUE; UseTargets(wow.m_eActivator, TRIG_TOGGLE, 0.0f); diff --git a/src/gs-entbase/server/multisource.qc b/src/gs-entbase/server/multisource.qc index e427f0ad..d71c815a 100644 --- a/src/gs-entbase/server/multisource.qc +++ b/src/gs-entbase/server/multisource.qc @@ -57,12 +57,12 @@ void multisource::Trigger(entity act, triggermode_t unused) { if (QueryTargets() == FALSE) { - NSLog("[^1MULTISOURCE^7] %s is inactive.", targetname); + EntLog("[^1MULTISOURCE^7] %s is inactive.", targetname); m_iValue = FALSE; return; } - NSLog("[^1MULTISOURCE^7] %s is now active.", targetname); + EntLog("[^1MULTISOURCE^7] %s is now active.", targetname); m_iValue = TRUE; UseTargets(act, TRIG_TOGGLE, m_flDelay); } diff --git a/src/gs-entbase/server/path_corner.qc b/src/gs-entbase/server/path_corner.qc index b911b0cc..27a760aa 100644 --- a/src/gs-entbase/server/path_corner.qc +++ b/src/gs-entbase/server/path_corner.qc @@ -228,7 +228,7 @@ void path_corner::PathPassTrigger(entity activatingEntity, triggermode_t triggerMode) { if (HasSpawnFlags(PC_FIREONCE) && m_iFired) { - NSLog("path_corner (%s) can only fire its targets once", targetname); + EntLog("tried to fire more than once"); return; } @@ -240,9 +240,7 @@ path_corner::PathPassTrigger(entity activatingEntity, triggermode_t triggerMode) for (entity f = world; (f = find(f, ::targetname, m_strMessage));) { NSTrigger trigger = (NSTrigger)f; - NSLog("^2%s::^3PathPassTrigger^7:" \ - "Triggering %s `%s` from %s", \ - classname, f.classname, \ + EntLog("Triggering %s `%s` from %s", f.classname, \ trigger.targetname, activatingEntity.classname); if (trigger.Trigger != __NULL__) { diff --git a/src/gs-entbase/server/path_track.qc b/src/gs-entbase/server/path_track.qc index 2e5e7c88..cdbda5d6 100644 --- a/src/gs-entbase/server/path_track.qc +++ b/src/gs-entbase/server/path_track.qc @@ -270,10 +270,7 @@ path_track::PathEndTrigger(entity activatingEntity, triggermode_t triggerMode) for (entity f = world; (f = find(f, ::targetname, m_strEndTrigger));) { NSTrigger trigger = (NSTrigger)f; - NSLog("^2%s::^3PathEndTrigger^7:" \ - "Triggering %s `%s` from %s", \ - classname, f.classname, \ - trigger.targetname, activatingEntity.classname); + EntLog("Triggering %S %S from %S", f.classname, trigger.targetname, activatingEntity.classname); if (trigger.Trigger != __NULL__) { trigger.Trigger(activatingEntity, triggerMode); diff --git a/src/gs-entbase/server/phys_convert.qc b/src/gs-entbase/server/phys_convert.qc index f38b6c6f..7761a781 100644 --- a/src/gs-entbase/server/phys_convert.qc +++ b/src/gs-entbase/server/phys_convert.qc @@ -149,7 +149,7 @@ phys_convert::ConvertTarget(entity activatorEnt) NSPhysicsEntity new; if (!targetEnt) { - NSEntWarning("Cannot find target to convert."); + EntWarning("Cannot find target to convert."); return; } diff --git a/src/gs-entbase/server/prop_door_rotating.qc b/src/gs-entbase/server/prop_door_rotating.qc index 63b46a43..b7145569 100644 --- a/src/gs-entbase/server/prop_door_rotating.qc +++ b/src/gs-entbase/server/prop_door_rotating.qc @@ -119,7 +119,7 @@ prop_door_rotating::Turn(vector vecDest, void(void) vFunc) float flTravelLength, flTravelTime; if (!m_flSpeed) { - NSLog("^1prop_door_rotating::^3RotToDest^7: No speed defined for %s!", targetname); + EntError("No speed defined for %s!", targetname); prop_door_rotating::Respawn(); return; } diff --git a/src/gs-entbase/server/random_speaker.qc b/src/gs-entbase/server/random_speaker.qc index 9bdabf39..97cbbf3c 100644 --- a/src/gs-entbase/server/random_speaker.qc +++ b/src/gs-entbase/server/random_speaker.qc @@ -173,19 +173,13 @@ random_speaker::Enable(void) r += (m_flMinPos * (m_flRandPercent / 100)) * random(); ScheduleThink(PlaySample, r); - - NSLog("^2random_speaker::^3Disable^7: " \ - "%s playing %s in %d\n", \ - targetname, m_strSample, r); + EntLog("%s playing %s in %d\n", targetname, m_strSample, r); } void random_speaker::Disable(void) { - NSLog("^2random_speaker::^3Disable^7: " \ - "Disabled %s playing %s\n", \ - targetname, m_strSample); - + EntLog("Disabled %s playing %s\n", targetname, m_strSample); m_iValue = 0; ReleaseThink(); } diff --git a/src/gs-entbase/server/scripted_sentence.qc b/src/gs-entbase/server/scripted_sentence.qc index a3a11ada..4fce40e4 100644 --- a/src/gs-entbase/server/scripted_sentence.qc +++ b/src/gs-entbase/server/scripted_sentence.qc @@ -28,6 +28,14 @@ world. It'll enable mouth flapping and all sorts of other cool effects. - "pitch" : Desired sound pitch. May be overridden in the titles.txt entry. - "delay" : Delay before it'll be triggered? UNUSED RIGHT NOW. - "wait" : Delay before it can be triggered again? UNUSED RIGHT NOW. +- "listener" : The name of the entity we'll look at when speaking. Can be "player". + +# INPUTS +- "BeginSentence" : Starts the sentence. + +# OUTPUTS +- "OnBeginSentence" : Fired when the sentence starts. +- "OnEndSentence" : Fired when the sentence ends. # TRIVIA This entity was introduced in Half-Life (1998). @@ -39,18 +47,26 @@ public: void scripted_sentence(void); /* overrides */ + virtual void Spawned(void); virtual void Save(float); virtual void Restore(string,string); virtual void SpawnKey(string,string); virtual void Trigger(entity, triggermode_t); + virtual void Input(entity, string, string); + + nonvirtual void SentenceEnded(void); private: string m_strSpeaker; string m_strSentence; + int m_iSentenceID; float m_flDelay; float m_flWait; float m_flPitch; float m_flDuration; + string m_strListener; + string m_strOnBeginSentence; + string m_strOnEndSentence; }; void @@ -62,6 +78,23 @@ scripted_sentence::scripted_sentence(void) m_flWait = 0.0f; m_flPitch = 0.0f; m_flDuration = 0.0f; + m_strListener = __NULL__; + m_strOnBeginSentence = __NULL__; + m_strOnEndSentence = __NULL__; + m_iSentenceID = 0i; +} + +void +scripted_sentence::Spawned(void) +{ + super::Spawned(); + + m_iSentenceID = Sentences_GetID(m_strSentence); + + if (m_strOnBeginSentence) + m_strOnBeginSentence = CreateOutput(m_strOnBeginSentence); + if (m_strOnEndSentence) + m_strOnEndSentence = CreateOutput(m_strOnEndSentence); } void @@ -74,6 +107,10 @@ scripted_sentence::Save(float handle) SaveFloat(handle, "m_flWait", m_flWait); SaveFloat(handle, "m_flPitch", m_flPitch); SaveFloat(handle, "m_flDuration", m_flDuration); + SaveString(handle, "m_strListener", m_strListener); + SaveString(handle, "m_strOnBeginSentence", m_strOnBeginSentence); + SaveString(handle, "m_strOnEndSentence", m_strOnEndSentence); + SaveInt(handle, "m_iSentenceID", m_iSentenceID); } void @@ -98,35 +135,74 @@ scripted_sentence::Restore(string strKey, string strValue) case "m_flDuration": m_flDuration = ReadFloat(strValue); break; + case "m_strListener": + m_strListener = ReadString(strValue); + break; + case "m_strOnBeginSentence": + m_strOnBeginSentence = ReadString(strValue); + break; + case "m_strOnEndSentence": + m_strOnEndSentence = ReadString(strValue); + break; + case "m_iSentenceID": + m_iSentenceID = ReadInt(strValue); + break; default: super::Restore(strKey, strValue); } } void -scripted_sentence::SpawnKey(string strKey, string strValue) +scripted_sentence::SpawnKey(string keyName, string setValue) { - switch (strKey) { + switch (keyName) { case "entity": - m_strSpeaker = strValue; + m_strSpeaker = setValue; break; case "sentence": - m_strSentence = strtoupper(strValue); + m_strSentence = strtoupper(setValue); break; case "pitch": - m_flPitch = stof(strValue); + m_flPitch = ReadFloat(setValue); break; case "duration": - m_flDuration = stof(strValue); + m_flDuration = ReadFloat(setValue); break; case "wait": - m_flWait = stof(strValue); + m_flWait = ReadFloat(setValue); + break; + case "listener": + m_strListener = ReadString(setValue); + break; + case "OnBeginSentence": + m_strOnBeginSentence = ReadString(setValue); + break; + case "OnEndSentence": + m_strOnEndSentence = ReadString(setValue); break; default: - super::SpawnKey(strKey, strValue); + super::SpawnKey(keyName, setValue); } } +void +scripted_sentence::Input(entity entityActivator, string inputName, string dataField) +{ + switch (inputName) { + case "BeginSentence": + Trigger(entityActivator, TRIG_TOGGLE); + break; + default: + super::Input(entityActivator, inputName, dataField); + } +} + +void +scripted_sentence::SentenceEnded(void) +{ + UseOutput(this, m_strOnEndSentence); +} + void scripted_sentence::Trigger(entity act, triggermode_t unused) { @@ -150,19 +226,32 @@ scripted_sentence::Trigger(entity act, triggermode_t unused) } if (!spe) { - print(sprintf("^1scripted_sentence::^3Trigger^7: Couldn't find %s!\n", m_strSpeaker)); + NSError("Couldn't find %s!\n", m_strSpeaker); return; } - NSLog("^2scripted_sentence::^3Trigger^7: %s on %s", m_strSentence, m_strSpeaker); + EntLog("%s on %s", m_strSentence, m_strSpeaker); NSTalkMonster npc = (NSTalkMonster)spe; WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); WriteByte(MSG_MULTICAST, EV_SENTENCE); WriteEntity(MSG_MULTICAST, npc); - WriteInt(MSG_MULTICAST, Sentences_GetID(m_strSentence)); + WriteInt(MSG_MULTICAST, m_iSentenceID); msg_entity = npc; multicast(npc.origin, MULTICAST_PVS); npc.m_flNextSentence = time + m_flDuration; UseTargets(act, TRIG_TOGGLE, m_flDelay); + + /* I/O */ + /* Uncertain: Are we triggering the output on behalf of someone maybe? */ + UseOutput(this, m_strOnBeginSentence); + ScheduleThink(SentenceEnded, m_flDuration); + + if (m_strListener) { + if (m_strListener == "player") { + npc.m_eLookAt = find(world, ::classname, "player"); + } else { + npc.m_eLookAt = find(world, ::targetname, m_strListener); + } + } } diff --git a/src/gs-entbase/server/stubs.qc b/src/gs-entbase/server/stubs.qc index 59e57ba1..21779ee1 100644 --- a/src/gs-entbase/server/stubs.qc +++ b/src/gs-entbase/server/stubs.qc @@ -78,8 +78,8 @@ This entity was introduced in Quake (1996). */ CLASSEXPORT(info_target, info_notnull) -CLASSEXPORT(env_sound, info_notnull) -CLASSEXPORT(env_sun, info_notnull) +CLASSEXPORT(env_sound, info_null) +CLASSEXPORT(env_sun, info_null) CLASSEXPORT(info_intermission, info_notnull) CLASSEXPORT(prop_static, info_null) diff --git a/src/gs-entbase/server/target_cdaudio.qc b/src/gs-entbase/server/target_cdaudio.qc index 95c889bf..38cc97bd 100644 --- a/src/gs-entbase/server/target_cdaudio.qc +++ b/src/gs-entbase/server/target_cdaudio.qc @@ -110,9 +110,7 @@ target_cdaudio::Touch(entity eToucher) return; } - NSLog("^2target_cdaudio::^3Trigger^7: CD Track %i requested", - m_iCDTrack); - + EntLog(" CD Track %i requested", m_iCDTrack); WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); WriteByte(MSG_MULTICAST, EV_MUSICTRACK); WriteByte(MSG_MULTICAST, m_iCDTrack); diff --git a/src/gs-entbase/server/trigger_auto.qc b/src/gs-entbase/server/trigger_auto.qc index 41d76f49..5f24f02b 100644 --- a/src/gs-entbase/server/trigger_auto.qc +++ b/src/gs-entbase/server/trigger_auto.qc @@ -114,8 +114,9 @@ trigger_auto::Respawn(void) /* deliberately add a bit more time in case we're first in the ent-lump also we'll only do this in multiplayer games. SP games will call trigger_auto_trigger() for when one player has fully joined */ - if (cvar("sv_playerslots") > 1) + if (cvar("sv_playerslots") > 1) { ScheduleThink(Processing, 0.25f); + } } void @@ -130,7 +131,7 @@ trigger_auto::Processing(void) //print(sprintf("%S %d %f %f\n", target, m_iTriggerState, m_flDelay, time)); if (HasSpawnFlags(1)) { - NSLog("^2trigger_auto::^3Processing^7: %s triggerer removed self", target); + EntLog("Trigger instructed to destroy itself."); Destroy(); } } diff --git a/src/gs-entbase/server/trigger_autosave.qc b/src/gs-entbase/server/trigger_autosave.qc index 953dedfe..ee6191c2 100644 --- a/src/gs-entbase/server/trigger_autosave.qc +++ b/src/gs-entbase/server/trigger_autosave.qc @@ -99,8 +99,7 @@ trigger_autosave::Touch(entity eToucher) msg_entity = this; multicast(origin, MULTICAST_ALL); - NSLog("^2trigger_autosave::^3Touch^7: %s called autosave", - eToucher.netname); + EntLog("%S called autosave", eToucher.netname); localcmd("save autosave\n"); SetSolid(SOLID_NOT); diff --git a/src/gs-entbase/server/trigger_cdaudio.qc b/src/gs-entbase/server/trigger_cdaudio.qc index f42021c6..1b87548d 100644 --- a/src/gs-entbase/server/trigger_cdaudio.qc +++ b/src/gs-entbase/server/trigger_cdaudio.qc @@ -94,8 +94,7 @@ trigger_cdaudio::Trigger(entity act, triggermode_t unused) return; } - NSLog("^2trigger_cdaudio::^3Trigger^7: CD Track %i requested", - m_iCDTrack); + EntLog("CD Track %i requested", m_iCDTrack); WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); WriteByte(MSG_MULTICAST, EV_MUSICTRACK); diff --git a/src/gs-entbase/server/trigger_changelevel.qc b/src/gs-entbase/server/trigger_changelevel.qc index dded661f..025835a8 100644 --- a/src/gs-entbase/server/trigger_changelevel.qc +++ b/src/gs-entbase/server/trigger_changelevel.qc @@ -94,10 +94,16 @@ to define a shared point and a transition area for entities respectively. - TRIGGER_ONLY (2) : Can't activate through touching, only via triggers. # NOTES -When a Landmark is specified, you will have to position two info_landmark +When a `landmark` is specified, you will have to position two info_landmark entities across your two levels with the same name. They'll mark a translation point for the coordinates in your levels. +If you have set a landmark, you might also want to restrict the area in which entities get carried across to the next level. This is accomplished by placing a trigger_transition volume with the same name as the specified `landmark`. + +If you do not make use of the trigger_transition entity, it will carry over all of the entities that are in the same PVS (room and attached hallways) of the info_landmark. + +The PVS-culling method can prove difficult to work with. Developers have been spotted using 'killtarget' on entities before level transitions take place to manually filter through them (Half-Life's c1a0e - c1a0c). + # TRIVIA This entity was introduced in Quake (1996). */ @@ -250,10 +256,8 @@ trigger_changelevel::Change(void) /* standard level change */ if (!m_strLandmark) { - NSLog("^2trigger_changelevel::^3Change^7: Change to `%s`", - m_strMap); + EntLog("Change to %S", m_strMap); parm_string = m_strChangeTarget; - trigger_transition_pvsfallback(this); changelevel(m_strMap); return; } @@ -286,13 +290,13 @@ trigger_changelevel::Change(void) info_landmark lm = (info_landmark)e; /* found it */ if (lm.targetname == m_strLandmark) { - NSLog("^2trigger_changelevel::^3Change^7: Found landmark for %s", m_strLandmark); + EntLog("Found landmark for %S", m_strLandmark); g_landmarkpos = m_activator.origin - lm.origin; if (transitionHelper) { transitionHelper.SaveTransition(__NULL__, false); } else { - trigger_transition_pvsfallback(this); + trigger_transition_pvsfallback(lm); } changelevel(m_strMap, m_strLandmark); @@ -361,7 +365,7 @@ Landmark_GetSpot(void) /* return something useful at least */ entity ips = find(world, ::classname, "info_player_start"); - print(sprintf("^1ERROR^7: Landmark_GetSpot: Cannot find startspot '%s'!\n",startspot)); + NSError("Cannot find startspot %S!\n", startspot); return ips.origin; } diff --git a/src/gs-entbase/server/trigger_changetarget.qc b/src/gs-entbase/server/trigger_changetarget.qc index 969320ec..3fc7867a 100644 --- a/src/gs-entbase/server/trigger_changetarget.qc +++ b/src/gs-entbase/server/trigger_changetarget.qc @@ -86,8 +86,7 @@ trigger_changetarget::Trigger(entity act, triggermode_t state) for (f = __NULL__; (f = (NSEntity)find(f, ::targetname, target));) { - NSLog("^2trigger_changetarget::^3Trigger^7: " \ - "Changing %s (%s) target from '%s' to '%s'\n", \ + EntLog("Changing %s (%s) target from '%s' to '%s'\n", \ target, f.classname, f.target, target); /* now change the target */ diff --git a/src/gs-entbase/server/trigger_counter.qc b/src/gs-entbase/server/trigger_counter.qc index e3aa2d42..bc996f88 100644 --- a/src/gs-entbase/server/trigger_counter.qc +++ b/src/gs-entbase/server/trigger_counter.qc @@ -116,9 +116,7 @@ trigger_counter::Trigger(entity act, triggermode_t state) m_iCounted++; - NSLog("^2trigger_counter::^3Trigger^7: " \ - "Incremented '%s' by 1 (%i/%i)\n", \ - targetname, m_iCounted, m_iMaxCount); + EntLog("Incremented '%s' by 1 (%i/%i)\n", targetname, m_iCounted, m_iMaxCount); if (m_iCounted < m_iMaxCount) return; diff --git a/src/gs-entbase/server/trigger_hurt.qc b/src/gs-entbase/server/trigger_hurt.qc index 485513d1..882020a0 100644 --- a/src/gs-entbase/server/trigger_hurt.qc +++ b/src/gs-entbase/server/trigger_hurt.qc @@ -266,11 +266,9 @@ trigger_hurt::Touch(entity eToucher) type |= DMG_CHEMICAL; } + EntLog("Hurting %S (%d) with %i.", eToucher.classname, num_for_edict(eToucher), m_iDamage); Damage_Apply(eToucher, this, m_iDamage, 0, type); - NSLog("^2trigger_hurt::^3Touch^7: Hurting '%s' with %i", - eToucher.netname, m_iDamage); - /* shut it down if used once */ if (HasSpawnFlags(SF_HURT_ONCE)) { Trigger(eToucher, TRIG_OFF); diff --git a/src/gs-entbase/server/trigger_look.qc b/src/gs-entbase/server/trigger_look.qc index 87197c46..b004d070 100644 --- a/src/gs-entbase/server/trigger_look.qc +++ b/src/gs-entbase/server/trigger_look.qc @@ -169,7 +169,7 @@ trigger_look::Touch(entity eToucher) /* find the looktarget */ lt = find(world, ::targetname, m_strLookTarget); if (!lt) { - NSLog("^1trigger_look:Touch^7: Invalid m_strLookTarget %s!", m_strLookTarget); + EntLog("^1trigger_look:Touch^7: Invalid m_strLookTarget %s!", m_strLookTarget); Destroy(); return; } diff --git a/src/gs-entbase/server/trigger_once.qc b/src/gs-entbase/server/trigger_once.qc index 61c78793..6f1aaa4b 100644 --- a/src/gs-entbase/server/trigger_once.qc +++ b/src/gs-entbase/server/trigger_once.qc @@ -187,11 +187,11 @@ trigger_once::Touch(entity eToucher) m_iValue = 1; if (!target && !m_strKillTarget) { - NSLog("^2trigger_once::^3Touch^7: %S is triggering OnStartTouch", eToucher.classname); + EntLog("%S is triggering OnStartTouch", eToucher.classname); UseOutput(eToucher, m_strOnStartTouch); return; } - NSLog("^2trigger_once::^3Touch^7: %S is triggering %S", eToucher.classname, target); + EntLog("%S is triggering %S", eToucher.classname, target); UseTargets(eToucher, TRIG_TOGGLE, m_flDelay); } diff --git a/src/gs-entbase/server/trigger_relay.qc b/src/gs-entbase/server/trigger_relay.qc index 43a7a609..d522a2c5 100644 --- a/src/gs-entbase/server/trigger_relay.qc +++ b/src/gs-entbase/server/trigger_relay.qc @@ -116,7 +116,7 @@ void trigger_relay::Trigger(entity act, triggermode_t state) { if (m_iEnabled == FALSE) { - NSLog("trigger_relay (%s) has already been triggered", targetname); + EntLog("trigger_relay (%s) has already been triggered", targetname); return; } @@ -125,6 +125,6 @@ trigger_relay::Trigger(entity act, triggermode_t state) } m_iValue = TRUE; - NSLog("trigger_relay (%s) will trigger %s with state %d", targetname, target, m_iTriggerState); + EntLog("trigger_relay (%s) will trigger %s with state %d", targetname, target, m_iTriggerState); UseTargets(act, m_iTriggerState, m_flDelay); } diff --git a/src/gs-entbase/server/trigger_teleport.qc b/src/gs-entbase/server/trigger_teleport.qc index b8e76550..4371d88d 100644 --- a/src/gs-entbase/server/trigger_teleport.qc +++ b/src/gs-entbase/server/trigger_teleport.qc @@ -253,11 +253,9 @@ trigger_teleport::Touch(entity eToucher) Sound_Play(eTarget, CHAN_VOICE, m_sndTeleportExit); } - NSLog("^2trigger_teleport::^3Touch^7: Teleported '%s' to `%v`", - eToucher.netname, endpos); + EntLog("Teleported %S to %v", eToucher.netname, endpos); } else { - print(sprintf("^2trigger_teleport::^3Touch^7: Failed to teleport '%s'\n", - eToucher.netname)); + EntWarning("Failed to teleport %S", eToucher.netname); } } } diff --git a/src/gs-entbase/server/trigger_transition.qc b/src/gs-entbase/server/trigger_transition.qc index 9eca24e6..a20dad89 100644 --- a/src/gs-entbase/server/trigger_transition.qc +++ b/src/gs-entbase/server/trigger_transition.qc @@ -25,11 +25,6 @@ All entities touching this volume will carry across to the next level. # NOTES In order for this entity to work, one has to assign a working info_landmark entity to a trigger_changelevel, and give this entity the same targetname as said landmark. -In GoldSrc games, it appears that every point-entity that's part of the current PVS (mostly the 'room' and attached path-ways you're currently in) carries over to the next level - if a trigger_transition is not defined. -This is probably not what you want to ever do, especially in large outdoor maps where the 'room' is the entire map. - -You can also have more than one trigger_transition with the same name, so if any entity is in any of them they will move with the player across the desired level. - # TRIVIA This entity was introduced in Half-Life (1998). */ @@ -72,17 +67,25 @@ trigger_transition::SaveTransition(entity pvsTest, bool usePVS) /* loop through all entities */ for (NSEntity a = __NULL__; (a = (NSEntity)findfloat(a, ::identity, 1));) { bool replicateEntity = false; + bool continueInNextMap = false; + + /* no classname? never allow */ + if not (a.classname) { + continue; + } + //print(sprintf("TRANSITION: %i %S %S\n", i, a.classname, a.m_strGlobalName)); - /* if we're using the PVS, don't use the transition trigger as reference */ - if (usePVS == true && !a.m_strGlobalName) { - if (checkpvs(a.origin, pvsTest) == true) { + /* if we're using the PVS, use the info_landmark as a reference */ + if (usePVS == true) { + if (checkpvs(pvsTest.origin, a) == true) { replicateEntity = true; /* these checks are somewhat safe assumptions. */ if (a.classname == "player") { replicateEntity = false; } + if (a.classname == "info_landmark") { replicateEntity = false; } @@ -90,23 +93,31 @@ trigger_transition::SaveTransition(entity pvsTest, bool usePVS) /* to get rid of the 'out of model slots' error */ if (a.model == "" && solid != SOLID_NOT) { replicateEntity = false; - } - - /* one thing is verified in GoldSrc: no brushes carry over. */ - if (a.m_bIsBrush == true) { - continue; + continueInNextMap = false; } } } else if (WithinBounds(a) == true) { replicateEntity = true; } + /* only carry brushes with a global name */ + if (a.m_bIsBrush == true) { + replicateEntity = false; + continueInNextMap = false; + } + + /* global name = always find target in next map */ + if (a.m_strGlobalName) { + continueInNextMap = true; + replicateEntity = false; + } + if (replicateEntity == true) { fputs(transFile, sprintf("ENTITY \"%i\" %S\n", i, a.classname)); fputs(transFile, "{\n"); a.Save(transFile); fputs(transFile, "}\n"); - } else if (a.m_strGlobalName) { + } else if (continueInNextMap == true) { fputs(transFile, sprintf("CONTINUE \"%i\" %S\n", i, a.m_strGlobalName)); fputs(transFile, "{\n"); a.Save(transFile); @@ -129,11 +140,14 @@ trigger_transition::FindCarrierEntity(string globalName) return a; } } - return __NULL__; + + return (__NULL__); } vector Landmark_GetPosition(void); + + void trigger_transition::LoadTransition(void) { @@ -144,10 +158,10 @@ trigger_transition::LoadTransition(void) filestream transFile = fopen("trans.dat", FILE_READ); if (transFile < 0) { - error("this should never happen."); + NSError("Called to transition, but trans.dat does not exist."); } - print(sprintf("Found transition file. Will transition over entities.\n")); + NSLog("Found transition file. Will transition over entities."); while ((lineFeed = fgets(transFile))) { int c = tokenize(lineFeed); @@ -156,8 +170,17 @@ trigger_transition::LoadTransition(void) if (argv(0) == "{") { continue; } else if (argv(0) == "}") { - carrierEntity.TransitionComplete(); - carrierEntity = __NULL__; + + if (carrierEntity.solid == 0 && carrierEntity.movetype == 0) { + carrierEntity.Destroy(); + carrierEntity = __NULL__; + } + + if (carrierEntity) { + carrierEntity.TransitionComplete(); + carrierEntity.SendFlags = -1; + carrierEntity = __NULL__; + } continue; } @@ -166,16 +189,20 @@ trigger_transition::LoadTransition(void) carrierEntity = FindCarrierEntity(argv(2)); isNew = false; } else if (argv(0) == "ENTITY") { - carrierEntity = EntityDef_CreateClassname(argv(2)); + string desiredClass = argv(2); + if (desiredClass == "corpse") { + carrierEntity = __NULL__; + continue; + } + + carrierEntity = Entity_CreateClass(desiredClass); isNew = true; } } else if (c == 2) { /* key value pairs */ if (carrierEntity) { switch (argv(0)) { case "model": - if (isNew) { - carrierEntity.Restore(argv(0), argv(1)); - } + carrierEntity.model = argv(1); case "modelindex": break; #if 0 diff --git a/src/gs-entbase/shared/ambient_generic.qc b/src/gs-entbase/shared/ambient_generic.qc index 21c886f4..d2e8eea1 100644 --- a/src/gs-entbase/shared/ambient_generic.qc +++ b/src/gs-entbase/shared/ambient_generic.qc @@ -273,7 +273,7 @@ ambient_generic::Respawn(void) void ambient_generic::UseNormal(entity act, triggermode_t state) { - SndLog( "^2%s::^3UseNormal^7: %S Volume: %f; Radius: %d; Pitch: %f", classname, m_strActivePath, m_flVolume, m_flRadius, m_flPitch); + SndEntLog("Sample: %S Volume: %f; Radius: %d; Pitch: %f", m_strActivePath, m_flVolume, m_flRadius, m_flPitch); if (substring(m_strActivePath, 0, 1) == "!") { string seq = Sentences_GetSamples(m_strActivePath); @@ -300,11 +300,11 @@ void ambient_generic::UseLoop(entity act, triggermode_t state) { if (m_bToggle == true) { - SndLog( "^2%s::^3UseLoop^7: %s stops %S", classname, target, m_strActivePath); + SndEntLog( "%s stops %S", target, m_strActivePath); m_strActivePath = "common/null.wav"; } else { m_strActivePath = m_strSpawnPath; - SndLog( "^2%s::^3UseLoop^7: %s plays %S", classname, target, m_strActivePath); + SndEntLog( "%s plays %S", target, m_strActivePath); } m_bToggle = !m_bToggle; @@ -421,7 +421,7 @@ ambient_generic::ReceiveEntity(float isnew, float flChanged) if (flChanged & AMBIENT_ENABLED) m_bLoops = readbyte(); - SndLog( "^2%s::^3ReceiveEntity^7: received: %S Volume: %f; Radius: %d; Pitch: %d, Org: %v", classname, m_strActivePath, m_flVolume, m_flRadius, m_flPitch, origin); + SndEntLog("Received: %S Volume: %d%%; Radius: %d units; Pitch: %d, Org: %v", m_strActivePath, m_flVolume * 100, cvar("s_nominaldistance") / m_flRadius, m_flPitch, origin); if (m_bLoops == true) { if (flChanged & AMBIENT_MODERN) { diff --git a/src/gs-entbase/shared/decals.qc b/src/gs-entbase/shared/decals.qc index 1779667b..ab55f82f 100644 --- a/src/gs-entbase/shared/decals.qc +++ b/src/gs-entbase/shared/decals.qc @@ -157,7 +157,8 @@ decal::Place(vector org, string dname) /* we never hit any wall. */ if (g_tracedDecal.fraction == 1.0f) { - print(sprintf("^1infodecal tracing failed at %v\n", org)); + NSWarning("Placing of decal %S failed at %v", dname, org); + if (classname != "tempdecal") remove(this); return; diff --git a/src/gs-entbase/shared/env_glow.qc b/src/gs-entbase/shared/env_glow.qc index cd25bea2..1395d12e 100644 --- a/src/gs-entbase/shared/env_glow.qc +++ b/src/gs-entbase/shared/env_glow.qc @@ -92,7 +92,7 @@ void env_glow::Respawn(void) { if (!model && !m_strMaterial) { - NSEntWarning("no model specified"); + EntWarning("no model specified"); Destroy(); return; } @@ -209,7 +209,7 @@ env_glow::RendererRestarted(void) model = modelnameforindex(modelindex); m_strMaterial = spriteframe(model, 0, 0.0f); m_vecSize = drawgetimagesize(m_strMaterial) / 2; - //NSEntWarning("%S %d %S %v", model, modelindex, m_strMaterial, m_vecSize); + //EntWarning("%S %d %S %v", model, modelindex, m_strMaterial, m_vecSize); } } diff --git a/src/gs-entbase/shared/env_muzzleflash.qc b/src/gs-entbase/shared/env_muzzleflash.qc index 85e3c2d5..ea41181f 100644 --- a/src/gs-entbase/shared/env_muzzleflash.qc +++ b/src/gs-entbase/shared/env_muzzleflash.qc @@ -156,7 +156,7 @@ env_muzzleflash::Trigger(entity theActivator, triggermode_t triggerState) targetEnt = (NSEntity)find(world, ::targetname, m_parent); if (!targetEnt) { - NSEntWarning("Entity specified but not found."); + EntWarning("Entity specified but not found."); return; } } @@ -190,6 +190,10 @@ env_muzzleflash::predraw(void) addentity(this); alpha -= frametime * 16.0f; + if (m_eOwner.alpha == 0.0f) { + alpha = 0.0f; + } + if (alpha <= 0.0) { Destroy(); } diff --git a/src/gs-entbase/shared/func_vehicle.qc b/src/gs-entbase/shared/func_vehicle.qc index f3123f12..bf32caea 100644 --- a/src/gs-entbase/shared/func_vehicle.qc +++ b/src/gs-entbase/shared/func_vehicle.qc @@ -687,9 +687,9 @@ func_vehicle::Realign(void) vector end_pos; first = (NSEntity)first; second = (NSEntity)second; - NSLog("func_vehicle angles were: %v\n", angles); + EntLog("func_vehicle angles were: %v\n", angles); angles = vectoangles(first.origin - second.origin); - NSLog("func_vehicle angles is now: %v\n", angles); + EntLog("func_vehicle angles is now: %v\n", angles); end_pos = first.origin; end_pos[2] = m_oldOrigin[2] + 64; diff --git a/src/gs-entbase/shared/phys_rope.qc b/src/gs-entbase/shared/phys_rope.qc index e3a0b6db..fec2d8f4 100644 --- a/src/gs-entbase/shared/phys_rope.qc +++ b/src/gs-entbase/shared/phys_rope.qc @@ -201,7 +201,7 @@ phys_rope::EvaluateEntity(void) entity eFind = find(world, ::targetname, target); if (!eFind) { - print(sprintf("phys_rope: Unable to find target %S\n", target)); + EntError("phys_rope: Unable to find target %S\n", target); return; } diff --git a/src/gs-entbase/shared/point_spotlight.qc b/src/gs-entbase/shared/point_spotlight.qc index 34a11cb9..b6d0b233 100644 --- a/src/gs-entbase/shared/point_spotlight.qc +++ b/src/gs-entbase/shared/point_spotlight.qc @@ -104,8 +104,8 @@ point_spotlight::BeamViewDelta(vector cameraAngle) upDelta = (v * v_up); forwardDelta = (v * v_forward); - //NSLog("forwardDelta: %f\n", forwardDelta); - //NSLog("upDelta: %f (%f)\n", upDelta, 1.0 - upDelta); + //EntLog("forwardDelta: %f\n", forwardDelta); + //EntLog("upDelta: %f (%f)\n", upDelta, 1.0 - upDelta); if (forwardDelta < 0.0) return upDelta * (1.0 - forwardDelta); @@ -135,7 +135,7 @@ point_spotlight::predraw(void) vector vecAngle = g_view.GetCameraAngle(); float coneAlpha = BeamViewDelta(vecAngle); - //NSLog("coneAlpha: %f\n", coneAlpha); + //EntLog("coneAlpha: %f\n", coneAlpha); /* beam */ if (coneAlpha > 0.0) { diff --git a/src/gs-entbase/shared/prop_rope.qc b/src/gs-entbase/shared/prop_rope.qc index 75a0fff1..0dc3bde4 100644 --- a/src/gs-entbase/shared/prop_rope.qc +++ b/src/gs-entbase/shared/prop_rope.qc @@ -211,7 +211,7 @@ prop_rope::EvaluateEntity(void) entity eFind = find(world, ::targetname, target); if (!eFind) { - print(sprintf("prop_rope: Unable to find target %S\n", target)); + EntError("Unable to find rope target %S", target); return; } diff --git a/src/gs-entbase/shared/trigger_camera.qc b/src/gs-entbase/shared/trigger_camera.qc index 7eaac291..1f941900 100644 --- a/src/gs-entbase/shared/trigger_camera.qc +++ b/src/gs-entbase/shared/trigger_camera.qc @@ -70,13 +70,14 @@ private: string m_strMoveTo; entity m_eLooker_net; float m_flSpeed; + float m_flInitialSpeed; #endif }; void trigger_camera::trigger_camera(void) { - m_flWait = 4.0f; + m_flWait = 0.0f; m_eLooker = __NULL__; #ifndef CLIENT m_strAimAt = __NULL__; @@ -155,6 +156,9 @@ trigger_camera::SpawnKey(string strKey, string strValue) case "wait": m_flWait = ReadFloat(strValue); break; + case "speed": + m_flSpeed = ReadFloat(strValue); + break; default: super::SpawnKey(strKey, strValue); } @@ -200,7 +204,7 @@ trigger_camera::Restore(string strKey, string strValue) m_strMoveTo = ReadString(strValue); break; case "m_flSpeed": - m_flSpeed = ReadFloat(strValue); + m_flInitialSpeed = ReadFloat(strValue); break; default: super::Restore(strKey, strValue); @@ -239,15 +243,18 @@ trigger_camera::SendEntity(entity ePEnt, float flFlags) void trigger_camera::EvaluateEntity(void) { - entity t; + NSEntity aimingAt; if (!m_eLooker) return; - t = find(world, ::targetname, m_strAimAt); + aimingAt = (NSEntity)find(world, ::targetname, m_strAimAt); - if (t) { - angles = vectoangles(t.origin - origin); + if (aimingAt) { + TurnToPos(aimingAt.GetOrigin()); + } else { + //NSEntity targetNode = (NSEntity)find(world, ::targetname, target); + //TurnToPos(targetNode.GetOrigin()); } if (ATTR_CHANGED(origin)) { @@ -272,70 +279,87 @@ trigger_camera::EvaluateEntity(void) void trigger_camera::GoToTarget(void) { - float flTravelTime; - vector vecVelocity; + float travelTime; + vector camVelocity; + path_corner targetNode; - path_corner eNode; - eNode = (path_corner)find(world, ::targetname, target); + targetNode = (path_corner)find(world, ::targetname, target); - if (!eNode) { + if (!targetNode) { + EntError("Cannot find target %S", target); return; } - vecVelocity = (eNode.origin - origin); - flTravelTime = (vlen(vecVelocity) / eNode.m_flSpeed); + camVelocity = (targetNode.GetOrigin() - GetOrigin()); - NSLog("trigger_camera (%s): Moving to path_corner %S within %f secs", targetname, target, flTravelTime); + if (targetNode.m_flSpeed) { + m_flSpeed = targetNode.m_flSpeed; + } - if (!flTravelTime) { - NSEntWarning("distance too short, going to next"); + travelTime = (vlen(camVelocity) / m_flSpeed); + + EntLog("Moving to path_corner %S at %d within %f secs (%v)", target, m_flSpeed, travelTime, camVelocity); + + if (!travelTime) { + EntWarning("Distance too short, going to next."); NextPath(); return; } - SetVelocity(vecVelocity * (1 / flTravelTime)); - ScheduleThink(NextPath, flTravelTime); + if (!m_strAimAt) { + vector vecAngleDiff = targetNode.GetOrigin() - GetOrigin(); + vector vecAngleDest = vectoangles(vecAngleDiff); + vecAngleDiff = Math_AngleDiff(vecAngleDest, angles); + SetAngularVelocity(vecAngleDiff * (1 / travelTime)); + } + + SetVelocity(camVelocity * (1 / travelTime)); + ScheduleThink(NextPath, travelTime); } void trigger_camera::NextPath(void) { - path_corner eNode; + path_corner nextNode; if (target == "") { return; } - print(sprintf("Looking for target %S\n", target)); - eNode = (path_corner)find(world, ::targetname, target); + nextNode = (path_corner)find(world, ::targetname, target); - if (!eNode) { + if (!nextNode) { + NSError("Node %S suddenly missing from map!", target); return; } - NSLog("trigger_camera (%s): Touched base with path_corner %S", targetname, target); + EntLog("Arrived at target node %S.", target); /* fire the path_corners' target */ - eNode.Trigger(this, TRIG_TOGGLE); + nextNode.PathPassTrigger(this, TRIG_TOGGLE); + + if (target != m_strMoveTo) + m_strAimAt = __NULL__; + + SetOrigin(nextNode.origin - (mins + maxs) * 0.5); + SetTriggerTarget(nextNode.target); - SetOrigin(eNode.origin - (mins + maxs) * 0.5); - SetTriggerTarget(eNode.target); ClearVelocity(); /* warp next frame */ - if (eNode.HasSpawnFlags(PC_TELEPORT)) { - NSLog("^1trigger_camera::^3NextPath^7: Node %s wants %s to teleport\n", eNode.targetname, targetname); + if (nextNode.HasSpawnFlags(PC_TELEPORT)) { + EntLog("Node %S wants %S to teleport.", nextNode.targetname, targetname); ScheduleThink(NextPath, 0.0f); return; } /* stop until triggered again */ - if (eNode.HasSpawnFlags(PC_WAIT)) { + if (nextNode.HasSpawnFlags(PC_WAIT)) { return; } - if (eNode.m_flWait > 0) { - ScheduleThink(GoToTarget, eNode.m_flWait); + if (nextNode.m_flWait > 0) { + ScheduleThink(GoToTarget, nextNode.m_flWait); } else { GoToTarget(); } @@ -350,7 +374,7 @@ trigger_camera::Trigger(entity act, triggermode_t state) act = find(world, ::classname, "player"); } - NSLog("trigger_camera for %s %S is now %S\n", act.classname, act.netname, targetname); + EntLog("Controlling camera of %S", act.netname); /* kill the other cams the player may be attached to */ for (trigger_camera cam = __NULL__; (cam = (trigger_camera)find(cam, ::classname, "trigger_camera"));) { @@ -367,15 +391,20 @@ trigger_camera::Trigger(entity act, triggermode_t state) m_eLooker = act; m_eLooker.view2 = this; - NSLog("Triggering it on %s\n", act.netname); + m_flSpeed = m_flInitialSpeed; + + if (!m_flSpeed) { + m_flSpeed = 100.0f; + } + + /* Reset to the spawn values */ + SetMovetype(MOVETYPE_PUSH); + SetSolid(SOLID_NOT); SetOrigin(GetSpawnOrigin()); - ClearVelocity(); - ReleaseThink(); SetTriggerTarget(m_strMoveTo); NextPath(); GoToTarget(); SetSendFlags(0xFFFFFF); - ScheduleThink(DeactivateCamera, m_flWait); pvsflags = PVSF_IGNOREPVS; } @@ -383,7 +412,7 @@ trigger_camera::Trigger(entity act, triggermode_t state) void trigger_camera::DeactivateCamera(void) { - NSLog("Turning it off on %s\n", m_eLooker.netname); + EntLog("Turning it off on %S", m_eLooker.netname); m_eLooker.view2 = __NULL__; m_eLooker = __NULL__; SetSendFlags(-1); diff --git a/src/gs-entbase/shared/worldspawn.qc b/src/gs-entbase/shared/worldspawn.qc index ed6f9728..96cbb711 100644 --- a/src/gs-entbase/shared/worldspawn.qc +++ b/src/gs-entbase/shared/worldspawn.qc @@ -97,9 +97,9 @@ worldspawn::worldspawn(void) m_strAmbientSound = ""; m_strBGMTrack = ""; - print("--------- Map Initialization ---------\n"); - print(sprintf("Map: %s\n", mapname)); - print("----------- Game Map Init ------------\n"); + InitPrint("Map Initialization"); + NSLog("Map: %s", mapname); + InitPrint("Game Map Init"); lightstyle(0, "m"); lightstyle(1, "mmnmmommommnonmmonqnmmo"); @@ -125,7 +125,7 @@ worldspawn::worldspawn(void) if (autocvar_sv_levelexec) readcmd(sprintf("exec maps/%s.cfg\n", mapname)); - print("Spawning entities\n"); + InitStart(); } void @@ -202,6 +202,11 @@ worldspawn::SpawnKey(string strKey, string strValue) m_flHDRIrisFadeDown = ReadFloat(strValue); m_bHDREnabled = true; break; + /* empty, ignore */ + case "wad": + case "MaxRange": + case "sounds": + break; default: super::SpawnKey(strKey, strValue); break; diff --git a/src/menu-fn/entry.qc b/src/menu-fn/entry.qc index 31a87120..f752dec8 100644 --- a/src/menu-fn/entry.qc +++ b/src/menu-fn/entry.qc @@ -54,12 +54,12 @@ Menu_GammaHack(void) { if (cvar("brightness") != cvar("vid_brightness")) { localcmd("seta brightness 0\n"); - print("^1Menu_RendererRestarted^7: Brightness hack.\n"); + NSLog("Old config brightness. Applying brightness hack."); } if (cvar("gamma") != cvar("vid_gamma")) { localcmd("seta gamma 1\n"); - print("^1Menu_RendererRestarted^7: Gamma hack.\n"); + NSLog("Old config gamma. Applying gamma hack."); } } @@ -75,7 +75,7 @@ Menu_HasStartupVideos(void) void Menu_PlayStartupVideos(void) { - print("playing startup videos\n"); + NSLog("Playing startup videos.\n"); //localcmd("playvideo av:media/sierra.avi av:media/valve.avi\n"); } @@ -94,9 +94,9 @@ m_init(void) string menuMap; - print("--------- Initializing Menu ----------\n"); - print("Built: " __DATE__ " " __TIME__"\n"); - print("QCC: " __QCCVER__ "\n"); + NSLog("--------- Initializing Menu ----------"); + NSLog("Built: %s %s", __DATE__, __TIME__); + NSLog("QCC: %s", __QCCVER__); /* things that should really be default. platform_default.cfg is supposed to set * them the first time - however FTE doesn't do that when switching manifests diff --git a/src/menu-fn/layout_script.qc b/src/menu-fn/layout_script.qc index 7d0a4b3f..b64a07e0 100644 --- a/src/menu-fn/layout_script.qc +++ b/src/menu-fn/layout_script.qc @@ -87,7 +87,7 @@ Layout_FromFile_Create(CPageTab target, string cvar, string descr, string type, //new = spawn(CTextBox); //break; default: - warning(sprintf("Unknown widget type %S for cvar %S, ignoring", type, cvar)); + NSWarning("Unknown widget type %S for cvar %S, ignoring.", type, cvar); } if (!new) diff --git a/src/platform/gamelibrary.qc b/src/platform/gamelibrary.qc index 922555f4..3d382a03 100644 --- a/src/platform/gamelibrary.qc +++ b/src/platform/gamelibrary.qc @@ -468,8 +468,11 @@ GameLibrary_InitCustom(void) games = (gameinfo_t *)memrealloc(games, sizeof(gameinfo_t), old_count, (gameinfo_count + packageinfo_count)); /* The things we do for frequent flyer mileage. */ - if (!games) - error(sprintf("Attempting to allocate mod data for %i entries failed\n", gameinfo_count)); + if (!games) { + NSError("Attempting to allocate mod data for %i entries failed.", gameinfo_count); + crash(); + return; + } /* now loop through all the mods we found and load in the metadata */ for (id = 1; id < gameinfo_count; id++) { @@ -533,12 +536,12 @@ GameLibrary_InitCustom(void) /* we may have some mods, but we're not running any of them. Fatal */ if (gameinfo_current == -1) { - print("^1FATAL ERROR: NO LIBLIST.GAM FOR CURRENT MOD FOUND!\n"); + NSError("No definition for current game found. Fatal."); crash(); return; } - print(sprintf("GameLibrary initialized (%i entries).\n", gameinfo_count)); + NSLog("...GameLibrary initialized (%i entries).", gameinfo_count); } #endif @@ -583,7 +586,7 @@ static void GameLibrary_EndInstall(void) { int gid = g_iModInstallCache; - print(sprintf("Installation ended for %S!\n", g_strModInstallCache)); + NSLog("Installation ended for %S.", g_strModInstallCache); localcmd(sprintf("game %s\n", g_strModInstallCache)); localcmd("stopmusic\nsnd_restart\nwait\nvid_reload\n"); @@ -662,14 +665,13 @@ GameLibrary_InstallStart(int gameid) for (int i = 0; i < count; i++) { int pkgid = GameLibrary_IDForPackageName(argv(i)); localcmd(sprintf("pkg add %s\n", argv(i))); - print(sprintf("Marking package %s for install.\n", - argv(i))); + NSLog("Marking package %s for install.", argv(i)); } g_iModInstallCache = gameid; g_strModInstallCache = games[gameid].gamedir; localcmd("pkg apply\n"); - print("Starting installation of custom game packages\n"); + NSLog("Starting installation of custom game packages."); } void @@ -678,15 +680,12 @@ GameLibrary_Install(int gameID) string st; if (gameID >= gameinfo_count || gameID < 0i) { - print(sprintf("GameLibrary_Install: Invalid game id %i!\n", gameID)); + NSError("Invalid game id %i!\n", gameID); return; } st = getpackagemanagerinfo(games[gameID].pkgid, GPMI_INSTALLED); - print(st); - print("\n"); - if (st != "enabled") { GameLibrary_InstallStart(gameID); return; @@ -701,7 +700,7 @@ void GameLibrary_Activate(int gameID) { if (gameID >= gameinfo_count || gameID < 0i) { - print(sprintf("GameLibrary_Activate: Invalid game id %i!\n", gameID)); + NSError("Invalid game id %i.", gameID); return; } @@ -757,7 +756,7 @@ __variant GameLibrary_GetGameInfo(int gameID, gameInfo_t infoType) { if (gameID >= gameinfo_count || gameID < 0i) { - print(sprintf("GameLibrary_GetGameInfo: Invalid game id %i!\n", gameID)); + NSError("Invalid game id %i.", gameID); return __NULL__; } @@ -836,5 +835,5 @@ GameLibrary_DebugList(void) print(sprintf("%i %s (%s)\n", i, games[i].game, games[i].gamedir)); } - print(sprintf("\t%i game(s) loaded\n", gameinfo_count)); + print(sprintf("\t%i game(s) loaded.", gameinfo_count)); } diff --git a/src/platform/maplibrary.qc b/src/platform/maplibrary.qc index dd201fd0..a9b2c92a 100644 --- a/src/platform/maplibrary.qc +++ b/src/platform/maplibrary.qc @@ -170,7 +170,7 @@ MapLibrary_Init(void) } search_end(mapsearch); - print(sprintf("MapLibrary initialized (%i entries).\n", g_mapLibrary_count)); + NSLog("...MapLibrary initialized (%i entries).", g_mapLibrary_count); } int @@ -183,7 +183,7 @@ __variant MapLibrary_GetInfo(int mapID, mapType_t infoType) { if (mapID >= g_mapLibrary_count || mapID < 0i) { - print(sprintf("MapLibrary_GetInfo: Invalid map id %i!\n", mapID)); + NSError("Invalid map id %i", mapID); return __NULL__; } diff --git a/src/platform/master.qc b/src/platform/master.qc index 4d2468a3..466d09da 100644 --- a/src/platform/master.qc +++ b/src/platform/master.qc @@ -37,7 +37,8 @@ Master_Resolve(void) dprint("...\n"); if (!out) { - dprint("Failed to resolve address.\n"); + NSError("Failed to resolve master server address."); + return __NULL__; } return out; @@ -51,6 +52,7 @@ Master_GetTotalServers(void) if (a) { NSLog("Master reports a total of %i servers.", a); } + return gethostcachevalue(SLIST_HOSTCACHETOTALCOUNT); } @@ -95,7 +97,8 @@ Master_RecountServers(void) void Master_RefreshCache(void) { - dprint("Refreshing host cache...\n"); + NSLog("Refreshing host cache..."); + resethostcachemasks(); sethostcachemaskstring(0, gethostcacheindexforkey("gamedir"), cvar_string("game"), SLIST_TEST_EQUAL); sethostcachesort(gethostcacheindexforkey("ping"), FALSE); @@ -112,7 +115,7 @@ Master_RefreshCache(void) void Master_UpdateCache(void) { - dprint("Updating host cache...\n"); + NSLog("Updating host cache..."); resethostcachemasks(); sethostcachemaskstring(0, gethostcacheindexforkey("gamedir"), cvar_string("game"), SLIST_TEST_EQUAL); sethostcachesort(gethostcacheindexforkey("ping"), FALSE); diff --git a/src/server/NSGameRules.qc b/src/server/NSGameRules.qc index 972ce4b3..2a0b792f 100644 --- a/src/server/NSGameRules.qc +++ b/src/server/NSGameRules.qc @@ -374,10 +374,8 @@ NSGameRules::DamageApply(entity t, entity c, float dmg, int w, damageType_t type g_dmg_iFlags = type; g_dmg_iWeapon = w; - NSLog("Damage: %s damages %s with %d damage", c.classname, t.classname, dmg); - NSLog("\tHit-body: %d", g_dmg_iHitBody); - NSLog("\tFlags: %i", g_dmg_iFlags); - NSLog("\tWeapon: %i", g_dmg_iWeapon); + NSLog("%S does %d dmg to %S (body: %d, flags: %i, weapon: %i)", + c.classname, dmg, t.classname, g_dmg_iHitBody, g_dmg_iFlags, g_dmg_iWeapon); /* friendly fire penalty */ if (isFriendlyFire) { @@ -553,19 +551,25 @@ NSGameRules::PlayerRequestRespawn(NSClientPlayer bp) void NSGameRules::ChatMessageAll(NSClient cl, string strMessage) { + float edictNum = num_for_edict(cl) - 1; + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); WriteByte(MSG_MULTICAST, EV_CHAT); - WriteByte(MSG_MULTICAST, num_for_edict(cl) - 1); + WriteByte(MSG_MULTICAST, edictNum); WriteByte(MSG_MULTICAST, cl.team); WriteString(MSG_MULTICAST, strMessage); multicast([0,0,0], MULTICAST_ALL_R); - localcmd(sprintf("echo [ALL] %s: %s\n", cl.netname, strMessage)); + /* TODO: don't print on listen games */ + print(Util_ChatFormat(edictNum, 0, strMessage)); + print("\n"); } void NSGameRules::ChatMessageTeam(NSClient cl, string strMessage) { + float edictNum = num_for_edict(cl) - 1; + /* their finger probably slipped */ if (IsTeamplay() == false) { ChatMessageAll(cl, strMessage); @@ -580,7 +584,7 @@ NSGameRules::ChatMessageTeam(NSClient cl, string strMessage) WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); WriteByte(MSG_MULTICAST, EV_CHAT_TEAM); - WriteByte(MSG_MULTICAST, num_for_edict(cl) - 1); + WriteByte(MSG_MULTICAST, edictNum); WriteByte(MSG_MULTICAST, cl.team); WriteString(MSG_MULTICAST, strMessage); @@ -588,7 +592,8 @@ NSGameRules::ChatMessageTeam(NSClient cl, string strMessage) multicast([0,0,0], MULTICAST_ONE_R); } - localcmd(sprintf("echo [TEAM] %s: %s\n", cl.netname, strMessage)); + print(Util_ChatFormat(edictNum, cl.team, strMessage)); + print("\n"); } string diff --git a/src/server/defs.h b/src/server/defs.h index b2765cc1..6f3e2789 100644 --- a/src/server/defs.h +++ b/src/server/defs.h @@ -154,3 +154,4 @@ void main(void) NSEntity EntityDef_SpawnClassname(string className); NSEntity EntityDef_CreateClassname(string className); +NSEntity Entity_CreateClass(string className); diff --git a/src/server/entityDef.qc b/src/server/entityDef.qc index ec20c429..56d5204d 100644 --- a/src/server/entityDef.qc +++ b/src/server/entityDef.qc @@ -125,13 +125,15 @@ EntityDef_ReadFile(string filePath) /* bounds check */ if (g_entDefCount >= ENTITYDEF_MAX) { - error(sprintf("EntityDef_ReadFile: reached limit of %d defs\n", ENTITYDEF_MAX)); + NSError("Reached limit of %d defs.", ENTITYDEF_MAX); + error("Crash."); } /* open file */ defFile = fopen(filePath, FILE_READ); if (defFile < 0) { - error(sprintf("EntityDef_ReadFile: unable to read %S\n", filePath)); + NSError("Unable to read %S\n", filePath); + error("Crash."); } /* line by line */ @@ -248,6 +250,8 @@ EntityDef_Init(void) { searchhandle pm; + InitStart(); + g_entDefInclude = ""; pm = search_begin("def/*.def", TRUE, TRUE); @@ -284,6 +288,8 @@ EntityDef_Init(void) } } #endif + + InitEnd(); } static bool @@ -331,6 +337,8 @@ EntityDef_CheckCondition(int id, string keyWord, float tweakCondition, string ke tmp1 = stof(keyValue); tmp2 = stof(value); + print(sprintf("%d & %d\n", tmp1, tmp2)); + if (key == keyWord && tmp2 & tmp1) return true; break; @@ -498,7 +506,6 @@ EntityDef_SpawnClassname(string className) } } - NSLog("^1Failed spawning eDef %S", className); return __NULL__; } @@ -507,9 +514,17 @@ EntityDef_CreateClassname(string className) { entity oldSelf = self; NSEntity new = spawn(NSEntity); + NSEntity test; self = new; - EntityDef_SpawnClassname(className); + test = EntityDef_SpawnClassname(className); self = oldSelf; + + /* Failure */ + if (test == __NULL__) { + new.Destroy(); + return __NULL__; + } + return new; } @@ -564,4 +579,27 @@ EntityDef_HasSpawnClass(string className) } return false; +} + +static void +CallSpawnfuncByName(entity target, string className) +{ + entity oldSelf = self; + string spawnClass = strcat("spawnfunc_", className); + self = target; + callfunction(spawnClass); + self = oldSelf; +} + +NSEntity +Entity_CreateClass(string className) +{ + NSEntity newEntity = EntityDef_CreateClassname(className); + + if (!newEntity) { + newEntity = spawn(NSEntity); + CallSpawnfuncByName(newEntity, className); + } + + return newEntity; } \ No newline at end of file diff --git a/src/server/entry.qc b/src/server/entry.qc index 081334a6..721952ee 100644 --- a/src/server/entry.qc +++ b/src/server/entry.qc @@ -89,6 +89,8 @@ ClientDisconnect(void) /* this will hide/remove the player from other clients */ player pl = (player)self; pl.Disappear(); + pl.classname = ""; + pl.flags = 0; } /** Called by the `kill` console command. @@ -147,6 +149,12 @@ PutClientInServer(void) /* handle transitions */ if (whichpack("data/trans.dat")) { + + for (entity a = world; (a = findfloat(a, ::identity, 1));) { + NSEntity levelEnt = (NSEntity)a; + levelEnt.TransitionComplete(); + } + trigger_transition::LoadTransition(); } @@ -232,7 +240,7 @@ The `self` global does not refer to anything. void SetNewParms(void) { - print("--------- Setting New Level Parameters ----------\n"); + InitPrint("Setting New Level Parameters"); if (g_ents_initialized) g_grMode.LevelNewParms(); @@ -248,7 +256,7 @@ allocated for every client. void SetChangeParms(void) { - print("--------- Setting Level-Change Parameters ----------\n"); + InitPrint("Setting Level-Change Parameters"); if (g_ents_initialized) g_grMode.LevelChangeParms((NSClientPlayer)self); @@ -358,9 +366,9 @@ So avoid calling spawn() related functions here. */ void init(float prevprogs) { - print("--------- Initializing Server Game ----------\n"); - print("Built: " __DATE__ " " __TIME__"\n"); - print("QCC: " __QCCVER__ "\n"); + InitPrint("Initializing Server Game"); + NSLog("Built: %s %s", __DATE__, __TIME__); + NSLog("QCC: %s", __QCCVER__); Plugin_Init(); @@ -369,7 +377,6 @@ init(float prevprogs) PropData_Init(); SurfData_Init(); DecalGroups_Init(); - Skill_Init(); /* DO NOT EVER CHANGE THESE. */ cvar_set("r_meshpitch", "1"); @@ -391,7 +398,9 @@ init_respawn(void) endspawn++; } - print(sprintf("...%i entities spawned (%i inhibited)\n", g_ent_spawned, g_ent_spawned - endspawn)); + NSLog("...%i entities spawned (%i inhibited)", g_ent_spawned, g_ent_spawned - endspawn); + + InitEnd(); remove(self); } @@ -464,7 +473,7 @@ initents(void) g_ents_initialized = TRUE; /* engine hacks for dedicated servers */ - cvar_set("s_nominaldistance", "1024"); + cvar_set("s_nominaldistance", "1536"); /* other engine hacks */ cvar_set("sv_nqplayerphysics", "0"); @@ -518,7 +527,11 @@ ConsoleCmd(string cmd) tokenize(cmd); switch (argv(0)) { case "addBot": - Bot_AddBot_f(strtolower(argv(1))); + string botProfile = strtolower(argv(1)); + float teamValue = stof(argv(2)); + float spawnDelay = stof(argv(3)); + string newName = argv(4); + Bot_AddBot_f(botProfile, teamValue, spawnDelay, newName); break; case "killAllBots": Bot_KillAllBots(); @@ -597,6 +610,12 @@ ConsoleCmd(string cmd) if (finder) setorigin(pl, finder.origin); break; + case "renetworkEntities": + for (entity a = world; (a = findfloat(a, ::identity, 1));) { + NSEntity ent = (NSEntity)a; + ent.SendFlags = -1; + } + break; case "respawnEntities": for (entity a = world; (a = findfloat(a, ::identity, 1));) { NSEntity ent = (NSEntity)a; @@ -658,7 +677,7 @@ SV_PerformLoad(float fh, float entcount, float playerslots) NSEntity loadent = __NULL__; int num_loaded = 0i; - print("--------- Loading Existing Save ----------\n"); + InitPrint("Loading Existing Save"); g_isloading = true; #if 0 @@ -695,7 +714,7 @@ SV_PerformLoad(float fh, float entcount, float playerslots) #ifndef REEDICT n = stof(argv(1)); e = edict_num(n); - print(sprintf("Creating %s (edict %d)\n", cname, n)); + NSLog("Creating %s (edict %d)", cname, n); #else entity e = spawn(); #endif @@ -719,7 +738,7 @@ SV_PerformLoad(float fh, float entcount, float playerslots) loadent = (NSEntity)e; self = eold; } else { - print(sprintf("Could not spawn %s\n", cname)); + NSError("Could not spawn %s", cname); remove(e); self = eold; continue; @@ -729,7 +748,7 @@ SV_PerformLoad(float fh, float entcount, float playerslots) if (loadent) { loadent.RestoreComplete(); num_loaded++; - print(sprintf("completed %s (edict %d)\n\n", loadent.classname, n)); + NSLog("completed %s (edict %d)", loadent.classname, n); loadent = __NULL__; } } else { @@ -744,7 +763,7 @@ SV_PerformLoad(float fh, float entcount, float playerslots) } } - print(sprintf("loaded %i entities\n", num_loaded)); + NSLog("...loaded %i entities", num_loaded); g_isloading = false; } @@ -759,7 +778,7 @@ SV_PerformSave(float fh, float entcount, float playerslots) int num_saved = 0i; entity e; - print("--------- Performing Save ----------\n"); + InitPrint("Performing Save"); for (i = 0; i < entcount; i++) { NSEntity willsave; @@ -782,7 +801,7 @@ SV_PerformSave(float fh, float entcount, float playerslots) num_saved++; } fclose(fh); - print(sprintf("saved %i entities\n", num_saved)); + NSLog("saved %i entities", num_saved); } /** Called by the engine to check with us if a spawn function exists. @@ -793,17 +812,20 @@ to remove in case we won't initialize it. void CheckSpawn(void() spawnfunc) { - if (MapTweak_EntitySpawn(self)) - return; - if (EntityDef_SpawnClassname(self.classname)) - return; + string desiredClass = self.classname; - if (spawnfunc) { + if (MapTweak_EntitySpawn(self)) { + self._mapspawned = true; + self.classname = desiredClass; + } else if (EntityDef_SpawnClassname(desiredClass)) { + self._mapspawned = true; + } else if (spawnfunc) { spawnfunc(); + self.classname = desiredClass; self._mapspawned = true; g_ent_spawned++; } else { - print(sprintf("^1Cannot find entity class ^7%s\n", self.classname)); + NSError("Unable to spawn %s", desiredClass); remove(self); } @@ -816,4 +838,4 @@ CheckSpawn(void() spawnfunc) g_ent_spawned--; } } -} +} \ No newline at end of file diff --git a/src/server/mapcycle.qc b/src/server/mapcycle.qc index 90124b7b..08a4945b 100644 --- a/src/server/mapcycle.qc +++ b/src/server/mapcycle.qc @@ -28,7 +28,7 @@ Mapcycle_Load(string filename) fs_mapcycle = fopen(filename, FILE_READ); if (fs_mapcycle < 0) { - print(strcat("^1could not load ", filename, "\n")); + NSError("Missing file %s", filename); return; } @@ -57,7 +57,7 @@ Mapcycle_Load(string filename) /* the current map in the list will decide the nextmap */ localcmd(sprintf("alias nextmap m%i\n", map_next)); - print(sprintf("mapcycle initialized with %i entries.\n", mapcount)); + NSLog("...MapCycle initialized with %i entries.", mapcount); } void @@ -69,14 +69,15 @@ Mapcycle_Init(void) if (g_grMode.IsMultiplayer() == false) return; - print("--------- Initializing MapCycle ----------\n"); + InitStart(); /* in case some server admin wants a map to continously loop */ if (cycleFile == "") { - print("mapcycle disabled via cvar. skipping\n"); + NSLog("MapCycle disabled via cvar. Skipping."); localcmd("alias nextmap map_restart 0\n"); return; } Mapcycle_Load(cycleFile); + InitEnd(); } diff --git a/src/server/maptweaks.qc b/src/server/maptweaks.qc index 498fed72..06d09c60 100644 --- a/src/server/maptweaks.qc +++ b/src/server/maptweaks.qc @@ -47,6 +47,8 @@ MapTweaks_Init(void) string newCvar, newInfo, newItem; int atTweak = 0i; + InitStart(); + tweakFile = fopen("scripts/maptweaks.txt", FILE_READ); g_mapTweakCount = 0; newCvar = newInfo = newItem = ""; @@ -60,6 +62,8 @@ MapTweaks_Init(void) } } } else { + NSError("Missing file scripts/maptweaks.txt"); + InitEnd(); return; } @@ -97,6 +101,7 @@ MapTweaks_Init(void) } fclose(tweakFile); + InitEnd(); } static bool diff --git a/src/server/nodes.qc b/src/server/nodes.qc index b9bf488f..f434dc7c 100644 --- a/src/server/nodes.qc +++ b/src/server/nodes.qc @@ -164,7 +164,7 @@ Nodes_InsertNodeForClassname(string classn) void Nodes_BuildFromEnts(void) { - print("rebuilding node tree..."); + NSLog("Rebuilding node tree..."); /* run through the ents and rebuild the tree */ Nodes_InsertNodeForClassname("info_node"); @@ -179,13 +179,13 @@ Nodes_BuildFromEnts(void) if (g_iNodes == 0) Nodes_InsertNodeForClassname("info_player_deathmatch"); - print(sprintf("%i possible nodes found in %s\n", g_iNodes, mapname)); + NSLog("%i possible nodes found in %s", g_iNodes, mapname); if (g_iNodes) { - print(sprintf("saving nodes nodes for %s\n", mapname)); + NSLog("saving nodes nodes for %s", mapname); Nodes_Save(sprintf("%s.way", mapname)); } else { - print(sprintf("no node data found for %s\n", mapname)); + NSLog("no node data found for %s", mapname); } } @@ -193,14 +193,14 @@ Nodes_BuildFromEnts(void) void Nodes_Init(void) { - print("--------- Initializing Nodes Subsystem ----------\n"); + InitStart(); g_nodes_present = FALSE; /* skip if present. TODO: check if they're out of date? */ if (whichpack(sprintf("data/%s.way", mapname))) { g_nodes_present = TRUE; #ifdef NODE_DEBUG - print(sprintf("loading existing nodes for %s\n", mapname)); + NSLog("loading existing nodes for %s", mapname); Nodes_Load(sprintf("%s.way", mapname)); #endif } else { @@ -216,7 +216,7 @@ Nodes_Init(void) g_iNodes = 0; #endif - print("Nodes subsystem initialized.\n"); + InitEnd(); } #ifdef NODE_DEBUG @@ -231,13 +231,16 @@ SV_AddDebugPolygons(void) { Way_DrawDebugInfo(); - if (!g_iNodes) { - return; - } - if (cvar("developer") != 1) return; +#if 1 + for (entity s = world; (s = find(s, ::classname, "func_tracktrain"));) { + func_tracktrain train = (func_tracktrain)s; + train.RenderDebugInfo(); + } +#endif + makevectors(self.v_angle); /* draw the rectangles */ @@ -251,6 +254,22 @@ SV_AddDebugPolygons(void) R_EndPolygon(); } + for (entity s = world; (s = find(s, ::classname, "path_track"));) { + vector pos = s.origin; + pos[2] += 32; + R_BeginPolygon("textures/dev/path_track", 0, 0); + R_PolygonVertex(pos + v_right * 24 - v_up * 24, [1,1], [1,1,1], 1.0f); + R_PolygonVertex(pos - v_right * 24 - v_up * 24, [0,1], [1,1,1], 1.0f); + R_PolygonVertex(pos - v_right * 24 + v_up * 24, [0,0], [1,1,1], 1.0f); + R_PolygonVertex(pos + v_right * 24 + v_up * 24, [1,0], [1,1,1], 1.0f); + R_EndPolygon(); + + R_BeginPolygon("", 0, 0); + R_PolygonVertex(s.origin, [0,1], [1,1,1], NODE_LINE_ALPHA); + R_PolygonVertex(pos, [1,1], [1,1,1], NODE_LINE_ALPHA); + R_EndPolygon(); + } + for (entity s = world; (s = find(s, ::classname, "scripted_sequence"));) { vector pos = s.origin; pos[2] += 32; @@ -267,45 +286,5 @@ SV_AddDebugPolygons(void) R_PolygonVertex(pos, [1,1], [1,1,1], NODE_LINE_ALPHA); R_EndPolygon(); } - - /* draw the radius */ - R_BeginPolygon("", 0, 0); - for (int i = 0; i < g_iNodes; i++) { - node_t *w = g_pNodes + i; - vector org = w->origin; - - for (float j = 0; j < (2 * M_PI); j += (2 * M_PI) / 4) { - R_PolygonVertex( - org + [sin(j),cos(j)]*w->radius, - [1,1], - [0,0.25,0], - 1.0f - ); - } - R_EndPolygon(); - } - - /* draw the lines */ - R_BeginPolygon("", 1, 0); - for (int i = 0; i < g_iNodes; i++) { - node_t *w = g_pNodes+i; - vector org = w->origin; - vector rgb = [1,1,1]; - - for (int j = 0; j < w->nb_count; j++) { - int k = w->nb[j].node; - - /* check for invalids */ - if (k < 0 || k >= g_iNodes) { - break; - } - - node_t *w2 = &g_pNodes[k]; - - R_PolygonVertex(org, [0,1], [1,1,1], NODE_LINE_ALPHA); - R_PolygonVertex(w2->origin, [1,1], [1,1,1], NODE_LINE_ALPHA); - R_EndPolygon(); - } - } } #endif diff --git a/src/server/plugins.qc b/src/server/plugins.qc index c6de6de3..6b7e2437 100644 --- a/src/server/plugins.qc +++ b/src/server/plugins.qc @@ -31,18 +31,20 @@ Plugin_Init(void) int i; if (autocvar_sv_plugins) { - print("--------- Initializing Plugins ----------\n"); g_plugins_enabled = 1; } else { g_plugins_enabled = 0; return; } + InitStart(); + pdb = fopen("plugins.txt", FILE_READ); if (pdb < 0) { - print("^1no plugins.txt found.\n"); + NSWarning("No plugins.txt found. Plugins disabled.\n"); g_plugins_enabled = 0; + InitEnd(); return; } @@ -85,7 +87,8 @@ Plugin_Init(void) } } - print(sprintf("initialized %i plugins.\n", g_plugincount)); + NSLog("...initialized %i plugins.", g_plugincount); + InitEnd(); } /* diff --git a/src/server/skill.qc b/src/server/skill.qc index 8f05d784..643c7f99 100644 --- a/src/server/skill.qc +++ b/src/server/skill.qc @@ -27,8 +27,13 @@ This will almost always result in them using default values, or (worst case) 0. void Skill_Init(void) { + string mapSkillFile = sprintf("maps/%s_skl.cfg", serverkey("mapname")); + Skill_ParseConfig("cfg/skill_manifest.cfg"); - Skill_ParseConfig(sprintf("maps/%s_skl.cfg", mapname)); + + if (FileExists(mapSkillFile)) { + Skill_ParseConfig(mapSkillFile); + } } /* @@ -68,7 +73,7 @@ Skill_ParseConfig(string fileName) filestream configFile = fopen(fileName, FILE_READ); if (configFile < 0) { - print(sprintf("^1Warning: Unable to exec %S for parsing.\n", fileName)); + NSWarning("Unable to exec %S for parsing.", fileName); return (false); } diff --git a/src/server/way.h b/src/server/way.h index d7394cab..e14a3108 100644 --- a/src/server/way.h +++ b/src/server/way.h @@ -23,4 +23,5 @@ #define LF_WALK 0x00000010i #define LF_AIM 0x00000020i #define LF_USER 0x00000040i +#define LF_HAZARDOUS 0x00000080i #define LF_DESTINATION 0x80000000i diff --git a/src/shared/NSBrushTrigger.qc b/src/shared/NSBrushTrigger.qc index 867a72eb..8adc83d7 100644 --- a/src/shared/NSBrushTrigger.qc +++ b/src/shared/NSBrushTrigger.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 diff --git a/src/shared/NSClient.h b/src/shared/NSClient.h index 34f68100..4e594095 100644 --- a/src/shared/NSClient.h +++ b/src/shared/NSClient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -62,19 +62,20 @@ public: virtual float predraw(void); #endif + /** Get the string value of an InfoKey. */ + nonvirtual string GetInfoKey(string); + /** Floating point based version of GetInfoKey(). */ + nonvirtual float GetInfoKeyFloat(string); + #ifdef SERVER /** Server: This is where the input* variables arrive after sending them out from the client (see ClientInputFrame). This is also where we will instruct the server to run physics on the client. */ virtual void ServerInputFrame(void); - /** Set the value of an InfoKey. */ + /** Server: Set the value of an InfoKey. */ nonvirtual void SetInfoKey(string, string); - /** Get the string value of an InfoKey. */ - nonvirtual string GetInfoKey(string); - /** Floating point based version of SetInfoKey(). */ + /** Server: Floating point based version of SetInfoKey(). */ nonvirtual void SetInfoKeyFloat(string, float); - /** Floating point based version of GetInfoKey(). */ - nonvirtual float GetInfoKeyFloat(string); /* overrides */ virtual void Save(float); diff --git a/src/shared/NSClient.qc b/src/shared/NSClient.qc index 9b6de012..1198fd5d 100644 --- a/src/shared/NSClient.qc +++ b/src/shared/NSClient.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -69,25 +69,38 @@ NSClient::SetInfoKey(string strKey, string strValue) forceinfokey(this, strKey, strValue); } -string -NSClient::GetInfoKey(string strKey) -{ - return infokey(this, strKey); -} - void NSClient::SetInfoKeyFloat(string strKey, float floatValue) { forceinfokey(this, strKey, ftos(floatValue)); } +#endif + +string +NSClient::GetInfoKey(string strKey) +{ +#ifdef SERVER + return infokey(this, strKey); +#endif + +#ifdef CLIENT + return getplayerkeyvalue(entnum-1, strKey); +#endif +} + float NSClient::GetInfoKeyFloat(string strKey) { +#ifdef SERVER return infokeyf(this, strKey); +#endif + +#ifdef CLIENT + return getplayerkeyfloat(entnum-1, strKey); +#endif } -#endif void NSClient::SharedInputFrame(void) diff --git a/src/shared/NSClientPlayer.qc b/src/shared/NSClientPlayer.qc index 598b12b5..48b83d64 100644 --- a/src/shared/NSClientPlayer.qc +++ b/src/shared/NSClientPlayer.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 diff --git a/src/shared/NSClientSpectator.qc b/src/shared/NSClientSpectator.qc index c50e0a62..f88ed487 100644 --- a/src/shared/NSClientSpectator.qc +++ b/src/shared/NSClientSpectator.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 diff --git a/src/shared/NSDebris.qc b/src/shared/NSDebris.qc index 7373adf9..d63af324 100644 --- a/src/shared/NSDebris.qc +++ b/src/shared/NSDebris.qc @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2023-2024 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 CLIENT void NSDebris::NSDebris(void) @@ -17,4 +33,4 @@ NSDebris::SetImpactDecal(string impactDecal) { m_strImpactDecal = impactDecal; } -#endif \ No newline at end of file +#endif diff --git a/src/shared/NSEntity.h b/src/shared/NSEntity.h index d61a1a52..d8ed2b30 100644 --- a/src/shared/NSEntity.h +++ b/src/shared/NSEntity.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -147,6 +147,9 @@ public: /** Unsets any any angle related values within the entity. */ nonvirtual void ClearAngles(void); + + /** Forces the entity to re-network updates to all clients. */ + nonvirtual void ForceNetworkUpdate(void); #endif /* sets */ @@ -202,6 +205,11 @@ public: /** Remove one or more special flags from the entity. */ nonvirtual void RemoveFlags(float); + /** Turns to the specified angle. */ + nonvirtual void TurnTo(float); + /** Turns towards the specified position. */ + nonvirtual void TurnToPos(vector); + /** Overrides the Think function of the entity. Only use it when you want to retain a think timer that's already been set for the entity. */ nonvirtual void SetThink(void()); @@ -399,4 +407,4 @@ NSEntity_SpawnClass(string className, vector spawnOrigin, vector 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 adfe9253..4b0f5179 100644 --- a/src/shared/NSEntity.qc +++ b/src/shared/NSEntity.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -39,7 +39,7 @@ void NSEntity::Spawned( void ) { #ifdef SERVER m_oldstrTarget = target; - if ( m_oldModel ) { + if ( m_oldModel && m_oldModel != "" ) { precache_model( GetSpawnModel() ); } @@ -332,7 +332,11 @@ void NSEntity::RestoreAngles( void ) { } void NSEntity::ClearAngles( void ) { - angles =[0, 0, 0]; + angles = [0, 0, 0]; +} + +void NSEntity::ForceNetworkUpdate( void ) { + SendFlags = -1; } #endif @@ -532,6 +536,14 @@ void NSEntity::RemoveFlags( float fl ) { flags &= ~fl; } +void NSEntity::TurnTo( float targetAngle ) { + angles[1] = targetAngle; +} + +void NSEntity::TurnToPos( vector targetPos ) { + angles = vectoangles(targetPos - WorldSpaceCenter()); +} + void NSEntity::SetThink( void ( void ) func ) { think = func; } @@ -546,7 +558,7 @@ void NSEntity::SetNextThink( float fl ) { if ( flTime >= 0 ) nextthink = flTime; else - NSLog( "%s sets bogus nextthink value %f\n", classname, flTime ); + EntError( "%s sets bogus nextthink value %f\n", classname, flTime ); } void NSEntity::ScheduleThink( void ( void ) func, float fl ) { @@ -676,13 +688,11 @@ void NSEntity::ClearVelocity( void ) { #ifdef SERVER void NSEntity::Respawn( void ) { - NSTrigger::Respawn(); - + super::Respawn(); SetSolid( m_oldSolid ); SetAngles( GetSpawnAngles() ); SetOrigin( GetSpawnOrigin() ); SetModel( GetSpawnModel() ); - SetTriggerTarget( m_oldstrTarget ); /* FIXME: Move into NSTrigger::Respawn */ } void NSEntity::Save( float handle ) { @@ -690,6 +700,7 @@ void NSEntity::Save( float handle ) { SaveFloat( handle, "pvsflags", pvsflags ); SaveFloat( handle, "_mapspawned", _mapspawned ); SaveFloat( handle, "scale", scale ); + SaveFloat( handle, "friction", friction ); SaveVector( handle, "m_vecMins", m_vecMins ); SaveVector( handle, "m_vecMaxs", m_vecMaxs ); SaveVector( handle, "m_oldOrigin", m_oldOrigin ); @@ -714,6 +725,9 @@ void NSEntity::Restore( string strKey, string strValue ) { case "scale": scale = ReadFloat( strValue ); break; + case "friction": + friction = ReadFloat( strValue ); + break; case "m_vecMins": m_vecMins = ReadVector( strValue ); break; @@ -857,6 +871,9 @@ void NSEntity::SpawnKey( string strKey, string strValue ) { case "solid": solid = ReadFloat( strValue ); break; + case "friction": + friction = ReadFloat( strValue ); + break; #ifdef SERVER case "health": health = ReadFloat( strValue ); @@ -875,6 +892,8 @@ void NSEntity::SpawnKey( string strKey, string strValue ) { break; #endif + case "_minlight": + break; default: super::SpawnKey( strKey, strValue ); break; @@ -888,6 +907,10 @@ void NSEntity::Destroy( void ) { removed = 1; /* mark this as cleanly removed */ OnRemoveEntity(); customphysics = __NULL__; + modelindex = 0; + solid = 0; + movetype = 0; + classname = 0; ScheduleThink(Util_Destroy, 0.0f ); } @@ -960,13 +983,13 @@ bool NSEntity::StartSound( string strSample, float channel, float flags, bool br #endif } - SndLog( "^2%s::^3StartSound^7: %s (chan: %d bcast: %d) (%v)", classname, strSample, channel, broadcast, origin ); + SndEntLog( "%s (chan: %d bcast: %d) (%v)", strSample, channel, broadcast, origin ); return ( true ); } bool NSEntity::StartSoundDef( string strSample, float channel, bool broadcast ) { - SndLog( "^2%s::^3StartSoundDef^7: %s (chan: %d bcast: %d)", classname, strSample, channel, broadcast ); + SndEntLog( "%s (chan: %d bcast: %d)", strSample, channel, broadcast ); Sound_Play( this, channel, strSample ); return ( true ); } @@ -1108,4 +1131,4 @@ NSEntity::GetNearbySpot(void) return testPos; return g_vec_null; -} \ No newline at end of file +} diff --git a/src/shared/NSIO.h b/src/shared/NSIO.h index 87e5b6f6..65ef6bd7 100644 --- a/src/shared/NSIO.h +++ b/src/shared/NSIO.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -137,3 +137,47 @@ public: }; .bool _mapspawned; + +void +_NSEntLog(string className, string functionName, float edictNum, string warnMessage) +{ + if (autocvar_g_developerTimestamps) + print(sprintf("^9%f ^7%s (%d)^7: %s\n", time, className, edictNum, warnMessage)); + else + print(sprintf("^7%s (%d)^7: %s\n", className, edictNum, warnMessage)); +} + +void +_NSEntWarning(string className, string functionName, float edictNum, string warnMessage) +{ + if (autocvar_g_developerTimestamps) + print(sprintf("^9%f ^3%s (%d)^7: %s\n", time, functionName, edictNum, warnMessage)); + else + print(sprintf("^3%s (%d)^7: %s\n", functionName, edictNum, warnMessage)); +} + +void +_NSEntError(string className, string functionName, float edictNum, string warnMessage) +{ + if (autocvar_g_developerTimestamps) + print(sprintf("^9%f ^1%s (id: %d)^7: %s\n", time, functionName, edictNum, warnMessage)); + else + print(sprintf("^1%s (id: %d)^7: %s\n", functionName, edictNum, warnMessage)); +} +/** Logs an entity class specific log message, with detailed info. + The console variable `entity_developer` has to be `1` for them to be visible. + +@param description(...) contains a formatted string containing a description. */ +#define EntLog(...) if (autocvar_g_developer) _NSEntLog(classname, __FUNC__, num_for_edict(this), sprintf(__VA_ARGS__)) + +/** Logs an entity class specific warning message, with detailed info. + The console variable `entity_developer` has to be `1` for them to be visible. + +@param description(...) contains a formatted string containing a description. */ +#define EntWarning(...) _NSEntWarning(classname, __FUNC__, num_for_edict(this), sprintf(__VA_ARGS__)) + +/** Logs an entity class specific error message, with detailed info. + The console variable `entity_developer` has to be `1` for them to be visible. + +@param description(...) contains a formatted string containing a description. */ +#define EntError(...) _NSEntError(classname, __FUNC__, num_for_edict(this), sprintf(__VA_ARGS__)) diff --git a/src/shared/NSIO.qc b/src/shared/NSIO.qc index 6a264523..9cdfe66b 100644 --- a/src/shared/NSIO.qc +++ b/src/shared/NSIO.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -204,7 +204,7 @@ NSIO::CreateOutput(string outmsg) NSLog("Input: %s", new_minion.m_strInput); NSLog("Data Message: %s", new_minion.m_strData); NSLog("Delay: %f", new_minion.m_flDelay); - NSLog("Uses: %i\n", new_minion.m_iCount); + NSLog("Uses: %i", new_minion.m_iCount); } /* return the name that'll act as the trigger for all outputs */ @@ -251,12 +251,13 @@ NSIO::Input(entity eAct, string strInput, string strData) UseOutput(eAct, m_strOnUser4); break; default: - if (strData != "") - NSLog("^2%s::^3Input^7: Receives input %s from %s with data %s\n", - this.classname, strInput, eAct.classname, strData); - else - NSLog("^2%s::^3Input^7: Receives input %s from %s\n", - this.classname, strInput, eAct.classname); + if (strData != "") { + EntWarning("Receives unknown input %S from %d with data %S", + strInput, num_for_edict(eAct), strData); + } else { + EntWarning("Receives unknown input %S from %d", + strInput, num_for_edict(eAct)); + } } } @@ -737,8 +738,10 @@ NSIO::SpawnKey(string strKey, string strValue) break; #endif default: - NSLog("^3%s^7::SpawnKey:: Unknown key '%s' with value '%s'", +#ifdef SERVER + EntWarning("%s has unknown key %S with value %S", classname, strKey, strValue); +#endif break; } } @@ -753,4 +756,4 @@ float NSIO::GetTime(void) { return (movetype == MOVETYPE_PUSH) ? ltime : time; -} \ No newline at end of file +} diff --git a/src/shared/NSItem.qc b/src/shared/NSItem.qc index 6c0e9b9b..11f065d7 100644 --- a/src/shared/NSItem.qc +++ b/src/shared/NSItem.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Vera Visions LLC. + * Copyright (c) 2024 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 diff --git a/src/shared/NSMonster.h b/src/shared/NSMonster.h index 84f1c64c..598f3917 100644 --- a/src/shared/NSMonster.h +++ b/src/shared/NSMonster.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -16,12 +16,14 @@ var bool autocvar_ai_debugLogic = false; void -_NSMonster_Log(string msg) +_NSMonster_Log(string className, string functionName, float edictNum, string warnMessage) { - if (autocvar_ai_debugLogic == true) - print(sprintf("%f %s\n", time, msg)); + if (autocvar_g_developerTimestamps) + printf("^9%f ^5%s (%d) ^7: %s\n", time, functionName, edictNum, warnMessage); + else + printf("^5%s (%d) ^7: %s\n", functionName, edictNum, warnMessage); } -#define NSMonster_Log(...) _NSMonster_Log(sprintf(__VA_ARGS__)) +#define NSMonsterLog(...) if (autocvar_ai_debugLogic == true) _NSMonster_Log(classname, __FUNC__, num_for_edict(this), sprintf(__VA_ARGS__)) /** Bitfield enumeration for NSMonster its SendFlags field. diff --git a/src/shared/NSMonster.qc b/src/shared/NSMonster.qc index e87ecb95..2fe32020 100644 --- a/src/shared/NSMonster.qc +++ b/src/shared/NSMonster.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -604,7 +604,7 @@ NSMonster::AlertNearby(void) if (vlen(origin - w.origin) > 512) continue; - //NSMonster_Log("Alert! %s get %s", w.classname, m_eEnemy.classname); + //NSMonsterLog("Alert! %s get %s", w.classname, m_eEnemy.classname); NSMonster f = (NSMonster)w; /* we shouldn't override this when they already got a target */ @@ -663,6 +663,10 @@ NSMonster_TraceAgainsTarget(NSMonster monster, NSEntity target) void NSMonster::SeeThink(void) { + if (HasSpawnFlags(MSF_PRISONER) == true) { + return; + } + if (m_eLookAt) { vector vecDelta; makevectors( angles ); @@ -675,7 +679,7 @@ NSMonster::SeeThink(void) makevectors(v_angle); vector tmp = vectoangles(v_forward); subblendfrac = tmp[0] / 90; - bonecontrol1 = m_flHeadYaw; /* head turning */ + bonecontrol1 = Math_Lerp(bonecontrol1, m_flHeadYaw, frametime * 15.0f); /* head turning */ } } @@ -983,7 +987,7 @@ NSMonster::AttackRanged(void) } static void AttackRanged_RangedSpecial(void) { - NSMonster_Log("AttackRanged_RangedSpecial: %S", m_defRanged2); + NSMonsterLog("AttackRanged_RangedSpecial: %S", m_defRanged2); NSProjectile_SpawnDef(m_defRanged2, this); } @@ -1001,7 +1005,7 @@ NSMonster::AttackRanged(void) if (_m_flReloadTracker > m_flReloadCount) { throwAnyway = true; _m_bShouldThrow = true; - NSMonster_Log("throwAnyway: true!"); + NSMonsterLog("throwAnyway: true!"); } /* special always first if possible */ @@ -1027,14 +1031,14 @@ NSMonster::AttackRanged(void) /* out of ammo, cannot reload */ if (m_flReserveAmmo == 0) { - //NSMonster_Log("Out of ammo!"); + //NSMonsterLog("Out of ammo!"); return 0; } /* do we not have unlimited ammo? */ if (m_flReserveAmmo != -1) { m_flReserveAmmo -= m_flReloadCount; - NSMonster_Log("Reserve ammo: %d", m_flReserveAmmo); + NSMonsterLog("Reserve ammo: %d", m_flReserveAmmo); /* oh no, we're below 0 in terms of ammo. */ if (m_flReserveAmmo < 0) { @@ -1043,7 +1047,7 @@ NSMonster::AttackRanged(void) } } - NSMonster_Log("Starting at %d bullets", startAmmo); + NSMonsterLog("Starting at %d bullets", startAmmo); _m_flReloadTracker = startAmmo; AnimPlay(actReload); StartSoundDef(m_sndReload, CHAN_WEAPON, true); @@ -1051,11 +1055,11 @@ NSMonster::AttackRanged(void) if (m_flReloadDelay) { m_flAttackThink = time + m_flReloadDelay; - NSMonster_Log("Reloading, delay %f seconds", m_flReloadDelay); + NSMonsterLog("Reloading, delay %f seconds", m_flReloadDelay); } else { float actDuration = frameduration(modelindex, actReload); m_flAttackThink = time + actDuration; - NSMonster_Log("Reloading, act delays it by %f seconds", actDuration); + NSMonsterLog("Reloading, act delays it by %f seconds", actDuration); } return 1; @@ -1068,10 +1072,10 @@ NSMonster::AttackRanged(void) if (m_defRanged1) if (EntityDef_HasSpawnClass(m_defRanged1)) { NSProjectile_SpawnDef(m_defRanged1, this); - NSMonster_Log("Firing ranged def %S", m_defRanged1); + NSMonsterLog("Firing ranged def %S", m_defRanged1); } else { TraceAttack_FireBullets(1, GetEyePos(), rangedDmg, [0.01,0.01] * m_flAttackAccuracy, 0); - NSMonster_Log("Firing traceline def with %d", rangedDmg); + NSMonsterLog("Firing traceline def with %d", rangedDmg); } StartSoundDef(m_sndRangedAttack, CHAN_WEAPON, true); @@ -1086,11 +1090,11 @@ NSMonster::AttackRanged(void) if (rangedDly) { m_flAttackThink = time + rangedDly + burstTime; - NSMonster_Log("Primary ranged attack, delay %f seconds (burst %d)", rangedDly, burstTime); + NSMonsterLog("Primary ranged attack, delay %f seconds (burst %d)", rangedDly, burstTime); } else { float actAttackTime = frameduration(modelindex, actRanged); m_flAttackThink = time + actAttackTime + burstTime; - NSMonster_Log("Primary ranged attack, act delays it by %f seconds (burst %f)", actAttackTime, burstTime); + NSMonsterLog("Primary ranged attack, act delays it by %f seconds (burst %f)", actAttackTime, burstTime); } return 1; @@ -1173,7 +1177,7 @@ NSMonster::FreeState(void) NSEntity findKT = (NSEntity)find(world, ::targetname, m_strSequenceKillTarget); if (findKT) { - NSMonster_Log("^2%s::^3FreeState^7: Killing %S", classname, m_strSequenceKillTarget); + NSMonsterLog("Killing %S", m_strSequenceKillTarget); findKT.Destroy(); } else { error("Could not remove scripted killtarget!\n"); @@ -1207,7 +1211,8 @@ NSMonster::FreeState(void) if (m_iSequenceRemove) { Hide(); } - NSMonster_Log("^2%s::^3FreeState^7: (%i, %S)", classname, m_iSequenceRemove, to_trigger); + + NSMonsterLog("Sequence over (hidden: %i, triggering: %S)", m_iSequenceRemove, to_trigger); } void @@ -1215,7 +1220,7 @@ NSMonster::FreeStateMoved(void) { vector new_origin; new_origin = gettaginfo(this, 1); - NSMonster_Log("^2%s::^3FreeStateMoved^7: moved to %v", classname, new_origin); + NSMonsterLog("Moved to %v", new_origin); SetOrigin(new_origin); DropToFloor(); FreeState(); @@ -1227,7 +1232,7 @@ NSMonster::FreeStateDead(void) vector new_origin; new_origin = gettaginfo(this, 1); - NSMonster_Log("^2%s::^3FreeStateMoved^7: moved to %v", classname, new_origin); + NSMonsterLog("Moved to %v", new_origin); SetOrigin(new_origin); DropToFloor(); @@ -1251,14 +1256,14 @@ NSMonster::RouteEnded(void) m_iSequenceState = SEQUENCESTATE_ENDING; think = (m_iSequenceFlags & SSFL_NOSCRIPTMOVE) ? FreeState : FreeStateMoved; nextthink = time + duration; - NSMonster_Log("^2%s::^3RouteEnded^7: %s overriding anim for %f seconds (modelindex %d, frame %d)", \ - classname, this.targetname, duration, modelindex, m_flSequenceEnd); + NSMonsterLog("%s overriding anim for %f seconds (modelindex %d, frame %d)", \ + this.targetname, duration, modelindex, m_flSequenceEnd); } else { /* we still need to trigger targets */ think = (m_iSequenceFlags & SSFL_NOSCRIPTMOVE) ? FreeState : FreeStateMoved; nextthink = time; - NSMonster_Log("^2%s::^3RouteEnded^7: %s has no anim, finished sequence", \ - classname, this.targetname); + NSMonsterLog("%s has no anim, finished sequence", \ + this.targetname); } } @@ -2279,7 +2284,7 @@ NSMonster_AlertEnemyAlliance(vector pos, float radius, int alliance) return; if (autocvar_ai_debugAlerts) - NSMonster_Log("AI alert from %v with radius %f and alliance %i", pos, radius, alliance); + NSLog("AI alert from %v with radius %f and alliance %i", pos, radius, alliance); for (entity w = world; (w = nextent(w));) { if (w.takedamage == DAMAGE_NO) @@ -2293,7 +2298,7 @@ NSMonster_AlertEnemyAlliance(vector pos, float radius, int alliance) /* only target monsters */ if (!(w.flags & FL_MONSTER)) { if (autocvar_ai_debugAlerts) - NSMonster_Log("\t%S is not a monster", w.classname); + NSLog("\t%S is not a monster", w.classname); continue; } @@ -2302,26 +2307,26 @@ NSMonster_AlertEnemyAlliance(vector pos, float radius, int alliance) /* they already got a target of some kind */ if (f.m_eEnemy) { if (autocvar_ai_debugAlerts) - NSMonster_Log("\t%S already has a target", w.classname); + NSLog("\t%S already has a target", w.classname); continue; } /* if they're our friend... ignore*/ if (f.IsFriend(alliance)) { if (autocvar_ai_debugAlerts) - NSMonster_Log("\t%S is friend of alliance %i", w.classname, alliance); + NSLog("\t%S is friend of alliance %i", w.classname, alliance); continue; } /* if the monster is dead... ignore */ if (f.health <= 0) { if (autocvar_ai_debugAlerts) - NSMonster_Log("\t%S is dead, cannot be alerted", w.classname); + NSLog("\t%S is dead, cannot be alerted", w.classname); continue; } if (autocvar_ai_debugAlerts) - NSMonster_Log("\twe're alerting %S to go to %v", w.classname, pos); + NSLog("\twe're alerting %S to go to %v", w.classname, pos); /* we've heard a noise. investigate the location */ f.RouteClear(); diff --git a/src/shared/NSMoverEntity.qc b/src/shared/NSMoverEntity.qc index a5d2b0cc..24b78d05 100644 --- a/src/shared/NSMoverEntity.qc +++ b/src/shared/NSMoverEntity.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Vera Visions LLC. + * Copyright (c) 2023-2024 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 @@ -203,6 +203,9 @@ NSMoverEntity::GetMoverRotation2(void) void NSMoverEntity::MoveToPosition(vector vecDest, float flSpeed) { + if (vecDest == origin) + return; + MoveAndRotateToPosition(vecDest, GetAngles(), flSpeed); } @@ -240,7 +243,7 @@ NSMoverEntity::MoveAndRotateToPosition(vector vecDest, vector vecAngle, float fl /* abort if no speed is defined whatsoever */ if (!flSpeed) { - NSEntWarning("NSMoverEntity::MoveToPosition: No speed defined!"); + EntWarning("NSMoverEntity::MoveToPosition: No speed defined!"); return; } @@ -261,7 +264,6 @@ NSMoverEntity::MoveAndRotateToPosition(vector vecDest, vector vecAngle, float fl /* if we're already there, don't bother and trigger it right now. */ if (fTravelTime <= 0.0) { - if (m_moverState == MOVER_1TO2) { MoverStartsMoving(); _ArrivedAtRotPosition2(); @@ -379,4 +381,4 @@ NSMoverEntity::MoverStartsMoving(void) void NSMoverEntity::MoverFinishesMoving(void) { -} \ No newline at end of file +} diff --git a/src/shared/NSNavAI.h b/src/shared/NSNavAI.h index 787b3ff8..a9db8e30 100644 --- a/src/shared/NSNavAI.h +++ b/src/shared/NSNavAI.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 diff --git a/src/shared/NSNavAI.qc b/src/shared/NSNavAI.qc index 72d747ee..1b17656d 100644 --- a/src/shared/NSNavAI.qc +++ b/src/shared/NSNavAI.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -97,8 +97,7 @@ NSNavAI::CheckRoute_Path(void) /* close enough...? */ if (flDist < 80) { - NSNavAI_Log("^2%s::^3CheckRoute_Path^7: " \ - "reached path node %s", classname, m_pathTarget); + NSNavAI_Log("Reached path node %S", m_pathTarget); m_pathTarget = m_pathEntity.target; m_pathEntity = (NSEntity)m_pathEntity.GetTargetEntity(); @@ -127,12 +126,10 @@ NSNavAI::CheckRoute(void) /* HACK: for followers */ if (m_eFollowing) { RouteToPosition(m_eFollowing.origin); - NSNavAI_Log("^2%s::^3CheckRoute^7: " \ - "Giving up current route to follower, re-calculating", classname); + NSNavAI_Log("Giving up current route to follower, re-calculating"); } else { RouteToPosition(m_vecLastNode); - NSNavAI_Log("^2%s::^3CheckRoute^7: " \ - "Giving up current route, re-calculating", classname); + NSNavAI_Log("Giving up current route, re-calculating."); } } _m_flRouteGiveUp = time + 2.0f; @@ -156,8 +153,7 @@ NSNavAI::CheckRoute(void) flDist = floor(vlen(evenpos - origin)); if (flDist < flNodeRadius) { - NSNavAI_Log("^2%s::^3CheckRoute^7: " \ - "%s reached node", classname, targetname); + NSNavAI_Log("%S reached node", targetname); m_iCurNode--; velocity = [0,0,0]; /* clamp friction */ @@ -168,8 +164,7 @@ NSNavAI::CheckRoute(void) /* can we walk directly to our target destination? */ if (trace_fraction == 1.0) { - NSNavAI_Log("^2%s::^3CheckRoute^7: Walking directly to last node at '%v'", \ - classname, m_vecLastNode); + NSNavAI_Log("Walking directly to last node at '%v'", m_vecLastNode); m_iCurNode = -1; } } @@ -188,8 +183,7 @@ NSNavAI::CheckRoute(void) if (!trace_startsolid && trace_fraction == 1.0f) { evenpos = vecNextNode; m_iCurNode = iNextNode; - NSNavAI_Log("^2%s::^3CheckRoute^7: skipping to next node %i at '%v'", \ - classname, iNextNode, vecNextNode); + NSNavAI_Log("Skipping to next node %i at '%v'", iNextNode, vecNextNode); return; } } @@ -199,7 +193,7 @@ NSNavAI::CheckRoute(void) if (m_iCurNode < -1) { RouteClear(); RouteEnded(); - NSNavAI_Log("^2%s::^3CheckRoute^7: %s reached end", classname, targetname); + NSNavAI_Log("%S reached end", targetname); } /* crouch attempt */ @@ -304,12 +298,10 @@ NSNavAI::RouteToPositionDenyFlags(vector destination, int denylinkflags) /* can we walk directly to our target destination? */ if (trace_fraction == 1.0) { - NSNavAI_Log("^2%s::^3RouteToPosition^7: " \ - "Walking directly to last node", p.classname); + NSNavAI_Log("Walking directly to last node"); p.m_iCurNode = -1; } else { - NSNavAI_Log("^2%s::^3RouteToPosition^7: " \ - "Path obstructed, calculating route", p.classname); + NSNavAI_Log("Path obstructed, calculating route"); /* run through all nodes, mark the closest direct path possible */ for (int i = 0; i < p.m_iNodes; i++) { @@ -354,7 +346,7 @@ NSNavAI::ChasePath(string startPath) m_pathTarget = startPath; m_pathEntity = (NSEntity)find(world, ::targetname, m_pathTarget); - NSNavAI_Log("Actor %S chase Path set to %S\n", netname, m_pathEntity.targetname); + NSNavAI_Log("Actor %S chase Path set to %S", netname, m_pathEntity.targetname); } void diff --git a/src/shared/NSPhysicsConstraint.qc b/src/shared/NSPhysicsConstraint.qc index 93fee309..faa27a53 100644 --- a/src/shared/NSPhysicsConstraint.qc +++ b/src/shared/NSPhysicsConstraint.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Vera Visions LLC. + * Copyright (c) 2023-2024 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 @@ -328,7 +328,7 @@ NSPhysicsConstraint::Ballsocket(entity firstEnt, entity secondEnt, vector pos1, new.velocity = pos2; new.WakeTargets(); - print(sprintf("Created ballsocket between %s and %s\n", firstEnt.classname, secondEnt.classname)); + EntLog("Created ballsocket between %S and %S.", firstEnt.classname, secondEnt.classname); return new; } @@ -336,7 +336,7 @@ NSPhysicsConstraint NSPhysicsConstraint::Weld(entity firstEnt, entity secondEnt, float bone1, float bone2, float forceLimit, bool noCollide, bool deleteEnt1OnBreak) { if (firstEnt == secondEnt) { - print("^1Cannot weld the entity with itself!\n"); + EntError("Cannot weld the entity with itself!"); return __NULL__; } @@ -346,7 +346,7 @@ NSPhysicsConstraint::Weld(entity firstEnt, entity secondEnt, float bone1, float new.SetEntity2(secondEnt); new.WakeTargets(); - print(sprintf("Created weld between %s and %s\n", firstEnt.classname, secondEnt.classname)); + EntLog("Created weld between %S and %S.", firstEnt.classname, secondEnt.classname); return new; } @@ -361,7 +361,7 @@ NSPhysicsConstraint::Rope(entity firstEnt, entity secondEnt, vector pos1, vector new.velocity = pos2; new.WakeTargets(); - print(sprintf("Created rope between %s and %s\n", firstEnt.classname, secondEnt.classname)); + EntLog("Created rope between %S and %S", firstEnt.classname, secondEnt.classname); return new; } diff --git a/src/shared/NSPhysicsEntity.qc b/src/shared/NSPhysicsEntity.qc index c9f1fb65..ed5d5aab 100644 --- a/src/shared/NSPhysicsEntity.qc +++ b/src/shared/NSPhysicsEntity.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -502,7 +502,6 @@ NSPhysicsEntity::_TouchThink(void) if (NSPhysicsEntity_Contents(origin) & CONTENTBIT_WATER) { makevectors([0,0,0]); velocity[2] += m_flBuoyancyRatio; - print(sprintf("in water... applying %v\n", v_up * (GetMass() * m_flBuoyancyRatio))); } #endif @@ -688,7 +687,7 @@ NSPhysicsEntity::SpawnKey(string strKey, string strValue) vector NSPhysicsEntity::AlignAngles(vector from, vector to) { - NSEntWarning("Not implemented"); + EntWarning("Not implemented"); return angles; } @@ -762,7 +761,7 @@ NSPhysicsEntity::ApplyTorqueCenter(vector vecTorque) void NSPhysicsEntity::EnableDrag(bool setEnabled) { - NSEntWarning("Not implemented"); + EntWarning("Not implemented"); } void @@ -775,7 +774,7 @@ NSPhysicsEntity::EnableGravity(bool setEnabled) void NSPhysicsEntity::EnableMotion(bool setEnabled) { - NSEntWarning("Not implemented"); + EntWarning("Not implemented"); } float @@ -904,7 +903,7 @@ NSPhysicsEntity::IsPenetrating(void) void NSPhysicsEntity::SetAngleDragCoefficient(float setValue) { - NSEntWarning("Not implemented"); + EntWarning("Not implemented"); } void @@ -923,7 +922,7 @@ NSPhysicsEntity::SetDamping(float linearDamp, float angleDamp) void NSPhysicsEntity::SetDragCoefficient(float dragValue) { - NSEntWarning("Not implemented"); + EntWarning("Not implemented"); } void @@ -993,4 +992,4 @@ NSPhysicsEntity::Sleep(void) SetSolid(SOLID_BBOX); } m_iEnabled = FALSE; -} \ No newline at end of file +} diff --git a/src/shared/NSPointTrigger.qc b/src/shared/NSPointTrigger.qc index 784f9033..5d78a471 100644 --- a/src/shared/NSPointTrigger.qc +++ b/src/shared/NSPointTrigger.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 diff --git a/src/shared/NSPortal.h b/src/shared/NSPortal.h index d1c52a05..dd7dabce 100644 --- a/src/shared/NSPortal.h +++ b/src/shared/NSPortal.h @@ -28,7 +28,9 @@ typedef enumflags PORTALFL_CHANGED_TARG_ORIGIN_Z, PORTALFL_CHANGED_TARG_ANGLES_X, PORTALFL_CHANGED_TARG_ANGLES_Y, - PORTALFL_CHANGED_TARG_ANGLES_Z + PORTALFL_CHANGED_TARG_ANGLES_Z, + PORTALFL_CHANGED_ENABLED, + PORTALFL_CHANGED_MODELINDEX } nsportal_changed_t; class @@ -50,28 +52,40 @@ NSPortal:NSEntity virtual void EvaluateEntity(void); virtual float SendEntity(entity, float); + virtual void PortalWasClosed(void); + virtual void PortalWasOpened(void); + /** Sets the NSPortal ID. Only used to link portals together via PortalAutoLink. */ nonvirtual void SetPortalID(int); /** Will link this portal to another NSPortal. */ - nonvirtual bool PortalLinkTo(NSPortal); + nonvirtual bool PortalLinkTo(NSPortal, bool); /** Will link this portal to the youngest other NSPortal. */ - nonvirtual void PortalAutoLink(void); + nonvirtual void PortalAutoLink(bool); + /** Closes the portal, will not remove it from world. */ + nonvirtual void PortalClose(void); + /** Sets the model to use for the portal. */ + nonvirtual void SetPortalModel(string); #endif #ifdef CLIENT virtual void ReceiveEntity(float, float); + virtual float predraw(void); #endif private: NSPortal m_ePortalTarget; NSPortal m_ePortalTarget_net; - PREDICTED_VECTOR(m_vecTargetPos) - PREDICTED_VECTOR(m_vecTargetAngle) + NETWORKED_VECTOR(m_vecTargetPos) + NETWORKED_VECTOR(m_vecTargetAngle) + NETWORKED_BOOL(m_bEnabled) + NETWORKED_FLOAT(m_flPortalModel) vector m_vecPortalPos; vector m_vecPortalN; vector m_vecPortalS; vector m_vecPortalT; + bool m_bWasEnabled; + /** Will transport an entity from its position to the exit position. */ nonvirtual void TransportEntity(NSEntity); @@ -80,6 +94,7 @@ private: vector m_vecTargetN; vector m_vecTargetS; vector m_vecTargetT; + float m_flSize; #endif #ifdef SERVER @@ -98,7 +113,8 @@ private: } #endif -#define SOLID_PORTAL 21 +#define SOLID_PORTAL 21 -.float portalnum; -.float impulse; //used as the radius for the solid_portal csg subtraction \ No newline at end of file +.float portalnum; +.float impulse; //used as the radius for the solid_portal csg subtraction +.bool isPortal; \ No newline at end of file diff --git a/src/shared/NSPortal.qc b/src/shared/NSPortal.qc index c7ee4c62..1eff1d74 100644 --- a/src/shared/NSPortal.qc +++ b/src/shared/NSPortal.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Vera Visions LLC. + * Copyright (c) 2024 Vera Visions LLC. * Copyright (c) 2014 David Walton * * Permission to use, copy, modify, and distribute this software for any @@ -30,6 +30,8 @@ NSPortal::NSPortal(void) m_vecPortalS = g_vec_null; m_vecPortalT = g_vec_null; m_brushNum = -1; + m_bEnabled = false; + isPortal = true; #ifdef CLIENT m_vecTargetPos = g_vec_null; @@ -47,10 +49,14 @@ NSPortal::NSPortal(void) /* unique portal IDs */ { float numPortals = 0; - for (NSPortal e = __NULL__; (e = (NSPortal)find(e, ::classname, "NSPortal"));) { + for (NSPortal e = __NULL__; (e = (NSPortal)findfloat(e, ::isPortal, true));) { e.portalnum = numPortals++; } } + + /* default fallback */ + precache_model("models/b_portal.bsp"); + SetPortalModel("models/b_portal.bsp"); #endif } @@ -104,7 +110,7 @@ NSPortal::Restore(string strKey, string strValue) } void -NSPortal::PortalAutoLink(void) +NSPortal::PortalAutoLink(bool openPortal) { /* this just links against the youngest portal of the same ID at this time */ NSPortal youngestPortal, oldestPortal; @@ -113,7 +119,7 @@ NSPortal::PortalAutoLink(void) float oldestTime = 0.0f; /* delete any portal with the same id */ - for (NSPortal e = __NULL__; (e = (NSPortal)find(e, ::classname, "NSPortal"));) { + for (NSPortal e = __NULL__; (e = (NSPortal)findfloat(e, ::isPortal, true));) { if (e == this) continue; @@ -132,24 +138,43 @@ NSPortal::PortalAutoLink(void) /* remove the first portal from the world */ if (youngestPortal != oldestPortal) { - oldestPortal.Destroy(); + oldestPortal.PortalClose(); } - PortalLinkTo(youngestPortal); + PortalLinkTo(youngestPortal, openPortal); +} + +void +NSPortal::PortalClose(void) +{ + /* invalidate the other portal's reference to this one, only + if we're still actively linked. */ + if (m_ePortalTarget && m_ePortalTarget.m_ePortalTarget == this) { + m_ePortalTarget.m_bEnabled = false; + m_ePortalTarget.m_ePortalTarget = __NULL__; + m_ePortalTarget._PortalUpdated(); + } + + /* now kill our own reference */ + m_ePortalTarget = __NULL__; + m_bEnabled = false; + _PortalUpdated(); } bool -NSPortal::PortalLinkTo(NSPortal target) +NSPortal::PortalLinkTo(NSPortal target, bool openPortal) { m_ePortalTarget = target; - skin = m_ePortalTarget ? 0 : 1; - SendFlags |= 1; + + m_bEnabled = openPortal; + + SendFlags = -1; _PortalUpdated(); if (m_ePortalTarget) { m_ePortalTarget.m_ePortalTarget = this; - m_ePortalTarget.skin = skin; - m_ePortalTarget.SendFlags |= 1; + m_ePortalTarget.m_bEnabled = openPortal; + m_ePortalTarget.SendFlags = -1; m_ePortalTarget._PortalUpdated(); } @@ -161,6 +186,22 @@ NSPortal::SetPortalID(int value) { m_iPortalValue = value; } + +void +NSPortal::SetPortalModel(string modelPath) +{ + m_flPortalModel = getmodelindex(modelPath); +} + +void +NSPortal::PortalWasOpened(void) +{ +} + +void +NSPortal::PortalWasClosed(void) +{ +} #endif void @@ -179,9 +220,29 @@ NSPortal::_PortalUpdated(void) /* expand the size of the object along the plane, and set up a portal region. */ movetype = MOVETYPE_NONE; - solid = skin ? SOLID_BSP : SOLID_PORTAL; - precache_model("models/b_portal.bsp"); - setmodel(this, "models/b_portal.bsp"); + + if (m_bEnabled == true) { + solid = SOLID_PORTAL; + setmodel(this, modelnameforindex(m_flPortalModel)); + if (m_bWasEnabled == false) { + m_bWasEnabled = true; +#ifdef SERVER + PortalWasOpened(); +#endif +#ifdef CLIENT + m_flSize = 0.0f; +#endif + } + } else { + if (m_bWasEnabled == true) { + m_bWasEnabled = false; +#ifdef SERVER + PortalWasClosed(); +#endif + } + solid = SOLID_BSP; + //modelindex = 0; + } /* determine size of major axis */ float portalSize = max(size[0], size[1], size[2]); @@ -374,6 +435,8 @@ NSPortal::EvaluateEntity(void) EVALUATE_VECTOR(m_vecTargetAngle, 0, PORTALFL_CHANGED_TARG_ANGLES_X) EVALUATE_VECTOR(m_vecTargetAngle, 1, PORTALFL_CHANGED_TARG_ANGLES_Y) EVALUATE_VECTOR(m_vecTargetAngle, 2, PORTALFL_CHANGED_TARG_ANGLES_Z) + EVALUATE_FIELD(m_bEnabled, PORTALFL_CHANGED_ENABLED) + EVALUATE_FIELD(m_flPortalModel, PORTALFL_CHANGED_MODELINDEX) } float @@ -399,6 +462,9 @@ NSPortal::SendEntity(entity ePEnt, float flChanged) SENDENTITY_FLOAT(m_vecTargetAngle[2], PORTALFL_CHANGED_TARG_ANGLES_Z) } + SENDENTITY_BYTE(m_bEnabled, PORTALFL_CHANGED_ENABLED) + SENDENTITY_FLOAT(m_flPortalModel, PORTALFL_CHANGED_MODELINDEX) + return (true); } #endif @@ -427,13 +493,15 @@ NSPortal::ReceiveEntity(float flNew, float flChanged) READENTITY_FLOAT(m_vecTargetAngle[1], PORTALFL_CHANGED_TARG_ANGLES_Y) READENTITY_FLOAT(m_vecTargetAngle[2], PORTALFL_CHANGED_TARG_ANGLES_Z) + READENTITY_BYTE(m_bEnabled, PORTALFL_CHANGED_ENABLED) + READENTITY_FLOAT(m_flPortalModel, PORTALFL_CHANGED_MODELINDEX) + if (m_ePortalTarget) { if (m_ePortalTarget.m_ePortalTarget) m_ePortalTarget.m_ePortalTarget.m_ePortalTarget = __NULL__; m_ePortalTarget. m_ePortalTarget = this; } else { - skin = 1; makevectors(angles); m_vecTargetPos = origin; m_vecTargetN = v_forward; @@ -443,6 +511,21 @@ NSPortal::ReceiveEntity(float flNew, float flChanged) _PortalUpdated(); drawmask = MASK_ENGINE; - predraw = 0; +// predraw = 0; } -#endif \ No newline at end of file + +float +NSPortal::predraw(void) +{ + scale = m_flSize; + + addentity(this); + + m_flSize += frametime * 10.0f; + + if (m_flSize > 1.0) + m_flSize = 1.0f; + + return PREDRAW_NEXT; +} +#endif diff --git a/src/shared/NSProjectile.h b/src/shared/NSProjectile.h index 3bccc97d..cc61d965 100644 --- a/src/shared/NSProjectile.h +++ b/src/shared/NSProjectile.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -171,4 +171,4 @@ public: NSProjectile NSProjectile_SpawnDef(string entityDef, NSEntity theOwner); NSProjectile NSProjectile_SpawnDefAtPosition(string entityDef, NSEntity theOwner, vector vecOrigin, vector vecAngles); NSProjectile NSProjectile_SpawnDefAttachment(string entityDef, NSEntity theOwner, int attachmentID); -#endif \ No newline at end of file +#endif diff --git a/src/shared/NSProjectile.qc b/src/shared/NSProjectile.qc index 745d3b4c..6bb217bd 100644 --- a/src/shared/NSProjectile.qc +++ b/src/shared/NSProjectile.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -190,7 +190,7 @@ NSProjectile::SpawnKey(string strKey, string strValue) case "explode_light_color": m_vecExplodeLightColor = ReadVector(strValue); break; - case "explode_light_radus": + case "explode_light_radius": m_fExplodelLightRadius = ReadFloat(strValue); break; case "explode_light_fadetime": @@ -976,4 +976,4 @@ NSProjectile_SpawnDefAttachment(string entityDef, NSEntity theOwner, int attachm rocket.Launch(attachmentPos, theOwner.GetAngles(), 0.0f, 0.0f, 0.0f); return rocket; } -#endif \ No newline at end of file +#endif diff --git a/src/shared/NSRenderableEntity.qc b/src/shared/NSRenderableEntity.qc index 7e6987ba..7704d292 100644 --- a/src/shared/NSRenderableEntity.qc +++ b/src/shared/NSRenderableEntity.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -985,11 +985,10 @@ NSRenderableEntity::HandleAnimEvent(float flTimeStamp, int iCode, string strData case 1003: /* trigger SSQC entity with specific targetname */ for (entity f = world; (f = find(f, ::targetname, strData));) { NSEntity trigger = (NSEntity)f; + if (trigger.Trigger != __NULL__) { trigger.Trigger(this, TRIG_TOGGLE); - NSLog("^2%s^7::^3ModelEvent^7: " \ - "Calling trigger '%s'\n", - classname, strData); + EntLog("Calling trigger '%s'", strData); } } break; @@ -1017,9 +1016,9 @@ NSRenderableEntity::HandleAnimEvent(float flTimeStamp, int iCode, string strData } //print(sprintf("Received: %f %i %S\n", flTimeStamp, iCode, strData)); - NSLog("SSQC model event: %f %i %S", flTimeStamp, iCode, strData); + EntWarning("Unknown server model event: %f %i %S", flTimeStamp, iCode, strData); #else - NSLog("CSQC model event: %f %i %S", flTimeStamp, iCode, strData); + EntWarning("Unknown client model event: %f %i %S", flTimeStamp, iCode, strData); #endif } } @@ -1110,6 +1109,9 @@ NSRenderableEntity::Input(entity eAct, string strInput, string strData) case "Alpha": SetRenderAmt(stof(strData) / 255); break; + case "Skin": + SetSkin(stof(strData)); + break; case "DisableShadow": effects |= EF_NOSHADOW; break; @@ -1119,7 +1121,7 @@ NSRenderableEntity::Input(entity eAct, string strInput, string strData) case "SetAnimation": float animFrame = frameforname(modelindex, strcat("@", strData)); SetFrame(animFrame); - print(sprintf("SetAnimation: %S (%d) on %S\n",strData, animFrame, model)); + //print(sprintf("SetAnimation: %S (%d) on %S\n",strData, animFrame, model)); break; case "SetBodyInGroup": int argC = tokenize(strData); @@ -1206,4 +1208,4 @@ NSRenderableEntity::SpawnKey(string strKey, string strValue) super::SpawnKey(strKey, strValue); break; } -} \ No newline at end of file +} diff --git a/src/shared/NSSpraylogo.qc b/src/shared/NSSpraylogo.qc index 75a9fb4e..f81a0a41 100644 --- a/src/shared/NSSpraylogo.qc +++ b/src/shared/NSSpraylogo.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 diff --git a/src/shared/NSSquadMonster.qc b/src/shared/NSSquadMonster.qc index 3a8594f2..d4267b5d 100644 --- a/src/shared/NSSquadMonster.qc +++ b/src/shared/NSSquadMonster.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Vera Visions LLC. + * Copyright (c) 2023-2024 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 @@ -185,7 +185,7 @@ NSSquadMonster::AddToSquad(NSSquadMonster addMember) m_eSquadLeader = this; startMember = this; m_inSquad = true; - NSMonster_Log("%s (%d) became squad leader\n", classname, num_for_edict(this)); + NSMonsterLog("%s (%d) became squad leader\n", classname, num_for_edict(this)); //SetBody(GetBody() | m_iSquadLeaderBody); /* apply the squad leader body */ @@ -211,7 +211,7 @@ NSSquadMonster::AddToSquad(NSSquadMonster addMember) addMember.m_eSquadLeader = startMember; addMember.m_inSquad = true; addMember.HasJoinedSquad(); - NSMonster_Log("%s (%d) added to squad, member %i\n", classname, num_for_edict(this), i); + NSMonsterLog("%s (%d) added to squad, member %i\n", classname, num_for_edict(this), i); return; } } @@ -315,4 +315,4 @@ NSSquadMonster::GetFarthestSquadMember(void) return farthestMember; } -#endif \ No newline at end of file +#endif diff --git a/src/shared/NSSurfacePropEntity.h b/src/shared/NSSurfacePropEntity.h index 2660d013..0f858d21 100644 --- a/src/shared/NSSurfacePropEntity.h +++ b/src/shared/NSSurfacePropEntity.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -124,6 +124,16 @@ public: /** Returns how many seconds have passed since we died. Will return -1 if not applicable. */ nonvirtual float TimeSinceDeath(void); + /** Called when a different entity gets damaged by this entity. */ + virtual void DamageFeedback(NSSurfacePropEntity, NSSurfacePropEntity, int); + + /** Sets which function to call upon taking pain. */ + nonvirtual void SetPainCallback(void(void)); + /** Sets which function to call upon taking death. */ + nonvirtual void SetDeathCallback(void(void)); + /** Returns whether this entity reacts to damage being inflicted. */ + nonvirtual bool CanBeDamaged(void); + /** Sets the colour of the blood of this entity. */ nonvirtual void SetBloodColor(vector); /** Returns the blood color of this entity. */ @@ -179,4 +189,4 @@ private: #ifdef CLIENT void NSSurfacePropEntity_ReadEntity(bool); -#endif \ No newline at end of file +#endif diff --git a/src/shared/NSSurfacePropEntity.qc b/src/shared/NSSurfacePropEntity.qc index 2f2c851a..e69bf17f 100644 --- a/src/shared/NSSurfacePropEntity.qc +++ b/src/shared/NSSurfacePropEntity.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -37,16 +37,17 @@ NSSurfacePropEntity::NSSurfacePropEntity(void) vector NSSurfacePropEntity::GetEyePos(void) { - if (HasFlags(FL_FAKESPEC)) - return origin; + if (HasFlags(FL_FAKESPEC)) { + return (origin); + } - return origin + view_ofs; + return (origin + view_ofs); } vector NSSurfacePropEntity::GetViewAngle(void) { - return v_angle; + return (v_angle); } void @@ -82,7 +83,7 @@ NSSurfacePropEntity::SetBloodColor(vector newColor) vector NSSurfacePropEntity::GetBloodColor(void) { - return m_vecBloodColor; + return (m_vecBloodColor); } bool @@ -100,7 +101,7 @@ NSSurfacePropEntity::SetCanBleed(bool bleedValue) bool NSSurfacePropEntity::CanBleed(void) { - return iBleeds; + return (iBleeds); } void @@ -129,17 +130,17 @@ NSSurfacePropEntity::SetMaxHealth(float new_health) float NSSurfacePropEntity::GetHealth(void) { - return health; + return (health); } float NSSurfacePropEntity::GetMaxHealth(void) { - return max_health; + return (max_health); } float NSSurfacePropEntity::GetSpawnHealth(void) { - return m_oldHealth; + return (m_oldHealth); } void @@ -150,7 +151,7 @@ NSSurfacePropEntity::SetArmor(float new_armor) float NSSurfacePropEntity::GetArmor(void) { - return armor; + return (armor); } bool @@ -264,96 +265,97 @@ NSSurfacePropEntity::Save(float handle) } void -NSSurfacePropEntity::Restore(string strKey, string strValue) +NSSurfacePropEntity::Restore(string keyName, string savedValue) { - switch (strKey) { + switch (keyName) { case "m_flBurnNext": - m_flBurnNext = ReadFloat(strValue); + m_flBurnNext = ReadFloat(savedValue); break; case "armor": - armor = ReadFloat(strValue); + armor = ReadFloat(savedValue); break; case "health": - health = ReadFloat(strValue); + health = ReadFloat(savedValue); break; case "m_eBurner": - m_eBurner = edict_num(ReadFloat(strValue)); + m_eBurner = edict_num(ReadFloat(savedValue)); break; case "m_iBurnWeapon": - m_iBurnWeapon = ReadInt(strValue); + m_iBurnWeapon = ReadInt(savedValue); break; case "m_flBurnTime": - m_flBurnTime = ReadFloat(strValue); + m_flBurnTime = ReadFloat(savedValue); break; case "m_flBurnDmgTime": - m_flBurnDmgTime = ReadFloat(strValue); + m_flBurnDmgTime = ReadFloat(savedValue); break; case "m_strOnBreak": - m_strOnBreak = ReadString(strValue); + m_strOnBreak = ReadString(savedValue); break; case "m_oldHealth": - m_oldHealth = ReadFloat(strValue); + m_oldHealth = ReadFloat(savedValue); break; case "m_vecBloodColor": - m_vecBloodColor = ReadVector(strValue); + m_vecBloodColor = ReadVector(savedValue); break; case "m_iMaterial": - m_iMaterial = ReadInt(strValue); + m_iMaterial = ReadInt(savedValue); break; case "m_iPropData": - m_iPropData = ReadInt(strValue); + m_iPropData = ReadInt(savedValue); break; case "m_flDeathTime": - m_flDeathTime = ReadFloat(strValue); + m_flDeathTime = ReadFloat(savedValue); break; default: - super::Restore(strKey, strValue); + super::Restore(keyName, savedValue); } } void -NSSurfacePropEntity::Input(entity eAct, string strInput, string strData) +NSSurfacePropEntity::Input(entity entityActivator, string inputName, string dataField) { - switch (strInput) { + switch (inputName) { case "Ignite": - Ignite(eAct, 5000, 0); + Ignite(entityActivator, 5000, 0); break; case "IgniteLifetime": - Ignite(eAct, stof(strData), 0); + float lifeTime = stof(dataField); + Ignite(entityActivator, lifeTime, 0); break; case "Extinguish": Extinguish(); break; default: - super::Input(eAct, strInput, strData); + super::Input(entityActivator, inputName, dataField); } } void -NSSurfacePropEntity::SpawnKey(string strKey, string strValue) +NSSurfacePropEntity::SpawnKey(string keyName, string setValue) { - switch (strKey) { + switch (keyName) { case "health": - max_health = health = ReadFloat(strValue); + max_health = health = ReadFloat(setValue); m_oldHealth = health; break; case "propdata": - m_strPropData = ReadString(strValue); + m_strPropData = ReadString(setValue); break; case "surfdata": case "materialdata": - m_strSurfData = ReadString(strValue); + m_strSurfData = ReadString(setValue); break; /* entityDef */ case "blood_color": - m_vecBloodColor = ReadVector(strValue); + m_vecBloodColor = ReadVector(setValue); break; /* Input/Output system */ case "OnBreak": - m_strOnBreak = PrepareOutput(m_strOnBreak, ReadString(strValue)); + m_strOnBreak = PrepareOutput(m_strOnBreak, ReadString(setValue)); break; default: - super::SpawnKey(strKey, strValue); + super::SpawnKey(keyName, setValue); break; } } @@ -361,7 +363,13 @@ NSSurfacePropEntity::SpawnKey(string strKey, string strValue) void NSSurfacePropEntity::Pain(void) { - + /* implemented in sub-class */ +} + +void +NSSurfacePropEntity::DamageFeedback(NSSurfacePropEntity theVictim, NSSurfacePropEntity theInflictor, int desiredDamage) +{ + /* implemented in sub-class */ } void @@ -371,8 +379,9 @@ NSSurfacePropEntity::Death(void) UseOutput(g_dmg_eAttacker, m_strOnBreak); - if (HasPropData() == false) + if (HasPropData() == false) { return; + } if (GetPropData(PROPINFO_SKIN) != 0) { SetSkin(GetPropData(PROPINFO_SKIN)); @@ -406,6 +415,7 @@ NSSurfacePropEntity::SetSurfaceData(string type) m_strSurfData = type; _SurfaceDataFinish(); } + void NSSurfacePropEntity::SetPropData(string type) { @@ -423,6 +433,7 @@ NSSurfacePropEntity::_SurfaceDataFinish(void) else m_iMaterial = -1; } + void NSSurfacePropEntity::_PropDataFinish(void) { @@ -438,9 +449,27 @@ float NSSurfacePropEntity::TimeSinceDeath(void) { if (IsAlive()) - return -1; + return (-1); - return time - m_flDeathTime; + return (time - m_flDeathTime); +} + +void +NSSurfacePropEntity::SetPainCallback(void(void) painFunc) +{ + Pain = painFunc; +} + +void +NSSurfacePropEntity::SetDeathCallback(void(void) deathFunc) +{ + Death = deathFunc; +} + +bool +NSSurfacePropEntity::CanBeDamaged(void) +{ + return (takedamage == DAMAGE_NO) ? false : true; } void @@ -602,10 +631,13 @@ NSSurfacePropEntity::ReceiveEntity(float flNew, float flChanged) if (scale == 0.0) scale = 1.0f; - if (flChanged & SRFENT_CHANGED_SIZE) + if (flChanged & SRFENT_CHANGED_SIZE) { setsize(this, mins * scale, maxs * scale); - if (flChanged & SRFENT_CHANGED_BODY) + } + + if (flChanged & SRFENT_CHANGED_BODY) { setcustomskin(this, "", sprintf("geomset 0 %i\ngeomset 1 %i\n", m_iBody, m_iBody)); + } } void @@ -626,20 +658,27 @@ NSSurfacePropEntity::RenderFire(void) float NSSurfacePropEntity::predraw(void) { - RenderFire(); - return super::predraw(); + float returnValue = super::predraw(); + + if (returnValue) { + RenderFire(); + } + + return returnValue; } void -NSSurfacePropEntity_ReadEntity(bool new) +NSSurfacePropEntity_ReadEntity(bool isNew) { - float fl; - NSSurfacePropEntity rend = (NSSurfacePropEntity)self; - if (new) { + float networkFlags; + NSSurfacePropEntity rendEnt = (NSSurfacePropEntity)self; + + if (isNew) { spawnfunc_NSSurfacePropEntity(); } - fl = readfloat(); - rend.ReceiveEntity(new, fl); + + networkFlags = readfloat(); + rendEnt.ReceiveEntity(isNew, networkFlags); } #endif @@ -653,4 +692,4 @@ NSSurfacePropEntity::SetModel(string newModel) m_iPropData = PropData_ForModel(model); } #endif -} \ No newline at end of file +} diff --git a/src/shared/NSTalkMonster.qc b/src/shared/NSTalkMonster.qc index 937031d9..c7919c2e 100644 --- a/src/shared/NSTalkMonster.qc +++ b/src/shared/NSTalkMonster.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -288,6 +288,8 @@ NSTalkMonster::Sentence(string sentence) WriteInt(MSG_MULTICAST, Sentences_GetID(seq)); msg_entity = this; multicast(origin, MULTICAST_PVS); + + SndEntLog("Attempting to say %S", seq); } void @@ -576,7 +578,7 @@ NSTalkMonster::FollowPlayer(void) /* Give up after 1024 units */ if (flPlayerDist > m_flMaxFollowDistance) { m_eFollowing = world; - NSMonster_Log("Maximum follow distance reached. Will stop following."); + NSMonsterLog("Maximum follow distance reached. Will stop following."); } else if (flPlayerDist >= m_flFollowDistance) { /* we only allow speed changes every second, avoid jitter */ if (m_flFollowSpeedChanged < time) { @@ -958,7 +960,7 @@ NSTalkMonster::ProcessWordQue(void) SentenceSample(m_pSentenceQue[m_iSentencePos].m_strSnd); - NSMonster_Log("^2NSEntity::^3ProcessWordQue^7: Speaking %s", m_pSentenceQue[m_iSentencePos].m_strSnd); + NSMonsterLog("Speaking sentence sample %S", m_pSentenceQue[m_iSentencePos].m_strSnd); m_iSentencePos++; if (m_iSentencePos == m_iSentenceCount) { @@ -1008,6 +1010,9 @@ NSTalkMonster::Sentence(string msg) m_pSentenceQue[i].m_flPitch = 100; } m_flSentenceTime = time; + + + SndEntLog("Saying %S", msg); } float @@ -1146,15 +1151,14 @@ NSTalkMonster_ParseSentence(void) ent = findfloat(world, entnum, e); if (ent) { - if (ent.classname != "speaker" && ent.classname != "NSTalkMonster" && ent.classname != "ambient_generic") - NSMonster_Log("^3 NSTalkMonster_ParseSentence ^7: Entity %d not a NSTalkMonster!", e); - else { + if (ent.classname != "speaker" && ent.classname != "NSTalkMonster" && ent.classname != "ambient_generic") { + NSError("Entity %d not a NSTalkMonster!", e); + } else { targ = (NSTalkMonster)ent; targ.Sentence(sentence); - NSMonster_Log("^3 NSTalkMonster_ParseSentence ^7: Entity %d saying %s", e, sentence); } } else { - NSMonster_Log("^3 NSTalkMonster_ParseSentence ^7: Entity %d not in PVS", e); + NSError("Entity %d not in PVS", e); } } #endif diff --git a/src/shared/NSTimer.qc b/src/shared/NSTimer.qc index 4049b1b8..19511710 100644 --- a/src/shared/NSTimer.qc +++ b/src/shared/NSTimer.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Vera Visions LLC. + * Copyright (c) 2022-2024 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 @@ -180,4 +180,4 @@ NSTimer::Restore(string strKey, string strValue) break; } } -#endif \ No newline at end of file +#endif diff --git a/src/shared/NSTrigger.h b/src/shared/NSTrigger.h index b1cb7058..6fbc2309 100644 --- a/src/shared/NSTrigger.h +++ b/src/shared/NSTrigger.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -92,6 +92,7 @@ public: /* overrides */ virtual void Save(float); virtual void Restore(string,string); + virtual void Respawn(void); virtual void Input(entity,string,string); /* Called to check if the target entity can touch trigger itself. */ @@ -169,4 +170,4 @@ private: #ifdef CLIENT float team; #endif -}; \ No newline at end of file +}; diff --git a/src/shared/NSTrigger.qc b/src/shared/NSTrigger.qc index 054f1596..b9f970aa 100644 --- a/src/shared/NSTrigger.qc +++ b/src/shared/NSTrigger.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -37,6 +37,12 @@ NSTrigger::NSTrigger(void) } #ifdef SERVER +void +NSTrigger::Respawn(void) +{ + super::Respawn(); + SetTriggerTarget( m_oldstrTarget ); +} bool NSTrigger::CanBeTriggeredBy(entity testEnt) @@ -78,34 +84,27 @@ NSTrigger::CanBeTriggeredBy(entity testEnt) void NSTrigger::Trigger(entity act, triggermode_t state) { - NSLog("^2%s::^3Trigger^7: Triggered by %s with no consequence", - classname, act.classname); + EntWarning("Triggered by %S with no consequence", act.classname); } void -NSTrigger::UseTargets(entity act, int state, float fDelay) +NSTrigger::UseTargets(entity act, int state, float triggerDelay) { static void Entities_UseTargets_Think(void) { NSTrigger::UseTargets(self.owner, self.health, 0.0f); remove(self); } - if not (target) + if (!m_strKillTarget && !target) return; - if not (m_strKillTarget) - if not (target) - return; - - if (fDelay > 0.0f) { - NSLog("^2%s::^3UseTargets^7: Triggering `%s`", - classname, target); - + if (triggerDelay > 0.0f) { + EntLog("Scheduling trigger of %S in %f seconds.", target, triggerDelay); NSTrigger eTimer = spawn(NSTrigger); eTimer.owner = act; eTimer.think = Entities_UseTargets_Think; eTimer.target = target; - eTimer.nextthink = time + fDelay; + eTimer.nextthink = time + triggerDelay; eTimer.health = state; /* ugly */ } else { if (m_strMessage) { @@ -115,10 +114,9 @@ NSTrigger::UseTargets(entity act, int state, float fDelay) for (entity f = world; (f = find(f, ::targetname, target));) { NSTrigger trigger = (NSTrigger)f; - NSLog("^2%s::^3UseTargets^7:" \ - "Triggering %s `%s` from %s", \ - classname, f.classname, \ - trigger.targetname, act.classname); + EntLog("Triggering %s %S, activator %S (%d)", \ + f.classname, trigger.targetname, \ + act.classname, num_for_edict(act)); if (trigger.Trigger != __NULL__) { trigger.Trigger(act, state); @@ -127,8 +125,8 @@ NSTrigger::UseTargets(entity act, int state, float fDelay) if (m_strKillTarget && m_strKillTarget != "") { NSEntity eKill = (NSEntity)find(world, ::targetname, m_strKillTarget); - NSLog("^2%s::^3UseTargets^7: Killing `%s`", - classname, m_strKillTarget); + EntLog("Killtargeting %S", m_strKillTarget); + if (eKill) { eKill.Destroy(); } @@ -175,18 +173,20 @@ NSTrigger::GetMaster(entity queryingEntity) /* we couldn't find it, so let's not even bother going further */ if (!t) { - NSLog("^2%s::^3GetMaster^7: Invalid master (%s), return success", - classname, m_strMaster); + /*NSLog("^2%s::^3GetMaster^7: Invalid master (%s), return success", + classname, m_strMaster);*/ return (1); } +/* if (t.GetValue(queryingEntity) == 1) NSLog("^2%s::^3GetMaster^7: %s learns %s ^2POSITIVE", classname, targetname, m_strMaster); else NSLog("^2%s::^3GetMaster^7: %s learns %s ^1NEGATIVE", classname, targetname, m_strMaster); - +*/ + return t.GetValue(queryingEntity); } diff --git a/src/shared/NSVehicle.h b/src/shared/NSVehicle.h index f7d7a1a0..2347f599 100644 --- a/src/shared/NSVehicle.h +++ b/src/shared/NSVehicle.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -16,12 +16,14 @@ var bool autocvar_vehicle_developer = false; void -_NSVehicle_Log(string msg) +_NSVehicle_Log(string className, string functionName, float edictNum, string warnMessage) { - if (autocvar_vehicle_developer == true) - print(sprintf("%f %s\n", time, msg)); + if (autocvar_g_developerTimestamps) + printf("^9%f ^2%s (%d) ^7: %s\n", time, functionName, edictNum, warnMessage); + else + printf("^2%s (%d) ^7: %s\n", functionName, edictNum, warnMessage); } -#define NSVehicle_Log(...) _NSVehicle_Log(sprintf(__VA_ARGS__)) +#define NSVehicle_Log(...) if (autocvar_vehicle_developer == true) _NSVehicle_Log(classname, __FUNC__, num_for_edict(this), sprintf(__VA_ARGS__)) /** This entity class represents vehicles that are predicted across the network. */ class NSVehicle:NSSurfacePropEntity diff --git a/src/shared/NSVehicle.qc b/src/shared/NSVehicle.qc index 63cac0a3..72879bfa 100644 --- a/src/shared/NSVehicle.qc +++ b/src/shared/NSVehicle.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -446,6 +446,7 @@ NSVehicle::PlayerEnter(NSClientPlayer pl) m_eDriverLast = m_eDriver; pl.vehicle = this; pl.flags |= FL_INVEHICLE; + EntLog("Player %S entered this vehicle.", pl.GetInfoKey("name")); } void @@ -454,6 +455,8 @@ NSVehicle::PlayerLeave(NSClientPlayer pl) if (!pl) return; + EntLog("Player %S exits this vehicle.", pl.GetInfoKey("name")); + owner = __NULL__; pl.flags &= ~FL_INVEHICLE; pl.velocity = g_vec_null; diff --git a/src/shared/cloader.h b/src/shared/cloader.h index e53b54fd..23436711 100644 --- a/src/shared/cloader.h +++ b/src/shared/cloader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Vera Visions LLC. + * Copyright (c) 2023-2024 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 @@ -13,43 +13,43 @@ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -/*! @file cloader.h - @brief Constants macro loader - -Scripters and level designers are able to define parameters through the use -of name-based lookups, so they can change them later in one convenient place. - -In the game directory, they are defined within `scripts/constants.txt`. -An example file looks like this: - -``` -// weapon constants -WEAPON_NONE 0 -WEAPON_KNIFE 1 -WEAPON_POTATO 2 -``` - -Within [EntityDefs](Documentation/EntityDef.md) files, you will then be able to set a given key to the value -of one of the defined constants by prefixing the name with a `$` symbol. -That would look something like this: - -``` -"weapon" "$WEAPON_POTATO" -``` - -The same applies to data read within level files and most routines related to parsing key/value pairs, so it is not limited to usage within EntityDef. -*/ - -/** Called upon game init internally to populate our look-up table. -*/ -void Constants_Init(void); - -/** Look up a name and retrieve its value. - -@param constName Name of the constant to look up. -@param returnValue The value to return if constName is not defined. -@return The value of the named constant. Will return returnValue if it does not exist. */ -string Constants_LookUp(string constName, string returnValue); - -var hashtable g_hashConstants; \ No newline at end of file + +/*! @file cloader.h + @brief Constants macro loader + +Scripters and level designers are able to define parameters through the use +of name-based lookups, so they can change them later in one convenient place. + +In the game directory, they are defined within `scripts/constants.txt`. +An example file looks like this: + +``` +// weapon constants +WEAPON_NONE 0 +WEAPON_KNIFE 1 +WEAPON_POTATO 2 +``` + +Within [EntityDefs](Documentation/EntityDef.md) files, you will then be able to set a given key to the value +of one of the defined constants by prefixing the name with a `$` symbol. +That would look something like this: + +``` +"weapon" "$WEAPON_POTATO" +``` + +The same applies to data read within level files and most routines related to parsing key/value pairs, so it is not limited to usage within EntityDef. +*/ + +/** Called upon game init internally to populate our look-up table. +*/ +void Constants_Init(void); + +/** Look up a name and retrieve its value. + +@param constName Name of the constant to look up. +@param returnValue The value to return if constName is not defined. +@return The value of the named constant. Will return returnValue if it does not exist. */ +string Constants_LookUp(string constName, string returnValue); + +var hashtable g_hashConstants; diff --git a/src/shared/cloader.qc b/src/shared/cloader.qc index 93be55d3..dbdc0643 100644 --- a/src/shared/cloader.qc +++ b/src/shared/cloader.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Vera Visions LLC. + * Copyright (c) 2023-2024 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 @@ -13,59 +13,65 @@ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef MAX_CONSTANTS_ID +#define MAX_CONSTANTS_ID 128 +#endif + +string g_constIndex[MAX_CONSTANTS_ID]; + +void +Constants_Init(void) +{ + filestream constFile; + string tempString; + int arguments = 0i; + int indexCount = 0i; -#ifndef MAX_CONSTANTS_ID -#define MAX_CONSTANTS_ID 128 -#endif + InitStart(); + + if (!g_hashConstants) { + g_hashConstants = hash_createtab(2, HASH_ADD); + } + + constFile = fopen("scripts/constants.txt", FILE_READ); + + if (constFile < 0) { + NSError("Missing file scripts/constants.txt"); + InitEnd(); + return; + } + + while ((tempString = fgets(constFile))) { + arguments = (int)tokenize_console(tempString); + + if (arguments != 2) { + continue; + } + + /* sanity bounds check */ + if (indexCount == MAX_CONSTANTS_ID) { + NSError("Hit maximum number of %d constants.", MAX_CONSTANTS_ID); + InitEnd(); + return; + } + + g_constIndex[indexCount] = argv(1); + hash_add(g_hashConstants, argv(0), indexCount); + indexCount++; + } -string g_constIndex[MAX_CONSTANTS_ID]; - -void -Constants_Init(void) -{ - filestream constFile; - string tempString; - int arguments = 0i; - int indexCount = 0i; - - if (!g_hashConstants) { - g_hashConstants = hash_createtab(2, HASH_ADD); - } - - constFile = fopen("scripts/constants.txt", FILE_READ); - - if (constFile < 0) { - print("Unable to load scripts/constants.txt"); - return; - } - - while ((tempString = fgets(constFile))) { - arguments = (int)tokenize_console(tempString); - - if (arguments != 2) { - continue; - } - - /* sanity bounds check */ - if (indexCount == MAX_CONSTANTS_ID) { - print("Constants_Init: Hit maximum number of constants.\n"); - return; - } - - g_constIndex[indexCount] = argv(1); - hash_add(g_hashConstants, argv(0), indexCount); - indexCount++; - } -} - -string -Constants_LookUp(string constName, string returnValue) -{ - int constIndex = -1i; - - /* only if we're prefixed */ - if (substring(constName, 0, 1) == "$") - constIndex = hash_get(g_hashConstants, substring(constName, 1, -1), -1i); - - return (constIndex == -1i) ? returnValue : g_constIndex[constIndex]; -} \ No newline at end of file + InitEnd(); +} + +string +Constants_LookUp(string constName, string returnValue) +{ + int constIndex = -1i; + + /* only if we're prefixed */ + if (substring(constName, 0, 1) == "$") + constIndex = hash_get(g_hashConstants, substring(constName, 1, -1), -1i); + + return (constIndex == -1i) ? returnValue : g_constIndex[constIndex]; +} diff --git a/src/shared/colors.h b/src/shared/colors.h index d8298ff9..a29fa1c3 100644 --- a/src/shared/colors.h +++ b/src/shared/colors.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 diff --git a/src/shared/damage.h b/src/shared/damage.h index 5118fa72..68829b07 100644 --- a/src/shared/damage.h +++ b/src/shared/damage.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 diff --git a/src/shared/decalgroups.h b/src/shared/decalgroups.h index d90bda3f..5eff9d0e 100644 --- a/src/shared/decalgroups.h +++ b/src/shared/decalgroups.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2023 Vera Visions LLC. + * Copyright (c) 2022-2024 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 @@ -48,4 +48,4 @@ int DecalGroups_NumForName(string group); #ifdef CLIENT void DecalGroups_Precache(void); void DecalGroups_Receive(void); -#endif \ No newline at end of file +#endif diff --git a/src/shared/decalgroups.qc b/src/shared/decalgroups.qc index 236ab60c..95385ff8 100644 --- a/src/shared/decalgroups.qc +++ b/src/shared/decalgroups.qc @@ -1,4 +1,18 @@ -/* Copyright (c) 2022, Vera Visions, L.L.C. All rights reserved. */ +/* + * Copyright (c) 2022-2024 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 CLIENT typedef struct @@ -100,8 +114,8 @@ DecalGroups_Init(void) filestream fh; string line; + InitStart(); g_decalgroup_count = 0i; - print("--------- Initializing Decal Groups ----------\n"); /* create the hash-table if it doesn't exist */ if (!g_hashdecalgroup) { @@ -110,7 +124,8 @@ DecalGroups_Init(void) fh = fopen("scripts/decals.txt", FILE_READ); if (fh < 0) { - print("^1[DECALS] Can't find scripts/decals.txt\n"); + NSError("Missing file scripts/decals.txt"); + InitEnd(); return; } @@ -148,7 +163,8 @@ DecalGroups_Init(void) #endif #endif - print(sprintf("decal groups initialized with %i entries.\n", g_decalgroup_count)); + NSLog("...decal groups initialized with %i entries.", g_decalgroup_count); + InitEnd(); } #ifdef CLIENT diff --git a/src/shared/defs.h b/src/shared/defs.h index f7e5bd4c..01d3cc7f 100644 --- a/src/shared/defs.h +++ b/src/shared/defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -139,8 +139,6 @@ string __fullspawndata; #define CLASSEXPORT(a,b) void a(void) { if (!isfunction(#b)) { self.classname = strcat("spawnfunc_", #b); } else { self.classname = #b; } callfunction(self.classname); } -#define printf(x, ...) print(sprintf(x, ...)) - const vector VEC_HULL_MIN = [-16,-16,-36]; const vector VEC_HULL_MAX = [16,16,36]; const vector VEC_CHULL_MIN = [-16,-16,-18]; @@ -204,27 +202,30 @@ crossprint(string m) #endif } +#if 0 __wrap string precache_model(string m) { if not (m) { breakpoint(); + return ""; + } + + if (m == "") { + breakpoint(); + return ""; } -#ifdef CLIENT - NSLog("^3Client precaching model ^7%s", m); -#else - NSLog("^3Server precaching model ^7%s", m); -#endif return prior(m); } +#endif __wrap string precache_sound(string sample) { if (sample != "") /* not empty */ if not(whichpack(strcat("sound/", sample))) { /* not present on disk */ - print(strcat("^1sfx sample ", sample, " does not exist!\n")); + NSError("SFX sample %S does not exist.", sample); return "misc/missing.wav"; } @@ -514,4 +515,4 @@ FileExists(string filePath) return false; return true; -} \ No newline at end of file +} diff --git a/src/shared/entities.h b/src/shared/entities.h index 6aad2556..b2e766a0 100644 --- a/src/shared/entities.h +++ b/src/shared/entities.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -104,7 +104,7 @@ Entity_SelectRandom(string className) /* immediately exit out if we've got none */ if (max < 1i) { - print(sprintf("^1Error: %s is not present on this map.\n", className)); + NSError("%S is not present on this map.", className); return __NULL__; } diff --git a/src/shared/events.h b/src/shared/events.h index bbc6345d..443f5146 100644 --- a/src/shared/events.h +++ b/src/shared/events.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 diff --git a/src/shared/global.h b/src/shared/global.h index e7d6d2a6..5b10fa2d 100644 --- a/src/shared/global.h +++ b/src/shared/global.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -14,6 +14,11 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +var bool autocvar_g_developer = false; +var bool autocvar_g_developerTimestamps = false; + +#define printf(...) print(sprintf(__VA_ARGS__)) + #ifdef DOXYGEN /** Doxygen doesn't know what enumflags (aka bitfields) are, used as e.g. */ #define enumflags enum @@ -22,8 +27,28 @@ void _NSLog(string msg) { - if (cvar("g_developer") == 1) - print(sprintf("%f %s\n", time, msg)); + if (autocvar_g_developerTimestamps) + print(sprintf("^9%f ^7%s\n", time, msg)); + else + print(sprintf("^7%s\n", msg)); +} + +void +_NSError(string functionName, string msg) +{ + if (autocvar_g_developerTimestamps) + print(sprintf("^9%f ^1%s^7: %s\n", time, functionName, msg)); + else + print(sprintf("^1%s^7: %s\n", functionName, msg)); +} + +void +_NSWarning(string functionName, string msg) +{ + if (autocvar_g_developerTimestamps) + print(sprintf("^9%f ^3%s^7: %s\n", time, functionName, msg)); + else + print(sprintf("^3%s^7: %s\n", functionName, msg)); } void @@ -37,27 +62,31 @@ _NSAssert(bool condition, string function, string descr) } } -void -_NSEntWarning(string className, vector classOrg, string warnMessage) -{ - print(sprintf("^1Class %s at %v: %s\n", className, classOrg, warnMessage)); -} - -/** Logs an error type message, with timestamp. +/** Logs an message, with timestamp. The console variable `g_developer` has to be `1` for them to be visible. @param description(...) contains a formatted string containing a description. */ -#define NSLog(...) _NSLog(sprintf(__VA_ARGS__)) +#define NSLog(...) if (autocvar_g_developer) _NSLog(sprintf(__VA_ARGS__)) + +/** Logs an error message, with timestamp. + The console variable `g_developer` has to be `1` for them to be visible. + +@param description(...) contains a formatted string containing a description. */ +#define NSError(...) _NSError(__FUNC__, sprintf(__VA_ARGS__)) + +/** Logs a warning message, with timestamp. + The console variable `g_developer` has to be `1` for them to be visible. + +@param description(...) contains a formatted string containing a description. */ +#define NSWarning(...) _NSWarning(__FUNC__, sprintf(__VA_ARGS__)) /** Generates an assertion, if a given condition is false. + The console variable `g_developer` has to be `1` for them to be visible. @param condition is the expression to be evaluated. @param description(...) contains a formatted string containing an error description. */ -#define NSAssert(condition, ...) _NSAssert(condition, __FUNC__, sprintf(__VA_ARGS__)) - - -#define NSEntWarning(...) _NSEntWarning(classname, origin, sprintf(__VA_ARGS__)) +#define NSAssert(condition, ...) if (autocvar_g_developer) _NSAssert(condition, __FUNC__, sprintf(__VA_ARGS__)) typedef enumflags { @@ -69,4 +98,60 @@ typedef enumflags SEARCH_NAMESORT /**< Sort the results alphabetically (slower) */ } searchFlags_t; -const vector g_vec_null = [0.0f, 0.0f, 0.0f]; \ No newline at end of file +const vector g_vec_null = [0.0f, 0.0f, 0.0f]; + +/* the console needs some attention too. */ +var float g_initTime; + +void +InitPrint(string functionName) +{ + int chars = 51i; + int charsLeft; + int charExtra; + string sideLeft = ""; + string sideRight = ""; + + if (functionName == __NULL__) { + NSLog("---------------------------------------------------"); + return; + } + + /* word and padding */ + chars = chars - (int)strlen(functionName) - 2i; + charsLeft = chars / 2i; + charExtra = chars % 2i; + + for (int i = 0i; i < charsLeft; i++) + sideLeft = strcat(sideLeft,"-"); + + for (int i = 0i; i < (charsLeft + charExtra); i++) { + sideRight = strcat(sideRight,"-"); + } + + NSLog( "%s %s %s", sideLeft, functionName, sideRight); +} + +void +_InitStart(string functionName) +{ + if (g_initTime != 0) + error("Called InitStart() without InitEnd()ing the previous one!"); + + InitPrint(functionName); + g_initTime = gettime(1); +} + +#define InitStart() _InitStart(__FUNC__) + + +void +_InitEnd(void) +{ + float endTime = gettime(1); + NSLog("loaded in %.1f seconds", (endTime - g_initTime)); + NSLog("---------------------------------------------------"); + g_initTime = 0; +} + +#define InitEnd() _InitEnd() diff --git a/src/shared/materials.h b/src/shared/materials.h index 82adb481..52c09d04 100644 --- a/src/shared/materials.h +++ b/src/shared/materials.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -36,179 +36,179 @@ var bool g_materialsAreLegacy; /* FIXME: world.... sigh, we should box this into a worldspawn class */ .string materials_file; -// Impact types -typedef enum -{ - IMPACT_MELEE, - IMPACT_EXPLOSION, - IMPACT_DEFAULT, - IMPACT_ALIEN, - IMPACT_COMPUTER, - IMPACT_CONCRETE, - IMPACT_DIRT, - IMPACT_FLESH, - IMPACT_FOLIAGE, - IMPACT_GLASS, - IMPACT_GRATE, - IMPACT_METAL, - IMPACT_SAND, - IMPACT_SLOSH, - IMPACT_SNOW, - IMPACT_TILE, - IMPACT_VENT, - IMPACT_WOOD -} impactType_t; - -typedef enum -{ - GSMATERIAL_GLASS, - GSMATERIAL_WOOD, - GSMATERIAL_METAL, - GSMATERIAL_FLESH, - GSMATERIAL_CINDER, - GSMATERIAL_TILE, - GSMATERIAL_COMPUTER, - GSMATERIAL_GLASS_UNBREAKABLE, - GSMATERIAL_ROCK, - GSMATERIAL_NONE -} materialType_t; - - -/* q3 bsp base flags */ -#define SURF_NODAMAGE 0x1i // never give falling damage -#define SURF_SLICK 0x2i // effects game physics -#define SURF_SKY 0x4i // lighting from environment map -#define SURF_LADDER 0x8i // climb this surface -#define SURF_NOIMPACT 0x10i // don't make missile explosions -#define SURF_NOMARKS 0x20i // don't leave missile marks -#define SURF_Q3FLESH 0x40i // make flesh sounds and effects -#define SURF_NODRAW 0x80i // don't generate a drawsurface at all -#define SURF_HINT 0x100i // make a primary bsp splitter -#define SURF_SKIP 0x200i // completely ignore, allowing non-closed brushes -#define SURF_NOLIGHTMAP 0x400i // surface doesn't need a lightmap -#define SURF_POINTLIGHT 0x800i // generate lighting info at vertexes -#define SURF_METALSTEPS 0x1000i // clanking footsteps -#define SURF_NOSTEPS 0x2000i // no footstep sounds -#define SURF_NONSOLID 0x4000i // don't collide against curves with this set -#define SURF_LIGHTFILTER 0x8000i // act as a light filter during q3map -light -#define SURF_ALPHASHADOW 0x10000i // do per-pixel light shadow casting in q3map -#define SURF_NODLIGHT 0x20000i // don't dlight even if solid (solid lava, skies) -#define SURF_DUST 0x40000i // leave a dust trail when walking on this surface - -/* behaviour surfaceflags */ -#define SURF_LEAKSTEAM 0x00080000i /* when shot, the material emits steam */ -#define SURF_LEAKWATER 0x00100000i /* when shot, the material emits water */ -#define SURF_RESERVED1 0x00200000i -#define SURF_RESERVED2 0x00400000i -#define SURF_RESERVED3 0x00800000i -#define SURF_RESERVED4 0x01000000i -#define SURF_RESERVED5 0x02000000i -#define SURF_RESERVED6 0x04000000i -#define SURF_PENETRATE 0x08000000i - -/* old TW material surfaceflags (need to be masked) */ -#define SURF_MASK 0x0FFFFFFFi -#define SURF_ALIEN 0x10000000i -#define SURF_BLOODYFLESH 0x20000000i -#define SURF_FOLIAGE 0x30000000i -#define SURF_COMPUTER 0x40000000i -#define SURF_DIRT 0x50000000i -#define SURF_VENT 0x60000000i -#define SURF_GRATE 0x70000000i -#define SURF_METAL 0x80000000i -#define SURF_GLASS 0x90000000i -#define SURF_SAND 0xA0000000i -#define SURF_SLOSH 0xB0000000i -#define SURF_SNOW 0xC0000000i -#define SURF_TILE 0xD0000000i -#define SURF_WOOD 0xE0000000i -#define SURF_CONCRETE 0xF0000000i - -const int CONTENTBIT_NONE = 0x00000000i; - -const int CONTENTBIT_SOLID = 0x00000001i -; /* SOLID_BSP */ -const int CONTENTBIT_UNUSED1 = 0x00000002i -; -const int CONTENTBIT_UNUSED2 = 0x00000004i -; -const int CONTENTBIT_LAVA = 0x00000008i; - /* surfaceParm lava */ - -const int CONTENTBIT_SLIME = 0x00000010i; - /* surfaceParm slime */ -const int CONTENTBIT_WATER = 0x00000020i; - /* surfaceParm water */ -const int CONTENTBIT_UNUSED3 = 0x00000040i -; -const int CONTENTBIT_GRENADECLIP = 0x00000080i -; /* surfaceParm grenadeclip */ - -const int CONTENTBIT_UNUSED4 = 0x00000100i; -const int CONTENTBIT_UNUSED5 = 0x00000200i; -const int CONTENTBIT_UNUSED6 = 0x00000400i -; -const int CONTENTBIT_UNUSED7 = 0x00000800i -; - -const int CONTENTBIT_UNUSED8 = 0x00001000i; -const int CONTENTBIT_UNUSED9 = 0x00002000i; -const int CONTENTBIT_FTELADDER = 0x00004000i; /* surfaceparm climb */ -const int CONTENTBIT_VEHICLECLIP = 0x00008000i; - -const int CONTENTBIT_PLAYERCLIP = 0x00010000i; - /* surfaceParm playerclip */ -const int CONTENTBIT_MONSTERCLIP = 0x00020000i; - /* surfaceParm monsterclip */ -const int CONTENTBIT_PROJECTILE = 0x00040000i; -const int CONTENTBIT_UNUSED12 = 0x00080000i; - -const int CONTENTBIT_CLUSTERPORTAL = 0x00100000i; -const int CONTENTBIT_DONOTENTER = 0x00200000i; -const int CONTENTBIT_BOTCLIP = 0x00400000i -; /* surfaceParm botclip */ -const int CONTENTBIT_MOVER = 0x00800000i -; - -const int CONTENTBIT_UNUSED13 = 0x01000000i -; -const int CONTENTBIT_BODY = 0x02000000i; /* SOLID_BBOX/SLIDEBOX */ -const int CONTENTBIT_CORPSE = 0x04000000i; /* SOLID_CORPSE */ -const int CONTENTBIT_UNUSED14 = 0x08000000i; - -const int CONTENTBIT_UNUSED15 = 0x10000000i; -const int CONTENTBIT_Q2LADDER = 0x20000000i; /* Q2BSP climbables */ -const int CONTENTBIT_UNUSED16 = 0x40000000i; -const int CONTENTBIT_SKY = 0x80000000i; /* Q1BSP only! */ +// Impact types +typedef enum +{ + IMPACT_MELEE, + IMPACT_EXPLOSION, + IMPACT_DEFAULT, + IMPACT_ALIEN, + IMPACT_COMPUTER, + IMPACT_CONCRETE, + IMPACT_DIRT, + IMPACT_FLESH, + IMPACT_FOLIAGE, + IMPACT_GLASS, + IMPACT_GRATE, + IMPACT_METAL, + IMPACT_SAND, + IMPACT_SLOSH, + IMPACT_SNOW, + IMPACT_TILE, + IMPACT_VENT, + IMPACT_WOOD +} impactType_t; + +typedef enum +{ + GSMATERIAL_GLASS, + GSMATERIAL_WOOD, + GSMATERIAL_METAL, + GSMATERIAL_FLESH, + GSMATERIAL_CINDER, + GSMATERIAL_TILE, + GSMATERIAL_COMPUTER, + GSMATERIAL_GLASS_UNBREAKABLE, + GSMATERIAL_ROCK, + GSMATERIAL_NONE +} materialType_t; + + +/* q3 bsp base flags */ +#define SURF_NODAMAGE 0x1i // never give falling damage +#define SURF_SLICK 0x2i // effects game physics +#define SURF_SKY 0x4i // lighting from environment map +#define SURF_LADDER 0x8i // climb this surface +#define SURF_NOIMPACT 0x10i // don't make missile explosions +#define SURF_NOMARKS 0x20i // don't leave missile marks +#define SURF_Q3FLESH 0x40i // make flesh sounds and effects +#define SURF_NODRAW 0x80i // don't generate a drawsurface at all +#define SURF_HINT 0x100i // make a primary bsp splitter +#define SURF_SKIP 0x200i // completely ignore, allowing non-closed brushes +#define SURF_NOLIGHTMAP 0x400i // surface doesn't need a lightmap +#define SURF_POINTLIGHT 0x800i // generate lighting info at vertexes +#define SURF_METALSTEPS 0x1000i // clanking footsteps +#define SURF_NOSTEPS 0x2000i // no footstep sounds +#define SURF_NONSOLID 0x4000i // don't collide against curves with this set +#define SURF_LIGHTFILTER 0x8000i // act as a light filter during q3map -light +#define SURF_ALPHASHADOW 0x10000i // do per-pixel light shadow casting in q3map +#define SURF_NODLIGHT 0x20000i // don't dlight even if solid (solid lava, skies) +#define SURF_DUST 0x40000i // leave a dust trail when walking on this surface + +/* behaviour surfaceflags */ +#define SURF_LEAKSTEAM 0x00080000i /* when shot, the material emits steam */ +#define SURF_LEAKWATER 0x00100000i /* when shot, the material emits water */ +#define SURF_RESERVED1 0x00200000i +#define SURF_RESERVED2 0x00400000i +#define SURF_RESERVED3 0x00800000i +#define SURF_RESERVED4 0x01000000i +#define SURF_RESERVED5 0x02000000i +#define SURF_RESERVED6 0x04000000i +#define SURF_PENETRATE 0x08000000i + +/* old TW material surfaceflags (need to be masked) */ +#define SURF_MASK 0x0FFFFFFFi +#define SURF_ALIEN 0x10000000i +#define SURF_BLOODYFLESH 0x20000000i +#define SURF_FOLIAGE 0x30000000i +#define SURF_COMPUTER 0x40000000i +#define SURF_DIRT 0x50000000i +#define SURF_VENT 0x60000000i +#define SURF_GRATE 0x70000000i +#define SURF_METAL 0x80000000i +#define SURF_GLASS 0x90000000i +#define SURF_SAND 0xA0000000i +#define SURF_SLOSH 0xB0000000i +#define SURF_SNOW 0xC0000000i +#define SURF_TILE 0xD0000000i +#define SURF_WOOD 0xE0000000i +#define SURF_CONCRETE 0xF0000000i + +const int CONTENTBIT_NONE = 0x00000000i; + +const int CONTENTBIT_SOLID = 0x00000001i +; /* SOLID_BSP */ +const int CONTENTBIT_UNUSED1 = 0x00000002i +; +const int CONTENTBIT_UNUSED2 = 0x00000004i +; +const int CONTENTBIT_LAVA = 0x00000008i; + /* surfaceParm lava */ + +const int CONTENTBIT_SLIME = 0x00000010i; + /* surfaceParm slime */ +const int CONTENTBIT_WATER = 0x00000020i; + /* surfaceParm water */ +const int CONTENTBIT_UNUSED3 = 0x00000040i +; +const int CONTENTBIT_GRENADECLIP = 0x00000080i +; /* surfaceParm grenadeclip */ + +const int CONTENTBIT_UNUSED4 = 0x00000100i; +const int CONTENTBIT_UNUSED5 = 0x00000200i; +const int CONTENTBIT_UNUSED6 = 0x00000400i +; +const int CONTENTBIT_UNUSED7 = 0x00000800i +; + +const int CONTENTBIT_UNUSED8 = 0x00001000i; +const int CONTENTBIT_UNUSED9 = 0x00002000i; +const int CONTENTBIT_FTELADDER = 0x00004000i; /* surfaceparm climb */ +const int CONTENTBIT_VEHICLECLIP = 0x00008000i; + +const int CONTENTBIT_PLAYERCLIP = 0x00010000i; + /* surfaceParm playerclip */ +const int CONTENTBIT_MONSTERCLIP = 0x00020000i; + /* surfaceParm monsterclip */ +const int CONTENTBIT_PROJECTILE = 0x00040000i; +const int CONTENTBIT_UNUSED12 = 0x00080000i; + +const int CONTENTBIT_CLUSTERPORTAL = 0x00100000i; +const int CONTENTBIT_DONOTENTER = 0x00200000i; +const int CONTENTBIT_BOTCLIP = 0x00400000i +; /* surfaceParm botclip */ +const int CONTENTBIT_MOVER = 0x00800000i +; + +const int CONTENTBIT_UNUSED13 = 0x01000000i +; +const int CONTENTBIT_BODY = 0x02000000i; /* SOLID_BBOX/SLIDEBOX */ +const int CONTENTBIT_CORPSE = 0x04000000i; /* SOLID_CORPSE */ +const int CONTENTBIT_UNUSED14 = 0x08000000i; + +const int CONTENTBIT_UNUSED15 = 0x10000000i; +const int CONTENTBIT_Q2LADDER = 0x20000000i; /* Q2BSP climbables */ +const int CONTENTBIT_UNUSED16 = 0x40000000i; +const int CONTENTBIT_SKY = 0x80000000i; /* Q1BSP only! */ /* a bit content group */ const int CONTENTBITS_MONSTER = CONTENTBIT_SOLID|CONTENTBIT_BODY|CONTENTBIT_MONSTERCLIP|CONTENTBIT_BOTCLIP; - -/* this is used for material-lookups using the external materials.txt file - * method used in Half-Life. In that environment we have to strip any - * prefixes and limit our material-name to 12 chars for everything to be - * identified correctly */ -string -Materials_FixName(string old_name) -{ - string tex_name = old_name; - - /* strip the first 2 chars when they're frame/random indicators */ - if (str2chr(tex_name, 0) == '-') - tex_name = substring(tex_name, 2, -1); - else if (str2chr(tex_name, 0) == '+') - tex_name = substring(tex_name, 2, -1); - - /* also not allowed */ - if (str2chr(tex_name, 0) == '~') - tex_name = substring(tex_name, 1, -1); - else if (str2chr(tex_name, 0) == '{') - tex_name = substring(tex_name, 1, -1); - - /* limit to 12 chars! */ - tex_name = substring(tex_name, 0, 12); - - NSLog("%s > %s", old_name, tex_name); - - return tex_name; -} \ No newline at end of file + +/* this is used for material-lookups using the external materials.txt file + * method used in Half-Life. In that environment we have to strip any + * prefixes and limit our material-name to 12 chars for everything to be + * identified correctly */ +string +Materials_FixName(string old_name) +{ + string tex_name = old_name; + + /* strip the first 2 chars when they're frame/random indicators */ + if (str2chr(tex_name, 0) == '-') + tex_name = substring(tex_name, 2, -1); + else if (str2chr(tex_name, 0) == '+') + tex_name = substring(tex_name, 2, -1); + + /* also not allowed */ + if (str2chr(tex_name, 0) == '~') + tex_name = substring(tex_name, 1, -1); + else if (str2chr(tex_name, 0) == '{') + tex_name = substring(tex_name, 1, -1); + + /* limit to 12 chars! */ + tex_name = substring(tex_name, 0, 12); + + //NSLog("%s > %s", old_name, tex_name); + + return tex_name; +} diff --git a/src/shared/materials.qc b/src/shared/materials.qc index 82b4daa1..feb8c3c1 100644 --- a/src/shared/materials.qc +++ b/src/shared/materials.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -42,7 +42,7 @@ Materials_LoadFromText(string filename) fclose(fileMaterial); } else { - dprint(strcat("^1Failed to load ", filename,"!\n")); + NSError("Missing file %s", filename); } #endif } @@ -178,7 +178,7 @@ Materials_LoadFromLegacyText(string filename) } fclose(fileMaterial); } else { - dprint(strcat("^1Failed to load ", filename,"!\n")); + NSError("Missing file %s", filename); } } @@ -186,7 +186,7 @@ Materials_LoadFromLegacyText(string filename) void Materials_Init(void) { - print("--------- Initializing Material Data ----------\n"); + InitStart(); g_mat_total = 0i; g_hashMaterials = __NULL__; @@ -206,6 +206,9 @@ Materials_Init(void) /* we're dealing with legacy materials */ if (g_materialsAreLegacy) { + string wastesName = sprintf("maps/%s.mat", mapname); + string svenName = sprintf("maps/%s_materials.txt", mapname); + /* prepare the mapper */ Materials_Mapper_Init(); @@ -225,10 +228,12 @@ Materials_Init(void) search_end(pm); /* the way TW did it back in '03 */ - Materials_LoadFromLegacyText(sprintf("maps/%s.mat", mapname)); + if (FileExists(wastesName)) + Materials_LoadFromLegacyText(wastesName); /* Trinity-Renderer does it this way */ - Materials_LoadFromLegacyText(sprintf("maps/%s_materials.txt", mapname)); + if (FileExists(svenName)) + Materials_LoadFromLegacyText(svenName); /* no longer needed! */ Materials_Mapper_Shutdown(); @@ -250,5 +255,6 @@ Materials_Init(void) search_end(mdlsearch); } - print(sprintf("material data initialized with %i entries.\n", g_mat_total)); + NSLog("material data initialized with %i entries.", g_mat_total); + InitEnd(); } diff --git a/src/shared/math.h b/src/shared/math.h index f2ee41f3..9dea56cf 100644 --- a/src/shared/math.h +++ b/src/shared/math.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Vera Visions LLC. + * Copyright (c) 2016-2024 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 diff --git a/src/shared/math.qc b/src/shared/math.qc index 75bfb5d7..0b301b4d 100644 --- a/src/shared/math.qc +++ b/src/shared/math.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Vera Visions LLC. + * Copyright (c) 2016-2024 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 diff --git a/src/shared/motd.h b/src/shared/motd.h index a00adb3d..4959ecaa 100644 --- a/src/shared/motd.h +++ b/src/shared/motd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Vera Visions LLC. + * Copyright (c) 2024 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 @@ -37,4 +37,4 @@ void MOTD_Init(void); string MOTD_GetTextBody(void); /** Returns how many individual lines are present in the message of the day. */ int MOTD_GetLineCount(void); -#endif \ No newline at end of file +#endif diff --git a/src/shared/motd.qc b/src/shared/motd.qc index 2e661f77..a28859bc 100644 --- a/src/shared/motd.qc +++ b/src/shared/motd.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Vera Visions LLC. + * Copyright (c) 2024 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 @@ -22,7 +22,9 @@ static int g_motd_lines; void MOTD_Init(void) { + InitStart(); #ifdef SERVER + /* wipe the slate clean */ for (int i = 0; i < MOTD_LINES; i++) { localcmd(sprintf("serverinfo motdline%i \"\"\n", i)); @@ -44,6 +46,7 @@ MOTD_Init(void) g_motd_lines = motdLines; #endif + InitEnd(); } #ifdef SERVER @@ -99,4 +102,4 @@ MOTD_GetLineCount(void) { return g_motd_lines; } -#endif \ No newline at end of file +#endif diff --git a/src/shared/platform.h b/src/shared/platform.h index 249ef136..137a68ca 100644 --- a/src/shared/platform.h +++ b/src/shared/platform.h @@ -82,7 +82,7 @@ Platform_FileInGamedir(string fileName, string gameDir) fileSearch = search_begin(fileName, SEARCH_FULLPACKAGE, TRUE); fileCount = search_getsize(fileSearch); - print(sprintf("looking for %S in %S\n", fileName, gameDir)); + NSLog("Looking for %S in %S", fileName, gameDir); /* doesn't exist */ if (fileCount <= 0) @@ -94,11 +94,13 @@ Platform_FileInGamedir(string fileName, string gameDir) fileDir = substring(fullPath, 0, strlen(gameDir)); /* only need to check same-ness */ if (fileDir == gameDir) { - print("found it\n"); + NSLog("Found %S in %S", fileName, gameDir); return true; } } + NSError("Did not find %S in %S", fileName, gameDir); + /* file exists but is in a different gamedir */ return false; } diff --git a/src/shared/player_pmove.qc b/src/shared/player_pmove.qc index c76cab46..bca52194 100644 --- a/src/shared/player_pmove.qc +++ b/src/shared/player_pmove.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 diff --git a/src/shared/pmove.qc b/src/shared/pmove.qc index f5eae09d..cf8a0f3f 100644 --- a/src/shared/pmove.qc +++ b/src/shared/pmove.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 diff --git a/src/shared/pmove_custom.qc b/src/shared/pmove_custom.qc index 40c80c7d..b654ef69 100644 --- a/src/shared/pmove_custom.qc +++ b/src/shared/pmove_custom.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -785,4 +785,4 @@ PMoveCustom_RunCrouchPhysics(entity target) target.view_ofs = PHY_VIEWPOS; } PMoveCustom_RunPlayerPhysics(target); -} \ No newline at end of file +} diff --git a/src/shared/propdata.qc b/src/shared/propdata.qc index cce8c152..d4a5b049 100644 --- a/src/shared/propdata.qc +++ b/src/shared/propdata.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -276,6 +276,9 @@ PropData_ForModel(string modelname) string line; int index; + if (!g_propdata_count) + return -1; + if (!modelname) return -1; @@ -309,7 +312,7 @@ PropData_ForModel(string modelname) g_propdata = (propdata_t *)memrealloc(g_propdata, sizeof(propdata_t), index, g_propdata_count); #else if (g_propdata_count >= PROPDATA_MAX) { - printf(sprintf("PropData_ForModel: Reached PROPDATA_MAX (%d)\n", PROPDATA_MAX)); + NSError("PropData_ForModel: Reached PROPDATA_MAX (%d)", PROPDATA_MAX); return -1i; } #endif @@ -323,7 +326,7 @@ PropData_ForModel(string modelname) if (fh < 0) { g_propdata_count--; - NSLog("Can't find propdata for model %s", modelname); + NSWarning("No PropData for model %S", modelname); return -1; } @@ -398,10 +401,7 @@ PropData_ForModel(string modelname) } fclose(fh); - dprint("^1[PROPDATA] No type found for "); - dprint(modelname); - dprint("\n"); - + NSError("No type found for %s", modelname); return -1; } @@ -418,7 +418,7 @@ PropData_Load(string type) index = (int)hash_get(g_hashpropdata, type, -1); if (index < 0) { - crossprint(sprintf("^1 PropData_Load: type %s is not defined\n", type)); + NSError("PropData type %S is not defined.", type); return -1; } else { return index; @@ -541,11 +541,7 @@ PropData_Init(void) string line; int index; -#ifdef SERVER - print("--------- Initializing PropDefs (SERVER) ----------\n"); -#else - print("--------- Initializing PropDefs (CLIENT) ----------\n"); -#endif + InitStart(); /* remove old data */ PropData_Shutdown(); @@ -561,7 +557,8 @@ PropData_Init(void) /* Defaults go here */ fh = fopen("scripts/propdata.txt", FILE_READ); if (fh < 0) { - print("^1[PROPDATA] Can't find propdata.txt\n"); + NSWarning("Missing file scripts/propdata.txt"); + InitEnd(); return; } @@ -578,8 +575,8 @@ PropData_Init(void) /* alocate our stuff */ g_propdata = (propdata_t *)memalloc(sizeof(propdata_t) * PROPDATA_MAX); g_breakmodel = (breakmodel_t *)memalloc(sizeof(breakmodel_t) * PROPDATA_MAX); - print(sprintf("allocated %d bytes for prop data.\n", sizeof(propdata_t) * PROPDATA_MAX)); - print(sprintf("allocated %d bytes for breakmodels.\n", sizeof(breakmodel_t) * PROPDATA_MAX)); + NSLog("...allocated %d bytes for prop data.", sizeof(propdata_t) * PROPDATA_MAX); + NSLog("...allocated %d bytes for breakmodels.", sizeof(breakmodel_t) * PROPDATA_MAX); #endif fseek(fh, 0); @@ -607,7 +604,6 @@ PropData_Init(void) } precache_model(mname); - NSLog("precaching break model: %S", mname); /* gotta tokenize our inputs again */ x = tokenize(g_breakmodel[i].data); @@ -619,7 +615,7 @@ PropData_Init(void) } g_breakmodel_end = g_breakmodel_count; - print("PropData initialized.\n"); + InitEnd(); } /* we can only tokenize one thing at a time, so we save the type for the current @@ -717,8 +713,8 @@ BreakModel_SpawnID(vector smins, vector smaxs, vector dir, float speed, int coun impactDecal = value; break; default: - print(sprintf("^1BreakModel_Spawn: Unrecognized model attribute %S with value %S\n", - key, value)); + NSError("Unrecognized model attribute %S with value %S", + key, value); } } @@ -801,11 +797,11 @@ BreakModel_Receive(void) /* sanity check */ if (index >= g_breakmodel_count) { - print(sprintf("^1Unable to spawn breakmodel of id %i. Not cached on client. (Client knows of %i)\n", index, g_breakmodel_count)); + NSError("Unable to spawn breakmodel of id %i. Not cached on client. (Client knows of %i)", index, g_breakmodel_count); return; } - //print(sprintf("i: %i max: %i name: %S\n", index, g_breakmodel_count, g_breakmodel[index].name)); + NSLog("BreakModel: i: %i max: %i name: %S", index, g_breakmodel_count, g_breakmodel[index].name); BreakModel_SpawnID(smins, smaxs, dir, speed, count, index); } @@ -846,11 +842,14 @@ void BreakModel_Spawn(vector smins, vector smaxs, vector dir, float speed, int count, string type) { int index; + vector pvsPosition; index = (int)hash_get(g_hashbreakmodel, type, -1); if (index == -1) return; + pvsPosition = (smins + ( 0.5 * ( smaxs - smins ))); + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); WriteByte(MSG_MULTICAST, EV_BREAKMODEL); WriteByte(MSG_MULTICAST, index); @@ -865,7 +864,7 @@ BreakModel_Spawn(vector smins, vector smaxs, vector dir, float speed, int count, WriteCoord(MSG_MULTICAST, dir[2]); WriteFloat(MSG_MULTICAST, speed); WriteByte(MSG_MULTICAST, count); - multicast((smins - smaxs), MULTICAST_PVS); + multicast(pvsPosition, MULTICAST_PVS); } void @@ -895,4 +894,4 @@ BreakModel_Entity(NSSurfacePropEntity target, vector dir, float speed) WriteByte(MSG_MULTICAST, count); multicast(pos, MULTICAST_PVS); } -#endif \ No newline at end of file +#endif diff --git a/src/shared/sentences.qc b/src/shared/sentences.qc index 171e649c..dfee853e 100644 --- a/src/shared/sentences.qc +++ b/src/shared/sentences.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -53,14 +53,15 @@ Sentences_Init(void) string temp; int c, i; - print("--------- Initializing SentencesDef (CLIENT) ----------\n"); + InitStart(); Sentences_Shutdown(); fs_sentences = fopen("sound/sentences.txt", FILE_READ); if (fs_sentences < 0) { - print("^1could not load sound/sentences.txt\n"); + NSError("Missing file sound/sentences.txt"); + InitEnd(); return; } @@ -91,7 +92,7 @@ Sentences_Init(void) g_sentences_count); #else if (g_sentences_count + 1 >= SENTENCES_LIMIT) { - print("^1reached limit of max sentences!\n"); + NSError("Reached limit of %d SentenceDefs.", SENTENCES_LIMIT); return; } @@ -118,7 +119,8 @@ Sentences_Init(void) } fclose(fs_sentences); - print(sprintf("SentencesDef initialized with %i entries.\n", g_sentences_count)); + NSLog("...SentencesDef initialized with %i entries.", g_sentences_count); + InitEnd(); } string @@ -151,7 +153,7 @@ Sentences_GetSamples(string msg) if (i != -1i) return g_sentences[i].m_strSamples; else { - print(sprintf("^1ERROR: Cannot find sentence %S\n", msg)); + NSError("Can't find sentence %S", msg); return ""; } } @@ -171,7 +173,7 @@ Sentences_Init(void) string temp; int c; - print("--------- Initializing SentencesDef (SERVER) ----------\n"); + InitStart(); if (g_sentences_count > 0) { g_sentences_count = 0; @@ -185,7 +187,8 @@ Sentences_Init(void) fs_sentences = fopen("sound/sentences.txt", FILE_READ); if (fs_sentences < 0) { - print("^1could not load sound/sentences.txt\n"); + NSError("Missing file sound/sentences.txt"); + InitEnd(); return; } @@ -216,7 +219,8 @@ Sentences_Init(void) g_sentences_count); #else if (g_sentences_count + 1 >= SENTENCES_LIMIT) { - print("^1reached limit of max sentences!\n"); + NSError("Reached limit of max sentences!"); + InitEnd(); return; } @@ -228,7 +232,8 @@ Sentences_Init(void) } fclose(fs_sentences); - print(sprintf("SentencesDef initialized with %i entries.\n", g_sentences_count)); + NSLog("SentencesDef initialized with %i entries.", g_sentences_count); + InitEnd(); } string @@ -264,12 +269,12 @@ Sentences_GetSamples(string word) /* if we've got one, choose a random sample of them */ if (gc) { r = floor(random(0, gc)); - NSLog("^3Sentences_GetSamples^7: Choosing %s%i", word, r); + SndLog("Choosing %s%i", word, r); return sprintf("%s%i", word, r); } /* we've somehow messed up catastrophically */ - print(sprintf("^1ERROR: Invalid sentence keyword %s\n", word)); + NSError("Invalid sentence keyword %s", word); return (""); } @@ -279,11 +284,11 @@ Sentences_GetID(string sentence) int i = (int)hash_get(g_hashsentences, sentence, -1i); if (i != -1i) { - print(sprintf("^2SUCCESS: Found sentence %S\n", sentence)); + SndLog("Found sentence %S", sentence); return i; } else { - print(sprintf("^1ERROR: Cannot find sentence %S\n", sentence)); + NSError("Can't find sentence %S", sentence); return 0; } } -#endif \ No newline at end of file +#endif diff --git a/src/shared/sound.h b/src/shared/sound.h index b5719da8..2d9f843d 100644 --- a/src/shared/sound.h +++ b/src/shared/sound.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -30,12 +30,34 @@ var bool autocvar_s_developer = false; void -_Sound_Log(string msg) +_SndLog(string functionName, string msg) { - if (autocvar_s_developer == true) - print(sprintf("%f %s\n", time, msg)); + if (autocvar_g_developerTimestamps) + print(sprintf("^9%f ^xF50%s^7: %s\n", time, functionName, msg)); + else + print(sprintf("^xF50%s^7: %s\n", functionName, msg)); } -#define SndLog(...) _Sound_Log(sprintf(__VA_ARGS__)) + +/** Logs an sound system specific log message. + The console variable `s_developer` has to be `1` for them to be visible. + +@param description(...) contains a formatted string containing a description. */ +#define SndLog(...) if (autocvar_s_developer) _SndLog(__FUNC__, sprintf(__VA_ARGS__)) + +void +_SndEntLog(string className, string functionName, float edictNum, string warnMessage) +{ + if (autocvar_g_developerTimestamps) + print(sprintf("^9%f ^xF50%s (id: %d)^7: %s\n", time, functionName, edictNum, warnMessage)); + else + print(sprintf("^xF50%s (id: %d)^7: %s\n", functionName, edictNum, warnMessage)); +} + +/** Logs an sound specific entity class log message. + The console variable `s_developer` has to be `1` for them to be visible. + +@param description(...) contains a formatted string containing a description. */ +#define SndEntLog(...) if (autocvar_s_developer) _SndEntLog(classname, __FUNC__, num_for_edict(this), sprintf(__VA_ARGS__)) /** Global hash table for name > soundDef id lookup. */ var hashtable g_hashsounds; @@ -112,4 +134,4 @@ void Sound_Speak(entity targetEntity, string sentencesEntry); /** Stops sounds on a given channel, on a target entity. */ void Sound_Stop(entity target, int chan); -void Sound_DebugList(); \ No newline at end of file +void Sound_DebugList(); diff --git a/src/shared/sound.qc b/src/shared/sound.qc index 18316592..5c219b72 100644 --- a/src/shared/sound.qc +++ b/src/shared/sound.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -49,26 +49,21 @@ void SoundSource_Init(void); void Sound_Init(void) { -#ifdef SERVER - print("--------- Initializing SoundDef (SERVER) ----------\n"); -#else - print("--------- Initializing SoundDef (CLIENT) ----------\n"); -#endif + InitStart(); /* make sure it's all reset */ Sound_Shutdown(); #ifndef SOUNDSHADER_DYNAMIC g_sounds = (snd_t *)memalloc(sizeof(snd_t) * SOUNDSHADER_MAX); - print(sprintf("allocated %d bytes for soundDef\n", sizeof(snd_t) * SOUNDSHADER_MAX)); + NSLog("...allocated %d bytes for SoundDef", sizeof(snd_t) * SOUNDSHADER_MAX); #endif /* Source Engine conventions */ SoundSource_Init(); precache_sound("common/null.wav"); - - print("SoundDef initialized.\n"); + InitEnd(); } static void @@ -407,7 +402,6 @@ Sound_Precache(string shader) cache = (int)hash_get(g_hashsounds, shader, -1); if (cache >= 0) { - SndLog("^1Sound_Precache: def %s already precached", shader); return cache; } } @@ -418,7 +412,7 @@ Sound_Precache(string shader) g_sounds = (snd_t *)memrealloc(g_sounds, sizeof(snd_t), index, g_sounds_count); #else if (g_sounds_count >= SOUNDSHADER_MAX) { - error(sprintf("Sound_Precache: Reached SOUNDSHADER_MAX (%d)\n", SOUNDSHADER_MAX)); + NSError("Reached SOUNDSHADER_MAX (%d)", SOUNDSHADER_MAX); return -1; } #endif @@ -454,11 +448,8 @@ Sound_Precache(string shader) fclose(fh); } - print("^1no SoundDef found for "); - print(shader); - print("\n"); + NSError("No SoundDef %S found.", shader); g_sounds_count--; - search_end(sh); return -1; } @@ -477,7 +468,7 @@ Sound_Distance(entity target, string shader) sample = (int)hash_get(g_hashsounds, shader, -1); if (sample < 0) { - crossprint(sprintf("^1Sound_Distance: def %s is not precached\n", shader)); + NSError("SoundDef %S is not precached", shader); return; } @@ -510,10 +501,6 @@ Sound_Distance(entity target, string shader) } #endif -#ifdef DEVELOPER - print(sprintf("Sound_Distance: %s\n", argv(r))); -#endif - sound( target, 5, @@ -540,7 +527,7 @@ Sound_DistancePos(vector pos, string shader) sample = (int)hash_get(g_hashsounds, shader, -1); if (sample < 0) { - SndLog("^1Sound_DistancePos: def %s is not precached (SERVER)\n", shader); + NSError("SoundDef %S is not precached", shader); return; } @@ -573,7 +560,7 @@ Sound_DistancePos(vector pos, string shader) } #endif - SndLog(sprintf("Sound_DistancePos: %s\n", argv(r))); + SndLog("Playing %S", argv(r)); pointsound_proper(pos, argv(r), volume, ATTN_NONE, pitch); } @@ -600,7 +587,7 @@ Sound_Play(entity target, int chan, string shader) sample = (int)hash_get(g_hashsounds, shader, -1); if (sample < 0) { - SndLog("^1Sound_Play: def %s is not precached\n", shader); + NSError("SoundDef %S is not precached", shader); return; } @@ -661,9 +648,7 @@ Sound_Play(entity target, int chan, string shader) } #endif -#ifdef DEVELOPER - print(sprintf("Sound_Play: %s\n", argv(r))); -#endif + SndLog("Playing %S", argv(r)); #ifdef SERVER if (g_sounds[sample].shakes > 0.0) { @@ -688,7 +673,7 @@ Sound_Play(entity target, int chan, string shader) pointparticles(g_sounds[sample].pointparticle, target.origin, [0,0,0], 1); #else if (g_sounds[sample].pointparticle) - print(sprintf("SoundDef %S is attempting to spawn a particle on the server side.\n", shader)); + NSWarning("SoundDef %S is attempting to spawn a particle on the server side.", shader); #endif sound( @@ -723,7 +708,7 @@ Sound_PlayAt(vector pos, string shader) sample = (int)hash_get(g_hashsounds, shader, -1); if (sample < 0) { - SndLog("^1Sound_PlayAt: def %s is not precached\n", shader); + NSError("SoundDef %S is not precached", shader); return; } @@ -779,7 +764,7 @@ Sound_PlayLocal(string shader) sample = (int)hash_get(g_hashsounds, shader, -1); if (sample < 0) { - SndLog("^1Sound_PlayLocal: def %s is not precached\n", shader); + NSError("SoundDef %S is not precached", shader); return; } @@ -865,7 +850,7 @@ Sound_Speak(entity target, string shader) sample = (int)hash_get(g_hashsounds, shader, -1); if (sample < 0) { - SndLog("^1Sound_Speak: def %s is not precached (SERVER)\n", shader); + NSError("SoundDef %S is not precached", shader); return; } @@ -956,4 +941,4 @@ Sound_DebugList(void) } print(sprintf("\t%i total soundDef loaded\n", g_sounds_count)); -} \ No newline at end of file +} diff --git a/src/shared/surfaceproperties.qc b/src/shared/surfaceproperties.qc index 6897fd21..b5600b54 100644 --- a/src/shared/surfaceproperties.qc +++ b/src/shared/surfaceproperties.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -175,7 +175,7 @@ SurfData_Load(string type) index = (int)hash_get(g_hashsurfdata, type, -1); if (index < 0) { - crossprint(sprintf("^1 SurfData_Load: type %s is not defined\n", type)); + NSError("SurfData %S is not defined.", type); return -1; } else { return index; @@ -207,7 +207,7 @@ SurfData_CountLine(string line) default: /* new definition starts */ if (c == 1 && braced == 0) { - t_name = strtolower(line); + t_name = strtolower(argv(0)); if (t_name) g_surfdata_count++; @@ -312,7 +312,7 @@ SurfData_Init(void) string line; int index; - print("--------- Initializing Surface Data ----------\n"); + InitStart(); /* remove old data */ SurfData_Shutdown(); @@ -328,7 +328,7 @@ SurfData_Init(void) /* it's OK for one to not exist... */ if (fh < 0) { - print("^1[SURFDATA] Can't find surfaceproperties.txt\n"); + NSError("missing scripts/surfaceproperties.txt!"); return; } @@ -339,7 +339,7 @@ SurfData_Init(void) /* we did not find 'default' as the first entry. */ if (g_spDefaultSet == false) { - error("^1no 'default' defined at the top of scripts/surfaceproperties.txt"); + NSError("no 'default' defined at the top of scripts/surfaceproperties.txt!"); return; } @@ -394,7 +394,8 @@ SurfData_Init(void) Sound_Precache(g_surfdata[i].m_sndBreak); } - print(sprintf("surface data initialized with %i entries.\n", g_surfdata_count)); + NSLog("...SurfData initialized with %i entries.", g_surfdata_count); + InitEnd(); } static string g_curSurfData; @@ -474,11 +475,6 @@ SurfData_Impact_Parse(void) string impactfx = SurfData_GetInfo(SurfData_TexToSurfData(tex_name), SURFDATA_FX_BULLETIMPACT); float impactid = SurfData_GetInfo(SurfData_TexToSurfData(tex_name), SURFDATA_FX_BULLETIMPACTID); - NSLog("SurfData_Impact_Parse:"); - NSLog("\tent: %S texture: %S", surfnum.classname, tex_name); - NSLog("\tplaying impact sfx %S at %v", impactsfx, impactorg); - NSLog("\temitting impact fx %S at %v", impactfx, impactorg); - Sound_PlayAt(impactorg, impactsfx); pointparticles( impactid, impactorg, impactang, 1 ); } @@ -520,7 +516,6 @@ SurfData_Impact(entity e, vector org, vector ang) if (trace_surfacename != "") { string n = strcat(dirname(e.model), "/", trace_surfacename); int texdata = SurfData_TexToSurfData(n); - NSLog("SurfData_Impact: %S %i\n", n, texdata); SurfData_ImpactID_Net(texdata, org, ang); } else SurfData_Impact_SurfaceParm(e, org, ang); @@ -549,4 +544,4 @@ SurfData_ImpactOfNamedType(string materialName, vector worldPosition, vector imp { int index = (int)hash_get(g_hashsurfdata, materialName, -1); SurfData_ImpactOfType(index, worldPosition, impactNormal); -} \ No newline at end of file +} diff --git a/src/shared/util.h b/src/shared/util.h index c89f6f01..568ad24f 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -1,2 +1,19 @@ +/* + * Copyright (c) 2016-2024 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. +*/ + void Util_ChangeClass(entity, string); -string Util_ExtensionFromString(string inputString); \ No newline at end of file +string Util_ExtensionFromString(string inputString); +string Util_ChatFormat(float playerNum, float teamNum, string chatMessage); \ No newline at end of file diff --git a/src/shared/util.qc b/src/shared/util.qc index c91e4a78..bc606b9e 100644 --- a/src/shared/util.qc +++ b/src/shared/util.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 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 @@ -76,4 +76,24 @@ Util_ExtensionFromString(string inputString) { int modelNameLength = strlen(inputString); return substring(inputString, modelNameLength - 3, modelNameLength); +} + +string +Util_ChatFormat(float playerNum, float teamNum, string chatMessage) +{ + vector teamColor = stov(serverkey(sprintf("teamcolor_%d", teamNum))); + string teamColorString = sprintf("^x%x%x%x", teamColor[0] * 15,teamColor[1] * 15,teamColor[2] * 15); + string teamName = serverkey(sprintf("team_%d", teamNum)); + +#ifdef CLIENT + string playerName = getplayerkeyvalue(playerNum, "name"); +#else + string playerName = infokey(edict_num(playerNum+1), "name"); +#endif + + if (teamNum == 0) { + return sprintf("%s^7: %s", playerName, chatMessage); + } else { + return sprintf("%s %s(%s)^7: %s", playerName, teamColorString, teamName, chatMessage); + } } \ No newline at end of file diff --git a/src/shared/weapons.qc b/src/shared/weapons.qc index 4d5f24d5..f0181daa 100644 --- a/src/shared/weapons.qc +++ b/src/shared/weapons.qc @@ -96,4 +96,4 @@ void Weapon_DropCurrentWeapon(NSClientPlayer pl) {} int Weapon_GetCount() {} int Weapon_GetBitID(int) {} int Weapons_IsEmpty(NSClientPlayer, int) {} -#endif \ No newline at end of file +#endif