QuakeC Entry Functions ================================== QuakeC can output 3 different types of modules. A client-side module, a menu module and a server-side module. The server-side module can talk to the client-side module and vice versa. However, the menu module is, as of yet, only a stripped down, omni-present variant of the client-side module. CSQC = client-side module MenuQC = menu module SSQC = server-side module All of them have different entry functions. They're like callbacks from the engine for whenever something happens. SSQC SPECIFIC ENTRY FUNCTIONS ============================= Standard Quake (minimum, required!): ------------------------------------ This is unused and will never be called from the engine in standard Quake. void main( void ) Called once every frame, before all the entities ran. `self` is not valid: void StartFrame ( void ) Run before player physics. `self` is one of the clients on the server: void PlayerPreThink ( void ) Run after player physics. `self` is one of the clients on the server: void PlayerPostThink( void ) 'kill' command issued. `self` in this function, is the client in question: void ClientKill( void ) Handle player connection message. `self` in this function, is the client in question: void ClientConnect( void ) Handle player spawning/setup. `self` in this function, is the client in question: void PutClientInServer( void ) Handle player parting message. `self` in this function, is the client in question: void ClientDisconnect( void ) Singleplayer stuff. Sets the parmX `globals` for each player. Take a look at what Quake does and you'll hopefully understand. It's quite limited and `self` in these functions is the client in question: void SetNewParms( void ) void SetChangeParms( void ) Noteworthy QuakeWorld / FTE QuakeWorld additions: ------------------------------------------------- Called when a spectator joins the game. `self` in this function, is the spectator in question: void SpectatorConnect( void ) Called when a spectator disconnects from the game. `self` in this function, is the spectator in question: void SpectatorDisconnect( void ) Called each frame for each spectator. `self` in this function, is the spectator in question: void SpectatorThink( void ) Provides QC with a way to intercept 'cmd foo' commands from the client. Very handy. Self will be set to the sending client, while the 'cmd' argument can be tokenize()d and each element retrieved via argv(argno). Unrecognised cmds MUST be passed on to the clientcommand builtin. `self` in this function, is the client in question: void SV_ParseClientCommand( string strCmd ) For each frame that the server is paused, this function will be called to give the gamecode a chance to unpause the server again. the flPaused argument says how long the server has been paused for (the time global is frozen and will not increment while paused). `self` is not valid: void SV_PausedTic( float flPaused ) Called to give the qc a change to block pause/unpause requests. Return false for the pause request to be ignored. newstatus is 1 if the user is trying to pause the game. For the duration of the call, self will be set to the player who tried to pause, or to world if it was triggered by a server-side event. `self` is not valid: float SV_ShouldPause( float flNewStatus ) { return FALSE; } Called each time a player movement packet was received from a client. `self` is set to the player entity which should be updated, while the input_* globals specify the various properties stored within the input packet. The contents of this function should be somewaht identical to the equivalent function in CSQC, or prediction misses will occur. If you're feeling lazy, you can simply call 'runstandardplayerphysics' after modifying the inputs. void SV_RunClientCommand ( void ) Called after non-player entities have been run at the end of the physics frame. Player physics is performed out of order and can/will still occur between EndFrame and BeginFrame. `self` is not valid: void EndFrame ( void ) Called whenever a new entity is set to be spawned by the SSQC, Override this function if you want to prevent the engine from filtering entities by skill/deathmatch - which it will absolutely do otherwise! void CheckSpawn( void() spawnfunc ) Gives you the opportunity to handle loading of save-files. 'fh' is the filehandle which is already opened. You only need to parse it with fgets(fh) while it returns a valid result. I suggest you remove all existing entities beforehand manually before spawning new ones. void SV_PerformLoad( float fh, float entcount, float playerslots ) Gives you the opportunity to save the game. Just like PerformLoad, the filehandle is already open for you. void SV_PerformSave( float fh, float entcount, float playerslots ) This is also valid for CSQC: This function is called when the progs is confirmed to be officially loaded. Beware however that entities are not ready to spawn just yet. You can however insert data into globals or other data structures, which can be respected by all entities later. void init ( void ) This is also valid for CSQC: This is the equivalent of init(), but at a point where entity slots are available to be allocated to the server side progs. If you need to call spawn() on any entity, do it no earlier than here. void initents ( void ) CSQC SPECIFIC ENTRY FUNCTIONS ============================= None of the CSQC entry functions are mandatory, you use them depending on your use case. However I'll try to prop up the important ones for the majority of programmers and those lesser used (The Wastes uses ALL of them). Essentials: ----------- Called once at the initialization of the CSQC module, which happens upon joining a server. void CSQC_Init ( float flAPI, string strBuild, float flVersion ) Happens when a current game session running the CSQC module is shutting down or the client disconnects. void CSQC_Shutdown ( void ) Run every frame. This calls the engine to render the 3D scene and to draw and overlay if desired. That overlay could be a HUD, it could be another scene as well. There are no limits as to what and how many of such things you can and will display. void CSQC_UpdateView ( float flWidth, float flHeight, float fNotMenu ) Whenever an input device is pressed, the engine calls this function to let the CSQC know. You will then have to filter out what input events you support and how they interact with your game-logic. For example, flEV could be IE_KEYDOWN and flKey could be K_ESCAPE. This means the Escape key on your keyboard was being held down. The this function returns TRUE, then the engine won't handle the input event internally any further until the next. float CSQC_InputEvent ( float flEV, float flKey, float flChar, float fDevID ) Pretty good ones: ----------------- Called whenever the video mode has changed, or vid_reload has been called. If you define custom shaders, you want those initialized in here, otherwise they'll get wiped after clients' change their video mode: void CSQC_RendererRestarted ( string strRenderer ) Called whenever the client enters a console command. This is the first place where it will get checked. If this function returns FALSE, then the engine will attempt to interpret the command (unless a MenuQC module is present): float CSQC_ConsoleCommand ( string strCommand ) This is where all WriteByte() SVC_GAMEEVENT network packets arrive. That way the Server-Side QuakeC can send reliable/unreliable packets to all or individual players manually. void CSQC_Parse_Event ( void ) This is where you have the chance to alter the input_* globals before the client sends them off to the server, where they'd arrive inside SSQC's entry function SV_RunClientCommand if present: void CSQC_Input_Frame ( void ) Called when the world has finished loading on the client. void CSQC_WorldLoaded ( void ) This is where you handle all the entity packets that the .SendEntity field sends out to the individual players: void CSQC_Ent_Update ( float flNew ) MENUQC SPECIFIC ENTRY FUNCTIONS =============================== void() m_init; void() m_shutdown; Provides the menuqc with a chance to draw. Will be called even if the menu does not have focus, so be sure to avoid that. WARNING: vecScreenSize is not provided in DP. void m_draw (vector vecScreenSize) Additional drawing function to draw loading screens. If flOpaque is set, then this function must ensure that the entire screen is overdrawn (even if just by a black drawfill): void m_drawloading (vector vecScreenSize, float flOpaque) Called whenever a key is pressed, the mouse is moved, etc. evtype will be one of the IE_* constants. The other arguments vary depending on the evtype. Key presses are not guarenteed to have both scan and unichar values set at the same time. This mirrors the CSQC version of the input function. FTE ONLY: float Menu_InputEvent ( float evtype, float scanx, float chary, float devid ) Legacy/Darkplaces KeyUp/KeyDown functions, mirroring Quake 1/2's internal menu code: void m_keydown (float scan, float chr) void m_keyup (float scan, float chr) This is a bit of an annoyance, this is meant to be called whenever `togglemenu` is called. Which only works when the focus is on the game. So it doesn't always toggle in all situations. void m_toggle (float flWantmode) Basically what happens when CSQC_ConsoleCommand returns FALSE or MenuQC is in focus first. If this method returns FALSE then the engine will attempt to interpret the command, unless CSQC_ConsoleCommand returns TRUE and the game is not in focus. Basically just store your damn menu specific commands here: float m_consolecommand ( string strCommand )