-
Notifications
You must be signed in to change notification settings - Fork 0
/
Weapon.cpp
executable file
·93 lines (66 loc) · 2.64 KB
/
Weapon.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include "Weapon.h"
#include "Player.h"
#include "Person.h"
#include "GameMap.h"
void Weapon::fire(const Enemy& shooter) {
if (cooldown_ != 0) return;
cooldown_ = max_cooldown_;
Sounds::global().play(Sounds::fire_enemy, 100);
bool valid;
float int_param;
std::tie(int_param, valid) = shoot_thing(Player::instance(), shooter);
if (valid) {
Player::instance().damage(int_param * damage_);
}
else {
Sounds::global().play(Sounds::bullet_wall, 100);
}
}
void Weapon::fire(const Player& shooter) {
if (cooldown_ != 0) return;
cooldown_ = max_cooldown_;
Sounds::global().play(Sounds::fire_player, 100);
std::vector<std::pair<Person*, float>> shooted_things;
bool valid;
float int_param;
for (auto&& thing : shooter.get_map()->get_things()) {
std::tie(int_param, valid) = shoot_thing(*thing, shooter);
if (valid) {
Enemy * enemy = dynamic_cast<Enemy*>(thing.get());
if (enemy != nullptr) shooted_things.push_back({ enemy, int_param });
}
}
Vector pos = shooter.get_position();
//sort shooted_things
std::sort(shooted_things.begin(), shooted_things.end(), [&](const std::pair<Person*, float>& lhs, const std::pair<Person*, float>& rhs) {
return lhs.first->get_distance(pos) < rhs.first->get_distance(pos);
});
// damage nearest of them
if (!shooted_things.empty()) shooted_things.front().first->damage(shooted_things.front().second * damage_);
}
std::tuple<float, bool> Weapon::shoot_thing(const Thing& thing, const Person& shooter) {
float psin = std::sinf(shooter.get_direction() * PI_180);
float pcos = std::cosf(shooter.get_direction() * PI_180);
Vector pos = shooter.get_position();
Vector dir = { psin, pcos };
Vector perp = { dir.Y, -dir.X };
// thing is out of range
if ((thing.get_position() - pos).length() > range_) return { 0.0f, false };
// same object
if (&shooter == &thing) return { 0.0f, false };
// bullet vs enemy plane intersection
Vector change = thing.get_position() - pos;
Vector perp_tng = { change.Y, -change.X };
Vector start = thing.get_position() - thing.get_radius() / perp_tng.length() * perp_tng;
Vector end = thing.get_position() + thing.get_radius() / perp_tng.length() * perp_tng;
StraightLine ray(pos, pos + dir);
float t = ray.ray_segment_intersection(start, end);
if (t == -1) return { 0.0f, false };
// thing is not reachable by bullet
if (!shooter.get_map()->check_los( shooter.get_head_level(), pos,
start + t * (end - start),
thing.get_head_level(),
thing.get_foot_level()))
return { 0.0f, false };
return { 1 - std::abs(2.0f * t - 1.0f), true };
}