- add GetNextWeapon(), GetPreviousWeapon(), GetLastWeapon() to NSActor

- allow weapon sorting in overridable NSActor::SortWeaponChain() method
- add isClient() as isPlayer() doesn't take spectators into account
- fix various CS specific zone
- ungodly amount of documentation improvements
- worldspawn ent work delegated to separate ent slot
- NSClientPlayer::MakePlayer no longer wipes the inventory.
- fix team selection race condition exploit in FreeCS
This commit is contained in:
Marco Cawthorne 2024-08-14 16:10:57 -07:00
parent e4ab1bd671
commit 02301994ce
Signed by: eukara
GPG key ID: CE2032F0A2882A22
33 changed files with 507 additions and 303 deletions

View file

@ -56,7 +56,6 @@ public:
virtual void RenderView(void);
virtual void SetupView(void);
private:
/* internal */
vector m_vecOrigin;

View file

@ -236,6 +236,18 @@ CMD_ListModelFramegroups(void)
print("} framegroups_e;\n");
}
void
NSWeapon_SelectWeapon(NSWeapon nextWeapon)
{
if (!nextWeapon) {
pSeat->m_iHUDWeaponSelected = 0i;
return;
}
/* this gets passed in NSClientPlayer::ClientInputFrame() to the server */
pSeat->m_iHUDWeaponSelected = nextWeapon.GetSharedID();
}
/*
=================
Cmd_Parse
@ -249,6 +261,7 @@ to handle it from there.
bool
Cmd_Parse(string sCMD)
{
NSClient localPlayer = (NSClient)pSeat->m_ePlayer;
switch (argv(0)) {
case "listFramegroups":
CMD_ListModelFramegroups();
@ -391,13 +404,13 @@ Cmd_Parse(string sCMD)
pSeat->m_iInputJump = false;
break;
case "weapnext":
NSWeapon_NextWeapon((NSClientPlayer)pSeat->m_ePlayer);
NSWeapon_SelectWeapon(localPlayer.GetNextWeapon());
break;
case "weapprev":
NSWeapon_PrevWeapon((NSClientPlayer)pSeat->m_ePlayer);
NSWeapon_SelectWeapon(localPlayer.GetPreviousWeapon());
break;
case "weaplast":
NSWeapon_LastWeapon((NSClientPlayer)pSeat->m_ePlayer);
NSWeapon_SelectWeapon(localPlayer.GetLastWeapon());
break;
case "+showscores":
pSeat->m_iScoresVisible = TRUE;

View file

@ -18,6 +18,13 @@
void EntityDef_Init(void);
void MapTweaks_Init(void);
var int autocvar_sv_levelexec = 1;
void serverinfoSet(string keyName, string setValue)
{
//localcmd(sprintf("echo Server Info set: %S %S\n", keyName, setValue));
localcmd(sprintf("serverinfo %S %S\n", keyName, setValue));
}
#endif
/*! \brief Shared-Entity: Game World */
@ -55,10 +62,10 @@ This entity was introduced in Quake (1996).
*/
#ifdef SERVER
class worldspawn:NSEntity
class NSWorldspawn:NSEntity
{
public:
void worldspawn(void);
void NSWorldspawn(void);
virtual void Spawned(void);
virtual void Save(float);
@ -83,7 +90,7 @@ private:
};
void
worldspawn::worldspawn(void)
NSWorldspawn::NSWorldspawn(void)
{
/* defaults */
m_flHDRIrisMinValue = 0.0;
@ -110,7 +117,6 @@ worldspawn::worldspawn(void)
InitPrint("Map Initialization");
NSLog("Map: %s", mapname);
InitPrint("Game Map Init");
lightstyle(0, "m");
lightstyle(1, "mmnmmommommnonmmonqnmmo");
@ -131,47 +137,46 @@ worldspawn::worldspawn(void)
//if (autocvar_sv_levelexec)
// readcmd(sprintf("exec maps/%s.cfg\n", mapname));
InitStart();
}
void
worldspawn::Spawned(void)
NSWorldspawn::Spawned(void)
{
super::Spawned();
touch = __NULL__;
blocked = __NULL__;
forceinfokey(world, "skyname", m_strSkyName);
forceinfokey(world, "chaptertitle", m_strChapterTitle);
forceinfokey(world, "ambientsound", m_strAmbientSound);
forceinfokey(world, "bgm", m_strBGMTrack);
serverinfoSet("skyname", m_strSkyName);
serverinfoSet("chaptertitle", m_strChapterTitle);
serverinfoSet("ambientsound", m_strAmbientSound);
serverinfoSet("bgm", m_strBGMTrack);
/* these set cvars so we kinda always want to set them to ~something~ */
forceinfokey(world, "hdr_iris_minvalue", ftos(m_flHDRIrisMinValue));
forceinfokey(world, "hdr_iris_maxvalue", ftos(m_flHDRIrisMaxValue));
forceinfokey(world, "hdr_iris_multiplier", ftos(m_flHDRIrisMultiplier));
forceinfokey(world, "hdr_iris_fade_up", ftos(m_flHDRIrisFadeUp));
forceinfokey(world, "hdr_iris_fade_down", ftos(m_flHDRIrisFadeDown));
forceinfokey(world, "hdr", ftos(m_bHDREnabled));
serverinfoSet("hdr_iris_minvalue", ftos(m_flHDRIrisMinValue));
serverinfoSet("hdr_iris_maxvalue", ftos(m_flHDRIrisMaxValue));
serverinfoSet("hdr_iris_multiplier", ftos(m_flHDRIrisMultiplier));
serverinfoSet("hdr_iris_fade_up", ftos(m_flHDRIrisFadeUp));
serverinfoSet("hdr_iris_fade_down", ftos(m_flHDRIrisFadeDown));
serverinfoSet("hdr", ftos(m_bHDREnabled));
/* don't want to litter serverinfo with '0' keys. */
if (m_bGameTitle) {
forceinfokey(world, "gametitle", ftos(m_bGameTitle));
serverinfoSet("gametitle", ftos(m_bGameTitle));
} else {
forceinfokey(world, "gametitle", "");
serverinfoSet("gametitle", "");
}
if (m_bStartDark) {
forceinfokey(world, "startdark", ftos(m_bStartDark));
serverinfoSet("startdark", ftos(m_bStartDark));
} else {
forceinfokey(world, "startdark", "");
serverinfoSet("startdark", "");
}
if (m_bLitWater) {
forceinfokey(world, "litwater", ftos(m_bLitWater));
serverinfoSet("litwater", ftos(m_bLitWater));
} else {
forceinfokey(world, "litwater", "");
serverinfoSet("litwater", "");
}
#if 0
@ -185,7 +190,7 @@ worldspawn::Spawned(void)
}
void
worldspawn::SpawnKey(string strKey, string strValue)
NSWorldspawn::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "skyname":
@ -242,7 +247,7 @@ worldspawn::SpawnKey(string strKey, string strValue)
}
void
worldspawn::Save(float handle)
NSWorldspawn::Save(float handle)
{
super::Save(handle);
@ -262,7 +267,7 @@ worldspawn::Save(float handle)
}
void
worldspawn::Restore(string strKey, string strValue)
NSWorldspawn::Restore(string strKey, string strValue)
{
switch (strKey) {
case "m_strSkyName":
@ -309,6 +314,23 @@ worldspawn::Restore(string strKey, string strValue)
break;
}
}
void
worldspawn(void)
{
NSWorldspawn ourWorld = spawn(NSWorldspawn);
ourWorld.pvsflags = PVSF_IGNOREPVS;
/* fill the delegate with spawndata */
if (__fullspawndata) {
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
ourWorld.SpawnKey(argv(i), argv(i+1));
}
}
ourWorld.Spawned();
}
#endif
#ifdef CLIENT

View file

@ -14,17 +14,18 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @defgroup achievements Achievements
* @brief Achievements, unlockables API reference.
* @ingroup menu
*
* The Achievements API manages the retrieval, storage and networking
* of game achievements.
*
* This is a work in progress.
* @{
*
*/
/**
@defgroup achievements Achievements
@brief Achievements, unlockables API reference.
@ingroup menu
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
@ -78,4 +79,4 @@ void Achievement_IndicateProgress(string strName, int iCurrent, int iMax);
@return Will return false upon failure. */
bool Achievement_RequestStats(achievement_t *ptr, int count);
/** @} */ // end of achievements
/** @} */ // end of achievements

View file

@ -14,20 +14,21 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @defgroup activitypub ActivityPub
@brief ActivityPub social networking integration
@ingroup menu
/**
@defgroup activitypub ActivityPub
@brief ActivityPub social networking integration
@ingroup menu
The console command `ap_userID` can be used
to set certain infokeys of the local user to mimic
that of a certain ActivityPub id. An example format
would look like: `/ap_userID @johndoe@example.com`
The console command `ap_userID` can be used
to set certain infokeys of the local user to mimic
that of a certain ActivityPub id. An example format
would look like: `/ap_userID @johndoe@example.com`
Currently we're not broadcasting the identity
because there's no real way of verifying who
you are without a central authority.
Currently we're not broadcasting the identity
because there's no real way of verifying who
you are without a central authority.
@{
@{
*/
#define ACTIVITYPUB_ACCOUNTS 400
@ -36,4 +37,4 @@
void ActivityPub_FetchAccountData(string apUserID);
void ActivityPub_UpdatePlayerInfo(string jsonData);
/** @} */ // end of activitypub
/** @} */ // end of activitypub

View file

@ -27,4 +27,4 @@
bool Platform_ConsoleCommand(string commandString, int wordCount);
/** Called in order to register the platform library console commands. Called in your menu progs' m_init() function. */
void Platform_RegisterCommands(void);
void Platform_RegisterCommands(void);

View file

@ -43,4 +43,4 @@ typedef enum
GPMI_ACTION, /**< desired state */
GPMI_AVAILABLE, /**< whether it may be downloaded or not. */
GPMI_FILESIZE, /**< size to download. */
} packageType_t;
} packageType_t;

View file

@ -17,13 +17,13 @@
var string g_lastDisconnectReason = "";
/** @defgroup servererror Server Error Message Query
@brief Retrieve server error messages, reasons etc.
@ingroup menu
/**
@defgroup servererror Server Error Message Query
@brief Retrieve server error messages, reasons etc.
@ingroup menu
@{
*/
@{
*/
/** 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.
@ -56,4 +56,4 @@ Error_GetDisconnectReason(void)
return g_lastDisconnectReason;
}
/** @} */ // end of servererror
/** @} */ // end of servererror

View file

@ -14,39 +14,40 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @defgroup gamelibrary Game Library
@ingroup menu
@brief Locally-installed games, modification control functions
/**
@defgroup gamelibrary Game Library
@ingroup menu
@brief Locally-installed games, modification control functions
The GameLibrary concerns itself with everything around what a game is,
how to install, activate and deactivate it. Mods are included in this,
so we'll proceed calling them 'games' or 'custom games'.
The GameLibrary concerns itself with everything around what a game is,
how to install, activate and deactivate it. Mods are included in this,
so we'll proceed calling them 'games' or 'custom games'.
A game can be installed through two primary means:
A game can be installed through two primary means:
- Manual install, like from a .zip or some installer or archive
- Engine package manager install, through our own user interface
- Manual install, like from a .zip or some installer or archive
- Engine package manager install, through our own user interface
And between these, they can come with different metadata/manifests.
And between these, they can come with different metadata/manifests.
It assumed that every game has either a FTE Manifest description,
a gameinfo.txt (Source Engine format) or liblist.gam (GoldSrc format)
that describes various aspects of the game. Like which version it is, what
map will be loaded when you press 'New Game' and so on.
It assumed that every game has either a FTE Manifest description,
a gameinfo.txt (Source Engine format) or liblist.gam (GoldSrc format)
that describes various aspects of the game. Like which version it is, what
map will be loaded when you press 'New Game' and so on.
If that info is not available, some placeholder data will be used instead.
However, games installed via the package manager will at least for the
custom game menus not use the on-disk manifest file, but information
provided by the package manager. Once you switch into said game everything
within will be pulled from a file on disk, such as a liblist.gam or gameinfo.txt.
If that info is not available, some placeholder data will be used instead.
However, games installed via the package manager will at least for the
custom game menus not use the on-disk manifest file, but information
provided by the package manager. Once you switch into said game everything
within will be pulled from a file on disk, such as a liblist.gam or gameinfo.txt.
The menu needs to call GameLibrary_Init() once for parsing the currently running
game its own metadata. If you want to index custom games, aka mods, you need
to do so with GameLibrary_InitCustom() afterwards.
The menu needs to call GameLibrary_Init() once for parsing the currently running
game its own metadata. If you want to index custom games, aka mods, you need
to do so with GameLibrary_InitCustom() afterwards.
Because indexing mods can take a very long time depending on the amount
that is stored on disk, you may want to call GameLibrary_InitCustom() at
a later time.
Because indexing mods can take a very long time depending on the amount
that is stored on disk, you may want to call GameLibrary_InitCustom() at
a later time.
@{
*/
@ -152,4 +153,4 @@ int gameinfo_count;
gameEntry_t *games;
#endif
/** @} */ // end of gamelibrary
/** @} */ // end of gamelibrary

View file

@ -14,24 +14,24 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @defgroup maplibrary Map Library
@brief Locally installed maps/levels control functions
@ingroup menu
Menus need to be aware of what levels aka maps are available for modes like
multiplayer. The MapLibrary is by configured to only parse levels from the
current game directory (much like GoldSrc) and optionally can blacklist
maps based on a variety of criteria which may be configurable at some point
in time.
The menu needs to call MapLibrary_Init() at least once, after which you can
query the total amount of maps that are available via MapLibrary_GetMapCount().
You can then iterate over the individual entries with MapLibrary_GetInfo().
@{
/**
@defgroup maplibrary Map Library
@brief Locally installed maps/levels control functions
@ingroup menu
*/
Menus need to be aware of what levels aka maps are available for modes like
multiplayer. The MapLibrary is by configured to only parse levels from the
current game directory (much like GoldSrc) and optionally can blacklist
maps based on a variety of criteria which may be configurable at some point
in time.
The menu needs to call MapLibrary_Init() at least once, after which you can
query the total amount of maps that are available via MapLibrary_GetMapCount().
You can then iterate over the individual entries with MapLibrary_GetInfo().
@{
*/
/** Options querying Map Library entries using `MapLibrary_GetInfo()`. */
typedef enum
@ -62,4 +62,4 @@ int MapLibrary_GetMapCount(void);
/** Retrieve information about a given mapID. See mapType_t for which fields you can query. */
__variant MapLibrary_GetInfo(int, mapType_t);
/** @} */ // end of maplibrary
/** @} */ // end of maplibrary

View file

@ -14,12 +14,13 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*! @defgroup masterserver Master Server
@ingroup menu
@brief Master Server related functions.
/*!
@defgroup masterserver Master Server
@ingroup menu
@brief Master Server related functions.
Various functions to help communicate with the master
server(s).
Various functions to help communicate with the master
server(s).
@{
*/

View file

@ -14,17 +14,18 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @defgroup modserver Mod Server
@ingroup menu
@brief Remotely available modifications, addons control/install functions
/**
@defgroup modserver Mod Server
@ingroup menu
@brief Remotely available modifications, addons control/install functions
The ModServer API manages the retrieval of custom game info
(usually modifications) into the [Game Library](@ref gamelibrary).
The ModServer API manages the retrieval of custom game info
(usually modifications) into the [Game Library](@ref gamelibrary).
This is kept separate, in case where
connections to remote sources is disallowed.
This is kept separate, in case where
connections to remote sources is disallowed.
@{
@{
*/
/* Emscripten builds and mods? Forgetaboutit! */

View file

@ -14,20 +14,21 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @defgroup music Music
* @ingroup menu
@brief Music looping, stinger related functions
/**
@defgroup music Music
@ingroup menu
@brief Music looping, stinger related functions
This is the internal music handler.
Games primarily will use in-game entities such as trigger_cdaudio
and target_cdaudio to play/change music tracks.
This is the internal music handler.
Games primarily will use in-game entities such as trigger_cdaudio
and target_cdaudio to play/change music tracks.
This is the code that handles how music track id's are translated
into different path/naming conventions and file formats.
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).
Some tracks may only want to be played once (as opposed to looping).
@{
@{
*/
/* we're forced to support a few different paths */
@ -93,4 +94,4 @@ void Music_ParseLoop(string parm);
Will start playing whatever track is defined in the manifest or liblist file. */
void Music_MenuStart(void);
/** @} */ // end of music
/** @} */ // end of music

View file

@ -14,25 +14,26 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @defgroup richpresence Rich Presence
@ingroup menu
@brief Sharing of game state/info for social purposes.
/**
@defgroup richpresence Rich Presence
@ingroup menu
@brief Sharing of game state/info for social purposes.
This is the internal rich presence handler.
Rich presence is when the platform outside of the game communicates
to other users what game it is we are playing and how to connect to it.
This is the internal rich presence handler.
Rich presence is when the platform outside of the game communicates
to other users what game it is we are playing and how to connect to it.
An example would be a friends-list where you see that a player
is in game "Example Game" playing a multiplayer game on "Example map".
An example would be a friends-list where you see that a player
is in game "Example Game" playing a multiplayer game on "Example map".
In addition it will expose a way for the game to supply a connect
command to the command-line, so that those players can join via the
platform interface.
In addition it will expose a way for the game to supply a connect
command to the command-line, so that those players can join via the
platform interface.
The console command `richpresence_dump` will output the current set
of key/value pairs that will be shared with the platform.
The console command `richpresence_dump` will output the current set
of key/value pairs that will be shared with the platform.
@{
@{
*/
/** Sets a rich-presence key to the desired value.
@ -55,4 +56,4 @@ bool RichPresence_WasSet(void);
/** Debug function that prints the currently active rich-presence keys to console. */
void RichPresence_DumpInfo(void);
/** @} */ // end of richpresence
/** @} */ // end of richpresence

View file

@ -14,22 +14,23 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @defgroup tcp TCP/IP
* @ingroup menu
@brief TCP/IP Networking API
/**
@defgroup tcp TCP/IP
@ingroup menu
@brief TCP/IP Networking API
The TCP API manages the sending/receiving of data over TCP sockets.
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.
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.
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
@ -83,4 +84,4 @@ void TCP_Frame(tcpinfo_t *in);
@param in Pointer to an active TCP connection.*/
tcpstate_t TCP_GetState(tcpinfo_t *in);
/** @} */ // end of tcp
/** @} */ // end of tcp

View file

@ -14,9 +14,10 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @defgroup updates Update Manager
* @ingroup menu
@brief Game and content update handler functions.
/**
@defgroup updates Update Manager
@ingroup menu
@brief Game and content update handler functions.
The updater is an abstraction of the engine its own package manager.
Not all packages the engine offers are related to the game you're currently
@ -30,7 +31,7 @@ The function Updates_GetPackageCount() will report the total amount of update pa
Use Updates_GetInfo() to retrieve metadata about individual packages.
@{
@{
*/
/** Different options you can pass to Updates_GetInfo() to retrieve details about a given Update entry. */
@ -126,4 +127,4 @@ bool Updates_Destroy(int);
/** Apply all pending changes to packages. May return true/false if it succeeded in doing so. */
bool Updates_ApplyPendingChanges(void);
/** @} */ // end of updates
/** @} */ // end of updates

View file

@ -19,27 +19,31 @@ Cmd_ParseClientCommand(NSClient sender, string cmd, int commandArguments)
{
switch (argv(0)) {
case "say":
if (commandArguments == 2)
if (commandArguments == 2) {
g_grMode.ChatMessageAll(sender, argv(1));
else
} else {
g_grMode.ChatMessageAll(sender, substring(cmd, 4, -1));
}
break;
case "say_team":
if (commandArguments == 2)
if (commandArguments == 2) {
g_grMode.ChatMessageTeam(sender, argv(1));
else
} else {
g_grMode.ChatMessageTeam(sender, substring(cmd, 10, -2));
}
break;
case "spectate":
if (sender.classname != "player")
if (sender.classname != "player") {
break;
}
NSClientPlayer pl = (NSClientPlayer)sender;
pl.MakeSpectator();
break;
case "play":
if (sender.classname != "spectator")
if (sender.classname != "spectator") {
break;
}
EntityDef_SpawnClassname("player");
PutClientInServer();
@ -63,16 +67,13 @@ Cmd_ParseClientCommand(NSClient sender, string cmd, int commandArguments)
NSActor_ListInventory((NSActor)self);
break;
case "giveInventoryItem":
NSActor player = (NSActor)self;
player.GiveItem(argv(1));
(NSActor)sender.GiveItem(argv(1));
break;
case "removeInventoryItem":
NSActor player = (NSActor)self;
player.RemoveItem(argv(1));
(NSActor)sender.RemoveItem(argv(1));
break;
case "removeAllInventoryItems":
NSActor player = (NSActor)self;
player.RemoveAllItems(false);
(NSActor)sender.RemoveAllItems(false);
break;
case "listAmmo":
Ammo_DebugList();

View file

@ -365,8 +365,6 @@ init_respawn(void)
NSLog("...%i entities spawned (%i inhibited)", g_ent_spawned, g_ent_spawned - endspawn);
InitEnd();
Nodes_Init();
remove(self);
@ -679,7 +677,9 @@ CheckSpawn(void() spawnfunc)
NSEntity ent = (NSEntity)self;
string desiredClass = ent.classname;
if (ent.classname == "worldspawn") {
/* cancel out early */
if (ent == world) {
worldspawn();
return;
}

View file

@ -1155,16 +1155,6 @@ NSClientPlayer::MakePlayer(void)
armor = 0;
}
if (m_activeWeapon) {
m_activeWeapon.Destroy();
m_activeWeapon = __NULL__;
}
if (m_itemList) {
m_itemList.Destroy();
m_itemList = __NULL__;
}
effects = 0;
alpha = 1.0f;
SetSolid(SOLID_SLIDEBOX);

View file

@ -14,6 +14,18 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @defgroup decl Declaration Files
@brief External plain text files often containing groups of key-value pairs.
The core of Nuclide embraces external files called 'declaration files'.
They often contain key-value pairs, much like the entity spawn data
within a level.
You will commonly find them within `<gamedir>/decls/`.
@{
*/
/** This class is responsible for handling groups of key/value pairs.
It handles entity spawns, respawns,
@ -22,6 +34,8 @@ which is our basic entity model.
This is a very low-level class. You're never meant to use this.
Use NSEntity as a basis for your classes.
@ingroup decl
*/
class
NSDict
@ -46,3 +60,5 @@ private:
nonvirtual void _AddRemoveKey(string, string, bool);
string m_strBody;
};
/** @} */ // end of decl

View file

@ -438,6 +438,8 @@ bool isAlive(entity entityToCheck);
bool isGodMode(entity entityToCheck);
bool isClient(entity entityToCheck);
bool isPlayer(entity entityToCheck);
bool isSentient(entity entityToCheck);

View file

@ -1540,6 +1540,12 @@ isGodMode(entity entityToCheck)
return (false);
}
bool
isClient(entity entityToCheck)
{
return (entityToCheck.flags & FL_CLIENT) ? (true) : (false);
}
bool
isPlayer(entity entityToCheck)
{

View file

@ -116,9 +116,9 @@ public:
private:
/** Called to signal that the owner added this weapon to their inventory. */
nonvirtual void _AddedCallback(void);
virtual void _AddedCallback(void);
/** Called to signal that the owner removed this weapon from their inventory. */
nonvirtual void _RemovedCallback(void);
virtual void _RemovedCallback(void);
int m_iClip;
int m_iWasDropped;

View file

@ -1796,7 +1796,6 @@ NSMonster::Respawn(void)
RestoreAngles();
m_vecSequenceAngle = GetAngles();
SetOrigin(GetSpawnVector("origin"));
NSError("%S: %v, %v", classname, GetAngles(), GetOrigin());
DropToFloor();
SetOriginUnstick(origin);
}

View file

@ -115,6 +115,15 @@ public:
nonvirtual void LaunchProjectile(string, bool, float);
nonvirtual bool PlantCharge(string);
/** Returns the first weapon in the chain, while ensuring the inventory is sorted. */
virtual NSWeapon SortWeaponChain(void);
/** Retrieve the 'next' weapon in the inventory, sorted by SortWeaponChain(). */
nonvirtual NSWeapon GetNextWeapon(void);
/** Retrieve the 'next' weapon in the inventory, sorted by SortWeaponChain(). */
nonvirtual NSWeapon GetPreviousWeapon(void);
/** Retrieve the 'last' weapon they had chosen. If not valid, returns the next best. */
nonvirtual NSWeapon GetLastWeapon(void);
#ifdef SERVER
/* overrides */
virtual void Save(float);

View file

@ -787,7 +787,7 @@ NSActor::SwitchToBestWeapon(bool ignoreActive)
float weight;
if (toIgnore == weaponName) {
linkedList = linkedList.chain;
linkedList = (NSItem)linkedList.chain;
continue;
}
@ -799,11 +799,11 @@ NSActor::SwitchToBestWeapon(bool ignoreActive)
}
}
linkedList = linkedList.chain;
linkedList = (NSItem)linkedList.chain;
}
if (bestWeapon) {
SwitchToExactWeapon(bestWeapon);
SwitchToExactWeapon((NSWeapon)bestWeapon);
}
}
@ -988,6 +988,129 @@ NSActor::AddItem(NSItem theItem)
return (false);
}
NSWeapon
NSActor::SortWeaponChain(void)
{
NSWeapon itemChain = (NSWeapon)m_itemList;
int heighestSlot = -1i;
int heighestPos = -1i;
NSWeapon firstWeapon, lastWeapon;
int hudSlot, hudPos;
firstWeapon = lastWeapon = __NULL__;
if (!m_itemList) {
return __NULL__;
}
/* first we determine the range of our hud buckets. */
while (itemChain) {
if (itemChain.IsWeapon() == true) {
hudSlot = itemChain.GetDefInt("hudSlot");
hudPos = itemChain.GetDefInt("hudSlotPos");
if (hudSlot > heighestSlot) {
heighestSlot = hudSlot;
}
if (hudPos > heighestPos) {
heighestPos = hudPos;
}
}
itemChain = (NSWeapon)itemChain.chain;
}
for (int hS = 0i; hS <= heighestSlot; hS++) {
for (int hP = 0i; hP <= heighestPos; hP++) {
itemChain = (NSWeapon)m_itemList;
while (itemChain) {
if (itemChain.IsWeapon() == true) {
hudSlot = itemChain.GetDefInt("hudSlot");
hudPos = itemChain.GetDefInt("hudSlotPos");
if (hudSlot == hS && hudPos == hP) {
/* first weapon in the chain? */
if (!lastWeapon) {
firstWeapon = itemChain;
lastWeapon = firstWeapon;
} else {
/* assign this weapon to the last weapon of our chain. */
lastWeapon.m_nextWeapon = itemChain;
itemChain.m_prevWeapon = lastWeapon;
lastWeapon = itemChain;
}
}
}
itemChain = (NSWeapon)itemChain.chain;
}
}
}
/* test */
NSWeapon weaponTest = firstWeapon;
while (weaponTest) {
weaponTest = weaponTest.m_nextWeapon;
}
firstWeapon.m_prevWeapon = lastWeapon;
return (firstWeapon);
}
bool
NSWeapon_CanSwitch(NSActor pl)
{
if (!pl.m_activeWeapon)
return false;
return true;
}
NSWeapon
NSActor::GetNextWeapon(void)
{
NSWeapon firstWeapon;
if (NSWeapon_CanSwitch(this) == false) {
return (__NULL__);
}
firstWeapon = SortWeaponChain();
if (m_activeWeapon.m_nextWeapon) {
return (m_activeWeapon.m_nextWeapon);
} else {
return (firstWeapon);
}
}
NSWeapon
NSActor::GetPreviousWeapon(void)
{
NSWeapon firstWeapon;
if (NSWeapon_CanSwitch(this) == false) {
return (__NULL__);
}
firstWeapon = SortWeaponChain();
if (m_activeWeapon.m_prevWeapon) {
return (m_activeWeapon.m_prevWeapon);
} else {
return (firstWeapon);
}
}
NSWeapon
NSActor::GetLastWeapon(void)
{
/* TODO: Finish this */
return (m_activeWeapon);
}
void
NSActor_ListInventory(NSActor targetEntity)
{

View file

@ -32,7 +32,7 @@ enumflags
Environmental soundscape and reverb controller.
# KEYS
- "efx_file" : File to load EFX values from.
- "efx_file" : File to load EFX values from. See @decl_efx
- "density" : See SetDensity()
- "diffusion" : See SetDiffusion()
- "gain" : See SetGain()
@ -58,25 +58,6 @@ Environmental soundscape and reverb controller.
- "decay_limit" : See SetDecayHFLimit()
- "radius" : See SetRadius()
# HISTORY
## Creative's Environmental Audio Extensions (EAX) {#eax}
Creative Technology's **Environmental Audio Extensions**, also known as **EAX**, attempted to create more ambiance within video games by more accurately simulating a real-world audio environment.
The release of Windows Vista deprecated the DirectSound3D API on which EAX relied on in 2007, so Creative Technology encouraged the move to OpenAL's EFX.
## EFX
EFX is a system in [OpenAL](https://www.openal.org/) that delivers high quality sound reverberation. It is the successor to @ref eax.
**Nuclide** offers abstraction for new and old entities relying on **digital signal processing**.
# NOTES
Reverb effects only work with the OpenAL sound backend.
# See Also
- https://openal-soft.org/misc-downloads/Effects%20Extension%20Guide.pdf
@ingroup shared
@ingroup sound
@ingroup baseclass
@ -215,6 +196,30 @@ private:
NETWORKED_FLOAT(m_radius)
};
/** @defgroup decl_efx EFX Definition
@ingroup decl
# HISTORY
## Creative's Environmental Audio Extensions (EAX) {#eax}
Creative Technology's **Environmental Audio Extensions**, also known as **EAX**, attempted to create more ambiance within video games by more accurately simulating a real-world audio environment.
The release of Windows Vista deprecated the DirectSound3D API on which EAX relied on in 2007, so Creative Technology encouraged the move to OpenAL's EFX.
## EFX
EFX is a system in [OpenAL](https://www.openal.org/) that delivers high quality sound reverberation. It is the successor to @ref eax.
# NOTES
Reverb effects only work with the OpenAL sound backend.
# See Also
- https://openal-soft.org/misc-downloads/Effects%20Extension%20Guide.pdf
@{
*/
/** @} */ // end of decl_efx
#ifdef CLIENT
void EFX_UpdateSoundScape(NSSoundScape);
#endif

View file

@ -427,7 +427,6 @@ NSTrigger::_TouchHandler(void)
}
#endif
/* start touch in case we haven't */
if (m_beingTouched != true)
StartTouch(other);

View file

@ -267,6 +267,13 @@ private:
nonvirtual void _PrimaryAttack(void);
nonvirtual void _SecondaryAttack(void);
nonvirtual void _SwitchedWeaponMode(void);
virtual void _AddedCallback(void);
virtual void _RemovedCallback(void);
/** Returns the weapon in the next slot of the owners' inventory. */
nonvirtual NSWeapon GetNextWeapon(void);
/** Returns the weapon in the previous slot of the owners' inventory. */
nonvirtual NSWeapon GetPreviousWeapon(void);
#ifdef SERVER
nonvirtual void _ReloadFinished(void);
@ -310,6 +317,9 @@ private:
float m_flSpeedMod;
bool m_bAltModeSwitch;
NSWeapon m_nextWeapon;
NSWeapon m_prevWeapon;
/* cached fireInfo */
string m_fiDetonateOnFire;
float m_fiMeleeRange;

View file

@ -44,11 +44,43 @@ NSWeapon::NSWeapon(void)
m_flReloadSpeed = -1.0f;
}
void
NSWeapon::_AddedCallback(void)
{
NSActor ourOwner = (NSActor)owner;
super::_AddedCallback();
if (!owner) {
return;
}
/* after being stored in someones inventory,
re-sort our inventory according to their logic */
ourOwner.SortWeaponChain();
}
void
NSWeapon::_RemovedCallback(void)
{
if (owner) {
/* give the weapon a chance to clean up the owners inventory */
NSActor ourOwner = (NSActor)owner;
ourOwner.SortWeaponChain();
}
super::_RemovedCallback();
}
void
NSWeapon::AddedToInventory(void)
{
}
void
NSWeapon::RemovedFromInventory(void)
{
}
void
NSWeapon::SwitchedToWeapon(void)
{
@ -59,11 +91,6 @@ NSWeapon::SwitchedFromWeapon(void)
{
}
void
NSWeapon::RemovedFromInventory(void)
{
}
void
NSWeapon::_SetWeaponState(nsweapon_state_t newState)
{
@ -74,7 +101,7 @@ NSWeapon::_SetWeaponState(nsweapon_state_t newState)
m_dState = newState;
#ifdef SERVER
printf("State changed to %s\n", nsweapon_state_s[newState]);
//printf("State changed to %s\n", nsweapon_state_s[newState]);
#endif
}
@ -87,7 +114,6 @@ NSWeapon::GetWeaponState(void)
void
NSWeapon::UpdateFireInfoCache(void)
{
string viewGeomset;
string ammoPerShot = GetSubDefString(m_strLastFireInfo, "ammoPerShot");
string reloadSpeed = GetSubDefString(m_strLastFireInfo, "reloadTime");
m_fiDetonateOnFire = GetSubDefString(m_strLastFireInfo, "detonateOnFire");
@ -128,7 +154,7 @@ NSWeapon::UpdateFireInfoCache(void)
}
#ifdef CLIENT
viewGeomset = GetSubDefString(m_strLastFireInfo, "view_geomset");
string viewGeomset = GetSubDefString(m_strLastFireInfo, "view_geomset");
if (viewGeomset) {
setcustomskin(pSeat->m_eViewModel, "", viewGeomset);
@ -1421,7 +1447,6 @@ NSWeapon::Release(void)
#ifdef SERVER
if (m_bFiring == true) {
NSClientPlayer ourOwner = (NSClientPlayer)GetOwner();
if (m_fiSndFireStop) {
ourOwner.StartSoundDef(m_fiSndFireStop, CHAN_WEAPON, true);
@ -1567,6 +1592,18 @@ NSWeapon::CanReload(void)
return (true);
}
NSWeapon
NSWeapon::GetNextWeapon(void)
{
return (m_nextWeapon);
}
NSWeapon
NSWeapon::GetPreviousWeapon(void)
{
return (m_prevWeapon);
}
/* required because we might need to look it up inside the
info for the primary attack mode. */
static string
@ -1657,9 +1694,6 @@ isWeaponDetonationTimed(string weaponDef)
return (isFused);
}
.NSWeapon m_nextWeapon;
.NSWeapon m_prevWeapon;
NSWeapon
NSWeapon_SortWeaponChain(NSActor targetPlayer)
{
@ -1731,29 +1765,6 @@ NSWeapon_SortWeaponChain(NSActor targetPlayer)
return (firstWeapon);
}
#ifdef CLIENT
bool
NSWeapon_CanSwitch(NSActor pl)
{
if (!pl.m_activeWeapon)
return false;
return true;
}
void
NSWeapon_SelectWeapon(NSWeapon nextWeapon)
{
if (!nextWeapon) {
pSeat->m_iHUDWeaponSelected = 0i;
return;
}
/* this gets passed in NSClientPlayer::ClientInputFrame() to the server */
pSeat->m_iHUDWeaponSelected = nextWeapon.GetSharedID();
}
#endif
/** Select the next item in the list. */
void
NSWeapon_NextWeapon(NSActor pl)

View file

@ -18,17 +18,23 @@
@brief Entity class declaration system.
@ingroup shared
@ingroup entities
@ingroup decl
# Introduction
An 'entityDef' is a type of @ref decl containing spawn
data. It is used for prefab entity configurations
but is also the very definitions base for designing
actors, items and weapons.
These definitions are a further abstraction from how we view
entity definitions. this system tries to be mostly compatible
with the def system in id Tech 4 (Doom 3, Quake 4, Prey, etc.)
with the def system in id Tech 4 [1] (Doom 3, Quake 4, Prey, etc.)
but does not guarantee to be compatible as-is.
The first references to such a system existing can be found when
Team Fortress Software was working on Team Fortress 2,
originally on Quake II's engine.
originally on Quake II's engine. [2]
The gist is, that an entity def can set a base spawnclass (e.g. func_door)
and populate it with key/value pairs.
@ -74,8 +80,8 @@ entityDef foobar {
# See Also
- http://www.teamfortress.com/tfii/mc2mapc.html
- http://icculus.org/~marco/notmine/id-dev/www.iddevnet.com/doom3/entitydefs.html
- [1] http://www.teamfortress.com/tfii/mc2mapc.html
- [2] http://icculus.org/~marco/notmine/id-dev/www.iddevnet.com/doom3/entitydefs.html
@{

View file

@ -29,16 +29,16 @@ void Materials_Init(void);
/** @} */ // end of materials
#define SURF_NODAMAGE 0x1i /**< never give falling damage */
#define SURF_SLICK 0x2i /**< effects game physics */
#define SURF_SKY 0x4i /**< lighting from environment map */
#define SURF_LADDER 0x8i /**< climb this surface */
#define SURF_NOIMPACT 0x10i /**< don't make missile explosions */
#define SURF_NOMARKS 0x20i /**< don't leave missile marks */
#define SURF_Q3FLESH 0x40i /**< make flesh sounds and effects */
#define SURF_NODRAW 0x80i /**< don't generate a drawsurface at all */
#define SURF_HINT 0x100i /**< make a primary bsp splitter */
#define SURF_SKIP 0x200i /**< completely ignore, allowing non-closed brushes */
#define SURF_NODAMAGE 0x1i /**< never give falling damage */
#define SURF_SLICK 0x2i /**< effects game physics */
#define SURF_SKY 0x4i /**< lighting from environment map */
#define SURF_LADDER 0x8i /**< climb this surface */
#define SURF_NOIMPACT 0x10i /**< don't make missile explosions */
#define SURF_NOMARKS 0x20i /**< don't leave missile marks */
#define SURF_Q3FLESH 0x40i /**< make flesh sounds and effects */
#define SURF_NODRAW 0x80i /**< don't generate a drawsurface at all */
#define SURF_HINT 0x100i /**< make a primary bsp splitter */
#define SURF_SKIP 0x200i /**< completely ignore, allowing non-closed brushes */
#define SURF_NOLIGHTMAP 0x400i /**< surface doesn't need a lightmap */
#define SURF_POINTLIGHT 0x800i /**< generate lighting info at vertexes */
#define SURF_METALSTEPS 0x1000i /**< clanking footsteps */
@ -49,67 +49,50 @@ void Materials_Init(void);
#define SURF_NODLIGHT 0x20000i /**< don't dlight even if solid (solid lava, skies) */
#define SURF_DUST 0x40000i /**< leave a dust trail when walking on this surface */
const int CONTENTBIT_NONE = 0x00000000i;
const int CONTENTBIT_NONE = 0x00000000i;
const int CONTENTBIT_SOLID = 0x00000001i
; /* SOLID_BSP */
const int CONTENTBIT_UNUSED1 = 0x00000002i
;
const int CONTENTBIT_UNUSED2 = 0x00000004i
;
const int CONTENTBIT_LAVA = 0x00000008i;
/* surfaceParm lava */
const int CONTENTBIT_SOLID = 0x00000001i; /* SOLID_BSP */
const int CONTENTBIT_UNUSED1 = 0x00000002i;
const int CONTENTBIT_UNUSED2 = 0x00000004i;
const int CONTENTBIT_LAVA = 0x00000008i; /* surfaceParm lava */
const int CONTENTBIT_SLIME = 0x00000010i;
/* surfaceParm slime */
const int CONTENTBIT_WATER = 0x00000020i;
/* surfaceParm water */
const int CONTENTBIT_UNUSED3 = 0x00000040i
;
const int CONTENTBIT_GRENADECLIP = 0x00000080i
; /* surfaceParm grenadeclip */
const int CONTENTBIT_SLIME = 0x00000010i; /* surfaceParm slime */
const int CONTENTBIT_WATER = 0x00000020i; /* surfaceParm water */
const int CONTENTBIT_UNUSED3 = 0x00000040i;
const int CONTENTBIT_GRENADECLIP = 0x00000080i; /* surfaceParm grenadeclip */
const int CONTENTBIT_UNUSED4 = 0x00000100i;
const int CONTENTBIT_UNUSED5 = 0x00000200i;
const int CONTENTBIT_UNUSED6 = 0x00000400i
;
const int CONTENTBIT_UNUSED7 = 0x00000800i
;
const int CONTENTBIT_UNUSED6 = 0x00000400i;
const int CONTENTBIT_UNUSED7 = 0x00000800i;
const int CONTENTBIT_UNUSED8 = 0x00001000i;
const int CONTENTBIT_UNUSED9 = 0x00002000i;
const int CONTENTBIT_FTELADDER = 0x00004000i; /* surfaceparm climb */
const int CONTENTBIT_VEHICLECLIP = 0x00008000i;
const int CONTENTBIT_VEHICLECLIP = 0x00008000i;
const int CONTENTBIT_PLAYERCLIP = 0x00010000i;
/* surfaceParm playerclip */
const int CONTENTBIT_MONSTERCLIP = 0x00020000i;
/* surfaceParm monsterclip */
const int CONTENTBIT_PLAYERCLIP = 0x00010000i; /* surfaceParm playerclip */
const int CONTENTBIT_MONSTERCLIP = 0x00020000i; /* surfaceParm monsterclip */
const int CONTENTBIT_PROJECTILE = 0x00040000i;
const int CONTENTBIT_UNUSED12 = 0x00080000i;
const int CONTENTBIT_CLUSTERPORTAL = 0x00100000i;
const int CONTENTBIT_DONOTENTER = 0x00200000i;
const int CONTENTBIT_BOTCLIP = 0x00400000i
; /* surfaceParm botclip */
const int CONTENTBIT_MOVER = 0x00800000i
;
const int CONTENTBIT_BOTCLIP = 0x00400000i; /* surfaceParm botclip */
const int CONTENTBIT_MOVER = 0x00800000i;
const int CONTENTBIT_UNUSED13 = 0x01000000i
;
const int CONTENTBIT_BODY = 0x02000000i; /* SOLID_BBOX/SLIDEBOX */
const int CONTENTBIT_CORPSE = 0x04000000i; /* SOLID_CORPSE */
const int CONTENTBIT_UNUSED13 = 0x01000000i;
const int CONTENTBIT_BODY = 0x02000000i; /* SOLID_BBOX/SLIDEBOX */
const int CONTENTBIT_CORPSE = 0x04000000i; /* SOLID_CORPSE */
const int CONTENTBIT_UNUSED14 = 0x08000000i;
const int CONTENTBIT_UNUSED15 = 0x10000000i;
const int CONTENTBIT_Q2LADDER = 0x20000000i; /* Q2BSP climbables */
const int CONTENTBIT_UNUSED16 = 0x40000000i;
const int CONTENTBIT_SKY = 0x80000000i; /* Q1BSP only! */
const int CONTENTBIT_SKY = 0x80000000i; /* Q1BSP only! */
/* a bit content group */
const int CONTENTBITS_MONSTER = CONTENTBIT_SOLID|CONTENTBIT_BODY|CONTENTBIT_MONSTERCLIP|CONTENTBIT_BOTCLIP;
typedef enum
{

View file

@ -17,6 +17,7 @@
/** @defgroup sounddefs Sound Definitions
@brief SoundDef system functions.
@ingroup sound
@ingroup decl
# SoundDefs {#sounddefs}