LCOV - code coverage report
Current view: top level - core/physics - SoldierPhysics.cpp (source / functions) Coverage Total Hit
Test: coverage-src.info Lines: 0.0 % 427 0
Test Date: 2025-05-27 23:26:07 Functions: 0.0 % 15 0

            Line data    Source code
       1              : #include "SoldierPhysics.hpp"
       2              : 
       3              : #include <math.h>
       4              : 
       5              : #include "core/animations/AnimationData.hpp"
       6              : #include "core/animations/AnimationState.hpp"
       7              : #include "core/physics/SoldierPhysics.hpp"
       8              : #include "core/physics/SoldierSkeletonPhysics.hpp"
       9              : 
      10              : #include "core/math/Calc.hpp"
      11              : #include "core/entities/Bullet.hpp"
      12              : #include "core/types/TeamType.hpp"
      13              : #include "core/types/WeaponType.hpp"
      14              : #include "core/entities/WeaponParametersFactory.hpp"
      15              : 
      16              : #include "core/physics/Constants.hpp"
      17              : 
      18              : #include "spdlog/spdlog.h"
      19              : 
      20              : #include <cmath>
      21              : #include <utility>
      22              : #include <vector>
      23              : #include <algorithm>
      24              : 
      25              : namespace Soldank::SoldierPhysics
      26              : {
      27            0 : const Weapon& GetPrimaryWeapon(Soldier& soldier)
      28              : {
      29            0 :     return soldier.weapons[soldier.active_weapon];
      30              : }
      31              : 
      32            0 : const Weapon& GetSecondaryWeapon(Soldier& soldier)
      33              : {
      34            0 :     return soldier.weapons[(soldier.active_weapon + 1) % 2];
      35              : }
      36              : 
      37            0 : const Weapon& GetTertiaryWeapon(Soldier& soldier)
      38              : {
      39            0 :     return soldier.weapons[2];
      40              : }
      41              : 
      42            0 : void SwitchWeapon(Soldier& soldier)
      43              : {
      44            0 :     int new_active_weapon = (soldier.active_weapon + 1) % 2;
      45            0 :     soldier.active_weapon = new_active_weapon;
      46              :     // weapons[new_active_weapon].start_up_time_count =
      47              :     //   weapons[new_active_weapon].GetWeaponParameters().start_up_time;
      48            0 :     soldier.weapons[new_active_weapon].ResetStartUpTimeCount();
      49              :     // weapons[new_active_weapon].reload_time_prev = weapons[new_active_weapon].reload_time_count;
      50            0 :     soldier.weapons[new_active_weapon].SetReloadTimePrev(
      51            0 :       soldier.weapons[new_active_weapon].GetReloadTimeCount());
      52            0 : }
      53              : 
      54            0 : void UpdateKeys(Soldier& soldier, const Control& control)
      55              : {
      56            0 :     soldier.control = control;
      57            0 : }
      58              : 
      59            0 : void HandleSpecialPolytypes(const Map& map, PMSPolygonType polytype, Soldier& soldier)
      60              : {
      61            0 :     if (polytype == PMSPolygonType::Deadly || polytype == PMSPolygonType::BloodyDeadly ||
      62              :         polytype == PMSPolygonType::Explosive) {
      63            0 :         soldier.particle.position = glm::vec2(map.GetSpawnPoints()[0].x, map.GetSpawnPoints()[0].y);
      64              :     }
      65            0 : }
      66              : 
      67            0 : void Update(StateManager& state_manager,
      68              :             Soldier& soldier,
      69              :             const PhysicsEvents& physics_events,
      70              :             const AnimationDataManager& animation_data_manager,
      71              :             std::vector<BulletParams>& bullet_emitter,
      72              :             float gravity)
      73              : {
      74            0 :     const Map& map = state_manager.GetConstMap();
      75            0 :     float body_y = 0.0F;
      76            0 :     float arm_s = 0.0F;
      77              : 
      78            0 :     soldier.particle.Euler();
      79              : 
      80            0 :     if (!soldier.control.fire) {
      81            0 :         soldier.is_shooting = false;
      82              :     }
      83              : 
      84            0 :     if (soldier.legs_animation->GetSpeed() < 1) {
      85            0 :         soldier.legs_animation->SetSpeed(1);
      86              :     }
      87              : 
      88            0 :     if (soldier.legs_animation->GetSpeed() < 1) {
      89            0 :         soldier.legs_animation->SetSpeed(1);
      90              :     }
      91              : 
      92            0 :     if (soldier.body_animation->GetSpeed() < 1) {
      93            0 :         soldier.body_animation->SetSpeed(1);
      94              :     }
      95              : 
      96            0 :     auto conflicting_keys_pressed = [](const Control& c) {
      97            0 :         return ((int)c.throw_grenade + (int)c.change + (int)c.drop + (int)c.reload) > 1;
      98              :     };
      99              : 
     100              :     // Handle simultaneous key presses that would conflict
     101            0 :     if (conflicting_keys_pressed(soldier.control)) {
     102              :         // At least two buttons pressed, so deactivate any previous one
     103            0 :         if (soldier.control.was_throwing_grenade) {
     104            0 :             soldier.control.throw_grenade = false;
     105            0 :         } else if (soldier.control.was_changing_weapon) {
     106            0 :             soldier.control.change = false;
     107            0 :         } else if (soldier.control.was_throwing_weapon) {
     108            0 :             soldier.control.drop = false;
     109            0 :         } else if (soldier.control.was_reloading_weapon) {
     110            0 :             soldier.control.reload = false;
     111              :         }
     112              : 
     113              :         // If simultaneously pressing two or more new buttons, then deactivate them
     114              :         // in order of least preference
     115            0 :         while (conflicting_keys_pressed(soldier.control)) {
     116            0 :             if (soldier.control.reload) {
     117            0 :                 soldier.control.reload = false;
     118            0 :             } else if (soldier.control.change) {
     119            0 :                 soldier.control.change = false;
     120            0 :             } else if (soldier.control.drop) {
     121            0 :                 soldier.control.drop = false;
     122            0 :             } else if (soldier.control.throw_grenade) {
     123            0 :                 soldier.control.throw_grenade = false;
     124              :             }
     125              :         }
     126              :     } else {
     127            0 :         soldier.control.was_throwing_grenade = soldier.control.throw_grenade;
     128            0 :         soldier.control.was_changing_weapon = soldier.control.change;
     129            0 :         soldier.control.was_throwing_weapon = soldier.control.drop;
     130            0 :         soldier.control.was_reloading_weapon = soldier.control.reload;
     131              :     }
     132              : 
     133              :     // self.fired = 0;
     134            0 :     soldier.control.mouse_aim_x =
     135            0 :       (int)((float)soldier.control.mouse_aim_x + soldier.particle.GetVelocity().x);
     136            0 :     soldier.control.mouse_aim_y =
     137            0 :       (int)((float)soldier.control.mouse_aim_y + soldier.particle.GetVelocity().y);
     138              : 
     139            0 :     auto maybe_new_legs_animation_state_machine = soldier.legs_animation->HandleInput(soldier);
     140            0 :     if (maybe_new_legs_animation_state_machine.has_value()) {
     141            0 :         soldier.legs_animation->Exit(soldier, physics_events);
     142            0 :         soldier.legs_animation = *maybe_new_legs_animation_state_machine;
     143            0 :         soldier.legs_animation->Enter(soldier);
     144              :     }
     145              : 
     146            0 :     soldier.body_animation->TryToShoot(soldier, physics_events);
     147            0 :     soldier.body_animation->TryToThrowFlags(soldier, physics_events);
     148            0 :     auto maybe_new_body_animation_state_machine = soldier.body_animation->HandleInput(soldier);
     149            0 :     if (maybe_new_body_animation_state_machine.has_value()) {
     150            0 :         soldier.body_animation->Exit(soldier, physics_events);
     151            0 :         soldier.body_animation = *maybe_new_body_animation_state_machine;
     152            0 :         soldier.body_animation->Enter(soldier);
     153              :     }
     154              : 
     155            0 :     soldier.legs_animation->Update(soldier, physics_events);
     156            0 :     soldier.body_animation->Update(soldier, physics_events);
     157              : 
     158            0 :     bool jets_can_be_applied = true;
     159            0 :     if (soldier.legs_animation->GetType() == AnimationType::RollBack && soldier.control.up) {
     160              :         // jets cannot be applied during RollBack animation when "up" is pressed because
     161              :         // that animation adds its forces on the soldier
     162            0 :         jets_can_be_applied = false;
     163              :     }
     164              : 
     165            0 :     if (jets_can_be_applied && soldier.control.jets && (soldier.jets_count > 0)) {
     166            0 :         if (soldier.on_ground) {
     167            0 :             glm::vec2 particle_force = soldier.particle.GetForce();
     168            0 :             if (gravity > 0.05F) {
     169            0 :                 soldier.particle.SetForce({ particle_force.x, -2.5F * PhysicsConstants::JETSPEED });
     170              :             } else {
     171            0 :                 soldier.particle.SetForce({ particle_force.x, -2.5F * (gravity * 2.0F) });
     172              :             }
     173            0 :         } else if (soldier.stance != PhysicsConstants::STANCE_PRONE) {
     174            0 :             glm::vec2 particle_force = soldier.particle.GetForce();
     175            0 :             if (gravity > 0.05F) {
     176            0 :                 soldier.particle.SetForce(
     177            0 :                   { particle_force.x, particle_force.y - PhysicsConstants::JETSPEED });
     178              :             } else {
     179            0 :                 soldier.particle.SetForce({ particle_force.x, particle_force.y - gravity * 2.0F });
     180              :             }
     181              :         } else {
     182            0 :             glm::vec2 particle_force = soldier.particle.GetForce();
     183            0 :             soldier.particle.SetForce(
     184            0 :               { particle_force.x +
     185            0 :                   (float)soldier.direction *
     186            0 :                     (gravity > 0.05F ? PhysicsConstants::JETSPEED / 2.0F : gravity),
     187              :                 particle_force.y });
     188              :         }
     189            0 :         soldier.jets_count -= 1;
     190              :     }
     191              : 
     192            0 :     RepositionSoldierSkeletonParts(soldier);
     193              : 
     194            0 :     for (int i = 1; i <= 20; i++) {
     195            0 :         if ((soldier.dead_meat || soldier.half_dead) && (i < 17) && (i != 7) && (i != 8)) {
     196            0 :             auto xy = soldier.particle.position;
     197            0 :             soldier.on_ground = CheckSkeletonMapCollision(soldier, map, i, xy.x, xy.y);
     198              :         }
     199              :     }
     200              : 
     201            0 :     if (!soldier.dead_meat) {
     202            0 :         soldier.body_animation->DoAnimation();
     203            0 :         soldier.legs_animation->DoAnimation();
     204              : 
     205            0 :         soldier.on_ground = false;
     206              : 
     207            0 :         auto xy = soldier.particle.position;
     208              : 
     209            0 :         CheckMapCollision(soldier, map, xy.x - 3.5, xy.y - 12.0, 1, physics_events);
     210              : 
     211            0 :         xy = soldier.particle.position;
     212              : 
     213            0 :         CheckMapCollision(soldier, map, xy.x + 3.5, xy.y - 12.0, 1, physics_events);
     214              : 
     215            0 :         body_y = 0.0;
     216            0 :         arm_s = 0.0;
     217              : 
     218              :         // Walking either left or right (though only one can be active at once)
     219            0 :         if (soldier.control.left ^ soldier.control.right) {
     220            0 :             if (soldier.control.left ^ (soldier.direction == 1)) {
     221              :                 // WRONG
     222            0 :                 arm_s = 0.25;
     223              :             } else {
     224            0 :                 body_y = 0.25;
     225              :             }
     226              :         }
     227              :         // If a leg is inside a polygon, caused by the modification of ArmS and
     228              :         // BodyY, this is there to not lose contact to ground on slope polygons
     229            0 :         if (std::abs(body_y) <= 0.00001) {
     230            0 :             glm::vec2 leg_vector = { soldier.particle.position.x + 2.0F,
     231            0 :                                      soldier.particle.position.y + 1.9F };
     232            0 :             float leg_distance = 0.0F;
     233            0 :             if (map.RayCast(leg_vector, leg_vector, leg_distance, 10)) {
     234            0 :                 body_y = 0.25;
     235              :             }
     236              :         }
     237            0 :         if (std::abs(arm_s) <= 0.00001) {
     238            0 :             glm::vec2 leg_vector = { soldier.particle.position.x - 2.0F,
     239            0 :                                      soldier.particle.position.y + 1.9F };
     240            0 :             float leg_distance = 0.0F;
     241            0 :             if (map.RayCast(leg_vector, leg_vector, leg_distance, 10)) {
     242            0 :                 arm_s = 0.25;
     243              :             }
     244              :         }
     245              : 
     246            0 :         xy = soldier.particle.position;
     247            0 :         soldier.on_ground =
     248            0 :           CheckMapCollision(soldier, map, xy.x + 2.0, xy.y + 2.0 - body_y, 0, physics_events);
     249              : 
     250            0 :         xy = soldier.particle.position;
     251            0 :         soldier.on_ground =
     252            0 :           soldier.on_ground ||
     253            0 :           CheckMapCollision(soldier, map, xy.x - 2.0, xy.y + 2.0 - arm_s, 0, physics_events);
     254              : 
     255            0 :         xy = soldier.particle.position;
     256            0 :         auto grounded = soldier.on_ground;
     257            0 :         soldier.on_ground_for_law =
     258            0 :           CheckRadiusMapCollision(soldier, map, xy.x, xy.y - 1.0, grounded, physics_events);
     259              : 
     260            0 :         xy = soldier.particle.position;
     261            0 :         grounded = soldier.on_ground || soldier.on_ground_for_law;
     262            0 :         soldier.on_ground =
     263            0 :           CheckMapVerticesCollision(soldier, map, xy.x, xy.y, 3.0, grounded, physics_events) ||
     264            0 :           soldier.on_ground;
     265              : 
     266            0 :         if (!(soldier.on_ground ^ soldier.on_ground_last_frame)) {
     267            0 :             soldier.on_ground_permanent = soldier.on_ground;
     268              :         }
     269              : 
     270            0 :         soldier.on_ground_last_frame = soldier.on_ground;
     271              : 
     272            0 :         if ((soldier.jets_count < map.GetJetCount()) && !(soldier.control.jets)) {
     273              :             // if self.on_ground
     274              :             /* (MainTickCounter mod 2 = 0) */
     275              :             {
     276            0 :                 soldier.jets_count += 1;
     277              :             }
     278              :         }
     279            0 :         soldier.alpha = 255;
     280              : 
     281            0 :         state_manager.TransformItems([&](auto& item) {
     282            0 :             if (item.holding_soldier_id == soldier.id && item.style == ItemType::Parachute) {
     283            0 :                 glm::vec2 force = soldier.particle.GetForce();
     284            0 :                 soldier.particle.SetForce(
     285              :                   { force.x, PhysicsConstants::SOLDIER_SPEED_WITH_PARACHUTE });
     286              :                 // {$IFDEF SERVER}
     287              :                 // if CeaseFireCounter < 1 then
     288              :                 // {$ELSE}
     289              :                 // if ((sv_survivalmode.Value) and (CeaseFireCounter < CeaseFireTime * 3 - 30)) or
     290              :                 //    (CeaseFireCounter < CeaseFireTime - 30) then
     291              :                 // {$ENDIF}
     292            0 :                 if (soldier.on_ground || soldier.control.jets) {
     293            0 :                     item.holding_soldier_id = 0;
     294              :                     // TODO
     295              :                     // Dec(Thing[HoldedThing].Skeleton.ConstraintCount);
     296            0 :                     item.time_out = 3 * 60;
     297              :                     // HoldedThing := 0;
     298              :                 }
     299              :             }
     300            0 :         });
     301              : 
     302            0 :         soldier.skeleton->DoVerletTimestepFor(22, 29);
     303            0 :         soldier.skeleton->DoVerletTimestepFor(24, 30);
     304              :     }
     305              : 
     306            0 :     if (soldier.dead_meat) {
     307            0 :         soldier.skeleton->DoVerletTimestep();
     308            0 :         soldier.particle.position = soldier.skeleton->GetPos(12);
     309              :         // CheckSkeletonOutOfBounds;
     310              : 
     311            0 :         state_manager.TransformItems([&](auto& item) {
     312            0 :             if (item.holding_soldier_id == soldier.id && item.style == ItemType::Parachute) {
     313            0 :                 glm::vec2 force = soldier.skeleton->GetForce(12);
     314            0 :                 soldier.skeleton->SetForce(
     315              :                   12, { force.x, 25 * PhysicsConstants::SOLDIER_SPEED_WITH_PARACHUTE });
     316            0 :                 if (soldier.on_ground) {
     317            0 :                     item.holding_soldier_id = 0;
     318              :                     // TODO
     319              :                     // Dec(Thing[HoldedThing].Skeleton.ConstraintCount);
     320            0 :                     item.time_out = 3 * 60;
     321              :                 }
     322              :             }
     323            0 :         });
     324              :     }
     325              : 
     326            0 :     if (soldier.particle.velocity_.x > PhysicsConstants::MAX_VELOCITY) {
     327            0 :         soldier.particle.velocity_.x = PhysicsConstants::MAX_VELOCITY;
     328              :     }
     329            0 :     if (soldier.particle.velocity_.x < -PhysicsConstants::MAX_VELOCITY) {
     330            0 :         soldier.particle.velocity_.x = -PhysicsConstants::MAX_VELOCITY;
     331              :     }
     332            0 :     if (soldier.particle.velocity_.y > PhysicsConstants::MAX_VELOCITY) {
     333            0 :         soldier.particle.velocity_.y = PhysicsConstants::MAX_VELOCITY;
     334              :     }
     335            0 :     if (soldier.particle.velocity_.y < -PhysicsConstants::MAX_VELOCITY) {
     336            0 :         soldier.particle.velocity_.y = -PhysicsConstants::MAX_VELOCITY;
     337              :     }
     338            0 : }
     339              : 
     340            0 : bool CheckMapCollision(Soldier& soldier,
     341              :                        const Map& map,
     342              :                        float x,
     343              :                        float y,
     344              :                        int area,
     345              :                        const PhysicsEvents& physics_events)
     346              : {
     347            0 :     auto pos = glm::vec2(x, y) + soldier.particle.velocity_;
     348            0 :     auto rx = ((int)std::round((pos.x / (float)map.GetSectorsSize()))) + 25;
     349            0 :     auto ry = ((int)std::round((pos.y / (float)map.GetSectorsSize()))) + 25;
     350              : 
     351            0 :     if ((rx > 0) && (rx < map.GetSectorsCount() + 25) && (ry > 0) &&
     352            0 :         (ry < map.GetSectorsCount() + 25)) {
     353            0 :         for (int j = 0; j < map.GetSector(rx, ry).polygons.size(); j++) {
     354            0 :             auto poly = map.GetSector(rx, ry).polygons[j] - 1;
     355            0 :             auto polytype = map.GetPolygons()[poly].polygon_type;
     356              : 
     357            0 :             if ((polytype != PMSPolygonType::NoCollide) &&
     358              :                 (polytype != PMSPolygonType::OnlyBulletsCollide)) {
     359            0 :                 auto polygons = map.GetPolygons()[poly];
     360              : 
     361            0 :                 if (Map::PointInPoly(pos, polygons)) {
     362            0 :                     HandleSpecialPolytypes(map, polytype, soldier);
     363              : 
     364            0 :                     auto dist = 0.0F;
     365            0 :                     auto k = 0;
     366              : 
     367            0 :                     auto perp = map.ClosestPerpendicular(poly, pos, &dist, &k);
     368              : 
     369            0 :                     auto step = perp;
     370              : 
     371            0 :                     perp = Calc::Vec2Normalize(perp);
     372            0 :                     perp *= dist;
     373            0 :                     dist = Calc::Vec2Length(soldier.particle.velocity_);
     374              : 
     375            0 :                     if (Calc::Vec2Length(perp) > dist) {
     376            0 :                         perp = Calc::Vec2Normalize(perp);
     377            0 :                         perp *= dist;
     378              :                     }
     379            0 :                     if ((area == 0) ||
     380            0 :                         ((area == 1) &&
     381            0 :                          ((soldier.particle.velocity_.y < 0.0) ||
     382            0 :                           (soldier.particle.velocity_.x > PhysicsConstants::SLIDELIMIT) ||
     383            0 :                           (soldier.particle.velocity_.x < -PhysicsConstants::SLIDELIMIT)))) {
     384            0 :                         soldier.particle.old_position = soldier.particle.position;
     385            0 :                         soldier.particle.position -= perp;
     386            0 :                         if (map.GetPolygons()[poly].polygon_type == PMSPolygonType::Bouncy) {
     387            0 :                             perp = Calc::Vec2Normalize(perp);
     388            0 :                             perp *= map.GetPolygons()[poly].bounciness * dist;
     389              :                         }
     390            0 :                         soldier.particle.velocity_ -= perp;
     391              :                     }
     392              : 
     393            0 :                     if (area == 0) {
     394            0 :                         if ((soldier.legs_animation->GetType() == AnimationType::Stand) ||
     395            0 :                             (soldier.legs_animation->GetType() == AnimationType::Crouch) ||
     396            0 :                             (soldier.legs_animation->GetType() == AnimationType::Prone) ||
     397            0 :                             (soldier.legs_animation->GetType() == AnimationType::ProneMove) ||
     398            0 :                             (soldier.legs_animation->GetType() == AnimationType::GetUp) ||
     399            0 :                             (soldier.legs_animation->GetType() == AnimationType::Fall) ||
     400            0 :                             (soldier.legs_animation->GetType() == AnimationType::Mercy) ||
     401            0 :                             (soldier.legs_animation->GetType() == AnimationType::Mercy2) ||
     402            0 :                             (soldier.legs_animation->GetType() == AnimationType::Own)) {
     403            0 :                             if ((soldier.particle.velocity_.x < PhysicsConstants::SLIDELIMIT) &&
     404            0 :                                 (soldier.particle.velocity_.x > -PhysicsConstants::SLIDELIMIT) &&
     405            0 :                                 (step.y > PhysicsConstants::SLIDELIMIT)) {
     406            0 :                                 soldier.particle.position = soldier.particle.old_position;
     407            0 :                                 glm::vec2 particle_force = soldier.particle.GetForce();
     408            0 :                                 particle_force.y -= PhysicsConstants::GRAV;
     409            0 :                                 soldier.particle.SetForce(particle_force);
     410              :                             }
     411              : 
     412            0 :                             if ((step.y > PhysicsConstants::SLIDELIMIT) &&
     413            0 :                                 (polytype != PMSPolygonType::Ice) &&
     414              :                                 (polytype != PMSPolygonType::Bouncy)) {
     415            0 :                                 if ((soldier.legs_animation->GetType() == AnimationType::Stand) ||
     416            0 :                                     (soldier.legs_animation->GetType() == AnimationType::Fall) ||
     417            0 :                                     (soldier.legs_animation->GetType() == AnimationType::Crouch)) {
     418            0 :                                     soldier.particle.velocity_.x *=
     419              :                                       PhysicsConstants::STANDSURFACECOEFX;
     420            0 :                                     soldier.particle.velocity_.y *=
     421              :                                       PhysicsConstants::STANDSURFACECOEFY;
     422              : 
     423            0 :                                     glm::vec2 particle_force = soldier.particle.GetForce();
     424            0 :                                     particle_force.x -= soldier.particle.velocity_.x;
     425            0 :                                     soldier.particle.SetForce(particle_force);
     426            0 :                                 } else if (soldier.legs_animation->GetType() ==
     427              :                                            AnimationType::Prone) {
     428            0 :                                     if (soldier.legs_animation->GetFrame() > 24) {
     429            0 :                                         if (!(soldier.control.down &&
     430            0 :                                               (soldier.control.left || soldier.control.right))) {
     431            0 :                                             soldier.particle.velocity_.x *=
     432              :                                               PhysicsConstants::STANDSURFACECOEFX;
     433            0 :                                             soldier.particle.velocity_.y *=
     434              :                                               PhysicsConstants::STANDSURFACECOEFY;
     435              : 
     436            0 :                                             glm::vec2 particle_force = soldier.particle.GetForce();
     437            0 :                                             particle_force.x -= soldier.particle.velocity_.x;
     438            0 :                                             soldier.particle.SetForce(particle_force);
     439              :                                         }
     440              :                                     } else {
     441            0 :                                         soldier.particle.velocity_.x *=
     442              :                                           PhysicsConstants::SURFACECOEFX;
     443            0 :                                         soldier.particle.velocity_.y *=
     444              :                                           PhysicsConstants::SURFACECOEFY;
     445              :                                     }
     446            0 :                                 } else if (soldier.legs_animation->GetType() ==
     447              :                                            AnimationType::GetUp) {
     448            0 :                                     soldier.particle.velocity_.x *= PhysicsConstants::SURFACECOEFX;
     449            0 :                                     soldier.particle.velocity_.y *= PhysicsConstants::SURFACECOEFY;
     450            0 :                                 } else if (soldier.legs_animation->GetType() ==
     451              :                                            AnimationType::ProneMove) {
     452            0 :                                     soldier.particle.velocity_.x *=
     453              :                                       PhysicsConstants::STANDSURFACECOEFX;
     454            0 :                                     soldier.particle.velocity_.y *=
     455              :                                       PhysicsConstants::STANDSURFACECOEFY;
     456              :                                 }
     457              :                             }
     458            0 :                         } else if ((soldier.legs_animation->GetType() ==
     459            0 :                                     AnimationType::CrouchRun) ||
     460            0 :                                    (soldier.legs_animation->GetType() ==
     461              :                                     AnimationType::CrouchRunBack)) {
     462            0 :                             soldier.particle.velocity_.x *=
     463              :                               PhysicsConstants::CROUCHMOVESURFACECOEFX;
     464            0 :                             soldier.particle.velocity_.y *=
     465              :                               PhysicsConstants::CROUCHMOVESURFACECOEFY;
     466              :                         } else {
     467            0 :                             soldier.particle.velocity_.x *= PhysicsConstants::SURFACECOEFX;
     468            0 :                             soldier.particle.velocity_.y *= PhysicsConstants::SURFACECOEFY;
     469              :                         }
     470              :                     }
     471              : 
     472            0 :                     physics_events.soldier_collides_with_polygon.Notify(soldier, polygons);
     473            0 :                     return true;
     474              :                 }
     475              :             }
     476              :         }
     477              :     }
     478              : 
     479            0 :     return false;
     480              : }
     481              : 
     482            0 : bool CheckMapVerticesCollision(Soldier& soldier,
     483              :                                const Map& map,
     484              :                                float x,
     485              :                                float y,
     486              :                                float r,
     487              :                                bool has_collided,
     488              :                                const PhysicsEvents& physics_events)
     489              : {
     490            0 :     auto pos = glm::vec2(x, y);
     491            0 :     auto rx = ((int)std::round(pos.x / (float)map.GetSectorsSize())) + 25;
     492            0 :     auto ry = ((int)std::round(pos.y / (float)map.GetSectorsSize())) + 25;
     493              : 
     494            0 :     if ((rx > 0) && (rx < map.GetSectorsCount() + 25) && (ry > 0) &&
     495            0 :         (ry < map.GetSectorsCount() + 25)) {
     496            0 :         for (int j = 0; j < map.GetSector(rx, ry).polygons.size(); ++j) {
     497            0 :             auto poly = map.GetSector(rx, ry).polygons[j] - 1;
     498            0 :             PMSPolygonType polytype = map.GetPolygons()[poly].polygon_type;
     499              : 
     500              :             // TODO: this if has more poly types
     501            0 :             if (polytype != PMSPolygonType::NoCollide &&
     502              :                 polytype != PMSPolygonType::OnlyBulletsCollide) {
     503            0 :                 for (int i = 0; i < 3; i++) {
     504            0 :                     auto vert = glm::vec2(map.GetPolygons()[poly].vertices[i].x,
     505            0 :                                           map.GetPolygons()[poly].vertices[i].y);
     506              : 
     507            0 :                     auto dist = Calc::Distance(vert, pos);
     508            0 :                     if (dist < r) {
     509            0 :                         if (!has_collided) {
     510            0 :                             HandleSpecialPolytypes(map, polytype, soldier);
     511              :                         }
     512            0 :                         auto dir = pos - vert;
     513            0 :                         dir = Calc::Vec2Normalize(dir);
     514            0 :                         soldier.particle.position += dir;
     515            0 :                         physics_events.soldier_collides_with_polygon.Notify(
     516            0 :                           soldier, map.GetPolygons()[poly]);
     517              : 
     518            0 :                         return true;
     519              :                     }
     520              :                 }
     521              :             }
     522              :         }
     523              :     }
     524            0 :     return false;
     525              : }
     526              : 
     527            0 : bool CheckRadiusMapCollision(Soldier& soldier,
     528              :                              const Map& map,
     529              :                              float x,
     530              :                              float y,
     531              :                              bool has_collided,
     532              :                              const PhysicsEvents& physics_events)
     533              : {
     534            0 :     auto s_pos = glm::vec2(x, y - 3.0f);
     535              : 
     536            0 :     auto det_acc = (int)Calc::Vec2Length(soldier.particle.velocity_);
     537            0 :     if (det_acc == 0) {
     538            0 :         det_acc = 1;
     539              :     }
     540              : 
     541            0 :     auto step = soldier.particle.velocity_ * (1.0f / (float)det_acc);
     542              : 
     543            0 :     for (int _z = 0; _z < det_acc; _z++) {
     544            0 :         s_pos += step;
     545              : 
     546            0 :         auto rx = ((int)std::round(s_pos.x / (float)map.GetSectorsSize())) + 25;
     547            0 :         auto ry = ((int)std::round(s_pos.y / (float)map.GetSectorsSize())) + 25;
     548              : 
     549            0 :         if ((rx > 0) && (rx < map.GetSectorsCount() + 25) && (ry > 0) &&
     550            0 :             (ry < map.GetSectorsCount() + 25)) {
     551            0 :             for (int j = 0; j < map.GetSector(rx, ry).polygons.size(); j++) {
     552            0 :                 auto poly = map.GetSector(rx, ry).polygons[j] - 1;
     553            0 :                 auto polytype = map.GetPolygons()[poly].polygon_type;
     554              : 
     555            0 :                 if (polytype != PMSPolygonType::NoCollide &&
     556              :                     polytype != PMSPolygonType::OnlyBulletsCollide) {
     557            0 :                     for (int k = 0; k < 2; k++) { // TODO: czy tu powinno być k < 3?
     558            0 :                         auto norm = glm::vec2(map.GetPolygons()[poly].perpendiculars[k].x,
     559            0 :                                               map.GetPolygons()[poly].perpendiculars[k].y);
     560            0 :                         norm *= -PhysicsConstants::SOLDIER_COL_RADIUS;
     561              : 
     562            0 :                         auto pos = s_pos + norm;
     563              : 
     564            0 :                         if (map.PointInPolyEdges(pos.x, pos.y, poly)) {
     565            0 :                             if (!has_collided) {
     566            0 :                                 HandleSpecialPolytypes(map, polytype, soldier);
     567              :                             }
     568            0 :                             auto d = 0.0f;
     569            0 :                             auto b = 0;
     570            0 :                             auto perp = map.ClosestPerpendicular(poly, pos, &d, &b);
     571              : 
     572            0 :                             auto p1 = glm::vec2(0.0, 0.0);
     573            0 :                             auto p2 = glm::vec2(0.0, 0.0);
     574            0 :                             switch (b) {
     575            0 :                                 case 1: {
     576            0 :                                     p1 = glm::vec2(map.GetPolygons()[poly].vertices[0].x,
     577            0 :                                                    map.GetPolygons()[poly].vertices[0].y);
     578            0 :                                     p2 = glm::vec2(map.GetPolygons()[poly].vertices[1].x,
     579            0 :                                                    map.GetPolygons()[poly].vertices[1].y);
     580            0 :                                     break;
     581              :                                 }
     582            0 :                                 case 2: {
     583            0 :                                     p1 = glm::vec2(map.GetPolygons()[poly].vertices[1].x,
     584            0 :                                                    map.GetPolygons()[poly].vertices[1].y);
     585            0 :                                     p2 = glm::vec2(map.GetPolygons()[poly].vertices[2].x,
     586            0 :                                                    map.GetPolygons()[poly].vertices[2].y);
     587            0 :                                     break;
     588              :                                 }
     589            0 :                                 case 3: {
     590            0 :                                     p1 = glm::vec2(map.GetPolygons()[poly].vertices[2].x,
     591            0 :                                                    map.GetPolygons()[poly].vertices[2].y);
     592            0 :                                     p2 = glm::vec2(map.GetPolygons()[poly].vertices[0].x,
     593            0 :                                                    map.GetPolygons()[poly].vertices[0].y);
     594            0 :                                     break;
     595              :                                 }
     596              :                             }
     597              : 
     598            0 :                             auto p3 = pos;
     599            0 :                             d = Calc::PointLineDistance(p1, p2, p3);
     600            0 :                             perp *= d;
     601              : 
     602            0 :                             soldier.particle.position = soldier.particle.old_position;
     603            0 :                             soldier.particle.velocity_ = soldier.particle.GetForce() - perp;
     604            0 :                             physics_events.soldier_collides_with_polygon.Notify(
     605            0 :                               soldier, map.GetPolygons()[poly]);
     606              : 
     607            0 :                             return true;
     608              :                         }
     609              :                     }
     610              :                 }
     611              :             }
     612              :         }
     613              :     }
     614              : 
     615            0 :     return false;
     616              : }
     617              : 
     618            0 : bool CheckSkeletonMapCollision(Soldier& soldier, const Map& map, unsigned int i, float x, float y)
     619              : {
     620            0 :     auto result = false;
     621            0 :     auto pos = glm::vec2(x - 1.0f, y + 4.0f);
     622            0 :     auto rx = ((int)std::round(pos.x / (float)map.GetSectorsSize())) + 25;
     623            0 :     auto ry = ((int)std::round(pos.y / (float)map.GetSectorsSize())) + 25;
     624              : 
     625            0 :     if ((rx > 0) && (rx < map.GetSectorsCount() + 25) && (ry > 0) &&
     626            0 :         (ry < map.GetSectorsCount() + 25)) {
     627            0 :         for (int j = 0; j < map.GetSector(rx, ry).polygons.size(); j++) {
     628            0 :             auto poly = map.GetSector(rx, ry).polygons[j] - 1;
     629              : 
     630            0 :             if (map.PointInPolyEdges(pos.x, pos.y, poly)) {
     631            0 :                 auto dist = 0.0f;
     632            0 :                 auto b = 0;
     633            0 :                 auto perp = map.ClosestPerpendicular(poly, pos, &dist, &b);
     634            0 :                 perp = Calc::Vec2Normalize(perp);
     635            0 :                 perp *= dist;
     636              : 
     637            0 :                 soldier.skeleton->SetPos(i, soldier.skeleton->GetOldPos(i) - perp);
     638              : 
     639            0 :                 result = true;
     640              :             }
     641              :         }
     642              :     }
     643              : 
     644            0 :     if (result) {
     645            0 :         auto pos = glm::vec2(x, y + 1.0);
     646            0 :         auto rx = ((int)std::round(pos.x / (float)map.GetSectorsSize())) + 25;
     647            0 :         auto ry = ((int)std::round(pos.y / (float)map.GetSectorsSize())) + 25;
     648              : 
     649            0 :         if ((rx > 0) && (rx < map.GetSectorsCount() + 25) && (ry > 0) &&
     650            0 :             (ry < map.GetSectorsCount() + 25)) {
     651            0 :             for (int j = 0; j < map.GetSector(rx, ry).polygons.size(); j++) {
     652            0 :                 auto poly = map.GetSector(rx, ry).polygons[j] - 1;
     653              :                 // if (Map.PolyType[poly] <> POLY_TYPE_DOESNT) and (Map.PolyType[poly] <>
     654              :                 // POLY_TYPE_ONLY_BULLETS) then
     655            0 :                 if (map.PointInPolyEdges(pos.x, pos.y, poly)) {
     656            0 :                     auto dist = 0.0F;
     657            0 :                     auto b = 0;
     658            0 :                     auto perp = map.ClosestPerpendicular(poly, pos, &dist, &b);
     659            0 :                     perp = Calc::Vec2Normalize(perp);
     660            0 :                     perp *= dist;
     661              : 
     662            0 :                     soldier.skeleton->SetPos(i, soldier.skeleton->GetOldPos(i) - perp);
     663              : 
     664            0 :                     result = true;
     665              :                 }
     666              :             }
     667              :         }
     668              :     }
     669              : 
     670            0 :     return result;
     671              : }
     672              : 
     673            0 : void Fire(Soldier& soldier, std::vector<BulletParams>& bullet_emitter)
     674              : {
     675            0 :     auto weapon = GetPrimaryWeapon(soldier);
     676              : 
     677              :     glm::vec2 dir;
     678            0 :     if (weapon.GetWeaponParameters().bullet_style == BulletType::Blade ||
     679            0 :         soldier.body_animation->GetType() == AnimationType::Mercy ||
     680            0 :         soldier.body_animation->GetType() == AnimationType::Mercy2) {
     681            0 :         dir = Calc::Vec2Normalize(soldier.skeleton->GetPos(15) - soldier.skeleton->GetPos(16));
     682              :     } else {
     683            0 :         auto aim_x = (float)soldier.control.mouse_aim_x;
     684            0 :         auto aim_y = (float)soldier.control.mouse_aim_y;
     685            0 :         dir = Calc::Vec2Normalize(glm::vec2(aim_x, aim_y) - soldier.skeleton->GetPos(15));
     686              :     };
     687              : 
     688            0 :     auto pos = soldier.skeleton->GetPos(15) + dir * 4.0F - glm::vec2(0.0, 2.0);
     689            0 :     auto bullet_velocity = dir * weapon.GetWeaponParameters().speed;
     690              :     auto inherited_velocity =
     691            0 :       soldier.particle.velocity_ * weapon.GetWeaponParameters().inherited_velocity;
     692              : 
     693            0 :     BulletParams params{
     694            0 :         weapon.GetWeaponParameters().bullet_style,
     695            0 :         weapon.GetWeaponParameters().kind,
     696              :         pos,
     697            0 :         bullet_velocity + inherited_velocity,
     698            0 :         (std::int16_t)weapon.GetWeaponParameters().timeout,
     699            0 :         weapon.GetWeaponParameters().hit_multiply,
     700              :         TeamType::None,
     701            0 :         soldier.id,
     702            0 :     };
     703              : 
     704            0 :     switch (weapon.GetWeaponParameters().kind) {
     705            0 :         case WeaponType::DesertEagles: {
     706            0 :             if (!soldier.is_shooting) {
     707            0 :                 bullet_emitter.push_back(params);
     708              : 
     709            0 :                 auto signx = dir.x > 0.0F ? 1.0F : (dir.x < 0.0F ? -1.0F : 0.0F);
     710            0 :                 auto signy = dir.x > 0.0F ? 1.0F : (dir.x < 0.0F ? -1.0F : 0.0F);
     711              : 
     712            0 :                 params.position += glm::vec2(-signx * dir.y, signy * dir.x) * 3.0F;
     713            0 :                 bullet_emitter.push_back(params);
     714              :             }
     715            0 :             break;
     716              :         }
     717            0 :         case WeaponType::Spas12:
     718              :         case WeaponType::Flamer:
     719              :         case WeaponType::NoWeapon:
     720              :         case WeaponType::Knife:
     721              :         case WeaponType::Chainsaw:
     722            0 :             break;
     723            0 :         case WeaponType::LAW: {
     724            0 :             if ((soldier.on_ground || soldier.on_ground_permanent || soldier.on_ground_for_law) &&
     725            0 :                 (((soldier.legs_animation->GetType() == AnimationType::Crouch &&
     726            0 :                    soldier.legs_animation->GetFrame() > 13) ||
     727            0 :                   soldier.legs_animation->GetType() == AnimationType::CrouchRun ||
     728            0 :                   soldier.legs_animation->GetType() == AnimationType::CrouchRunBack) ||
     729            0 :                  (soldier.legs_animation->GetType() == AnimationType::Prone &&
     730            0 :                   soldier.legs_animation->GetFrame() > 23))) {
     731            0 :                 bullet_emitter.push_back(params);
     732              :             }
     733            0 :             break;
     734              :         }
     735            0 :         default: {
     736            0 :             bullet_emitter.push_back(params);
     737              :         }
     738              :     };
     739              : 
     740            0 :     soldier.is_shooting = true;
     741            0 : }
     742              : } // namespace Soldank::SoldierPhysics
        

Generated by: LCOV version 2.0-1