狐狸接入

This commit is contained in:
2025-10-08 02:52:32 +08:00
parent 089e0a2b2c
commit 3f8c38b000
26 changed files with 250 additions and 36 deletions

View File

@ -31,10 +31,6 @@ void ABusyPawnBase::BeginPlay()
// SpineAnimationComponent->SetAnimation(0, DefaultAnimationName, true);
}
void ABusyPawnBase::UpdateMoveDirection_Implementation(const FVector2D& InDirection)
{
}
float ABusyPawnBase::GetSpeed_Implementation()const
{

View File

@ -30,8 +30,13 @@ FVector2D UBusyPawnMovement::GetMoveDirection()const
return FVector2D();
}
FVector2D UBusyPawnMovement::GetForwardDirection() const
{
return ForwardDirection;
}
void UBusyPawnMovement::TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction)
FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
@ -64,6 +69,17 @@ void UBusyPawnMovement::TickComponent(float DeltaTime, ELevelTick TickType,
{
Owner->SetActorLocation(NewLocation, true);
}
Movable->Execute_UpdateMoveDirection(Owner, GetMoveDirection());
FVector2D &&NewDirection=GetMoveDirection();
if (!NewDirection.Equals(FVector2D::Zero(), 0.01))
{
ForwardDirection = NewDirection;
}
if (!NewDirection.Equals(LastMoveDirection))
{
Movable->Execute_OnMoveDirectionChanged(Owner, NewDirection);
LastMoveDirection = NewDirection;
}
}

View File

@ -51,6 +51,7 @@ void ALevelPlayerController::SetupInputComponent()
BindEnhancedInputAction(EnhancedInput, CameraDetachAction, this, "OnCameraDetach");
BindEnhancedInputAction(EnhancedInput, PrimarySkillAction, this, "OnPrimarySkill");
BindEnhancedInputAction(EnhancedInput, UltimateSkillAction, this, "OnUltimateSkill");
BindEnhancedInputAction(EnhancedInput, SwitchRoleAction, this, "OnSwitchRole");
}
void ALevelPlayerController::Tick(float DeltaTime)
@ -168,3 +169,13 @@ void ALevelPlayerController::OnCameraDetach(const FInputActionValue& Value)
SetViewTarget(ControlledRole);
}
}
void ALevelPlayerController::OnSwitchRole(const FInputActionValue& Value)
{
const int32 Index = static_cast<int32>(Value.GetMagnitude() - 1);
if (ALevelPlayerState* PS = GetPlayerState<ALevelPlayerState>())
{
ABusyPlayerRole* ControlledRole = PS->SwitchControlledRole(Index);
SwitchControlledRole(ControlledRole);
}
}

View File

@ -67,6 +67,19 @@ ABusyPlayerRole* ALevelPlayerState::GetControlledRole() const
}
}
ABusyPlayerRole* ALevelPlayerState::SwitchControlledRole(int32 Index)
{
if (RoleRoster.IsValidIndex(Index))
{
ControlledRoleIndex = Index;
return RoleRoster[ControlledRoleIndex];
}
else
{
return nullptr;
}
}
FVector2D ALevelPlayerState::GetSpawnLocation()const
{
return FVector2D::ZeroVector;

View File

@ -54,9 +54,16 @@ inline static IGameMapInterface * GetMapActor(const UActorComponent* Component)
void UStaticResourceLayerComponent::GenerateResources()
{
TArray<FVector2D> ResourcePoints;
// 生成资源点
GenerateResourcePoints(ResourcePoints);
// 生成必定生成的资源
GenerateAlwaysPresentInfo(ResourcePoints);
// 利用剩下的资源点,根据权重生成资源
GenerateResourceByWeight(ResourcePoints);
AActor *Owner = GetOwner();
UWorld* World = GetWorld();
@ -115,6 +122,34 @@ void UStaticResourceLayerComponent::GetAlwaysPresentResourceList(TMap<FName, int
}
}
#pragma optimize("",off)
bool UStaticResourceLayerComponent::GetCanGenerateResourcesWeight(const FVector2D& Position,
TArray<TTuple<FName, int>>& OutResourcesWeight) const
{
using FTuple = TTuple<FName, int>;
AActor *Owner;
IGameMapInterface * MapInterface;
OutResourcesWeight.Empty();
if (!GetOwnerInfo(Owner, MapInterface)) return false;
if (!GenerateConfig) return false;
FGameplayTag &&Terrain = MapInterface->Execute_GetTerrainAt(Owner, Position.X, Position.Y);
if (!Terrain.IsValid()) return false;
for (const auto& Pair : GenerateConfig->GetRowMap())
{
const FStaticResourceGenerateConfig* RowData = reinterpret_cast<FStaticResourceGenerateConfig*>(Pair.Value);
if (!RowData->TerrainTypes.HasTag(Terrain)) continue;
const float *TerrainWeightFindResult = RowData->TerrainWeights.Find(Terrain);
float TotalWeight = RowData->GenerateWeight * (TerrainWeightFindResult ? *TerrainWeightFindResult : 1.0);
OutResourcesWeight.Add(FTuple(Pair.Key, TotalWeight));
}
return !OutResourcesWeight.IsEmpty();
}
bool UStaticResourceLayerComponent::GenerateAlwaysPresentInfo(TArray<FVector2D>& ResourcePoints)
{
AActor *Owner = GetOwner();
@ -143,7 +178,8 @@ bool UStaticResourceLayerComponent::GenerateAlwaysPresentInfo(TArray<FVector2D>&
if (Config->TerrainTypes.HasTag(CurrentTerrain)) // 资源的地形配置包含当前的地形,则添加进生成的列表
{
GeneratedResourcePoints.Add(TTuple<FName, FVector2D>(CurrentSelected, FVector2D(ResourcePoints[i].X, ResourcePoints[i].Y)));
TryPushGenerateResult(CurrentSelected, CurrentPoint);
// GeneratedResourcePoints.Add(TTuple<FName, FVector2D>(CurrentSelected, FVector2D(ResourcePoints[i].X, ResourcePoints[i].Y)));
ConsumeOneOfAlwaysPresent(AlwaysPresentResource, CurrentSelected);
ResourcePoints[i].X = ResourcePoints[i].Y = -1;
UE_LOG(LogMapGenerate, Log, TEXT("UStaticResourceLayerComponent::GenerateAlwaysPresentInfo Create %s at (%d, %d)"),
@ -164,3 +200,52 @@ bool UStaticResourceLayerComponent::GenerateAlwaysPresentInfo(TArray<FVector2D>&
ResourcePoints.RemoveAll([](const FVector2D Element){ return Element.X < 0 && Element.Y < 0; });
return true;
}
void UStaticResourceLayerComponent::GenerateResourceByWeight(TArray<FVector2D>& ResourcePoints)
{
using FTuple = TTuple<FName, int>;
TArray<TTuple<FName, int>> ResourceWeightList;
for (const FVector2D& Point : ResourcePoints)
{
ResourceWeightList.Empty();
if (!GetCanGenerateResourcesWeight(Point, ResourceWeightList)) continue;
float Base = 0.f;
const float RandNum = static_cast<float>(FMath::Rand()) / static_cast<float>(RAND_MAX);
const float TotalWeight = Algo::Accumulate(ResourceWeightList, 0.f, [](const float Sum, const FTuple& Element)
{
return Sum + Element.Value;
});
for (FTuple& Element : ResourceWeightList)
{
const float RandomBolder = Base + Element.Value / TotalWeight;
if (RandNum >= Base && RandNum < RandomBolder)
{
TryPushGenerateResult(Element.Key, Point);
break;
}
Base = RandomBolder;
}
}
}
#pragma optimize("",on)
void UStaticResourceLayerComponent::TryPushGenerateResult(const FName& ResourceID, const FVector2D& Position)
{
GeneratedResourcePoints.Add(TTuple<FName, FVector2D>(ResourceID, Position));
}
bool UStaticResourceLayerComponent::GetOwnerInfo(AActor*& Owner, IGameMapInterface*& MapInterface) const
{
AActor *SelfOwner = GetOwner();
if (!SelfOwner) return false;
IGameMapInterface * OwnerMapInterface = Cast<IGameMapInterface>(SelfOwner);
if (!OwnerMapInterface) return false;
Owner = SelfOwner;
MapInterface = OwnerMapInterface;
return true;
}

View File

@ -21,8 +21,6 @@ public:
virtual void BeginPlay()override;
virtual void UpdateMoveDirection_Implementation(const FVector2D& InDirection) override;
virtual float GetSpeed_Implementation()const override;
protected:

View File

@ -15,9 +15,9 @@ public:
UFUNCTION(BlueprintNativeEvent)
float GetSpeed() const;
UFUNCTION(BlueprintNativeEvent, Category = "Movement")
void UpdateMoveDirection(const FVector2D &InDirection);
void OnMoveDirectionChanged(const FVector2D &InDirection);
};
@ -33,12 +33,30 @@ public:
UFUNCTION(BlueprintCallable)
void MoveTo(const FVector2D& Target);
/**
* 获取当前移动的方向
* @return 返回朝向的单位向量,如果没动返回(0,0)
*/
UFUNCTION(BlueprintCallable)
FVector2D GetMoveDirection()const;
/**
* 获取当前朝向
* @return 返回当前朝向的单位向量,如果没动,返回上一次运动时的朝向
*/
UFUNCTION(BlueprintCallable)
FVector2D GetForwardDirection()const;
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)override;
protected:
UPROPERTY(EditAnywhere, BlueprintReadOnly)
FVector2D MoveTargetLocation;
UPROPERTY(EditAnywhere, BlueprintReadOnly)
FVector2D LastMoveDirection;
UPROPERTY(EditAnywhere, BlueprintReadOnly)
FVector2D ForwardDirection;
};

View File

@ -85,6 +85,8 @@ public: // 输入相关
UPROPERTY(EditDefaultsOnly, Category = "Input")
TObjectPtr<class UInputAction> CameraDetachAction; // 相机脱离
UPROPERTY(EditDefaultsOnly, Category = "Input")
TObjectPtr<class UInputAction> SwitchRoleAction; // 切换控制的角色
public:
UFUNCTION()
@ -99,6 +101,9 @@ public:
UFUNCTION()
void OnCameraDetach(const FInputActionValue& Value);
UFUNCTION()
void OnSwitchRole(const FInputActionValue& Value);
protected:
UPROPERTY()

View File

@ -26,6 +26,9 @@ public: // 给蓝图的Get接口
UFUNCTION(BlueprintCallable)
ABusyPlayerRole* GetControlledRole() const;
public:
UFUNCTION(BlueprintCallable)
ABusyPlayerRole* SwitchControlledRole(int32 Index);
protected:
virtual FVector2D GetSpawnLocation()const;

View File

@ -5,6 +5,7 @@
#include "StaticResourceLayerComponent.generated.h"
class IGameMapInterface;
USTRUCT(BlueprintType, Blueprintable)
struct FStaticResourceGenerateConfig: public FTableRowBase
@ -17,11 +18,15 @@ struct FStaticResourceGenerateConfig: public FTableRowBase
UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName="生成的最少数量")
int MinGenerateCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName="可以在哪些地形生成")
FGameplayTagContainer TerrainTypes;
UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName="生成权重")
int GenerateWeight = 1;
UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName="可以在哪些地形生成")
FGameplayTagContainer TerrainTypes;
// 在这种地形上,最终的权重为 [生成权重]*[地形权重系数]若地形权重系数没有配置默认为1.0
UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName="地形权重系数", meta = (ClampMin = "0.0"))
TMap<FGameplayTag, float> TerrainWeights;
// 用于该资源生成时应该与某些资源保持多远的距离
UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName="生成距离规则")
@ -39,14 +44,27 @@ class UStaticResourceLayerComponent :public UActorComponent
public:
void GenerateResources();
protected: // get
void GetAlwaysPresentResourceList(TMap<FName, int32>& OutAlwaysPresentResource)const;
/**
* 获取某个点所有能生成的资源权重列表
* @param Position 给定点的位置
* @param[out] OutResourcesWeight 给定点所处的地形能够生成的所有资源列表包含资源ID和权重
*/
bool GetCanGenerateResourcesWeight(const FVector2D& Position, TArray<TTuple<FName, int>>& OutResourcesWeight)const;
protected:
virtual void GenerateResourcePoints(TArray<FVector2D>& OutResourcePoint);
void GetAlwaysPresentResourceList(TMap<FName, int32>& OutAlwaysPresentResource)const;
bool GenerateAlwaysPresentInfo(TArray<FVector2D>& ResourcePoints);
void GenerateResourceByWeight(TArray<FVector2D>& ResourcePoints);
void TryPushGenerateResult(const FName& ResourceID, const FVector2D& Position);
public:
@ -58,6 +76,7 @@ public:
TArray<TTuple<FName, FVector2D>> GeneratedResourcePoints;
protected:
private:
bool GetOwnerInfo(AActor* &Owner, IGameMapInterface* &MapInterface) const;
};