Line data Source code
1 : #include "core/CoreEventHandler.hpp"
2 :
3 : #include "core/math/Calc.hpp"
4 :
5 : #include "core/entities/Bullet.hpp"
6 : #include "core/entities/WeaponParametersFactory.hpp"
7 :
8 : #include "core/physics/SoldierPhysics.hpp"
9 :
10 : #include "core/types/ItemType.hpp"
11 : #include "spdlog/spdlog.h"
12 : #include <utility>
13 :
14 : namespace Soldank
15 : {
16 0 : ItemType WeaponTypeToItemType(WeaponType weapon_type)
17 : {
18 0 : switch (weapon_type) {
19 0 : case WeaponType::DesertEagles:
20 0 : return ItemType::DesertEagles;
21 0 : case WeaponType::MP5:
22 0 : return ItemType::MP5;
23 0 : case WeaponType::Ak74:
24 0 : return ItemType::Ak74;
25 0 : case WeaponType::SteyrAUG:
26 0 : return ItemType::SteyrAUG;
27 0 : case WeaponType::Spas12:
28 0 : return ItemType::Spas12;
29 0 : case WeaponType::Ruger77:
30 0 : return ItemType::Ruger77;
31 0 : case WeaponType::M79:
32 0 : return ItemType::M79;
33 0 : case WeaponType::Barrett:
34 0 : return ItemType::Barrett;
35 0 : case WeaponType::Minimi:
36 0 : return ItemType::Minimi;
37 0 : case WeaponType::Minigun:
38 0 : return ItemType::Minigun;
39 0 : case WeaponType::USSOCOM:
40 0 : return ItemType::USSOCOM;
41 0 : case WeaponType::Knife:
42 0 : return ItemType::Knife;
43 0 : case WeaponType::Chainsaw:
44 0 : return ItemType::Chainsaw;
45 0 : case WeaponType::LAW:
46 0 : return ItemType::LAW;
47 0 : case WeaponType::FlameBow:
48 : case WeaponType::Bow:
49 0 : return ItemType::Bow;
50 0 : case WeaponType::Flamer:
51 : case WeaponType::M2:
52 : case WeaponType::NoWeapon:
53 : case WeaponType::FragGrenade:
54 : case WeaponType::ClusterGrenade:
55 : case WeaponType::Cluster:
56 : case WeaponType::ThrownKnife:
57 : std::unreachable();
58 : }
59 : }
60 :
61 0 : void CoreEventHandler::ObserveAll(IWorld* world)
62 : {
63 0 : ObserveAllWorldEvents(world);
64 0 : ObserveAllPhysicsEvents(world);
65 0 : }
66 :
67 0 : void CoreEventHandler::ObserveAllWorldEvents(IWorld* world)
68 : {
69 0 : world->GetWorldEvents().after_soldier_spawns.AddObserver([](const Soldier& soldier) {
70 0 : spdlog::debug("soldier {} spawned at ({}, {})",
71 0 : soldier.id,
72 0 : soldier.particle.position.x,
73 0 : soldier.particle.position.y);
74 0 : });
75 0 : }
76 :
77 0 : void CoreEventHandler::ObserveAllPhysicsEvents(IWorld* world)
78 : {
79 0 : world->GetPhysicsEvents().soldier_hit_by_bullet.AddObserver(
80 0 : [world](Soldier& soldier, float damage) {
81 0 : soldier.health -= damage;
82 0 : spdlog::debug("soldier {} hit by {} damage", soldier.id, damage);
83 0 : if (soldier.health <= 0.0F) {
84 0 : world->KillSoldier(soldier.id);
85 : }
86 0 : });
87 0 : world->GetPhysicsEvents().soldier_switches_weapon.AddObserver([world](Soldier& soldier) {
88 0 : spdlog::debug(
89 : "soldier {} switched weapon from {} to {}",
90 0 : soldier.id,
91 0 : std::to_underlying(soldier.weapons[soldier.active_weapon].GetWeaponParameters().kind),
92 0 : std::to_underlying(
93 0 : soldier.weapons[(soldier.active_weapon + 1) % 2].GetWeaponParameters().kind));
94 0 : world->GetStateManager()->SwitchSoldierWeapon(soldier.id);
95 0 : });
96 0 : world->GetPhysicsEvents().soldier_throws_active_weapon.AddObserver([world](
97 : const Soldier& soldier) {
98 0 : if (soldier.weapons[soldier.active_weapon].GetWeaponParameters().kind ==
99 : WeaponType::Knife) {
100 0 : spdlog::debug("soldier {} throws knife", soldier.id);
101 0 : Weapon weapon{ WeaponParametersFactory::GetParameters(WeaponType::ThrownKnife, false) };
102 0 : auto aim_x = (float)soldier.control.mouse_aim_x;
103 0 : auto aim_y = (float)soldier.control.mouse_aim_y;
104 0 : auto dir = Calc::Vec2Normalize(glm::vec2(aim_x, aim_y) - soldier.skeleton->GetPos(15));
105 0 : auto frame = (float)soldier.body_animation->GetFrame();
106 0 : auto thrown_mul = 1.5F * std::min(16.0F, std::max(8.0F, frame)) / 16.0F;
107 0 : auto bullet_vel = dir * weapon.GetWeaponParameters().speed * thrown_mul;
108 : auto inherited_vel =
109 0 : soldier.particle.GetVelocity() * weapon.GetWeaponParameters().inherited_velocity;
110 0 : auto velocity = bullet_vel + inherited_vel;
111 :
112 0 : BulletParams params{
113 0 : weapon.GetWeaponParameters().bullet_style,
114 0 : weapon.GetWeaponParameters().kind,
115 0 : soldier.skeleton->GetPos(16) + velocity,
116 : velocity,
117 0 : (std::int16_t)weapon.GetWeaponParameters().timeout,
118 0 : weapon.GetWeaponParameters().hit_multiply,
119 : TeamType::None,
120 0 : soldier.id,
121 : 0.0F // TODO: Add push
122 0 : };
123 0 : world->GetStateManager()->EnqueueNewProjectile(params);
124 0 : world->GetStateManager()->ChangeSoldierPrimaryWeapon(soldier.id, WeaponType::NoWeapon);
125 0 : } else {
126 0 : spdlog::debug("soldier {} throws a weapon", soldier.id);
127 : WeaponType current_soldier_weapon_type =
128 0 : soldier.weapons[soldier.active_weapon].GetWeaponParameters().kind;
129 0 : Item& new_item = world->GetStateManager()->CreateItem(
130 0 : soldier.skeleton->GetPos(16),
131 0 : soldier.id,
132 : WeaponTypeToItemType(current_soldier_weapon_type));
133 0 : world->GetStateManager()->ChangeSoldierPrimaryWeapon(soldier.id, WeaponType::NoWeapon);
134 0 : new_item.skeleton->SetPos(
135 0 : 1, new_item.skeleton->GetPos(1) + soldier.particle.GetVelocity());
136 0 : new_item.skeleton->SetPos(
137 0 : 2, new_item.skeleton->GetPos(2) + soldier.particle.GetVelocity());
138 :
139 0 : glm::vec2 aim_direction = { soldier.control.mouse_aim_x, soldier.control.mouse_aim_y };
140 0 : aim_direction -= soldier.skeleton->GetPos(15);
141 0 : aim_direction = Calc::Vec2Normalize(aim_direction);
142 :
143 0 : float weapon_throw_speed_pos1 = 0.01F;
144 0 : float weapon_throw_speed_pos2 = 3.0F;
145 0 : if (soldier.dead_meat) {
146 0 : weapon_throw_speed_pos1 = 0.02F;
147 0 : weapon_throw_speed_pos2 = 0.64F;
148 : }
149 :
150 : glm::vec2 weapon_throw_velocity =
151 0 : Calc::Vec2Scale(aim_direction, weapon_throw_speed_pos1);
152 0 : new_item.skeleton->SetPos(1, new_item.skeleton->GetPos(1) + weapon_throw_velocity);
153 0 : weapon_throw_velocity = Calc::Vec2Scale(aim_direction, weapon_throw_speed_pos2);
154 0 : new_item.skeleton->SetPos(2, new_item.skeleton->GetPos(2) + weapon_throw_velocity);
155 : }
156 0 : });
157 0 : world->GetPhysicsEvents().soldier_fires_primary_weapon.AddObserver([world](Soldier& soldier) {
158 0 : std::vector<BulletParams> bullet_emitter;
159 0 : SoldierPhysics::Fire(soldier, bullet_emitter);
160 0 : for (auto& bullet_params : bullet_emitter) {
161 0 : world->GetStateManager()->EnqueueNewProjectile(bullet_params);
162 : }
163 0 : });
164 0 : world->GetPhysicsEvents().soldier_collides_with_item.AddObserver(
165 0 : [world](Soldier& soldier, Item& item) {
166 0 : if (IsItemTypeFlag(item.style)) {
167 0 : if (item.holding_soldier_id == 0) {
168 0 : item.static_type = false;
169 0 : item.holding_soldier_id = soldier.id;
170 0 : soldier.is_holding_flags = true;
171 : }
172 0 : } else if (IsItemTypeWeapon(item.style)) {
173 0 : if (soldier.weapons[soldier.active_weapon].GetWeaponParameters().kind ==
174 : WeaponType::NoWeapon) {
175 0 : world->GetStateManager()->SoldierPickupWeapon(soldier.id, item);
176 0 : item.active = false;
177 : }
178 0 : } else if (IsItemTypeKit(item.style)) {
179 0 : world->GetStateManager()->SoldierPickupKit(soldier.id, item.id);
180 : }
181 0 : });
182 0 : world->GetPhysicsEvents().soldier_throws_flags.AddObserver([world](Soldier& soldier) {
183 0 : spdlog::info("PLAYER {} THROWS FLAGS", soldier.id);
184 0 : world->GetStateManager()->ThrowSoldierFlags(soldier.id);
185 0 : });
186 0 : world->GetPhysicsEvents().bullet_collides_with_polygon.AddObserver(
187 0 : [world](const Bullet& bullet, const glm::vec2& collision_position) {
188 0 : if (bullet.style == BulletType::ThrownKnife) {
189 0 : glm::vec2 knife_as_item_position = collision_position;
190 0 : knife_as_item_position -= bullet.particle.GetVelocity() * 2.0F;
191 :
192 0 : world->GetStateManager()->CreateItem(knife_as_item_position, 0, ItemType::Knife);
193 : }
194 0 : });
195 0 : }
196 : } // namespace Soldank
|