]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'Mario/monster_lod_models' into 'master'
authorterencehill <piuntn@gmail.com>
Wed, 25 Jan 2023 11:00:41 +0000 (11:00 +0000)
committerterencehill <piuntn@gmail.com>
Wed, 25 Jan 2023 11:00:41 +0000 (11:00 +0000)
Add LOD models for the monsters to boost performance with lots of monsters in the map and fix some LOD related bugs

See merge request xonotic/xonotic-data.pk3dir!1069

20 files changed:
models/monsters/golem_lod1.dpm [new file with mode: 0644]
models/monsters/golem_lod1.dpm.framegroups [new file with mode: 0644]
models/monsters/golem_lod2.dpm [new file with mode: 0644]
models/monsters/golem_lod2.dpm.framegroups [new file with mode: 0644]
models/monsters/nanomage_lod1.dpm [new file with mode: 0644]
models/monsters/nanomage_lod1.dpm.framegroups [new file with mode: 0644]
models/monsters/nanomage_lod2.dpm [new file with mode: 0644]
models/monsters/nanomage_lod2.dpm.framegroups [new file with mode: 0644]
models/monsters/spider_lod1.dpm [new file with mode: 0644]
models/monsters/spider_lod1.dpm.framegroups [new file with mode: 0644]
models/monsters/spider_lod2.dpm [new file with mode: 0644]
models/monsters/spider_lod2.dpm.framegroups [new file with mode: 0644]
models/monsters/wyvern_lod1.dpm [new file with mode: 0644]
models/monsters/wyvern_lod1.dpm.framegroups [new file with mode: 0644]
models/monsters/wyvern_lod2.dpm [new file with mode: 0644]
models/monsters/wyvern_lod2.dpm.framegroups [new file with mode: 0644]
qcsrc/client/csqcmodel_hooks.qc
qcsrc/client/csqcmodel_hooks.qh
qcsrc/common/mapobjects/models.qc
qcsrc/common/mapobjects/subs.qc

diff --git a/models/monsters/golem_lod1.dpm b/models/monsters/golem_lod1.dpm
new file mode 100644 (file)
index 0000000..be4d08d
Binary files /dev/null and b/models/monsters/golem_lod1.dpm differ
diff --git a/models/monsters/golem_lod1.dpm.framegroups b/models/monsters/golem_lod1.dpm.framegroups
new file mode 100644 (file)
index 0000000..c6fa58f
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+Generated framegroups file for golem
+Used by DarkPlaces to simulate frame groups in DPM models.
+*/
+
+1 21 5 1 // golem idle
+22 61 30 1 // golem run
+83 21 30 1 // golem runangry
+104 36 30 1 // golem melee01
+140 36 30 1 // golem melee02
+176 61 30 1 // golem melee03
+237 61 30 1 // golem melee04
+298 21 30 0 // golem hit01
+319 21 30 0 // golem hit02
+340 21 30 0 // golem hit03
+361 21 30 0 // golem hit04
+382 61 30 0 // golem hithard
+443 101 30 0 // golem enrage
+544 61 30 0 // golem death01
+605 2 30 0 // golem dead01
+607 36 30 0 // golem death02
+643 2 30 0 // golem dead01
+645 46 30 0 // golem deathback
+691 2 30 0 // golem deadback
+693 2 30 0 // golem dead01
+695 2 30 0 // golem dead01
+697 2 30 0 // golem dead01
+699 2 30 0 // golem dead01
+701 2 30 0 // golem dead01
diff --git a/models/monsters/golem_lod2.dpm b/models/monsters/golem_lod2.dpm
new file mode 100644 (file)
index 0000000..45eced3
Binary files /dev/null and b/models/monsters/golem_lod2.dpm differ
diff --git a/models/monsters/golem_lod2.dpm.framegroups b/models/monsters/golem_lod2.dpm.framegroups
new file mode 100644 (file)
index 0000000..c6fa58f
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+Generated framegroups file for golem
+Used by DarkPlaces to simulate frame groups in DPM models.
+*/
+
+1 21 5 1 // golem idle
+22 61 30 1 // golem run
+83 21 30 1 // golem runangry
+104 36 30 1 // golem melee01
+140 36 30 1 // golem melee02
+176 61 30 1 // golem melee03
+237 61 30 1 // golem melee04
+298 21 30 0 // golem hit01
+319 21 30 0 // golem hit02
+340 21 30 0 // golem hit03
+361 21 30 0 // golem hit04
+382 61 30 0 // golem hithard
+443 101 30 0 // golem enrage
+544 61 30 0 // golem death01
+605 2 30 0 // golem dead01
+607 36 30 0 // golem death02
+643 2 30 0 // golem dead01
+645 46 30 0 // golem deathback
+691 2 30 0 // golem deadback
+693 2 30 0 // golem dead01
+695 2 30 0 // golem dead01
+697 2 30 0 // golem dead01
+699 2 30 0 // golem dead01
+701 2 30 0 // golem dead01
diff --git a/models/monsters/nanomage_lod1.dpm b/models/monsters/nanomage_lod1.dpm
new file mode 100644 (file)
index 0000000..ff13d64
Binary files /dev/null and b/models/monsters/nanomage_lod1.dpm differ
diff --git a/models/monsters/nanomage_lod1.dpm.framegroups b/models/monsters/nanomage_lod1.dpm.framegroups
new file mode 100644 (file)
index 0000000..9042da1
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+Generated framegroups file for nanomage
+Used by DarkPlaces to simulate frame groups in DPM models.
+*/
+
+1 61 12 1 // nanomage idle
+62 9 10 1 // nanomage run
+71 71 30 0 // nanomage attack01
+142 43 30 0 // nanomage attack02
+185 61 30 0 // nanomage attack03
+246 101 30 0 // nanomage attack04
+347 11 30 0 // nanomage pain01
+358 16 30 0 // nanomage pain02
+374 31 30 0 // nanomage pain03
+405 86 30 0 // nanomage death01
+491 56 30 0 // nanomage death02
+547 2 1 0 // nanomage dead01
+549 2 1 0 // nanomage dead02
diff --git a/models/monsters/nanomage_lod2.dpm b/models/monsters/nanomage_lod2.dpm
new file mode 100644 (file)
index 0000000..7d8f94e
Binary files /dev/null and b/models/monsters/nanomage_lod2.dpm differ
diff --git a/models/monsters/nanomage_lod2.dpm.framegroups b/models/monsters/nanomage_lod2.dpm.framegroups
new file mode 100644 (file)
index 0000000..9042da1
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+Generated framegroups file for nanomage
+Used by DarkPlaces to simulate frame groups in DPM models.
+*/
+
+1 61 12 1 // nanomage idle
+62 9 10 1 // nanomage run
+71 71 30 0 // nanomage attack01
+142 43 30 0 // nanomage attack02
+185 61 30 0 // nanomage attack03
+246 101 30 0 // nanomage attack04
+347 11 30 0 // nanomage pain01
+358 16 30 0 // nanomage pain02
+374 31 30 0 // nanomage pain03
+405 86 30 0 // nanomage death01
+491 56 30 0 // nanomage death02
+547 2 1 0 // nanomage dead01
+549 2 1 0 // nanomage dead02
diff --git a/models/monsters/spider_lod1.dpm b/models/monsters/spider_lod1.dpm
new file mode 100644 (file)
index 0000000..02172e4
Binary files /dev/null and b/models/monsters/spider_lod1.dpm differ
diff --git a/models/monsters/spider_lod1.dpm.framegroups b/models/monsters/spider_lod1.dpm.framegroups
new file mode 100644 (file)
index 0000000..73d92e0
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+Generated framegroups file for spider
+Used by DarkPlaces to simulate frame groups in DPM models.
+*/
+
+1 51 30 0 // spider spiderbite
+52 51 30 0 // spider spiderdeath01
+103 51 30 0 // spider spiderdeath02
+154 11 30 0 // spider spiderfire01
+165 31 30 0 // spider spiderfire02
+196 51 5 1 // spider spideridle
+247 51 30 0 // spider spiderintimidate
+298 11 25 0 // spider spiderpain01
+309 11 25 0 // spider spiderpain02
+320 11 15 0 // spider spiderpain03
+331 101 30 1 // spider spiderwalkforward
+432 101 30 1 // spider spiderwalkforwardright
+533 101 30 1 // spider spiderwalkright
+634 101 30 1 // spider spiderwalkbackright
+735 101 30 1 // spider spiderwalkback
+836 101 30 1 // spider spiderwalkbackleft
+937 101 30 1 // spider spiderwalkleft
+1038 101 30 1 // spider spiderwalkforwardleft
diff --git a/models/monsters/spider_lod2.dpm b/models/monsters/spider_lod2.dpm
new file mode 100644 (file)
index 0000000..8de39d5
Binary files /dev/null and b/models/monsters/spider_lod2.dpm differ
diff --git a/models/monsters/spider_lod2.dpm.framegroups b/models/monsters/spider_lod2.dpm.framegroups
new file mode 100644 (file)
index 0000000..73d92e0
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+Generated framegroups file for spider
+Used by DarkPlaces to simulate frame groups in DPM models.
+*/
+
+1 51 30 0 // spider spiderbite
+52 51 30 0 // spider spiderdeath01
+103 51 30 0 // spider spiderdeath02
+154 11 30 0 // spider spiderfire01
+165 31 30 0 // spider spiderfire02
+196 51 5 1 // spider spideridle
+247 51 30 0 // spider spiderintimidate
+298 11 25 0 // spider spiderpain01
+309 11 25 0 // spider spiderpain02
+320 11 15 0 // spider spiderpain03
+331 101 30 1 // spider spiderwalkforward
+432 101 30 1 // spider spiderwalkforwardright
+533 101 30 1 // spider spiderwalkright
+634 101 30 1 // spider spiderwalkbackright
+735 101 30 1 // spider spiderwalkback
+836 101 30 1 // spider spiderwalkbackleft
+937 101 30 1 // spider spiderwalkleft
+1038 101 30 1 // spider spiderwalkforwardleft
diff --git a/models/monsters/wyvern_lod1.dpm b/models/monsters/wyvern_lod1.dpm
new file mode 100644 (file)
index 0000000..5559e41
Binary files /dev/null and b/models/monsters/wyvern_lod1.dpm differ
diff --git a/models/monsters/wyvern_lod1.dpm.framegroups b/models/monsters/wyvern_lod1.dpm.framegroups
new file mode 100644 (file)
index 0000000..0791d6f
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+Generated framegroups file for wyvern
+Used by DarkPlaces to simulate frame groups in DPM models.
+*/
+
+1 101 30 1 // wyvern idle
+102 101 30 1 // wyvern glide
+203 101 30 1 // wyvern fly
+304 26 30 0 // wyvern pain1
+330 26 30 0 // wyvern pain2
+356 51 30 0 // wyvern melee
+407 51 30 0 // wyvern fireball
+458 101 30 1 // wyvern dying
+559 26 30 0 // wyvern dead
diff --git a/models/monsters/wyvern_lod2.dpm b/models/monsters/wyvern_lod2.dpm
new file mode 100644 (file)
index 0000000..a8bd83c
Binary files /dev/null and b/models/monsters/wyvern_lod2.dpm differ
diff --git a/models/monsters/wyvern_lod2.dpm.framegroups b/models/monsters/wyvern_lod2.dpm.framegroups
new file mode 100644 (file)
index 0000000..0791d6f
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+Generated framegroups file for wyvern
+Used by DarkPlaces to simulate frame groups in DPM models.
+*/
+
+1 101 30 1 // wyvern idle
+102 101 30 1 // wyvern glide
+203 101 30 1 // wyvern fly
+304 26 30 0 // wyvern pain1
+330 26 30 0 // wyvern pain2
+356 51 30 0 // wyvern melee
+407 51 30 0 // wyvern fireball
+458 101 30 1 // wyvern dying
+559 26 30 0 // wyvern dead
index 121af1947a9b256ae2b4e0e7013ea4865db10898..0565c9d86630484edfb9f5a084e3798dab5f6e08 100644 (file)
 .int lodmodelindex0;
 .int lodmodelindex1;
 .int lodmodelindex2;
-void CSQCPlayer_LOD_Apply(entity this, bool isplayer)
+.float loddistance1;
+.float loddistance2;
+void CSQCModel_LOD_Apply(entity this, bool isplayer)
 {
        int detailreduction = ((isplayer) ? autocvar_cl_playerdetailreduction : autocvar_cl_modeldetailreduction);
 
        // LOD model loading
-       if(this.lodmodelindex0 != this.modelindex)
+       if(this.lodmodelindex0 != this.modelindex && this.lodmodelindex1 != this.modelindex && this.lodmodelindex2 != this.modelindex)
        {
                string modelname = this.model;
                string s;
@@ -48,7 +50,7 @@ void CSQCPlayer_LOD_Apply(entity this, bool isplayer)
                        precache_model(s);
                        _setmodel(this, s);
                        if(this.modelindex)
-                               this.lodmodelindex1 = this.modelindex;
+                               this.lodmodelindex2 = this.lodmodelindex1 = this.modelindex;
                }
 
                s = strcat(substring(modelname, 0, strlen(modelname)-4), "_lod2", substring(modelname, -4, 4));
@@ -77,11 +79,13 @@ void CSQCPlayer_LOD_Apply(entity this, bool isplayer)
        else
        {
                float distance = vlen(((isplayer) ? this.origin : NearestPointOnBox(this, view_origin)) - view_origin); // TODO: perhaps it should just use NearestPointOnBox all the time, player hitbox can potentially be huge
+               float dist1 = (this.loddistance1 > 0) ? this.loddistance1 : autocvar_cl_loddistance1;
+               float dist2 = (this.loddistance2 > 0) ? this.loddistance2 : autocvar_cl_loddistance2;
                float f = (distance * current_viewzoom + 100.0) * detailreduction;
                f *= 1.0 / bound(0.01, view_quality, 1);
-               if(f > autocvar_cl_loddistance2)
+               if(f > dist2)
                        this.modelindex = this.lodmodelindex2;
-               else if(f > autocvar_cl_loddistance1)
+               else if(f > dist1)
                        this.modelindex = this.lodmodelindex1;
                else
                        this.modelindex = this.lodmodelindex0;
@@ -669,7 +673,7 @@ void CSQCModel_Hook_PreDraw(entity this, bool isplayer)
        if((this.isplayermodel & ISPLAYER_MODEL) && this.drawmask) // this checks if it's a player MODEL!
        {
                CSQCPlayer_ModelAppearance_Apply(this, (this.isplayermodel & ISPLAYER_LOCAL));
-               CSQCPlayer_LOD_Apply(this, true);
+               CSQCModel_LOD_Apply(this, true);
 
                if(!isplayer)
                {
@@ -748,7 +752,7 @@ void CSQCModel_Hook_PreDraw(entity this, bool isplayer)
                }
        }
        else
-               CSQCPlayer_LOD_Apply(this, false);
+               CSQCModel_LOD_Apply(this, false);
 
        CSQCModel_AutoTagIndex_Apply(this);
 
index 165008ee940e76de7fd51ba1956c6057e566129f..d7ccc52133f84552bdb967076dffd9a190ebd23f 100644 (file)
@@ -48,4 +48,6 @@ const int MF_TRACER3 =  BIT(7);  // purple trail
 
 void CSQCModel_Effects_Apply(entity this);
 
+void CSQCModel_LOD_Apply(entity this, bool isplayer);
+
 void CSQCModel_Hook_PreDraw(entity this, bool isplayer);
index 85a8ab843620a151c774747bb3fd7001b0ff5386..f342ebb257bf4312b78801f376fa20751b088b8e 100644 (file)
@@ -1,5 +1,9 @@
 #include "models.qh"
 
+#ifdef CSQC
+       #include <client/csqcmodel_hooks.qh>
+#endif
+
 #ifdef SVQC
 #include <common/constants.qh>
 #include <common/mapobjects/bgmscript.qh>
@@ -69,13 +73,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)
@@ -151,42 +163,48 @@ bool g_clientmodel_genericsendentity(entity this, entity to, int sf)
        return true;
 }
 
-
-#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); \
+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;
+       SetBrushEntityModel(ent,true);
+       ent.use = g_model_setcolormaptoactivator;
+       InitializeEntity(ent, g_model_dropbyspawnflags, INITPRIO_DROPTOFLOOR);
+       if(!ent.solid) ent.solid = (sol);
        else if(ent.solid < 0) ent.solid = SOLID_NOT;
+}
 
-#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); \
+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;
+       SetBrushEntityModel(ent,true);
+       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.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.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_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_static)            { G_MODEL_INIT      (this, SOLID_BSP) } // DEPRECATED old alias name from some other game
+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;
@@ -243,30 +261,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);
 
@@ -343,10 +338,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;
                }
index 9c8eda61bb45f5232cd9fa6b50ca5904b8ba6678..31ffee064fb361df3522cb3586723a7a79242e25 100644 (file)
@@ -499,7 +499,7 @@ void LODmodel_attach(entity this)
                this.lodmodel1 = this.lodmodel2 = ""; // don't even initialize
        }
 
-       if(this.lodmodel1 != "")
+       if(this.lodmodel1 != "" && fexists(this.lodmodel1))
        {
                vector mi, ma;
                mi = this.mins;
@@ -509,7 +509,7 @@ void LODmodel_attach(entity this)
                _setmodel(this, this.lodmodel1);
                this.lodmodelindex1 = this.modelindex;
 
-               if(this.lodmodel2 != "")
+               if(this.lodmodel2 != "" && fexists(this.lodmodel2))
                {
                        precache_model(this.lodmodel2);
                        _setmodel(this, this.lodmodel2);