diff --git a/quakec/csqctest/src/common/classes.qc b/quakec/csqctest/src/common/classes.qc index f4f87ad8d..0cbaf76d0 100644 --- a/quakec/csqctest/src/common/classes.qc +++ b/quakec/csqctest/src/common/classes.qc @@ -35,7 +35,7 @@ }; #else #ifdef CSQC - var void(float isnew) ParseEntityClass[ ] = { + nonstatic var void(float isnew) ParseEntityClass[ ] = { #define eclass(eid,func) func , eclasses #undef eclass diff --git a/quakec/csqctest/src/common/extensions.qc b/quakec/csqctest/src/common/extensions.qc index dbb37bc9e..f8a59b16b 100644 --- a/quakec/csqctest/src/common/extensions.qc +++ b/quakec/csqctest/src/common/extensions.qc @@ -90,6 +90,7 @@ string(string s) cvar_string = #448; #ifdef CSQC float(float modelindex, string skinname) skinforname = #237; float(string skinname) shaderforname = #238; +float(float midx, string framename) frameforname = #275; #endif //UNNAMED_FTE_CS_TAG_SUPPORT diff --git a/quakec/csqctest/src/common/makeallstatic.qc b/quakec/csqctest/src/common/makeallstatic.qc new file mode 100644 index 000000000..648b60b48 --- /dev/null +++ b/quakec/csqctest/src/common/makeallstatic.qc @@ -0,0 +1,12 @@ +#ifdef FTEQCC +// #define DOTHESTATICTHING +#endif + +#ifdef DOTHESTATICTHING + #pragma defaultstatic 1 +#else +#ifndef FTEQCC + #define static + #define nonstatic +#endif +#endif \ No newline at end of file diff --git a/quakec/csqctest/src/common/pmove.qc b/quakec/csqctest/src/common/pmove.qc index a822d5ef6..33749ba2a 100644 --- a/quakec/csqctest/src/common/pmove.qc +++ b/quakec/csqctest/src/common/pmove.qc @@ -1,27 +1,3 @@ - -float clientcommandframe; -float input_timelength; -vector input_angles; -vector input_movevalues; -float input_buttons; -float input_impulse; -//float input_lightlevel; -//float input_weapon; -//float input_servertime; - -float pmove_type; -vector pmove_org; -vector pmove_vel; -vector pmove_mins; -vector pmove_maxs; -float pmove_jump_held; -float pmove_waterjumptime; - -float movevars_friction; -float movevars_gravity; - -float movevars_stepheight = 22; - #ifdef OWNPLAYERPHYSICS void PMove_Move(vector dest) //move forwards (preferably on the level) (does step ups) diff --git a/quakec/csqctest/src/common/pmovedefs.qc b/quakec/csqctest/src/common/pmovedefs.qc new file mode 100644 index 000000000..1691cf593 --- /dev/null +++ b/quakec/csqctest/src/common/pmovedefs.qc @@ -0,0 +1,23 @@ +//This file contains the system globals for the default pmove code + +noref float input_timelength; +noref vector input_angles; +noref vector input_movevalues; +noref float input_buttons; +noref float input_impulse; +//float input_lightlevel; +//float input_weapon; +//float input_servertime; + +float pmove_type; +vector pmove_org; +vector pmove_vel; +vector pmove_mins; +vector pmove_maxs; +float pmove_jump_held; +float pmove_waterjumptime; + +float movevars_friction; +float movevars_gravity; + +const float movevars_stepheight = 22; \ No newline at end of file diff --git a/quakec/csqctest/src/cs/constants.qc b/quakec/csqctest/src/cs/constants.qc index 4c9c73dbd..af3b94d12 100644 --- a/quakec/csqctest/src/cs/constants.qc +++ b/quakec/csqctest/src/cs/constants.qc @@ -64,7 +64,13 @@ float INPUT_MOUSEMOVE = 2; #define STAT_ROCKETS 8 #define STAT_CELLS 9 #define STAT_ACTIVEWEAPON 10 //the one shown on the hud +#define STAT_TOTALSECRETS 11 +#define STAT_TOTALMONSTERS 12 +#define STAT_FOUNDSECRETS 13 +#define STAT_KILLEDMONSTERS 14 #define STAT_ITEMS 15 +#define STAT_VIEWHEIGHT 16 +#define STAT_VIEWZOOM 21 //DP extension //stats 32 onwards are filled by the csqc. diff --git a/quakec/csqctest/src/cs/csbuiltins.qc b/quakec/csqctest/src/cs/csbuiltins.qc index b38475442..93c3eb21d 100644 --- a/quakec/csqctest/src/cs/csbuiltins.qc +++ b/quakec/csqctest/src/cs/csbuiltins.qc @@ -1,6 +1,9 @@ //csqc only builtins. +float(string s) checkextension = #99; //this is core for csqc, but still an extension for ssqc + + void() clearscene = #300; // (EXT_CSQC) void(float mask) addentities = #301; // (EXT_CSQC) void(entity ent) addentity = #302; // (EXT_CSQC) @@ -39,7 +42,11 @@ string(float mdlindex) modelnameforindex = #334; // (EXT_CSQC) float(string effectname) particleeffectforname = #335; // (EXT_CSQC) #ifdef WORKINDP -void(entity ent, float effectnum, vector start, vector end) trailparticles = #336; // (EXT_CSQC), +void(entity ent, float effectnum, vector start, vector end) trailparticles_dp = #336; // (EXT_CSQC), +void(float effectnum, entity ent, vector start, vector end) trailparticles = +{ + trailparticles_dp(ent, effectnum, start, end); +}; #else void(float effectnum, entity ent, vector start, vector end) trailparticles = #336; // (EXT_CSQC), #endif diff --git a/quakec/csqctest/src/cs/defs.qc b/quakec/csqctest/src/cs/defs.qc index 0434d9bf3..589ea94f1 100644 --- a/quakec/csqctest/src/cs/defs.qc +++ b/quakec/csqctest/src/cs/defs.qc @@ -1,6 +1,9 @@ -float chasecam; -entity player_local; +float chasecam; //chasecam active +entity player_local; //handle to the local player entity +float isdp; //if we're running under DP +string levelname; +//q3playerm .entity headent; .entity torsoent; .entity legsent; @@ -8,7 +11,29 @@ entity player_local; .float modelnum; .float animnum; .float framechangetime; + +//player .float lerptime; +.void() removefunc; +.vector lastorg; +.vector lastvel; +.float haddied; +.float modelstyle; +.string oldskin; + +//the genders you can have. +//we're generous with three. +enum { + GENDER_NEUTER, + GENDER_MALE, + GENDER_FEMALE +}; + +// +.float ideal_yaw; +.float yaw_speed; +.float tag_index; + .float sveffects; //lower 4 is weapon, next is nopred, upper 3 is powerups #define SVE_INVIS 128 @@ -17,4 +42,29 @@ entity player_local; #define SVE_NOPRED 16 #define SVE_WEAPONSMASK 15 -.float gibbable; \ No newline at end of file +.float removetime; +.float gibbable; + +//q3playerm +float(string newmodelskin) Anim_SetModel; +void() Anim_Draw; +void() Anim_UnsetModel; +entity() Anim_DupModel; +float(string fname) Anim_ReadAnimationFile; +float() Anim_GetGender; +float(string skinname) Anim_GetHeadModelIndex; +float(string skinname) Anim_GetHeadSkinNumber; +vector(string skinname) Anim_GetHeadOffset; + +//prediction +void() Pred_PlayerUpdated; +void() Pred_UpdateLocalMovement; +vector vieworg; + +//menu +void(void(float, float, float, float) fnc) Menu_Activate; +void() Menu_Main; +void() Menu_Think; +var void(float event, float button, float mousex, float mousey) MenuEventFunc; + +void() Movetype_Bounce; \ No newline at end of file diff --git a/quakec/csqctest/src/cs/entrypoints.qc b/quakec/csqctest/src/cs/entrypoints.qc index 9a76db85c..4adc2a8ec 100644 --- a/quakec/csqctest/src/cs/entrypoints.qc +++ b/quakec/csqctest/src/cs/entrypoints.qc @@ -1,6 +1,86 @@ +void(string model, void(float isnew) updatefunc, float flags) deltalisten = #371; +void(float flags, float simtime) readserverentitystate = #369; +#define RSES_NOLERP 1 //only really for use on predicted player entities +#define RSES_AUTOROTATE 0 +#define RSES_NOROTATE 2 +#define RSES_AUTOTRAILS 0 +#define RSES_NOTRAILS 4 +#define RSES_AUTOLIGHTS 0 +#define RSES_NOLIGHTS 8 + +#ifdef WORKINDP + #define show_scoreboard sb_showscores +#endif + +float show_scoreboard; + +//check engine extensions, and give suitable warning +void() checkengineversion = +{ + if (checkextension("FTE_STRINGS")) + { + isdp = substring(" ", 0, -1) == ""; + if (isdp) + print("broken FTE_STRINGS support\n"); + } + else + print("no FTE_STRINGS support, this mod might crash... sorry\n"); +}; + + +//check compiler, and give suitable warnings (unfortunatly at run time) +float(float f) testfunc = +{ + return f; +} +float(float f1, float f2) testfunc2 = +{ + return f1+f2; +} +float testarray[2]; +void() checkcompilerversion = +{ + local entity testent; + + testent = spawn(); + testent.entnum = -5; + testent.owner = testent; + testent.owner.entnum += 5; + if (testent.entnum) + print("compiler failed on e.e.f += \n"); + remove(testent); + + testarray[0] = 5; + testarray[1] = 6; + + if (testfunc(5)+testfunc(6) != 11) + print("compiler failed on f()+f()\n"); + if (testfunc2(5, testfunc(6)) != 11) + print("compiler failed on f2(0,f1(1))\n"); + if (testfunc2(testfunc(5),testfunc(6)) != 11) + print("compiler failed on f2(f(),f())\n"); + if (testarray[0]+testarray[1] != 11) + print("compiler failed on a[0]+a[1]\n"); +}; + + void(float isnew) RefreshPlayer; + +void(float isnew) RefreshOther = +{ + self.drawmask = MASK_ENGINE; + setmodelindex(self, self.modelindex); + + if (self.entnum <= maxclients) + RefreshPlayer(isnew); + else if (self.colormap) + self.modelindex = 0; //don't show dead bodies, we do dying ourselves. +}; + + + float(string centertext) centerprinted = { //warning! @@ -49,10 +129,10 @@ void() regcommands = registercommand("-showteamscores"); registercommand("osgk"); - registercommand("cin_command"); - registercommand("cin_resize"); - registercommand("cin_mousemove"); - registercommand("cin_keypress"); + registercommand("osgk_command"); + registercommand("osgk_resize"); + registercommand("osgk_mousemove"); + registercommand("osgk_keypress"); }; float(string str) CSQC_ConsoleCommand = @@ -70,27 +150,29 @@ float(string str) CSQC_ConsoleCommand = case "randomskin": SelectRandomSkin(); break; - case "test": - test(); - break; case "+showscores": - case "-showscores": + show_scoreboard = 1; + return false; case "+showteamscores": + show_scoreboard = 2; + return false; + case "-showscores": case "-showteamscores": - break; + show_scoreboard = 0; + return false; case "osgk": Menu_OSGK(argv(1)); break; - case "cin_command": + case "osgk_command": gecko_navigate(argv(1), argv(2)); break; - case "cin_keypress": + case "osgk_keypress": gecko_keyevent(argv(1), stof(argv(2)), 2); break; - case "cin_resize": + case "osgk_resize": gecko_resize(argv(1), stof(argv(2)), stof(argv(3))); break; - case "cin_mousemove": + case "osgk_mousemove": gecko_mousemove(argv(1), stof(argv(2)), stof(argv(3))); break; default: @@ -101,11 +183,6 @@ float(string str) CSQC_ConsoleCommand = void() CSQC_Ent_Remove = //the ent disappeared on the server. { - if (self == player_local) - print("WARNING: Player disappeared!\n"); - -// print("csqc ", ftos(self.modelindex), "(", self.model, ") removed\n"); - if (self.removefunc) self.removefunc(); remove(self); @@ -148,11 +225,14 @@ void() drawloadingscreen = void() CSQC_Init = { + checkengineversion(); + checkcompilerversion(); + //set some cvars to their defaults, and create them at the same time if (cvar_string("cg_giblevel") == "") localcmd("set cg_giblevel 1\n"); if (cvar_string("cg_thirdPerson") == "") localcmd("set cg_thirdPerson 0\n"); if (cvar_string("cg_forceskin") == "") localcmd("set cg_forceskin \"\"\n"); - if (cvar_string("cg_hudtype") == "") localcmd("set cg_hudtype 0\n"); + if (cvar_string("cg_hudtype") == "") localcmd("set cg_hudtype 1\n"); if (cvar_string("cg_nopred") == "") localcmd("set cg_nopred 0\n"); if (cvar_string("v_viewheight") == "") localcmd("set v_viewheight 0\n");//normally an engine cvar in quakeworld. if (cvar_string("cg_nostep") == "") localcmd("set cg_nostep 0\n"); @@ -161,12 +241,20 @@ void() CSQC_Init = if (cvar_string("cg_noselfjumpsound") == "") localcmd("set cg_noselfjumpsound 0\n"); viewentity = spawn(); - viewentity.renderflags = RF_VIEWMODEL; + viewentity.renderflags = RF_VIEWMODEL|RF_DEPTHHACK; drawloadingscreen (); - ResetPlayerPrediction(); + Pred_ResetPlayerPrediction(); regcommands(); + +#ifndef FTEDEPENDANT + if (checkextension("EXT_CSQC_1")) +#endif + { +// deltalisten("*", RefreshOther, 0); //catch-all + deltalisten("progs/player.mdl", RefreshPlayer, RSES_NOLERP|RSES_NOROTATE); //animate players/player-corpses + } }; void(entity ent) CSQC_DrawViewModel = @@ -178,6 +266,16 @@ void(entity ent) CSQC_DrawViewModel = ent.fatness = 0; DoThatViewModelThing(ent); + +#ifdef WORKINDP + //DP doesn't support RF_VIEWMODEL + //so hack around that + ent.renderflags = RF_DEPTHHACK; //nope, not a view model, that just breaks things + ent.origin = vieworg; + ent.angles = input_angles; + ent.angles_x = -ent.angles_x; +#endif + addentity(ent); if (player_local.sveffects & SVE_QUAD) { @@ -193,21 +291,6 @@ void(entity ent) CSQC_DrawViewModel = } } -void(float isnew) CSQC_Delta_Update = -{ - self.drawmask = MASK_NORMAL; - setmodelindex(self, self.modelindex); -// if (isnew) -// { -// print("delt ", self.model, " updated at ", vtos(self.origin), "\n"); -// } - - if (self.entnum <= maxclients) - RefreshPlayer(isnew); - else if (self.colormap) - self.modelindex = 0; //don't show dead bodies, we do dying ourselves. -}; - //a bit of fun void() CSQC_Input_Frame = { @@ -228,33 +311,17 @@ void() CSQC_Delta_Remove = remove(self); }; -void(float flags, float simtime) readserverentitystate = #369; -#define RSES_AUTOLERP 0 -#define RSES_NOLERP 1 -#define RSES_AUTOROTATE 0 -#define RSES_NOROTATE 2 -#define RSES_AUTOTRAILS 0 -#define RSES_NOTRAILS 4 -#define RSES_AUTOLIGHTS 0 -#define RSES_NOLIGHTS 8 - void(float width, float height, float do2d) CSQC_UpdateView = { - float lagged; - float i; float hudtype = cvar("cg_hudtype"); chasecam = cvar("cg_thirdPerson"); if (getstati(STAT_HEALTH) <= 0) chasecam = 1; -#ifndef WORKINDP - readserverentitystate(RSES_AUTOLERP|RSES_AUTOROTATE|RSES_AUTOTRAILS|RSES_AUTOLIGHTS, 0); -#endif - clearscene(); - if (hudtype) + if (hudtype != 1) { setviewprop(VF_DRAWENGINESBAR, 0); } @@ -264,10 +331,15 @@ void(float width, float height, float do2d) CSQC_UpdateView = } setviewprop(VF_DRAWCROSSHAIR, 1); + //force fullscreen views (ignore viewsize). + setviewprop(VF_MIN, '0 0 0'); + setviewprop(VF_SIZE_X, width); + setviewprop(VF_SIZE_Y, height); + + addentities(MASK_NORMAL|MASK_ENGINE); + if (player_local) { - UpdateLocalMovement(); - setviewprop(VF_ORIGIN, vieworg); setviewprop(VF_ANGLES, view_angles); @@ -275,26 +347,22 @@ void(float width, float height, float do2d) CSQC_UpdateView = SetListener(vieworg, v_forward, v_right, v_up); if (!chasecam) + { CSQC_DrawViewModel(viewentity); + } + } + else + { + //engine didn't tell us about our player entity. that's not right... + addentities(MASK_ENGINEVIEWMODEL); } - - //force fullscreen views. - setviewprop(VF_MIN, '0 0 0'); - setviewprop(VF_SIZE_X, width); - setviewprop(VF_SIZE_Y, height); - -#ifdef WORKINDP - addentities(MASK_NORMAL|MASK_ENGINE); -#else - addentities(MASK_NORMAL); -#endif renderscene(); if (do2d) { if (hudtype) - Hud_Draw(hudtype, width, height); + Hud_Draw(hudtype, show_scoreboard, width, height); Menu_Think(); } diff --git a/quakec/csqctest/src/cs/fun/osgk.qc b/quakec/csqctest/src/cs/fun/osgk.qc index d12fc8439..ebb623090 100644 --- a/quakec/csqctest/src/cs/fun/osgk.qc +++ b/quakec/csqctest/src/cs/fun/osgk.qc @@ -2,8 +2,6 @@ string osgkname; void(float event, float button, float mousex, float mousey) OSGKMenuEvent = { - float f; - string str; if (event == ME_DRAW) { //nothing. @@ -31,7 +29,7 @@ void(float event, float button, float mousex, float mousey) OSGKMenuEvent = */}; -void(string posgkname) Menu_OSGK +nonstatic void(string posgkname) Menu_OSGK { if (osgkname) strunzone(osgkname); diff --git a/quakec/csqctest/src/cs/fun/skinchooser.qc b/quakec/csqctest/src/cs/fun/skinchooser.qc index cecacebad..0305a83f6 100644 --- a/quakec/csqctest/src/cs/fun/skinchooser.qc +++ b/quakec/csqctest/src/cs/fun/skinchooser.qc @@ -1,41 +1,29 @@ -var float c_modellist = -1; -var float c_skinlist = -1; +static var float c_modellist = -1; +static var float c_skinlist = -1; -float c_modelnum; -float c_skinnum; +static float c_modelnum; +static float c_skinnum; -string(float num) ModelForNum = +static string(float num) ModelForNum = { string str; float slashpos; str = search_getfilename(c_modellist, num); -#ifdef WORKINDP - str = substring(str, 15, strlen(str)-15); // models/players/ -#else str = substring(str, 15, -1); // models/players/ -#endif slashpos = strstrofs(str, "/"); return substring(str, 0, slashpos); } -string(float num) SkinForNum = +static string(float num) SkinForNum = { string str; float slashpos; str = search_getfilename(c_skinlist, num); -#ifdef WORKINDP - str = substring(str, 15, strlen(str)-15); // models/players/ -#else str = substring(str, 15, -1); // models/players/ -#endif slashpos = strstrofs(str, "/"); -#ifdef WORKINDP - return substring(str, slashpos+7, strlen(str)-slashpos-7-5); // /upper_ .skin-1 -#else return substring(str, slashpos+7, -6); // /upper_ .skin-1 -#endif } -void() CheckSkinNumber = +static void() CheckSkinNumber = { if (c_skinnum < 0) c_skinnum = search_getsize(c_skinlist)-1; @@ -43,7 +31,7 @@ void() CheckSkinNumber = c_skinnum = 0; }; -void() FindPlayerSkins = +static void() FindPlayerSkins = { string str; @@ -71,7 +59,7 @@ void() FindPlayerSkins = } }; -void() FindPlayerModels = +static void() FindPlayerModels = { if (c_modellist >= 0) search_end(c_modellist); @@ -82,10 +70,15 @@ void() FindPlayerModels = FindPlayerSkins(); }; -void() DrawSkinChooser = +static void() DrawSkinChooser = { string modname; string skinname; + if (c_skinlist < 0) + return; + if (c_modellist < 0) + return; + modname = ModelForNum(c_modelnum); skinname = SkinForNum(c_skinnum); cprint(modname, "/", skinname); @@ -93,9 +86,8 @@ void() DrawSkinChooser = chasecam = true; } -void(float event, float button, float mousex, float mousey) SkinChooserMenuEvent = +static void(float event, float button, float mousex, float mousey) SkinChooserMenuEvent = { - float f; string str; if (event == ME_DRAW) { @@ -152,7 +144,7 @@ void(float event, float button, float mousex, float mousey) SkinChooserMenuEvent }; -void() Menu_SkinChooser +nonstatic void() Menu_SkinChooser { c_modellist = -1; c_skinlist = -1; @@ -161,7 +153,7 @@ void() Menu_SkinChooser Menu_Activate(SkinChooserMenuEvent); }; -void() SelectRandomSkin = +nonstatic void() SelectRandomSkin = { local string str; diff --git a/quakec/csqctest/src/cs/fun/tetris.qc b/quakec/csqctest/src/cs/fun/tetris.qc index 1eeecd470..83eb88da3 100644 --- a/quakec/csqctest/src/cs/fun/tetris.qc +++ b/quakec/csqctest/src/cs/fun/tetris.qc @@ -4,8 +4,6 @@ Quake tetris, origionally created by FrikaC Ported to csqc by Spike, primarily for testing in a fun way. */ -vector tet_org; - float tetris_on, tet_time, tet_autodown, tet_old_keys, tet_keys; vector piece_pos; float piece_type, next_piece, tet_score, tet_lines; @@ -662,7 +660,7 @@ void(float event, float button, float mousex, float mousey) TetrisMenuEvent = tet_old_keys = tet_keys; }; -void() Menu_Tetris = +nonstatic void() Menu_Tetris = { tetris_on = 1; ResetTetris(); diff --git a/quakec/csqctest/src/cs/hlpm.qc b/quakec/csqctest/src/cs/hlpm.qc new file mode 100644 index 000000000..78b351490 --- /dev/null +++ b/quakec/csqctest/src/cs/hlpm.qc @@ -0,0 +1,130 @@ +#ifdef HLPMODELS + +#include "playerframes.inc" + +.float oldframe; + +#pragma noref 1 +//FTE_CSQC_BASEFRAME +.float basebone; +.float baseframe; +.float baseframe2; +.float baseframe1time; +.float baseframe2time; +.float subblendfrac; +.float baselerpfrac; + +//FTE_CSQC_HALFLIFE_MODELS +.float bonecontrol1, bonecontrol2, bonecontrol3, bonecontrol4; + +//DP_QC_WHICHPACK +string(string fname) whichpack = #503; + +#pragma noref 0 + +.float starttime; + +static void(string framename) ForceToAnim = +{ + float a, s; + float newframe; + + self.basebone = gettagindex(self, "Bip01 Spine"); //use this bone to split base/normal frames + + newframe = frameforname(self.modelindex, framename); + self.frame = newframe; + self.frame2 = newframe; + + newframe = frameforname(self.modelindex, "run2"); + self.baseframe = newframe; + self.baseframe2 = newframe; + self.baselerpfrac = 0; + + self.baseframe1time = time; + + if (self.velocity_x == 0 && self.velocity_y == 0) + { + a = 0; + s = 0; + } + else + { + a = self.angles_y - vectoyaw(self.velocity); + s = vlen(self.velocity); + if (s < 100) + a *= s/100; + } + s /= 400; + if (a < -180) + a += 360; + if (a > 180) + a -= 360; + + if (a > 120) + a = 120; + if (a < -120) + a = -120; + self.bonecontrol1 = self.bonecontrol2 = self.bonecontrol3 = self.bonecontrol4 = (a)/150;///4; + self.angles_y -= a; + + self.baseframe1time += (time - self.starttime)*s; + self.starttime = time; + + self.subblendfrac = self.angles_x*(1/15); + self.angles_x = 0; + + //halflife players were made for bigger maps. + self.scale = 52/72.0; + self.origin_z += 12; +}; + +void() updatesequences = +{ + if (self.frame == $nailatt1 || self.frame == $nailatt2 || + self.frame == $light1 || self.frame == $light2) + ForceToAnim ("ref_shoot_onehanded"); //these ones loop +// else if (random() < 0.005 && !(self.velocity_x || self.velocity_y) && (chasecam || self != player_local)) +// { //randomly taunt, when standing still, when not first-person (making the sounds is just confusing when first person) +// sexedsound(self, "taunt.wav"); +// ForceToAnim (TORSO_GESTURE); +// } + else if ((self.frame >= $axrun1 && self.frame <= $axrun6) || + (self.frame >= $axstnd1 && self.frame <= $axstnd12) || + (self.frame >= $axpain1 && self.frame <= $axpain6)) + ForceToAnim ("ref_aim_crowbar"); + else + ForceToAnim ("ref_aim_onehanded"); +} + +void() HLPM_Draw = +{ + setmodel(self, self.model); + updatesequences(); +}; + +float(string skinname) HLPM_SetModel = +{ + string mname = strcat("models/player/", skinname, "/", skinname, ".mdl"); + + //check to see if it exists (this is too slow for my liking really) + if (whichpack(mname) == "") + return false; + + setmodel(self, mname); + + self.oldframe = -1; + self.scale = 20/72.0; + + return true; +}; + +void() HLPM_UnsetModel = +{ + self.scale = 0; +}; + +entity() HLPM_DupModel = +{ + return spawn(); +}; +#endif diff --git a/quakec/csqctest/src/cs/hud.qc b/quakec/csqctest/src/cs/hud.qc index d0b3efeb7..9e052ecbe 100644 --- a/quakec/csqctest/src/cs/hud.qc +++ b/quakec/csqctest/src/cs/hud.qc @@ -119,6 +119,40 @@ void Hud_DrawWeaponWide(float num, vector pos) //for LG drawpic(pos, weaponnames[num], '48 16 0', '1 1 1', 1, 0); }; +string(float f, float chars, string lead) FormatFloat +{ + string s = ftos(f); + if (f < 10 && chars >= 3) + s = strcat(lead, lead, s); + else if (f < 10 && chars == 2) + s = strcat(lead, s); + else if (f < 100 && chars >= 3) + s = strcat(lead, s); + return s; +}; + +void() Hud_CoopScores_SBar = +{ + string s; + float secs; + float mins; + //When you press tab in single player/coop, you get some replacement info over the sbar + vector sbar = screensize_y * ' 0 1 0' - '0 24 0'; + drawpic(sbar, "scorebar", '320 24 0', '1 1 1', 0.333, 0); + + s = strcat("Monsters:", FormatFloat(getstati(STAT_KILLEDMONSTERS), 3, " "), "/", FormatFloat(getstati(STAT_TOTALMONSTERS), 3, " ")); + drawstring(sbar + '8 4', s, '8 8 8', '1 1 1', 1, 0); + s = strcat("Secrets :", FormatFloat(getstati(STAT_FOUNDSECRETS), 3, " "), "/", FormatFloat(getstati(STAT_TOTALSECRETS), 3, " ")); + drawstring(sbar + '8 12', s, '8 8 8', '1 1 1', 1, 0); + + mins = floor(time/60); + secs = floor(time - mins*60); + s = strcat("Time :", FormatFloat(mins, 3, " "), ":", FormatFloat(secs, 2, "0")); + drawstring(sbar + '184 4', s, '8 8 8', '1 1 1', 1, 0); + + drawstring(sbar + '232 12' - strlen(levelname)*'4 0', levelname, '8 8 8', '1 1 1', 1, 0); +}; + void Hud_DrawSBar(void) { vector sbar; @@ -243,7 +277,7 @@ void Hud_DrawQ3Number(vector pos, float value, vector colours) entity hud3ditem; -void Hud_Draw3dScene(vector topleft, vector size) +void Hud_Draw3dScene(vector topleft, vector sz) { clearscene(); @@ -251,7 +285,7 @@ void Hud_Draw3dScene(vector topleft, vector size) setviewprop(VF_DRAWENGINESBAR, 0); setviewprop(VF_DRAWCROSSHAIR, 0); setviewprop(VF_MIN, topleft); - setviewprop(VF_SIZE, size); + setviewprop(VF_SIZE, sz); setviewprop(VF_FOV, '30 30'); setviewprop(VF_ORIGIN, '0 0 0'); setviewprop(VF_ANGLES, '0 0 0'); @@ -260,7 +294,7 @@ void Hud_Draw3dScene(vector topleft, vector size) renderscene(); } -void Hud_Draw3dItem(vector topleft, vector size, string modelname, vector org, vector ang) +void Hud_Draw3dItem(vector topleft, vector sz, string modelname, vector org, vector ang) { if (!hud3ditem) hud3ditem = spawn(); @@ -269,10 +303,10 @@ void Hud_Draw3dItem(vector topleft, vector size, string modelname, vector org, v hud3ditem.angles = ang; setmodel(hud3ditem, modelname); - Hud_Draw3dScene(topleft, size); + Hud_Draw3dScene(topleft, sz); } -void Hud_DrawQ3Head(vector topleft, vector size, string skinname, vector ang) +void Hud_DrawQ3Head(vector topleft, vector sz, string skinname, vector ang) { float headmodelindex; vector headoffset; @@ -305,7 +339,7 @@ void Hud_DrawQ3Head(vector topleft, vector size, string skinname, vector ang) hud3ditem.origin = org; hud3ditem.angles = ang; - Hud_Draw3dScene(topleft, size); + Hud_Draw3dScene(topleft, sz); hud3ditem.skin = 0; } @@ -323,9 +357,8 @@ void Hud_Q3(void) Hud_DrawQ3Number(sbar+'248 0 0', getstati(STAT_AMMO), '1 1 1'); } -void Hud_Draw(float hudtype, float width, float height) +nonstatic void Hud_Draw(float hudtype, float scoreboard, float width, float height) { - vector sbar; screensize_x = width; screensize_y = height; screensize_z = 0; @@ -334,14 +367,21 @@ void Hud_Draw(float hudtype, float width, float height) items2 = getstatbits(STAT_ITEMS, 23, 9); //if hudtype == 0 then the engine already drew it. - if (hudtype == 2) + if (hudtype == 3) { Hud_Q3(); return; } - else + else if (hudtype == 2) { - Hud_DrawSBar(); + if (scoreboard) + { + Hud_CoopScores_SBar(); + } + else + { + Hud_DrawSBar(); + } Hud_DrawIBar(); } }; diff --git a/quakec/csqctest/src/cs/keys.qc b/quakec/csqctest/src/cs/keys.qc index 6081a8d4d..da2234dd6 100644 --- a/quakec/csqctest/src/cs/keys.qc +++ b/quakec/csqctest/src/cs/keys.qc @@ -110,5 +110,5 @@ float K_MOUSE8 = 519; float K_MOUSE9 = 520; float K_MOUSE10 = 521; -float K_MWHEELDOWN = K_MOUSE4; -float K_MWHEELUP = K_MOUSE5; +const noref float K_MWHEELDOWN = K_MOUSE4; +const noref float K_MWHEELUP = K_MOUSE5; diff --git a/quakec/csqctest/src/cs/map.qc b/quakec/csqctest/src/cs/map.qc index a38d14be9..3a1312e48 100644 --- a/quakec/csqctest/src/cs/map.qc +++ b/quakec/csqctest/src/cs/map.qc @@ -1,19 +1,87 @@ .string target; .string targetname; +.vector mangle; +.string message; string() getentitytoken = #355; +//fixme: I want an engine solution +entity triggerchain; +.entity nexttrigger; +void() pmovetouchtriggers = +{ + vector amin = pmove_org+pmove_mins; + vector amax = pmove_org+pmove_maxs; + vector emin; + vector emax; + entity t; + entity oself = self; + for (self = triggerchain; self; self = self.nexttrigger) + { + emin = self.origin+self.mins; + if (emin_x > amax_x) + continue; + if (emin_y > amax_y) + continue; + if (emin_z > amax_z) + continue; + + emax = self.origin+self.maxs; + if (emax_x < amin_x) + continue; + if (emax_y < amin_y) + continue; + if (emax_z < amin_z) + continue; + + if (self.classname == "trigger_teleport") + { + t = find(world, targetname, self.target); + if (t) + { + makevectors(t.angles); + Pred_Predict_Teleport(t.origin + '0 0 27', v_forward*300, t.angles); + } + //maybe they use a mod that uses some other choice pattern + } + if (self.classname == "trigger_push") + { + //fixme: add support for trigger_push + } + } + + self = oself; +} + void() spawn_trigger_teleport = { + self.solid = SOLID_NOT;//SOLID_TRIGGER; setmodel(self, self.model); self.model = ""; - print("teleport at ", vtos(self.mins), vtos(self.maxs), " to ", self.target, "\n"); + self.nexttrigger = triggerchain; + triggerchain = self; }; void() spawn_info_teleport_destination = { - print("teleport_dest at ", vtos(self.origin), " called ", self.targetname, "\n"); +}; + +void() spawn_trigger_push = +{ + self.solid = SOLID_NOT;//SOLID_TRIGGER; + setmodel(self, self.model); + self.model = ""; + + self.nexttrigger = triggerchain; + triggerchain = self; +}; + +void() spawn_worldspawn = +{ + levelname = self.message; + mapname = "that was the mapname, dumbass"; + remove(self); }; float() parsenewmapentity = @@ -23,7 +91,6 @@ float() parsenewmapentity = local void() spawnfunc; nent = spawn(); -// print("new entity\n"); while (1) { field = getentitytoken(); @@ -38,7 +105,16 @@ float() parsenewmapentity = { self = nent; spawnfunc(); + return true; } + +// print("ignoring ", nent.classname, "\n"); + //I don't know what you are, go away. + if (nent.classname!="") + strunzone(nent.classname); + if (nent.message!="") + strunzone(nent.message); + remove(nent); return true; } @@ -54,12 +130,16 @@ float() parsenewmapentity = spawnfunc = spawn_trigger_teleport; if (value == "info_teleport_destination") spawnfunc = spawn_info_teleport_destination; - nent.classname = value; + if (value == "trigger_push") + spawnfunc = spawn_trigger_push; + if (value == "worldspawn") + spawnfunc = spawn_worldspawn; + nent.classname = strzone(value); } else if (field == "targetname") - nent.targetname = value; + nent.targetname = strzone(value); else if (field == "target") - nent.target = value; + nent.target = strzone(value); else if (field == "origin") nent.origin = stov(value); else if (field == "angles") @@ -70,8 +150,12 @@ float() parsenewmapentity = nent.angles_y = stof(value); nent.angles_z = 0; } + else if (field == "mangle") + nent.angles = stov(value); else if (field == "model") nent.model = value; + else if (field == "message") + nent.message = strzone(value); /* else if (field == "light"); else if (field == "mangle"); else if (field == "killtarget"); @@ -81,7 +165,6 @@ float() parsenewmapentity = else if (field == "count"); else if (field == "dmg"); else if (field == "delay"); - else if (field == "message"); else if (field == "worldtype"); else if (field == "sounds"); else if (field == "map"); diff --git a/quakec/csqctest/src/cs/menu.qc b/quakec/csqctest/src/cs/menu.qc index fa38db7e5..513e7cdc8 100644 --- a/quakec/csqctest/src/cs/menu.qc +++ b/quakec/csqctest/src/cs/menu.qc @@ -7,15 +7,13 @@ enum { ME_DRAW = 200 }; -var void(float event, float button, float mousex, float mousey) MenuEventFunc = __NULL__; - -void(void(float, float, float, float) fnc) Menu_Activate = +nonstatic void(void(float, float, float, float) fnc) Menu_Activate = { inmenu = TRUE; MenuEventFunc = fnc; }; -vector mousepos; +noref vector mousepos; //z is not set float (float event, float parama, float paramb) CSQC_InputEvent = { if (!inmenu) @@ -40,7 +38,7 @@ float (float event, float parama, float paramb) CSQC_InputEvent = return true; }; -void() Menu_Think = +nonstatic void() Menu_Think = { if (!inmenu) return; @@ -51,7 +49,7 @@ void() Menu_Think = }; //We don't have a main menu for the csqc yet, so just pop it instead, so submenus can close properly. -void() Menu_Main = +nonstatic void() Menu_Main = { inmenu = FALSE; }; diff --git a/quakec/csqctest/src/cs/movetypes.qc b/quakec/csqctest/src/cs/movetypes.qc index 07735c76f..e6a48a008 100644 --- a/quakec/csqctest/src/cs/movetypes.qc +++ b/quakec/csqctest/src/cs/movetypes.qc @@ -75,7 +75,7 @@ void(vector end) PushSelf = }; //MOVETYPE_BOUNCE and MOVETYPE_TOSS -void() BounceProject = +nonstatic void() Movetype_Bounce = { local vector dest; local float td; @@ -120,7 +120,7 @@ void() BounceProject = setorigin(self, self.origin); }; -void() WalkProject = +void() Movetype_Walk = { float tl, td; RunThink(); @@ -142,7 +142,7 @@ void() WalkProject = setorigin(self, self.origin); }; -void() NoclipProject = +void() Movetype_Noclip = { float td; RunThink(); @@ -154,7 +154,7 @@ void() NoclipProject = self.origin += self.velocity*td; }; -void() NomoveProject = +void() Movetype_Nomove = { RunThink(); }; \ No newline at end of file diff --git a/quakec/csqctest/src/cs/player.qc b/quakec/csqctest/src/cs/player.qc index 1ccefd438..ed5a3102b 100644 --- a/quakec/csqctest/src/cs/player.qc +++ b/quakec/csqctest/src/cs/player.qc @@ -1,250 +1,202 @@ -// -// running -// -$frame axrun1 axrun2 axrun3 axrun4 axrun5 axrun6 +/* +this file handles the local player, and marshalling between the different sorts of player models. -$frame rockrun1 rockrun2 rockrun3 rockrun4 rockrun5 rockrun6 +RefreshPlayer: Called from the engine each time a player (ent with player.mdl) is about to be drawn +ParsePlayer: Called from CSQC_Ent_Parse for csqc protocol ents +*/ -// -// standing -// -$frame stand1 stand2 stand3 stand4 stand5 +#include "playerframes.inc" -$frame axstnd1 axstnd2 axstnd3 axstnd4 axstnd5 axstnd6 -$frame axstnd7 axstnd8 axstnd9 axstnd10 axstnd11 axstnd12 +static void() RemovePlayer; - -// -// pain -// -$frame axpain1 axpain2 axpain3 axpain4 axpain5 axpain6 - -$frame pain1 pain2 pain3 pain4 pain5 pain6 - - -// -// death -// - -$frame axdeth1 axdeth2 axdeth3 axdeth4 axdeth5 axdeth6 -$frame axdeth7 axdeth8 axdeth9 - -$frame deatha1 deatha2 deatha3 deatha4 deatha5 deatha6 deatha7 deatha8 -$frame deatha9 deatha10 deatha11 - -$frame deathb1 deathb2 deathb3 deathb4 deathb5 deathb6 deathb7 deathb8 -$frame deathb9 - -$frame deathc1 deathc2 deathc3 deathc4 deathc5 deathc6 deathc7 deathc8 -$frame deathc9 deathc10 deathc11 deathc12 deathc13 deathc14 deathc15 - -$frame deathd1 deathd2 deathd3 deathd4 deathd5 deathd6 deathd7 -$frame deathd8 deathd9 - -$frame deathe1 deathe2 deathe3 deathe4 deathe5 deathe6 deathe7 -$frame deathe8 deathe9 - -// -// attacks -// -$frame nailatt1 nailatt2 - -$frame light1 light2 - -$frame rockatt1 rockatt2 rockatt3 rockatt4 rockatt5 rockatt6 - -$frame shotatt1 shotatt2 shotatt3 shotatt4 shotatt5 shotatt6 - -$frame axatt1 axatt2 axatt3 axatt4 axatt5 axatt6 - -$frame axattb1 axattb2 axattb3 axattb4 axattb5 axattb6 - -$frame axattc1 axattc2 axattc3 axattc4 axattc5 axattc6 - -$frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6 - -#define ERRORTIME 20 -#define STEPTIME 10 - -.vector lastorg; -.vector lastvel; -.float haddied; - -vector player_org, vieworg; -vector player_vel; -float player_jump_held; -float player_sequence; -float player_steptime; -float player_step; -entity player_local; //refers to the local player -float player_localentnum; -float recframe; - -vector pmove_error; -float pmove_errortime; -float pmove_step; -float pmove_steptime; - -.void() removefunc; - -float pmoveframe; -void() ResetPlayerPrediction = +enum { -//reset the pmove to lerp from the new position - pmove_org = player_org; - pmove_vel = player_vel; - pmoveframe = player_sequence+1; //the recieved frame has the move already done (server side) - pmove_jump_held = player_jump_held; - pmove_steptime = player_steptime; - pmove_step = player_step; - - if (pmoveframe < clientcommandframe-128) - pmoveframe = clientcommandframe-128; //avoid an infinate loop - -//print("reset, porg is ", ftos(pmove_org_z), "\n"); -}; - -void(float endframe) RunMovement = -{ - float oz; - - if (servercommandframe >= player_sequence+63) - { - //we're meant to be updating the player faster than this - //hopefully its just that we're throttled... - player_sequence = servercommandframe-63; - - return; - } - - oz = pmove_org_z; -ResetPlayerPrediction (); - if (getstati(STAT_HEALTH) <= 0) - { - pmoveframe = clientcommandframe; - //just update the angles - if (!getinputstate(pmoveframe-1)) - { - } - return; //dead, so don't run prediction. :D - } - - if (cvar("cg_nopred") || cvar("cl_nopred")) - { - pmoveframe = clientcommandframe; - //just update the angles - if (!getinputstate(pmoveframe-1)) - { - } - return; - } -//print("start, porg is ", ftos(pmove_org_z), "\n"); - while(pmoveframe < endframe) - { - if (!getinputstate(pmoveframe)) - { -#ifndef WORKINDP - break; + MF_BAD, +#ifdef MD3PMODELS + MF_QUAKE3, #endif - } - runstandardplayerphysics(); - pmoveframe++; - } -//print(" ran, porg is ", ftos(pmove_org_z), "\n"); - - if (pmove_org_z > oz+8 && pmove_org_z < oz+24 && pmove_vel_z == 0) - { - //evaluate out the remaining old step - if (pmove_steptime - time > 0) - pmove_step = (pmove_steptime - time)*STEPTIME*pmove_step; - else - pmove_step = 0; - - //work out the new step - pmove_step += (oz-pmove_org_z); - pmove_steptime = time + 1/STEPTIME; - } - - //add in anything that was applied after (for low packet rate protocols) - input_angles = view_angles; +#ifdef HLPMODELS + MF_HLPM, +#endif + MF_QUAKE }; -void() UpdateLocalMovement = -{ - local float viewheight; +#ifdef NOEXTENSIONS //FRIK_FILE is an extension still, unfortunatly. but hey, the model code depends upon it more +#define strunzone(s) //so really we can get away with this for this module +#define strzone(s) "" +#endif - RunMovement(clientcommandframe); - - //allow the user to move the viewheight down 6 units so it's at +16, where projectiles come from. - viewheight = cvar("v_viewheight"); - if (viewheight < -7) - viewheight = -7; - if (viewheight > 7) - viewheight = 7; - - vieworg = pmove_org; //the default view height - vieworg_z += 22 + viewheight; - - //correct the view position to compensate for any errors, slowly over time, 0.1 seconds. - if (pmove_errortime - time > 0) - vieworg += (pmove_errortime - time)*ERRORTIME * pmove_error; - - if (!cvar("cg_nostep")) - if (pmove_steptime - time > 0) - vieworg_z += (pmove_steptime - time)*STEPTIME * pmove_step; - - if (chasecam) - { - makevectors(input_angles); - traceline(pmove_org, vieworg - v_forward * 72+v_up*32, FALSE, self); - vieworg = trace_endpos + v_forward*8; - } -}; - -.string oldskin; -void() RemovePlayer; - -void() Player_Interpolate = +static void() Player_Interpolate = { //do some frame interpolation. - if (self.modelnum != -1 && self.model!="") - Anim_Draw(); - else + if (self.entnum == player_localentnum) { - self.lerpfrac = 1-(time-self.lerptime)*10; + Pred_UpdateLocalMovement(); + self.origin = pmove_org; + self.angles = input_angles; + self.angles_x = self.angles_x * -0.3333; + } + + switch(self.modelstyle) + { +#ifdef MD3PMODELS + case MF_QUAKE3: + Anim_Draw(); + break; +#endif +#ifdef HLPMODELS + case MF_HLPM: + HLPM_Draw(); + break; +#endif + default: + if (self.lerptime) + self.lerpfrac = 1-(time-self.lerptime)*10; if (chasecam || self.entnum != player_localentnum) self.renderflags = 0; else self.renderflags = RF_EXTERNALMODEL; +#ifdef POWERUP_SHELLS + if (!isdp) + { + if (self.sveffects & SVE_INVIS) + self.forceshader = shaderforname("powerups/invisibility"); + else + self.forceshader = 0; + + self.fatness = 0; + + if (!(self.sveffects & SVE_INVIS)) + { + if (self.sveffects & SVE_QUAD) + { + addentity(self); + + self.fatness = -2; + self.forceshader = shaderforname("powerups/quad"); + } + if (self.sveffects & SVE_GOD) + { + addentity(self); + + self.fatness = -2.8; + self.forceshader = shaderforname("powerups/regen"); + } + } + break; + } +#endif if (self.sveffects & SVE_INVIS) - self.forceshader = shaderforname("powerups/invisibility"); + setmodel(self, "progs/eyes.mdl"); else - self.forceshader = 0; - self.fatness = 0; - - if (self.sveffects & SVE_QUAD) - { - addentity(self); - - self.fatness = -2; - self.forceshader = shaderforname("powerups/quad"); - } - if (self.sveffects & SVE_GOD) - { - addentity(self); - - self.fatness = -2.8; - self.forceshader = shaderforname("powerups/regen"); - } + setmodel(self, "progs/player.mdl"); + break; } }; -void() BounceProject; -.float removetime; +static void(float g) Player_SetLocalInfoGender = +{ + if (player_local == self) + { + switch(g) + { + case GENDER_FEMALE: + localcmd("setinfo s f\n"); + break; + case GENDER_MALE: + localcmd("setinfo s \"\"\n"); + break; + default: + case GENDER_NEUTER: + localcmd("setinfo s n\n"); + break; + } + } +} + +static void() Player_SetQ1Model = +{ + self.modelstyle = MF_QUAKE; + + Player_SetLocalInfoGender(GENDER_MALE); +} + +#ifdef MD3PMODELS +static void(string skinname) Player_SetQ3Model = +{ + if (!Anim_SetModel(skinname)) + { + Anim_UnsetModel(); + return; + } + Player_SetLocalInfoGender(Anim_GetGender()); + self.modelstyle = MF_QUAKE3; +}; +#endif + +#ifdef HLPMODELS +static void(string skinname) Player_SetHLModel = +{ + if (!HLPM_SetModel(skinname)) + { + HLPM_UnsetModel(); + return; + } + Player_SetLocalInfoGender(GENDER_MALE); + self.modelstyle = MF_HLPM; +}; +#endif + +static void() Player_UnsetModel = +{ + switch(self.modelstyle) + { +#ifdef MD3PMODELS + case MF_QUAKE3: + Anim_UnsetModel(); + break; +#endif +#ifdef HLPMODELS + case MF_HLPM: + HLPM_UnsetModel(); + break; +#endif + default: + //nothing to do + break; + } + self.modelstyle = MF_BAD; + setmodel(self, ""); +}; + +static entity() Player_DupModel = +{ + local entity e; + + switch(self.modelstyle) + { +#ifdef MD3PMODELS + case MF_QUAKE3: + e = Anim_DupModel(); + break; +#endif +#ifdef HLPMODELS + case MF_HLPM: + e = HLPM_DupModel(); + break; +#endif + default: + e = spawn(); + break; + } + e.modelstyle = self.modelstyle; + return e; +}; + .float starttime; .float oldframe; -void() bodythink = +static void() bodythink = { local float final; if (self.frame >= $axdeth1 && self.frame <= $axdeth9) @@ -267,29 +219,29 @@ void() bodythink = self.nextthink = time + 0.1; }; -void() DeadBodyPredraw = +static void() DeadBodyPredraw = { float ftime; ftime = time - self.starttime; if (self.removetime < time) { - Anim_UnsetModel(); + Player_UnsetModel(); remove(self); return; } - BounceProject(); + Movetype_Bounce(); Player_Interpolate(); self.origin_z -= ftime*0.5; }; -void() JustRessed = +static void() JustRessed = { local entity e; - e = Anim_DupModel(); + e = Player_DupModel(); e.frame = self.oldframe; //and stay dead! e.frame2 = self.oldframe; //and stay dead! setmodel(e, "progs/player.mdl"); @@ -297,6 +249,7 @@ void() JustRessed = e.velocity = self.lastvel; e.predraw = DeadBodyPredraw; e.removetime = time + 30; + e.lerptime = time; e.gibbable = GIB_PLAYER; e.solid = SOLID_TRIGGER; @@ -310,68 +263,21 @@ void() JustRessed = e.drawmask = self.drawmask; }; -void() PlayerUpdated = -{ - local float noerror; - local vector o; - - noerror = cvar("cg_noerror"); - - //reset the prediction to last-known-good state - ResetPlayerPrediction(); - RunMovement(servercommandframe+1); - player_jump_held = pmove_jump_held; - player_step = pmove_step; - player_steptime = pmove_steptime; - - player_org = self.origin; - player_vel = self.velocity; - pmove_mins = self.mins; - pmove_maxs = self.maxs; - player_sequence = servercommandframe; - - if (noerror) - { - pmove_error = '0 0 0'; - pmove_errortime = time; - - ResetPlayerPrediction(); - } - else - { - RunMovement(clientcommandframe); //make sure we're up to date - o = pmove_org; //save off the old for the teleport check below. - - //reset it, then update to now to guage how much our previous prediction was incorrect by - ResetPlayerPrediction(); - RunMovement(clientcommandframe); - - if (vlen(o - pmove_org) > 64) - {//teleport - pmove_error = '0 0 0'; - pmove_errortime = time; - } - else - { //figure out the error ammount, and lerp back to it, without forgetting about any current inaccuracies. - pmove_error = (pmove_errortime - time)*ERRORTIME * pmove_error + (o - pmove_org); - if (vlen(pmove_error) < 1) - pmove_error = '0 0 0'; - pmove_errortime = time + 1/ERRORTIME; - } - } -}; - -void() RemovePlayer = +static void() RemovePlayer = { + if (player_local == self) + player_local = world; + if (self.haddied) { JustRessed(); self.haddied = false; } + Player_UnsetModel(); + strunzone(self.oldskin); self.oldskin = ""; - Anim_UnsetModel(); self.predraw = __NULL__; }; @@ -409,38 +315,52 @@ void(float isnew) RefreshPlayer = player_local = self; } - self.model = "progs/player.mdl"; + self.modelstyle = MF_BAD; + self.oldskin = strzone(""); - Anim_UnsetModel(); self.drawmask = MASK_NORMAL; self.removefunc = RemovePlayer; } - newskin = cvar_string("cg_forceskin"); - if (newskin == "") - newskin = getplayerkeyvalue(self.entnum-1, "skin"); - if (newskin != self.oldskin) + if (self.sveffects & SVE_INVIS) { - strunzone(self.oldskin); - self.oldskin = strzone(newskin); - if (!Anim_SetModel(self.oldskin)) - { Anim_UnsetModel(); - } -/* - switch(Anim_GetGender()) + if (self.modelstyle != MF_QUAKE) { - case GENDER_FEMALE: - localcmd("setinfo sex f\n"); - break; - case GENDER_MALE: - localcmd("setinfo sex m\n"); - break; - case GENDER_NEUTER: - localcmd("setinfo sex n\n"); - break; + Player_UnsetModel(); + Player_SetQ1Model(); //every model uses eyes + } + } + else + { + newskin = cvar_string("cg_forceskin"); + if (newskin == "") + newskin = getplayerkeyvalue(self.entnum-1, "model"); + if (newskin == "") + newskin = getplayerkeyvalue(self.entnum-1, "skin"); + if (newskin != self.oldskin) + { + Player_UnsetModel(); + + strunzone(self.oldskin); + self.oldskin = strzone(newskin); + } + + if (self.modelstyle == MF_BAD) + { + newskin = self.oldskin; + +#ifdef MD3PMODELS + if (self.modelstyle == MF_BAD && newskin != "") + Player_SetHLModel(newskin); +#endif +#ifdef HLPMODELS + if (self.modelstyle == MF_BAD && newskin != "") + Player_SetQ3Model(newskin); +#endif + if (self.modelstyle == MF_BAD) + Player_SetQ1Model(); } -*/ } setsize(self, VEC_HULL_MIN, VEC_HULL_MAX); @@ -448,13 +368,15 @@ void(float isnew) RefreshPlayer = self.oldframe = self.frame; if (player_local != self) + { return; + } - PlayerUpdated(); + Pred_PlayerUpdated(); }; //this is sent after the server has run our movement command. -void(float isnew) ParsePlayer = +nonstatic void(float isnew) ParsePlayer = { local float f; @@ -472,9 +394,9 @@ void(float isnew) ParsePlayer = self.origin_x = readcoord(); self.origin_y = readcoord(); self.origin_z = readcoord(); - self.velocity_x = readshort()/64; - self.velocity_y = readshort()/64; - self.velocity_z = readshort()/64; + self.velocity_x = readshort(); + self.velocity_y = readshort(); + self.velocity_z = readshort(); self.colormap = self.entnum; self.sveffects = readbyte(); @@ -482,3 +404,7 @@ void(float isnew) ParsePlayer = RefreshPlayer(isnew); }; +#ifdef NOEXTENSIONS +#undef strunzone +#undef strzone +#endif diff --git a/quakec/csqctest/src/cs/playerframes.inc b/quakec/csqctest/src/cs/playerframes.inc new file mode 100644 index 000000000..236fc6134 --- /dev/null +++ b/quakec/csqctest/src/cs/playerframes.inc @@ -0,0 +1,65 @@ + +// +// running +// +$frame axrun1 axrun2 axrun3 axrun4 axrun5 axrun6 + +$frame rockrun1 rockrun2 rockrun3 rockrun4 rockrun5 rockrun6 + +// +// standing +// +$frame stand1 stand2 stand3 stand4 stand5 + +$frame axstnd1 axstnd2 axstnd3 axstnd4 axstnd5 axstnd6 +$frame axstnd7 axstnd8 axstnd9 axstnd10 axstnd11 axstnd12 + + +// +// pain +// +$frame axpain1 axpain2 axpain3 axpain4 axpain5 axpain6 + +$frame pain1 pain2 pain3 pain4 pain5 pain6 + + +// +// death +// + +$frame axdeth1 axdeth2 axdeth3 axdeth4 axdeth5 axdeth6 +$frame axdeth7 axdeth8 axdeth9 + +$frame deatha1 deatha2 deatha3 deatha4 deatha5 deatha6 deatha7 deatha8 +$frame deatha9 deatha10 deatha11 + +$frame deathb1 deathb2 deathb3 deathb4 deathb5 deathb6 deathb7 deathb8 +$frame deathb9 + +$frame deathc1 deathc2 deathc3 deathc4 deathc5 deathc6 deathc7 deathc8 +$frame deathc9 deathc10 deathc11 deathc12 deathc13 deathc14 deathc15 + +$frame deathd1 deathd2 deathd3 deathd4 deathd5 deathd6 deathd7 +$frame deathd8 deathd9 + +$frame deathe1 deathe2 deathe3 deathe4 deathe5 deathe6 deathe7 +$frame deathe8 deathe9 + +// +// attacks +// +$frame nailatt1 nailatt2 + +$frame light1 light2 + +$frame rockatt1 rockatt2 rockatt3 rockatt4 rockatt5 rockatt6 + +$frame shotatt1 shotatt2 shotatt3 shotatt4 shotatt5 shotatt6 + +$frame axatt1 axatt2 axatt3 axatt4 axatt5 axatt6 + +$frame axattb1 axattb2 axattb3 axattb4 axattb5 axattb6 + +$frame axattc1 axattc2 axattc3 axattc4 axattc5 axattc6 + +$frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6 diff --git a/quakec/csqctest/src/cs/prediction.qc b/quakec/csqctest/src/cs/prediction.qc new file mode 100644 index 000000000..ba3b18a58 --- /dev/null +++ b/quakec/csqctest/src/cs/prediction.qc @@ -0,0 +1,219 @@ +/* +UpdateLocalMovement: runs the local prediction (called from player.qc - local players are drawn for mirrors etc) + out: vieworg (view origin, with chasecam/viewheight added) + out: pmove_org (raw player ent origin) + +PlayerUpdated: updates internal state, called from player.qc any time we got an update from the server. + in: self (the player ent origin/velocity/mins/maxs) + +ResetPlayerPrediction: call if you broke the special pmove globals +*/ + +#define ERRORTIME 20 +#define STEPTIME 8 + +vector player_org; +vector player_vel; +float player_jump_held; +float player_sequence; +float player_steptime; +float player_step; + +vector pmove_error; +float pmove_errortime; + +float pmove_step; +float pmove_steptime; +float pmove_step_oldz; + +void() pmovetouchtriggers; + +float pmoveframe; +nonstatic void() Pred_ResetPlayerPrediction = +{ +//reset the pmove to lerp from the new position + pmove_org = player_org; + pmove_vel = player_vel; + pmoveframe = player_sequence+1; //+1 because the recieved frame has the move already done (server side) + pmove_jump_held = player_jump_held; + + if (pmoveframe < clientcommandframe-128) + pmoveframe = clientcommandframe-128; //avoid an infinate loop +}; + +//called from map.qc when a teleport trigger was predicted to be touched. +void(vector newteleorg, vector newtelevel, vector newteleang) Pred_Predict_Teleport = +{ + float teleframe; + teleframe = pmoveframe; + + //if this is the first client frame that shows us moving into the teleporter + if (teleframe == clientcommandframe-1) + { + //update the client's view angles + setviewprop(33, newteleang); + view_angles = newteleang; + } + pmove_org = newteleorg; + pmove_vel = newtelevel; + input_angles = newteleang; +}; + +void(float endframe) Pred_RunMovement; + +nonstatic void() Pred_PlayerUpdated = +{ + local float noerror; + local vector o; + + noerror = cvar("cg_noerror"); + + //reset the prediction to last-known-good state + Pred_ResetPlayerPrediction(); + Pred_RunMovement(servercommandframe+1); + player_jump_held = pmove_jump_held; + player_step = pmove_step; + player_steptime = pmove_steptime; + + //pull out the new values + player_org = self.origin; + player_vel = self.velocity; + pmove_mins = self.mins; + pmove_maxs = self.maxs; + player_sequence = servercommandframe; + + if (noerror) + { + pmove_error = '0 0 0'; + pmove_errortime = time; + + Pred_ResetPlayerPrediction(); + } + else + { + Pred_RunMovement(clientcommandframe); //make sure we're up to date + o = pmove_org; //save off the old for the teleport check below. + + //reset it, then update to now to guage how much our previous prediction was incorrect by + Pred_ResetPlayerPrediction(); + Pred_RunMovement(clientcommandframe); + + if (vlen(o - pmove_org) > 64) + {//teleport + pmove_error = '0 0 0'; + pmove_errortime = time; + } + else + { //figure out the error ammount, and lerp back to it, without forgetting about any current inaccuracies. + pmove_error = (pmove_errortime - time)*ERRORTIME * pmove_error + (o - pmove_org); + if (vlen(pmove_error) < 1) + pmove_error = '0 0 0'; + pmove_errortime = time + 1/ERRORTIME; + } + } +}; + +void(float endframe) Pred_RunMovement = +{ + if (servercommandframe >= player_sequence+63) + { + //we're meant to be updating the player faster than this + //hopefully its just that we're throttled... + + //you can comment out this block and the player will continue to be predicted locally. But its best to freeze them + + player_sequence = servercommandframe-63; + + return; + } + +#ifdef WORKINDP + //DP handily corrupts this for us, so waste some more cpu cycles to compensate + if (isdp) + Pred_ResetPlayerPrediction(); +#endif + + if (getstati(STAT_HEALTH) <= 0) + { + pmoveframe = clientcommandframe; + //just update the angles + if (!getinputstate(pmoveframe-1)) + { + } + return; //dead, so don't run prediction. :D + } + + if (cvar("cg_nopred")) + { + pmoveframe = clientcommandframe; + //just update the angles + if (!getinputstate(pmoveframe-1)) + { + } + input_angles = view_angles; + return; + } + + while(pmoveframe < endframe) + { + if (!getinputstate(pmoveframe)) + { + break; + } + runstandardplayerphysics(); + + pmovetouchtriggers(); + + pmoveframe++; + } + + //add in anything that was applied after (for low packet rate protocols) + input_angles = view_angles; +}; + +nonstatic void() Pred_UpdateLocalMovement = +{ + local float viewheight; + + Pred_RunMovement(clientcommandframe); + + if (pmove_org_z > pmove_step_oldz+8 && pmove_org_z < pmove_step_oldz+24 && pmove_vel_z == 0) + { + //evaluate out the remaining old step + if (pmove_steptime - time > 0) + pmove_step = (pmove_steptime - time)*STEPTIME*pmove_step; + else + pmove_step = 0; + + //work out the new step + pmove_step += (pmove_step_oldz-pmove_org_z); + pmove_steptime = time + 1/STEPTIME; + } + pmove_step_oldz = pmove_org_z; + + //allow the user to move the viewheight down 6 units so it's at +16, where projectiles come from. + viewheight = cvar("v_viewheight"); + if (viewheight < -7) + viewheight = -7; + else if (viewheight > 7) + viewheight = 7; + + vieworg = pmove_org; //the default view height + vieworg_z += getstati(STAT_VIEWHEIGHT) + viewheight; + + //correct the view position to compensate for any errors, slowly over time, 0.1 seconds. + if (pmove_errortime - time > 0) + vieworg += (pmove_errortime - time)*ERRORTIME * pmove_error; + + if (!cvar("cg_nostep")) + if (pmove_steptime - time > 0) + vieworg_z += (pmove_steptime - time)*STEPTIME * pmove_step; + + if (chasecam) + { + view_angles_y += 180; + makevectors(view_angles); + traceline(pmove_org, vieworg - v_forward * 72+v_up*32, TRUE, self); + vieworg = trace_endpos + v_forward*8; + } +}; diff --git a/quakec/csqctest/src/cs/animation.qc b/quakec/csqctest/src/cs/q3playerm.qc similarity index 89% rename from quakec/csqctest/src/cs/animation.qc rename to quakec/csqctest/src/cs/q3playerm.qc index f62322b21..b682494ee 100644 --- a/quakec/csqctest/src/cs/animation.qc +++ b/quakec/csqctest/src/cs/q3playerm.qc @@ -33,75 +33,9 @@ */ +#ifdef MD3PMODELS - -//These $frame lines of course state the quake player frames that we're using as cues for which animation to play. -//(less work that way) - -// -// running -// -$frame axrun1 axrun2 axrun3 axrun4 axrun5 axrun6 - -$frame rockrun1 rockrun2 rockrun3 rockrun4 rockrun5 rockrun6 - -// -// standing -// -$frame stand1 stand2 stand3 stand4 stand5 - -$frame axstnd1 axstnd2 axstnd3 axstnd4 axstnd5 axstnd6 -$frame axstnd7 axstnd8 axstnd9 axstnd10 axstnd11 axstnd12 - - -// -// pain -// -$frame axpain1 axpain2 axpain3 axpain4 axpain5 axpain6 - -$frame pain1 pain2 pain3 pain4 pain5 pain6 - - -// -// death -// - -$frame axdeth1 axdeth2 axdeth3 axdeth4 axdeth5 axdeth6 -$frame axdeth7 axdeth8 axdeth9 - -$frame deatha1 deatha2 deatha3 deatha4 deatha5 deatha6 deatha7 deatha8 -$frame deatha9 deatha10 deatha11 - -$frame deathb1 deathb2 deathb3 deathb4 deathb5 deathb6 deathb7 deathb8 -$frame deathb9 - -$frame deathc1 deathc2 deathc3 deathc4 deathc5 deathc6 deathc7 deathc8 -$frame deathc9 deathc10 deathc11 deathc12 deathc13 deathc14 deathc15 - -$frame deathd1 deathd2 deathd3 deathd4 deathd5 deathd6 deathd7 -$frame deathd8 deathd9 - -$frame deathe1 deathe2 deathe3 deathe4 deathe5 deathe6 deathe7 -$frame deathe8 deathe9 - -// -// attacks -// -$frame nailatt1 nailatt2 - -$frame light1 light2 - -$frame rockatt1 rockatt2 rockatt3 rockatt4 rockatt5 rockatt6 - -$frame shotatt1 shotatt2 shotatt3 shotatt4 shotatt5 shotatt6 - -$frame axatt1 axatt2 axatt3 axatt4 axatt5 axatt6 - -$frame axattb1 axattb2 axattb3 axattb4 axattb5 axattb6 - -$frame axattc1 axattc2 axattc3 axattc4 axattc5 axattc6 - -$frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6 +#include "playerframes.inc" //these are the animation sequence names used in quake3. enum { @@ -163,14 +97,6 @@ nosave string anim_name[MAXMODELS]; //names the (skinless) player model, so the nosave float anim_headmodel[MAXMODELS]; nosave vector anim_headoffset[MAXMODELS]; -//the genders you can have. -//we're generous with three. -enum { - GENDER_NEUTER, - GENDER_MALE, - GENDER_FEMALE -}; - //note: q3 assumes male. //we assume male too, due to the player model that is typically used if we have no q3 models. #define GENDER_DEFAULT GENDER_MALE @@ -341,7 +267,8 @@ void(entity ent, string soundname) sexedsound = //our player's frames changed to some new sequence. //our animation function will animate acordingly. -void(float anum) ForceToAnim = + +static void(float anum) ForceToAnim = { if (anum <= TORSO_STAND2) { @@ -366,7 +293,6 @@ float(entity ent) animate = float fnum; float numframes; float fps; - float firstframe; float loopingframes; float ret; @@ -424,7 +350,7 @@ float(entity ent) animate = void() LegsUpdateAnim = { float inair; - float onground; + tracebox(self.origin, self.mins, self.maxs, self.origin-'0 0 2', FALSE, self); if (trace_fraction == 1) @@ -550,12 +476,8 @@ void(entity ent) AddModelWithEffects = ent.forceshader = 0; }; -.float ideal_yaw; -.float yaw_speed; -.float tag_index; - //this function is called inside your base entity's predraw function (which should then return false) -void() Anim_Draw = +nonstatic void() Anim_Draw = { vector tf, tr, tu; vector ang; @@ -825,7 +747,7 @@ void() Anim_Draw = }; //remove our attached models, restoring the player model to being a boring player. -void() Anim_UnsetModel = +nonstatic void() Anim_UnsetModel = { if (self.torsoent) remove(self.torsoent); @@ -845,7 +767,7 @@ void() Anim_UnsetModel = setmodel(self, self.model); }; -float() Anim_GetGender = +nonstatic float() Anim_GetGender = { if (self.headent) return anim_gender[self.headent.modelnum]; @@ -854,7 +776,7 @@ float() Anim_GetGender = //Attempts to read the animation file for the named q3 player model //-1 on failure. -float(string modname) Anim_ReadAnimationFile = +nonstatic float(string modname) Anim_ReadAnimationFile = { local float modnum; local string str; @@ -885,7 +807,7 @@ float(string modname) Anim_ReadAnimationFile = if (file < 0) { print("fopen ", modname, " failed\n"); - return false; + return -1; } modname= strzone(modname); @@ -966,7 +888,7 @@ float(string modname) Anim_ReadAnimationFile = //attempts to apply a player model/skin to the given entity. //this may load the configuration.cfg //skinname is of the form: ranger/default -float(string skinname) Anim_SetModel = +nonstatic float(string skinname) Anim_SetModel = { local string lowermodelname; local string uppermodelname; @@ -980,11 +902,7 @@ float(string skinname) Anim_SetModel = local float uppermodnum; local float headmodnum; - local string str; local float slashpos; - local float file; - local float sequencenum; - local float stupid; tokenize(skinname); lowermodelname = argv(2); @@ -992,27 +910,15 @@ float(string skinname) Anim_SetModel = headmodelname = argv(0); slashpos = strstrofs(lowermodelname, "/"); -#ifdef WORKINDP - lowerskinname = substring(lowermodelname, slashpos+1, strlen(lowermodelname) - (slashpos+1)); -#else lowerskinname = substring(lowermodelname, slashpos+1, -1); -#endif lowermodelname = substring(lowermodelname, 0, slashpos); slashpos = strstrofs(uppermodelname, "/"); -#ifdef WORKINDP - upperskinname = substring(uppermodelname, slashpos+1, strlen(uppermodelname) - (slashpos+1)); -#else upperskinname = substring(uppermodelname, slashpos+1, -1); -#endif uppermodelname = substring(uppermodelname, 0, slashpos); slashpos = strstrofs(headmodelname, "/"); -#ifdef WORKINDP - headskinname = substring(headmodelname, slashpos+1, strlen(headmodelname) - (slashpos+1)); -#else headskinname = substring(headmodelname, slashpos+1, -1); -#endif headmodelname = substring(headmodelname, 0, slashpos); //seeing as we support loading each part from a different player model (well, q3 does) @@ -1157,7 +1063,7 @@ entity(entity src) CloneModel = return dest; }; -entity() Anim_DupModel = +nonstatic entity() Anim_DupModel = { local entity o, n; o = self; @@ -1174,7 +1080,7 @@ entity() Anim_DupModel = return n; }; -float(string skinname) Anim_GetHeadModelIndex = +nonstatic float(string skinname) Anim_GetHeadModelIndex = { float slashpos; string modelname; @@ -1197,7 +1103,7 @@ float(string skinname) Anim_GetHeadModelIndex = return anim_headmodel[modnum]; }; -float(string skinname) Anim_GetHeadSkinNumber = +nonstatic float(string skinname) Anim_GetHeadSkinNumber = { float slashpos; string modelname; @@ -1209,11 +1115,7 @@ float(string skinname) Anim_GetHeadSkinNumber = return 0; //0 = default slashpos = strstrofs(modelname, "/"); -#ifdef WORKINDP - skinname = substring(modelname, slashpos+1, strlen(modelname) - (slashpos+1)); -#else skinname = substring(modelname, slashpos+1, -1); -#endif modelname = substring(modelname, 0, slashpos); if (stof(skinname)) @@ -1231,7 +1133,7 @@ float(string skinname) Anim_GetHeadSkinNumber = return skinforname(anim_headmodel[modnum], strcat("models/players/", modelname, "/head_", skinname, ".skin")); }; -vector(string skinname) Anim_GetHeadOffset = +nonstatic vector(string skinname) Anim_GetHeadOffset = { float slashpos; string modelname; @@ -1240,7 +1142,7 @@ vector(string skinname) Anim_GetHeadOffset = tokenize(skinname); modelname = argv(0); if (modelname == "") - return 0; //an invalid modelindex. + return '0 0 0'; //an invalid modelindex. slashpos = strstrofs(modelname, "/"); modelname = substring(modelname, 0, slashpos); @@ -1249,7 +1151,7 @@ vector(string skinname) Anim_GetHeadOffset = //we load it three times. modnum = Anim_ReadAnimationFile(modelname); if (modnum < 0) - return 0; + return '0 0 0'; return anim_headoffset[modnum]; } @@ -1348,3 +1250,4 @@ float(float sventnum, float channel, string soundname, float vol, float att, vec return CSQC_ServerSound(channel, soundname, org, vol, att); return false; }; +#endif \ No newline at end of file diff --git a/quakec/csqctest/src/cs/system.qc b/quakec/csqctest/src/cs/system.qc index fdcbe2fa4..ff5f80c86 100644 --- a/quakec/csqctest/src/cs/system.qc +++ b/quakec/csqctest/src/cs/system.qc @@ -15,9 +15,7 @@ #define CSQC 1 #endif -#ifndef WORKINDP -#pragma TARGET FTE -#endif +#pragma noref 1 /* ============================================================================== @@ -189,4 +187,6 @@ float pmove_jump_held; float pmove_waterjumptime; .float frame1time; //for automatic framegroups. -.float frame2time; \ No newline at end of file +.float frame2time; + +#pragma noref 0 \ No newline at end of file diff --git a/quakec/csqctest/src/cs/test.qc b/quakec/csqctest/src/cs/test.qc index 6aeaf6c85..e69de29bb 100644 --- a/quakec/csqctest/src/cs/test.qc +++ b/quakec/csqctest/src/cs/test.qc @@ -1,16 +0,0 @@ - -void() runtest = -{ - self.frame1time = time; -}; - -void() test = -{ - precache_model("test/test.txt"); - self = spawn(); - setmodel(self, "test/test.txt"); - setorigin(self, player_local.origin); - self.drawmask = 1; - self.frame = floor(random()*2); - self.predraw = runtest; -}; \ No newline at end of file diff --git a/quakec/csqctest/src/cs/weapons.qc b/quakec/csqctest/src/cs/weapons.qc index 0598e3055..0fc9877c9 100644 --- a/quakec/csqctest/src/cs/weapons.qc +++ b/quakec/csqctest/src/cs/weapons.qc @@ -2,8 +2,6 @@ #define crandom() (random()*2 - 1) .float starttime; .vector source; -.vector angles; -.float alpha; //Moves the entity to where it should be void() RocketProject = @@ -13,16 +11,12 @@ void() RocketProject = self.origin = self.source + self.velocity * (time - self.starttime); //Do the trail thing, if possible. -#ifdef WORKINDP - trailparticles(self, particleeffectforname("tr_rocket"), self.origin, oldorg); -#else trailparticles(particleeffectforname("tr_rocket"), self, self.origin, oldorg); -#endif adddynamiclight(self.origin, 400, '0 1 0'); }; -void(float isnew) ParseRocketClass = +nonstatic void(float isnew) ParseRocketClass = { self.starttime = time; self.source_x = readcoord(); @@ -43,23 +37,19 @@ void(float isnew) ParseRocketClass = self.predraw = RocketProject; }; -void() NailProject = +nonstatic void() NailProject = { local vector oldorg; oldorg = self.origin; self.origin = self.source + self.velocity * (time - self.starttime); //Do the trail thing, if possible. -#ifdef WORKINDP - trailparticles(self, particleeffectforname("tr_nail"), self.origin, oldorg); -#else trailparticles(particleeffectforname("tr_nail"), self, self.origin, oldorg); -#endif // adddynamiclight(self.origin, 100, '1 0 0'); }; -void(float isnew) ParseNailClass = +nonstatic void(float isnew) ParseNailClass = { local float speed; self.starttime = time; @@ -129,12 +119,8 @@ void() GibProject = self.alpha -= td; } - BounceProject(); -#ifdef WORKINDP - trailparticles(self, particleeffectforname("tr_blood"), self.origin, oldorg); -#else + Movetype_Bounce(); trailparticles(particleeffectforname("tr_blood"), self, self.origin, oldorg); -#endif }; void(string gibname, float dm, vector org) ThrowGib = @@ -273,14 +259,11 @@ void TossGibs(vector org, float type, float dm) } }; -void(float isnew) ParseGibbing = +nonstatic void(float isnew) ParseGibbing = { float type; vector org; float dm; - float i; - - float giblevel; type = readbyte(); dm = readbyte(); @@ -295,7 +278,7 @@ void(float isnew) ParseGibbing = TossGibs(org, type, dm); } -void(float isnew) ParseExplosion = +nonstatic void(float isnew) ParseExplosion = { local vector org; local entity e; diff --git a/quakec/csqctest/src/csprogs.src b/quakec/csqctest/src/csprogs.src index bb7c68c3f..0acbc5c00 100644 --- a/quakec/csqctest/src/csprogs.src +++ b/quakec/csqctest/src/csprogs.src @@ -16,16 +16,22 @@ common/extensions.qc common/econstants.qc cs/constants.qc -common/pmove.qc +common/pmovedefs.qc -cs/animation.qc +cs/keys.qc + +common/makeallstatic.qc + +common/pmove.qc +cs/prediction.qc +cs/q3playerm.qc +cs/hlpm.qc cs/player.qc cs/hud.qc cs/movetypes.qc cs/map.qc -cs/keys.qc cs/menu.qc cs/fun/tetris.qc cs/fun/osgk.qc diff --git a/quakec/csqctest/src/miscext.qc b/quakec/csqctest/src/miscext.qc index 138475a71..fc8fcfed0 100644 --- a/quakec/csqctest/src/miscext.qc +++ b/quakec/csqctest/src/miscext.qc @@ -74,7 +74,24 @@ string(float fhandle) fgets = #112; // reads a line of text from the file and re void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file float(string s) strlen = #114; // returns how many characters are in a string string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring +#ifdef WORKINDP +string(string s, float start, float length) substring_frik = #116; // returns a section of a string as a tempstring +string(string s, float start, float length) substring_fte = #116; // returns a section of a string as a tempstring + +string(string s, float start, float length) substring = +{ + if not (ext_fte_strings) + { + if (length < 0) + length = strlen(s) - start + length+1; + return substring_frik(s, start, length); + } + return substring_fte(s, start, length); +}; +#else string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring +#endif + vector(string s) stov = #117; // returns vector value from a string string(string s) strzone = #118; // makes a copy of a string into the string zone and returns it, this is often used to keep around a tempstring for longer periods of time (tempstrings are replaced often) void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!) diff --git a/quakec/csqctest/src/optsall.qc b/quakec/csqctest/src/optsall.qc index 599e045b5..5a65eab91 100644 --- a/quakec/csqctest/src/optsall.qc +++ b/quakec/csqctest/src/optsall.qc @@ -1,2 +1,26 @@ -//#define WORKINDP -#define OWNPLAYERPHYSICS +//#define WORKINDP //use workarounds for DP. +//#define FTEDEPENDANT //explicitly depend upon FTE-only extensions (mostly prototype EXT_CSQC_1 features). +//#define OWNPLAYERPHYSICS //run our own prediction code, instead of the engine-supplied default + +#define MD3PMODELS //support Q3 segmented player models +#define HLPMODELS //support HalfLife skeletal models +#define POWERUP_SHELLS //show shells around players for powerups + +//#define NOEXTENSIONS + +#ifdef NOEXTENSIONS +#undef HLPMODELS +#undef MD3PMODELS +#endif + +#ifdef WORKINDP +# warning "WORKINDP defined: Mod will only work properly in DP" +# ifdef FTEDEPENDANT +# undef FTEDEPENDANT +# endif +#endif + +#ifdef FTEDEPENDANT +# warning "FTEDEPENDANT defined: Mod will only work properly in FTE" +# pragma TARGET FTE +#endif diff --git a/quakec/csqctest/src/ss/client.qc b/quakec/csqctest/src/ss/client.qc index 6be66ff65..f61d7889f 100644 --- a/quakec/csqctest/src/ss/client.qc +++ b/quakec/csqctest/src/ss/client.qc @@ -12,7 +12,6 @@ float modelindex_eyes, modelindex_player; void() DefaultPlayerPhysics; .float usingcsqc; -.float lackofcsqckicktime; /* ============================================================================= @@ -478,12 +477,6 @@ float(entity to) SendPlayer = float ef; float f; - if (!to.usingcsqc) - { - to.usingcsqc = 1; - self.dimension_see = 1; - } - //encode the current weapon in the lower 4 bits. for (f = 1, ef = 0; ef < 16; ef=ef+1,f*=2) { @@ -509,9 +502,9 @@ float(entity to) SendPlayer = WriteCoord(MSG_ENTITY, self.origin_x); WriteCoord(MSG_ENTITY, self.origin_y); WriteCoord(MSG_ENTITY, self.origin_z); - WriteShort(MSG_ENTITY, self.velocity_x*64); - WriteShort(MSG_ENTITY, self.velocity_y*64); - WriteShort(MSG_ENTITY, self.velocity_z*64); + WriteShort(MSG_ENTITY, self.velocity_x); + WriteShort(MSG_ENTITY, self.velocity_y); + WriteShort(MSG_ENTITY, self.velocity_z); WriteByte(MSG_ENTITY, ef); return TRUE; }; @@ -997,17 +990,6 @@ void() PlayerPreThink = self.weapon = W_BestWeapon (); W_SetCurrentAmmo (); } - - if (self.lackofcsqckicktime) - { - if (!self.usingcsqc && self.lackofcsqckicktime < time) - { //well, you could kick them instead, if you were feeling mean. - bprint(self.netname); - bprint(" is not using csqc!\n"); - centerprint(self, "You are not using csqc.\nThis could be due to version differences or only a partially installed mod.\nIf you are using FTEQW, please type \n\sallow_download_csprogs 1\s\n in the console, and then reconnect.\n\nNote that certain incompatabilities may exist if you do not."); - self.lackofcsqckicktime = 0; - } - } }; /* @@ -1214,7 +1196,7 @@ ClientConnect called when a player connects to a server ============ */ -void() ClientConnect = +void(float csqcenabled) ClientConnect = { bprint (self.netname); bprint (" entered the game\n"); @@ -1223,10 +1205,18 @@ void() ClientConnect = if (intermission_running) ExitIntermission (); - if (serverusingcsqc) - self.lackofcsqckicktime = time + 10; - self.usingcsqc = false; - self.dimension_see = 3; + + self.usingcsqc = csqcenabled; + if (self.usingcsqc) + self.dimension_see = 1; + else + { + self.dimension_see = 3; + + bprint(self.netname); + bprint(" is not using csqc!\n"); + sprint(self, "You are not using csqc.\nThis could be due to version differences or only a partially installed mod.\nIf you are using FTEQW, please type \sallow_download_csprogs 1\s in the console, and then reconnect.\n\nNote that certain incompatabilities may exist if you do not."); + } }; @@ -1266,7 +1256,7 @@ float(entity ent) GetGender = local string s; if (infokeyworks) { - s = infokey(ent, "sex"); + s = infokey(ent, "s"); if (s == "" || s == "m" || s == "male" || s == "yesplease") return GENDER_MALE; if (s == "f" || s == "female" || s == "onthebeach") @@ -1554,18 +1544,14 @@ void(entity targ, entity attacker) ClientObituary = } }; - -/* - -void() SV_ClientMovementCommand = +void() DefaultPlayerPhysics = #347; +void() SV_RunClientCommand = { - PlayerPreThink(); - pmove_org = self.origin; pmove_vel = self.velocity; pmove_mins = self.mins; pmove_maxs = self.maxs; - pmove_jump_held = self.jump_held; +// pmove_jump_held = self.jump_held; pmove_waterjumptime = self.teleport_time; //should match the one used by csqc. @@ -1577,7 +1563,7 @@ void() SV_ClientMovementCommand = self.origin = pmove_org; self.velocity = pmove_vel; - self.jump_held = pmove_jump_held; +// self.jump_held = pmove_jump_held; self.teleport_time = pmove_waterjumptime; self.waterlevel = 0;//FIXME @@ -1585,22 +1571,20 @@ void() SV_ClientMovementCommand = self.button0 = (input_buttons & 1); self.button2 = !!(input_buttons & 2); - +/* self.button3 = !!(input_buttons & 4); self.button4 = !!(input_buttons & 8); self.button5 = !!(input_buttons & 16); self.button6 = !!(input_buttons & 32); self.button7 = !!(input_buttons & 64); self.button8 = !!(input_buttons & 128); - +*/ self.v_angle = input_angles; self.angles = input_angles; self.angles_x *= -1/3; - self.movement = input_movevalues; self.impulse = input_impulse; - PlayerPostThink(); - self.Version++; +//we don't need this DP extension +// self.movement = input_movevalues; }; -*/ \ No newline at end of file diff --git a/quakec/csqctest/src/ss/defs.qc b/quakec/csqctest/src/ss/defs.qc index c25dfc72d..9f5fdcd2f 100644 --- a/quakec/csqctest/src/ss/defs.qc +++ b/quakec/csqctest/src/ss/defs.qc @@ -73,7 +73,7 @@ void() PlayerPreThink; void() PlayerPostThink; void() ClientKill; -void() ClientConnect; +void(float csqcenabled) ClientConnect; void() PutClientInServer; // call after setting the parm1... parms void() ClientDisconnect; diff --git a/quakec/csqctest/src/ss/soldier.qc b/quakec/csqctest/src/ss/soldier.qc index 84148007c..99d821a88 100644 --- a/quakec/csqctest/src/ss/soldier.qc +++ b/quakec/csqctest/src/ss/soldier.qc @@ -41,20 +41,20 @@ float(float f) mapsoldieframetoplayer = { switch(f) { - case $stand1 .. $stand8: + case $stand1 .. $stand8 : return $stand1; - case $death1 .. $deathc11; + case $death1 .. $deathc11 : return $deatha1; - case $load1 .. $load11; + case $load1 .. $load11 : return 0; //never used! - case $death1 .. $deathc11; + case $death1 .. $deathc11 : return $deatha1; - case $pain1 .. $painc13; + case $pain1 .. $painc13 : return $pain1; - case $prowl_1 .. $prowl_24; - case $run1 .. $run8; + case $prowl_1 .. $prowl_24 : + case $run1 .. $run8 : return $rockrun1; - case $shoot1 .. $shoot9; + case $shoot1 .. $shoot9 : return $shotatt1; } return f; diff --git a/quakec/csqctest/src/ss/triggers.qc b/quakec/csqctest/src/ss/triggers.qc index 1c49c9a4f..a97e2216e 100644 --- a/quakec/csqctest/src/ss/triggers.qc +++ b/quakec/csqctest/src/ss/triggers.qc @@ -408,7 +408,11 @@ local vector org; other.angles = t.mangle; if (other.classname == "player") { - other.fixangle = 1; // turn this way immediately + // turn this way immediately + //note that csqc should have predicted this already + if (!other.usingcsqc) + other.fixangle = 1; + other.teleport_time = time + 0.7; if (other.flags & FL_ONGROUND) other.flags = other.flags - FL_ONGROUND; diff --git a/quakec/csqctest/src/ss/world.qc b/quakec/csqctest/src/ss/world.qc index efd6b25b5..3bb8ecad2 100644 --- a/quakec/csqctest/src/ss/world.qc +++ b/quakec/csqctest/src/ss/world.qc @@ -337,7 +337,7 @@ void() worldspawn = #ifdef WORKINDP serverusingcsqc = TRUE; #else - serverusingcsqc = checkextension("EXT_CSQC"); + serverusingcsqc = checkextension("EXT_CSQC") || checkextension("EXT_CSQC_1"); #endif }; diff --git a/quakec/csqctest/src/ssqc.src b/quakec/csqctest/src/ssqc.src index 1e350d8a6..18e0b718f 100644 --- a/quakec/csqctest/src/ssqc.src +++ b/quakec/csqctest/src/ssqc.src @@ -10,6 +10,7 @@ common/extensions.qc common/econstants.qc common/classes.qc +common/pmovedefs.qc common/pmove.qc ss/subs.qc