added cprint console command.

fixed nq client loading-screen persisting bug
fixed nq clients getting flooded by packets.
fixed nq clients not receiving any entities
removed a bit of redundant code in pmove
fteqcc: merged array function calls with real function calls, fixing return values in the process.
vid_preservegamma now defaults to off. windows sucks.
tweeked the prototype FTE_CSQC_SKELETONOBJECTS a bit. still not official nor advertised.
added a little bit more functionality to halflife support
csqc got some pmove tweeks. this is how I want it to work. nothing has been changed that is really incompatible with darkplaces in this commit.
added markers around some ext_csqc_1 features.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3178 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2009-04-19 00:50:42 +00:00
parent 42b4577802
commit 5f1a9d8cbf
20 changed files with 1141 additions and 614 deletions

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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!

View File

@ -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",

View File

@ -105,4 +105,4 @@ enum
LS_CLIENT,
};
int SCR_GetLoadingStage(void);
void SCR_SetLoadingStage(int stage);
void SCR_SetLoadingStage(int stage);

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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 ; i<pmove.numtouch ; i++)
{
if (pmove.physents[pmove.touchindex[i]].notouch)
continue;
n = pmove.physents[pmove.touchindex[i]].info;
touched = EDICT_NUM(svprogfuncs, n);
if (!ent->v->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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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__);}