diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 37334cc69..f881ded8a 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -2460,6 +2460,7 @@ Con_DPrintf ("CL_SignonReply: %i\n", cls.signon); case 4: SCR_EndLoadingPlaque (); // allow normal screen updates + SCR_SetLoadingStage(LS_NONE); break; } } diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 0203fb27c..f52084f80 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -206,6 +206,7 @@ float oldsbar = 0; void SCR_ScreenShot_f (void); void SCR_RSShot_f (void); +void SCR_CPrint_f(void); cvar_t show_fps = SCVARF("show_fps", "0", CVAR_ARCHIVE); cvar_t show_fps_x = SCVAR("show_fps_x", "-1"); @@ -223,6 +224,8 @@ cvar_t show_speed_y = SCVAR("show_speed_y", "-9"); extern char cl_screengroup[]; void CLSCR_Init(void) { + Cmd_AddCommand("cprint", SCR_CPrint_f); + Cvar_Register(&show_fps, cl_screengroup); Cvar_Register(&show_fps_x, cl_screengroup); Cvar_Register(&show_fps_y, cl_screengroup); @@ -432,9 +435,9 @@ Called for important messages that should stay in the center of the screen for a few moments ============== */ -void SCR_CenterPrint (int pnum, char *str, qboolean fromgamecode) +void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode) { - if (!fromgamecode) + if (!skipgamecode) { #ifdef CSQC_DAT if (CSQC_CenterPrint(pnum, str)) //csqc nabbed it. @@ -466,6 +469,11 @@ void SCR_CenterPrint (int pnum, char *str, qboolean fromgamecode) } } +void SCR_CPrint_f(void) +{ + SCR_CenterPrint(0, Cmd_Argv(0), true); +} + void SCR_EraseCenterString (void) { int pnum; diff --git a/engine/client/clhl_game.c b/engine/client/clhl_game.c index 796f4366f..f97ccfc8a 100644 --- a/engine/client/clhl_game.c +++ b/engine/client/clhl_game.c @@ -1,16 +1,18 @@ #include "quakedef.h" - #include "glquake.h" #ifdef HLCLIENT -#define CLIENTDLLNAME "cl_dlls/client" - #define notimp(l) Con_Printf("halflife cl builtin not implemented on line %i\n", l) //#define HLCL_API_VERSION 6 #define HLCL_API_VERSION 7 + +//make shared +struct hlcvar_s *GHL_CVarGetPointer(char *varname); + + #define HLPIC model_t* typedef struct @@ -534,12 +536,12 @@ void CLGHL_setcrosshair (HLPIC pic, hlsubrect_t rect, int r, int g, int b) { } -int CLGHL_cvar_register (char *name, char *defvalue, int flags) +struct hlcvar_s *CLGHL_cvar_register (char *name, char *defvalue, int flags) { if (Cvar_Get(name, defvalue, 0, "Halflife cvars")) return GHL_CVarGetPointer(name); else - return false; + return NULL; } float CLGHL_cvar_getfloat (char *name) { @@ -598,7 +600,23 @@ void CLGHL_localcmd (char *command) void CLGHL_getplayerinfo (int entnum, hlplayerinfo_t *result) { - notimp(__LINE__); + player_info_t *player; + entnum--; + if (entnum < 0 || entnum >= MAX_CLIENTS) + return; + + player = &cl.players[entnum]; + result->name = player->name; + result->ping = player->ping; + result->tcolour = player->rtopcolor; + result->bcolour = player->rbottomcolor; + result->isus = true; + result->isspec = player->spectator; + result->pl = player->pl; + if (player->skin) + result->model = player->skin->name; + else + result->model = ""; } void CLGHL_startsound_name (char *name, float vol) @@ -630,7 +648,21 @@ void CLGHL_anglevectors (float *ina, float *outf, float *outr, float *outu) hlmsginfo_t *CLGHL_get_message_info (char *name) { //fixme: add parser - return NULL; + hlmsginfo_t *ret; + ret = Z_Malloc(sizeof(*ret)); + memset(ret, 0, sizeof(*ret)); + ret->name = name; + ret->message = name; + ret->x = 0; + ret->y = 0; + *(int*)&ret->c1 = 0xffffffff; + *(int*)&ret->c2 = 0xffffffff; + ret->effect = 0; + ret->fadein = 0; + ret->fadeout = 0; + ret->fxtime = 0; + ret->holdtime = 1000; + return ret; } int CLGHL_drawchar (int x, int y, int charnum, int r, int g, int b) { @@ -714,6 +746,7 @@ int CLGHL_keyevent(int key, int down) Key_Event(K_MOUSE1+key-241, down); else Con_Printf("CLGHL_keyevent: Unrecognised HL key code\n"); + return true; //fixme: check the return type } void CLGHL_getmousepos(int *outx, int *outy){notimp(__LINE__);} int CLGHL_movetypeisnoclip(void){notimp(__LINE__);return 0;} @@ -806,8 +839,8 @@ model_t *CLGHL_loadmapsprite(char *name) notimp(__LINE__);return NULL; } -void CLGHL_fs_addgamedir(char *basedir, char *appname){notimp(__LINE__);return NULL;} -int CLGHL_expandfilename(char *filename, char *outbuff, int outsize){notimp(__LINE__);return NULL;} +void CLGHL_fs_addgamedir(char *basedir, char *appname){notimp(__LINE__);} +int CLGHL_expandfilename(char *filename, char *outbuff, int outsize){notimp(__LINE__);return false;} char *CLGHL_player_key(int pnum, char *key){notimp(__LINE__);return NULL;} void CLGHL_player_setkey(char *key, char *value){notimp(__LINE__);return NULL;} @@ -836,7 +869,7 @@ void CLGHL_setmouseenable(qboolean enable) - +#if HLCL_API_VERSION >= 7 int CLGHL_demo_isrecording(void) { return cls.demorecording; @@ -863,6 +896,7 @@ struct hl_demo_api_s hl_demo_api = 0xdeadbeef }; +#endif CLHL_cgamefuncs_t CLHL_cgamefuncs; CLHL_enginecgamefuncs_t CLHL_enginecgamefuncs = @@ -1000,22 +1034,29 @@ dllhandle_t clg; int CLHL_GamecodeDoesMouse(void) { - if (!clg || !CLHL_cgamefuncs.CL_CreateMove) - return false; - return true; +#if HLCL_API_VERSION >= 7 + if (clg && CLHL_cgamefuncs.CL_CreateMove) + return true; +#endif + return false; } int CLHL_MouseEvent(unsigned int buttonmask) { +#if HLCL_API_VERSION >= 7 if (!CLHL_GamecodeDoesMouse()) return false; CLHL_cgamefuncs.IN_MouseEvent(buttonmask); return true; +#else + return false; +#endif } void CLHL_SetMouseActive(int activate) { +#if HLCL_API_VERSION >= 7 static int oldactive; if (!clg) { @@ -1036,6 +1077,7 @@ void CLHL_SetMouseActive(int activate) if (CLHL_cgamefuncs.IN_DeactivateMouse) CLHL_cgamefuncs.IN_DeactivateMouse(); } +#endif } void CLHL_UnloadClientGame(void) @@ -1062,18 +1104,6 @@ void CLHL_LoadClientGame(void) dllfunction_t funcs[] = { {(void*)&initfunc, "Initialize"}, - {(void*)&CLHL_cgamefuncs.HUD_VidInit, "HUD_VidInit"}, - {(void*)&CLHL_cgamefuncs.HUD_Init, "HUD_Init"}, - {(void*)&CLHL_cgamefuncs.HUD_Shutdown, "HUD_Shutdown"}, - {(void*)&CLHL_cgamefuncs.HUD_Redraw, "HUD_Redraw"}, - {(void*)&CLHL_cgamefuncs.HUD_UpdateClientData, "HUD_UpdateClientData"}, - {(void*)&CLHL_cgamefuncs.HUD_Reset, "HUD_Reset"}, -#if HLCL_API_VERSION >= 7 - {(void*)&CLHL_cgamefuncs.CL_CreateMove, "CL_CreateMove"}, - {(void*)&CLHL_cgamefuncs.IN_ActivateMouse, "IN_ActivateMouse"}, - {(void*)&CLHL_cgamefuncs.IN_DeactivateMouse, "IN_DeactivateMouse"}, - {(void*)&CLHL_cgamefuncs.IN_MouseEvent, "IN_MouseEvent"}, -#endif {NULL} }; @@ -1102,12 +1132,28 @@ void CLHL_LoadClientGame(void) return; } - CLHL_cgamefuncs.HUD_Init(); - CLHL_cgamefuncs.HUD_VidInit(); + CLHL_cgamefuncs.HUD_VidInit = (void*)Sys_GetAddressForName(clg, "HUD_VidInit"); + CLHL_cgamefuncs.HUD_Init = (void*)Sys_GetAddressForName(clg, "HUD_Init"); + CLHL_cgamefuncs.HUD_Shutdown = (void*)Sys_GetAddressForName(clg, "HUD_Shutdown"); + CLHL_cgamefuncs.HUD_Redraw = (void*)Sys_GetAddressForName(clg, "HUD_Redraw"); + CLHL_cgamefuncs.HUD_UpdateClientData = (void*)Sys_GetAddressForName(clg, "HUD_UpdateClientData"); + CLHL_cgamefuncs.HUD_Reset = (void*)Sys_GetAddressForName(clg, "HUD_Reset"); +#if HLCL_API_VERSION >= 7 + CLHL_cgamefuncs.CL_CreateMove = (void*)Sys_GetAddressForName(clg, "CL_CreateMove"); + CLHL_cgamefuncs.IN_ActivateMouse = (void*)Sys_GetAddressForName(clg, "IN_ActivateMouse"); + CLHL_cgamefuncs.IN_DeactivateMouse = (void*)Sys_GetAddressForName(clg, "IN_DeactivateMouse"); + CLHL_cgamefuncs.IN_MouseEvent = (void*)Sys_GetAddressForName(clg, "IN_MouseEvent"); +#endif + + if (CLHL_cgamefuncs.HUD_Init) + CLHL_cgamefuncs.HUD_Init(); + if (CLHL_cgamefuncs.HUD_VidInit) + CLHL_cgamefuncs.HUD_VidInit(); } int CLHL_BuildUserInput(int msecs, usercmd_t *cmd) { +#if HLCL_API_VERSION >= 7 hlusercmd_t hlcmd; if (!clg || !CLHL_cgamefuncs.CL_CreateMove) return false; @@ -1127,6 +1173,9 @@ int CLHL_BuildUserInput(int msecs, usercmd_t *cmd) cmd->buttons = hlcmd.buttons; cmd->lightlevel = hlcmd.lightlevel; return true; +#else + return false; +#endif } int CLHL_DrawHud(void) @@ -1137,6 +1186,8 @@ int CLHL_DrawHud(void) if (!clg || !CLHL_cgamefuncs.HUD_Redraw) return false; + memset(&state, 0, sizeof(state)); + // state.origin; // state.viewangles; #if HLCL_API_VERSION < 7 diff --git a/engine/client/merged.h b/engine/client/merged.h index 783457ebf..face5dc6f 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -118,7 +118,7 @@ extern void SCR_EndLoadingPlaque (void); extern void SCR_DrawConsole (qboolean noback); extern void SCR_SetUpToDrawConsole (void); extern void SCR_EraseCenterString (void); -extern void SCR_CenterPrint (int pnum, char *str, qboolean fromgamecode); +extern void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode); #endif @@ -141,7 +141,7 @@ extern qboolean Mod_GetTag (struct model_s *model, int tagnum, framestate_t extern int Mod_TagNumForName (struct model_s *model, char *name); int Mod_GetNumBones(struct model_s *model, qboolean allowtags); -int Mod_GetBoneRelations(struct model_s *model, int numbones, framestate_t *fstate, float *result); +int Mod_GetBoneRelations(struct model_s *model, int firstbone, int lastbone, framestate_t *fstate, float *result); int Mod_GetBoneParent(struct model_s *model, int bonenum); char *Mod_GetBoneName(struct model_s *model, int bonenum); diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 68f38f34b..9c24c8fd6 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -281,6 +281,7 @@ static void CSQC_FindGlobals(void) fieldvector(origin); \ fieldvector(angles); \ fieldvector(velocity); \ + fieldfloat(pmove_flags); /*transparency*/ \ fieldfloat(alpha); /*transparency*/ \ fieldfloat(scale); /*model scale*/ \ fieldfloat(fatness); /*expand models X units along their normals.*/ \ @@ -326,7 +327,9 @@ static void CSQC_FindGlobals(void) fieldentity(chain); \ fieldentity(enemy); \ fieldentity(groundentity); \ - fieldentity(owner); \ + fieldentity(owner); \ + \ + fieldfunction(touch); \ \ fieldfloat(solid); \ fieldvector(mins); \ @@ -482,6 +485,87 @@ void CS_ClearWorld (void) CS_LinkEdict((csqcedict_t*)EDICT_NUM(csqcprogs, i), false); } +#define MAX_NODELINKS 256 //all this means is that any more than this will not touch. +static csqcedict_t *csnodelinks[MAX_NODELINKS]; +void CS_TouchLinks ( csqcedict_t *ent, areanode_t *node ) +{ //Spike: rewritten this function to cope with killtargets used on a few maps. + link_t *l, *next; + csqcedict_t *touch; + int old_self, old_other; + + int linkcount = 0, ln; + + //work out who they are first. + for (l = node->trigger_edicts.next ; l != &node->trigger_edicts ; l = next) + { + if (linkcount == MAX_NODELINKS) + break; + next = l->next; + touch = (csqcedict_t*)EDICT_FROM_AREA(l); + if (touch == ent) + continue; + + if (!touch->v->touch || touch->v->solid != SOLID_TRIGGER) + continue; + + if (ent->v->absmin[0] > touch->v->absmax[0] + || ent->v->absmin[1] > touch->v->absmax[1] + || ent->v->absmin[2] > touch->v->absmax[2] + || ent->v->absmax[0] < touch->v->absmin[0] + || ent->v->absmax[1] < touch->v->absmin[1] + || ent->v->absmax[2] < touch->v->absmin[2] ) + continue; + +// if (!((int)ent->xv->dimension_solid & (int)touch->xv->dimension_hit)) +// continue; + + csnodelinks[linkcount++] = touch; + } + + old_self = *csqcg.self; + old_other = *csqcg.other; + for (ln = 0; ln < linkcount; ln++) + { + touch = csnodelinks[ln]; + + //make sure nothing moved it away + if (touch->isfree) + continue; + if (!touch->v->touch || touch->v->solid != SOLID_TRIGGER) + continue; + if (ent->v->absmin[0] > touch->v->absmax[0] + || ent->v->absmin[1] > touch->v->absmax[1] + || ent->v->absmin[2] > touch->v->absmax[2] + || ent->v->absmax[0] < touch->v->absmin[0] + || ent->v->absmax[1] < touch->v->absmin[1] + || ent->v->absmax[2] < touch->v->absmin[2] ) + continue; + +// if (!((int)ent->xv->dimension_solid & (int)touch->xv->dimension_hit)) //didn't change did it?... +// continue; + + *csqcg.self = EDICT_TO_PROG(csqcprogs, (edict_t*)touch); + *csqcg.other = EDICT_TO_PROG(csqcprogs, (edict_t*)ent); + + PR_ExecuteProgram (csqcprogs, touch->v->touch); + + if (ent->isfree) + break; + } + *csqcg.self = old_self; + *csqcg.other = old_other; + + +// recurse down both sides + if (node->axis == -1 || ent->isfree) + return; + + if ( ent->v->absmax[node->axis] > node->dist ) + CS_TouchLinks ( ent, node->children[0] ); + if ( ent->v->absmin[node->axis] < node->dist ) + CS_TouchLinks ( ent, node->children[1] ); +} + static void CS_UnlinkEdict (csqcedict_t *ent) { if (!ent->area.prev) @@ -542,9 +626,13 @@ static void CS_LinkEdict(csqcedict_t *ent, qboolean touchtriggers) // link it in if (ent->v->solid == SOLID_TRIGGER) - InsertLinkBefore (&ent->area, &node->trigger_edicts); + InsertLinkBefore(&ent->area, &node->trigger_edicts); else - InsertLinkBefore (&ent->area, &node->solid_edicts); + InsertLinkBefore(&ent->area, &node->solid_edicts); + + // if touch_triggers, touch all entities at this node and decend for more + if (touchtriggers) + CS_TouchLinks(ent, cs_areanodes); } typedef struct { @@ -1812,6 +1900,8 @@ static void csqc_setmodel(progfuncs_t *prinst, csqcedict_t *ent, int modelindex) VectorClear(ent->v->mins); VectorClear(ent->v->maxs); } + + CS_LinkEdict(ent, false); } static void PF_cs_SetModel(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -2127,6 +2217,12 @@ static void PF_cs_runplayerphysics (progfuncs_t *prinst, struct globalvars_s *pr extern vec3_t player_mins; extern vec3_t player_maxs; + csqcedict_t *ent; + if (*prinst->callargc >= 1) + ent = (void*)G_EDICT(prinst, OFS_PARM0); + else + ent = NULL; + if (!cl.worldmodel) return; //urm.. /* @@ -2181,14 +2277,12 @@ typedef struct { */ + //debugging field pmove.sequence = *csqcg.clientcommandframe; + pmove.pm_type = PM_NORMAL; pmove.jump_msec = 0;//(cls.z_ext & Z_EXT_PM_TYPE) ? 0 : from->jump_msec; - if (csqcg.pmove_jump_held) - pmove.jump_held = *csqcg.pmove_jump_held; - if (csqcg.pmove_waterjumptime) - pmove.waterjumptime = *csqcg.pmove_waterjumptime; //set up the movement command msecs = *csqcg.input_timelength*1000 + 0.5f; @@ -2203,16 +2297,30 @@ typedef struct { pmove.cmd.upmove = csqcg.input_movevalues[2]; pmove.cmd.buttons = *csqcg.input_buttons; - VectorCopy(csqcg.pmove_org, pmove.origin); - VectorCopy(csqcg.pmove_vel, pmove.velocity); - VectorCopy(csqcg.pmove_maxs, player_maxs); - VectorCopy(csqcg.pmove_mins, player_mins); + if (ent) + { + pmove.jump_held = (int)ent->v->pmove_flags & PMF_JUMP_HELD; + pmove.waterjumptime = 0; + VectorCopy(ent->v->origin, pmove.origin); + VectorCopy(ent->v->velocity, pmove.velocity); + VectorCopy(ent->v->maxs, player_maxs); + VectorCopy(ent->v->mins, player_mins); + } + else + { + if (csqcg.pmove_jump_held) + pmove.jump_held = *csqcg.pmove_jump_held; + if (csqcg.pmove_waterjumptime) + pmove.waterjumptime = *csqcg.pmove_waterjumptime; + VectorCopy(csqcg.pmove_org, pmove.origin); + VectorCopy(csqcg.pmove_vel, pmove.velocity); + VectorCopy(csqcg.pmove_maxs, player_maxs); + VectorCopy(csqcg.pmove_mins, player_mins); + } pmove.hullnum = 1; CL_SetSolidEntities(); - - while(msecs) //break up longer commands { pmove.cmd.msec = msecs; @@ -2222,16 +2330,29 @@ typedef struct { PM_PlayerMove(1); } - if (csqcg.pmove_jump_held) - *csqcg.pmove_jump_held = pmove.jump_held; - if (csqcg.pmove_waterjumptime) - *csqcg.pmove_waterjumptime = pmove.waterjumptime; - VectorCopy(pmove.origin, csqcg.pmove_org); - VectorCopy(pmove.velocity, csqcg.pmove_vel); + if (ent) + { + VectorCopy(pmove.angles, ent->v->angles); + ent->v->angles[0] *= -1/3.0f; + VectorCopy(pmove.origin, ent->v->origin); + VectorCopy(pmove.velocity, ent->v->velocity); + ent->v->pmove_flags = 0; + ent->v->pmove_flags += pmove.jump_held ? PMF_JUMP_HELD : 0; + ent->v->pmove_flags += pmove.onladder ? PMF_LADDER : 0; + } + else + { + if (csqcg.pmove_jump_held) + *csqcg.pmove_jump_held = pmove.jump_held; + if (csqcg.pmove_waterjumptime) + *csqcg.pmove_waterjumptime = pmove.waterjumptime; + VectorCopy(pmove.origin, csqcg.pmove_org); + VectorCopy(pmove.velocity, csqcg.pmove_vel); + } - pmove.origin[0] = ((int)(pmove.origin[0]*8))/8.0f; - pmove.origin[1] = ((int)(pmove.origin[1]*8))/8.0f; - pmove.origin[2] = ((int)(pmove.origin[2]*8))/8.0f; + //fixme: touch solids + + CS_LinkEdict (ent, true); } static void PF_cs_getentitytoken (progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -3529,35 +3650,24 @@ skelobject_t *skel_get(progfuncs_t *prinst, int skelidx, int bonecount) } } -//#263 float(entity ent) skel_buildrel (FTE_CSQC_SKELETONOBJECTS) -//#263 float(entity ent, float skel) skel_updaterel (FTE_CSQC_SKELETONOBJECTS) -static void PF_skel_buildrel (progfuncs_t *prinst, struct globalvars_s *pr_globals) +//float(float modelindex) skel_create (FTE_CSQC_SKELETONOBJECTS) +static void PF_skel_create (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0); - int skelidx; int numbones; - framestate_t fstate; skelobject_t *skelobj; qboolean isabs; model_t *model; - if (*prinst->callargc > 1) - skelidx = G_FLOAT(OFS_PARM1); - else - skelidx = 0; + int midx; + + midx = G_FLOAT(OFS_PARM0); //default to failure G_FLOAT(OFS_RETURN) = 0; - model = CSQC_GetModelForIndex(ent->v->modelindex); + model = CSQC_GetModelForIndex(midx); if (!model) return; //no model set, can't get a skeleton - cs_getframestate(ent, ent->v->renderflags, &fstate); - - //heh... don't copy. - fstate.bonecount = 0; - fstate.bonestate = NULL; - isabs = false; numbones = Mod_GetNumBones(model, isabs); if (!numbones) @@ -3568,26 +3678,76 @@ static void PF_skel_buildrel (progfuncs_t *prinst, struct globalvars_s *pr_globa return; //this isn't a skeletal model. } - skelobj = skel_get(prinst, skelidx, numbones); + skelobj = skel_get(prinst, 0, numbones); if (!skelobj) return; //couldn't get one, ran out of memory or something? - if (isabs || skelobj->numbones != Mod_GetBoneRelations(model, skelobj->numbones, &fstate, skelobj->bonematrix)) - { - isabs = true; -// float *ab; -// ab = Alias_GetBonePositions(model, &fstate, skelobj->bonematrix, skelobj->numbones); -// if (ab != skelobj->bonematrix) -// memcpy(skelobj->bonematrix, ab, skelobj->numbones*12*sizeof(float)); - } - skelobj->model = model; skelobj->absolute = isabs; G_FLOAT(OFS_RETURN) = (skelobj - skelobjects) + 1; } -//#264 float(float skel) skel_get_numbones (FTE_CSQC_SKELETONOBJECTS) +//float(float skel, entity ent, float modelindex, float retainfrac, float firstbone, float lastbone) skel_get_numbones (FTE_CSQC_SKELETONOBJECTS) +static void PF_skel_build(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int skelidx = G_FLOAT(OFS_PARM0); + csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM1); + int midx = G_FLOAT(OFS_PARM2); + int retainfrac = G_FLOAT(OFS_PARM3); + int firstbone = G_FLOAT(OFS_PARM4)-1; + int lastbone = G_FLOAT(OFS_PARM5)-1; + + int numbones; + framestate_t fstate; + skelobject_t *skelobj; + model_t *model; + + //default to failure + G_FLOAT(OFS_RETURN) = 0; + + model = CSQC_GetModelForIndex(midx); + if (!model) + return; //invalid model, can't get a skeleton + + cs_getframestate(ent, ent->v->renderflags, &fstate); + + //heh... don't copy. + fstate.bonecount = 0; + fstate.bonestate = NULL; + + numbones = Mod_GetNumBones(model, false); + if (!numbones) + { + return; //this isn't a skeletal model. + } + + skelobj = skel_get(prinst, skelidx, 0); + if (!skelobj) + return; //couldn't get one, ran out of memory or something? + + if (lastbone < 0) + lastbone = numbones; + if (lastbone > numbones) + lastbone = numbones; + if (firstbone < 0) + firstbone = 0; + + if (retainfrac >= 1) + { + //retain everything... + } + else if (retainfrac>0) + { + //codeme + } + else + Mod_GetBoneRelations(model, firstbone, lastbone, &fstate, skelobj->bonematrix); + + G_FLOAT(OFS_RETURN) = (skelobj - skelobjects) + 1; +} + +//float(float skel) skel_get_numbones (FTE_CSQC_SKELETONOBJECTS) static void PF_skel_get_numbones (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int skelidx = G_FLOAT(OFS_PARM0); @@ -3601,7 +3761,7 @@ static void PF_skel_get_numbones (progfuncs_t *prinst, struct globalvars_s *pr_g G_FLOAT(OFS_RETURN) = skelobj->numbones; } -//#265 string(float skel, float bonenum) skel_get_bonename (FTE_CSQC_SKELETONOBJECTS) (returns tempstring) +//string(float skel, float bonenum) skel_get_bonename (FTE_CSQC_SKELETONOBJECTS) (returns tempstring) static void PF_skel_get_bonename (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int skelidx = G_FLOAT(OFS_PARM0); @@ -3618,7 +3778,7 @@ static void PF_skel_get_bonename (progfuncs_t *prinst, struct globalvars_s *pr_g } } -//#266 float(float skel, float bonenum) skel_get_boneparent (FTE_CSQC_SKELETONOBJECTS) +//float(float skel, float bonenum) skel_get_boneparent (FTE_CSQC_SKELETONOBJECTS) static void PF_skel_get_boneparent (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int skelidx = G_FLOAT(OFS_PARM0); @@ -3633,7 +3793,7 @@ static void PF_skel_get_boneparent (progfuncs_t *prinst, struct globalvars_s *pr G_FLOAT(OFS_RETURN) = Mod_GetBoneParent(skelobj->model, boneidx); } -//#267 float(float skel, string tagname) gettagindex (DP_MD3_TAGSINFO) +//float(float skel, string tagname) gettagindex (DP_MD3_TAGSINFO) static void PF_skel_find_bone (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int skelidx = G_FLOAT(OFS_PARM0); @@ -3647,7 +3807,7 @@ static void PF_skel_find_bone (progfuncs_t *prinst, struct globalvars_s *pr_glob G_FLOAT(OFS_RETURN) = Mod_TagNumForName(skelobj->model, bname); } -//#268 vector(float skel, float bonenum) skel_get_bonerel (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) +//vector(float skel, float bonenum) skel_get_bonerel (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) static void PF_skel_get_bonerel (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int skelidx = G_FLOAT(OFS_PARM0); @@ -3687,34 +3847,98 @@ static void PF_skel_get_bonerel (progfuncs_t *prinst, struct globalvars_s *pr_gl } } -//#269 vector(float skel, float bonenum) skel_get_boneabs (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) +//vector(float skel, float bonenum) skel_get_boneabs (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) static void PF_skel_get_boneabs (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int skelidx = G_FLOAT(OFS_PARM0); int boneidx = G_FLOAT(OFS_PARM1)-1; - float *matrix[4]; + float *rmatrix[4]; + float workingm[12], tempmatrix[3][4]; skelobject_t *skelobj; - matrix[0] = csqcg.forward; - matrix[1] = csqcg.right; - matrix[2] = csqcg.up; - matrix[3] = G_VECTOR(OFS_RETURN); + int i; + rmatrix[0] = csqcg.forward; + rmatrix[1] = csqcg.right; + rmatrix[2] = csqcg.up; + rmatrix[3] = G_VECTOR(OFS_RETURN); skelobj = skel_get(prinst, skelidx, 0); - //codeme + if (!skelobj || (unsigned int)boneidx >= skelobj->numbones) + { + rmatrix[0][0] = 1; + rmatrix[0][1] = 0; + rmatrix[0][2] = 0; + + rmatrix[1][0] = 0; + rmatrix[1][1] = 1; + rmatrix[1][2] = 0; + + rmatrix[2][0] = 0; + rmatrix[2][1] = 0; + rmatrix[2][2] = 1; + + rmatrix[3][0] = 0; + rmatrix[3][1] = 0; + rmatrix[3][2] = 0; + } + else if (skelobj->absolute) + { + //can just copy it out + memcpy(rmatrix[0], skelobj->bonematrix + boneidx*12 + 0, sizeof(vec3_t)); + memcpy(rmatrix[1], skelobj->bonematrix + boneidx*12 + 3, sizeof(vec3_t)); + memcpy(rmatrix[2], skelobj->bonematrix + boneidx*12 + 6, sizeof(vec3_t)); + memcpy(rmatrix[3], skelobj->bonematrix + boneidx*12 + 9, sizeof(vec3_t)); + } + else + { + //we need to work out the abs position + + //testme + + //set up an identity matrix + for (i = 0;i < 12;i++) + workingm[i] = 0; + workingm[0] = 1; + workingm[5] = 1; + workingm[10] = 1; + + while(boneidx >= 0) + { + //copy out the previous working matrix, so we don't stomp on it + memcpy(tempmatrix, workingm, sizeof(tempmatrix)); + R_ConcatTransforms((void*)(skelobj->bonematrix + boneidx*12), (void*)tempmatrix, (void*)workingm); + + boneidx = Mod_GetBoneParent(skelobj->model, boneidx+1)-1; + } + memcpy(rmatrix[0], (workingm+0), sizeof(vec3_t)); + memcpy(rmatrix[1], (workingm+3), sizeof(vec3_t)); + memcpy(rmatrix[2], (workingm+6), sizeof(vec3_t)); + memcpy(rmatrix[3], (workingm+9), sizeof(vec3_t)); + } } -//#270 void(float skel, float bonenum, vector org) skel_set_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) +//void(float skel, float bonenum, vector org) skel_set_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) static void PF_skel_set_bone (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int skelidx = G_FLOAT(OFS_PARM0); unsigned int boneidx = G_FLOAT(OFS_PARM1)-1; float *matrix[4]; skelobject_t *skelobj; - matrix[0] = csqcg.forward; - matrix[1] = csqcg.right; - matrix[2] = csqcg.up; - matrix[3] = G_VECTOR(OFS_PARM2); + + if (*prinst->callargc > 5) + { + matrix[3] = G_VECTOR(OFS_PARM2); + matrix[0] = G_VECTOR(OFS_PARM3); + matrix[1] = G_VECTOR(OFS_PARM4); + matrix[2] = G_VECTOR(OFS_PARM5); + } + else + { + matrix[0] = csqcg.forward; + matrix[1] = csqcg.right; + matrix[2] = csqcg.up; + matrix[3] = G_VECTOR(OFS_PARM2); + } skelobj = skel_get(prinst, skelidx, 0); if (!skelobj || boneidx >= skelobj->numbones) @@ -3726,7 +3950,7 @@ static void PF_skel_set_bone (progfuncs_t *prinst, struct globalvars_s *pr_globa VectorCopy(matrix[3], skelobj->bonematrix+12*boneidx+9); } -//#271 void(float skel, float bonenum, vector org) skel_mul_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) +//void(float skel, float bonenum, vector org) skel_mul_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) static void PF_skel_mul_bone (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int skelidx = G_FLOAT(OFS_PARM0); @@ -3734,10 +3958,20 @@ static void PF_skel_mul_bone (progfuncs_t *prinst, struct globalvars_s *pr_globa float temp[3][4]; float mult[3][4]; skelobject_t *skelobj; - VectorCopy(csqcg.forward, mult[0]); - VectorCopy(csqcg.right, mult[1]); - VectorCopy(csqcg.up, mult[2]); - VectorCopy(G_VECTOR(OFS_PARM2), mult[3]); + if (*prinst->callargc > 5) + { + VectorCopy(G_VECTOR(OFS_PARM2), mult[3]); + VectorCopy(G_VECTOR(OFS_PARM3), mult[0]); + VectorCopy(G_VECTOR(OFS_PARM4), mult[1]); + VectorCopy(G_VECTOR(OFS_PARM5), mult[2]); + } + else + { + VectorCopy(csqcg.forward, mult[0]); + VectorCopy(csqcg.right, mult[1]); + VectorCopy(csqcg.up, mult[2]); + VectorCopy(G_VECTOR(OFS_PARM2), mult[3]); + } skelobj = skel_get(prinst, skelidx, 0); if (!skelobj || boneidx >= skelobj->numbones) @@ -3750,7 +3984,7 @@ static void PF_skel_mul_bone (progfuncs_t *prinst, struct globalvars_s *pr_globa R_ConcatTransforms(mult, temp, (float(*)[4])(skelobj->bonematrix+12*boneidx)); } -//#272 void(float skel, float startbone, float endbone, vector org) skel_mul_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) +//void(float skel, float startbone, float endbone, vector org) skel_mul_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) static void PF_skel_mul_bones (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int skelidx = G_FLOAT(OFS_PARM0); @@ -3759,10 +3993,20 @@ static void PF_skel_mul_bones (progfuncs_t *prinst, struct globalvars_s *pr_glob float temp[3][4]; float mult[3][4]; skelobject_t *skelobj; - VectorCopy(csqcg.forward, mult[0]); - VectorCopy(csqcg.right, mult[1]); - VectorCopy(csqcg.up, mult[2]); - VectorCopy(G_VECTOR(OFS_PARM2), mult[3]); + if (*prinst->callargc > 6) + { + VectorCopy(G_VECTOR(OFS_PARM3), mult[3]); + VectorCopy(G_VECTOR(OFS_PARM4), mult[0]); + VectorCopy(G_VECTOR(OFS_PARM5), mult[1]); + VectorCopy(G_VECTOR(OFS_PARM6), mult[2]); + } + else + { + VectorCopy(csqcg.forward, mult[0]); + VectorCopy(csqcg.right, mult[1]); + VectorCopy(csqcg.up, mult[2]); + VectorCopy(G_VECTOR(OFS_PARM3), mult[3]); + } skelobj = skel_get(prinst, skelidx, 0); if (!skelobj) @@ -3781,7 +4025,7 @@ static void PF_skel_mul_bones (progfuncs_t *prinst, struct globalvars_s *pr_glob } } -//#273 void(float skeldst, float skelsrc, float startbone, float entbone) skel_copybones (FTE_CSQC_SKELETONOBJECTS) +//void(float skeldst, float skelsrc, float startbone, float entbone) skel_copybones (FTE_CSQC_SKELETONOBJECTS) static void PF_skel_copybones (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int skeldst = G_FLOAT(OFS_PARM0); @@ -3796,6 +4040,8 @@ static void PF_skel_copybones (progfuncs_t *prinst, struct globalvars_s *pr_glob skelobjsrc = skel_get(prinst, skelsrc, 0); if (!skelobjdst || !skelobjsrc) return; + if (skelobjsrc->absolute != skelobjdst->absolute) + return; if (startbone == -1) startbone = 0; @@ -3809,7 +4055,7 @@ static void PF_skel_copybones (progfuncs_t *prinst, struct globalvars_s *pr_glob } } -//#274 void(float skel) skel_delete (FTE_CSQC_SKELETONOBJECTS) +//void(float skel) skel_delete (FTE_CSQC_SKELETONOBJECTS) static void PF_skel_delete (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int skelidx = G_FLOAT(OFS_PARM0); @@ -4802,19 +5048,20 @@ static struct { {"stoh", PF_stoh, 261}, {"htos", PF_htos, 262}, - {"skel_buildrel", PF_skel_buildrel, 263},//float(entity ent) skel_buildrel (FTE_CSQC_SKELETONOBJECTS) - {"skel_get_numbones", PF_skel_get_numbones, 264},//float(float skel) skel_get_numbones (FTE_CSQC_SKELETONOBJECTS) - {"skel_get_bonename", PF_skel_get_bonename, 265},//string(float skel, float bonenum) skel_get_bonename (FTE_CSQC_SKELETONOBJECTS) (returns tempstring) - {"skel_get_boneparent", PF_skel_get_boneparent, 266},//float(float skel, float bonenum) skel_get_boneparent (FTE_CSQC_SKELETONOBJECTS) - {"skel_find_bone", PF_skel_find_bone, 267},//float(float skel, string tagname) gettagindex (DP_MD3_TAGSINFO) - {"skel_get_bonerel", PF_skel_get_bonerel, 268},//vector(float skel, float bonenum) skel_get_bonerel (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) - {"skel_get_boneabs", PF_skel_get_boneabs, 269},//vector(float skel, float bonenum) skel_get_boneabs (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) - {"skel_set_bone", PF_skel_set_bone, 270},//void(float skel, float bonenum, vector org) skel_set_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) - {"skel_mul_bone", PF_skel_mul_bone, 271},//void(float skel, float bonenum, vector org) skel_mul_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) - {"skel_mul_bones", PF_skel_mul_bones, 272},//void(float skel, float startbone, float endbone, vector org) skel_mul_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) - {"skel_copybones", PF_skel_copybones, 273},//void(float skeldst, float skelsrc, float startbone, float entbone) skel_copybones (FTE_CSQC_SKELETONOBJECTS) - {"skel_delete", PF_skel_delete, 274},//void(float skel) skel_delete (FTE_CSQC_SKELETONOBJECTS) - {"frameforname", PF_frameforname, 275}, // #275 + {"skel_create", PF_skel_create, 263},//float(float modlindex) skel_create = #263; // (FTE_CSQC_SKELETONOBJECTS) + {"skel_build", PF_skel_build, 264},//float(float skel, entity ent, float modlindex, float firstbone, float lastbone) skel_build = #263; // (FTE_CSQC_SKELETONOBJECTS) + {"skel_get_numbones", PF_skel_get_numbones, 265},//float(float skel) skel_get_numbones = #264; // (FTE_CSQC_SKELETONOBJECTS) + {"skel_get_bonename", PF_skel_get_bonename, 266},//string(float skel, float bonenum) skel_get_bonename = #265; // (FTE_CSQC_SKELETONOBJECTS) (returns tempstring) + {"skel_get_boneparent", PF_skel_get_boneparent, 267},//float(float skel, float bonenum) skel_get_boneparent = #266; // (FTE_CSQC_SKELETONOBJECTS) + {"skel_find_bone", PF_skel_find_bone, 268},//float(float skel, string tagname) skel_get_boneidx = #267; // (FTE_CSQC_SKELETONOBJECTS) + {"skel_get_bonerel", PF_skel_get_bonerel, 269},//vector(float skel, float bonenum) skel_get_bonerel = #268; // (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) + {"skel_get_boneabs", PF_skel_get_boneabs, 270},//vector(float skel, float bonenum) skel_get_boneabs = #269; // (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) + {"skel_set_bone", PF_skel_set_bone, 271},//void(float skel, float bonenum, vector org) skel_set_bone = #270; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) + {"skel_mul_bone", PF_skel_mul_bone, 272},//void(float skel, float bonenum, vector org) skel_mul_bone = #271; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) + {"skel_mul_bones", PF_skel_mul_bones, 273},//void(float skel, float startbone, float endbone, vector org) skel_mul_bone = #272; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) + {"skel_copybones", PF_skel_copybones, 274},//void(float skeldst, float skelsrc, float startbone, float entbone) skel_copybones = #273; // (FTE_CSQC_SKELETONOBJECTS) + {"skel_delete", PF_skel_delete, 275},//void(float skel) skel_delete = #274; // (FTE_CSQC_SKELETONOBJECTS) + {"frameforname", PF_frameforname, 276},//void(float modidx, string framename) frameforname = #275 (FTE_CSQC_SKELETONOBJECTS) //300 {"clearscene", PF_R_ClearScene, 300}, // #300 void() clearscene (EXT_CSQC) @@ -5157,8 +5404,19 @@ void CSQC_Shutdown(void) } csqcprogs = NULL; + Z_Free(csqcdelta_pack_new.e); + memset(&csqcdelta_pack_new, 0, sizeof(csqcdelta_pack_new)); + Z_Free(csqcdelta_pack_old.e); + memset(&csqcdelta_pack_old, 0, sizeof(csqcdelta_pack_old)); + memset(&deltafunction, 0, sizeof(deltafunction)); + memset(csqcdelta_playerents, 0, sizeof(csqcdelta_playerents)); + + csqcmapentitydata = NULL; + csqcmapentitydataloaded = false; + in_sensitivityscale = 1; + num_csqc_edicts = 0; csqc_usinglistener = false; } @@ -5276,6 +5534,7 @@ double csqctime; qboolean CSQC_Init (unsigned int checksum) { int i; + string_t *str; csqcedict_t *worldent; csqcchecksum = checksum; @@ -5349,6 +5608,7 @@ qboolean CSQC_Init (unsigned int checksum) csqcprogs = InitProgs(&csqcprogparms); PR_Configure(csqcprogs, -1, 16); + CS_ClearWorld(); CSQC_InitFields(); //let the qclib know the field order that the engine needs. csqc_isdarkplaces = false; @@ -5368,18 +5628,16 @@ qboolean CSQC_Init (unsigned int checksum) return false; } - num_csqc_edicts = 0; - CS_ClearWorld(); PF_InitTempStrings(csqcprogs); + CSQC_FindGlobals(); + csqc_fakereadbyte = -1; memset(csqcent, 0, sizeof(*csqcent)*maxcsqcentities); //clear the server->csqc entity translations. csqcentsize = PR_InitEnts(csqcprogs, pr_csmaxedicts.value); - CSQC_FindGlobals(); - ED_Alloc(csqcprogs); //we need a word entity. //world edict becomes readonly worldent = (csqcedict_t *)EDICT_NUM(csqcprogs, 0); @@ -5388,17 +5646,18 @@ qboolean CSQC_Init (unsigned int checksum) worldent->isfree = false; worldent->v->model = PR_SetString(csqcprogs, cl.model_name[1]); - Z_Free(csqcdelta_pack_new.e); - memset(&csqcdelta_pack_new, 0, sizeof(csqcdelta_pack_new)); - Z_Free(csqcdelta_pack_old.e); - memset(&csqcdelta_pack_old, 0, sizeof(csqcdelta_pack_old)); - - memset(&deltafunction, 0, sizeof(deltafunction)); - - memset(csqcdelta_playerents, 0, sizeof(csqcdelta_playerents)); - - csqcmapentitydata = NULL; - csqcmapentitydataloaded = false; + str = (string_t*)csqcprogs->GetEdictFieldValue(csqcprogs, (edict_t*)worldent, "message", NULL); + if (str) + *str = PR_SetString(csqcprogs, cl.levelname); + + str = (string_t*)PR_FindGlobal(csqcprogs, "mapname", 0); + if (str) + { + char *s = Info_ValueForKey(cl.serverinfo, "map"); + if (!*s) + s = "unknown"; + *str = PR_NewString(csqcprogs, s, strlen(s)+1); + } if (csqcg.init_function) { @@ -5410,6 +5669,7 @@ qboolean CSQC_Init (unsigned int checksum) } Con_Printf("Loaded csqc\n"); + csqcmapentitydataloaded = false; } return true; //success! diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 8f3c39613..4c4984d8d 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -356,7 +356,7 @@ cvar_t r_shadows = SCVARF ("r_shadows", "0", CVAR_ARCHIVE | CVAR_RENDERERLATCH); cvar_t r_vertexdlights = SCVAR ("r_vertexdlights", "1"); -cvar_t vid_preservegamma = SCVAR ("vid_preservegamma", "1"); +cvar_t vid_preservegamma = SCVAR ("vid_preservegamma", "0"); cvar_t vid_hardwaregamma = SCVARF ("vid_hardwaregamma", "1", CVAR_ARCHIVE | CVAR_RENDERERLATCH); cvar_t vid_desktopgamma = SCVARF ("vid_desktopgamma", "0", diff --git a/engine/client/screen.h b/engine/client/screen.h index 04f765066..84347ea10 100644 --- a/engine/client/screen.h +++ b/engine/client/screen.h @@ -105,4 +105,4 @@ enum LS_CLIENT, }; int SCR_GetLoadingStage(void); -void SCR_SetLoadingStage(int stage); \ No newline at end of file +void SCR_SetLoadingStage(int stage); diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 00b9d6bf7..086cdc1d4 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -133,7 +133,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define Q2CLIENT //client can connect to q2 servers #define Q3CLIENT #define Q3SERVER -// #define HLSERVER +// #define HLCLIENT //we can run HL gamecode (not protocol compatible) +// #define HLSERVER //we can run HL gamecode (not protocol compatible) #define NQPROT //server and client are capable of using quake1/netquake protocols. (qw is still prefered. uses the command 'nqconnect') #define FISH //sw rendering only #define ZLIB //zip/pk3 support diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 1e611324b..decc74724 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -194,7 +194,7 @@ static int Alias_BuildLerps(float plerp[4], float *pose[4], int numbones, galias } // -int Alias_GetBoneRelations(galiasinfo_t *inf, framestate_t *fstate, float *result, int numbones) +int Alias_GetBoneRelations(galiasinfo_t *inf, framestate_t *fstate, float *result, int firstbone, int lastbones) { #ifdef SKELETALMODELS if (inf->numbones) @@ -215,20 +215,20 @@ int Alias_GetBoneRelations(galiasinfo_t *inf, framestate_t *fstate, float *resul int bonegroup; int cbone = 0; - int lastbone; + int endbone; - if (numbones > inf->numbones) - numbones = inf->numbones; - if (!numbones) + if (lastbones > inf->numbones) + lastbones = inf->numbones; + if (!lastbones) return 0; for (bonegroup = 0; bonegroup < FS_COUNT; bonegroup++) { - lastbone = fstate->g[bonegroup].endbone; - if (bonegroup == FS_COUNT-1 || lastbone > numbones) - lastbone = numbones; + endbone = fstate->g[bonegroup].endbone; + if (bonegroup == FS_COUNT-1 || endbone > lastbones) + endbone = lastbones; - if (lastbone == cbone) + if (endbone == cbone) continue; frame1 = fstate->g[bonegroup].frame[0]; @@ -259,14 +259,14 @@ int Alias_GetBoneRelations(galiasinfo_t *inf, framestate_t *fstate, float *resul if (numposes == 1) { - memcpy(result, pose[0]+cbone*12, (lastbone-cbone)*12*sizeof(float)); - result += (lastbone-cbone)*12; - cbone = lastbone; + memcpy(result, pose[0]+cbone*12, (lastbones-cbone)*12*sizeof(float)); + result += (lastbones-cbone)*12; + cbone = lastbones; } else { //set up the identity matrix - for (; cbone < lastbone; cbone++) + for (; cbone < lastbones; cbone++) { //set up the per-bone transform matrix for (k = 0;k < 12;k++) @@ -306,7 +306,7 @@ float *Alias_GetBonePositions(galiasinfo_t *inf, framestate_t *fstate, float *bu } else { - numbones = Alias_GetBoneRelations(inf, fstate, (float*)relationsbuf, inf->numbones); + numbones = Alias_GetBoneRelations(inf, fstate, (float*)relationsbuf, 0, inf->numbones); if (numbones == inf->numbones) relations = (float*)relationsbuf; } @@ -2351,7 +2351,7 @@ int Mod_GetNumBones(model_t *model, qboolean allowtags) return 0; } -int Mod_GetBoneRelations(model_t *model, int numbones, framestate_t *fstate, float *result) +int Mod_GetBoneRelations(model_t *model, int firstbone, int lastbone, framestate_t *fstate, float *result) { #ifdef SKELETALMODELS galiasinfo_t *inf; @@ -2361,7 +2361,7 @@ int Mod_GetBoneRelations(model_t *model, int numbones, framestate_t *fstate, flo return false; inf = Mod_Extradata(model); - return Alias_GetBoneRelations(inf, fstate, result, numbones); + return Alias_GetBoneRelations(inf, fstate, result, firstbone, lastbone); #endif return 0; } diff --git a/engine/common/fs.c b/engine/common/fs.c index d9017a24e..539245118 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -2131,6 +2131,9 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base //append SteamApps\common\hexen 2 } +#ifndef NPQTV //this is *really* unfortunate, but doing this crashes the browser + //I assume its because the client + if (poshname) { char resultpath[MAX_PATH]; @@ -2173,6 +2176,7 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base return true; } } +#endif return false; } diff --git a/engine/common/pmove.c b/engine/common/pmove.c index 7d236aacd..434949598 100644 --- a/engine/common/pmove.c +++ b/engine/common/pmove.c @@ -623,7 +623,6 @@ PM_AirMove void PM_AirMove (void) { int i; - vec3_t wishvel; float fmove, smove; vec3_t wishdir; float wishspeed; @@ -637,10 +636,9 @@ void PM_AirMove (void) VectorNormalize (right); for (i=0 ; i<2 ; i++) - wishvel[i] = forward[i]*fmove + right[i]*smove; - wishvel[2] = 0; + wishdir[i] = forward[i]*fmove + right[i]*smove; + wishdir[2] = 0; - VectorCopy (wishvel, wishdir); wishspeed = VectorNormalize(wishdir); // @@ -648,7 +646,6 @@ void PM_AirMove (void) // if (wishspeed > movevars.maxspeed) { - VectorScale (wishvel, movevars.maxspeed/wishspeed, wishvel); wishspeed = movevars.maxspeed; } diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 4225e0416..5df47c102 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -1325,6 +1325,12 @@ static void QCC_FreeTemps(void) { temp_t *t; + if (def_ret.temp && def_ret.temp->used) + { + QCC_PR_ParseWarning(WARN_DEBUGGING, "Return value still in use in %s", pr_scope->name); + def_ret.temp->used = false; + } + t = functemps; while(t) { @@ -2583,6 +2589,208 @@ void QCC_PrecacheFileOptimised (char *n, int ch) numfiles++; } +QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], int argcount) //warning, the func could have no name set if it's a field call. +{ + QCC_def_t *d, *oldret, *oself; + int i; + QCC_type_t *t; + int extraparms=false; + int np; + int laststatement = numstatements; + + int callconvention; + QCC_dstatement_t *st; + + + func->timescalled++; + + if (QCC_OPCodeValid(&pr_opcodes[OP_CALL1H])) + callconvention = OP_CALL1H; //FTE extended + else + callconvention = OP_CALL1; //standard + + t = func->type; + + if (t->type == ev_variant) + { + t->aux_type = type_variant; + } + + if (t->type != ev_function && t->type != ev_variant) + { + QCC_PR_ParseErrorPrintDef (ERR_NOTAFUNCTION, func, "not a function"); + } + +// copy the arguments to the global parameter variables + if (t->type == ev_variant) + { + extraparms = true; + np = 0; + } + else if (t->num_parms < 0) + { + extraparms = true; + np = (t->num_parms * -1) - 1; + } + else + np = t->num_parms; + + if (strchr(func->name, ':') && laststatement && statements[laststatement-1].op == OP_LOAD_FNC && statements[laststatement-1].c == func->ofs) + { //we're entering OO code with a different self. + //eg: other.touch(self) + + //FIXME: problems could occur with hexen2 calling conventions when parm0/1 is 'self' + //thiscall. copy the right ent into 'self' (if it's not the same offset) + d = QCC_PR_GetDef(type_entity, "self", NULL, true, 1, false); + if (statements[laststatement-1].a != d->ofs) + { + oself = QCC_GetTemp(type_entity); + //oself = self + QCC_PR_SimpleStatement(OP_STORE_ENT, d->ofs, oself->ofs, 0, false); + //self = other + QCC_PR_SimpleStatement(OP_STORE_ENT, statements[laststatement-1].a, d->ofs, 0, false); + + //if the args refered to self, update them to refer to oself instead + //(as self is now set to 'other') + for (i = 0; i < argcount; i++) + { + if (arglist[i]->ofs == d->ofs) + { + arglist[i] = oself; + } + } + } + else + { + //it was self.func() anyway + oself = NULL; + d = NULL; + } + } + else + { //regular func call + oself = NULL; + d = NULL; + } + +// write the arguments (except for first two if hexenc) + for (i = 0; i < argcount; i++) + { + if (i>=MAX_PARMS) + d = extra_parms[i - MAX_PARMS]; + else + d = &def_parms[i]; + + if (callconvention == OP_CALL1H) + if (i < 2) + { + //first two args are passed in the call opcode, so don't need to be copied + arglist[i]->references++; + d->references++; + QCC_FreeTemp(arglist[i]); + continue; + } + + if (arglist[i]->type->size>1 || !opt_nonvec_parms) + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_V], arglist[i], d, (QCC_dstatement_t **)0xffffffff)); + else + { + d->type = arglist[i]->type; + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], arglist[i], d, (QCC_dstatement_t **)0xffffffff)); + optres_nonvec_parms++; + } + } + + //if the return value was in use, save it off now, so that it doesn't get clobbered + if (def_ret.temp->used) + { + oldret = QCC_GetTemp(def_ret.type); + if (def_ret.type->size == 3) + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, oldret, NULL)); + else + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, oldret, NULL)); + QCC_UnFreeTemp(oldret); + QCC_UnFreeTemp(&def_ret); + QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient"); + } + else + oldret = NULL; + + //we dont need to lock the local containing the function index because its thrown away after the call anyway + //(if a function is called in the argument list then it'll be locked as part of that call) + QCC_FreeTemp(func); + QCC_LockActiveTemps(); //any temps before are likly to be used with the return value. + QCC_UnFreeTemp(func); + + //generate the call + if (argcount>MAX_PARMS) + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[callconvention-1+MAX_PARMS], func, 0, (QCC_dstatement_t **)&st)); + else if (argcount) + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[callconvention-1+argcount], func, 0, (QCC_dstatement_t **)&st)); + else + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_CALL0], func, 0, (QCC_dstatement_t **)&st)); + + if (callconvention == OP_CALL1H) + { + if (argcount) + { + st->b = arglist[0]->ofs; +// QCC_FreeTemp(param[0]); + if (argcount>1) + { + st->c = arglist[1]->ofs; +// QCC_FreeTemp(param[1]); + } + } + } + + //restore the class owner + if (oself) + QCC_PR_SimpleStatement(OP_STORE_ENT, oself->ofs, d->ofs, 0, false); + + for(; argcount; argcount--) + { + QCC_FreeTemp(arglist[argcount-1]); + } + + if (oldret) + { + //if we preserved the ofs_ret global, restore it here + if (t->type == ev_variant) + { + d = QCC_GetTemp(type_variant); + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, NULL)); + } + else + { + d = QCC_GetTemp(t->aux_type); + if (t->aux_type->size == 3) + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, &def_ret, d, NULL)); + else + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, NULL)); + } + if (def_ret.type->size == 3) + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, oldret, &def_ret, NULL)); + else + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, oldret, &def_ret, NULL)); + QCC_FreeTemp(oldret); + QCC_UnFreeTemp(&def_ret); + QCC_UnFreeTemp(d); + + return d; + } + + if (t->type == ev_variant) + def_ret.type = type_variant; + else + def_ret.type = t->aux_type; + if (def_ret.temp->used) + QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient"); + def_ret.temp->used = true; + + return &def_ret; +} + /* ============ PR_ParseFunctionCall @@ -2591,14 +2799,13 @@ PR_ParseFunctionCall QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could have no name set if it's a field call. { QCC_def_t *e, *d, *old, *oself; - int arg, i; + int arg; QCC_type_t *t, *p; int extraparms=false; int np; int laststatement = numstatements; int callconvention; - QCC_dstatement_t *st; QCC_def_t *param[MAX_PARMS+MAX_EXTRA_PARMS]; @@ -3009,361 +3216,161 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could else np = t->num_parms; - if (def_ret.temp->used) - { - old = QCC_GetTemp(def_ret.type); - if (def_ret.type->size == 3) - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, old, NULL)); - else - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, old, NULL)); - QCC_UnFreeTemp(old); - QCC_UnFreeTemp(&def_ret); - QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient"); - } - else - old = NULL; - - //we dont need to lock the local containing the function index because its thrown away after the call anyway - //(if a function is called in the argument list then it'll be locked as part of that call) - QCC_FreeTemp(func); - QCC_LockActiveTemps(); //any temps before are likly to be used with the return value. - QCC_UnFreeTemp(func); - //any temps referenced to build the parameters don't need to be locked. - - if (opt_vectorcalls && (t->num_parms == 1 && t->param->type == ev_vector)) - { //if we're using vectorcalls - //if it's a function, takes a vector - - //vectorcalls is an evil hack - //it'll make your mod bigger and less efficient. - //however, it'll cut down on numpr_globals, so your mod can become a much greater size. - vec3_t arg; - if (pr_token_type == tt_immediate && pr_immediate_type == type_vector) + if (!QCC_PR_CheckToken(")")) + { + p = t->param; + do { - memcpy(arg, pr_immediate.vector, sizeof(arg)); - while(*pr_file_p == ' ' || *pr_file_p == '\t' || *pr_file_p == '\n') - pr_file_p++; - if (*pr_file_p == ')') - { //woot - def_parms[0].ofs = OFS_PARM0+0; - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(arg[0]), &def_parms[0], (QCC_dstatement_t **)0xffffffff)); - def_parms[0].ofs = OFS_PARM0+1; - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(arg[1]), &def_parms[0], (QCC_dstatement_t **)0xffffffff)); - def_parms[0].ofs = OFS_PARM0+2; - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(arg[2]), &def_parms[0], (QCC_dstatement_t **)0xffffffff)); - def_parms[0].ofs = OFS_PARM0; + if (extraparms && arg >= MAX_PARMS) + QCC_PR_ParseErrorPrintDef (ERR_TOOMANYPARAMETERSVARARGS, func, "More than %i parameters on varargs function", MAX_PARMS); + else if (arg >= MAX_PARMS+MAX_EXTRA_PARMS) + QCC_PR_ParseErrorPrintDef (ERR_TOOMANYTOTALPARAMETERS, func, "More than %i parameters", MAX_PARMS+MAX_EXTRA_PARMS); + if (!extraparms && arg >= t->num_parms) + { + QCC_PR_ParseWarning (WARN_TOOMANYPARAMETERSFORFUNC, "too many parameters"); + QCC_PR_ParsePrintDef(WARN_TOOMANYPARAMETERSFORFUNC, func); + } + + + //with vectorcalls, we store the vector into the args as individual floats + //this allows better reuse of vector constants. + //copy it into the offset now, because we can. + if (opt_vectorcalls && pr_token_type == tt_immediate && pr_immediate_type == type_vector && arg < MAX_PARMS && !def_parms[arg].temp->used) + { + e = &def_parms[arg]; + + e->ofs = OFS_PARM0+0; + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(pr_immediate.vector[0]), e, (QCC_dstatement_t **)0xffffffff)); + e->ofs = OFS_PARM0+1; + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(pr_immediate.vector[1]), e, (QCC_dstatement_t **)0xffffffff)); + e->ofs = OFS_PARM0+2; + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(pr_immediate.vector[2]), e, (QCC_dstatement_t **)0xffffffff)); + e->ofs = OFS_PARM0; QCC_PR_Lex(); - QCC_PR_Expect(")"); } else - { //bum - e = QCC_PR_Expression (TOP_PRIORITY, false); - if (e->type->type != ev_vector) - { - if (flag_laxcasts) - { - QCC_PR_ParseWarning(WARN_LAXCAST, "type mismatch on parm %i - (%s should be %s)", 1, TypeName(e->type), TypeName(type_vector)); - QCC_PR_ParsePrintDef(WARN_LAXCAST, func); - } - else - QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i - (%s should be %s)", 1, TypeName(e->type), TypeName(type_vector)); - } - QCC_PR_Expect(")"); - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_V], e, &def_parms[0], (QCC_dstatement_t **)0xffffffff)); - } - } - else - { //bother - e = QCC_PR_Expression (TOP_PRIORITY, false); - if (e->type->type != ev_vector) - { - if (flag_laxcasts) - { - QCC_PR_ParseWarning(WARN_LAXCAST, "type mismatch on parm %i - (%s should be %s)", 1, TypeName(e->type), TypeName(type_vector)); - QCC_PR_ParsePrintDef(WARN_LAXCAST, func); - } - else - QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i - (%s should be %s)", 1, TypeName(e->type), TypeName(type_vector)); - } - QCC_PR_Expect(")"); - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_V], e, &def_parms[0], (QCC_dstatement_t **)0xffffffff)); - } - } - else - { - if (!QCC_PR_CheckToken(")")) - { - p = t->param; - do - { - if (extraparms && arg >= MAX_PARMS) - QCC_PR_ParseErrorPrintDef (ERR_TOOMANYPARAMETERSVARARGS, func, "More than %i parameters on varargs function", MAX_PARMS); - else if (arg >= MAX_PARMS+MAX_EXTRA_PARMS) - QCC_PR_ParseErrorPrintDef (ERR_TOOMANYTOTALPARAMETERS, func, "More than %i parameters", MAX_PARMS+MAX_EXTRA_PARMS); - if (!extraparms && arg >= t->num_parms) - { - QCC_PR_ParseWarning (WARN_TOOMANYPARAMETERSFORFUNC, "too many parameters"); - QCC_PR_ParsePrintDef(WARN_TOOMANYPARAMETERSFORFUNC, func); - } - e = QCC_PR_Expression (TOP_PRIORITY, false); - if (arg == 0 && func->name) + if (arg == 0 && func->name) + { + // save information for model and sound caching + if (!strncmp(func->name,"precache_", 9)) { - // save information for model and sound caching - if (!strncmp(func->name,"precache_", 9)) - { - if (!strncmp(func->name+9,"sound", 5)) - QCC_PrecacheSound (e, func->name[14]); - else if (!strncmp(func->name+9,"model", 5)) - QCC_PrecacheModel (e, func->name[14]); - else if (!strncmp(func->name+9,"texture", 7)) - QCC_PrecacheTexture (e, func->name[16]); - else if (!strncmp(func->name+9,"file", 4)) - QCC_PrecacheFile (e, func->name[13]); - } + if (!strncmp(func->name+9,"sound", 5)) + QCC_PrecacheSound (e, func->name[14]); + else if (!strncmp(func->name+9,"model", 5)) + QCC_PrecacheModel (e, func->name[14]); + else if (!strncmp(func->name+9,"texture", 7)) + QCC_PrecacheTexture (e, func->name[16]); + else if (!strncmp(func->name+9,"file", 4)) + QCC_PrecacheFile (e, func->name[13]); } + } - if (arg>=MAX_PARMS) + if (arg>=MAX_PARMS) + { + if (!extra_parms[arg - MAX_PARMS]) { - if (!extra_parms[arg - MAX_PARMS]) - { - d = (QCC_def_t *) qccHunkAlloc (sizeof(QCC_def_t)); - d->name = "extra parm"; - d->ofs = QCC_GetFreeOffsetSpace (3); - extra_parms[arg - MAX_PARMS] = d; - } - d = extra_parms[arg - MAX_PARMS]; + d = (QCC_def_t *) qccHunkAlloc (sizeof(QCC_def_t)); + d->name = "extra parm"; + d->ofs = QCC_GetFreeOffsetSpace (3); + extra_parms[arg - MAX_PARMS] = d; } - else - d = &def_parms[arg]; + d = extra_parms[arg - MAX_PARMS]; + } + else + d = &def_parms[arg]; - if (pr_classtype && e->type->type == ev_field && p->type != ev_field) - { //convert. - oself = QCC_PR_GetDef(type_entity, "self", NULL, true, 1, false); - switch(e->type->aux_type->type) - { - case ev_string: - e = QCC_PR_Statement(pr_opcodes+OP_LOAD_S, oself, e, NULL); - break; - case ev_integer: - e = QCC_PR_Statement(pr_opcodes+OP_LOAD_I, oself, e, NULL); - break; - case ev_float: - e = QCC_PR_Statement(pr_opcodes+OP_LOAD_F, oself, e, NULL); - break; - case ev_function: - e = QCC_PR_Statement(pr_opcodes+OP_LOAD_FNC, oself, e, NULL); - break; - case ev_vector: - e = QCC_PR_Statement(pr_opcodes+OP_LOAD_V, oself, e, NULL); - break; - case ev_entity: - e = QCC_PR_Statement(pr_opcodes+OP_LOAD_ENT, oself, e, NULL); - break; - default: - QCC_Error(ERR_INTERNAL, "Bad member type. Try forced expansion"); - } - } - - if (p) + if (pr_classtype && e->type->type == ev_field && p->type != ev_field) + { //convert. + oself = QCC_PR_GetDef(type_entity, "self", NULL, true, 1, false); + switch(e->type->aux_type->type) { - if (typecmp(e->type, p)) - /*if (e->type->type != ev_integer && p->type != ev_function) - if (e->type->type != ev_function && p->type != ev_integer) - if ( e->type->type != p->type )*/ + case ev_string: + e = QCC_PR_Statement(pr_opcodes+OP_LOAD_S, oself, e, NULL); + break; + case ev_integer: + e = QCC_PR_Statement(pr_opcodes+OP_LOAD_I, oself, e, NULL); + break; + case ev_float: + e = QCC_PR_Statement(pr_opcodes+OP_LOAD_F, oself, e, NULL); + break; + case ev_function: + e = QCC_PR_Statement(pr_opcodes+OP_LOAD_FNC, oself, e, NULL); + break; + case ev_vector: + e = QCC_PR_Statement(pr_opcodes+OP_LOAD_V, oself, e, NULL); + break; + case ev_entity: + e = QCC_PR_Statement(pr_opcodes+OP_LOAD_ENT, oself, e, NULL); + break; + default: + QCC_Error(ERR_INTERNAL, "Bad member type. Try forced expansion"); + } + } + + if (p) + { + if (typecmp(e->type, p)) + /*if (e->type->type != ev_integer && p->type != ev_function) + if (e->type->type != ev_function && p->type != ev_integer) + if ( e->type->type != p->type )*/ + { + if (p->type == ev_integer && e->type->type == ev_float) //convert float -> int... is this a constant? + e = QCC_PR_Statement(pr_opcodes+OP_CONV_FTOI, e, NULL, NULL); + else if (p->type == ev_float && e->type->type == ev_integer) //convert float -> int... is this a constant? + e = QCC_PR_Statement(pr_opcodes+OP_CONV_ITOF, e, NULL, NULL); + else if (p->type == ev_function && e->type->type == ev_integer && e->constant && !((int*)qcc_pr_globals)[e->ofs]) + { //you're allowed to use int 0 to pass a null function pointer + //this is basically because __NULL__ is defined as ~0 (int 0) + } + else if (p->type != ev_variant) //can cast to variant whatever happens { - if (p->type == ev_integer && e->type->type == ev_float) //convert float -> int... is this a constant? - e = QCC_PR_Statement(pr_opcodes+OP_CONV_FTOI, e, NULL, NULL); - else if (p->type == ev_float && e->type->type == ev_integer) //convert float -> int... is this a constant? - e = QCC_PR_Statement(pr_opcodes+OP_CONV_ITOF, e, NULL, NULL); - else if (p->type == ev_function && e->type->type == ev_integer && e->constant && !((int*)qcc_pr_globals)[e->ofs]) - { //you're allowed to use int 0 to pass a null function pointer - //this is basically because __NULL__ is defined as ~0 (int 0) - } - else if (p->type != ev_variant) //can cast to variant whatever happens + if (flag_laxcasts || (p->type == ev_function && e->type->type == ev_function)) { - if (flag_laxcasts || (p->type == ev_function && e->type->type == ev_function)) - { - QCC_PR_ParseWarning(WARN_LAXCAST, "type mismatch on parm %i - (%s should be %s)", arg+1, TypeName(e->type), TypeName(p)); - QCC_PR_ParsePrintDef(WARN_LAXCAST, func); - } - else - QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i - (%s should be %s)", arg+1, TypeName(e->type), TypeName(p)); + QCC_PR_ParseWarning(WARN_LAXCAST, "type mismatch on parm %i - (%s should be %s)", arg+1, TypeName(e->type), TypeName(p)); + QCC_PR_ParsePrintDef(WARN_LAXCAST, func); } + else + QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i - (%s should be %s)", arg+1, TypeName(e->type), TypeName(p)); } - - d->type = p; - - p=p->next; - } - // a vector copy will copy everything - else - d->type = type_void; - - if (arg == 1 && !STRCMP(func->name, "setmodel")) - { - QCC_SetModel(e); } - param[arg] = e; - /* if (e->type->size>1) - QCC_PR_Statement (&pr_opcodes[OP_STORE_V], e, d, (QCC_dstatement_t **)0xffffffff); - else - QCC_PR_Statement (&pr_opcodes[OP_STORE_F], e, d, (QCC_dstatement_t **)0xffffffff); - */ - arg++; - } while (QCC_PR_CheckToken (",")); + d->type = p; - if (t->num_parms != -1 && arg < np) - QCC_PR_ParseWarning (WARN_TOOFEWPARAMS, "too few parameters on call to %s", func->name); - QCC_PR_Expect (")"); - } - else if (np) - { - QCC_PR_ParseWarning (WARN_TOOFEWPARAMS, "%s: Too few parameters", func->name); - QCC_PR_ParsePrintDef (WARN_TOOFEWPARAMS, func); - } - - // qcc_functioncalled++; - for (i = 0; i < arg; i++) - { - if (i>=MAX_PARMS) - d = extra_parms[i - MAX_PARMS]; - else - d = &def_parms[i]; - - if (callconvention == OP_CALL1H) - if (i < 2) - { - param[i]->references++; - d->references++; - QCC_FreeTemp(param[i]); - continue; - } - - if (param[i]->type->size>1 || !opt_nonvec_parms) - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_V], param[i], d, (QCC_dstatement_t **)0xffffffff)); - else - { - d->type = param[i]->type; - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], param[i], d, (QCC_dstatement_t **)0xffffffff)); - optres_nonvec_parms++; + p=p->next; } - } - } - - if (strchr(func->name, ':') && laststatement && statements[laststatement-1].op == OP_LOAD_FNC && statements[laststatement-1].c == func->ofs) - { //we're entering OO code with a different self. - - //FIXME: problems could occur with hexen2 calling conventions when parm0/1 is 'self' - //thiscall. copy the right ent into 'self' (if it's not the same offset) - d = QCC_PR_GetDef(type_entity, "self", NULL, true, 1, false); - if (statements[laststatement-1].a != d->ofs) - { - oself = QCC_GetTemp(type_entity); - QCC_PR_SimpleStatement(OP_STORE_ENT, d->ofs, oself->ofs, 0, false); - QCC_PR_SimpleStatement(OP_STORE_ENT, statements[laststatement-1].a, d->ofs, 0, false); - - if (callconvention == OP_CALL1H) //other.function(self) - //hexenc calling convention would mean that the - //passed parameter is essentually (self=other), - //so pass oself instead which won't be affected - { - QCC_def_t *temp; - if (arg>=1 && param[0]->ofs == d->ofs) - { - temp = QCC_GetTemp(type_entity); - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_ENT, oself, temp, NULL)); - QCC_UnFreeTemp(temp); - param[0] = temp; - } - if (arg>=2 && param[1]->ofs == d->ofs) - { - temp = QCC_GetTemp(type_entity); - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_ENT, oself, temp, NULL)); - QCC_UnFreeTemp(temp); - param[1] = temp; - } - } - } - else - { - oself = NULL; - d = NULL; - } - } - else - { - oself = NULL; - d = NULL; - } - - if (arg>MAX_PARMS) - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[callconvention-1+MAX_PARMS], func, 0, (QCC_dstatement_t **)&st)); - else if (arg) - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[callconvention-1+arg], func, 0, (QCC_dstatement_t **)&st)); - else - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_CALL0], func, 0, (QCC_dstatement_t **)&st)); - - if (callconvention == OP_CALL1H) - { - if (arg) - { - st->b = param[0]->ofs; -// QCC_FreeTemp(param[0]); - if (arg>1) - { - st->c = param[1]->ofs; -// QCC_FreeTemp(param[1]); - } - } - } - if (oself) - QCC_PR_SimpleStatement(OP_STORE_ENT, oself->ofs, d->ofs, 0, false); - - for(; arg; arg--) - { - QCC_FreeTemp(param[arg-1]); - } - - if (old) - { - if (t->type == ev_variant) - { - d = QCC_GetTemp(type_variant); - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, NULL)); - } - else - { - d = QCC_GetTemp(t->aux_type); - if (t->aux_type->size == 3) - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, &def_ret, d, NULL)); + // a vector copy will copy everything else - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, NULL)); - } - if (def_ret.type->size == 3) - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, old, &def_ret, NULL)); - else - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, old, &def_ret, NULL)); - QCC_FreeTemp(old); - QCC_UnFreeTemp(&def_ret); - QCC_UnFreeTemp(d); + d->type = type_void; - return d; + if (arg == 1 && !STRCMP(func->name, "setmodel")) + { + QCC_SetModel(e); + } + + param[arg] = e; +/* if (e->type->size>1) + QCC_PR_Statement (&pr_opcodes[OP_STORE_V], e, d, (QCC_dstatement_t **)0xffffffff); + else + QCC_PR_Statement (&pr_opcodes[OP_STORE_F], e, d, (QCC_dstatement_t **)0xffffffff); + */ + arg++; + } while (QCC_PR_CheckToken (",")); + + if (t->num_parms != -1 && arg < np) + QCC_PR_ParseWarning (WARN_TOOFEWPARAMS, "too few parameters on call to %s", func->name); + QCC_PR_Expect (")"); + } + else if (np) + { + QCC_PR_ParseWarning (WARN_TOOFEWPARAMS, "%s: Too few parameters", func->name); + QCC_PR_ParsePrintDef (WARN_TOOFEWPARAMS, func); } - - if (t->type == ev_variant) - def_ret.type = type_variant; - else - def_ret.type = t->aux_type; - if (def_ret.temp->used) - QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient"); - def_ret.temp->used = true; - return &def_ret; + return QCC_PR_GenerateFunctionCall(func, param, arg); } int constchecks; @@ -3990,31 +3997,19 @@ reloop: { //hexen2 style retrieval, mixed with q1 style assignments... if (QCC_PR_CheckToken("=")) //(hideous concept) { - QCC_dstatement_t *st; QCC_def_t *funcretr; + QCC_def_t *args[2]; if (d->scope) QCC_PR_ParseError(0, "Scoped array without specific engine support"); - if (def_ret.temp->used && ao != &def_ret) - QCC_PR_ParseWarning(0, "RETURN VALUE ALREADY IN USE"); funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 1, false); nd = QCC_PR_Expression(TOP_PRIORITY, true); if (nd->type->type != d->type->type) QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment"); - QCC_LockActiveTemps(); - QCC_PR_Statement (&pr_opcodes[OP_CALL2H], funcretr, 0, &st); - st->a = ao->ofs; - st->b = nd->ofs; - QCC_FreeTemp(ao); - QCC_FreeTemp(nd); - qcc_usefulstatement = true; - - nd = &def_ret; - def_ret.temp->used = true; - d=nd; - d->type = newtype; - return d; + args[0] = ao; + args[1] = nd; + return QCC_PR_GenerateFunctionCall(funcretr, args, 2); } switch(newtype->type) @@ -4058,39 +4053,34 @@ reloop: QCC_def_t *funcretr; if (d->scope) QCC_PR_ParseError(0, "Scoped array without specific engine support"); - if (def_ret.temp->used && ao != &def_ret) - QCC_PR_ParseWarning(0, "RETURN VALUE ALREADY IN USE"); - if (QCC_PR_CheckToken("=")) { + QCC_def_t *args[2]; + funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 1, false); + nd = QCC_PR_Expression(TOP_PRIORITY, true); if (nd->type->type != d->type->type) QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment"); - def_parms[0].type = type_float; - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], ao, &def_parms[0], NULL)); - def_parms[1].type = nd->type; - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_V], nd, &def_parms[1], NULL)); - QCC_LockActiveTemps(); - QCC_PR_Statement (&pr_opcodes[OP_CALL2], funcretr, 0, NULL); - qcc_usefulstatement = true; + args[0] = ao; + args[1] = nd; + qcc_usefulstatement=true; + nd = QCC_PR_GenerateFunctionCall(funcretr, args, 2); + nd->type = d->type->aux_type; } else { - def_parms[0].type = type_float; - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], ao, &def_parms[0], NULL)); - funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 1, false); - QCC_LockActiveTemps(); - QCC_PR_Statement (&pr_opcodes[OP_CALL1], funcretr, 0, NULL); - } + QCC_def_t *args[1]; - nd = &def_ret; - def_ret.temp->used = true; - d=nd; - d->type = newtype; - return d; + def_parms[0].type = type_float; + funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 1, false); + + args[0] = ao; + nd = QCC_PR_GenerateFunctionCall(funcretr, args, 1); + nd->type = d->type->aux_type; + } } else { @@ -7258,7 +7248,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname) else QCC_PR_Statement3(&pr_opcodes[OP_FETCH_GBL_F], def, index, &def_ret, true); - QCC_PR_Statement(&pr_opcodes[OP_RETURN], &def_ret, NULL, NULL); + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_RETURN], &def_ret, NULL, NULL)); //finish the jump st->b = &statements[numstatements] - st; @@ -7291,6 +7281,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname) ret = QCC_PR_GetDef(type_vector, "vec__", pr_scope, true, 1, false); ret->references+=4; QCC_PR_Statement3(pr_opcodes+OP_STORE_V, &def_ret, ret, NULL, false); + QCC_FreeTemp(&def_ret); div3 = QCC_PR_Statement(pr_opcodes+OP_MUL_F, intdiv3, QCC_MakeFloatDef(3), NULL); QCC_PR_Statement3(pr_opcodes+OP_SUB_F, index, div3, index, false); @@ -7411,7 +7402,7 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname) //note that the array size is coded into the globals, one index before the array. QCC_PR_Statement3(&pr_opcodes[OP_CONV_FTOI], index, NULL, index, true); //address stuff is integer based, but standard qc (which this accelerates in supported engines) only supports floats - QCC_PR_SimpleStatement (OP_BOUNDCHECK, index->ofs, ((int*)qcc_pr_globals)[def->ofs-1], 0, true);//annoy the programmer. :p + QCC_PR_SimpleStatement (OP_BOUNDCHECK, index->ofs, ((int*)qcc_pr_globals)[def->ofs-1]+1, 0, true);//annoy the programmer. :p if (def->type->size != 1)//shift it upwards for larger types QCC_PR_Statement3(&pr_opcodes[OP_MUL_I], index, QCC_MakeIntDef(def->type->size), index, true); QCC_PR_Statement3(&pr_opcodes[OP_GLOBALADDRESS], def, index, index, true); //comes with built in add diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index eaf57ed9c..46860b297 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -117,31 +117,32 @@ builtin_t pr_builtin[1024]; extern BuiltinList_t BuiltinList[]; struct { - func_t ChatMessage; - - func_t getplayerstat[MAX_CL_STATS]; - func_t getplayerstati[MAX_CL_STATS]; - - func_t UserCmd, ParseClientCommand, ParseConnectionlessPacket; - func_t ConsoleCmd; + func_t ChatMessage; //mvdsv parsing of 'say' commands + func_t UserCmd; //mvdsv + func_t ConsoleCmd; //mvdsv func_t UserInfo_Changed; func_t localinfoChanged; + func_t ParseClientCommand; //KRIMZON_SV_PARSECLIENTCOMMAND + func_t ParseConnectionlessPacket; //FTE_QC_SENDPACKET + func_t PausedTic; func_t ShouldPause; - func_t ClassChangeWeapon; + func_t RunClientCommand; //EXT_CSQC_1 + + func_t ClassChangeWeapon;//hexen2 support } gfuncs; -func_t getplayerstat[MAX_CL_STATS]; -func_t getplayerstati[MAX_CL_STATS]; -func_t SpectatorConnect; -func_t SpectatorThink; -func_t SpectatorDisconnect; +func_t getplayerstat[MAX_CL_STATS]; //unnamed FTE extension +func_t getplayerstati[MAX_CL_STATS];//unnamed FTE extension +func_t SpectatorConnect; //QW +func_t SpectatorThink; //QW +func_t SpectatorDisconnect; //QW func_t SV_PlayerPhysicsQC; //DP's DP_SV_PLAYERPHYSICS extension -func_t EndFrameQC; +func_t EndFrameQC; //a common extension -qboolean pr_items2; +qboolean pr_items2; //hipnotic (or was it rogue?) nqglobalvars_t realpr_nqglobal_struct; nqglobalvars_t *pr_nqglobal_struct = &realpr_nqglobal_struct; @@ -483,6 +484,7 @@ void PR_LoadGlabalStruct(void) #define globalint(need,name) ((nqglobalvars_t*)pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n"); #define globalstring(need,name) ((nqglobalvars_t*)pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n"); #define globalvec(need,name) ((nqglobalvars_t*)pr_globals)->V_##name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->V_##name) SV_Error("Could not find export \""#name"\" in progs\n"); +#define globalvec_(need,name) ((nqglobalvars_t*)pr_globals)->name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n"); #define globalfunc(need,name) ((nqglobalvars_t*)pr_globals)->name = (func_t *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n"); // globalint(pad); globalint (true, self); //we need the qw ones, but any in standard quake and not quakeworld, we don't really care about. @@ -528,9 +530,15 @@ void PR_LoadGlabalStruct(void) globalfunc (false, SetNewParms); globalfunc (false, SetChangeParms); globalfloat (false, cycle_wrapped); - globalfloat (false, dimension_send); + + globalfloat (false, clientcommandframe); + globalfloat (false, input_timelength); + globalvec_ (false, input_angles); + globalvec_ (false, input_movevalues); + globalfloat (false, input_buttons); + memset(&evalc_idealpitch, 0, sizeof(evalc_idealpitch)); memset(&evalc_pitch_speed, 0, sizeof(evalc_pitch_speed)); @@ -550,6 +558,10 @@ void PR_LoadGlabalStruct(void) ((nqglobalvars_t*)pr_globals)->trace_surfaceflags = &writeonly; } + + + + pr_global_struct->dimension_send = 255; pr_teamfield = 0; @@ -575,6 +587,7 @@ void PR_LoadGlabalStruct(void) gfuncs.PausedTic = PR_FindFunction(svprogfuncs, "SV_PausedTic", PR_ANY); gfuncs.ShouldPause = PR_FindFunction(svprogfuncs, "SV_ShouldPause", PR_ANY); gfuncs.ClassChangeWeapon = PR_FindFunction(svprogfuncs, "ClassChangeWeapon", PR_ANY); + gfuncs.RunClientCommand = PR_FindFunction(svprogfuncs, "SV_RunClientCommand", PR_ANY); if (pr_no_playerphysics.value) SV_PlayerPhysicsQC = 0; @@ -8297,6 +8310,7 @@ void PF_sv_gettaginfo(progfuncs_t *prinst, struct globalvars_s *pr_globals) //the first implementation of this function was (float type, float num, string name) //it is now float num, float type, .field +//EXT_CSQC_1 void PF_clientstat(progfuncs_t *prinst, struct globalvars_s *pr_globals) { #if 0 //this is the old code @@ -8306,6 +8320,8 @@ void PF_clientstat(progfuncs_t *prinst, struct globalvars_s *pr_globals) SV_QCStatFieldIdx(G_FLOAT(OFS_PARM1), G_INT(OFS_PARM2)+prinst->fieldadjust, G_FLOAT(OFS_PARM0)); #endif } +//EXT_CSQC_1 +//void(float num, float type, string name) globalstat void PF_globalstat(progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *name = PF_VarString(prinst, 2, pr_globals); @@ -8316,42 +8332,60 @@ void PF_globalstat(progfuncs_t *prinst, struct globalvars_s *pr_globals) #endif } +//EXT_CSQC_1 void PF_runclientphys(progfuncs_t *prinst, struct globalvars_s *pr_globals) { + unsigned int i, n; extern vec3_t player_maxs, player_mins; - float msecs; - pmove.sequence = *pr_nqglobal_struct->clientcommandframe; - pmove.pm_type = PM_NORMAL; + extern qbyte playertouch[]; + unsigned int msecs; + edict_t *ent = G_EDICT(prinst, OFS_PARM0); + edict_t *touched; + if (pr_nqglobal_struct->clientcommandframe) + pmove.sequence = *pr_nqglobal_struct->clientcommandframe; + else + pmove.sequence = 0; + if (host_client && host_client->edict == ent) + pmove.pm_type = SV_PMTypeForClient(host_client); + else + pmove.pm_type = PM_NORMAL; pmove.jump_msec = 0;//(cls.z_ext & Z_EXT_PM_TYPE) ? 0 : from->jump_msec; - if (pr_nqglobal_struct->pmove_jump_held) - pmove.jump_held = *pr_nqglobal_struct->pmove_jump_held; - if (pr_nqglobal_struct->pmove_waterjumptime) - pmove.waterjumptime = *pr_nqglobal_struct->pmove_waterjumptime; + + pmove.jump_held = ((int)ent->xv->pmove_flags)&PMF_JUMP_HELD; + pmove.waterjumptime = ent->v->teleport_time; //set up the movement command - msecs = *pr_nqglobal_struct->input_timelength*1000 + 0.5f; + msecs = pr_global_struct->input_timelength*1000 + 0.5f; //precision inaccuracies. :( #define ANGLE2SHORT(x) (x) * (65536/360.0) - pmove.cmd.angles[0] = ANGLE2SHORT(pr_nqglobal_struct->input_angles[0]); - pmove.cmd.angles[1] = ANGLE2SHORT(pr_nqglobal_struct->input_angles[1]); - pmove.cmd.angles[2] = ANGLE2SHORT(pr_nqglobal_struct->input_angles[2]); - VectorCopy(pr_nqglobal_struct->input_angles, pmove.angles); + pmove.cmd.angles[0] = ANGLE2SHORT((pr_global_struct->input_angles)[0]); + pmove.cmd.angles[1] = ANGLE2SHORT((pr_global_struct->input_angles)[1]); + pmove.cmd.angles[2] = ANGLE2SHORT((pr_global_struct->input_angles)[2]); + VectorCopy(pr_global_struct->input_angles, pmove.angles); - pmove.cmd.forwardmove = (*pr_nqglobal_struct->input_movevalues)[0]; - pmove.cmd.sidemove = (*pr_nqglobal_struct->input_movevalues)[1]; - pmove.cmd.upmove = (*pr_nqglobal_struct->input_movevalues)[2]; - pmove.cmd.buttons = *pr_nqglobal_struct->input_buttons; + pmove.cmd.forwardmove = (pr_global_struct->input_movevalues)[0]; + pmove.cmd.sidemove = (pr_global_struct->input_movevalues)[1]; + pmove.cmd.upmove = (pr_global_struct->input_movevalues)[2]; + pmove.cmd.buttons = pr_global_struct->input_buttons; - VectorCopy(*pr_nqglobal_struct->pmove_org, pmove.origin); - VectorCopy(*pr_nqglobal_struct->pmove_vel, pmove.velocity); - VectorCopy(*pr_nqglobal_struct->pmove_maxs, player_maxs); - VectorCopy(*pr_nqglobal_struct->pmove_mins, player_mins); - pmove.hullnum = 1; + VectorCopy(ent->v->origin, pmove.origin); + VectorCopy(ent->v->velocity, pmove.velocity); + VectorCopy(ent->v->maxs, player_maxs); + VectorCopy(ent->v->mins, player_mins); + pmove.hullnum = SV_HullNumForPlayer(ent->xv->hull, ent->v->mins, ent->v->maxs); pmove.numphysent = 1; pmove.physents[0].model = sv.worldmodel; - AddLinksToPmove ( PROG_TO_EDICT(svprogfuncs, pr_global_struct->self), sv_areanodes ); + + for (i=0 ; i<3 ; i++) + { + extern vec3_t pmove_mins, pmove_maxs; + pmove_mins[i] = pmove.origin[i] - 256; + pmove_maxs[i] = pmove.origin[i] + 256; + } + AddLinksToPmove(ent, sv_areanodes); +// AddAllEntsToPmove(); while(msecs) //break up longer commands @@ -8363,12 +8397,160 @@ void PF_runclientphys(progfuncs_t *prinst, struct globalvars_s *pr_globals) PM_PlayerMove(1); } - if (pr_nqglobal_struct->pmove_jump_held) - *pr_nqglobal_struct->pmove_jump_held = pmove.jump_held; - if (pr_nqglobal_struct->pmove_waterjumptime) - *pr_nqglobal_struct->pmove_waterjumptime = pmove.waterjumptime; - VectorCopy(pmove.origin, *pr_nqglobal_struct->pmove_org); - VectorCopy(pmove.velocity, *pr_nqglobal_struct->pmove_vel); + ent->xv->pmove_flags = 0; + ent->xv->pmove_flags += ((int)pmove.jump_held?PMF_JUMP_HELD:0); + ent->xv->pmove_flags += ((int)pmove.onladder?PMF_LADDER:0); + ent->v->teleport_time = pmove.waterjumptime; + VectorCopy(pmove.origin, ent->v->origin); + VectorCopy(pmove.velocity, ent->v->velocity); + + + + ent->v->waterlevel = pmove.waterlevel; + + if (pmove.watertype & FTECONTENTS_SOLID) + ent->v->watertype = Q1CONTENTS_SOLID; + else if (pmove.watertype & FTECONTENTS_SKY) + ent->v->watertype = Q1CONTENTS_SKY; + else if (pmove.watertype & FTECONTENTS_LAVA) + ent->v->watertype = Q1CONTENTS_LAVA; + else if (pmove.watertype & FTECONTENTS_SLIME) + ent->v->watertype = Q1CONTENTS_SLIME; + else if (pmove.watertype & FTECONTENTS_WATER) + ent->v->watertype = Q1CONTENTS_WATER; + else + ent->v->watertype = Q1CONTENTS_EMPTY; + + if (pmove.onground) + { + ent->v->flags = (int)sv_player->v->flags | FL_ONGROUND; + ent->v->groundentity = EDICT_TO_PROG(svprogfuncs, EDICT_NUM(svprogfuncs, pmove.physents[pmove.groundent].info)); + } + else + ent->v->flags = (int)ent->v->flags & ~FL_ONGROUND; + + + SV_LinkEdict(ent, true); + for (i=0 ; iv->touch || (playertouch[n/8]&(1<<(n%8)))) + continue; + + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, touched); + pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, ent); + pr_global_struct->time = sv.time; +#ifdef VM_Q1 + if (svs.gametype == GT_Q1QVM) + Q1QVM_Touch(); + else +#endif + PR_ExecuteProgram (svprogfuncs, touched->v->touch); + playertouch[n/8] |= 1 << (n%8); + } +} + + +//EXT_CSQC_1 (called when a movement command is received. runs full acceleration + movement) +qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd) +{ + if (gfuncs.RunClientCommand) + { +#ifdef SVCHAT + if (SV_ChatMove(ucmd->impulse)) + { + ucmd->buttons = 0; + ucmd->impulse = 0; + ucmd->forwardmove = ucmd->sidemove = ucmd->upmove = 0; + } +#endif + + if (!sv_player->v->fixangle) + { + sv_player->v->v_angle[0] = SHORT2ANGLE(ucmd->angles[0]); + sv_player->v->v_angle[1] = SHORT2ANGLE(ucmd->angles[1]); + sv_player->v->v_angle[2] = SHORT2ANGLE(ucmd->angles[2]); + } + + if (progstype == PROG_H2) + sv_player->xv->light_level = 128; //hmm... HACK!!! + + sv_player->v->button0 = ucmd->buttons & 1; + sv_player->v->button2 = (ucmd->buttons >> 1) & 1; + // DP_INPUTBUTTONS + sv_player->xv->button3 = ((ucmd->buttons >> 2) & 1); + sv_player->xv->button4 = ((ucmd->buttons >> 3) & 1); + sv_player->xv->button5 = ((ucmd->buttons >> 4) & 1); + sv_player->xv->button6 = ((ucmd->buttons >> 5) & 1); + sv_player->xv->button7 = ((ucmd->buttons >> 6) & 1); + sv_player->xv->button8 = ((ucmd->buttons >> 7) & 1); + if (ucmd->impulse && SV_FiltureImpulse(ucmd->impulse, host_client->trustlevel)) + sv_player->v->impulse = ucmd->impulse; + + if (host_client->iscuffed) + { + sv_player->v->impulse = 0; + sv_player->v->button0 = 0; + } + + if (host_client->state && host_client->protocol != SCP_BAD) + { + sv_player->xv->movement[0] = ucmd->forwardmove * host_frametime; + sv_player->xv->movement[1] = ucmd->sidemove * host_frametime; + sv_player->xv->movement[2] = ucmd->upmove * host_frametime; + } + + SV_CheckVelocity(sv_player); + + // + // angles + // show 1/3 the pitch angle and all the roll angle + if (sv_player->v->health > 0) + { + if (!sv_player->v->fixangle) + { + sv_player->v->angles[PITCH] = -sv_player->v->v_angle[PITCH]/3; + sv_player->v->angles[YAW] = sv_player->v->v_angle[YAW]; + } + sv_player->v->angles[ROLL] = + V_CalcRoll (sv_player->v->angles, sv_player->v->velocity)*4; + } + + //prethink should be consistant with what the engine normally does + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, client->edict); + PR_ExecuteProgram (svprogfuncs, pr_global_struct->PlayerPreThink); + SV_RunThink (client->edict); + + + + + + + + + + + pr_global_struct->input_timelength = ucmd->msec/1000.0f; + //precision inaccuracies. :( +#define ANGLE2SHORT(x) (x) * (65536/360.0) + (pr_global_struct->input_angles)[0] = SHORT2ANGLE(ucmd->angles[0]); + (pr_global_struct->input_angles)[1] = SHORT2ANGLE(ucmd->angles[1]); + (pr_global_struct->input_angles)[2] = SHORT2ANGLE(ucmd->angles[2]); + + (pr_global_struct->input_movevalues)[0] = ucmd->forwardmove; + (pr_global_struct->input_movevalues)[1] = ucmd->sidemove; + (pr_global_struct->input_movevalues)[2] = ucmd->upmove; + pr_global_struct->input_buttons = ucmd->buttons; +// pr_global_struct->input_impulse = ucmd->impulse; + + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, client->edict); + PR_ExecuteProgram(svprogfuncs, gfuncs.RunClientCommand); + return true; + } + return false; } //DP_QC_GETSURFACE @@ -8931,8 +9113,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"calltimeofday", PF_calltimeofday, 0, 0, 0, 231}, //EXT_CSQC - {"clientstat", PF_clientstat, 0, 0, 0, 232}, - {"runclientphys", PF_runclientphys, 0, 0, 0, 233}, + {"clientstat", PF_clientstat, 0, 0, 0, 232}, //EXT_CSQC + {"globalstat", PF_globalstat, 0, 0, 0, 233}, //EXT_CSQC_1 actually //END EXT_CSQC {"isbackbuffered", PF_isbackbuffered, 0, 0, 0, 234}, {"te_bloodqw", PF_te_bloodqw, 0, 0, 0, 239}, @@ -8971,6 +9153,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs // {"cprint", PF_sv_cprint, 0, 0, 0, 338}, // #338 void(string s) cprint (EXT_CSQC) {"print", PF_print, 0, 0, 0, 339}, // #339 void(string s) print (EXT_CSQC) + {"runclientphys", PF_runclientphys, 0, 0, 0, 347}, + // {"runningserver", PF_sv_runningserver,0, 0, 0, 350}, // #350 float() isserver (EXT_CSQC) // {"registercommand", PF_sv_registercommand,0, 0, 0, 352}, // #352 void(string cmdname) registercommand (EXT_CSQC) {"wasfreed", PF_WasFreed, 0, 0, 0, 353}, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too) @@ -9550,7 +9734,7 @@ void PR_RegisterFields(void) //it's just easier to do it this way. fieldxfloat(fatness); fieldxentity(view2); fieldxvector(movement); - fieldxfloat(fteflags); + fieldxfloat(pmove_flags); fieldxfloat(vweapmodelindex); //dp extra fields diff --git a/engine/server/progdefs.h b/engine/server/progdefs.h index 07cf27bc6..4ff8dce1d 100644 --- a/engine/server/progdefs.h +++ b/engine/server/progdefs.h @@ -84,15 +84,9 @@ typedef struct nqglobalvars_s float *clientcommandframe; float *input_timelength; - float *input_angles; + vec3_t *input_angles; vec3_t *input_movevalues; float *input_buttons; - float *pmove_jump_held; - float *pmove_waterjumptime; - vec3_t *pmove_org; - vec3_t *pmove_vel; - vec3_t *pmove_mins; - vec3_t *pmove_maxs; } nqglobalvars_t; #define P_VEC(v) (pr_global_struct->V_##v) @@ -193,8 +187,7 @@ typedef struct extentvars_s float alpha; //DP_ENT_ALPHA float fatness; //FTE_PEXT_FATNESS int view2; //FTE_PEXT_VIEW2 - float fteflags; - vec3_t movement; + vec3_t movement; float vweapmodelindex; //dp extra fields @@ -248,10 +241,11 @@ typedef struct extentvars_s float hasted; //hexen2 uses this AS WELL as maxspeed //csqc stuph. - func_t SendEntity; - float SendFlags; - float Version; - float pvsflags; + func_t SendEntity; //EXT_CSQC + float SendFlags; //EXT_CSQC_1 (one of the DP guys came up with it) + float Version; //EXT_CSQC (obsolete) + float pvsflags; //EXT_CSQC_1 + float pmove_flags; //EXT_CSQC_1 (FIXME: is this really needed?) //FTE_ENT_UNIQUESPAWNID float uniquespawnid; diff --git a/engine/server/server.h b/engine/server/server.h index 0d4b4dc1c..6ba71db5a 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -817,8 +817,8 @@ typedef struct #define FL_MOVECHAIN_ANGLE 32768 // when in a move chain, will update the angle #define FL_CLASS_DEPENDENT 2097152 -#define FF_CROUCHING 1 //fte flags. seperate from flags -#define FF_LADDER 2 //fte flags. seperate from flags +#define PMF_JUMP_HELD 1 +#define PMF_LADDER 2 //pmove flags. seperate from flags #define PVSF_NORMALPVS 0x0 #define PVSF_NOTRACECHECK 0x1 diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index b9203628c..c95c93a52 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -1686,7 +1686,7 @@ void SV_WritePlayersToClient (client_t *client, edict_t *clent, qbyte *pvs, size { clstate_t clst; clst.playernum = j; - clst.onladder = (int)ent->xv->fteflags&FF_LADDER; + clst.onladder = (int)ent->xv->pmove_flags&PMF_LADDER; clst.lastcmd = &cl->lastcmd; clst.modelindex = vent->v->modelindex; clst.modelindex2 = vent->xv->vweapmodelindex; diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index a53e7ccd8..4188570eb 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -1916,7 +1916,8 @@ client_t *SVC_DirectConnect(void) #endif } - SV_FixupName(name, name, sizeof(name)); + SV_FixupName(name, temp.namebuf, sizeof(temp.namebuf)); + name = temp.namebuf; if (!*name) { @@ -2070,7 +2071,7 @@ client_t *SVC_DirectConnect(void) switch(newcl->protocol) { #ifdef Q3SERVER - case CP_QUAKE3: + case SCP_QUAKE3: Huff_PreferedCompressionCRC(); if (temp.frameunion.q3frames) Z_Free(temp.frameunion.q3frames); @@ -2078,7 +2079,8 @@ client_t *SVC_DirectConnect(void) break; #endif - case CP_QUAKE2: +#ifdef Q2SERVER + case SCP_QUAKE2: // build a new connection // accept the new client // this is the only place a client_t is ever initialized @@ -2088,6 +2090,7 @@ client_t *SVC_DirectConnect(void) temp.frameunion.q2frames = Z_Malloc(sizeof(q2client_frame_t)*Q2UPDATE_BACKUP); break; +#endif default: temp.frameunion.frames = newcl->frameunion.frames; //don't touch these. diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index a0caf55af..c46701c1d 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -1995,6 +1995,7 @@ void SV_SendClientMessages (void) { int i, j; client_t *c; + float pt = sv.physicstime; #ifdef Q3SERVER if (svs.gametype == GT_QUAKE3) @@ -2128,7 +2129,7 @@ void SV_SendClientMessages (void) if (ISNQCLIENT(c)) { //nq clients get artificial choke too c->send_message = false; - if (c->nextservertimeupdate != sv.physicstime && c->state != cs_zombie) + if (c->nextservertimeupdate != pt && c->state != cs_zombie) { c->send_message = true; diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 45249f70b..70bcc157c 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -1417,8 +1417,8 @@ void SV_Begin_Core(client_t *split) client_t *oh; int i; - if (progstype == PROG_H2 && host_client->playerclass) - host_client->edict->xv->playerclass = host_client->playerclass; //make sure it's set the same as the userinfo + if (progstype == PROG_H2 && split->playerclass) + split->edict->xv->playerclass = host_client->playerclass; //make sure it's set the same as the userinfo #ifdef Q2SERVER if (ge) @@ -1517,8 +1517,11 @@ void SV_Begin_Core(client_t *split) else #endif { + globalvars_t *pr_globals = PR_globals(svprogfuncs, PR_CURRENT); + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, split->edict); + G_FLOAT(OFS_PARM0) = split->csqcactive; //this arg is part of EXT_CSQC_1, but doesn't have to be supported by the mod PR_ExecuteProgram (svprogfuncs, pr_global_struct->ClientConnect); // actually spawn the player @@ -4640,7 +4643,7 @@ void AddLinksToPmove ( edict_t *player, areanode_t *node ) if (model) // test the point if (model->funcs.PointContents (model, player->v->origin) == FTECONTENTS_SOLID) - player->xv->fteflags = (int)player->xv->fteflags | FF_LADDER; //touch that ladder! + player->xv->pmove_flags = (int)player->xv->pmove_flags | PMF_LADDER; //touch that ladder! } } @@ -4822,6 +4825,11 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse) // end KK hack copied from QuakeForge anti-cheat //it's amazing how code get's copied around... + if (SV_RunFullQCMovement(host_client, ucmd)) + { + return; + } + cmd = *ucmd; @@ -5037,10 +5045,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse) pmove.numphysent = 1; pmove.physents[0].model = sv.worldmodel; pmove.cmd = *ucmd; - if (sv.worldmodel->fromgame == fg_quake) - pmove.hullnum = ((int)sv_player->xv->fteflags&FF_CROUCHING)?3:1; - else - pmove.hullnum = SV_HullNumForPlayer(sv_player->xv->hull, sv_player->v->mins, sv_player->v->maxs); + pmove.hullnum = SV_HullNumForPlayer(sv_player->xv->hull, sv_player->v->mins, sv_player->v->maxs); movevars.entgravity = host_client->entgravity/movevars.gravity; movevars.maxspeed = host_client->maxspeed; @@ -5059,14 +5064,14 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse) pmove_mins[i] = pmove.origin[i] - 256; pmove_maxs[i] = pmove.origin[i] + 256; } - sv_player->xv->fteflags = (int)sv_player->xv->fteflags & ~FF_LADDER; //assume not touching ladder trigger + sv_player->xv->pmove_flags = (int)sv_player->xv->pmove_flags & ~PMF_LADDER; //assume not touching ladder trigger #if 1 AddLinksToPmove ( sv_player, sv_areanodes ); #else AddAllEntsToPmove (); #endif - if ((int)sv_player->xv->fteflags & FF_LADDER) + if ((int)sv_player->xv->pmove_flags & PMF_LADDER) pmove.onladder = true; else pmove.onladder = false; @@ -5393,7 +5398,7 @@ haveannothergo: MSG_ReadDeltaUsercmd (&oldest, &oldcmd); MSG_ReadDeltaUsercmd (&oldcmd, &newcmd); } - break;; + break; } } @@ -5716,12 +5721,12 @@ void SVNQ_ReadClientMove (usercmd_t *move) else host_client->last_sequence = 0; cltime = MSG_ReadFloat (); + if (cltime < move->fservertime) + cltime = move->fservertime; if (cltime > sv.time) cltime = sv.time; if (cltime < sv.time - 2) //if you do lag more than this, you won't get your free time. cltime = sv.time - 2; - if (cltime < move->fservertime) - cltime = move->fservertime; timesincelast = cltime - move->fservertime; move->fservertime = cltime; move->servertime = move->fservertime; @@ -5800,6 +5805,23 @@ void SVNQ_ReadClientMove (usercmd_t *move) if (cursor_entitynumber) cursor_entitynumber->edict = entnum; } + if (SV_RunFullQCMovement(host_client, move)) + { + pr_global_struct->time = sv.physicstime; + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); +#ifdef VM_Q1 + if (svs.gametype == GT_Q1QVM) + Q1QVM_PostThink(); + else +#endif + { + if (pr_global_struct->PlayerPostThink) + PR_ExecuteProgram (svprogfuncs, pr_global_struct->PlayerPostThink); + } + host_client->isindependant = true; + return; + } + if (i && SV_FiltureImpulse(i, host_client->trustlevel)) host_client->edict->v->impulse = i; diff --git a/engine/server/svhl_game.c b/engine/server/svhl_game.c index b3e3ddecf..d6008ba2f 100644 --- a/engine/server/svhl_game.c +++ b/engine/server/svhl_game.c @@ -11,8 +11,6 @@ I think globals.maxentities is the hard cap, rather than current max like in q1. #include "crc.h" #include "model_hl.h" -#define GAMECODEMODULE Cvar_Get("hl_svgame", "valve/dlls/mp.dll", 0, "halflife cvars")->string - #define ignore(s) Con_Printf("Fixme: " s "\n") #define notimp(l) Con_Printf("halflife sv builtin not implemented on line %i\n", l) @@ -762,15 +760,27 @@ void GHL_GetGameDir(char *gamedir) } unk GHL_Cvar_RegisterVariable(unk){notimp(__LINE__);} unk GHL_FadeClientVolume(unk){notimp(__LINE__);} -unk GHL_SetClientMaxspeed(unk){notimp(__LINE__);} +unk GHL_SetClientMaxspeed(unk) +{ + notimp(__LINE__); +} unk GHL_CreateFakeClient(unk){notimp(__LINE__);} unk GHL_RunPlayerMove(unk){notimp(__LINE__);} int GHL_NumberOfEntities(void) { return 0; } -unk GHL_GetInfoKeyBuffer(unk){notimp(__LINE__);} -unk GHL_InfoKeyValue(unk){notimp(__LINE__);} +char *GHL_GetInfoKeyBuffer(hledict_t *ed) +{ + if (!ed) + return svs.info; + + return svs.clients[ed - SVHL_Edict - 1].userinfo; +} +char *GHL_InfoKeyValue(char *infostr, char *key) +{ + return Info_ValueForKey(infostr, key); +} unk GHL_SetKeyValue(unk){notimp(__LINE__);} unk GHL_SetClientKeyValue(unk){notimp(__LINE__);} unk GHL_IsMapValid(unk){notimp(__LINE__);}