Ce générateur utilise les données des Chroniques d'Urum pour produire des objets aléatoires cohérents avec leur contexte. Les Data Assets et Data Tables définissent les objets, leurs qualités et leurs modificateurs, tandis que les Gameplay Tags relient les catégories, les règles de génération et les fragments associés.
Unreal Engine 5
C++
Data Assets
Data Tables
Gameplay Tags
Génération procédurale
18types de modificateurs applicables selon l'objet
13types d'objets aux effets uniques selon les jets
7niveaux de rareté
272ingrédients et potions d'apothicaire
78types d'armes
54types d'armures
38types de gemmes
96runes aux effets magiques uniques
Générer l'objet à partir du contexte
ItemGeneratorComponent choisit d'abord une qualité, puis sélectionne le type d'objet à générer dans une table pondérée associée au lieu. Il assemble ensuite les fragments et calcule le poids total de l'instance obtenue.
UGeneratedItemInstance* UItemGeneratorComponent::CreateItem(const FGameplayTag Location)
{
UGeneratedItemInstance* NewItem = NewObject<UGeneratedItemInstance>(this);
ItemQualityData = GetItemQuality();
NewItem->QualityTag = ItemQualityData.ItemQualityTag;
NewItem->ItemColor = ItemQualityData.QualityColor;
NewItem->Rolls = ItemQualityData.Rolls;
NewItem->ItemTypeTag = GetItemTypeFromLocation(Location);
AddFragmentsFromTags(NewItem, NewItem->ItemTypeTag);
CalculateItemTotalBurden(NewItem);
return NewItem;
}
Assembler une instance composée de fragments
GeneratedItemInstance est l'objet final retourné par le générateur. Il conserve l'identité de l'objet, sa qualité, ses modificateurs et la collection de fragments qui portent ses propriétés de gameplay.
UCLASS(BlueprintType)
class URUM_PROTO_API UGeneratedItemInstance : public UObject
{
GENERATED_BODY()
public:
FGameplayTag ItemTypeTag;
FGameplayTag QualityTag;
FGameplayTagContainer ModifierTags;
FString ItemName;
float ItemBurden = 0.f;
FLinearColor ItemColor = FLinearColor::White;
int32 Rolls = 0;
UPROPERTY(BlueprintReadOnly, Instanced)
TArray<TObjectPtr<UItemFragment>> Fragments;
};
Fragment de base et modificateurs
Une règle associe le tag de l'objet à sa classe de fragment de base. Ce fragment récupère les données de la catégorie concernée, par exemple les dégâts, la résistance et la portée d'une arme. Selon la rareté, des jets supplémentaires sélectionnent des Modifier Fragments compatibles dans un pool pondéré, sans dupliquer un modificateur déjà appliqué.
void UItemGeneratorComponent::CreateModifierFragments(
UGeneratedItemInstance* ItemInstance, const FGameplayTag ItemTag) const
{
int32 Rolls = GetModifiersRollsAmount(ItemInstance->QualityTag, ItemTag);
TArray<FModifierPoolRow> PoolRows =
GetEligibleModifierRows(ItemInstance->QualityTag, ItemTag);
while (Rolls > 0 && PoolRows.Num() > 0)
{
FModifierPoolRow RandomRow;
GetRandomModifierRow(PoolRows, RandomRow);
if (ItemInstance->ModifierTags.HasTagExact(RandomRow.ModifierFragmentTag))
{
continue;
}
InitializeFragmentFromPoolRow(ItemInstance, RandomRow);
PoolRows.RemoveAll([&](const FModifierPoolRow& Row)
{
return Row.ModifierFragmentTag == RandomRow.ModifierFragmentTag;
});
Rolls--;
}
}
Qualité magique et jets de modificateurs
Cette définition de qualité magique applique une couleur distinctive et des ajustements de statistiques à l'objet généré. Elle garantit d'abord un Modifier Fragment, puis peut en ajouter d'autres grâce à une série de probabilités dégressives : 38 %, 25 %, 8 %, puis 4 %.
Qualité Item.Rarity.Magic
Modificateurs garantis 1
Chances supplémentaires 38 % / 25 % / 8 % / 4 %
Bonus de dégâts +3
Multiplicateur de résistance ×2
Nombre de jets 3
Le générateur commence donc avec le modificateur garanti. Il lance ensuite un premier jet à 38 % pour en ajouter un autre, puis un second à 25 % seulement si le premier réussit, et ainsi de suite. La séquence s'arrête immédiatement dès qu'un jet échoue : un échec au jet à 25 %, par exemple, empêche les jets à 8 % et 4 %. Cette progression dégressive limite naturellement le nombre de modificateurs tout en laissant une chance aux objets exceptionnels.
Exemple : une arme magique liée
Cet exemple illustre une génération possible. Dans un lieu où les armes peuvent apparaître, le tirage sélectionne une arme de mêlée, puis une qualité qui accorde au moins un jet de modificateur. Le pool compatible propose le tag Item.Modifier.Bonded : le fragment correspondant complète alors l'arme avec ses propriétés de lien.
1. Contexte
Lieu de génération
LocationTag
→
2. Tirage pondéré
Type d'objet
Item.Type.Weapon.Melee.Blade
→
3. Données de base
Weapon Fragment
Dégâts, résistance, portée, poids
→
4. Rareté
Qualité tirée
Couleur, bonus et nombre de jets
→
5. Modificateur
Bonded Fragment
Item.Modifier.Bonded
→
6. Instance finale
Arme magique liée
Fragments + tags + poids total
Le WeaponFragment applique les valeurs de base et les ajustements de qualité. Un fragment Bonded signifie que l'objet est lié à son porteur : il peut revenir à portée de main dans une limite de distance définie, et son utilisateur peut sentir sa présence à une distance configurée. Ces fragments sont conservés ensemble dans GeneratedItemInstance, qui constitue la représentation complète de l'objet.
// Le fragment d'arme applique les donnees de base et la qualite.
TotalDamage = FMath::Max(1, BaseDamage + ItemQualityData.DamageModifier);
TotalResistance = BaseResistance * ItemQualityData.ResistanceMultiplier;
// Le modificateur Bonded ajoute ses proprietes specialisees.
BondReturnDistance = BondedBaseData.BondReturnDistance;
BondPresenceDetectionDistance = BondedBaseData.BondPresenceDetectionDistance;
Exemple de définition : Épée longue
Cette entrée de Data Asset décrit une épée longue avant sa génération. Son Gameplay Tag Item.Type.Weapon.Melee.Blade.LongSword permet au générateur d'identifier sa catégorie et d'instancier le WeaponFragment approprié. Les statistiques indiquées constituent les valeurs de base, auxquelles la qualité et les modificateurs peuvent ensuite s'ajouter.
Type Arme à une main
Dégâts de base 10
Résistance de base 10
Prérequis Force 3 / Agilité 3
Portée Mêlée
Poids de base 10
Vers une présentation visuelle des objets
L'objectif du projet est d'exploiter au maximum les Gameplay Tags afin de construire un système data-driven, extensible à volonté sans multiplier les cas particuliers dans le code. La prochaine étape donnera une dimension plus visuelle au générateur, avec une animation de type loot box et une interface dédiée à la présentation des objets obtenus. À terme, chaque objet disposera de son propre rendu 3D et de VFX déterminés par ses caractéristiques, sa qualité et ses modificateurs.