.int lodmodelindex0;
.int lodmodelindex1;
.int lodmodelindex2;
-void CSQCPlayer_LOD_Apply(entity this)
+.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;
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));
}
// apply LOD
- if(autocvar_cl_playerdetailreduction <= 0)
+ if(detailreduction <= 0)
{
- if(autocvar_cl_playerdetailreduction <= -2)
+ if(detailreduction <= -2)
this.modelindex = this.lodmodelindex2;
- else if(autocvar_cl_playerdetailreduction <= -1)
+ else if(detailreduction <= -1)
this.modelindex = this.lodmodelindex1;
else
this.modelindex = this.lodmodelindex0;
}
else
{
- float distance = vlen(this.origin - view_origin);
- float f = (distance * current_viewzoom + 100.0) * autocvar_cl_playerdetailreduction;
+ 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;
if(MUTATOR_CALLHOOK(ForcePlayercolors_Skip, this, islocalplayer))
goto skipforcecolors;
+ bool forceplayercolors_enabled = false;
+ #define fpc autocvar_cl_forceplayercolors
+ if (gametype.m_1v1)
+ {
+ if ((myteam != NUM_SPECTATOR) && (fpc == 1 || fpc == 2 || fpc == 3 || fpc == 5))
+ forceplayercolors_enabled = true;
+ }
+ else if (teamplay)
+ {
+ if ((team_count == 2) && (myteam != NUM_SPECTATOR) && (fpc == 2 || fpc == 4 || fpc == 5))
+ forceplayercolors_enabled = true;
+ }
+ else
+ {
+ if (fpc == 1 || fpc == 2)
+ forceplayercolors_enabled = true;
+ }
+
// forceplayercolors too
if(teamplay)
{
// own team's color is never forced
- int forcecolor_friend = 0;
- int forcecolor_enemy = 0;
+ int forcecolor_friend = 0, forcecolor_enemy = 0;
entity tm;
if(autocvar_cl_forcemyplayercolors)
forcecolor_friend = 1024 + autocvar_cl_forcemyplayercolors;
- if((autocvar_cl_forceplayercolors == 2 && team_count == 2)
- || (autocvar_cl_forceplayercolors == 3 && IS_GAMETYPE(DUEL)))
+
+ if(forceplayercolors_enabled)
forcecolor_enemy = 1024 + autocvar__cl_color;
if(forcecolor_enemy && !forcecolor_friend)
this.colormap = forcecolor_enemy;
}
}
- else
+ else // if(!teamplay)
{
if(autocvar_cl_forcemyplayercolors && islocalplayer)
this.colormap = 1024 + autocvar_cl_forcemyplayercolors;
- else if(autocvar_cl_forceplayercolors)
+ else if (autocvar_cl_forceuniqueplayercolors && !islocalplayer && !gametype.m_1v1)
+ {
+ // Assign each enemy unique colors
+ // pick colors from 0 to 14 since 15 is the rainbow color
+ // pl01 0 1, pl02 1 2, ..., pl14 13 14, pl15 14 0
+ // pl16 0 2, pl17 1 3, ..., pl29 13 0, pl30 14 1
+ int num = this.entnum - 1;
+ int c1 = num % 15;
+ int q = floor(num / 15);
+ int c2 = (c1 + 1 + q) % 15;
+ this.colormap = 1024 + (c1 << 4) + c2;
+ }
+ else if(forceplayercolors_enabled)
this.colormap = player_localnum + 1;
}
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);
+ CSQCModel_LOD_Apply(this, true);
if(!isplayer)
{
}
}
}
+ else
+ CSQCModel_LOD_Apply(this, false);
CSQCModel_AutoTagIndex_Apply(this);
bool is_playermodel = (substring(this.model, 0, 14) == "models/player/" || substring(this.model, 0, 17) == "models/ok_player/" ||
(substring(this.model, 0, 16) == "models/monsters/" && (this.isplayermodel & BIT(1))));
this.isplayermodel = BITSET(this.isplayermodel, ISPLAYER_MODEL, is_playermodel);
+ this.csqcmodel_isdead = false; // workaround for dead players who become a spectator
// save values set by server
if((this.isplayermodel & ISPLAYER_MODEL))