V1.5 (LifePlay 2026.10.1.5) : version annee.mois.majeur.mineur, modules vin_* en un seul paquet, README

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
edujiro5972 2026-10-03 11:19:44 +02:00
parent 454941c53f
commit 1fc32f55d6
9 changed files with 93 additions and 24 deletions

View file

@ -1,7 +1,7 @@
[/Script/EngineSettings.GeneralProjectSettings]
ProjectID=543F4F9E4DE525696C82F5A52303C15C
ProjectName=LifePlay
ProjectVersion=2026.10.4
ProjectVersion=2026.10.1.5
Description=Portage UE 5.5 - assets integres depuis LifePlay 5.9 Full Source
[/Script/MoviePlayer.MoviePlayerSettings]

View file

@ -22,8 +22,11 @@ Vinfamy comme auteur original, lien Donate vers le Patreon de LifePlay Revival,
- **Version** : format du menu ramené à `LifePlay {text}` ; nouveau sous-système `Source/LifePlay/LPVersionSubsystem`
qui remplit `GI.version_text` au démarrage avec `ProjectVersion` de `Config/DefaultGame.ini`
(`[/Script/EngineSettings.GeneralProjectSettings]`). Format : **année.mois.publication**, le dernier nombre étant un
compteur de publications (V1.4 = 4) : `ProjectVersion=2026.10.4`. **À chaque publication**, mettre à jour cette ligne
(année et mois de la publication, compteur + 1).
compteur de publications (V1.4 = 4) : `ProjectVersion=2026.10.4`. **Depuis la V1.5 (décision du 2026-10-03)** :
**année.mois.majeur.mineur**, majeur et mineur étant ceux du numéro de version publié (V1.5 = `2026.10.1.5`,
V1.6 = `2026.<mois>.1.6`, V2.0 = `2026.<mois>.2.0`) ; la V1.4 publiée reste `2026.10.4`. Le jeu et les outils traitent
la version comme un texte (affichage, `Releases/<version>`, noms d'archives, comparaison exacte de
`MODULE_GAME_VERSION`) : aucun ne la compare numériquement. **À chaque publication**, mettre à jour cette ligne.
- **Menu** : nouvelle commandlet `LPEditWidget` (`Source/LifePlayEditorTools`), pilotée par une spécification versionnée
`Tools/ui/MainMenu_V1.4.json` ; chaque modification indique la valeur attendue avant (sinon rien n'est écrit), le
widget est compilé sans erreur puis sauvegardé. Modifications : format de version, URL Donate

View file

@ -57,3 +57,10 @@ gestionnaire de mods, où ils s'activent ou se désactivent. Pour en retirer un
partie texte serait livrée sans ses paquets ; utiliser un build neuf. Essai sur une copie des modules du build H3d :
15 archives, 640 fichiers déplacés = 640 archivés, aucun reste ; refus vérifié avec un mod d'assets installé (copies
d'essai dans `LifePlay_Backup_5.5\PUB_next`).
- **Rectification du 2026-10-03** : les modules `vin_*` optionnels (jeu d'origine de Vinfamy) forment **un seul zip**,
le paquet de base du jeu (`vin_Modules-for-LifePlay-<version>.zip`, 14 modules, notice listant chaque module et ses
prérequis) ; `vin_Base` et `vin_VanillaRealistic` restent dans le build. Les autres mods (ex. `lpr_hair_pocolov`) ont
chacun leur zip. Configuration : `"groups"` dans `Tools/modules/next.json` (`name`, `pattern`, `title`,
`description`) ; un module non couvert par un groupe a son propre zip. V1.5 : `vin_Modules` (875 911 octets, 626
fichiers) et `lpr_hair_pocolov-1.0` ; le premier découpage (un zip par module `vin_*`) est rangé dans
`LifePlay_Backup_5.5\PUB_V15\decoupage_un_zip_par_module`.

View file

@ -955,3 +955,4 @@ Validation L7c/L7d (2026-10-02, parc, même cadrage) : la nuit reste claire (sol
| CHG-108 | 2026-10-03 | H3c | `Docs/Modding/FullGuides/Creating_Asset_Mods.md` §5 | essai utilisateur de `Tools/EditMod.ps1` : mod monté et chargé (« Mounting Mod plugin lpr_hair_pocolov »), 12 coiffures visibles une fois « Afficher le contenu des plugins » coché dans le navigateur de contenu (masqué par défaut ; la recherche porte sur les noms d'assets) : précision ajoutée au guide. **H3c validé le 2026-10-03** | `git revert` du commit |
| CHG-109 | 2026-10-03 | PUB | `Tools/SplitModules.ps1` (mode `per_module` : une archive par module, notice tirée du `.lpmod`, `INDEX.txt` ; refus d'un build contenant un mod d'assets installé) ; `Tools/modules/next.json` ; `Docs/Migration/15_Modules_Optionnels.md` §5, `09_Commandes_Utiles.md` §7 | décision utilisateur pour la prochaine publication : chaque mod livré dans un zip indépendant, sauf les modules de base (texte) gardés dans le build Shipping ; diffusion des modules sur Discord dans un premier temps. Essai sur une copie (15 archives, 640 fichiers, garde-fou vérifié) | `git revert` du commit |
| CHG-110 | 2026-10-03 | H3c | sources texte de `ModSources/lpr_hair_pocolov` (`.uplugin`, `.lpmod`, 12 `.lphair`, `CREDITS.txt`) | incident : le commit `54f6604` (tag `H3c-valide`) a été fait pendant que le mod était monté dans `Mods/` par `EditMod.ps1` (éditeur ouvert) ; `git add -A` a enregistré la suppression de ses sources. Aucune perte sur disque (mod remis dans `ModSources/` à la fermeture de l'éditeur, 70 assets présents) ; sources réenregistrées par `bf9bb58`. Règle ajoutée (10_Protocole_Operations.md §6) : ne jamais commiter ni lancer un build tant que `Mods/` n'est pas vide. Le tag `H3c-valide` reste sur `54f6604` (déplacement non fait sans accord) | — |
| CHG-111 | 2026-10-03 | V1.5 | `Config/DefaultGame.ini` (`ProjectVersion=2026.10.1.5`), format de version (`14_Interface_V1.4.md`, `LPVersionSubsystem.h`), `README.md` (section V1.5, branche), `Tools/modules/next.json` (groupe `vin_*`), `Tools/SplitModules.ps1` (groupes), `Tools/BuildMod.ps1` (`INDEX.txt`), `15_Modules_Optionnels.md` ; build `LifePlay_Build_5.5_Shipping_V1.5` (version de référence `Releases/2026.10.1.5`, paquets identiques ; 2 modules de base) ; `Releases/2026.10.4` déplacé vers `LifePlay_Backup_5.5\Releases` ; modules `D:\Game\LifePlay_Publication\Modules_2026.10.1.5` (`vin_Modules`, `lpr_hair_pocolov-1.0`, `INDEX.txt`) | publication V1.5 (décisions utilisateur : version `année.mois.majeur.mineur` ; modules `vin_*` en un seul zip, autres mods chacun le leur ; diffusion des modules sur Discord, rien sur GitHub). Validé en jeu le 2026-10-03 ; les mods extraits dans le build pour le test et les fichiers de session ont été déplacés vers `LifePlay_Build_5.5_Shipping_V1.5_test_extraction` (build contrôlé contre le manifeste UAT : 0 fichier en trop, 1 459 fichiers) | `git revert` des commits V1.5 |

View file

@ -22,7 +22,8 @@ play, download the full source archive.
- Same layout as the original author's full source archives: the project folder at the archive root, 7z LZMA2.
- Contains the complete `Content` folder (including `Content/Heavy` converted to UE5 format), the compiled editor
modules in `Binaries` (the project opens without compiling), the `StreetMap` and `ModdingExtra` plugins, and a
`.git` folder matching this repository.
`.git` folder matching this repository. From V1.5: the mod sources (`ModSources/`, with their assets) and the
reference version `Releases/<version>` needed to cook asset mods.
- Not included: `Saved`, `Intermediate` (regenerated on first build), local development tools.
Check the file after downloading (PowerShell):
@ -31,6 +32,27 @@ Check the file after downloading (PowerShell):
Get-FileHash .\LifePlay_Revival_V1.4_UE5.5_Full_Source_Code.7z -Algorithm SHA256
```
## Status: V1.5 (tag `v1.5`, 2026-10-03) — LifePlay 2026.10.1.5
Mods can now bring their own 3D assets, and the Mod Manager is available from the title screen. Verified in game.
- **Version number.** New format `year.month.major.minor`: V1.5 is `LifePlay 2026.10.1.5` (V1.4 stays `2026.10.4`).
- **Asset mods.** A mod can ship cooked 3D assets (meshes, textures, materials) in `LifePlay/Mods/<mod>/` next to its
text module in `LifePlay/Content/Modules/<mod>/`, without rebuilding the game. Mods are cooked against the
**reference version** of the release (`Releases/2026.10.1.5`, included in the full source archive). Tools:
`Tools/NewMod.ps1`, `Tools/EditMod.ps1`, `Tools/HairPipeline.ps1`, `Tools/BuildMod.ps1`. Guide (English):
[`Docs/Modding/FullGuides/Creating_Asset_Mods.md`](Docs/Modding/FullGuides/Creating_Asset_Mods.md).
- **Mod Manager on the title screen.** Choose your mods before starting or loading a game; the choice is saved. A mod
that the game does not know yet starts disabled (as in the original game), unless its `.lpmod` declares
`MODULE_DEFAULT_ENABLED: true`.
- **Mod metadata and version warning.** New optional `.lpmod` keys (version, dates, license, author link, price, game
version), shown in the Mod Manager; the game warns when an enabled mod was built for another game version.
- **Pocolov hairstyles as a mod.** The Pocolov hairstyles left the base game: they are now the asset mod
`lpr_hair_pocolov` (12 hairstyles, CC BY 4.0; sources in `ModSources/lpr_hair_pocolov`, credits in its
`CREDITS.txt`).
- **Game build.** The packaged game only contains the base modules `vin_Base` and `vin_VanillaRealistic`. The source
archive and this repository keep all modules.
## Status: V1.4 (tag `v1.4`, 2026-10-02) — LifePlay 2026.10.4
Moddable hairstyles, first new content, and a lighter game build. Verified in game.
@ -128,6 +150,7 @@ Changes since V1, each validated in game against UE 4.27 on an identical play pa
| Branch | Contents |
|---|---|
| `main` | **reference**: the latest validated UE 5.5 version, base for further development |
| `ue5.5-v1.5` | the V1.5 as validated |
| `ue5.5-v1.4` | the V1.4 as validated |
| `ue5.5-v1.3` | the V1.3 as validated |
| `ue5.5-v1.2` | the V1.2 as validated |

View file

@ -2,7 +2,7 @@
//
// Le menu principal affiche "LifePlay {text}" (UI/MainMenu, Get_Version_Text_0) avec text = GI.version_text. Ce
// sous-systeme remplit GI.version_text au demarrage avec la version du projet (Config/DefaultGame.ini,
// [/Script/EngineSettings.GeneralProjectSettings] ProjectVersion, format annee.mois.publication : 2026.10.4).
// [/Script/EngineSettings.GeneralProjectSettings] ProjectVersion, format annee.mois.majeur.mineur depuis la V1.5 : 2026.10.1.5 ; V1.4 = 2026.10.4).
// GI.version_main et GI.version_sub (5 et 9, utilises par les sauvegardes et ReturnStatIfNeeded) ne sont pas modifies.
#pragma once

View file

@ -149,6 +149,15 @@ if ($staged -ne $listed) { throw "Archive : $listed fichier(s) pour $staged asse
$hash = (Get-FileHash $zip -Algorithm SHA256).Hash
Write-Host ("Archive : {0} ({1:N0} octets, {2} fichiers, SHA-256 {3})" -f $zip, (Get-Item $zip).Length, $listed, $hash)
# Index de diffusion (Tools/SplitModules.ps1, mode per_module) : ligne du mod ajoutee ou remplacee.
$index = Join-Path $Out 'INDEX.txt'
if (Test-Path $index) {
$entry = '{0} ({1}) : {2}, {3:N0} bytes, SHA-256 {4}' -f $title, $Name, (Split-Path $zip -Leaf), (Get-Item $zip).Length, $hash.ToLower()
$kept = @(Get-Content $index -Encoding utf8 | Where-Object { $_ -notlike "* ($Name) : *" })
[IO.File]::WriteAllText($index, (($kept + $entry) -join "`r`n") + "`r`n", (New-Object Text.UTF8Encoding $false))
Write-Host "Index mis a jour : $index"
}
# 5. Installation dans un jeu de test.
if ($Install) {
if (-not (Test-Path (Join-Path $Install 'LifePlay.exe'))) { throw "$Install ne contient pas LifePlay.exe" }

View file

@ -68,23 +68,42 @@ if ($cfg.per_module) {
'Install: extract the zip into the game folder (the one containing LifePlay.exe), merging the LifePlay folder, then enable',
'the module in "Mod Manager" (title screen). Installation : extraire le zip dans le dossier du jeu, puis activer le module.',
'Adult content, adults only / contenu adulte, reserve aux adultes.', '')
# Paquets : un groupe de la configuration ("groups" : name, pattern, title, description) reunit ses modules dans une
# seule archive (ex. vin_* = modules de base du jeu, decision du 2026-10-03) ; chaque autre module a la sienne.
$packages = @()
$grouped = @()
foreach ($g in @($cfg.groups)) {
if (-not $g) { continue }
$members = @($optional | Where-Object { $_.Name -like $g.pattern } | Sort-Object Name)
if ($members) { $packages += [pscustomobject]@{ Name = $g.name; Title = $g.title; Description = $g.description; Members = $members }; $grouped += $members.Name }
}
foreach ($m in ($optional | Where-Object { $_.Name -notin $grouped } | Sort-Object Name)) {
$packages += [pscustomobject]@{ Name = $m.Name; Title = ''; Description = ''; Members = @($m) }
}
$zipped = 0
foreach ($m in ($optional | Sort-Object Name)) {
$src = Join-Path $target $m.Name
$lp = Get-Content (Join-Path $src "$($m.Name).lpmod") -Encoding utf8
$val = { param($k) $l = $lp | Where-Object { $_ -match "^$k\s*:" } | Select-Object -First 1; if ($l) { ($l -split ':', 2)[1].Trim() } else { '' } }
$title = & $val 'MODULE_NAME'; $desc = & $val 'MODULE_DESCRIPTION'; $req = & $val 'MODULE_REQUIREMENTS'
$one = Join-Path $stage "_zip\$($m.Name)"
foreach ($p in $packages) {
$one = Join-Path $stage "_zip\$($p.Name)"
New-Item -ItemType Directory -Force (Join-Path $one 'LifePlay\Content\Modules') | Out-Null
Copy-Item $src (Join-Path $one "LifePlay\Content\Modules\$($m.Name)") -Recurse
$note = @("$title ($($m.Name)) - LifePlay Revival $($cfg.version)", '', $desc, $(if ($req) { "Requires / necessite : $req" } else { '' }), '',
$lines = @(); $expected = 0
foreach ($m in $p.Members) {
$src = Join-Path $target $m.Name
$lp = Get-Content (Join-Path $src "$($m.Name).lpmod") -Encoding utf8
$val = { param($k) $l = $lp | Where-Object { $_ -match "^$k\s*:" } | Select-Object -First 1; if ($l) { ($l -split ':', 2)[1].Trim() } else { '' } }
$title = & $val 'MODULE_NAME'; $desc = & $val 'MODULE_DESCRIPTION'; $req = & $val 'MODULE_REQUIREMENTS'
Copy-Item $src (Join-Path $one "LifePlay\Content\Modules\$($m.Name)") -Recurse
$expected += @(Get-ChildItem $src -Recurse -File).Count
$lines += "- $title ($($m.Name))$(if ($req) { ", requires / necessite : $req" })"
if ($p.Members.Count -eq 1) { $p.Title = $title; $p.Description = $desc }
}
$modulesDir = if ($p.Members.Count -eq 1) { "LifePlay\Content\Modules\$($p.Members[0].Name)" } else { 'LifePlay\Content\Modules\<module>' }
$note = @("$($p.Title) - LifePlay Revival $($cfg.version)", '', $p.Description, '') + $lines + @('',
'EN: extract this archive into the game folder (the one containing LifePlay.exe), merging the LifePlay folder, then',
"enable the module in `"Mod Manager`" (title screen). To remove it, delete LifePlay\Content\Modules\$($m.Name).",
"enable the module(s) in `"Mod Manager`" (title screen). To remove one, delete its folder $modulesDir.",
'FR : extraire cette archive dans le dossier du jeu (celui de LifePlay.exe) en fusionnant le dossier LifePlay, puis',
"activer le module dans `"Mod Manager`" (ecran titre). Pour le retirer : supprimer LifePlay\Content\Modules\$($m.Name).",
"activer le ou les modules dans `"Mod Manager`" (ecran titre). Pour en retirer un : supprimer $modulesDir.",
'Adult content, adults only / contenu adulte, reserve aux adultes.')
[IO.File]::WriteAllText((Join-Path $one 'README.txt'), ($note -join "`r`n") + "`r`n", (New-Object Text.UTF8Encoding $false))
$zip = Join-Path $dir "$($m.Name)-for-LifePlay-$($cfg.version).zip"
$zip = Join-Path $dir "$($p.Name)-for-LifePlay-$($cfg.version).zip"
if (Test-Path $zip) { throw "L'archive existe deja : $zip" }
Push-Location $one
& $SevenZip a -tzip -mx=7 $zip 'LifePlay' 'README.txt' | Out-Null
@ -92,17 +111,16 @@ if ($cfg.per_module) {
& $SevenZip t $zip | Out-Null
if ($LASTEXITCODE -ne 0) { throw "Test 7-Zip en echec : $zip" }
$n = (& $SevenZip l -slt $zip | Select-String '^Folder = -').Count - 1
$expected = @(Get-ChildItem $src -Recurse -File).Count
if ($n -ne $expected) { throw "$($m.Name) : $n fichier(s) dans l'archive pour $expected" }
if ($n -ne $expected) { throw "$($p.Name) : $n fichier(s) dans l'archive pour $expected" }
$zipped += $n
$h = (Get-FileHash $zip -Algorithm SHA256).Hash.ToLower()
$index += ('{0} ({1}) : {2}, {3:N0} bytes, SHA-256 {4}' -f $title, $m.Name, (Split-Path $zip -Leaf), (Get-Item $zip).Length, $h)
Write-Host " $($m.Name) : $(Split-Path $zip -Leaf) ($n fichiers)"
$index += ('{0} ({1}{2}) : {3}, {4:N0} bytes, SHA-256 {5}' -f $p.Title, $p.Name, $(if ($p.Members.Count -gt 1) { ': ' + ($p.Members.Name -join ', ') } else { '' }), (Split-Path $zip -Leaf), (Get-Item $zip).Length, $h)
Write-Host " $($p.Name) : $(Split-Path $zip -Leaf) ($($p.Members.Count) module(s), $n fichiers)"
}
[IO.File]::WriteAllText((Join-Path $dir 'INDEX.txt'), ($index -join "`r`n") + "`r`n", (New-Object Text.UTF8Encoding $false))
$left = Get-ChildItem $modules -Directory | Where-Object { $_.Name -in $optional.Name }
Write-Host "Modules gardes dans le build : $($cfg.essential -join ', ')"
Write-Host "Modules optionnels : $($optional.Count) archive(s) dans $dir ; fichiers deplaces $files, archives $zipped ; restes dans le build $(@($left).Count)"
Write-Host "Modules optionnels : $($optional.Count) en $($packages.Count) archive(s) dans $dir ; fichiers deplaces $files, archives $zipped ; restes dans le build $(@($left).Count)"
if ($zipped -ne $files -or @($left).Count -ne 0) { throw 'Controle en echec : contenu des archives different des fichiers deplaces' }
return
}

View file

@ -1,5 +1,13 @@
{
"version": "next",
"version": "2026.10.1.5",
"essential": ["vin_Base", "vin_VanillaRealistic"],
"per_module": true
}
"per_module": true,
"groups": [
{
"name": "vin_Modules",
"pattern": "vin_*",
"title": "LifePlay base game modules (vin_*, by Vinfamy)",
"description": "The optional modules of the original game by Vinfamy, in one package. Enable the ones you want in the Mod Manager (vin_NTR is disabled by default)."
}
]
}