Lots more documentation in server/*.c, minor fixes for some mod guns like

They Hunger, Gearbox, SciHunt and Poke646. Also cvar support for 'pausable'
This commit is contained in:
Marco Cawthorne 2021-01-06 13:58:37 +01:00
parent ae70642f14
commit ae6f3ebdfb
50 changed files with 591 additions and 134 deletions

View file

@ -15,7 +15,7 @@
*/
void
Game_ModelEvent(float flTimeStamp, int iCode, string strData)
Game_ClientModelEvent(float flTimeStamp, int iCode, string strData)
{
switch (iCode) {
default:

View file

@ -29,7 +29,7 @@
../base/hud_weaponselect.c
../base/scoreboard.c
../base/input.c
../base/event.c
../base/modelevent.c
../include.src
../../shared/include.src

View file

@ -36,7 +36,7 @@
../valve/scoreboard.c
../valve/input.c
../cstrike/radio.c
../base/event.c
../base/modelevent.c
../include.src
../../shared/include.src

View file

@ -91,6 +91,7 @@ void View_PlayAnimation(int);
void View_PlayAnimation(int);
void Vox_Play(string);
void Event_ProcessModel(float, int, string);
void Game_ClientModelEvent(float, int, string);
/* this really should be done in-engine */

View file

@ -32,7 +32,7 @@
../gearbox/hud_weaponselect.c
../valve/scoreboard.c
../valve/input.c
../base/event.c
../base/modelevent.c
../include.src
../../shared/include.src

View file

@ -32,7 +32,7 @@
../valve/hud_weaponselect.c
../valve/scoreboard.c
../valve/input.c
../base/event.c
../base/modelevent.c
../include.src
../../shared/include.src

View file

@ -12,7 +12,7 @@ player.c
predict.c
npc.c
entities.c
event.c
modelevent.c
view.c
damage.c
chat.c

View file

@ -60,37 +60,37 @@ tries to play an event.
====================
*/
void
Event_ProcessModel(float fTimeStamp, int iCode, string sData)
Event_ProcessModel(float flTimeStamp, int iCode, string strData)
{
switch(iCode) {
case 5004:
localsound(sData, CHAN_AUTO, 1.0);
case 5004: /* view model sound */
localsound(strData, CHAN_AUTO, 1.0);
break;
case 5001:
case 5001: /* muzzle flash on attachment 0 */
pSeat->m_eMuzzleflash.alpha = 1.0f;
pSeat->m_eMuzzleflash.scale = 0.25;
pSeat->m_eMuzzleflash.skin = pSeat->m_iVMBones;
Event_EjectShell();
break;
case 5011:
case 5011: /* muzzle flash on attachment 1 */
pSeat->m_eMuzzleflash.alpha = 1.0f;
pSeat->m_eMuzzleflash.scale = 0.25;
pSeat->m_eMuzzleflash.skin = pSeat->m_iVMBones + 1;
//setmodel(pSeat->m_eMuzzleflash, sprintf("sprites/muzzleflash%s.spr", substring(sData, 1, 1)));
//setmodel(pSeat->m_eMuzzleflash, sprintf("sprites/muzzleflash%s.spr", substring(strData, 1, 1)));
Event_EjectShell();
break;
case 5021:
case 5021: /* muzzle flash on attachment 2 */
pSeat->m_eMuzzleflash.alpha = 1.0f;
pSeat->m_eMuzzleflash.scale = 0.25;
pSeat->m_eMuzzleflash.skin = pSeat->m_iVMBones + 2;
//setmodel(pSeat->m_eMuzzleflash, sprintf("sprites/muzzleflash%s.spr", substring(sData, 1, 1)));
//setmodel(pSeat->m_eMuzzleflash, sprintf("sprites/muzzleflash%s.spr", substring(strData, 1, 1)));
Event_EjectShell();
break;
case 5031:
case 5031: /* muzzle flash on attachment 3 */
pSeat->m_eMuzzleflash.alpha = 1.0f;
pSeat->m_eMuzzleflash.scale = 0.25;
pSeat->m_eMuzzleflash.skin = pSeat->m_iVMBones + 3;
//setmodel(pSeat->m_eMuzzleflash, sprintf("sprites/muzzleflash%s.spr", substring(sData, 1, 1)));
//setmodel(pSeat->m_eMuzzleflash, sprintf("sprites/muzzleflash%s.spr", substring(strData, 1, 1)));
Event_EjectShell();
break;
}

View file

@ -32,7 +32,7 @@
../valve/hud_weaponselect.c
../valve/scoreboard.c
../valve/input.c
../base/event.c
../base/modelevent.c
../include.src
../../shared/include.src

View file

@ -32,7 +32,7 @@
../rewolf/hud_weaponselect.c
../valve/scoreboard.c
../valve/input.c
../base/event.c
../base/modelevent.c
../include.src
../../shared/include.src

View file

@ -31,7 +31,7 @@
../valve/hud_weaponselect.c
../valve/scoreboard.c
../valve/input.c
../base/event.c
../base/modelevent.c
../include.src
../../shared/include.src

View file

@ -31,7 +31,7 @@
../valve/hud_weaponselect.c
../valve/scoreboard.c
../valve/input.c
../base/event.c
../base/modelevent.c
../include.src
../../shared/include.src

View file

@ -31,7 +31,7 @@
../valve/hud_weaponselect.c
../valve/scoreboard.c
../valve/input.c
../base/event.c
../base/modelevent.c
../include.src
../../shared/include.src

View file

@ -154,7 +154,7 @@ View_DrawViewModel(void)
m_eViewModel.frame2time = pl.weapontime;
m_eViewModel.frame1time = pl.weapontime;
processmodelevents(m_eViewModel.modelindex, m_eViewModel.frame, fBaseTime,
m_eViewModel.frame1time, Game_ModelEvent);
m_eViewModel.frame1time, Game_ClientModelEvent);
makevectors(view_angles);
m_eViewModel.angles = view_angles;

View file

@ -417,31 +417,6 @@ CBaseMonster::NewRoute(vector destination)
}
}
void
CBaseMonster::ModelEvent(float fTimeStamp, int iCode, string sData)
{
switch (iCode) {
case 1003:
for (entity f = world; (f = find(f, ::targetname, sData));) {
CBaseTrigger trigger = (CBaseTrigger)f;
if (trigger.Trigger != __NULL__) {
trigger.Trigger(this, TRIG_TOGGLE);
dprint(sprintf("^2%s^7::^3ModelEvent^7: " \
"Calling trigger '%s'\n",
classname, sData));
}
}
break;
/* things handled on the client-side */
case 1004:
break;
default:
dprint(sprintf("^3[SERVER]^7 Unknown model-event code " \
"%i with data %s\n", iCode, sData));
break;
}
}
void
CBaseMonster::Physics(void)
{

View file

@ -141,7 +141,6 @@ class CBaseMonster:CBaseEntity
virtual void(void) IdleNoise;
virtual void(void) Gib;
virtual void(string) Sound;
virtual void(float, int, string) ModelEvent;
virtual void(string, string) SpawnKey;
/* see/hear subsystem */

View file

@ -424,7 +424,7 @@ CBaseNPC::Physics(void)
frame1time += frametime;
processmodelevents(modelindex, frame, m_flBaseTime,
frame1time, ModelEvent);
frame1time, Game_ServerModelEvent);
}
void

View file

@ -170,7 +170,7 @@ CBaseEntity::predraw(void)
ProcessWordQue();
processmodelevents(modelindex, frame, m_flBaseTime,
frame1time, ModelEvent);
frame1time, Game_ClientModelEvent);
if (alpha > 0.0)
addentity(this);
@ -392,23 +392,6 @@ CBaseEntity::customphysics(void)
}
}
void
CBaseEntity::ModelEvent(float fTimeStamp, int iCode, string sData)
{
switch (iCode) {
case 1004:
sound(this, CHAN_BODY, sData, 1.0f, ATTN_NORM);
break;
/* things handled on the server-side */
case 1003:
break;
default:
dprint(sprintf("^3[CLIENT]^7 Unknown model-event code " \
"%i with data %s\n", iCode, sData));
break;
}
}
void
CBaseEntity::Init(void)
{
@ -712,6 +695,8 @@ CBaseEntity::ParentUpdate(void)
SendFlags |= BASEFL_CHANGED_ANGLES;
}
frame1time += frametime;
if (m_parent) {
entity p = find(world, ::targetname, m_parent);

View file

@ -37,7 +37,6 @@ class CBaseEntity
virtual float(void) predraw;
virtual void(void) postdraw;
virtual void(void) customphysics;
virtual void(float, int, string) ModelEvent;
#endif
#ifdef SERVER

View file

@ -0,0 +1,25 @@
/*
* Copyright (c) 2016-2021 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_ServerModelEvent(float flTimeStamp, int iCode, string strData)
{
switch (iCode) {
default:
Event_ServerModelEvent(flTimeStamp, iCode, strData);
break;
}
}

View file

@ -31,6 +31,7 @@
../base/items.cpp
../base/rules.c
../base/flashlight.c
../base/modelevent.c
../base/input.c
../base/spawn.c

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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
@ -14,22 +14,14 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void
Client_TriggerCamera(entity target, vector pos, vector end, float wait)
{
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_CAMERATRIGGER);
WriteCoord(MSG_MULTICAST, pos[0]);
WriteCoord(MSG_MULTICAST, pos[1]);
WriteCoord(MSG_MULTICAST, pos[2]);
WriteCoord(MSG_MULTICAST, end[0]);
WriteCoord(MSG_MULTICAST, end[1]);
WriteCoord(MSG_MULTICAST, end[2]);
WriteFloat(MSG_MULTICAST, wait);
msg_entity = target;
multicast([0,0,0], MULTICAST_ONE);
}
/*
=================
Client_FixAngle
Forces the camera-angle on the specified 'target' client
to the euler angle in the 'ang' parameter.
=================
*/
void
Client_FixAngle(entity target, vector ang)
{
@ -42,6 +34,14 @@ Client_FixAngle(entity target, vector ang)
multicast([0,0,0], MULTICAST_ONE);
}
/*
=================
Client_ShakeOnce
Single unreliable request to shake the screen of all
players within a specified radius by the desired parameters.
=================
*/
void
Client_ShakeOnce(vector pos, float radius, float duration, float frequency, float amplitude)
{

View file

@ -52,6 +52,7 @@
../valve/damage.c
../valve/rules.c
../valve/flashlight.c
../base/modelevent.c
../cstrike/input.c
../cstrike/spawn.c

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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
@ -45,9 +45,11 @@ void TraceAttack_SetPenetrationPower(int);
void Damage_Radius(vector, entity, float, float, int, int);
void Damage_Apply(entity, entity, float, int, int);
void Client_TriggerCamera(entity, vector, vector, float);
void Client_FixAngle(entity, vector);
void Client_ShakeOnce(vector pos, float radius, float duration, float frequency, float amplitude);
void Client_ShakeOnce(vector, float, float, float, float);
void Game_ServerModelEvent(float, int, string);
void Event_ServerModelEvent(float, int, string);
void Game_Input(void);
int Rules_IsTeamPlay(void);
@ -80,3 +82,8 @@ int g_dmg_iDamage;
int g_dmg_iHitBody;
int g_dmg_iFlags;
int g_dmg_iWeapon;
/* main is a qcc leftover */
void main(void)
{
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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
@ -14,11 +14,13 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* main is a qcc leftover */
void main(void)
{
}
/*
=================
StartFrame
Called once every single frame.
=================
*/
void StartFrame(void)
{
for (entity a = world; (a = findfloat(a, ::identity, 1));) {
@ -30,6 +32,17 @@ void StartFrame(void)
Vote_Frame();
}
/*
=================
ClientConnect
Called when the client-slot is being prepared for a player.
The client may not fully spawn into the world (yet), as they're still
loading or receiving packets.
The 'self' global is the connecting client in question.
=================
*/
void ClientConnect(float csqc_active)
{
int playercount = 0;
@ -53,29 +66,84 @@ void ClientConnect(float csqc_active)
}
}
/*
=================
ClientDisconnect
Called when a player leaves the server. At the end of the function the
client slot referred to by the 'self' global will be cleared.
This means the fields will still be accessible inside of this function.
=================
*/
void ClientDisconnect(void)
{
g_grMode.PlayerDisconnect((base_player)self);
}
/*
=================
ClientKill
Called by the 'kill' command.
The 'self' global is the client issueing the command.
=================
*/
void ClientKill(void)
{
g_grMode.PlayerKill((base_player)self);
}
/*
=================
SpectatorThink
Run every frame on every spectator.
The 'self' global refers to one of any given amount of spectators.
=================
*/
void SpectatorThink(void)
{
Game_SpectatorThink();
}
/*
=================
SpectatorConnect
Called when a spectator joins the server.
The 'self' global is the connecting spectator in question.
=================
*/
void SpectatorConnect(void)
{
Game_SpectatorConnect();
}
/*
=================
SpectatorDisconnect
Called when a spectator leaves the server.
The 'self' global is the leaving spectator in question.
Attributes cleared when this function is done executing.
=================
*/
void SpectatorDisconnect(void)
{
Game_SpectatorDisconnect();
}
/*
=================
PutClientInServer
Called when a player enters the game, having fully connected and loaded into
the session.
The 'self' global is the player in question.
The 'parmX' globals are also populated with any data carried over from
past levels for the player in question.
=================
*/
void PutClientInServer(void)
{
g_grMode.PlayerSpawn((base_player)self);
@ -95,6 +163,15 @@ void PutClientInServer(void)
}
}
/*
=================
PlayerPreThink
Run before physics have taken place.
The 'self' global refers to a single client, as this function is called
times the amount of players in a given game.
=================
*/
void PlayerPreThink(void)
{
#ifdef BOT_INCLUDED
@ -105,6 +182,15 @@ void PlayerPreThink(void)
g_grMode.PlayerPreFrame((base_player)self);
}
/*
=================
PlayerPostThink
Run after physics have taken place.
The 'self' global refers to a single client, as this function is called
times the amount of players in a given game.
=================
*/
void PlayerPostThink(void)
{
#ifdef BOT_INCLUDED
@ -116,21 +202,53 @@ void PlayerPostThink(void)
g_grMode.PlayerPostFrame((base_player)self);
}
/*
=================
SetNewParms
Called when we spawn in a new map (both single and multiplayer) with no level
change ever having taken place.
The 'self' global does not refer to anything.
=================
*/
void SetNewParms(void)
{
iprint("Setting New Level Parameters");
g_grMode.LevelNewParms();
}
/*
=================
SetChangeParms
Called whenever a single-player level change is about to happen, carrying
over data from one level to the next. This is not called with the 'map' command.
The 'self' global refers to a client that's partaking in the level-change.
Make sure we're saving important fields/attributes in the 'parmX' globals
allocated for every client.
=================
*/
void SetChangeParms(void)
{
iprint("Setting Level-Change Parameters");
g_grMode.LevelChangeParms((base_player)self);
}
/*
=================
SV_RunClientCommand
Run whenever an input packet by a client has been received.
The 'self' global is the entity having sent the input packet,
with the input_X globals being set to the appropriate data.
=================
*/
void SV_RunClientCommand(void)
{
#ifdef BOT_INCLUDED
/* wait a few seconds, as we may not have been spawned yet */
if (time > 5.0)
if (clienttype(self) == CLIENTTYPE_BOT) {
((bot)self).RunAI();
@ -142,6 +260,17 @@ void SV_RunClientCommand(void)
}
}
/*
=================
SV_ParseClientCommand
Any 'cmd' from the client get sent here and handled.
Unlike ConsoleCommmand() if you want to let the server engine
take over, you need to pass the string 'cmd' over via clientcommand().
Notable examples of client cmd's involve the chat system.
=================
*/
void SV_ParseClientCommand(string cmd)
{
string newcmd = Plugin_ParseClientCommand(cmd);
@ -152,12 +281,27 @@ void SV_ParseClientCommand(string cmd)
Game_ParseClientCommand(newcmd);
}
/*
=================
init
Called when the QC module gets loaded. No entities exist yet.
=================
*/
void init(float prevprogs)
{
iprint("Initializing Server-Module");
Plugin_Init();
}
/*
=================
init_respawn
Called inside initents() to make sure the entities have their Respawn()
method called at the beginning of them having spawned.
=================
*/
void init_respawn(void)
{
iprint("Respawning Entities");
@ -170,6 +314,13 @@ void init_respawn(void)
remove(self);
}
/*
=================
initents
???
=================
*/
void initents(void)
{
iprint("Initializing Entities");
@ -253,6 +404,17 @@ void initents(void)
}
}
/*
=================
worldspawn
The first entity spawn function. You want to make sure to put anything in here
that'll affect subsequent initialization of map entities.
Any find() or similar function will not find any entity but 'world',
as they do not exist yet. Keep this in mind.
=================
*/
var int autocvar_sv_levelexec = 1;
void worldspawn(void)
{
@ -275,6 +437,17 @@ void worldspawn(void)
readcmd(sprintf("exec maps/%s.cfg\n", mapname));
}
/*
=================
ConsoleCmd
Any command executed on the server (either tty, rcon or 'sv') gets
sent here first.
When returning FALSE the server will interpret the command.
Returning TRUE will mark the command as 'resolved'.
=================
*/
float ConsoleCmd(string cmd)
{
player pl;
@ -320,11 +493,22 @@ float ConsoleCmd(string cmd)
return TRUE;
}
/*
=================
SV_ShouldPause
Returns TRUE if the server should pause the game-logic when the 'pause' command
is being executed.
=================
*/
float SV_ShouldPause(float newstatus)
{
if (serverkeyfloat("background") == 1)
return FALSE;
if (cvar("pausable") == 1)
return TRUE;
if (cvar("sv_playerslots") > 1)
return FALSE;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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
@ -14,23 +14,13 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* HLBSP materials.txt character id's */
#define MATID_ALIEN 'H'
#define MATID_BLOODYFLESH 'B'
#define MATID_COMPUTER 'P'
#define MATID_CONCRETE 'C'
#define MATID_DIRT 'D'
#define MATID_FLESH 'F'
#define MATID_FOLIAGE 'O'
#define MATID_GLASS 'Y'
#define MATID_GRATE 'G'
#define MATID_METAL 'M'
#define MATID_SLOSH 'S'
#define MATID_SNOW 'N'
#define MATID_TILE 'T'
#define MATID_VENT 'V'
#define MATID_WOOD 'W'
/*
=================
Footsteps_Init
Just precaching sound shaders for all the types of material oriented footsteps.
=================
*/
void
Footsteps_Init(void)
{
@ -70,7 +60,14 @@ Footsteps_Init(void)
Sound_Precache("step_ladder.right");
}
/* Valve Half-Life BSP */
/*
=================
Footsteps_HLBSP
Footstep code for BSP version 30, which uses an external materials.txt
to specify materials.
=================
*/
void
Footsteps_HLBSP(base_player target)
{
@ -142,7 +139,13 @@ Footsteps_HLBSP(base_player target)
}
}
/* Vera Visions BSP / Modified RFBSP */
/*
=================
Footsteps_VVBSP
Modern BSP format which uses surfaceflags to specify materials on surfaces.
=================
*/
void
Footsteps_VVBSP(base_player target)
{
@ -215,7 +218,14 @@ Footsteps_VVBSP(base_player target)
}
}
/* anything unsupported */
/*
=================
Footsteps_Default
Default for any map format which we don't support or don't know how to support
materials for.
=================
*/
void
Footsteps_Default(base_player target)
{

View file

@ -84,6 +84,7 @@
../valve/damage.c
../valve/rules.c
../valve/flashlight.c
../base/modelevent.c
../valve/input.c
../valve/spawn.c

View file

@ -81,6 +81,7 @@
../valve/damage.c
../valve/rules.c
../valve/flashlight.c
../base/modelevent.c
../hunger/input.c
../valve/spawn.c

View file

@ -14,5 +14,6 @@ footsteps.c
vote.c
weapons.c
vehicles.c
modelevent.c
entry.c
#endlist

47
src/server/modelevent.c Normal file
View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2016-2021 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.
*/
/*
=================
Event_ServerModelEvent
Handles standard/fallback model events. This should never be called directly
but instead be the default fallback for Game_ServerModelEvent.
The 'self' global is the entity the model-event is being run on.
=================
*/
void
Event_ServerModelEvent(float flTimeStamp, int iCode, string strData)
{
switch (iCode) {
case 1003:
for (entity f = world; (f = find(f, ::targetname, strData));) {
CBaseTrigger trigger = (CBaseTrigger)f;
if (trigger.Trigger != __NULL__) {
trigger.Trigger(self, TRIG_TOGGLE);
dprint(sprintf("^2%s^7::^3ModelEvent^7: " \
"Calling trigger '%s'\n",
self.classname, strData));
}
}
break;
default:
dprint(sprintf("^3[SERVER]^7 Unknown model-event code " \
"%i with data %s\n", iCode, strData));
break;
}
}

View file

@ -79,6 +79,7 @@
../valve/damage.c
../valve/rules.c
../valve/flashlight.c
../base/modelevent.c
../poke646/input.c
../valve/spawn.c

View file

@ -44,6 +44,7 @@
../valve/damage.c
../valve/rules.c
../valve/flashlight.c
../base/modelevent.c
../rewolf/input.c
../valve/spawn.c

View file

@ -77,6 +77,7 @@
../valve/damage.c
../valve/rules.c
../valve/flashlight.c
../base/modelevent.c
../../botlib/include.src

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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
@ -16,6 +16,16 @@
string(string cmd) readcmd = #0;
/*
=================
Skill_Init
Usually just parses a config file. Make sure readcmd() is used here because
localcmd() does not parse files instantly - so monsters/weapons may be
initialized before the skill variables are read!
This will almost always result in them using default values, or (worst case) 0.
=================
*/
void
Skill_Init(void)
{
@ -24,6 +34,13 @@ Skill_Init(void)
readcmd(sprintf("exec skill_%s.cfg\n", cvar_string("game")));
}
/*
=================
Skill_GetValue
Return a skill variable's value or return a defaultvalue if it's undefined.
=================
*/
float
Skill_GetValue(string variable, float defaultvalue)
{

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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
@ -14,12 +14,17 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
=================
Spawn_ObserverCam
Find a spawnpoint for spectators and set origin and angle of the 'pl' target.
=================
*/
void
Spawn_ObserverCam(base_player pl)
{
entity eTarget;
// Go find a camera if we aren't dead
entity eCamera = find(world, ::classname, "trigger_camera");
if (eCamera) {
@ -33,7 +38,7 @@ Spawn_ObserverCam(base_player pl)
}
}
} else {
// Can't find a camera? Just do this lazy thing, CS seems to do the same
/* can't find a camera? CS chooses to pick a spawnpoint instead */
eCamera = find (world, ::classname, "info_player_start");
if (eCamera) {
@ -52,6 +57,13 @@ Spawn_ObserverCam(base_player pl)
Client_FixAngle(pl, pl.angles);
}
/*
=================
Spawn_PlayerRange
Returns how close the closest player is to any given spot.
=================
*/
float Spawn_PlayerRange(entity spot) {
entity pl;
float bestdist;
@ -72,6 +84,14 @@ float Spawn_PlayerRange(entity spot) {
return bestdist;
}
/*
=================
Spawn_SelectRandom
Return a point in the map that's both 'random' and also not too close to any
living player.
=================
*/
entity Spawn_SelectRandom(string cname)
{
static entity lastspot;
@ -85,7 +105,7 @@ entity Spawn_SelectRandom(string cname)
spot = find(spot, classname, cname);
}
entity eFirstSpot = spot;
entity firstspot = spot;
do {
if (spot) {
if (Spawn_PlayerRange(spot) > 128) {
@ -98,14 +118,14 @@ entity Spawn_SelectRandom(string cname)
}
}
spot = find(spot, classname, cname);
} while (spot != eFirstSpot);
} while (spot != firstspot);
if (!spot) {
lastspot = spot;
return spot;
}
// We still haven't found one
/* still not found any */
if (spot == __NULL__) {
error(sprintf("Spawn_SelectRandom: no %s on level", cname));
return world;

View file

@ -33,6 +33,7 @@
../valve/damage.c
../valve/rules.c
../valve/flashlight.c
../base/modelevent.c
../../botlib/include.src

View file

@ -79,6 +79,7 @@
../valve/damage.c
../valve/rules.c
../valve/flashlight.c
../base/modelevent.c
../valve/input.c
../valve/spawn.c

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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
@ -17,18 +17,39 @@
/* force the drawing of the first weapon that's picked up */
var int autocvar_sv_forceweapondraw = TRUE;
/*
=================
Weapon_GetCount
Returns the total number of weapons in the game.
=================
*/
int
Weapon_GetCount(void)
{
return g_weapons.length;
}
/*
=================
Weapon_GetBitID
Returns the item bitflag of a weapon index.
=================
*/
int
Weapon_GetBitID(int i)
{
return g_weapons[i].id;
}
/*
=================
Weapons_PickupNotify
Tells the client if we picked up a NEW weapon item.
=================
*/
void
Weapons_PickupNotify(base_player pl, int w)
{
@ -39,6 +60,13 @@ Weapons_PickupNotify(base_player pl, int w)
multicast([0,0,0], MULTICAST_ONE);
}
/*
=================
Weapons_RefreshAmmo
Just calls updateammo() when available... maybe a bit redundant.
=================
*/
void
Weapons_RefreshAmmo(base_player pl)
{
@ -47,6 +75,15 @@ Weapons_RefreshAmmo(base_player pl)
}
}
/*
=================
Weapons_SwitchBest
Really basic function that cycles through the highest-to-lowest
weapon ID order and picks the next available item with no regard to
ammo, or any sort of weighting system. FIXME
=================
*/
void
Weapons_SwitchBest(base_player pl)
{
@ -65,7 +102,13 @@ Weapons_SwitchBest(base_player pl)
pl.gflags |= GF_SEMI_TOGGLED;
}
/* returns TRUE if weapon pickup gets removed from this world */
/*
=================
Weapons_AddItem
returns TRUE if weapon pickup gets removed from this world
=================
*/
int
Weapons_AddItem(base_player pl, int w, int startammo)
{
@ -135,6 +178,13 @@ Weapons_AddItem(base_player pl, int w, int startammo)
return value;
}
/*
=================
Weapons_RemoveItem
Makes sure the item bit of g_items is reliably unset without errors.
=================
*/
void
Weapons_RemoveItem(base_player pl, int w)
{
@ -147,6 +197,13 @@ Weapons_RemoveItem(base_player pl, int w)
Weapons_SwitchBest(pl);
}
/*
=================
Weapons_InitItem
Called by the weapon_X function to initialize an in-world pickup.
=================
*/
void
Weapons_InitItem(int w)
{
@ -155,6 +212,13 @@ Weapons_InitItem(int w)
it.SetItem(w);
}
/*
=================
Weapons_UpdateAmmo
Sets .a_ammoX fields and clamps them so they can be networked as a single byte.
=================
*/
void
Weapons_UpdateAmmo(base_player pl, int a1, int a2, int a3)
{
@ -169,12 +233,19 @@ Weapons_UpdateAmmo(base_player pl, int a1, int a2, int a3)
a3 = pl.a_ammo3;
}
/* Networked as bytes, since we don't need more. Clamp to avoid errors */
/* networked as bytes, since we don't need more. Clamp to avoid errors */
pl.a_ammo1 = bound(0, a1, 255);
pl.a_ammo2 = bound(0, a2, 255);
pl.a_ammo3 = bound(0, a3, 255);
}
/*
=================
Weapons_ReloadWeapon
Manipulates the .mag and .ammo field pointer with some basic reload logic.
=================
*/
void
Weapons_ReloadWeapon(base_player pl, .int mag, .int ammo, int max)
{
@ -190,6 +261,11 @@ Weapons_ReloadWeapon(base_player pl, .int mag, .int ammo, int max)
}
}
/*
=================
Weapon_DropCurrentWeapon
=================
*/
void
Weapon_DropCurrentWeapon(base_player pl)
{
@ -220,6 +296,13 @@ Weapon_DropCurrentWeapon(base_player pl)
Weapons_RemoveItem(pl, pl.activeweapon);
}
/*
=================
CSEv_DropWeapon
The 'drop' command from the client-module calls this.
=================
*/
void
CSEv_DropWeapon(void)
{

View file

@ -1,3 +1,19 @@
/*
* Copyright (c) 2016-2021 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.
*/
float Weapons_GetAim(int);
void Weapons_PickupNotify(base_player pl, int w);
void Weapons_RefreshAmmo(base_player pl);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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
@ -118,6 +118,13 @@ w_eagle_release(void)
{
player pl = (player)self;
/* auto-reload if need be */
if (pl.w_attack_next <= 0.0)
if (pl.a_ammo1 == 0 && pl.a_ammo2 > 0) {
Weapons_Reload();
return;
}
if (pl.w_idle_next) {
return;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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
@ -116,6 +116,13 @@ w_m249_release(void)
{
player pl = (player)self;
/* auto-reload if need be */
if (pl.w_attack_next <= 0.0)
if (pl.a_ammo1 == 0 && pl.a_ammo2 > 0) {
Weapons_Reload();
return;
}
if (pl.w_idle_next > 0.0) {
return;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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
@ -208,6 +208,14 @@ void
w_sniperrifle_release(void)
{
player pl = (player)self;
/* auto-reload if need be */
if (pl.w_attack_next <= 0.0)
if (pl.a_ammo1 == 0 && pl.a_ammo2 > 0) {
Weapons_Reload();
return;
}
if (pl.w_idle_next > 0.0) {
return;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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
@ -288,6 +288,13 @@ void w_sporelauncher_release(void)
{
player pl = (player)self;
/* auto-reload if need be */
if (pl.w_attack_next <= 0.0)
if (pl.a_ammo3 == SLSTATE_IDLE && pl.a_ammo1 == 0 && pl.a_ammo2 > 0) {
Weapons_Reload();
return;
}
if (pl.w_idle_next > 0.0) {
return;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* Permission to use, copy, modify, and distribute this software for any
@ -243,6 +243,13 @@ w_ap9_release(void)
{
player pl = (player)self;
/* auto-reload if need be */
if (pl.w_attack_next <= 0.0)
if (pl.a_ammo1 == 0 && pl.a_ammo2 > 0) {
Weapons_Reload();
return;
}
if (pl.w_idle_next > 0.0) {
return;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* Permission to use, copy, modify, and distribute this software for any
@ -106,6 +106,13 @@ w_chaingun_release(void)
{
player pl = (player)self;
/* auto-reload if need be */
if (pl.w_attack_next <= 0.0)
if (pl.a_ammo1 == 0 && pl.a_ammo2 > 0) {
Weapons_Reload();
return;
}
if (pl.w_idle_next > 0.0) {
return;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* Permission to use, copy, modify, and distribute this software for any
@ -104,6 +104,13 @@ w_sniper_release(void)
{
player pl = (player)self;
/* auto-reload if need be */
if (pl.w_attack_next <= 0.0)
if (pl.a_ammo1 == 0 && pl.a_ammo2 > 0) {
Weapons_Reload();
return;
}
if (pl.w_idle_next > 0.0) {
return;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* Permission to use, copy, modify, and distribute this software for any
@ -98,6 +98,13 @@ w_sniper2_release(void)
{
player pl = (player)self;
/* auto-reload if need be */
if (pl.w_attack_next <= 0.0)
if (pl.a_ammo1 == 0 && pl.a_ammo2 > 0) {
Weapons_Reload();
return;
}
if (pl.w_idle_next > 0.0) {
return;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* Permission to use, copy, modify, and distribute this software for any
@ -198,6 +198,13 @@ w_taurus_release(void)
player pl = (player)self;
int r;
/* auto-reload if need be */
if (pl.w_attack_next <= 0.0)
if (pl.a_ammo1 == 0 && pl.a_ammo2 > 0) {
Weapons_Reload();
return;
}
if (pl.w_idle_next > 0.0) {
return;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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
@ -166,6 +166,13 @@ void w_shotgun_release(void)
{
player pl = (player)self;
/* auto-reload if need be */
if (pl.w_attack_next <= 0.0)
if (pl.a_ammo3 == SHOTTY_IDLE && pl.a_ammo1 == 0 && pl.a_ammo2 > 0) {
Weapons_Reload();
return;
}
if (pl.w_idle_next > 0.0) {
return;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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
@ -197,6 +197,14 @@ void w_cannon_secondary(void)
void w_cannon_release(void)
{
player pl = (player)self;
/* auto-reload if need be */
if (pl.w_attack_next <= 0.0)
if (pl.a_ammo1 == 0 && pl.a_ammo2 > 0) {
Weapons_Reload();
return;
}
if (pl.w_idle_next > 0.0) {
return;
}