void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius);
void CSQC_RelinkAllEntities (int drawmask);
void CSQC_RelinkCSQCEntities (void);
-const char *Key_GetBind (int key);
// #1 void(vector ang) makevectors
static void VM_CL_makevectors (void)
if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
- trace = CL_TraceLine(v1, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true);
+ trace = CL_TraceLine(v1, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true, false);
CL_VM_SetTraceGlobals(&trace, svent);
// R_TimeReport("traceline");
start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
stop[2] = start[2] - 2*sv_stepheight.value;
- trace = CL_TraceLine(start, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+ trace = CL_TraceLine(start, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true, false);
if (trace.fraction == 1.0)
return;
start[0] = stop[0] = x ? maxs[0] : mins[0];
start[1] = stop[1] = y ? maxs[1] : mins[1];
- trace = CL_TraceLine(start, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+ trace = CL_TraceLine(start, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true, false);
if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
bottom = trace.endpos[2];
S_StaticSound (s, f, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3)*64);
}
-// #92 vector(vector org) getlight (DP_QC_GETLIGHT)
+// #92 vector(vector org[, float lpflag]) getlight (DP_QC_GETLIGHT)
static void VM_CL_getlight (void)
{
vec3_t ambientcolor, diffusecolor, diffusenormal;
vec_t *p;
- VM_SAFEPARMCOUNT(1, VM_CL_getlight);
+ VM_SAFEPARMCOUNTRANGE(1, 2, VM_CL_getlight);
p = PRVM_G_VECTOR(OFS_PARM0);
VectorClear(ambientcolor);
VectorClear(diffusecolor);
VectorClear(diffusenormal);
- if (cl.worldmodel && cl.worldmodel->brush.LightPoint)
+ if (prog->argc >= 2)
+ R_CompleteLightPoint(ambientcolor, diffusecolor, diffusenormal, p, PRVM_G_FLOAT(OFS_PARM1));
+ else if (cl.worldmodel && cl.worldmodel->brush.LightPoint)
cl.worldmodel->brush.LightPoint(cl.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
}
-
//============================================================================
//[515]: SCENE MANAGER builtins
extern qboolean CSQC_AddRenderEdict (prvm_edict_t *ed, int edictnum);//csprogs.c
static void CSQC_R_RecalcView (void)
{
extern matrix4x4_t viewmodelmatrix;
- Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], 1);
- Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], cl_viewmodel_scale.value);
+ Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, cl.csqc_vieworigin[0], cl.csqc_vieworigin[1], cl.csqc_vieworigin[2], cl.csqc_viewangles[0], cl.csqc_viewangles[1], cl.csqc_viewangles[2], 1);
+ Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, cl.csqc_vieworigin[0], cl.csqc_vieworigin[1], cl.csqc_vieworigin[2], cl.csqc_viewangles[0], cl.csqc_viewangles[1], cl.csqc_viewangles[2], cl_viewmodel_scale.value);
}
void CL_RelinkLightFlashes(void);
r_refdef.view.ortho_y = scr_fov.value * (3.0 / 4.0);
r_refdef.view.clear = true;
r_refdef.view.isoverlay = false;
- // FIXME: restore cl.csqc_origin
- // FIXME: restore cl.csqc_angles
- cl.csqc_vidvars.drawworld = r_drawworld.integer;
+ VectorCopy(cl.csqc_vieworiginfromengine, cl.csqc_vieworigin);
+ VectorCopy(cl.csqc_viewanglesfromengine, cl.csqc_viewangles);
+ cl.csqc_vidvars.drawworld = r_drawworld.integer != 0;
cl.csqc_vidvars.drawenginesbar = false;
cl.csqc_vidvars.drawcrosshair = false;
}
prog->globals.client->time = cl.time;
for(i=1;i<prog->num_edicts;i++)
{
+ // so we can easily check if CSQC entity #edictnum is currently drawn
+ cl.csqcrenderentities[i].entitynumber = 0;
ed = &prog->edicts[i];
if(ed->priv.required->free)
continue;
PRVM_G_FLOAT(OFS_RETURN) = r_refdef.view.height;
break;
case VF_VIEWPORT:
- VM_Warning("VM_CL_R_GetView : VF_VIEWPORT can't be retrieved, use VF_MIN/VF_SIZE instead\n", c);
+ VM_Warning("VM_CL_R_GetView : VF_VIEWPORT can't be retrieved, use VF_MIN/VF_SIZE instead\n");
break;
case VF_FOV:
VectorSet(PRVM_G_VECTOR(OFS_RETURN), r_refdef.view.ortho_x, r_refdef.view.ortho_y, 0);
PRVM_G_FLOAT(OFS_RETURN) = r_refdef.view.ortho_y;
break;
case VF_ORIGIN:
- VectorCopy(cl.csqc_origin, PRVM_G_VECTOR(OFS_RETURN));
+ VectorCopy(cl.csqc_vieworigin, PRVM_G_VECTOR(OFS_RETURN));
break;
case VF_ORIGIN_X:
- PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_origin[0];
+ PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_vieworigin[0];
break;
case VF_ORIGIN_Y:
- PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_origin[1];
+ PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_vieworigin[1];
break;
case VF_ORIGIN_Z:
- PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_origin[2];
+ PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_vieworigin[2];
break;
case VF_ANGLES:
- VectorCopy(cl.csqc_angles, PRVM_G_VECTOR(OFS_RETURN));
+ VectorCopy(cl.csqc_viewangles, PRVM_G_VECTOR(OFS_RETURN));
break;
case VF_ANGLES_X:
- PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_angles[0];
+ PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_viewangles[0];
break;
case VF_ANGLES_Y:
- PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_angles[1];
+ PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_viewangles[1];
break;
case VF_ANGLES_Z:
- PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_angles[2];
+ PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_viewangles[2];
break;
case VF_DRAWWORLD:
PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_vidvars.drawworld;
case VF_MIN:
r_refdef.view.x = (int)(f[0]);
r_refdef.view.y = (int)(f[1]);
+ DrawQ_RecalcView();
break;
case VF_MIN_X:
r_refdef.view.x = (int)(k);
+ DrawQ_RecalcView();
break;
case VF_MIN_Y:
r_refdef.view.y = (int)(k);
+ DrawQ_RecalcView();
break;
case VF_SIZE:
r_refdef.view.width = (int)(f[0]);
r_refdef.view.height = (int)(f[1]);
+ DrawQ_RecalcView();
break;
case VF_SIZE_X:
r_refdef.view.width = (int)(k);
+ DrawQ_RecalcView();
break;
case VF_SIZE_Y:
r_refdef.view.height = (int)(k);
+ DrawQ_RecalcView();
break;
case VF_VIEWPORT:
r_refdef.view.x = (int)(f[0]);
f = PRVM_G_VECTOR(OFS_PARM2);
r_refdef.view.width = (int)(f[0]);
r_refdef.view.height = (int)(f[1]);
+ DrawQ_RecalcView();
break;
case VF_FOV:
r_refdef.view.frustum_x = tan(f[0] * M_PI / 360.0);r_refdef.view.ortho_x = f[0];
r_refdef.view.frustum_y = tan(k * M_PI / 360.0);r_refdef.view.ortho_y = k;
break;
case VF_ORIGIN:
- VectorCopy(f, cl.csqc_origin);
+ VectorCopy(f, cl.csqc_vieworigin);
CSQC_R_RecalcView();
break;
case VF_ORIGIN_X:
- cl.csqc_origin[0] = k;
+ cl.csqc_vieworigin[0] = k;
CSQC_R_RecalcView();
break;
case VF_ORIGIN_Y:
- cl.csqc_origin[1] = k;
+ cl.csqc_vieworigin[1] = k;
CSQC_R_RecalcView();
break;
case VF_ORIGIN_Z:
- cl.csqc_origin[2] = k;
+ cl.csqc_vieworigin[2] = k;
CSQC_R_RecalcView();
break;
case VF_ANGLES:
- VectorCopy(f, cl.csqc_angles);
+ VectorCopy(f, cl.csqc_viewangles);
CSQC_R_RecalcView();
break;
case VF_ANGLES_X:
- cl.csqc_angles[0] = k;
+ cl.csqc_viewangles[0] = k;
CSQC_R_RecalcView();
break;
case VF_ANGLES_Y:
- cl.csqc_angles[1] = k;
+ cl.csqc_viewangles[1] = k;
CSQC_R_RecalcView();
break;
case VF_ANGLES_Z:
- cl.csqc_angles[2] = k;
+ cl.csqc_viewangles[2] = k;
CSQC_R_RecalcView();
break;
case VF_DRAWWORLD:
VM_SAFEPARMCOUNT(1, VM_CL_unproject);
f = PRVM_G_VECTOR(OFS_PARM0);
- if(v_flipped.integer)
- f[0] = (2 * r_refdef.view.x + r_refdef.view.width) * (vid_conwidth.integer / (float) vid.width) - f[0];
VectorSet(temp,
f[2],
- (-1.0 + 2.0 * (f[0] / (vid_conwidth.integer / (float) vid.width) - r_refdef.view.x) / r_refdef.view.width) * f[2] * -r_refdef.view.frustum_x,
- (-1.0 + 2.0 * (f[1] / (vid_conheight.integer / (float) vid.height) - r_refdef.view.y) / r_refdef.view.height) * f[2] * -r_refdef.view.frustum_y);
+ (-1.0 + 2.0 * (f[0] / vid_conwidth.integer)) * f[2] * -r_refdef.view.frustum_x,
+ (-1.0 + 2.0 * (f[1] / vid_conheight.integer)) * f[2] * -r_refdef.view.frustum_y);
+ if(v_flipped.integer)
+ temp[1] = -temp[1];
Matrix4x4_Transform(&r_refdef.view.matrix, temp, PRVM_G_VECTOR(OFS_RETURN));
}
if(v_flipped.integer)
v[1] = -v[1];
VectorSet(PRVM_G_VECTOR(OFS_RETURN),
- (vid_conwidth.integer / (float) vid.width) * (r_refdef.view.x + r_refdef.view.width*0.5*(1.0+v[1]/v[0]/-r_refdef.view.frustum_x)),
- (vid_conheight.integer / (float) vid.height) * (r_refdef.view.y + r_refdef.view.height*0.5*(1.0+v[2]/v[0]/-r_refdef.view.frustum_y)),
+ vid_conwidth.integer * (0.5*(1.0+v[1]/v[0]/-r_refdef.view.frustum_x)),
+ vid_conheight.integer * (0.5*(1.0+v[2]/v[0]/-r_refdef.view.frustum_y)),
v[0]);
+ // explanation:
+ // after transforming, relative position to viewport (0..1) = 0.5 * (1 + v[2]/v[0]/-frustum_{x \or y})
+ // as 2D drawing honors the viewport too, to get the same pixel, we simply multiply this by conwidth/height
}
//#330 float(float stnum) getstatf (EXT_CSQC)
static void VM_CL_boxparticles (void)
{
int effectnum;
- prvm_edict_t *own;
+ // prvm_edict_t *own;
float *origin_from, *origin_to, *dir_from, *dir_to;
float count;
int flags;
VM_SAFEPARMCOUNTRANGE(7, 8, VM_CL_boxparticles);
effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
- own = PRVM_G_EDICT(OFS_PARM1); // TODO find use for this
+ // own = PRVM_G_EDICT(OFS_PARM1); // TODO find use for this
origin_from = PRVM_G_VECTOR(OFS_PARM2);
origin_to = PRVM_G_VECTOR(OFS_PARM3);
dir_from = PRVM_G_VECTOR(OFS_PARM4);
cl.csqc_paused = false;
}
-//#342 string(float keynum) getkeybind (EXT_CSQC)
-static void VM_CL_getkeybind (void)
-{
- VM_SAFEPARMCOUNT(1, VM_CL_getkeybind);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(Key_GetBind((int)PRVM_G_FLOAT(OFS_PARM0)));
-}
-
//#343 void(float usecursor) setcursormode (EXT_CSQC)
static void VM_CL_setcursormode (void)
{
// texture found and loaded
// skip over the jpeg as we don't need it
for(i = 0; i < size; ++i)
- MSG_ReadByte();
+ (void) MSG_ReadByte();
}
else
{
// use the attached jpeg as texture
buf = (unsigned char *) Mem_Alloc(tempmempool, size);
MSG_ReadBytes(size, buf);
- data = JPEG_LoadImage_BGRA(buf, size);
+ data = JPEG_LoadImage_BGRA(buf, size, NULL);
Mem_Free(buf);
Draw_NewPic(name, image_width, image_height, false, data);
Mem_Free(data);
if (val && val->_float != 0)
scale = val->_float;
- // TODO do we need the same weird angle inverting logic here as in the server side case?
if(viewmatrix)
- Matrix4x4_CreateFromQuakeEntity(out, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], scale * cl_viewmodel_scale.value);
+ *out = r_refdef.view.matrix;
+ else if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.renderflags)) && ((int)val->_float & RF_USEAXIS))
+ {
+ vec3_t forward;
+ vec3_t left;
+ vec3_t up;
+ vec3_t origin;
+ VectorScale(prog->globals.client->v_forward, scale, forward);
+ VectorScale(prog->globals.client->v_right, -scale, left);
+ VectorScale(prog->globals.client->v_up, scale, up);
+ VectorCopy(ent->fields.client->origin, origin);
+ Matrix4x4_FromVectors(out, forward, left, up, origin);
+ }
else
{
pitchsign = CL_GetPitchSign(ent);
void VM_CL_ParticleThemeFromGlobals(vmparticletheme_t *theme)
{
theme->typeindex = (unsigned short)*vmpartspawner.particle_type;
- theme->blendmode = (pblend_t)*vmpartspawner.particle_blendmode;
- theme->orientation = (porientation_t)*vmpartspawner.particle_orientation;
+ theme->blendmode = (pblend_t)(int)*vmpartspawner.particle_blendmode;
+ theme->orientation = (porientation_t)(int)*vmpartspawner.particle_orientation;
theme->color1 = ((int)vmpartspawner.particle_color1[0] << 16) + ((int)vmpartspawner.particle_color1[1] << 8) + ((int)vmpartspawner.particle_color1[2]);
theme->color2 = ((int)vmpartspawner.particle_color2[0] << 16) + ((int)vmpartspawner.particle_color2[1] << 8) + ((int)vmpartspawner.particle_color2[2]);
theme->tex = (int)*vmpartspawner.particle_tex;
if (prog->argc < 3) // global-set particle
{
- part = CL_NewParticle(org, (unsigned short)*vmpartspawner.particle_type, ((int)(vmpartspawner.particle_color1[0]) << 16) + ((int)(vmpartspawner.particle_color1[1]) << 8) + ((int)(vmpartspawner.particle_color1[2])), ((int)vmpartspawner.particle_color2[0] << 16) + ((int)vmpartspawner.particle_color2[1] << 8) + ((int)vmpartspawner.particle_color2[2]), (int)*vmpartspawner.particle_tex, *vmpartspawner.particle_size, *vmpartspawner.particle_sizeincrease, *vmpartspawner.particle_alpha*256, *vmpartspawner.particle_alphafade*256, *vmpartspawner.particle_gravity, *vmpartspawner.particle_bounce, org[0], org[1], org[2], dir[0], dir[1], dir[2], *vmpartspawner.particle_airfriction, *vmpartspawner.particle_liquidfriction, *vmpartspawner.particle_originjitter, *vmpartspawner.particle_velocityjitter, (*vmpartspawner.particle_qualityreduction) ? true : false, *vmpartspawner.particle_time, *vmpartspawner.particle_stretch, (pblend_t)*vmpartspawner.particle_blendmode, (porientation_t)*vmpartspawner.particle_orientation, (int)(vmpartspawner.particle_staincolor1[0])*65536 + (int)(vmpartspawner.particle_staincolor1[1])*256 + (int)(vmpartspawner.particle_staincolor1[2]), (int)(vmpartspawner.particle_staincolor2[0])*65536 + (int)(vmpartspawner.particle_staincolor2[1])*256 + (int)(vmpartspawner.particle_staincolor2[2]), (int)*vmpartspawner.particle_staintex, *vmpartspawner.particle_stainalpha*256, *vmpartspawner.particle_stainsize, *vmpartspawner.particle_angle, *vmpartspawner.particle_spin, NULL);
+ part = CL_NewParticle(org, (unsigned short)*vmpartspawner.particle_type, ((int)(vmpartspawner.particle_color1[0]) << 16) + ((int)(vmpartspawner.particle_color1[1]) << 8) + ((int)(vmpartspawner.particle_color1[2])), ((int)vmpartspawner.particle_color2[0] << 16) + ((int)vmpartspawner.particle_color2[1] << 8) + ((int)vmpartspawner.particle_color2[2]), (int)*vmpartspawner.particle_tex, *vmpartspawner.particle_size, *vmpartspawner.particle_sizeincrease, *vmpartspawner.particle_alpha*256, *vmpartspawner.particle_alphafade*256, *vmpartspawner.particle_gravity, *vmpartspawner.particle_bounce, org[0], org[1], org[2], dir[0], dir[1], dir[2], *vmpartspawner.particle_airfriction, *vmpartspawner.particle_liquidfriction, *vmpartspawner.particle_originjitter, *vmpartspawner.particle_velocityjitter, (*vmpartspawner.particle_qualityreduction) ? true : false, *vmpartspawner.particle_time, *vmpartspawner.particle_stretch, (pblend_t)(int)*vmpartspawner.particle_blendmode, (porientation_t)(int)*vmpartspawner.particle_orientation, (int)(vmpartspawner.particle_staincolor1[0])*65536 + (int)(vmpartspawner.particle_staincolor1[1])*256 + (int)(vmpartspawner.particle_staincolor1[2]), (int)(vmpartspawner.particle_staincolor2[0])*65536 + (int)(vmpartspawner.particle_staincolor2[1])*256 + (int)(vmpartspawner.particle_staincolor2[2]), (int)*vmpartspawner.particle_staintex, *vmpartspawner.particle_stainalpha*256, *vmpartspawner.particle_stainsize, *vmpartspawner.particle_angle, *vmpartspawner.particle_spin, NULL);
if (!part)
{
PRVM_G_FLOAT(OFS_RETURN) = 0;
org = PRVM_G_VECTOR(OFS_PARM0);
dir = PRVM_G_VECTOR(OFS_PARM1);
if (prog->argc < 5) // global-set particle
- part = CL_NewParticle(org, (unsigned short)*vmpartspawner.particle_type, ((int)vmpartspawner.particle_color1[0] << 16) + ((int)vmpartspawner.particle_color1[1] << 8) + ((int)vmpartspawner.particle_color1[2]), ((int)vmpartspawner.particle_color2[0] << 16) + ((int)vmpartspawner.particle_color2[1] << 8) + ((int)vmpartspawner.particle_color2[2]), (int)*vmpartspawner.particle_tex, *vmpartspawner.particle_size, *vmpartspawner.particle_sizeincrease, *vmpartspawner.particle_alpha*256, *vmpartspawner.particle_alphafade*256, *vmpartspawner.particle_gravity, *vmpartspawner.particle_bounce, org[0], org[1], org[2], dir[0], dir[1], dir[2], *vmpartspawner.particle_airfriction, *vmpartspawner.particle_liquidfriction, *vmpartspawner.particle_originjitter, *vmpartspawner.particle_velocityjitter, (*vmpartspawner.particle_qualityreduction) ? true : false, *vmpartspawner.particle_time, *vmpartspawner.particle_stretch, (pblend_t)*vmpartspawner.particle_blendmode, (porientation_t)*vmpartspawner.particle_orientation, ((int)vmpartspawner.particle_staincolor1[0] << 16) + ((int)vmpartspawner.particle_staincolor1[1] << 8) + ((int)vmpartspawner.particle_staincolor1[2]), ((int)vmpartspawner.particle_staincolor2[0] << 16) + ((int)vmpartspawner.particle_staincolor2[1] << 8) + ((int)vmpartspawner.particle_staincolor2[2]), (int)*vmpartspawner.particle_staintex, *vmpartspawner.particle_stainalpha*256, *vmpartspawner.particle_stainsize, *vmpartspawner.particle_angle, *vmpartspawner.particle_spin, NULL);
+ part = CL_NewParticle(org, (unsigned short)*vmpartspawner.particle_type, ((int)vmpartspawner.particle_color1[0] << 16) + ((int)vmpartspawner.particle_color1[1] << 8) + ((int)vmpartspawner.particle_color1[2]), ((int)vmpartspawner.particle_color2[0] << 16) + ((int)vmpartspawner.particle_color2[1] << 8) + ((int)vmpartspawner.particle_color2[2]), (int)*vmpartspawner.particle_tex, *vmpartspawner.particle_size, *vmpartspawner.particle_sizeincrease, *vmpartspawner.particle_alpha*256, *vmpartspawner.particle_alphafade*256, *vmpartspawner.particle_gravity, *vmpartspawner.particle_bounce, org[0], org[1], org[2], dir[0], dir[1], dir[2], *vmpartspawner.particle_airfriction, *vmpartspawner.particle_liquidfriction, *vmpartspawner.particle_originjitter, *vmpartspawner.particle_velocityjitter, (*vmpartspawner.particle_qualityreduction) ? true : false, *vmpartspawner.particle_time, *vmpartspawner.particle_stretch, (pblend_t)(int)*vmpartspawner.particle_blendmode, (porientation_t)(int)*vmpartspawner.particle_orientation, ((int)vmpartspawner.particle_staincolor1[0] << 16) + ((int)vmpartspawner.particle_staincolor1[1] << 8) + ((int)vmpartspawner.particle_staincolor1[2]), ((int)vmpartspawner.particle_staincolor2[0] << 16) + ((int)vmpartspawner.particle_staincolor2[1] << 8) + ((int)vmpartspawner.particle_staincolor2[2]), (int)*vmpartspawner.particle_staintex, *vmpartspawner.particle_stainalpha*256, *vmpartspawner.particle_stainsize, *vmpartspawner.particle_angle, *vmpartspawner.particle_spin, NULL);
else // themed particle
{
themenum = (int)PRVM_G_FLOAT(OFS_PARM4);
{
rtexture_t *texture;
int drawflag;
+ qboolean hasalpha;
unsigned short elements[3];
}vmpolygons_triangle_t;
unsigned short *data_sortedelement3s;
qboolean begin_active;
+ int begin_draw2d;
rtexture_t *begin_texture;
int begin_drawflag;
int begin_vertices;
float begin_vertex[VMPOLYGONS_MAXPOINTS][3];
float begin_color[VMPOLYGONS_MAXPOINTS][4];
float begin_texcoord[VMPOLYGONS_MAXPOINTS][2];
+ qboolean begin_texture_hasalpha;
} vmpolygons_t;
// FIXME: make VM_CL_R_Polygon functions use Debug_Polygon functions?
vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
if(polys->progstarttime != prog->starttime) // from other progs? won't draw these (this can cause crashes!)
return;
- R_Mesh_ResetTextureState();
+// R_Mesh_ResetTextureState();
R_EntityMatrix(&identitymatrix);
GL_CullFace(GL_NONE);
- R_Mesh_VertexPointer(polys->data_vertex3f, 0, 0);
- R_Mesh_ColorPointer(polys->data_color4f, 0, 0);
- R_Mesh_TexCoordPointer(0, 2, polys->data_texcoord2f, 0, 0);
+ GL_DepthTest(true); // polys in 3D space shall always have depth test
+ GL_DepthRange(0, 1);
+ R_Mesh_PrepareVertices_Generic_Arrays(polys->num_vertices, polys->data_vertex3f, polys->data_color4f, polys->data_texcoord2f);
for (surfacelistindex = 0;surfacelistindex < numsurfaces;)
{
int numtriangles = 0;
rtexture_t *tex = polys->data_triangles[surfacelist[surfacelistindex]].texture;
int drawflag = polys->data_triangles[surfacelist[surfacelistindex]].drawflag;
- // this can't call _DrawQ_ProcessDrawFlag, but should be in sync with it
- // FIXME factor this out
- if(drawflag == DRAWFLAG_ADDITIVE)
- GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
- else if(drawflag == DRAWFLAG_MODULATE)
- GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
- else if(drawflag == DRAWFLAG_2XMODULATE)
- GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
- else if(drawflag == DRAWFLAG_SCREEN)
- GL_BlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ONE);
- else
- GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ DrawQ_ProcessDrawFlag(drawflag, polys->data_triangles[surfacelist[surfacelistindex]].hasalpha);
R_SetupShader_Generic(tex, NULL, GL_MODULATE, 1);
numtriangles = 0;
for (;surfacelistindex < numsurfaces;surfacelistindex++)
VectorCopy(polys->data_triangles[surfacelist[surfacelistindex]].elements, polys->data_sortedelement3s + 3*numtriangles);
numtriangles++;
}
- R_Mesh_Draw(0, polys->num_vertices, 0, numtriangles, NULL, polys->data_sortedelement3s, 0, 0);
+ R_Mesh_Draw(0, polys->num_vertices, 0, numtriangles, NULL, NULL, 0, polys->data_sortedelement3s, NULL, 0);
}
}
void VMPolygons_Store(vmpolygons_t *polys)
{
- if (r_refdef.draw2dstage)
+ qboolean hasalpha;
+ int i;
+
+ // detect if we have alpha
+ hasalpha = polys->begin_texture_hasalpha;
+ for(i = 0; !hasalpha && (i < polys->begin_vertices); ++i)
+ if(polys->begin_color[i][3] < 1)
+ hasalpha = true;
+
+ if (polys->begin_draw2d)
{
// draw the polygon as 2D immediately
drawqueuemesh_t mesh;
mesh.data_vertex3f = polys->begin_vertex[0];
mesh.data_color4f = polys->begin_color[0];
mesh.data_texcoord2f = polys->begin_texcoord[0];
- DrawQ_Mesh(&mesh, polys->begin_drawflag);
+ DrawQ_Mesh(&mesh, polys->begin_drawflag, hasalpha);
}
else
{
int i;
if (polys->max_triangles < polys->num_triangles + polys->begin_vertices-2)
{
- polys->max_triangles *= 2;
+ while (polys->max_triangles < polys->num_triangles + polys->begin_vertices-2)
+ polys->max_triangles *= 2;
VM_ResizePolygons(polys);
}
if (polys->num_vertices + polys->begin_vertices <= polys->max_vertices)
polys->data_triangles[polys->num_triangles].elements[0] = polys->num_vertices;
polys->data_triangles[polys->num_triangles].elements[1] = polys->num_vertices + i+1;
polys->data_triangles[polys->num_triangles].elements[2] = polys->num_vertices + i+2;
+ polys->data_triangles[polys->num_triangles].hasalpha = hasalpha;
polys->num_triangles++;
}
polys->num_vertices += polys->begin_vertices;
polys->num_vertices = 0; // otherwise it's not rendered at all and prints an error message --blub */
}
-//void(string texturename, float flag) R_BeginPolygon
+//void(string texturename, float flag[, float is2d]) R_BeginPolygon
void VM_CL_R_PolygonBegin (void)
{
const char *picname;
// better management of flags, and is more suited for 3D rendering), what
// about supporting Q3 shaders?
- VM_SAFEPARMCOUNT(2, VM_CL_R_PolygonBegin);
+ VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_R_PolygonBegin);
if (!polys->initialized)
VM_InitPolygons(polys);
}
polys->begin_texture = (sf && sf->base) ? sf->base : r_texture_white;
+ polys->begin_texture_hasalpha = (sf && sf->base) ? sf->hasalpha : false;
polys->begin_drawflag = (int)PRVM_G_FLOAT(OFS_PARM1) & DRAWFLAG_MASK;
polys->begin_vertices = 0;
polys->begin_active = true;
+ polys->begin_draw2d = (prog->argc >= 3 ? (int)PRVM_G_FLOAT(OFS_PARM2) : r_refdef.draw2dstage);
}
//void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
Con_Printf("Debug_PolygonBegin: called twice without Debug_PolygonEnd after first\n");
return;
}
- debugPolys.begin_texture = picname[0] ? Draw_CachePic (picname)->tex : r_texture_white;
+ debugPolys.begin_texture = picname[0] ? Draw_CachePic_Flags (picname, CACHEPICFLAG_NOTPERSISTENT)->tex : r_texture_white;
debugPolys.begin_drawflag = drawflag;
debugPolys.begin_vertices = 0;
debugPolys.begin_active = true;
start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
stop[2] = start[2] - 2*sv_stepheight.value;
- trace = CL_TraceLine(start, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true);
+ trace = CL_TraceLine(start, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true, false);
if (trace.fraction == 1.0)
return false;
start[0] = stop[0] = x ? maxs[0] : mins[0];
start[1] = stop[1] = y ? maxs[1] : mins[1];
- trace = CL_TraceLine(start, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true);
+ trace = CL_TraceLine(start, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true, false);
if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
bottom = trace.endpos[2];
break;
if (i == MAX_EDICTS)
return;
- prog->skeletons[i] = skeleton = Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
+ prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
PRVM_G_FLOAT(OFS_RETURN) = i + 1;
skeleton->model = model;
skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
PRVM_G_FLOAT(OFS_RETURN) = 0;
if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
return;
- PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
+ PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname);
}
// #269 vector(float skel, float bonenum) skel_get_bonerel = #269; // (FTE_CSQC_SKELETONOBJECTS) get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
}
+void VM_CL_RotateMoves(void)
+{
+ /*
+ * Obscure builtin used by GAME_XONOTIC.
+ *
+ * Edits the input history of cl_movement by rotating all move commands
+ * currently in the queue using the given transform.
+ *
+ * The vector passed is an "angles transform" as used by warpzonelib, i.e.
+ * v_angle-like (non-inverted) euler angles that perform the rotation
+ * of the space that is to be done.
+ *
+ * This is meant to be used as a fixangle replacement after passing
+ * through a warpzone/portal: the client is told about the warp transform,
+ * and calls this function in the same frame as the one on which the
+ * client's origin got changed by the serverside teleport. Then this code
+ * transforms the pre-warp input (which matches the empty space behind
+ * the warp plane) into post-warp input (which matches the target area
+ * of the warp). Also, at the same time, the client has to use
+ * R_SetView to adjust VF_CL_VIEWANGLES according to the same transform.
+ *
+ * This together allows warpzone motion to be perfectly predicted by
+ * the client!
+ *
+ * Furthermore, for perfect warpzone behaviour, the server side also
+ * has to detect input the client sent before it received the origin
+ * update, but after the warp occurred on the server, and has to adjust
+ * input appropriately.
+ */
+ matrix4x4_t m;
+ vec3_t v = {0, 0, 0};
+ vec3_t x, y, z;
+ VM_SAFEPARMCOUNT(1, VM_CL_RotateMoves);
+ AngleVectorsFLU(PRVM_G_VECTOR(OFS_PARM0), x, y, z);
+ Matrix4x4_FromVectors(&m, x, y, z, v);
+ CL_RotateMoves(&m);
+}
+
//============================================================================
// To create a almost working builtin file from this replace:
VM_CL_R_SetView, // #303 float(float property, ...) setproperty (EXT_CSQC)
VM_CL_R_RenderScene, // #304 void() renderscene (EXT_CSQC)
VM_CL_R_AddDynamicLight, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
-VM_CL_R_PolygonBegin, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
+VM_CL_R_PolygonBegin, // #306 void(string texturename, float flag, float is2d[NYI: , float lines]) R_BeginPolygon
VM_CL_R_PolygonVertex, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
VM_CL_R_PolygonEnd, // #308 void() R_EndPolygon
NULL /* R_LoadWorldModel in menu VM, should stay unassigned in client*/, // #309
VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
VM_keynumtostring, // #340 string(float keynum) keynumtostring (EXT_CSQC)
VM_stringtokeynum, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
-VM_CL_getkeybind, // #342 string(float keynum) getkeybind (EXT_CSQC)
+VM_getkeybind, // #342 string(float keynum[, float bindmap]) getkeybind (EXT_CSQC)
VM_CL_setcursormode, // #343 void(float usecursor) setcursormode (EXT_CSQC)
VM_CL_getmousepos, // #344 vector() getmousepos (EXT_CSQC)
VM_CL_getinputstate, // #345 float(float framenum) getinputstate (EXT_CSQC)
VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
VM_CL_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
VM_CL_videoplaying, // #355
-NULL, // #356
-NULL, // #357
+VM_findfont, // #356 float(string fontname) loadfont (DP_GFX_FONTS)
+VM_loadfont, // #357 float(string fontname, string fontmaps, string sizes, float slot) loadfont (DP_GFX_FONTS)
NULL, // #358
NULL, // #359
VM_CL_ReadByte, // #360 float() readbyte (EXT_CSQC)
VM_uri_escape, // #510 string(string in) uri_escape = #510;
VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
-VM_uri_get, // #513 float(string uril, float id) uri_get = #512; (DP_QC_URI_GET)
+VM_uri_get, // #513 float(string uri, float id, [string post_contenttype, string post_delim, [float buf]]) uri_get = #513; (DP_QC_URI_GET, DP_QC_URI_POST)
VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
VM_keynumtostring, // #520 string keynumtostring(float keynum)
-VM_findkeysforcommand, // #521 string findkeysforcommand(string command)
+VM_findkeysforcommand, // #521 string findkeysforcommand(string command[, float bindmap])
VM_CL_InitParticleSpawner, // #522 void(float max_themes) initparticlespawner (DP_CSQC_SPAWNPARTICLE)
VM_CL_ResetParticle, // #523 void() resetparticle (DP_CSQC_SPAWNPARTICLE)
VM_CL_ParticleTheme, // #524 void(float theme) particletheme (DP_CSQC_SPAWNPARTICLE)
NULL, // #537
NULL, // #538
NULL, // #539
-NULL, // #540
-NULL, // #541
-NULL, // #542
+VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
+VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
+VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
NULL, // #543
NULL, // #544
NULL, // #545
VM_isfunction, // #607
NULL, // #608
NULL, // #609
-NULL, // #610
+VM_findkeysforcommand, // #610 string findkeysforcommand(string command[, float bindmap])
NULL, // #611
NULL, // #612
VM_parseentitydata, // #613
VM_sprintf, // #627 string sprintf(string format, ...)
VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
-NULL, // #630
+VM_setkeybind, // #630 float(float key, string bind[, float bindmap]) setkeybind
+VM_getbindmaps, // #631 vector(void) getbindmap
+VM_setbindmaps, // #632 float(vector bm) setbindmap
+NULL, // #633
+NULL, // #634
+NULL, // #635
+NULL, // #636
+NULL, // #637
+VM_CL_RotateMoves, // #638
+NULL, // #639
};
const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);