private void MakePredictionKillReal(RemoteBulletState state) { switch (state) { case RemoteBulletState.Dying_Explosion: Alive = false; break; case RemoteBulletState.Dying_ShrinkFast: AddEntityOperation(new BulletDelayedDieOperation(0.15f)); break; case RemoteBulletState.Dying_ShrinkSlow: AddEntityOperation(new BulletDelayedDieOperation(0.35f)); break; case RemoteBulletState.Dying_Fade: AddEntityOperation(new BulletDelayedDieOperation(0.05f)); break; case RemoteBulletState.Dying_FadeSlow: AddEntityOperation(new BulletDelayedDieOperation(1f)); break; case RemoteBulletState.Dying_Instant: Alive = false; break; case RemoteBulletState.Normal: default: SAMLog.Error("RBULL::EnumSwitch_MPKR", "Invalid value: " + state); break; } }
public void RemoteUpdate(RemoteBulletState state, float px, float py, Vector2 veloc, Fraction fraction, float scale, long seq, float sendertime) { if (Math.Abs(Scale - scale) > 0.01f) { SAMLog.Error("RBULL::CHANGE-SCALE", $"Remote changed scale from {Scale} to {scale} "); } if (fraction != Fraction) { SAMLog.Error("RBULL::CHANGE-FRAC", $"Remote changed fraction from {Fraction} to {fraction} "); } Scale = scale; Fraction = fraction; var delta = GDOwner.LevelTime - sendertime; if (state == RemoteBulletState.Normal) { if (PredictionState == RemoteBulletState.Normal) { // all good BulletVelocity = veloc; var newpos = new FPoint(px, py) + BulletVelocity * delta * GDOwner.GameSpeed; ClientPredictionMiss = (newpos - BulletPosition).LengthSquared() > 1f; BulletPosition = newpos; LastRemotePosition = new FPoint(px, py); PhysicsBody.Position = ConvertUnits2.ToSimUnits(BulletPosition); PhysicsBody.LinearVelocity = ConvertUnits.ToSimUnits(veloc); RemoteState = state; } else { if (sendertime - DEATH_PREDICTION_TOLERANCE >= TimeOfPredictedDeath) { // prediction said we should be death - was wrong SAMLog.Debug("Revert prediction-miss: (Revive wrongfully killed bullet)"); // Well, I'm sorry ... I guess AbortAllOperations(o => o.Name == BulletShrinkAndDieOperation.NAME); AbortAllOperations(o => o.Name == BulletFadeAndDieOperation.NAME); BulletAlpha = 1f; BulletExtraScale = 1f; BulletVelocity = veloc; BulletPosition = new FPoint(px, py) + BulletVelocity * delta * GDOwner.GameSpeed; ClientPredictionMiss = true; LastRemotePosition = new FPoint(px, py); PhysicsBody.Position = ConvertUnits2.ToSimUnits(BulletPosition); PhysicsBody.LinearVelocity = ConvertUnits.ToSimUnits(veloc); RemoteState = state; PredictionState = state; } else { // we will (predictably) die in the future } } } else { if (PredictionState != RemoteBulletState.Normal) { if (state != PredictionState) { // Prediction was correct but death cause was wrong (wtf??) AbortAllOperations(o => o.Name == BulletShrinkAndDieOperation.NAME); AbortAllOperations(o => o.Name == BulletFadeAndDieOperation.NAME); BulletAlpha = 1f; BulletExtraScale = 1f; BulletPosition = new FPoint(px, py); BulletVelocity = veloc; LastRemotePosition = BulletPosition; PhysicsBody.Position = ConvertUnits2.ToSimUnits(BulletPosition); PhysicsBody.LinearVelocity = ConvertUnits.ToSimUnits(veloc); RemoteState = state; PredictionState = state; PredictKill(state, true); } else { // Prediction was right (lucky path) BulletPosition = new FPoint(px, py); BulletVelocity = veloc; LastRemotePosition = BulletPosition; PhysicsBody.Position = ConvertUnits2.ToSimUnits(BulletPosition); PhysicsBody.LinearVelocity = ConvertUnits.ToSimUnits(veloc); RemoteState = state; MakePredictionKillReal(state); } } else { // dead but no death prediction BulletPosition = new FPoint(px, py); BulletVelocity = veloc; LastRemotePosition = BulletPosition; PhysicsBody.Position = ConvertUnits2.ToSimUnits(BulletPosition); PhysicsBody.LinearVelocity = ConvertUnits.ToSimUnits(veloc); RemoteState = state; PredictionState = state; PredictKill(state, true); MainGame.Inst.GDSound.PlayEffectCollision(); } if (GDOwner.RemoteBulletMapping[BulletID] == this) { GDOwner.RemoteBulletMapping[BulletID] = null; } } LastUpdateBigSeq = seq; }
private void PredictKill(RemoteBulletState prediction, bool killReal = false) { TimeOfPredictedDeath = GDOwner.LevelTime; PredictionState = prediction; switch (prediction) { case RemoteBulletState.Dying_Explosion: if (MainGame.Inst.Profile.EffectsEnabled) { for (int i = 0; i < 8; i++) { Manager.AddEntity(new BulletSplitter(Owner, this, (FlatAlign8)i)); } } if (killReal) { Alive = false; } else { BulletAlpha = 0f; } break; case RemoteBulletState.Dying_ShrinkFast: AddEntityOperation(new BulletShrinkAndDieOperation(0.15f, killReal)); break; case RemoteBulletState.Dying_ShrinkSlow: AddEntityOperation(new BulletShrinkAndDieOperation(0.35f, killReal)); break; case RemoteBulletState.Dying_Fade: AddEntityOperation(new BulletFadeAndDieOperation(0.05f, killReal)); break; case RemoteBulletState.Dying_FadeSlow: AddEntityOperation(new BulletFadeAndDieOperation(1f, killReal)); break; case RemoteBulletState.Dying_Instant: if (killReal) { Alive = false; } else { BulletAlpha = 0f; } break; case RemoteBulletState.Normal: default: SAMLog.Error("RBULL::EnumSwitch_PK", "Invalid value: " + prediction); break; } BulletVelocity = Vector2.Zero; PhysicsBody.LinearVelocity = Vector2.Zero; }