commit d77429ae741744ab2929ee06a0e7f7b38751268c Author: Marco Cawthorne Date: Thu Mar 14 17:23:29 2024 -0700 Initial commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b874490 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +data.pk3dir/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..0c4f23c --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# FreeCoD + +Blub blub. + +![Preview 1](img/preview1.jpg) +![Preview 2](img/preview2.jpg) +![Preview 3](img/preview3.jpg) +![Preview 4](img/preview4.jpg) + +## To-do list: + +- Everything. + +Other than that, it should be fairly representative of Call of Duty. + +## Overview + +This is a port of Call of Duty (MP) to Nuclide. + +You have to own a copy of the game to play this. +All the code, resources etc. in this repo are of my own research and creation. + +## License +ISC License + +Copyright (c) 2024 Marco Hladik + +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. diff --git a/img/preview1.jpg b/img/preview1.jpg new file mode 100644 index 0000000..af839ce Binary files /dev/null and b/img/preview1.jpg differ diff --git a/img/preview2.jpg b/img/preview2.jpg new file mode 100644 index 0000000..cf26e0f Binary files /dev/null and b/img/preview2.jpg differ diff --git a/img/preview3.jpg b/img/preview3.jpg new file mode 100644 index 0000000..3433d6b Binary files /dev/null and b/img/preview3.jpg differ diff --git a/img/preview4.jpg b/img/preview4.jpg new file mode 100644 index 0000000..c76ad39 Binary files /dev/null and b/img/preview4.jpg differ diff --git a/manifest.fmf b/manifest.fmf new file mode 100644 index 0000000..0478b40 --- /dev/null +++ b/manifest.fmf @@ -0,0 +1,14 @@ +FTEMANIFEST 1 +NAME "Call of Duty" +GAME cod +BASEGAME platform +BASEGAME cod + +// you don't really want to change these +RTCBROKER master.frag-net.com:27950 +PROTOCOLNAME "Nuclide" +MAINCONFIG nuclide.cfg +DOWNLOADSURL "" + +-exec platform_default.cfg +-plug_load cod diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..5e8df06 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,6 @@ +CC=fteqcc + +all: + cd client && $(MAKE) + cd server && $(MAKE) + cd menu && $(MAKE) diff --git a/src/client/Makefile b/src/client/Makefile new file mode 100644 index 0000000..627019a --- /dev/null +++ b/src/client/Makefile @@ -0,0 +1,4 @@ +CC=fteqcc + +all: + $(CC) progs.src diff --git a/src/client/camera.qc b/src/client/camera.qc new file mode 100644 index 0000000..585e733 --- /dev/null +++ b/src/client/camera.qc @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016-2022 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. +*/ + +struct +{ + float m_flSpeed; + float m_flFracSin; + float m_flTime; + float m_flMove; + float m_flDelta; + int m_iCycle; +} g_camBobVars[4], *pCamBob; + +/* tilts the camera for a head-bob like effect when moving */ +void +Camera_RunBob(__inout vector camera_angle) +{ + if (!autocvar(v_cambob, 1, "Enables bobbing effect for the first-person camera")) + return; + + int s = (float)getproperty(VF_ACTIVESEAT); + pCamBob = &g_camBobVars[s]; + + /* we don't really care about the vertical velocity */ + vector speed = pSeat->m_vecPredictedVelocity; + speed[2] = 0.0f; + pCamBob->m_flSpeed = vlen(speed); + + /* don't bother on low speeds */ + if ( pCamBob->m_flSpeed < 5.0f ) { + pCamBob->m_flMove = 0.0f; + pCamBob->m_flTime = 0.0f; /* progress has halted, start anew */ + return; + } else if (pSeat->m_ePlayer.flags & FL_ONGROUND && pSeat->m_ePlayer.waterlevel == 0) { + pCamBob->m_flMove = clframetime * (pCamBob->m_flSpeed * 0.01); + } else { + pCamBob->m_flMove = 0.0f; + } + + pCamBob->m_flTime = (pCamBob->m_flTime += pCamBob->m_flMove); + pCamBob->m_flFracSin = fabs(sin(pCamBob->m_flTime * M_PI)); + pCamBob->m_iCycle = (int)pCamBob->m_flTime; + pCamBob->m_flDelta = (pCamBob->m_flFracSin * 0.0025f) * pCamBob->m_flSpeed; + + camera_angle[0] += pCamBob->m_flDelta; + + if (pCamBob->m_iCycle & 1) { + pCamBob->m_flDelta = -pCamBob->m_flDelta; + } + + camera_angle[2] += pCamBob->m_flDelta; +} + +/* applies a tilt to the camera for when we're strafing left to right */ +void +Camera_StrafeRoll(__inout vector camera_angle) +{ + if (!autocvar(v_camroll, 0, "Enables strafe-roll for the first-person camera")) + return; + + float roll; + makevectors(camera_angle); + + roll = dotproduct(pSeat->m_vecPredictedVelocity, v_right); + roll *= 0.015f; + + camera_angle[2] += roll; +} diff --git a/src/client/cmds.qc b/src/client/cmds.qc new file mode 100644 index 0000000..aa0c031 --- /dev/null +++ b/src/client/cmds.qc @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016-2022 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. +*/ + +/* This is where custom game-specific commands go! + * You'll also inherit all the commands defined in entry.c */ +int +ClientGame_ConsoleCommand(void) +{ + switch(argv(0)) { + default: + return (0); + } + return (1); +} diff --git a/src/client/defs.h b/src/client/defs.h new file mode 100644 index 0000000..13ad889 --- /dev/null +++ b/src/client/defs.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016-2022 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. +*/ + +vector g_hudmins; +vector g_hudres; + +struct +{ + float temp; +} g_seatslocal[4], *pSeatLocal; diff --git a/src/client/draw.qc b/src/client/draw.qc new file mode 100644 index 0000000..d30148a --- /dev/null +++ b/src/client/draw.qc @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016-2022 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 +ClientGame_PreDraw(void) +{ + +} + +void +ClientGame_PostDraw(void) +{ + +} diff --git a/src/client/entities.qc b/src/client/entities.qc new file mode 100644 index 0000000..4b7873d --- /dev/null +++ b/src/client/entities.qc @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2016-2022 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. +*/ + +int +ClientGame_EntityUpdate(float id, float new) +{ + switch (id) { + default: + return (0); + } + + return (1); +} diff --git a/src/client/game_event.qc b/src/client/game_event.qc new file mode 100644 index 0000000..f25757d --- /dev/null +++ b/src/client/game_event.qc @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016-2022 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. +*/ + +int +ClientGame_EventParse(float fHeader) +{ + switch (fHeader) { + case EV_CHAT: + float fSender = readbyte(); + float fTeam = readbyte(); + string sMessage = readstring(); + + CSQC_Parse_Print(sprintf("%s: %s", getplayerkeyvalue(fSender, "name"), sMessage), PRINT_CHAT); + break; + case EV_CHAT_TEAM: + float fSender2 = readbyte(); + float fTeam2 = readbyte(); + string sMessage2 = readstring(); + + CSQC_Parse_Print(sprintf("[TEAM] %s: %s", getplayerkeyvalue(fSender2, "name"), sMessage2), PRINT_CHAT); + break; + default: + return (0); + } + return (1); +} diff --git a/src/client/hud.qc b/src/client/hud.qc new file mode 100644 index 0000000..6dbf13a --- /dev/null +++ b/src/client/hud.qc @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016-2022 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. +*/ + +const float baseIconSize = 32.0; +const float baseIconPadding = 16.0; + +/* main entry */ +void +HUD_Init(void) +{ +} + +/* main entry */ +void +HUD_Draw(void) +{ + + Textmenu_Draw(); +} + +/* specatator main entry */ +void +HUD_DrawSpectator(void) +{ + +} diff --git a/src/client/hud_weaponselect.qc b/src/client/hud_weaponselect.qc new file mode 100644 index 0000000..ad8b892 --- /dev/null +++ b/src/client/hud_weaponselect.qc @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016-2022 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 +HUD_DrawWeaponSelect_Forward(void) +{ + +} + +void +HUD_DrawWeaponSelect_Back(void) +{ + +} + +void +HUD_DrawWeaponSelect_Trigger(void) +{ +} + +void +HUD_DrawWeaponSelect_Last(void) +{ + +} + +void +HUD_SlotSelect(int slot) +{ + +} + +void +HUD_DrawWeaponSelect(void) +{ + +} diff --git a/src/client/init.qc b/src/client/init.qc new file mode 100644 index 0000000..5d8a045 --- /dev/null +++ b/src/client/init.qc @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016-2022 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. +*/ + +/* +================= +ClientGame_Init + +Comparable to worldspawn in SSQC in that it's mostly used for precaches +================= +*/ +void +ClientGame_Init(float apilevel, string enginename, float engineversion) +{ +} + +void +ClientGame_InitDone(void) +{ +} + +void +ClientGame_RendererRestart(string rstr) +{ +} diff --git a/src/client/progs.src b/src/client/progs.src new file mode 100644 index 0000000..be89492 --- /dev/null +++ b/src/client/progs.src @@ -0,0 +1,40 @@ +#pragma target fte_5768 +#pragma progs_dat "../../csprogs.dat" + +#define CSQC +#define CLIENT + +#includelist +/* first the engine, then nuclide headers for client/shared */ +../../../src/shared/fteextensions.qc +../../../src/shared/defs.h +../../../src/client/defs.h + +/* mod specific header */ +defs.h + +/* for VGUI elements, we want to include this (optional) */ +../../../src/vgui/include.src + +/* include the entity codebase */ +../../../src/gs-entbase/client.src +../../../src/gs-entbase/shared.src + +/* mod specific functions */ +../shared/include.src + +draw.qc +init.qc +entities.qc +camera.qc +cmds.qc +game_event.qc +viewmodel.qc +hud.qc +hud_weaponselect.qc +scoreboard.qc + +/* global client/shared code */ +../../../src/client/include.src +../../../src/shared/include.src +#endlist diff --git a/src/client/scoreboard.qc b/src/client/scoreboard.qc new file mode 100644 index 0000000..519b262 --- /dev/null +++ b/src/client/scoreboard.qc @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2016-2022 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. +*/ + +#define SCORE_HEADER_C [255/255,156/255,0] +#define SCORE_LINE_C [255/255,200/255,0] + +var int autocvar_cl_centerscores = FALSE; +var int g_scores_teamplay = 0; + +void +Scores_Init(void) +{ + g_scores_teamplay = (int)serverkeyfloat("teamplay"); +} + +void +Scores_DrawTeam(player pl, vector pos) +{ + drawfill(pos, [290, 1], SCORE_LINE_C, 1.0f, DRAWFLAG_ADDITIVE); + + drawfont = Font_GetID(FONT_20); + drawstring(pos + [0,-18], "Teams", [8,8], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + drawstring(pos + [124,-18], "kills / deaths", [8,8], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + drawstring(pos + [240,-18], "latency", [8,8], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + + pos[1] += 12; + + for (int t = 1; t <= serverkeyfloat("teams"); t++) { + float l; + string temp; + drawstring(pos, serverkey(sprintf("team_%i", t)), [8,8], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + temp = serverkey(sprintf("teamscore_%i", t)); + l = stringwidth(temp, FALSE, [8,8]); + drawstring(pos + [150-l, 0], temp, [8,8], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + drawstring(pos + [158, 0], "wins", [8,8], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + pos[1] += 16; + + for (int i = -1; i > -32; i--) { + if (getplayerkeyfloat(i, "*team") != t) { + continue; + } + + temp = getplayerkeyvalue(i, "name"); + + /* Out of players */ + if (!temp) { + break; + } else if (temp == getplayerkeyvalue(pl.entnum-1, "name")) { + drawfill(pos, [290, 13], [0,0,1], 0.5f, DRAWFLAG_ADDITIVE); + } + + drawstring(pos + [24,0], getplayerkeyvalue(i, "name"), [8,8], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + drawstring(pos + [154,0], "/", [8,8], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + + /* Get the kills and align them left to right */ + temp = getplayerkeyvalue(i, "frags"); + l = stringwidth(temp, FALSE, [8,8]); + drawstring(pos + [150 - l,0], temp, [8,8], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + + /* Deaths are right to left aligned */ + temp = getplayerkeyvalue(i, "*deaths"); + drawstring(pos + [165,0], temp, [8,8], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + + /* Get the latency and align it left to right */ + temp = getplayerkeyvalue(i, "ping"); + l = stringwidth(temp, FALSE, [8,8]); + + drawstring(pos + [290 - l,0], temp, [8,8], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + pos[1] += 20; + } + pos[1] += 12; + } + + drawfont = Font_GetID(FONT_CON); +} + +void +Scores_DrawNormal(player pl, vector pos) +{ + drawfill(pos, [290, 1], SCORE_LINE_C, 1.0f, DRAWFLAG_ADDITIVE); + + drawfont = Font_GetID(FONT_20); + drawstring(pos + [0,-18], "Player", [8,8], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + drawstring(pos + [124,-18], "kills / deaths", [8,8], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + drawstring(pos + [240,-18], "latency", [8,8], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + + pos[1] += 12; + for (int i = -1; i > -32; i--) { + float l; + string ping; + string kills; + string deaths; + string name; + + name = getplayerkeyvalue(i, "name"); + + /* Out of players */ + if (!name) { + break; + } else if (name == getplayerkeyvalue(pl.entnum-1, "name")) { + drawfill(pos, [290, 13], [0,0,1], 0.5f, DRAWFLAG_ADDITIVE); + } + + drawstring(pos, getplayerkeyvalue(i, "name"), [8,8], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + drawstring(pos + [154,0], "/", [8,8], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + + /* Get the kills and align them left to right */ + kills = getplayerkeyvalue(i, "frags"); + l = stringwidth(kills, FALSE, [8,8]); + drawstring(pos + [150 - l,0], kills, [8,8], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + + /* Deaths are right to left aligned */ + deaths = getplayerkeyvalue(i, "*deaths"); + drawstring(pos + [165,0], deaths, [8,8], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + + /* Get the latency and align it left to right */ + ping = getplayerkeyvalue(i, "ping"); + l = stringwidth(ping, FALSE, [8,8]); + + drawstring(pos + [290 - l,0], ping, [8,8], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + pos[1] += 20; + } + + drawfont = Font_GetID(FONT_CON); +} + +void +Scores_Draw(void) +{ + vector pos; + player pl; + + pl = (player)pSeat->m_ePlayer; + + if (autocvar_cl_centerscores) { + int c = 10; + + /* calculate all valid entries */ + for (int i = -1; i > -32; i--) { + if (getplayerkeyvalue(i, "name")) { + break; + } + c += 10; + } + pos = video_mins + [(video_res[0] / 2) - 145, (video_res[1] / 2) - c]; + } else { + pos = video_mins + [(video_res[0] / 2) - 145, 30]; + } + + if (Util_IsTeamplay()) { + Scores_DrawTeam(pl, pos); + } else { + Scores_DrawNormal(pl, pos); + } +} diff --git a/src/client/viewmodel.qc b/src/client/viewmodel.qc new file mode 100644 index 0000000..77a1f6f --- /dev/null +++ b/src/client/viewmodel.qc @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2016-2022 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 float autocvar_v_bob = 0.01f; +var float autocvar_v_bobcycle = 1.0f; +var float autocvar_v_bobup = 0.5f; + +struct +{ + float m_flBobTime; + float m_flBobTime2; + float m_flBob; + float m_flBob2; + float m_flBobCycle; + float m_flBobCycle2; + float m_flSpeed; +} g_viewBobVars[4], *pViewBob; + + +/* bob vars are calculated separately from application, so that if there's + * more than one viewmodel we won't affect the speed of the bob by running + * the math too many times */ +void +Viewmodel_CalcBob(void) +{ + int s = (float)getproperty(VF_ACTIVESEAT); + pViewBob = &g_viewBobVars[s]; + + vector vecVel; + float flBob; + + float var_bob; + float var_cycle; + float var_up; + + var_bob = autocvar_v_bob; + var_cycle = autocvar_v_bobcycle; + var_up = autocvar_v_bobup; + + pViewBob->m_flBobTime += clframetime; + pViewBob->m_flBobTime2 += clframetime; + pViewBob->m_flBobCycle = pViewBob->m_flBobTime - (int)(pViewBob->m_flBobTime / var_cycle) * var_cycle; + pViewBob->m_flBobCycle /= var_cycle; + + if (pViewBob->m_flBobCycle < var_up) { + pViewBob->m_flBobCycle = MATH_PI * pViewBob->m_flBobCycle / var_up; + } else { + pViewBob->m_flBobCycle = MATH_PI + MATH_PI * (pViewBob->m_flBobCycle - var_up)/(1.0 - var_up); + } + + vecVel = pSeat->m_vecPredictedVelocity; + vecVel[2] = 0; + pViewBob->m_flSpeed = vlen(vecVel); + + flBob = pViewBob->m_flSpeed * var_bob; + flBob = flBob * 0.3 + flBob * 0.7 * sin(pViewBob->m_flBobCycle); + pViewBob->m_flBob = bound(-7, flBob, 4); + + /* BOB2, which is half the cycle of bob1 */ + pViewBob->m_flBobCycle2 = pViewBob->m_flBobTime2 - (int)(pViewBob->m_flBobTime2 / (var_cycle * 0.5f)) * (var_cycle * 0.5f); + pViewBob->m_flBobCycle2 /= (var_cycle * 0.5f); + + if (pViewBob->m_flBobCycle2 < var_up) { + pViewBob->m_flBobCycle2 = MATH_PI * pViewBob->m_flBobCycle2 / var_up; + } else { + pViewBob->m_flBobCycle2 = MATH_PI + MATH_PI * (pViewBob->m_flBobCycle2 - var_up)/(1.0 - var_up); + } + + flBob = pViewBob->m_flSpeed * var_bob; + flBob = flBob * 0.3 + flBob * 0.7 * sin(pViewBob->m_flBobCycle2); + pViewBob->m_flBob2 = bound(-7, flBob, 4); + + /* make sure it's adjusted for scale */ + pViewBob->m_flBob *= autocvar_cg_viewmodelScale; +} + +void +Viewmodel_ApplyBob(entity gun) +{ + int s = (float)getproperty(VF_ACTIVESEAT); + pViewBob = &g_viewBobVars[s]; + + float sintime; + float strength; + gun.angles[2] = -pViewBob->m_flBob; + + vector angmod = [0,0,0]; + angmod[0] -= pViewBob->m_flBob2 * 0.5f; + angmod[1] += pViewBob->m_flBob * 2.5f; + angmod[2] += pViewBob->m_flBob * 3.0f; + gun.angles += angmod * 1.5f; + + /* sway with speed */ + sintime = sin(time); + strength = pViewBob->m_flSpeed; + + if (strength > 240) + strength = 240; + + strength = 240 - strength; + strength *= 0.005f; + +#ifdef WASTES + float sprint; + if (pSeatLocal->m_iSprinting && vlen(pSeat->m_vecPredictedVelocity) > 240) { + pSeatLocal->m_flSprintLerp = bound(0.0f, pSeatLocal->m_flSprintLerp + clframetime, 1.0f); + } else { + pSeatLocal->m_flSprintLerp = bound(0.0f, pSeatLocal->m_flSprintLerp - clframetime, 1.0f); + } + sprint = 20 * pSeatLocal->m_flSprintLerp; + gun.angles[0] += sprint; + gun.angles[1] += sprint + (sprint * pViewBob->m_flBob) * 0.25f; + + if (pSeat->m_ePlayer.gflags & GF_IS_HEALING) { + pSeatLocal->m_flHealLerp = bound(0.0f, pSeatLocal->m_flHealLerp + clframetime, 1.0f); + } else { + pSeatLocal->m_flHealLerp = bound(0.0f, pSeatLocal->m_flHealLerp - clframetime, 1.0f); + } + gun.angles[0] += pSeatLocal->m_flHealLerp * 45; + gun.origin[2] -= pSeatLocal->m_flHealLerp * 5; +#endif + + gun.angles[0] += strength * sintime; + gun.angles[1] += strength * sintime; + gun.angles[2] += strength * sintime; + gun.origin += [0,0,-1]; +} diff --git a/src/menu/Makefile b/src/menu/Makefile new file mode 100644 index 0000000..627019a --- /dev/null +++ b/src/menu/Makefile @@ -0,0 +1,4 @@ +CC=fteqcc + +all: + $(CC) progs.src diff --git a/src/menu/progs.src b/src/menu/progs.src new file mode 100644 index 0000000..953b5b8 --- /dev/null +++ b/src/menu/progs.src @@ -0,0 +1,10 @@ +#pragma target fte_5768 +//#pragma flag enable assumeint +#pragma progs_dat "../../menu.dat" +#define MENU +#define GAME_DIR "base" + +#includelist +../../../src/menu-vgui/includes.src +#endlist + diff --git a/src/progs.src b/src/progs.src new file mode 100644 index 0000000..e7760ac --- /dev/null +++ b/src/progs.src @@ -0,0 +1,3 @@ +#pragma sourcefile client/progs.src +#pragma sourcefile server/progs.src +#pragma sourcefile menu/progs.src diff --git a/src/server/Makefile b/src/server/Makefile new file mode 100644 index 0000000..627019a --- /dev/null +++ b/src/server/Makefile @@ -0,0 +1,4 @@ +CC=fteqcc + +all: + $(CC) progs.src diff --git a/src/server/damage.qc b/src/server/damage.qc new file mode 100644 index 0000000..cca3ce6 --- /dev/null +++ b/src/server/damage.qc @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2016-2022 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. +*/ diff --git a/src/server/defs.h b/src/server/defs.h new file mode 100644 index 0000000..d4f59a2 --- /dev/null +++ b/src/server/defs.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016-2022 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. +*/ + +#include "gamerules.h" +#include "items.h" + +// stubs for spawning +void info_player_deathmatch(void) +{ + +} + +void info_player_start(void) +{ +} \ No newline at end of file diff --git a/src/server/gamerules.h b/src/server/gamerules.h new file mode 100644 index 0000000..0542ff1 --- /dev/null +++ b/src/server/gamerules.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016-2022 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. +*/ + +class GameRules:CGameRules +{ + void GameRules(void); + + virtual void(NSClientPlayer) PlayerConnect; + virtual void(NSClientPlayer) PlayerDisconnect; + virtual void(NSClientPlayer) PlayerKill; + virtual void(NSClientPlayer) PlayerPostFrame; + + virtual void(NSClientPlayer) LevelDecodeParms; + virtual void(NSClientPlayer) LevelChangeParms; + virtual void(void) LevelNewParms; +}; + +class SingleplayerRules:GameRules +{ + void SingleplayerRules(void); + + /* client */ + virtual void(NSClientPlayer) PlayerSpawn; + virtual void(NSClientPlayer) PlayerDeath; +}; + +class MultiplayerRules:GameRules +{ + + int m_iIntermission; + int m_iIntermissionTime; + + void MultiplayerRules(void); + virtual void(void) FrameStart; + + /* client */ + virtual void(NSClientPlayer) PlayerSpawn; + virtual void(NSClientPlayer) PlayerDeath; + virtual bool(NSClientPlayer, string) ConsoleCommand; +}; diff --git a/src/server/gamerules.qc b/src/server/gamerules.qc new file mode 100644 index 0000000..3e9b379 --- /dev/null +++ b/src/server/gamerules.qc @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2016-2022 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 +GameRules::GameRules(void) +{ + +} + +void +GameRules::LevelDecodeParms(NSClientPlayer pp) +{ + player pl = (player)pp; + g_landmarkpos[0] = parm1; + g_landmarkpos[1] = parm2; + g_landmarkpos[2] = parm3; + pl.angles[0] = parm4; + pl.angles[1] = parm5; + pl.angles[2] = parm6; + pl.velocity[0] = parm7; + pl.velocity[1] = parm8; + pl.velocity[2] = parm9; + pl.g_items = parm10; + pl.activeweapon = parm11; + pl.flags = parm64; + + if (pl.flags & FL_CROUCHING) { + setsize(pl, VEC_CHULL_MIN, VEC_CHULL_MAX); + } else { + setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX); + } +} + +void +GameRules::LevelChangeParms(NSClientPlayer pp) +{ + player pl = (player)pp; + parm1 = g_landmarkpos[0]; + parm2 = g_landmarkpos[1]; + parm3 = g_landmarkpos[2]; + parm4 = pl.angles[0]; + parm5 = pl.angles[1]; + parm6 = pl.angles[2]; + parm7 = pl.velocity[0]; + parm8 = pl.velocity[1]; + parm9 = pl.velocity[2]; + parm64 = pl.flags; + parm10 = pl.g_items; + parm11 = pl.activeweapon; +} + +void +GameRules::LevelNewParms(void) +{ + parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 = + parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 = + parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 = + parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 = + parm29 = parm30 = 0; + parm64 = FL_CLIENT; +} + +/* we check what fields have changed over the course of the frame and network + * only the ones that have actually changed */ +void +GameRules::PlayerPostFrame(NSClientPlayer pl) +{ +} + +void +GameRules::PlayerConnect(NSClientPlayer pl) +{ + if (Plugin_PlayerConnect(pl) == FALSE) + bprint(PRINT_HIGH, sprintf("%s connected\n", pl.netname)); +} + +void +GameRules::PlayerDisconnect(NSClientPlayer pl) +{ + if (Plugin_PlayerDisconnect(pl) == FALSE) + bprint(PRINT_HIGH, sprintf("%s disconnected\n", pl.netname)); + + /* Make this unusable */ + pl.solid = SOLID_NOT; + pl.movetype = MOVETYPE_NONE; + pl.modelindex = 0; + pl.health = 0; + pl.takedamage = 0; + pl.SendFlags = -1; +} + +void +GameRules::PlayerKill(NSClientPlayer pl) +{ + Damage_Apply(pl, pl, pl.health, 0, DMG_SKIP_ARMOR); +} + +void +Game_Worldspawn(void) +{ + +} \ No newline at end of file diff --git a/src/server/gamerules_multiplayer.qc b/src/server/gamerules_multiplayer.qc new file mode 100644 index 0000000..183c87d --- /dev/null +++ b/src/server/gamerules_multiplayer.qc @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2016-2022 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 +MultiplayerRules::MultiplayerRules(void) +{ + +} + +void +MultiplayerRules::FrameStart(void) +{ + if (cvar("mp_timelimit")) + if (time >= (cvar("mp_timelimit") * 60)) { + IntermissionStart(); + } + + IntermissionCycle(); +} + +void +MultiplayerRules::PlayerDeath(NSClientPlayer pl) +{ + Plugin_PlayerObituary(g_dmg_eAttacker, g_dmg_eTarget, g_dmg_iWeapon, g_dmg_iHitBody, g_dmg_iDamage); + + /* death-counter */ + pl.deaths++; + forceinfokey(pl, "*deaths", ftos(pl.deaths)); + + /* update score-counter */ + if (pl.flags & FL_CLIENT || pl.flags & FL_MONSTER) + if (g_dmg_eAttacker.flags & FL_CLIENT) { + if (pl == g_dmg_eAttacker) + g_dmg_eAttacker.frags--; + else + g_dmg_eAttacker.frags++; + } + + /* in DM we only care about the frags */ + if (cvar("mp_fraglimit")) + if (g_dmg_eAttacker.frags >= cvar("mp_fraglimit")) { + IntermissionStart(); + } + + pl.SetMovetype(MOVETYPE_NONE); + pl.SetSolid(SOLID_NOT); + pl.SetModelindex(0); + pl.takedamage = DAMAGE_NO; + pl.armor = pl.activeweapon = pl.g_items = 0; + + pl.think = PutClientInServer; + pl.nextthink = time + 4.0f; +} + +void +MultiplayerRules::PlayerSpawn(NSClientPlayer pp) +{ + player pl = (player)pp; + /* this is where the mods want to deviate */ + entity spot; + + pl.classname = "player"; + pl.health = pl.max_health = 100; + pl.takedamage = DAMAGE_YES; + pl.solid = SOLID_SLIDEBOX; + pl.movetype = MOVETYPE_WALK; + pl.flags = FL_CLIENT; + pl.viewzoom = 1.0; + pl.model = "models/player.mdl"; + setmodel(pl, pl.model); + + setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX); + pl.velocity = [0,0,0]; + pl.gravity = __NULL__; + pl.frame = 1; + pl.SendFlags = UPDATE_ALL; + pl.customphysics = Empty; + pl.iBleeds = TRUE; + forceinfokey(pl, "*spec", "0"); + forceinfokey(pl, "*deaths", ftos(pl.deaths)); + + LevelNewParms(); + LevelDecodeParms(pl); + + spot = Spawn_SelectRandom("info_player_deathmatch"); + setorigin(pl, spot.origin); + pl.angles = spot.angles; + Weapons_RefreshAmmo(pl); + + Client_FixAngle(pl, pl.angles); +} + +float +MultiplayerRules::ConsoleCommand(NSClientPlayer pp, string cmd) +{ + tokenize(cmd); + + switch (argv(0)) { + default: + return (0); + } + + return (1); +} + +void +Game_InitRules(void) +{ + g_grMode = spawn(MultiplayerRules); + + if (cvar("sv_playerslots") == 1 || cvar("coop") == 1) { + g_grMode = spawn(SingleplayerRules); + } else { + g_grMode = spawn(MultiplayerRules); + } +} diff --git a/src/server/gamerules_singleplayer.qc b/src/server/gamerules_singleplayer.qc new file mode 100644 index 0000000..b5ce14b --- /dev/null +++ b/src/server/gamerules_singleplayer.qc @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016-2022 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 +SingleplayerRules::SingleplayerRules(void) +{ + +} + +void +SingleplayerRules::PlayerDeath(NSClientPlayer pl) +{ + pl.movetype = MOVETYPE_NONE; + pl.solid = SOLID_NOT; + pl.takedamage = DAMAGE_NO; + pl.armor = pl.activeweapon = pl.g_items = pl.weapon = 0; + pl.health = 0; + + if (cvar("coop") == 1) { + pl.think = PutClientInServer; + pl.nextthink = time + 4.0f; + } +} + +void +SingleplayerRules::PlayerSpawn(NSClientPlayer pl) +{ + pl.classname = "player"; + pl.health = pl.max_health = 100; + pl.takedamage = DAMAGE_YES; + pl.solid = SOLID_SLIDEBOX; + pl.movetype = MOVETYPE_WALK; + pl.flags = FL_CLIENT; + pl.viewzoom = 1.0; + pl.model = "models/player.mdl"; + setmodel(pl, pl.model); + pl.AddEffects(EF_NOSHADOW); + + setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX); + pl.velocity = [0,0,0]; + pl.gravity = __NULL__; + pl.frame = 1; + pl.SendFlags = UPDATE_ALL; + pl.customphysics = Empty; + pl.iBleeds = TRUE; + forceinfokey(pl, "*spec", "0"); + forceinfokey(pl, "*deaths", ftos(pl.deaths)); + + /* this is where the mods want to deviate */ + entity spot; + + if (startspot != "") { + dprint(sprintf("^3Gamerules_Spawn^7: Startspot is %s\n", startspot)); + LevelDecodeParms(pl); + setorigin(pl, Landmark_GetSpot()); + } else { + LevelNewParms(); + spot = find(world, ::classname, "info_player_start"); + setorigin(pl, spot.origin); + pl.angles = spot.angles; + } + + Weapons_RefreshAmmo(pl); + Client_FixAngle(pl, pl.angles); +} diff --git a/src/server/items.h b/src/server/items.h new file mode 100644 index 0000000..7329901 --- /dev/null +++ b/src/server/items.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016-2022 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. +*/ + +/* PICKUP ITEMS */ +class item_pickup:NSRenderableEntity +{ + int m_bFloating; + int m_iClip; + int m_iWasDropped; + int id; + void item_pickup(void); + + virtual void Spawned(void); + virtual void Touch(entity); + virtual void SetItem(int i); + virtual void Respawn(void); + virtual void SetFloating(int); + virtual void PickupRespawn(void); +}; diff --git a/src/server/items.qc b/src/server/items.qc new file mode 100644 index 0000000..c20c8df --- /dev/null +++ b/src/server/items.qc @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2016-2022 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 item_pickup::Touch(entity eToucher) +{ + if (eToucher.classname != "player") { + return; + } + + /* don't remove if AddItem fails */ + if (Weapons_AddItem((player)eToucher, id, m_iClip) == FALSE) { + return; + } + + Logging_Pickup(eToucher, this, __NULL__); + Sound_Play(other, CHAN_ITEM, "weapon.pickup"); + + UseTargets(eToucher, TRIG_TOGGLE, m_flDelay); + + if (real_owner || m_iWasDropped == 1 || cvar("sv_playerslots") == 1) { + Destroy(); + } else { + Disappear(); + ScheduleThink(PickupRespawn, 30.0f); + } +} + +void item_pickup::SetItem(int i) +{ + id = i; + m_oldModel = Weapons_GetWorldmodel(id); + SetModel(GetSpawnModel()); + SetSize([-16,-16,0], [16,16,16]); +} + +void item_pickup::SetFloating(int i) +{ + m_bFloating = rint(bound(0, m_bFloating, 1)); +} + +void +item_pickup::PickupRespawn(void) +{ + Respawn(); + Sound_Play(this, CHAN_ITEM, "item.respawn"); +} + +void item_pickup::Respawn(void) +{ + SetSolid(SOLID_TRIGGER); + SetOrigin(GetSpawnOrigin()); + botinfo = BOTINFO_WEAPON; + + /* At some points, the item id might not yet be set */ + if (GetSpawnModel()) { + SetModel(GetSpawnModel()); + } + + SetSize([-16,-16,0], [16,16,16]); + ReleaseThink(); + + if (!m_bFloating) { + DropToFloor(); + SetMovetype(MOVETYPE_TOSS); + } +} + +void +item_pickup::Spawned(void) +{ + super::Spawned(); + + Sound_Precache("item.respawn"); + Sound_Precache("weapon.pickup"); +} + +void item_pickup::item_pickup(void) +{ +} diff --git a/src/server/modelevent.qc b/src/server/modelevent.qc new file mode 100644 index 0000000..1052cff --- /dev/null +++ b/src/server/modelevent.qc @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016-2022 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 +Game_ServerModelEvent(float flTimeStamp, int iCode, string strData) +{ + switch (iCode) { + default: + Event_ServerModelEvent(flTimeStamp, iCode, strData); + break; + } +} diff --git a/src/server/progs.src b/src/server/progs.src new file mode 100644 index 0000000..8fceff3 --- /dev/null +++ b/src/server/progs.src @@ -0,0 +1,35 @@ +#pragma target fte_5768 +//#pragma flag enable assumeint +#pragma progs_dat "../../progs.dat" + +#define QWSSQC +#define SERVER + +#includelist +/* engine, then nuclide headers & functions */ +../../../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 + +/* mod specific header */ +defs.h + +../shared/include.src + +/* include the botlib if desired (optional) */ +../../../src/botlib/include.src + +/* mod specific functions */ +gamerules.qc +gamerules_singleplayer.qc +gamerules_multiplayer.qc +modelevent.qc +items.qc + +/* global server/shared code */ +../../../src/server/include.src +../../../src/shared/include.src +#endlist diff --git a/src/shared/flags.h b/src/shared/flags.h new file mode 100644 index 0000000..3dd08ba --- /dev/null +++ b/src/shared/flags.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016-2022 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. +*/ + +/* game flags */ +#define GF_SEMI_TOGGLED (int)(1<<0) +#define GF_FLASHLIGHT (int)(1<<1) +#define GF_UNUSED3 (int)(1<<2) +#define GF_UNUSED4 (int)(1<<3) +#define GF_UNUSED5 (int)(1<<4) +#define GF_UNUSED6 (int)(1<<5) +#define GF_UNUSED7 (int)(1<<6) +#define GF_UNUSED8 (int)(1<<7) +#define GF_UNUSED9 (int)(1<<8) +#define GF_UNUSED10 (int)(1<<9) +#define GF_UNUSED11 (int)(1<<10) +#define GF_UNUSED12 (int)(1<<11) +#define GF_UNUSED13 (int)(1<<12) +#define GF_UNUSED14 (int)(1<<14) +#define GF_UNUSED15 (int)(1<<16) +#define GF_UNUSED16 (int)(1<<13) +#define GF_UNUSED17 (int)(1<<17) +#define GF_UNUSED18 (int)(1<<18) +#define GF_UNUSED19 (int)(1<<19) +#define GF_UNUSED20 (int)(1<<20) +#define GF_UNUSED21 (int)(1<<21) +#define GF_UNUSED22 (int)(1<<22) +#define GF_UNUSED23 (int)(1<<23) diff --git a/src/shared/fx_blood.qc b/src/shared/fx_blood.qc new file mode 100644 index 0000000..fbcd290 --- /dev/null +++ b/src/shared/fx_blood.qc @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016-2022 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 +var float PARTICLE_BLOOD; + +void +FX_Blood_Init(void) +{ + PARTICLE_BLOOD = particleeffectnum("part_blood"); +} +#endif + +void +FX_Blood(vector pos, vector color) +{ +#ifdef SERVER + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); + WriteByte(MSG_MULTICAST, EV_BLOOD); + WriteCoord(MSG_MULTICAST, pos[0]); + WriteCoord(MSG_MULTICAST, pos[1]); + WriteCoord(MSG_MULTICAST, pos[2]); + WriteByte(MSG_MULTICAST, color[0] * 255); + WriteByte(MSG_MULTICAST, color[1] * 255); + WriteByte(MSG_MULTICAST, color[2] * 255); + msg_entity = self; + multicast(pos, MULTICAST_PVS); +#else + if (cvar("violence_hblood") <= 0) { + return; + } + + pointparticles(PARTICLE_BLOOD, pos, [0,0,0], 1); +#endif +} diff --git a/src/shared/fx_corpse.qc b/src/shared/fx_corpse.qc new file mode 100644 index 0000000..0231ba2 --- /dev/null +++ b/src/shared/fx_corpse.qc @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016-2022 Vera Visions LLC. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifdef SERVER +#define CORPSES_MAX 16 +entity g_bodies; + +void +FX_Corpse_Init(void) +{ + entity next = spawn(NSRenderableEntity); + g_bodies = next; + + for ( int i = 0; i <= CORPSES_MAX; i++ ) { + next.classname = "corpse"; + next.owner = spawn(NSRenderableEntity); + + if ( i == CORPSES_MAX ) { + next.owner = g_bodies; + } else { + next = next.owner; + } + } +} + +entity +FX_Corpse_Next(void) +{ + entity r = g_bodies; + g_bodies = g_bodies.owner; + return r; +} + +entity +FX_Corpse_Spawn(player pl, float anim) +{ + NSRenderableEntity body_next = (NSRenderableEntity)FX_Corpse_Next(); + setorigin(body_next, pl.origin + [0,0,32]); + body_next.SetMovetype(MOVETYPE_TOSS); + body_next.SetSolid(SOLID_CORPSE); + setmodel(body_next, pl.model); + setsize(body_next, VEC_HULL_MIN, VEC_HULL_MAX); + body_next.SetModelindex(pl.modelindex); + body_next.SetAngles(pl.angles); + body_next.velocity = (pl.velocity) + [0,0,120]; + body_next.colormap = pl.colormap; + body_next.SetFrame(anim); + return (entity)body_next; +} +#endif diff --git a/src/shared/include.src b/src/shared/include.src new file mode 100644 index 0000000..364f0f1 --- /dev/null +++ b/src/shared/include.src @@ -0,0 +1,10 @@ + #includelist +player.qc +weapon_common.h +weapons.h +flags.h +fx_blood.qc +fx_corpse.qc +weapons.qc +weapon_common.qc +#endlist diff --git a/src/shared/player.qc b/src/shared/player.qc new file mode 100644 index 0000000..432a487 --- /dev/null +++ b/src/shared/player.qc @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2016-2022 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. +*/ + +/* all potential SendFlags bits we can possibly send */ +enumflags +{ + PLAYER_AMMO1 = PLAYER_CUSTOMFIELDSTART, + PLAYER_AMMO2, + PLAYER_AMMO3, + PLAYER_UNUSED5, + PLAYER_UNUSED6, + PLAYER_UNUSED7, + PLAYER_UNUSED7, + PLAYER_UNUSED8 +}; + +class player:NSClientPlayer +{ + PREDICTED_INT(mode_tempstate) + +#ifdef CLIENT + virtual void(float,float) ReceiveEntity; + virtual void(void) PredictPreFrame; + virtual void(void) PredictPostFrame; +#else + virtual void(void) EvaluateEntity; + virtual float(entity, float) SendEntity; +#endif +}; + +#ifdef CLIENT +/* +================= +player::ReceiveEntity +================= +*/ +void +player::ReceiveEntity(float new, float fl) +{ + NSClientPlayer::ReceiveEntity(new, fl); + setorigin(this, origin); +} + +/* +================= +player::PredictPostFrame + +Save the last valid server values away in the _net variants of each field +so we can roll them back later. +================= +*/ +void +player::PredictPreFrame(void) +{ + NSClientPlayer::PredictPreFrame(); +} + +/* +================= +player::PredictPostFrame + +Where we roll back our values to the ones last sent/verified by the server. +================= +*/ +void +player::PredictPostFrame(void) +{ + NSClientPlayer::PredictPostFrame(); +} + +#else +void +player::EvaluateEntity(void) +{ + NSClientPlayer::EvaluateEntity(); +} + +/* +================= +player::SendEntity +================= +*/ +float +player::SendEntity(entity ePEnt, float fChanged) +{ + /* don't broadcast invisible players */ + if (IsFakeSpectator() && ePEnt != this) + return (0); + if (!GetModelindex() && ePEnt != this) + return (0); + + fChanged = OptimiseChangedFlags(ePEnt, fChanged); + + WriteByte(MSG_ENTITY, ENT_PLAYER); + WriteFloat(MSG_ENTITY, fChanged); + + /* the generic client attributes */ + NSClientPlayer::SendEntity(ePEnt, fChanged); + return (1); +} +#endif diff --git a/src/shared/weapon_common.h b/src/shared/weapon_common.h new file mode 100644 index 0000000..1aac488 --- /dev/null +++ b/src/shared/weapon_common.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2016-2022 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. +*/ + +#ifndef NEW_INVENTORY +/* for AI identification purposes */ +typedef enum +{ + WPNTYPE_INVALID, /* no logic */ + WPNTYPE_RANGED, /* will want to keep their distance mostly */ + WPNTYPE_THROW, /* has to keep some distance, but not too far */ + WPNTYPE_CLOSE, /* have to get really close */ + WPNTYPE_FULLAUTO, /* for things that need to be held down */ + WPNTYPE_SEMI /* semi automatic */ +} weapontype_t; + +typedef struct +{ + string name; + int id; /* bitflag id */ + int slot; + int slot_pos; + int allow_drop; + int weight; /* required for bestweapon */ + void(void) precache; + string() wmodel; + string() deathmsg; + + /* player specific */ + string(player) pmodel; + float(player) aimanim; + weapontype_t(player) type; /* required for bot-AI */ + void(player) draw; + void(player) holster; + void(player) primary; + void(player) secondary; + void(player) reload; + void(player) release; + int(player, int, int) pickup; + void(player) updateammo; + + void(player, int) predraw; /* predraw... */ + void(player) postdraw; /* postdraw... */ + + int(player) isempty; /* kinda handy */ + void(player, int, vector, float) hudpic; +} weapon_t; + +void Weapons_Holster(player pl); +void Weapons_Primary(player pl); +void Weapons_Secondary(player pl); +void Weapons_Reload(player pl); +void Weapons_Release(player pl); +void Weapons_PreDraw(player pl, int); + +float Weapons_GetAim(player, int); +int Weapons_IsEmpty(player, int); +void Weapons_DrawCrosshair(player pl); +void Weapons_MakeVectors(player pl); +vector Weapons_GetCameraPos(player pl); +void Weapons_ViewAnimation(player pl, int); +void Weapons_ViewPunchAngle(player pl, vector); +int Weapons_IsPresent(player, int); +void Weapons_UpdateAmmo(player, int, int, int); +int Weapons_GetAnimation(player pl); +void Weapons_EnableModel(void); +void Weapons_DisableModel(void); +weapontype_t Weapons_GetType(player, int); + +void Weapons_SetLeftModel(string); +void Weapons_SetRightModel(string); + +void Weapons_SetRightGeomset(string); +void Weapons_SetLeftGeomset(string); + +/* compat */ +void Weapons_SetGeomset(string); +void Weapons_SetModel(string); + +void Weapons_Sound(entity, float, string); + +#ifdef CLIENT +string Weapons_GetPlayermodel(player, int); +void Weapons_HUDPic(player, int, int, vector, float); +#endif +#else +#endif \ No newline at end of file diff --git a/src/shared/weapon_common.qc b/src/shared/weapon_common.qc new file mode 100644 index 0000000..154aba0 --- /dev/null +++ b/src/shared/weapon_common.qc @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2016-2022 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. +*/ + +#ifndef NEW_INVENTORY +var int g_weapon_weights[g_weapons.length]; + +#ifdef CLIENT +var int g_weapon_order[g_weapons.length]; +#endif + +void +Weapons_Init(void) +{ + /* in the future we'll have no internal weapon table, then this will fill + * one up... */ + /*searchhandle sh; + filestream fh; + string line; + sh = search_begin("scripts/weapon_*.txt", TRUE, TRUE); + for (int i = 0; i < search_getsize(sh); i++) { + fh = fopen(search_getfilename(sh, i), FILE_READ); + if (fh < 0) { + continue; + } + + while ((line = fgets(fh))) { + int w = tokenize(line); + switch (argv(0)) { + case "name": + break; + case "slot": + break; + case "slot_pos": + break; + } + } + fclose(fh); + }*/ + + for (int i = 0; i < g_weapons.length; i++) + if (g_weapons[i].precache != __NULL__) + g_weapons[i].precache(); + + /* check our weapon weights */ + int max = 0; + for (int i = 0; i < g_weapons.length; i++) + if (g_weapons[i].weight > max) + max = g_weapons[i].weight; + + /* don't bother building the list if we've got no weights */ + if (max <= 0) + return; + + /* position in the weight array */ + int w = 0; + + /* loop through all weights */ + for (int b = 0; b <= max; b++) { + /* loop through all weapons */ + for (int i = 0; i < g_weapons.length; i++) { + /* if we've found a valid weight, add the weapon to the list */ + if (g_weapons[i].weight == b) { + g_weapon_weights[w] = i; + w++; + } + } + } + +#if 0 + for (int i = 0; i < g_weapons.length; i++) + print(sprintf("Weapon-Weight order: %s, %i\n", g_weapons[g_weapon_weights[i]].name, i)); +#endif + +#ifdef CLIENT + /* build our slot-order table */ + int st = 0; + + int max_slots = 0; + for (int i = 0; i < g_weapons.length; i++) + if (g_weapons[i].slot > max_slots) + max_slots = g_weapons[i].slot; + int max_pos = 0; + for (int i = 0; i < g_weapons.length; i++) + if (g_weapons[i].slot_pos > max_pos) + max_pos = g_weapons[i].slot_pos; + + /* loop through all slots */ + for (int s = 0; s <= max_slots; s++) { + /* loop through all positions */ + for (int p = 0; p < max_pos; p++) { + /* loop through all the weapons */ + for (int i = 0; i < g_weapons.length; i++) { + if (g_weapons[i].slot == s && g_weapons[i].slot_pos == p) { + g_weapon_order[st] = i; + st++; + } + } + } + } +#if 0 + for (int i = 0; i < g_weapons.length; i++) + print(sprintf("Weapon-List order: %s, %i\n", g_weapons[g_weapon_order[i]].name, i)); +#endif +#endif +} + +void +Weapons_SetLeftModel(string mdl) +{ +#ifdef CLIENT + setmodel(pSeat->m_eViewModelL, mdl); + setsize(pSeat->m_eViewModelL, [0,0,0], [0,0,0]); + pSeat->m_eViewModelL.effects |= EF_NOSHADOW; +#endif +} +void +Weapons_SetRightModel(string mdl) +{ +#ifdef CLIENT + setmodel(pSeat->m_eViewModel, mdl); + setsize(pSeat->m_eViewModel, [0,0,0], [0,0,0]); + pSeat->m_eViewModel.effects |= EF_NOSHADOW; +#endif +} + +void +Weapons_SetModel(string mdl) +{ + Weapons_SetRightModel(mdl); + Weapons_SetLeftModel(""); +} + +void +Weapons_SetRightGeomset(string set) +{ +#ifdef CLIENT + setcustomskin(pSeat->m_eViewModel, "", set); +#endif +} +void +Weapons_SetLeftGeomset(string set) +{ +#ifdef CLIENT + setcustomskin(pSeat->m_eViewModelL, "", set); +#endif +} + +void +Weapons_SetGeomset(string set) +{ + Weapons_SetRightGeomset(set); +} + +void +Weapons_Draw(player pl) +{ + int i = pl.activeweapon; + + /* In case the previous weapon hid the model */ + Weapons_EnableModel(); + + pl.w_attack_next = 0.5f; + pl.w_idle_next = 2.5f; + pl.viewzoom = 1.0f; + + /* we're meant to respawn when we're dead, don't unset! */ + if (pl.health > 0) { + pl.think = __NULL__; + pl.nextthink = 0.0f; + } + + /* make sure this is all wiped */ + pl.a_ammo1 = pl.a_ammo2 = pl.a_ammo3 = 0; + + if (g_weapons[i].draw != __NULL__) + g_weapons[i].draw(pl); + + if (g_weapons[i].updateammo != __NULL__) + g_weapons[i].updateammo(pl); + + pl.gflags |= GF_SEMI_TOGGLED; +} + +void +Weapons_Holster(player pl) +{ + int i = pl.activeweapon; + + if (g_weapons[i].holster != __NULL__) + g_weapons[i].holster(pl); +} + +void +Weapons_Primary(player pl) +{ + int i = pl.activeweapon; + + if (pl.gflags & GF_SEMI_TOGGLED) + return; + + if (g_weapons[i].primary != __NULL__) + g_weapons[i].primary(pl); + + if (g_weapons[i].updateammo != __NULL__) + g_weapons[i].updateammo(pl); +} + +void +Weapons_AmmoUpdate(entity target) +{ + player pl = (player)target; + int i = pl.activeweapon; + + if (g_weapons[i].updateammo != __NULL__) + g_weapons[i].updateammo(pl); + +} + +void +Weapons_Secondary(player pl) +{ + int i = pl.activeweapon; + + if (g_weapons[i].secondary != __NULL__) + g_weapons[i].secondary(pl); + + if (g_weapons[i].updateammo != __NULL__) + g_weapons[i].updateammo(pl); +} + +void +Weapons_Reload(player pl) +{ + int i = pl.activeweapon; + + if (g_weapons[i].reload != __NULL__) + g_weapons[i].reload(pl); + + if (g_weapons[i].updateammo != __NULL__) + g_weapons[i].updateammo(pl); +} + +void +Weapons_Release(player pl) +{ + int i = pl.activeweapon; + + if (g_weapons[i].release != __NULL__) + g_weapons[i].release(pl); + + pl.gflags &= ~GF_SEMI_TOGGLED; +} + +void +Weapons_PreDraw(player pl, int thirdperson) +{ + int i = pl.activeweapon; + + if (g_weapons[i].predraw != __NULL__) + g_weapons[i].predraw(pl, thirdperson); +} + +int +Weapons_IsEmpty(player pl, int w) +{ + int r = 0; + + entity oself = self; + self = pl; + + if (g_weapons[w].isempty != __NULL__) + r = g_weapons[w].isempty(pl); + + self = oself; + + return (r); +} + + +weapontype_t +Weapons_GetType(player pl, int w) +{ + weapontype_t r = WPNTYPE_INVALID; + + entity oself = self; + self = pl; + + if (g_weapons[w].type != __NULL__) + r = g_weapons[w].type(pl); + + self = oself; + + return (r); +} + +void +Weapons_DrawCrosshair(player pl) +{ + int i = pl.activeweapon; + + if (g_weapons[i].postdraw != __NULL__) + g_weapons[i].postdraw(pl); +} + +string +Weapons_GetWorldmodel(int id) +{ + if (g_weapons[id].wmodel != __NULL__) + return g_weapons[id].wmodel(); + + return ""; +} + +string +Weapons_GetPlayermodel(player pl, int id) +{ + if (g_weapons[id].pmodel != __NULL__) + return g_weapons[id].pmodel(pl); + + return ""; +} + +string +Weapons_GetDeathmessage(int id) +{ + if (g_weapons[id].deathmsg != __NULL__) + return g_weapons[id].deathmsg(); + + return ""; +} + +float +Weapons_GetAim(player pl, int id) +{ + if (g_weapons[id].aimanim != __NULL__) + return g_weapons[id].aimanim(pl); + + return (0); +} + +#ifdef CLIENT +void +Weapons_HUDPic(player pl, int id, int s, vector pos, float a) +{ + if (g_weapons[id].hudpic != __NULL__) + g_weapons[id].hudpic(pl, s, pos, a); +} +#endif + +void +Weapons_MakeVectors(player pl) +{ +#ifdef SERVER + makevectors(pl.v_angle); +#else + makevectors(view_angles); +#endif +} + +vector +Weapons_GetCameraPos(player pl) +{ +#ifdef SERVER + return (pl.origin + pl.view_ofs); +#else + return getproperty(VF_ORIGIN); +#endif +} + +void +Weapons_ViewAnimation(player pl, int i) +{ +#if 0 + View_PlayAnimation(i); +#endif + pl.weaponframe = i; + pl.weapontime = 0.0f; +} + +#ifdef CLIENT +int View_GetAnimation(void); +#endif + +int +Weapons_GetAnimation(player pl) +{ + return pl.weaponframe; +} + +void +Weapons_ViewPunchAngle(player pl, vector add) +{ + pl.punchangle += add; +} + +int +Weapons_IsPresent(player pl, int w) +{ + if (pl.g_items & g_weapons[w].id) { + return (1); + } else { + return (0); + } +} + +void +Weapons_EnableModel(void) +{ +#ifdef CLIENT + View_EnableViewmodel(); +#endif +} + +void +Weapons_DisableModel(void) +{ +#ifdef CLIENT + View_DisableViewmodel(); +#endif +} + +/* +================= +Weapons_UpdateAmmo + +Sets .a_ammoX fields and clamps them so they can be networked as a single byte. +================= +*/ +void +Weapons_UpdateAmmo(player pl, int a1, int a2, int a3) +{ + /* no change */ + if (a1 == -1) + a1 = pl.a_ammo1; + if (a2 == -1) + a2 = pl.a_ammo2; + if (a3 == -1) + a3 = pl.a_ammo3; + + /* networked as bytes, since we don't need more. Clamp to avoid errors */ + pl.a_ammo1 = a1; + pl.a_ammo2 = a2; + pl.a_ammo3 = a3; +} + +void +Weapons_Sound(entity pl, float channel, string snd) +{ +#if 0 +#ifdef SERVER + float prev = pl.dimension_see; + pl.dimension_see=0; + Sound_Play(pl, channel, snd); + pl.dimension_see = prev; +#else + /* client side == immediately */ + Sound_Play(pl, channel, snd); +#endif +#else + #ifdef SERVER + Sound_Play(pl, channel, snd); + #endif +#endif +} +#endif \ No newline at end of file diff --git a/src/shared/weapons.h b/src/shared/weapons.h new file mode 100644 index 0000000..cf3578e --- /dev/null +++ b/src/shared/weapons.h @@ -0,0 +1,20 @@ +/* + * 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. +*/ + +enum +{ + WEAPON_NONE +}; \ No newline at end of file diff --git a/src/shared/weapons.qc b/src/shared/weapons.qc new file mode 100644 index 0000000..bdadb62 --- /dev/null +++ b/src/shared/weapons.qc @@ -0,0 +1,20 @@ +/* + * 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. +*/ + +weapon_t w_null = {}; +weapon_t g_weapons[] = { + w_null +}; diff --git a/zpak001.pk3dir/def/spawns.def b/zpak001.pk3dir/def/spawns.def new file mode 100644 index 0000000..5dab18a --- /dev/null +++ b/zpak001.pk3dir/def/spawns.def @@ -0,0 +1,116 @@ +entityDef info_player_start +{ + editor_mins "-16 -16 -36" + editor_maxs "16 16 36" + editor_description "Singleplayer Spawn Point" + editor_color "1 0 0" + + spawnclass NSSpawnPoint +} + +entityDef mp_deathmatch_spawn +{ + editor_mins "-16 -16 -36" + editor_maxs "16 16 36" + editor_description "Deathmatch Spawn Point" + editor_color "1 0 0" + + spawnclass NSSpawnPoint +} + +entityDef mp_teamdeathmatch_spawn +{ + editor_mins "-16 -16 -36" + editor_maxs "16 16 36" + editor_description "Team Deathmatch Spawn Point" + editor_color "1 0 0" + + spawnclass NSSpawnPoint +} + +entityDef mp_retrieval_spawn_allied +{ + editor_mins "-16 -16 -36" + editor_maxs "16 16 36" + editor_description "Retrieval: Allied Spawn" + editor_color "1 0 0" + + + spawnclass NSSpawnPoint +} + +entityDef mp_retrieval_spawn_axis +{ + editor_mins "-16 -16 -36" + editor_maxs "16 16 36" + editor_description "Retrieval: Axis Spawn" + editor_color "1 0 0" + + + spawnclass NSSpawnPoint +} + +entityDef mp_searchanddestroy_spawn_allied +{ + editor_mins "-16 -16 -36" + editor_maxs "16 16 36" + editor_description "Search & Destroy: Allied Spawn" + editor_color "1 0 0" + + + spawnclass NSSpawnPoint +} + +entityDef mp_searchanddestroy_spawn_axis +{ + editor_mins "-16 -16 -36" + editor_maxs "16 16 36" + editor_description "Search & Destroy: Axis Spawn" + editor_color "1 0 0" + + + spawnclass NSSpawnPoint +} + +entityDef misc_model +{ + editor_mins "-16 -16 -36" + editor_maxs "16 16 36" + editor_description "Decorative Model" + editor_color "1 0 0" + + spawnclass NSRenderableEntity +} + +entityDef script_model +{ + editor_mins "-16 -16 -36" + editor_maxs "16 16 36" + editor_description "Scripted Model" + editor_color "1 0 0" + + spawnclass NSRenderableEntity +} + +entityDef func_static +{ + editor_mins "-16 -16 -36" + editor_maxs "16 16 36" + editor_description "Static Brush Model" + editor_color "1 0 0" + + spawnclass func_wall +} + +entityDef script_brushmodel +{ + editor_mins "-16 -16 -36" + editor_maxs "16 16 36" + editor_description "Scripted Brush Model" + editor_color "1 0 0" + + spawnclass func_wall +} + + + diff --git a/zpak001.pk3dir/def/weapons.def b/zpak001.pk3dir/def/weapons.def new file mode 100644 index 0000000..1d113af --- /dev/null +++ b/zpak001.pk3dir/def/weapons.def @@ -0,0 +1,51 @@ +entityDef item_ammo_stielhandgranate_open +{ + editor_color ".3 .3 1" + editor_mins "-16 -16 -16" + editor_maxs "16 16 16" + + model "xmodel/ammo_stielhandgranate1" + spawnclass NSItem +} + + +entityDef item_ammo_stielhandgranate_closed +{ + editor_color ".3 .3 1" + editor_mins "-16 -16 -16" + editor_maxs "16 16 16" + model "xmodel/ammo_stielhandgranate2" + spawnclass NSItem +} + + +entityDef item_health_small +{ + editor_color ".3 .3 1" + editor_mins "-16 -16 -16" + editor_maxs "16 16 16" + + model "xmodel/health_small" + spawnclass NSItem +} + +entityDef item_health +{ + editor_color ".3 .3 1" + editor_mins "-16 -16 -16" + editor_maxs "16 16 16" + + model xmodel/health_medium" + spawnclass NSItem +} + + +entityDef item_health_large +{ + editor_color ".3 .3 1" + editor_mins "-16 -16 -16" + editor_maxs "16 16 16" + + model xmodel/health_large" + spawnclass NSItem +}