]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/mapobjects/subs.qc
Merge branch 'z411/gamemenu_cvar' into 'master'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / mapobjects / subs.qc
index 2a237fdcb79abdb5be234fd7e65b0dd4512134c4..5d25bf4b5e9a6001b176d9b509d01aed1256ca7e 100644 (file)
@@ -1,9 +1,18 @@
 #include "subs.qh"
+
 void SUB_NullThink(entity this) { }
 
 void SUB_CalcMoveDone(entity this);
 void SUB_CalcAngleMoveDone(entity this);
 
+#ifdef SVQC
+spawnfunc(info_null)
+{
+       delete(this);
+       // if anything breaks, tell the mapper to fix his map! info_null is meant to remove itself immediately.
+}
+#endif
+
 /*
 ==================
 SUB_Friction
@@ -62,14 +71,16 @@ void SUB_SetFade_Think (entity this)
 ==================
 SUB_SetFade
 
-Fade 'ent' out when time >= 'when'
+Fade ent out when time >= vanish_time
 ==================
 */
-void SUB_SetFade (entity ent, float when, float fading_time)
+void SUB_SetFade(entity ent, float vanish_time, float fading_time)
 {
+       if (fading_time <= 0)
+               fading_time = 0.01;
        ent.fade_rate = 1/fading_time;
        setthink(ent, SUB_SetFade_Think);
-       ent.nextthink = when;
+       ent.nextthink = vanish_time;
 }
 
 /*
@@ -91,6 +102,12 @@ void SUB_CalcMoveDone(entity this)
                this.think1 (this);
 }
 
+void SUB_CalcMovePause(entity this)
+{
+       this.move_controller.animstate_starttime += frametime;
+       this.move_controller.animstate_endtime += frametime;
+}
+
 .float platmovetype_turn;
 void SUB_CalcMove_controller_think (entity this)
 {
@@ -158,7 +175,8 @@ void SUB_CalcMove_controller_setbezier (entity controller, vector org, vector co
        // 2 * control * t - 2 * control * t * t + destin * t * t
        // 2 * control * t + (destin - 2 * control) * t * t
 
-       setorigin(controller, org);
+       //setorigin(controller, org); // don't link to the world
+       controller.origin = org;
        control -= org;
        destin -= org;
 
@@ -173,19 +191,14 @@ void SUB_CalcMove_controller_setlinear (entity controller, vector org, vector de
        // 2 * control * t - 2 * control * t * t + destin * t * t
        // 2 * control * t + (destin - 2 * control) * t * t
 
-       setorigin(controller, org);
+       //setorigin(controller, org); // don't link to the world
+       controller.origin = org;
        destin -= org;
 
        controller.destvec = destin; // end point
        controller.destvec2 = '0 0 0';
 }
 
-float TSPEED_TIME = -1;
-float TSPEED_LINEAR = 0;
-float TSPEED_START = 1;
-float TSPEED_END = 2;
-// TODO average too?
-
 void SUB_CalcMove_Bezier (entity this, vector tcontrol, vector tdest, float tspeedtype, float tspeed, void(entity this) func)
 {
        float   traveltime;
@@ -227,7 +240,7 @@ void SUB_CalcMove_Bezier (entity this, vector tcontrol, vector tdest, float tspe
        {
                delete(this.move_controller);
        }
-       controller = new(SUB_CalcMove_controller);
+       controller = new_pure(SUB_CalcMove_controller);
        controller.owner = this;
        this.move_controller = controller;
        controller.platmovetype = this.platmovetype;
@@ -285,7 +298,7 @@ void SUB_CalcMove (entity this, vector tdest, float tspeedtype, float tspeed, vo
        // Very short animations don't really show off the effect
        // of controlled animation, so let's just use linear movement.
        // Alternatively entities can choose to specify non-controlled movement.
-        // The only currently implemented alternative movement is linear (value 1)
+       // The only currently implemented alternative movement is linear (value 1)
        if (traveltime < 0.15 || (this.platmovetype_start == 1 && this.platmovetype_end == 1)) // is this correct?
        {
                this.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division
@@ -367,3 +380,205 @@ void SUB_CalcAngleMoveEnt (entity ent, vector destangle, float tspeedtype, float
 {
        SUB_CalcAngleMove (ent, destangle, tspeedtype, tspeed, func);
 }
+
+#ifdef SVQC
+void ApplyMinMaxScaleAngles(entity e)
+{
+       if(e.angles.x != 0 || e.angles.z != 0 || e.avelocity.x != 0 || e.avelocity.z != 0) // "weird" rotation
+       {
+               e.maxs = '1 1 1' * vlen(
+                       '1 0 0' * max(-e.mins.x, e.maxs.x) +
+                       '0 1 0' * max(-e.mins.y, e.maxs.y) +
+                       '0 0 1' * max(-e.mins.z, e.maxs.z)
+               );
+               e.mins = -e.maxs;
+       }
+       else if(e.angles.y != 0 || e.avelocity.y != 0) // yaw only is a bit better
+       {
+               e.maxs_x = vlen(
+                       '1 0 0' * max(-e.mins.x, e.maxs.x) +
+                       '0 1 0' * max(-e.mins.y, e.maxs.y)
+               );
+               e.maxs_y = e.maxs.x;
+               e.mins_x = -e.maxs.x;
+               e.mins_y = -e.maxs.x;
+       }
+       if(e.scale)
+               setsize(e, RoundPerfectVector(e.mins * e.scale), RoundPerfectVector(e.maxs * e.scale));
+       else
+               setsize(e, e.mins, e.maxs);
+}
+
+void SetBrushEntityModel(entity this, bool with_lod)
+{
+       if(this.model != "")
+       {
+               precache_model(this.model);
+               if(this.mins != '0 0 0' || this.maxs != '0 0 0')
+               {
+                       vector mi = this.mins;
+                       vector ma = this.maxs;
+                       _setmodel(this, this.model); // no precision needed
+                       setsize(this, mi, ma);
+               }
+               else
+                       _setmodel(this, this.model); // no precision needed
+               if(with_lod)
+                       InitializeEntity(this, LODmodel_attach, INITPRIO_FINDTARGET);
+
+               if(endsWith(this.model, ".obj")) // WORKAROUND: darkplaces currently rotates .obj models on entities incorrectly, we need to add 180 degrees to the Y axis
+                       this.angles_y = anglemods(this.angles_y - 180);
+       }
+       setorigin(this, this.origin);
+       ApplyMinMaxScaleAngles(this);
+}
+
+bool LOD_customize(entity this, entity client)
+{
+       if(autocvar_loddebug)
+       {
+               int d = autocvar_loddebug;
+               if(d == 1)
+                       this.modelindex = this.lodmodelindex0;
+               else if(d == 2 || !this.lodmodelindex2)
+                       this.modelindex = this.lodmodelindex1;
+               else // if(d == 3)
+                       this.modelindex = this.lodmodelindex2;
+               return true;
+       }
+
+       // TODO csqc network this so it only gets sent once
+       vector near_point = NearestPointOnBox(this, client.origin);
+       if(vdist(near_point - client.origin, <, this.loddistance1))
+               this.modelindex = this.lodmodelindex0;
+       else if(!this.lodmodelindex2 || vdist(near_point - client.origin, <, this.loddistance2))
+               this.modelindex = this.lodmodelindex1;
+       else
+               this.modelindex = this.lodmodelindex2;
+
+       return true;
+}
+
+void LOD_uncustomize(entity this)
+{
+       this.modelindex = this.lodmodelindex0;
+}
+
+void LODmodel_attach(entity this)
+{
+       entity e;
+
+       if(!this.loddistance1)
+               this.loddistance1 = 1000;
+       if(!this.loddistance2)
+               this.loddistance2 = 2000;
+       this.lodmodelindex0 = this.modelindex;
+
+       if(this.lodtarget1 != "")
+       {
+               e = find(NULL, targetname, this.lodtarget1);
+               if(e)
+               {
+                       this.lodmodel1 = e.model;
+                       delete(e);
+               }
+       }
+       if(this.lodtarget2 != "")
+       {
+               e = find(NULL, targetname, this.lodtarget2);
+               if(e)
+               {
+                       this.lodmodel2 = e.model;
+                       delete(e);
+               }
+       }
+
+       if(autocvar_loddebug < 0)
+       {
+               this.lodmodel1 = this.lodmodel2 = ""; // don't even initialize
+       }
+
+       if(this.lodmodel1 != "")
+       {
+               vector mi, ma;
+               mi = this.mins;
+               ma = this.maxs;
+
+               precache_model(this.lodmodel1);
+               _setmodel(this, this.lodmodel1);
+               this.lodmodelindex1 = this.modelindex;
+
+               if(this.lodmodel2 != "")
+               {
+                       precache_model(this.lodmodel2);
+                       _setmodel(this, this.lodmodel2);
+                       this.lodmodelindex2 = this.modelindex;
+               }
+
+               this.modelindex = this.lodmodelindex0;
+               setsize(this, mi, ma);
+       }
+
+       if(this.lodmodelindex1)
+               if (!getSendEntity(this))
+                       SetCustomizer(this, LOD_customize, LOD_uncustomize);
+}
+
+/*
+================
+InitTrigger
+================
+*/
+
+void SetMovedir(entity this)
+{
+       if(this.movedir != '0 0 0')
+               this.movedir = normalize(this.movedir);
+       else
+       {
+               makevectors(this.angles);
+               this.movedir = v_forward;
+       }
+
+       this.angles = '0 0 0';
+}
+
+void InitTrigger(entity this)
+{
+// trigger angles are used for one-way touches.  An angle of 0 is assumed
+// to mean no restrictions, so use a yaw of 360 instead.
+       SetMovedir(this);
+       this.solid = SOLID_TRIGGER;
+       SetBrushEntityModel(this, false);
+       set_movetype(this, MOVETYPE_NONE);
+       this.modelindex = 0;
+       this.model = "";
+}
+
+void InitSolidBSPTrigger(entity this)
+{
+// trigger angles are used for one-way touches.  An angle of 0 is assumed
+// to mean no restrictions, so use a yaw of 360 instead.
+       SetMovedir(this);
+       this.solid = SOLID_BSP;
+       SetBrushEntityModel(this, false);
+       set_movetype(this, MOVETYPE_NONE); // why was this PUSH? -div0
+//     this.modelindex = 0;
+       this.model = "";
+}
+
+bool InitMovingBrushTrigger(entity this)
+{
+// trigger angles are used for one-way touches.  An angle of 0 is assumed
+// to mean no restrictions, so use a yaw of 360 instead.
+       this.solid = SOLID_BSP;
+       SetBrushEntityModel(this, true);
+       set_movetype(this, MOVETYPE_PUSH);
+       if(this.modelindex == 0)
+       {
+               objerror(this, "InitMovingBrushTrigger: no brushes found!");
+               return false;
+       }
+       return true;
+}
+#endif