Added a stripped down base game tree, which should pose as a decent

entry-point for starters into the SDK
This commit is contained in:
Marco Cawthorne 2020-12-22 01:56:44 +01:00
parent d04d2a83ef
commit 86daed3eec
55 changed files with 3006 additions and 14 deletions

View File

@ -2,6 +2,7 @@
set -e
FTE_MAKEFILE=./src/engine/engine/Makefile
BUILD_SDL2=0
mkdir -p ./bin
@ -17,9 +18,16 @@ else
cd ./engine/engine
fi
make -j $(nproc) makelibs FTE_TARGET=SDL2
make -j $(nproc) m-rel FTE_TARGET=SDL2
cp -v ./release/fteqw-sdl2 ../../../bin/fteqw
if [ "$BUILD_SDL2" -eq 1 ]; then
make -j $(nproc) makelibs FTE_TARGET=SDL2
make -j $(nproc) m-rel FTE_TARGET=SDL2
cp -v ./release/fteqw-sdl2 ../../../bin/fteqw
else
make -j $(nproc) makelibs
make -j $(nproc) m-rel
cp -v ./release/fteqw ../../../bin/fteqw
fi
make -j $(nproc) sv-rel
cp -v ./release/fteqw-sv ../../../bin/fteqw-sv
make -j $(nproc) qcc-rel

31
default.fmf Normal file
View File

@ -0,0 +1,31 @@
FTEMANIFEST 1
GAME base
NAME "Nuclide"
BASEGAME platform
BASEGAME logos
BASEGAME base
// custom game menu variables
-set gameinfo_game "Nuclide Base"
-set gameinfo_gamedir "base"
-set gameinfo_fallback_dir ""
-set gameinfo_mpentity "info_player_deathmatch"
-set gameinfo_size "1000080"
-set gameinfo_url_info "www.vera-visions.com"
-set gameinfo_version "1.0"
-set gameinfo_url_dl ""
-set gameinfo_type "Both"
-set gameinfo_nomodels 0
-set gameinfo_gamedll "progs.dat"
-set gameinfo_startmap "c0a0"
-set gameinfo_trainingmap "map t0a0"
-set gameinfo_cldll 1
-set gameinfo_hlversion "1110"
-set gameinfo_svonly "0"
-set gameinfo_menutrack ""
-set gameinfo_chatroom "lobby"
// you don't really want to change these
RTCBROKER master.frag-net.com:27950
PROTOCOLNAME "Nuclide"
MAINCONFIG nuclide.cfg

View File

@ -1,12 +1,20 @@
all:
make menu
make base
make plugs
make games
make mods
make plugs
menu:
cd menu-fn && $(MAKE)
base:
cd client/base && $(MAKE)
cd server/base && $(MAKE)
plugs:
cd plugins && $(MAKE)
games:
cd client/valve && $(MAKE)
cd server/valve && $(MAKE)
@ -16,8 +24,6 @@ games:
cd server/rewolf && $(MAKE)
cd client/gearbox && $(MAKE)
cd server/gearbox && $(MAKE)
#cd client/wastes && $(MAKE)
#cd server/wastes && $(MAKE)
mods:
cd client/cstrike && $(MAKE)
@ -28,6 +34,3 @@ mods:
cd server/poke646 && $(MAKE)
cd client/hunger && $(MAKE)
cd server/hunger && $(MAKE)
plugs:
cd plugins && $(MAKE)

5
src/client/base/Makefile Normal file
View File

@ -0,0 +1,5 @@
CC=fteqcc
all:
mkdir -p ../../../base/data.pk3dir
$(CC) progs.src

27
src/client/base/cmds.c Normal file
View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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
Game_ConsoleCommand(void)
{
switch(argv(0)) {
default:
return FALSE;
}
return TRUE;
}

105
src/client/base/defs.h Normal file
View File

@ -0,0 +1,105 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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_hud_color;
vector g_hudmins;
vector g_hudres;
struct
{
/* viewmodel stuff */
entity m_eViewModel;
entity m_eMuzzleflash;
int m_iVMBones;
int m_iVMEjectBone;
int m_iLastWeapon;
int m_iOldWeapon;
float m_flBobTime;
float m_flBob;
/* damage overlay */
float m_flDamageAlpha;
vector m_vecDamagePos;
/* +zoomin cmd */
int m_iZoomed;
float m_flZoomTime;
/* player fields */
entity m_ePlayer;
vector m_vecPredictedOrigin;
vector m_vecPredictedOriginOld;
vector m_vecPredictedVelocity;
float m_flPredictedFlags;
/* camera fields */
vector m_vecCameraOrigin;
vector m_vecCameraAngle;
float m_flCameraTime;
/* hud.c */
int m_iHealthOld;
float m_flHealthAlpha;
int m_iArmorOld;
float m_flArmorAlpha;
int m_iAmmo1Old;
float m_flAmmo1Alpha;
int m_iAmmo2Old;
float m_flAmmo2Alpha;
int m_iAmmo3Old;
float m_flAmmo3Alpha;
int m_iPickupWeapon;
float m_flPickupAlpha;
int m_iScoresVisible;
int m_iHUDWeaponSelected;
float m_flHUDWeaponSelectTime;
/* centerprint related */
float m_flCenterprintAlpha;
float m_flCenterprintTime;
float m_iCenterprintLines;
string m_strCenterprintBuffer[18];
/* chat related */
float m_flPrintTime;
string m_strPrintBuffer[5];
int m_iPrintLines;
int m_iInputAttack2;
int m_iInputReload;
int m_iInputUse;
int m_iInputDuck;
float m_flInputBlockTime;
/* fading */
float m_flFadeDuration;
float m_flFadeHold;
float m_flFadeMaxAlpha;
float m_flFadeStyle;
float m_flFadeAlpha;
float m_flFadeTime;
vector m_vecFadeColor;
int m_iFadeActive;
/* shake */
float m_flShakeFreq;
float m_flShakeDuration;
float m_flShakeTime;
float m_flShakeAmp;
entity m_pWeaponFX;
} g_seats[4], *pSeat;

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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
Game_Entity_Update(float id, float new)
{
switch (id) {
default:
return FALSE;
}
return TRUE;
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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_Parse_Event(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;
}
}

34
src/client/base/hud.c Normal file
View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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.
*/
/* main entry */
void
HUD_Init(void)
{
}
/* main entry */
void
HUD_Draw(void)
{
}
/* specatator main entry */
void
HUD_DrawSpectator(void)
{
// FIXME
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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)
{
}

37
src/client/base/init.c Normal file
View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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.
*/
/*
=================
Client_Init
Comparable to worldspawn in SSQC in that it's mostly used for precaches
=================
*/
void
Client_Init(float apilevel, string enginename, float engineversion)
{
}
void
Client_InitDone(void)
{
}
void
Game_RendererRestarted(string rstr)
{
}

29
src/client/base/input.c Normal file
View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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_Input(void)
{
if (input_buttons & INPUT_BUTTON0) {
Weapons_Primary();
} else if (input_buttons & INPUT_BUTTON4) {
Weapons_Reload();
} else if (input_buttons & INPUT_BUTTON3) {
Weapons_Secondary();
} else {
Weapons_Release();
}
}

149
src/client/base/player.c Normal file
View File

@ -0,0 +1,149 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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
Player_PreDraw(base_player pl, int thirdperson)
{
/* Handle the flashlights... */
if (pl.gflags & GF_FLASHLIGHT) {
vector src;
vector ang;
if (pl.entnum != player_localentnum) {
src = pl.origin + pl.view_ofs;
ang = [pl.pitch, pl.angles[1], pl.angles[2]];
} else {
src = pSeat->m_vecPredictedOrigin + [0,0,-8];
ang = view_angles;
}
makevectors(ang);
traceline(src, src + (v_forward * 8096), MOVE_NORMAL, pl);
if (serverkeyfloat("*bspversion") == BSPVER_HL) {
dynamiclight_add(trace_endpos + (v_forward * -2), 128, [1,1,1]);
} else {
float p = dynamiclight_add(src, 512, [1,1,1], 0, "textures/flashlight");
dynamiclight_set(p, LFIELD_ANGLES, ang);
dynamiclight_set(p, LFIELD_FLAGS, 3);
}
}
}
void
Player_ReceiveEntity(float new)
{
float fl;
player pl = (player)self;
if (new == TRUE) {
spawnfunc_player();
pl.classname = "player";
pl.solid = SOLID_SLIDEBOX;
pl.drawmask = MASK_ENGINE;
pl.customphysics = Empty;
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
} else {
/* Go through all the physics code between the last received frame
* and the newest frame and keep the changes this time around instead
* of rolling back, because we'll apply the new server-verified values
* right after anyway. */
/* FIXME: splitscreen */
if (pl.entnum == player_localentnum) {
/* FIXME: splitscreen */
pSeat = &g_seats[0];
for (int i = pl.sequence+1; i <= servercommandframe; i++) {
/* ...maybe the input state is too old? */
if (!getinputstate(i)) {
break;
}
input_sequence = i;
PMove_Run();
}
/* any differences in things that are read below are now
* officially from prediction misses. */
}
}
/* seed for our prediction table */
pl.sequence = servercommandframe;
fl = readfloat();
/* HACK: we need to make this more reliable */
if (fl == UPDATE_ALL) {
/* we respawned */
pl.gravity = __NULL__;
}
if (fl & PLAYER_MODELINDEX)
pl.modelindex = readshort();
if (fl & PLAYER_ORIGIN) {
pl.origin[0] = readcoord();
pl.origin[1] = readcoord();
}
if (fl & PLAYER_ORIGIN_Z)
pl.origin[2] = readcoord();
if (fl & PLAYER_ANGLES_X)
pl.pitch = readfloat();
if (fl & PLAYER_ANGLES_Y)
pl.angles[1] = readfloat();
if (fl & PLAYER_ANGLES_Z)
pl.angles[2] = readfloat();
if (fl & PLAYER_VELOCITY) {
pl.velocity[0] = readcoord();
pl.velocity[1] = readcoord();
}
if (fl & PLAYER_VELOCITY_Z)
pl.velocity[2] = readcoord();
if (fl & PLAYER_FLAGS) {
pl.flags = readfloat();
pl.gflags = readfloat();
}
if (fl & PLAYER_WEAPON)
pl.activeweapon = readbyte();
if (fl & PLAYER_ITEMS)
pl.g_items = (__variant)readfloat();
if (fl & PLAYER_HEALTH)
pl.health = readbyte();
if (fl & PLAYER_ARMOR)
pl.armor = readbyte();
if (fl & PLAYER_MOVETYPE)
pl.movetype = readbyte();
if (fl & PLAYER_VIEWOFS)
pl.view_ofs[2] = readfloat();
if (fl & PLAYER_BASEFRAME)
pl.baseframe = readbyte();
if (fl & PLAYER_FRAME) {
pl.frame = readbyte();
pl.frame1time = 0.0f;
pl.frame2time = 0.0f;
}
if (fl & PLAYER_AMMO1)
pl.a_ammo1 = readbyte();
if (fl & PLAYER_AMMO2)
pl.a_ammo2 = readbyte();
if (fl & PLAYER_AMMO3)
pl.a_ammo3 = readbyte();
setorigin(pl, pl.origin);
}

25
src/client/base/predict.c Normal file
View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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
GamePredict_PreFrame(player pl)
{
}
void
GamePredict_PostFrame(player pl)
{
}

35
src/client/base/progs.src Executable file
View File

@ -0,0 +1,35 @@
#pragma target fte
#pragma progs_dat "../../../base/data.pk3dir/csprogs.dat"
#define CSQC
#define CLIENT
#define CLASSIC_VGUI
#define GS_RENDERFX
#includelist
../../shared/fteextensions.qc
../../shared/defs.h
../base/defs.h
../defs.h
../../vgui/include.src
../../gs-entbase/client.src
../../gs-entbase/shared.src
../../shared/base/include.src
../base/predict.c
../base/init.c
../base/player.c
../base/entities.c
../base/cmds.c
../base/game_event.c
../base/view.c
../base/hud.c
../base/hud_weaponselect.c
../base/scoreboard.c
../base/input.c
../include.src
../../shared/include.src
#endlist

View File

@ -0,0 +1,168 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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_20;
drawstring(pos + [0,-18], "Teams", [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE);
drawstring(pos + [124,-18], "kills / deaths", [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE);
drawstring(pos + [240,-18], "latency", [20,20], 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)), [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE);
temp = serverkey(sprintf("teamscore_%i", t));
l = stringwidth(temp, FALSE, [20,20]);
drawstring(pos + [150-l, 0], temp, [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE);
drawstring(pos + [158, 0], "wins", [20,20], 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"), [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
drawstring(pos + [154,0], "/", [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
/* Get the kills and align them left to right */
temp = getplayerkeyvalue(i, "frags");
l = stringwidth(temp, FALSE, [20,20]);
drawstring(pos + [150 - l,0], temp, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
/* Deaths are right to left aligned */
temp = getplayerkeyvalue(i, "*deaths");
drawstring(pos + [165,0], temp, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
/* Get the latency and align it left to right */
temp = getplayerkeyvalue(i, "ping");
l = stringwidth(temp, FALSE, [20,20]);
drawstring(pos + [290 - l,0], temp, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
pos[1] += 20;
}
pos[1] += 12;
}
drawfont = FONT_CON;
}
void
Scores_DrawNormal(player pl, vector pos)
{
drawfill(pos, [290, 1], SCORE_LINE_C, 1.0f, DRAWFLAG_ADDITIVE);
drawfont = FONT_20;
drawstring(pos + [0,-18], "Player", [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE);
drawstring(pos + [124,-18], "kills / deaths", [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE);
drawstring(pos + [240,-18], "latency", [20,20], 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"), [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
drawstring(pos + [154,0], "/", [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
/* Get the kills and align them left to right */
kills = getplayerkeyvalue(i, "frags");
l = stringwidth(kills, FALSE, [20,20]);
drawstring(pos + [150 - l,0], kills, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
/* Deaths are right to left aligned */
deaths = getplayerkeyvalue(i, "*deaths");
drawstring(pos + [165,0], deaths, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
/* Get the latency and align it left to right */
ping = getplayerkeyvalue(i, "ping");
l = stringwidth(ping, FALSE, [20,20]);
drawstring(pos + [290 - l,0], ping, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
pos[1] += 20;
}
drawfont = 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 (serverkeyfloat("teams") > 0) {
Scores_DrawTeam(pl, pos);
} else {
Scores_DrawNormal(pl, pos);
}
}

51
src/client/base/view.c Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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
View_UpdateWeapon(entity vm, entity mflash)
{
player pl = (player)pSeat->m_ePlayer;
/* only bother upon change */
if (pSeat->m_iLastWeapon == pl.activeweapon) {
return;
}
pSeat->m_iOldWeapon = pSeat->m_iLastWeapon;
pSeat->m_iLastWeapon = pl.activeweapon;
if (!pl.activeweapon) {
return;
}
/* hack, we changed the wep, move this into Game_Input/PMove */
Weapons_Draw();
/* we forced a weapon call outside the prediction,
* thus we need to update all the net variables to
* make sure these updates are recognized. this is
* vile but it'll have to do for now */
pl.net_w_attack_next = pl.w_attack_next;
pl.net_w_idle_next = pl.w_idle_next;
pl.net_viewzoom = pl.viewzoom;
pl.net_weapontime = pl.weapontime;
/* figure out when the attachments start. in FTE attachments for
* HLMDL are treated as bones. they start at numbones + 1 */
skel_delete(mflash.skeletonindex);
mflash.skeletonindex = skel_create(vm.modelindex);
pSeat->m_iVMBones = skel_get_numbones(mflash.skeletonindex) + 1;
pSeat->m_iVMEjectBone = pSeat->m_iVMBones + 1;
}

View File

@ -65,7 +65,6 @@ void
SkyCamera_Setup(vector org)
{
if (g_skyscale != 0 && g_skypos) {
vector porg;
vector realpos;
if (autocvar_dev_skyscale) {

5
src/server/base/Makefile Normal file
View File

@ -0,0 +1,5 @@
CC=fteqcc
all:
mkdir -p ../../../base/data.pk3dir
$(CC) progs.src

75
src/server/base/client.c Normal file
View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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.
*/
/* called every input frame */
void
Game_RunClientCommand(void)
{
Footsteps_Update();
PMove_Run();
}
/* custom chat packet */
void
SV_SendChat(entity sender, string msg, entity eEnt, float fType)
{
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, fType == 0 ? EV_CHAT:EV_CHAT_TEAM);
WriteByte(MSG_MULTICAST, num_for_edict(sender) - 1);
WriteByte(MSG_MULTICAST, sender.team);
WriteString(MSG_MULTICAST, msg);
if (eEnt) {
msg_entity = eEnt;
multicast([0,0,0], MULTICAST_ONE);
} else {
multicast([0,0,0], MULTICAST_ALL);
}
localcmd(sprintf("echo [SERVER] %s: %s\n", sender.netname, msg));
}
/* client cmd overrides happen here */
void
Game_ParseClientCommand(string cmd)
{
tokenize(cmd);
if (argv(1) == "timeleft") {
string msg;
string timestring;
float timeleft;
timeleft = cvar("mp_timelimit") - (time / 60);
timestring = Vox_TimeToString(timeleft);
msg = sprintf("we have %s minutes remaining", timestring);
Vox_Singlecast(self, msg);
return;
}
if (argv(0) == "say") {
SV_SendChat(self, argv(1), world, 0);
return;
} else if (argv(0) == "say_team") {
entity a;
for (a = world; (a = find(a, ::classname, "player"));) {
if (a.team == self.team) {
SV_SendChat(self, argv(1), a, 1);
}
}
return;
}
clientcommand(self, cmd);
}

166
src/server/base/damage.c Normal file
View File

@ -0,0 +1,166 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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.
*/
/* generic function that applies damage, pain and suffering */
void
Damage_Apply(entity t, entity c, float dmg, int w, int type)
{
base_player tp = (base_player)t;
CGameRules rules = (CGameRules)g_grMode;
if (t.flags & FL_GODMODE) {
return;
}
/* already dead, please avoid recursion */
if (t.health <= 0) {
return;
}
/* skip armor */
if not (type & DMG_SKIP_ARMOR)
if (tp.armor && dmg > 0) {
float flArmor;
float flNewDamage;
flNewDamage = dmg * 0.2;
flArmor = (dmg - flNewDamage) * 0.5;
if (flArmor > tp.armor) {
flArmor = tp.armor;
flArmor *= (1/0.5);
flNewDamage = dmg - flArmor;
tp.armor = 0;
} else {
tp.armor -= flArmor;
}
dmg = flNewDamage;
}
dmg = rint(dmg);
t.health -= dmg;
/* the globals... */
g_dmg_eAttacker = c;
g_dmg_eTarget = t;
g_dmg_iDamage = dmg;
g_dmg_iHitBody = trace_surface_id;
g_dmg_iFlags = type;
g_dmg_iWeapon = w;
if (dmg > 0) {
t.dmg_take = dmg;
t.dmg_inflictor = c;
} else if (t.max_health && t.health > t.max_health) {
t.health = t.max_health;
}
/* set this global in case we need it later */
g_eAttacker = c;
CBaseEntity s = (CBaseEntity)t;
if (s.health <= 0) {
if (s.flags & FL_CLIENT) {
rules.PlayerDeath((player)s);
} else {
s.Death();
}
} else {
if (s.flags & FL_CLIENT) {
rules.PlayerPain((player)s);
} else {
s.Pain();
}
}
}
/* physical check of whether or not we can trace important parts of an ent */
float
Damage_CheckTrace(entity t, vector vecHitPos)
{
/* We're lazy. Who cares */
if (t.solid == SOLID_BSP) {
return TRUE;
}
traceline(vecHitPos, t.origin, 1, self);
if (trace_fraction == 1) {
return TRUE;
}
traceline(vecHitPos, t.origin + [15,15,0], 1, self);
if (trace_fraction == 1) {
return TRUE;
}
traceline(vecHitPos, t.origin + [-15,-15,0], 1, self);
if (trace_fraction == 1) {
return TRUE;
}
traceline(vecHitPos, t.origin + [-15,15,0], 1, self);
if (trace_fraction == 1) {
return TRUE;
}
traceline(vecHitPos, t.origin + [15,-15,0], 1, self);
if (trace_fraction == 1) {
return TRUE;
}
return FALSE;
}
/* even more pain and suffering, mostly used for explosives */
void
Damage_Radius(vector org, entity attacker, float dmg, float r, int check, int w)
{
float new_dmg;
float dist;
float diff;
vector pos;
for (entity e = world; (e = findfloat(e, ::takedamage, DAMAGE_YES));) {
pos[0] = e.absmin[0] + (0.5 * (e.absmax[0] - e.absmin[0]));
pos[1] = e.absmin[1] + (0.5 * (e.absmax[1] - e.absmin[1]));
pos[2] = e.absmin[2] + (0.5 * (e.absmax[2] - e.absmin[2]));
/* don't bother if it's not anywhere near us */
dist = vlen(org - pos);
if (dist > r) {
continue;
}
/* can we physically hit this thing? */
if (Damage_CheckTrace(e, org) == FALSE) {
if (check == TRUE) {
continue;
}
}
/* calculate new damage values */
diff = vlen(org - pos);
diff = (r - diff) / r;
new_dmg = rint(dmg * diff);
if (diff > 0) {
Damage_Apply(e, attacker, new_dmg, w, DMG_EXPLODE);
/* approximate, feel free to tweak */
if (e.movetype == MOVETYPE_WALK) {
makevectors(vectoangles(e.origin - org));
e.velocity += v_forward * (new_dmg * 5);
}
}
}
}

18
src/server/base/defs.h Normal file
View File

@ -0,0 +1,18 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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"

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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 Flashlight_Toggle(void)
{
if (cvar("sv_playerslots") != 1) {
if (cvar("mp_flashlight") != 1) {
return;
}
}
#ifdef VALVE
player pl = (player)self;
if (!(pl.g_items & ITEM_SUIT)) {
return;
}
#endif
if (self.health <= 0) {
return;
}
if (self.gflags & GF_FLASHLIGHT) {
self.gflags &= ~GF_FLASHLIGHT;
} else {
self.gflags |= GF_FLASHLIGHT;
}
sound(self, CHAN_ITEM, "items/flashlight1.wav", 1, ATTN_IDLE);
}

View File

@ -0,0 +1,197 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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_sv_playerkeepalive = TRUE;
void
GameRules::LevelDecodeParms(base_player 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(base_player 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(base_player pl)
{
Animation_PlayerUpdate();
if (autocvar_sv_playerkeepalive)
pl.SendFlags |= PLAYER_KEEPALIVE;
if (pl.old_modelindex != pl.modelindex)
pl.SendFlags |= PLAYER_MODELINDEX;
if (pl.old_origin[0] != pl.origin[0])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[1] != pl.origin[1])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[2] != pl.origin[2])
pl.SendFlags |= PLAYER_ORIGIN_Z;
if (pl.old_angles[0] != pl.v_angle[0])
pl.SendFlags |= PLAYER_ANGLES_X;
if (pl.old_angles[1] != pl.angles[1])
pl.SendFlags |= PLAYER_ANGLES_Y;
if (pl.old_angles[2] != pl.angles[2])
pl.SendFlags |= PLAYER_ANGLES_Z;
if (pl.old_velocity[0] != pl.velocity[0])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[1] != pl.velocity[1])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[2] != pl.velocity[2])
pl.SendFlags |= PLAYER_VELOCITY_Z;
if (pl.old_flags != pl.flags)
pl.SendFlags |= PLAYER_FLAGS;
if (pl.old_gflags != pl.gflags)
pl.SendFlags |= PLAYER_FLAGS;
if (pl.old_activeweapon != pl.activeweapon)
pl.SendFlags |= PLAYER_WEAPON;
if (pl.old_items != pl.g_items)
pl.SendFlags |= PLAYER_ITEMS;
if (pl.old_health != pl.health)
pl.SendFlags |= PLAYER_HEALTH;
if (pl.old_armor != pl.armor)
pl.SendFlags |= PLAYER_ARMOR;
if (pl.old_movetype != pl.movetype)
pl.SendFlags |= PLAYER_MOVETYPE;
if (pl.old_viewofs != pl.view_ofs[2])
pl.SendFlags |= PLAYER_VIEWOFS;
if (pl.old_baseframe != pl.baseframe)
pl.SendFlags |= PLAYER_BASEFRAME;
if (pl.old_frame != pl.frame)
pl.SendFlags |= PLAYER_FRAME;
if (pl.old_a_ammo1 != pl.a_ammo1)
pl.SendFlags |= PLAYER_AMMO1;
if (pl.old_a_ammo2 != pl.a_ammo2)
pl.SendFlags |= PLAYER_AMMO2;
if (pl.old_a_ammo3 != pl.a_ammo3)
pl.SendFlags |= PLAYER_AMMO3;
pl.old_modelindex = pl.modelindex;
pl.old_origin = pl.origin;
pl.old_angles = pl.angles;
pl.old_angles[0] = pl.v_angle[0];
pl.old_velocity = pl.velocity;
pl.old_flags = pl.flags;
pl.old_gflags = pl.gflags;
pl.old_activeweapon = pl.activeweapon;
pl.old_items = pl.g_items;
pl.old_health = pl.health;
pl.old_armor = pl.armor;
pl.old_movetype = pl.movetype;
pl.old_viewofs = pl.view_ofs[2];
pl.old_baseframe = pl.baseframe;
pl.old_frame = pl.frame;
pl.old_a_ammo1 = pl.a_ammo1;
pl.old_a_ammo2 = pl.a_ammo2;
pl.old_a_ammo3 = pl.a_ammo3;
}
void
GameRules::PlayerConnect(base_player pl)
{
if (Plugin_PlayerConnect(pl) == FALSE)
bprint(PRINT_HIGH, sprintf("%s connected\n", pl.netname));
}
void
GameRules::PlayerDisconnect(base_player 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(base_player pl)
{
Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR);
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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
{
virtual void(base_player) PlayerConnect;
virtual void(base_player) PlayerDisconnect;
virtual void(base_player) PlayerKill;
virtual void(base_player) PlayerPostFrame;
virtual void(base_player) LevelDecodeParms;
virtual void(base_player) LevelChangeParms;
virtual void(void) LevelNewParms;
};
class SingleplayerRules:GameRules
{
/* client */
virtual void(base_player) PlayerSpawn;
virtual void(base_player) PlayerDeath;
};
class MultiplayerRules:GameRules
{
int m_iIntermission;
int m_iIntermissionTime;
virtual void(void) FrameStart;
/* client */
virtual void(base_player) PlayerSpawn;
virtual void(base_player) PlayerDeath;
virtual float(base_player, string) ConsoleCommand;
};

View File

@ -0,0 +1,116 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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::FrameStart(void)
{
if (cvar("mp_timelimit"))
if (time >= (cvar("mp_timelimit") * 60)) {
IntermissionStart();
}
IntermissionCycle();
}
void
MultiplayerRules::PlayerDeath(base_player 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.movetype = MOVETYPE_NONE;
pl.solid = SOLID_NOT;
pl.takedamage = DAMAGE_NO;
pl.gflags &= ~GF_FLASHLIGHT;
pl.armor = pl.activeweapon = pl.g_items = 0;
pl.think = PutClientInServer;
pl.nextthink = time + 4.0f;
}
void
MultiplayerRules::PlayerSpawn(base_player 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.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendEntity = Player_SendEntity;
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(base_player pp, string cmd)
{
tokenize(cmd);
switch (argv(0)) {
case "bot_add":
Bot_AddQuick();
break;
default:
return FALSE;
}
return TRUE;
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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::PlayerDeath(base_player pl)
{
pl.movetype = MOVETYPE_NONE;
pl.solid = SOLID_NOT;
pl.takedamage = DAMAGE_NO;
pl.gflags &= ~GF_FLASHLIGHT;
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(base_player 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);
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendEntity = Player_SendEntity;
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);
}

71
src/server/base/input.c Normal file
View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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.
*/
/*
=================
Input_Handle
Handles impulse and whatnot
=================
*/
void Game_Input(void)
{
CGameRules rules = (CGameRules)g_grMode;
if (rules.m_iIntermission) {
rules.IntermissionEnd();
return;
}
if (input_buttons & INPUT_BUTTON0) {
Weapons_Primary();
} else if (input_buttons & INPUT_BUTTON4) {
Weapons_Reload();
} else if (input_buttons & INPUT_BUTTON3) {
Weapons_Secondary();
} else {
Weapons_Release();
}
if (input_buttons & INPUT_BUTTON5) {
Player_UseDown();
} else {
Player_UseUp();
}
if (self.impulse == 100) {
Flashlight_Toggle();
}
if (cvar("sv_cheats") == 1) {
player pl = (player)self;
if (self.impulse == 101) {
pl.health = 100;
pl.armor = 100;
}
if (self.impulse == 102) {
// Respawn all the entities
for (entity a = world; (a = findfloat(a, ::identity, 1));) {
CBaseEntity caw = (CBaseEntity)a;
caw.Respawn();
}
bprint(PRINT_HIGH, "Respawning all map entities...\n");
}
}
self.impulse = 0;
}

82
src/server/base/items.cpp Normal file
View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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(void)
{
if (other.classname != "player") {
return;
}
/* don't remove if AddItem fails */
if (Weapons_AddItem((player)other, id, m_iClip) == FALSE) {
return;
}
Logging_Pickup(other, this, __NULL__);
UseTargets(other, TRIG_TOGGLE, m_flDelay);
if (real_owner || m_iWasDropped == 1 || cvar("sv_playerslots") == 1) {
remove(self);
} else {
Hide();
think = Respawn;
nextthink = time + 30.0f;
}
}
void item_pickup::SetItem(int i)
{
id = i;
m_oldModel = Weapons_GetWorldmodel(id);
SetModel(m_oldModel);
}
void item_pickup::SetFloating(int i)
{
m_bFloating = rint(bound(0, m_bFloating, 1));
}
void item_pickup::Respawn(void)
{
SetSolid(SOLID_TRIGGER);
SetOrigin(m_oldOrigin);
/* At some points, the item id might not yet be set */
if (m_oldModel) {
SetModel(m_oldModel);
}
SetSize([-16,-16,0], [16,16,16]);
think = __NULL__;
nextthink = -1;
if (!m_iWasDropped && cvar("sv_playerslots") > 1) {
m_iClip = -1;
}
if (!m_bFloating) {
droptofloor();
SetMovetype(MOVETYPE_TOSS);
}
}
void item_pickup::item_pickup(void)
{
CBaseTrigger::CBaseTrigger();
Respawn();
}

30
src/server/base/items.h Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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:CBaseTrigger
{
int m_bFloating;
int m_iClip;
int m_iWasDropped;
int id;
void(void) item_pickup;
virtual void(void) touch;
virtual void(int i) SetItem;
virtual void(void) Respawn;
virtual void(int) SetFloating;
};

180
src/server/base/player.c Normal file
View File

@ -0,0 +1,180 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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.
*/
/*
====================
UseWorkaround
====================
*/
void UseWorkaround(entity eTarget)
{
eActivator = self;
entity eOldSelf = self;
self = eTarget;
self.PlayerUse();
self = eOldSelf;
}
/*
====================
Player_UseDown
====================
*/
void Player_UseDown(void)
{
vector vecSrc;
if (self.health <= 0) {
return;
} else if (!(self.flags & FL_USE_RELEASED)) {
return;
}
makevectors(self.v_angle);
vecSrc = self.origin + self.view_ofs;
self.hitcontentsmaski = CONTENTBITS_POINTSOLID;
traceline(vecSrc, vecSrc + (v_forward * 64), MOVE_HITMODEL, self);
if (trace_ent.PlayerUse) {
self.flags &= ~FL_USE_RELEASED;
UseWorkaround(trace_ent);
/* Some entities want to support Use spamming */
if (!(self.flags & FL_USE_RELEASED)) {
sound(self, CHAN_ITEM, "common/wpn_select.wav", 0.25, ATTN_IDLE);
}
} else {
sound(self, CHAN_ITEM, "common/wpn_denyselect.wav", 0.25, ATTN_IDLE);
self.flags &= ~FL_USE_RELEASED;
}
}
/*
====================
Player_UseUp
====================
*/
void Player_UseUp(void) {
if (!(self.flags & FL_USE_RELEASED)) {
self.flags |= FL_USE_RELEASED;
}
}
/*
=================
Player_SendEntity
=================
*/
float Player_SendEntity(entity ePEnt, float fChanged)
{
player pl = (player)self;
if (pl.health <= 0 && ePEnt != pl) {
return FALSE;
}
WriteByte(MSG_ENTITY, ENT_PLAYER);
WriteFloat(MSG_ENTITY, fChanged);
/* really trying to get our moneys worth with 23 bits of mantissa */
if (fChanged & PLAYER_MODELINDEX) {
WriteShort(MSG_ENTITY, pl.modelindex);
}
if (fChanged & PLAYER_ORIGIN) {
WriteCoord(MSG_ENTITY, pl.origin[0]);
WriteCoord(MSG_ENTITY, pl.origin[1]);
}
if (fChanged & PLAYER_ORIGIN_Z) {
WriteCoord(MSG_ENTITY, pl.origin[2]);
}
if (fChanged & PLAYER_ANGLES_X) {
WriteFloat(MSG_ENTITY, pl.v_angle[0]);
}
if (fChanged & PLAYER_ANGLES_Y) {
WriteFloat(MSG_ENTITY, pl.angles[1]);
}
if (fChanged & PLAYER_ANGLES_Z) {
WriteFloat(MSG_ENTITY, pl.angles[2]);
}
if (fChanged & PLAYER_VELOCITY) {
WriteCoord(MSG_ENTITY, pl.velocity[0]);
WriteCoord(MSG_ENTITY, pl.velocity[1]);
}
if (fChanged & PLAYER_VELOCITY_Z) {
WriteCoord(MSG_ENTITY, pl.velocity[2]);
}
if (fChanged & PLAYER_FLAGS) {
WriteFloat(MSG_ENTITY, pl.flags);
WriteFloat(MSG_ENTITY, pl.gflags);
}
if (fChanged & PLAYER_WEAPON) {
WriteByte(MSG_ENTITY, pl.activeweapon);
}
if (fChanged & PLAYER_ITEMS) {
WriteFloat(MSG_ENTITY, (__variant)pl.g_items);
}
if (fChanged & PLAYER_HEALTH) {
WriteByte(MSG_ENTITY, pl.health);
}
if (fChanged & PLAYER_ARMOR) {
WriteByte(MSG_ENTITY, pl.armor);
}
if (fChanged & PLAYER_MOVETYPE) {
WriteByte(MSG_ENTITY, pl.movetype);
}
if (fChanged & PLAYER_VIEWOFS) {
WriteFloat(MSG_ENTITY, pl.view_ofs[2]);
}
if (fChanged & PLAYER_BASEFRAME) {
WriteByte(MSG_ENTITY, pl.baseframe);
}
if (fChanged & PLAYER_FRAME) {
WriteByte(MSG_ENTITY, pl.frame);
}
if (fChanged & PLAYER_AMMO1) {
WriteByte(MSG_ENTITY, pl.a_ammo1);
}
if (fChanged & PLAYER_AMMO2) {
WriteByte(MSG_ENTITY, pl.a_ammo2);
}
if (fChanged & PLAYER_AMMO3) {
WriteByte(MSG_ENTITY, pl.a_ammo3);
}
return TRUE;
}
void Weapons_Draw(void);
void CSEv_PlayerSwitchWeapon_i(int w)
{
player pl = (player)self;
pl.activeweapon = w;
Weapons_Draw();
}
void
Player_Precache(void)
{
searchhandle pm;
pm = search_begin("models/player/*/*.mdl", TRUE, TRUE);
for (int i = 0; i < search_getsize(pm); i++) {
precache_model(search_getfilename(pm, i));
}
search_end(pm);
}

40
src/server/base/progs.src Executable file
View File

@ -0,0 +1,40 @@
#pragma target fte
#pragma progs_dat "../../../base/data.pk3dir/progs.dat"
#define QWSSQC
#define SERVER
#define GS_RENDERFX
#includelist
../../shared/fteextensions.qc
../../gs-entbase/server/defs.h
../../shared/defs.h
../defs.h
../../gs-entbase/server.src
../../gs-entbase/shared.src
../../shared/base/include.src
../base/defs.h
../base/player.c
../base/spectator.c
../../botlib/include.src
../base/gamerules.cpp
../base/gamerules_singleplayer.cpp
../base/gamerules_multiplayer.cpp
../base/client.c
../base/server.c
../base/damage.c
../base/items.cpp
../base/rules.c
../base/flashlight.c
../base/input.c
../base/spawn.c
../include.src
../../shared/include.src
#endlist

20
src/server/base/rules.c Normal file
View File

@ -0,0 +1,20 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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 Rules_IsTeamPlay(void)
{
return cvar("teamplay");
}

33
src/server/base/server.c Normal file
View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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_InitRules(void)
{
if (cvar("sv_playerslots") == 1 || cvar("coop") == 1) {
g_grMode = spawn(SingleplayerRules);
} else {
g_grMode = spawn(MultiplayerRules);
}
}
void
Game_Worldspawn(void)
{
precache_model("models/player.mdl");
Weapons_Init();
Player_Precache();
}

37
src/server/base/spawn.c Normal file
View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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 info_player_start(void)
{
self.solid = SOLID_TRIGGER;
setsize(self, VEC_HULL_MIN, VEC_HULL_MAX);
}
void info_player_deathmatch(void)
{
self.solid = SOLID_TRIGGER;
setsize(self, VEC_HULL_MIN, VEC_HULL_MAX);
}
void info_player_team1(void)
{
self.classname = "info_player_deathmatch";
}
void info_player_team2(void)
{
self.classname = "info_player_deathmatch";
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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_SpectatorThink(void)
{
}
void Game_SpectatorConnect(void)
{
}
void Game_SpectatorDisconnect(void)
{
}

47
src/shared/base/animations.c Executable file
View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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.
*/
/*
=================
Animation_PlayerUpdate
Called every frame to update the animation sequences
depending on what the player is doing
=================
*/
void
Animation_PlayerUpdate(void)
{
}
/*
=================
Animation_PlayerTop
Changes the animation sequence for the upper body part
=================
*/
void
Animation_PlayerTop(float fFrame)
{
}
void
Animation_PlayerTopTemp(float fFrame, float fTime)
{
}

View File

@ -0,0 +1,18 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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 Animation_PlayerTop(float);
void Animation_PlayerTopTemp(float, float);

40
src/shared/base/flags.h Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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 (1<<0)
#define GF_FLASHLIGHT (1<<1)
#define GF_UNUSED3 (1<<2)
#define GF_UNUSED4 (1<<3)
#define GF_UNUSED5 (1<<4)
#define GF_UNUSED6 (1<<5)
#define GF_UNUSED7 (1<<6)
#define GF_UNUSED8 (1<<7)
#define GF_UNUSED9 (1<<8)
#define GF_UNUSED10 (1<<9)
#define GF_UNUSED11 (1<<10)
#define GF_UNUSED12 (1<<11)
#define GF_UNUSED13 (1<<12)
#define GF_UNUSED14 (1<<14)
#define GF_UNUSED15 (1<<16)
#define GF_UNUSED16 (1<<13)
#define GF_UNUSED17 (1<<17)
#define GF_UNUSED18 (1<<18)
#define GF_UNUSED19 (1<<19)
#define GF_UNUSED20 (1<<20)
#define GF_UNUSED21 (1<<21)
#define GF_UNUSED22 (1<<22)
#define GF_UNUSED23 (1<<23)

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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
FX_BreakModel_Init(void)
{
}
#endif
void
FX_BreakModel(int count, vector vMins, vector vMaxs, vector vVel, float fStyle)
{
}

29
src/shared/base/fx_explosion.c Executable file
View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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
FX_Explosion_Init(void)
{
}
#endif
void
FX_Explosion(vector vecPos)
{
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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
FX_GibHuman_Init(void)
{
}
#endif
void
FX_GibHuman(vector pos)
{
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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
FX_Impact_Init(void)
{
}
#endif
void
FX_Impact(int iType, vector vecPos, vector vNormal)
{
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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_SPARK;
void
FX_Spark_Init(void)
{
PARTICLE_SPARK = particleeffectnum("fx_spark.effect");
}
#endif
void
FX_Spark(vector pos, vector ang)
{
#ifdef SERVER
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_SPARK);
WriteCoord(MSG_MULTICAST, pos[0]);
WriteCoord(MSG_MULTICAST, pos[1]);
WriteCoord(MSG_MULTICAST, pos[2]);
WriteCoord(MSG_MULTICAST, ang[0]);
WriteCoord(MSG_MULTICAST, ang[1]);
WriteCoord(MSG_MULTICAST, ang[2]);
msg_entity = self;
multicast(pos, MULTICAST_PVS);
#else
pointparticles(PARTICLE_SPARK, pos, ang, 1);
#endif
}

View File

@ -0,0 +1,21 @@
#includelist
../../shared/base/flags.h
../../shared/base/player.cpp
../../shared/base/weapon_common.h
../../shared/base/animations.h
../../shared/base/animations.c
../../shared/base/pmove.c
../../shared/base/pmove_water.c
../../shared/base/fx_blood.c
../../shared/base/fx_breakmodel.c
../../shared/base/fx_explosion.c
../../shared/base/fx_gibhuman.c
../../shared/base/fx_spark.c
../../shared/base/fx_impact.c
../../shared/base/items.h
../../shared/base/weapons.h
../../shared/base/weapons.c
../../shared/base/weapon_common.c
#endlist

16
src/shared/base/items.h Normal file
View File

@ -0,0 +1,16 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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.
*/

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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.
*/
noref int input_sequence;
class player:base_player
{
#ifdef CLIENT
/* External model */
entity p_model;
int p_hand_bone;
int p_model_bone;
float lastweapon;
virtual void(void) gun_offset;
virtual void(void) draw;
virtual float() predraw;
virtual void(void) postdraw;
#else
#endif
};

69
src/shared/base/pmove.c Normal file
View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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 PHY_JUMP_CHAINWINDOW 0.5
#define PHY_JUMP_CHAIN 100
#define PHY_JUMP_CHAINDECAY 50
.float waterlevel;
.float watertype;
float GamePMove_Maxspeed(player target)
{
return (target.flags & FL_CROUCHING) ? 135 : 270;
}
void GamePMove_Fall(player target, float impactspeed)
{
if (impactspeed > 580) {
#ifdef SERVER
float fFallDamage = (impactspeed - 580) * (100 / (1024 - 580));
Damage_Apply(target, world, fFallDamage, 0, DMG_FALL);
Sound_Play(target, CHAN_VOICE, "player.fall");
#endif
target.punchangle += [15,0,(input_sequence & 1) ? 15 : -15];
} else if (impactspeed > 400) {
target.punchangle += [15,0,0];
#ifdef SERVER
Sound_Play(target, CHAN_VOICE, "player.lightfall");
#endif
}
}
void GamePMove_Jump(player target)
{
float flJumptimeDelta;
float flChainBonus;
if (target.waterlevel >= 2) {
if (target.watertype == CONTENT_WATER) {
target.velocity[2] = 100;
} else if (target.watertype == CONTENT_SLIME) {
target.velocity[2] = 80;
} else {
target.velocity[2] = 50;
}
} else {
target.velocity[2] += 240;
}
if (target.jumptime > 0) {
flJumptimeDelta = 0 - (target.jumptime - PHY_JUMP_CHAINWINDOW);
flChainBonus = PHY_JUMP_CHAIN - (((PHY_JUMP_CHAINWINDOW - (PHY_JUMP_CHAINWINDOW - flJumptimeDelta)) * 2) * PHY_JUMP_CHAINDECAY);
target.velocity[2] += flChainBonus;
}
target.jumptime = PHY_JUMP_CHAINWINDOW;
}

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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
GamePMove_WaterMove(player target)
{
if (target.movetype == MOVETYPE_NOCLIP) {
return;
}
#ifdef SERVER
if (target.health < 0) {
return;
}
/* we've just exited water */
if (target.waterlevel != 3) {
if (target.underwater_time < time) {
Sound_Play(target, CHAN_BODY, "player.gasplight");
} else if (target.underwater_time < time + 9) {
Sound_Play(target, CHAN_BODY, "player.gaspheavy");
}
target.underwater_time = time + 12;
} else if (target.underwater_time < time) {
/* we've been underwater... for too long. */
if (target.pain_time < time) {
Damage_Apply(target, world, 5, DMG_DROWN, 0);
target.pain_time = time + 1;
}
}
#endif
if (!target.waterlevel){
if (target.flags & FL_INWATER) {
#ifdef SERVER
Sound_Play(target, CHAN_BODY, "player.waterexit");
#endif
target.flags &= ~FL_INWATER;
}
return;
}
#ifdef SERVER
if (target.watertype == CONTENT_LAVA) {
if (target.pain_time < time) {
target.pain_time = time + 0.2;
Damage_Apply(target, world, 10*target.waterlevel, DMG_BURN, 0);
}
} else if (target.watertype == CONTENT_SLIME) {
if (target.pain_time < time) {
target.pain_time = time + 1;
Damage_Apply(target, world, 4*target.waterlevel, DMG_ACID, 0);
}
}
#endif
if (!(target.flags & FL_INWATER)) {
#ifdef SERVER
Sound_Play(target, CHAN_BODY, "player.waterenter");
target.pain_time = 0;
#endif
target.flags |= FL_INWATER;
}
}

View File

@ -0,0 +1,283 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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
void Decals_Init(void);
#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();
}
}
}
void Weapons_SetModel(string mdl)
{
#ifdef CLIENT
setmodel(pSeat->m_eViewModel, mdl);
#endif
}
void Weapons_SetGeomset(string set)
{
#ifdef CLIENT
setcustomskin(pSeat->m_eViewModel, "", set);
#endif
}
void Weapons_Draw(void)
{
player pl = (player)self;
int i = pl.activeweapon;
pl.w_attack_next = 0.5f;
pl.w_idle_next = 2.5f;
pl.viewzoom = 1.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();
}
#ifdef SERVER
if (g_weapons[i].updateammo != __NULL__) {
g_weapons[i].updateammo(pl);
}
#endif
}
void Weapons_Holster(void)
{
player pl = (player)self;
int i = pl.activeweapon;
if (g_weapons[i].holster != __NULL__) {
g_weapons[i].holster();
}
}
void Weapons_Primary(void)
{
player pl = (player)self;
int i = pl.activeweapon;
if (pl.flags & FL_NOATTACK)
return;
if (g_weapons[i].primary != __NULL__) {
g_weapons[i].primary();
}
#ifdef SERVER
if (g_weapons[i].updateammo != __NULL__) {
g_weapons[i].updateammo(pl);
}
#endif
}
void Weapons_Secondary(void)
{
player pl = (player)self;
int i = pl.activeweapon;
if (pl.flags & FL_NOATTACK)
return;
if (g_weapons[i].secondary != __NULL__) {
g_weapons[i].secondary();
}
#ifdef SERVER
if (g_weapons[i].updateammo != __NULL__) {
g_weapons[i].updateammo(pl);
}
#endif
}
void Weapons_Reload(void)
{
player pl = (player)self;
int i = pl.activeweapon;
if (pl.flags & FL_NOATTACK)
return;
if (g_weapons[i].reload != __NULL__) {
g_weapons[i].reload();
}
#ifdef SERVER
if (g_weapons[i].updateammo != __NULL__) {
g_weapons[i].updateammo(pl);
}
#endif
}
void Weapons_Release(void)
{
player pl = (player)self;
int i = pl.activeweapon;
if (g_weapons[i].release != __NULL__) {
g_weapons[i].release();
}
pl.gflags &= ~GF_SEMI_TOGGLED;
}
void Weapons_DrawCrosshair(void)
{
player pl = (player)self;
int i = pl.activeweapon;
if (g_weapons[i].crosshair != __NULL__) {
g_weapons[i].crosshair();
}
}
string Weapons_GetWorldmodel(int id)
{
if (g_weapons[id].wmodel != __NULL__) {
return g_weapons[id].wmodel();
}
return "";
}
string Weapons_GetPlayermodel(int id)
{
if (g_weapons[id].pmodel != __NULL__) {
return g_weapons[id].pmodel();
}
return "";
}
string Weapons_GetDeathmessage(int id)
{
if (g_weapons[id].deathmsg != __NULL__) {
return g_weapons[id].deathmsg();
}
return "";
}
#ifdef SERVER
float Weapons_GetAim(int id)
{
if (g_weapons[id].aimanim != __NULL__) {
return g_weapons[id].aimanim();
}
return 0;
}
#endif
#ifdef CLIENT
void Weapons_HUDPic(int id, int s, vector pos, float a)
{
if (g_weapons[id].hudpic != __NULL__) {
g_weapons[id].hudpic(s, pos, a);
}
}
#endif
void Weapons_MakeVectors(void)
{
#ifdef SERVER
player pl = (player)self;
makevectors(pl.v_angle);
#else
makevectors(view_angles);
#endif
}
vector Weapons_GetCameraPos(void)
{
#ifdef SERVER
return self.origin + self.view_ofs;
#else
return getproperty(VF_ORIGIN);
#endif
}
void Weapons_ViewAnimation(int i)
{
#ifdef CLIENT
player pl = (player)pSeat->m_ePlayer;
View_PlayAnimation(i);
#else
player pl = (player)self;
#endif
pl.weapontime = 0.0f;
}
#ifdef CLIENT
int View_GetAnimation(void);
int Weapons_GetAnimation(void)
{
return View_GetAnimation();
}
#endif
void Weapons_ViewPunchAngle(vector add)
{
#ifdef CLIENT
player pl = (player)self;
pl.punchangle += add;
#endif
}
void Weapons_PlaySound(entity t, float ch, string s, float vol, float at)
{
#ifdef SERVER
sound(t, ch, s, vol, at);
#endif
}
int Weapons_IsPresent(player pl, int w)
{
if (pl.g_items & g_weapons[w].id) {
return TRUE;
} else {
return FALSE;
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
typedef struct
{
string name;
int id; /* bitflag id */
int slot;
int slot_pos;
int allow_drop;
void(void) draw;
void(void) holster;
void(void) primary;
void(void) secondary;
void(void) reload;
void(void) release;
void(void) crosshair;
void(void) precache;
int(int, int) pickup;
void(player) updateammo;
string() wmodel;
string() pmodel;
string() deathmsg;
float() aimanim;
void(int, vector, float) hudpic;
} weapon_t;
void Weapons_DrawCrosshair(void);
void Weapons_MakeVectors(void);
vector Weapons_GetCameraPos(void);
void Weapons_ViewAnimation(int);
void Weapons_ViewPunchAngle(vector);
void Weapons_PlaySound(entity, float, string, float, float);
int Weapons_IsPresent(player, int);
void Weapons_SetModel(string);
void Weapons_SetGeomset(string);
#ifdef CLIENT
string Weapons_GetPlayermodel(int);
int Weapons_GetAnimation(void);
void Weapons_HUDPic(int, int, vector, float);
#endif

20
src/shared/base/weapons.c Normal file
View File

@ -0,0 +1,20 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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
};

21
src/shared/base/weapons.h Normal file
View File

@ -0,0 +1,21 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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 Indices for the weapon table */
enum
{
WEAPON_NONE
};

View File

@ -316,15 +316,15 @@ Sound_Play(entity target, int chan, string shader)
if (g_sounds[sample].flags & SNDFL_STEP) {
float s = vlen(target.velocity);
if (target.flags & FL_CROUCHING)
s *= 2.0f;
/*if (target.flags & FL_CROUCHING)
s *= 2.0f;*/
if (s < PMOVE_STEP_WALKSPEED) {
return;
} else if (s < PMOVE_STEP_RUNSPEED) {
volume = 0.35f;
volume *= 0.35f;
} else {
volume = 0.75;
volume *= 0.75f;
}
}
#ifdef CLIENT