X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fclient%2Fcsqcmodel_hooks.qc;h=121af1947a9b256ae2b4e0e7013ea4865db10898;hb=561489d21c9053b7103c6604c362aa24ee5c7916;hp=f0ff55e8ab56a09021c507bfd963d6a72a19a3dd;hpb=93ea212d8c60d8c3e897f8b5b613ee112f88aa37;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/client/csqcmodel_hooks.qc b/qcsrc/client/csqcmodel_hooks.qc index f0ff55e8a..121af1947 100644 --- a/qcsrc/client/csqcmodel_hooks.qc +++ b/qcsrc/client/csqcmodel_hooks.qc @@ -1,19 +1,17 @@ #include "csqcmodel_hooks.qh" -#include "autocvars.qh" -#include "main.qh" + #include -#include -#include "player_skeleton.qh" -#include "weapons/projectile.qh" +#include +#include #include +#include +#include #include #include #include #include #include #include -#include -#include #include #include #include @@ -25,8 +23,10 @@ .int lodmodelindex0; .int lodmodelindex1; .int lodmodelindex2; -void CSQCPlayer_LOD_Apply(entity this) +void CSQCPlayer_LOD_Apply(entity this, bool isplayer) { + int detailreduction = ((isplayer) ? autocvar_cl_playerdetailreduction : autocvar_cl_modeldetailreduction); + // LOD model loading if(this.lodmodelindex0 != this.modelindex) { @@ -65,19 +65,19 @@ void CSQCPlayer_LOD_Apply(entity this) } // 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 f = (distance * current_viewzoom + 100.0) * detailreduction; f *= 1.0 / bound(0.01, view_quality, 1); if(f > autocvar_cl_loddistance2) this.modelindex = this.lodmodelindex2; @@ -236,18 +236,35 @@ void CSQCPlayer_ModelAppearance_Apply(entity this, bool islocalplayer) 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) @@ -282,11 +299,23 @@ void CSQCPlayer_ModelAppearance_Apply(entity this, bool islocalplayer) 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; } @@ -301,7 +330,7 @@ void CSQCPlayer_ModelAppearance_Apply(entity this, bool islocalplayer) // GLOWMOD AND DEATH FADING if(this.colormap > 0) - this.glowmod = colormapPaletteColor(((this.colormap >= 1024) ? this.colormap : entcs_GetClientColors(this.colormap - 1)) & 0x0F, true) * 2; + this.glowmod = colormapPaletteColor(((this.colormap >= 1024) ? this.colormap : entcs_GetClientColors(this.colormap - 1)) & 0x0F, true); else this.glowmod = '1 1 1'; @@ -319,6 +348,10 @@ void CSQCPlayer_ModelAppearance_Apply(entity this, bool islocalplayer) } } + // don't let the engine increase player's glowmod + if (autocvar_r_hdr_glowintensity > 1) + this.glowmod /= autocvar_r_hdr_glowintensity; + //printf("CSQCPlayer_ModelAppearance_Apply(): state = %s, colormap = %f, glowmod = %s\n", (this.csqcmodel_isdead ? "DEAD" : "ALIVE"), this.colormap, vtos(this.glowmod)); } @@ -424,7 +457,7 @@ void CSQCModel_AutoTagIndex_Apply(entity this) } // recursive predraw call to fix issues with forcemodels and LOD if bone indexes mismatch - if(this.tag_entity.classname == "csqcmodel") + if(this.tag_entity.classname == "ENT_CLIENT_MODEL") { CSQCModel_Hook_PreDraw(this.tag_entity, (this.tag_entity.isplayermodel & ISPLAYER_CLIENT)); } @@ -620,7 +653,7 @@ void CSQCModel_Hook_PreDraw(entity this, bool isplayer) return; this.csqcmodel_predraw_run = framecount; - if(!this.modelindex || this.model == "null" || this.alpha < 0) + if(!this.modelindex || this.model == "null") { this.drawmask = 0; if(this.snd_looping > 0) @@ -636,7 +669,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); + CSQCPlayer_LOD_Apply(this, true); if(!isplayer) { @@ -676,6 +709,8 @@ void CSQCModel_Hook_PreDraw(entity this, bool isplayer) tracebox(this.origin + '0 0 1', this.mins, this.maxs, this.origin - '0 0 4', MOVE_NORMAL, this); if(trace_startsolid || trace_fraction < 1) onground = 1; + // predicted clients handle smoothing in the prediction code + this.origin = CSQCModel_ApplyStairSmoothing(this, onground, this.origin); } animdecide_load_if_needed(this); animdecide_setimplicitstate(this, onground); @@ -712,6 +747,8 @@ void CSQCModel_Hook_PreDraw(entity this, bool isplayer) } } } + else + CSQCPlayer_LOD_Apply(this, false); CSQCModel_AutoTagIndex_Apply(this); @@ -738,6 +775,7 @@ void CSQCModel_Hook_PostUpdate(entity this, bool isnew, bool isplayer, bool islo 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))