]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/mapobjects/models.qc
Transifex autosync
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / mapobjects / models.qc
index 18d033663eaff85541fadfffe49dcbf849370484..dfc96666e55ac88a09f4d407b44401f720cac6fa 100644 (file)
@@ -1,23 +1,18 @@
 #include "models.qh"
 
-#ifdef SVQC
-#include <server/defs.qh>
-#include <server/miscfunctions.qh>
-#include <common/net_linked.qh>
-#include "subs.qh"
-#include "triggers.qh"
-
-entityclass(BGMScript);
-classfield(BGMScript) .string bgmscript;
-classfield(BGMScript) .float bgmscriptattack;
-classfield(BGMScript) .float bgmscriptdecay;
-classfield(BGMScript) .float bgmscriptsustain;
-classfield(BGMScript) .float bgmscriptrelease;
+#ifdef CSQC
+       #include <client/csqcmodel_hooks.qh>
+#endif
 
+#ifdef SVQC
 #include <common/constants.qh>
-#include "../../lib/csqcmodel/sv_model.qh"
-
-.float modelscale;
+#include <common/mapobjects/bgmscript.qh>
+#include <common/mapobjects/subs.qh>
+#include <common/mapobjects/triggers.qh>
+#include <common/net_linked.qh>
+#include <common/stats.qh>
+#include <common/weapons/_all.qh>
+#include <lib/csqcmodel/sv_model.qh>
 
 void g_model_setcolormaptoactivator(entity this, entity actor, entity trigger)
 {
@@ -49,12 +44,20 @@ void g_clientmodel_use(entity this, entity actor, entity trigger)
        if (this.antiwall_flag == 1)
        {
                this.inactive = 1;
-               this.solid = SOLID_NOT;
+               if (this.solid != SOLID_NOT)
+               {
+                       this.solid = SOLID_NOT;
+                       setorigin(this, this.origin); // unlink
+               }
        }
        else if (this.antiwall_flag == 2)
        {
                this.inactive = 0;
-               this.solid = this.default_solid;
+               if (this.solid != this.default_solid)
+               {
+                       this.solid = this.default_solid;
+                       setorigin(this, this.origin); // link
+               }
        }
        g_clientmodel_setcolormaptoactivator(this, actor, trigger);
 }
@@ -78,13 +81,21 @@ void g_model_dropbyspawnflags(entity this)
        }
 }
 
+void g_clientmodel_think(entity this)
+{
+       this.nextthink = time;
+       if(this.oldorigin != this.origin)
+               this.SendFlags |= BIT(1);
+       this.oldorigin = this.origin;
+}
+
 void g_clientmodel_dropbyspawnflags(entity this)
 {
        vector o0;
        o0 = this.origin;
        g_model_dropbyspawnflags(this);
        if(this.origin != o0)
-               this.SendFlags |= 2;
+               this.SendFlags |= BIT(1);
 }
 
 bool g_clientmodel_genericsendentity(entity this, entity to, int sf)
@@ -117,11 +128,7 @@ bool g_clientmodel_genericsendentity(entity this, entity to, int sf)
        if(sf & BIT(2))
        {
                if(sf & 0x10)
-               {
-                       WriteAngle(MSG_ENTITY, this.angles.x);
-                       WriteAngle(MSG_ENTITY, this.angles.y);
-                       WriteAngle(MSG_ENTITY, this.angles.z);
-               }
+                       WriteAngleVector(MSG_ENTITY, this.angles);
        }
 
        if(sf & BIT(3))
@@ -129,9 +136,9 @@ bool g_clientmodel_genericsendentity(entity this, entity to, int sf)
                if(sf & 0x80)
                {
                        WriteShort(MSG_ENTITY, this.lodmodelindex0);
-                       WriteShort(MSG_ENTITY, bound(0, this.loddistance1, 65535));
+                       WriteShort(MSG_ENTITY, bound(0, this.loddistance1, 32767));
                        WriteShort(MSG_ENTITY, this.lodmodelindex1);
-                       WriteShort(MSG_ENTITY, bound(0, this.loddistance2, 65535));
+                       WriteShort(MSG_ENTITY, bound(0, this.loddistance2, 32767));
                        WriteShort(MSG_ENTITY, this.lodmodelindex2);
                }
                else
@@ -153,8 +160,8 @@ bool g_clientmodel_genericsendentity(entity this, entity to, int sf)
                        WriteVector(MSG_ENTITY, this.movedir);
                        WriteByte(MSG_ENTITY, floor(this.lip * 255));
                }
-               WriteShort(MSG_ENTITY, bound(0, this.fade_start, 65535));
-               WriteShort(MSG_ENTITY, bound(0, this.fade_end, 65535));
+               WriteShort(MSG_ENTITY, bound(0, this.fade_start, 32767));
+               WriteShort(MSG_ENTITY, bound(0, this.fade_end, 32767));
                WriteByte(MSG_ENTITY, floor(this.alpha_max * 256));
                WriteByte(MSG_ENTITY, floor(this.alpha_min * 256));
                WriteByte(MSG_ENTITY, this.inactive);
@@ -164,42 +171,52 @@ bool g_clientmodel_genericsendentity(entity this, entity to, int sf)
        return true;
 }
 
+void g_model_init(entity ent, float sol)
+{
+       if(ent.geomtype && autocvar_physics_ode && checkextension("DP_PHYSICS_ODE")) set_movetype(ent, MOVETYPE_PHYSICS);
+       if(!ent.scale) ent.scale = ent.modelscale;
 
-#define G_MODEL_INIT(ent,sol) \
-       if(ent.geomtype && autocvar_physics_ode && checkextension("DP_PHYSICS_ODE")) set_movetype(ent, MOVETYPE_PHYSICS); \
-       if(!ent.scale) ent.scale = ent.modelscale; \
-       SetBrushEntityModel(ent,true); \
-       ent.use = g_model_setcolormaptoactivator; \
-       InitializeEntity(ent, g_model_dropbyspawnflags, INITPRIO_DROPTOFLOOR); \
-       if(!ent.solid) ent.solid = (sol); \
+       if(!ent.solid) ent.solid = (sol);
        else if(ent.solid < 0) ent.solid = SOLID_NOT;
+       SetBrushEntityModel(ent,true); // called after setting .solid to ensure correct area grid linking/unlinking
 
-#define G_CLIENTMODEL_INIT(ent,sol) \
-       if(ent.geomtype && autocvar_physics_ode && checkextension("DP_PHYSICS_ODE")) set_movetype(ent, MOVETYPE_PHYSICS); \
-       if(!ent.scale) ent.scale = ent.modelscale; \
-       SetBrushEntityModel(ent,true); \
-       ent.use = g_clientmodel_use; \
-       InitializeEntity(ent, g_clientmodel_dropbyspawnflags, INITPRIO_DROPTOFLOOR); \
-       if(!ent.solid) ent.solid = (sol); \
-       else if(ent.solid < 0) ent.solid = SOLID_NOT; \
-       if(!ent.bgmscriptsustain) ent.bgmscriptsustain = 1; \
-       else if(ent.bgmscriptsustain < 0) ent.bgmscriptsustain = 0; \
-       Net_LinkEntity(ent, true, 0, g_clientmodel_genericsendentity); \
+       ent.use = g_model_setcolormaptoactivator;
+       InitializeEntity(ent, g_model_dropbyspawnflags, INITPRIO_DROPTOFLOOR);
+}
+
+void g_clientmodel_init(entity ent, float sol)
+{
+       if(ent.geomtype && autocvar_physics_ode && checkextension("DP_PHYSICS_ODE")) set_movetype(ent, MOVETYPE_PHYSICS);
+       if(!ent.scale) ent.scale = ent.modelscale;
+
+       if(!ent.solid) ent.solid = (sol);
+       else if(ent.solid < 0) ent.solid = SOLID_NOT;
+       SetBrushEntityModel(ent,true); // called after setting .solid to ensure correct area grid linking/unlinking
+
+       ent.use = g_clientmodel_use;
+       setthink(ent, g_clientmodel_think);
+       ent.nextthink = time;
+       ent.oldorigin = ent.origin; // don't run an initial double update
+       InitializeEntity(ent, g_clientmodel_dropbyspawnflags, INITPRIO_DROPTOFLOOR);
+       if(!ent.bgmscriptsustain) ent.bgmscriptsustain = 1;
+       else if(ent.bgmscriptsustain < 0) ent.bgmscriptsustain = 0;
+       Net_LinkEntity(ent, true, 0, g_clientmodel_genericsendentity);
        ent.default_solid = sol;
+}
 
 // non-solid model entities:
-spawnfunc(misc_gamemodel)         { this.angles_x = -this.angles.x; G_MODEL_INIT      (this, SOLID_NOT) } // model entity
-spawnfunc(misc_clientmodel)       { this.angles_x = -this.angles.x; G_CLIENTMODEL_INIT(this, SOLID_NOT) } // model entity
-spawnfunc(misc_models)            { this.angles_x = -this.angles.x; G_MODEL_INIT      (this, SOLID_NOT) } // DEPRECATED old compat entity with confusing name, do not use
+spawnfunc(misc_gamemodel)         { this.angles_x = -this.angles.x; g_model_init(this, SOLID_NOT); } // model entity
+spawnfunc(misc_clientmodel)       { this.angles_x = -this.angles.x; g_clientmodel_init(this, SOLID_NOT); } // model entity
+spawnfunc(misc_models)            { this.angles_x = -this.angles.x; g_model_init(this, SOLID_NOT); } // DEPRECATED old compat entity with confusing name, do not use
 
 // non-solid brush entities:
-spawnfunc(func_illusionary)       { G_MODEL_INIT      (this, SOLID_NOT) } // Q1 name (WARNING: MISPREDICTED)
-spawnfunc(func_clientillusionary) { G_CLIENTMODEL_INIT(this, SOLID_NOT) } // brush entity
-spawnfunc(func_static)            { G_MODEL_INIT      (this, SOLID_NOT) } // DEPRECATED old alias name from some other game
+spawnfunc(func_illusionary)       { g_model_init(this, SOLID_NOT); } // Q1 name (WARNING: MISPREDICTED)
+spawnfunc(func_clientillusionary) { g_clientmodel_init(this, SOLID_NOT); } // brush entity
 
 // solid brush entities
-spawnfunc(func_wall)              { G_MODEL_INIT      (this, SOLID_BSP) } // Q1 name
-spawnfunc(func_clientwall)        { G_CLIENTMODEL_INIT(this, SOLID_BSP) } // brush entity (WARNING: MISPREDICTED)
+spawnfunc(func_wall)              { g_model_init(this, SOLID_BSP); } // Q1 name
+spawnfunc(func_clientwall)        { g_clientmodel_init(this, SOLID_BSP); } // brush entity (WARNING: MISPREDICTED)
+spawnfunc(func_static)            { g_model_init(this, SOLID_BSP); } // DEPRECATED old alias name from some other game
 #elif defined(CSQC)
 .float alpha;
 .float scale;
@@ -256,30 +273,7 @@ void Ent_Wall_Draw(entity this)
                fld = origin;
        this.(fld) = this.saved;
 
-       if(this.lodmodelindex1)
-       {
-               if(autocvar_cl_modeldetailreduction <= 0)
-               {
-                       if(this.lodmodelindex2 && autocvar_cl_modeldetailreduction <= -2)
-                               this.modelindex = this.lodmodelindex2;
-                       else if(autocvar_cl_modeldetailreduction <= -1)
-                               this.modelindex = this.lodmodelindex1;
-                       else
-                               this.modelindex = this.lodmodelindex0;
-               }
-               else
-               {
-                       float distance = vlen(NearestPointOnBox(this, view_origin) - view_origin);
-                       f = (distance * current_viewzoom + 100.0) * autocvar_cl_modeldetailreduction;
-                       f *= 1.0 / bound(0.01, view_quality, 1);
-                       if(this.lodmodelindex2 && f > this.loddistance2)
-                               this.modelindex = this.lodmodelindex2;
-                       else if(f > this.loddistance1)
-                               this.modelindex = this.lodmodelindex1;
-                       else
-                               this.modelindex = this.lodmodelindex0;
-               }
-       }
+       CSQCModel_LOD_Apply(this, false);
 
        InterpolateOrigin_Do(this);
 
@@ -342,11 +336,7 @@ NET_HANDLE(ENT_CLIENT_WALL, bool isnew)
        if(f & 4)
        {
                if(f & 0x10)
-               {
-                       this.angles_x = ReadAngle();
-                       this.angles_y = ReadAngle();
-                       this.angles_z = ReadAngle();
-               }
+                       this.angles = ReadAngleVector();
                else
                        this.angles = '0 0 0';
        }
@@ -360,10 +350,21 @@ NET_HANDLE(ENT_CLIENT_WALL, bool isnew)
                        this.lodmodelindex1 = ReadShort();
                        this.loddistance2 = ReadShort();
                        this.lodmodelindex2 = ReadShort();
+                       this.modelindex = this.lodmodelindex0;
+                       vector pmin = this.mins, pmax = this.maxs;
+                       setmodelindex(this, this.modelindex); // this retrieves the .model key and sets mins/maxs/absmin/absmax
+                       setsize(this, pmin, pmax);
+                       // if there's no second LOD model, fall back to the first
+                       // avoids using the high quality model at a distance
+                       if(!this.lodmodelindex2 && this.lodmodelindex1)
+                               this.lodmodelindex2 = this.lodmodelindex1;
                }
                else
                {
                        this.modelindex = ReadShort();
+                       vector pmin = this.mins, pmax = this.maxs;
+                       setmodelindex(this, this.modelindex); // this retrieves the .model key and sets mins/maxs/absmin/absmax
+                       setsize(this, pmin, pmax);
                        this.loddistance1 = 0;
                        this.loddistance2 = 0;
                }