Improvements to console output to make debugging easier, simplified

entry.qc by pushing more code into external functions. Add support
for mods to override networked events (after we added support for
ent update overrides the other week).
This commit is contained in:
Marco Cawthorne 2022-03-03 14:16:02 -08:00
parent 93124fa6de
commit 53f5780ac0
Signed by: eukara
GPG Key ID: C196CD8BA993248A
14 changed files with 591 additions and 464 deletions

View File

@ -14,7 +14,7 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void
int
ClientGame_EventParse(float fHeader)
{
switch (fHeader) {
@ -32,5 +32,8 @@ ClientGame_EventParse(float fHeader)
CSQC_Parse_Print(sprintf("[TEAM] %s: %s", getplayerkeyvalue(fSender2, "name"), sMessage2), PRINT_CHAT);
break;
default:
return (0);
}
return (1);
}

View File

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

18
src/client/cmd.h Normal file
View File

@ -0,0 +1,18 @@
/*
* Copyright (c) 2016-2022 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 Cmd_Init(void);
int Cmd_Parse(string);

268
src/client/cmd.qc Normal file
View File

@ -0,0 +1,268 @@
/*
* Copyright (c) 2016-2022 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.
*/
/*
=================
Cmd_Parse
Called from CSQC_ConsoleCommand to handle any builtin
commands from the Nuclide SDK.
Returns 0 if the command isn't handled and the engine is expected
to handle it from there.
=================
*/
int
Cmd_Parse(string sCMD)
{
switch (argv(0)) {
case "testPointLight":
makevectors(getproperty(VF_ANGLES));
traceline(getproperty(VF_ORIGIN), getproperty(VF_ORIGIN) + v_forward * 4096, FALSE, pSeat->m_ePlayer);
dynamiclight_spawnstatic(trace_endpos + (v_forward * -16), 1024, [1,1,1]);
break;
case "dev_modeltest":
entity mt = spawn();
mt.drawmask = MASK_ENGINE;
setmodel(mt, argv(1));
setsize(mt, [0,0,0], [0,0,0]);
setorigin(mt, getproperty(VF_ORIGIN));
mt.angles = getproperty(VF_ANGLES);
mt.angles[0] = mt.angles[2] = 0;
break;
case "dev_explode":
makevectors(getproperty(VF_ANGLES));
traceline(getproperty(VF_ORIGIN), getproperty(VF_ORIGIN) + v_forward * 4096, FALSE, pSeat->m_ePlayer);
FX_Explosion(trace_endpos);
break;
case "dev_sunpos":
vector sunpos, sunang;
vector lepos, leang;
makevectors(getproperty(VF_ANGLES));
sunpos = v_forward * -1;
sunang = vectoangles(sunpos);
makevectors(getproperty(VF_ANGLES));
lepos = v_forward * -1;
leang = vectoangles(lepos);
leang[1] -= 180;
leang[0] *= -1;
localcmd(sprintf("r_shadows_throwdirection %v\n", sunpos));
print(sprintf("env_sun: pitch: %d; angle: %d\n", -sunang[0], sunang[1]));
print(sprintf("light_environment: sunangle: %d; pitch: %d\n", leang[1], leang[0]));
break;
case "dev_measure":
static vector measurepos;
if (!vlen(measurepos)) {
measurepos = getproperty(VF_ORIGIN);
CSQC_Parse_CenterPrint(sprintf( "First marker set at\n%v", measurepos));
} else {
CSQC_Parse_CenterPrint(sprintf("Distance: %d\n", vlen(measurepos - getproperty(VF_ORIGIN))));
measurepos = [0,0,0];
}
break;
case "vote":
if (argv(1) == "yes") {
sendevent("VoteY", "");
} else if (argv(1) == "no") {
sendevent("VoteN", "");
}
break;
case "getpos":
print(sprintf("setpos %v;setang -%v\n", getproperty(VF_ORIGIN), getproperty(VF_ANGLES)));
break;
case "setpos":
localcmd(sprintf("cmd setpos \"%s\"\n", argv(1)));
break;
case "setang":
setproperty(VF_CL_VIEWANGLES, stov(argv(1)));
setproperty(VF_ANGLES, stov(argv(1)));
break;
case "callvote":
sendevent("CallVote", "s", substring(sCMD, 9, strlen(sCMD)-9));
break;
case "+zoomin":
pSeat->m_iZoomed = TRUE;
break;
case "-zoomin":
pSeat->m_iZoomed = FALSE;
break;
case "buildcubemaps":
CMap_Build();
break;
case "titles_test":
GameMessage_Setup(argv(1), 0);
break;
case "+attack2":
pSeat->m_iInputAttack2 = TRUE;
break;
case "-attack2":
pSeat->m_iInputAttack2 = FALSE;
break;
case "+reload":
pSeat->m_iInputReload = TRUE;
break;
case "-reload":
pSeat->m_iInputReload = FALSE;
break;
case "+use":
pSeat->m_iInputUse = TRUE;
break;
case "-use":
pSeat->m_iInputUse = FALSE;
break;
case "+duck":
pSeat->m_iInputDuck = TRUE;
break;
case "-duck":
pSeat->m_iInputDuck = FALSE;
break;
case "invnext":
HUD_DrawWeaponSelect_Back();
break;
case "invprev":
HUD_DrawWeaponSelect_Forward();
break;
case "lastinv":
HUD_DrawWeaponSelect_Last();
break;
case "+showscores":
pSeat->m_iScoresVisible = TRUE;
break;
case "-showscores":
pSeat->m_iScoresVisible = FALSE;
break;
case "slot1":
HUD_SlotSelect(0);
break;
case "slot2":
HUD_SlotSelect(1);
break;
case "slot3":
HUD_SlotSelect(2);
break;
case "slot4":
HUD_SlotSelect(3);
break;
case "slot5":
HUD_SlotSelect(4);
break;
case "slot6":
HUD_SlotSelect(5);
break;
case "slot7":
HUD_SlotSelect(6);
break;
case "slot8":
HUD_SlotSelect(7);
break;
case "slot9":
HUD_SlotSelect(8);
break;
case "slot10":
HUD_SlotSelect(9);
break;
case "way_menu":
Way_Autoload();
Textmenu_Call("WAY_MENU");
break;
case "_fnchat_msg":
CSQC_Parse_Print(argv(1), PRINT_CHAT);
break;
case "view_geomtest":
Weapons_SetGeomset(sprintf("geomset %s %s\n", argv(1), argv(2)));
break;
case "player_geomtest":
setcustomskin(pSeat->m_ePlayer, "", sprintf("geomset %s %s\n", argv(1), argv(2)));
break;
default:
return (0);
}
return (1);
}
/*
=================
Cmd_Init
Register our commands for Nuclide
=================
*/
void
Cmd_Init(void)
{
print("--------- Initializing Cmds ----------\n");
/* developer/debug commands */
registercommand("testLight");
registercommand("testPointLight");
registercommand("getpos");
registercommand("setpos");
registercommand("setang");
registercommand("dev_sentence");
registercommand("titles_test");
registercommand("buildcubemaps");
registercommand("dev_sunpos");
registercommand("dev_measure");
registercommand("view_geomtest");
registercommand("player_geomtest");
registercommand("way_menu");
registercommand("dev_explode");
registercommand("dev_modeltest");
/* basic actions */
registercommand("+attack");
registercommand("-attack");
registercommand("+attack2");
registercommand("-attack2");
registercommand("+reload");
registercommand("-reload");
registercommand("+use");
registercommand("-use");
registercommand("+duck");
registercommand("-duck");
/* voting */
registercommand("vote");
registercommand("callvote");
/* hud weapon selection system */
registercommand("slot1");
registercommand("slot2");
registercommand("slot3");
registercommand("slot4");
registercommand("slot5");
registercommand("slot6");
registercommand("slot7");
registercommand("slot8");
registercommand("slot9");
registercommand("slot10");
registercommand("lastinv");
registercommand("invnext");
registercommand("invprev");
/* scoreboard */
registercommand("+showscores");
registercommand("-showscores");
/* meant to be hidden */
registercommand("_fnchat_msg");
/* Requested by Slacer */
registercommand("+zoomin");
registercommand("-zoomin");
}

View File

@ -18,6 +18,7 @@
#include "efx.h"
#include "font.h"
#include "fade.h"
#include "cmd.h"
/* flags for 2d drawing */
#define DRAWFLAG_NORMAL 0

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2022 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
@ -23,6 +23,8 @@
MAPTEXTURENAME PATH_TO_SOME_OVERLAY XSCALE YSCALE
*/
static int g_detail_initialized;
const string g_detail_shader = \
"{\n" \
"{\n" \
@ -65,13 +67,17 @@ DetailTex_Init(void)
{
filestream fh;
string line;
int n = 0;
if (!autocvar(r_detailtextures, 0, "High-res detail texture overlays for selected maps"))
return;
print("--------- Initializing DetailTex ----------\n");
fh = fopen(strcat("maps/", mapname, "_detail.txt"), FILE_READ);
if (fh < 0) {
print(sprintf("DeailTex definition not found for %s.\n", mapname));
return;
}
@ -82,7 +88,9 @@ DetailTex_Init(void)
continue;
DetailTex_Parse(strtolower(argv(0)), argv(1), stof(argv(2)), stof(argv(3)));
n++;
}
print(sprintf("DeailTex initialized with %i entries.\n", n));
fclose(fh);
}
}

View File

@ -210,6 +210,7 @@ EFX_Load(string efx_file)
}
}
print(sprintf("parsed EFXDef file %s\n", efx_file));
fclose(fh);
return i;
}
@ -337,6 +338,8 @@ EFX_Init(void)
g_efx = (reverbinfo_t *)memalloc(sizeof(reverbinfo_t) * EFXDATA_MAX);
g_efx_name = (string *)memalloc(sizeof(string) * EFXDATA_MAX);
print(sprintf("allocated %d bytes for EFXDefs.\n", (sizeof(string) * EFXDATA_MAX) + (sizeof(reverbinfo_t) * EFXDATA_MAX)));
#else
print("dynamic allocation for EFXDefs enabled.\n");
#endif
efx_default = EFX_Load("default");

View File

@ -14,6 +14,118 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void
Entity_EntityUpdate(float type, float new)
{
switch (type) {
case ENT_ENTITY:
NSEntity me = (NSEntity)self;
if (new) {
spawnfunc_NSEntity();
}
me.ReceiveEntity(new, readfloat());
break;
case ENT_ENTITYRENDERABLE:
NSRenderableEntity rend = (NSRenderableEntity)self;
if (new) {
spawnfunc_NSRenderableEntity();
}
rend.ReceiveEntity(new, readfloat());
break;
case ENT_MONSTER:
NSMonster_ReadEntity(new);
break;
case ENT_TALKMONSTER:
NSTalkMonster_ReadEntity(new);
break;
case ENT_VEHICLE:
basevehicle_readentity(new);
break;
case ENT_VEH_TANKMORTAR:
func_tankmortar_readentity(new);
break;
case ENT_VEH_4WHEEL:
prop_vehicle_driveable_readentity(new);
break;
case ENT_PLAYER:
player pl = (player)self;
/* splitscreen */
CSQC_UpdateSeat();
Predict_EntityUpdate(pl, new);
/* any differences in things that are read below are now
officially from prediction misses. */
float a = readfloat();
pl.ReceiveEntity(new, a);
break;
case ENT_SPECTATOR:
Spectator_ReadEntity(new);
break;
case ENT_SPRITE:
env_sprite spr = (env_sprite)self;
if (new) {
spawnfunc_env_sprite();
}
spr.ReceiveEntity(new, readfloat());
break;
case ENT_SPRAY:
Spray_Parse();
break;
case ENT_DECAL:
Decal_Parse();
break;
case ENT_AMBIENTSOUND:
Sound_ParseLoopingEntity(self, new);
break;
case ENT_OLDCAMERA:
trigger_camera tc = (trigger_camera)self;
if (new) {
spawnfunc_trigger_camera();
}
tc.ReceiveEntity(new, readfloat());
break;
case ENT_MONITOR:
func_monitor fc = (func_monitor)self;
if (new) {
spawnfunc_func_monitor();
}
fc.ReceiveEntity(new, readfloat());
break;
case ENT_DLIGHT:
light_dynamic dl = (light_dynamic)self;
if (new) {
spawnfunc_light_dynamic();
}
dl.ReceiveEntity(new, readfloat());
break;
case ENT_PROJECTEDTEXTURE:
env_projectedtexture ept = (env_projectedtexture)self;
if (new) {
spawnfunc_env_projectedtexture();
}
ept.ReceiveEntity(new, readfloat());
break;
case ENT_ENVLASER:
env_laser l = (env_laser)self;
if (new) {
spawnfunc_env_laser();
}
l.ReceiveEntity(new, readfloat());
break;
case ENT_PARTSYSTEM:
info_particle_system ips = (info_particle_system)self;
if (new) {
spawnfunc_info_particle_system();
}
ips.ReceiveEntity(new, readfloat());
break;
default:
//error(sprintf("Unknown entity type update received. (%d)\n", t));
}
}
float
Entities_ParseLump(void)
{
@ -82,8 +194,14 @@ Entities_ParseLump(void)
void
Entities_RendererRestarted(void)
{
int c = 0;
print("--------- Reloading Entity Resources ----------\n");
for (entity b = world; (b = findfloat(b, ::isCSQC, TRUE));) {
NSEntity pf = (NSEntity) b;
pf.RendererRestarted();
c++;
}
print(sprintf("resource reload called on %i entities\n", c));
}

View File

@ -46,64 +46,7 @@ CSQC_Init(float apilevel, string enginename, float engineversion)
pSeat = &g_seats[0];
pSeatLocal = &g_seatslocal[0];
/* developer/debug commands */
registercommand("testLight");
registercommand("testPointLight");
registercommand("getpos");
registercommand("setpos");
registercommand("setang");
registercommand("dev_sentence");
registercommand("titles_test");
registercommand("buildcubemaps");
registercommand("dev_sunpos");
registercommand("dev_measure");
registercommand("view_geomtest");
registercommand("player_geomtest");
registercommand("way_menu");
registercommand("dev_explode");
registercommand("dev_modeltest");
/* basic actions */
registercommand("+attack");
registercommand("-attack");
registercommand("+attack2");
registercommand("-attack2");
registercommand("+reload");
registercommand("-reload");
registercommand("+use");
registercommand("-use");
registercommand("+duck");
registercommand("-duck");
/* voting */
registercommand("vote");
registercommand("callvote");
/* hud weapon selection system */
registercommand("slot1");
registercommand("slot2");
registercommand("slot3");
registercommand("slot4");
registercommand("slot5");
registercommand("slot6");
registercommand("slot7");
registercommand("slot8");
registercommand("slot9");
registercommand("slot10");
registercommand("lastinv");
registercommand("invnext");
registercommand("invprev");
/* scoreboard */
registercommand("+showscores");
registercommand("-showscores");
/* meant to be hidden */
registercommand("_fnchat_msg");
/* Requested by Slacer */
registercommand("+zoomin");
registercommand("-zoomin");
Cmd_Init();
/* Sound shaders */
Sound_Init();
@ -175,7 +118,7 @@ CSQC_RendererRestarted(string rstr)
DetailTex_Init();
/* end msg */
print("Graphical resources reloaded.\n");
print("Graphical resources reloaded\n");
}
/* this is so that profile_csqc reports more accurate statistics as to
@ -550,14 +493,9 @@ CSQC_Input_Frame(void)
CSQC_UpdateSeat();
me = pSeat->m_ePlayer;
if (me.classname == "player") {
player pl;
pl = (player)pSeat->m_ePlayer;
if (me.classname == "player" || me.classname == "spectator") {
base_client pl = (base_client)me;
pl.ClientInputFrame();
} else if (me.classname == "spectator") {
spectator spec;
spec = (spectator)pSeat->m_ePlayer;
spec.ClientInputFrame();
}
}
@ -572,125 +510,28 @@ Whenever we call a SVC_CGAMEPACKET on the SSQC, this is being run
void
CSQC_Parse_Event(void)
{
entity me;
/* always 0, unless it was sent with a MULTICAST_ONE or MULTICAST_ONE_R to p2+ */
CSQC_UpdateSeat();
me = pSeat->m_ePlayer;
float fHeader = readbyte();
switch (fHeader) {
case EV_DAMAGE:
vector vecDmgPos;
int iDmgTake;
int iDmgFlags;
vecDmgPos[0] = readcoord();
vecDmgPos[1] = readcoord();
vecDmgPos[2] = readcoord();
iDmgTake = readint();
iDmgFlags = readint();
CSQC_Parse_Damage_New(vecDmgPos, iDmgTake, iDmgFlags);
break;
case EV_INTERMISSION:
int cam;
vector pos, ang;
cam = (int)readbyte();
if (cam) {
ang[0] = readfloat();
ang[1] = readfloat();
ang[2] = readfloat();
pos[0] = readcoord();
pos[1] = readcoord();
pos[2] = readcoord();
} else {
pos = getproperty(VF_ORIGIN);
ang = getproperty(VF_ANGLES);
}
pSeat->m_vecCameraOrigin = pos;
pSeat->m_vecCameraAngle = ang;
g_iIntermission = TRUE;
break;
case EV_MUSICTRACK:
Music_ParseTrack();
break;
case EV_MUSICLOOP:
Music_ParseLoop();
break;
case EV_SPEAK:
string msg;
float pit;
entity t = findfloat(world, entnum, readentitynum());
msg = readstring();
pit = readfloat();
sound(t, CHAN_VOICE, msg, 1.0, ATTN_NORM, pit);
break;
case EV_SENTENCE:
NSTalkMonster_ParseSentence();
break;
case EV_HUDHINT:
string hint;
hint = readstring();
/* TODO: Handle the event properly */
Chat_Parse(sprintf("Hint: %s", hint));
break;
case EV_FADE:
Fade_Parse();
break;
case EV_SPRITE:
EnvSprite_ParseEvent();
break;
case EV_TEXT:
GameText_Parse();
break;
case EV_MESSAGE:
GameMessage_Parse();
break;
case EV_CAMERATRIGGER:
vector cam_newpos;
cam_newpos[0] = readcoord();
cam_newpos[1] = readcoord();
cam_newpos[2] = readcoord();
pSeat->m_vecCameraAngle[0] = readcoord();
pSeat->m_vecCameraAngle[1] = readcoord();
pSeat->m_vecCameraAngle[2] = readcoord();
pSeat->m_flCameraTime = time + readfloat();
/* if the same camera as last-time (hack) is still active,
then make sure it becomes inactive... */
if (pSeat->m_vecCameraOrigin == cam_newpos) {
pSeat->m_flCameraTime = 0.0f;
} else {
pSeat->m_vecCameraOrigin = cam_newpos;
}
break;
case EV_ANGLE:
vector a;
a[0] = readfloat();
a[1] = readfloat();
a[2] = readfloat();
setproperty(VF_CL_VIEWANGLES, a);
setproperty(VF_ANGLES, a);
break;
case EV_SHAKE:
if (me.classname == "spectator")
break;
pSeat->m_flShakeDuration = readfloat();
pSeat->m_flShakeAmp = readfloat();
pSeat->m_flShakeFreq = readfloat();
pSeat->m_flShakeTime = pSeat->m_flShakeDuration;
break;
default:
ClientGame_EventParse(fHeader);
int ret = ClientGame_EventParse(fHeader);
if (ret == 1) {
return;
}
Event_Parse(fHeader);
}
/*
=================
CSQC_ConsoleCommand
Commands not protected by the engine get passed here.
If we return 0 this means the engine needs to either handle
the command or throw a 'unrecognized command' message.
=================
*/
float
CSQC_ConsoleCommand(string sCMD)
{
@ -706,185 +547,36 @@ CSQC_ConsoleCommand(string sCMD)
if (ret == (1))
return (1);
switch (argv(0)) {
case "testPointLight":
makevectors(getproperty(VF_ANGLES));
traceline(getproperty(VF_ORIGIN), getproperty(VF_ORIGIN) + v_forward * 4096, FALSE, pSeat->m_ePlayer);
dynamiclight_spawnstatic(trace_endpos + (v_forward * -16), 1024, [1,1,1]);
break;
case "dev_modeltest":
entity mt = spawn();
mt.drawmask = MASK_ENGINE;
setmodel(mt, argv(1));
setsize(mt, [0,0,0], [0,0,0]);
setorigin(mt, getproperty(VF_ORIGIN));
mt.angles = getproperty(VF_ANGLES);
mt.angles[0] = mt.angles[2] = 0;
break;
case "dev_explode":
makevectors(getproperty(VF_ANGLES));
traceline(getproperty(VF_ORIGIN), getproperty(VF_ORIGIN) + v_forward * 4096, FALSE, pSeat->m_ePlayer);
FX_Explosion(trace_endpos);
break;
case "dev_sunpos":
vector sunpos, sunang;
vector lepos, leang;
makevectors(getproperty(VF_ANGLES));
sunpos = v_forward * -1;
sunang = vectoangles(sunpos);
makevectors(getproperty(VF_ANGLES));
lepos = v_forward * -1;
leang = vectoangles(lepos);
leang[1] -= 180;
leang[0] *= -1;
localcmd(sprintf("r_shadows_throwdirection %v\n", sunpos));
print(sprintf("env_sun: pitch: %d; angle: %d\n", -sunang[0], sunang[1]));
print(sprintf("light_environment: sunangle: %d; pitch: %d\n", leang[1], leang[0]));
break;
case "dev_measure":
static vector measurepos;
if (!vlen(measurepos)) {
measurepos = getproperty(VF_ORIGIN);
CSQC_Parse_CenterPrint(sprintf( "First marker set at\n%v", measurepos));
} else {
CSQC_Parse_CenterPrint(sprintf("Distance: %d\n", vlen(measurepos - getproperty(VF_ORIGIN))));
measurepos = [0,0,0];
}
break;
case "vote":
if (argv(1) == "yes") {
sendevent("VoteY", "");
} else if (argv(1) == "no") {
sendevent("VoteN", "");
}
break;
case "getpos":
print(sprintf("setpos %v;setang -%v\n", getproperty(VF_ORIGIN), getproperty(VF_ANGLES)));
break;
case "setpos":
localcmd(sprintf("cmd setpos \"%s\"\n", argv(1)));
break;
case "setang":
setproperty(VF_CL_VIEWANGLES, stov(argv(1)));
setproperty(VF_ANGLES, stov(argv(1)));
break;
case "callvote":
sendevent("CallVote", "s", substring(sCMD, 9, strlen(sCMD)-9));
break;
case "+zoomin":
pSeat->m_iZoomed = TRUE;
break;
case "-zoomin":
pSeat->m_iZoomed = FALSE;
break;
case "buildcubemaps":
CMap_Build();
break;
case "titles_test":
GameMessage_Setup(argv(1), 0);
break;
case "+attack2":
pSeat->m_iInputAttack2 = TRUE;
break;
case "-attack2":
pSeat->m_iInputAttack2 = FALSE;
break;
case "+reload":
pSeat->m_iInputReload = TRUE;
break;
case "-reload":
pSeat->m_iInputReload = FALSE;
break;
case "+use":
pSeat->m_iInputUse = TRUE;
break;
case "-use":
pSeat->m_iInputUse = FALSE;
break;
case "+duck":
pSeat->m_iInputDuck = TRUE;
break;
case "-duck":
pSeat->m_iInputDuck = FALSE;
break;
case "invnext":
HUD_DrawWeaponSelect_Back();
break;
case "invprev":
HUD_DrawWeaponSelect_Forward();
break;
case "lastinv":
HUD_DrawWeaponSelect_Last();
break;
case "+showscores":
pSeat->m_iScoresVisible = TRUE;
break;
case "-showscores":
pSeat->m_iScoresVisible = FALSE;
break;
case "slot1":
HUD_SlotSelect(0);
break;
case "slot2":
HUD_SlotSelect(1);
break;
case "slot3":
HUD_SlotSelect(2);
break;
case "slot4":
HUD_SlotSelect(3);
break;
case "slot5":
HUD_SlotSelect(4);
break;
case "slot6":
HUD_SlotSelect(5);
break;
case "slot7":
HUD_SlotSelect(6);
break;
case "slot8":
HUD_SlotSelect(7);
break;
case "slot9":
HUD_SlotSelect(8);
break;
case "slot10":
HUD_SlotSelect(9);
break;
case "way_menu":
Way_Autoload();
Textmenu_Call("WAY_MENU");
break;
case "_fnchat_msg":
CSQC_Parse_Print(argv(1), PRINT_CHAT);
break;
case "view_geomtest":
Weapons_SetGeomset(sprintf("geomset %s %s\n", argv(1), argv(2)));
break;
case "player_geomtest":
setcustomskin(pSeat->m_ePlayer, "", sprintf("geomset %s %s\n", argv(1), argv(2)));
break;
default:
return (0);
}
return (1);
return Cmd_Parse(sCMD);
}
/*
=================
CSQC_ConsoleCommand
Engine or server game will occasionally pass messages through here.
There are 4 different types currently:
PRINT_LOW = low on the screen.
PRINT_MEDIUM = medium level on the screen.
PRINT_HIGH = top level on the screen
PRINT_CHAT = chat message
Currently, everything but chat gets piped into a single printbuffer,
similar to NetQuake.
FIXME: We'd like to expose this further to modification.
=================
*/
void
CSQC_Parse_Print(string sMessage, float fLevel)
{
CSQC_UpdateSeat();
/* This gives messages other than chat an orange tint */
/* chat goes through here */
if (fLevel == PRINT_CHAT) {
Chat_Parse(sMessage);
return;
}
/* the rest goes into our print buffer */
if (pSeat->m_iPrintLines < 4) {
pSeat->m_strPrintBuffer[pSeat->m_iPrintLines + 1] = sMessage;
pSeat->m_iPrintLines++;
@ -897,7 +589,7 @@ CSQC_Parse_Print(string sMessage, float fLevel)
pSeat->m_flPrintTime = time + CHAT_TIME;
// Log to console
/* log to console */
localcmd(sprintf("echo \"%s\"\n", sMessage));
}
@ -932,7 +624,10 @@ CSQC_Parse_CenterPrint(string sMessage)
=================
CSQC_Ent_Update
Called whenever an entity is sent manually via .SendFlags and so on
Called when an entity is being networked from the server game.
ClientGame_EntityUpdate allows the project to do game specific
overrides. If that returns 0 Nuclide will attempt to handle it.
If neither handles it we'll get a protocol error.
=================
*/
void
@ -946,113 +641,7 @@ CSQC_Ent_Update(float new)
return;
}
switch (t) {
case ENT_ENTITY:
NSEntity me = (NSEntity)self;
if (new) {
spawnfunc_NSEntity();
}
me.ReceiveEntity(new, readfloat());
break;
case ENT_ENTITYRENDERABLE:
NSRenderableEntity rend = (NSRenderableEntity)self;
if (new) {
spawnfunc_NSRenderableEntity();
}
rend.ReceiveEntity(new, readfloat());
break;
case ENT_MONSTER:
NSMonster_ReadEntity(new);
break;
case ENT_TALKMONSTER:
NSTalkMonster_ReadEntity(new);
break;
case ENT_VEHICLE:
basevehicle_readentity(new);
break;
case ENT_VEH_TANKMORTAR:
func_tankmortar_readentity(new);
break;
case ENT_VEH_4WHEEL:
prop_vehicle_driveable_readentity(new);
break;
case ENT_PLAYER:
player pl = (player)self;
/* splitscreen */
CSQC_UpdateSeat();
Predict_EntityUpdate(pl, new);
/* any differences in things that are read below are now
officially from prediction misses. */
float a = readfloat();
pl.ReceiveEntity(new, a);
break;
case ENT_SPECTATOR:
Spectator_ReadEntity(new);
break;
case ENT_SPRITE:
env_sprite spr = (env_sprite)self;
if (new) {
spawnfunc_env_sprite();
}
spr.ReceiveEntity(new, readfloat());
break;
case ENT_SPRAY:
Spray_Parse();
break;
case ENT_DECAL:
Decal_Parse();
break;
case ENT_AMBIENTSOUND:
Sound_ParseLoopingEntity(self, new);
break;
case ENT_OLDCAMERA:
trigger_camera tc = (trigger_camera)self;
if (new) {
spawnfunc_trigger_camera();
}
tc.ReceiveEntity(new, readfloat());
break;
case ENT_MONITOR:
func_monitor fc = (func_monitor)self;
if (new) {
spawnfunc_func_monitor();
}
fc.ReceiveEntity(new, readfloat());
break;
case ENT_DLIGHT:
light_dynamic dl = (light_dynamic)self;
if (new) {
spawnfunc_light_dynamic();
}
dl.ReceiveEntity(new, readfloat());
break;
case ENT_PROJECTEDTEXTURE:
env_projectedtexture ept = (env_projectedtexture)self;
if (new) {
spawnfunc_env_projectedtexture();
}
ept.ReceiveEntity(new, readfloat());
break;
case ENT_ENVLASER:
env_laser l = (env_laser)self;
if (new) {
spawnfunc_env_laser();
}
l.ReceiveEntity(new, readfloat());
break;
case ENT_PARTSYSTEM:
info_particle_system ips = (info_particle_system)self;
if (new) {
spawnfunc_info_particle_system();
}
ips.ReceiveEntity(new, readfloat());
break;
default:
//error(sprintf("Unknown entity type update received. (%d)\n", t));
}
Entity_EntityUpdate(t, new);
}
/*
@ -1066,7 +655,7 @@ void
CSQC_WorldLoaded(void)
{
print("--------- Initializing Client World ----------\n");
DetailTex_Init();
//DetailTex_Init();
/* Primarily for the flashlight */
if (serverkeyfloat("*bspversion") != BSPVER_HL) {

116
src/client/event.qc Normal file
View File

@ -0,0 +1,116 @@
void
Event_Parse(float type)
{
entity me = pSeat->m_ePlayer;
switch (type) {
case EV_DAMAGE:
vector vecDmgPos;
int iDmgTake;
int iDmgFlags;
vecDmgPos[0] = readcoord();
vecDmgPos[1] = readcoord();
vecDmgPos[2] = readcoord();
iDmgTake = readint();
iDmgFlags = readint();
CSQC_Parse_Damage_New(vecDmgPos, iDmgTake, iDmgFlags);
break;
case EV_INTERMISSION:
int cam;
vector pos, ang;
cam = (int)readbyte();
if (cam) {
ang[0] = readfloat();
ang[1] = readfloat();
ang[2] = readfloat();
pos[0] = readcoord();
pos[1] = readcoord();
pos[2] = readcoord();
} else {
pos = getproperty(VF_ORIGIN);
ang = getproperty(VF_ANGLES);
}
pSeat->m_vecCameraOrigin = pos;
pSeat->m_vecCameraAngle = ang;
g_iIntermission = TRUE;
break;
case EV_MUSICTRACK:
Music_ParseTrack();
break;
case EV_MUSICLOOP:
Music_ParseLoop();
break;
case EV_SPEAK:
string msg;
float pit;
entity t = findfloat(world, entnum, readentitynum());
msg = readstring();
pit = readfloat();
sound(t, CHAN_VOICE, msg, 1.0, ATTN_NORM, pit);
break;
case EV_SENTENCE:
NSTalkMonster_ParseSentence();
break;
case EV_HUDHINT:
string hint;
hint = readstring();
/* TODO: Handle the event properly */
Chat_Parse(sprintf("Hint: %s", hint));
break;
case EV_FADE:
Fade_Parse();
break;
case EV_SPRITE:
EnvSprite_ParseEvent();
break;
case EV_TEXT:
GameText_Parse();
break;
case EV_MESSAGE:
GameMessage_Parse();
break;
case EV_CAMERATRIGGER:
vector cam_newpos;
cam_newpos[0] = readcoord();
cam_newpos[1] = readcoord();
cam_newpos[2] = readcoord();
pSeat->m_vecCameraAngle[0] = readcoord();
pSeat->m_vecCameraAngle[1] = readcoord();
pSeat->m_vecCameraAngle[2] = readcoord();
pSeat->m_flCameraTime = time + readfloat();
/* if the same camera as last-time (hack) is still active,
then make sure it becomes inactive... */
if (pSeat->m_vecCameraOrigin == cam_newpos) {
pSeat->m_flCameraTime = 0.0f;
} else {
pSeat->m_vecCameraOrigin = cam_newpos;
}
break;
case EV_ANGLE:
vector a;
a[0] = readfloat();
a[1] = readfloat();
a[2] = readfloat();
setproperty(VF_CL_VIEWANGLES, a);
setproperty(VF_ANGLES, a);
break;
case EV_SHAKE:
if (me.classname == "spectator")
break;
pSeat->m_flShakeDuration = readfloat();
pSeat->m_flShakeAmp = readfloat();
pSeat->m_flShakeFreq = readfloat();
pSeat->m_flShakeTime = pSeat->m_flShakeDuration;
break;
default:
error("event not recognized. abort immediately.\n");
}
}

View File

@ -76,14 +76,14 @@ Font_Load(string strFile, font_s &fntNew)
}
fclose(fileFont);
} else {
error(sprintf("[FONT] Cannot load font file %s!", strFile));
error(sprintf("cannot load font file %s!", strFile));
}
if (!fntNew.iScaleX || !fntNew.iScaleY) {
error(sprintf("[FONT] No valid size defined for %s!", strFile));
error(sprintf("no valid size defined for %s!", strFile));
}
//print(sprintf("[FONT] %s: %s %s\n", strFile, strFontPath, strRenderSize));
print(sprintf("loaded font definition for %s\n", strFile));
if (strRenderSize != "")
fntNew.iID = (int)loadfont("", strFontPath, strRenderSize, -1, 0, 0);

View File

@ -23,5 +23,7 @@ way.qc
efx.qc
detailtex.qc
shake.qc
cmd.qc
event.qc
entry.qc
#endlist

View File

@ -22,5 +22,6 @@ Sky_Update(int force)
if (g_strSkyName != serverkey("skyname") || force == TRUE) {
g_strSkyName = serverkey("skyname");
localcmd(sprintf("sky \"%s\"\n", g_strSkyName));
print(sprintf("sky update applying %s.\n", g_strSkyName));
}
}

View File

@ -188,9 +188,9 @@ NSRenderableEntity::SendEntity(entity ePEnt, float fChanged)
WriteCoord(MSG_ENTITY, origin[2]);
}
if (fChanged & BASEFL_CHANGED_ANGLES) {
angles[0] = Math_FixDelta(angles[0]);
angles[1] = Math_FixDelta(angles[1]);
angles[2] = Math_FixDelta(angles[2]);
/* fix angles and try to avoid a net update next frame */
angles = Math_FixDeltaVector(angles);
angles_net = angles;
WriteShort(MSG_ENTITY, angles[0] * 32767 / 360);
WriteShort(MSG_ENTITY, angles[1] * 32767 / 360);
WriteShort(MSG_ENTITY, angles[2] * 32767 / 360);