H3d : metadonnees des mods, avertissement de version, paquet lpr_hair_pocolov (12 coiffures)

- LPModInfoSubsystem : metadonnees des .lpmod ; fenetre d'avertissement quand un mod actif
  a ete construit pour une autre version du jeu (Slate, sans Blueprint).
- NewMod/BuildMod : MODULE_VERSION, _CREATED, _LICENSE, _AUTHOR_LINK, _PRICE, _PACKAGED,
  _GAME_VERSION ; ordre des 3 premieres lignes controle ; prix et licences controles.
- lpr_hair_pocolov 1.0 : les 12 coiffures Pocolov CC BY ; lp_Revival et les 6 Pocolov
  retires du jeu de base ; mod d'essai LPHairSample retire.

Valide en jeu le 2026-10-03 (CHG-106, CHG-107).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
edujiro5972 2026-10-03 10:14:37 +02:00
parent 45bdb6dfb2
commit 5a2829ebd9
34 changed files with 769 additions and 74 deletions

View file

@ -155,6 +155,7 @@ cmd /c '"<UE>\Build\BatchFiles\RunUAT.bat" BuildCookRun -project="<projet>\LifeP
Get-FileHash Releases\<version>\Windows\LifePlay-Windows.utoc, <build>\Windows\LifePlay\Content\Paks\LifePlay-Windows.utoc
# 5. Releases\ ne garde que la version publiée (les précédentes vers LifePlay_Backup_5.5\Releases) : l'archive des
# sources la contient (≈ 1,3 Go) ; exclure aussi les produits de cuisson des mods : -x!ModSources\*\Saved
# 6. Mod d'essai recuit contre la nouvelle version (contrôle de la chaîne) : .\Tools\BuildMod.ps1 -Name LPHairSample
# 6. Mods officiels recuits contre la nouvelle version : .\Tools\BuildMod.ps1 -Name lpr_hair_pocolov
# Modules livrés à part : Tools\modules\next.json (essentiels : vin_Base, vin_VanillaRealistic ; lp_Revival retiré en H3d)
# 7. README : section de la version avec le lien vers Docs/Modding/FullGuides/Creating_Asset_Mods.md
```

View file

@ -166,3 +166,32 @@ Corrections du lot :
sont donc possibles pour les moddeurs à partir de la publication suivante (la V1.4 reste jouable avec des mods cuits
ici contre `Releases/2026.10.4`).
- Ne pas faire de build complet destiné à la publication sans recréer la version de référence correspondante.
## 8. Métadonnées, avertissement de version et paquet Pocolov (H3d, 2026-10-03)
Validé en jeu le 2026-10-03 (build `LifePlay_Build_5.5_H3d`).
- **Lecture des `.lpmod` par le jeu** (vérifiée dans `GI`) : seules les lignes 1 à 3 sont lues, **par position**
(`MODULE_UNIQUEID`, `MODULE_NAME`, `MODULE_AUTHOR`) ; le gestionnaire de mods affiche le fichier entier
(`ModuleTick.FullString`). Toute ligne ajoutée après la troisième est donc sans risque et visible des joueurs.
- **Clés ajoutées** : `MODULE_VERSION`, `MODULE_CREATED`, `MODULE_LICENSE`, `MODULE_AUTHOR_LINK`, `MODULE_PRICE`
(écrites par `Tools/NewMod.ps1`), `MODULE_PACKAGED`, `MODULE_GAME_VERSION` (écrites par `Tools/BuildMod.ps1` dans la
copie livrée). `BuildMod.ps1` contrôle l'ordre des trois premières lignes, reporte la version et le lien de l'auteur
dans le `.uplugin` livré (`VersionName`, `CreatedByURL`), nomme l'archive `<Nom>-<version>-for-LifePlay-<jeu>.zip`
et refuse un mod payant dont `CREDITS.txt` cite une licence non commerciale ou de magasin.
- **Avertissement** : `ULPModInfoSubsystem` (C++, `Source/LifePlay`) lit les `.lpmod` et, toutes les 2 s, compare le
`MODULE_GAME_VERSION` des modules **actifs** à `ProjectVersion` ; un écart ouvre une fenêtre Slate « Mod version
warning » (indépendante des Blueprints, aussi sur l'écran titre), une fois par module et par session. Testé avec un
module texte déclaré pour 2026.9.1 (déplacé ensuite vers `LifePlay_Backup_5.5\H3d`). Métadonnées accessibles aux
Blueprints : `GetModuleMetadata(Module, Key)`.
- **Paquet `lpr_hair_pocolov` 1.0** : sur 192 produits Pocolov (Fab), les 12 coiffures CC BY (03, 05, 06, 07, 09, 10,
11, 13, 14, 15, 16, 17) ; exclus : 5 coiffures payantes (licence standard Fab : redistribution interdite), vêtements
« Avatall » (autre squelette), objets, armes, véhicules. Configuration `Tools/mods/lpr_hair_pocolov.json` (réglages
HAIRS1 repris ; détection identique aux choix validés). Pocolov 07, 09, 10, 13, 14 téléchargées (CC BY 4.0, accord du
2026-10-03). La Pocolov 09 a sa calotte en maillage séparé, non convertie : rendu jugé correct en jeu.
`MODULE_DEFAULT_ENABLED: true` (les sauvegardes qui utilisaient les anciennes coiffures du jeu les retrouvent dès que
le paquet est installé). Archive `lpr_hair_pocolov-1.0-for-LifePlay-2026.10.4.zip` (3,8 Mo, 70 paquets cuits).
- **Jeu de base allégé** : les 6 Pocolov de `/Game/Heavy/New5/Hairs` et le module `lp_Revival` sont retirés du jeu
(déplacés vers `LifePlay_Backup_5.5\H3d\retires`), leurs crédits passent dans le `CREDITS.txt` du paquet ; le mod
d'essai `LPHairSample` est retiré (même dossier). Modules essentiels de la prochaine publication :
`Tools/modules/next.json`.

View file

@ -950,3 +950,5 @@ Validation L7c/L7d (2026-10-02, parc, même cadrage) : la nuit reste claire (sol
| CHG-103 | 2026-10-03 | UI15 | `Content/UI/MainMenu.uasset`, `Content/UI/ModManager.uasset` (snapshot `LifePlay_Backup_5.5\UI15`) ; nouveaux `Source/LifePlayEditorTools/LPTitleModManagerCommandlet.h/.cpp`, `Source/LifePlay/LPModSettingsLibrary.h/.cpp`, `Docs/Migration/17_Mods_Ecran_Titre.md` ; build `LifePlay_Build_5.5_UI15b` | demande utilisateur : gestionnaire de mods dès l'écran titre, puis choix entre nouvelle partie et partie sauvegardée. Entrée dédiée sur l'écran titre (copie de « Load »), fermeture vers le menu titre avec relecture des données et enregistrement du choix (`SaveModSelection`, sans toucher à la dernière sauvegarde) ; entrée d'origine inchangée en partie. Première version (entrée d'origine rendue visible) remplacée après retour (alignement). **Validé en jeu le 2026-10-03** | `.\Tools\Restore.ps1 -Lot UI15` ; `git revert` du commit |
| CHG-104 | 2026-10-03 | H3b | nouveaux `Tools/BuildMod.ps1`, `Tools/ModSource.ps1` ; `Tools/HairPipeline.ps1` (mode `mod` : montage temporaire, `.lphair` et crédits dans `ModSources/<Nom>/Module`, `-Rebuild` déplace aussi les textures) ; `Tools/HairMaterials.py` (analyse synchrone du dossier, réutilisation des textures) ; `Tools/mods/LPHairSample.json` (`mod`) ; `Source/LifePlay/LPHairstyleSubsystem.cpp` (repli `DoesPackageExist`) ; Pocolov 05 reconstruite (précédente dans `LifePlay_Backup_5.5\H3a\Pocolov05\precedente_*`) ; build `LifePlay_Build_5.5_H3b` ; archive `D:\Game\LifePlay_Publication\Mods\LPHairSample-for-LifePlay-2026.10.4.zip` (334 473 octets, SHA-256 `8F6A45ED…CBC8`) | lot H3b : un mod d'assets en une commande ; plantage de `HairMaterials.py` dans un plugin expliqué (registre de la commandlet sans les assets du plugin) et corrigé ; build de base sans rien du mod par construction. **Validé en jeu le 2026-10-03** (16_H3_Mods_Paquets.md §6) | `git revert` du commit, recompiler |
| CHG-105 | 2026-10-03 | H3c | nouveaux `Docs/Modding/FullGuides/Creating_Asset_Mods.md`, `Docs/Modding/ShortGuides/explanation.lphair`, `Tools/NewMod.ps1`, `Tools/EditMod.ps1` ; `Docs/Modding/ShortGuides/explanation.lpmod` (`MODULE_DEFAULT_ENABLED`) ; `Docs/Migration/10_Protocole_Operations.md` §6, `09_Commandes_Utiles.md` §7 (liste de contrôle de publication), `16_H3_Mods_Paquets.md` §7 | lot H3c : guide des moddeurs en anglais, outils de création et d'édition d'un mod, version de référence intégrée à la procédure de publication (livrée dans l'archive des sources ; `Mods/` vide au build) | `git revert` du commit |
| CHG-106 | 2026-10-03 | H3d | nouveaux `Source/LifePlay/LPModInfoSubsystem.h/.cpp` ; `Source/LifePlay/LifePlay.Build.cs` (`Slate`, `SlateCore`) ; `Tools/NewMod.ps1` (métadonnées), `Tools/BuildMod.ps1` (ordre des lignes 1 à 3, `MODULE_PACKAGED`, `MODULE_GAME_VERSION`, `.uplugin` livré, contrôle prix et licences, nom d'archive) ; `Docs/Modding/FullGuides/Creating_Asset_Mods.md` §4b, `explanation.lpmod` | demande utilisateur : métadonnées extensibles (dates, licence, lien de l'auteur, prix) et avertissement en jeu quand un mod a été construit pour une autre version. Le jeu ne lit que les 3 premières lignes d'un `.lpmod`, par position ; fenêtre Slate C++, sans Blueprint. **Validé en jeu le 2026-10-03** | `git revert` du commit, recompiler |
| CHG-107 | 2026-10-03 | H3d | nouveau mod `ModSources/lpr_hair_pocolov` (`.uplugin`, `Module/` : `.lpmod`, 12 `.lphair`, `CREDITS.txt` ; assets non versionnés), `Tools/mods/lpr_hair_pocolov.json` ; retirés : `Content/Modules/lp_Revival` (6 `.lphair`, `.lpmod`), assets `Content/Heavy/New5/Hairs/Pocolov*` (non versionnés), `ModSources/LPHairSample`, `Tools/mods/LPHairSample.json` (tous vers `LifePlay_Backup_5.5\H3d\retires`) ; `Licenses/Free_3D_Models_Credits.txt` (lignes Pocolov remplacées par un renvoi ; snapshot `H3d`) ; nouveau `Tools/modules/next.json` ; builds `LifePlay_Build_5.5_H3d` ; archive `D:\Game\LifePlay_Publication\Mods\lpr_hair_pocolov-1.0-for-LifePlay-2026.10.4.zip` (3 807 460 octets, SHA-256 `4E9420E5…2B8F`) | demande utilisateur : module `lpr_hair_pocolov` regroupant les assets Pocolov ; choix utilisateur : les 12 coiffures CC BY, les 6 du jeu de base déplacées dans le paquet, mod d'essai retiré ; 5 archives téléchargées (accord). **Validé en jeu le 2026-10-03** | remettre les dossiers de `LifePlay_Backup_5.5\H3d\retires` ; `.\Tools\Restore.ps1 -Lot H3d` ; `git revert` du commit |

View file

@ -26,7 +26,7 @@ La migration a été reprise le 2026-09-29, après l'échec d'un premier portage
| [13_Protocole_Coiffure.md](13_Protocole_Coiffure.md) | protocole | ajouter une coiffure (FBX statique, Fab) : import, ajustement sur la tête de Bridget, matériaux, fichier `.lphair`, contrôles |
| [14_Interface_V1.4.md](14_Interface_V1.4.md) | lot | menu principal : version année.mois.publication, crédits (Vinfamy, auteur original), liens Donate et Discord, bouton Commission masqué |
| [15_Modules_Optionnels.md](15_Modules_Optionnels.md) | lot | build Shipping réduite aux modules essentiels, modules optionnels dans une archive séparée (`Tools/SplitModules.ps1`) |
| [16_H3_Mods_Paquets.md](16_H3_Mods_Paquets.md) | étude, prototype | H3 : assets apportés par les mods (plugins `Mods/`, cuisson DLC contre la version publiée) ; constats, architecture, risques, lots H3a à H3c ; §5 résultats du prototype H3a, §6 outillage H3b (`ModSources/`, `Tools/BuildMod.ps1`), validés ; §7 guide des moddeurs (`Docs/Modding/FullGuides/Creating_Asset_Mods.md`) et publication |
| [16_H3_Mods_Paquets.md](16_H3_Mods_Paquets.md) | étude, prototype | H3 : assets apportés par les mods (plugins `Mods/`, cuisson DLC contre la version publiée) ; constats, architecture, risques, lots H3a à H3c ; §5 résultats du prototype H3a, §6 outillage H3b (`ModSources/`, `Tools/BuildMod.ps1`), validés ; §7 guide des moddeurs (`Docs/Modding/FullGuides/Creating_Asset_Mods.md`) et publication ; §8 métadonnées, avertissement de version, paquet `lpr_hair_pocolov` (H3d) |
| [17_Mods_Ecran_Titre.md](17_Mods_Ecran_Titre.md) | lot | UI15 : gestionnaire de mods depuis l'écran titre (entrée dédiée, retour au menu titre, choix enregistré) |
| [Journal_Modifications.md](Journal_Modifications.md) | traçabilité | `CHG-001` à `CHG-057`, chacune avec son retour arrière |
| [Registre_Erreurs.md](Registre_Erreurs.md) | traçabilité | `ERR-001` à `ERR-037`, statut et lot |

View file

@ -68,8 +68,8 @@ it fits the hair to the default head, transfers skin weights from the body (head
the character without cutting through the skin, and creates `DazHair` material instances.
1. Download the hairstyle archives (zip/rar/7z with an FBX and its textures).
2. Add one entry per hairstyle in `Tools/mods/MyHairPack.json` (see `Tools/mods/LPHairSample.json` for a complete
example):
2. Add one entry per hairstyle in `Tools/mods/MyHairPack.json` (see `Tools/mods/lpr_hair_pocolov.json`, the 12 Pocolov
hairstyles, for a complete example):
```json
{
@ -109,6 +109,23 @@ SEX: F
DAZ: true
```
## 4b. Mod metadata
The first three lines of `<Name>.lpmod` are read **by position** by the game and must stay first, in this order:
`MODULE_UNIQUEID`, `MODULE_NAME`, `MODULE_AUTHOR`. The other lines are free; the Mod Manager shows the whole file in its
detail panel, so every line below is visible to players.
| Key | Written by | Meaning |
|---|---|---|
| `MODULE_VERSION` | you (`NewMod.ps1 -ModVersion`, default 1.0) | version of the mod; also in the archive name and the plugin `VersionName` |
| `MODULE_CREATED` | `NewMod.ps1` | creation date (YYYY-MM-DD) |
| `MODULE_LICENSE` | you (`-License`) | license of the mod as a whole (each asset's license stays in `CREDITS.txt`) |
| `MODULE_AUTHOR_LINK` | you (`-AuthorLink`) | author page; also the plugin `CreatedByURL` |
| `MODULE_PRICE` | you (`-Price`, default Free) | information only, the game sells nothing. A non-free mod is refused by `BuildMod.ps1` if `CREDITS.txt` mentions a non-commercial or store license (`NC`, `Standard License`, `Personal`) |
| `MODULE_DEFAULT_ENABLED` | you | `true`: enabled the first time the game finds it; otherwise a new mod starts disabled |
| `MODULE_PACKAGED` | `BuildMod.ps1` (shipped copy only) | packaging date |
| `MODULE_GAME_VERSION` | `BuildMod.ps1` (shipped copy only) | game version the assets were cooked for. If an **enabled** mod declares another version than the game, the game shows a "Mod version warning" window (once per session) |
## 5. Edit the mod in the editor
```powershell

View file

@ -11,4 +11,8 @@ MODULE_LINK: www.loverslab.com
MODULE_DESCRIPTION: Netorare, cuckoldry, being cheated on - aka the most divisive fetish on the internet
MODULE_REQUIREMENTS: vin_VanillaRealistic // unique IDs of the prerequisite mods, without all these mods enabled, this mod cannot be enabled.
LifePlay Revival addition:
MODULE_DEFAULT_ENABLED: true // optional: the mod is enabled the first time the game finds it (otherwise a new mod starts disabled until the player ticks it in the Mod Manager). Used by lp_Revival, shipped with the game.
MODULE_DEFAULT_ENABLED: true // optional: the mod is enabled the first time the game finds it (otherwise a new mod starts disabled until the player ticks it in the Mod Manager). Used by lpr_hair_pocolov.
The first three lines (MODULE_UNIQUEID, MODULE_NAME, MODULE_AUTHOR) are read by position: keep them first, in this order.
Other optional keys, shown as-is in the Mod Manager: MODULE_VERSION, MODULE_CREATED, MODULE_LICENSE, MODULE_AUTHOR_LINK, MODULE_PRICE,
MODULE_PACKAGED and MODULE_GAME_VERSION (written by Tools/BuildMod.ps1; the game warns when an enabled mod was built for another
game version). See Docs/Modding/FullGuides/Creating_Asset_Mods.md, section 4b.

View file

@ -26,9 +26,4 @@ In no particular order, these are the authors of the original (most have been he
- Joel Palmius
LifePlay Revival (UE 5.5) additions:
- Pocolov Hair 17 by Pocolov (Pocolov Studio 2019, artist Thang), Creative Commons Attribution 4.0 (CC BY 4.0), https://www.fab.com/listings/7f6f687d-bb13-40c6-8b69-64044ededc1d . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (Content/Heavy/New5/Hairs/Pocolov17*, declared by Content/Modules/lp_Revival/Hairstyles/pocolov17.lphair).
- Pocolov Hair 03 by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, https://www.fab.com/listings/2257098d-b77c-4eef-9132-85f1454f0ae3 . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/Game/Heavy/New5/Hairs/Pocolov03*).
- Pocolov Hair 06 by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, https://www.fab.com/listings/14c3cd52-02f9-4bfe-bb40-b5c3acb1f428 . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/Game/Heavy/New5/Hairs/Pocolov06*).
- Pocolov Hair 11 by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, https://www.fab.com/listings/c31c219e-bc62-4957-91c5-720440375f79 . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/Game/Heavy/New5/Hairs/Pocolov11*).
- Pocolov Hair 15 by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, https://www.fab.com/listings/ed8e016a-0bf0-4a6c-94b0-2760083b879d . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/Game/Heavy/New5/Hairs/Pocolov15*).
- Pocolov Hair 16 by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, https://www.fab.com/listings/802dc956-6211-4b83-8ba1-37beb3cb338f . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/Game/Heavy/New5/Hairs/Pocolov16*).
- The Pocolov hairstyles (Pocolov Studio, artist Thang, CC BY 4.0) are no longer part of the game: they are in the optional mod lpr_hair_pocolov, credited in its CREDITS.txt (ModSources/lpr_hair_pocolov/Module/CREDITS.txt in the source archive, Content/Modules/lpr_hair_pocolov/CREDITS.txt once installed).

View file

@ -1,12 +0,0 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "LifePlay Hair Sample",
"Description": "Sample LifePlay mod: one hairstyle (Pocolov Hair 05, CC BY 4.0) cooked as a separate package.",
"Category": "LifePlay Mods",
"CreatedBy": "LifePlay Revival",
"CanContainContent": true,
"IsBetaVersion": false,
"Installed": false
}

View file

@ -1 +0,0 @@
- Pocolov Hair 05 by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, https://www.fab.com/listings/4025749f-d597-4332-91aa-16e355b94974 . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/LPHairSample/Hairs/Pocolov05*).

View file

@ -1,6 +0,0 @@
MODULE_UNIQUEID: LPHairSample
MODULE_NAME: LifePlay Hair Sample
MODULE_AUTHOR: LifePlay Revival
MODULE_LINK: https://github.com/edujiro5972/LifePlay-Revival
MODULE_DESCRIPTION: Sample mod: one hairstyle (Pocolov Hair 05, CC BY 4.0) shipped as a cooked package in Mods/LPHairSample. Disabling this module removes the hairstyle from the game list.
MODULE_REQUIREMENTS: vin_Base

View file

@ -0,0 +1,13 @@
Credits and licenses of the assets in Pocolov Hairstyles (one line per asset: title, author, license, source URL, changes).
- Pocolov Hair 03 by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, https://www.fab.com/listings/2257098d-b77c-4eef-9132-85f1454f0ae3 . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/lpr_hair_pocolov/Hairs/Pocolov03*).
- Pocolov Hair 05 by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, https://www.fab.com/listings/4025749f-d597-4332-91aa-16e355b94974 . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/lpr_hair_pocolov/Hairs/Pocolov05*).
- Pocolov Hair 06 by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, https://www.fab.com/listings/14c3cd52-02f9-4bfe-bb40-b5c3acb1f428 . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/lpr_hair_pocolov/Hairs/Pocolov06*).
- Pocolov Hair 11 by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, https://www.fab.com/listings/c31c219e-bc62-4957-91c5-720440375f79 . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/lpr_hair_pocolov/Hairs/Pocolov11*).
- Pocolov Hair 15 by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, https://www.fab.com/listings/ed8e016a-0bf0-4a6c-94b0-2760083b879d . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/lpr_hair_pocolov/Hairs/Pocolov15*).
- Pocolov Hair 16 by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, https://www.fab.com/listings/802dc956-6211-4b83-8ba1-37beb3cb338f . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/lpr_hair_pocolov/Hairs/Pocolov16*).
- Pocolov Hair 17 by Pocolov (Pocolov Studio 2019, artist Thang), CC BY 4.0, https://www.fab.com/listings/7f6f687d-bb13-40c6-8b69-64044ededc1d . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/lpr_hair_pocolov/Hairs/Pocolov17*).
- Pocolov Hair 07 by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, https://www.fab.com/listings/4d1ba957-b420-4bdc-8984-b528a73b1d58 . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/lpr_hair_pocolov/Hairs/Pocolov07*).
- Pocolov Hair 09 by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, https://www.fab.com/listings/80383c46-f491-4db2-a63d-48d279f35782 . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/lpr_hair_pocolov/Hairs/Pocolov09*).
- Pocolov Hair 10 by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, https://www.fab.com/listings/40a91685-76dc-4384-91f1-0040f44e8958 . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/lpr_hair_pocolov/Hairs/Pocolov10*).
- Pocolov Hair 13 by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, https://www.fab.com/listings/a3933681-f5e3-4d93-99f0-c5fff444d405 . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/lpr_hair_pocolov/Hairs/Pocolov13*).
- Pocolov Hair 14 by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, https://www.fab.com/listings/4911f6b9-d548-45d7-86be-a6971da97c54 . Changes: skinned to the Genesis 8 skeleton by weight transfer from the body (head, neck, chest), fitted to the Bridget head, DazHair materials (/lpr_hair_pocolov/Hairs/Pocolov14*).

View file

@ -0,0 +1,6 @@
// Pocolov Hair 03 - Pocolov (Pocolov Studio, artist Thang) - licence CC BY 4.0
// Source : https://www.fab.com/listings/2257098d-b77c-4eef-9132-85f1454f0ae3
// Modifications (Tools/HairPipeline.ps1) : liee au squelette Genesis 8 par transfert de poids depuis le corps (tete, cou, poitrine), ajustee a la tete de Bridget, materiaux DazHair.
HAIRSTYLE: /lpr_hair_pocolov/Hairs/Pocolov03.Pocolov03
SEX: F
DAZ: true

View file

@ -1,6 +1,6 @@
// Pocolov Hair 05 - Pocolov (Pocolov Studio, artist Thang) - licence CC BY 4.0
// Source : https://www.fab.com/listings/4025749f-d597-4332-91aa-16e355b94974
// Modifications (Tools/HairPipeline.ps1) : liee au squelette Genesis 8 par transfert de poids depuis le corps (tete, cou, poitrine), ajustee a la tete de Bridget, materiaux DazHair.
HAIRSTYLE: /LPHairSample/Hairs/Pocolov05.Pocolov05
HAIRSTYLE: /lpr_hair_pocolov/Hairs/Pocolov05.Pocolov05
SEX: F
DAZ: true

View file

@ -0,0 +1,6 @@
// Pocolov Hair 06 - Pocolov (Pocolov Studio, artist Thang) - licence CC BY 4.0
// Source : https://www.fab.com/listings/14c3cd52-02f9-4bfe-bb40-b5c3acb1f428
// Modifications (Tools/HairPipeline.ps1) : liee au squelette Genesis 8 par transfert de poids depuis le corps (tete, cou, poitrine), ajustee a la tete de Bridget, materiaux DazHair.
HAIRSTYLE: /lpr_hair_pocolov/Hairs/Pocolov06.Pocolov06
SEX: F
DAZ: true

View file

@ -0,0 +1,6 @@
// Pocolov Hair 07 - Pocolov (Pocolov Studio, artist Thang) - licence CC BY 4.0
// Source : https://www.fab.com/listings/4d1ba957-b420-4bdc-8984-b528a73b1d58
// Modifications (Tools/HairPipeline.ps1) : liee au squelette Genesis 8 par transfert de poids depuis le corps (tete, cou, poitrine), ajustee a la tete de Bridget, materiaux DazHair.
HAIRSTYLE: /lpr_hair_pocolov/Hairs/Pocolov07.Pocolov07
SEX: F
DAZ: true

View file

@ -0,0 +1,6 @@
// Pocolov Hair 09 - Pocolov (Pocolov Studio, artist Thang) - licence CC BY 4.0
// Source : https://www.fab.com/listings/80383c46-f491-4db2-a63d-48d279f35782
// Modifications (Tools/HairPipeline.ps1) : liee au squelette Genesis 8 par transfert de poids depuis le corps (tete, cou, poitrine), ajustee a la tete de Bridget, materiaux DazHair.
HAIRSTYLE: /lpr_hair_pocolov/Hairs/Pocolov09.Pocolov09
SEX: F
DAZ: true

View file

@ -0,0 +1,6 @@
// Pocolov Hair 10 - Pocolov (Pocolov Studio, artist Thang) - licence CC BY 4.0
// Source : https://www.fab.com/listings/40a91685-76dc-4384-91f1-0040f44e8958
// Modifications (Tools/HairPipeline.ps1) : liee au squelette Genesis 8 par transfert de poids depuis le corps (tete, cou, poitrine), ajustee a la tete de Bridget, materiaux DazHair.
HAIRSTYLE: /lpr_hair_pocolov/Hairs/Pocolov10.Pocolov10
SEX: F
DAZ: true

View file

@ -0,0 +1,6 @@
// Pocolov Hair 11 - Pocolov (Pocolov Studio, artist Thang) - licence CC BY 4.0
// Source : https://www.fab.com/listings/c31c219e-bc62-4957-91c5-720440375f79
// Modifications (Tools/HairPipeline.ps1) : liee au squelette Genesis 8 par transfert de poids depuis le corps (tete, cou, poitrine), ajustee a la tete de Bridget, materiaux DazHair.
HAIRSTYLE: /lpr_hair_pocolov/Hairs/Pocolov11.Pocolov11
SEX: F
DAZ: true

View file

@ -0,0 +1,6 @@
// Pocolov Hair 13 - Pocolov (Pocolov Studio, artist Thang) - licence CC BY 4.0
// Source : https://www.fab.com/listings/a3933681-f5e3-4d93-99f0-c5fff444d405
// Modifications (Tools/HairPipeline.ps1) : liee au squelette Genesis 8 par transfert de poids depuis le corps (tete, cou, poitrine), ajustee a la tete de Bridget, materiaux DazHair.
HAIRSTYLE: /lpr_hair_pocolov/Hairs/Pocolov13.Pocolov13
SEX: F
DAZ: true

View file

@ -0,0 +1,6 @@
// Pocolov Hair 14 - Pocolov (Pocolov Studio, artist Thang) - licence CC BY 4.0
// Source : https://www.fab.com/listings/4911f6b9-d548-45d7-86be-a6971da97c54
// Modifications (Tools/HairPipeline.ps1) : liee au squelette Genesis 8 par transfert de poids depuis le corps (tete, cou, poitrine), ajustee a la tete de Bridget, materiaux DazHair.
HAIRSTYLE: /lpr_hair_pocolov/Hairs/Pocolov14.Pocolov14
SEX: F
DAZ: true

View file

@ -0,0 +1,6 @@
// Pocolov Hair 15 - Pocolov (Pocolov Studio, artist Thang) - licence CC BY 4.0
// Source : https://www.fab.com/listings/ed8e016a-0bf0-4a6c-94b0-2760083b879d
// Modifications (Tools/HairPipeline.ps1) : liee au squelette Genesis 8 par transfert de poids depuis le corps (tete, cou, poitrine), ajustee a la tete de Bridget, materiaux DazHair.
HAIRSTYLE: /lpr_hair_pocolov/Hairs/Pocolov15.Pocolov15
SEX: F
DAZ: true

View file

@ -0,0 +1,6 @@
// Pocolov Hair 16 - Pocolov (Pocolov Studio, artist Thang) - licence CC BY 4.0
// Source : https://www.fab.com/listings/802dc956-6211-4b83-8ba1-37beb3cb338f
// Modifications (Tools/HairPipeline.ps1) : liee au squelette Genesis 8 par transfert de poids depuis le corps (tete, cou, poitrine), ajustee a la tete de Bridget, materiaux DazHair.
HAIRSTYLE: /lpr_hair_pocolov/Hairs/Pocolov16.Pocolov16
SEX: F
DAZ: true

View file

@ -0,0 +1,6 @@
// Pocolov Hair 17 - Pocolov (Pocolov Studio 2019, artist Thang) - licence CC BY 4.0
// Source : https://www.fab.com/listings/7f6f687d-bb13-40c6-8b69-64044ededc1d
// Modifications (Tools/HairPipeline.ps1) : liee au squelette Genesis 8 par transfert de poids depuis le corps (tete, cou, poitrine), ajustee a la tete de Bridget, materiaux DazHair.
HAIRSTYLE: /lpr_hair_pocolov/Hairs/Pocolov17.Pocolov17
SEX: F
DAZ: true

View file

@ -0,0 +1,12 @@
MODULE_UNIQUEID: lpr_hair_pocolov
MODULE_NAME: Pocolov Hairstyles
MODULE_AUTHOR: LifePlay Revival (hairstyles by Pocolov)
MODULE_LINK: https://github.com/edujiro5972/LifePlay-Revival
MODULE_DESCRIPTION: 12 free hairstyles by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, converted for LifePlay
MODULE_REQUIREMENTS: vin_Base
MODULE_VERSION: 1.0
MODULE_CREATED: 2026-10-03
MODULE_LICENSE: CC BY 4.0
MODULE_AUTHOR_LINK: https://www.fab.com/sellers/Pocolov
MODULE_PRICE: Free
MODULE_DEFAULT_ENABLED: true

View file

@ -0,0 +1,13 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "Pocolov Hairstyles",
"Description": "12 free hairstyles by Pocolov (Pocolov Studio, artist Thang), CC BY 4.0, converted for LifePlay",
"Category": "LifePlay Mods",
"CreatedBy": "LifePlay Revival (hairstyles by Pocolov)",
"CanContainContent": true,
"IsBetaVersion": false,
"Installed": false,
"CreatedByURL": "https://www.fab.com/sellers/Pocolov"
}

View file

@ -0,0 +1,202 @@
// Portage UE 5.5 - voir LPModInfoSubsystem.h
#include "LPModInfoSubsystem.h"
#include "Engine/Engine.h"
#include "Engine/GameInstance.h"
#include "Engine/GameViewportClient.h"
#include "GeneralProjectSettings.h"
#include "HAL/FileManager.h"
#include "HAL/PlatformTime.h"
#include "LifePlay.h"
#include "Misc/FileHelper.h"
#include "Misc/Paths.h"
#include "Styling/CoreStyle.h"
#include "UObject/UnrealType.h"
#include "Widgets/Input/SButton.h"
#include "Widgets/Layout/SBorder.h"
#include "Widgets/Layout/SBox.h"
#include "Widgets/SBoxPanel.h"
#include "Widgets/SOverlay.h"
#include "Widgets/Text/STextBlock.h"
namespace
{
constexpr double CheckInterval = 2.0;
FString FieldText(const UStruct* Struct, const void* Data, const TCHAR* AuthoredName)
{
for (TFieldIterator<FProperty> It(Struct); It; ++It)
{
if (It->GetAuthoredName() == AuthoredName)
{
FString Out;
It->ExportTextItem_InContainer(Out, Data, nullptr, nullptr, PPF_None);
return Out.TrimQuotes();
}
}
return FString();
}
}
void ULPModInfoSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
GameVersion = GetDefault<UGeneralProjectSettings>()->ProjectVersion;
// Modules/<id>/<id>.lpmod (meme regle que le jeu : un fichier par dossier de module, a sa racine).
const FString ModulesDir = FPaths::ConvertRelativePathToFull(FPaths::ProjectContentDir() / TEXT("Modules"));
TArray<FString> Dirs;
IFileManager::Get().FindFiles(Dirs, *(ModulesDir / TEXT("*")), false, true);
int32 WithGameVersion = 0;
for (const FString& Dir : Dirs)
{
FString Text;
if (!FFileHelper::LoadFileToString(Text, *(ModulesDir / Dir / Dir + TEXT(".lpmod"))))
{
continue;
}
TMap<FString, FString>& Keys = Metadata.Add(Dir);
TArray<FString> Lines;
Text.ParseIntoArrayLines(Lines, true);
for (const FString& Line : Lines)
{
FString Key, Value;
if (!Line.TrimStart().StartsWith(TEXT("//")) && Line.Split(TEXT(":"), &Key, &Value))
{
Keys.Add(Key.TrimStartAndEnd().ToUpper(), Value.TrimStartAndEnd());
}
}
WithGameVersion += Keys.Contains(TEXT("MODULE_GAME_VERSION")) ? 1 : 0;
}
UE_LOG(LogLifePlay, Display, TEXT("Modules : %d .lpmod lu(s), %d avec MODULE_GAME_VERSION (jeu %s)"), Metadata.Num(), WithGameVersion, *GameVersion);
if (WithGameVersion > 0)
{
TickHandle = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateUObject(this, &ULPModInfoSubsystem::Tick));
}
}
void ULPModInfoSubsystem::Deinitialize()
{
FTSTicker::GetCoreTicker().RemoveTicker(TickHandle);
CloseWarning();
Super::Deinitialize();
}
FString ULPModInfoSubsystem::GetModuleMetadata(const FString& Module, const FString& Key) const
{
for (const TPair<FString, TMap<FString, FString>>& Pair : Metadata)
{
if (Pair.Key.Equals(Module, ESearchCase::IgnoreCase))
{
const FString* Value = Pair.Value.Find(Key.ToUpper());
return Value ? *Value : FString();
}
}
return FString();
}
bool ULPModInfoSubsystem::IsModuleEnabled(const FString& Module) const
{
// Meme regle que GI.IsModEnabled : un module absent de GI.ModEnableds est inactif.
const UObject* GI = GetGameInstance();
const FArrayProperty* Prop = GI ? CastField<FArrayProperty>(GI->GetClass()->FindPropertyByName(TEXT("ModEnableds"))) : nullptr;
const FStructProperty* Inner = Prop ? CastField<FStructProperty>(Prop->Inner) : nullptr;
if (!Inner)
{
return false;
}
FScriptArrayHelper Helper(Prop, Prop->ContainerPtrToValuePtr<void>(GI));
for (int32 i = 0; i < Helper.Num(); ++i)
{
if (FieldText(Inner->Struct, Helper.GetRawPtr(i), TEXT("UniqueID")).Equals(Module, ESearchCase::IgnoreCase))
{
return FieldText(Inner->Struct, Helper.GetRawPtr(i), TEXT("IsEnabled")).Equals(TEXT("True"), ESearchCase::IgnoreCase);
}
}
return false;
}
bool ULPModInfoSubsystem::Tick(float DeltaTime)
{
const double Now = FPlatformTime::Seconds();
if (Now < NextCheck || !GEngine || !GEngine->GameViewport || Popup.IsValid())
{
return true;
}
NextCheck = Now + CheckInterval;
TArray<FString> Lines;
for (const TPair<FString, TMap<FString, FString>>& Pair : Metadata)
{
const FString* Built = Pair.Value.Find(TEXT("MODULE_GAME_VERSION"));
if (!Built || Built->IsEmpty() || *Built == GameVersion || Warned.Contains(Pair.Key) || !IsModuleEnabled(Pair.Key))
{
continue;
}
Warned.Add(Pair.Key);
const FString* Name = Pair.Value.Find(TEXT("MODULE_NAME"));
Lines.Add(FString::Printf(TEXT("- %s (%s) : built for LifePlay %s"), Name ? **Name : *Pair.Key, *Pair.Key, **Built));
UE_LOG(LogLifePlay, Warning, TEXT("Modules : %s construit pour LifePlay %s, jeu %s"), *Pair.Key, **Built, *GameVersion);
}
if (Lines.Num() > 0)
{
ShowWarning(Lines);
}
return true;
}
void ULPModInfoSubsystem::ShowWarning(const TArray<FString>& Lines)
{
const FString Body = FString::Printf(TEXT("This game is LifePlay %s. The following enabled mod(s) were built for another version:\n\n%s\n\n")
TEXT("Their 3D assets may fail to load (missing hair, clothes...) or look wrong. Update the mod, or ask its author for a ")
TEXT("version built for LifePlay %s. You can disable it in the Mod Manager."), *GameVersion, *FString::Join(Lines, TEXT("\n")), *GameVersion);
Popup = SNew(SOverlay)
+ SOverlay::Slot().HAlign(HAlign_Center).VAlign(VAlign_Center)
[
SNew(SBox).WidthOverride(760.f)
[
SNew(SBorder)
.BorderImage(FCoreStyle::Get().GetBrush("WhiteBrush"))
.BorderBackgroundColor(FLinearColor(0.02f, 0.02f, 0.03f, 0.94f))
.Padding(24.f)
[
SNew(SVerticalBox)
+ SVerticalBox::Slot().AutoHeight().Padding(0.f, 0.f, 0.f, 12.f)
[
SNew(STextBlock)
.Text(FText::FromString(TEXT("Mod version warning")))
.Font(FCoreStyle::GetDefaultFontStyle("Bold", 22))
.ColorAndOpacity(FLinearColor(1.f, 0.75f, 0.2f))
]
+ SVerticalBox::Slot().AutoHeight().Padding(0.f, 0.f, 0.f, 18.f)
[
SNew(STextBlock)
.Text(FText::FromString(Body))
.Font(FCoreStyle::GetDefaultFontStyle("Regular", 14))
.ColorAndOpacity(FLinearColor(0.92f, 0.92f, 0.92f))
.AutoWrapText(true)
]
+ SVerticalBox::Slot().AutoHeight().HAlign(HAlign_Right)
[
SNew(SButton)
.ContentPadding(FMargin(28.f, 6.f))
.OnClicked_Lambda([this]() { CloseWarning(); return FReply::Handled(); })
[
SNew(STextBlock).Text(FText::FromString(TEXT("OK"))).Font(FCoreStyle::GetDefaultFontStyle("Bold", 16))
]
]
]
]
];
GEngine->GameViewport->AddViewportWidgetContent(Popup.ToSharedRef(), 1000);
}
void ULPModInfoSubsystem::CloseWarning()
{
if (Popup.IsValid() && GEngine && GEngine->GameViewport)
{
GEngine->GameViewport->RemoveViewportWidgetContent(Popup.ToSharedRef());
}
Popup.Reset();
}

View file

@ -0,0 +1,48 @@
// Portage UE 5.5 - lot H3d (metadonnees des modules, Docs/Migration/16_H3_Mods_Paquets.md §8).
//
// Lit les metadonnees de chaque module (Content/Modules/<id>/<id>.lpmod, lignes "CLE: valeur"). Le jeu (GI) ne lit que
// les trois premieres lignes, par position (MODULE_UNIQUEID, MODULE_NAME, MODULE_AUTHOR) ; le gestionnaire de mods
// affiche le fichier entier. Cles ajoutees (facultatives, apres la ligne 3) :
// MODULE_VERSION, MODULE_CREATED, MODULE_PACKAGED (dates AAAA-MM-JJ), MODULE_LICENSE, MODULE_AUTHOR_LINK,
// MODULE_PRICE, MODULE_GAME_VERSION (version du jeu contre laquelle les assets du mod ont ete cuits, ecrite par
// Tools/BuildMod.ps1), MODULE_DEFAULT_ENABLED (lu par LPHairstyleSubsystem).
//
// Avertissement : un module ACTIF dont MODULE_GAME_VERSION differe de la version du jeu (ProjectVersion) declenche une
// fenetre (Slate, independante des Blueprints, aussi sur l'ecran titre), une fois par module et par session.
#pragma once
#include "CoreMinimal.h"
#include "Containers/Ticker.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "LPModInfoSubsystem.generated.h"
class SWidget;
UCLASS()
class LIFEPLAY_API ULPModInfoSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
/** Valeur d'une cle du .lpmod d'un module (vide si absente). */
UFUNCTION(BlueprintCallable, Category = "LifePlay|Mods")
FString GetModuleMetadata(const FString& Module, const FString& Key) const;
private:
bool Tick(float DeltaTime);
bool IsModuleEnabled(const FString& Module) const;
void ShowWarning(const TArray<FString>& Lines);
void CloseWarning();
/** Module -> (cle en majuscules -> valeur). */
TMap<FString, TMap<FString, FString>> Metadata;
FString GameVersion;
TSet<FString> Warned;
TSharedPtr<SWidget> Popup;
FTSTicker::FDelegateHandle TickHandle;
double NextCheck = 0.0;
};

View file

@ -27,6 +27,10 @@ public class LifePlay : ModuleRules
// Portage 5.5 (L3) : ULPSessionLogSubsystem lit UGeneralProjectSettings (nom et version du jeu)
PrivateDependencyModuleNames.AddRange(new string[] { "EngineSettings" });
// H3d : ULPModInfoSubsystem affiche un avertissement (fenetre Slate) quand un mod a ete construit pour une
// autre version du jeu
PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
// Uncomment if you are using Slate UI
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });

View file

@ -15,8 +15,8 @@
5. -Install <dossier du jeu> : copie le mod dans un jeu de test (dossier contenant LifePlay.exe).
.EXAMPLE
.\Tools\BuildMod.ps1 -Name LPHairSample
.\Tools\BuildMod.ps1 -Name LPHairSample -Install D:\Game\LifePlay_Build_5.5_H3b\Windows
.\Tools\BuildMod.ps1 -Name lpr_hair_pocolov
.\Tools\BuildMod.ps1 -Name lpr_hair_pocolov -Install D:\Game\LifePlay_Build_5.5_H3d\Windows
#>
param(
[Parameter(Mandatory)] [string] $Name,
@ -44,6 +44,23 @@ if (-not (Test-Path $lpmod)) { throw "ModSources\$Name\Module\$Name.lpmod introu
$id = (Select-String -Path $lpmod -Pattern '^MODULE_UNIQUEID:\s*(.+)$' | Select-Object -First 1).Matches[0].Groups[1].Value.Trim()
if ($id -ne $Name) { throw "MODULE_UNIQUEID ($id) different du nom du mod ($Name)" }
$title = (Select-String -Path $lpmod -Pattern '^MODULE_NAME:\s*(.+)$' | Select-Object -First 1).Matches[0].Groups[1].Value.Trim()
# Metadonnees (H3d) : le jeu lit les trois premieres lignes par position.
$lpmodLines = @(Get-Content $lpmod -Encoding utf8)
$expected = 'MODULE_UNIQUEID:', 'MODULE_NAME:', 'MODULE_AUTHOR:'
for ($i = 0; $i -lt 3; $i++) {
if ($lpmodLines.Count -le $i -or -not $lpmodLines[$i].StartsWith($expected[$i])) { throw "$Name.lpmod : la ligne $($i + 1) doit commencer par $($expected[$i]) (le jeu lit ces lignes par position)" }
}
function Get-LpmodValue([string] $Key) {
$m = $lpmodLines | Select-String -Pattern "^$([regex]::Escape($Key)):\s*(.*)$" | Select-Object -First 1
if ($m) { $m.Matches[0].Groups[1].Value.Trim() } else { '' }
}
$modVersion = Get-LpmodValue 'MODULE_VERSION'
# Mod payant : aucune licence d'asset non commerciale ou de magasin dans les credits.
$price = Get-LpmodValue 'MODULE_PRICE'
if ($price -and $price -notmatch '^(free|gratuit|0+([.,]0+)?)$') {
$blocking = Select-String -Path (Join-Path $src 'Module\CREDITS.txt') -Pattern '\bNC\b|NonCommercial|Non-Commercial|Standard License|Personal' -ErrorAction SilentlyContinue
if ($blocking) { throw "MODULE_PRICE '$price' : licence(s) incompatible(s) avec la vente dans CREDITS.txt ($($blocking[0].Line.Trim()))" }
}
$release = Join-Path $Root "Releases\$Version\Windows"
if (-not (Test-Path (Join-Path $release 'AssetRegistry.bin'))) { throw "Version de reference absente : $release (build de publication avec -createreleaseversion=$Version)" }
$stray = Get-StrayMods $Root
@ -79,7 +96,7 @@ try {
# 4. Assemblage.
New-Item -ItemType Directory -Force $Out | Out-Null
$base = "$Name-for-LifePlay-$Version"
$base = if ($modVersion) { "$Name-$modVersion-for-LifePlay-$Version" } else { "$Name-for-LifePlay-$Version" }
$stage = Join-Path $Out $base
$zip = "$stage.zip"
$stamp = Get-Date -Format 'yyyyMMdd_HHmmss'
@ -90,8 +107,19 @@ try {
Copy-Item $uplugin $modDir
$files | Copy-Item -Destination (Join-Path $modDir 'Content\Paks\Windows')
Copy-Item (Join-Path $mounted 'Module') (Join-Path $stage "LifePlay\Content\Modules\$Name") -Recurse
# Copie livree (pas les sources) : date de paquet et version du jeu visee (avertissement en jeu si elle differe).
$stagedLpmod = Join-Path $stage "LifePlay\Content\Modules\$Name\$Name.lpmod"
$stamped = @($lpmodLines | Where-Object { $_ -notmatch '^MODULE_(PACKAGED|GAME_VERSION):' }) + "MODULE_PACKAGED: $(Get-Date -Format 'yyyy-MM-dd')" + "MODULE_GAME_VERSION: $Version"
[IO.File]::WriteAllText($stagedLpmod, ($stamped -join "`r`n") + "`r`n", (New-Object Text.UTF8Encoding $false))
# Descripteur livre : version du mod et lien de l'auteur dans les champs natifs du plugin.
$stagedPlugin = Join-Path $modDir "$Name.uplugin"
$desc = Get-Content $stagedPlugin -Raw | ConvertFrom-Json
if ($modVersion) { $desc.VersionName = $modVersion }
$authorLink = Get-LpmodValue 'MODULE_AUTHOR_LINK'
if ($authorLink) { $desc | Add-Member CreatedByURL $authorLink -Force }
[IO.File]::WriteAllText($stagedPlugin, ($desc | ConvertTo-Json) + "`r`n", (New-Object Text.UTF8Encoding $false))
$readme = @(
"$title ($Name) - built for LifePlay $Version",
"$title ($Name)$(if ($modVersion) { " $modVersion" }) - built for LifePlay $Version",
'',
'INSTALL: extract this archive into the game folder (the one containing LifePlay.exe), merging the LifePlay folder.',
"Then open `"Mod Manager`" on the title screen and enable the mod. To uninstall, delete LifePlay\Mods\$Name",

View file

@ -8,7 +8,7 @@
sous "<Nom> Content" (chemin /<Nom>/) ; un editeur deja ouvert ne voit pas le mod : le fermer d'abord.
.EXAMPLE
.\Tools\EditMod.ps1 -Name LPHairSample
.\Tools\EditMod.ps1 -Name lpr_hair_pocolov
#>
param(
[Parameter(Mandatory)] [string] $Name

View file

@ -12,7 +12,7 @@
Refuse un nom deja pris (sources, module du jeu ou plugin).
.EXAMPLE
.\Tools\NewMod.ps1 -Name MyHairPack -Title "My Hair Pack" -Author "Me" -Hairs
.\Tools\NewMod.ps1 -Name MyHairPack -Title "My Hair Pack" -Author "Me" -License "CC BY 4.0" -AuthorLink https://example.org -Hairs
#>
param(
[Parameter(Mandatory)] [ValidatePattern('^[A-Za-z][A-Za-z0-9_]{2,40}$')] [string] $Name,
@ -20,6 +20,10 @@ param(
[Parameter(Mandatory)] [string] $Author,
[string] $Description = '',
[string] $Link = '',
[string] $ModVersion = '1.0',
[string] $License = '',
[string] $AuthorLink = '',
[string] $Price = 'Free',
[switch] $Hairs
)
@ -33,12 +37,13 @@ $utf8 = New-Object Text.UTF8Encoding $false
New-Item -ItemType Directory -Force (Join-Path $src 'Content'), (Join-Path $src 'Module') | Out-Null
$plugin = [ordered]@{
FileVersion = 3; Version = 1; VersionName = '1.0'
FileVersion = 3; Version = 1; VersionName = $ModVersion
FriendlyName = $Title
Description = $(if ($Description) { $Description } else { "LifePlay mod: $Title" })
Category = 'LifePlay Mods'; CreatedBy = $Author
CanContainContent = $true; IsBetaVersion = $false; Installed = $false
}
if ($AuthorLink) { $plugin.CreatedByURL = $AuthorLink }
[IO.File]::WriteAllText((Join-Path $src "$Name.uplugin"), ($plugin | ConvertTo-Json) + "`r`n", $utf8)
$lpmod = @(
@ -47,7 +52,13 @@ $lpmod = @(
"MODULE_AUTHOR: $Author",
"MODULE_LINK: $Link",
"MODULE_DESCRIPTION: $(if ($Description) { $Description } else { $Title })",
'MODULE_REQUIREMENTS: vin_Base')
'MODULE_REQUIREMENTS: vin_Base',
# Metadonnees (H3d) ; MODULE_PACKAGED et MODULE_GAME_VERSION sont ecrites par BuildMod.ps1 dans la copie livree.
"MODULE_VERSION: $ModVersion",
"MODULE_CREATED: $(Get-Date -Format 'yyyy-MM-dd')",
"MODULE_LICENSE: $License",
"MODULE_AUTHOR_LINK: $AuthorLink",
"MODULE_PRICE: $Price")
[IO.File]::WriteAllText((Join-Path $src "Module\$Name.lpmod"), ($lpmod -join "`r`n") + "`r`n", $utf8)
[IO.File]::WriteAllText((Join-Path $src 'Module\CREDITS.txt'), "Credits and licenses of the assets in $Title (one line per asset: title, author, license, source URL, changes).`r`n", $utf8)
@ -61,7 +72,7 @@ if ($Hairs) {
}
New-Item -ItemType Directory -Force (Split-Path $cfgPath -Parent) | Out-Null
[IO.File]::WriteAllText($cfgPath, ($cfg | ConvertTo-Json -Depth 4) + "`r`n", $utf8)
Write-Host "Configuration des coiffures : $cfgPath (ajouter les entrees de 'hairs', voir Tools/mods/LPHairSample.json)"
Write-Host "Configuration des coiffures : $cfgPath (ajouter les entrees de 'hairs', voir Tools/mods/lpr_hair_pocolov.json)"
}
Write-Host "Mod cree : $src"
Write-Host "Suite : .\Tools\EditMod.ps1 -Name $Name (assets dans l'editeur), puis .\Tools\BuildMod.ps1 -Name $Name"

View file

@ -1,32 +0,0 @@
{
"mod": "LPHairSample",
"module": "LPHairSample",
"folder": "/LPHairSample/Hairs",
"backup": "D:/Game/LifePlay_Backup_5.5/H3a",
"hairs": [
{
"name": "Pocolov05",
"archive": "D:/Game/pocolov-hair-05.zip",
"title": "Pocolov Hair 05",
"url": "https://www.fab.com/listings/4025749f-d597-4332-91aa-16e355b94974",
"mesh": "/LPHairSample/Hairs/_Work_Pocolov05/Box001",
"head": "/LPHairSample/Hairs/_Work_Pocolov05/Head",
"cap_slots": "Hair_Base",
"diffuse": "D:/Game/LifePlay_Backup_5.5/H3a/Pocolov05/norm/tex01_Hair_01_Gray.png",
"strands_opacity": "D:/Game/LifePlay_Backup_5.5/H3a/Pocolov05/norm/tex02_Hair_01A1.jpg",
"cap_opacity": "white",
"thicken": 1,
"sex": "F",
"license": "CC BY 4.0",
"author": "Pocolov (Pocolov Studio, artist Thang)",
"auto_fields": [
"mesh",
"head",
"cap_slots",
"diffuse",
"strands_opacity"
],
"inspected": true
}
]
}

View file

@ -0,0 +1,296 @@
{
"mod": "lpr_hair_pocolov",
"module": "lpr_hair_pocolov",
"folder": "/lpr_hair_pocolov/Hairs",
"backup": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov",
"hairs": [
{
"name": "Pocolov03",
"archive": "D:/Game/pocolov-hair-03.zip",
"title": "Pocolov Hair 03",
"url": "https://www.fab.com/listings/2257098d-b77c-4eef-9132-85f1454f0ae3",
"mesh": "/lpr_hair_pocolov/Hairs/_Work_Pocolov03/Box001",
"head": "/lpr_hair_pocolov/Hairs/_Work_Pocolov03/Head",
"cap_slots": "Hair_Base",
"diffuse": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov03/norm/tex10_Hair_01_Gray.png",
"strands_opacity": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov03/norm/tex12_Hair_01A1.jpg",
"cap_opacity": "white",
"thicken": 1,
"sex": "F",
"license": "CC BY 4.0",
"author": "Pocolov (Pocolov Studio, artist Thang)",
"auto_fields": [
"mesh",
"head",
"cap_slots",
"diffuse",
"strands_opacity"
],
"inspected": true
},
{
"name": "Pocolov05",
"archive": "D:/Game/pocolov-hair-05.zip",
"title": "Pocolov Hair 05",
"url": "https://www.fab.com/listings/4025749f-d597-4332-91aa-16e355b94974",
"mesh": "/lpr_hair_pocolov/Hairs/_Work_Pocolov05/Box001",
"head": "/lpr_hair_pocolov/Hairs/_Work_Pocolov05/Head",
"cap_slots": "Hair_Base",
"diffuse": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov05/norm/tex01_Hair_01_Gray.png",
"strands_opacity": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov05/norm/tex02_Hair_01A1.jpg",
"cap_opacity": "white",
"thicken": 1,
"sex": "F",
"license": "CC BY 4.0",
"author": "Pocolov (Pocolov Studio, artist Thang)",
"auto_fields": [
"mesh",
"head",
"cap_slots",
"diffuse",
"strands_opacity"
],
"inspected": true
},
{
"name": "Pocolov06",
"archive": "D:/Game/pocolov-hair-06.zip",
"title": "Pocolov Hair 06",
"url": "https://www.fab.com/listings/14c3cd52-02f9-4bfe-bb40-b5c3acb1f428",
"mesh": "/lpr_hair_pocolov/Hairs/_Work_Pocolov06/Hair_06",
"head": "/lpr_hair_pocolov/Hairs/_Work_Pocolov06/Head",
"cap_slots": "Hair_Base",
"diffuse": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov06/norm/tex01_Hair_01_Gray.png",
"strands_opacity": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov06/norm/tex02_Hair_01A1.jpg",
"cap_opacity": "white",
"thicken": 1,
"sex": "F",
"license": "CC BY 4.0",
"author": "Pocolov (Pocolov Studio, artist Thang)",
"auto_fields": [
"mesh",
"head",
"cap_slots",
"diffuse",
"strands_opacity"
],
"inspected": true
},
{
"name": "Pocolov07",
"archive": "D:/Game/pocolov-hair-07.zip",
"title": "Pocolov Hair 07",
"url": "https://www.fab.com/listings/4d1ba957-b420-4bdc-8984-b528a73b1d58",
"mesh": "/lpr_hair_pocolov/Hairs/_Work_Pocolov07/Hair_07",
"head": "/lpr_hair_pocolov/Hairs/_Work_Pocolov07/Head",
"cap_slots": "Hair_Base",
"diffuse": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov07/norm/tex01_Hair_01_Gray.png",
"strands_opacity": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov07/norm/tex02_Hair_01A1.jpg",
"cap_opacity": "white",
"thicken": 1,
"sex": "F",
"license": "CC BY 4.0",
"author": "Pocolov (Pocolov Studio, artist Thang)",
"auto_fields": [
"mesh",
"head",
"cap_slots",
"diffuse",
"strands_opacity"
],
"inspected": true
},
{
"name": "Pocolov09",
"archive": "D:/Game/pocolov-hair-09.zip",
"title": "Pocolov Hair 09",
"url": "https://www.fab.com/listings/80383c46-f491-4db2-a63d-48d279f35782",
"mesh": "/lpr_hair_pocolov/Hairs/_Work_Pocolov09/Hair_09",
"head": "/lpr_hair_pocolov/Hairs/_Work_Pocolov09/Head",
"cap_slots": "",
"diffuse": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov09/norm/tex01_Hair_01_Gray.png",
"strands_opacity": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov09/norm/tex04_Hair_Texture_A.jpg",
"cap_opacity": "white",
"thicken": 1,
"sex": "F",
"license": "CC BY 4.0",
"author": "Pocolov (Pocolov Studio, artist Thang)",
"auto_fields": [
"mesh",
"head",
"cap_slots",
"diffuse",
"strands_opacity"
],
"inspected": true
},
{
"name": "Pocolov10",
"archive": "D:/Game/pocolov-hair-10.zip",
"title": "Pocolov Hair 10",
"url": "https://www.fab.com/listings/40a91685-76dc-4384-91f1-0040f44e8958",
"mesh": "/lpr_hair_pocolov/Hairs/_Work_Pocolov10/Hair_10",
"head": "/lpr_hair_pocolov/Hairs/_Work_Pocolov10/Head",
"cap_slots": "Hair_Base",
"diffuse": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov10/norm/tex01_Hair_01_Gray.png",
"strands_opacity": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov10/norm/tex02_Hair_01A1.jpg",
"cap_opacity": "white",
"thicken": 1,
"sex": "F",
"license": "CC BY 4.0",
"author": "Pocolov (Pocolov Studio, artist Thang)",
"auto_fields": [
"mesh",
"head",
"cap_slots",
"diffuse",
"strands_opacity"
],
"inspected": true
},
{
"name": "Pocolov11",
"archive": "D:/Game/pocolov-hair-11.zip",
"title": "Pocolov Hair 11",
"url": "https://www.fab.com/listings/c31c219e-bc62-4957-91c5-720440375f79",
"mesh": "/lpr_hair_pocolov/Hairs/_Work_Pocolov11/Hair_11",
"head": "/lpr_hair_pocolov/Hairs/_Work_Pocolov11/Head",
"cap_slots": "",
"diffuse": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov11/norm/tex01_Hair_01_Gray.png",
"strands_opacity": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov11/norm/tex04_Hair_Texture_A.jpg",
"cap_opacity": "white",
"thicken": 1,
"sex": "F",
"license": "CC BY 4.0",
"author": "Pocolov (Pocolov Studio, artist Thang)",
"auto_fields": [
"mesh",
"head",
"cap_slots",
"diffuse",
"strands_opacity"
],
"inspected": true
},
{
"name": "Pocolov13",
"archive": "D:/Game/pocolov-hair-13.zip",
"title": "Pocolov Hair 13",
"url": "https://www.fab.com/listings/a3933681-f5e3-4d93-99f0-c5fff444d405",
"mesh": "/lpr_hair_pocolov/Hairs/_Work_Pocolov13/Hair_13",
"head": "/lpr_hair_pocolov/Hairs/_Work_Pocolov13/Head",
"cap_slots": "Hair_Base",
"diffuse": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov13/norm/tex01_Hair_01_Gray.png",
"strands_opacity": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov13/norm/tex02_Hair_01A1.jpg",
"cap_opacity": "white",
"thicken": 1,
"sex": "F",
"license": "CC BY 4.0",
"author": "Pocolov (Pocolov Studio, artist Thang)",
"auto_fields": [
"mesh",
"head",
"cap_slots",
"diffuse",
"strands_opacity"
],
"inspected": true
},
{
"name": "Pocolov14",
"archive": "D:/Game/pocolov-hair-14.zip",
"title": "Pocolov Hair 14",
"url": "https://www.fab.com/listings/4911f6b9-d548-45d7-86be-a6971da97c54",
"mesh": "/lpr_hair_pocolov/Hairs/_Work_Pocolov14/Hair_14",
"head": "/lpr_hair_pocolov/Hairs/_Work_Pocolov14/Head",
"cap_slots": "Hair_Base",
"diffuse": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov14/norm/tex01_Hair_01_Gray.png",
"strands_opacity": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov14/norm/tex02_Hair_01A1.jpg",
"cap_opacity": "white",
"thicken": 1,
"sex": "F",
"license": "CC BY 4.0",
"author": "Pocolov (Pocolov Studio, artist Thang)",
"auto_fields": [
"mesh",
"head",
"cap_slots",
"diffuse",
"strands_opacity"
],
"inspected": true
},
{
"name": "Pocolov15",
"archive": "D:/Game/pocolov-hair-15.zip",
"title": "Pocolov Hair 15",
"url": "https://www.fab.com/listings/ed8e016a-0bf0-4a6c-94b0-2760083b879d",
"mesh": "/lpr_hair_pocolov/Hairs/_Work_Pocolov15/Hair_15",
"head": "/lpr_hair_pocolov/Hairs/_Work_Pocolov15/Head",
"cap_slots": "Hair_Base",
"diffuse": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov15/norm/tex01_Hair_01_Gray.png",
"strands_opacity": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov15/norm/tex02_Hair_01A1.jpg",
"cap_opacity": "white",
"thicken": 1,
"sex": "F",
"license": "CC BY 4.0",
"author": "Pocolov (Pocolov Studio, artist Thang)",
"auto_fields": [
"mesh",
"head",
"cap_slots",
"diffuse",
"strands_opacity"
],
"inspected": true
},
{
"name": "Pocolov16",
"archive": "D:/Game/pocolov-hair-16.zip",
"title": "Pocolov Hair 16",
"url": "https://www.fab.com/listings/802dc956-6211-4b83-8ba1-37beb3cb338f",
"mesh": "/lpr_hair_pocolov/Hairs/_Work_Pocolov16/Hair_16",
"head": "/lpr_hair_pocolov/Hairs/_Work_Pocolov16/Head",
"cap_slots": "Hair_Base",
"diffuse": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov16/norm/tex01_Hair_01_Gray.png",
"strands_opacity": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov16/norm/tex04_Hair_01A.jpg",
"cap_opacity": "white",
"thicken": 1,
"sex": "F",
"license": "CC BY 4.0",
"author": "Pocolov (Pocolov Studio, artist Thang)",
"auto_fields": [
"mesh",
"head",
"cap_slots",
"diffuse",
"strands_opacity"
],
"inspected": true
},
{
"name": "Pocolov17",
"archive": "D:/Game/pocolov-hair-17.zip",
"title": "Pocolov Hair 17",
"url": "https://www.fab.com/listings/7f6f687d-bb13-40c6-8b69-64044ededc1d",
"mesh": "/lpr_hair_pocolov/Hairs/_Work_Pocolov17/Hair_17",
"head": "/lpr_hair_pocolov/Hairs/_Work_Pocolov17/Head",
"cap_slots": "Hair_Base",
"diffuse": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov17/norm/tex01_Hair_01_Gray.png",
"strands_opacity": "D:/Game/LifePlay_Backup_5.5/mods/lpr_hair_pocolov/Pocolov17/norm/tex02_Hair_01A1.jpg",
"cap_opacity": "white",
"thicken": 1,
"sex": "F",
"license": "CC BY 4.0",
"author": "Pocolov (Pocolov Studio 2019, artist Thang)",
"auto_fields": [
"mesh",
"head",
"cap_slots",
"diffuse",
"strands_opacity"
],
"inspected": true
}
]
}

5
Tools/modules/next.json Normal file
View file

@ -0,0 +1,5 @@
{
"version": "next",
"essential": ["vin_Base", "vin_VanillaRealistic"],
"zip": "LifePlay_Revival_Optional_Modules.zip"
}