Fixed freezes on controller calling MarkPath() to invalid locations
This commit is contained in:
parent
28a226e35d
commit
26d3289962
146
AdventureMap.cpp
146
AdventureMap.cpp
@ -7,6 +7,7 @@
|
|||||||
#include "AdventurePlayerController.h"
|
#include "AdventurePlayerController.h"
|
||||||
#include "Kismet/GameplayStatics.h"
|
#include "Kismet/GameplayStatics.h"
|
||||||
#include "Algo/Reverse.h"
|
#include "Algo/Reverse.h"
|
||||||
|
#include "Util/IndexPriorityQueue.h"
|
||||||
|
|
||||||
// Sets default values
|
// Sets default values
|
||||||
AAdventureMap::AAdventureMap()
|
AAdventureMap::AAdventureMap()
|
||||||
@ -85,12 +86,12 @@ AHexTile* AAdventureMap::RandomHex()
|
|||||||
TArray<AHexTile*> AAdventureMap::Neighbors(AHexTile* OfHex, bool bFreeOnly = false)
|
TArray<AHexTile*> AAdventureMap::Neighbors(AHexTile* OfHex, bool bFreeOnly = false)
|
||||||
{
|
{
|
||||||
TArray<AHexTile*> Results;
|
TArray<AHexTile*> Results;
|
||||||
for (auto& V : UnitVectors) {
|
for (FHexVector NeighborVector : UnitVectors) {
|
||||||
int32 I = GridIndex(OfHex->Q + V.Q, OfHex->R + V.R);
|
int32 Index = GridIndex(OfHex->Q + NeighborVector.Q, OfHex->R + NeighborVector.R);
|
||||||
if (Grid.IsValidIndex(I)) {
|
if (Grid.IsValidIndex(Index)) {
|
||||||
AHexTile* H = Grid[I];
|
AHexTile* Hex = Grid[Index];
|
||||||
if (bFreeOnly && !H->bFree) { continue; }
|
if (bFreeOnly && !Hex->bFree) { continue; }
|
||||||
if (H->Distance(OfHex) == 1) { Results.Add(H); }
|
if (Hex->Distance(OfHex) == 1) { Results.Add(Hex); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Results;
|
return Results;
|
||||||
@ -120,66 +121,66 @@ TArray<AHexTile*> AAdventureMap::FreeDiagonals(AHexTile* OfHex)
|
|||||||
TSet<AHexTile*> AAdventureMap::BreadthFirstSearch(AHexTile* Start, int32 Radius)
|
TSet<AHexTile*> AAdventureMap::BreadthFirstSearch(AHexTile* Start, int32 Radius)
|
||||||
{
|
{
|
||||||
TSet<AHexTile*> Results;
|
TSet<AHexTile*> Results;
|
||||||
TArray<AHexTile*> ToExamine;
|
TArray<AHexTile*> Frontier;
|
||||||
TSet<AHexTile*> Processed;
|
TSet<AHexTile*> Processed;
|
||||||
Results.Add(Start);
|
Results.Add(Start);
|
||||||
ToExamine.Add(Start);
|
Frontier.Add(Start);
|
||||||
|
|
||||||
while (!ToExamine.IsEmpty()) {
|
while (!Frontier.IsEmpty()) {
|
||||||
AHexTile* Candidate = ToExamine[0];
|
AHexTile* Current = Frontier[0];
|
||||||
Processed.Add(Candidate);
|
Processed.Add(Current);
|
||||||
ToExamine.Remove(Candidate);
|
Frontier.Remove(Current);
|
||||||
|
|
||||||
for (AHexTile* Neighbor : Neighbors(Candidate)) {
|
for (AHexTile* Neighbor : Neighbors(Current)) {
|
||||||
if (Neighbor->Distance(Candidate) > 1) { continue; }
|
if (Neighbor->Distance(Current) > 1) { continue; }
|
||||||
if (Processed.Contains(Neighbor)) { continue; }
|
if (Processed.Contains(Neighbor)) { continue; }
|
||||||
if (Neighbor->Distance(Start) > Radius) { continue; }
|
if (Neighbor->Distance(Start) > Radius) { continue; }
|
||||||
|
|
||||||
ToExamine.Add(Neighbor);
|
Frontier.Add(Neighbor);
|
||||||
Results.Add(Neighbor);
|
Results.Add(Neighbor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Results;
|
return Results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* // Faulty implementation which uses an actual PriorityQueue
|
||||||
TArray<AHexTile*> AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal, bool bDiags)
|
TArray<AHexTile*> AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal, bool bDiags)
|
||||||
{
|
{
|
||||||
TArray<AHexTile*> ToExamine;
|
|
||||||
TSet<AHexTile*> Processed;
|
TSet<AHexTile*> Processed;
|
||||||
ToExamine.Add(Start);
|
TSet<AHexTile*> ToSearch;
|
||||||
|
TPriorityQueue<AHexTile*> Frontier;
|
||||||
|
|
||||||
while (!ToExamine.IsEmpty()) {
|
Start->GCost = 0;
|
||||||
AHexTile* Candidate = ToExamine[0];
|
Frontier.Push(Start, .0f);
|
||||||
ToExamine.Remove(Candidate);
|
ToSearch.Add(Start);
|
||||||
// find Hex with lower estimatet F-cost
|
|
||||||
for (AHexTile* t : ToExamine) {
|
|
||||||
t->FCost = t->GCost + t->HCost;
|
|
||||||
if (t->FCost < Candidate->FCost || t->FCost == Candidate->FCost && t->HCost < Candidate->HCost) { Candidate = t; }
|
|
||||||
}
|
|
||||||
|
|
||||||
Processed.Add(Candidate);
|
while (!Frontier.IsEmpty()) {
|
||||||
// exit
|
AHexTile* Current = Frontier.Pop();
|
||||||
if (Candidate == Goal) { break; }
|
ToSearch.Remove(Current);
|
||||||
|
|
||||||
// expand frontier & adjust path data
|
if (Current == Goal) { break; }
|
||||||
for (AHexTile* Neighbor : Neighbors(Candidate, true)) {
|
Processed.Add(Current);
|
||||||
if (!Neighbor->bFree) { continue; }
|
|
||||||
|
for (AHexTile* Neighbor : Neighbors(Current, true)) {
|
||||||
if (Processed.Contains(Neighbor)) { continue; }
|
if (Processed.Contains(Neighbor)) { continue; }
|
||||||
|
bool bInToSearch = ToSearch.Contains(Start);
|
||||||
|
|
||||||
bool bInToExamine = ToExamine.Contains(Neighbor);
|
int32 NewGCost = Current->GCost + Neighbor->MoveCost;
|
||||||
float NewGCost = Candidate->GCost + Neighbor->MoveCost;
|
|
||||||
|
|
||||||
if (NewGCost < Neighbor->GCost || !bInToExamine) {
|
if (!bInToSearch || NewGCost < Neighbor->GCost) {
|
||||||
Neighbor->GCost = NewGCost;
|
Neighbor->GCost = NewGCost;
|
||||||
Neighbor->CameFrom = Candidate; // chain
|
Neighbor->CameFrom = Current;
|
||||||
Neighbor->bDiagMove = false;
|
|
||||||
|
|
||||||
if (!bInToExamine) {
|
if (!bInToSearch) {
|
||||||
Neighbor->HCost = Neighbor->Distance(Goal);
|
Neighbor->HCost = Neighbor->Distance(Goal);
|
||||||
ToExamine.Add(Neighbor);
|
Frontier.Push(Neighbor, NewGCost + Neighbor->HCost);
|
||||||
} }
|
ToSearch.Add(Neighbor);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TArray<AHexTile*> Path;
|
TArray<AHexTile*> Path;
|
||||||
if (!IsValid(Goal->CameFrom)) { return Path; }
|
if (!IsValid(Goal->CameFrom)) { return Path; }
|
||||||
AHexTile* iPathNode = Goal;
|
AHexTile* iPathNode = Goal;
|
||||||
@ -188,10 +189,62 @@ TArray<AHexTile*> AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal,
|
|||||||
iPathNode = iPathNode->CameFrom;
|
iPathNode = iPathNode->CameFrom;
|
||||||
}
|
}
|
||||||
Algo::Reverse(Path);
|
Algo::Reverse(Path);
|
||||||
|
return Path;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (bDiags) { // DO NOT USE
|
TArray<AHexTile*> AAdventureMap::FindPathAStar(AHexTile * Start, AHexTile * Goal, bool bDiags)
|
||||||
Path = ShortcutAStar(Path);
|
{
|
||||||
|
TArray<AHexTile*> Frontier;
|
||||||
|
TSet<AHexTile*> Processed;
|
||||||
|
Frontier.Add(Start);
|
||||||
|
while (!Frontier.IsEmpty()) {
|
||||||
|
// Pop
|
||||||
|
AHexTile* Candidate = Frontier[0];
|
||||||
|
|
||||||
|
// Exit
|
||||||
|
if (Candidate == Goal) { break; }
|
||||||
|
|
||||||
|
// Find contender with an even lower F-cost
|
||||||
|
for (AHexTile* Other : Frontier) {
|
||||||
|
if (Other->FCost < Candidate->FCost
|
||||||
|
|| Other->FCost == Candidate->FCost && Other->HCost < Candidate->HCost)
|
||||||
|
{ Candidate = Other; }
|
||||||
|
}
|
||||||
|
|
||||||
|
Frontier.Remove(Candidate);
|
||||||
|
Processed.Add(Candidate);
|
||||||
|
// Expand frontier, make connections when appropriate
|
||||||
|
for (AHexTile* Neighbor : Neighbors(Candidate, true)) {
|
||||||
|
if (Processed.Contains(Neighbor)) { continue; }
|
||||||
|
|
||||||
|
bool bInFrontier = Frontier.Contains(Neighbor);
|
||||||
|
int32 NewGCost = Candidate->GCost + Neighbor->MoveCost;
|
||||||
|
|
||||||
|
if (NewGCost < Neighbor->GCost || !bInFrontier) {
|
||||||
|
Neighbor->GCost = NewGCost;
|
||||||
|
Neighbor->HCost = Neighbor->Distance(Goal);
|
||||||
|
Neighbor->FCost = Neighbor->GCost + Neighbor->HCost;
|
||||||
|
Neighbor->CameFrom = Candidate; // chain
|
||||||
|
if (!bInFrontier) {
|
||||||
|
Frontier.Add(Neighbor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build and return path
|
||||||
|
TArray<AHexTile*> Path;
|
||||||
|
AHexTile* iPathNode = Goal;
|
||||||
|
while (iPathNode != Start) {
|
||||||
|
if (!IsValid(iPathNode->CameFrom) || !iPathNode->bFree) {
|
||||||
|
Path.Empty();
|
||||||
|
return Path;
|
||||||
|
}
|
||||||
|
Path.Emplace(iPathNode);
|
||||||
|
iPathNode = iPathNode->CameFrom;
|
||||||
|
}
|
||||||
|
Algo::Reverse(Path);
|
||||||
return Path;
|
return Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,11 +299,11 @@ TArray<AHexTile*> AAdventureMap::ShortcutAStar(TArray<AHexTile*> Path)
|
|||||||
if (DiagIsReachable(CurrentHex, UnitDiag)) {
|
if (DiagIsReachable(CurrentHex, UnitDiag)) {
|
||||||
int32 CanIndex = GridIndex(CurrentHex->Q + UnitDiag.Q, CurrentHex->R + UnitDiag.R);
|
int32 CanIndex = GridIndex(CurrentHex->Q + UnitDiag.Q, CurrentHex->R + UnitDiag.R);
|
||||||
if (Grid.IsValidIndex(CanIndex)) {
|
if (Grid.IsValidIndex(CanIndex)) {
|
||||||
AHexTile* Candidate = Grid[CanIndex];
|
AHexTile* Current = Grid[CanIndex];
|
||||||
if (Candidate->bFree) {
|
if (Current->bFree) {
|
||||||
Shortcut.Add(Candidate);
|
Shortcut.Add(Current);
|
||||||
bDiagAdded = true;
|
bDiagAdded = true;
|
||||||
CurrentHex = Candidate;
|
CurrentHex = Current;
|
||||||
NumDiags--;
|
NumDiags--;
|
||||||
continue;
|
continue;
|
||||||
} } }
|
} } }
|
||||||
@ -298,4 +351,5 @@ bool AAdventureMap::DiagIsReachable(AHexTile* InStart, FHexVector InDiagUnitVec)
|
|||||||
AHexTile* HexA = Grid[IndexA];
|
AHexTile* HexA = Grid[IndexA];
|
||||||
AHexTile* HexB = Grid[IndexB];
|
AHexTile* HexB = Grid[IndexB];
|
||||||
return (HexA->bFree && HexB->bFree);
|
return (HexA->bFree && HexB->bFree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,3 +106,63 @@ protected:
|
|||||||
// Called when the game starts or when spawned
|
// Called when the game starts or when spawned
|
||||||
virtual void BeginPlay() override;
|
virtual void BeginPlay() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// only used for an experimental implementation of A*
|
||||||
|
template <typename InElementType>
|
||||||
|
struct TPriorityQueueNode {
|
||||||
|
InElementType Element;
|
||||||
|
float Priority;
|
||||||
|
|
||||||
|
TPriorityQueueNode()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TPriorityQueueNode(InElementType InElement, float InPriority)
|
||||||
|
{
|
||||||
|
Element = InElement;
|
||||||
|
Priority = InPriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const TPriorityQueueNode<InElementType> Other) const
|
||||||
|
{
|
||||||
|
return Priority < Other.Priority;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template <typename InElementType>
|
||||||
|
class TPriorityQueue {
|
||||||
|
public:
|
||||||
|
TPriorityQueue()
|
||||||
|
{
|
||||||
|
Array.Heapify();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Always check if IsEmpty() before Pop-ing!
|
||||||
|
InElementType Pop()
|
||||||
|
{
|
||||||
|
TPriorityQueueNode<InElementType> Node;
|
||||||
|
Array.HeapPop(Node);
|
||||||
|
return Node.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
TPriorityQueueNode<InElementType> PopNode()
|
||||||
|
{
|
||||||
|
TPriorityQueueNode<InElementType> Node;
|
||||||
|
Array.HeapPop(Node);
|
||||||
|
return Node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Push(InElementType Element, float Priority)
|
||||||
|
{
|
||||||
|
Array.HeapPush(TPriorityQueueNode<InElementType>(Element, Priority));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEmpty() const
|
||||||
|
{
|
||||||
|
return Array.Num() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public: // make private later on
|
||||||
|
TArray<TPriorityQueueNode<InElementType>> Array;
|
||||||
|
};
|
@ -59,7 +59,6 @@ TArray<AHexTile*> AAdventurePlayerController::Vision(int32 Radius)
|
|||||||
{
|
{
|
||||||
TArray<AHexTile*> Results;
|
TArray<AHexTile*> Results;
|
||||||
TSet<AHexTile*> Visible;
|
TSet<AHexTile*> Visible;
|
||||||
if (CurrentHex->bDiagMove) { Radius = FMath::FloorToInt(float(Radius) * (2.f / 3.f)); }
|
|
||||||
Visible = MapRef->BreadthFirstSearch(CurrentHex, Radius);
|
Visible = MapRef->BreadthFirstSearch(CurrentHex, Radius);
|
||||||
for (auto& Hex : Visible) {
|
for (auto& Hex : Visible) {
|
||||||
if (ExploredHexes.Contains(Hex)) { continue; }
|
if (ExploredHexes.Contains(Hex)) { continue; }
|
||||||
@ -71,6 +70,10 @@ TArray<AHexTile*> AAdventurePlayerController::Vision(int32 Radius)
|
|||||||
|
|
||||||
void AAdventurePlayerController::MarkPath(TArray<AHexTile*> Path)
|
void AAdventurePlayerController::MarkPath(TArray<AHexTile*> Path)
|
||||||
{
|
{
|
||||||
|
if (Path.IsEmpty()) { return; }
|
||||||
|
else if (!IsValid(Path[0])) { return; }
|
||||||
|
else if (CurrentHex->Distance(Path[0])>1) { return; }
|
||||||
|
|
||||||
FHexVector DirA = FHexVector(Path[0]->Q - CurrentHex->Q, Path[0]->R - CurrentHex->R);
|
FHexVector DirA = FHexVector(Path[0]->Q - CurrentHex->Q, Path[0]->R - CurrentHex->R);
|
||||||
FHexVector DirB;
|
FHexVector DirB;
|
||||||
for (int32 i = 0; i < Path.Num() - 1; i++)
|
for (int32 i = 0; i < Path.Num() - 1; i++)
|
||||||
|
18
HexTile.h
18
HexTile.h
@ -48,19 +48,15 @@ public:
|
|||||||
|
|
||||||
// Pathfinding
|
// Pathfinding
|
||||||
UPROPERTY(BlueprintReadWrite)
|
UPROPERTY(BlueprintReadWrite)
|
||||||
float MoveCost = 10;
|
int32 MoveCost = 1;
|
||||||
|
UPROPERTY()
|
||||||
|
int32 FCost;
|
||||||
|
UPROPERTY()
|
||||||
|
int32 GCost = 9999;
|
||||||
|
UPROPERTY()
|
||||||
|
int32 HCost;
|
||||||
UPROPERTY(BlueprintReadWrite, VisibleInstanceOnly, Category = "Runtime")
|
UPROPERTY(BlueprintReadWrite, VisibleInstanceOnly, Category = "Runtime")
|
||||||
AHexTile* CameFrom;
|
AHexTile* CameFrom;
|
||||||
UPROPERTY(BlueprintReadWrite, VisibleInstanceOnly, Category = "Runtime")
|
|
||||||
AHexTile* LeadsTo;
|
|
||||||
UPROPERTY(BlueprintReadWrite, VisibleInstanceOnly, Category = "Runtime")
|
|
||||||
bool bDiagMove = false;
|
|
||||||
UPROPERTY()
|
|
||||||
float FCost;
|
|
||||||
UPROPERTY()
|
|
||||||
float GCost;
|
|
||||||
UPROPERTY()
|
|
||||||
float HCost = 9999;
|
|
||||||
|
|
||||||
// MapObject Placement
|
// MapObject Placement
|
||||||
UPROPERTY(BlueprintReadWrite, VisibleAnywhere)
|
UPROPERTY(BlueprintReadWrite, VisibleAnywhere)
|
||||||
|
@ -26,60 +26,51 @@ AMovementArrow::AMovementArrow()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AMovementArrow::SetVariant(FHexVector InVector, FHexVector OutVector) {
|
void AMovementArrow::SetVariant(FHexVector InVector, FHexVector OutVector) {
|
||||||
|
|
||||||
int32 InVectorIndex = MapRef->UnitVectors.Find(InVector);
|
int32 InVectorIndex = MapRef->UnitVectors.Find(InVector);
|
||||||
int32 OutVectorIndex = MapRef->UnitVectors.Find(OutVector);
|
int32 OutVectorIndex = MapRef->UnitVectors.Find(OutVector);
|
||||||
int32 VariantIndex;
|
int32 VariantIndex;
|
||||||
|
if (InVectorIndex == 0) {
|
||||||
if (InVectorIndex == 0)
|
|
||||||
{
|
|
||||||
if (OutVectorIndex == 0) { VariantIndex = 0; }
|
if (OutVectorIndex == 0) { VariantIndex = 0; }
|
||||||
if (OutVectorIndex == 1) { VariantIndex = 1; }
|
if (OutVectorIndex == 1) { VariantIndex = 1; }
|
||||||
if (OutVectorIndex == 2) { VariantIndex = 2; }
|
if (OutVectorIndex == 2) { VariantIndex = 2; }
|
||||||
if (OutVectorIndex == 4) { VariantIndex = 3; }
|
if (OutVectorIndex == 4) { VariantIndex = 3; }
|
||||||
if (OutVectorIndex == 5) { VariantIndex = 4; }
|
if (OutVectorIndex == 5) { VariantIndex = 4; }
|
||||||
}
|
}
|
||||||
if (InVectorIndex == 1)
|
if (InVectorIndex == 1) {
|
||||||
{
|
|
||||||
if (OutVectorIndex == 0) { VariantIndex = 4; }
|
if (OutVectorIndex == 0) { VariantIndex = 4; }
|
||||||
if (OutVectorIndex == 1) { VariantIndex = 0; }
|
if (OutVectorIndex == 1) { VariantIndex = 0; }
|
||||||
if (OutVectorIndex == 2) { VariantIndex = 1; }
|
if (OutVectorIndex == 2) { VariantIndex = 1; }
|
||||||
if (OutVectorIndex == 3) { VariantIndex = 2; }
|
if (OutVectorIndex == 3) { VariantIndex = 2; }
|
||||||
if (OutVectorIndex == 5) { VariantIndex = 3; }
|
if (OutVectorIndex == 5) { VariantIndex = 3; }
|
||||||
}
|
}
|
||||||
if (InVectorIndex == 2)
|
if (InVectorIndex == 2) {
|
||||||
{
|
|
||||||
if (OutVectorIndex == 0) { VariantIndex = 3; }
|
if (OutVectorIndex == 0) { VariantIndex = 3; }
|
||||||
if (OutVectorIndex == 1) { VariantIndex = 4; }
|
if (OutVectorIndex == 1) { VariantIndex = 4; }
|
||||||
if (OutVectorIndex == 2) { VariantIndex = 0; }
|
if (OutVectorIndex == 2) { VariantIndex = 0; }
|
||||||
if (OutVectorIndex == 3) { VariantIndex = 1; }
|
if (OutVectorIndex == 3) { VariantIndex = 1; }
|
||||||
if (OutVectorIndex == 4) { VariantIndex = 2; }
|
if (OutVectorIndex == 4) { VariantIndex = 2; }
|
||||||
}
|
}
|
||||||
if (InVectorIndex == 3)
|
if (InVectorIndex == 3) {
|
||||||
{
|
|
||||||
if (OutVectorIndex == 1) { VariantIndex = 3; }
|
if (OutVectorIndex == 1) { VariantIndex = 3; }
|
||||||
if (OutVectorIndex == 2) { VariantIndex = 4; }
|
if (OutVectorIndex == 2) { VariantIndex = 4; }
|
||||||
if (OutVectorIndex == 3) { VariantIndex = 0; }
|
if (OutVectorIndex == 3) { VariantIndex = 0; }
|
||||||
if (OutVectorIndex == 4) { VariantIndex = 1; }
|
if (OutVectorIndex == 4) { VariantIndex = 1; }
|
||||||
if (OutVectorIndex == 5) { VariantIndex = 2; }
|
if (OutVectorIndex == 5) { VariantIndex = 2; }
|
||||||
}
|
}
|
||||||
if (InVectorIndex == 4)
|
if (InVectorIndex == 4) {
|
||||||
{
|
|
||||||
if (OutVectorIndex == 0) { VariantIndex = 2; }
|
if (OutVectorIndex == 0) { VariantIndex = 2; }
|
||||||
if (OutVectorIndex == 2) { VariantIndex = 3; }
|
if (OutVectorIndex == 2) { VariantIndex = 3; }
|
||||||
if (OutVectorIndex == 3) { VariantIndex = 4; }
|
if (OutVectorIndex == 3) { VariantIndex = 4; }
|
||||||
if (OutVectorIndex == 4) { VariantIndex = 0; }
|
if (OutVectorIndex == 4) { VariantIndex = 0; }
|
||||||
if (OutVectorIndex == 5) { VariantIndex = 1; }
|
if (OutVectorIndex == 5) { VariantIndex = 1; }
|
||||||
}
|
}
|
||||||
if (InVectorIndex == 5)
|
if (InVectorIndex == 5) {
|
||||||
{
|
|
||||||
if (OutVectorIndex == 0) { VariantIndex = 1; }
|
if (OutVectorIndex == 0) { VariantIndex = 1; }
|
||||||
if (OutVectorIndex == 1) { VariantIndex = 2; }
|
if (OutVectorIndex == 1) { VariantIndex = 2; }
|
||||||
if (OutVectorIndex == 3) { VariantIndex = 3; }
|
if (OutVectorIndex == 3) { VariantIndex = 3; }
|
||||||
if (OutVectorIndex == 4) { VariantIndex = 4; }
|
if (OutVectorIndex == 4) { VariantIndex = 4; }
|
||||||
if (OutVectorIndex == 5) { VariantIndex = 0; }
|
if (OutVectorIndex == 5) { VariantIndex = 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneComponent->SetRelativeRotation(FRotator(0, InVectorIndex * 60.f, 0));
|
SceneComponent->SetRelativeRotation(FRotator(0, InVectorIndex * 60.f, 0));
|
||||||
MeshVariants[VariantIndex]->ToggleVisibility();
|
MeshVariants[VariantIndex]->ToggleVisibility();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user