Git Repos / fte_dogmode / qc / sv_entry.qc
Last update to this file was on 2024-11-20 at 23:54.
Show sv_entry.qc
//==============================================================================
// server-side entrypoints; inspired by Nuclide's server/entry.qc -- CEV
//==============================================================================
//======================================================================
// globals
//======================================================================
#ifdef SSQC
float gameover; // set when a rule exits
float intermission;
float intermission_exittime;
entity used_exit;
string nextmap;
float skill; // latched, reset on StartFrame
float framecount;
nosave float clean_up_client_stuff;
nosave float gamestarted;
// Reports which ssqc entnum was hit when a csqc traceline impacts an
// ssqc-based brush entity.
// Only active in CSQC but needed here to compile pmove. -- CEV
nosave float trace_networkentity;
#endif
//======================================================================
// forward declarations
//======================================================================
#ifdef SSQC
// helper functions
void() NextLevel;
void() CheckRules;
void(string message) ShowIntermissionMessage;
void() StartMessageIntermission;
void() Episode1End;
void() Episode2End;
void() Episode3End;
void() Episode4End;
float() RunId1Intermissions;
entity() FindIntermission;
void() GotoNextMap;
float(float start) ShowIntermissionTextEntity;
void() ExitIntermission;
void() IntermissionThink;
void() WriteIntermission;
void() RestartLoopSounds_think;
void() RestartLoopSounds;
// proper entrypoints
void() main;
void() ClientConnect;
void() ClientDisconnect;
void() ClientKill;
void() SetNewParms;
void() SetChangeParms;
void() PutClientInServer;
void() PlayerPreThink;
void() SV_RunClientCommand;
void() PlayerPostThink;
void() StartFrame;
// void() EndFrame;
// void(void() spawnfunc) CheckSpawn;
#endif
//------------------------------------------------------------------------------
//======================================================================
// Helper functions - map & game rules
//======================================================================
#ifdef SSQC
//----------------------------------------------------------------------
// NextLevel -- go to the next level for deathmatch
// only called if a time or frag limit has expired
//----------------------------------------------------------------------
void() NextLevel =
{
local entity t_level;
if (mapname == "start")
{
if (!cvar ("registered"))
{
mapname = "e1m1";
}
else if (!(serverflags & 1))
{
mapname = "e1m1";
serverflags = serverflags | 1;
}
else if (!(serverflags & 2))
{
mapname = "e2m1";
serverflags = serverflags | 2;
}
else if (!(serverflags & 4))
{
mapname = "e3m1";
serverflags = serverflags | 4;
}
else if (!(serverflags & 8))
{
mapname = "e4m1";
serverflags = serverflags - 7;
}
t_level = spawn_trigger_changelevel (self,
self.origin, mapname);
}
else
{
// find a trigger changelevel
t_level = findfloat (world, classtype, CT_TRIGGER_CHANGELEVEL);
// go back to start if no trigger_changelevel
if (!t_level)
t_level = spawn_trigger_changelevel (self,
self.origin, "start");
}
nextmap = t_level.map;
gameover = TRUE;
if (t_level.nextthink < time)
t_level.nextthink = time + 0.1;
};
//----------------------------------------------------------------------
// CheckRules -- Exit deathmatch games upon conditions; 'self' is client
//----------------------------------------------------------------------
void() CheckRules =
{
// someone else quit the game already
if (gameover)
return;
local float timelimit = cvar ("timelimit") * 60;
local float fraglimit = cvar ("fraglimit");
// 1998-07-27 Timelimit/Fraglimit fix by Maddes
if (deathmatch && timelimit && time >= timelimit)
{
NextLevel ();
return;
}
// 1998-07-27 Timelimit/Fraglimit fix by Maddes
if (deathmatch && fraglimit && self.frags >= fraglimit)
{
NextLevel ();
return;
}
};
#endif
//======================================================================
// Helper functions - intermission handling
//======================================================================
#ifdef SSQC
//----------------------------------------------------------------------
void(string message) ShowIntermissionMessage =
{
WriteByte (MSG_ALL, SVC_FINALE);
WriteString (MSG_ALL, message);
};
//----------------------------------------------------------------------
void() StartMessageIntermission =
{
WriteByte (MSG_ALL, SVC_CDTRACK);
WriteByte (MSG_ALL, 2);
WriteByte (MSG_ALL, 3);
};
//----------------------------------------------------------------------
void() Episode1End =
{
StartMessageIntermission ();
if (!cvar("registered"))
{
ShowIntermissionMessage ("As the corpse of the monstrous "
"entity\nChthon sinks back into the lava whence\n"
"it rose, you grip the Rune of Earth\n"
"Magic tightly. Now that you have\n"
"conquered the Dimension of the Doomed,\n"
"realm of Earth Magic, you are ready to\n"
"complete your task in the other three\n"
"haunted lands of Quake. Or are you? If\n"
"you don't register Quake, you'll never\n"
"know what awaits you in the Realm of\n"
"Black Magic, the Netherworld, and the\nElder World!");
}
else
{
ShowIntermissionMessage ("As the corpse of the monstrous"
"entity\nChthon sinks back into the lava whence\n"
"it rose, you grip the Rune of Earth\n"
"Magic tightly. Now that you have\n"
"conquered the Dimension of the Doomed,\n"
"realm of Earth Magic, you are ready to\n"
"complete your task. A Rune of magic\n"
"power lies at the end of each haunted\n"
"land of Quake. Go forth, seek the\n"
"totality of the four Runes!");
}
};
//----------------------------------------------------------------------
void() Episode2End =
{
StartMessageIntermission ();
ShowIntermissionMessage ("The Rune of Black Magic throbs evilly in\n"
"your hand and whispers dark thoughts\n"
"into your brain. You learn the inmost\n"
"lore of the Hell-Mother; Shub-Niggurath!\n"
"You now know that she is behind all the\n"
"terrible plotting which has led to so\n"
"much death and horror. But she is not\n"
"inviolate! Armed with this Rune, you\n"
"realize that once all four Runes are\n"
"combined, the gate to Shub-Niggurath's\n"
"Pit will open, and you can face the\n"
"Witch-Goddess herself in her frightful\n"
"otherworld cathedral.");
};
//----------------------------------------------------------------------
void() Episode3End =
{
StartMessageIntermission ();
ShowIntermissionMessage ("The charred viscera of diabolic horrors\n"
"bubble viscously as you seize the Rune\n"
"of Hell Magic. Its heat scorches your\n"
"hand, and its terrible secrets blight\n"
"your mind. Gathering the shreds of your\n"
"courage, you shake the devil's shackles\n"
"from your soul, and become ever more\n"
"hard and determined to destroy the\n"
"hideous creatures whose mere existence\n"
"threatens the souls and psyches of all\n"
"the population of Earth.");
};
//----------------------------------------------------------------------
void() Episode4End =
{
StartMessageIntermission ();
ShowIntermissionMessage ("Despite the awful might of the Elder\n"
"World, you have achieved the Rune of\n"
"Elder Magic, capstone of all types of\n"
"arcane wisdom. Beyond good and evil,\n"
"beyond life and death, the Rune\n"
"pulsates, heavy with import. Patient and\n"
"potent, the Elder Being Shub-Niggurath\n"
"weaves her dire plans to clear off all\n"
"life from the Earth, and bring her own\n"
"foul offspring to our world! For all the\n"
"dwellers in these nightmare dimensions\n"
"are her descendants! Once all Runes of\n"
"magic power are united, the energy\n"
"behind them will blast open the Gateway\n"
"to Shub-Niggurath, and you can travel\n"
"there to foil the Hell-Mother's plots\nin person.");
};
//----------------------------------------------------------------------
float() RunId1Intermissions =
{
if (world.skip_id1_overrides == 0)
{
if (world.model == "maps/e1m7.bsp")
{
Episode1End ();
return 1;
}
else if (world.model == "maps/e2m6.bsp")
{
Episode2End ();
return 1;
}
else if (world.model == "maps/e3m6.bsp")
{
Episode3End ();
return 1;
}
else if (world.model == "maps/e4m7.bsp")
{
Episode4End ();
return 1;
}
}
return 0;
};
//----------------------------------------------------------------------
// FindIntermission -- Returns the entity to view from
//----------------------------------------------------------------------
entity() FindIntermission =
{
local entity spot;
local float cyc;
// look for info_intermission first
spot = findfloat (world, classtype, CT_INFO_INTERMISSION);
if (spot)
{ // pick a random one
cyc = random() * 4;
while (cyc > 1)
{
spot = findfloat (spot, classtype,
CT_INFO_INTERMISSION);
if (!spot)
spot = findfloat (spot, classtype,
CT_INFO_INTERMISSION);
cyc = cyc - 1;
}
return spot;
}
// then look for the start position
spot = findfloat (world, classtype, CT_INFO_PLAYER_START);
if (spot)
return spot;
// testinfo_player_start is only found in regioned levels
spot = findfloat (world, classtype, CT_INFO_TESTPLAYERSTART);
if (spot)
return spot;
objerror ("FindIntermission: no spot");
// just to suppress the compiler warning
return world;
};
//----------------------------------------------------------------------
void() GotoNextMap =
{
if (cvar("samelevel"))
// if samelevel is set, stay on same level
changelevel (mapname);
else
changelevel (nextmap);
};
//----------------------------------------------------------------------
float(float start) ShowIntermissionTextEntity =
{
if (!(used_exit.spawnflags & 2))
{
local entity end_message;
for (end_message = world; (end_message = findfloat
(end_message, classtype, CT_INFO_INTERMISSIONTEXT)); )
{
if (end_message.cnt == (intermission - 1))
{
if (start == 1)
StartMessageIntermission ();
ShowIntermissionMessage (end_message.message);
return 1;
}
}
}
return 0;
};
//----------------------------------------------------------------------
void() ExitIntermission =
{
// skip any text in deathmatch
if (deathmatch)
{
GotoNextMap ();
return;
}
intermission_exittime = time + 1;
intermission = intermission + 1;
// run some text if at the end of an episode
if (intermission == 2)
{
if (RunId1Intermissions() == 1)
{
return;
}
else
{
if (used_exit.message != "")
{
// favor message on changelevel
StartMessageIntermission ();
ShowIntermissionMessage (used_exit.message);
return;
}
if (ShowIntermissionTextEntity(1))
{
return;
}
}
GotoNextMap ();
}
if (intermission == 3)
{
if (!cvar("registered"))
{
// shareware episode has been completed,
// go to sell screen
WriteByte (MSG_ALL, SVC_SELLSCREEN);
return;
}
if (ShowIntermissionTextEntity(0))
{
return;
}
if ((serverflags & 15) == 15)
{
ShowIntermissionMessage ("Now, you have all four Runes."
" You sense\ntremendous invisible forces moving"
" to\nunseal ancient barriers."
" Shub-Niggurath\nhad hoped to use the Runes"
" Herself to\nclear off the Earth, but now"
" instead,\nyou will use them to enter her"
" home and\nconfront her as an avatar of"
" avenging\nEarth-life. If you defeat her,"
" you will\nbe remembered forever as the"
" savior of\nthe planet. If she conquers,"
" it will be\nas if you had never been born.");
return;
}
}
if (intermission > 3)
{
if (ShowIntermissionTextEntity(0))
{
return;
}
}
GotoNextMap ();
};
//----------------------------------------------------------------------
// IntermissionThink
// When the player presses attack or jump, change to the next level
// 'self' in this context is the client/player
//----------------------------------------------------------------------
void() IntermissionThink =
{
if (time < intermission_exittime)
return;
if (!self.button0 && !self.button1 && !self.button2)
return;
ExitIntermission ();
};
//----------------------------------------------------------------------
// WriteIntermission -- CEV
//----------------------------------------------------------------------
void() WriteIntermission =
{
WriteByte (MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte (MSG_MULTICAST, EVENT_INTERMISSION);
WriteFloat (MSG_MULTICAST, intermission);
multicast ('0 0 0', MULTICAST_ALL);
};
//----------------------------------------------------------------------
void() RestartLoopSounds_think =
{
sound (self, self.impulse, self.noise, self.volume, self.speed);
};
//----------------------------------------------------------------------
void() RestartLoopSounds =
{
entity e;
e = findfloat (world, classtype, CT_MISC_PLAY_SOUND_TRIGGERED);
while (e) {
if (e.spawnflags & 3 == 3) {
// both "toggle" and "looped" need to be set
if (e.state == 1) {
e.nextthink = time + 0.1;
e.think = RestartLoopSounds_think;
}
}
e = findfloat (e, classtype, CT_MISC_PLAY_SOUND_TRIGGERED);
}
};
#endif
//======================================================================
// REAL entrypoints (the following functions are called by the engine)
//======================================================================
#ifdef SSQC
//----------------------------------------------------------------------
void() main =
{
dprint ("main function\n");
// these are just commands the the prog compiler to copy these files
precache_file ("progs.dat");
precache_file ("gfx.wad");
precache_file ("quake.rc");
precache_file ("default.cfg");
precache_file ("end1.bin");
precache_file2 ("end2.bin");
precache_file ("demo1.dem");
precache_file ("demo2.dem");
precache_file ("demo3.dem");
// these are all of the lumps from the cached.ls files
precache_file ("gfx/palette.lmp");
precache_file ("gfx/colormap.lmp");
precache_file2 ("gfx/pop.lmp");
precache_file ("gfx/complete.lmp");
precache_file ("gfx/inter.lmp");
precache_file ("gfx/ranking.lmp");
precache_file ("gfx/vidmodes.lmp");
precache_file ("gfx/finale.lmp");
precache_file ("gfx/conback.lmp");
precache_file ("gfx/qplaque.lmp");
precache_file ("gfx/menudot1.lmp");
precache_file ("gfx/menudot2.lmp");
precache_file ("gfx/menudot3.lmp");
precache_file ("gfx/menudot4.lmp");
precache_file ("gfx/menudot5.lmp");
precache_file ("gfx/menudot6.lmp");
precache_file ("gfx/menuplyr.lmp");
precache_file ("gfx/bigbox.lmp");
precache_file ("gfx/dim_modm.lmp");
precache_file ("gfx/dim_drct.lmp");
precache_file ("gfx/dim_ipx.lmp");
precache_file ("gfx/dim_tcp.lmp");
precache_file ("gfx/dim_mult.lmp");
precache_file ("gfx/mainmenu.lmp");
precache_file ("gfx/box_tl.lmp");
precache_file ("gfx/box_tm.lmp");
precache_file ("gfx/box_tr.lmp");
precache_file ("gfx/box_ml.lmp");
precache_file ("gfx/box_mm.lmp");
precache_file ("gfx/box_mm2.lmp");
precache_file ("gfx/box_mr.lmp");
precache_file ("gfx/box_bl.lmp");
precache_file ("gfx/box_bm.lmp");
precache_file ("gfx/box_br.lmp");
precache_file ("gfx/sp_menu.lmp");
precache_file ("gfx/ttl_sgl.lmp");
precache_file ("gfx/ttl_main.lmp");
precache_file ("gfx/ttl_cstm.lmp");
precache_file ("gfx/mp_menu.lmp");
precache_file ("gfx/netmen1.lmp");
precache_file ("gfx/netmen2.lmp");
precache_file ("gfx/netmen3.lmp");
precache_file ("gfx/netmen4.lmp");
precache_file ("gfx/netmen5.lmp");
precache_file ("gfx/sell.lmp");
precache_file ("gfx/help0.lmp");
precache_file ("gfx/help1.lmp");
precache_file ("gfx/help2.lmp");
precache_file ("gfx/help3.lmp");
precache_file ("gfx/help4.lmp");
precache_file ("gfx/help5.lmp");
precache_file ("gfx/pause.lmp");
precache_file ("gfx/loading.lmp");
precache_file ("gfx/p_option.lmp");
precache_file ("gfx/p_load.lmp");
precache_file ("gfx/p_save.lmp");
precache_file ("gfx/p_multi.lmp");
// sounds loaded by C code
precache_sound ("misc/menu1.wav");
precache_sound ("misc/menu2.wav");
precache_sound ("misc/menu3.wav");
precache_sound ("ambience/water1.wav");
precache_sound ("ambience/wind2.wav");
// shareware
precache_file ("maps/start.bsp");
precache_file ("maps/e1m1.bsp");
precache_file ("maps/e1m2.bsp");
precache_file ("maps/e1m3.bsp");
precache_file ("maps/e1m4.bsp");
precache_file ("maps/e1m5.bsp");
precache_file ("maps/e1m6.bsp");
precache_file ("maps/e1m7.bsp");
precache_file ("maps/e1m8.bsp");
// registered
precache_file2 ("gfx/pop.lmp");
precache_file2 ("maps/e2m1.bsp");
precache_file2 ("maps/e2m2.bsp");
precache_file2 ("maps/e2m3.bsp");
precache_file2 ("maps/e2m4.bsp");
precache_file2 ("maps/e2m5.bsp");
precache_file2 ("maps/e2m6.bsp");
precache_file2 ("maps/e2m7.bsp");
precache_file2 ("maps/e3m1.bsp");
precache_file2 ("maps/e3m2.bsp");
precache_file2 ("maps/e3m3.bsp");
precache_file2 ("maps/e3m4.bsp");
precache_file2 ("maps/e3m5.bsp");
precache_file2 ("maps/e3m6.bsp");
precache_file2 ("maps/e3m7.bsp");
precache_file2 ("maps/e4m1.bsp");
precache_file2 ("maps/e4m2.bsp");
precache_file2 ("maps/e4m3.bsp");
precache_file2 ("maps/e4m4.bsp");
precache_file2 ("maps/e4m5.bsp");
precache_file2 ("maps/e4m6.bsp");
precache_file2 ("maps/e4m7.bsp");
precache_file2 ("maps/e4m8.bsp");
precache_file2 ("maps/end.bsp");
precache_file2 ("maps/dm1.bsp");
precache_file2 ("maps/dm2.bsp");
precache_file2 ("maps/dm3.bsp");
precache_file2 ("maps/dm4.bsp");
precache_file2 ("maps/dm5.bsp");
precache_file2 ("maps/dm6.bsp");
};
//----------------------------------------------------------------------
// ClientConnect
// called when a player connects to a server; the client may not have
// fully spawned yet (according to Nuclide's comments). self in this
// context refers to the connecting client. -- CEV
//----------------------------------------------------------------------
void() ClientConnect =
{
// a client connecting during an intermission can cause problems
if (intermission)
ExitIntermission ();
if (self.classname != "player")
// run the player spawn function, initializing 'self'
// as a player object -- CEV
player_init (self);
bprint (self.netname);
bprint (" entered the game\n");
};
//----------------------------------------------------------------------
// ClientDisconnect
// called when a player disconnects from a server; the client will be
// removed after this function, so 'self' in this context is the player
// and any fields of self can be accessed. -- CEV
//----------------------------------------------------------------------
void() ClientDisconnect =
{
// if the level end trigger has been activated, just return
// since they aren't *really* leaving
if (gameover)
return;
// let everyone else know
bprint (self.netname);
bprint (" left the game with ");
bprint (ftos(self.frags));
bprint (" frags\n");
sound (self, CHAN_BODY, "player/tornoff2.wav", VOL_HIGH, ATTN_NONE);
if (self.classtype == CT_PLAYER)
player_set_suicide_frame ();
else
dprint ("ClientDisconnect: ERROR! Encountered a non-player!\n");
};
//----------------------------------------------------------------------
// ClientKill -- Player entered the suicide command; 'self' is the client
//----------------------------------------------------------------------
void() ClientKill =
{
// 1998-07-27 Suicide during intermission fix by Zhenga start
// not allowed during intermission
if ((intermission) && ((coop) || (deathmatch)))
return;
// 1998-07-27 Suicide during intermission fix by Zhenga end
bprint (self.netname);
bprint (" suicides\n");
if (self.classtype == CT_PLAYER)
{
player_set_suicide_frame ();
self.modelindex = modelindex_player;
// extra penalty
self.frags = self.frags - 2;
player_respawn ();
}
else
{
dprint ("ClientKill: ERROR! suicide from a non-player!\n");
}
};
//----------------------------------------------------------------------
void() SetNewParms =
{
parm2 = 100; // self.health
parm3 = 0; // self.armorvalue
parm5 = 0; // self.ammo_nails
parm6 = 0; // self.ammo_rockets
parm7 = 0; // self.ammo_cells
parm9 = 0; // self.armortype * 100
// "reset_items 2" makes the player start with only the axe -- iw
if (world.reset_items == 2)
{
parm1 = IT_AXE; // self.items
parm4 = 0; // self.ammo_shells
parm8 = IT_AXE; // self.weapon
}
else
{
parm1 = IT_AXE | IT_SHOTGUN; // self.items
parm4 = 25; // self.ammo_shells
parm8 = IT_SHOTGUN; // self.weapon
}
};
//----------------------------------------------------------------------
void() SetChangeParms =
{
if (self.health <= 0)
{
SetNewParms ();
return;
}
// remove items
self.items = self.items - (self.items &
(IT_KEY1 | IT_KEY2 | IT_INVISIBILITY | IT_INVULNERABILITY
| IT_SUIT | IT_QUAD)
);
// cap super health
if (self.health > 100)
self.health = 100;
if (self.health < 50)
self.health = 50;
parm1 = self.items;
parm2 = self.health;
parm3 = self.armorvalue;
if (self.ammo_shells < 25)
parm4 = 25;
else
parm4 = self.ammo_shells;
parm5 = self.ammo_nails;
parm6 = self.ammo_rockets;
parm7 = self.ammo_cells;
parm8 = self.weapon;
parm9 = self.armortype * 100;
};
//----------------------------------------------------------------------
// PutClientInServer -- called each time a player is spawned
// according to Nuclide: player has fully connected and loaded in.
// 'self' is the player/client, parmX are populated with data carried
// over from previous levels for this specific client. -- CEV
//----------------------------------------------------------------------
void() PutClientInServer =
{
if (self.classname == "player")
dprint ("PutClientInServer: classname already player!\n");
};
//----------------------------------------------------------------------
// PlayerPreThink -- Called every frame before physics are run
//----------------------------------------------------------------------
void() PlayerPreThink =
{
if (intermission)
{
// otherwise a button could be missed between the think tics
IntermissionThink ();
return;
}
if (self.view_ofs == '0 0 0')
{
// Check for cutscene stuff.
// TODO CEV Cutscene_Think ();
// intermission or finale
return;
}
// Check map / gametype rules, change to next level if requested -- CEV
CheckRules ();
// call prethink on the player after double checking classtype -- CEV
if (self.classtype == CT_PLAYER)
player_prethink ();
else
dprint (sprintf("PlayerPreThink: called for a %s!\n",
self.classname));
};
//----------------------------------------------------------------------
// SV_RunClientCommand -- Called every frame to run physics
//----------------------------------------------------------------------
void() SV_RunClientCommand =
{
// see pmove.qc -- CEV
PM_MOVE_PRE ()
PM_MOVE_MOVETYPES ()
PM_MOVE_POST ()
};
//----------------------------------------------------------------------
// PlayerPostThink -- Called every frame after physics are run
//----------------------------------------------------------------------
void() PlayerPostThink =
{
if (intermission)
return;
// call postthink on the player after double checking classtype -- CEV
if (self.classtype == CT_PLAYER)
player_postthink ();
};
//----------------------------------------------------------------------
void() StartFrame =
{
// new spawnflags for all entities -- iw
if (!done_inhibition_summary)
PrintInhibitionSummary ();
// per-frame latched variables -- CEV
teamplay = cvar ("teamplay");
skill = cvar ("skill");
if (clean_up_client_stuff)
{
clean_up_client_stuff -= 1;
RestartLoopSounds ();
}
else if (!gamestarted)
{
if (framecount > 2)
{
if (framecount != 3)
clean_up_client_stuff += 2;
gamestarted = TRUE;
}
}
/*
// aid clientside prediction by updating any networked SOLID_BSP
// MOVETYPE_PUSH entities that are in motion. I hate looping
// through all entities like this. -- CEV
local entity e = world;
while ((e = nextent(e)))
{
// only SOLID PUSH entities
if (e.solid == SOLID_BSP && e.movetype == MOVETYPE_PUSH)
// only CG_FUNC entities
if (e.classgroup & CG_FUNC)
// only ents in motion with a SendEntity func
if (e.velocity && e.SendEntity)
// transmit origin and velocity
e.SendFlags |= BASE_FUNC_NET_ORIGIN |
BASE_FUNC_NET_VELOCITY |
BASE_FUNC_NET_SPEED;
}
*/
};
//----------------------------------------------------------------------
// "Called after non-player entities have run at the end of the physics frame"
// according to fteextensions.qc
//----------------------------------------------------------------------
/*
void() EndFrame =
{
};
*/
/*
// placeholder in case it's necessary; based on code from Nuclide SDK -- CEV
void(void() spawnfunc) CheckSpawn =
{
if (spawnfunc)
{
// dprint (sprintf("CheckSpawn: creating %s\n",
// self.classname));
spawnfunc ();
}
else
{
// print (sprintf("CheckSpawn: cannot find entity class %s\n",
// self.classname));
remove (self);
}
};
*/
#endif
Return to the top of this page or return to the overview of this repo.
Log sv_entry.qc
Date | Commit Message | Author | + | - |
---|---|---|---|---|
2024-11-20 | pmove refactor into prepoc macros, view bobbing | cev | +15 | -7 |
2024-09-17 | Ice, improved stairs, other movement changes | cev | +3 | |
2024-07-17 | pmove changes, smooth crouching | cev | +3 | -1 |
2024-06-26 | pmove fixes, GL now a faux tribolt, wall climbing | cev | +5 | -8 |
2024-06-15 | Major update, committing as-is, will have bugs | cev | +39 | -14 |
2024-03-24 | 2nd pass refactor, rework QC class structure | cev | +903 |
Return to the top of this page or return to the overview of this repo.