Run clang-format on the entire codebase
FossilOrigin-Name: 0a0d4f91558171cf85e108964a5fed9e1c390a8343e9d2eda086c9c20fde7d1a
This commit is contained in:
parent
b8e3744913
commit
f84e7f7c72
37 changed files with 9648 additions and 7254 deletions
|
@ -1,4 +1,5 @@
|
|||
// loading and saving of savegames & demos, dumps the spawn state of all mapents, the full state of all dynents (monsters + player)
|
||||
// loading and saving of savegames & demos, dumps the spawn state of all
|
||||
// mapents, the full state of all dynents (monsters + player)
|
||||
|
||||
#include "cube.h"
|
||||
|
||||
|
@ -13,137 +14,209 @@ int democlientnum = 0;
|
|||
|
||||
void startdemo();
|
||||
|
||||
void gzput(int i) { gzputc(f, i); };
|
||||
void gzputi(int i) { gzwrite(f, &i, sizeof(int)); };
|
||||
void gzputv(vec &v) { gzwrite(f, &v, sizeof(vec)); };
|
||||
|
||||
void gzcheck(int a, int b) { if(a!=b) fatal("savegame file corrupt (short)"); };
|
||||
int gzget() { char c = gzgetc(f); return c; };
|
||||
int gzgeti() { int i; gzcheck(gzread(f, &i, sizeof(int)), sizeof(int)); return i; };
|
||||
void gzgetv(vec &v) { gzcheck(gzread(f, &v, sizeof(vec)), sizeof(vec)); };
|
||||
|
||||
void stop()
|
||||
void
|
||||
gzput(int i)
|
||||
{
|
||||
if(f)
|
||||
{
|
||||
if(demorecording) gzputi(-1);
|
||||
gzclose(f);
|
||||
};
|
||||
f = NULL;
|
||||
demorecording = false;
|
||||
demoplayback = false;
|
||||
demoloading = false;
|
||||
loopv(playerhistory) zapdynent(playerhistory[i]);
|
||||
playerhistory.setsize(0);
|
||||
gzputc(f, i);
|
||||
};
|
||||
void
|
||||
gzputi(int i)
|
||||
{
|
||||
gzwrite(f, &i, sizeof(int));
|
||||
};
|
||||
void
|
||||
gzputv(vec &v)
|
||||
{
|
||||
gzwrite(f, &v, sizeof(vec));
|
||||
};
|
||||
|
||||
void stopifrecording() { if(demorecording) stop(); };
|
||||
|
||||
void savestate(char *fn)
|
||||
void
|
||||
gzcheck(int a, int b)
|
||||
{
|
||||
stop();
|
||||
f = gzopen(fn, "wb9");
|
||||
if(!f) { conoutf("could not write %s", fn); return; };
|
||||
gzwrite(f, (void *)"CUBESAVE", 8);
|
||||
gzputc(f, islittleendian);
|
||||
gzputi(SAVEGAMEVERSION);
|
||||
gzputi(sizeof(dynent));
|
||||
gzwrite(f, getclientmap(), _MAXDEFSTR);
|
||||
gzputi(gamemode);
|
||||
gzputi(ents.length());
|
||||
loopv(ents) gzputc(f, ents[i].spawned);
|
||||
gzwrite(f, player1, sizeof(dynent));
|
||||
dvector &monsters = getmonsters();
|
||||
gzputi(monsters.length());
|
||||
loopv(monsters) gzwrite(f, monsters[i], sizeof(dynent));
|
||||
gzputi(players.length());
|
||||
loopv(players)
|
||||
{
|
||||
gzput(players[i]==NULL);
|
||||
gzwrite(f, players[i], sizeof(dynent));
|
||||
};
|
||||
if (a != b)
|
||||
fatal("savegame file corrupt (short)");
|
||||
};
|
||||
int
|
||||
gzget()
|
||||
{
|
||||
char c = gzgetc(f);
|
||||
return c;
|
||||
};
|
||||
int
|
||||
gzgeti()
|
||||
{
|
||||
int i;
|
||||
gzcheck(gzread(f, &i, sizeof(int)), sizeof(int));
|
||||
return i;
|
||||
};
|
||||
void
|
||||
gzgetv(vec &v)
|
||||
{
|
||||
gzcheck(gzread(f, &v, sizeof(vec)), sizeof(vec));
|
||||
};
|
||||
|
||||
void savegame(char *name)
|
||||
void
|
||||
stop()
|
||||
{
|
||||
if(!m_classicsp) { conoutf("can only save classic sp games"); return; };
|
||||
sprintf_sd(fn)("savegames/%s.csgz", name);
|
||||
savestate(fn);
|
||||
stop();
|
||||
conoutf("wrote %s", fn);
|
||||
if (f) {
|
||||
if (demorecording)
|
||||
gzputi(-1);
|
||||
gzclose(f);
|
||||
};
|
||||
f = NULL;
|
||||
demorecording = false;
|
||||
demoplayback = false;
|
||||
demoloading = false;
|
||||
loopv(playerhistory) zapdynent(playerhistory[i]);
|
||||
playerhistory.setsize(0);
|
||||
};
|
||||
|
||||
void loadstate(char *fn)
|
||||
void
|
||||
stopifrecording()
|
||||
{
|
||||
stop();
|
||||
if(multiplayer()) return;
|
||||
f = gzopen(fn, "rb9");
|
||||
if(!f) { conoutf("could not open %s", fn); return; };
|
||||
|
||||
string buf;
|
||||
gzread(f, buf, 8);
|
||||
if(strncmp(buf, "CUBESAVE", 8)) goto out;
|
||||
if(gzgetc(f)!=islittleendian) goto out; // not supporting save->load accross incompatible architectures simpifies things a LOT
|
||||
if(gzgeti()!=SAVEGAMEVERSION || gzgeti()!=sizeof(dynent)) goto out;
|
||||
string mapname;
|
||||
gzread(f, mapname, _MAXDEFSTR);
|
||||
nextmode = gzgeti();
|
||||
changemap(mapname); // continue below once map has been loaded and client & server have updated
|
||||
return;
|
||||
out:
|
||||
conoutf("aborting: savegame/demo from a different version of cube or cpu architecture");
|
||||
stop();
|
||||
if (demorecording)
|
||||
stop();
|
||||
};
|
||||
|
||||
void loadgame(char *name)
|
||||
void
|
||||
savestate(char *fn)
|
||||
{
|
||||
sprintf_sd(fn)("savegames/%s.csgz", name);
|
||||
loadstate(fn);
|
||||
stop();
|
||||
f = gzopen(fn, "wb9");
|
||||
if (!f) {
|
||||
conoutf("could not write %s", fn);
|
||||
return;
|
||||
};
|
||||
gzwrite(f, (void *)"CUBESAVE", 8);
|
||||
gzputc(f, islittleendian);
|
||||
gzputi(SAVEGAMEVERSION);
|
||||
gzputi(sizeof(dynent));
|
||||
gzwrite(f, getclientmap(), _MAXDEFSTR);
|
||||
gzputi(gamemode);
|
||||
gzputi(ents.length());
|
||||
loopv(ents) gzputc(f, ents[i].spawned);
|
||||
gzwrite(f, player1, sizeof(dynent));
|
||||
dvector &monsters = getmonsters();
|
||||
gzputi(monsters.length());
|
||||
loopv(monsters) gzwrite(f, monsters[i], sizeof(dynent));
|
||||
gzputi(players.length());
|
||||
loopv(players)
|
||||
{
|
||||
gzput(players[i] == NULL);
|
||||
gzwrite(f, players[i], sizeof(dynent));
|
||||
};
|
||||
};
|
||||
|
||||
void loadgameout()
|
||||
void
|
||||
savegame(char *name)
|
||||
{
|
||||
stop();
|
||||
conoutf("loadgame incomplete: savegame from a different version of this map");
|
||||
if (!m_classicsp) {
|
||||
conoutf("can only save classic sp games");
|
||||
return;
|
||||
};
|
||||
sprintf_sd(fn)("savegames/%s.csgz", name);
|
||||
savestate(fn);
|
||||
stop();
|
||||
conoutf("wrote %s", fn);
|
||||
};
|
||||
|
||||
void loadgamerest()
|
||||
void
|
||||
loadstate(char *fn)
|
||||
{
|
||||
if(demoplayback || !f) return;
|
||||
|
||||
if(gzgeti()!=ents.length()) return loadgameout();
|
||||
loopv(ents)
|
||||
{
|
||||
ents[i].spawned = gzgetc(f)!=0;
|
||||
if(ents[i].type==CARROT && !ents[i].spawned) trigger(ents[i].attr1, ents[i].attr2, true);
|
||||
};
|
||||
restoreserverstate(ents);
|
||||
|
||||
gzread(f, player1, sizeof(dynent));
|
||||
player1->lastaction = lastmillis;
|
||||
|
||||
int nmonsters = gzgeti();
|
||||
dvector &monsters = getmonsters();
|
||||
if(nmonsters!=monsters.length()) return loadgameout();
|
||||
loopv(monsters)
|
||||
{
|
||||
gzread(f, monsters[i], sizeof(dynent));
|
||||
monsters[i]->enemy = player1; // lazy, could save id of enemy instead
|
||||
monsters[i]->lastaction = monsters[i]->trigger = lastmillis+500; // also lazy, but no real noticable effect on game
|
||||
if(monsters[i]->state==CS_DEAD) monsters[i]->lastaction = 0;
|
||||
};
|
||||
restoremonsterstate();
|
||||
|
||||
int nplayers = gzgeti();
|
||||
loopi(nplayers) if(!gzget())
|
||||
{
|
||||
dynent *d = getclient(i);
|
||||
assert(d);
|
||||
gzread(f, d, sizeof(dynent));
|
||||
};
|
||||
|
||||
conoutf("savegame restored");
|
||||
if(demoloading) startdemo(); else stop();
|
||||
stop();
|
||||
if (multiplayer())
|
||||
return;
|
||||
f = gzopen(fn, "rb9");
|
||||
if (!f) {
|
||||
conoutf("could not open %s", fn);
|
||||
return;
|
||||
};
|
||||
|
||||
string buf;
|
||||
gzread(f, buf, 8);
|
||||
if (strncmp(buf, "CUBESAVE", 8))
|
||||
goto out;
|
||||
if (gzgetc(f) != islittleendian)
|
||||
goto out; // not supporting save->load accross incompatible
|
||||
// architectures simpifies things a LOT
|
||||
if (gzgeti() != SAVEGAMEVERSION || gzgeti() != sizeof(dynent))
|
||||
goto out;
|
||||
string mapname;
|
||||
gzread(f, mapname, _MAXDEFSTR);
|
||||
nextmode = gzgeti();
|
||||
changemap(mapname); // continue below once map has been loaded and
|
||||
// client & server have updated
|
||||
return;
|
||||
out:
|
||||
conoutf("aborting: savegame/demo from a different version of cube or "
|
||||
"cpu architecture");
|
||||
stop();
|
||||
};
|
||||
|
||||
void
|
||||
loadgame(char *name)
|
||||
{
|
||||
sprintf_sd(fn)("savegames/%s.csgz", name);
|
||||
loadstate(fn);
|
||||
};
|
||||
|
||||
void
|
||||
loadgameout()
|
||||
{
|
||||
stop();
|
||||
conoutf("loadgame incomplete: savegame from a different version of "
|
||||
"this map");
|
||||
};
|
||||
|
||||
void
|
||||
loadgamerest()
|
||||
{
|
||||
if (demoplayback || !f)
|
||||
return;
|
||||
|
||||
if (gzgeti() != ents.length())
|
||||
return loadgameout();
|
||||
loopv(ents)
|
||||
{
|
||||
ents[i].spawned = gzgetc(f) != 0;
|
||||
if (ents[i].type == CARROT && !ents[i].spawned)
|
||||
trigger(ents[i].attr1, ents[i].attr2, true);
|
||||
};
|
||||
restoreserverstate(ents);
|
||||
|
||||
gzread(f, player1, sizeof(dynent));
|
||||
player1->lastaction = lastmillis;
|
||||
|
||||
int nmonsters = gzgeti();
|
||||
dvector &monsters = getmonsters();
|
||||
if (nmonsters != monsters.length())
|
||||
return loadgameout();
|
||||
loopv(monsters)
|
||||
{
|
||||
gzread(f, monsters[i], sizeof(dynent));
|
||||
monsters[i]->enemy =
|
||||
player1; // lazy, could save id of enemy instead
|
||||
monsters[i]->lastaction = monsters[i]->trigger =
|
||||
lastmillis +
|
||||
500; // also lazy, but no real noticable effect on game
|
||||
if (monsters[i]->state == CS_DEAD)
|
||||
monsters[i]->lastaction = 0;
|
||||
};
|
||||
restoremonsterstate();
|
||||
|
||||
int nplayers = gzgeti();
|
||||
loopi(nplayers) if (!gzget())
|
||||
{
|
||||
dynent *d = getclient(i);
|
||||
assert(d);
|
||||
gzread(f, d, sizeof(dynent));
|
||||
};
|
||||
|
||||
conoutf("savegame restored");
|
||||
if (demoloading)
|
||||
startdemo();
|
||||
else
|
||||
stop();
|
||||
};
|
||||
|
||||
// demo functions
|
||||
|
@ -153,204 +226,265 @@ int playbacktime = 0;
|
|||
int ddamage, bdamage;
|
||||
vec dorig;
|
||||
|
||||
void record(char *name)
|
||||
void
|
||||
record(char *name)
|
||||
{
|
||||
if(m_sp) { conoutf("cannot record singleplayer games"); return; };
|
||||
int cn = getclientnum();
|
||||
if(cn<0) return;
|
||||
sprintf_sd(fn)("demos/%s.cdgz", name);
|
||||
savestate(fn);
|
||||
gzputi(cn);
|
||||
conoutf("started recording demo to %s", fn);
|
||||
demorecording = true;
|
||||
starttime = lastmillis;
|
||||
if (m_sp) {
|
||||
conoutf("cannot record singleplayer games");
|
||||
return;
|
||||
};
|
||||
int cn = getclientnum();
|
||||
if (cn < 0)
|
||||
return;
|
||||
sprintf_sd(fn)("demos/%s.cdgz", name);
|
||||
savestate(fn);
|
||||
gzputi(cn);
|
||||
conoutf("started recording demo to %s", fn);
|
||||
demorecording = true;
|
||||
starttime = lastmillis;
|
||||
ddamage = bdamage = 0;
|
||||
};
|
||||
|
||||
void demodamage(int damage, vec &o) { ddamage = damage; dorig = o; };
|
||||
void demoblend(int damage) { bdamage = damage; };
|
||||
|
||||
void incomingdemodata(uchar *buf, int len, bool extras)
|
||||
void
|
||||
demodamage(int damage, vec &o)
|
||||
{
|
||||
if(!demorecording) return;
|
||||
gzputi(lastmillis-starttime);
|
||||
gzputi(len);
|
||||
gzwrite(f, buf, len);
|
||||
gzput(extras);
|
||||
if(extras)
|
||||
{
|
||||
gzput(player1->gunselect);
|
||||
gzput(player1->lastattackgun);
|
||||
gzputi(player1->lastaction-starttime);
|
||||
gzputi(player1->gunwait);
|
||||
gzputi(player1->health);
|
||||
gzputi(player1->armour);
|
||||
gzput(player1->armourtype);
|
||||
loopi(NUMGUNS) gzput(player1->ammo[i]);
|
||||
gzput(player1->state);
|
||||
ddamage = damage;
|
||||
dorig = o;
|
||||
};
|
||||
void
|
||||
demoblend(int damage)
|
||||
{
|
||||
bdamage = damage;
|
||||
};
|
||||
|
||||
void
|
||||
incomingdemodata(uchar *buf, int len, bool extras)
|
||||
{
|
||||
if (!demorecording)
|
||||
return;
|
||||
gzputi(lastmillis - starttime);
|
||||
gzputi(len);
|
||||
gzwrite(f, buf, len);
|
||||
gzput(extras);
|
||||
if (extras) {
|
||||
gzput(player1->gunselect);
|
||||
gzput(player1->lastattackgun);
|
||||
gzputi(player1->lastaction - starttime);
|
||||
gzputi(player1->gunwait);
|
||||
gzputi(player1->health);
|
||||
gzputi(player1->armour);
|
||||
gzput(player1->armourtype);
|
||||
loopi(NUMGUNS) gzput(player1->ammo[i]);
|
||||
gzput(player1->state);
|
||||
gzputi(bdamage);
|
||||
bdamage = 0;
|
||||
gzputi(ddamage);
|
||||
if(ddamage) { gzputv(dorig); ddamage = 0; };
|
||||
// FIXME: add all other client state which is not send through the network
|
||||
};
|
||||
if (ddamage) {
|
||||
gzputv(dorig);
|
||||
ddamage = 0;
|
||||
};
|
||||
// FIXME: add all other client state which is not send through
|
||||
// the network
|
||||
};
|
||||
};
|
||||
|
||||
void demo(char *name)
|
||||
void
|
||||
demo(char *name)
|
||||
{
|
||||
sprintf_sd(fn)("demos/%s.cdgz", name);
|
||||
loadstate(fn);
|
||||
demoloading = true;
|
||||
sprintf_sd(fn)("demos/%s.cdgz", name);
|
||||
loadstate(fn);
|
||||
demoloading = true;
|
||||
};
|
||||
|
||||
void stopreset()
|
||||
void
|
||||
stopreset()
|
||||
{
|
||||
conoutf("demo stopped (%d msec elapsed)", lastmillis-starttime);
|
||||
stop();
|
||||
loopv(players) zapdynent(players[i]);
|
||||
disconnect(0, 0);
|
||||
conoutf("demo stopped (%d msec elapsed)", lastmillis - starttime);
|
||||
stop();
|
||||
loopv(players) zapdynent(players[i]);
|
||||
disconnect(0, 0);
|
||||
};
|
||||
|
||||
VAR(demoplaybackspeed, 10, 100, 1000);
|
||||
int scaletime(int t) { return (int)(t*(100.0f/demoplaybackspeed))+starttime; };
|
||||
|
||||
void readdemotime()
|
||||
{
|
||||
if(gzeof(f) || (playbacktime = gzgeti())==-1)
|
||||
{
|
||||
stopreset();
|
||||
return;
|
||||
};
|
||||
playbacktime = scaletime(playbacktime);
|
||||
int
|
||||
scaletime(int t)
|
||||
{
|
||||
return (int)(t * (100.0f / demoplaybackspeed)) + starttime;
|
||||
};
|
||||
|
||||
void startdemo()
|
||||
void
|
||||
readdemotime()
|
||||
{
|
||||
democlientnum = gzgeti();
|
||||
demoplayback = true;
|
||||
starttime = lastmillis;
|
||||
conoutf("now playing demo");
|
||||
dynent *d = getclient(democlientnum);
|
||||
assert(d);
|
||||
*d = *player1;
|
||||
readdemotime();
|
||||
if (gzeof(f) || (playbacktime = gzgeti()) == -1) {
|
||||
stopreset();
|
||||
return;
|
||||
};
|
||||
playbacktime = scaletime(playbacktime);
|
||||
};
|
||||
|
||||
void
|
||||
startdemo()
|
||||
{
|
||||
democlientnum = gzgeti();
|
||||
demoplayback = true;
|
||||
starttime = lastmillis;
|
||||
conoutf("now playing demo");
|
||||
dynent *d = getclient(democlientnum);
|
||||
assert(d);
|
||||
*d = *player1;
|
||||
readdemotime();
|
||||
};
|
||||
|
||||
VAR(demodelaymsec, 0, 120, 500);
|
||||
|
||||
void catmulrom(vec &z, vec &a, vec &b, vec &c, float s, vec &dest) // spline interpolation
|
||||
void
|
||||
catmulrom(
|
||||
vec &z, vec &a, vec &b, vec &c, float s, vec &dest) // spline interpolation
|
||||
{
|
||||
vec t1 = b, t2 = c;
|
||||
|
||||
vsub(t1, z); vmul(t1, 0.5f)
|
||||
vsub(t2, a); vmul(t2, 0.5f);
|
||||
vsub(t1, z);
|
||||
vmul(t1, 0.5f) vsub(t2, a);
|
||||
vmul(t2, 0.5f);
|
||||
|
||||
float s2 = s*s;
|
||||
float s3 = s*s2;
|
||||
float s2 = s * s;
|
||||
float s3 = s * s2;
|
||||
|
||||
dest = a;
|
||||
vec t = b;
|
||||
|
||||
vmul(dest, 2*s3 - 3*s2 + 1);
|
||||
vmul(t, -2*s3 + 3*s2); vadd(dest, t);
|
||||
vmul(t1, s3 - 2*s2 + s); vadd(dest, t1);
|
||||
vmul(t2, s3 - s2); vadd(dest, t2);
|
||||
vmul(dest, 2 * s3 - 3 * s2 + 1);
|
||||
vmul(t, -2 * s3 + 3 * s2);
|
||||
vadd(dest, t);
|
||||
vmul(t1, s3 - 2 * s2 + s);
|
||||
vadd(dest, t1);
|
||||
vmul(t2, s3 - s2);
|
||||
vadd(dest, t2);
|
||||
};
|
||||
|
||||
void fixwrap(dynent *a, dynent *b)
|
||||
void
|
||||
fixwrap(dynent *a, dynent *b)
|
||||
{
|
||||
while(b->yaw-a->yaw>180) a->yaw += 360;
|
||||
while(b->yaw-a->yaw<-180) a->yaw -= 360;
|
||||
while (b->yaw - a->yaw > 180)
|
||||
a->yaw += 360;
|
||||
while (b->yaw - a->yaw < -180)
|
||||
a->yaw -= 360;
|
||||
};
|
||||
|
||||
void demoplaybackstep()
|
||||
void
|
||||
demoplaybackstep()
|
||||
{
|
||||
while(demoplayback && lastmillis>=playbacktime)
|
||||
{
|
||||
int len = gzgeti();
|
||||
if(len<1 || len>MAXTRANS)
|
||||
{
|
||||
conoutf("error: huge packet during demo play (%d)", len);
|
||||
stopreset();
|
||||
return;
|
||||
};
|
||||
uchar buf[MAXTRANS];
|
||||
gzread(f, buf, len);
|
||||
localservertoclient(buf, len); // update game state
|
||||
|
||||
dynent *target = players[democlientnum];
|
||||
assert(target);
|
||||
|
||||
while (demoplayback && lastmillis >= playbacktime) {
|
||||
int len = gzgeti();
|
||||
if (len < 1 || len > MAXTRANS) {
|
||||
conoutf(
|
||||
"error: huge packet during demo play (%d)", len);
|
||||
stopreset();
|
||||
return;
|
||||
};
|
||||
uchar buf[MAXTRANS];
|
||||
gzread(f, buf, len);
|
||||
localservertoclient(buf, len); // update game state
|
||||
|
||||
dynent *target = players[democlientnum];
|
||||
assert(target);
|
||||
|
||||
int extras;
|
||||
if(extras = gzget()) // read additional client side state not present in normal network stream
|
||||
{
|
||||
target->gunselect = gzget();
|
||||
target->lastattackgun = gzget();
|
||||
target->lastaction = scaletime(gzgeti());
|
||||
target->gunwait = gzgeti();
|
||||
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); };
|
||||
// FIXME: set more client state here
|
||||
};
|
||||
|
||||
// insert latest copy of player into history
|
||||
if(extras && (playerhistory.empty() || playerhistory.last()->lastupdate!=playbacktime))
|
||||
{
|
||||
dynent *d = newdynent();
|
||||
*d = *target;
|
||||
d->lastupdate = playbacktime;
|
||||
playerhistory.add(d);
|
||||
if(playerhistory.length()>20)
|
||||
{
|
||||
zapdynent(playerhistory[0]);
|
||||
playerhistory.remove(0);
|
||||
};
|
||||
};
|
||||
|
||||
readdemotime();
|
||||
};
|
||||
|
||||
if(demoplayback)
|
||||
{
|
||||
int itime = lastmillis-demodelaymsec;
|
||||
loopvrev(playerhistory) if(playerhistory[i]->lastupdate<itime) // find 2 positions in history that surround interpolation time point
|
||||
{
|
||||
dynent *a = playerhistory[i];
|
||||
dynent *b = a;
|
||||
if(i+1<playerhistory.length()) b = playerhistory[i+1];
|
||||
*player1 = *b;
|
||||
if(a!=b) // interpolate pos & angles
|
||||
{
|
||||
if (extras = gzget()) // read additional client side state not
|
||||
// present in normal network stream
|
||||
{
|
||||
target->gunselect = gzget();
|
||||
target->lastattackgun = gzget();
|
||||
target->lastaction = scaletime(gzgeti());
|
||||
target->gunwait = gzgeti();
|
||||
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);
|
||||
};
|
||||
// FIXME: set more client state here
|
||||
};
|
||||
|
||||
// insert latest copy of player into history
|
||||
if (extras &&
|
||||
(playerhistory.empty() ||
|
||||
playerhistory.last()->lastupdate != playbacktime)) {
|
||||
dynent *d = newdynent();
|
||||
*d = *target;
|
||||
d->lastupdate = playbacktime;
|
||||
playerhistory.add(d);
|
||||
if (playerhistory.length() > 20) {
|
||||
zapdynent(playerhistory[0]);
|
||||
playerhistory.remove(0);
|
||||
};
|
||||
};
|
||||
|
||||
readdemotime();
|
||||
};
|
||||
|
||||
if (demoplayback) {
|
||||
int itime = lastmillis - demodelaymsec;
|
||||
loopvrev(playerhistory) if (playerhistory[i]->lastupdate <
|
||||
itime) // find 2 positions in
|
||||
// history that surround
|
||||
// interpolation time point
|
||||
{
|
||||
dynent *a = playerhistory[i];
|
||||
dynent *b = a;
|
||||
if (i + 1 < playerhistory.length())
|
||||
b = playerhistory[i + 1];
|
||||
*player1 = *b;
|
||||
if (a != b) // interpolate pos & angles
|
||||
{
|
||||
dynent *c = b;
|
||||
if(i+2<playerhistory.length()) c = playerhistory[i+2];
|
||||
if (i + 2 < playerhistory.length())
|
||||
c = playerhistory[i + 2];
|
||||
dynent *z = a;
|
||||
if(i-1>=0) z = playerhistory[i-1];
|
||||
//if(a==z || b==c) printf("* %d\n", lastmillis);
|
||||
float bf = (itime-a->lastupdate)/(float)(b->lastupdate-a->lastupdate);
|
||||
if (i - 1 >= 0)
|
||||
z = playerhistory[i - 1];
|
||||
// if(a==z || b==c) printf("* %d\n",
|
||||
// lastmillis);
|
||||
float bf =
|
||||
(itime - a->lastupdate) /
|
||||
(float)(b->lastupdate - a->lastupdate);
|
||||
fixwrap(a, player1);
|
||||
fixwrap(c, player1);
|
||||
fixwrap(z, player1);
|
||||
vdist(dist, v, z->o, c->o);
|
||||
if(dist<16) // if teleport or spawn, dont't interpolate
|
||||
if (dist < 16) // if teleport or spawn, dont't
|
||||
// interpolate
|
||||
{
|
||||
catmulrom(z->o, a->o, b->o, c->o, bf, player1->o);
|
||||
catmulrom(*(vec *)&z->yaw, *(vec *)&a->yaw, *(vec *)&b->yaw, *(vec *)&c->yaw, bf, *(vec *)&player1->yaw);
|
||||
catmulrom(z->o, a->o, b->o, c->o, bf,
|
||||
player1->o);
|
||||
catmulrom(*(vec *)&z->yaw,
|
||||
*(vec *)&a->yaw, *(vec *)&b->yaw,
|
||||
*(vec *)&c->yaw, bf,
|
||||
*(vec *)&player1->yaw);
|
||||
};
|
||||
fixplayer1range();
|
||||
};
|
||||
break;
|
||||
};
|
||||
//if(player1->state!=CS_DEAD) showscores(false);
|
||||
};
|
||||
break;
|
||||
};
|
||||
// if(player1->state!=CS_DEAD) showscores(false);
|
||||
};
|
||||
};
|
||||
|
||||
void stopn() { if(demoplayback) stopreset(); else stop(); conoutf("demo stopped"); };
|
||||
void
|
||||
stopn()
|
||||
{
|
||||
if (demoplayback)
|
||||
stopreset();
|
||||
else
|
||||
stop();
|
||||
conoutf("demo stopped");
|
||||
};
|
||||
|
||||
COMMAND(record, ARG_1STR);
|
||||
COMMAND(demo, ARG_1STR);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue