+
+ SV_VM_End();
+}
+
+/////////////////////////////////////////////////////
+// SV VM stuff
+
+void SV_VM_CB_BeginIncreaseEdicts(void)
+{
+ int i;
+ prvm_edict_t *ent;
+
+ PRVM_Free( sv.moved_edicts );
+ sv.moved_edicts = (prvm_edict_t **)PRVM_Alloc(prog->max_edicts * sizeof(prvm_edict_t *));
+
+ // links don't survive the transition, so unlink everything
+ for (i = 0, ent = prog->edicts;i < prog->max_edicts;i++, ent++)
+ {
+ if (!ent->priv.server->free)
+ SV_UnlinkEdict(prog->edicts + i);
+ memset(&ent->priv.server->areagrid, 0, sizeof(ent->priv.server->areagrid));
+ }
+ SV_ClearWorld();
+}
+
+void SV_VM_CB_EndIncreaseEdicts(void)
+{
+ int i;
+ prvm_edict_t *ent;
+
+ for (i = 0, ent = prog->edicts;i < prog->max_edicts;i++, ent++)
+ {
+ // link every entity except world
+ if (!ent->priv.server->free)
+ SV_LinkEdict(ent, false);
+ }
+}
+
+void SV_VM_CB_InitEdict(prvm_edict_t *e)
+{
+ // LordHavoc: for consistency set these here
+ int num = PRVM_NUM_FOR_EDICT(e) - 1;
+
+ e->priv.server->move = false; // don't move on first frame
+
+ if (num >= 0 && num < svs.maxclients)
+ {
+ prvm_eval_t *val;
+ // set colormap and team on newly created player entity
+ e->fields.server->colormap = num + 1;
+ e->fields.server->team = (svs.clients[num].colors & 15) + 1;
+ // set netname/clientcolors back to client values so that
+ // DP_SV_CLIENTNAME and DP_SV_CLIENTCOLORS will not immediately
+ // reset them
+ e->fields.server->netname = PRVM_SetEngineString(svs.clients[num].name);
+ if ((val = PRVM_GETEDICTFIELDVALUE(e, eval_clientcolors)))
+ val->_float = svs.clients[num].colors;
+ // NEXUIZ_PLAYERMODEL and NEXUIZ_PLAYERSKIN
+ if( eval_playermodel )
+ PRVM_GETEDICTFIELDVALUE(e, eval_playermodel)->string = PRVM_SetEngineString(svs.clients[num].playermodel);
+ if( eval_playerskin )
+ PRVM_GETEDICTFIELDVALUE(e, eval_playerskin)->string = PRVM_SetEngineString(svs.clients[num].playerskin);
+ }
+}
+
+void SV_VM_CB_FreeEdict(prvm_edict_t *ed)
+{
+ SV_UnlinkEdict (ed); // unlink from world bsp
+
+ ed->fields.server->model = 0;
+ ed->fields.server->takedamage = 0;
+ ed->fields.server->modelindex = 0;
+ ed->fields.server->colormap = 0;
+ ed->fields.server->skin = 0;
+ ed->fields.server->frame = 0;
+ VectorClear(ed->fields.server->origin);
+ VectorClear(ed->fields.server->angles);
+ ed->fields.server->nextthink = -1;
+ ed->fields.server->solid = 0;
+}
+
+void SV_VM_CB_CountEdicts(void)
+{
+ int i;
+ prvm_edict_t *ent;
+ int active, models, solid, step;
+
+ active = models = solid = step = 0;
+ for (i=0 ; i<prog->num_edicts ; i++)
+ {
+ ent = PRVM_EDICT_NUM(i);
+ if (ent->priv.server->free)
+ continue;
+ active++;
+ if (ent->fields.server->solid)
+ solid++;
+ if (ent->fields.server->model)
+ models++;
+ if (ent->fields.server->movetype == MOVETYPE_STEP)
+ step++;
+ }
+
+ Con_Printf("num_edicts:%3i\n", prog->num_edicts);
+ Con_Printf("active :%3i\n", active);
+ Con_Printf("view :%3i\n", models);
+ Con_Printf("touch :%3i\n", solid);
+ Con_Printf("step :%3i\n", step);
+}
+
+qboolean SV_VM_CB_LoadEdict(prvm_edict_t *ent)
+{
+ // remove things from different skill levels or deathmatch
+ if (gamemode != GAME_TRANSFUSION) //Transfusion does this in QC
+ {
+ if (deathmatch.integer)
+ {
+ if (((int)ent->fields.server->spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
+ {
+ return false;
+ }
+ }
+ else if ((current_skill <= 0 && ((int)ent->fields.server->spawnflags & SPAWNFLAG_NOT_EASY ))
+ || (current_skill == 1 && ((int)ent->fields.server->spawnflags & SPAWNFLAG_NOT_MEDIUM))
+ || (current_skill >= 2 && ((int)ent->fields.server->spawnflags & SPAWNFLAG_NOT_HARD )))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+cvar_t pr_checkextension = {CVAR_READONLY, "pr_checkextension", "1", "indicates to QuakeC that the standard quakec extensions system is available (if 0, quakec should not attempt to use extensions)"};
+cvar_t nomonsters = {0, "nomonsters", "0", "unused cvar in quake, can be used by mods"};
+cvar_t gamecfg = {0, "gamecfg", "0", "unused cvar in quake, can be used by mods"};
+cvar_t scratch1 = {0, "scratch1", "0", "unused cvar in quake, can be used by mods"};
+cvar_t scratch2 = {0,"scratch2", "0", "unused cvar in quake, can be used by mods"};
+cvar_t scratch3 = {0, "scratch3", "0", "unused cvar in quake, can be used by mods"};
+cvar_t scratch4 = {0, "scratch4", "0", "unused cvar in quake, can be used by mods"};
+cvar_t savedgamecfg = {CVAR_SAVE, "savedgamecfg", "0", "unused cvar in quake that is saved to config.cfg on exit, can be used by mods"};
+cvar_t saved1 = {CVAR_SAVE, "saved1", "0", "unused cvar in quake that is saved to config.cfg on exit, can be used by mods"};
+cvar_t saved2 = {CVAR_SAVE, "saved2", "0", "unused cvar in quake that is saved to config.cfg on exit, can be used by mods"};
+cvar_t saved3 = {CVAR_SAVE, "saved3", "0", "unused cvar in quake that is saved to config.cfg on exit, can be used by mods"};
+cvar_t saved4 = {CVAR_SAVE, "saved4", "0", "unused cvar in quake that is saved to config.cfg on exit, can be used by mods"};
+cvar_t nehx00 = {0, "nehx00", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx01 = {0, "nehx01", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx02 = {0, "nehx02", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx03 = {0, "nehx03", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx04 = {0, "nehx04", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx05 = {0, "nehx05", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx06 = {0, "nehx06", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx07 = {0, "nehx07", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx08 = {0, "nehx08", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx09 = {0, "nehx09", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx10 = {0, "nehx10", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx11 = {0, "nehx11", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx12 = {0, "nehx12", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx13 = {0, "nehx13", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx14 = {0, "nehx14", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx15 = {0, "nehx15", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx16 = {0, "nehx16", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx17 = {0, "nehx17", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx18 = {0, "nehx18", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t nehx19 = {0, "nehx19", "0", "nehahra data storage cvar (used in singleplayer)"};
+cvar_t cutscene = {0, "cutscene", "1", "enables cutscenes in nehahra, can be used by other mods"};
+
+void SV_VM_Init(void)
+{
+ Cvar_RegisterVariable (&pr_checkextension);
+ Cvar_RegisterVariable (&nomonsters);
+ Cvar_RegisterVariable (&gamecfg);
+ Cvar_RegisterVariable (&scratch1);
+ Cvar_RegisterVariable (&scratch2);
+ Cvar_RegisterVariable (&scratch3);
+ Cvar_RegisterVariable (&scratch4);
+ Cvar_RegisterVariable (&savedgamecfg);
+ Cvar_RegisterVariable (&saved1);
+ Cvar_RegisterVariable (&saved2);
+ Cvar_RegisterVariable (&saved3);
+ Cvar_RegisterVariable (&saved4);
+ // LordHavoc: Nehahra uses these to pass data around cutscene demos
+ if (gamemode == GAME_NEHAHRA)
+ {
+ Cvar_RegisterVariable (&nehx00);
+ Cvar_RegisterVariable (&nehx01);
+ Cvar_RegisterVariable (&nehx02);
+ Cvar_RegisterVariable (&nehx03);
+ Cvar_RegisterVariable (&nehx04);
+ Cvar_RegisterVariable (&nehx05);
+ Cvar_RegisterVariable (&nehx06);
+ Cvar_RegisterVariable (&nehx07);
+ Cvar_RegisterVariable (&nehx08);
+ Cvar_RegisterVariable (&nehx09);
+ Cvar_RegisterVariable (&nehx10);
+ Cvar_RegisterVariable (&nehx11);
+ Cvar_RegisterVariable (&nehx12);
+ Cvar_RegisterVariable (&nehx13);
+ Cvar_RegisterVariable (&nehx14);
+ Cvar_RegisterVariable (&nehx15);
+ Cvar_RegisterVariable (&nehx16);
+ Cvar_RegisterVariable (&nehx17);
+ Cvar_RegisterVariable (&nehx18);
+ Cvar_RegisterVariable (&nehx19);
+ }
+ Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
+}
+
+// LordHavoc: in an effort to eliminate time wasted on GetEdictFieldValue... these are defined as externs in progs.h
+int eval_gravity;
+int eval_button3;
+int eval_button4;
+int eval_button5;
+int eval_button6;
+int eval_button7;
+int eval_button8;
+int eval_button9;
+int eval_button10;
+int eval_button11;
+int eval_button12;
+int eval_button13;
+int eval_button14;
+int eval_button15;
+int eval_button16;
+int eval_buttonuse;
+int eval_buttonchat;
+int eval_glow_size;
+int eval_glow_trail;
+int eval_glow_color;
+int eval_items2;
+int eval_scale;
+int eval_alpha;
+int eval_renderamt; // HalfLife support
+int eval_rendermode; // HalfLife support
+int eval_fullbright;
+int eval_ammo_shells1;
+int eval_ammo_nails1;
+int eval_ammo_lava_nails;
+int eval_ammo_rockets1;
+int eval_ammo_multi_rockets;
+int eval_ammo_cells1;
+int eval_ammo_plasma;
+int eval_idealpitch;
+int eval_pitch_speed;
+int eval_viewmodelforclient;
+int eval_nodrawtoclient;
+int eval_exteriormodeltoclient;
+int eval_drawonlytoclient;
+int eval_ping;
+int eval_movement;
+int eval_pmodel;
+int eval_punchvector;
+int eval_viewzoom;
+int eval_clientcolors;
+int eval_tag_entity;
+int eval_tag_index;
+int eval_light_lev;
+int eval_color;
+int eval_style;
+int eval_pflags;
+int eval_cursor_active;
+int eval_cursor_screen;
+int eval_cursor_trace_start;
+int eval_cursor_trace_endpos;
+int eval_cursor_trace_ent;
+int eval_colormod;
+int eval_playermodel;
+int eval_playerskin;
+int eval_SendEntity;
+int eval_Version;
+int eval_customizeentityforclient;
+int eval_dphitcontentsmask;
+
+int gval_trace_dpstartcontents;
+int gval_trace_dphitcontents;
+int gval_trace_dphitq3surfaceflags;
+int gval_trace_dphittexturename;
+
+mfunction_t *SV_PlayerPhysicsQC;
+mfunction_t *EndFrameQC;
+//KrimZon - SERVER COMMANDS IN QUAKEC
+mfunction_t *SV_ParseClientCommandQC;
+
+ddef_t *PRVM_ED_FindGlobal(const char *name);
+
+void SV_VM_FindEdictFieldOffsets(void)
+{
+ eval_gravity = PRVM_ED_FindFieldOffset("gravity");
+ eval_button3 = PRVM_ED_FindFieldOffset("button3");
+ eval_button4 = PRVM_ED_FindFieldOffset("button4");
+ eval_button5 = PRVM_ED_FindFieldOffset("button5");
+ eval_button6 = PRVM_ED_FindFieldOffset("button6");
+ eval_button7 = PRVM_ED_FindFieldOffset("button7");
+ eval_button8 = PRVM_ED_FindFieldOffset("button8");
+ eval_button9 = PRVM_ED_FindFieldOffset("button9");
+ eval_button10 = PRVM_ED_FindFieldOffset("button10");
+ eval_button11 = PRVM_ED_FindFieldOffset("button11");
+ eval_button12 = PRVM_ED_FindFieldOffset("button12");
+ eval_button13 = PRVM_ED_FindFieldOffset("button13");
+ eval_button14 = PRVM_ED_FindFieldOffset("button14");
+ eval_button15 = PRVM_ED_FindFieldOffset("button15");
+ eval_button16 = PRVM_ED_FindFieldOffset("button16");
+ eval_buttonuse = PRVM_ED_FindFieldOffset("buttonuse");
+ eval_buttonchat = PRVM_ED_FindFieldOffset("buttonchat");
+ eval_glow_size = PRVM_ED_FindFieldOffset("glow_size");
+ eval_glow_trail = PRVM_ED_FindFieldOffset("glow_trail");
+ eval_glow_color = PRVM_ED_FindFieldOffset("glow_color");
+ eval_items2 = PRVM_ED_FindFieldOffset("items2");
+ eval_scale = PRVM_ED_FindFieldOffset("scale");
+ eval_alpha = PRVM_ED_FindFieldOffset("alpha");
+ eval_renderamt = PRVM_ED_FindFieldOffset("renderamt"); // HalfLife support
+ eval_rendermode = PRVM_ED_FindFieldOffset("rendermode"); // HalfLife support
+ eval_fullbright = PRVM_ED_FindFieldOffset("fullbright");
+ eval_ammo_shells1 = PRVM_ED_FindFieldOffset("ammo_shells1");
+ eval_ammo_nails1 = PRVM_ED_FindFieldOffset("ammo_nails1");
+ eval_ammo_lava_nails = PRVM_ED_FindFieldOffset("ammo_lava_nails");
+ eval_ammo_rockets1 = PRVM_ED_FindFieldOffset("ammo_rockets1");
+ eval_ammo_multi_rockets = PRVM_ED_FindFieldOffset("ammo_multi_rockets");
+ eval_ammo_cells1 = PRVM_ED_FindFieldOffset("ammo_cells1");
+ eval_ammo_plasma = PRVM_ED_FindFieldOffset("ammo_plasma");
+ eval_idealpitch = PRVM_ED_FindFieldOffset("idealpitch");
+ eval_pitch_speed = PRVM_ED_FindFieldOffset("pitch_speed");
+ eval_viewmodelforclient = PRVM_ED_FindFieldOffset("viewmodelforclient");
+ eval_nodrawtoclient = PRVM_ED_FindFieldOffset("nodrawtoclient");
+ eval_exteriormodeltoclient = PRVM_ED_FindFieldOffset("exteriormodeltoclient");
+ eval_drawonlytoclient = PRVM_ED_FindFieldOffset("drawonlytoclient");
+ eval_ping = PRVM_ED_FindFieldOffset("ping");
+ eval_movement = PRVM_ED_FindFieldOffset("movement");
+ eval_pmodel = PRVM_ED_FindFieldOffset("pmodel");
+ eval_punchvector = PRVM_ED_FindFieldOffset("punchvector");
+ eval_viewzoom = PRVM_ED_FindFieldOffset("viewzoom");
+ eval_clientcolors = PRVM_ED_FindFieldOffset("clientcolors");
+ eval_tag_entity = PRVM_ED_FindFieldOffset("tag_entity");
+ eval_tag_index = PRVM_ED_FindFieldOffset("tag_index");
+ eval_light_lev = PRVM_ED_FindFieldOffset("light_lev");
+ eval_color = PRVM_ED_FindFieldOffset("color");
+ eval_style = PRVM_ED_FindFieldOffset("style");
+ eval_pflags = PRVM_ED_FindFieldOffset("pflags");
+ eval_cursor_active = PRVM_ED_FindFieldOffset("cursor_active");
+ eval_cursor_screen = PRVM_ED_FindFieldOffset("cursor_screen");
+ eval_cursor_trace_start = PRVM_ED_FindFieldOffset("cursor_trace_start");
+ eval_cursor_trace_endpos = PRVM_ED_FindFieldOffset("cursor_trace_endpos");
+ eval_cursor_trace_ent = PRVM_ED_FindFieldOffset("cursor_trace_ent");
+ eval_colormod = PRVM_ED_FindFieldOffset("colormod");
+ eval_playermodel = PRVM_ED_FindFieldOffset("playermodel");
+ eval_playerskin = PRVM_ED_FindFieldOffset("playerskin");
+ eval_SendEntity = PRVM_ED_FindFieldOffset("SendEntity");
+ eval_Version = PRVM_ED_FindFieldOffset("Version");
+ eval_customizeentityforclient = PRVM_ED_FindFieldOffset("customizeentityforclient");
+ eval_dphitcontentsmask = PRVM_ED_FindFieldOffset("dphitcontentsmask");
+
+ // LordHavoc: allowing QuakeC to override the player movement code
+ SV_PlayerPhysicsQC = PRVM_ED_FindFunction ("SV_PlayerPhysics");
+ // LordHavoc: support for endframe
+ EndFrameQC = PRVM_ED_FindFunction ("EndFrame");
+ //KrimZon - SERVER COMMANDS IN QUAKEC
+ SV_ParseClientCommandQC = PRVM_ED_FindFunction ("SV_ParseClientCommand");
+
+ //[515]: init stufftext string (it is sent before svc_serverinfo)
+ if(PRVM_ED_FindGlobal("SV_InitCmd") && PRVM_ED_FindGlobal("SV_InitCmd")->type & ev_string)
+ SV_InitCmd = PRVM_G_STRING(PRVM_ED_FindGlobal("SV_InitCmd")->ofs);
+ else
+ SV_InitCmd = NULL;
+
+ gval_trace_dpstartcontents = PRVM_ED_FindGlobalOffset("trace_dpstartcontents");
+ gval_trace_dphitcontents = PRVM_ED_FindGlobalOffset("trace_dphitcontents");
+ gval_trace_dphitq3surfaceflags = PRVM_ED_FindGlobalOffset("trace_dphitq3surfaceflags");
+ gval_trace_dphittexturename = PRVM_ED_FindGlobalOffset("trace_dphittexturename");