diff --git a/Processes/Proposal/ContinuousProcess.cc b/Processes/Proposal/ContinuousProcess.cc
index d222a80b121e21c7de1de50e03fd1df820f026f4..53eddcc85e810cd6cd1c00b99ee1033931209d65 100644
--- a/Processes/Proposal/ContinuousProcess.cc
+++ b/Processes/Proposal/ContinuousProcess.cc
@@ -59,20 +59,46 @@ namespace corsika::process::proposal {
     }
   }
 
+  template <>
   HEPEnergyType ContinuousProcess::TotalEnergyLoss(SetupParticle const& vP,
-                                                   GrammageType const vDX) {
-    std::cout << "distance: " << vDX / 1_g * 1_cm * 1_cm << std::endl;
-    return vP.GetEnergy() - GetCalculator(vP)->second->UpperLimitTrackIntegral(
-                                vP.GetEnergy() / 1_MeV, vDX / 1_g * 1_cm * 1_cm) *
+                                                   GrammageType const& vDX) {
+    auto calc = GetCalculator(vP);
+    return vP.GetEnergy() - get<DISPLACEMENT>(calc->second)
+                                    ->UpperLimitTrackIntegral(vP.GetEnergy() / 1_MeV,
+                                                              vDX / 1_g * 1_cm * 1_cm) *
                                 1_MeV;
   }
 
+  template <>
+  void ContinuousProcess::Scatter(SetupParticle& vP, HEPEnergyType const& loss,
+                                           GrammageType const& grammage) {
+    auto calc = GetCalculator(vP);
+    auto d = vP.GetDirection().GetComponents();
+    auto direction = PROPOSAL::Vector3D(d.GetX().magnitude(), d.GetY().magnitude(),
+                                        d.GetZ().magnitude());
+    auto E_f = vP.GetEnergy() - loss; // final energy
+    std::uniform_real_distribution<double> distr(0., 1.);
+    auto rnd = array<double, 4>();
+    for (auto& it : rnd) it = distr(fRNG);
+    auto [mean_dir, final_dir] =
+        get<SCATTERING>(calc->second)
+            ->Scatter(grammage / 1_g * square(1_cm), vP.GetEnergy() / 1_MeV, E_f / 1_MeV,
+                      direction, rnd);
+    auto vec = corsika::geometry::QuantityVector(
+        final_dir.GetX() * E_f, final_dir.GetY() * E_f, final_dir.GetZ() * E_f);
+    vP.SetMomentum(corsika::stack::MomentumVector(
+        corsika::geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(),
+        vec));
+  }
+
   template <>
   EProcessReturn ContinuousProcess::DoContinuous(SetupParticle& vP,
                                                  SetupTrack const& vT) {
     if (vP.GetChargeNumber() == 0) return process::EProcessReturn::eOk;
     auto dX = vP.GetNode()->GetModelProperties().IntegratedGrammage(vT, vT.GetLength());
-    vP.SetEnergy(vP.GetEnergy() - TotalEnergyLoss(vP, dX));
+    auto energy_loss = TotalEnergyLoss(vP, dX);
+    Scatter(vP, energy_loss, dX);
+    vP.SetEnergy(vP.GetEnergy() - energy_loss);
     if (vP.GetEnergy() < cut.GetECut()) return process::EProcessReturn::eParticleAbsorbed;
     vP.SetMomentum(vP.GetMomentum() * vP.GetEnergy() / vP.GetMomentum().GetNorm());
     return process::EProcessReturn::eOk;
@@ -82,8 +108,9 @@ namespace corsika::process::proposal {
   units::si::LengthType ContinuousProcess::MaxStepLength(SetupParticle const& vP,
                                                          SetupTrack const& vT) {
     auto energy_lim = 0.9 * vP.GetEnergy() / 1_MeV;
-    auto grammage = GetCalculator(vP)->second->SolveTrackIntegral(vP.GetEnergy() / 1_MeV,
-                                                                  energy_lim) *
+    auto calc = GetCalculator(vP);
+    auto grammage = get<DISPLACEMENT>(calc->second)
+                        ->SolveTrackIntegral(vP.GetEnergy() / 1_MeV, energy_lim) *
                     1_g / square(1_cm);
     return vP.GetNode()->GetModelProperties().ArclengthFromGrammage(vT, grammage) *
            1.0001;
diff --git a/Processes/Proposal/ContinuousProcess.h b/Processes/Proposal/ContinuousProcess.h
index e0cfe6e2679fda8389c44a230160c571a81b0b9b..7a42c122430eac408bf6939152d71edeba48dc9f 100644
--- a/Processes/Proposal/ContinuousProcess.h
+++ b/Processes/Proposal/ContinuousProcess.h
@@ -37,10 +37,11 @@ namespace corsika::process::proposal {
     static unordered_map<particles::Code, PROPOSAL::ParticleDef> particles;
     unordered_map<const NuclearComposition*, PROPOSAL::Medium> media;
 
-
     bool CanInteract(particles::Code pcode) const noexcept;
 
     using calc_key_t = std::pair<const NuclearComposition*, particles::Code>;
+    using calc_t =
+        tuple<unique_ptr<PROPOSAL::Displacement>, unique_ptr<PROPOSAL::Scattering>>;
 
     struct disp_hash {
       size_t operator()(const calc_key_t& p) const {
@@ -49,18 +50,21 @@ namespace corsika::process::proposal {
       }
     };
 
-    unordered_map<calc_key_t, unique_ptr<PROPOSAL::Displacement>, disp_hash> calc;
+    enum { DISPLACEMENT, SCATTERING };
+    unordered_map<calc_key_t, calc_t, disp_hash> calc;
 
     template <typename Particle>
     auto BuildCalculator(particles::Code code, Particle p_def,
                          NuclearComposition const& comp) {
-      auto medium = media.at(&comp);
       auto cross = GetStdCrossSections(
           p_def, media.at(&comp),
           make_shared<const PROPOSAL::EnergyCutSettings>(cut.GetECut() / 1_MeV, 1, false),
           true);
-      auto [insert_it, success] = calc.insert(
-          {std::make_pair(&comp, code), PROPOSAL::make_displacement(cross, true)});
+      auto [insert_it, success] =
+          calc.insert({std::make_pair(&comp, code),
+                       std::make_tuple(PROPOSAL::make_displacement(cross, true),
+                                       PROPOSAL::make_scattering("highland", p_def,
+                                                                 media.at(&comp)))});
       return insert_it;
     }
 
@@ -90,20 +94,25 @@ namespace corsika::process::proposal {
       return BuildCalculator(vP.GetPID(), comp);
     }
 
-    units::si::HEPEnergyType TotalEnergyLoss(setup::Stack::ParticleType const&,
-                                             const units::si::GrammageType);
-
   public:
     template <typename TEnvironment>
-    ContinuousProcess(TEnvironment const& env, CORSIKA_ParticleCut& cut);
+    ContinuousProcess(TEnvironment const&, CORSIKA_ParticleCut&);
 
     void Init(){};
 
+    template <typename Particle>
+    corsika::units::si::HEPEnergyType TotalEnergyLoss(
+        Particle const&, corsika::units::si::GrammageType const&);
+
+    template <typename Particle>
+    void Scatter(Particle&, corsika::units::si::HEPEnergyType const&,
+                 corsika::units::si::GrammageType const&);
+
     template <typename Particle, typename Track>
     EProcessReturn DoContinuous(Particle&, Track const&);
 
     template <typename Particle, typename Track>
-    units::si::LengthType MaxStepLength(Particle const& p, Track const& track);
+    corsika::units::si::LengthType MaxStepLength(Particle const&, Track const&);
   };
 } // namespace corsika::process::proposal