summaryrefslogtreecommitdiff
path: root/src/fpsgame/render.cpp
diff options
context:
space:
mode:
authorxolatile2025-08-06 22:54:55 +0200
committerxolatile2025-08-06 22:54:55 +0200
commit0a1172b75f571685c264a8b9d8ee224bbf11381f (patch)
treed041fdc68a60f0ebb48a3852bbcce6d9432f83d5 /src/fpsgame/render.cpp
parentaffde05dc07a94643f1fd2751b2b441f57f73d7d (diff)
downloadxolatile-badassbug-0a1172b75f571685c264a8b9d8ee224bbf11381f.tar.xz
xolatile-badassbug-0a1172b75f571685c264a8b9d8ee224bbf11381f.tar.zst
Please do not hate me, it makes sense...
Diffstat (limited to 'src/fpsgame/render.cpp')
-rw-r--r--src/fpsgame/render.cpp224
1 files changed, 65 insertions, 159 deletions
diff --git a/src/fpsgame/render.cpp b/src/fpsgame/render.cpp
index f35daec..dacdcd9 100644
--- a/src/fpsgame/render.cpp
+++ b/src/fpsgame/render.cpp
@@ -3,21 +3,16 @@
struct spawninfo { const extentity *e; float weight; };
extern float gatherspawninfos(dynent *d, int tag, vector<spawninfo> &spawninfos);
-namespace game
-{
+namespace game {
vector<fpsent *> bestplayers;
vector<const char *> bestteams;
-
VARP(ragdoll, 0, 1, 1);
VARP(ragdollmillis, 0, 10000, 300000);
VARP(ragdollfade, 0, 1000, 300000);
VARP(playermodel, 0, 0, 0);
VARP(hidedead, 0, 0, 2);
-
vector<fpsent *> ragdolls;
-
- void saveragdoll(fpsent *d)
- {
+ void saveragdoll(fpsent *d) {
if(!d->ragdoll || !ragdollmillis || (!ragdollfade && lastmillis > d->lastpain + ragdollmillis)) return;
fpsent *r = new fpsent(*d);
r->lastupdate = ragdollfade && lastmillis > d->lastpain + max(ragdollmillis - ragdollfade, 0) ? lastmillis - max(ragdollmillis - ragdollfade, 0) : d->lastpain;
@@ -28,49 +23,38 @@ namespace game
ragdolls.add(r);
d->ragdoll = NULL;
}
-
- void clearragdolls()
- {
+ void clearragdolls() {
ragdolls.deletecontents();
}
-
- void moveragdolls()
- {
- loopv(ragdolls)
- {
+ void moveragdolls() {
+ loopv(ragdolls) {
fpsent *d = ragdolls[i];
- if(lastmillis > d->lastupdate + ragdollmillis)
- {
+ if(lastmillis > d->lastupdate + ragdollmillis) {
delete ragdolls.remove(i--);
continue;
}
moveragdoll(d);
}
}
-
- static const playermodelinfo playermodels[1] =
- {
- { "mrfixit", "mrfixit/blue", "mrfixit/red", "mrfixit/hudguns", NULL, "mrfixit/horns", { "mrfixit/armor/blue", "mrfixit/armor/green", "mrfixit/armor/yellow" }, "mrfixit", "mrfixit_blue", "mrfixit_red", true },
+ static const playermodelinfo playermodels[1] = {
+ {
+ "mrfixit", "mrfixit/blue", "mrfixit/red", "mrfixit/hudguns", NULL, "mrfixit/horns", {
+ "mrfixit/armor/blue", "mrfixit/armor/green", "mrfixit/armor/yellow" },
+ "mrfixit", "mrfixit_blue", "mrfixit_red", true },
};
-
- const playermodelinfo *getplayermodelinfo(int n)
- {
+ const playermodelinfo *getplayermodelinfo(int n) {
(void) n;
return &playermodels[0];
}
-
- const playermodelinfo &getplayermodelinfo(fpsent *d)
- {
+ const playermodelinfo &getplayermodelinfo(fpsent *d) {
+ (void) d;
const playermodelinfo *mdl = getplayermodelinfo(0);
if(!mdl) mdl = getplayermodelinfo(playermodel);
return *mdl;
}
-
- void preloadplayermodel()
- {
+ void preloadplayermodel() {
const playermodelinfo *mdl = getplayermodelinfo(0);
- if(m_teammode)
- {
+ if(m_teammode) {
preloadmodel(mdl->blueteam);
preloadmodel(mdl->redteam);
}
@@ -79,23 +63,18 @@ namespace game
if(mdl->quad) preloadmodel(mdl->quad);
loopj(3) if(mdl->armour[j]) preloadmodel(mdl->armour[j]);
}
-
VAR(testquad, 0, 0, 1);
VAR(testarmour, 0, 0, 1);
VAR(testteam, 0, 0, 3);
-
- void renderplayer(fpsent *d, const playermodelinfo &mdl, int team, float fade, bool mainpass)
- {
+ void renderplayer(fpsent *d, const playermodelinfo &mdl, int team, float fade, bool mainpass) {
int lastaction = d->lastaction, hold = mdl.vwep || d->gunselect==GUN_PISTOL ? 0 : (ANIM_HOLD1+d->gunselect)|ANIM_LOOP, attack = ANIM_ATTACK1+d->gunselect, delay = mdl.vwep ? 300 : guns[d->gunselect].attackdelay+50;
- if(intermission && d->state!=CS_DEAD)
- {
+ if(intermission && d->state!=CS_DEAD) {
lastaction = 0;
hold = attack = ANIM_LOSE|ANIM_LOOP;
delay = 0;
if(m_teammode ? bestteams.htfind(d->team)>=0 : bestplayers.find(d)>=0) hold = attack = ANIM_WIN|ANIM_LOOP;
}
- else if(d->state==CS_ALIVE && d->lasttaunt && lastmillis-d->lasttaunt<1000 && lastmillis-d->lastaction>delay)
- {
+ else if(d->state==CS_ALIVE && d->lasttaunt && lastmillis-d->lasttaunt<1000 && lastmillis-d->lastaction>delay) {
lastaction = d->lasttaunt;
hold = attack = ANIM_TAUNT;
delay = 1000;
@@ -103,94 +82,75 @@ namespace game
modelattach a[5];
static const char * const vweps[] = {"vwep/fist", "vwep/shotg", "vwep/chaing", "vwep/rocket", "vwep/rifle", "vwep/gl", "vwep/pistol"};
int ai = 0;
- if((!mdl.vwep || d->gunselect!=GUN_FIST) && d->gunselect<=GUN_PISTOL)
- {
+ if((!mdl.vwep || d->gunselect!=GUN_FIST) && d->gunselect<=GUN_PISTOL) {
int vanim = ANIM_VWEP_IDLE|ANIM_LOOP, vtime = 0;
- if(lastaction && d->lastattackgun==d->gunselect && lastmillis < lastaction + delay)
- {
+ if(lastaction && d->lastattackgun==d->gunselect && lastmillis < lastaction + delay) {
vanim = ANIM_VWEP_SHOOT;
vtime = lastaction;
}
a[ai++] = modelattach("tag_weapon", mdl.vwep ? mdl.vwep : vweps[d->gunselect], vanim, vtime);
}
- if(d->state==CS_ALIVE)
- {
+ if(d->state==CS_ALIVE) {
if((testquad || d->quadmillis) && mdl.quad)
a[ai++] = modelattach("tag_powerup", mdl.quad, ANIM_POWERUP|ANIM_LOOP, 0);
- if(testarmour || d->armour)
- {
+ if(testarmour || d->armour) {
int type = clamp(d->armourtype, (int)A_BLUE, (int)A_YELLOW);
if(mdl.armour[type])
a[ai++] = modelattach("tag_shield", mdl.armour[type], ANIM_SHIELD|ANIM_LOOP, 0);
}
}
- if(mainpass)
- {
+ if(mainpass) {
d->muzzle = vec(-1, -1, -1);
a[ai++] = modelattach("tag_muzzle", &d->muzzle);
}
const char *mdlname = mdl.ffa;
- switch(testteam ? testteam-1 : team)
- {
+ switch(testteam ? testteam-1 : team) {
case 1: mdlname = mdl.blueteam; break;
case 2: mdlname = mdl.redteam; break;
}
renderclient(d, mdlname, a[0].tag ? a : NULL, hold, attack, delay, lastaction, intermission && d->state!=CS_DEAD ? 0 : d->lastpain, fade, ragdoll && mdl.ragdoll);
}
-
VARP(teamskins, 0, 0, 1);
-
VARP(statusicons, 0, 1, 1);
-
- void renderstatusicons(fpsent *d, int team, float yoffset)///TODO
- {
+ void renderstatusicons(fpsent *d, int team, float yoffset) {///TODO {
vec p = d->abovehead().madd(camup, yoffset);
int icons = 0;
const itemstat &boost = itemstats[I_BOOST-I_SHELLS];
- if(statusicons && (d->state==CS_ALIVE || d->state==CS_LAGGED))
- {
+ if(statusicons && (d->state==CS_ALIVE || d->state==CS_LAGGED)) {
if(d->quadmillis) icons++;
if(d->maxhealth>100) icons += (min(d->maxhealth, boost.max) - 100 + boost.info-1) / boost.info;
if(d->armour>0 && d->armourtype>=A_GREEN && !m_noitems) icons++;
}
if(icons) concatstring(d->info, " ");
particle_text(p, d->info, PART_TEXT, 1, team ? (team==1 ? 0x6496FF : 0xFF4B19) : 0x1EC850, 2.0f, 0, icons);
- if(icons)
- {
+ if(icons) {
float tw, th;
text_boundsf(d->info, tw, th);
float offset = (tw - icons*th)/2;
- if(d->armour>0 && d->armourtype>=A_GREEN && !m_noitems)
- {
+ if(d->armour>0 && d->armourtype>=A_GREEN && !m_noitems) {
int icon = itemstats[(d->armourtype==A_YELLOW ? I_YELLOWARMOUR : I_GREENARMOUR)-I_SHELLS].icon;
particle_texticon(p, icon%4, icon/4, offset, PART_TEXT_ICON, 1, 0xFFFFFF, 2.0f);
offset += th;
}
- for(int i = 100; i < min(d->maxhealth, boost.max); i += boost.info)
- {
+ for(int i = 100; i < min(d->maxhealth, boost.max); i += boost.info) {
particle_texticon(p, boost.icon%4, boost.icon/4, offset, PART_TEXT_ICON, 1, 0xFFFFFF, 2.0f);
offset += th;
}
- if(d->quadmillis)
- {
+ if(d->quadmillis) {
int icon = itemstats[I_QUAD-I_SHELLS].icon;
particle_texticon(p, icon%4, icon/4, offset, PART_TEXT_ICON, 1, 0xFFFFFF, 2.0f);
offset += th;
}
}
}
-
VARP(statusbars, 0, 1, 2);
FVARP(statusbarscale, 0, 1, 2);
-
- float renderstatusbars(fpsent *d, int team)///TODO
- {
+ float renderstatusbars(fpsent *d, int team) {///TODO {
if(!statusbars || m_insta || (player1->state==CS_SPECTATOR ? statusbars <= 1 : team != 1) || (d->state!=CS_ALIVE && d->state!=CS_LAGGED)) return 0;
vec p = d->abovehead().msub(camdir, 50/80.0f).msub(camup, 2.0f);
float offset = 0;
float scale = statusbarscale;
- if(d->armour > 0)
- {
+ if(d->armour > 0) {
int limit = d->armourtype==A_YELLOW ? 200 : (d->armourtype==A_GREEN ? 100 : 50);
int color = d->armourtype==A_YELLOW ? 0xFFC040 : (d->armourtype==A_GREEN ? 0x008C00 : 0x0B5899);
float size = scale*sqrtf(max(d->armour, limit)/100.0f);
@@ -205,48 +165,36 @@ namespace game
particle_meter(vec(p).madd(camup, offset), fill, PART_METER, 1, color, 0, size);
return offset;
}
-
- void rendergame(bool mainpass)
- {
+ void rendergame(bool mainpass) {
if(mainpass) ai::render();
-
- if(intermission)
- {
+ if(intermission) {
bestteams.shrink(0);
bestplayers.shrink(0);
if(m_teammode) getbestteams(bestteams);
else getbestplayers(bestplayers);
}
-
startmodelbatches();
-
fpsent *exclude = isthirdperson() ? NULL : followingplayer();
- loopv(players)
- {
+ loopv(players) {
fpsent *d = players[i];
if(d == player1 || d->state==CS_SPECTATOR || d->state==CS_SPAWNING || d->lifesequence < 0 || d == exclude || (d->state==CS_DEAD && hidedead)) continue;
int team = 0;
if(teamskins || m_teammode) team = isteam(player1->team, d->team) ? 1 : 2;
renderplayer(d, getplayermodelinfo(d), team, 1, mainpass);
-
vec dir = vec(d->o).sub(camera1->o);
float dist = dir.magnitude();
dir.div(dist);
- if(d->state!=CS_EDITING && raycube(camera1->o, dir, dist, 0) < dist)
- {
+ if(d->state!=CS_EDITING && raycube(camera1->o, dir, dist, 0) < dist) {
d->info[0] = '\0';
continue;
}
-
copystring(d->info, colorname(d));
- if(d->state!=CS_DEAD)
- {
+ if(d->state!=CS_DEAD) {
float offset = renderstatusbars(d, team);
renderstatusicons(d, team, offset);
}
}
- loopv(ragdolls)
- {
+ loopv(ragdolls) {
fpsent *d = ragdolls[i];
int team = 0;
if(teamskins || m_teammode) team = isteam(player1->team, d->team) ? 1 : 2;
@@ -259,42 +207,32 @@ namespace game
entities::renderentities();
renderbouncers();
renderprojectiles();
-
endmodelbatches();
}
-
VARP(hudgun, 0, 1, 1);
VARP(hudgunsway, 0, 1, 1);
VARP(teamhudguns, 0, 1, 1);
VARP(chainsawhudgun, 0, 1, 1);
VAR(testhudgun, 0, 0, 1);
-
FVAR(swaystep, 1, 35.0f, 100);
FVAR(swayside, 0, 0.04f, 1);
FVAR(swayup, -1, 0.05f, 1);
-
float swayfade = 0, swayspeed = 0, swaydist = 0;
vec swaydir(0, 0, 0);
-
- void swayhudgun(int curtime)
- {
+ void swayhudgun(int curtime) {
fpsent *d = hudplayer();
- if(d->state != CS_SPECTATOR)
- {
- if(d->physstate >= PHYS_SLOPE)
- {
+ if(d->state != CS_SPECTATOR) {
+ if(d->physstate >= PHYS_SLOPE) {
swayspeed = min(sqrtf(d->vel.x*d->vel.x + d->vel.y*d->vel.y), d->maxspeed);
swaydist += swayspeed*curtime/1000.0f;
swaydist = fmod(swaydist, 2*swaystep);
swayfade = 1;
}
- else if(swayfade > 0)
- {
+ else if(swayfade > 0) {
swaydist += swayspeed*swayfade*curtime/1000.0f;
swaydist = fmod(swaydist, 2*swaystep);
swayfade -= 0.5f*(curtime*d->maxspeed)/(swaystep*1000.0f);
}
-
float k = pow(0.7f, curtime/10.0f);
swaydir.mul(k);
vec vel(d->vel);
@@ -302,18 +240,12 @@ namespace game
swaydir.add(vec(vel).mul((1-k)/(15*max(vel.magnitude(), d->maxspeed))));
}
}
-
- struct hudent : dynent
- {
+ struct hudent : dynent {
hudent() { type = ENT_CAMERA; }
} guninterp;
-
SVARP(hudgunsdir, "");
-
- void drawhudmodel(fpsent *d, int anim, float speed = 0, int base = 0)
- {
+ void drawhudmodel(fpsent *d, int anim, float speed = 0, int base = 0) {
if(d->gunselect>GUN_PISTOL) return;
-
vec sway;
vecfromyawpitch(d->yaw, 0, 0, 1, sway);
float steps = swaydist/swaystep*M_PI;
@@ -323,8 +255,7 @@ namespace game
if(!hudgunsway) sway = d->o;
#if 0
- if(player1->state!=CS_DEAD && player1->quadmillis)
- {
+ if(player1->state!=CS_DEAD && player1->quadmillis) {
float t = 0.5f + 0.5f*sinf(2*M_PI*lastmillis/1000.0f);
color.y = color.y*(1-t) + t;
}
@@ -339,8 +270,7 @@ namespace game
d->muzzle = vec(-1, -1, -1);
a[0] = modelattach("tag_muzzle", &d->muzzle);
dynent *interp = NULL;
- if(d->gunselect==GUN_FIST && chainsawhudgun)
- {
+ if(d->gunselect==GUN_FIST && chainsawhudgun) {
anim |= ANIM_LOOP;
base = 0;
interp = &guninterp;
@@ -348,37 +278,26 @@ namespace game
rendermodel(NULL, gunname, anim, sway, testhudgun ? 0 : d->yaw+90, testhudgun ? 0 : d->pitch, MDL_LIGHT|MDL_HUD, interp, a, base, (int)ceil(speed));
if(d->muzzle.x >= 0) d->muzzle = calcavatarpos(d->muzzle, 12);
}
-
- void drawhudgun()
- {
+ void drawhudgun() {
fpsent *d = hudplayer();
- if(d->state==CS_SPECTATOR || d->state==CS_EDITING || !hudgun || editmode)
- {
+ if(d->state==CS_SPECTATOR || d->state==CS_EDITING || !hudgun || editmode) {
d->muzzle = player1->muzzle = vec(-1, -1, -1);
return;
}
-
int rtime = guns[d->gunselect].attackdelay;
- if(d->lastaction && d->lastattackgun==d->gunselect && lastmillis-d->lastaction<rtime)
- {
+ if(d->lastaction && d->lastattackgun==d->gunselect && lastmillis-d->lastaction<rtime) {
drawhudmodel(d, ANIM_GUN_SHOOT|ANIM_SETSPEED, rtime/17.0f, d->lastaction);
}
- else
- {
+ else {
drawhudmodel(d, ANIM_GUN_IDLE|ANIM_LOOP);
}
}
-
- void renderavatar()
- {
+ void renderavatar() {
drawhudgun();
}
-
- void renderplayerpreview(int model, int team, int weap)
- {
+ void renderplayerpreview(int model, int team, int weap) {
static fpsent *previewent = NULL;
- if(!previewent)
- {
+ if(!previewent) {
previewent = new fpsent;
previewent->light.color = vec(1, 1, 1);
previewent->light.dir = vec(0, -1, 2).normalize();
@@ -394,18 +313,15 @@ namespace game
if(!mdlinfo) return;
renderplayer(previewent, *mdlinfo, team >= 0 && team <= 2 ? team : 0, 1, false);
}
-
- vec hudgunorigin(int gun, const vec &from, const vec &to, fpsent *d)
- {
+ vec hudgunorigin(int gun, const vec &from, const vec &to, fpsent *d) {
+ (void) gun;
if(d->muzzle.x >= 0) return d->muzzle;
vec offset(from);
- if(d!=hudplayer() || isthirdperson())
- {
+ if(d!=hudplayer() || isthirdperson()) {
vec front, right;
vecfromyawpitch(d->yaw, d->pitch, 1, 0, front);
offset.add(front.mul(d->radius));
- if(d->type!=ENT_AI)
- {
+ if(d->type!=ENT_AI) {
offset.z += (d->aboveeye + d->eyeheight)*0.75f - d->eyeheight;
vecfromyawpitch(d->yaw, 0, 0, -1, right);
offset.add(right.mul(0.5f*d->radius));
@@ -414,30 +330,24 @@ namespace game
return offset;
}
offset.add(vec(to).sub(from).normalize().mul(2));
- if(hudgun)
- {
+ if(hudgun) {
offset.sub(vec(camup).mul(1.0f));
offset.add(vec(camright).mul(0.8f));
}
else offset.sub(vec(camup).mul(0.8f));
return offset;
}
-
- void preloadweapons()
- {
+ void preloadweapons() {
const playermodelinfo &mdl = getplayermodelinfo(player1);
- loopi(NUMGUNS)
- {
+ loopi(NUMGUNS) {
const char *file = guns[i].file;
if(!file) continue;
string fname;
- if((m_teammode || teamskins) && teamhudguns)
- {
+ if((m_teammode || teamskins) && teamhudguns) {
formatstring(fname, "%s/%s/blue", hudgunsdir[0] ? hudgunsdir : mdl.hudguns, file);
preloadmodel(fname);
}
- else
- {
+ else {
formatstring(fname, "%s/%s", hudgunsdir[0] ? hudgunsdir : mdl.hudguns, file);
preloadmodel(fname);
}
@@ -445,14 +355,10 @@ namespace game
preloadmodel(fname);
}
}
-
- void preloadsounds()
- {
+ void preloadsounds() {
for(int i = S_JUMP; i <= S_HIT; i++) preloadsound(i);
}
-
- void preload()
- {
+ void preload() {
if(hudgun) preloadweapons();
preloadbouncers();
preloadplayermodel();