- H3a : version de reference 2026.10.4 (identique au V1.4 publie), mod d'essai LPHairSample (ModSources/, cuisson DLC contre 2026.10.4), pipeline de coiffures compatible plugins. - Activation des modules alignee sur le jeu (module absent = inactif) ; cle .lpmod MODULE_DEFAULT_ENABLED (lp_Revival). - UI15 : entree Mod Manager sur l'ecran titre, retour au menu titre, choix enregistre sans toucher a la derniere sauvegarde (LPTitleModManager, SaveModSelection). Valide en jeu le 2026-10-03 (CHG-101 a CHG-103, ERR-040, ERR-041). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
110 lines
5 KiB
C++
110 lines
5 KiB
C++
// Portage UE 5.5 - lots H1 et H2 (Docs/Migration/11_Audit_Optimisation.md §16.7 et §16.9).
|
|
//
|
|
// La liste des coiffures du jeu est la valeur par defaut de GI.HairstyleTable (126 entrees ecrites dans le Blueprint),
|
|
// avec GI.MorphableHairs (morph d'ajustement par coiffure) : un mod ne pouvait pas y toucher. Ce sous-systeme lit les
|
|
// fichiers texte Modules/<module>/**/*.lphair. Un fichier peut decrire plusieurs coiffures : chaque ligne HAIRSTYLE
|
|
// ouvre une entree, les lignes suivantes la completent.
|
|
//
|
|
// HAIRSTYLE: /Game/Heavy/New5/Hairs/Exemple.Exemple chemin complet d'un SkeletalMesh (squelette Genesis 8),
|
|
// ou NONE (option "sans cheveux")
|
|
// SEX: F F ou M (defaut F)
|
|
// DAZ: true defaut true ; false = coiffure "legacy", chargee seulement
|
|
// si GI.LegacyPercentage > 0
|
|
// FIT_MORPH: Exemple__AllExpand 0.45 facultatif : morph applique par Person.FitMorphableHair
|
|
// MORPHABLE: Cle [Morph Valeur] entree brute de GI.MorphableHairs (fichier de base)
|
|
// MODE: BASE fichier de base (H2) : la table est reconstruite a partir de
|
|
// ce fichier, dans son ordre, avant l'ajout des autres modules
|
|
//
|
|
// Pilosite (textures appliquees a la peau par Person.setBHairstyle, lot H2b) : listes de noms de textures, dans le
|
|
// dossier impose par le Blueprint (prefixe + nom) :
|
|
// FACIAL_HAIR: Facial_Hair__1_ GI.FHairstyles (barbe ; /Game/Heavy/Daz/Michael/hairs/other/)
|
|
// BODY_HAIR_M: JPBH78-TorsoNG-01 GI.BHairstyles_M (torse masculin ; meme dossier)
|
|
// BODY_HAIR_F: Pubes01 GI.BHairstyles (pubis feminin ; /Game/Heavy/Daz/Bridget/Hairs/Pubic/)
|
|
// Le fichier de base reconstruit chaque liste qu'il decrit ; les autres modules y ajoutent des noms (texture verifiee).
|
|
//
|
|
// Sans fichier de base, les coiffures sont ajoutees en fin de la table du Blueprint (H1). Les coiffures des modules
|
|
// sont controlees (SkeletalMesh present, pas de doublon) ; celles du fichier de base sont reprises telles quelles,
|
|
// comme dans le Blueprint (35 coiffures "legacy" absentes du projet depuis 4.27 y figurent).
|
|
// Les modules desactives dans GI.ModEnableds sont ignores ; la table est reconstruite quand cette liste change.
|
|
// Option -LPVerifyHairstyles : la table et les morphs construits depuis le fichier de base sont compares a ceux du
|
|
// Blueprint (texte exporte), avant l'ajout des modules.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "Containers/Ticker.h"
|
|
#include "Subsystems/GameInstanceSubsystem.h"
|
|
#include "LPHairstyleSubsystem.generated.h"
|
|
|
|
UCLASS()
|
|
class LIFEPLAY_API ULPHairstyleSubsystem : public UGameInstanceSubsystem
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
|
virtual void Deinitialize() override;
|
|
|
|
private:
|
|
struct FHairDef
|
|
{
|
|
FString File;
|
|
FString Module;
|
|
FString Path;
|
|
bool bNone = false;
|
|
bool bMale = false;
|
|
bool bDaz = true;
|
|
FString FitMorph;
|
|
FString FitValue;
|
|
};
|
|
|
|
struct FTextureDef
|
|
{
|
|
int32 List = 0;
|
|
FString Name;
|
|
FString File;
|
|
FString Module;
|
|
};
|
|
|
|
struct FMorphDef
|
|
{
|
|
FString Key;
|
|
FString Morph;
|
|
FString Value;
|
|
};
|
|
|
|
bool Tick(float DeltaTime);
|
|
/** Releve des fichiers .lphair (une fois : les fichiers de Modules ne changent pas en cours de partie). */
|
|
void ScanFiles();
|
|
void ParseFile(const FString& Relative, const FString& Module, const FString& Text);
|
|
/** Reconstruit la table : base (fichier MODE: BASE ou Blueprint) puis coiffures des modules actifs. */
|
|
void Sync();
|
|
/** Listes de pilosite : base (fichier ou Blueprint) puis noms des modules actifs. */
|
|
void SyncTextureLists(UObject* GI);
|
|
FString EnabledSignature() const;
|
|
/** Meme regle que GI.IsModEnabled : un module absent de GI.ModEnableds est inactif (lot H3a). */
|
|
bool IsModuleEnabled(const FString& Module) const;
|
|
/** Modules a cle MODULE_DEFAULT_ENABLED: true absents de GI.ModEnableds : ajoutes actifs (le gestionnaire de mods les
|
|
* affiche coches). Renvoie vrai si la liste a change. */
|
|
bool EnsureDefaultEnabledModules();
|
|
|
|
FTSTicker::FDelegateHandle TickHandle;
|
|
double NextCheck = 0.0;
|
|
FString LastSignature;
|
|
/** Modules dont le .lpmod porte MODULE_DEFAULT_ENABLED: true (lp_Revival, livre avec le jeu). */
|
|
TArray<FString> DefaultEnabledModules;
|
|
/** Coiffures et morphs du fichier de base, dans l'ordre. */
|
|
FString BaseFile;
|
|
TArray<FHairDef> BaseDefs;
|
|
TArray<FMorphDef> BaseMorphs;
|
|
/** Coiffures des autres fichiers. */
|
|
TArray<FHairDef> Defs;
|
|
/** Noms de textures de pilosite : fichier de base et autres fichiers ; listes du Blueprint (texte exporte). */
|
|
TArray<FTextureDef> BaseTextures;
|
|
TArray<FTextureDef> Textures;
|
|
TArray<FString> BlueprintListTexts;
|
|
/** Table et morphs du Blueprint, captures au premier passage (texte exporte, pour revenir a la base sans fichier). */
|
|
FString BlueprintTableText;
|
|
FString BlueprintMorphsText;
|
|
bool bCaptured = false;
|
|
};
|