static void readdemotime() { if (gzeof(f) || (playbacktime = gzgeti())==-1) { stopreset(); return; } playbacktime = scaletime(playbacktime); }
void stopn() { if (demoplayback) stopreset(); else stop(); conoutf("demo stopped"); }
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); 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 { dynent *c = b; 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); 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 { 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); }; };
static void stopn(void) { if (demoplayback) stopreset(); else stop(); con::out("demo stopped"); }
void playbackstep(void) { while (demoplayback && game::lastmillis()>=playbacktime) { int len = gzgeti(); if (len<1 || len>MAXTRANS) { con::out("error: huge packet during demo play (%d)", len); stopreset(); return; } u8 buf[MAXTRANS]; gzread(f, buf, len); client::localservertoclient(buf, len); // update game state game::dynent *target = game::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(game::NUMGUNS) target->ammo[i] = gzget(); target->state = gzget(); target->lastmove = playbacktime; // if ((bdamage = gzgeti()) != 0) rr::damageblend(bdamage); if ((ddamage = gzgeti()) != 0) { gzgetv(dorig); rr::particle_splash(rr::PT_BLOOD_SPATS, ddamage, 1000, dorig); } // FIXME: set more client state here } // insert latest copy of player into history if (extras && (playerhistory.empty() || playerhistory.last()->lastupdate!=playbacktime)) { game::dynent *d = game::newdynent(); *d = *target; d->lastupdate = playbacktime; playerhistory.add(d); if (playerhistory.length()>20) { game::zapdynent(playerhistory[0]); playerhistory.remove(0); } } readdemotime(); } if (demoplayback) { int itime = game::lastmillis()-demodelaymsec; loopvrev(playerhistory) if (playerhistory[i]->lastupdate<itime) { // find 2 positions in history that surround interpolation time point game::dynent *a = playerhistory[i]; game::dynent *b = a; if (i+1<playerhistory.length()) b = playerhistory[i+1]; *game::player1 = *b; if (a!=b) { // interpolate pos & angles game::dynent *c = b; if (i+2<playerhistory.length()) c = playerhistory[i+2]; game::dynent *z = a; if (i-1>=0) z = playerhistory[i-1]; float bf = (itime-a->lastupdate)/(float)(b->lastupdate-a->lastupdate); fixwrap(a, game::player1); fixwrap(c, game::player1); fixwrap(z, game::player1); const float dist = distance(z->o,c->o); if (dist<16.f) { // if teleport or spawn, dont't interpolate catmulrom(z->o, a->o, b->o, c->o, bf, game::player1->o); // catmulrom(*(vec3f*)&z->ypr.x, *(vec3f*)&a->ypr.x, *(vec3f*)&b->ypr.x, *(vec3f*)&c->ypr.x, bf, *(vec3f *)&game::player1->ypr.x); vec3f dstangle; catmulrom(z->ypr, a->ypr, b->ypr, c->ypr, bf, dstangle); game::player1->ypr.x = dstangle.x; game::player1->ypr.y = dstangle.y; game::player1->ypr.z = dstangle.z; } game::fixplayer1range(); } break; } } }