+cvar_t pr_checkextension = {CVAR_READONLY, "pr_checkextension", "1"};
+cvar_t nomonsters = {0, "nomonsters", "0"};
+cvar_t gamecfg = {0, "gamecfg", "0"};
+cvar_t scratch1 = {0, "scratch1", "0"};
+cvar_t scratch2 = {0,"scratch2", "0"};
+cvar_t scratch3 = {0, "scratch3", "0"};
+cvar_t scratch4 = {0, "scratch4", "0"};
+cvar_t savedgamecfg = {CVAR_SAVE, "savedgamecfg", "0"};
+cvar_t saved1 = {CVAR_SAVE, "saved1", "0"};
+cvar_t saved2 = {CVAR_SAVE, "saved2", "0"};
+cvar_t saved3 = {CVAR_SAVE, "saved3", "0"};
+cvar_t saved4 = {CVAR_SAVE, "saved4", "0"};
+cvar_t decors = {0, "decors", "0"};
+cvar_t nehx00 = {0, "nehx00", "0"};cvar_t nehx01 = {0, "nehx01", "0"};
+cvar_t nehx02 = {0, "nehx02", "0"};cvar_t nehx03 = {0, "nehx03", "0"};
+cvar_t nehx04 = {0, "nehx04", "0"};cvar_t nehx05 = {0, "nehx05", "0"};
+cvar_t nehx06 = {0, "nehx06", "0"};cvar_t nehx07 = {0, "nehx07", "0"};
+cvar_t nehx08 = {0, "nehx08", "0"};cvar_t nehx09 = {0, "nehx09", "0"};
+cvar_t nehx10 = {0, "nehx10", "0"};cvar_t nehx11 = {0, "nehx11", "0"};
+cvar_t nehx12 = {0, "nehx12", "0"};cvar_t nehx13 = {0, "nehx13", "0"};
+cvar_t nehx14 = {0, "nehx14", "0"};cvar_t nehx15 = {0, "nehx15", "0"};
+cvar_t nehx16 = {0, "nehx16", "0"};cvar_t nehx17 = {0, "nehx17", "0"};
+cvar_t nehx18 = {0, "nehx18", "0"};cvar_t nehx19 = {0, "nehx19", "0"};
+cvar_t cutscene = {0, "cutscene", "1"};
+
+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: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
+ Cvar_RegisterVariable (&decors);
+ // 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_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;
+
+mfunction_t *SV_PlayerPhysicsQC;
+mfunction_t *EndFrameQC;
+//KrimZon - SERVER COMMANDS IN QUAKEC
+mfunction_t *SV_ParseClientCommandQC;
+
+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_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");
+
+ // 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");
+}
+
+#define REQFIELDS (sizeof(reqfields) / sizeof(prvm_required_field_t))
+
+prvm_required_field_t reqfields[] =
+{
+ {ev_entity, "cursor_trace_ent"},
+ {ev_entity, "drawonlytoclient"},
+ {ev_entity, "exteriormodeltoclient"},
+ {ev_entity, "nodrawtoclient"},
+ {ev_entity, "tag_entity"},
+ {ev_entity, "viewmodelforclient"},
+ {ev_float, "alpha"},
+ {ev_float, "ammo_cells1"},
+ {ev_float, "ammo_lava_nails"},
+ {ev_float, "ammo_multi_rockets"},
+ {ev_float, "ammo_nails1"},
+ {ev_float, "ammo_plasma"},
+ {ev_float, "ammo_rockets1"},
+ {ev_float, "ammo_shells1"},
+ {ev_float, "button3"},
+ {ev_float, "button4"},
+ {ev_float, "button5"},
+ {ev_float, "button6"},
+ {ev_float, "button7"},
+ {ev_float, "button8"},
+ {ev_float, "buttonchat"},
+ {ev_float, "buttonuse"},
+ {ev_float, "clientcolors"},
+ {ev_float, "cursor_active"},
+ {ev_float, "fullbright"},
+ {ev_float, "glow_color"},
+ {ev_float, "glow_size"},
+ {ev_float, "glow_trail"},
+ {ev_float, "gravity"},
+ {ev_float, "idealpitch"},
+ {ev_float, "items2"},
+ {ev_float, "light_lev"},
+ {ev_float, "pflags"},
+ {ev_float, "ping"},
+ {ev_float, "pitch_speed"},
+ {ev_float, "pmodel"},
+ {ev_float, "renderamt"}, // HalfLife support
+ {ev_float, "rendermode"}, // HalfLife support
+ {ev_float, "scale"},
+ {ev_float, "style"},
+ {ev_float, "tag_index"},
+ {ev_float, "viewzoom"},
+ {ev_vector, "color"},
+ {ev_vector, "colormod"},
+ {ev_vector, "cursor_screen"},
+ {ev_vector, "cursor_trace_endpos"},
+ {ev_vector, "cursor_trace_start"},
+ {ev_vector, "movement"},
+ {ev_vector, "punchvector"},
+ {ev_string, "playermodel"},
+ {ev_string, "playerskin"}
+};
+
+void SV_VM_Setup(void)
+{
+ PRVM_Begin;
+ PRVM_InitProg( PRVM_SERVERPROG );
+
+ // allocate the mempools
+ prog->progs_mempool = Mem_AllocPool("Server Progs", 0, NULL);
+ prog->builtins = vm_sv_builtins;
+ prog->numbuiltins = vm_sv_numbuiltins;
+ prog->headercrc = PROGHEADER_CRC;
+ prog->max_edicts = 512;
+ prog->limit_edicts = MAX_EDICTS;
+ prog->reserved_edicts = svs.maxclients;
+ prog->edictprivate_size = sizeof(edict_engineprivate_t);
+ prog->name = "server";
+ prog->extensionstring = vm_sv_extensions;
+ prog->loadintoworld = true;
+
+ prog->begin_increase_edicts = SV_VM_CB_BeginIncreaseEdicts;
+ prog->end_increase_edicts = SV_VM_CB_EndIncreaseEdicts;
+ prog->init_edict = SV_VM_CB_InitEdict;
+ prog->free_edict = SV_VM_CB_FreeEdict;
+ prog->count_edicts = SV_VM_CB_CountEdicts;
+ prog->load_edict = SV_VM_CB_LoadEdict;
+ prog->init_cmd = VM_SV_Cmd_Init;
+ prog->reset_cmd = VM_SV_Cmd_Reset;
+ prog->error_cmd = Host_Error;
+
+ // TODO: add a requiredfuncs list (ask LH if this is necessary at all)
+ PRVM_LoadProgs( sv_progs.string, 0, NULL, REQFIELDS, reqfields );
+ SV_VM_FindEdictFieldOffsets();
+
+ PRVM_End;
+}
+
+void SV_VM_Begin(void)
+{
+ PRVM_Begin;
+ PRVM_SetProg( PRVM_SERVERPROG );
+
+ *prog->time = (float) sv.time;
+}
+
+void SV_VM_End(void)
+{
+ PRVM_End;
+}