53 const PieceInterpolationSample& sample)
noexcept
55 const float yaw = std::atan2(sample.forward.x, sample.forward.z);
56 const float pitch = -std::asin(std::clamp(sample.forward.y, -1.0F, 1.0F));
60 sample.location.x, sample.location.y, sample.location.z));
68 const auto info =
const_cast<engine::SequencePlayback&
>(
playback)
70 return info && info->endTime <= info->sequenceClock;
74 const PieceJailRoutePlan&
route)
noexcept
76 if (
route.path.used == 0)
return {};
77 return route.path.segments[
route.path.used - 1][3];
83 std::uint8_t endingAction)
86 std::nullopt : std::optional<data::DataId>{
previous};
96 if (!
pose)
return std::unexpected(
"missing token board orientation");
97 return playback.transitionRySTxzDropStayAtEnd(std::nullopt,
id,
104 bool animationsEnabled, std::uint8_t
randomBit)
106 if (
active())
return std::unexpected(
"GoToJail playback already active");
110 return std::unexpected(
"invalid GoToJail request");
112 animationsEnabled_ = animationsEnabled;
113 randomBit_ =
static_cast<std::uint8_t
>(
randomBit & 1U);
115 playerInPaddywagon_.reset();
116 outbound_.reset(); inbound_.reset();
127 if (!
active())
return result;
129 return std::unexpected(
"GoToJail player no longer valid");
137 if (!animationsEnabled_) { state_ = 14;
continue; }
138 result.playSiren =
true;
141 if (!
route)
return std::unexpected(
"failed to build paddy outbound route");
142 outbound_ = std::move(*
route);
143 result.camera = outbound_->camera;
144 if (outbound_->skipMotion) { state_ = 14;
continue; }
152 if (paddySequence_ !=
popIn)
155 outbound_->path, outbound_->path.startTick);
159 if (!started)
return std::unexpected(started.error());
160 paddySequence_ =
popIn;
165 const auto duration = outbound_->path.endTick - outbound_->path.startTick;
167 outbound_->path.endTick =
tickValue + duration;
172 rolling, paddyMatrix_, LoopToBeginning);
173 if (!started)
return std::unexpected(started.error());
185 if (!moved)
return std::unexpected(moved.error());
186 const auto cameraTick = outbound_->path.endTick > 55U ?
187 outbound_->path.endTick - 55U : 0
U;
202 if (!started)
return std::unexpected(started.error());
210 idle, paddyMatrix_, LoopToBeginning);
211 if (!started)
return std::unexpected(started.error());
212 paddySequence_ =
idle;
220 playerInPaddywagon_ = request_.
player;
223 if (tokenSequence_ !=
wanted)
226 static_cast<std::uint8_t
>(request_.
before));
227 if (!started)
return std::unexpected(started.error());
243 if (!started)
return std::unexpected(started.error());
253 if (!stopped)
return std::unexpected(stopped.error());
258 rolling, paddyMatrix_, LoopToBeginning);
259 if (!started)
return std::unexpected(started.error());
267 result.playSiren =
true;
269 static_cast<std::uint8_t
>(request_.
before),
271 if (!
route)
return std::unexpected(
"failed to build paddy return route");
272 inbound_ = std::move(*
route);
273 result.camera = inbound_->camera;
284 if (!moved)
return std::unexpected(moved.error());
285 const auto cameraTick = inbound_->path.endTick > 55U ?
286 inbound_->path.endTick - 55U : 0
U;
301 if (!started)
return std::unexpected(started.error());
309 idle, paddyMatrix_, LoopToBeginning);
311 paddySequence_ =
idle;
335 if (!stopped)
return std::unexpected(stopped.error());
339 playerInPaddywagon_.reset();
342 if (!started)
return std::unexpected(started.error());
356 if (!started)
return std::unexpected(started.error());
374 if (!stopped)
return std::unexpected(stopped.error());
381 if (!stopped)
return std::unexpected(stopped.error());
385 playerInPaddywagon_.reset();
386 outbound_.reset(); inbound_.reset();
388 result.completed =
true;
395 return std::unexpected(
"invalid GoToJail playback state");
std::expected< PieceJailPlaybackUpdate, std::string > tick(std::uint64_t tick, engine::SequencePlayback &playback, rules::GameState &uiState)
std::expected< void, std::string > begin(const PieceMoveSpecialRequest &request, std::uint64_t tick, bool animationsEnabled, std::uint8_t randomBit=0)
bool active() const noexcept
constexpr DataId EmptyDataId
constexpr DataId packDataId(std::uint16_t group, DataTag tag) noexcept
constexpr std::uint8_t LoopToBeginning
PieceInterpolationSample samplePieceInterpolation(const PieceInterpolationPath &path, std::uint64_t tick) noexcept
std::optional< TokenPose > tokenOrientation(std::uint8_t boardSquare) noexcept
BoardCameraView pickCameraFor3Squares(std::int32_t square) noexcept
constexpr std::uint16_t JailPlaybackPriority
constexpr data::DataTag AnimationsPerToken
std::expected< PieceJailRoutePlan, PieceJailPlanError > planPaddyToJail(std::uint8_t tokenSquare, InterpolationVec3 startLocation, std::uint64_t startTick)
std::expected< PieceJailRoutePlan, PieceJailPlanError > planPaddyToToken(std::uint8_t tokenSquare, std::uint64_t startTick, std::uint8_t randomBit)
constexpr PlayerNumber MaxPlayers
std::variant< std::monostate, Matrix2D, Matrix3D > SequenceTransform
Matrix3D translate3D(float x, float y, float z) noexcept
Matrix3D identity3D() noexcept
Matrix2D multiply(const Matrix2D &left, const Matrix2D &right) noexcept
rules::PlayerNumber player