Character can now move interactively

This commit is contained in:
2024-02-16 15:48:22 -05:00
parent abb967f20b
commit 89fcb6bf8d
8 changed files with 75 additions and 8 deletions

Binary file not shown.

View File

@@ -279,6 +279,9 @@ FlxAnimTracker::FlxAnimTracker() {
void FlxAnimTracker::Clear() { void FlxAnimTracker::Clear() {
AQ.Empty(); AQ.Empty();
Changed = true; Changed = true;
AutoFinish = false;
AutoFinishAction.Empty();
AutoFinishXYZ.Set(0,0,0);
} }
void FlxAnimTracker::FinishedAnimation(uint64 hash) { void FlxAnimTracker::FinishedAnimation(uint64 hash) {
@@ -358,7 +361,6 @@ void FlxAnimTracker::Update(std::string_view encqueue) {
while (!newsteps.IsEmpty()) { while (!newsteps.IsEmpty()) {
FlxAnimationStepView step = newsteps.Pop(); FlxAnimationStepView step = newsteps.Pop();
AQ.EmplaceLast(step.Hash, step.Body); AQ.EmplaceLast(step.Hash, step.Body);
} }
// If there are too many animations in AQ, discard // If there are too many animations in AQ, discard
@@ -374,6 +376,36 @@ void FlxAnimTracker::Update(std::string_view encqueue) {
AQ.PopFirst(); AQ.PopFirst();
} }
} }
// Autofinish up to one animation.
//
if (AutoFinish) {
for (int i = 0; i < AQ.Num(); i++) {
if (!AQ[i].Finished) {
if (MatchesAutoFinish(AQ[i])) {
AQ[i].Finished = true;
}
break;
}
}
AutoFinish = false;
AutoFinishAction.Empty();
AutoFinishXYZ.Set(0,0,0);
}
}
void FlxAnimTracker::SetAutoFinish(const FString &action, const FVector &xyz) {
AutoFinish = true;
AutoFinishAction = action;
AutoFinishXYZ = xyz;
}
bool FlxAnimTracker::MatchesAutoFinish(const FlxAnimationStep &step) {
FVector xyz = UlxAnimationStepLibrary::AnimationStepGetVector(step, TEXT("xyz"));
if (xyz != AutoFinishXYZ) return false;
FString action = UlxAnimationStepLibrary::AnimationStepGetString(step, TEXT("action"));
if (action != AutoFinishAction) return false;
return true;
} }
FString FlxAnimTracker::GetCurrentBlueprintName() { FString FlxAnimTracker::GetCurrentBlueprintName() {
@@ -393,6 +425,8 @@ FlxAnimationStep FlxAnimTracker::GetCurrentAnimation() {
} }
} }
result = AQ.Last(); result = AQ.Last();
result.Hash = 0; // This next line is a hack. We need the idle step to have a unique
// hash. This is a passable way to get a unique hash value.
result.Hash += 1;
return result; return result;
} }

View File

@@ -259,7 +259,15 @@ public:
// //
bool Changed; bool Changed;
// Autofinish parameters.
//
bool AutoFinish;
FString AutoFinishAction;
FVector AutoFinishXYZ;
private: private:
bool MatchesAutoFinish(const FlxAnimationStep &step);
public: public:
// Construct a tracker. // Construct a tracker.
// //
@@ -278,6 +286,14 @@ public:
// //
void Update(std::string_view encqueue); void Update(std::string_view encqueue);
// Auto-finish animation.
//
// Next time 'update' is called, we will check for the presence
// of a new animation matching these parameters. If there is
// one, it is automatically marked 'finished'.
//
void SetAutoFinish(const FString &action, const FVector &xyz);
// Get the current blueprint name, as a string. // Get the current blueprint name, as a string.
// //
FString GetCurrentBlueprintName(); FString GetCurrentBlueprintName();

View File

@@ -132,7 +132,7 @@ void AIntegrationGameModeBase::UpdateTangibles() {
TangibleManager->DeleteFarawayTangibles(); TangibleManager->DeleteFarawayTangibles();
} }
void AIntegrationGameModeBase::InvokeEngioMove(const FString &action, const FVector &xyz) { void AIntegrationGameModeBase::InvokeEngioMove(const FString &action, const FVector &xyz, double facing) {
FTCHARToUTF8 utf8action(action); FTCHARToUTF8 utf8action(action);
std::string uaction(utf8action.Get(), utf8action.Length()); std::string uaction(utf8action.Get(), utf8action.Length());
FlxStreamBuffer sb; FlxStreamBuffer sb;
@@ -141,6 +141,8 @@ void AIntegrationGameModeBase::InvokeEngioMove(const FString &action, const FVec
sb.write_string(uaction); sb.write_string(uaction);
sb.write_simple_dynamic_tag(SimpleDynamicTag::VECTOR); sb.write_simple_dynamic_tag(SimpleDynamicTag::VECTOR);
sb.write_fvector(xyz); sb.write_fvector(xyz);
sb.write_simple_dynamic_tag(SimpleDynamicTag::NUMBER);
sb.write_double(facing);
std::string_view datapk = sb.view(); std::string_view datapk = sb.view();
FlxLockedWrapper w(LockableWrapper); FlxLockedWrapper w(LockableWrapper);
int64 player = w.GetActor(); int64 player = w.GetActor();
@@ -197,6 +199,8 @@ void AIntegrationGameModeBase::OnWorldPreActorTick(UWorld* InWorld, ELevelTick I
{ {
LuprexUpdateTask.Wait(); LuprexUpdateTask.Wait();
EngineSeconds += deltaseconds; EngineSeconds += deltaseconds;
UpdateConsoleOutput();
UpdateTangibles();
} }
} }

View File

@@ -43,7 +43,7 @@ public:
int64 GetPlayerId(); int64 GetPlayerId();
UFUNCTION(BlueprintCallable, Category = "Luprex") UFUNCTION(BlueprintCallable, Category = "Luprex")
void InvokeEngioMove(const FString &action, const FVector &xyz); void InvokeEngioMove(const FString &action, const FVector &xyz, double facing);
// Execute a debugging command, typed on the GUI. // Execute a debugging command, typed on the GUI.
void ExecuteDebuggingCommand(FlxLockedWrapper &w, const FString &fs); void ExecuteDebuggingCommand(FlxLockedWrapper &w, const FString &fs);

View File

@@ -163,3 +163,8 @@ bool UlxTangible::IsCurrentPlayer(AActor* target) {
AIntegrationGameModeBase *gamemode = tan->Manager->GetGameMode(); AIntegrationGameModeBase *gamemode = tan->Manager->GetGameMode();
return (tan->TangibleId == gamemode->PlayerId); return (tan->TangibleId == gamemode->PlayerId);
} }
void UlxTangible::SetAutoFinish(AActor *target, const FString &action, const FVector &xyz) {
UlxTangible *tan = GetActorTangible(target);
tan->AnimTracker.SetAutoFinish(action, xyz);
}

View File

@@ -165,6 +165,9 @@ public:
UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "target"), Category = Luprex) UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "target"), Category = Luprex)
static bool IsCurrentPlayer(AActor *target); static bool IsCurrentPlayer(AActor *target);
UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "target"), Category = Luprex)
static void SetAutoFinish(AActor *target, const FString &action, const FVector &xyz);
}; };

View File

@@ -37,14 +37,19 @@ private:
// This event is used to wake up the thread. // This event is used to wake up the thread.
// //
// This is an auto-reset event, meaning that each time we
// call trigger, the background thread is gated exactly once.
//
// Normally, this means we want the worker to run the task // Normally, this means we want the worker to run the task
// once. But if ThreadStopRequested is true, it means we // once. But if ThreadStopRequested is true, it means we
// want the thread to exit. // want the thread to exit.
// //
FEvent* CallEvent; FEvent* CallEvent;
// This event is used when the thread is done // This event is used when the thread is done with its work.
// with its work. //
// This is not an auto-reset event. This event stays triggered
// whenever the background thread is not running.
// //
FEvent* ReturnEvent; FEvent* ReturnEvent;