// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Animation/AnimInstance.h" #include "FpsPlayer.h" #include "FpsArmsAnimInstance.generated.h" /** * AnimInstance des bras en vue premiere personne. * * Elle ne DECIDE de rien : elle lit l'etat du pawn une fois par frame et le * republie sous forme de variables. C'est la machine a etats du Blueprint enfant * (ABP_FpsArms) qui choisit l'animation. La separation est volontaire -- une * transition d'animation se regle a l'oeil, avec des durees de fondu, et ca n'a * rien a faire dans du C++ qu'il faut recompiler. * * Corollaire : ces variables ne sont JAMAIS repliquees. Les bras ne sont vus que * par leur proprietaire, donc chaque machine calcule les siens a partir d'un etat * de pawn que la replication a deja synchronise (vitesse, sprint, accroupi). */ UCLASS() class EMBERWILD_API UFpsArmsAnimInstance : public UAnimInstance { GENERATED_BODY() public: virtual void NativeInitializeAnimation() override; virtual void NativeUpdateAnimation(float DeltaSeconds) override; protected: // ------------------------------------------------------------------ // Etat publie vers le Blueprint d'animation // ------------------------------------------------------------------ /** Vitesse horizontale en cm/s. Sert aussi a moduler le PlayRate de la course. */ UPROPERTY(BlueprintReadOnly, Category = "Movement") float GroundSpeed = 0.f; /** Vrai quand le joueur se deplace REELLEMENT, freinage exclu. */ UPROPERTY(BlueprintReadOnly, Category = "Movement") bool bIsMoving = false; /** * Intention brute de sprint : la touche est enfoncee, rien de plus. * * NE PAS la brancher sur une transition de la machine a etats -- c'est * exactement ce qui faisait courir les bras d'un joueur immobile qui appuyait * sur Maj. Elle reste publiee parce qu'elle est la seule a dire ce que le * joueur VEUT (un effet de FOV, un cout de stamina) ; pour l'animation, c'est * bIsRunning qu'on lit. */ UPROPERTY(BlueprintReadOnly, Category = "Movement") bool bIsSprinting = false; /** * Sprint EFFECTIF : au sol, debout, et le joueur avance pour de bon. * * Toute la composition est faite ici, en un seul endroit, plutot que * reconstruite dans chaque transition du Blueprint. Une machine a etats a * autant d'entrees vers Run que d'etats voisins ; recomposer la condition a * la main dans chacune, c'est se garantir d'en oublier une. */ UPROPERTY(BlueprintReadOnly, Category = "Movement") bool bIsRunning = false; /** Deplacement au sol, debout, sans sprint. Complementaire exact de bIsRunning. */ UPROPERTY(BlueprintReadOnly, Category = "Movement") bool bIsWalking = false; UPROPERTY(BlueprintReadOnly, Category = "Movement") bool bIsFalling = false; /** * La reception qui vient d'avoir lieu, ou None tant qu'on est en l'air. * * C'est elle qui pilote la SORTIE de l'etat de chute, et il n'y a rien a * composer autour : les trois valeurs menent aux trois etats de sortie * (reception normale, reception encaissee, retour direct a la locomotion) et * s'excluent par construction. Le seuil sous lequel une chute ne merite * aucune animation vit sur le pawn -- c'est le meme que celui de la secousse * de camera, pour que les deux effets ne se contredisent jamais. */ UPROPERTY(BlueprintReadOnly, Category = "Movement") ELandingImpact LandingImpact = ELandingImpact::None; /** * Vitesse verticale signee (cm/s), positive vers le haut. * * C'est elle, et pas bIsFalling, qui distingue un saut d'une chute : le * moteur appelle « falling » tout ce qui n'est pas au sol, donc sortir d'un * rebord jouerait l'animation de detente si on se fiait au seul booleen. */ UPROPERTY(BlueprintReadOnly, Category = "Movement") float VerticalSpeed = 0.f; UPROPERTY(BlueprintReadOnly, Category = "Movement") bool bIsCrouching = false; /** * Le joueur tient un objet VISIBLE dans la main. * * A brancher sur un « Blend Poses by bool » A L'INTERIEUR de l'etat de * deplacement, jamais sur une transition vers un etat jumeau. Deux etats * « marche avec » et « marche sans » doubleraient la machine et, surtout, * equiper un outil en pleine course claquerait d'un cycle a l'autre. Un blend * fond les deux poses, l'outil apparaissant pendant que la foulee continue. * * C'est le nombre de MESHES montes qu'elle reflete, pas le contenu de la case * active : la plupart des ressources n'ont pas bShowInHand, et les tenir ne * doit pas changer la posture des bras. */ UPROPERTY(BlueprintReadOnly, Category = "Held Item") bool bHasItemInHand = false; /** * Vitesse de lecture du cycle de deplacement, a brancher sur la broche * Play Rate du noeud d'animation. * * Le projet a trois vitesses de jeu (accroupi 200, marche 400, sprint 650) * pour un seul cycle d'animation. Plutot qu'un etat par vitesse -- trois * seuils, donc trois occasions de claquer quand on les franchit -- on etire * le meme cycle. La cadence des bras suit alors la vitesse en continu, y * compris pendant l'acceleration. * * Un vrai etat Sprint n'aura de sens que le jour ou l'animateur livrera une * animation de sprint a la POSTURE differente. Le meme cycle joue plus vite * n'est pas une animation de sprint. */ UPROPERTY(BlueprintReadOnly, Category = "Movement") float LocomotionPlayRate = 1.f; /** * En dessous de cette vitesse (cm/s) on considere le joueur immobile. * * Un seuil strictement a zero ferait clignoter la transition course/repos * pendant le freinage, ou la vitesse decroit en passant par des valeurs * minuscules mais non nulles. */ UPROPERTY(EditDefaultsOnly, Category = "Movement", meta = (ClampMin = "0")) float MovingSpeedThreshold = 10.f; /** * Vitesse (cm/s) a laquelle le cycle tourne a sa cadence d'origine. * * A regler a l'oeil dans ABP_FpsArms : c'est la vitesse ou les bras ont l'air * naturels sans etirement. Par defaut la vitesse de marche du pawn, donc le * sprint accelere d'environ 60 %. */ UPROPERTY(EditDefaultsOnly, Category = "Movement", meta = (ClampMin = "1")) float ReferenceLocomotionSpeed = 400.f; /** * Bornes du Play Rate. Sans le plancher, un joueur qui rampe a 20 cm/s * regarderait des bras quasi immobiles ; sans le plafond, une future vitesse * bonus donnerait des bras en accelere qui sortent du registre credible. */ UPROPERTY(EditDefaultsOnly, Category = "Movement", meta = (ClampMin = "0.1")) float MinLocomotionPlayRate = 0.6f; UPROPERTY(EditDefaultsOnly, Category = "Movement", meta = (ClampMin = "0.1")) float MaxLocomotionPlayRate = 1.8f; private: /** * Cache du pawn. TryGetPawnOwner() fait un Cast a chaque appel, et cette * fonction tourne a chaque frame sur un mesh anime. * * TWeakObjectPtr et pas un pointeur nu : apres un respawn le pawn est detruit, * et cet objet peut lui survivre d'une frame. */ TWeakObjectPtr OwningPlayer; };