forked from Shardstone/trail-into-darkness
602 lines
24 KiB
C#
602 lines
24 KiB
C#
using Jovian.InGameLogging;
|
|
using Jovian.InGameLogging.UI;
|
|
using Jovian.SaveSystem;
|
|
using Nox.Core;
|
|
using Nox.Game;
|
|
using Nox.Game.UI;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using ZLinq;
|
|
using Attribute = Nox.Game.Attribute;
|
|
using PlayMode = Nox.Core.PlayMode;
|
|
|
|
namespace Nox.UI {
|
|
public class CharacterCreationView : IGameLifecycle, IMenuView {
|
|
public ISaveSystem SaveSystem { get; }
|
|
|
|
private readonly CharacterCreationReference characterCreationReference;
|
|
private readonly MenuGameStateData menuGameStateData;
|
|
private readonly GameDataState gameDataState;
|
|
private readonly PartySettings partySettings;
|
|
private readonly ICharacterSystems characterSystems;
|
|
private readonly PortraitsHolder portraitsHolder;
|
|
private readonly StarterCharacterSettings starterCharacterSettings;
|
|
|
|
// Logger
|
|
private GameLogView gameLogView;
|
|
private InGameLogger inGameLogger;
|
|
|
|
// Working state
|
|
private CharacterRace selectedRace;
|
|
private CharacterClass selectedClass;
|
|
private int currentPortraitIndex;
|
|
private int remainingPoints;
|
|
private readonly int[] allocatedPoints = new int[4]; // Might, Reflex, Knowledge, Perception (AttributeType 1-4)
|
|
private int previousHealth;
|
|
private int previousStamina;
|
|
|
|
// Modifier source tracking
|
|
private PerksData racialPerks = new();
|
|
private ModifiersData racialModifiers = new();
|
|
private PerksData classPerks = new();
|
|
private ModifiersData classModifiers = new();
|
|
private readonly List<PerkDefinition> playerPerks = new();
|
|
private List<IPerk> availablePerks = new();
|
|
|
|
// Computed state
|
|
private EntityAttributes workingAttributes;
|
|
private EntityStats workingStats;
|
|
|
|
// Output
|
|
private List<CharacterCreationRequest> characterCreationRequests;
|
|
private Action canStartCheck;
|
|
|
|
// Back confirmation (null until popup is implemented)
|
|
private Action confirmBackAction;
|
|
|
|
public CharacterCreationView(CharacterCreationReference characterCreationReference,
|
|
MenuGameStateData menuGameStateData,
|
|
ISaveSystem saveSystem,
|
|
GameDataState gameDataState,
|
|
PartySettings partySettings,
|
|
ICharacterSystems characterSystems,
|
|
PortraitsHolder portraitsHolder,
|
|
StarterCharacterSettings starterCharacterSettings) {
|
|
SaveSystem = saveSystem;
|
|
this.characterCreationReference = characterCreationReference;
|
|
this.menuGameStateData = menuGameStateData;
|
|
this.gameDataState = gameDataState;
|
|
this.partySettings = partySettings;
|
|
this.characterSystems = characterSystems;
|
|
this.portraitsHolder = portraitsHolder;
|
|
this.starterCharacterSettings = starterCharacterSettings;
|
|
}
|
|
|
|
public void Initialize() {
|
|
// Logger
|
|
var store = new GameLogStore(500);
|
|
gameLogView = characterCreationReference.gameLogView;
|
|
gameLogView.Initialize(store);
|
|
inGameLogger = new InGameLogger(store, LogChannel.CharacterCreation);
|
|
inGameLogger.Enable();
|
|
|
|
// Start Game button
|
|
canStartCheck = () => {
|
|
var canStart = characterCreationRequests is { Count: > 0 };
|
|
characterCreationReference.startGameButton.interactable = canStart;
|
|
};
|
|
characterCreationReference.startGameButton.interactable = false;
|
|
characterCreationReference.startGameButton.onClick.AddListener(() => {
|
|
Hide();
|
|
menuGameStateData.startGameRequests?.Invoke(PlayMode.Adventure);
|
|
});
|
|
|
|
// Back buttons with popup check
|
|
characterCreationReference.backButton.onClick.AddListener(OnBackClicked);
|
|
characterCreationReference.backButtonCenter.onClick.AddListener(OnBackClicked);
|
|
|
|
// Accept button
|
|
characterCreationReference.acceptButton.onClick.AddListener(OnAcceptClicked);
|
|
|
|
// Race dropdown
|
|
PopulateEnumDropdown<CharacterRace>(characterCreationReference.raceDropdown);
|
|
characterCreationReference.raceDropdown.onValueChanged.AddListener(OnRaceChanged);
|
|
|
|
// Class dropdown
|
|
PopulateEnumDropdown<CharacterClass>(characterCreationReference.classDropdown);
|
|
characterCreationReference.classDropdown.onValueChanged.AddListener(OnClassChanged);
|
|
|
|
// Perks dropdown
|
|
PopulatePerksDropdown();
|
|
characterCreationReference.perksDropdown.onValueChanged.AddListener(OnPerkSelected);
|
|
|
|
// Attribute +/- buttons
|
|
var attrTypes = new[] { AttributeType.Might, AttributeType.Reflex, AttributeType.Knowledge, AttributeType.Perception };
|
|
var attrRefs = characterCreationReference.attributeReference;
|
|
for(int i = 0; i < attrRefs.Length && i < attrTypes.Length; i++) {
|
|
var type = attrTypes[i];
|
|
attrRefs[i].attributeName.text = type.ToString();
|
|
attrRefs[i].addPointsButton.onClick.AddListener(() => OnAttributeAdd(type));
|
|
attrRefs[i].removePointsButton.onClick.AddListener(() => OnAttributeRemove(type));
|
|
}
|
|
|
|
// Portrait navigation
|
|
currentPortraitIndex = 0;
|
|
if(portraitsHolder != null && portraitsHolder.portraits.Length > 0) {
|
|
characterCreationReference.portraitImage.sprite = portraitsHolder.portraits[0];
|
|
}
|
|
characterCreationReference.portraitSelectionLeftButton.onClick.AddListener(OnPortraitLeft);
|
|
characterCreationReference.portraitSelectionRightButton.onClick.AddListener(OnPortraitRight);
|
|
|
|
// Initial state
|
|
selectedRace = CharacterRace.Human;
|
|
selectedClass = CharacterClass.Warrior;
|
|
characterCreationReference.raceDropdown.SetValueWithoutNotify(0);
|
|
characterCreationReference.classDropdown.SetValueWithoutNotify(0);
|
|
ResetWorkingState();
|
|
}
|
|
|
|
// --- Dropdown helpers ---
|
|
|
|
private void PopulateEnumDropdown<T>(TMP_Dropdown dropdown) where T : Enum {
|
|
dropdown.ClearOptions();
|
|
var options = new List<string>();
|
|
foreach(T value in Enum.GetValues(typeof(T))) {
|
|
if(Convert.ToInt32(value) == 0) {
|
|
continue; // skip None
|
|
}
|
|
options.Add(value.ToString());
|
|
}
|
|
dropdown.AddOptions(options);
|
|
}
|
|
|
|
private void PopulatePerksDropdown() {
|
|
var dropdown = characterCreationReference.perksDropdown;
|
|
dropdown.ClearOptions();
|
|
availablePerks = new List<IPerk>(characterSystems.PerkFactory.GetAll());
|
|
|
|
var options = new List<string> { "Select a perk..." };
|
|
foreach(var perk in availablePerks) {
|
|
options.Add(perk.Name);
|
|
}
|
|
dropdown.AddOptions(options);
|
|
dropdown.SetValueWithoutNotify(0);
|
|
}
|
|
|
|
// --- State management ---
|
|
|
|
private void ResetWorkingState() {
|
|
Array.Clear(allocatedPoints, 0, allocatedPoints.Length);
|
|
racialPerks = new PerksData();
|
|
racialModifiers = new ModifiersData();
|
|
classPerks = new PerksData();
|
|
classModifiers = new ModifiersData();
|
|
playerPerks.Clear();
|
|
|
|
ApplyRacialBonuses();
|
|
ApplyClassBonuses();
|
|
UpdateRemainingPoints();
|
|
RecalculateAll();
|
|
|
|
// Initialize previous values so first change doesn't log a delta from 0
|
|
previousHealth = workingStats.GetValue(StatType.Health);
|
|
previousStamina = workingStats.GetValue(StatType.Mana);
|
|
}
|
|
|
|
private void ApplyRacialBonuses() {
|
|
racialPerks = new PerksData();
|
|
racialModifiers = new ModifiersData();
|
|
var bonuses = starterCharacterSettings.racialBonuses;
|
|
if(bonuses == null) {
|
|
return;
|
|
}
|
|
foreach(var rb in bonuses) {
|
|
if(rb.race == selectedRace) {
|
|
racialPerks = rb.startingPerks ?? new PerksData();
|
|
racialModifiers = rb.permanentModifiers ?? new ModifiersData();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ApplyClassBonuses() {
|
|
classPerks = new PerksData();
|
|
classModifiers = new ModifiersData();
|
|
var bonuses = starterCharacterSettings.classBonuses;
|
|
if(bonuses == null) {
|
|
return;
|
|
}
|
|
foreach(var cb in bonuses) {
|
|
if(cb.@class == selectedClass) {
|
|
classPerks = cb.startingPerks ?? new PerksData();
|
|
classModifiers = cb.permanentModifiers ?? new ModifiersData();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void UpdateRemainingPoints() {
|
|
var totalPoints = 0;
|
|
if(starterCharacterSettings.distributionPointsPerClass != null) {
|
|
foreach(var dpc in starterCharacterSettings.distributionPointsPerClass) {
|
|
if(dpc.@class == selectedClass) {
|
|
totalPoints = dpc.points;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
var spent = 0;
|
|
for(int i = 0; i < allocatedPoints.Length; i++) {
|
|
spent += allocatedPoints[i];
|
|
}
|
|
remainingPoints = totalPoints - spent;
|
|
}
|
|
|
|
// --- Core calculation ---
|
|
|
|
private void RecalculateAll() {
|
|
// 1. Start from default attributes + player allocations
|
|
var baseAttrs = starterCharacterSettings.defaultEntityAttributes;
|
|
var attrTypes = new[] { AttributeType.Might, AttributeType.Reflex, AttributeType.Knowledge, AttributeType.Perception };
|
|
var finalAttrs = new Attribute[attrTypes.Length];
|
|
for(int i = 0; i < attrTypes.Length; i++) {
|
|
var baseVal = baseAttrs.GetValue(attrTypes[i]);
|
|
finalAttrs[i] = new Attribute(attrTypes[i], baseVal + allocatedPoints[i]);
|
|
}
|
|
workingAttributes = new EntityAttributes { attributes = finalAttrs };
|
|
|
|
// 2. Build combined perks and modifiers (defaults + racial + class + player)
|
|
// Racial/class attribute and stat bonuses flow through permanentModifiers
|
|
var combinedPerks = BuildCombinedPerks();
|
|
var combinedModifiers = BuildCombinedModifiers();
|
|
|
|
// 3. Build temp entity for modifier collection
|
|
var tempEntity = new CharacterCreationRequest {
|
|
Id = Guid.NewGuid(),
|
|
Race = selectedRace,
|
|
Class = selectedClass,
|
|
Role = CharacterRole.Protagonist,
|
|
Attributes = workingAttributes,
|
|
Perks = combinedPerks,
|
|
Modifiers = combinedModifiers
|
|
};
|
|
|
|
// 4. Resolve attributes through modifiers (racial/class attribute bonuses come via modifiers)
|
|
var resolver = characterSystems.ModifierResolver;
|
|
var resolvedAttrs = new Attribute[attrTypes.Length];
|
|
for(int i = 0; i < attrTypes.Length; i++) {
|
|
var mods = resolver.CollectModifiers(tempEntity, attrTypes[i]);
|
|
resolvedAttrs[i] = new Attribute(attrTypes[i], resolver.Resolve(finalAttrs[i].value, mods, tempEntity));
|
|
}
|
|
workingAttributes = new EntityAttributes { attributes = resolvedAttrs };
|
|
tempEntity.Attributes = workingAttributes;
|
|
|
|
// 5. Calculate stats through modifiers (racial/class stat bonuses come via modifiers)
|
|
var baseStats = starterCharacterSettings.defaultEntityStats;
|
|
var statTypes = new[] { StatType.Health, StatType.Mana, StatType.Level, StatType.Experience };
|
|
var resolvedStats = new Stat[statTypes.Length];
|
|
for(int i = 0; i < statTypes.Length; i++) {
|
|
var baseVal = baseStats.GetValue(statTypes[i]);
|
|
var mods = resolver.CollectModifiers(tempEntity, statTypes[i]);
|
|
resolvedStats[i] = new Stat(statTypes[i], resolver.Resolve(baseVal, mods, tempEntity));
|
|
}
|
|
workingStats = new EntityStats { stats = resolvedStats };
|
|
|
|
// 9. Update UI
|
|
UpdateAttributeUI();
|
|
UpdateStatUI();
|
|
UpdatePointsDisplay();
|
|
|
|
// 10. Log stat deltas
|
|
var newHealth = workingStats.GetValue(StatType.Health);
|
|
var newStamina = workingStats.GetValue(StatType.Mana);
|
|
if(newHealth != previousHealth && previousHealth != 0) {
|
|
var delta = newHealth - previousHealth;
|
|
var sign = delta > 0 ? "+" : "";
|
|
inGameLogger.Log($"Health: {previousHealth} -> {newHealth} ({sign}{delta})", "#87CEEB");
|
|
}
|
|
if(newStamina != previousStamina && previousStamina != 0) {
|
|
var delta = newStamina - previousStamina;
|
|
var sign = delta > 0 ? "+" : "";
|
|
inGameLogger.Log($"Stamina: {previousStamina} -> {newStamina} ({sign}{delta})", "#FFFF99");
|
|
}
|
|
previousHealth = newHealth;
|
|
previousStamina = newStamina;
|
|
}
|
|
|
|
private PerksData BuildCombinedPerks() {
|
|
// Start with defaults, add racial/class/player perks (deduplicate by Id)
|
|
var combined = new PerksData { perks = new List<PerkDefinition>() };
|
|
var seenIds = new HashSet<Guid>();
|
|
|
|
void AddPerks(PerksData source) {
|
|
if(source?.perks == null) {
|
|
return;
|
|
}
|
|
foreach(var perk in source.perks) {
|
|
if(perk != null && seenIds.Add(perk.Id)) {
|
|
combined.perks.Add(perk);
|
|
}
|
|
}
|
|
}
|
|
|
|
AddPerks(starterCharacterSettings.defaultPerksData);
|
|
AddPerks(racialPerks);
|
|
AddPerks(classPerks);
|
|
foreach(var perk in playerPerks) {
|
|
if(perk != null && seenIds.Add(perk.Id)) {
|
|
combined.perks.Add(perk);
|
|
}
|
|
}
|
|
return combined;
|
|
}
|
|
|
|
private ModifiersData BuildCombinedModifiers() {
|
|
// Start with defaults. Racial/class modifiers override defaults that target the same
|
|
// thing, but ONLY if the override's requirements are currently met. If requirements
|
|
// are not met, the default stays and the override is still added — the resolver will
|
|
// skip the unqualified override at resolution time, leaving the default active.
|
|
var combined = new ModifiersData { modifiers = new List<ModifierDefinition>() };
|
|
|
|
// Seed with defaults
|
|
if(starterCharacterSettings.defaultModifiersData?.modifiers != null) {
|
|
combined.modifiers.AddRange(starterCharacterSettings.defaultModifiersData.modifiers);
|
|
}
|
|
|
|
// Override with racial modifiers
|
|
OverrideModifiers(combined, racialModifiers, workingAttributes);
|
|
|
|
// Override with class modifiers
|
|
OverrideModifiers(combined, classModifiers, workingAttributes);
|
|
|
|
return combined;
|
|
}
|
|
|
|
private static void OverrideModifiers(ModifiersData combined, ModifiersData overrides, EntityAttributes currentAttributes) {
|
|
if(overrides?.modifiers == null) {
|
|
return;
|
|
}
|
|
foreach(var mod in overrides.modifiers) {
|
|
if(mod?.Target == null) {
|
|
continue;
|
|
}
|
|
// Only remove the default if the override's requirements are currently met.
|
|
// Both are added regardless — the resolver skips unqualified modifiers at
|
|
// resolution time, so if requirements aren't met, the default still applies.
|
|
var requirementsMet = AreRequirementsMet(mod, currentAttributes);
|
|
if(requirementsMet) {
|
|
for(int i = combined.modifiers.Count - 1; i >= 0; i--) {
|
|
var existing = combined.modifiers[i];
|
|
if(existing?.Target != null && TargetsMatch(existing.Target, mod.Target)) {
|
|
combined.modifiers.RemoveAt(i);
|
|
}
|
|
}
|
|
}
|
|
combined.modifiers.Add(mod);
|
|
}
|
|
}
|
|
|
|
private static bool AreRequirementsMet(ModifierDefinition mod, EntityAttributes attributes) {
|
|
if(mod.Requirements == null || mod.Requirements.Count == 0) {
|
|
return true;
|
|
}
|
|
foreach(var req in mod.Requirements) {
|
|
if(!req.IsMet(attributes)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private static bool TargetsMatch(ModifierTarget a, ModifierTarget b) {
|
|
if(a.Type != b.Type) {
|
|
return false;
|
|
}
|
|
return a.Type switch {
|
|
ModifierTargetType.Attribute => a.AttributeType == b.AttributeType,
|
|
ModifierTargetType.Stat => a.StatType == b.StatType,
|
|
ModifierTargetType.CombatScore => a.CombatScoreType == b.CombatScoreType,
|
|
_ => false
|
|
};
|
|
}
|
|
|
|
// --- UI updates ---
|
|
|
|
private void UpdateAttributeUI() {
|
|
var attrTypes = new[] { AttributeType.Might, AttributeType.Reflex, AttributeType.Knowledge, AttributeType.Perception };
|
|
var attrRefs = characterCreationReference.attributeReference;
|
|
for(int i = 0; i < attrRefs.Length && i < attrTypes.Length; i++) {
|
|
attrRefs[i].attributeValue.text = workingAttributes.GetValue(attrTypes[i]).ToString();
|
|
attrRefs[i].addPointsButton.interactable = remainingPoints > 0;
|
|
attrRefs[i].removePointsButton.interactable = allocatedPoints[i] > 0;
|
|
}
|
|
}
|
|
|
|
private void UpdateStatUI() {
|
|
var statTypes = new[] { StatType.Health, StatType.Mana };
|
|
var statRefs = characterCreationReference.statReference;
|
|
for(int i = 0; i < statRefs.Length && i < statTypes.Length; i++) {
|
|
var value = workingStats.GetValue(statTypes[i]);
|
|
statRefs[i].statName.text = statTypes[i].ToString();
|
|
statRefs[i].statValue.text = value.ToString();
|
|
statRefs[i].statBar.fillAmount = Mathf.Clamp01(value / 200f);
|
|
}
|
|
}
|
|
|
|
private void UpdatePointsDisplay() {
|
|
characterCreationReference.pointsToDistribute.text = remainingPoints.ToString();
|
|
}
|
|
|
|
// --- Event handlers ---
|
|
|
|
private void OnRaceChanged(int index) {
|
|
selectedRace = (CharacterRace)(index + 1);
|
|
Array.Clear(allocatedPoints, 0, allocatedPoints.Length);
|
|
ApplyRacialBonuses();
|
|
UpdateRemainingPoints();
|
|
RecalculateAll();
|
|
inGameLogger.Log($"Race changed to {selectedRace}");
|
|
}
|
|
|
|
private void OnClassChanged(int index) {
|
|
selectedClass = (CharacterClass)(index + 1);
|
|
Array.Clear(allocatedPoints, 0, allocatedPoints.Length);
|
|
ApplyClassBonuses();
|
|
UpdateRemainingPoints();
|
|
RecalculateAll();
|
|
inGameLogger.Log($"Class changed to {selectedClass}");
|
|
}
|
|
|
|
private void OnPerkSelected(int index) {
|
|
if(index <= 0 || index > availablePerks.Count) {
|
|
return; // "Select a perk..." placeholder
|
|
}
|
|
|
|
var perkIndex = index - 1; // offset for placeholder
|
|
var perk = availablePerks[perkIndex];
|
|
playerPerks.Add(new PerkDefinition {
|
|
Id = perk.Id,
|
|
Name = perk.Name,
|
|
Modifiers = perk.Modifiers
|
|
});
|
|
availablePerks.RemoveAt(perkIndex);
|
|
PopulatePerksDropdown();
|
|
RecalculateAll();
|
|
inGameLogger.Log($"Perk added: {perk.Name}");
|
|
}
|
|
|
|
private void OnAttributeAdd(AttributeType type) {
|
|
if(remainingPoints <= 0) {
|
|
return;
|
|
}
|
|
var idx = (int)type - 1;
|
|
allocatedPoints[idx]++;
|
|
remainingPoints--;
|
|
RecalculateAll();
|
|
}
|
|
|
|
private void OnAttributeRemove(AttributeType type) {
|
|
var idx = (int)type - 1;
|
|
if(allocatedPoints[idx] <= 0) {
|
|
return;
|
|
}
|
|
allocatedPoints[idx]--;
|
|
remainingPoints++;
|
|
RecalculateAll();
|
|
}
|
|
|
|
private void OnPortraitLeft() {
|
|
if(portraitsHolder == null || portraitsHolder.portraits.Length == 0) {
|
|
return;
|
|
}
|
|
currentPortraitIndex--;
|
|
if(currentPortraitIndex < 0) {
|
|
currentPortraitIndex = portraitsHolder.portraits.Length - 1;
|
|
}
|
|
characterCreationReference.portraitImage.sprite = portraitsHolder.portraits[currentPortraitIndex];
|
|
}
|
|
|
|
private void OnPortraitRight() {
|
|
if(portraitsHolder == null || portraitsHolder.portraits.Length == 0) {
|
|
return;
|
|
}
|
|
currentPortraitIndex++;
|
|
if(currentPortraitIndex >= portraitsHolder.portraits.Length) {
|
|
currentPortraitIndex = 0;
|
|
}
|
|
characterCreationReference.portraitImage.sprite = portraitsHolder.portraits[currentPortraitIndex];
|
|
}
|
|
|
|
private void OnBackClicked() {
|
|
if(confirmBackAction != null) {
|
|
confirmBackAction();
|
|
return;
|
|
}
|
|
Hide();
|
|
}
|
|
|
|
// --- Accept ---
|
|
|
|
private void OnAcceptClicked() {
|
|
var errors = new List<string>();
|
|
if(selectedRace == CharacterRace.None) {
|
|
errors.Add("Race must be selected");
|
|
}
|
|
if(selectedClass == CharacterClass.None) {
|
|
errors.Add("Class must be selected");
|
|
}
|
|
if(remainingPoints > 0) {
|
|
errors.Add($"{remainingPoints} distribution points remaining");
|
|
}
|
|
var characterName = characterCreationReference.nameInputField.text;
|
|
if(string.IsNullOrWhiteSpace(characterName)) {
|
|
errors.Add("Name cannot be empty");
|
|
}
|
|
|
|
if(errors.Count > 0) {
|
|
foreach(var error in errors) {
|
|
inGameLogger.Log(error, "#FF4444");
|
|
}
|
|
return;
|
|
}
|
|
|
|
var request = new CharacterCreationRequest {
|
|
Id = Guid.NewGuid(),
|
|
Name = characterName,
|
|
Race = selectedRace,
|
|
Class = selectedClass,
|
|
Role = CharacterRole.Protagonist,
|
|
PortraitIndex = currentPortraitIndex,
|
|
Attributes = workingAttributes,
|
|
Stats = workingStats,
|
|
Perks = BuildCombinedPerks(),
|
|
Modifiers = BuildCombinedModifiers()
|
|
};
|
|
|
|
characterCreationRequests = new List<CharacterCreationRequest> { request };
|
|
|
|
// Log full breakdown
|
|
inGameLogger.Log("--- Character Accepted ---");
|
|
inGameLogger.Log($"Name: {request.Name}", "#FFBF00");
|
|
inGameLogger.Log($"Race: {request.Race}");
|
|
inGameLogger.Log($"Class: {request.Class}");
|
|
inGameLogger.Log($"Portrait: #{request.PortraitIndex}");
|
|
inGameLogger.Log($"{request.Attributes}");
|
|
inGameLogger.Log($"{request.Stats}");
|
|
if(request.Perks?.perks != null && request.Perks.perks.Count > 0) {
|
|
foreach(var perk in request.Perks.perks) {
|
|
inGameLogger.Log($"Perk: {perk.Name}");
|
|
}
|
|
}
|
|
|
|
CreateParty();
|
|
canStartCheck.Invoke();
|
|
}
|
|
|
|
private void CreateParty() {
|
|
var partyCreatorModel = new PartyCreatorModel(characterSystems.CharacterFactory, characterSystems.PartyFactory, characterCreationRequests, partySettings);
|
|
var party = partyCreatorModel.CreatePartyForNewRun();
|
|
gameDataState.ActiveParty = party;
|
|
}
|
|
|
|
// --- Lifecycle ---
|
|
|
|
public void Tick() {
|
|
}
|
|
|
|
public void Show() {
|
|
characterCreationReference.gameObject.SetActive(true);
|
|
}
|
|
|
|
public void Hide() {
|
|
characterCreationReference.gameObject.SetActive(false);
|
|
}
|
|
|
|
public void Dispose() {
|
|
inGameLogger.Disable();
|
|
}
|
|
}
|
|
}
|