djcev.com

//

Git Repos / fte_dogmode / qc / cl_entry.qc

Last update to this file was on 2024-11-20 at 23:54.

Show cl_entry.qc

//==============================================================================
// CSQC entrypoints
//==============================================================================

//======================================================================
// globals
//======================================================================

#ifdef CSQC
float nocsqc; // CSQC State (0=on, 1=off)
float sitems; // CSQC copy of .items
float sitems2; // CSQC copy of .items2 (or serverflags)
float sweapon; // CSQC copy of .weapon
float shealth; // CSQC copy of .health

float painfinishtime; // Track player damage for hud face

float intermission; // in intermission
float intermission_time; // when the intermission started

float numclientseats; // coop or splitscreen?
float maxclients; // max players possible on this server
float cltime; // inc. regardless of pause or gamespeed

float player_localentnum; // Ent number that csqc is attached to

float sb_showscores; // Show lower tab scores

// This is the input-frame sequence. frames < clientcommandframe have been
// sent to the server. frame==clientcommandframe is still being generated
// and can still change.
float clientcommandframe;
// This is the input-frame that was last acknowledged by the server.
// Input frames greater than this should be applied to the player's entity.
float servercommandframe;

// Reports which ssqc entnum was hit when a csqc traceline impacts an
// ssqc-based brush entity.
float trace_networkentity;

entity view_pl; // handle to the local player entity
entity viewentity; // camera -- CEV
vector view_origin; // origin for viewentity -- CEV
vector view_angles; // +x=DOWN

__used var float physics_mode = 2; // 0 = not run, 1 = DP, 2 = movetypes
#endif

//======================================================================
// fields
//======================================================================

#ifdef CSQC
.float drawmask; // a filter in the addentities call
.float entnum; // The entnum as its known on the server
.float renderflags;

// The current frame the entity is meant to be displayed in. In CSQC,
// note the lerpfrac and frame2 fields as well. if it specifies a
// framegroup, the framegroup will autoanimate in ssqc, but not in csqc.
// .float frame; // already defined in entvars_t -- CEV
.float frame1time; // absolute time into anim/framegroup
.float frame2; // alt frame visible when lerpfrac is 1
.float frame2time; // absolute time into anim/group frame2
.float oldframe;
.float lerpfrac; // if 0 use frame1, if 1 use frame2,
.float lerptime; // mix together for values between

.string oldskin;

// Called by addentities after the filter and before the entity is actually
// drawn. Do your interpolation and animation in here. Should return one of
// the PREDRAW_* constants.
.float() predraw;

.void(entity e) preframe; // called before setting up view
.void(entity e) postframe; // called after renderscene
.void() removefunc; // called when ent removed on the server
#endif

//======================================================================
// forward declarations
//======================================================================

#ifdef CSQC
void(float eid, vector start, vector end) CL_TE_Lightning2;
#endif

#ifdef CSQC
float(string cmd) CSQC_ConsoleCommand;
// float(float evtype, float scanx, float chary, float devid) CSQC_InputEvent;
// __used void() CSQC_Input_Frame;
float(float save, float take, vector dir) CSQC_Parse_Damage;
void() CSQC_Parse_Event;
// void(string printmsg, float printlvl) CSQC_Parse_Print;
void(entity ent) CSQC_DrawViewModel;
void(float vwidth, float vheight, float notmenu) CSQC_UpdateView;
float() CSQC_Parse_TempEntity;
void(float isnew) CSQC_Ent_Update;
void() CSQC_Ent_Remove;
void(float apilevel, string enginename, float engineversion) CSQC_Init;
__wrap float(string str) CSQC_ConsoleCommand;
#endif

//------------------------------------------------------------------------------

#ifdef CSQC
//----------------------------------------------------------------------
// stubs for server-side entry functions (silences compiler warnings)
//----------------------------------------------------------------------
void() main = sub_null;
void() StartFrame = sub_null;
void() PlayerPreThink = sub_null;
void() PlayerPostThink = sub_null;
void() ClientKill = sub_null;
void() ClientConnect = sub_null;
void() PutClientInServer = sub_null;
void() ClientDisconnect = sub_null;
void() SetNewParms = sub_null;
void() SetChangeParms = sub_null;
#endif

#ifdef CSQC
//----------------------------------------------------------------------
void(float eid, vector start, vector end) CL_TE_Lightning2 =
{
// TODO CEV
local vector org;
local float isknown = getentity (eid, GE_ACTIVE);

if (isknown)
{
org = getentity (eid, GE_ORIGIN);
dprint (sprintf("CL_TE_Lightning2: known; "
"pos %v, end %v, eid %g, org %v\n",
start, end, eid, org));
te_lightning2 (world, start, end);
}
else
{
if (deathmatch == 0)
org = view_pl.origin;
else
org = '999 999 999';
dprint (sprintf("CL_TE_Lightning2: unknown; "
"pos %v, end %v, eid %g, org %v\n",
start, end, eid, org));
te_lightning2 (world, start, end);
}
};
#endif

#ifdef CSQC
//----------------------------------------------------------------------
// Stubs for extra CSQC functions (not all supported)
//----------------------------------------------------------------------

// Can query or check anything types on the console here
float(string cmd) CSQC_ConsoleCommand =
{
tokenize_console (cmd);
return FALSE;
};

// Can query/check keyboard/mouse/joystick input with this function
// For key events, scanx is one of the KEY_* values
// chary is the character code (chr2str to shove it into a string)
// For mouse events then x+y are the mouse delta/position values
/*
float(float evtype, float scanx, float chary, float devid) CSQC_InputEvent =
{
return FALSE;
};
*/

// Called just before each time clientcommandframe is updated. You
// can edit the input_* globals in order to apply your own player
// inputs within csqc, which may allow you a convienient way to
// pass certain info to ssqc.
#if 0
__used void() CSQC_Input_Frame =
{
if (serverkeyfloat(SERVERKEY_PAUSESTATE))
return;

if (intermission == TRUE)
return;

// rework user input, copying something like QuakeSpasm's always run
// feature here. This turns the +speed button into a hold-to-walk
// button when cl_run is 0 (when FTE's always run setting is on).
// -- CEV
/*
if (world_clrun == FALSE)
{
*/
local float m;

// we care about x and y, not so much z -- CEV
if (input_movevalues_x)
{
m = fabs (input_movevalues_x);
if (m > 400.0f)
input_movevalues_x = PM_WALKSPEED *
(input_movevalues_x / m);
else if (m == 400.0f)
input_movevalues_x = PM_RUNSPEED *
(input_movevalues_x / m);
else if (m != 0)
input_movevalues_x = PM_RUNSPEED *
(input_movevalues_x / m);
}

if (input_movevalues_y)
{
m = fabs (input_movevalues_y);
if (m > 400.0f)
input_movevalues_y = PM_WALKSPEED *
(input_movevalues_y / m);
else if (m == 400.0f)
input_movevalues_y = PM_RUNSPEED *
(input_movevalues_y / m);
else if (m != 0)
input_movevalues_y = PM_RUNSPEED *
(input_movevalues_y / m);
}
/*
}
*/
};
#endif

// This is linked to client dmg_take / dmg_save / dmg_inflictor fields
// returning TRUE will block the red flash damage stuff
float(float save, float take, vector dir) CSQC_Parse_Damage =
{
dprint (sprintf("CSQC_Parse_Damage: save %g, take %g, dir %v\n",
save, take, dir));
painfinishtime = time + 0.2;
return FALSE;
};

//----------------------------------------------------------------------
// Can query/check server MSG events
// CSQC_Parse_Event is called when the client sees a
// #define svcfte_cgamepacket (83) message from the server
// Not supported for DP, is called from only QSS/FTE
//----------------------------------------------------------------------
void() CSQC_Parse_Event =
{
local float event = ReadByte ();
switch (event)
{
case EVENT_INTERMISSION:
intermission = ReadFloat ();
return;
case EVENT_CSHIFT_FADE:
csf_fade_netreceive (view_pl);
return;
case EVENT_CSHIFT_SET:
csf_set_netreceive (view_pl);
return;
default:
dprint ("CSQC_Parse_Event: received unknown event "
"type!\n");
return;
}
};

//----------------------------------------------------------------------
// Can intercept printed messages from the server (top of screen)
// printlvl (text filtering) 0=low, 1=medium, 2=high, 3=chat
// con_notifytime = amount of time the text remains on screen
// ONLY define this function, if doing something with the text!!
//----------------------------------------------------------------------
/*
void(string printmsg, float printlvl) CSQC_Parse_Print =
{
print (printmsg);
};
*/

//----------------------------------------------------------------------
// TODO CEV
//----------------------------------------------------------------------
void(entity ent) CSQC_DrawViewModel =
{
local float newframe, newmodel;

newframe = getstatf (STAT_WEAPONFRAME);
newmodel = getstatf (STAT_WEAPONMODELI);

if (newmodel != ent.modelindex)
{
// changed entirely
ent.modelindex = newmodel;
ent.frame2 = ent.frame = newframe;
ent.lerptime = time;
}
else if (newframe != ent.frame)
{
ent.frame2 = ent.frame;
ent.frame = newframe;
ent.lerptime = time;
}

ent.lerpfrac = 1 - (time - ent.lerptime) * 10;

// apply user's configured viewmodel offset -- CEV
ent.origin = [0 + autocvar(cl_gunx, 0), 0 + autocvar(cl_guny, 0),
0 + autocvar(cl_gunz, 0)];
ent.angles = '0 0 0';

addentity (ent);
};

//----------------------------------------------------------------------
void(float vwidth, float vheight, float notmenu) CSQC_UpdateView =
{
local vector ssize = [vwidth, vheight, 0];

// Is the CSQC functionality enabled/disabled?
nocsqc = cvar ("cl_nocsqc");

clearscene ();

setproperty (VF_MIN, '0 0');
setproperty (VF_SIZE, ssize);

// If hud is disabled, draw engine hud instead
setproperty (VF_DRAWENGINESBAR, nocsqc);

if (view_pl)
{
player_prediction_preframe (view_pl);

// read our smoothed & predicted view origin
setproperty (VF_ORIGIN, view_origin);

if (intermission)
{
makevectors (view_angles);

// camera wobble
view_angles_x += autocvar(v_ipitch_level, 0.3) *
sin(time * autocvar(v_ipitch_cycle, 1));
view_angles_y += autocvar(v_iyaw_level, 0.3) *
sin(time * autocvar(v_iyaw_cycle, 2));
view_angles_z += autocvar(v_iroll_level, 0.1) *
sin(time * autocvar(v_iroll_cycle, 0.5));

setproperty (VF_DRAWCROSSHAIR, FALSE);
setproperty (VF_ANGLES, view_angles);
SetListener (view_origin, v_forward, v_right, v_up);
}
else
{
// view_angle adjustments performed in
// player_prediction_preframe -- CEV
setproperty (VF_ANGLES, view_angles);

// v_forward et al should still match the makevectors
// call in player_prediction_preframe -- CEV
SetListener (view_origin, v_forward, v_right, v_up);

// draw view model when not invisible
if (!(sitems & IT_INVISIBILITY))
{
setproperty (VF_VIEWENTITY, viewentity.entnum);
CSQC_DrawViewModel (viewentity);
}

setproperty (VF_DRAWCROSSHAIR, TRUE);
}

addentities (DRAWMASK_ENGINE | DRAWMASK_NORMAL);
renderscene ();

player_prediction_postframe (view_pl);
}
else
{
dprint ("CSQC_UpdateView: no local player!\n");
if (intermission)
{
setproperty (VF_DRAWCROSSHAIR, FALSE);
addentities (DRAWMASK_ENGINE | DRAWMASK_NORMAL);
}
else
{
setproperty (VF_DRAWCROSSHAIR, TRUE);
addentities (DRAWMASK_ENGINE | DRAWMASK_VIEWMODEL |
DRAWMASK_NORMAL);
}
renderscene ();
}

#if 0
local entity t = world;
while ((t = nextent(t)))
{
dprint (sprintf("CSQC_UpdateView: found %s, model %s\n",
t.classname, modelnameforindex(t.modelindex)));
}
#endif

#if 0
local float count = getentity (0, -1);
local float i;
for (i = 0; i < count; i++)
{
if (getentity(i, GE_ACTIVE))
dprint (sprintf("CSQC_UpdateView: CSQC ent num %g, "
"origin %v\n",
i, getentity (i, GE_ORIGIN)));
}
#endif

// Revert back to using engine HUD?
if (nocsqc > 0)
return;

// Used on intermission screen later
if (!intermission)
intermission_time = time;

// Read deathmatch variable and create csprogs coop variable
// csprogs has no knowledge of the coop variable
deathmatch = stof (serverkey("deathmatch"));
coop = !deathmatch && maxclients > 1;

// Draw the HUDs, scoreboards, and any requested colorshifts
CSQC_DrawHud (ssize, sb_showscores);
CSQC_DrawScores (ssize, sb_showscores);
csf_draw (ssize);
};

//----------------------------------------------------------------------
// Handle SVC_TEMPENTITY data from the server -- CEV
//
// Based on code by PrimalLove found at:
// https://forums.insideqc.com/viewtopic.php?p=55772#p55772
//----------------------------------------------------------------------
float() CSQC_Parse_TempEntity =
{
local float teid = ReadByte ();

switch (teid)
{
case TE_LIGHTNING2:
local float eid = ReadEntityNum ();
local vector lgpos, lgend;
lgpos_x = ReadCoord ();
lgpos_y = ReadCoord ();
lgpos_z = ReadCoord ();
lgend_x = ReadCoord ();
lgend_y = ReadCoord ();
lgend_z = ReadCoord ();

// TODO CEV fix FTE particle effect te_lightning2
CL_TE_Lightning2 (eid, lgpos, lgend);

return TRUE;
default:
return FALSE;
}

return FALSE;
};

//----------------------------------------------------------------------
// Handle incoming MSG_ENTITY data from the server
// Entities are networked in this way either because they need movement
// prediction or they can affect movement prediction -- CEV
//----------------------------------------------------------------------
void(float isnew) CSQC_Ent_Update =
{
local float type = ReadShort ();

if (self.classtype && self.classtype != type)
{
if (self.classtype != type)
{
dprint (sprintf("CSQC_Ent_Update: classtype "
"mismatch, calling removefunc for entity "
"of type %s\n", self.classname));

if (self.removefunc)
self.removefunc ();
isnew = TRUE;
self.classtype = type;
}
}
else
{
self.classtype = type;
}

switch (self.classtype)
{
case CT_FUNC_DOOR:
func_door_netreceive (isnew);
return;
case CT_FUNC_MOVEWALL:
func_movewall_netreceive (isnew);
return;
case CT_FUNC_NEW_PLAT:
func_new_plat_netreceive (isnew);
return;
case CT_FUNC_PLAT:
func_plat_netreceive (isnew);
return;
case CT_FUNC_TOGGLEWALL:
func_togglewall_netreceive (isnew);
return;
case CT_FUNC_TRAIN:
func_train_netreceive (isnew);
return;
case CT_MISC_EXPLOBOX:
case CT_MISC_EXPLOBOX2:
base_explobox_netreceive (isnew);
return;
case CT_MISC_MODEL:
base_misc_model_netreceive (isnew);
return;
case CT_PLAYER:
player_netreceive (isnew);
return;
case CT_TRIGGER_LADDER:
trigger_ladder_netreceive (isnew);
return;
case CT_TRIGGER_PUSH:
case CT_TRIGGER_PUSH_CUSTOM:
base_trigger_push_netreceive (isnew);
return;
case CT_TRIGGER_SETGRAVITY:
trigger_setgravity_netreceive (isnew);
return;
}
};

//----------------------------------------------------------------------
// Entity has been removed on the server
//----------------------------------------------------------------------
void() CSQC_Ent_Remove =
{
if (self.removefunc)
self.removefunc ();
remove (self);
};

//----------------------------------------------------------------------
void() CSQC_WorldLoaded =
{
// set latched-at-map-load-time cvars -- CEV
world_latched_cvars ();

// now read (some, not many) entities from the map file.
// the following is based on CSQC_WorldLoaded in CSQCTest
// and CSQC_WorldLoaded in Nuclide -- CEV
local string token = "";
getentitytoken (0);

while (1)
{
token = getentitytoken ();
if (token == "")
break;

if (token != "{")
{
dprint (sprintf("CSQC_WorldLoaded: bad entity data!, "
"token %s\n", token));
return;
}

if (base_entity_parsemapdata() == FALSE)
{
dprint (sprintf("CSQC_WorldLoaded: bad map data %s!\n",
token));
return;
}
}
};

//----------------------------------------------------------------------
// Registers HUD gfx images (all setup in string arrays)
//----------------------------------------------------------------------
void(float apilevel, string enginename, float engineversion) CSQC_Init =
{
local float i, wadonly;

// Is the CSQC functionality enabled/disabled?
nocsqc = cvar ("cl_nocsqc");

// Revert back to using engine HUD?
if (nocsqc > 0)
return;

// precache from gfx.wad ONLY!?!
wadonly = TRUE;

// Cache all string tables
for (i = 0; i < 14; i++)
{
// HUD background images (320 wide+)
if (i < backgrd.length)
precache_pic (backgrd[i], wadonly);
// Large 24x24 brown/red numbers
if (i < number.length)
{
precache_pic (number[i], wadonly);
precache_pic (anumber[i], wadonly);
}
// Large 24x24 extra font characters (intermission)
if (i < extrachar.length)
precache_pic (extrachar[i], wadonly);
// Large 24x24 player face
if (i < facetab.length)
precache_pic (facetab[i], wadonly);
// Large 24x24 icons
if (i < sbitems.length)
precache_pic (sbitems[i], wadonly);
// Small 16x16 icons
if (i < ibitems.length)
precache_pic (ibitems[i], wadonly);
// Special 8x16 runes
if (i < ibrunes.length)
precache_pic (ibrunes[i], wadonly);
// All weapon setups (on/off/flashing)
if (i < wpnnames.length)
{
precache_pic(strcat(wpnselect[0], wpnnames[i]),wadonly);
precache_pic(strcat(wpnselect[1], wpnnames[i]),wadonly);
precache_pic(strcat(wpnflash[0], wpnnames[i]), wadonly);
precache_pic(strcat(wpnflash[1], wpnnames[i]), wadonly);
precache_pic(strcat(wpnflash[2], wpnnames[i]), wadonly);
precache_pic(strcat(wpnflash[3], wpnnames[i]), wadonly);
precache_pic(strcat(wpnflash[4], wpnnames[i]), wadonly);
}
}

// TODO CEV
// precache_model ("progs/player.mdl");

// spawn the view entity now -- CEV
if (!viewentity)
{
viewentity = spawn ();
viewentity.classname = "viewentity";
viewentity.renderflags = RF_DEPTHHACK | RF_NOSHADOW |
RF_VIEWMODEL;
viewentity.think = sub_null;
}
};

//----------------------------------------------------------------------
// Wrapper for CSQC_ConsoleCommand to show different scoreboards
//----------------------------------------------------------------------
__wrap float(string str) CSQC_ConsoleCommand =
{
if (prior(str))
return TRUE;

string c = argv(0);

if (c == "+showscores")
sb_showscores |= 1;
else if (c == "-showscores")
sb_showscores &= ~1;
else if (c == "+showteamscores")
sb_showscores |= 2;
else if (c == "-showteamscores")
sb_showscores &= ~2;
else
return FALSE;

return TRUE;
};
#endif

Return to the top of this page or return to the overview of this repo.

Log cl_entry.qc

Return to the top of this page or return to the overview of this repo.