mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-23 21:05:58 +02:00
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
This commit is contained in:
1 parent
8ede361755
commit
118c489fdb
25 files changed
+1449
-89
No files matched your search
@@ -58,12 +58,49 @@ void presses() {
|
||||
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;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
|
||||
namespace dingosdk::first_person {
|
||||
@@ -7,20 +8,46 @@ namespace dingosdk::first_person {
|
||||
// (true is the high camera). With the option on, ReSkate turns that into high -> low -> first
|
||||
// person -> high by changing the value written: the step into first person keeps the low camera
|
||||
// behind it, and the step out of first person always lands on the high camera.
|
||||
//
|
||||
// A plugin's camera can be in the cycle too, last (reskate.camera.cycle): high -> low -> first
|
||||
// person -> the plugin's camera -> high (without first person in it, or where first person cannot
|
||||
// start: high -> low -> the plugin's camera -> high). Its step keeps the low camera behind it as well.
|
||||
enum class CycleStep : std::uint8_t { none, enter, leave };
|
||||
struct CycleState {
|
||||
bool enabled{}; // the option is on and the local skater is in control
|
||||
bool first_person{}; // first person has the camera
|
||||
bool can_enter{}; // first person can take the camera now: on the board, no Freecam
|
||||
bool plugin_enabled{}; // a plugin's camera is in the cycle now
|
||||
bool plugin{}; // that camera is on
|
||||
bool plugin_can_enter{}; // that camera is off and can start
|
||||
};
|
||||
struct CycleWrite {
|
||||
bool high{}; // the height the game keeps
|
||||
CycleStep step{}; // what first person does
|
||||
bool high{}; // the height the game keeps
|
||||
CycleStep step{}; // what first person does
|
||||
CycleStep plugin{}; // what the plugin's camera does
|
||||
};
|
||||
constexpr CycleWrite cycle_height_write(const CycleState& state, bool high) noexcept {
|
||||
if (!state.enabled) return {high, CycleStep::none};
|
||||
if (state.first_person) return {true, CycleStep::leave};
|
||||
if (high && state.can_enter) return {false, CycleStep::enter};
|
||||
return {high, CycleStep::none};
|
||||
// The plugin's camera is last: out of it, the high camera.
|
||||
if (state.plugin_enabled && state.plugin) return {true, CycleStep::none, CycleStep::leave};
|
||||
if (state.enabled && state.first_person) {
|
||||
if (state.plugin_enabled && state.plugin_can_enter) return {false, CycleStep::leave, CycleStep::enter};
|
||||
return {true, CycleStep::leave, CycleStep::none};
|
||||
}
|
||||
if (high) { // the game steps low -> high: first person, else the plugin's camera, comes in between
|
||||
if (state.enabled && state.can_enter) return {false, CycleStep::enter, CycleStep::none};
|
||||
if (state.plugin_enabled && state.plugin_can_enter) return {false, CycleStep::none, CycleStep::enter};
|
||||
}
|
||||
return {high, CycleStep::none, CycleStep::none};
|
||||
}
|
||||
|
||||
// The plugin's half of the link (the plugin runtime keeps it). Each tick the plugin in the cycle has
|
||||
// its flags published; the height write (on the thread that handles the button) leaves the step it
|
||||
// asks of the plugin's camera in `request`, taken on the plugin runtime's next tick.
|
||||
enum PluginFlag : std::uint8_t { plugin_flag_enabled = 1, plugin_flag_on = 2, plugin_flag_can_enter = 4 };
|
||||
struct PluginLink {
|
||||
std::atomic<std::uint8_t> flags{};
|
||||
std::atomic<std::uint8_t> request{}; // a CycleStep
|
||||
std::atomic<std::uint64_t> published{}; // GetTickCount64 when the flags were published
|
||||
};
|
||||
inline PluginLink plugin_link{};
|
||||
}
|
||||
Reference in new issue
Block a user