]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Working on adding CheckContentsTransition to CSQC movetypes
authorSamual Lenks <samual@xonotic.org>
Tue, 24 Dec 2013 06:49:54 +0000 (01:49 -0500)
committerSamual Lenks <samual@xonotic.org>
Tue, 24 Dec 2013 06:49:54 +0000 (01:49 -0500)
qcsrc/client/movetypes.qc

index 254362aca746837b10836aad9a0a49853a1ad957..072f9114cb17c8bacf2a429fe48c1dc329b28755 100644 (file)
@@ -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);