Compare commits

...

6 Commits

29 changed files with 690 additions and 97 deletions

View File

@ -9,6 +9,8 @@ This is a software development kit (SDK) and development environment created by
The Nuclide project produces a freely available game-logic component and
development platform on top of [FTEQW](https://www.fteqw.org); which is the engine we happen to use.
**The general idea is that Nuclide takes care of ~90% of the code you shouldn't have to worry about.**
The goal is to create a modern research base for new advancements, as well
as to have a stable base with a decent API for making games.
@ -16,13 +18,17 @@ It comes with a simple example game (simply referred to as 'Base') and some test
General feature overview:
- SDK in the spirit of 'id Tech' development environments
- Client-side predicted movement, predicted weapons and vehicle systems
- Implementations of well known, established entity classes as seen in popular and critically acclaimed games
- Reference implementations for a lot of features exlusive to the FTEQW engine
- Designed to be familar to developers who are used to GoldSrc and Source engine
project workflows
- Everything written from scratch with the modern QuakeC language advancements in mind
- The 'missing' SDK for engines like FTEQW
- Support for client-side predicted movement, weaponry and vehicles
- Documented APIs for everything you need to interface with the engine
- APIs and Frameworks for managing updates, mods, servers, and platform specific features
- Complete re-implementations of hundreds of entities, from GoldSrc/Source engine games
- Entity communication via traditional one-way triggers, or our Source Engine I/O compatible system
- Includes BotLib, a framework for multiplayer-AI that can receive game-specific overrides
- Includes VGUILib, a re-imagining of Valve's GUI library, which can also be used for in-game surface based interfaces
- Designed to be familar to developers coming from GoldSrc/Source
- VR/XR aware codebase
- All permissively licensed
### 1. Why might I want to use it? {#why}
@ -67,9 +73,9 @@ If you do posess a basic knowledge of the following:
Then you will have a good time.
We strive to keep the codebase portable and conform to open standards wherever possible.
This means that if you develop on Windows, you probably want to install something like [Cygwin](https://www.cygwin.com/) to make this bearable.
This means that if you develop on Windows, you probably want to install something like WSL or even [Cygwin](https://www.cygwin.com/) to make this bearable.
Please don't ask us how to learn UNIX/Cygwin.
Please don't ask us how to use WSL or Cygwin. We do not provide support for either. We do not develop on Windows.
**This is a development kit and a development environment. This is not a game.**

View File

@ -1,12 +1,27 @@
# ![FTE Logo](Documentation/fte.svg) Nuclide - Software Development Kit
Software Development Kit, built around idTech with focus on advanced features and
Software Development Kit, built around id Technology with focus on advanced features and
clean-room implementations of true-and-tested game-logic frameworks.
It's been used to ship a commercial product. So it's proven to some extent.
*It's been used to ship a commercial product. So it's proven to some extent.*
All of this is written in QuakeC, but there's also some GLSL and shell scripts
in here. If you and your team are unfamilar with any of these, you may want something else.
## Features
- The missing SDK for engines like FTEQW
- Support for client-side predicted movement, weaponry and vehicles
- Documented APIs for everything you need to interface with the engine
- APIs and Frameworks for managing updates, mods, servers, and platform specific features
- Complete re-implementations of hundreds of entities, from GoldSrc/Source engine games
- Entity communication via traditional one-way triggers, or our Source Engine I/O compatible system
- Includes BotLib, a framework for multiplayer-AI that can receive game-specific overrides
- Includes VGUILib, a re-imagining of Valve's GUI library, which can also be used for in-game surface based interfaces
- Designed to be familar to developers coming from GoldSrc/Source
- VR/XR aware codebase
- All permissively licensed
## Documentation
You can find up-to-date documentation over at https://developer.vera-visions.com/
@ -14,10 +29,17 @@ You can find up-to-date documentation over at https://developer.vera-visions.com
This documentation is built entirely from this repository using doxygen.
You do not need to be on-line to view the documentation.
You can build the HTML documentation by running `doxygen` inside the root
of the repository. The output is located under `Documentation/html/index.html`
## Support
You can get personal support for Nuclide by negotiating a support contract with us. Reach out to marco@vera-visions.com if you want to know about our rates.
## Special Thanks
To id software and specifically John Carmack for having released the sources of
various pieces of id Technology under free licenses.
various works of id Technology under free licenses, without which a project like this would be unfeasible.
David Walton for **FTEQW** and the **FTEQCC** compiler, which is the brain of this SDK.

View File

@ -0,0 +1,7 @@
{
{
map "gfx/playericon.tga"
rgbGen vertex
blendFunc blend
}
}

Binary file not shown.

View File

@ -64,6 +64,11 @@ seta mp_td_dmgToKick 300 // Specifies how much damage one player has to inflict
seta mp_td_dmgToWarn 200 // Specifies how much damage one player has to inflict to others players before getting warned.
alias mp_friendlyfire sv_friendlyFire
// xr related cvars
seta xr_roomScale 1.0 // Scales world<>game translation.
seta xr_viewHeight -48.0 // Specifies the head offset when in XR mode.
seta xr_testInputs 0 // Send faux XR input signals when enabled.
// aliases for the older commands (may be removed some day)
alias cl_autojump pm_autoJump
alias cl_showfps com_showFPS

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2022 Vera Visions LLC.
* Copyright (c) 2016-2023 Vera Visions LLC.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -15,25 +15,32 @@
*/
#define COST_INFINITE 99999
/** The desired target destination has been reached. */
#define BOTROUTE_DESTINATION -1
/** Unloading of the route in progress. */
#define BOTROUTE_END -2
/** Bot Personality */
typedef enum
{
BOT_PERSONALITY_NORMAL, /* this bot will be dynamic */
BOT_PERSONALITY_AGRESSIVE, /* this bot will always prefer to be attacking */
BOT_PERSONALITY_DEFENSIVE /* this bot will always prefer to stay behind */
BOT_PERSONALITY_NORMAL, /**< this bot will be dynamic */
BOT_PERSONALITY_AGRESSIVE, /**< this bot will always prefer to be attacking */
BOT_PERSONALITY_DEFENSIVE /**< this bot will always prefer to stay behind */
} botpersonality_t;
/** Bot State */
typedef enum
{
BOT_STATE_IDLE, /* this should rarely happen */
BOT_STATE_PATROLLING, /* this is basically most deathmatch cases */
BOT_STATE_DEFENDING, /* this is for when bots stay put and stay around spawn, or their teams goalitem */
BOT_STATE_ATTACKING, /* this is for when bots go to the enemy spawn, or to the enemy team's goalitem */
BOT_STATE_FLEEING /* this is for when the AI should just get as far away as possible */
BOT_STATE_IDLE, /**< this should rarely happen */
BOT_STATE_PATROLLING, /**< this is basically most deathmatch cases */
BOT_STATE_DEFENDING, /**< this is for when bots stay put and stay around spawn, or their teams goalitem */
BOT_STATE_ATTACKING, /**< this is for when bots go to the enemy spawn, or to the enemy team's goalitem */
BOT_STATE_FLEEING /**< this is for when the AI should just get as far away as possible */
} botstate_t;
/** Base class for the Bot AI.
*/
class bot:player
{
/* routing */
@ -95,8 +102,10 @@ class bot:player
virtual void(string) SetName;
};
/** Adds a bot to the game with some basic info. Returns the resulting entity. __NULL__ if unavailable. */
entity Bot_AddQuick(void);
/** Applies random custom colors to the given bot entity. */
void
Bot_RandomColormap(bot target)
{

View File

@ -161,7 +161,7 @@ NSInteractiveSurface::predraw(void)
makevectors(angles);
R_BeginPolygon(m_strSurfaceMat, 0, 0);
R_PolygonVertex(origin + v_right * fsize[0] - v_up * fsize[1],
[1,1], [1,0,0], 1.0f);
[1,1], [1,1,1], 1.0f);
R_PolygonVertex(origin - v_right * fsize[0] - v_up * fsize[1],
[0,1], [1,1,1], 1.0f);
R_PolygonVertex(origin - v_right * fsize[0] + v_up * fsize[1],

71
src/client/NSRadar.h Normal file
View File

@ -0,0 +1,71 @@
/*
* 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.
*/
/** Tasked with managing overview/radar type widgets.
It's able to load different types of overviews, in addition to none at all.
It's able to load HLTV styled overviews used in GoldSrc and Source.*/
class
NSRadar:NSView
{
public:
void NSRadar(void);
/** Init a radar for the map we're currently on. */
nonvirtual NSRadar InitForCurrentMap(void);
/** Init a radar for a specified map, will automatically choose the best available type. */
nonvirtual NSRadar InitWithMapname(string);
/** Init as Overview from GoldSrc HLTV script file. */
nonvirtual NSRadar InitFromHLTVScript(string);
/** Init as Overview from Source Engine HLTV script file. */
nonvirtual NSRadar InitFromSourceHLTVScript(string);
/** Init an empty (wireframe) overview */
nonvirtual NSRadar InitWireframe(void);
nonvirtual void RenderOverviewPlane(void);
nonvirtual void RenderWireframePlane(void);
nonvirtual void SetRadarPitch(float);
virtual void RenderPlayerIcon(entity);
/* overrides */
virtual void RenderView(void);
virtual void SetupView(void);
private:
/* internal */
vector m_vecOrigin;
bool m_bRotated;
string m_strMaterial;
float m_flScale;
float m_flHeight;
float m_flZoom;
vector m_vecVert1;
vector m_vecVert2;
vector m_vecVert3;
vector m_vecVert4;
bool m_bShowPlayers;
float m_flRadarPitch;
nonvirtual void CalculateVertices(void);
nonvirtual void CalculateVerticesSource(float, float);
};

365
src/client/NSRadar.qc Normal file
View File

@ -0,0 +1,365 @@
/*
* 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.
*/
void
NSRadar::NSRadar(void)
{
m_vecOrigin = g_vec_null;
m_flScale = 1.0f;
m_bRotated = false;
m_strMaterial = __NULL__;
m_flHeight = 0.0f;
m_flZoom = 1.0f;
m_bShowPlayers = true;
m_flRadarPitch = 90; /* straight down */
}
void
NSRadar::SetRadarPitch(float pitchValue)
{
m_flRadarPitch = pitchValue;
}
void
NSRadar::SetupView(void)
{
vector playerPos = g_view.GetCameraOrigin();
//drawfill( atPos, ofSize, '0 0 0', 1.0f, 0 );
setproperty(VF_DRAWENGINESBAR, (float)0);
setproperty(VF_DRAWCROSSHAIR, (float)0);
setproperty(VF_MIN, video_mins+ m_vecPosition);
setproperty(VF_SIZE, m_vecSize);
setproperty(VF_AFOV, 90);
setproperty(VF_VIEWENTITY, 0);
setproperty(VF_DRAWWORLD, (float)0);
setproperty(VF_ORIGIN, [playerPos[0], playerPos[1], m_flHeight + 1024] );
makevectors(view_angles);
setproperty(VF_ANGLES, [m_flRadarPitch, view_angles[1], 0]);
}
void
NSRadar::RenderPlayerIcon(entity playerEnt)
{
vector playerColor = [1,1,1];
string teamValue = getplayerkeyvalue(playerEnt.entnum-1, "*team");
float psize = 32.0f;
if (playerEnt == pSeat->m_ePlayer)
return;
R_BeginPolygon( "gfx/playericon" );
if (teamValue)
playerColor = stov(serverkey(strcat("teamcolor_", teamValue)));
vector basePos = playerEnt.origin + [0.0, 0.0, 16.0f];
makevectors([0, playerEnt.v_angle[1], 0]);
R_PolygonVertex( basePos + (v_forward * psize) - (v_right * psize), '0 0', playerColor, 1.0f );
R_PolygonVertex( basePos + (v_forward * psize) + (v_right * psize), '1 0', playerColor, 1.0f );
R_PolygonVertex( basePos - (v_forward * psize) + (v_right * psize), '1 1', playerColor, 1.0f );
R_PolygonVertex( basePos - (v_forward * psize) - (v_right * psize), '0 1', playerColor, 1.0f );
R_EndPolygon();
}
void
NSRadar::RenderOverviewPlane(void)
{
R_BeginPolygon( m_strMaterial );
if ( m_bRotated == true ) {
R_PolygonVertex( [ m_vecVert4[0], m_vecVert4[1], m_flHeight ], '1 0', '1 1 1', 1.0f ); // Top Left
R_PolygonVertex( [ m_vecVert3[0], m_vecVert3[1], m_flHeight ], '1 1', '1 1 1', 1.0f ); // Top Right
R_PolygonVertex( [ m_vecVert1[0], m_vecVert1[1], m_flHeight ], '0 1', '1 1 1', 1.0f ); // Bottom right
R_PolygonVertex( [ m_vecVert2[0], m_vecVert2[1], m_flHeight ], '0 0', '1 1 1', 1.0f ); // Bottom left
} else {
R_PolygonVertex( [ m_vecVert4[0], m_vecVert4[1], m_flHeight ], '0 0', '1 1 1', 1.0f ); // Top Left
R_PolygonVertex( [ m_vecVert3[0], m_vecVert3[1], m_flHeight ], '1 0', '1 1 1', 1.0f ); // Top Right
R_PolygonVertex( [ m_vecVert1[0], m_vecVert1[1], m_flHeight ], '1 1', '1 1 1', 1.0f ); // Bottom right
R_PolygonVertex( [ m_vecVert2[0], m_vecVert2[1], m_flHeight ], '0 1', '1 1 1', 1.0f ); // Bottom left
}
R_EndPolygon();
}
void
NSRadar::RenderWireframePlane(void)
{
vector vert1, vert2, vert3, vert4;
vector wireColor = [0.0f, 1.0f, 0.0f];
vert1 = [256,0];
vert2 = [0, 0];
vert3 = [0, 256];
vert4 = [256, 256];
for (int x = -4096; x < 4096; x += 256) {
for (int y = -4096; y < 4096; y += 256) {
R_BeginPolygon( "" );
R_PolygonVertex( [ x + vert1[0], y + vert1[1] ], '0 0', wireColor, 1.0f );
R_PolygonVertex( [ x + vert2[0], y + vert2[1] ], '1 0', wireColor, 1.0f );
R_EndPolygon();
R_BeginPolygon( "" );
R_PolygonVertex( [ x + vert2[0], y + vert2[1] ], '1 0', wireColor, 1.0f );
R_PolygonVertex( [ x + vert3[0], y + vert3[1] ], '1 1', wireColor, 1.0f );
R_EndPolygon();
R_BeginPolygon( "" );
R_PolygonVertex( [ x + vert3[0], y + vert3[1] ], '1 1', wireColor, 1.0f );
R_PolygonVertex( [ x + vert4[0], y + vert4[1] ], '0 1', wireColor, 1.0f );
R_EndPolygon();
R_BeginPolygon( "" );
R_PolygonVertex( [ x + vert4[0], y + vert4[1] ], '0 1', wireColor, 1.0f );
R_PolygonVertex( [ x + vert1[0], y + vert1[1] ], '0 0', wireColor, 1.0f );
R_EndPolygon();
}
}
}
void
NSRadar::RenderView(void)
{
if (m_strMaterial != __NULL__) {
RenderOverviewPlane();
} else {
RenderWireframePlane();
}
if (m_bShowPlayers)
for ( entity eFind = world; ( eFind = find( eFind, ::classname, "player" ) ); ) {
RenderPlayerIcon(eFind);
}
renderscene();
}
NSRadar
NSRadar::InitWireframe(void)
{
NSRadar newRadar = spawn(NSRadar);
newRadar.m_bDrawEntities = false;
newRadar.CalculateVertices();
newRadar.m_strMaterial = __NULL__;
return newRadar;
}
NSRadar
NSRadar::InitForCurrentMap(void)
{
return InitWithMapname(mapname);
}
NSRadar
NSRadar::InitWithMapname(string mapName)
{
string sourceFile = strcat("resource/overviews/", mapName, ".txt");
string hlFile = strcat("overviews/", mapName, ".txt");
/* try Source first, then GoldSrc */
if (FileExists(sourceFile)) {
return InitFromSourceHLTVScript(sourceFile);
} else if (FileExists(hlFile)) {
return InitFromHLTVScript(hlFile);
}
/* empty */
return InitWireframe();
}
void
NSRadar::CalculateVertices(void)
{
if ( m_bRotated == true ) {
m_vecVert1 = m_vecOrigin -( ( 4096/m_flZoom ) * '1 0.75 0' );
m_vecVert4 = m_vecOrigin + ( 4096/m_flZoom ) * '1 0.75 0';
m_vecVert2 = [ m_vecVert1[0], m_vecVert4[1] ] ;
m_vecVert3 = [ m_vecVert4[0], m_vecVert1[1] ] ;
} else {
m_vecVert1 = m_vecOrigin -( ( 4096/m_flZoom ) * '0.75 1 0' );
m_vecVert4 = m_vecOrigin + ( 4096/m_flZoom ) * '0.75 1 0';
m_vecVert2 = [ m_vecVert1[0], m_vecVert4[1] ] ;
m_vecVert3 = [ m_vecVert4[0], m_vecVert1[1] ] ;
}
}
void
NSRadar::CalculateVerticesSource(float width, float height)
{
m_vecVert2 = m_vecOrigin;
m_vecVert1 = m_vecOrigin + [(width), 0.0f];
m_vecVert3 = m_vecOrigin + [(width), (height)];
m_vecVert4 = m_vecOrigin + [0.0f, (height)];
m_vecVert1 -= [0.0, height];
m_vecVert2 -= [0.0, height];
m_vecVert3 -= [0.0, height];
m_vecVert4 -= [0.0, height];
}
NSRadar
NSRadar::InitFromHLTVScript(string fileName)
{
filestream overviewFile;
NSRadar newRadar = spawn(NSRadar);
string temp;
int c;
overviewFile = fopen(fileName, FILE_READ);
/* sane switch */
newRadar.m_bDrawEntities = false;
if (overviewFile < 0) {
error("Fatal: Unable to load HL file that exists on disk.");
return newRadar;
}
/* the most primitive parser possible, technically the format
is supposed to support layers - but that was never utilized
and may not even be implemented. didn't check though. */
while ((temp = fgets(overviewFile))) {
c = tokenize_console(temp);
switch(argv(0)) {
case "ZOOM":
NSAssert((c >= 2i), "Too few parameters on ZOOM");
newRadar.m_flZoom = stof(argv(1));
break;
case "ORIGIN":
NSAssert((c >= 4i), "Too few parameters on ORIGIN");
newRadar.m_vecOrigin[0] = stof(argv(1));
newRadar.m_vecOrigin[1] = stof(argv(2));
newRadar.m_vecOrigin[2] = stof(argv(3));
break;
case "ROTATED":
NSAssert((c >= 2i), "Too few parameters on ROTATED");
newRadar.m_bRotated = stof(argv(1)) == 0 ? false : true;
break;
case "IMAGE":
NSAssert((c >= 2i), "Too few parameters on IMAGE");
newRadar.m_strMaterial = argv(1);
break;
case "HEIGHT":
NSAssert((c >= 2i), "Too few parameters on HEIGHT");
newRadar.m_flHeight = stof(argv(1));
break;
default:
break;
}
}
newRadar.CalculateVertices();
/* load the (presumably) .bmp file */
int width, height, format;
int *imgData = r_readimage(newRadar.m_strMaterial, width, height, format);
NSAssert((imgData != __NULL__), "Cannot read overview image.");
/* blank out the areas that are supposed to be transparent */
for (int i = 0i; i < (width * height); i += 1i) {
int r = (imgData[i] & 0xFF);
int g = ((imgData[i] >> 8) & 0xFF);
int b = ((imgData[i] >> 16) & 0xFF);
/* check for purple, blue color */
if (r == 255 && g == 0 && b == 255) {
imgData[i] = 0i;
} else if (r == 0 && g == 0 && b == 255) {
imgData[i] = 0i;
} else if (r == 0 && g == 255 && b == 0) {
imgData[i] = 0i;
}
}
shaderforname("overview", "{\n{\nmap $rt:overview\nblendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA\n}\n}\n");
r_uploadimage("overview", width, height, (void *)imgData);
memfree(imgData);
newRadar.m_strMaterial = "overview";
print("Overview loaded.\n");
return newRadar;
}
NSRadar
NSRadar::InitFromSourceHLTVScript(string fileName)
{
filestream overviewFile;
NSRadar newRadar = spawn(NSRadar);
string temp;
int c;
overviewFile = fopen(fileName, FILE_READ);
/* sane switch */
newRadar.m_bDrawEntities = false;
if (overviewFile < 0) {
error("Fatal: Unable to load file that exists on disk.");
return newRadar;
}
/* the most primitive parser possible, technically the format
is supposed to support layers - but that was never utilized
and may not even be implemented. didn't check though. */
while ((temp = fgets(overviewFile))) {
c = tokenize_console(temp);
switch(argv(0)) {
case "zoom":
NSAssert((c >= 2i), "Too few parameters on 'zoom'");
newRadar.m_flZoom = stof(argv(1));
break;
case "scale":
NSAssert((c >= 2i), "Too few parameters on 'scale'");
newRadar.m_flScale = stof(argv(1));
break;
case "pos_x":
NSAssert((c >= 2i), "Too few parameters on 'pos_x'");
newRadar.m_vecOrigin[0] = stof(argv(1));
break;
case "pos_y":
NSAssert((c >= 2i), "Too few parameters on 'pos_y'");
newRadar.m_vecOrigin[1] = stof(argv(1));
break;
case "rotate":
NSAssert((c >= 2i), "Too few parameters on 'rotate'");
/* this seems to be ignored? whatever */
//newRadar.m_bRotated = stof(argv(1)) == 0 ? false : true;
break;
case "material":
NSAssert((c >= 2i), "Too few parameters on 'material'");
newRadar.m_strMaterial = strcat("materials/", argv(1));
break;
case "height":
NSAssert((c >= 2i), "Too few parameters on 'height'");
newRadar.m_flHeight = stof(argv(1));
break;
default:
break;
}
}
vector imageSize = drawgetimagesize(newRadar.m_strMaterial);
imageSize *= newRadar.m_flScale;
newRadar.CalculateVerticesSource(imageSize[0], imageSize[1]);
print("Overview loaded.\n");
return newRadar;
}

View File

@ -14,6 +14,15 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*! @file achievements.h
@brief Achievement APIs
The Achievements API manages the retrieval, storage and networking
of game achievements.
This is a work in progress.
*/
/** Data for an achievement definition. */
typedef struct
{

View File

@ -20,7 +20,6 @@
#include "modserver.h"
#include "music.h"
#include "richpresence.h"
#include "servers.h"
#include "tcp.h"
#include "updates.h"
#include "gamelibrary.h"

View File

@ -1,5 +1,25 @@
/*
* 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.
*/
var string g_lastDisconnectReason = "";
/** Query if we've been disconnected from the server.
The function is designed to be run every frame. It will return `true` only once per server session, so check it in one place and cache the result if necessary. This is meant for menu developers. If you are adding onto an existing menu framework, calling it more than once and out of order may break core menu functionality in your module.
@return Will return `true` if we've been disconnected and `false` any other time. */
bool
Error_ServerDisconnected(void)
{
@ -18,6 +38,9 @@ Error_ServerDisconnected(void)
return true;
}
/** Query the last reason for a server disconnect. Will stick and always return something valid when you've been disconnected at least once.
@return The reason for the disconnect. */
string
Error_GetDisconnectReason(void)
{

View File

@ -4,7 +4,6 @@ master.qc
modserver.qc
music.qc
richpresence.qc
servers.qc
tcp.qc
util.qc
updates.qc

View File

@ -14,6 +14,16 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*! @file modserver.h
@brief Remote ModServer APIs
The ModServer API manages the retrieval of custom game info
(usually modifications) into the ModLibrary.
This is kept separate from ModLibrary, in case where
connections to remote sources is disallowed.
*/
/* Emscripten builds and mods? Forgetaboutit! */
#ifndef WEBMENU

View File

@ -23,6 +23,8 @@
This is the code that handles how music track id's are translated
into different path/naming conventions and file formats.
Some tracks may only want to be played once (as opposed to looping).
*/
/* we're forced to support a few different paths */

View File

@ -1,18 +0,0 @@
/*
* 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.
*/
/* returns if a given address is external */
int Server_IsLan(string address);

View File

@ -1,30 +0,0 @@
/*
* 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
Server_IsLan(string address)
{
#if 0
return (0);
#endif
tokenizebyseparator(address, ".");
if (argv(0) == "192" && argv(1) == "168") {
return (1);
} else {
return (0);
}
}

View File

@ -14,6 +14,21 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*! @file tcp.h
@brief TCP/IP Networking API
The TCP API manages the sending/receiving of data over TCP sockets.
First, establish a connection with TCP_Connect(), which will return
a file descriptior.
If TCP_Connect returns a value below 0, no connection is possible.
You can send data through TCP_Send() once TCP_GetState returns
STATE_CONNECTED.
You need to run TCP_Frame() on your tcpinfo_t struct every frame
in order to listen to network activity.
*/
#define TCP_BUFFER_LENGTH 32
/** State of a TCP connection. */

View File

@ -140,21 +140,41 @@ typedef enum {
/** Monster flags, these are defined by the level designers. */
typedef enumflags
{
MSF_WAITTILLSEEN,
MSF_GAG,
MSF_MONSTERCLIP,
MSF_RESERVED1,
MSF_PRISONER,
MSF_RESERVED2,
MSF_IGNOREPLAYER,
MSF_WAITFORSCRIPT,
MSF_RESERVED3,
MSF_FADECORPSE,
MSF_MULTIPLAYER,
MSF_FALLING,
MSF_HORDE
MSF_WAITTILLSEEN, /**< AI will be enabled once seen (1) */
MSF_GAG, /**< Won't talk (2) */
MSF_MONSTERCLIP, /**< Collides against func_monsterclip (4) */
MSF_RESERVED1, /**< Reserved for entityDef (8) */
MSF_PRISONER, /**< Only reacts to scripted sequences (16) */
MSF_RESERVED2, /**< Reserved for entityDef (32) */
MSF_IGNOREPLAYER, /**< Ignores players (64) */
MSF_WAITFORSCRIPT, /**< AI waits for scripted_sequence to end (128) */
MSF_RESERVED3, /**< Reserved for entityDef (256) */
MSF_FADECORPSE, /**< Corpse fades instead of staying (512) */
MSF_MULTIPLAYER, /**< Will spawn in multiplayer NSGameRules (1024) */
MSF_FALLING, /**< Is falling (2048) */
MSF_HORDE /**< Part of a horde (4096) */
} monsterFlag_t;
/** For future use: SpawnFlags used in Source */
typedef enumflags
{
SMSF_WAITTILLSEEN, /**< AI will be enable once seen (1) */
SMSF_GAG, /**< Won't talk (2) */
SMSF_FALLTOGROUND, /**< Fall to ground, instead of dropping instantly (4) */
SMSF_DROPHEALTHKIT, /**< Drops healthkit (8) */
SMSF_EFFICIENT, /**< Walks direct paths (16) */
SMSF_RESERVED1, /**< Reserved for entityDef (32) */
SMSF_RESERVED2, /**< Reserved for entityDef (64) */
SMSF_WAITFORSCRIPT, /**< AI waits for scripted_sequence to end (128) */
SMSF_LONGVISIBILITY, /**< Long visibility and line of sight (256) */
SMSF_FADECORPSE, /**< Corpse fades instead of staying (512) */
SMSF_THINKOUTPVS, /**< Think outside the PVS (1024) */
SMSF_TEMPLATE, /**< Will spawn through npc_maker (2048) */
SMSF_ALTCOLLISION, /**< Alternative collision, avoiding players (4096) */
SMSF_NODROPWEAPONS, /**< Don't drop weapons (8192) */
SMSF_IGNOREPLAYERPUSH /**< Ignore pushing players (16384) */
} sourceMonsterFlag_t;
/** Behaviour states. */
typedef enum
{

View File

@ -382,7 +382,7 @@ NSRenderableEntity::RenderFXPass(void)
break;
case RM_SOLID:
colormod = [1,1,1];
alpha = 1.0f;
alpha = m_flRenderAmt == 0.0 ? 0.0f : 1.0f;
glowmod[0] = 0.5f;
break;
case RM_ADDITIVE:

View File

@ -14,7 +14,42 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*! @file cloader.h
@brief Constants macro loader
Scripters and level designers are able to define parameters through the use
of name-based lookups.
In the game directory, they are defined within `scripts/constants.txt`.
An example file looks like this:
```
// weapon constants
WEAPON_NONE 0
WEAPON_KNIFE 1
WEAPON_POTATO 2
```
Within [EntityDefs](Documentation/EntityDef.md) files, you will then be able to set a given key to the value
of one of the defined constants by prefixing the name with a `$` symbol.
That would look something like this:
```
"weapon" "$WEAPON_POTATO"
```
The same applies to data read within level files and most routines related to parsing key/value pairs, so it is not limited to usage within EntityDef.
*/
/** Called upon world init internally to populate our look-up table.
*/
void Constants_Init(void);
string Constants_LookUp(string, string);
/** Look up a name and retrieve its value.
@param constName Name of the constant to look up.
@param returnValue The value to return if constName is not defined.
@return The value of the named constant. Will return returnValue if it does not exist. */
string Constants_LookUp(string constName, string returnValue);
var hashtable g_hashConstants;

View File

@ -15,7 +15,10 @@
*/
/** Takes a normalized color vector and returns the hexadecimal equivalent
for "funstrings". E.g. '1.0 0.0 0.0' becomes "^xF00". */
for "funstrings". E.g. '1.0 0.0 0.0' becomes "^xF00".
@param color Normalized color value to convert.
@return Returns the funstring equivalent.*/
string
Colors_RGB8_to_HEX(vector color)
{
@ -23,7 +26,10 @@ Colors_RGB8_to_HEX(vector color)
}
/** Takes a 0-255 based color vector and returns the hexadecimal equivalent
for "funstrings". E.g. '255 0 0' becomes "^xF00". */
for "funstrings". E.g. '255 0 0' becomes "^xF00".
@param color 0-255 based color value to convert.
@return Returns the funstring equivalent.*/
string
Colors_RGB255_to_HEX(vector color)
{

View File

@ -126,6 +126,7 @@ string __fullspawndata;
#include "colors.h"
#include "weapons.h"
#include "motd.h"
#include "util.h"
#define BSPVER_PREREL 28
#define BSPVER_Q1 29
@ -503,4 +504,14 @@ Route_GetJumpVelocity(vector vecFrom, vector vecTo, float flGravMod)
vecJump[2] = 280;
#endif
return vecJump;
}
bool
FileExists(string filePath)
{
if (filePath != "") /* not empty */
if not(whichpack(filePath)) /* not present on disk */
return false;
return true;
}

1
src/shared/util.h Normal file
View File

@ -0,0 +1 @@
void Util_ChangeClass(entity, string);

View File

@ -60,4 +60,13 @@ Util_IsTeamplay(void)
#else
return (serverkeyfloat("teams") > 0) ? (true) : (false);
#endif
}
void
Util_ChangeClass(entity objectID, string className)
{
entity oldSelf = self;
self = objectID;
callfunction(strcat("spawnfunc_", className));
self = oldSelf;
}

View File

@ -14,6 +14,12 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*! @file NSXRInput.h
@brief Managing of Input sources.
An NSXRInput contains the state of a potential input source.
*/
/** Various input device types.
Right now each client will have a single head, a 'left' and a 'right' NSXRInput. */
typedef enum

View File

@ -14,9 +14,16 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** This class represents a local client space in the world.
/*! @file NSXRSpace.h
@brief Managing of simulated Spaces.
It's used to handle room to world translation for VR, for example.
NSXRSpace manages the conversion between real-world
to game-world coordinates.
It's used to handle room to world translation for VR, for example.
*/
/** This class represents a local client space in the world.
*/
class NSXRSpace {
public:

View File

@ -14,15 +14,20 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** Called internally by client/server modules for when a player joins. */
void XR_Init(entity);
/** Called internally by client/server modules for when a player leaves. */
void XR_Shutdown(entity);
/** Returns if XR features are available on the entity. */
bool XR_Available(entity);
/** Called on client/server modules after an input packet has been dispatched. */
void XR_InputFrame(entity);
#ifdef CLIENT
/** Sets up view properties from a client entity before a rendering call. */
void XR_UpdateView(entity);
#endif
var float autocvar_xr_roomscale = 1.0f;
var float autocvar_xr_viewheight = -48.0f;
var bool autocvar_xr_debug_fakeinputs = false;
var float autocvar_xr_roomScale = 1.0f;
var float autocvar_xr_viewHeight = -48.0f;
var bool autocvar_xr_testInputs = false;

View File

@ -73,7 +73,7 @@ XR_UpdateView(entity ePlayer)
/* now we get the HMD's org/ang and send that off to the renderer */
setviewprop(VF_ANGLES, pl.m_xrInputHead.GetAngles());
setviewprop(VF_ORIGIN, pl.m_xrInputHead.GetOrigin() + [0,0,autocvar_xr_viewheight]);
setviewprop(VF_ORIGIN, pl.m_xrInputHead.GetOrigin() + [0,0, autocvar_xr_viewHeight]);
} else {
pl.m_xrSpace.SetOrigin(g_view.GetCameraOrigin());
pl.m_xrSpace.SetAngles(input_angles);
@ -95,7 +95,7 @@ XR_InputFrame(entity ePlayer)
if (!pl.m_xrSpace)
return;
if (autocvar_xr_debug_fakeinputs) {
if (autocvar_xr_testInputs) {
input_head_status = (XR_STATUS_ORG | XR_STATUS_ANG);
input_left_status = (XR_STATUS_ORG | XR_STATUS_ANG);
input_right_status = (XR_STATUS_ORG | XR_STATUS_ANG);
@ -113,7 +113,6 @@ XR_InputFrame(entity ePlayer)
pl.m_xrInputHead.InputFrame();
pl.m_xrInputLeft.InputFrame();
pl.m_xrInputRight.InputFrame();
}
bool