From: Samual Lenks Date: Tue, 24 Dec 2013 06:49:54 +0000 (-0500) Subject: Working on adding CheckContentsTransition to CSQC movetypes X-Git-Tag: xonotic-v0.8.0~233^2~8 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=943d053416e8f7ed147fb28bb577973240c13498;p=xonotic%2Fxonotic-data.pk3dir.git Working on adding CheckContentsTransition to CSQC movetypes --- diff --git a/qcsrc/client/movetypes.qc b/qcsrc/client/movetypes.qc index 254362aca..072f9114c 100644 --- a/qcsrc/client/movetypes.qc +++ b/qcsrc/client/movetypes.qc @@ -10,14 +10,284 @@ void _Movetype_CheckVelocity() // SV_CheckVelocity { } -float _Movetype_CheckWater() // SV_CheckWater +#if 0 +int Mod_Q1BSP_SuperContentsFromNativeContents(dp_model_t *model, int nativecontents) { - return FALSE; + switch(nativecontents) + { + case CONTENTS_EMPTY: + return 0; + case CONTENTS_SOLID: + return SUPERCONTENTS_SOLID | SUPERCONTENTS_OPAQUE; + case CONTENTS_WATER: + return SUPERCONTENTS_WATER; + case CONTENTS_SLIME: + return SUPERCONTENTS_SLIME; + case CONTENTS_LAVA: + return SUPERCONTENTS_LAVA | SUPERCONTENTS_NODROP; + case CONTENTS_SKY: + return SUPERCONTENTS_SKY | SUPERCONTENTS_NODROP | SUPERCONTENTS_OPAQUE; // to match behaviour of Q3 maps, let sky count as opaque + } + return 0; +} +int Mod_Q1BSP_NativeContentsFromSuperContents(dp_model_t *model, int supercontents) +{ + if (supercontents & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY)) + return CONTENTS_SOLID; + if (supercontents & SUPERCONTENTS_SKY) + return CONTENTS_SKY; + if (supercontents & SUPERCONTENTS_LAVA) + return CONTENTS_LAVA; + if (supercontents & SUPERCONTENTS_SLIME) + return CONTENTS_SLIME; + if (supercontents & SUPERCONTENTS_WATER) + return CONTENTS_WATER; + return CONTENTS_EMPTY; +} +static qboolean SV_CheckWater (prvm_edict_t *ent) +{ + prvm_prog_t *prog = SVVM_prog; + int cont; + int nNativeContents; + vec3_t point; + + point[0] = PRVM_serveredictvector(ent, origin)[0]; + point[1] = PRVM_serveredictvector(ent, origin)[1]; + point[2] = PRVM_serveredictvector(ent, origin)[2] + PRVM_serveredictvector(ent, mins)[2] + 1; + + // DRESK - Support for Entity Contents Transition Event + // NOTE: Some logic needed to be slightly re-ordered + // to not affect performance and allow for the feature. + + // Acquire Super Contents Prior to Resets + cont = SV_PointSuperContents(point); + // Acquire Native Contents Here + nNativeContents = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, cont); + + // DRESK - Support for Entity Contents Transition Event + if(PRVM_serveredictfloat(ent, watertype)) + // Entity did NOT Spawn; Check + SV_CheckContentsTransition(ent, nNativeContents); + + + PRVM_serveredictfloat(ent, waterlevel) = 0; + PRVM_serveredictfloat(ent, watertype) = CONTENTS_EMPTY; + cont = SV_PointSuperContents(point); + if (cont & (SUPERCONTENTS_LIQUIDSMASK)) + { + PRVM_serveredictfloat(ent, watertype) = nNativeContents; + PRVM_serveredictfloat(ent, waterlevel) = 1; + point[2] = PRVM_serveredictvector(ent, origin)[2] + (PRVM_serveredictvector(ent, mins)[2] + PRVM_serveredictvector(ent, maxs)[2])*0.5; + if (SV_PointSuperContents(point) & (SUPERCONTENTS_LIQUIDSMASK)) + { + PRVM_serveredictfloat(ent, waterlevel) = 2; + point[2] = PRVM_serveredictvector(ent, origin)[2] + PRVM_serveredictvector(ent, view_ofs)[2]; + if (SV_PointSuperContents(point) & (SUPERCONTENTS_LIQUIDSMASK)) + PRVM_serveredictfloat(ent, waterlevel) = 3; + } + } + + return PRVM_serveredictfloat(ent, waterlevel) > 1; +} +static int SV_CheckContentsTransition(prvm_edict_t *ent, const int nContents) +{ + prvm_prog_t *prog = SVVM_prog; + int bValidFunctionCall; + + // Default Valid Function Call to False + bValidFunctionCall = false; + + if(PRVM_serveredictfloat(ent, watertype) != nContents) + { // Changed Contents + // Acquire Contents Transition Function from QC + if(PRVM_serveredictfunction(ent, contentstransition)) + { // Valid Function; Execute + // Assign Valid Function + bValidFunctionCall = true; + // Prepare Parameters (Original Contents, New Contents) + // Original Contents + PRVM_G_FLOAT(OFS_PARM0) = PRVM_serveredictfloat(ent, watertype); + // New Contents + PRVM_G_FLOAT(OFS_PARM1) = nContents; + // Assign Self + PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent); + // Set Time + PRVM_serverglobalfloat(time) = sv.time; + // Execute VM Function + prog->ExecuteProgram(prog, PRVM_serveredictfunction(ent, contentstransition), "contentstransition: NULL function"); + } + } + + // Return if Function Call was Valid + return bValidFunctionCall; +} + +static void SV_CheckWaterTransition (prvm_edict_t *ent) +{ + vec3_t entorigin; + prvm_prog_t *prog = SVVM_prog; + // LordHavoc: bugfixes in this function are keyed to the sv_gameplayfix_bugfixedcheckwatertransition cvar - if this cvar is 0 then all the original bugs should be reenabled for compatibility + int cont; + VectorCopy(PRVM_serveredictvector(ent, origin), entorigin); + cont = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(entorigin)); + if (!PRVM_serveredictfloat(ent, watertype)) + { + // just spawned here + if (!sv_gameplayfix_fixedcheckwatertransition.integer) + { + PRVM_serveredictfloat(ent, watertype) = cont; + PRVM_serveredictfloat(ent, waterlevel) = 1; + return; + } + } + // DRESK - Support for Entity Contents Transition Event + // NOTE: Call here BEFORE updating the watertype below, + // and suppress watersplash sound if a valid function + // call was made to allow for custom "splash" sounds. + else if( !SV_CheckContentsTransition(ent, cont) ) + { // Contents Transition Function Invalid; Potentially Play Water Sound + // check if the entity crossed into or out of water + if (sv_sound_watersplash.string && ((PRVM_serveredictfloat(ent, watertype) == CONTENTS_WATER || PRVM_serveredictfloat(ent, watertype) == CONTENTS_SLIME) != (cont == CONTENTS_WATER || cont == CONTENTS_SLIME))) + SV_StartSound (ent, 0, sv_sound_watersplash.string, 255, 1, false, 1.0f); + } + + if (cont <= CONTENTS_WATER) + { + PRVM_serveredictfloat(ent, watertype) = cont; + PRVM_serveredictfloat(ent, waterlevel) = 1; + } + else + { + PRVM_serveredictfloat(ent, watertype) = CONTENTS_EMPTY; + PRVM_serveredictfloat(ent, waterlevel) = sv_gameplayfix_fixedcheckwatertransition.integer ? 0 : cont; + } +} +#endif + +.float watertype; +.float waterlevel; +float Mod_Q1BSP_SuperContentsFromNativeContents(float nativecontents) +{ + switch(nativecontents) + { + case CONTENT_EMPTY: + return 0; + case CONTENT_SOLID: + return DPCONTENTS_SOLID | DPCONTENTS_OPAQUE; + case CONTENT_WATER: + return DPCONTENTS_WATER; + case CONTENT_SLIME: + return DPCONTENTS_SLIME; + case CONTENT_LAVA: + return DPCONTENTS_LAVA | DPCONTENTS_NODROP; + case CONTENT_SKY: + return DPCONTENTS_SKY | DPCONTENTS_NODROP | DPCONTENTS_OPAQUE; // to match behaviour of Q3 maps, let sky count as opaque + } + return 0; +} + +float Mod_Q1BSP_NativeContentsFromSuperContents(float supercontents) +{ + if (supercontents & (DPCONTENTS_SOLID | DPCONTENTS_BODY)) + return CONTENT_SOLID; + if (supercontents & DPCONTENTS_SKY) + return CONTENT_SKY; + if (supercontents & DPCONTENTS_LAVA) + return CONTENT_LAVA; + if (supercontents & DPCONTENTS_SLIME) + return CONTENT_SLIME; + if (supercontents & DPCONTENTS_WATER) + return CONTENT_WATER; + return CONTENT_EMPTY; +} + +float _Movetype_CheckWater(entity ent) // SV_CheckWater +{ + float contents; + float nativecontents; + vector point; + + point = ent.move_origin; + point_z += (ent.mins_z + 1); + + contents = pointcontents(point); + nativecontents = Mod_Q1BSP_NativeContentsFromSuperContents(contents); + + if(ent.watertype) + if(ent.watertype != nativecontents) + { + print(sprintf("_Movetype_CheckWater(): Original: '%d', New: '%d'\n", ent.watertype, nativecontents)); + //ent.contentstransition(ent.watertype, contents); + } + + ent.waterlevel = 0; + ent.watertype = CONTENT_EMPTY; + + contents = pointcontents(point); + if(contents & DPCONTENTS_LIQUIDSMASK) + { + ent.watertype = nativecontents; + ent.waterlevel = 1; + point_y = (ent.origin_y + ((ent.mins_z + ent.maxs_y) * 0.5)); + if(pointcontents(point) & DPCONTENTS_LIQUIDSMASK) + { + ent.waterlevel = 2; + point_y = ent.origin_y + ent.view_ofs_y; + if(pointcontents(point) & DPCONTENTS_LIQUIDSMASK) + ent.waterlevel = 3; + } + } + + return (ent.waterlevel > 1); } -void _Movetype_CheckWaterTransition() // SV_CheckWaterTransition +#if 0 +void _Movetype_CheckContentsTransition(entity ent, float contents) { - print("foobar\n"); + if(ent.watertype != contents) + { + print(sprintf("_Movetype_CheckWaterTransition(): Original: '%d', New: '%d'\n", ent.watertype, contents)); + //ent.contentstransition(ent.watertype, contents); + } +} +#endif + +float autocvar_sv_gameplayfix_fixedcheckwatertransition; +void _Movetype_CheckWaterTransition(entity ent) // SV_CheckWaterTransition +{ + float contents = Mod_Q1BSP_NativeContentsFromSuperContents(pointcontents(ent.move_origin)); + + if(!ent.watertype) + { + // just spawned here + if(!autocvar_sv_gameplayfix_fixedcheckwatertransition) + { + ent.watertype = contents; + ent.waterlevel = 1; + return; + } + } + //else if(!_Movetype_CheckContentsTransition(ent, contents)) + //{ + //if (sv_sound_watersplash.string && ((PRVM_serveredictfloat(ent, watertype) == CONTENTS_WATER || PRVM_serveredictfloat(ent, watertype) == CONTENTS_SLIME) != (cont == CONTENTS_WATER || cont == CONTENTS_SLIME))) + // SV_StartSound (ent, 0, sv_sound_watersplash.string, 255, 1, false, 1.0f); + //} + else if(ent.watertype != contents) + { + print(sprintf("_Movetype_CheckWaterTransition(): Original: '%d', New: '%d'\n", ent.watertype, contents)); + //ent.contentstransition(ent.watertype, contents); + } + + if(contents <= CONTENT_WATER) + { + ent.watertype = contents; + ent.waterlevel = 1; + } + else + { + ent.watertype = CONTENT_EMPTY; + ent.waterlevel = (autocvar_sv_gameplayfix_fixedcheckwatertransition ? 0 : contents); + } } void _Movetype_Impact(entity oth) // SV_Impact @@ -343,7 +613,7 @@ void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss self.move_velocity_z -= 0.5 * dt * getstatf(STAT_MOVEVARS_GRAVITY); } - _Movetype_CheckWaterTransition(); + _Movetype_CheckWaterTransition(self); } void _Movetype_Physics_Frame(float movedt) @@ -361,7 +631,7 @@ void _Movetype_Physics_Frame(float movedt) error("SV_Physics_Follow not implemented"); break; case MOVETYPE_NOCLIP: - _Movetype_CheckWater(); + _Movetype_CheckWater(self); self.move_origin = self.move_origin + ticrate * self.move_velocity; self.move_angles = self.move_angles + ticrate * self.move_avelocity; _Movetype_LinkEdict(FALSE);