decomp3: more engine stuff, fix ja macro detection for jak 2/3, unmerged let matcher, part-tracker-spawn macro (#3436)

- `aligner`
- `effect-control`
- `pov-camera`
- `powerups`
- `los-control-h`
- `airlock`
- `water-anim`
- `blocking-plane`
- `proc-focusable-spawner`
- `idle-control`
- `enemy-h`
- `nav-enemy-h`
- `enemy`
- `enemy-states`
- `particle-curves`
- `base-plat`
- `plat`
- `bouncer`
- `elevator`
- `rigid-body`
- `rigid-body-queue`
- `process-taskable`
- `scene-actor`
- `warp-gate`
- `guard-projectile`
- `metalhead-projectile`
- `los-control`
- `joint-exploder`
- `ragdoll-test`
- `debris`
- `shield-sphere`
- `text`
- `target-launch`
This commit is contained in:
Hat Kid
2024-03-30 15:28:02 +01:00
committed by GitHub
parent ee015e3b22
commit dacb704ef6
217 changed files with 51939 additions and 5934 deletions
+67
View File
@@ -243,6 +243,15 @@ Matcher Matcher::let(bool is_star,
return m;
}
Matcher Matcher::unmerged_let(const std::vector<LetEntryMatcher>& entries,
const std::vector<Matcher>& elts) {
Matcher m;
m.m_kind = Kind::UNMERGED_LET;
m.m_entry_matchers = entries;
m.m_sub_matchers = elts;
return m;
}
bool Matcher::do_match(Form* input, MatchResult::Maps* maps_out, const Env* const env) const {
switch (m_kind) {
case Kind::ANY:
@@ -722,6 +731,64 @@ bool Matcher::do_match(Form* input, MatchResult::Maps* maps_out, const Env* cons
return false;
}
case Kind::UNMERGED_LET: {
auto as_let = dynamic_cast<LetElement*>(input->try_as_single_active_element());
if (as_let) {
size_t entries_matched = 0;
Form* innermost_let_body = nullptr;
// first try to find the innermost let, matching all let entries with the entry matchers
// throughout
as_let->apply_form([&](Form* form) {
for (int idx = 0; idx < form->size(); idx++) {
auto* f = form->at(idx);
// if this is the entry of the outermost let, try to do the first match
if (f->parent_form->parent_element == as_let) {
if (m_entry_matchers.at(entries_matched)
.do_match(as_let->entries().at(0), maps_out, env)) {
entries_matched++;
} else {
return;
}
}
auto let = dynamic_cast<LetElement*>(f);
if (!let) {
continue;
}
auto let_body = dynamic_cast<LetElement*>(let->body()->at(0));
if (!let_body) {
break;
}
if (m_entry_matchers.at(entries_matched)
.do_match(let_body->entries().at(0), maps_out, env)) {
entries_matched++;
} else {
return;
}
if (entries_matched == m_entry_matchers.size()) {
innermost_let_body = let_body->body();
return;
}
}
});
if (entries_matched == m_entry_matchers.size() && innermost_let_body) {
// now match body of innermost let
for (int i = 0; i < (int)m_sub_matchers.size(); ++i) {
Form fake;
fake.elts().push_back(innermost_let_body->elts().at(i));
if (!m_sub_matchers.at(i).do_match(&fake, maps_out, env)) {
return false;
}
}
return true;
}
}
return false;
}
default:
ASSERT(false);
return false;