forked from sashavol/Frozlunky
-
Notifications
You must be signed in to change notification settings - Fork 0
/
game_state_detector.cpp
93 lines (82 loc) · 2.33 KB
/
game_state_detector.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 "game_state_detector.h"
GameStateDetector::GameStateDetector(std::shared_ptr<DerandomizePatch> dp) :
spel(dp->spel),
is_valid(true),
current_id(1),
last_state(-1)
{
g_CurrentGamePtr = dp->game_ptr();
if(g_CurrentGamePtr == 0x0) {
is_valid = false;
return;
}
game_state_offset = spel->get_stored_hook("game_state_offset");
if(game_state_offset == 0x0) {
GameHooks(spel, dp);
game_state_offset = spel->get_stored_hook("game_state_offset");
if(game_state_offset == 0x0) {
is_valid = false;
return;
}
}
last_state = current_state();
}
GameStateDetector::bind_id GameStateDetector::bind(int state, bind_callback callback, bool every) {
auto state_binds_iter = binds.find(state);
if(state_binds_iter == binds.end()) {
binds[state] = binds_type();
bind_id id = current_id;
binds[state][id] = bind_info(callback, every);
current_id++;
return id;
}
else {
bind_id id = current_id;
state_binds_iter->second[id] = bind_info(callback, every);
current_id++;
return id;
}
return 0;
}
void GameStateDetector::real_unbind(bind_id id) {
for(auto state_bind_iter = binds.begin(); state_bind_iter != binds.end(); state_bind_iter++) {
binds_type& state_binds = state_bind_iter->second;
auto inner_iter = state_binds.find(id);
if(inner_iter != state_binds.end()) {
state_binds.erase(inner_iter);
}
}
}
void GameStateDetector::request_unbind(bind_id id) {
unbind_req_mu.lock();
unbind_requests.push_back(id);
unbind_req_mu.unlock();
}
void GameStateDetector::cycle() {
unbind_req_mu.lock();
for(bind_id unbind_req : unbind_requests) {
real_unbind(unbind_req);
}
unbind_requests.clear();
unbind_req_mu.unlock();
int current = current_state();
bool changed = current != last_state;
auto iter = binds.find(current);
if(iter != binds.end()) {
binds_type& map = iter->second;
for(auto map_iter = map.begin(); map_iter != map.end(); map_iter++) {
bind_info& info = map_iter->second;
if(info.every || changed) {
info.callback(last_state, current, map_iter->first);
}
}
}
last_state = current;
}
int GameStateDetector::current_state() {
Address game;
spel->read_mem(g_CurrentGamePtr, &game, sizeof(Address));
int state;
spel->read_mem(game+game_state_offset, &state, sizeof(int));
return state;
}