(Feat) Add Craft Systeme
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include "FpsPlayer.h"
|
||||
|
||||
#include "Camera/CameraComponent.h"
|
||||
#include "Camera/CameraTypes.h"
|
||||
#include "Components/CapsuleComponent.h"
|
||||
#include "Components/SkeletalMeshComponent.h"
|
||||
#include "EnhancedInputComponent.h"
|
||||
@@ -12,6 +13,7 @@
|
||||
#include "GameFramework/CharacterMovementComponent.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "InputActionValue.h"
|
||||
#include "CraftingComponent.h"
|
||||
#include "InteractionComponent.h"
|
||||
#include "InventoryComponent.h"
|
||||
#include "ItemDataAsset.h"
|
||||
@@ -19,6 +21,32 @@
|
||||
#include "SurvivalStatsComponent.h"
|
||||
#include "SurvivalUserSettings.h"
|
||||
|
||||
float FCameraSpring::Update(float Step, float Frequency, float Damping, float RampTime, float MaxOffset)
|
||||
{
|
||||
// L'impulsion n'est pas versee d'un coup : la vitesse passerait de 0 a
|
||||
// plusieurs centaines d'unites par seconde en une frame, et cette
|
||||
// discontinuite se lit comme un a-coup. On l'etale sur RampTime.
|
||||
if (!FMath::IsNearlyZero(PendingImpulse))
|
||||
{
|
||||
const float ReleaseRatio = (RampTime > KINDA_SMALL_NUMBER)
|
||||
? FMath::Clamp(Step / RampTime, 0.f, 1.f)
|
||||
: 1.f;
|
||||
const float Released = PendingImpulse * ReleaseRatio;
|
||||
Velocity += Released;
|
||||
PendingImpulse -= Released;
|
||||
}
|
||||
|
||||
// Ressort amorti classique : acceleration = -k*x - c*v.
|
||||
// On exprime k et c a partir d'une frequence et d'un taux d'amortissement,
|
||||
// beaucoup plus parlants a regler qu'une raideur brute.
|
||||
const float Omega = 2.f * PI * Frequency;
|
||||
const float Acceleration = -(Omega * Omega * Offset) - (2.f * Damping * Omega * Velocity);
|
||||
Velocity += Acceleration * Step;
|
||||
Offset = FMath::Clamp(Offset + Velocity * Step, -MaxOffset, MaxOffset);
|
||||
|
||||
return Offset;
|
||||
}
|
||||
|
||||
// Sets default values
|
||||
AFpsPlayer::AFpsPlayer()
|
||||
{
|
||||
@@ -47,6 +75,7 @@ AFpsPlayer::AFpsPlayer()
|
||||
|
||||
InteractionComponent = CreateDefaultSubobject<UInteractionComponent>(TEXT("InteractionComponent"));
|
||||
InventoryComponent = CreateDefaultSubobject<UInventoryComponent>(TEXT("InventoryComponent"));
|
||||
CraftingComponent = CreateDefaultSubobject<UCraftingComponent>(TEXT("CraftingComponent"));
|
||||
SurvivalStats = CreateDefaultSubobject<USurvivalStatsComponent>(TEXT("SurvivalStats"));
|
||||
|
||||
// En vue FPS on ne veut pas voir son propre corps (mesh 3e personne),
|
||||
@@ -73,6 +102,10 @@ void AFpsPlayer::BeginPlay()
|
||||
|
||||
SurvivalStats->OnDied.AddDynamic(this, &AFpsPlayer::HandleDeath);
|
||||
|
||||
// Sans cet abonnement, un objet fabrique alors que l'inventaire est plein
|
||||
// serait purement et simplement perdu.
|
||||
CraftingComponent->OnCraftOverflow.AddDynamic(this, &AFpsPlayer::HandleCraftOverflow);
|
||||
|
||||
// Les reglages d'abord : le pawn est recree a chaque respawn et repart des
|
||||
// valeurs de son CDO, il doit donc les relire lui-meme. L'abonnement couvre
|
||||
// ensuite les changements faits en cours de partie depuis le menu de pause.
|
||||
@@ -184,28 +217,14 @@ void AFpsPlayer::UpdateCameraEffects(float DeltaTime)
|
||||
}
|
||||
|
||||
// ==================================================================
|
||||
// 2. Ressort d'impact (saut, atterrissage, et tout AddCameraPunch)
|
||||
// 2. Ressorts : impact (saut, atterrissage) et bascule de tete
|
||||
// ==================================================================
|
||||
// L'impulsion n'est pas versee d'un coup : la vitesse de la camera passerait
|
||||
// de 0 a plusieurs centaines de cm/s en une frame, et cette discontinuite se
|
||||
// lit comme un a-coup. On l'etale sur PunchImpulseRampTime.
|
||||
if (!FMath::IsNearlyZero(PendingPunch))
|
||||
{
|
||||
const float ReleaseRatio = (PunchImpulseRampTime > KINDA_SMALL_NUMBER)
|
||||
? FMath::Clamp(Step / PunchImpulseRampTime, 0.f, 1.f)
|
||||
: 1.f;
|
||||
const float Released = PendingPunch * ReleaseRatio;
|
||||
PunchVelocity += Released;
|
||||
PendingPunch -= Released;
|
||||
}
|
||||
PunchSpring.Update(Step, PunchFrequency, PunchDamping, PunchImpulseRampTime, PunchMaxOffset);
|
||||
|
||||
// Ressort amorti classique : acceleration = -k*x - c*v.
|
||||
// On exprime k et c a partir d'une frequence et d'un taux d'amortissement,
|
||||
// beaucoup plus parlants a regler qu'une raideur brute.
|
||||
const float Omega = 2.f * PI * PunchFrequency;
|
||||
const float Acceleration = -(Omega * Omega * PunchOffset) - (2.f * PunchDamping * Omega * PunchVelocity);
|
||||
PunchVelocity += Acceleration * Step;
|
||||
PunchOffset = FMath::Clamp(PunchOffset + PunchVelocity * Step, -PunchMaxOffset, PunchMaxOffset);
|
||||
// Le garde-fou est en unites normalisees, ou 1 = le pic d'une bascule
|
||||
// complete. A 1.5 on laisse passer un leger cumul quand deux impulsions se
|
||||
// suivent de tres pres, sans jamais laisser la tete partir.
|
||||
CrouchTiltSpring.Update(Step, CrouchTiltFrequency, CrouchTiltDamping, CrouchTiltRampTime, 1.5f);
|
||||
|
||||
// ==================================================================
|
||||
// 3. FOV de sprint
|
||||
@@ -216,8 +235,15 @@ void AFpsPlayer::UpdateCameraEffects(float DeltaTime)
|
||||
const float TargetFOV = BaseFOV + ((bIsSprinting && bMovingFastEnough) ? SprintFOVOffset : 0.f);
|
||||
FirstPersonCamera->SetFieldOfView(FMath::FInterpTo(FirstPersonCamera->FieldOfView, TargetFOV, Step, FOVInterpSpeed));
|
||||
|
||||
// L'application est laissee a ApplyCameraTransform : CalcCamera la rappelle
|
||||
// juste avant que la vue soit lue, avec l'etat le plus frais de la capsule.
|
||||
ApplyCameraTransform();
|
||||
}
|
||||
|
||||
void AFpsPlayer::ApplyCameraTransform()
|
||||
{
|
||||
// ==================================================================
|
||||
// 4. Application : position
|
||||
// Position
|
||||
// ==================================================================
|
||||
// SmoothStep donne une courbe en S : demarrage doux, acceleration, arrivee douce.
|
||||
const float Smoothed = FMath::SmoothStep(0.f, 1.f, CrouchAlpha);
|
||||
@@ -227,22 +253,25 @@ void AFpsPlayer::UpdateCameraEffects(float DeltaTime)
|
||||
// d'un coup pour garder les pieds au sol. La camera, attachee a la capsule,
|
||||
// suivait ce saut instantane -- c'est ce qui rendait le crouch "snap".
|
||||
// En raisonnant en hauteur d'oeil AU-DESSUS DES PIEDS et en soustrayant la
|
||||
// demi-hauteur courante de la capsule, ce saut est annule exactement.
|
||||
// demi-hauteur courante de la capsule, ce saut est annule exactement --
|
||||
// a condition de lire les deux au meme instant, d'ou l'appel depuis CalcCamera.
|
||||
const float CapsuleHalfHeight = GetCapsuleComponent()->GetScaledCapsuleHalfHeight();
|
||||
FirstPersonCamera->SetRelativeLocation(FVector(0.f, 0.f, EyeHeightAboveFeet - CapsuleHalfHeight + PunchOffset));
|
||||
FirstPersonCamera->SetRelativeLocation(FVector(0.f, 0.f, EyeHeightAboveFeet - CapsuleHalfHeight + PunchSpring.Offset));
|
||||
|
||||
// ==================================================================
|
||||
// 5. Application : rotation
|
||||
// Rotation
|
||||
// ==================================================================
|
||||
// sin(alpha * PI) vaut 0 aux deux extremites et 1 au milieu : le tilt monte
|
||||
// puis redescend tout seul pendant la transition, et est nul au repos.
|
||||
// CrouchTiltDirection inverse le sens selon qu'on descend ou qu'on remonte.
|
||||
const float CrouchTiltShape = FMath::Sin(CrouchAlpha * PI) * CrouchTiltDirection;
|
||||
// La bascule ne depend plus de l'avancement de la transition : c'est l'etat
|
||||
// d'un ressort, donc elle reste continue meme si le joueur change d'avis en
|
||||
// plein mouvement. L'ancienne forme sin(alpha*PI) multipliee par un signe
|
||||
// sautait de +CrouchTiltPitch a -CrouchTiltPitch en une frame des qu'on
|
||||
// s'accroupissait et se relevait coup sur coup.
|
||||
const float CrouchTilt = CrouchTiltSpring.Offset;
|
||||
|
||||
FRotator ViewOffset(-CrouchTiltPitch * CrouchTiltShape, 0.f, CrouchTiltRoll * CrouchTiltShape);
|
||||
FRotator ViewOffset(-CrouchTiltPitch * CrouchTilt, 0.f, CrouchTiltRoll * CrouchTilt);
|
||||
// Le regard suit le deplacement vertical de la camera : elle descend, on
|
||||
// regarde vers le bas. C'est ce qui vend l'impact a l'atterrissage.
|
||||
ViewOffset.Pitch += PunchOffset * PunchPitchPerCm;
|
||||
ViewOffset.Pitch += PunchSpring.Offset * PunchPitchPerCm;
|
||||
|
||||
if (const AController* OwningController = GetController())
|
||||
{
|
||||
@@ -250,6 +279,23 @@ void AFpsPlayer::UpdateCameraEffects(float DeltaTime)
|
||||
}
|
||||
}
|
||||
|
||||
void AFpsPlayer::CalcCamera(float DeltaTime, FMinimalViewInfo& OutResult)
|
||||
{
|
||||
ApplyCameraTransform();
|
||||
|
||||
Super::CalcCamera(DeltaTime, OutResult);
|
||||
}
|
||||
|
||||
void AFpsPlayer::AddCrouchTilt(float Direction)
|
||||
{
|
||||
// Impulsion normalisee pour qu'un ressort critique culmine exactement a 1 :
|
||||
// x(t) = v0 * t * e^(-w*t) atteint son maximum v0/(e*w) en t = 1/w, donc
|
||||
// v0 = e*w. CrouchTiltPitch et CrouchTiltRoll restent ainsi des degres au
|
||||
// pic, et non un reglage a l'aveugle.
|
||||
const float Omega = 2.f * PI * CrouchTiltFrequency;
|
||||
CrouchTiltSpring.AddImpulse(Direction * UE_EULERS_NUMBER * Omega);
|
||||
}
|
||||
|
||||
void AFpsPlayer::AddCameraPunch(float Strength)
|
||||
{
|
||||
// Le reglage s'applique ICI et pas sur chaque source d'impact : tout ce qui
|
||||
@@ -257,7 +303,7 @@ void AFpsPlayer::AddCameraPunch(float Strength)
|
||||
// reculs d'arme a venir. A 0, la camera ne bouge plus du tout.
|
||||
// Mis en attente plutot qu'applique directement : c'est UpdateCameraEffects
|
||||
// qui l'injecte progressivement dans le ressort.
|
||||
PendingPunch += Strength * CameraShakeMultiplier;
|
||||
PunchSpring.AddImpulse(Strength * CameraShakeMultiplier);
|
||||
}
|
||||
|
||||
void AFpsPlayer::Landed(const FHitResult& Hit)
|
||||
@@ -529,6 +575,37 @@ bool AFpsPlayer::DropSlot(int32 SlotIndex, int32 Quantity)
|
||||
return true;
|
||||
}
|
||||
|
||||
void AFpsPlayer::HandleCraftOverflow(UItemDataAsset* Item, int32 Quantity, int32 RemainingUses)
|
||||
{
|
||||
if (!Item || Quantity <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DroppedPickupClass)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("AFpsPlayer : DroppedPickupClass n'est pas assignee, %d x %s sortis de la fabrication sont perdus."),
|
||||
Quantity, *GetNameSafe(Item));
|
||||
return;
|
||||
}
|
||||
|
||||
FInventorySlot Overflow;
|
||||
Overflow.Item = Item;
|
||||
Overflow.Quantity = Quantity;
|
||||
Overflow.RemainingUses = RemainingUses;
|
||||
|
||||
// Aux pieds et non devant les yeux comme DropSlot : le joueur fabrique le
|
||||
// nez dans un menu, il ne vise rien. Poser a distance risquerait de traverser
|
||||
// une cloison qu'on ne regarde meme pas.
|
||||
const FVector DropLocation = GetActorLocation() + GetActorForwardVector() * 40.f;
|
||||
|
||||
if (!SpawnPickup(Overflow, PlaceOnGround(DropLocation)))
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("AFpsPlayer : impossible de poser au sol %d x %s issus de la fabrication."),
|
||||
Quantity, *GetNameSafe(Item));
|
||||
}
|
||||
}
|
||||
|
||||
void AFpsPlayer::DropAllItems()
|
||||
{
|
||||
if (!DroppedPickupClass)
|
||||
@@ -597,8 +674,12 @@ void AFpsPlayer::ClearTransientInputStates()
|
||||
|
||||
void AFpsPlayer::StartCrouch()
|
||||
{
|
||||
// En mode bascule, la meme touche releve le personnage.
|
||||
if (bCrouchToggleMode && bIsCrouched)
|
||||
// En mode bascule, la meme touche releve le personnage. On teste l'INTENTION
|
||||
// (bWantsToCrouch) et non l'etat applique (bIsCrouched) : le CharacterMovement
|
||||
// ne redimensionne la capsule qu'a son propre tick, donc deux appuis dans la
|
||||
// meme frame verraient tous les deux bIsCrouched a false et le personnage
|
||||
// resterait accroupi. Symptome typique quand on martele la touche.
|
||||
if (bCrouchToggleMode && GetCharacterMovement()->bWantsToCrouch)
|
||||
{
|
||||
StopCrouch();
|
||||
return;
|
||||
@@ -635,7 +716,7 @@ void AFpsPlayer::OnStartCrouch(float HalfHeightAdjust, float ScaledHalfHeightAdj
|
||||
Super::OnStartCrouch(HalfHeightAdjust, ScaledHalfHeightAdjust);
|
||||
|
||||
CrouchTargetAlpha = 1.f;
|
||||
CrouchTiltDirection = 1.f;
|
||||
AddCrouchTilt(1.f);
|
||||
}
|
||||
|
||||
void AFpsPlayer::OnEndCrouch(float HalfHeightAdjust, float ScaledHalfHeightAdjust)
|
||||
@@ -643,5 +724,5 @@ void AFpsPlayer::OnEndCrouch(float HalfHeightAdjust, float ScaledHalfHeightAdjus
|
||||
Super::OnEndCrouch(HalfHeightAdjust, ScaledHalfHeightAdjust);
|
||||
|
||||
CrouchTargetAlpha = 0.f;
|
||||
CrouchTiltDirection = -1.f;
|
||||
AddCrouchTilt(-1.f);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user