diff --git a/docs/reference.xml b/docs/reference.xml
index e40be05e..159992c7 100644
--- a/docs/reference.xml
+++ b/docs/reference.xml
@@ -3884,6 +3884,11 @@ Output:
+
+ Turns on/off the display of the hudgun when spectating a player in first-person view. Works in demo mode as well.
+
+
+
Turns on/off display of FPS/rendering statistics on the HUD.
diff --git a/source/src/clients2c.cpp b/source/src/clients2c.cpp
index d2d8f786..6915e29c 100644
--- a/source/src/clients2c.cpp
+++ b/source/src/clients2c.cpp
@@ -676,11 +676,14 @@ void parsemessages(int cn, playerent *d, ucharbuf &p)
loopk(3) from[k] = s->o.v[k];
if(gun==GUN_SHOTGUN) createrays(from, to);
s->lastaction = lastmillis;
+ s->weaponchanging = 0;
s->mag[gun]--;
if(s->weapons[gun])
{
s->lastattackweapon = s->weapons[gun];
+ s->weapons[gun]->gunwait = s->weapons[gun]->info.attackdelay;
s->weapons[gun]->attackfx(from, to, -1);
+ s->weapons[gun]->reloading = 0;
}
s->pstatshots[gun]++; //NEW
break;
@@ -694,8 +697,13 @@ void parsemessages(int cn, playerent *d, ucharbuf &p)
int nademillis = getint(p);
if(!d) break;
d->lastaction = lastmillis;
+ d->weaponchanging = 0;
d->lastattackweapon = d->weapons[GUN_GRENADE];
- if(d->weapons[GUN_GRENADE]) d->weapons[GUN_GRENADE]->attackfx(from, to, nademillis);
+ if(d->weapons[GUN_GRENADE])
+ {
+ d->weapons[GUN_GRENADE]->attackfx(from, to, nademillis);
+ d->weapons[GUN_GRENADE]->reloading = 0;
+ }
if(d!=player1) d->pstatshots[GUN_GRENADE]++; //NEW
break;
}
@@ -708,6 +716,8 @@ void parsemessages(int cn, playerent *d, ucharbuf &p)
int bullets = magsize(gun)-p->mag[gun];
p->ammo[gun] -= bullets;
p->mag[gun] += bullets;
+ p->weapons[gun]->reloading = lastmillis;
+ p->weaponchanging = 0;
break;
}
diff --git a/source/src/hudgun.h b/source/src/hudgun.h
index a8269d47..76ce22d4 100644
--- a/source/src/hudgun.h
+++ b/source/src/hudgun.h
@@ -15,17 +15,17 @@ struct weaponmove
weaponmove() : k_rot(0), kick(0), anim(0), basetime(0) { pos.x = pos.y = pos.z = 0.0f; }
- void calcmove(vec aimdir, int lastaction)
+ void calcmove(vec aimdir, int lastaction, playerent *p)
{
kick = k_rot = 0.0f;
- pos = player1->o;
+ pos = p->o;
if(!nosway)
{
float k = pow(0.7f, (lastmillis-lastsway)/10.0f);
swaydir.mul(k);
- vec dv(player1->vel);
- dv.mul((1-k)/max(player1->vel.magnitude(), player1->maxspeed));
+ vec dv(p->vel);
+ dv.mul((1-k)/max(p->vel.magnitude(), p->maxspeed));
dv.x *= 1.5f;
dv.y *= 1.5f;
dv.z *= 0.4f;
@@ -33,22 +33,22 @@ struct weaponmove
pos.add(swaydir);
}
- if(player1->onfloor || player1->onladder || player1->inwater) swaymillis += lastmillis-lastsway;
+ if(p->onfloor || p->onladder || p->inwater) swaymillis += lastmillis-lastsway;
lastsway = lastmillis;
- if(player1->weaponchanging)
+ if(p->weaponchanging)
{
anim = ANIM_GUN_RELOAD;
- basetime = player1->weaponchanging;
- float progress = clamp((lastmillis - player1->weaponchanging)/(float)weapon::weaponchangetime, 0.0f, 1.0f);
+ basetime = p->weaponchanging;
+ float progress = clamp((lastmillis - p->weaponchanging)/(float)weapon::weaponchangetime, 0.0f, 1.0f);
k_rot = -90*sinf(progress*M_PI);
}
- else if(player1->weaponsel->reloading)
+ else if(p->weaponsel->reloading)
{
anim = ANIM_GUN_RELOAD;
- basetime = player1->weaponsel->reloading;
- float reloadtime = (float)player1->weaponsel->info.reloadtime,
- progress = clamp((lastmillis - player1->weaponsel->reloading)/reloadtime, 0.0f, clamp(1.0f - (player1->lastaction + player1->weaponsel->gunwait - lastmillis)/reloadtime, 0.5f, 1.0f));
+ basetime = p->weaponsel->reloading;
+ float reloadtime = (float)p->weaponsel->info.reloadtime,
+ progress = clamp((lastmillis - p->weaponsel->reloading)/reloadtime, 0.0f, clamp(1.0f - (p->lastaction + p->weaponsel->gunwait - lastmillis)/reloadtime, 0.5f, 1.0f));
k_rot = -90*sinf(progress*M_PI);
}
else
@@ -57,24 +57,24 @@ struct weaponmove
basetime = lastaction;
int timediff = lastmillis-lastaction,
- animtime = min(player1->weaponsel->gunwait, (int)player1->weaponsel->info.attackdelay);
+ animtime = min(p->weaponsel->gunwait, (int)p->weaponsel->info.attackdelay);
vec sway = aimdir;
float progress = 0.0f;
float k_back = 0.0f;
- if(player1->weaponsel==player1->lastattackweapon)
+ if(p->weaponsel==p->lastattackweapon)
{
progress = max(0.0f, min(1.0f, timediff/(float)animtime));
// f(x) = -sin(x-1.5)^3
kick = -sinf(pow((1.5f*progress)-1.5f,3));
- if(player1->crouching) kick *= 0.75f;
- if(player1->lastaction) anim = player1->weaponsel->modelanim();
+ if(p->crouching) kick *= 0.75f;
+ if(p->lastaction) anim = p->weaponsel->modelanim();
}
- if(player1->weaponsel->info.mdl_kick_rot || player1->weaponsel->info.mdl_kick_back)
+ if(p->weaponsel->info.mdl_kick_rot || p->weaponsel->info.mdl_kick_back)
{
- k_rot = player1->weaponsel->info.mdl_kick_rot*kick;
- k_back = player1->weaponsel->info.mdl_kick_back*kick/10;
+ k_rot = p->weaponsel->info.mdl_kick_rot*kick;
+ k_back = p->weaponsel->info.mdl_kick_back*kick/10;
}
if(nosway) sway.x = sway.y = sway.z = 0;
@@ -83,7 +83,7 @@ struct weaponmove
float swayspeed = sinf((float)swaymillis/swayspeeddiv)/(swaymovediv/10.0f);
float swayupspeed = cosf((float)swaymillis/swayupspeeddiv)/(swayupmovediv/10.0f);
- float plspeed = min(1.0f, sqrtf(player1->vel.x*player1->vel.x + player1->vel.y*player1->vel.y));
+ float plspeed = min(1.0f, sqrtf(p->vel.x*p->vel.x + p->vel.y*p->vel.y));
swayspeed *= plspeed/2;
swayupspeed *= plspeed/2;
@@ -98,7 +98,7 @@ struct weaponmove
sway.y *= swayspeed;
sway.z *= swayupspeed;
- if(player1->crouching) sway.mul(0.75f);
+ if(p->crouching) sway.mul(0.75f);
}
pos.x -= aimdir.x*k_back+sway.x;
diff --git a/source/src/rendergl.cpp b/source/src/rendergl.cpp
index 68005a3c..c39dc9f8 100644
--- a/source/src/rendergl.cpp
+++ b/source/src/rendergl.cpp
@@ -808,6 +808,7 @@ void cleanupgl()
int xtraverts;
VARP(hudgun, 0, 1, 1);
+VARP(spechudgun, 0, 1, 1);
void setperspective(float fovy, float aspect, float nearplane, float farplane)
{
@@ -832,7 +833,7 @@ void drawhudgun(int w, int h, float aspect, int farplane)
{
sethudgunperspective(true);
- if(hudgun && !player1->isspectating() && camera1->type==ENT_PLAYER)
+ if(hudgun && (spechudgun || !player1->isspectating()) && camera1->type==ENT_PLAYER)
{
playerent *p = (playerent *)camera1;
if(p->state==CS_ALIVE) p->weaponsel->renderhudmodel();
diff --git a/source/src/renderparticles.cpp b/source/src/renderparticles.cpp
index 5458e306..2611d2a4 100644
--- a/source/src/renderparticles.cpp
+++ b/source/src/renderparticles.cpp
@@ -645,8 +645,9 @@ VARP(bulletairsounddestrad, 0, 8, 1000);
void addshotline(dynent *pl, const vec &from, const vec &to)
{
- if(pl == player1 || !shotlinettl || !shotline) return;
- bool fx = shotlinettl > 0 && (player1->isspectating() || !multiplayer(false)); // allow fx only in spect mode and locally
+ bool spectating = player1->isspectating();
+ if(pl == player1 || (spectating && camera1->type==ENT_PLAYER) || !shotlinettl || !shotline) return;
+ bool fx = shotlinettl > 0 && (spectating || !multiplayer(false)); // allow fx only in spect mode and locally
if(rnd(3) && !fx) return; // show all shotlines when fx enabled
int start = (camera1->o.dist(to) <= 10.0f) ? 8 : 5;
diff --git a/source/src/weapon.cpp b/source/src/weapon.cpp
index 41ee8c78..5e692373 100644
--- a/source/src/weapon.cpp
+++ b/source/src/weapon.cpp
@@ -716,7 +716,7 @@ void weapon::sendshoot(vec &from, vec &to, int millis)
addmsg(SV_SHOOT, "ri2i3iv", millis, owner->weaponsel->type,
(int)(to.x*DMF), (int)(to.y*DMF), (int)(to.z*DMF),
hits.length(), hits.length()*sizeof(hitmsg)/sizeof(int), hits.getbuf());
- player1->pstatshots[player1->weaponsel->type]++; //NEW
+ player1->pstatshots[player1->weaponsel->type]++; //NEW
}
bool weapon::modelattacking()
@@ -808,15 +808,16 @@ VARP(righthanded, 0, 1, 1); // flowtron 20090727
void weapon::renderhudmodel(int lastaction, int index)
{
+ playerent *p = owner;
vec unitv;
- float dist = worldpos.dist(owner->o, unitv);
+ float dist = worldpos.dist(p->o, unitv);
unitv.div(dist);
- weaponmove wm;
- if(!intermission) wm.calcmove(unitv, lastaction);
+ weaponmove wm;
+ if(!intermission) wm.calcmove(unitv, p->lastaction, p);
defformatstring(path)("weapons/%s", info.modelname);
- bool emit = (wm.anim&ANIM_INDEX)==ANIM_GUN_SHOOT && (lastmillis - lastaction) < flashtime();
- rendermodel(path, wm.anim|ANIM_DYNALLOC|(righthanded==index ? ANIM_MIRROR : 0)|(emit ? ANIM_PARTICLE : 0), 0, -1, wm.pos, player1->yaw+90, player1->pitch+wm.k_rot, 40.0f, wm.basetime, NULL, NULL, 1.28f);
+ bool emit = (wm.anim&ANIM_INDEX)==ANIM_GUN_SHOOT && (lastmillis - p->lastaction) < flashtime();
+ rendermodel(path, wm.anim|ANIM_DYNALLOC|(righthanded==index ? ANIM_MIRROR : 0)|(emit ? ANIM_PARTICLE : 0), 0, -1, wm.pos, p->yaw+90, p->pitch+wm.k_rot, 40.0f, wm.basetime, NULL, NULL, 1.28f);
}
void weapon::updatetimers(int millis)
@@ -922,7 +923,7 @@ void grenadeent::activate(const vec &from, const vec &to)
(int)(to.x*DMF), (int)(to.y*DMF), (int)(to.z*DMF),
0);
audiomgr.playsound(S_GRENADEPULL, SP_HIGH);
- player1->pstatshots[GUN_GRENADE]++; //NEW
+ player1->pstatshots[GUN_GRENADE]++; //NEW
}
}
@@ -1132,18 +1133,18 @@ bool gun::attack(vec &targ)
if(!mag)
{
audiomgr.playsoundc(S_NOAMMO);
- gunwait += 250;
- owner->lastattackweapon = NULL;
+ gunwait += 250;
+ owner->lastattackweapon = NULL;
shots = 0;
checkautoreload();
return false;
}
owner->lastattackweapon = this;
- shots++;
- if(type==GUN_SUBGUN) flag4subgunDMGalt = !flag4subgunDMGalt;
+ shots++;
+ if(type==GUN_SUBGUN) flag4subgunDMGalt = !flag4subgunDMGalt;
- if(!info.isauto) owner->attacking = false;
+ if(!info.isauto) owner->attacking = false;
vec from = owner->o;
vec to = targ;
@@ -1532,9 +1533,9 @@ void checkakimbo()
// transfer ammo to pistol
p.mag = min((int)p.info.magsize, max(a.mag, p.mag));
p.ammo = max(p.ammo, p.ammo);
- // fix akimbo magcontent
- a.mag = 0;
- a.ammo = 0;
+ // fix akimbo magcontent
+ a.mag = 0;
+ a.ammo = 0;
if(player1->weaponsel->type==GUN_AKIMBO)
{
@@ -1560,7 +1561,7 @@ void checkakimbo()
default: break;
}
}
- if(player1->state != CS_DEAD) audiomgr.playsoundc(S_AKIMBOOUT);
+ if(player1->state != CS_DEAD) audiomgr.playsoundc(S_AKIMBOOUT);
}
}
}