#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)
{
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);
}
}
}
+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)
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))
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
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);
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;
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);
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';
}
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;
}