demo
git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@997 e016b1c5-ed68-44aa-a2f7-31cac88cffde
This commit is contained in:
@@ -127,6 +127,12 @@ void disconnect(int onlyclean, int async)
|
||||
conoutf("disconnected");
|
||||
cleanup = true;
|
||||
}
|
||||
else if(demoplayback)
|
||||
{
|
||||
// todo: additional cleanups
|
||||
cleanup = true;
|
||||
}
|
||||
|
||||
if(cleanup)
|
||||
{
|
||||
stop();
|
||||
|
||||
@@ -564,14 +564,14 @@ void flagmsg(int flag, int action)
|
||||
case SV_FLAGDROP:
|
||||
{
|
||||
playsound(S_FLAGDROP);
|
||||
if(f.actor==player1) conoutf("you lost the flag");
|
||||
if(f.actor==player1) conoutf("\f2you lost the flag");
|
||||
else conoutf("\f2%s lost %s flag", f.actor->name, (own ? "your" : "the enemy"));
|
||||
break;
|
||||
}
|
||||
case SV_FLAGRETURN:
|
||||
{
|
||||
playsound(S_FLAGRETURN);
|
||||
if(f.actor==player1) conoutf("you returned your flag");
|
||||
if(f.actor==player1) conoutf("\f2you returned your flag");
|
||||
else conoutf("\f2%s returned %s flag", f.actor->name, (own ? "your" : "the enemy"));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "cube.h"
|
||||
#include "bot/bot.h"
|
||||
|
||||
extern int democlientnum;
|
||||
extern bool c2sinit, senditemstoserver;
|
||||
extern string clientpassword;
|
||||
|
||||
@@ -40,6 +41,10 @@ void updatepos(playerent *d)
|
||||
if(fx<fy) d->o.y += dy<0 ? r-fy : -(r-fy); // push aside
|
||||
else d->o.x += dx<0 ? r-fx : -(r-fx);
|
||||
}
|
||||
}
|
||||
|
||||
void updatelagtime(playerent *d)
|
||||
{
|
||||
int lagtime = lastmillis-d->lastupdate;
|
||||
if(lagtime)
|
||||
{
|
||||
@@ -89,6 +94,7 @@ void parsepositions(ucharbuf &p)
|
||||
f >>= 3;
|
||||
d->onladder = f&1;
|
||||
if(!demoplayback) updatepos(d);
|
||||
updatelagtime(d);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -131,7 +137,7 @@ void parsemessages(int cn, playerent *d, ucharbuf &p)
|
||||
}
|
||||
|
||||
case SV_SOUND:
|
||||
playsound(getint(p), d ? &d->o : NULL);
|
||||
playsound(getint(p), !d || (demoplayback && cn == democlientnum) ? NULL : &d->o);
|
||||
break;
|
||||
|
||||
|
||||
@@ -272,7 +278,7 @@ void parsemessages(int cn, playerent *d, ucharbuf &p)
|
||||
conoutf("\f2%s suicided", d->name);
|
||||
act = d;
|
||||
}
|
||||
else if(actor==getclientnum())
|
||||
else if(actor==getclientnum() || (demoplayback && actor==democlientnum))
|
||||
{
|
||||
act = player1;
|
||||
int frags;
|
||||
@@ -553,6 +559,15 @@ void parsemessages(int cn, playerent *d, ucharbuf &p)
|
||||
break;
|
||||
|
||||
default:
|
||||
if(demoplayback) // filter demo messages
|
||||
{
|
||||
int size = msgsizelookup(type);
|
||||
if(size)
|
||||
{
|
||||
loopi(size) getint(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
neterr("type");
|
||||
return;
|
||||
}
|
||||
|
||||
+2
-2
@@ -400,7 +400,7 @@ void renderdoc(int x, int y)
|
||||
|
||||
if(ident->examples.length()) // examples
|
||||
{
|
||||
doclines.add(ident->examples.length() == 1 ? "Example:" : "Examples:");
|
||||
doclines.add(newstring(ident->examples.length() == 1 ? "Example:" : "Examples:"));
|
||||
loopvj(ident->examples)
|
||||
{
|
||||
cvector lines;
|
||||
@@ -413,7 +413,7 @@ void renderdoc(int x, int y)
|
||||
|
||||
if(ident->keys.length()) // default keys
|
||||
{
|
||||
doclines.add(ident->keys.length() == 1 ? "Default key:" : "Default keys:");
|
||||
doclines.add(newstring(ident->keys.length() == 1 ? "Default key:" : "Default keys:"));
|
||||
loopvj(ident->keys)
|
||||
{
|
||||
dockey &k = ident->keys[j];
|
||||
|
||||
+7
-1
@@ -306,7 +306,13 @@ int main(int argc, char **argv)
|
||||
else if(curtime<1) curtime = 1;
|
||||
|
||||
cleardlights();
|
||||
if(lastmillis) updateworld(curtime, lastmillis);
|
||||
|
||||
if(demoplayback && demopaused)
|
||||
{
|
||||
curtime = 0;
|
||||
millis = lastmillis;
|
||||
}
|
||||
else if(lastmillis) updateworld(curtime, lastmillis);
|
||||
|
||||
lastmillis += curtime;
|
||||
curmillis = millis;
|
||||
|
||||
@@ -433,6 +433,7 @@ void attack(bool on)
|
||||
{
|
||||
if(intermission) return;
|
||||
if(editmode) editdrag(on);
|
||||
else if(demoplayback && on) shiftdemoplayer(1);
|
||||
else if(player1->state==CS_DEAD) respawn();
|
||||
else player1->attacking = on;
|
||||
}
|
||||
@@ -440,7 +441,8 @@ void attack(bool on)
|
||||
void jumpn(bool on)
|
||||
{
|
||||
if(intermission) return;
|
||||
if(player1->state==CS_DEAD)
|
||||
if(demoplayback && on) demopaused = !demopaused;
|
||||
else if(player1->state==CS_DEAD)
|
||||
{
|
||||
if(on) respawn();
|
||||
}
|
||||
@@ -474,7 +476,7 @@ void mousemove(int dx, int dy)
|
||||
camera1->yaw += (dx/SENSF)*(sensitivity/(float)sensitivityscale);
|
||||
camera1->pitch -= (dy/SENSF)*(sensitivity/(float)sensitivityscale)*(invmouse ? -1 : 1);
|
||||
fixcamerarange();
|
||||
if(camera1!=player1 && player1->state!=CS_DEAD)
|
||||
if(camera1!=player1 && player1->state!=CS_DEAD && !demoplayback)
|
||||
{
|
||||
player1->yaw = camera1->yaw;
|
||||
player1->pitch = camera1->pitch;
|
||||
|
||||
@@ -225,6 +225,11 @@ extern void stop();
|
||||
extern void stopifrecording();
|
||||
extern void demodamage(int damage, vec &o);
|
||||
extern void demoblend(int damage);
|
||||
extern bool demopaused;
|
||||
extern playerent *demoplayer;
|
||||
extern void shiftdemoplayer(int i);
|
||||
extern bool localdemoplayer1st();
|
||||
extern int demomillis();
|
||||
|
||||
// physics
|
||||
extern float raycube(const vec &o, const vec &ray, vec &surface);
|
||||
|
||||
+31
-2
@@ -228,7 +228,36 @@ COMMAND(trypitch, ARG_1INT);
|
||||
|
||||
void recomputecamera()
|
||||
{
|
||||
if(editmode || player1->state!=CS_DEAD)
|
||||
if(demoplayback && demoplayer)
|
||||
{
|
||||
static physent democam;
|
||||
extern bool firstpersondemo;
|
||||
|
||||
if(demoplayer == player1 && firstpersondemo)
|
||||
{
|
||||
democam = *(physent *)player1;
|
||||
}
|
||||
else
|
||||
{
|
||||
static playerent *lastplayer = NULL;
|
||||
if(lastplayer != demoplayer)
|
||||
{
|
||||
lastplayer = demoplayer;
|
||||
democam = *(physent *)demoplayer;
|
||||
democam.type = ENT_CAMERA;
|
||||
democam.reset();
|
||||
democam.roll = 0;
|
||||
democam.move = -1;
|
||||
camera1 = &democam;
|
||||
}
|
||||
democam.o = demoplayer->o;
|
||||
democam.o.x -= (float)(cosf(RAD*(demoplayer->yaw-90)))*demoplayer->radius*1.5f;
|
||||
democam.o.y -= (float)(sinf(RAD*(demoplayer->yaw-90)))*demoplayer->radius*1.5f;
|
||||
democam.o.z += demoplayer->eyeheight/3.0f;
|
||||
if(!demopaused) democam.yaw = demoplayer->yaw;
|
||||
}
|
||||
}
|
||||
else if(editmode || player1->state!=CS_DEAD)
|
||||
{
|
||||
camera1 = player1;
|
||||
}
|
||||
@@ -505,7 +534,7 @@ void drawhudgun(int w, int h, float aspect, int farplane)
|
||||
gluPerspective((float)100.0f*h/w, aspect, 0.3f, farplane); // fov fixed at 100°
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
if(player1->state!=CS_DEAD) renderhudgun();
|
||||
if(player1->state!=CS_DEAD && (!demoplayback || localdemoplayer1st())) renderhudgun();
|
||||
rendermenumdl();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
|
||||
+41
-22
@@ -50,6 +50,7 @@ VARP(radarres, 1, 64, 1024);
|
||||
VARP(radarentsize, 1, 4, 64);
|
||||
VARP(hidectfhud, 0, 0, 1);
|
||||
VARP(hideteamhud, 0, 0, 1);
|
||||
VARP(hidedemohud, 0, 0, 1);
|
||||
|
||||
VAR(showmap, 0, 0, 1);
|
||||
|
||||
@@ -259,31 +260,35 @@ void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwat
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
bool demo3rd = demoplayback && !localdemoplayer1st();
|
||||
playerent *targetplayer = playerincrosshair();
|
||||
bool didteamkill = player1->lastteamkill && player1->lastteamkill + 5000 > lastmillis;
|
||||
bool menuvisible = rendermenu();
|
||||
|
||||
if(player1->state==CS_ALIVE && !player1->reloading && !didteamkill && !menuvisible)
|
||||
{
|
||||
bool drawteamwarning = targetplayer ? (isteam(targetplayer->team, player1->team) && targetplayer->state!=CS_DEAD) : false;
|
||||
if(player1->gunselect==GUN_SNIPER && scoped) drawscope();
|
||||
else if((player1->gunselect!=GUN_SNIPER || drawteamwarning)) drawcrosshair(drawteamwarning);
|
||||
}
|
||||
|
||||
drawequipicons();
|
||||
|
||||
if(!hideradar)
|
||||
{
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
drawradar(w, h);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
}
|
||||
|
||||
char *infostr = editinfo();
|
||||
bool command = getcurcommand() ? true : false;
|
||||
if(command) rendercommand(20, 1570);
|
||||
else if(infostr) draw_text(infostr, 20, 1570);
|
||||
else if(targetplayer) draw_text(targetplayer->name, 20, 1570);
|
||||
|
||||
if(!demo3rd)
|
||||
{
|
||||
if(player1->state==CS_ALIVE && !player1->reloading && !didteamkill && !menuvisible)
|
||||
{
|
||||
bool drawteamwarning = targetplayer ? (isteam(targetplayer->team, player1->team) && targetplayer->state!=CS_DEAD) : false;
|
||||
if(player1->gunselect==GUN_SNIPER && scoped) drawscope();
|
||||
else if((player1->gunselect!=GUN_SNIPER || drawteamwarning)) drawcrosshair(drawteamwarning);
|
||||
}
|
||||
|
||||
drawequipicons();
|
||||
|
||||
if(!hideradar)
|
||||
{
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
drawradar(w, h);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
}
|
||||
|
||||
char *infostr = editinfo();
|
||||
if(command) rendercommand(20, 1570);
|
||||
else if(infostr) draw_text(infostr, 20, 1570);
|
||||
else if(targetplayer) draw_text(targetplayer->name, 20, 1570);
|
||||
}
|
||||
|
||||
glLoadIdentity();
|
||||
glOrtho(0, VIRTW*2, VIRTH*2, 0, -1, 1);
|
||||
@@ -299,8 +304,22 @@ void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwat
|
||||
draw_textf("wvt %d", left, top+240, curvert);
|
||||
draw_textf("evt %d", left, top+320, xtraverts);
|
||||
}
|
||||
|
||||
if(!hidedemohud && demoplayback)
|
||||
{
|
||||
const int left = VIRTW*2/80, top = VIRTH*2*3/4;
|
||||
int dmillis = demomillis();
|
||||
s_sprintfd(time)("%d:%02d", dmillis/1000/60, dmillis/1000%60);
|
||||
s_sprintfd(following)("\f0Following %s", demoplayer->name);
|
||||
|
||||
if(player1->state==CS_ALIVE)
|
||||
draw_text(time, left, top-FONTH);
|
||||
draw_text(following, left, top);
|
||||
draw_text("jump to pause", left, top+2*FONTH);
|
||||
draw_text("attack to change view", left, top+3*FONTH);
|
||||
draw_text("reload for slow-motion", left, top+4*FONTH);
|
||||
}
|
||||
|
||||
if(player1->state==CS_ALIVE && !demo3rd)
|
||||
{
|
||||
glLoadIdentity();
|
||||
glOrtho(0, VIRTW/2, VIRTH/2, 0, -1, 1);
|
||||
|
||||
@@ -259,6 +259,6 @@ void renderclients()
|
||||
{
|
||||
playerent *d;
|
||||
loopv(players) if((d = players[i]) && (!demoplayback || i!=democlientnum)) renderclient(d);
|
||||
if(player1->state==CS_DEAD || (reflecting && !refracting)) renderclient(player1);
|
||||
if(player1->state==CS_DEAD || (reflecting && !refracting) || (demoplayback && !localdemoplayer1st())) renderclient(player1);
|
||||
}
|
||||
|
||||
|
||||
+87
-19
@@ -33,6 +33,7 @@ void stop()
|
||||
demoloading = false;
|
||||
loopv(playerhistory) zapplayer(playerhistory[i]);
|
||||
playerhistory.setsize(0);
|
||||
setvar("gamespeed", 100);
|
||||
}
|
||||
|
||||
void stopifrecording() { if(demorecording) stop(); }
|
||||
@@ -116,9 +117,10 @@ void loadgamerest()
|
||||
int nplayers = gzgeti();
|
||||
loopi(nplayers) if(!gzget())
|
||||
{
|
||||
playerent *d = getclient(i);
|
||||
playerent *d = newclient(i);
|
||||
ASSERT(d);
|
||||
gzread(f, d, sizeof(playerent));
|
||||
d->lastaction = d->lastpain = lastmillis;
|
||||
}
|
||||
|
||||
conoutf("savegame restored");
|
||||
@@ -132,6 +134,8 @@ int playbacktime = 0;
|
||||
int ddamage, bdamage;
|
||||
vec dorig;
|
||||
|
||||
int demomillis() { return lastmillis-starttime; }
|
||||
|
||||
void record(char *name)
|
||||
{
|
||||
int cn = getclientnum();
|
||||
@@ -160,14 +164,32 @@ void incomingdemodata(int chan, uchar *buf, int len, bool extras)
|
||||
{
|
||||
gzput(player1->gunselect);
|
||||
gzput(player1->lastattackgun);
|
||||
gzputi(player1->lastaction-starttime);
|
||||
gzputi(player1->akimbolastaction[0]-starttime);
|
||||
gzputi(player1->akimbolastaction[1]-starttime);
|
||||
gzputi(player1->gunwait);
|
||||
gzputi(player1->lastaction-starttime);
|
||||
gzputi(player1->lastanimswitchtime[0]);
|
||||
gzputi(player1->lastanimswitchtime[1]);
|
||||
loopi(NUMGUNS) { gzput(player1->ammo[i]); gzput(player1->mag[i]); }
|
||||
gzput(player1->akimbo ? 1 : 0 | (player1->reloading ? 1 : 0) << 1 | (player1->weaponchanging ? 1 : 0) << 2);
|
||||
switch(player1->gunselect) // AH,demo
|
||||
{
|
||||
case GUN_GRENADE:
|
||||
gzputi(player1->thrownademillis); // AH,demo
|
||||
gzput(player1->inhandnade ? 1 : 0); // AH,demo
|
||||
break;
|
||||
case GUN_PISTOL:
|
||||
if(player1->akimbo)
|
||||
{
|
||||
gzputi(player1->akimbolastaction[0]-starttime);
|
||||
gzputi(player1->akimbolastaction[1]-starttime);
|
||||
}
|
||||
break;
|
||||
case GUN_SNIPER:
|
||||
gzput(scoped ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
|
||||
gzputi(player1->health);
|
||||
gzputi(player1->armour);
|
||||
//gzput(player1->armourtype);
|
||||
loopi(NUMGUNS) gzput(player1->ammo[i]);
|
||||
gzput(player1->state);
|
||||
gzputi(bdamage);
|
||||
bdamage = 0;
|
||||
@@ -187,8 +209,7 @@ void demo(char *name)
|
||||
void stopreset()
|
||||
{
|
||||
conoutf("demo stopped (%d msec elapsed)", lastmillis-starttime);
|
||||
stop();
|
||||
loopv(players) zapplayer(players[i]);
|
||||
player1 = newplayerent();
|
||||
disconnect(0, 0);
|
||||
}
|
||||
|
||||
@@ -205,15 +226,36 @@ void readdemotime()
|
||||
playbacktime = scaletime(playbacktime);
|
||||
}
|
||||
|
||||
bool demopaused = false;
|
||||
void togglepause() { demopaused = !demopaused; }
|
||||
|
||||
playerent *demoplayer = player1;
|
||||
bool firstpersondemo = true;
|
||||
bool localdemoplayer1st() { return demoplayback && demoplayer == player1 && firstpersondemo; }
|
||||
|
||||
void shiftdemoplayer(int i)
|
||||
{
|
||||
if(!i) return;
|
||||
if(demoplayer == player1)
|
||||
{
|
||||
firstpersondemo = !firstpersondemo;
|
||||
if(!firstpersondemo) return;
|
||||
}
|
||||
vector<playerent *> plrs;
|
||||
loopv(players) if(players[i] != NULL) plrs.add(players[i]);
|
||||
int cur = plrs.find(demoplayer);
|
||||
if(cur >= 0) demoplayer = plrs[(cur+i) % plrs.length()];
|
||||
}
|
||||
|
||||
void startdemo()
|
||||
{
|
||||
democlientnum = gzgeti();
|
||||
demoplayback = true;
|
||||
starttime = lastmillis;
|
||||
conoutf("now playing demo");
|
||||
dynent *d = newclient(democlientnum);
|
||||
ASSERT(d);
|
||||
*d = *player1;
|
||||
while(democlientnum>=players.length()) players.add(NULL);
|
||||
players[democlientnum] = player1;
|
||||
demoplayer = player1;
|
||||
readdemotime();
|
||||
}
|
||||
|
||||
@@ -261,19 +303,40 @@ void demoplaybackstep()
|
||||
{
|
||||
target->gunselect = gzget();
|
||||
target->lastattackgun = gzget();
|
||||
target->lastaction = scaletime(gzgeti());
|
||||
target->akimbolastaction[0] = scaletime(gzgeti());
|
||||
target->akimbolastaction[1] = scaletime(gzgeti());
|
||||
target->gunwait = gzgeti();
|
||||
target->lastaction = scaletime(gzgeti());
|
||||
target->lastanimswitchtime[0] = scaletime(gzgeti()); // AH,demo
|
||||
target->lastanimswitchtime[1] = scaletime(gzgeti()); // AH,demo
|
||||
loopi(NUMGUNS) { target->ammo[i] = gzget(); target->mag[i] = gzget(); } // AH,demo
|
||||
uchar flags = gzget();
|
||||
target->akimbo = flags&1 ? true : false; // AH, demo
|
||||
target->reloading = (flags>>1)&1 ? true : false; // AH,demo
|
||||
target->weaponchanging = (flags>>2)&1 ? true : false; //
|
||||
switch(target->gunselect)
|
||||
{
|
||||
case GUN_GRENADE:
|
||||
target->thrownademillis = scaletime(gzgeti()); // AH,demo
|
||||
target->inhandnade = gzget() ? (bounceent *)1 : NULL; // AH,demo
|
||||
break;
|
||||
case GUN_PISTOL:
|
||||
if(player1->akimbo)
|
||||
{
|
||||
target->akimbolastaction[0] = scaletime(gzgeti());
|
||||
target->akimbolastaction[1] = scaletime(gzgeti());
|
||||
}
|
||||
break;
|
||||
case GUN_SNIPER:
|
||||
scoped = gzget() ? true : false;
|
||||
break;
|
||||
}
|
||||
|
||||
target->health = gzgeti();
|
||||
target->armour = gzgeti();
|
||||
//target->armourtype = gzget();
|
||||
loopi(NUMGUNS) target->ammo[i] = gzget();
|
||||
target->state = gzget();
|
||||
target->lastmove = playbacktime;
|
||||
if((bdamage = gzgeti())) damageblend(bdamage);
|
||||
if((ddamage = gzgeti())) { gzgetv(dorig); particle_splash(3, ddamage, 1000, dorig); }
|
||||
if((ddamage = gzgeti())) { gzgetv(dorig); particle_splash(3, ddamage, 1000, dorig); };
|
||||
// FIXME: set more client state here
|
||||
target->lastmove = playbacktime;
|
||||
}
|
||||
|
||||
// insert latest copy of player into history
|
||||
@@ -295,13 +358,16 @@ void demoplaybackstep()
|
||||
|
||||
if(demoplayback)
|
||||
{
|
||||
if(playerhistory.length()) memcpy(player1, playerhistory.last(), sizeof(playerent));
|
||||
int itime = lastmillis-demodelaymsec;
|
||||
loopvrev(playerhistory) if(playerhistory[i]->lastupdate<itime) // find 2 positions in history that surround interpolation time point
|
||||
{
|
||||
playerent *a = playerhistory[i];
|
||||
playerent *b = a;
|
||||
if(i+1<playerhistory.length()) b = playerhistory[i+1];
|
||||
memcpy(player1, b, sizeof(playerent));
|
||||
player1->o = b->o;
|
||||
player1->yaw = b->yaw;
|
||||
player1->pitch = b->pitch;
|
||||
if(a!=b) // interpolate pos & angles
|
||||
{
|
||||
dynent *c = b;
|
||||
@@ -332,6 +398,8 @@ void stopn() { if(demoplayback) stopreset(); else stop(); conoutf("demo stopped"
|
||||
COMMAND(record, ARG_1STR);
|
||||
COMMAND(demo, ARG_1STR);
|
||||
COMMANDN(stop, stopn, ARG_NONE);
|
||||
COMMANDN(demopause, togglepause, ARG_NONE);
|
||||
COMMANDN(demoplayer, shiftdemoplayer, ARG_1INT);
|
||||
|
||||
COMMAND(savegame, ARG_1STR);
|
||||
COMMAND(loadgame, ARG_1STR);
|
||||
|
||||
@@ -203,7 +203,12 @@ void updatevol()
|
||||
}
|
||||
}
|
||||
|
||||
void playsoundc(int n) { addmsg(SV_SOUND, "i", n); playsound(n); }
|
||||
void playsoundc(int n)
|
||||
{
|
||||
if(demoplayback) return;
|
||||
addmsg(SV_SOUND, "i", n);
|
||||
playsound(n);
|
||||
}
|
||||
|
||||
int soundsatonce = 0, lastsoundmillis = 0;
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ COMMAND(setscope, ARG_1INT);
|
||||
|
||||
void reload(playerent *d)
|
||||
{
|
||||
if(demoplayback) { setvar("gamespeed", getvar("gamespeed") != 100 ? 100 : 35); return; }
|
||||
if(!d || d->state!=CS_ALIVE || d->reloading || d->weaponchanging) return;
|
||||
if(!reloadable_gun(d->gunselect) || d->ammo[d->gunselect]<=0) return;
|
||||
if(d->mag[d->gunselect] >= (has_akimbo(d) ? 2 : 1)*guns[d->gunselect].magsize) return;
|
||||
@@ -500,7 +501,7 @@ bounceent *new_nade(playerent *d, int millis = 0)
|
||||
|
||||
d->inhandnade = p;
|
||||
d->thrownademillis = 0;
|
||||
playsound(S_GRENADEPULL, (d==player1 ? NULL : &d->o));
|
||||
if(d==player1 && !demoplayback) playsoundc(S_GRENADEPULL);
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -514,7 +515,7 @@ void explode_nade(bounceent *i)
|
||||
|
||||
void shootv(int gun, vec &from, vec &to, playerent *d, bool local, int nademillis) // create visual effect from a shot
|
||||
{
|
||||
playsound(guns[gun].sound, d==player1 ? NULL : &d->o);
|
||||
if(guns[gun].sound) playsound(guns[gun].sound, d==player1 ? NULL : &d->o);
|
||||
switch(gun)
|
||||
{
|
||||
case GUN_KNIFE:
|
||||
@@ -543,7 +544,7 @@ void shootv(int gun, vec &from, vec &to, playerent *d, bool local, int nademilli
|
||||
|
||||
case GUN_GRENADE:
|
||||
{
|
||||
if(d!=player1)
|
||||
if(d!=player1 || demoplayback)
|
||||
{
|
||||
bounceent *p = new_nade(d, nademillis);
|
||||
throw_nade(d, to, p);
|
||||
|
||||
Reference in New Issue
Block a user