X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=clvm_cmds.c;h=fc0ad58546b7577db59a85e59cb0674d8f31f2e8;hp=11277881d36056fe5d11884eb3335d6b48e57a49;hb=36db1374c6782cadb439e5d642e0ffed73236034;hpb=b51464f3b30341bac7a487d5b9d8c6ee83a68e2c diff --git a/clvm_cmds.c b/clvm_cmds.c index 11277881..fc0ad585 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -21,6 +21,7 @@ //4 feature darkplaces csqc: add builtins to clientside qc for gl calls extern cvar_t v_flipped; +extern cvar_t r_equalize_entities_fullbright; sfx_t *S_FindName(const char *name); int Sbar_GetSortedPlayerIndex (int index); @@ -261,7 +262,7 @@ static void VM_CL_traceline (void) if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2])) PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent)); - trace = CL_Move(v1, vec3_origin, vec3_origin, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true); + trace = CL_TraceLine(v1, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true); CL_VM_SetTraceGlobals(&trace, svent); } @@ -299,7 +300,7 @@ static void VM_CL_tracebox (void) if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2])) PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_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_Move(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), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true); CL_VM_SetTraceGlobals(&trace, svent); } @@ -334,7 +335,7 @@ trace_t CL_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore, int *svent) VectorMA (tossent->fields.client->angles, 0.05, tossent->fields.client->avelocity, tossent->fields.client->angles); VectorScale (tossent->fields.client->velocity, 0.05, move); VectorAdd (tossent->fields.client->origin, move, end); - trace = CL_Move (tossent->fields.client->origin, tossent->fields.client->mins, tossent->fields.client->maxs, end, MOVE_NORMAL, tossent, CL_GenericHitSuperContentsMask(tossent), true, true, NULL, true); + trace = CL_TraceBox(tossent->fields.client->origin, tossent->fields.client->mins, tossent->fields.client->maxs, end, MOVE_NORMAL, tossent, CL_GenericHitSuperContentsMask(tossent), true, true, NULL, true); VectorCopy (trace.endpos, tossent->fields.client->origin); if (trace.fraction < 1) @@ -522,7 +523,7 @@ static void VM_CL_droptofloor (void) VectorCopy (ent->fields.client->origin, end); end[2] -= 256; - trace = CL_Move(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + trace = CL_TraceBox(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); if (trace.fraction != 1) { @@ -551,7 +552,7 @@ static void VM_CL_lightstyle (void) VM_Warning("VM_CL_lightstyle >= MAX_LIGHTSTYLES\n"); return; } - strlcpy (cl.lightstyle[i].map, MSG_ReadString(), sizeof (cl.lightstyle[i].map)); + strlcpy (cl.lightstyle[i].map, c, sizeof (cl.lightstyle[i].map)); cl.lightstyle[i].map[MAX_STYLESTRING - 1] = 0; cl.lightstyle[i].length = (int)strlen(cl.lightstyle[i].map); } @@ -601,7 +602,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_Move (start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + trace = CL_TraceLine(start, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); if (trace.fraction == 1.0) return; @@ -615,7 +616,7 @@ realcheck: start[0] = stop[0] = x ? maxs[0] : mins[0]; start[1] = stop[1] = y ? maxs[1] : mins[1]; - trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + trace = CL_TraceLine(start, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); if (trace.fraction != 1.0 && trace.endpos[2] > bottom) bottom = trace.endpos[2]; @@ -726,6 +727,7 @@ extern void CSQC_Predraw (prvm_edict_t *ed);//csprogs.c extern void CSQC_Think (prvm_edict_t *ed);//csprogs.c void VM_CL_R_AddEntities (void) { + double t = Sys_DoubleTime(); int i, drawmask; prvm_edict_t *ed; VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntities); @@ -750,13 +752,18 @@ void VM_CL_R_AddEntities (void) continue; CSQC_AddRenderEdict(ed); } + + // callprofile fixing hack: do not include this time in what is counted for CSQC_UpdateView + prog->functions[prog->funcoffsets.CSQC_UpdateView].totaltime -= Sys_DoubleTime() - t; } //#302 void(entity ent) addentity (EXT_CSQC) void VM_CL_R_AddEntity (void) { + double t = Sys_DoubleTime(); VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntity); CSQC_AddRenderEdict(PRVM_G_EDICT(OFS_PARM0)); + prog->functions[prog->funcoffsets.CSQC_UpdateView].totaltime -= Sys_DoubleTime() - t; } //#303 float(float property, ...) setproperty (EXT_CSQC) @@ -844,13 +851,13 @@ void VM_CL_R_SetView (void) CSQC_R_RecalcView(); break; case VF_DRAWWORLD: - cl.csqc_vidvars.drawworld = k; + cl.csqc_vidvars.drawworld = k != 0; break; case VF_DRAWENGINESBAR: - cl.csqc_vidvars.drawenginesbar = k; + cl.csqc_vidvars.drawenginesbar = k != 0; break; case VF_DRAWCROSSHAIR: - cl.csqc_vidvars.drawcrosshair = k; + cl.csqc_vidvars.drawcrosshair = k != 0; break; case VF_CL_VIEWANGLES: VectorCopy(f, cl.viewangles); @@ -881,6 +888,7 @@ void VM_CL_R_SetView (void) //#305 void(vector org, float radius, vector lightcolours[, float style, string cubemapname, float pflags]) adddynamiclight (EXT_CSQC) void VM_CL_R_AddDynamicLight (void) { + double t = Sys_DoubleTime(); vec_t *org; float radius = 300; vec_t *col; @@ -927,6 +935,7 @@ void VM_CL_R_AddDynamicLight (void) 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++]; + prog->functions[prog->funcoffsets.CSQC_UpdateView].totaltime -= Sys_DoubleTime() - t; } //============================================================================ @@ -1142,7 +1151,7 @@ static void VM_CL_getkeybind (void) static void VM_CL_setcursormode (void) { VM_SAFEPARMCOUNT(1, VM_CL_setcursormode); - cl.csqc_wantsmousemove = PRVM_G_FLOAT(OFS_PARM0); + cl.csqc_wantsmousemove = PRVM_G_FLOAT(OFS_PARM0) != 0; cl_ignoremousemoves = 2; } @@ -1434,6 +1443,11 @@ static void VM_CL_makestatic (void) staticent->render.scale = 1; if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale)) && val->_float) staticent->render.scale = val->_float; if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.colormod)) && VectorLength2(val->vector)) VectorCopy(val->vector, staticent->render.colormod); + if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.glowmod)) && VectorLength2(val->vector)) VectorCopy(val->vector, staticent->render.glowmod); + if (!VectorLength2(staticent->render.colormod)) + VectorSet(staticent->render.colormod, 1, 1, 1); + if (!VectorLength2(staticent->render.glowmod)) + VectorSet(staticent->render.glowmod, 1, 1, 1); renderflags = 0; if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.renderflags)) && val->_float) renderflags = (int)val->_float; @@ -1448,11 +1462,22 @@ static void VM_CL_makestatic (void) Matrix4x4_CreateFromQuakeEntity(&staticent->render.matrix, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], staticent->render.scale); // either fullbright or lit - if (!(staticent->render.effects & EF_FULLBRIGHT) && !r_fullbright.integer) - staticent->render.flags |= RENDER_LIGHT; + if(!r_fullbright.integer) + { + 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)) staticent->render.flags |= RENDER_SHADOW; + if (staticent->render.effects & EF_NODEPTHTEST) + staticent->render.flags |= RENDER_NODEPTHTEST; + if (staticent->render.effects & EF_ADDITIVE) + staticent->render.flags |= RENDER_ADDITIVE; + if (staticent->render.effects & EF_DOUBLESIDED) + staticent->render.flags |= RENDER_DOUBLESIDED; CL_UpdateRenderEntity(&staticent->render); } @@ -2219,12 +2244,19 @@ int CL_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, cons return 1; } +int CL_GetPitchSign(prvm_edict_t *ent) +{ + dp_model_t *model; + if ((model = CL_GetModelFromEdict(ent)) && model->type == mod_alias) + return -1; + return 1; +} + void CL_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix) { prvm_eval_t *val; float scale; - float pitchsign; - dp_model_t *model; + float pitchsign = 1; scale = 1; val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale); @@ -2236,18 +2268,17 @@ void CL_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatri Matrix4x4_CreateFromQuakeEntity(out, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], scale * cl_viewmodel_scale.value); else { - pitchsign = 1; - if ((model = CL_GetModelFromEdict(ent)) && model->type == mod_alias) - pitchsign = -1; + pitchsign = CL_GetPitchSign(ent); Matrix4x4_CreateFromQuakeEntity(out, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], pitchsign * ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], scale); } } - int CL_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out) { int frame; + int ret; dp_model_t *model; + entity_render_t cheatentity; if (tagindex >= 0 && (model = CL_GetModelFromEdict(ent)) && model->animscenes) @@ -2256,7 +2287,15 @@ int CL_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out frame = (int)ent->fields.client->frame; if (frame < 0 || frame >= model->numframes) frame = 0; - return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out); + // now we'll do some CHEATING + memset(&cheatentity, 0, sizeof(cheatentity)); + cheatentity.model = model; + CL_LoadFrameGroupBlend(ent, &cheatentity); + R_LerpAnimation(&cheatentity); + ret = CL_BlendTagMatrix(&cheatentity, tagindex, out); + if(ret) + *out = identitymatrix; + return ret; } *out = identitymatrix; return 0; @@ -2443,6 +2482,448 @@ void VM_CL_gettaginfo (void) //============================================================================ +//==================== +// DP_CSQC_SPAWNPARTICLE +// a QC hook to engine's CL_NewParticle +//==================== + +// particle theme struct +typedef struct vmparticletheme_s +{ + unsigned short typeindex; + qboolean initialized; + pblend_t blendmode; + porientation_t orientation; + int color1; + int color2; + int tex; + float size; + float sizeincrease; + int alpha; + int alphafade; + float gravity; + float bounce; + float airfriction; + float liquidfriction; + float originjitter; + float velocityjitter; + qboolean qualityreduction; + float lifetime; + float stretch; + int staincolor1; + int staincolor2; + int staintex; + float delayspawn; + float delaycollision; +}vmparticletheme_t; + +// particle spawner +typedef struct vmparticlespawner_s +{ + mempool_t *pool; + qboolean initialized; + qboolean 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_staintex; + float *particle_delayspawn; + float *particle_delaycollision; +}vmparticlespawner_t; + +vmparticlespawner_t vmpartspawner; + +// TODO: automatic max_themes grow +static void VM_InitParticleSpawner (int maxthemes) +{ + prvm_eval_t *val; + + // bound max themes to not be an insane value + if (maxthemes < 4) + maxthemes = 4; + if (maxthemes > 2048) + maxthemes = 2048; + // allocate and set up structure + if (vmpartspawner.initialized) // reallocate + { + Mem_FreePool(&vmpartspawner.pool); + memset(&vmpartspawner, 0, sizeof(vmparticlespawner_t)); + } + vmpartspawner.pool = Mem_AllocPool("VMPARTICLESPAWNER", 0, NULL); + vmpartspawner.themes = (vmparticletheme_t *)Mem_Alloc(vmpartspawner.pool, sizeof(vmparticletheme_t)*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) + #define getglobal(v,s) val = PRVM_GLOBALFIELDVALUE(PRVM_ED_FindGlobalOffset(s)); if (val) { vmpartspawner.v = &val->_float; } else { VM_Warning("VM_InitParticleSpawner: missing global '%s', spawner cannot work\n", s); vmpartspawner.verified = false; } + #define getglobalvector(v,s) val = PRVM_GLOBALFIELDVALUE(PRVM_ED_FindGlobalOffset(s)); if (val) { vmpartspawner.v = (float *)val->vector; } else { VM_Warning("VM_InitParticleSpawner: missing global '%s', spawner cannot work\n", s); vmpartspawner.verified = false; } + getglobal(particle_type, "particle_type"); + getglobal(particle_blendmode, "particle_blendmode"); + getglobal(particle_orientation, "particle_orientation"); + getglobalvector(particle_color1, "particle_color1"); + getglobalvector(particle_color2, "particle_color2"); + getglobal(particle_tex, "particle_tex"); + getglobal(particle_size, "particle_size"); + getglobal(particle_sizeincrease, "particle_sizeincrease"); + getglobal(particle_alpha, "particle_alpha"); + getglobal(particle_alphafade, "particle_alphafade"); + getglobal(particle_time, "particle_time"); + getglobal(particle_gravity, "particle_gravity"); + getglobal(particle_bounce, "particle_bounce"); + getglobal(particle_airfriction, "particle_airfriction"); + getglobal(particle_liquidfriction, "particle_liquidfriction"); + getglobal(particle_originjitter, "particle_originjitter"); + getglobal(particle_velocityjitter, "particle_velocityjitter"); + getglobal(particle_qualityreduction, "particle_qualityreduction"); + getglobal(particle_stretch, "particle_stretch"); + getglobalvector(particle_staincolor1, "particle_staincolor1"); + getglobalvector(particle_staincolor2, "particle_staincolor2"); + getglobal(particle_staintex, "particle_staintex"); + getglobal(particle_delayspawn, "particle_delayspawn"); + getglobal(particle_delaycollision, "particle_delaycollision"); + #undef getglobal + #undef getglobalvector +} + +// reset particle theme to default values +static void VM_ResetParticleTheme (vmparticletheme_t *theme) +{ + theme->initialized = true; + theme->typeindex = pt_static; + theme->blendmode = PBLEND_ADD; + theme->orientation = PARTICLE_BILLBOARD; + theme->color1 = 0x808080; + theme->color2 = 0xFFFFFF; + theme->tex = 63; + theme->size = 2; + theme->sizeincrease = 0; + theme->alpha = 256; + theme->alphafade = 512; + theme->gravity = 0.0f; + theme->bounce = 0.0f; + theme->airfriction = 1.0f; + theme->liquidfriction = 4.0f; + theme->originjitter = 0.0f; + theme->velocityjitter = 0.0f; + theme->qualityreduction = false; + theme->lifetime = 4; + theme->stretch = 1; + theme->staincolor1 = -1; + theme->staincolor2 = -1; + theme->staintex = -1; + theme->delayspawn = 0.0f; + theme->delaycollision = 0.0f; +} + +// particle theme -> QC globals +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 = (float)theme->alpha/256; + *vmpartspawner.particle_alphafade = (float)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] = (theme->staincolor1 >> 16) & 0xFF; + vmpartspawner.particle_staincolor1[1] = (theme->staincolor1 >> 8) & 0xFF; + vmpartspawner.particle_staincolor1[2] = (theme->staincolor1 >> 0) & 0xFF; + vmpartspawner.particle_staincolor2[0] = (theme->staincolor2 >> 16) & 0xFF; + vmpartspawner.particle_staincolor2[1] = (theme->staincolor2 >> 8) & 0xFF; + vmpartspawner.particle_staincolor2[2] = (theme->staincolor2 >> 0) & 0xFF; + *vmpartspawner.particle_staintex = (float)theme->staintex; + *vmpartspawner.particle_delayspawn = theme->delayspawn; + *vmpartspawner.particle_delaycollision = theme->delaycollision; +} + +// QC globals -> particle theme +void VM_CL_ParticleThemeFromGlobals(vmparticletheme_t *theme) +{ + theme->typeindex = (unsigned short)*vmpartspawner.particle_type; + theme->blendmode = (pblend_t)*vmpartspawner.particle_blendmode; + theme->orientation = (porientation_t)*vmpartspawner.particle_orientation; + theme->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 = (int)(*vmpartspawner.particle_alpha*256); + theme->alphafade = (int)(*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 = vmpartspawner.particle_staincolor1[0]*65536 + vmpartspawner.particle_staincolor1[1]*256 + vmpartspawner.particle_staincolor1[2]; + theme->staincolor2 = vmpartspawner.particle_staincolor2[0]*65536 + vmpartspawner.particle_staincolor2[1]*256 + vmpartspawner.particle_staincolor2[2]; + theme->staintex =(int)*vmpartspawner.particle_staintex; + theme->delayspawn = *vmpartspawner.particle_delayspawn; + theme->delaycollision = *vmpartspawner.particle_delaycollision; +} + +// init particle spawner interface +// # float(float max_themes) initparticlespawner +void VM_CL_InitParticleSpawner (void) +{ + VM_SAFEPARMCOUNTRANGE(0, 1, VM_CL_InitParticleSpawner); + VM_InitParticleSpawner((int)PRVM_G_FLOAT(OFS_PARM0)); + vmpartspawner.themes[0].initialized = true; + VM_ResetParticleTheme(&vmpartspawner.themes[0]); + PRVM_G_FLOAT(OFS_RETURN) = (vmpartspawner.verified == true) ? 1 : 0; +} + +// void() resetparticle +void VM_CL_ResetParticle (void) +{ + VM_SAFEPARMCOUNT(0, VM_CL_ResetParticle); + if (vmpartspawner.verified == false) + { + VM_Warning("VM_CL_ResetParticle: particle spawner not initialized\n"); + return; + } + VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]); +} + +// void(float themenum) particletheme +void VM_CL_ParticleTheme (void) +{ + int themenum; + + VM_SAFEPARMCOUNT(1, VM_CL_ParticleTheme); + if (vmpartspawner.verified == false) + { + VM_Warning("VM_CL_ParticleTheme: particle spawner not initialized\n"); + return; + } + themenum = (int)PRVM_G_FLOAT(OFS_PARM0); + if (themenum < 0 || themenum >= vmpartspawner.max_themes) + { + VM_Warning("VM_CL_ParticleTheme: bad theme number %i\n", themenum); + VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]); + return; + } + if (vmpartspawner.themes[themenum].initialized == false) + { + VM_Warning("VM_CL_ParticleTheme: theme #%i not exists\n", themenum); + VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]); + return; + } + // load particle theme into globals + VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[themenum]); +} + +// float() saveparticletheme +// void(float themenum) updateparticletheme +void VM_CL_ParticleThemeSave (void) +{ + int themenum; + + VM_SAFEPARMCOUNTRANGE(0, 1, VM_CL_ParticleThemeSave); + if (vmpartspawner.verified == false) + { + VM_Warning("VM_CL_ParticleThemeSave: particle spawner not initialized\n"); + return; + } + // allocate new theme, save it and return + if (prog->argc < 1) + { + for (themenum = 0; themenum < vmpartspawner.max_themes; themenum++) + if (vmpartspawner.themes[themenum].initialized == false) + break; + if (themenum >= vmpartspawner.max_themes) + { + if (vmpartspawner.max_themes == 2048) + VM_Warning("VM_CL_ParticleThemeSave: no free theme slots\n"); + else + VM_Warning("VM_CL_ParticleThemeSave: no free theme slots, try initparticlespawner() with highter max_themes\n"); + PRVM_G_FLOAT(OFS_RETURN) = -1; + return; + } + vmpartspawner.themes[themenum].initialized = true; + VM_CL_ParticleThemeFromGlobals(&vmpartspawner.themes[themenum]); + PRVM_G_FLOAT(OFS_RETURN) = themenum; + return; + } + // update existing theme + themenum = (int)PRVM_G_FLOAT(OFS_PARM0); + if (themenum < 0 || themenum >= vmpartspawner.max_themes) + { + VM_Warning("VM_CL_ParticleThemeSave: bad theme number %i\n", themenum); + return; + } + vmpartspawner.themes[themenum].initialized = true; + VM_CL_ParticleThemeFromGlobals(&vmpartspawner.themes[themenum]); +} + +// void(float themenum) freeparticletheme +void VM_CL_ParticleThemeFree (void) +{ + int themenum; + + VM_SAFEPARMCOUNT(1, VM_CL_ParticleThemeFree); + if (vmpartspawner.verified == false) + { + VM_Warning("VM_CL_ParticleThemeFree: particle spawner not initialized\n"); + return; + } + themenum = (int)PRVM_G_FLOAT(OFS_PARM0); + // check parms + if (themenum <= 0 || themenum >= vmpartspawner.max_themes) + { + VM_Warning("VM_CL_ParticleThemeFree: bad theme number %i\n", themenum); + return; + } + if (vmpartspawner.themes[themenum].initialized == false) + { + VM_Warning("VM_CL_ParticleThemeFree: theme #%i already freed\n", themenum); + VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]); + return; + } + // free theme + VM_ResetParticleTheme(&vmpartspawner.themes[themenum]); + vmpartspawner.themes[themenum].initialized = false; +} + +// float(vector org, vector dir, [float theme]) particle +// returns 0 if failed, 1 if succesful +void VM_CL_SpawnParticle (void) +{ + float *org, *dir; + vmparticletheme_t *theme; + particle_t *part; + int themenum; + + VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_SpawnParticle2); + if (vmpartspawner.verified == false) + { + VM_Warning("VM_CL_SpawnParticle: particle spawner not initialized\n"); + PRVM_G_FLOAT(OFS_RETURN) = 0; + return; + } + org = PRVM_G_VECTOR(OFS_PARM0); + dir = PRVM_G_VECTOR(OFS_PARM1); + + if (prog->argc < 3) // global-set particle + { + part = CL_NewParticle((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, (int)(*vmpartspawner.particle_alpha*256), (int)(*vmpartspawner.particle_alphafade*256), *vmpartspawner.particle_gravity, *vmpartspawner.particle_bounce, org[0], org[1], org[2], dir[0], dir[1], dir[2], *vmpartspawner.particle_airfriction, *vmpartspawner.particle_liquidfriction, *vmpartspawner.particle_originjitter, *vmpartspawner.particle_velocityjitter, (*vmpartspawner.particle_qualityreduction) ? true : false, *vmpartspawner.particle_time, *vmpartspawner.particle_stretch, (pblend_t)*vmpartspawner.particle_blendmode, (porientation_t)*vmpartspawner.particle_orientation, ((int)vmpartspawner.particle_staincolor1[0] << 16) + ((int)vmpartspawner.particle_staincolor1[1] << 8) + ((int)vmpartspawner.particle_staincolor1[2]), ((int)vmpartspawner.particle_staincolor2[0] << 16) + ((int)vmpartspawner.particle_staincolor2[1] << 8) + ((int)vmpartspawner.particle_staincolor2[2]), (int)*vmpartspawner.particle_staintex); + if (!part) + { + 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; + } + else // quick themed particle + { + themenum = (int)PRVM_G_FLOAT(OFS_PARM2); + if (themenum <= 0 || themenum >= vmpartspawner.max_themes) + { + VM_Warning("VM_CL_SpawnParticle: bad theme number %i\n", themenum); + PRVM_G_FLOAT(OFS_RETURN) = 0; + return; + } + theme = &vmpartspawner.themes[themenum]; + part = CL_NewParticle(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); + if (!part) + { + PRVM_G_FLOAT(OFS_RETURN) = 0; + return; + } + if (theme->delayspawn) + part->delayedspawn = cl.time + theme->delayspawn; + if (theme->delaycollision) + part->delayedcollisions = cl.time + theme->delaycollision; + } + 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 +void VM_CL_SpawnParticleDelayed (void) +{ + float *org, *dir; + vmparticletheme_t *theme; + particle_t *part; + int themenum; + + VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_SpawnParticle2); + if (vmpartspawner.verified == false) + { + VM_Warning("VM_CL_SpawnParticle: particle spawner not initialized\n"); + PRVM_G_FLOAT(OFS_RETURN) = 0; + return; + } + org = PRVM_G_VECTOR(OFS_PARM0); + dir = PRVM_G_VECTOR(OFS_PARM1); + if (prog->argc < 5) // global-set particle + part = CL_NewParticle((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, (int)(*vmpartspawner.particle_alpha*256), (int)(*vmpartspawner.particle_alphafade*256), *vmpartspawner.particle_gravity, *vmpartspawner.particle_bounce, org[0], org[1], org[2], dir[0], dir[1], dir[2], *vmpartspawner.particle_airfriction, *vmpartspawner.particle_liquidfriction, *vmpartspawner.particle_originjitter, *vmpartspawner.particle_velocityjitter, (*vmpartspawner.particle_qualityreduction) ? true : false, *vmpartspawner.particle_time, *vmpartspawner.particle_stretch, (pblend_t)*vmpartspawner.particle_blendmode, (porientation_t)*vmpartspawner.particle_orientation, ((int)vmpartspawner.particle_staincolor1[0] << 16) + ((int)vmpartspawner.particle_staincolor1[1] << 8) + ((int)vmpartspawner.particle_staincolor1[2]), ((int)vmpartspawner.particle_staincolor2[0] << 16) + ((int)vmpartspawner.particle_staincolor2[1] << 8) + ((int)vmpartspawner.particle_staincolor2[2]), (int)*vmpartspawner.particle_staintex); + else // themed particle + { + themenum = (int)PRVM_G_FLOAT(OFS_PARM4); + if (themenum <= 0 || themenum >= vmpartspawner.max_themes) + { + VM_Warning("VM_CL_SpawnParticle: bad theme number %i\n", themenum); + PRVM_G_FLOAT(OFS_RETURN) = 0; + return; + } + theme = &vmpartspawner.themes[themenum]; + part = CL_NewParticle(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); + } + 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); + PRVM_G_FLOAT(OFS_RETURN) = 0; +} + +// //==================== //QC POLYGON functions //==================== @@ -2491,8 +2972,10 @@ vmpolygons_t vmpolygons[PRVM_MAXPROGS]; // --blub void VM_CL_R_RenderScene (void) { + double t = Sys_DoubleTime(); vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr(); VM_SAFEPARMCOUNT(0, VM_CL_R_RenderScene); + // we need to update any RENDER_VIEWMODEL entities at this point because // csqc supplies its own view matrix CL_UpdateViewEntities(); @@ -2501,6 +2984,9 @@ void VM_CL_R_RenderScene (void) polys->num_vertices = polys->num_triangles = 0; polys->progstarttime = prog->starttime; + + // callprofile fixing hack: do not include this time in what is counted for CSQC_UpdateView + prog->functions[prog->funcoffsets.CSQC_UpdateView].totaltime -= Sys_DoubleTime() - t; } static void VM_ResizePolygons(vmpolygons_t *polys) @@ -2601,7 +3087,8 @@ void VMPolygons_Store(vmpolygons_t *polys) mesh.texture = polys->begin_texture; mesh.num_vertices = polys->begin_vertices; mesh.num_triangles = polys->begin_vertices-2; - mesh.data_element3s = polygonelements; + 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]; @@ -2870,7 +3357,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_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true); + trace = CL_TraceLine(start, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true); if (trace.fraction == 1.0) return false; @@ -2883,7 +3370,7 @@ realcheck: start[0] = stop[0] = x ? maxs[0] : mins[0]; start[1] = stop[1] = y ? maxs[1] : mins[1]; - trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true); + trace = CL_TraceLine(start, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true); if (trace.fraction != 1.0 && trace.endpos[2] > bottom) bottom = trace.endpos[2]; @@ -2932,7 +3419,7 @@ qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean if (dz < 30) neworg[2] += 8; } - trace = CL_Move (ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true); + trace = CL_TraceBox(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true); if (settrace) CL_VM_SetTraceGlobals(&trace, svent); @@ -2960,14 +3447,14 @@ qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean VectorCopy (neworg, end); end[2] -= sv_stepheight.value*2; - trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true); + trace = CL_TraceBox(neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true); if (settrace) CL_VM_SetTraceGlobals(&trace, svent); if (trace.startsolid) { neworg[2] -= sv_stepheight.value; - trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true); + trace = CL_TraceBox(neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true); if (settrace) CL_VM_SetTraceGlobals(&trace, svent); if (trace.startsolid) @@ -3692,16 +4179,16 @@ VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION) VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME) VM_keynumtostring, // #520 string keynumtostring(float keynum) -VM_findkeysforcommand, // #521 string findkeysforcommand(string command) -NULL, // #522 -NULL, // #523 -NULL, // #524 -NULL, // #525 -NULL, // #526 -NULL, // #527 -NULL, // #528 -NULL, // #529 -NULL, // #530 +VM_findkeysforcommand, // #521 string findkeysforcommand(string command) +VM_CL_InitParticleSpawner, // #522 void(float max_themes) initparticlespawner (DP_CSQC_SPAWNPARTICLE) +VM_CL_ResetParticle, // #523 void() resetparticle (DP_CSQC_SPAWNPARTICLE) +VM_CL_ParticleTheme, // #524 void(float theme) particletheme (DP_CSQC_SPAWNPARTICLE) +VM_CL_ParticleThemeSave, // #525 void() particlethemesave, void(float theme) particlethemeupdate (DP_CSQC_SPAWNPARTICLE) +VM_CL_ParticleThemeFree, // #526 void() particlethemefree (DP_CSQC_SPAWNPARTICLE) +VM_CL_SpawnParticle, // #527 float(vector org, vector vel, [float theme]) particle (DP_CSQC_SPAWNPARTICLE) +VM_CL_SpawnParticleDelayed, // #528 float(vector org, vector vel, float delay, float collisiondelay, [float theme]) delayedparticle (DP_CSQC_SPAWNPARTICLE) +VM_loadfromdata, // #529 +VM_loadfromfile, // #530 NULL, // #531 NULL, // #532 NULL, // #533 @@ -3776,15 +4263,15 @@ NULL, // #601 NULL, // #602 NULL, // #603 NULL, // #604 -NULL, // #605 -NULL, // #606 -NULL, // #607 +VM_callfunction, // #605 +VM_writetofile, // #606 +VM_isfunction, // #607 NULL, // #608 NULL, // #609 NULL, // #610 NULL, // #611 NULL, // #612 -NULL, // #613 +VM_parseentitydata, // #613 NULL, // #614 NULL, // #615 NULL, // #616 @@ -3821,6 +4308,7 @@ void VM_CL_Cmd_Init(void) void VM_CL_Cmd_Reset(void) { + World_End(&cl.world); VM_Cmd_Reset(); VM_Polygons_Reset(); }