NSItem: new entity class, designed to use with entityDefs. Subject to change (a lot).

Develop
Marco Cawthorne 11 months ago
parent 20415c7ebc
commit f8a3e227d4
Signed by: eukara
GPG Key ID: CE2032F0A2882A22

@ -73,9 +73,9 @@ We'd like to streamline a lot of this further, so this may be subject to change.
## Event updates
This is pretty simple. The server will use the FTE QuakeWorld supported `SVC_CGAMEPACKET` packet type to network events.
The server will use the FTE QuakeWorld supported `SVC_CGAMEPACKET` packet type to network events.
An example of such an event is as follows, it can be called at any time:
An example of such an event is as follows, it can be called at any time, anywhere on the server:
```
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
@ -92,14 +92,6 @@ From there you can use the builtins `readbyte()`, `readshort()` etc. which are a
There's a few different means of networking things to the server as a client.
### infokeys
Clients can set their own custom infokey data at any time, using the `setinfo` console command. For example: `setinfo foo bar` will set the infokey `foo` to the value of `bar`. The server can then read any given infokey on a given client like so: `string value = infokey(someplayer, "foo");`
The server can also assign its own infokeys to a player. These can be overriden by the client at any given time as well, **unless the server prefixes them** with an asterisk. Here is an example: `forceinfokey(somePlayer, "*team", "1");`
infokeys are visible to all other clients. So be careful about the type of data you store in them. Storing passwords or other sensitive information is not recommended.
### sendevent
`sendevent()` is the builtin you call from the client game to communicate, reliably, to
@ -216,4 +208,82 @@ Whenever the client issues a `cmd` based command, say: `cmd say foobar` in conso
## ServerInfo
To be written.
ServerInfo keys can be set by server admins, or the game-logic. Those keys are networked to clients inside the game, as well as outside of the game. They can be queried through tools like `qstat` or `GameSpy`.
### Setting ServerInfo
#### Console (admins/debugging)
When in the console, you can set the key `foo` to the value `bar` like this:
```
serverinfo foo bar
```
#### Server-side code
The same thing can be done in the **SSQC** side with this line of code:
```
forceinfokey(world, "foo", "bar");
```
### Retrieving ServerInfo
#### Console (Debugging)
At any time, the server and clients can enter `serverinfo` by itself into the console, and it will print out all known ServerInfo keys.
Some of the keys are set by the engine, noteworthy ones include `*bspversion` and `mapname`. I encourage you try it and see if there's any keys that seem interesting to you and to make note of them.
#### Client/server-side code
We have two builtins to query ServerInfo keys from the client-side. `serverkey` and `serverkeyfloat`. Their usage goes like this:
```
string maybeBar = serverkey("foo");
float someNum = serverkeyfloat("maxclients");
```
## UserInfo
UserInfo keys are means of allowing clients (and the server, more on that later) to communicate bits of information about themselves to the server and all other clients. Much like **ServerInfo**. Those are networked regardless of whether another client is in the same **PVS**.
### Setting UserInfo
#### Console (clients)
Clients can set their own custom infokey data at any time, using the `setinfo` console command. For example: `setinfo foo bar` will set the infokey `foo` to the value of `bar`.
#### Server-side code
The server can also assign its own infokeys to a player. These can be overriden by the client at any given time - **unless the server prefixes them** with an asterisk. Here is an example: `forceinfokey(somePlayer, "*team", "1");`
Client infokeys are visible to all other clients. That's how most of the scoreboard is filled in with information. So be careful about the type of data you store in them. Storing passwords or other sensitive information is not recommended.
### Retrieving UserInfo
#### Client-side code
On the client-side, if you wanted to query your own players' specific infokey value, you can query it like this:
```
float myTeam = getplayerkeyfloat(player_localnum, "*team");
```
And if you want to query a specific player entity, this is perfectly valid:
```
string theirName = getplayerkey(playerEnty.entnum-1, "name");
```
As to why we have to subtract 1 from an entity its entnum for this, is because the clients in the infokey table start at **0**, and player entities on the server start at **1**; *0 being reserved for `world`*.
#### Server-side code
The server can then read any given infokey on a given client like so:
```
string value = infokey(someplayer, "foo");
float otherValue = infokeyf(someplayer, "somenumber");
```

@ -0,0 +1,45 @@
/*
* 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.
*/
#ifdef SERVER
/* PICKUP ITEMS */
class NSItem:NSRenderableEntity
{
public:
void NSItem(void);
/* overrides */
virtual void Spawned(void);
virtual void Touch(entity);
virtual void Respawn(void);
virtual void SpawnKey(string, string);
virtual void SetItem(int i);
virtual void SetFloating(int);
virtual void PickupRespawn(void);
private:
int m_iClip;
int m_iWasDropped;
/* spawn keys */
int m_iInvItem;
string m_sndAcquire;
string m_sndRespawn;
int m_bFloating;
bool m_bSpins;
};
#endif

@ -0,0 +1,136 @@
/*
* 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.
*/
#ifdef SERVER
void NSItem::NSItem(void)
{
m_iClip = 0i;
m_iWasDropped = 0i;
m_iInvItem = 0i;
m_sndAcquire = __NULL__;
m_sndRespawn = __NULL__;
m_bFloating = false;
}
void
NSItem::Spawned(void)
{
super::Spawned();
Sound_Precache(m_sndAcquire);
Sound_Precache(m_sndRespawn);
}
void NSItem::Respawn(void)
{
SetSolid(SOLID_TRIGGER);
SetOrigin(GetSpawnOrigin());
botinfo = BOTINFO_WEAPON;
if (m_bSpins)
modelflags = MF_ROTATE;
else
modelflags &= ~MF_ROTATE;
/* At some points, the item id might not yet be set */
if (GetSpawnModel()) {
SetModel(GetSpawnModel());
}
SetSize([-16,-16,0], [16,16,16]);
ReleaseThink();
if (!m_bFloating) {
DropToFloor();
SetMovetype(MOVETYPE_TOSS);
}
}
void
NSItem::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "inv_item":
m_iInvItem = ReadInt(strValue);
break;
case "snd_acquire":
m_sndAcquire = ReadString(strValue);
break;
case "snd_respawn":
m_sndRespawn = ReadString(strValue);
break;
case "modelflags":
modelflags = ReadFloat(strValue);
break;
case "spin":
m_bSpins = ReadBool(strValue);
break;
case "frame":
frame = ReadFloat(strValue);
break;
case "body":
m_iBody = ReadInt(strValue);
break;
default:
super::SpawnKey(strKey, strValue);
break;
}
}
void NSItem::Touch(entity eToucher)
{
if (eToucher.classname != "player") {
return;
}
/* don't remove if AddItem fails */
if (Weapons_AddItem((player)eToucher, m_iInvItem, m_iClip) == FALSE) {
return;
}
Logging_Pickup(eToucher, this, __NULL__);
StartSoundDef(m_sndAcquire, CHAN_ITEM, true);
UseTargets(eToucher, TRIG_TOGGLE, m_flDelay);
if (real_owner || m_iWasDropped == 1 || cvar("sv_playerslots") == 1) {
Destroy();
} else {
Disappear();
ScheduleThink(PickupRespawn, 30.0f);
}
}
void NSItem::SetItem(int i)
{
m_iInvItem = i;
m_oldModel = Weapons_GetWorldmodel(m_iInvItem);
SetModel(GetSpawnModel());
SetSize([-16,-16,0], [16,16,16]);
}
void NSItem::SetFloating(int i)
{
m_bFloating = i ? true : false;
}
void
NSItem::PickupRespawn(void)
{
Respawn();
StartSoundDef(m_sndRespawn, CHAN_ITEM, true);
}
#endif

@ -64,6 +64,7 @@ string __fullspawndata;
#include "NSMonster.h"
#include "NSTalkMonster.h"
#include "NSProjectile.h"
#include "NSItem.h"
#include "NSSpraylogo.h"
#include "../xr/defs.h"

@ -16,6 +16,7 @@ NSNavAI.qc
NSMonster.qc
NSTalkMonster.qc
NSProjectile.qc
NSItem.qc
NSClient.qc
NSClientSpectator.qc

Loading…
Cancel
Save