Files
ReSkate/Engine/Game/Skater/Test/first_person_cycle_tests.cpp
T
AyeZeeBB 118c489fdb Plugins: what the Filmer needs as a plugin: carry, who sees a pose, a step in the camera cycle
PR 343's Filmer becomes a Luau plugin mod (kept in contrib/plugins/filmer) on general APIs instead of
its own C++:

- reskate.skater.carry: something held out in one or both hands and aimed, the body crouched (feet
  kept) and hunched over it, turned on the spot after it (Extension/Skater/carry.cpp, from the PR's
  filmer_hold.cpp, with tests)
- shown = "everyone" | "others" | "me" on skater.pose, reach and carry: the pose sent to the other
  players and the one drawn here are split when asked
- reskate.camera.cycle and the camera_cycle event: a plugin's camera as the last step of the camera
  height button's cycle, after first person
- reskate.session.nametags(false) holds the names over the other players off
- board.hide(bone, {others = true}) hides it in the board the others are sent too (a sent-pose filter)
- outfit.set takes hand wear slots; input.bind takes an action with no key of its own
2026-10-22 18:46:49 -05:00

111 lines
5.1 KiB
C++

#include "Engine/Game/Skater/first_person_cycle.h"
#include <cstdio>
#include <string_view>
// First person in the camera cycle (first_person::cycle_height_write): the game's camera height
// button flips UseHighCam; the option turns that into high -> low -> first person -> high.
namespace {
using namespace dingosdk::first_person;
int failures = 0;
void expect(bool condition, std::string_view what) {
if (condition) return;
++failures;
std::printf("FAIL: %.*s\n", static_cast<int>(what.size()), what.data());
}
bool same(const CycleWrite& write, bool high, CycleStep step) { return write.high == high && write.step == step; }
void off() {
for (const bool first_person : {false, true})
for (const bool high : {false, true})
expect(same(cycle_height_write({false, first_person, true}, high), high, CycleStep::none),
"with the option off the game's height passes through and first person is left alone");
}
void steps() {
expect(same(cycle_height_write({true, false, true}, false), false, CycleStep::none), "high -> low is the game's own step");
expect(same(cycle_height_write({true, false, true}, true), false, CycleStep::enter),
"low -> first person keeps the low camera behind it");
expect(same(cycle_height_write({true, true, false}, true), true, CycleStep::leave),
"first person (low behind it) -> the high camera");
expect(same(cycle_height_write({true, true, false}, false), true, CycleStep::leave),
"first person switched on in the menu over the high camera still lands on high");
expect(same(cycle_height_write({true, false, false}, true), true, CycleStep::none),
"where first person cannot start (on foot, Freecam) low -> high is the game's own step");
}
// The game reads the height it keeps and writes the opposite on every press.
void presses() {
for (const bool start_high : {true, false}) {
bool high = start_high, first_person = false;
const auto press = [&] {
const auto write = cycle_height_write({true, first_person, !first_person}, !high);
high = write.high;
if (write.step == CycleStep::enter) first_person = true;
if (write.step == CycleStep::leave) first_person = false;
};
if (!start_high) press(); // low -> first person
if (!start_high) press(); // first person -> high
for (int round = 0; round < 3; ++round) {
expect(high && !first_person, "the cycle starts each round on the high camera");
press();
expect(!high && !first_person, "first press: low camera");
press();
expect(!high && first_person, "second press: first person over the low camera");
press();
}
expect(high && !first_person, "the third press of each round returns to the high camera");
}
}
// With a plugin's camera in the cycle: high -> low -> first person -> the plugin's camera -> high, and
// without first person (or on foot, where it cannot start) high -> low -> the plugin's camera -> high.
void plugin() {
for (const bool with_first_person : {true, false}) {
bool high = true, first_person = false, on = false;
const auto press = [&] {
CycleState state{with_first_person, first_person, !first_person && !on, true, on, !on};
const auto write = cycle_height_write(state, !high);
high = write.high;
if (write.step == CycleStep::enter) first_person = true;
if (write.step == CycleStep::leave) first_person = false;
if (write.plugin == CycleStep::enter) on = true;
if (write.plugin == CycleStep::leave) on = false;
};
for (int round = 0; round < 3; ++round) {
expect(high && !first_person && !on, "each round starts on the high camera");
press();
expect(!high && !first_person && !on, "first press: low camera");
if (with_first_person) {
press();
expect(!high && first_person && !on, "second press: first person");
}
press();
expect(!high && !first_person && on, "then the plugin's camera, the low camera behind it");
press();
}
expect(high && !first_person && !on, "out of the plugin's camera: the high camera");
}
// No plugin in the cycle: the first-person cycle as before.
expect(same(cycle_height_write({true, true, false, false, false, true}, true), true, CycleStep::leave),
"without a plugin's camera, first person -> high");
// Turned on by the plugin itself over the high camera: the button still takes it out to high.
const auto out = cycle_height_write({false, false, true, true, true, false}, false);
expect(out.high && out.plugin == CycleStep::leave, "a plugin's camera on by itself: the button leaves it for high");
}
} // namespace
int main() {
off();
steps();
presses();
plugin();
if (failures) {
std::printf("%d first-person cycle test(s) failed\n", failures);
return 1;
}
std::printf("first-person cycle tests passed\n");
return 0;
}