diff --git a/source/games/duke/src/actors.cpp b/source/games/duke/src/actors.cpp index afb382804..163f5a2e0 100644 --- a/source/games/duke/src/actors.cpp +++ b/source/games/duke/src/actors.cpp @@ -762,7 +762,15 @@ void movecrane(int i, int crane) s->owner = -2; ps[p].on_crane = i; S_PlayActorSound(isRR() ? 390 : DUKE_GRUNT, ps[p].i); - ps[p].setang(s->ang + 1024, true); + int ang = s->ang + 1024; + if (!cl_syncinput) + { + ps[p].angAdjust += ps[p].getang() + ang; + } + else + { + ps[p].setang(ang); + } } else { @@ -2685,7 +2693,15 @@ void handle_se00(int i, int LASERLINE) { if (ps[p].cursectnum == s->sectnum && ps[p].on_ground == 1) { - ps[p].angAdjust += l * q; + int ang = l * q; + if (!cl_syncinput) + { + ps[p].angAdjust += ang; + } + else + { + ps[p].addang(ang); + } ps[p].posz += zchange; @@ -2877,7 +2893,14 @@ void handle_se14(int i, bool checkstat, int RPG, int JIBS6) ps[p].bobposx += m; ps[p].bobposy += x; - ps[p].angAdjust += q; + if (!cl_syncinput) + { + ps[p].angAdjust += q; + } + else + { + ps[p].addang(q); + } if (numplayers > 1) { diff --git a/source/games/duke/src/actors_d.cpp b/source/games/duke/src/actors_d.cpp index 9fa812d07..2f56879b3 100644 --- a/source/games/duke/src/actors_d.cpp +++ b/source/games/duke/src/actors_d.cpp @@ -1852,7 +1852,15 @@ void moveweapons_d(void) if (s->picnum == SPIT) { - ps[p].horizAdjust += 32; + int horiz = 32; + if (!cl_syncinput) + { + ps[p].horizAdjust += horiz; + } + else + { + ps[p].addhoriz(horiz); + } ps[p].return_to_center = 8; if (ps[p].loogcnt == 0) diff --git a/source/games/duke/src/actors_r.cpp b/source/games/duke/src/actors_r.cpp index 88e0ac76d..95fd3e136 100644 --- a/source/games/duke/src/actors_r.cpp +++ b/source/games/duke/src/actors_r.cpp @@ -1398,7 +1398,16 @@ void moveweapons_r(void) guts_r(s, RABBITJIBB, 2, myconnectindex); guts_r(s, RABBITJIBC, 2, myconnectindex); } - ps[p].horizAdjust += 32; + + int horiz = 32; + if (!cl_syncinput) + { + ps[p].horizAdjust += horiz; + } + else + { + ps[p].addhoriz(horiz); + } ps[p].return_to_center = 8; if (ps[p].loogcnt == 0) diff --git a/source/games/duke/src/funct.h b/source/games/duke/src/funct.h index 90052bc95..5e7adea90 100644 --- a/source/games/duke/src/funct.h +++ b/source/games/duke/src/funct.h @@ -249,5 +249,6 @@ void backuplook(player_struct* p); void backupview(player_struct* p); void backupweapon(player_struct* p); void resetinputhelpers(player_struct* p); +void checkhardlanding(player_struct* p); END_DUKE_NS diff --git a/source/games/duke/src/input.cpp b/source/games/duke/src/input.cpp index de7f61aa3..094144a8d 100644 --- a/source/games/duke/src/input.cpp +++ b/source/games/duke/src/input.cpp @@ -1242,14 +1242,9 @@ void GetInput() processVehicleInput(p, info, input, scaleAdjust); FinalizeInput(myconnectindex, input, true); - if (!cl_syncinput) + if (!cl_syncinput && sprite[p->i].extra > 0) { - p->q16ang = (p->q16ang + input.q16avel) & 0x7FFFFFF; - p->q16horiz = clamp(p->q16horiz, F16(HORIZ_MIN), F16(HORIZ_MAX)); - if (sprite[p->i].extra > 0) - { - apply_seasick(p, scaleAdjust); - } + apply_seasick(p, scaleAdjust); } } else @@ -1258,14 +1253,14 @@ void GetInput() checkCrouchToggle(p); processInputBits(p, info); FinalizeInput(myconnectindex, input, false); + } - if (!cl_syncinput) - { - // Do these in the same order as the old code. - calcviewpitch(p, scaleAdjust); - applylook(myconnectindex, scaleAdjust, input.q16avel); - sethorizon(myconnectindex, loc.bits, scaleAdjust, true, input.q16horz); - } + if (!cl_syncinput) + { + // Do these in the same order as the old code. + calcviewpitch(p, scaleAdjust); + applylook(myconnectindex, scaleAdjust, input.q16avel); + sethorizon(myconnectindex, loc.bits, scaleAdjust, true, input.q16horz); } } diff --git a/source/games/duke/src/player.cpp b/source/games/duke/src/player.cpp index da5d39175..e3a198646 100644 --- a/source/games/duke/src/player.cpp +++ b/source/games/duke/src/player.cpp @@ -163,7 +163,15 @@ void forceplayerangle(struct player_struct* p) n = 128 - (krand() & 255); - p->horizAdjust += 64; + int horiz = 64; + if (!cl_syncinput) + { + p->horizAdjust += horiz; + } + else + { + p->addhoriz(horiz); + } p->return_to_center = 9; p->setlookang(n >> 1); p->setrotscrnang(n >> 1); @@ -405,7 +413,15 @@ void dokneeattack(int snum, int pi, const std::initializer_list & respawnli if (p->knee_incs > 0) { p->knee_incs++; - p->horizAdjust -= 48; + int horiz = -48; + if (!cl_syncinput) + { + p->horizAdjust += horiz; + } + else + { + p->addhoriz(horiz); + } p->return_to_center = 9; if (p->knee_incs > 15) { @@ -822,9 +838,16 @@ void applylook(int snum, double factor, fixed_t adjustment) } p->q16ang += add; } - p->q16ang += fix16_from_dbl(factor * p->angAdjust) + adjustment; apply_seasick(p, factor); } + + // Add angAdjust if input is unsynchronised. + if (!cl_syncinput) + { + p->q16ang += fix16_from_dbl(factor * p->angAdjust); + } + + p->q16ang = (p->q16ang + adjustment) & 0x7FFFFFF; } //--------------------------------------------------------------------------- @@ -911,6 +934,29 @@ void resetinputhelpers(player_struct* p) // //--------------------------------------------------------------------------- +void checkhardlanding(player_struct* p) +{ + if (p->hard_landing > 0) + { + int horiz = p->hard_landing << 4; + if (!cl_syncinput) + { + p->horizAdjust -= horiz; + } + else + { + p->addhoriz(-horiz); + } + p->hard_landing--; + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void checklook(int snum, int sb_snum) { auto p = &ps[snum]; @@ -970,7 +1016,16 @@ void sethorizon(int snum, int sb_snum, double factor, bool frominput, fixed_t ad } } - p->q16horiz = clamp((F16(100) + xs_CRoundToInt(F16(128) * tan(horizAngle * (pi::pi() / 512.)))) + (factor * (p->horizAdjust * 65536.)), F16(HORIZ_MIN), F16(HORIZ_MAX)); + // Convert back to Build's horizon. + p->q16horiz = F16(100) + xs_CRoundToInt(F16(128) * tan(horizAngle * (pi::pi() / 512.))); + + // Add horizAdjust if input is unsynchronised. + if (!cl_syncinput) + { + p->q16horiz += xs_CRoundToInt(factor * (p->horizAdjust * 65536.)); + } + + p->q16horiz = clamp(p->q16horiz, F16(HORIZ_MIN), F16(HORIZ_MAX)); } //--------------------------------------------------------------------------- diff --git a/source/games/duke/src/player_d.cpp b/source/games/duke/src/player_d.cpp index 2f9b14643..d97f07933 100644 --- a/source/games/duke/src/player_d.cpp +++ b/source/games/duke/src/player_d.cpp @@ -3028,9 +3028,22 @@ HORIZONLY: playerAimDown(snum, sb_snum); } + if (cl_syncinput) + { + sethorizon(snum, sb_snum, 1, sync[snum].q16horz); + } + if (p->hard_landing > 0) { - p->horizAdjust -= p->hard_landing << 4; + int horiz = p->hard_landing << 4; + if (!cl_syncinput) + { + p->horizAdjust -= horiz; + } + else + { + p->addhoriz(-horiz); + } p->hard_landing--; } @@ -3052,11 +3065,6 @@ HORIZONLY: dokneeattack(snum, pi, { FEM1, FEM2, FEM3, FEM4, FEM5, FEM6, FEM7, FEM8, FEM9, FEM10, PODFEM1, NAKED1, STATUE }); - if (cl_syncinput) - { - sethorizon(snum, sb_snum, 1, false, sync[snum].q16horz); - } - if (fi.doincrements(p)) return; if (p->weapon_pos != 0) diff --git a/source/games/duke/src/player_r.cpp b/source/games/duke/src/player_r.cpp index 2be28dab7..944229ac7 100644 --- a/source/games/duke/src/player_r.cpp +++ b/source/games/duke/src/player_r.cpp @@ -1410,31 +1410,6 @@ int doincrements_r(struct player_struct* p) else if (p->knuckle_incs == 22 || PlayerInput(snum, SKB_FIRE)) p->knuckle_incs = 0; - // Originally, these functions were called before this function in processinput_r(), however with unsynchronised input changes, - // we need to call them after calling processweapon(), which happens after this function is called. - // Since this function returning 1 causes processinput_r() to return, we call them here in the event this function will return 1. - if (cl_syncinput) - { - if (!movementBlocked(snum)) - { - auto sb_avel = PlayerInputAngVel(snum); - - if (sector[p->cursectnum].lotag == ST_2_UNDERWATER) - { - p->q16angvel = (sb_avel - (sb_avel >> 3)) * sgn(TICSPERFRAME); - } - else - { - p->q16angvel = sb_avel * sgn(TICSPERFRAME); - } - - applylook(snum, 1, p->q16angvel); - - p->crack_time = 777; - } - sethorizon(snum, PlayerInputBits(snum, SKB_ALL), 1, !cl_syncinput, sync[snum].q16horz); - } - return 1; } return 0; @@ -1528,6 +1503,18 @@ void checkweapons_r(struct player_struct* p) } } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static inline double calcVehicleHorizAdjust(fixed_t q16horiz, int adjustment) +{ + return -1. * ((q16horiz / 65536.) - adjustment); +} + + //--------------------------------------------------------------------------- // // @@ -1705,19 +1692,28 @@ static void onMotorcycle(int snum, ESyncBits &sb_snum) } if (p->TurbCount) { + int horiz; if (p->TurbCount <= 1) { - p->sethoriz(100); + horiz = 100; p->TurbCount = 0; p->VBumpTarget = 0; p->VBumpNow = 0; } else { - p->sethoriz(100 + ((krand() & 15) - 7)); + horiz = 100 + ((krand() & 15) - 7); p->TurbCount--; p->moto_drink = (krand() & 3) - 2; } + if (!cl_syncinput) + { + p->horizAdjust += calcVehicleHorizAdjust(p->q16horiz, horiz); + } + else + { + p->sethoriz(horiz); + } } else if (p->VBumpTarget > p->VBumpNow) { @@ -1727,7 +1723,14 @@ static void onMotorcycle(int snum, ESyncBits &sb_snum) p->VBumpNow++; if (p->VBumpTarget < p->VBumpNow) p->VBumpNow = p->VBumpTarget; - p->sethoriz(100 + p->VBumpNow / 3); + if (!cl_syncinput) + { + p->horizAdjust += calcVehicleHorizAdjust(p->q16horiz, 100 + p->VBumpNow / 3); + } + else + { + p->sethoriz(100 + p->VBumpNow / 3); + } } else if (p->VBumpTarget < p->VBumpNow) { @@ -1737,7 +1740,14 @@ static void onMotorcycle(int snum, ESyncBits &sb_snum) p->VBumpNow--; if (p->VBumpTarget > p->VBumpNow) p->VBumpNow = p->VBumpTarget; - p->sethoriz(100 + p->VBumpNow / 3); + if (!cl_syncinput) + { + p->horizAdjust += calcVehicleHorizAdjust(p->q16horiz, 100 + p->VBumpNow / 3); + } + else + { + p->sethoriz(100 + p->VBumpNow / 3); + } } else { @@ -1757,6 +1767,7 @@ static void onMotorcycle(int snum, ESyncBits &sb_snum) var98 = 350; else var98 = -350; + int ang; if (p->moto_on_mud || p->moto_on_oil || !p->NotOnWater) { if (p->moto_on_oil) @@ -1767,13 +1778,13 @@ static void onMotorcycle(int snum, ESyncBits &sb_snum) { p->posxv += (var8c >> 5) * (sintable[(var94 * -51 + var90 + 512) & 2047] << 4); p->posyv += (var8c >> 5) * (sintable[(var94 * -51 + var90) & 2047] << 4); - p->setang((var90 - (var98 >> 2)) & 2047); + ang = var98 >> 2; } else { p->posxv += (var8c >> 7) * (sintable[(var94 * -51 + var90 + 512) & 2047] << 4); p->posyv += (var8c >> 7) * (sintable[(var94 * -51 + var90) & 2047] << 4); - p->setang((var90 - (var98 >> 6)) & 2047); + ang = var98 >> 6; } p->moto_on_mud = 0; p->moto_on_oil = 0; @@ -1784,7 +1795,7 @@ static void onMotorcycle(int snum, ESyncBits &sb_snum) { p->posxv += (var8c >> 5) * (sintable[(var94 * -51 + var90 + 512) & 2047] << 4); p->posyv += (var8c >> 5) * (sintable[(var94 * -51 + var90) & 2047] << 4); - p->setang((var90 - (var98 >> 4)) & 2047); + ang = var98 >> 4; if (!S_CheckActorSoundPlaying(pi, 220)) S_PlayActorSound(220, pi); } @@ -1792,9 +1803,17 @@ static void onMotorcycle(int snum, ESyncBits &sb_snum) { p->posxv += (var8c >> 7) * (sintable[(var94 * -51 + var90 + 512) & 2047] << 4); p->posyv += (var8c >> 7) * (sintable[(var94 * -51 + var90) & 2047] << 4); - p->setang((var90 - (var98 >> 7)) & 2047); + ang = var98 >> 7; } } + if (!cl_syncinput) + { + p->angAdjust -= ang; + } + else + { + p->setang((var90 - ang) & 2047); + } } else if (p->MotoSpeed >= 20 && p->on_ground == 1 && (p->moto_on_mud || p->moto_on_oil)) { @@ -2025,19 +2044,28 @@ static void onBoat(int snum, ESyncBits& sb_snum) } if (p->TurbCount) { + int horiz; if (p->TurbCount <= 1) { - p->sethoriz(100); + horiz = 100; p->TurbCount = 0; p->VBumpTarget = 0; p->VBumpNow = 0; } else { - p->sethoriz(100 + ((krand() & 15) - 7)); + horiz = 100 + ((krand() & 15) - 7); p->TurbCount--; p->moto_drink = (krand() & 3) - 2; } + if (!cl_syncinput) + { + p->horizAdjust += calcVehicleHorizAdjust(p->q16horiz, horiz); + } + else + { + p->sethoriz(horiz); + } } else if (p->VBumpTarget > p->VBumpNow) { @@ -2047,7 +2075,14 @@ static void onBoat(int snum, ESyncBits& sb_snum) p->VBumpNow++; if (p->VBumpTarget < p->VBumpNow) p->VBumpNow = p->VBumpTarget; - p->sethoriz(100 + p->VBumpNow / 3); + if (!cl_syncinput) + { + p->horizAdjust += calcVehicleHorizAdjust(p->q16horiz, 100 + p->VBumpNow / 3); + } + else + { + p->sethoriz(100 + p->VBumpNow / 3); + } } else if (p->VBumpTarget < p->VBumpNow) { @@ -2057,7 +2092,14 @@ static void onBoat(int snum, ESyncBits& sb_snum) p->VBumpNow--; if (p->VBumpTarget > p->VBumpNow) p->VBumpNow = p->VBumpTarget; - p->sethoriz(100 + p->VBumpNow / 3); + if (!cl_syncinput) + { + p->horizAdjust += calcVehicleHorizAdjust(p->q16horiz, 100 + p->VBumpNow / 3); + } + else + { + p->sethoriz(100 + p->VBumpNow / 3); + } } else { @@ -2078,17 +2120,26 @@ static void onBoat(int snum, ESyncBits& sb_snum) else vare0 = -350; vard4 <<= 2; + int ang; if (p->moto_do_bump) { p->posxv += (vard4 >> 6) * (sintable[(vardc * -51 + vard8 + 512) & 2047] << 4); p->posyv += (vard4 >> 6) * (sintable[(vardc * -51 + vard8) & 2047] << 4); - p->setang((vard8 - (vare0 >> 5)) & 2047); + ang = vare0 >> 5; } else { p->posxv += (vard4 >> 7) * (sintable[(vardc * -51 + vard8 + 512) & 2047] << 4); p->posyv += (vard4 >> 7) * (sintable[(vardc * -51 + vard8) & 2047] << 4); - p->setang((vard8 - (vare0 >> 6)) & 2047); + ang = vare0 >> 6; + } + if (!cl_syncinput) + { + p->angAdjust -= ang; + } + else + { + p->setang((vard8 - ang) & 2047); } } if (p->NotOnWater) @@ -2421,15 +2472,24 @@ void onMotorcycleMove(int snum, int psect, int j) j &= (MAXWALLS - 1); var108 = getangle(wall[wall[j].point2].x - wall[j].x, wall[wall[j].point2].y - wall[j].y); var10c = abs(p->getang() - var108); + int ang; switch (krand() & 1) { case 0: - p->angAdjust += p->MotoSpeed >> 1; + ang = p->MotoSpeed >> 1; break; case 1: - p->angAdjust -= p->MotoSpeed >> 1; + ang = -(p->MotoSpeed >> 1); break; } + if (!cl_syncinput) + { + p->angAdjust += ang; + } + else + { + p->addang(ang); + } if (var10c >= 441 && var10c <= 581) { var104 = (p->MotoSpeed * p->MotoSpeed) >> 8; @@ -2486,15 +2546,24 @@ void onBoatMove(int snum, int psect, int j) j &= (MAXWALLS - 1); var114 = getangle(wall[wall[j].point2].x - wall[j].x, wall[wall[j].point2].y - wall[j].y); var118 = abs(p->getang() - var114); + int ang; switch (krand() & 1) { case 0: - p->angAdjust += p->MotoSpeed >> 2; + ang = p->MotoSpeed >> 2; break; case 1: - p->angAdjust -= p->MotoSpeed >> 2; + ang = -(p->MotoSpeed >> 2); break; } + if (!cl_syncinput) + { + p->angAdjust += ang; + } + else + { + p->addang(ang); + } if (var118 >= 441 && var118 <= 581) { p->MotoSpeed = ((p->MotoSpeed >> 1) + (p->MotoSpeed >> 2)) >> 2; @@ -3028,7 +3097,14 @@ static void operateweapon(int snum, ESyncBits sb_snum, int psect) case RIFLEGUN_WEAPON: p->kickback_pic++; - p->horizAdjust += 1; + if (!cl_syncinput) + { + p->horizAdjust += 1; + } + else + { + p->addhoriz(1); + } p->recoil++; if (p->kickback_pic <= 12) @@ -3118,11 +3194,25 @@ static void operateweapon(int snum, ESyncBits sb_snum, int psect) } if (p->kickback_pic == 2) { - p->angAdjust += 16; + if (!cl_syncinput) + { + p->angAdjust += 16; + } + else + { + p->addang(16); + } } else if (p->kickback_pic == 4) { - p->angAdjust -= 16; + if (!cl_syncinput) + { + p->angAdjust -= 16; + } + else + { + p->addang(-16); + } } if (p->kickback_pic > 4) p->kickback_pic = 1; @@ -3148,11 +3238,26 @@ static void operateweapon(int snum, ESyncBits sb_snum, int psect) } if (p->kickback_pic == 2) { - p->angAdjust += 4; + int ang = 4; + if (!cl_syncinput) + { + p->angAdjust += 4; + } + else + { + p->addang(4); + } } else if (p->kickback_pic == 4) { - p->angAdjust -= 4; + if (!cl_syncinput) + { + p->angAdjust -= -4; + } + else + { + p->addang(-4); + } } if (p->kickback_pic > 4) p->kickback_pic = 1; @@ -3200,7 +3305,14 @@ static void operateweapon(int snum, ESyncBits sb_snum, int psect) { p->posxv -= sintable[(p->getang() + 512) & 2047] << 4; p->posyv -= sintable[p->getang() & 2047] << 4; - p->horizAdjust += 20; + if (!cl_syncinput) + { + p->horizAdjust += 20; + } + else + { + p->addhoriz(20); + } p->recoil += 20; } if (p->kickback_pic > 20) @@ -3709,6 +3821,34 @@ void processinput_r(int snum) movement(snum, sb_snum, psect, fz, cz, shrunk, truefdist); } + //Do the quick lefts and rights + + if (movementBlocked(snum)) + { + doubvel = 0; + p->posxv = 0; + p->posyv = 0; + } + else if (cl_syncinput) + { + //p->ang += syncangvel * constant + //ENGINE calculates angvel for you + // may still be needed later for demo recording + + if (psectlotag == ST_2_UNDERWATER) + { + p->q16angvel = (sb_avel - (sb_avel >> 3)) * sgn(doubvel); + } + else + { + p->q16angvel = sb_avel * sgn(doubvel); + } + + applylook(snum, 1, p->q16angvel); + + p->crack_time = 777; + } + if (p->spritebridge == 0) { j = sector[s->sectnum].floorpicnum; @@ -4056,14 +4196,24 @@ HORIZONLY: if (!d) d = 1; p->recoil -= d; - p->horizAdjust -= d; + + if (!cl_syncinput) + { + p->horizAdjust -= d; + } + else + { + p->addhoriz(-d); + } } - if (p->hard_landing > 0) + + if (cl_syncinput) { - p->horizAdjust -= p->hard_landing << 4; - p->hard_landing--; + sethorizon(snum, sb_snum, 1, sync[snum].q16horz); } + checkhardlanding(p); + //Shooting code/changes if (p->show_empty_weapon > 0) @@ -4096,38 +4246,6 @@ HORIZONLY: } processweapon(snum, sb_snum, psect); - - //Do the quick lefts and rights - - if (movementBlocked(snum)) - { - doubvel = 0; - p->posxv = 0; - p->posyv = 0; - } - else if (cl_syncinput) - { - //p->ang += syncangvel * constant - //ENGINE calculates angvel for you - // may still be needed later for demo recording - - if (psectlotag == ST_2_UNDERWATER) - { - p->q16angvel = (sb_avel - (sb_avel >> 3)) * sgn(doubvel); - } - else - { - p->q16angvel = sb_avel * sgn(doubvel); - } - - applylook(snum, 1, p->q16angvel); - - p->crack_time = 777; - } - if (cl_syncinput) - { - sethorizon(snum, sb_snum, 1, !cl_syncinput, sync[snum].q16horz); - } } //--------------------------------------------------------------------------- diff --git a/source/games/duke/src/types.h b/source/games/duke/src/types.h index bff7f998b..f8245b260 100644 --- a/source/games/duke/src/types.h +++ b/source/games/duke/src/types.h @@ -214,23 +214,25 @@ struct player_struct int8_t crouch_toggle; // input stuff. - int horizAdjust, angAdjust, pitchAdjust; + double horizAdjust, angAdjust, pitchAdjust; bool lookLeft, lookRight; // Access helpers for the widened angle and horizon fields. void setlookang(int b) { q16look_ang = b << FRACBITS; } void addlookang(int b) { q16look_ang += b << FRACBITS; } - void addlookang(double b) { q16look_ang += int(b *65536.); } + void addlookang(double b) { q16look_ang += xs_CRoundToInt(b * FRACUNIT); } void setrotscrnang(int b) { q16rotscrnang = b << FRACBITS; } void addrotscrnang(int b) { q16rotscrnang += b << FRACBITS; } - void addrotscrnang(double b) { q16rotscrnang += int(b *65536.); } + void addrotscrnang(double b) { q16rotscrnang += xs_CRoundToInt(b * FRACUNIT); } int getang() { return q16ang >> FRACBITS; } int getoang() { return oq16ang >> FRACBITS; } - void setang(int v, bool smooth = false) { q16ang = v << FRACBITS; } + void setang(int v) { q16ang = v << FRACBITS; } + void addang(int v) { q16ang = (q16ang + (v << FRACBITS)) & 0x7FFFFFF; } void setoang(int v) { oq16ang = v << FRACBITS; } + void addhoriz(int v) { q16horiz += (v << FRACBITS); } void addhorizoff(int v) { q16horiz += (v << FRACBITS); } - void addhorizoff(double v) { q16horiz += int(v * 65536.); } + void addhorizoff(double v) { q16horiz += xs_CRoundToInt(v * FRACUNIT); } void sethoriz(int v) { q16horiz = (v << FRACBITS); } void sethorizoff(int v) { q16horizoff = (v << FRACBITS); } int gethoriz() { return q16horiz >> FRACBITS; }