X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=clvm_cmds.c;h=2a2cefa68a67f07024856b4f513eae87c56bbb55;hp=5809bd07a1ae8b0fb44ada038fc1941740e367d5;hb=4be7d59693a1e9fb66852a4f279cfef85c1880a8;hpb=b4223996191ebdbd41cee2a878cc22e1ba755514 diff --git a/clvm_cmds.c b/clvm_cmds.c index 5809bd07..2a2cefa6 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -21,7 +21,6 @@ //4 feature darkplaces csqc: add builtins to clientside qc for gl calls extern cvar_t v_flipped; -extern cvar_t r_equalize_entities_fullbright; r_refdef_view_t csqc_original_r_refdef_view; r_refdef_view_t csqc_main_r_refdef_view; @@ -29,15 +28,20 @@ r_refdef_view_t csqc_main_r_refdef_view; // #1 void(vector ang) makevectors static void VM_CL_makevectors (prvm_prog_t *prog) { + vec3_t angles, forward, right, up; VM_SAFEPARMCOUNT(1, VM_CL_makevectors); - AngleVectors (PRVM_G_VECTOR(OFS_PARM0), PRVM_clientglobalvector(v_forward), PRVM_clientglobalvector(v_right), PRVM_clientglobalvector(v_up)); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), angles); + AngleVectors(angles, forward, right, up); + VectorCopy(forward, PRVM_clientglobalvector(v_forward)); + VectorCopy(right, PRVM_clientglobalvector(v_right)); + VectorCopy(up, PRVM_clientglobalvector(v_up)); } // #2 void(entity e, vector o) setorigin static void VM_CL_setorigin (prvm_prog_t *prog) { prvm_edict_t *e; - float *org; + prvm_vec_t *org; VM_SAFEPARMCOUNT(2, VM_CL_setorigin); e = PRVM_G_EDICT(OFS_PARM0); @@ -46,7 +50,7 @@ static void VM_CL_setorigin (prvm_prog_t *prog) VM_Warning(prog, "setorigin: can not modify world entity\n"); return; } - if (e->priv.required->free) + if (e->free) { VM_Warning(prog, "setorigin: can not modify free entity\n"); return; @@ -58,7 +62,7 @@ static void VM_CL_setorigin (prvm_prog_t *prog) CL_LinkEdict(e); } -static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max) +static void SetMinMaxSizePRVM (prvm_prog_t *prog, prvm_edict_t *e, prvm_vec_t *min, prvm_vec_t *max) { int i; @@ -74,12 +78,20 @@ static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float CL_LinkEdict (e); } +static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, const vec_t *min, const vec_t *max) +{ + prvm_vec3_t mins, maxs; + VectorCopy(min, mins); + VectorCopy(max, maxs); + SetMinMaxSizePRVM(prog, e, mins, maxs); +} + // #3 void(entity e, string m) setmodel static void VM_CL_setmodel (prvm_prog_t *prog) { prvm_edict_t *e; const char *m; - dp_model_t *mod; + model_t *mod; int i; VM_SAFEPARMCOUNT(2, VM_CL_setmodel); @@ -116,7 +128,8 @@ static void VM_CL_setmodel (prvm_prog_t *prog) if( mod ) { // TODO: check if this breaks needed consistency and maybe add a cvar for it too?? [1/10/2008 Black] - //SetMinMaxSize (e, mod->normalmins, mod->normalmaxs); + // LadyHavoc: erm you broke it by commenting this out - setmodel must do setsize or else the qc can't find out the model size, and ssqc does this by necessity, consistency. + SetMinMaxSize (prog, e, mod->normalmins, mod->normalmaxs); } else { @@ -129,7 +142,7 @@ static void VM_CL_setmodel (prvm_prog_t *prog) static void VM_CL_setsize (prvm_prog_t *prog) { prvm_edict_t *e; - float *min, *max; + vec3_t mins, maxs; VM_SAFEPARMCOUNT(3, VM_CL_setsize); e = PRVM_G_EDICT(OFS_PARM0); @@ -138,28 +151,29 @@ static void VM_CL_setsize (prvm_prog_t *prog) VM_Warning(prog, "setsize: can not modify world entity\n"); return; } - if (e->priv.server->free) + if (e->free) { VM_Warning(prog, "setsize: can not modify free entity\n"); return; } - min = PRVM_G_VECTOR(OFS_PARM1); - max = PRVM_G_VECTOR(OFS_PARM2); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs); - SetMinMaxSize( prog, e, min, max ); + SetMinMaxSize( prog, e, mins, maxs ); CL_LinkEdict(e); } -// #8 void(entity e, float chan, string samp, float volume, float atten) sound +// #8 void(entity e, float chan, string samp, float volume, float atten[, float pitchchange[, float flags]]) sound static void VM_CL_sound (prvm_prog_t *prog) { const char *sample; int channel; prvm_edict_t *entity; - float volume; + float fvolume; float attenuation; float pitchchange; + float startposition; int flags; vec3_t org; @@ -168,10 +182,10 @@ static void VM_CL_sound (prvm_prog_t *prog) entity = PRVM_G_EDICT(OFS_PARM0); channel = (int)PRVM_G_FLOAT(OFS_PARM1); sample = PRVM_G_STRING(OFS_PARM2); - volume = PRVM_G_FLOAT(OFS_PARM3); + fvolume = PRVM_G_FLOAT(OFS_PARM3); attenuation = PRVM_G_FLOAT(OFS_PARM4); - if (volume < 0 || volume > 1) + if (fvolume < 0 || fvolume > 1) { VM_Warning(prog, "VM_CL_sound: volume must be in range 0-1\n"); return; @@ -187,14 +201,23 @@ static void VM_CL_sound (prvm_prog_t *prog) pitchchange = 0; else pitchchange = PRVM_G_FLOAT(OFS_PARM5); - // ignoring prog->argc < 7 for now (no flags supported yet) if (prog->argc < 7) flags = 0; else - flags = PRVM_G_FLOAT(OFS_PARM6); + { + // LadyHavoc: we only let the qc set certain flags, others are off-limits + flags = (int)PRVM_G_FLOAT(OFS_PARM6) & (CHANNELFLAG_RELIABLE | CHANNELFLAG_FORCELOOP | CHANNELFLAG_PAUSED | CHANNELFLAG_FULLVOLUME); + } - channel = CHAN_USER2ENGINE(channel); + // sound_starttime exists instead of sound_startposition because in a + // networking sense you might not know when something is being received, + // so making sounds match up in sync would be impossible if relative + // position was sent + if (PRVM_clientglobalfloat(sound_starttime)) + startposition = cl.time - PRVM_clientglobalfloat(sound_starttime); + else + startposition = 0; if (!IS_CHAN(channel)) { @@ -203,14 +226,14 @@ static void VM_CL_sound (prvm_prog_t *prog) } CL_VM_GetEntitySoundOrigin(MAX_EDICTS + PRVM_NUM_FOR_EDICT(entity), org); - S_StartSound_StartPosition_Flags(MAX_EDICTS + PRVM_NUM_FOR_EDICT(entity), channel, S_FindName(sample), org, volume, attenuation, 0, flags, pitchchange > 0.0f ? pitchchange * 0.01f : 1.0f); + S_StartSound_StartPosition_Flags(MAX_EDICTS + PRVM_NUM_FOR_EDICT(entity), channel, S_FindName(sample), org, fvolume, attenuation, startposition, flags, pitchchange > 0.0f ? pitchchange * 0.01f : 1.0f); } // #483 void(vector origin, string sample, float volume, float attenuation) pointsound static void VM_CL_pointsound(prvm_prog_t *prog) { const char *sample; - float volume; + float fvolume; float attenuation; vec3_t org; @@ -218,10 +241,10 @@ static void VM_CL_pointsound(prvm_prog_t *prog) VectorCopy( PRVM_G_VECTOR(OFS_PARM0), org); sample = PRVM_G_STRING(OFS_PARM1); - volume = PRVM_G_FLOAT(OFS_PARM2); + fvolume = PRVM_G_FLOAT(OFS_PARM2); attenuation = PRVM_G_FLOAT(OFS_PARM3); - if (volume < 0 || volume > 1) + if (fvolume < 0 || fvolume > 1) { VM_Warning(prog, "VM_CL_pointsound: volume must be in range 0-1\n"); return; @@ -234,7 +257,7 @@ static void VM_CL_pointsound(prvm_prog_t *prog) } // Send World Entity as Entity to Play Sound (for CSQC, that is MAX_EDICTS) - S_StartSound(MAX_EDICTS, 0, S_FindName(sample), org, volume, attenuation); + S_StartSound(MAX_EDICTS, 0, S_FindName(sample), org, fvolume, attenuation); } // #14 entity() spawn @@ -257,7 +280,7 @@ static void CL_VM_SetTraceGlobals(prvm_prog_t *prog, const trace_t *trace, int s // #16 void(vector v1, vector v2, float movetype, entity ignore) traceline static void VM_CL_traceline (prvm_prog_t *prog) { - float *v1, *v2; + vec3_t v1, v2; trace_t trace; int move, svent; prvm_edict_t *ent; @@ -268,15 +291,15 @@ static void VM_CL_traceline (prvm_prog_t *prog) prog->xfunction->builtinsprofile += 30; - v1 = PRVM_G_VECTOR(OFS_PARM0); - v2 = PRVM_G_VECTOR(OFS_PARM1); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2); move = (int)PRVM_G_FLOAT(OFS_PARM2); ent = PRVM_G_EDICT(OFS_PARM3); - 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])) + if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2])) prog->error_cmd("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", prog->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, false); + trace = CL_TraceLine(v1, v2, move, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtracelinelength.value, CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true, false); CL_VM_SetTraceGlobals(prog, &trace, svent); // R_TimeReport("traceline"); @@ -293,10 +316,10 @@ if the tryents flag is set. tracebox (vector1, vector mins, vector maxs, vector2, tryents) ================= */ -// LordHavoc: added this for my own use, VERY useful, similar to traceline +// LadyHavoc: added this for my own use, VERY useful, similar to traceline static void VM_CL_tracebox (prvm_prog_t *prog) { - float *v1, *v2, *m1, *m2; + vec3_t v1, v2, m1, m2; trace_t trace; int move, svent; prvm_edict_t *ent; @@ -306,17 +329,17 @@ static void VM_CL_tracebox (prvm_prog_t *prog) prog->xfunction->builtinsprofile += 30; - v1 = PRVM_G_VECTOR(OFS_PARM0); - m1 = PRVM_G_VECTOR(OFS_PARM1); - m2 = PRVM_G_VECTOR(OFS_PARM2); - v2 = PRVM_G_VECTOR(OFS_PARM3); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2); + VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2); move = (int)PRVM_G_FLOAT(OFS_PARM4); ent = PRVM_G_EDICT(OFS_PARM5); - 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])) + if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2])) prog->error_cmd("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent)); - trace = CL_TraceBox(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true); + trace = CL_TraceBox(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtraceboxlength.value, CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true); CL_VM_SetTraceGlobals(prog, &trace, svent); // R_TimeReport("tracebox"); @@ -326,7 +349,7 @@ static trace_t CL_Trace_Toss (prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edi { int i; float gravity; - vec3_t move, end; + vec3_t start, end, mins, maxs, move; vec3_t original_origin; vec3_t original_velocity; vec3_t original_angles; @@ -343,13 +366,16 @@ static trace_t CL_Trace_Toss (prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edi gravity = 1.0f; gravity *= cl.movevars_gravity * 0.05; - for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds + for (i = 0;i < 200;i++) // LadyHavoc: sanity check; never trace more than 10 seconds { PRVM_clientedictvector(tossent, velocity)[2] -= gravity; VectorMA (PRVM_clientedictvector(tossent, angles), 0.05, PRVM_clientedictvector(tossent, avelocity), PRVM_clientedictvector(tossent, angles)); VectorScale (PRVM_clientedictvector(tossent, velocity), 0.05, move); VectorAdd (PRVM_clientedictvector(tossent, origin), move, end); - trace = CL_TraceBox(PRVM_clientedictvector(tossent, origin), PRVM_clientedictvector(tossent, mins), PRVM_clientedictvector(tossent, maxs), end, MOVE_NORMAL, tossent, CL_GenericHitSuperContentsMask(tossent), true, true, NULL, true); + VectorCopy(PRVM_clientedictvector(tossent, origin), start); + VectorCopy(PRVM_clientedictvector(tossent, mins), mins); + VectorCopy(PRVM_clientedictvector(tossent, maxs), maxs); + trace = CL_TraceBox(start, mins, maxs, end, MOVE_NORMAL, tossent, CL_GenericHitSuperContentsMask(tossent), 0, 0, collision_extendmovelength.value, true, true, NULL, true); VectorCopy (trace.endpos, PRVM_clientedictvector(tossent, origin)); if (trace.fraction < 1) @@ -394,7 +420,7 @@ static void VM_CL_precache_model (prvm_prog_t *prog) { const char *name; int i; - dp_model_t *m; + model_t *m; VM_SAFEPARMCOUNT(1, VM_CL_precache_model); @@ -415,7 +441,7 @@ static void VM_CL_precache_model (prvm_prog_t *prog) { if (!cl.csqc_model_precache[i]) { - cl.csqc_model_precache[i] = (dp_model_t*)m; + cl.csqc_model_precache[i] = (model_t*)m; PRVM_G_FLOAT(OFS_RETURN) = -(i+1); return; } @@ -426,22 +452,6 @@ static void VM_CL_precache_model (prvm_prog_t *prog) VM_Warning(prog, "VM_CL_precache_model: model \"%s\" not found\n", name); } -static int CSQC_EntitiesInBox (prvm_prog_t *prog, vec3_t mins, vec3_t maxs, int maxlist, prvm_edict_t **list) -{ - prvm_edict_t *ent; - int i, k; - - ent = PRVM_NEXT_EDICT(prog->edicts); - for(k=0,i=1; inum_edicts ;i++, ent = PRVM_NEXT_EDICT(ent)) - { - if (ent->priv.required->free) - continue; - if(BoxesOverlap(mins, maxs, PRVM_clientedictvector(ent, absmin), PRVM_clientedictvector(ent, absmax))) - list[k++] = ent; - } - return k; -} - // #22 entity(vector org, float rad) findradius static void VM_CL_findradius (prvm_prog_t *prog) { @@ -473,7 +483,7 @@ static void VM_CL_findradius (prvm_prog_t *prog) maxs[0] = org[0] + (radius + 1); maxs[1] = org[1] + (radius + 1); maxs[2] = org[2] + (radius + 1); - numtouchedicts = CSQC_EntitiesInBox(prog, mins, maxs, MAX_EDICTS, touchedicts); + numtouchedicts = World_EntitiesInBox(&cl.world, mins, maxs, MAX_EDICTS, touchedicts); if (numtouchedicts > MAX_EDICTS) { // this never happens //[515]: for what then ? @@ -487,7 +497,7 @@ static void VM_CL_findradius (prvm_prog_t *prog) // (note: this is the reason you can't blow up fallen zombies) if (PRVM_clientedictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer) continue; - // LordHavoc: compare against bounding box rather than center so it + // LadyHavoc: compare against bounding box rather than center so it // doesn't miss large objects, and use DotProduct instead of Length // for a major speedup VectorSubtract(org, PRVM_clientedictvector(ent, origin), eorg); @@ -513,7 +523,7 @@ static void VM_CL_findradius (prvm_prog_t *prog) static void VM_CL_droptofloor (prvm_prog_t *prog) { prvm_edict_t *ent; - vec3_t end; + vec3_t start, end, mins, maxs; trace_t trace; VM_SAFEPARMCOUNTRANGE(0, 2, VM_CL_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype @@ -527,16 +537,19 @@ static void VM_CL_droptofloor (prvm_prog_t *prog) VM_Warning(prog, "droptofloor: can not modify world entity\n"); return; } - if (ent->priv.server->free) + if (ent->free) { VM_Warning(prog, "droptofloor: can not modify free entity\n"); return; } - VectorCopy (PRVM_clientedictvector(ent, origin), end); + VectorCopy(PRVM_clientedictvector(ent, origin), start); + VectorCopy(PRVM_clientedictvector(ent, mins), mins); + VectorCopy(PRVM_clientedictvector(ent, maxs), maxs); + VectorCopy(PRVM_clientedictvector(ent, origin), end); end[2] -= 256; - trace = CL_TraceBox(PRVM_clientedictvector(ent, origin), PRVM_clientedictvector(ent, mins), PRVM_clientedictvector(ent, maxs), end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + trace = CL_TraceBox(start, mins, maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, true, true, NULL, true); if (trace.fraction != 1) { @@ -614,7 +627,7 @@ realcheck: 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, false); + trace = CL_TraceLine(start, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, true, true, NULL, true, false); if (trace.fraction == 1.0) return; @@ -628,7 +641,7 @@ realcheck: 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, false); + trace = CL_TraceLine(start, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, true, true, NULL, true, false); if (trace.fraction != 1.0 && trace.endpos[2] > bottom) bottom = trace.endpos[2]; @@ -643,20 +656,22 @@ realcheck: // #41 float(vector v) pointcontents static void VM_CL_pointcontents (prvm_prog_t *prog) { + vec3_t point; VM_SAFEPARMCOUNT(1, VM_CL_pointcontents); - PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, CL_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0))); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point); + PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(CL_PointSuperContents(point)); } // #48 void(vector o, vector d, float color, float count) particle static void VM_CL_particle (prvm_prog_t *prog) { - float *org, *dir; + vec3_t org, dir; int count; unsigned char color; VM_SAFEPARMCOUNT(4, VM_CL_particle); - org = PRVM_G_VECTOR(OFS_PARM0); - dir = PRVM_G_VECTOR(OFS_PARM1); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir); color = (int)PRVM_G_FLOAT(OFS_PARM2); count = (int)PRVM_G_FLOAT(OFS_PARM3); CL_ParticleEffect(EFFECT_SVC_PARTICLE, count, org, org, dir, dir, NULL, color); @@ -665,11 +680,11 @@ static void VM_CL_particle (prvm_prog_t *prog) // #74 void(vector pos, string samp, float vol, float atten) ambientsound static void VM_CL_ambientsound (prvm_prog_t *prog) { - float *f; + vec3_t f; sfx_t *s; VM_SAFEPARMCOUNT(4, VM_CL_ambientsound); - s = S_FindName(PRVM_G_STRING(OFS_PARM0)); - f = PRVM_G_VECTOR(OFS_PARM1); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), f); + s = S_FindName(PRVM_G_STRING(OFS_PARM1)); S_StaticSound (s, f, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3)*64); } @@ -677,18 +692,13 @@ static void VM_CL_ambientsound (prvm_prog_t *prog) static void VM_CL_getlight (prvm_prog_t *prog) { vec3_t ambientcolor, diffusecolor, diffusenormal; - vec_t *p; + vec3_t p; + int flags = prog->argc >= 2 ? PRVM_G_FLOAT(OFS_PARM1) : LP_LIGHTMAP; VM_SAFEPARMCOUNTRANGE(1, 3, VM_CL_getlight); - p = PRVM_G_VECTOR(OFS_PARM0); - VectorClear(ambientcolor); - VectorClear(diffusecolor); - VectorClear(diffusenormal); - 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); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p); + R_CompleteLightPoint(ambientcolor, diffusecolor, diffusenormal, p, flags, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity); VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN)); if (PRVM_clientglobalvector(getlight_ambient)) VectorCopy(ambientcolor, PRVM_clientglobalvector(getlight_ambient)); @@ -701,11 +711,14 @@ static void VM_CL_getlight (prvm_prog_t *prog) //============================================================================ //[515]: SCENE MANAGER builtins +extern cvar_t v_yshearing; void CSQC_R_RecalcView (void) { extern matrix4x4_t viewmodelmatrix_nobob; extern matrix4x4_t viewmodelmatrix_withbob; 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); + if (v_yshearing.value > 0) + Matrix4x4_QuakeToDuke3D(&r_refdef.view.matrix, &r_refdef.view.matrix, v_yshearing.value); Matrix4x4_Copy(&viewmodelmatrix_nobob, &r_refdef.view.matrix); Matrix4x4_ConcatScale(&viewmodelmatrix_nobob, cl_viewmodel_scale.value); Matrix4x4_Concat(&viewmodelmatrix_withbob, &r_refdef.view.matrix, &cl.csqc_viewmodelmatrixfromengine); @@ -720,12 +733,16 @@ static void VM_CL_R_ClearScene (prvm_prog_t *prog) r_refdef.scene.numlights = 0; // restore the view settings to the values that VM_CL_UpdateView received from the client code r_refdef.view = csqc_original_r_refdef_view; + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = false; 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; CSQC_R_RecalcView(); + // clear the CL_Mesh_Scene() used for CSQC polygons and engine effects, they will be added by CSQC_RelinkAllEntities and manually created by CSQC + CL_MeshEntities_Scene_Clear(); } //#301 void(float mask) addentities (EXT_CSQC) @@ -737,7 +754,6 @@ static void VM_CL_R_AddEntities (prvm_prog_t *prog) VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntities); drawmask = (int)PRVM_G_FLOAT(OFS_PARM0); CSQC_RelinkAllEntities(drawmask); - CL_RelinkLightFlashes(); PRVM_clientglobalfloat(time) = cl.time; for(i=1;inum_edicts;i++) @@ -745,14 +761,14 @@ static void VM_CL_R_AddEntities (prvm_prog_t *prog) // 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) + if(ed->free) continue; CSQC_Think(ed); - if(ed->priv.required->free) + if(ed->free) continue; // note that for RF_USEAXIS entities, Predraw sets v_forward/v_right/v_up globals that are read by CSQC_AddRenderEdict CSQC_Predraw(ed); - if(ed->priv.required->free) + if(ed->free) continue; if(!((int)PRVM_clientedictfloat(ed, drawmask) & drawmask)) continue; @@ -783,7 +799,7 @@ static void VM_CL_R_AddEntity (prvm_prog_t *prog) static void VM_CL_R_SetView (prvm_prog_t *prog) { int c; - float *f; + prvm_vec_t *f; float k; VM_SAFEPARMCOUNTRANGE(1, 3, VM_CL_R_SetView); @@ -1079,15 +1095,15 @@ static void VM_CL_R_SetView (prvm_prog_t *prog) static void VM_CL_R_AddDynamicLight (prvm_prog_t *prog) { double t = Sys_DirtyTime(); - vec_t *org; + vec3_t org; float radius = 300; - vec_t *col; + vec3_t col; int style = -1; const char *cubemapname = NULL; int pflags = PFLAGS_CORONA | PFLAGS_FULLDYNAMIC; float coronaintensity = 1; float coronasizescale = 0.25; - qboolean castshadow = true; + qbool castshadow = true; float ambientscale = 0; float diffusescale = 1; float specularscale = 1; @@ -1095,79 +1111,856 @@ static void VM_CL_R_AddDynamicLight (prvm_prog_t *prog) vec3_t forward, left, up; VM_SAFEPARMCOUNTRANGE(3, 8, VM_CL_R_AddDynamicLight); - // if we've run out of dlights, just return - if (r_refdef.scene.numlights >= MAX_DLIGHTS) - return; + // if we've run out of dlights, just return + if (r_refdef.scene.numlights >= MAX_DLIGHTS) + return; + + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org); + radius = PRVM_G_FLOAT(OFS_PARM1); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), col); + if (prog->argc >= 4) + { + style = (int)PRVM_G_FLOAT(OFS_PARM3); + if (style >= MAX_LIGHTSTYLES) + { + Con_DPrintf("VM_CL_R_AddDynamicLight: out of bounds lightstyle index %i\n", style); + style = -1; + } + } + if (prog->argc >= 5) + cubemapname = PRVM_G_STRING(OFS_PARM4); + if (prog->argc >= 6) + pflags = (int)PRVM_G_FLOAT(OFS_PARM5); + coronaintensity = (pflags & PFLAGS_CORONA) != 0; + castshadow = (pflags & PFLAGS_NOSHADOW) == 0; + + VectorScale(PRVM_clientglobalvector(v_forward), radius, forward); + VectorScale(PRVM_clientglobalvector(v_right), -radius, left); + VectorScale(PRVM_clientglobalvector(v_up), radius, up); + Matrix4x4_FromVectors(&matrix, forward, left, up, org); + + R_RTLight_Update(&r_refdef.scene.templights[r_refdef.scene.numlights], false, &matrix, col, style, cubemapname, castshadow, coronaintensity, coronasizescale, ambientscale, diffusescale, specularscale, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); + r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights];r_refdef.scene.numlights++; + t = Sys_DirtyTime() - t;if (t < 0 || t >= 1800) t = 0; + prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= t; +} + +//============================================================================ + +//#310 vector (vector v) cs_unproject (EXT_CSQC) +static void VM_CL_unproject (prvm_prog_t *prog) +{ + vec3_t f; + vec3_t temp; + vec3_t result; + + VM_SAFEPARMCOUNT(1, VM_CL_unproject); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), f); + VectorSet(temp, + f[2], + (-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, result); + VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); +} + +//#311 vector (vector v) cs_project (EXT_CSQC) +static void VM_CL_project (prvm_prog_t *prog) +{ + vec3_t f; + vec3_t v; + matrix4x4_t m; + + VM_SAFEPARMCOUNT(1, VM_CL_project); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), f); + Matrix4x4_Invert_Full(&m, &r_refdef.view.matrix); + Matrix4x4_Transform(&m, f, v); + if(v_flipped.integer) + v[1] = -v[1]; + VectorSet(PRVM_G_VECTOR(OFS_RETURN), + 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 +} + +//============================================================================= +// Draw builtins (client & menu) + +/* +======================== +VM_drawline + +void drawline(float width, vector pos1, vector pos2, vector rgb, float alpha, float flags) +======================== +*/ +void VM_drawline (prvm_prog_t *prog) +{ + prvm_vec_t *c1, *c2, *rgb; + float alpha, width; + unsigned char flags; + + VM_SAFEPARMCOUNT(6, VM_drawline); + + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + + width = PRVM_G_FLOAT(OFS_PARM0); + c1 = PRVM_G_VECTOR(OFS_PARM1); + c2 = PRVM_G_VECTOR(OFS_PARM2); + rgb = PRVM_G_VECTOR(OFS_PARM3); + alpha = PRVM_G_FLOAT(OFS_PARM4); + flags = (int)PRVM_G_FLOAT(OFS_PARM5); + DrawQ_Line(width, c1[0], c1[1], c2[0], c2[1], rgb[0], rgb[1], rgb[2], alpha, flags); +} + +/* +========= +VM_iscachedpic + +float iscachedpic(string pic) +========= +*/ +void VM_iscachedpic(prvm_prog_t *prog) +{ + VM_SAFEPARMCOUNT(1,VM_iscachedpic); + + // drawq hasnt such a function, thus always return true + PRVM_G_FLOAT(OFS_RETURN) = false; +} + +/* +========= +VM_precache_pic + +string precache_pic(string pic) +========= +*/ +#define PRECACHE_PIC_FROMWAD 1 /* FTEQW, not supported here */ +#define PRECACHE_PIC_NOTPERSISTENT 2 +//#define PRECACHE_PIC_NOCLAMP 4 +#define PRECACHE_PIC_MIPMAP 8 +void VM_precache_pic(prvm_prog_t *prog) +{ + const char *s; + int flags = CACHEPICFLAG_FAILONMISSING; + + VM_SAFEPARMCOUNTRANGE(1, 2, VM_precache_pic); + + s = PRVM_G_STRING(OFS_PARM0); + PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0); + VM_CheckEmptyString(prog, s); + + if(prog->argc >= 2) + { + int f = PRVM_G_FLOAT(OFS_PARM1); + if(f & PRECACHE_PIC_NOTPERSISTENT) + flags |= CACHEPICFLAG_NOTPERSISTENT; + //if(f & PRECACHE_PIC_NOCLAMP) + // flags |= CACHEPICFLAG_NOCLAMP; + if(f & PRECACHE_PIC_MIPMAP) + flags |= CACHEPICFLAG_MIPMAP; + } + + if( !Draw_IsPicLoaded(Draw_CachePic_Flags(s, flags | CACHEPICFLAG_QUIET)) ) + PRVM_G_INT(OFS_RETURN) = OFS_NULL; +} + +/* +========= +VM_freepic + +freepic(string s) +========= +*/ +void VM_freepic(prvm_prog_t *prog) +{ + const char *s; + + VM_SAFEPARMCOUNT(1,VM_freepic); + + s = PRVM_G_STRING(OFS_PARM0); + VM_CheckEmptyString(prog, s); + + Draw_FreePic(s); +} + +static void getdrawfontscale(prvm_prog_t *prog, float *sx, float *sy) +{ + vec3_t v; + *sx = *sy = 1; + VectorCopy(PRVM_drawglobalvector(drawfontscale), v); + if(VectorLength2(v) > 0) + { + *sx = v[0]; + *sy = v[1]; + } +} + +static dp_font_t *getdrawfont(prvm_prog_t *prog) +{ + int f = (int) PRVM_drawglobalfloat(drawfont); + if(f < 0 || f >= dp_fonts.maxsize) + return FONT_DEFAULT; + return &dp_fonts.f[f]; +} + +/* +========= +VM_drawcharacter + +float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag) +========= +*/ +void VM_drawcharacter(prvm_prog_t *prog) +{ + prvm_vec_t *pos,*scale,*rgb; + char character; + int flag; + float sx, sy; + VM_SAFEPARMCOUNT(6,VM_drawcharacter); + + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + + character = (char) PRVM_G_FLOAT(OFS_PARM1); + if(character == 0) + { + PRVM_G_FLOAT(OFS_RETURN) = -1; + VM_Warning(prog, "VM_drawcharacter: %s passed null character !\n",prog->name); + return; + } + + pos = PRVM_G_VECTOR(OFS_PARM0); + scale = PRVM_G_VECTOR(OFS_PARM2); + rgb = PRVM_G_VECTOR(OFS_PARM3); + flag = (int)PRVM_G_FLOAT(OFS_PARM5); + + if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS) + { + PRVM_G_FLOAT(OFS_RETURN) = -2; + VM_Warning(prog, "VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",prog->name,flag); + return; + } + + if(pos[2] || scale[2]) + VM_Warning(prog, "VM_drawcharacter: z value%c from %s discarded\n",(pos[2] && scale[2]) ? 's' : 0,((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale"))); + + if(!scale[0] || !scale[1]) + { + PRVM_G_FLOAT(OFS_RETURN) = -3; + VM_Warning(prog, "VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y"); + return; + } + + getdrawfontscale(prog, &sx, &sy); + DrawQ_String_Scale(pos[0], pos[1], &character, 1, scale[0], scale[1], sx, sy, rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag, NULL, true, getdrawfont(prog)); + PRVM_G_FLOAT(OFS_RETURN) = 1; +} + +/* +========= +VM_drawstring + +float drawstring(vector position, string text, vector scale, vector rgb, float alpha[, float flag]) +========= +*/ +void VM_drawstring(prvm_prog_t *prog) +{ + prvm_vec_t *pos,*scale,*rgb; + const char *string; + int flag = 0; + float sx, sy; + VM_SAFEPARMCOUNTRANGE(5,6,VM_drawstring); + + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + + string = PRVM_G_STRING(OFS_PARM1); + pos = PRVM_G_VECTOR(OFS_PARM0); + scale = PRVM_G_VECTOR(OFS_PARM2); + rgb = PRVM_G_VECTOR(OFS_PARM3); + if (prog->argc >= 6) + flag = (int)PRVM_G_FLOAT(OFS_PARM5); + + if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS) + { + PRVM_G_FLOAT(OFS_RETURN) = -2; + VM_Warning(prog, "VM_drawstring: %s: wrong DRAWFLAG %i !\n",prog->name,flag); + return; + } + + if(!scale[0] || !scale[1]) + { + PRVM_G_FLOAT(OFS_RETURN) = -3; + VM_Warning(prog, "VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y"); + return; + } + + if(pos[2] || scale[2]) + VM_Warning(prog, "VM_drawstring: z value%s from %s discarded\n",(pos[2] && scale[2]) ? "s" : " ",((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale"))); + + getdrawfontscale(prog, &sx, &sy); + DrawQ_String_Scale(pos[0], pos[1], string, 0, scale[0], scale[1], sx, sy, rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag, NULL, true, getdrawfont(prog)); + //Font_DrawString(pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag, NULL, true); + PRVM_G_FLOAT(OFS_RETURN) = 1; +} + +/* +========= +VM_drawcolorcodedstring + +float drawcolorcodedstring(vector position, string text, vector scale, float alpha, float flag) +/ +float drawcolorcodedstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) +========= +*/ +void VM_drawcolorcodedstring(prvm_prog_t *prog) +{ + prvm_vec_t *pos, *scale; + const char *string; + int flag; + vec3_t rgb; + float sx, sy, alpha; + + VM_SAFEPARMCOUNTRANGE(5,6,VM_drawcolorcodedstring); + + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + + if (prog->argc == 6) // full 6 parms, like normal drawstring + { + pos = PRVM_G_VECTOR(OFS_PARM0); + string = PRVM_G_STRING(OFS_PARM1); + scale = PRVM_G_VECTOR(OFS_PARM2); + VectorCopy(PRVM_G_VECTOR(OFS_PARM3), rgb); + alpha = PRVM_G_FLOAT(OFS_PARM4); + flag = (int)PRVM_G_FLOAT(OFS_PARM5); + } + else + { + pos = PRVM_G_VECTOR(OFS_PARM0); + string = PRVM_G_STRING(OFS_PARM1); + scale = PRVM_G_VECTOR(OFS_PARM2); + rgb[0] = 1.0; + rgb[1] = 1.0; + rgb[2] = 1.0; + alpha = PRVM_G_FLOAT(OFS_PARM3); + flag = (int)PRVM_G_FLOAT(OFS_PARM4); + } + + if(flag < DRAWFLAG_NORMAL || flag >= DRAWFLAG_NUMFLAGS) + { + PRVM_G_FLOAT(OFS_RETURN) = -2; + VM_Warning(prog, "VM_drawcolorcodedstring: %s: wrong DRAWFLAG %i !\n",prog->name,flag); + return; + } + + if(!scale[0] || !scale[1]) + { + PRVM_G_FLOAT(OFS_RETURN) = -3; + VM_Warning(prog, "VM_drawcolorcodedstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y"); + return; + } + + if(pos[2] || scale[2]) + VM_Warning(prog, "VM_drawcolorcodedstring: z value%s from %s discarded\n",(pos[2] && scale[2]) ? "s" : " ",((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale"))); + + getdrawfontscale(prog, &sx, &sy); + DrawQ_String_Scale(pos[0], pos[1], string, 0, scale[0], scale[1], sx, sy, rgb[0], rgb[1], rgb[2], alpha, flag, NULL, false, getdrawfont(prog)); + if (prog->argc == 6) // also return vector of last color + VectorCopy(DrawQ_Color, PRVM_G_VECTOR(OFS_RETURN)); + else + PRVM_G_FLOAT(OFS_RETURN) = 1; +} +/* +========= +VM_stringwidth + +float stringwidth(string text, float allowColorCodes, float size) +========= +*/ +void VM_stringwidth(prvm_prog_t *prog) +{ + const char *string; + vec2_t szv; + float mult; // sz is intended font size so we can later add freetype support, mult is font size multiplier in pixels per character cell + int colors; + float sx, sy; + size_t maxlen = 0; + VM_SAFEPARMCOUNTRANGE(2, 3, VM_stringwidth); + + getdrawfontscale(prog, &sx, &sy); + if(prog->argc == 3) + { + Vector2Copy(PRVM_G_VECTOR(OFS_PARM2), szv); + mult = 1; + } + else + { + // we want the width for 8x8 font size, divided by 8 + Vector2Set(szv, 8, 8); + mult = 0.125; + // to make sure snapping is turned off, ALWAYS use a nontrivial scale in this case + if(sx >= 0.9 && sx <= 1.1) + { + mult *= 2; + sx /= 2; + sy /= 2; + } + } + + string = PRVM_G_STRING(OFS_PARM0); + colors = (int)PRVM_G_FLOAT(OFS_PARM1); + + PRVM_G_FLOAT(OFS_RETURN) = DrawQ_TextWidth_UntilWidth_TrackColors_Scale(string, &maxlen, szv[0], szv[1], sx, sy, NULL, !colors, getdrawfont(prog), 1000000000) * mult; +/* + if(prog->argc == 3) + { + mult = sz = PRVM_G_FLOAT(OFS_PARM2); + } + else + { + sz = 8; + mult = 1; + } + + string = PRVM_G_STRING(OFS_PARM0); + colors = (int)PRVM_G_FLOAT(OFS_PARM1); + + PRVM_G_FLOAT(OFS_RETURN) = DrawQ_TextWidth(string, 0, !colors, getdrawfont()) * mult; // 1x1 characters, don't actually draw +*/ +} + +/* +========= +VM_findfont + +float findfont(string s) +========= +*/ + +static float getdrawfontnum(const char *fontname) +{ + int i; + + for(i = 0; i < dp_fonts.maxsize; ++i) + if(!strcmp(dp_fonts.f[i].title, fontname)) + return i; + return -1; +} + +void VM_findfont(prvm_prog_t *prog) +{ + VM_SAFEPARMCOUNT(1,VM_findfont); + PRVM_G_FLOAT(OFS_RETURN) = getdrawfontnum(PRVM_G_STRING(OFS_PARM0)); +} + +/* +========= +VM_loadfont + +float loadfont(string fontname, string fontmaps, string sizes, float slot) +========= +*/ + +void VM_loadfont(prvm_prog_t *prog) +{ + const char *fontname, *filelist, *sizes, *c, *cm; + char mainfont[MAX_QPATH]; + int i, numsizes; + float sz, scale, voffset; + dp_font_t *f; + + VM_SAFEPARMCOUNTRANGE(3,6,VM_loadfont); + + fontname = PRVM_G_STRING(OFS_PARM0); + if (!fontname[0]) + fontname = "default"; + + filelist = PRVM_G_STRING(OFS_PARM1); + if (!filelist[0]) + filelist = "gfx/conchars"; + + sizes = PRVM_G_STRING(OFS_PARM2); + if (!sizes[0]) + sizes = "10"; + + // find a font + f = NULL; + if (prog->argc >= 4) + { + i = PRVM_G_FLOAT(OFS_PARM3); + if (i >= 0 && i < dp_fonts.maxsize) + { + f = &dp_fonts.f[i]; + strlcpy(f->title, fontname, sizeof(f->title)); // replace name + } + } + if (!f) + f = FindFont(fontname, true); + if (!f) + { + PRVM_G_FLOAT(OFS_RETURN) = -1; + return; // something go wrong + } + + memset(f->fallbacks, 0, sizeof(f->fallbacks)); + memset(f->fallback_faces, 0, sizeof(f->fallback_faces)); + + // first font is handled "normally" + c = strchr(filelist, ':'); + cm = strchr(filelist, ','); + if(c && (!cm || c < cm)) + f->req_face = atoi(c+1); + else + { + f->req_face = 0; + c = cm; + } + if(!c || (c - filelist) > MAX_QPATH) + strlcpy(mainfont, filelist, sizeof(mainfont)); + else + { + memcpy(mainfont, filelist, c - filelist); + mainfont[c - filelist] = 0; + } + + // handle fallbacks + for(i = 0; i < MAX_FONT_FALLBACKS; ++i) + { + c = strchr(filelist, ','); + if(!c) + break; + filelist = c + 1; + if(!*filelist) + break; + c = strchr(filelist, ':'); + cm = strchr(filelist, ','); + if(c && (!cm || c < cm)) + f->fallback_faces[i] = atoi(c+1); + else + { + f->fallback_faces[i] = 0; // f->req_face; could make it stick to the default-font's face index + c = cm; + } + if(!c || (c-filelist) > MAX_QPATH) + { + strlcpy(f->fallbacks[i], filelist, sizeof(mainfont)); + } + else + { + memcpy(f->fallbacks[i], filelist, c - filelist); + f->fallbacks[i][c - filelist] = 0; + } + } + + // handle sizes + for(i = 0; i < MAX_FONT_SIZES; ++i) + f->req_sizes[i] = -1; + for (numsizes = 0,c = sizes;;) + { + if (!COM_ParseToken_VM_Tokenize(&c, 0)) + break; + sz = atof(com_token); + // detect crap size + if (sz < 0.001f || sz > 1000.0f) + { + VM_Warning(prog, "VM_loadfont: crap size %s", com_token); + continue; + } + // check overflow + if (numsizes == MAX_FONT_SIZES) + { + VM_Warning(prog, "VM_loadfont: MAX_FONT_SIZES = %i exceeded", MAX_FONT_SIZES); + break; + } + f->req_sizes[numsizes] = sz; + numsizes++; + } + + // additional scale/hoffset parms + scale = 1; + voffset = 0; + if (prog->argc >= 5) + { + scale = PRVM_G_FLOAT(OFS_PARM4); + if (scale <= 0) + scale = 1; + } + if (prog->argc >= 6) + voffset = PRVM_G_FLOAT(OFS_PARM5); + + // load + LoadFont(true, mainfont, f, scale, voffset); + + // return index of loaded font + PRVM_G_FLOAT(OFS_RETURN) = (f - dp_fonts.f); +} + +/* +========= +VM_drawpic + +float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag) +========= +*/ +void VM_drawpic(prvm_prog_t *prog) +{ + const char *picname; + prvm_vec_t *size, *pos, *rgb; + int flag = 0; + + VM_SAFEPARMCOUNTRANGE(5,6,VM_drawpic); + + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + + picname = PRVM_G_STRING(OFS_PARM1); + VM_CheckEmptyString(prog, picname); + + // is pic cached ? no function yet for that + if(!1) + { + PRVM_G_FLOAT(OFS_RETURN) = -4; + VM_Warning(prog, "VM_drawpic: %s: %s not cached !\n", prog->name, picname); + return; + } + + pos = PRVM_G_VECTOR(OFS_PARM0); + size = PRVM_G_VECTOR(OFS_PARM2); + rgb = PRVM_G_VECTOR(OFS_PARM3); + if (prog->argc >= 6) + flag = (int) PRVM_G_FLOAT(OFS_PARM5); + + if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS) + { + PRVM_G_FLOAT(OFS_RETURN) = -2; + VM_Warning(prog, "VM_drawpic: %s: wrong DRAWFLAG %i !\n",prog->name,flag); + return; + } + + if(pos[2] || size[2]) + VM_Warning(prog, "VM_drawpic: z value%s from %s discarded\n",(pos[2] && size[2]) ? "s" : " ",((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size"))); + + DrawQ_Pic(pos[0], pos[1], Draw_CachePic_Flags (picname, CACHEPICFLAG_NOTPERSISTENT), size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag); + PRVM_G_FLOAT(OFS_RETURN) = 1; +} +/* +========= +VM_drawrotpic + +float drawrotpic(vector position, string pic, vector size, vector org, float angle, vector rgb, float alpha, float flag) +========= +*/ +void VM_drawrotpic(prvm_prog_t *prog) +{ + const char *picname; + prvm_vec_t *size, *pos, *org, *rgb; + int flag; + + VM_SAFEPARMCOUNT(8,VM_drawrotpic); + + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + + picname = PRVM_G_STRING(OFS_PARM1); + VM_CheckEmptyString(prog, picname); + + // is pic cached ? no function yet for that + if(!1) + { + PRVM_G_FLOAT(OFS_RETURN) = -4; + VM_Warning(prog, "VM_drawrotpic: %s: %s not cached !\n", prog->name, picname); + return; + } + + pos = PRVM_G_VECTOR(OFS_PARM0); + size = PRVM_G_VECTOR(OFS_PARM2); + org = PRVM_G_VECTOR(OFS_PARM3); + rgb = PRVM_G_VECTOR(OFS_PARM5); + flag = (int) PRVM_G_FLOAT(OFS_PARM7); + + if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS) + { + PRVM_G_FLOAT(OFS_RETURN) = -2; + VM_Warning(prog, "VM_drawrotpic: %s: wrong DRAWFLAG %i !\n",prog->name,flag); + return; + } + + if(pos[2] || size[2] || org[2]) + VM_Warning(prog, "VM_drawrotpic: z value from pos/size/org discarded\n"); + + DrawQ_RotPic(pos[0], pos[1], Draw_CachePic_Flags(picname, CACHEPICFLAG_NOTPERSISTENT), size[0], size[1], org[0], org[1], PRVM_G_FLOAT(OFS_PARM4), rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM6), flag); + PRVM_G_FLOAT(OFS_RETURN) = 1; +} +/* +========= +VM_drawsubpic + +float drawsubpic(vector position, vector size, string pic, vector srcPos, vector srcSize, vector rgb, float alpha, float flag) + +========= +*/ +void VM_drawsubpic(prvm_prog_t *prog) +{ + const char *picname; + prvm_vec_t *size, *pos, *rgb, *srcPos, *srcSize, alpha; + int flag; + + VM_SAFEPARMCOUNT(8,VM_drawsubpic); + + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + + picname = PRVM_G_STRING(OFS_PARM2); + VM_CheckEmptyString(prog, picname); + + // is pic cached ? no function yet for that + if(!1) + { + PRVM_G_FLOAT(OFS_RETURN) = -4; + VM_Warning(prog, "VM_drawsubpic: %s: %s not cached !\n", prog->name, picname); + return; + } + + pos = PRVM_G_VECTOR(OFS_PARM0); + size = PRVM_G_VECTOR(OFS_PARM1); + srcPos = PRVM_G_VECTOR(OFS_PARM3); + srcSize = PRVM_G_VECTOR(OFS_PARM4); + rgb = PRVM_G_VECTOR(OFS_PARM5); + alpha = PRVM_G_FLOAT(OFS_PARM6); + flag = (int) PRVM_G_FLOAT(OFS_PARM7); + + if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS) + { + PRVM_G_FLOAT(OFS_RETURN) = -2; + VM_Warning(prog, "VM_drawsubpic: %s: wrong DRAWFLAG %i !\n",prog->name,flag); + return; + } + + if(pos[2] || size[2]) + VM_Warning(prog, "VM_drawsubpic: z value%s from %s discarded\n",(pos[2] && size[2]) ? "s" : " ",((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size"))); + + DrawQ_SuperPic(pos[0], pos[1], Draw_CachePic_Flags (picname, CACHEPICFLAG_NOTPERSISTENT), + size[0], size[1], + srcPos[0], srcPos[1], rgb[0], rgb[1], rgb[2], alpha, + srcPos[0] + srcSize[0], srcPos[1], rgb[0], rgb[1], rgb[2], alpha, + srcPos[0], srcPos[1] + srcSize[1], rgb[0], rgb[1], rgb[2], alpha, + srcPos[0] + srcSize[0], srcPos[1] + srcSize[1], rgb[0], rgb[1], rgb[2], alpha, + flag); + PRVM_G_FLOAT(OFS_RETURN) = 1; +} + +/* +========= +VM_drawfill + +float drawfill(vector position, vector size, vector rgb, float alpha, float flag) +========= +*/ +void VM_drawfill(prvm_prog_t *prog) +{ + prvm_vec_t *size, *pos, *rgb; + int flag; + + VM_SAFEPARMCOUNT(5,VM_drawfill); + + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + + pos = PRVM_G_VECTOR(OFS_PARM0); + size = PRVM_G_VECTOR(OFS_PARM1); + rgb = PRVM_G_VECTOR(OFS_PARM2); + flag = (int) PRVM_G_FLOAT(OFS_PARM4); - org = PRVM_G_VECTOR(OFS_PARM0); - radius = PRVM_G_FLOAT(OFS_PARM1); - col = PRVM_G_VECTOR(OFS_PARM2); - if (prog->argc >= 4) + if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS) { - style = (int)PRVM_G_FLOAT(OFS_PARM3); - if (style >= MAX_LIGHTSTYLES) - { - Con_DPrintf("VM_CL_R_AddDynamicLight: out of bounds lightstyle index %i\n", style); - style = -1; - } + PRVM_G_FLOAT(OFS_RETURN) = -2; + VM_Warning(prog, "VM_drawfill: %s: wrong DRAWFLAG %i !\n",prog->name,flag); + return; } - if (prog->argc >= 5) - cubemapname = PRVM_G_STRING(OFS_PARM4); - if (prog->argc >= 6) - pflags = (int)PRVM_G_FLOAT(OFS_PARM5); - coronaintensity = (pflags & PFLAGS_CORONA) != 0; - castshadow = (pflags & PFLAGS_NOSHADOW) == 0; - VectorScale(PRVM_clientglobalvector(v_forward), radius, forward); - VectorScale(PRVM_clientglobalvector(v_right), -radius, left); - VectorScale(PRVM_clientglobalvector(v_up), radius, up); - Matrix4x4_FromVectors(&matrix, forward, left, up, org); + if(pos[2] || size[2]) + VM_Warning(prog, "VM_drawfill: z value%s from %s discarded\n",(pos[2] && size[2]) ? "s" : " ",((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size"))); - R_RTLight_Update(&r_refdef.scene.templights[r_refdef.scene.numlights], false, &matrix, col, style, cubemapname, castshadow, coronaintensity, coronasizescale, ambientscale, diffusescale, specularscale, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); - r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights];r_refdef.scene.numlights++; - t = Sys_DirtyTime() - t;if (t < 0 || t >= 1800) t = 0; - prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= t; + DrawQ_Fill(pos[0], pos[1], size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag); + PRVM_G_FLOAT(OFS_RETURN) = 1; } -//============================================================================ +/* +========= +VM_drawsetcliparea -//#310 vector (vector v) cs_unproject (EXT_CSQC) -static void VM_CL_unproject (prvm_prog_t *prog) +drawsetcliparea(float x, float y, float width, float height) +========= +*/ +void VM_drawsetcliparea(prvm_prog_t *prog) { - float *f; - vec3_t temp; + float x,y,w,h; + VM_SAFEPARMCOUNT(4,VM_drawsetcliparea); - VM_SAFEPARMCOUNT(1, VM_CL_unproject); - f = PRVM_G_VECTOR(OFS_PARM0); - VectorSet(temp, - f[2], - (-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)); + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + + x = bound(0, PRVM_G_FLOAT(OFS_PARM0), vid_conwidth.integer); + y = bound(0, PRVM_G_FLOAT(OFS_PARM1), vid_conheight.integer); + w = bound(0, PRVM_G_FLOAT(OFS_PARM2) + PRVM_G_FLOAT(OFS_PARM0) - x, (vid_conwidth.integer - x)); + h = bound(0, PRVM_G_FLOAT(OFS_PARM3) + PRVM_G_FLOAT(OFS_PARM1) - y, (vid_conheight.integer - y)); + + DrawQ_SetClipArea(x, y, w, h); } -//#311 vector (vector v) cs_project (EXT_CSQC) -static void VM_CL_project (prvm_prog_t *prog) +/* +========= +VM_drawresetcliparea + +drawresetcliparea() +========= +*/ +void VM_drawresetcliparea(prvm_prog_t *prog) { - float *f; - vec3_t v; - matrix4x4_t m; + VM_SAFEPARMCOUNT(0,VM_drawresetcliparea); - VM_SAFEPARMCOUNT(1, VM_CL_project); - f = PRVM_G_VECTOR(OFS_PARM0); - Matrix4x4_Invert_Simple(&m, &r_refdef.view.matrix); - Matrix4x4_Transform(&m, f, v); - if(v_flipped.integer) - v[1] = -v[1]; - VectorSet(PRVM_G_VECTOR(OFS_RETURN), - 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 + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + + DrawQ_ResetClipArea(); +} + +/* +========= +VM_getimagesize + +vector getimagesize(string pic) +========= +*/ +void VM_getimagesize(prvm_prog_t *prog) +{ + const char *p; + cachepic_t *pic; + + VM_SAFEPARMCOUNT(1,VM_getimagesize); + + p = PRVM_G_STRING(OFS_PARM0); + VM_CheckEmptyString(prog, p); + + pic = Draw_CachePic_Flags (p, CACHEPICFLAG_QUIET | CACHEPICFLAG_NOTPERSISTENT); + if (!Draw_IsPicLoaded(pic)) + { + PRVM_G_VECTOR(OFS_RETURN)[0] = 0; + PRVM_G_VECTOR(OFS_RETURN)[1] = 0; + } + else + { + PRVM_G_VECTOR(OFS_RETURN)[0] = Draw_GetPicWidth(pic); + PRVM_G_VECTOR(OFS_RETURN)[1] = Draw_GetPicHeight(pic); + } + PRVM_G_VECTOR(OFS_RETURN)[2] = 0; } //#330 float(float stnum) getstatf (EXT_CSQC) @@ -1281,7 +2074,7 @@ static void VM_CL_setmodelindex (prvm_prog_t *prog) //#334 string(float mdlindex) modelnameforindex (EXT_CSQC) static void VM_CL_modelnameforindex (prvm_prog_t *prog) { - dp_model_t *model; + model_t *model; VM_SAFEPARMCOUNT(1, VM_CL_modelnameforindex); @@ -1305,18 +2098,19 @@ static void VM_CL_particleeffectnum (prvm_prog_t *prog) static void VM_CL_trailparticles (prvm_prog_t *prog) { int i; - float *start, *end; + vec3_t start, end, velocity; prvm_edict_t *t; VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_trailparticles); t = PRVM_G_EDICT(OFS_PARM0); i = (int)PRVM_G_FLOAT(OFS_PARM1); - start = PRVM_G_VECTOR(OFS_PARM2); - end = PRVM_G_VECTOR(OFS_PARM3); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start); + VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end); + VectorCopy(PRVM_clientedictvector(t, velocity), velocity); if (i < 0) return; - CL_ParticleEffect(i, 1, start, end, PRVM_clientedictvector(t, velocity), PRVM_clientedictvector(t, velocity), NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0); + CL_ParticleTrail(i, 1, start, end, velocity, velocity, NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0, true, true, NULL, NULL, 1); } //#337 void(float effectnum, vector origin, vector dir, float count[, float color]) pointparticles (EXT_CSQC) @@ -1324,11 +2118,11 @@ static void VM_CL_pointparticles (prvm_prog_t *prog) { int i; float n; - float *f, *v; + vec3_t f, v; VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_pointparticles); i = (int)PRVM_G_FLOAT(OFS_PARM0); - f = PRVM_G_VECTOR(OFS_PARM1); - v = PRVM_G_VECTOR(OFS_PARM2); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), f); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), v); n = PRVM_G_FLOAT(OFS_PARM3); if (i < 0) return; @@ -1340,25 +2134,32 @@ static void VM_CL_boxparticles (prvm_prog_t *prog) { int effectnum; // prvm_edict_t *own; - float *origin_from, *origin_to, *dir_from, *dir_to; + vec3_t origin_from, origin_to, dir_from, dir_to; float count; int flags; - float tintmins[4], tintmaxs[4]; + qbool istrail; + float tintmins[4], tintmaxs[4], fade; VM_SAFEPARMCOUNTRANGE(7, 8, VM_CL_boxparticles); effectnum = (int)PRVM_G_FLOAT(OFS_PARM0); + if (effectnum < 0) + return; // 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); - dir_to = PRVM_G_VECTOR(OFS_PARM5); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin_from); + VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin_to ); + VectorCopy(PRVM_G_VECTOR(OFS_PARM4), dir_from ); + VectorCopy(PRVM_G_VECTOR(OFS_PARM5), dir_to ); count = PRVM_G_FLOAT(OFS_PARM6); if(prog->argc >= 8) flags = PRVM_G_FLOAT(OFS_PARM7); else flags = 0; + Vector4Set(tintmins, 1, 1, 1, 1); Vector4Set(tintmaxs, 1, 1, 1, 1); + fade = 1; + istrail = false; + if(flags & 1) // read alpha { tintmins[3] = PRVM_clientglobalfloat(particles_alphamin); @@ -1369,19 +2170,32 @@ static void VM_CL_boxparticles (prvm_prog_t *prog) VectorCopy(PRVM_clientglobalvector(particles_colormin), tintmins); VectorCopy(PRVM_clientglobalvector(particles_colormax), tintmaxs); } - if (effectnum < 0) - return; - CL_ParticleTrail(effectnum, count, origin_from, origin_to, dir_from, dir_to, NULL, 0, true, true, tintmins, tintmaxs); + if(flags & 4) // read fade + { + fade = PRVM_clientglobalfloat(particles_fade); + } + if(flags & 128) // draw as trail + { + istrail = true; + } + + if (istrail) + CL_ParticleTrail(effectnum, count, origin_from, origin_to, dir_from, dir_to, NULL, 0, true, true, tintmins, tintmaxs, fade); + else + CL_ParticleBox(effectnum, count, origin_from, origin_to, dir_from, dir_to, NULL, 0, true, true, tintmins, tintmaxs, fade); } //#531 void(float pause) setpause static void VM_CL_setpause(prvm_prog_t *prog) { VM_SAFEPARMCOUNT(1, VM_CL_setpause); - if ((int)PRVM_G_FLOAT(OFS_PARM0) != 0) - cl.csqc_paused = true; - else - cl.csqc_paused = false; + if(cl.islocalgame) + { + if ((int)PRVM_G_FLOAT(OFS_PARM0) != 0) + host.paused = true; + else + host.paused = false; + } } //#343 void(float usecursor) setcursormode (DP_CSQC) @@ -1408,9 +2222,9 @@ static void VM_CL_getmousepos(prvm_prog_t *prog) //#345 float(float framenum) getinputstate (EXT_CSQC) static void VM_CL_getinputstate (prvm_prog_t *prog) { - int i, frame; + unsigned int i, frame; VM_SAFEPARMCOUNT(1, VM_CL_getinputstate); - frame = (int)PRVM_G_FLOAT(OFS_PARM0); + frame = (unsigned int)PRVM_G_FLOAT(OFS_PARM0); PRVM_G_FLOAT(OFS_RETURN) = false; for (i = 0;i < CL_MAX_USERCMDS;i++) { @@ -1455,12 +2269,15 @@ static void VM_CL_runplayerphysics (prvm_prog_t *prog) cl_clientmovement_state_t s; prvm_edict_t *ent; + memset(&s, 0, sizeof(s)); + VM_SAFEPARMCOUNTRANGE(0, 1, VM_CL_runplayerphysics); ent = (prog->argc == 1 ? PRVM_G_EDICT(OFS_PARM0) : prog->edicts); if(ent == prog->edicts) { // deprecated use + s.self = NULL; VectorCopy(PRVM_clientglobalvector(pmove_org), s.origin); VectorCopy(PRVM_clientglobalvector(pmove_vel), s.velocity); VectorCopy(PRVM_clientglobalvector(pmove_mins), s.mins); @@ -1472,6 +2289,7 @@ static void VM_CL_runplayerphysics (prvm_prog_t *prog) else { // new use + s.self = ent; VectorCopy(PRVM_clientedictvector(ent, origin), s.origin); VectorCopy(PRVM_clientedictvector(ent, velocity), s.velocity); VectorCopy(PRVM_clientedictvector(ent, mins), s.mins); @@ -1562,20 +2380,6 @@ static void VM_CL_getplayerkey (prvm_prog_t *prog) else if(!strcasecmp(c, "viewentity")) dpsnprintf(t, sizeof(t), "%i", i+1); - else - if(gamemode == GAME_XONOTIC && !strcasecmp(c, "TEMPHACK_origin")) - { - // PLEASE REMOVE THIS once deltalisten() of EXT_CSQC_1 - // is implemented, or Xonotic uses CSQC-networked - // players, whichever comes first - entity_t *e = cl.entities + (i+1); - if(e->state_current.active) - { - vec3_t origin; - Matrix4x4_OriginFromMatrix(&e->render.matrix, origin); - dpsnprintf(t, sizeof(t), "%.9g %.9g %.9g", origin[0], origin[1], origin[2]); - } - } if(!t[0]) return; PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, t); @@ -1584,28 +2388,22 @@ static void VM_CL_getplayerkey (prvm_prog_t *prog) //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC) static void VM_CL_setlistener (prvm_prog_t *prog) { + vec3_t origin, forward, left, up; VM_SAFEPARMCOUNT(4, VM_CL_setlistener); - Matrix4x4_FromVectors(&cl.csqc_listenermatrix, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_VECTOR(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0)); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), origin); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), forward); + VectorNegate(PRVM_G_VECTOR(OFS_PARM2), left); + VectorCopy(PRVM_G_VECTOR(OFS_PARM3), up); + Matrix4x4_FromVectors(&cl.csqc_listenermatrix, forward, left, up, origin); cl.csqc_usecsqclistener = true; //use csqc listener at this frame } //#352 void(string cmdname) registercommand (EXT_CSQC) static void VM_CL_registercmd (prvm_prog_t *prog) { - char *t; VM_SAFEPARMCOUNT(1, VM_CL_registercmd); - if(!Cmd_Exists(PRVM_G_STRING(OFS_PARM0))) - { - size_t alloclen; - - alloclen = strlen(PRVM_G_STRING(OFS_PARM0)) + 1; - t = (char *)Z_Malloc(alloclen); - memcpy(t, PRVM_G_STRING(OFS_PARM0), alloclen); - Cmd_AddCommand(t, NULL, "console command created by QuakeC"); - } - else - Cmd_AddCommand(PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC"); - + if(!Cmd_Exists(cmd_local, PRVM_G_STRING(OFS_PARM0))) + Cmd_AddCommand(CF_CLIENT, PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC"); } //#360 float() readbyte (EXT_CSQC) @@ -1671,26 +2469,24 @@ static void VM_CL_ReadPicture (prvm_prog_t *prog) const char *name; unsigned char *data; unsigned char *buf; - int size; + unsigned short size; int i; cachepic_t *pic; VM_SAFEPARMCOUNT(0, VM_CL_ReadPicture); name = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)); - size = MSG_ReadShort(&cl_message); + size = (unsigned short) MSG_ReadShort(&cl_message); // check if a texture of that name exists // if yes, it is used and the data is discarded // if not, the (low quality) data is used to build a new texture, whose name will get returned - pic = Draw_CachePic_Flags (name, CACHEPICFLAG_NOTPERSISTENT); + pic = Draw_CachePic_Flags(name, CACHEPICFLAG_NOTPERSISTENT | CACHEPICFLAG_FAILONMISSING); if(size) { - if(pic->tex == r_texture_notexture) - pic->tex = NULL; // don't overwrite the notexture by Draw_NewPic - if(pic->tex && !cl_readpicture_force.integer) + if (Draw_IsPicLoaded(pic) && !cl_readpicture_force.integer) { // texture found and loaded // skip over the jpeg as we don't need it @@ -1705,7 +2501,7 @@ static void VM_CL_ReadPicture (prvm_prog_t *prog) MSG_ReadBytes(&cl_message, size, buf); data = JPEG_LoadImage_BGRA(buf, size, NULL); Mem_Free(buf); - Draw_NewPic(name, image_width, image_height, false, data); + Draw_NewPic(name, image_width, image_height, data, TEXTYPE_BGRA, TEXF_CLAMP); Mem_Free(data); } } @@ -1727,7 +2523,7 @@ static void VM_CL_makestatic (prvm_prog_t *prog) VM_Warning(prog, "makestatic: can not modify world entity\n"); return; } - if (ent->priv.server->free) + if (ent->free) { VM_Warning(prog, "makestatic: can not modify free entity\n"); return; @@ -1765,9 +2561,12 @@ static void VM_CL_makestatic (prvm_prog_t *prog) renderflags = (int)PRVM_clientedictfloat(ent, renderflags); if (renderflags & RF_USEAXIS) { - vec3_t left; + vec3_t forward, left, up, origin; + VectorCopy(PRVM_clientglobalvector(v_forward), forward); VectorNegate(PRVM_clientglobalvector(v_right), left); - Matrix4x4_FromVectors(&staticent->render.matrix, PRVM_clientglobalvector(v_forward), left, PRVM_clientglobalvector(v_up), PRVM_clientedictvector(ent, origin)); + VectorCopy(PRVM_clientglobalvector(v_up), up); + VectorCopy(PRVM_clientedictvector(ent, origin), origin); + Matrix4x4_FromVectors(&staticent->render.matrix, forward, left, up, origin); Matrix4x4_Scale(&staticent->render.matrix, staticent->render.scale, 1); } else @@ -1778,8 +2577,6 @@ static void VM_CL_makestatic (prvm_prog_t *prog) { if (!(staticent->render.effects & EF_FULLBRIGHT)) staticent->render.flags |= RENDER_LIGHT; - else if(r_equalize_entities_fullbright.integer) - staticent->render.flags |= RENDER_LIGHT | RENDER_EQUALIZE; } // turn off shadows from transparent objects if (!(staticent->render.effects & (EF_NOSHADOW | EF_ADDITIVE | EF_NODEPTHTEST)) && (staticent->render.alpha >= 1)) @@ -1822,7 +2619,7 @@ static void VM_CL_copyentity (prvm_prog_t *prog) VM_Warning(prog, "copyentity: can not read world entity\n"); return; } - if (in->priv.server->free) + if (in->free) { VM_Warning(prog, "copyentity: can not read free entity\n"); return; @@ -1833,12 +2630,15 @@ static void VM_CL_copyentity (prvm_prog_t *prog) VM_Warning(prog, "copyentity: can not modify world entity\n"); return; } - if (out->priv.server->free) + if (out->free) { VM_Warning(prog, "copyentity: can not modify free entity\n"); return; } - memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4); + memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t)); + + if (VectorCompare(PRVM_clientedictvector(out, absmin), PRVM_clientedictvector(out, absmax))) + return; CL_LinkEdict(out); } @@ -1847,28 +2647,36 @@ static void VM_CL_copyentity (prvm_prog_t *prog) // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT) static void VM_CL_effect (prvm_prog_t *prog) { + model_t *model; + vec3_t org; VM_SAFEPARMCOUNT(5, VM_CL_effect); - CL_Effect(PRVM_G_VECTOR(OFS_PARM0), (int)PRVM_G_FLOAT(OFS_PARM1), (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4)); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org); + + model = Mod_FindName(PRVM_G_STRING(OFS_PARM1), NULL); + if(model->loaded) + CL_Effect(org, model, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4)); + else + Con_Printf(CON_ERROR "VM_CL_effect: Could not load model '%s'\n", PRVM_G_STRING(OFS_PARM1)); } // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD) static void VM_CL_te_blood (prvm_prog_t *prog) { - float *pos; - vec3_t pos2; + vec3_t pos, vel, pos2; VM_SAFEPARMCOUNT(3, VM_CL_te_blood); if (PRVM_G_FLOAT(OFS_PARM2) < 1) return; - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), vel); CL_FindNonSolidLocation(pos, pos2, 4); - CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0); + CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, vel, vel, NULL, 0); } // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER) static void VM_CL_te_bloodshower (prvm_prog_t *prog) { vec_t speed; - vec3_t vel1, vel2; + vec3_t mincorner, maxcorner, vel1, vel2; VM_SAFEPARMCOUNT(4, VM_CL_te_bloodshower); if (PRVM_G_FLOAT(OFS_PARM3) < 1) return; @@ -1879,66 +2687,79 @@ static void VM_CL_te_bloodshower (prvm_prog_t *prog) vel2[0] = speed; vel2[1] = speed; vel2[2] = speed; - CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), vel1, vel2, NULL, 0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), mincorner); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), maxcorner); + CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM3), mincorner, maxcorner, vel1, vel2, NULL, 0); } // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB) static void VM_CL_te_explosionrgb (prvm_prog_t *prog) { - float *pos; + vec3_t pos; vec3_t pos2; matrix4x4_t tempmatrix; VM_SAFEPARMCOUNT(2, VM_CL_te_explosionrgb); - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); CL_FindNonSolidLocation(pos, pos2, 10); CL_ParticleExplosion(pos2); Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]); - CL_AllocLightFlash(NULL, &tempmatrix, 350, PRVM_G_VECTOR(OFS_PARM1)[0], PRVM_G_VECTOR(OFS_PARM1)[1], PRVM_G_VECTOR(OFS_PARM1)[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); + CL_AllocLightFlash(NULL, &tempmatrix, 350, PRVM_G_VECTOR(OFS_PARM1)[0], PRVM_G_VECTOR(OFS_PARM1)[1], PRVM_G_VECTOR(OFS_PARM1)[2], 700, 0.5, NULL, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); } // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE) static void VM_CL_te_particlecube (prvm_prog_t *prog) { + vec3_t mincorner, maxcorner, vel; VM_SAFEPARMCOUNT(7, VM_CL_te_particlecube); - CL_ParticleCube(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), PRVM_G_FLOAT(OFS_PARM5), PRVM_G_FLOAT(OFS_PARM6)); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), mincorner); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), maxcorner); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel); + CL_ParticleCube(mincorner, maxcorner, vel, (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), PRVM_G_FLOAT(OFS_PARM5), PRVM_G_FLOAT(OFS_PARM6)); } // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN) static void VM_CL_te_particlerain (prvm_prog_t *prog) { + vec3_t mincorner, maxcorner, vel; VM_SAFEPARMCOUNT(5, VM_CL_te_particlerain); - CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), mincorner); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), maxcorner); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel); + CL_ParticleRain(mincorner, maxcorner, vel, (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 0); } // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW) static void VM_CL_te_particlesnow (prvm_prog_t *prog) { + vec3_t mincorner, maxcorner, vel; VM_SAFEPARMCOUNT(5, VM_CL_te_particlesnow); - CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 1); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), mincorner); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), maxcorner); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel); + CL_ParticleRain(mincorner, maxcorner, vel, (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 1); } // #411 void(vector org, vector vel, float howmany) te_spark static void VM_CL_te_spark (prvm_prog_t *prog) { - float *pos; - vec3_t pos2; + vec3_t pos, pos2, vel; VM_SAFEPARMCOUNT(3, VM_CL_te_spark); - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), vel); CL_FindNonSolidLocation(pos, pos2, 4); - CL_ParticleEffect(EFFECT_TE_SPARK, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0); + CL_ParticleEffect(EFFECT_TE_SPARK, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, vel, vel, NULL, 0); } extern cvar_t cl_sound_ric_gunshot; // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1) static void VM_CL_te_gunshotquad (prvm_prog_t *prog) { - float *pos; - vec3_t pos2; + vec3_t pos, pos2; int rnd; VM_SAFEPARMCOUNT(1, VM_CL_te_gunshotquad); - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); CL_FindNonSolidLocation(pos, pos2, 4); CL_ParticleEffect(EFFECT_TE_GUNSHOTQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0); if(cl_sound_ric_gunshot.integer >= 2) @@ -1957,12 +2778,11 @@ static void VM_CL_te_gunshotquad (prvm_prog_t *prog) // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1) static void VM_CL_te_spikequad (prvm_prog_t *prog) { - float *pos; - vec3_t pos2; + vec3_t pos, pos2; int rnd; VM_SAFEPARMCOUNT(1, VM_CL_te_spikequad); - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); CL_FindNonSolidLocation(pos, pos2, 4); CL_ParticleEffect(EFFECT_TE_SPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0); if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1); @@ -1978,12 +2798,11 @@ static void VM_CL_te_spikequad (prvm_prog_t *prog) // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1) static void VM_CL_te_superspikequad (prvm_prog_t *prog) { - float *pos; - vec3_t pos2; + vec3_t pos, pos2; int rnd; VM_SAFEPARMCOUNT(1, VM_CL_te_superspikequad); - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); CL_FindNonSolidLocation(pos, pos2, 4); CL_ParticleEffect(EFFECT_TE_SUPERSPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0); if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos, 1, 1); @@ -1999,11 +2818,10 @@ static void VM_CL_te_superspikequad (prvm_prog_t *prog) // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1) static void VM_CL_te_explosionquad (prvm_prog_t *prog) { - float *pos; - vec3_t pos2; + vec3_t pos, pos2; VM_SAFEPARMCOUNT(1, VM_CL_te_explosionquad); - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); CL_FindNonSolidLocation(pos, pos2, 10); CL_ParticleEffect(EFFECT_TE_EXPLOSIONQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0); S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1); @@ -2012,11 +2830,10 @@ static void VM_CL_te_explosionquad (prvm_prog_t *prog) // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH) static void VM_CL_te_smallflash (prvm_prog_t *prog) { - float *pos; - vec3_t pos2; + vec3_t pos, pos2; VM_SAFEPARMCOUNT(1, VM_CL_te_smallflash); - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); CL_FindNonSolidLocation(pos, pos2, 10); CL_ParticleEffect(EFFECT_TE_SMALLFLASH, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0); } @@ -2024,26 +2841,24 @@ static void VM_CL_te_smallflash (prvm_prog_t *prog) // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH) static void VM_CL_te_customflash (prvm_prog_t *prog) { - float *pos; - vec3_t pos2; + vec3_t pos, pos2; matrix4x4_t tempmatrix; VM_SAFEPARMCOUNT(4, VM_CL_te_customflash); - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); CL_FindNonSolidLocation(pos, pos2, 4); Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]); - CL_AllocLightFlash(NULL, &tempmatrix, PRVM_G_FLOAT(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM3)[0], PRVM_G_VECTOR(OFS_PARM3)[1], PRVM_G_VECTOR(OFS_PARM3)[2], PRVM_G_FLOAT(OFS_PARM1) / PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM2), 0, -1, true, 1, 0.25, 1, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); + CL_AllocLightFlash(NULL, &tempmatrix, PRVM_G_FLOAT(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM3)[0], PRVM_G_VECTOR(OFS_PARM3)[1], PRVM_G_VECTOR(OFS_PARM3)[2], PRVM_G_FLOAT(OFS_PARM1) / PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM2), NULL, -1, true, 1, 0.25, 1, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); } // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS) static void VM_CL_te_gunshot (prvm_prog_t *prog) { - float *pos; - vec3_t pos2; + vec3_t pos, pos2; int rnd; VM_SAFEPARMCOUNT(1, VM_CL_te_gunshot); - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); CL_FindNonSolidLocation(pos, pos2, 4); CL_ParticleEffect(EFFECT_TE_GUNSHOT, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0); if(cl_sound_ric_gunshot.integer == 1 || cl_sound_ric_gunshot.integer == 3) @@ -2062,12 +2877,11 @@ static void VM_CL_te_gunshot (prvm_prog_t *prog) // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS) static void VM_CL_te_spike (prvm_prog_t *prog) { - float *pos; - vec3_t pos2; + vec3_t pos, pos2; int rnd; VM_SAFEPARMCOUNT(1, VM_CL_te_spike); - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); CL_FindNonSolidLocation(pos, pos2, 4); CL_ParticleEffect(EFFECT_TE_SPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0); if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1); @@ -2083,12 +2897,11 @@ static void VM_CL_te_spike (prvm_prog_t *prog) // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS) static void VM_CL_te_superspike (prvm_prog_t *prog) { - float *pos; - vec3_t pos2; + vec3_t pos, pos2; int rnd; VM_SAFEPARMCOUNT(1, VM_CL_te_superspike); - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); CL_FindNonSolidLocation(pos, pos2, 4); CL_ParticleEffect(EFFECT_TE_SUPERSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0); if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1); @@ -2104,11 +2917,10 @@ static void VM_CL_te_superspike (prvm_prog_t *prog) // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS) static void VM_CL_te_explosion (prvm_prog_t *prog) { - float *pos; - vec3_t pos2; + vec3_t pos, pos2; VM_SAFEPARMCOUNT(1, VM_CL_te_explosion); - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); CL_FindNonSolidLocation(pos, pos2, 10); CL_ParticleEffect(EFFECT_TE_EXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0); S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1); @@ -2117,11 +2929,10 @@ static void VM_CL_te_explosion (prvm_prog_t *prog) // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS) static void VM_CL_te_tarexplosion (prvm_prog_t *prog) { - float *pos; - vec3_t pos2; + vec3_t pos, pos2; VM_SAFEPARMCOUNT(1, VM_CL_te_tarexplosion); - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); CL_FindNonSolidLocation(pos, pos2, 10); CL_ParticleEffect(EFFECT_TE_TAREXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0); S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1); @@ -2130,11 +2941,10 @@ static void VM_CL_te_tarexplosion (prvm_prog_t *prog) // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS) static void VM_CL_te_wizspike (prvm_prog_t *prog) { - float *pos; - vec3_t pos2; + vec3_t pos, pos2; VM_SAFEPARMCOUNT(1, VM_CL_te_wizspike); - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); CL_FindNonSolidLocation(pos, pos2, 4); CL_ParticleEffect(EFFECT_TE_WIZSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0); S_StartSound(-1, 0, cl.sfx_wizhit, pos2, 1, 1); @@ -2143,11 +2953,10 @@ static void VM_CL_te_wizspike (prvm_prog_t *prog) // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS) static void VM_CL_te_knightspike (prvm_prog_t *prog) { - float *pos; - vec3_t pos2; + vec3_t pos, pos2; VM_SAFEPARMCOUNT(1, VM_CL_te_knightspike); - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); CL_FindNonSolidLocation(pos, pos2, 4); CL_ParticleEffect(EFFECT_TE_KNIGHTSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0); S_StartSound(-1, 0, cl.sfx_knighthit, pos2, 1, 1); @@ -2156,28 +2965,31 @@ static void VM_CL_te_knightspike (prvm_prog_t *prog) // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS) static void VM_CL_te_lavasplash (prvm_prog_t *prog) { + vec3_t pos; VM_SAFEPARMCOUNT(1, VM_CL_te_lavasplash); - CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); + CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); } // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS) static void VM_CL_te_teleport (prvm_prog_t *prog) { + vec3_t pos; VM_SAFEPARMCOUNT(1, VM_CL_te_teleport); - CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); + CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); } // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS) static void VM_CL_te_explosion2 (prvm_prog_t *prog) { - float *pos; - vec3_t pos2, color; + vec3_t pos, pos2, color; matrix4x4_t tempmatrix; int colorStart, colorLength; unsigned char *tempcolor; VM_SAFEPARMCOUNT(3, VM_CL_te_explosion2); - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); colorStart = (int)PRVM_G_FLOAT(OFS_PARM1); colorLength = (int)PRVM_G_FLOAT(OFS_PARM2); CL_FindNonSolidLocation(pos, pos2, 10); @@ -2187,7 +2999,7 @@ static void VM_CL_te_explosion2 (prvm_prog_t *prog) color[1] = tempcolor[1] * (2.0f / 255.0f); color[2] = tempcolor[2] * (2.0f / 255.0f); Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]); - CL_AllocLightFlash(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); + CL_AllocLightFlash(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, NULL, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1); } @@ -2195,39 +3007,50 @@ static void VM_CL_te_explosion2 (prvm_prog_t *prog) // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS) static void VM_CL_te_lightning1 (prvm_prog_t *prog) { + vec3_t start, end; VM_SAFEPARMCOUNT(3, VM_CL_te_lightning1); - CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), start); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), end); + CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), start, end, cl.model_bolt, true); } // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS) static void VM_CL_te_lightning2 (prvm_prog_t *prog) { + vec3_t start, end; VM_SAFEPARMCOUNT(3, VM_CL_te_lightning2); - CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), start); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), end); + CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), start, end, cl.model_bolt2, true); } // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS) static void VM_CL_te_lightning3 (prvm_prog_t *prog) { + vec3_t start, end; VM_SAFEPARMCOUNT(3, VM_CL_te_lightning3); - CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), start); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), end); + CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), start, end, cl.model_bolt3, false); } // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS) static void VM_CL_te_beam (prvm_prog_t *prog) { + vec3_t start, end; VM_SAFEPARMCOUNT(3, VM_CL_te_beam); - CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), start); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), end); + CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), start, end, cl.model_beam, false); } // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN) static void VM_CL_te_plasmaburn (prvm_prog_t *prog) { - float *pos; - vec3_t pos2; + vec3_t pos, pos2; VM_SAFEPARMCOUNT(1, VM_CL_te_plasmaburn); - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); CL_FindNonSolidLocation(pos, pos2, 4); CL_ParticleEffect(EFFECT_TE_PLASMABURN, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0); } @@ -2235,14 +3058,14 @@ static void VM_CL_te_plasmaburn (prvm_prog_t *prog) // #457 void(vector org, vector velocity, float howmany) te_flamejet (DP_TE_FLAMEJET) static void VM_CL_te_flamejet (prvm_prog_t *prog) { - float *pos; - vec3_t pos2; + vec3_t pos, pos2, vel; VM_SAFEPARMCOUNT(3, VM_CL_te_flamejet); if (PRVM_G_FLOAT(OFS_PARM2) < 1) return; - pos = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), vel); CL_FindNonSolidLocation(pos, pos2, 4); - CL_ParticleEffect(EFFECT_TE_FLAMEJET, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0); + CL_ParticleEffect(EFFECT_TE_FLAMEJET, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, vel, vel, NULL, 0); } @@ -2254,7 +3077,7 @@ static void VM_CL_setattachment (prvm_prog_t *prog) const char *tagname; int modelindex; int tagindex; - dp_model_t *model; + model_t *model; VM_SAFEPARMCOUNT(3, VM_CL_setattachment); e = PRVM_G_EDICT(OFS_PARM0); @@ -2266,7 +3089,7 @@ static void VM_CL_setattachment (prvm_prog_t *prog) VM_Warning(prog, "setattachment: can not modify world entity\n"); return; } - if (e->priv.server->free) + if (e->free) { VM_Warning(prog, "setattachment: can not modify free entity\n"); return; @@ -2299,7 +3122,7 @@ static void VM_CL_setattachment (prvm_prog_t *prog) static int CL_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname) { - dp_model_t *model = CL_GetModelFromEdict(e); + model_t *model = CL_GetModelFromEdict(e); if (model) return Mod_Alias_GetTagIndexForName(model, (int)PRVM_clientedictfloat(e, skin), tagname); else @@ -2309,7 +3132,7 @@ static int CL_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagna static int CL_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix) { int r; - dp_model_t *model; + model_t *model; *tagname = NULL; *parentindex = 0; @@ -2332,13 +3155,13 @@ static int CL_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagind int CL_GetPitchSign(prvm_prog_t *prog, prvm_edict_t *ent) { - dp_model_t *model; + model_t *model; if ((model = CL_GetModelFromEdict(ent)) && model->type == mod_alias) return -1; return 1; } -void CL_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix) +void CL_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qbool viewmatrix) { float scale; float pitchsign = 1; @@ -2370,13 +3193,13 @@ void CL_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, static int CL_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out) { - dp_model_t *model; + model_t *model; if (tagindex >= 0 && (model = CL_GetModelFromEdict(ent)) && model->animscenes) { VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent); - VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model); + VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, cl.time); VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend); return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out); } @@ -2394,18 +3217,19 @@ static int CL_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int extern cvar_t cl_bob; extern cvar_t cl_bobcycle; extern cvar_t cl_bobup; -int CL_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex) +int CL_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex, prvm_vec_t *returnshadingorigin) { int ret; int attachloop; matrix4x4_t entitymatrix, tagmatrix, attachmatrix; - dp_model_t *model; + model_t *model; + vec3_t shadingorigin; *out = identitymatrix; // warnings and errors return identical matrix if (ent == prog->edicts) return 1; - if (ent->priv.server->free) + if (ent->free) return 2; model = CL_GetModelFromEdict(ent); @@ -2450,9 +3274,9 @@ int CL_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int if (PRVM_clientedictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value) { double bob, cycle; - // LordHavoc: this code is *weird*, but not replacable (I think it + // LadyHavoc: this code is *weird*, but not replacable (I think it // should be done in QC on the server, but oh well, quake is quake) - // LordHavoc: figured out bobup: the time at which the sin is at 180 + // LadyHavoc: figured out bobup: the time at which the sin is at 180 // degrees (which allows lengthening or squishing the peak or valley) cycle = cl.time/cl_bobcycle.value; cycle -= (int)cycle; @@ -2467,7 +3291,17 @@ int CL_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4)); } */ + + // return the origin of the view + Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, shadingorigin); + } + else + { + // return the origin of the root entity in the chain + Matrix4x4_OriginFromMatrix(out, shadingorigin); } + if (returnshadingorigin) + VectorCopy(shadingorigin, returnshadingorigin); return 0; } @@ -2487,7 +3321,7 @@ static void VM_CL_gettagindex (prvm_prog_t *prog) VM_Warning(prog, "VM_CL_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent)); return; } - if (ent->priv.server->free) + if (ent->free) { VM_Warning(prog, "VM_CL_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent)); return; @@ -2516,29 +3350,32 @@ static void VM_CL_gettaginfo (prvm_prog_t *prog) int parentindex; const char *tagname; int returncode; - vec3_t fo, le, up, trans; - const dp_model_t *model; + vec3_t forward, left, up, origin; + const model_t *model; VM_SAFEPARMCOUNT(2, VM_CL_gettaginfo); e = PRVM_G_EDICT(OFS_PARM0); tagindex = (int)PRVM_G_FLOAT(OFS_PARM1); - returncode = CL_GetTagMatrix(prog, &tag_matrix, e, tagindex); - Matrix4x4_ToVectors(&tag_matrix, PRVM_clientglobalvector(v_forward), le, PRVM_clientglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN)); - VectorScale(le, -1, PRVM_clientglobalvector(v_right)); + returncode = CL_GetTagMatrix(prog, &tag_matrix, e, tagindex, NULL); + Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin); + VectorCopy(forward, PRVM_clientglobalvector(v_forward)); + VectorScale(left, -1, PRVM_clientglobalvector(v_right)); + VectorCopy(up, PRVM_clientglobalvector(v_up)); + VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN)); model = CL_GetModelFromEdict(e); VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e); - VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model); + VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, cl.time); VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend); CL_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix); - Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans); + Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin); PRVM_clientglobalfloat(gettaginfo_parent) = parentindex; PRVM_clientglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0; - VectorCopy(trans, PRVM_clientglobalvector(gettaginfo_offset)); - VectorCopy(fo, PRVM_clientglobalvector(gettaginfo_forward)); - VectorScale(le, -1, PRVM_clientglobalvector(gettaginfo_right)); + VectorCopy(forward, PRVM_clientglobalvector(gettaginfo_forward)); + VectorScale(left, -1, PRVM_clientglobalvector(gettaginfo_right)); VectorCopy(up, PRVM_clientglobalvector(gettaginfo_up)); + VectorCopy(origin, PRVM_clientglobalvector(gettaginfo_offset)); switch(returncode) { @@ -2571,7 +3408,7 @@ static void VM_CL_gettaginfo (prvm_prog_t *prog) typedef struct vmparticletheme_s { unsigned short typeindex; - qboolean initialized; + qbool initialized; pblend_t blendmode; porientation_t orientation; int color1; @@ -2587,7 +3424,7 @@ typedef struct vmparticletheme_s float liquidfriction; float originjitter; float velocityjitter; - qboolean qualityreduction; + qbool qualityreduction; float lifetime; float stretch; int staincolor1; @@ -2605,39 +3442,10 @@ typedef struct vmparticletheme_s typedef struct vmparticlespawner_s { mempool_t *pool; - qboolean initialized; - qboolean verified; + qbool initialized; + qbool verified; vmparticletheme_t *themes; int max_themes; - // global addresses - float *particle_type; - float *particle_blendmode; - float *particle_orientation; - float *particle_color1; - float *particle_color2; - float *particle_tex; - float *particle_size; - float *particle_sizeincrease; - float *particle_alpha; - float *particle_alphafade; - float *particle_time; - float *particle_gravity; - float *particle_bounce; - float *particle_airfriction; - float *particle_liquidfriction; - float *particle_originjitter; - float *particle_velocityjitter; - float *particle_qualityreduction; - float *particle_stretch; - float *particle_staincolor1; - float *particle_staincolor2; - float *particle_stainalpha; - float *particle_stainsize; - float *particle_staintex; - float *particle_delayspawn; - float *particle_delaycollision; - float *particle_angle; - float *particle_spin; }vmparticlespawner_t; vmparticlespawner_t vmpartspawner; @@ -2661,38 +3469,6 @@ static void VM_InitParticleSpawner (prvm_prog_t *prog, int maxthemes) vmpartspawner.max_themes = maxthemes; vmpartspawner.initialized = true; vmpartspawner.verified = true; - // get field addresses for fast querying (we can do 1000 calls of spawnparticle in a frame) - vmpartspawner.particle_type = &PRVM_clientglobalfloat(particle_type); - vmpartspawner.particle_blendmode = &PRVM_clientglobalfloat(particle_blendmode); - vmpartspawner.particle_orientation = &PRVM_clientglobalfloat(particle_orientation); - vmpartspawner.particle_color1 = PRVM_clientglobalvector(particle_color1); - vmpartspawner.particle_color2 = PRVM_clientglobalvector(particle_color2); - vmpartspawner.particle_tex = &PRVM_clientglobalfloat(particle_tex); - vmpartspawner.particle_size = &PRVM_clientglobalfloat(particle_size); - vmpartspawner.particle_sizeincrease = &PRVM_clientglobalfloat(particle_sizeincrease); - vmpartspawner.particle_alpha = &PRVM_clientglobalfloat(particle_alpha); - vmpartspawner.particle_alphafade = &PRVM_clientglobalfloat(particle_alphafade); - vmpartspawner.particle_time = &PRVM_clientglobalfloat(particle_time); - vmpartspawner.particle_gravity = &PRVM_clientglobalfloat(particle_gravity); - vmpartspawner.particle_bounce = &PRVM_clientglobalfloat(particle_bounce); - vmpartspawner.particle_airfriction = &PRVM_clientglobalfloat(particle_airfriction); - vmpartspawner.particle_liquidfriction = &PRVM_clientglobalfloat(particle_liquidfriction); - vmpartspawner.particle_originjitter = &PRVM_clientglobalfloat(particle_originjitter); - vmpartspawner.particle_velocityjitter = &PRVM_clientglobalfloat(particle_velocityjitter); - vmpartspawner.particle_qualityreduction = &PRVM_clientglobalfloat(particle_qualityreduction); - vmpartspawner.particle_stretch = &PRVM_clientglobalfloat(particle_stretch); - vmpartspawner.particle_staincolor1 = PRVM_clientglobalvector(particle_staincolor1); - vmpartspawner.particle_staincolor2 = PRVM_clientglobalvector(particle_staincolor2); - vmpartspawner.particle_stainalpha = &PRVM_clientglobalfloat(particle_stainalpha); - vmpartspawner.particle_stainsize = &PRVM_clientglobalfloat(particle_stainsize); - vmpartspawner.particle_staintex = &PRVM_clientglobalfloat(particle_staintex); - vmpartspawner.particle_staintex = &PRVM_clientglobalfloat(particle_staintex); - vmpartspawner.particle_delayspawn = &PRVM_clientglobalfloat(particle_delayspawn); - vmpartspawner.particle_delaycollision = &PRVM_clientglobalfloat(particle_delaycollision); - vmpartspawner.particle_angle = &PRVM_clientglobalfloat(particle_angle); - vmpartspawner.particle_spin = &PRVM_clientglobalfloat(particle_spin); - #undef getglobal - #undef getglobalvector } // reset particle theme to default values @@ -2728,77 +3504,70 @@ static void VM_ResetParticleTheme (vmparticletheme_t *theme) } // particle theme -> QC globals -static void VM_CL_ParticleThemeToGlobals(vmparticletheme_t *theme) -{ - *vmpartspawner.particle_type = theme->typeindex; - *vmpartspawner.particle_blendmode = theme->blendmode; - *vmpartspawner.particle_orientation = theme->orientation; - vmpartspawner.particle_color1[0] = (theme->color1 >> 16) & 0xFF; // VorteX: int only can store 0-255, not 0-256 which means 0 - 0,99609375... - vmpartspawner.particle_color1[1] = (theme->color1 >> 8) & 0xFF; - vmpartspawner.particle_color1[2] = (theme->color1 >> 0) & 0xFF; - vmpartspawner.particle_color2[0] = (theme->color2 >> 16) & 0xFF; - vmpartspawner.particle_color2[1] = (theme->color2 >> 8) & 0xFF; - vmpartspawner.particle_color2[2] = (theme->color2 >> 0) & 0xFF; - *vmpartspawner.particle_tex = (float)theme->tex; - *vmpartspawner.particle_size = theme->size; - *vmpartspawner.particle_sizeincrease = theme->sizeincrease; - *vmpartspawner.particle_alpha = theme->alpha/256; - *vmpartspawner.particle_alphafade = theme->alphafade/256; - *vmpartspawner.particle_time = theme->lifetime; - *vmpartspawner.particle_gravity = theme->gravity; - *vmpartspawner.particle_bounce = theme->bounce; - *vmpartspawner.particle_airfriction = theme->airfriction; - *vmpartspawner.particle_liquidfriction = theme->liquidfriction; - *vmpartspawner.particle_originjitter = theme->originjitter; - *vmpartspawner.particle_velocityjitter = theme->velocityjitter; - *vmpartspawner.particle_qualityreduction = theme->qualityreduction; - *vmpartspawner.particle_stretch = theme->stretch; - vmpartspawner.particle_staincolor1[0] = ((int)theme->staincolor1 >> 16) & 0xFF; - vmpartspawner.particle_staincolor1[1] = ((int)theme->staincolor1 >> 8) & 0xFF; - vmpartspawner.particle_staincolor1[2] = ((int)theme->staincolor1 >> 0) & 0xFF; - vmpartspawner.particle_staincolor2[0] = ((int)theme->staincolor2 >> 16) & 0xFF; - vmpartspawner.particle_staincolor2[1] = ((int)theme->staincolor2 >> 8) & 0xFF; - vmpartspawner.particle_staincolor2[2] = ((int)theme->staincolor2 >> 0) & 0xFF; - *vmpartspawner.particle_staintex = (float)theme->staintex; - *vmpartspawner.particle_stainalpha = (float)theme->stainalpha/256; - *vmpartspawner.particle_stainsize = (float)theme->stainsize; - *vmpartspawner.particle_delayspawn = theme->delayspawn; - *vmpartspawner.particle_delaycollision = theme->delaycollision; - *vmpartspawner.particle_angle = theme->angle; - *vmpartspawner.particle_spin = theme->spin; +static void VM_CL_ParticleThemeToGlobals(vmparticletheme_t *theme, prvm_prog_t *prog) +{ + PRVM_clientglobalfloat(particle_type) = theme->typeindex; + PRVM_clientglobalfloat(particle_blendmode) = theme->blendmode; + PRVM_clientglobalfloat(particle_orientation) = theme->orientation; + // VorteX: int only can store 0-255, not 0-256 which means 0 - 0,99609375... + VectorSet(PRVM_clientglobalvector(particle_color1), (theme->color1 >> 16) & 0xFF, (theme->color1 >> 8) & 0xFF, (theme->color1 >> 0) & 0xFF); + VectorSet(PRVM_clientglobalvector(particle_color2), (theme->color2 >> 16) & 0xFF, (theme->color2 >> 8) & 0xFF, (theme->color2 >> 0) & 0xFF); + PRVM_clientglobalfloat(particle_tex) = (prvm_vec_t)theme->tex; + PRVM_clientglobalfloat(particle_size) = theme->size; + PRVM_clientglobalfloat(particle_sizeincrease) = theme->sizeincrease; + PRVM_clientglobalfloat(particle_alpha) = theme->alpha/256; + PRVM_clientglobalfloat(particle_alphafade) = theme->alphafade/256; + PRVM_clientglobalfloat(particle_time) = theme->lifetime; + PRVM_clientglobalfloat(particle_gravity) = theme->gravity; + PRVM_clientglobalfloat(particle_bounce) = theme->bounce; + PRVM_clientglobalfloat(particle_airfriction) = theme->airfriction; + PRVM_clientglobalfloat(particle_liquidfriction) = theme->liquidfriction; + PRVM_clientglobalfloat(particle_originjitter) = theme->originjitter; + PRVM_clientglobalfloat(particle_velocityjitter) = theme->velocityjitter; + PRVM_clientglobalfloat(particle_qualityreduction) = theme->qualityreduction; + PRVM_clientglobalfloat(particle_stretch) = theme->stretch; + VectorSet(PRVM_clientglobalvector(particle_staincolor1), ((int)theme->staincolor1 >> 16) & 0xFF, ((int)theme->staincolor1 >> 8) & 0xFF, ((int)theme->staincolor1 >> 0) & 0xFF); + VectorSet(PRVM_clientglobalvector(particle_staincolor2), ((int)theme->staincolor2 >> 16) & 0xFF, ((int)theme->staincolor2 >> 8) & 0xFF, ((int)theme->staincolor2 >> 0) & 0xFF); + PRVM_clientglobalfloat(particle_staintex) = (prvm_vec_t)theme->staintex; + PRVM_clientglobalfloat(particle_stainalpha) = (prvm_vec_t)theme->stainalpha/256; + PRVM_clientglobalfloat(particle_stainsize) = (prvm_vec_t)theme->stainsize; + PRVM_clientglobalfloat(particle_delayspawn) = theme->delayspawn; + PRVM_clientglobalfloat(particle_delaycollision) = theme->delaycollision; + PRVM_clientglobalfloat(particle_angle) = theme->angle; + PRVM_clientglobalfloat(particle_spin) = theme->spin; } // QC globals -> particle theme -static void VM_CL_ParticleThemeFromGlobals(vmparticletheme_t *theme) -{ - theme->typeindex = (unsigned short)*vmpartspawner.particle_type; - 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; - theme->size = *vmpartspawner.particle_size; - theme->sizeincrease = *vmpartspawner.particle_sizeincrease; - theme->alpha = *vmpartspawner.particle_alpha*256; - theme->alphafade = *vmpartspawner.particle_alphafade*256; - theme->lifetime = *vmpartspawner.particle_time; - theme->gravity = *vmpartspawner.particle_gravity; - theme->bounce = *vmpartspawner.particle_bounce; - theme->airfriction = *vmpartspawner.particle_airfriction; - theme->liquidfriction = *vmpartspawner.particle_liquidfriction; - theme->originjitter = *vmpartspawner.particle_originjitter; - theme->velocityjitter = *vmpartspawner.particle_velocityjitter; - theme->qualityreduction = (*vmpartspawner.particle_qualityreduction) ? true : false; - theme->stretch = *vmpartspawner.particle_stretch; - theme->staincolor1 = ((int)vmpartspawner.particle_staincolor1[0])*65536 + (int)(vmpartspawner.particle_staincolor1[1])*256 + (int)(vmpartspawner.particle_staincolor1[2]); - theme->staincolor2 = (int)(vmpartspawner.particle_staincolor2[0])*65536 + (int)(vmpartspawner.particle_staincolor2[1])*256 + (int)(vmpartspawner.particle_staincolor2[2]); - theme->staintex =(int)*vmpartspawner.particle_staintex; - theme->stainalpha = *vmpartspawner.particle_stainalpha*256; - theme->stainsize = *vmpartspawner.particle_stainsize; - theme->delayspawn = *vmpartspawner.particle_delayspawn; - theme->delaycollision = *vmpartspawner.particle_delaycollision; - theme->angle = *vmpartspawner.particle_angle; - theme->spin = *vmpartspawner.particle_spin; +static void VM_CL_ParticleThemeFromGlobals(vmparticletheme_t *theme, prvm_prog_t *prog) +{ + theme->typeindex = (unsigned short)PRVM_clientglobalfloat(particle_type); + theme->blendmode = (pblend_t)(int)PRVM_clientglobalfloat(particle_blendmode); + theme->orientation = (porientation_t)(int)PRVM_clientglobalfloat(particle_orientation); + theme->color1 = ((int)PRVM_clientglobalvector(particle_color1)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color1)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color1)[2]); + theme->color2 = ((int)PRVM_clientglobalvector(particle_color2)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color2)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color2)[2]); + theme->tex = (int)PRVM_clientglobalfloat(particle_tex); + theme->size = PRVM_clientglobalfloat(particle_size); + theme->sizeincrease = PRVM_clientglobalfloat(particle_sizeincrease); + theme->alpha = PRVM_clientglobalfloat(particle_alpha)*256; + theme->alphafade = PRVM_clientglobalfloat(particle_alphafade)*256; + theme->lifetime = PRVM_clientglobalfloat(particle_time); + theme->gravity = PRVM_clientglobalfloat(particle_gravity); + theme->bounce = PRVM_clientglobalfloat(particle_bounce); + theme->airfriction = PRVM_clientglobalfloat(particle_airfriction); + theme->liquidfriction = PRVM_clientglobalfloat(particle_liquidfriction); + theme->originjitter = PRVM_clientglobalfloat(particle_originjitter); + theme->velocityjitter = PRVM_clientglobalfloat(particle_velocityjitter); + theme->qualityreduction = PRVM_clientglobalfloat(particle_qualityreduction) != 0 ? true : false; + theme->stretch = PRVM_clientglobalfloat(particle_stretch); + theme->staincolor1 = ((int)PRVM_clientglobalvector(particle_staincolor1)[0])*65536 + (int)(PRVM_clientglobalvector(particle_staincolor1)[1])*256 + (int)(PRVM_clientglobalvector(particle_staincolor1)[2]); + theme->staincolor2 = (int)(PRVM_clientglobalvector(particle_staincolor2)[0])*65536 + (int)(PRVM_clientglobalvector(particle_staincolor2)[1])*256 + (int)(PRVM_clientglobalvector(particle_staincolor2)[2]); + theme->staintex =(int)PRVM_clientglobalfloat(particle_staintex); + theme->stainalpha = PRVM_clientglobalfloat(particle_stainalpha)*256; + theme->stainsize = PRVM_clientglobalfloat(particle_stainsize); + theme->delayspawn = PRVM_clientglobalfloat(particle_delayspawn); + theme->delaycollision = PRVM_clientglobalfloat(particle_delaycollision); + theme->angle = PRVM_clientglobalfloat(particle_angle); + theme->spin = PRVM_clientglobalfloat(particle_spin); } // init particle spawner interface @@ -2821,7 +3590,7 @@ static void VM_CL_ResetParticle (prvm_prog_t *prog) VM_Warning(prog, "VM_CL_ResetParticle: particle spawner not initialized\n"); return; } - VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]); + VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0], prog); } // void(float themenum) particletheme @@ -2839,17 +3608,17 @@ static void VM_CL_ParticleTheme (prvm_prog_t *prog) if (themenum < 0 || themenum >= vmpartspawner.max_themes) { VM_Warning(prog, "VM_CL_ParticleTheme: bad theme number %i\n", themenum); - VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]); + VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0], prog); return; } if (vmpartspawner.themes[themenum].initialized == false) { VM_Warning(prog, "VM_CL_ParticleTheme: theme #%i not exists\n", themenum); - VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]); + VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0], prog); return; } // load particle theme into globals - VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[themenum]); + VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[themenum], prog); } // float() saveparticletheme @@ -2880,7 +3649,7 @@ static void VM_CL_ParticleThemeSave (prvm_prog_t *prog) return; } vmpartspawner.themes[themenum].initialized = true; - VM_CL_ParticleThemeFromGlobals(&vmpartspawner.themes[themenum]); + VM_CL_ParticleThemeFromGlobals(&vmpartspawner.themes[themenum], prog); PRVM_G_FLOAT(OFS_RETURN) = themenum; return; } @@ -2892,7 +3661,7 @@ static void VM_CL_ParticleThemeSave (prvm_prog_t *prog) return; } vmpartspawner.themes[themenum].initialized = true; - VM_CL_ParticleThemeFromGlobals(&vmpartspawner.themes[themenum]); + VM_CL_ParticleThemeFromGlobals(&vmpartspawner.themes[themenum], prog); } // void(float themenum) freeparticletheme @@ -2916,7 +3685,7 @@ static void VM_CL_ParticleThemeFree (prvm_prog_t *prog) if (vmpartspawner.themes[themenum].initialized == false) { VM_Warning(prog, "VM_CL_ParticleThemeFree: theme #%i already freed\n", themenum); - VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]); + VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0], prog); return; } // free theme @@ -2928,33 +3697,66 @@ static void VM_CL_ParticleThemeFree (prvm_prog_t *prog) // returns 0 if failed, 1 if succesful static void VM_CL_SpawnParticle (prvm_prog_t *prog) { - float *org, *dir; + vec3_t org, dir; vmparticletheme_t *theme; particle_t *part; int themenum; - VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_SpawnParticle2); + VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_SpawnParticle); if (vmpartspawner.verified == false) { VM_Warning(prog, "VM_CL_SpawnParticle: particle spawner not initialized\n"); - PRVM_G_FLOAT(OFS_RETURN) = 0; + PRVM_G_FLOAT(OFS_RETURN) = 0; return; } - org = PRVM_G_VECTOR(OFS_PARM0); - dir = PRVM_G_VECTOR(OFS_PARM1); - + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir); + 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)(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); + part = CL_NewParticle(org, + (unsigned short)PRVM_clientglobalfloat(particle_type), + ((int)PRVM_clientglobalvector(particle_color1)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color1)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color1)[2]), + ((int)PRVM_clientglobalvector(particle_color2)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color2)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color2)[2]), + (int)PRVM_clientglobalfloat(particle_tex), + PRVM_clientglobalfloat(particle_size), + PRVM_clientglobalfloat(particle_sizeincrease), + PRVM_clientglobalfloat(particle_alpha)*256, + PRVM_clientglobalfloat(particle_alphafade)*256, + PRVM_clientglobalfloat(particle_gravity), + PRVM_clientglobalfloat(particle_bounce), + org[0], + org[1], + org[2], + dir[0], + dir[1], + dir[2], + PRVM_clientglobalfloat(particle_airfriction), + PRVM_clientglobalfloat(particle_liquidfriction), + PRVM_clientglobalfloat(particle_originjitter), + PRVM_clientglobalfloat(particle_velocityjitter), + (PRVM_clientglobalfloat(particle_qualityreduction)) ? true : false, + PRVM_clientglobalfloat(particle_time), + PRVM_clientglobalfloat(particle_stretch), + (pblend_t)(int)PRVM_clientglobalfloat(particle_blendmode), + (porientation_t)(int)PRVM_clientglobalfloat(particle_orientation), + (int)(PRVM_clientglobalvector(particle_staincolor1)[0])*65536 + (int)(PRVM_clientglobalvector(particle_staincolor1)[1])*256 + (int)(PRVM_clientglobalvector(particle_staincolor1)[2]), + (int)(PRVM_clientglobalvector(particle_staincolor2)[0])*65536 + (int)(PRVM_clientglobalvector(particle_staincolor2)[1])*256 + (int)(PRVM_clientglobalvector(particle_staincolor2)[2]), + (int)PRVM_clientglobalfloat(particle_staintex), + PRVM_clientglobalfloat(particle_stainalpha)*256, + PRVM_clientglobalfloat(particle_stainsize), + PRVM_clientglobalfloat(particle_angle), + PRVM_clientglobalfloat(particle_spin), + NULL); if (!part) { - PRVM_G_FLOAT(OFS_RETURN) = 0; + PRVM_G_FLOAT(OFS_RETURN) = 0; return; } - if (*vmpartspawner.particle_delayspawn) - part->delayedspawn = cl.time + *vmpartspawner.particle_delayspawn; - //if (*vmpartspawner.particle_delaycollision) - // part->delayedcollisions = cl.time + *vmpartspawner.particle_delaycollision; + if (PRVM_clientglobalfloat(particle_delayspawn)) + part->delayedspawn = cl.time + PRVM_clientglobalfloat(particle_delayspawn); + //if (PRVM_clientglobalfloat(particle_delaycollision)) + // part->delayedcollisions = cl.time + PRVM_clientglobalfloat(particle_delaycollision); } else // quick themed particle { @@ -2962,14 +3764,47 @@ static void VM_CL_SpawnParticle (prvm_prog_t *prog) if (themenum <= 0 || themenum >= vmpartspawner.max_themes) { VM_Warning(prog, "VM_CL_SpawnParticle: bad theme number %i\n", themenum); - PRVM_G_FLOAT(OFS_RETURN) = 0; + PRVM_G_FLOAT(OFS_RETURN) = 0; return; } theme = &vmpartspawner.themes[themenum]; - part = CL_NewParticle(org, theme->typeindex, theme->color1, theme->color2, theme->tex, theme->size, theme->sizeincrease, theme->alpha, theme->alphafade, theme->gravity, theme->bounce, org[0], org[1], org[2], dir[0], dir[1], dir[2], theme->airfriction, theme->liquidfriction, theme->originjitter, theme->velocityjitter, theme->qualityreduction, theme->lifetime, theme->stretch, theme->blendmode, theme->orientation, theme->staincolor1, theme->staincolor2, theme->staintex, theme->stainalpha, theme->stainsize, theme->angle, theme->spin, NULL); + part = CL_NewParticle(org, + theme->typeindex, + theme->color1, + theme->color2, + theme->tex, + theme->size, + theme->sizeincrease, + theme->alpha, + theme->alphafade, + theme->gravity, + theme->bounce, + org[0], + org[1], + org[2], + dir[0], + dir[1], + dir[2], + theme->airfriction, + theme->liquidfriction, + theme->originjitter, + theme->velocityjitter, + theme->qualityreduction, + theme->lifetime, + theme->stretch, + theme->blendmode, + theme->orientation, + theme->staincolor1, + theme->staincolor2, + theme->staintex, + theme->stainalpha, + theme->stainsize, + theme->angle, + theme->spin, + NULL); if (!part) { - PRVM_G_FLOAT(OFS_RETURN) = 0; + PRVM_G_FLOAT(OFS_RETURN) = 0; return; } if (theme->delayspawn) @@ -2977,45 +3812,111 @@ static void VM_CL_SpawnParticle (prvm_prog_t *prog) //if (theme->delaycollision) // part->delayedcollisions = cl.time + theme->delaycollision; } - PRVM_G_FLOAT(OFS_RETURN) = 1; + PRVM_G_FLOAT(OFS_RETURN) = 1; } // float(vector org, vector dir, float spawndelay, float collisiondelay, [float theme]) delayedparticle // returns 0 if failed, 1 if success static void VM_CL_SpawnParticleDelayed (prvm_prog_t *prog) { - float *org, *dir; + vec3_t org, dir; vmparticletheme_t *theme; particle_t *part; int themenum; - VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_SpawnParticle2); + VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_SpawnParticleDelayed); if (vmpartspawner.verified == false) { - VM_Warning(prog, "VM_CL_SpawnParticle: particle spawner not initialized\n"); - PRVM_G_FLOAT(OFS_RETURN) = 0; + VM_Warning(prog, "VM_CL_SpawnParticleDelayed: particle spawner not initialized\n"); + PRVM_G_FLOAT(OFS_RETURN) = 0; return; } - org = PRVM_G_VECTOR(OFS_PARM0); - dir = PRVM_G_VECTOR(OFS_PARM1); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir); 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)(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); + part = CL_NewParticle(org, + (unsigned short)PRVM_clientglobalfloat(particle_type), + ((int)PRVM_clientglobalvector(particle_color1)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color1)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color1)[2]), + ((int)PRVM_clientglobalvector(particle_color2)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color2)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color2)[2]), + (int)PRVM_clientglobalfloat(particle_tex), + PRVM_clientglobalfloat(particle_size), + PRVM_clientglobalfloat(particle_sizeincrease), + PRVM_clientglobalfloat(particle_alpha)*256, + PRVM_clientglobalfloat(particle_alphafade)*256, + PRVM_clientglobalfloat(particle_gravity), + PRVM_clientglobalfloat(particle_bounce), + org[0], + org[1], + org[2], + dir[0], + dir[1], + dir[2], + PRVM_clientglobalfloat(particle_airfriction), + PRVM_clientglobalfloat(particle_liquidfriction), + PRVM_clientglobalfloat(particle_originjitter), + PRVM_clientglobalfloat(particle_velocityjitter), + (PRVM_clientglobalfloat(particle_qualityreduction)) ? true : false, + PRVM_clientglobalfloat(particle_time), + PRVM_clientglobalfloat(particle_stretch), + (pblend_t)(int)PRVM_clientglobalfloat(particle_blendmode), + (porientation_t)(int)PRVM_clientglobalfloat(particle_orientation), + ((int)PRVM_clientglobalvector(particle_staincolor1)[0] << 16) + ((int)PRVM_clientglobalvector(particle_staincolor1)[1] << 8) + ((int)PRVM_clientglobalvector(particle_staincolor1)[2]), + ((int)PRVM_clientglobalvector(particle_staincolor2)[0] << 16) + ((int)PRVM_clientglobalvector(particle_staincolor2)[1] << 8) + ((int)PRVM_clientglobalvector(particle_staincolor2)[2]), + (int)PRVM_clientglobalfloat(particle_staintex), + PRVM_clientglobalfloat(particle_stainalpha)*256, + PRVM_clientglobalfloat(particle_stainsize), + PRVM_clientglobalfloat(particle_angle), + PRVM_clientglobalfloat(particle_spin), + NULL); else // themed particle { themenum = (int)PRVM_G_FLOAT(OFS_PARM4); if (themenum <= 0 || themenum >= vmpartspawner.max_themes) { - VM_Warning(prog, "VM_CL_SpawnParticle: bad theme number %i\n", themenum); - PRVM_G_FLOAT(OFS_RETURN) = 0; + VM_Warning(prog, "VM_CL_SpawnParticleDelayed: bad theme number %i\n", themenum); + PRVM_G_FLOAT(OFS_RETURN) = 0; return; } theme = &vmpartspawner.themes[themenum]; - part = CL_NewParticle(org, theme->typeindex, theme->color1, theme->color2, theme->tex, theme->size, theme->sizeincrease, theme->alpha, theme->alphafade, theme->gravity, theme->bounce, org[0], org[1], org[2], dir[0], dir[1], dir[2], theme->airfriction, theme->liquidfriction, theme->originjitter, theme->velocityjitter, theme->qualityreduction, theme->lifetime, theme->stretch, theme->blendmode, theme->orientation, theme->staincolor1, theme->staincolor2, theme->staintex, theme->stainalpha, theme->stainsize, theme->angle, theme->spin, NULL); + part = CL_NewParticle(org, + theme->typeindex, + theme->color1, + theme->color2, + theme->tex, + theme->size, + theme->sizeincrease, + theme->alpha, + theme->alphafade, + theme->gravity, + theme->bounce, + org[0], + org[1], + org[2], + dir[0], + dir[1], + dir[2], + theme->airfriction, + theme->liquidfriction, + theme->originjitter, + theme->velocityjitter, + theme->qualityreduction, + theme->lifetime, + theme->stretch, + theme->blendmode, + theme->orientation, + theme->staincolor1, + theme->staincolor2, + theme->staintex, + theme->stainalpha, + theme->stainsize, + theme->angle, + theme->spin, + NULL); } - if (!part) - { - PRVM_G_FLOAT(OFS_RETURN) = 0; - return; + if (!part) + { + PRVM_G_FLOAT(OFS_RETURN) = 0; + return; } part->delayedspawn = cl.time + PRVM_G_FLOAT(OFS_PARM2); //part->delayedcollisions = cl.time + PRVM_G_FLOAT(OFS_PARM3); @@ -3033,8 +3934,8 @@ static void VM_CL_SpawnParticleDelayed (prvm_prog_t *prog) static void VM_CL_GetEntity (prvm_prog_t *prog) { int entnum, fieldnum; - float org[3], v1[3], v2[3]; - VM_SAFEPARMCOUNT(2, VM_CL_GetEntityVec); + vec3_t forward, left, up, org; + VM_SAFEPARMCOUNT(2, VM_CL_GetEntity); entnum = PRVM_G_FLOAT(OFS_PARM0); if (entnum < 0 || entnum >= cl.num_entities) @@ -3049,26 +3950,34 @@ static void VM_CL_GetEntity (prvm_prog_t *prog) PRVM_G_FLOAT(OFS_RETURN) = cl.entities_active[entnum]; break; case 1: // origin - Matrix4x4_OriginFromMatrix(&cl.entities[entnum].render.matrix, PRVM_G_VECTOR(OFS_RETURN)); - break; + Matrix4x4_OriginFromMatrix(&cl.entities[entnum].render.matrix, org); + VectorCopy(org, PRVM_G_VECTOR(OFS_RETURN)); + break; case 2: // forward - Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, PRVM_G_VECTOR(OFS_RETURN), v1, v2, org); + Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, forward, left, up, org); + VectorCopy(forward, PRVM_G_VECTOR(OFS_RETURN)); break; case 3: // right - Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, v1, PRVM_G_VECTOR(OFS_RETURN), v2, org); + Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, forward, left, up, org); + VectorNegate(left, PRVM_G_VECTOR(OFS_RETURN)); break; case 4: // up - Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, v1, v2, PRVM_G_VECTOR(OFS_RETURN), org); + Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, forward, left, up, org); + VectorCopy(up, PRVM_G_VECTOR(OFS_RETURN)); break; case 5: // scale PRVM_G_FLOAT(OFS_RETURN) = Matrix4x4_ScaleFromMatrix(&cl.entities[entnum].render.matrix); - break; + break; case 6: // origin + v_forward, v_right, v_up - Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, PRVM_clientglobalvector(v_forward), PRVM_clientglobalvector(v_right), PRVM_clientglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN)); - break; + Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, forward, left, up, org); + VectorCopy(forward, PRVM_clientglobalvector(v_forward)); + VectorNegate(left, PRVM_clientglobalvector(v_right)); + VectorCopy(up, PRVM_clientglobalvector(v_up)); + VectorCopy(org, PRVM_G_VECTOR(OFS_RETURN)); + break; case 7: // alpha PRVM_G_FLOAT(OFS_RETURN) = cl.entities[entnum].render.alpha; - break; + break; case 8: // colormor VectorCopy(cl.entities[entnum].render.colormod, PRVM_G_VECTOR(OFS_RETURN)); break; @@ -3080,24 +3989,24 @@ static void VM_CL_GetEntity (prvm_prog_t *prog) break; case 11: // skinnum PRVM_G_FLOAT(OFS_RETURN) = cl.entities[entnum].render.skinnum; - break; + break; case 12: // mins - VectorCopy(cl.entities[entnum].render.mins, PRVM_G_VECTOR(OFS_RETURN)); - break; + VectorCopy(cl.entities[entnum].render.mins, PRVM_G_VECTOR(OFS_RETURN)); + break; case 13: // maxs - VectorCopy(cl.entities[entnum].render.maxs, PRVM_G_VECTOR(OFS_RETURN)); - break; + VectorCopy(cl.entities[entnum].render.maxs, PRVM_G_VECTOR(OFS_RETURN)); + break; case 14: // absmin Matrix4x4_OriginFromMatrix(&cl.entities[entnum].render.matrix, org); - VectorAdd(cl.entities[entnum].render.mins, org, PRVM_G_VECTOR(OFS_RETURN)); - break; + VectorAdd(cl.entities[entnum].render.mins, org, PRVM_G_VECTOR(OFS_RETURN)); + break; case 15: // absmax Matrix4x4_OriginFromMatrix(&cl.entities[entnum].render.matrix, org); - VectorAdd(cl.entities[entnum].render.maxs, org, PRVM_G_VECTOR(OFS_RETURN)); + VectorAdd(cl.entities[entnum].render.maxs, org, PRVM_G_VECTOR(OFS_RETURN)); break; case 16: // light - VectorMA(cl.entities[entnum].render.modellight_ambient, 0.5, cl.entities[entnum].render.modellight_diffuse, PRVM_G_VECTOR(OFS_RETURN)); - break; + VectorMA(cl.entities[entnum].render.render_modellight_ambient, 0.5, cl.entities[entnum].render.render_modellight_diffuse, PRVM_G_VECTOR(OFS_RETURN)); + break; default: PRVM_G_FLOAT(OFS_RETURN) = 0; break; @@ -3114,350 +4023,176 @@ static void VM_CL_GetEntity (prvm_prog_t *prog) // --blub static void VM_CL_R_RenderScene (prvm_prog_t *prog) { + qbool ismain = r_refdef.view.ismain; double t = Sys_DirtyTime(); - vmpolygons_t *polys = &prog->vmpolygons; VM_SAFEPARMCOUNT(0, VM_CL_R_RenderScene); // update the views - if(r_refdef.view.ismain) + if(ismain) { // set the main view csqc_main_r_refdef_view = r_refdef.view; - - // clear the flags so no other view becomes "main" unless CSQC sets VF_MAINVIEW - r_refdef.view.ismain = false; - csqc_original_r_refdef_view.ismain = false; } + // now after all of the predraw we know the geometry in the scene mesh and can finalize it for rendering + CL_MeshEntities_Scene_FinalizeRenderEntity(); + // we need to update any RENDER_VIEWMODEL entities at this point because // csqc supplies its own view matrix CL_UpdateViewEntities(); + CL_UpdateEntityShading(); // now draw stuff! - R_RenderView(); - - polys->num_vertices = polys->num_triangles = 0; + R_RenderView(0, NULL, NULL, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height); // callprofile fixing hack: do not include this time in what is counted for CSQC_UpdateView t = Sys_DirtyTime() - t;if (t < 0 || t >= 1800) t = 0; prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= t; -} - -static void VM_ResizePolygons(vmpolygons_t *polys) -{ - float *oldvertex3f = polys->data_vertex3f; - float *oldcolor4f = polys->data_color4f; - float *oldtexcoord2f = polys->data_texcoord2f; - vmpolygons_triangle_t *oldtriangles = polys->data_triangles; - unsigned short *oldsortedelement3s = polys->data_sortedelement3s; - polys->max_vertices = min(polys->max_triangles*3, 65536); - polys->data_vertex3f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[3])); - polys->data_color4f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[4])); - polys->data_texcoord2f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[2])); - polys->data_triangles = (vmpolygons_triangle_t *)Mem_Alloc(polys->pool, polys->max_triangles*sizeof(vmpolygons_triangle_t)); - polys->data_sortedelement3s = (unsigned short *)Mem_Alloc(polys->pool, polys->max_triangles*sizeof(unsigned short[3])); - if (polys->num_vertices) - { - memcpy(polys->data_vertex3f, oldvertex3f, polys->num_vertices*sizeof(float[3])); - memcpy(polys->data_color4f, oldcolor4f, polys->num_vertices*sizeof(float[4])); - memcpy(polys->data_texcoord2f, oldtexcoord2f, polys->num_vertices*sizeof(float[2])); - } - if (polys->num_triangles) - { - memcpy(polys->data_triangles, oldtriangles, polys->num_triangles*sizeof(vmpolygons_triangle_t)); - memcpy(polys->data_sortedelement3s, oldsortedelement3s, polys->num_triangles*sizeof(unsigned short[3])); - } - if (oldvertex3f) - Mem_Free(oldvertex3f); - if (oldcolor4f) - Mem_Free(oldcolor4f); - if (oldtexcoord2f) - Mem_Free(oldtexcoord2f); - if (oldtriangles) - Mem_Free(oldtriangles); - if (oldsortedelement3s) - Mem_Free(oldsortedelement3s); -} - -static void VM_InitPolygons (vmpolygons_t* polys) -{ - memset(polys, 0, sizeof(*polys)); - polys->pool = Mem_AllocPool("VMPOLY", 0, NULL); - polys->max_triangles = 1024; - VM_ResizePolygons(polys); - polys->initialized = true; -} - -static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) -{ - int surfacelistindex; - vmpolygons_t *polys = (vmpolygons_t *)ent; -// R_Mesh_ResetTextureState(); - R_EntityMatrix(&identitymatrix); - GL_CullFace(GL_NONE); - 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; - DrawQ_ProcessDrawFlag(drawflag, polys->data_triangles[surfacelist[surfacelistindex]].hasalpha); - R_SetupShader_Generic(tex, NULL, GL_MODULATE, 1, false, false, false); - numtriangles = 0; - for (;surfacelistindex < numsurfaces;surfacelistindex++) - { - if (polys->data_triangles[surfacelist[surfacelistindex]].texture != tex || polys->data_triangles[surfacelist[surfacelistindex]].drawflag != drawflag) - break; - VectorCopy(polys->data_triangles[surfacelist[surfacelistindex]].elements, polys->data_sortedelement3s + 3*numtriangles); - numtriangles++; - } - R_Mesh_Draw(0, polys->num_vertices, 0, numtriangles, NULL, NULL, 0, polys->data_sortedelement3s, NULL, 0); - } -} - -static void VMPolygons_Store(vmpolygons_t *polys) -{ - 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.texture = polys->begin_texture; - mesh.num_vertices = polys->begin_vertices; - mesh.num_triangles = polys->begin_vertices-2; - mesh.data_element3i = polygonelement3i; - mesh.data_element3s = polygonelement3s; - 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, hasalpha); - } - else - { - // queue the polygon as 3D for sorted transparent rendering later - int i; - if (polys->max_triangles < polys->num_triangles + polys->begin_vertices-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) - { - // needle in a haystack! - // polys->num_vertices was used for copying where we actually want to copy begin_vertices - // that also caused it to not render the first polygon that is added - // --blub - memcpy(polys->data_vertex3f + polys->num_vertices * 3, polys->begin_vertex[0], polys->begin_vertices * sizeof(float[3])); - memcpy(polys->data_color4f + polys->num_vertices * 4, polys->begin_color[0], polys->begin_vertices * sizeof(float[4])); - memcpy(polys->data_texcoord2f + polys->num_vertices * 2, polys->begin_texcoord[0], polys->begin_vertices * sizeof(float[2])); - for (i = 0;i < polys->begin_vertices-2;i++) - { - polys->data_triangles[polys->num_triangles].texture = polys->begin_texture; - polys->data_triangles[polys->num_triangles].drawflag = polys->begin_drawflag; - 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->begin_active = false; -} - -// TODO: move this into the client code and clean-up everything else, too! [1/6/2008 Black] -// LordHavoc: agreed, this is a mess -void VM_CL_AddPolygonsToMeshQueue (prvm_prog_t *prog) -{ - int i; - vmpolygons_t *polys = &prog->vmpolygons; - vec3_t center; - - // only add polygons of the currently active prog to the queue - if there is none, we're done - if( !prog ) - return; - if (!polys->num_triangles) - return; + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = false; - for (i = 0;i < polys->num_triangles;i++) + // update the views + if (ismain) { - VectorMAMAM(1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[0], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[1], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[2], center); - R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, VM_DrawPolygonCallback, (entity_render_t *)polys, i, NULL); + // clear the flags so no other view becomes "main" unless CSQC sets VF_MAINVIEW + r_refdef.view.ismain = false; + csqc_original_r_refdef_view.ismain = false; } - - /*polys->num_triangles = 0; // now done after rendering the scene, - polys->num_vertices = 0; // otherwise it's not rendered at all and prints an error message --blub */ } //void(string texturename, float flag[, float is2d]) R_BeginPolygon static void VM_CL_R_PolygonBegin (prvm_prog_t *prog) { - const char *picname; - skinframe_t *sf; - vmpolygons_t *polys = &prog->vmpolygons; - int tf; - - // TODO instead of using skinframes here (which provides the benefit of - // better management of flags, and is more suited for 3D rendering), what - // about supporting Q3 shaders? + const char *texname; + int drawflags; + qbool draw2d; + model_t *mod; VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_R_PolygonBegin); - if (!polys->initialized) - VM_InitPolygons(polys); - if (polys->begin_active) - { - VM_Warning(prog, "VM_CL_R_PolygonBegin: called twice without VM_CL_R_PolygonBegin after first\n"); - return; - } - picname = PRVM_G_STRING(OFS_PARM0); - - sf = NULL; - if(*picname) + texname = PRVM_G_STRING(OFS_PARM0); + drawflags = (int)PRVM_G_FLOAT(OFS_PARM1); + if (prog->argc >= 3) + draw2d = PRVM_G_FLOAT(OFS_PARM2) != 0; + else { - tf = TEXF_ALPHA; - if((int)PRVM_G_FLOAT(OFS_PARM1) & DRAWFLAG_MIPMAP) - tf |= TEXF_MIPMAP; - - do - { - sf = R_SkinFrame_FindNextByName(sf, picname); - } - while(sf && sf->textureflags != tf); - - if(!sf || !sf->base) - sf = R_SkinFrame_LoadExternal(picname, tf, true); - - if(sf) - R_SkinFrame_MarkUsed(sf); + // weird hacky way to figure out if this is a 2D HUD polygon or a scene + // polygon, for compatibility with mods aimed at old darkplaces versions + // - polygonbegin_guess2d is 0 if the most recent major call was + // clearscene, 1 if the most recent major call was drawpic (and similar) + // or renderscene + draw2d = prog->polygonbegin_guess2d; } - 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); + // we need to remember whether this is a 2D or 3D mesh we're adding to + mod = draw2d ? CL_Mesh_UI() : CL_Mesh_Scene(); + prog->polygonbegin_model = mod; + if (texname == NULL || texname[0] == 0) + texname = "$whiteimage"; + strlcpy(prog->polygonbegin_texname, texname, sizeof(prog->polygonbegin_texname)); + prog->polygonbegin_drawflags = drawflags; + prog->polygonbegin_numvertices = 0; } //void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex static void VM_CL_R_PolygonVertex (prvm_prog_t *prog) { - vmpolygons_t *polys = &prog->vmpolygons; + const prvm_vec_t *v = PRVM_G_VECTOR(OFS_PARM0); + const prvm_vec_t *tc = PRVM_G_VECTOR(OFS_PARM1); + const prvm_vec_t *c = PRVM_G_VECTOR(OFS_PARM2); + const prvm_vec_t a = PRVM_G_FLOAT(OFS_PARM3); + float *o; + model_t *mod = prog->polygonbegin_model; VM_SAFEPARMCOUNT(4, VM_CL_R_PolygonVertex); - if (!polys->begin_active) + if (!mod) { VM_Warning(prog, "VM_CL_R_PolygonVertex: VM_CL_R_PolygonBegin wasn't called\n"); return; } - if (polys->begin_vertices >= VMPOLYGONS_MAXPOINTS) + if (prog->polygonbegin_maxvertices <= prog->polygonbegin_numvertices) { - VM_Warning(prog, "VM_CL_R_PolygonVertex: may have %i vertices max\n", VMPOLYGONS_MAXPOINTS); - return; + prog->polygonbegin_maxvertices = max(16, prog->polygonbegin_maxvertices * 2); + prog->polygonbegin_vertexdata = (float *)Mem_Realloc(prog->progs_mempool, prog->polygonbegin_vertexdata, prog->polygonbegin_maxvertices * sizeof(float[10])); } + o = prog->polygonbegin_vertexdata + prog->polygonbegin_numvertices++ * 10; - polys->begin_vertex[polys->begin_vertices][0] = PRVM_G_VECTOR(OFS_PARM0)[0]; - polys->begin_vertex[polys->begin_vertices][1] = PRVM_G_VECTOR(OFS_PARM0)[1]; - polys->begin_vertex[polys->begin_vertices][2] = PRVM_G_VECTOR(OFS_PARM0)[2]; - polys->begin_texcoord[polys->begin_vertices][0] = PRVM_G_VECTOR(OFS_PARM1)[0]; - polys->begin_texcoord[polys->begin_vertices][1] = PRVM_G_VECTOR(OFS_PARM1)[1]; - polys->begin_color[polys->begin_vertices][0] = PRVM_G_VECTOR(OFS_PARM2)[0]; - polys->begin_color[polys->begin_vertices][1] = PRVM_G_VECTOR(OFS_PARM2)[1]; - polys->begin_color[polys->begin_vertices][2] = PRVM_G_VECTOR(OFS_PARM2)[2]; - polys->begin_color[polys->begin_vertices][3] = PRVM_G_FLOAT(OFS_PARM3); - polys->begin_vertices++; + o[0] = v[0]; + o[1] = v[1]; + o[2] = v[2]; + o[3] = tc[0]; + o[4] = tc[1]; + o[5] = tc[2]; + o[6] = c[0]; + o[7] = c[1]; + o[8] = c[2]; + o[9] = a; } //void() R_EndPolygon static void VM_CL_R_PolygonEnd (prvm_prog_t *prog) { - vmpolygons_t *polys = &prog->vmpolygons; + int i; + qbool hascolor; + qbool hasalpha; + int e0 = 0, e1 = 0, e2 = 0; + float *o; + model_t *mod = prog->polygonbegin_model; + msurface_t *surf; + texture_t *tex; + int materialflags; VM_SAFEPARMCOUNT(0, VM_CL_R_PolygonEnd); - if (!polys->begin_active) + if (!mod) { VM_Warning(prog, "VM_CL_R_PolygonEnd: VM_CL_R_PolygonBegin wasn't called\n"); return; } - polys->begin_active = false; - if (polys->begin_vertices >= 3) - VMPolygons_Store(polys); - else - VM_Warning(prog, "VM_CL_R_PolygonEnd: %i vertices isn't a good choice\n", polys->begin_vertices); -} - -static vmpolygons_t debugPolys; - -void Debug_PolygonBegin(const char *picname, int drawflag) -{ - if(!debugPolys.initialized) - VM_InitPolygons(&debugPolys); - if(debugPolys.begin_active) - { - Con_Printf("Debug_PolygonBegin: called twice without Debug_PolygonEnd after first\n"); - return; - } - 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; -} -void Debug_PolygonVertex(float x, float y, float z, float s, float t, float r, float g, float b, float a) -{ - if(!debugPolys.begin_active) + // determine if vertex alpha is being used so we can provide that hint to GetTexture... + hascolor = false; + hasalpha = false; + for (i = 0; i < prog->polygonbegin_numvertices; i++) { - Con_Printf("Debug_PolygonVertex: Debug_PolygonBegin wasn't called\n"); - return; + o = prog->polygonbegin_vertexdata + 10 * i; + if (o[6] != 1.0f || o[7] != 1.0f || o[8] != 1.0f) + hascolor = true; + if (o[9] != 1.0f) + hasalpha = true; } - if(debugPolys.begin_vertices > VMPOLYGONS_MAXPOINTS) + // create the surface, looking up the best matching texture/shader + materialflags = MATERIALFLAG_WALL; + if (csqc_polygons_defaultmaterial_nocullface.integer) + materialflags |= MATERIALFLAG_NOCULLFACE; + if (hascolor) + materialflags |= MATERIALFLAG_VERTEXCOLOR; + if (hasalpha) + materialflags |= MATERIALFLAG_ALPHAGEN_VERTEX | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; + tex = Mod_Mesh_GetTexture(mod, prog->polygonbegin_texname, prog->polygonbegin_drawflags, TEXF_ALPHA, materialflags); + surf = Mod_Mesh_AddSurface(mod, tex, false); + // create triangle fan + for (i = 0; i < prog->polygonbegin_numvertices; i++) { - Con_Printf("Debug_PolygonVertex: may have %i vertices max\n", VMPOLYGONS_MAXPOINTS); - return; + o = prog->polygonbegin_vertexdata + 10 * i; + e2 = Mod_Mesh_IndexForVertex(mod, surf, o[0], o[1], o[2], 0, 0, 0, o[3], o[4], 0, 0, o[6], o[7], o[8], o[9]); + if (i >= 2) + Mod_Mesh_AddTriangle(mod, surf, e0, e1, e2); + else if (i == 0) + e0 = e2; + e1 = e2; } + // build normals (since they are not provided) + Mod_BuildNormals(surf->num_firstvertex, surf->num_vertices, surf->num_triangles, mod->surfmesh.data_vertex3f, mod->surfmesh.data_element3i + 3 * surf->num_firsttriangle, mod->surfmesh.data_normal3f, true); - debugPolys.begin_vertex[debugPolys.begin_vertices][0] = x; - debugPolys.begin_vertex[debugPolys.begin_vertices][1] = y; - debugPolys.begin_vertex[debugPolys.begin_vertices][2] = z; - debugPolys.begin_texcoord[debugPolys.begin_vertices][0] = s; - debugPolys.begin_texcoord[debugPolys.begin_vertices][1] = t; - debugPolys.begin_color[debugPolys.begin_vertices][0] = r; - debugPolys.begin_color[debugPolys.begin_vertices][1] = g; - debugPolys.begin_color[debugPolys.begin_vertices][2] = b; - debugPolys.begin_color[debugPolys.begin_vertices][3] = a; - debugPolys.begin_vertices++; -} - -void Debug_PolygonEnd(void) -{ - if (!debugPolys.begin_active) - { - Con_Printf("Debug_PolygonEnd: Debug_PolygonBegin wasn't called\n"); - return; - } - debugPolys.begin_active = false; - if (debugPolys.begin_vertices >= 3) - VMPolygons_Store(&debugPolys); - else - Con_Printf("Debug_PolygonEnd: %i vertices isn't a good choice\n", debugPolys.begin_vertices); + // reset state + prog->polygonbegin_model = NULL; + prog->polygonbegin_texname[0] = 0; + prog->polygonbegin_drawflags = 0; + prog->polygonbegin_numvertices = 0; } /* @@ -3469,7 +4204,7 @@ is not a staircase. ============= */ -static qboolean CL_CheckBottom (prvm_edict_t *ent) +static qbool CL_CheckBottom (prvm_edict_t *ent) { prvm_prog_t *prog = CLVM_prog; vec3_t mins, maxs, start, stop; @@ -3505,7 +4240,7 @@ realcheck: 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, false); + trace = CL_TraceLine(start, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, true, false, NULL, true, false); if (trace.fraction == 1.0) return false; @@ -3518,7 +4253,7 @@ realcheck: 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, false); + trace = CL_TraceLine(start, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, true, false, NULL, true, false); if (trace.fraction != 1.0 && trace.endpos[2] > bottom) bottom = trace.endpos[2]; @@ -3538,16 +4273,19 @@ The move will be adjusted for slopes and stairs, but if the move isn't possible, no move is done and false is returned ============= */ -static qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, qboolean settrace) +static qbool CL_movestep (prvm_edict_t *ent, vec3_t move, qbool relink, qbool noenemy, qbool settrace) { prvm_prog_t *prog = CLVM_prog; float dz; vec3_t oldorg, neworg, end, traceendpos; + vec3_t mins, maxs, start; trace_t trace; int i, svent; prvm_edict_t *enemy; // try the move + VectorCopy(PRVM_clientedictvector(ent, mins), mins); + VectorCopy(PRVM_clientedictvector(ent, maxs), maxs); VectorCopy (PRVM_clientedictvector(ent, origin), oldorg); VectorAdd (PRVM_clientedictvector(ent, origin), move, neworg); @@ -3567,7 +4305,8 @@ static qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qb if (dz < 30) neworg[2] += 8; } - trace = CL_TraceBox(PRVM_clientedictvector(ent, origin), PRVM_clientedictvector(ent, mins), PRVM_clientedictvector(ent, maxs), neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true); + VectorCopy(PRVM_clientedictvector(ent, origin), start); + trace = CL_TraceBox(start, mins, maxs, neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, true, true, &svent, true); if (settrace) CL_VM_SetTraceGlobals(prog, &trace, svent); @@ -3595,14 +4334,14 @@ static qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qb VectorCopy (neworg, end); end[2] -= sv_stepheight.value*2; - trace = CL_TraceBox(neworg, PRVM_clientedictvector(ent, mins), PRVM_clientedictvector(ent, maxs), end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true); + trace = CL_TraceBox(neworg, mins, maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, true, true, &svent, true); if (settrace) CL_VM_SetTraceGlobals(prog, &trace, svent); if (trace.startsolid) { neworg[2] -= sv_stepheight.value; - trace = CL_TraceBox(neworg, PRVM_clientedictvector(ent, mins), PRVM_clientedictvector(ent, maxs), end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true); + trace = CL_TraceBox(neworg, mins, maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, true, true, &svent, true); if (settrace) CL_VM_SetTraceGlobals(prog, &trace, svent); if (trace.startsolid) @@ -3664,7 +4403,7 @@ static void VM_CL_walkmove (prvm_prog_t *prog) vec3_t move; mfunction_t *oldf; int oldself; - qboolean settrace; + qbool settrace; VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_walkmove); @@ -3677,7 +4416,7 @@ static void VM_CL_walkmove (prvm_prog_t *prog) VM_Warning(prog, "walkmove: can not modify world entity\n"); return; } - if (ent->priv.server->free) + if (ent->free) { VM_Warning(prog, "walkmove: can not modify free entity\n"); return; @@ -3744,11 +4483,11 @@ static void VM_CL_checkpvs (prvm_prog_t *prog) unsigned char fatpvs[MAX_MAP_LEAFS/8]; #endif - VM_SAFEPARMCOUNT(2, VM_SV_checkpvs); + VM_SAFEPARMCOUNT(2, VM_CL_checkpvs); VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos); viewee = PRVM_G_EDICT(OFS_PARM1); - if(viewee->priv.required->free) + if(viewee->free) { VM_Warning(prog, "checkpvs: can not check free entity\n"); PRVM_G_FLOAT(OFS_RETURN) = 4; @@ -3759,36 +4498,36 @@ static void VM_CL_checkpvs (prvm_prog_t *prog) VectorAdd(PRVM_serveredictvector(viewee, origin), PRVM_serveredictvector(viewee, maxs), ma); #if 1 - if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS) + if(!cl.worldmodel || !cl.worldmodel->brush.GetPVS || !cl.worldmodel->brush.BoxTouchingPVS) { // no PVS support on this worldmodel... darn PRVM_G_FLOAT(OFS_RETURN) = 3; return; } - pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos); + pvs = cl.worldmodel->brush.GetPVS(cl.worldmodel, viewpos); if(!pvs) { // viewpos isn't in any PVS... darn PRVM_G_FLOAT(OFS_RETURN) = 2; return; } - PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, mi, ma); + PRVM_G_FLOAT(OFS_RETURN) = cl.worldmodel->brush.BoxTouchingPVS(cl.worldmodel, pvs, mi, ma); #else // using fat PVS like FTEQW does (slow) - if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS) + if(!cl.worldmodel || !cl.worldmodel->brush.FatPVS || !cl.worldmodel->brush.BoxTouchingPVS) { // no PVS support on this worldmodel... darn PRVM_G_FLOAT(OFS_RETURN) = 3; return; } - fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false); + fatpvsbytes = cl.worldmodel->brush.FatPVS(cl.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false); if(!fatpvsbytes) { // viewpos isn't in any PVS... darn PRVM_G_FLOAT(OFS_RETURN) = 2; return; } - PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, mi, ma); + PRVM_G_FLOAT(OFS_RETURN) = cl.worldmodel->brush.BoxTouchingPVS(cl.worldmodel, fatpvs, mi, ma); #endif } @@ -3796,7 +4535,7 @@ static void VM_CL_checkpvs (prvm_prog_t *prog) static void VM_CL_skel_create(prvm_prog_t *prog) { int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0); - dp_model_t *model = CL_GetModelByIndex(modelindex); + model_t *model = CL_GetModelByIndex(modelindex); skeleton_t *skeleton; int i; PRVM_G_FLOAT(OFS_RETURN) = 0; @@ -3826,14 +4565,13 @@ static void VM_CL_skel_build(prvm_prog_t *prog) float retainfrac = PRVM_G_FLOAT(OFS_PARM3); int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1; int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1; - dp_model_t *model = CL_GetModelByIndex(modelindex); - float blendfrac; + model_t *model = CL_GetModelByIndex(modelindex); int numblends; int bonenum; int blendindex; framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS]; frameblend_t frameblend[MAX_FRAMEBLENDS]; - matrix4x4_t blendedmatrix; + matrix4x4_t bonematrix; matrix4x4_t matrix; PRVM_G_FLOAT(OFS_RETURN) = 0; if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex])) @@ -3842,20 +4580,19 @@ static void VM_CL_skel_build(prvm_prog_t *prog) lastbone = min(lastbone, model->num_bones - 1); lastbone = min(lastbone, skeleton->model->num_bones - 1); VM_GenerateFrameGroupBlend(prog, framegroupblend, ed); - VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model); - blendfrac = 1.0f - retainfrac; + VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, cl.time); for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++) - frameblend[numblends].lerp *= blendfrac; + ; for (bonenum = firstbone;bonenum <= lastbone;bonenum++) { - memset(&blendedmatrix, 0, sizeof(blendedmatrix)); - Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac); + memset(&bonematrix, 0, sizeof(bonematrix)); for (blendindex = 0;blendindex < numblends;blendindex++) { - Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum)); - Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp); + Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum)); + Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp); } - skeleton->relativetransforms[bonenum] = blendedmatrix; + Matrix4x4_Normalize3(&bonematrix, &bonematrix); + Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac); } PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1; } @@ -4071,7 +4808,7 @@ static void VM_CL_skel_delete(prvm_prog_t *prog) static void VM_CL_frameforname(prvm_prog_t *prog) { int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0); - dp_model_t *model = CL_GetModelByIndex(modelindex); + model_t *model = CL_GetModelByIndex(modelindex); const char *name = PRVM_G_STRING(OFS_PARM1); int i; PRVM_G_FLOAT(OFS_RETURN) = -1; @@ -4091,7 +4828,7 @@ static void VM_CL_frameforname(prvm_prog_t *prog) static void VM_CL_frameduration(prvm_prog_t *prog) { int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0); - dp_model_t *model = CL_GetModelByIndex(modelindex); + model_t *model = CL_GetModelByIndex(modelindex); int framenum = (int)PRVM_G_FLOAT(OFS_PARM1); PRVM_G_FLOAT(OFS_RETURN) = 0; if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes) @@ -4131,9 +4868,10 @@ static void VM_CL_RotateMoves(prvm_prog_t *prog) */ matrix4x4_t m; vec3_t v = {0, 0, 0}; - vec3_t x, y, z; + vec3_t a, x, y, z; VM_SAFEPARMCOUNT(1, VM_CL_RotateMoves); - AngleVectorsFLU(PRVM_G_VECTOR(OFS_PARM0), x, y, z); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), a); + AngleVectorsFLU(a, x, y, z); Matrix4x4_FromVectors(&m, x, y, z, v); CL_RotateMoves(&m); } @@ -4156,11 +4894,11 @@ static void VM_CL_V_CalcRefdef(prvm_prog_t *prog) { matrix4x4_t entrendermatrix; vec3_t clviewangles; - qboolean teleported; - qboolean clonground; - qboolean clcmdjump; - qboolean cldead; - qboolean clintermission; + vec3_t clvelocity; + qbool teleported; + qbool clonground; + qbool clcmdjump; + qbool cldead; float clstatsviewheight; prvm_edict_t *ent; int flags; @@ -4170,7 +4908,7 @@ static void VM_CL_V_CalcRefdef(prvm_prog_t *prog) flags = PRVM_G_FLOAT(OFS_PARM1); // use the CL_GetTagMatrix function on self to ensure consistent behavior (duplicate code would be bad) - CL_GetTagMatrix(prog, &entrendermatrix, ent, 0); + CL_GetTagMatrix(prog, &entrendermatrix, ent, 0, NULL); VectorCopy(cl.csqc_viewangles, clviewangles); teleported = (flags & REFDEFFLAG_TELEPORTED) != 0; @@ -4178,9 +4916,10 @@ static void VM_CL_V_CalcRefdef(prvm_prog_t *prog) clcmdjump = (flags & REFDEFFLAG_JUMPING) != 0; clstatsviewheight = PRVM_clientedictvector(ent, view_ofs)[2]; cldead = (flags & REFDEFFLAG_DEAD) != 0; - clintermission = (flags & REFDEFFLAG_INTERMISSION) != 0; + cl.intermission = (flags & REFDEFFLAG_INTERMISSION) != 0; + VectorCopy(PRVM_clientedictvector(ent, velocity), clvelocity); - V_CalcRefdefUsing(&entrendermatrix, clviewangles, teleported, clonground, clcmdjump, clstatsviewheight, cldead, clintermission); + V_CalcRefdefUsing(&entrendermatrix, clviewangles, teleported, clonground, clcmdjump, clstatsviewheight, cldead, clvelocity); VectorCopy(cl.csqc_vieworiginfromengine, cl.csqc_vieworigin); VectorCopy(cl.csqc_viewanglesfromengine, cl.csqc_viewangles); @@ -4205,7 +4944,7 @@ VM_CL_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE) NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE) VM_break, // #6 void() break (QUAKE) VM_random, // #7 float() random (QUAKE) -VM_CL_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE) +VM_CL_sound, // #8 void(entity e, float chan, string samp, float volume, float atten[, float pitchchange[, float flags]]) sound (QUAKE) VM_normalize, // #9 vector(vector v) normalize (QUAKE) VM_error, // #10 void(string e) error (QUAKE) VM_objerror, // #11 void(string e) objerror (QUAKE) @@ -4243,7 +4982,7 @@ NULL, // #42 (QUAKE) VM_fabs, // #43 float(float f) fabs (QUAKE) NULL, // #44 vector(entity e, float speed) aim (QUAKE) VM_cvar, // #45 float(string s) cvar (QUAKE) -VM_localcmd, // #46 void(string s) localcmd (QUAKE) +VM_localcmd_local, // #46 void(string s) localcmd (QUAKE) VM_nextent, // #47 entity(entity e) nextent (QUAKE) VM_CL_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE) VM_changeyaw, // #49 void() ChangeYaw (QUAKE) @@ -4375,7 +5114,7 @@ NULL, // #173 NULL, // #174 NULL, // #175 NULL, // #176 -NULL, // #177 +VM_localsound, // #177 NULL, // #178 NULL, // #179 NULL, // #180 @@ -4444,7 +5183,7 @@ NULL, // #241 NULL, // #242 NULL, // #243 NULL, // #244 -NULL, // #245 +VM_modulo, // #245 NULL, // #246 NULL, // #247 NULL, // #248 @@ -4527,7 +5266,7 @@ VM_drawfill, // #323 float(vector position, vector size, vector rgb, float a VM_drawsetcliparea, // #324 void(float x, float y, float width, float height) drawsetcliparea VM_drawresetcliparea, // #325 void(void) drawresetcliparea VM_drawcolorcodedstring, // #326 float drawcolorcodedstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) (EXT_CSQC) -VM_stringwidth, // #327 // FIXME is this okay? +VM_stringwidth, // #327 // FIXME is this okay? VM_drawsubpic, // #328 // FIXME is this okay? VM_drawrotpic, // #329 // FIXME is this okay? VM_CL_getstatf, // #330 float(float stnum) getstatf (EXT_CSQC) @@ -4600,7 +5339,7 @@ NULL, // #396 NULL, // #397 NULL, // #398 NULL, // #399 -// LordHavoc's range #400-#499 +// LadyHavoc's range #400-#499 VM_CL_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY) NULL, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR) VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN) @@ -4736,10 +5475,10 @@ VM_CL_setpause, // #531 float(float ispaused) setpause = #531 (DP_CSQC_SETPA VM_log, // #532 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME) VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME) -NULL, // #535 -NULL, // #536 -NULL, // #537 -NULL, // #538 +VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP) +VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP) +VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP) +VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP) NULL, // #539 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) @@ -4843,31 +5582,23 @@ VM_CL_RotateMoves, // #638 VM_digest_hex, // #639 VM_CL_V_CalcRefdef, // #640 void(entity e) V_CalcRefdef (DP_CSQC_V_CALCREFDEF) NULL, // #641 +VM_coverage, // #642 +NULL }; const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t); -void VM_Polygons_Reset(prvm_prog_t *prog) -{ - vmpolygons_t *polys = &prog->vmpolygons; - - // TODO: replace vm_polygons stuff with a more general debugging polygon system, and make vm_polygons functions use that system - if(polys->initialized) - { - Mem_FreePool(&polys->pool); - polys->initialized = false; - } -} - void CLVM_init_cmd(prvm_prog_t *prog) { VM_Cmd_Init(prog); - VM_Polygons_Reset(prog); + prog->polygonbegin_model = NULL; + prog->polygonbegin_guess2d = 0; } void CLVM_reset_cmd(prvm_prog_t *prog) { World_End(&cl.world); VM_Cmd_Reset(prog); - VM_Polygons_Reset(prog); + prog->polygonbegin_model = NULL; + prog->polygonbegin_guess2d = 0; }