Rendere la tua mod di Skyrim compatibile a metà partita
L’importanza della compatibilità a metà partita
I giocatori di Skyrim sono noti per la loro dedizione, spesso investendo centinaia, persino migliaia di ore in una singola partita. Chiedere a questi giocatori di iniziare una nuova partita per provare la tua mod, o anche solo per un aggiornamento, può essere un deterrente importante. Dal punto di vista dell’utente, ricominciare significa perdere innumerevoli ore di progressi e potenzialmente perdere del tutto la tua mod.
Questa guida è pensata per gli autori di mod, in particolare per coloro che hanno familiarità con il Creation Kit e le basi del modding. Esploreremo come implementare tecniche che consentono alla tua mod di essere installata o aggiornata a metà partita, garantendo un’esperienza più fluida e piacevole per i tuoi utenti.
Gestione di aggiornamenti e installazioni
La chiave per la compatibilità a metà partita sta nel capire come gestire script, missioni e riferimenti agli oggetti durante un aggiornamento della mod o un’installazione per la prima volta. Poiché questi scenari condividono gli stessi principi, li affronteremo insieme.
Il tempismo è tutto: eseguire la tua logica
-
Evento OnInit: Un approccio semplice consiste nell’utilizzare la funzione
OnInit
all’interno di una nuova missione progettata specificamente per aggiornamenti/installazioni. Questa missione dovrebbe essere contrassegnata come "Abilitata all’avvio del gioco" nella Scheda Dati missione del Creation Kit. Allega uno script a questa missione tramite la Scheda Script e inserisci il tuo codice di aggiornamento/installazione all’interno della funzioneOnInit
. -
Evento OnPlayerLoadGame: Per gli aggiornamenti, l’evento
OnPlayerLoadGame
offre un’alternativa. Crea un alias nella Scheda Alias, forza il riferimento al giocatore e allega uno script (estendendo lo script ReferenceAlias) a questo alias. Implementa la tua logica di aggiornamento all’interno della funzioneOnPlayerLoadGame
. Tieni presente che questo evento si attiva solo quando si carica un salvataggio, non all’inizializzazione di una nuova missione. Tuttavia,OnInit
verrà comunque eseguito per questo script alias all’avvio della missione. -
Evento OnCellAttach: Alcune funzioni, come
GetDistance
oFindClosestReferenceOfAnyTypeInListFromRef
, richiedono ObjectReference caricati. Se la tua logica di aggiornamento/installazione dipende da questi, utilizza la funzioneOnCellAttach
.
Demistificare gli script
Gli script sono spesso fonte di ansia per gli autori di mod preoccupati per la compatibilità a metà partita. Tuttavia, a meno che uno script non sia in esecuzione attiva durante il processo di salvataggio (il che è raro), il suo codice e lo stato di esecuzione non vengono salvati. Gli script in genere vengono eseguiti rapidamente, soprattutto se si utilizza RegisterForSingleUpdate
e OnUpdate
per ritardi più lunghi anziché Utility.Wait
.
La preoccupazione principale riguarda le proprietà e le variabili di istanza dello script, che vengono salvate. Fortunatamente, queste sono gestibili:
-
Proprietà: Imposta direttamente i loro valori allo stato desiderato utilizzando Papyrus.
-
Variabili di istanza: Poiché queste sono private al loro script, crea funzioni setter per aggiornarle:
int myInstanceVar = 5 Function SetMyInstanceVar(int newValue) myInstanceVar = newValue EndFunction
È importante sottolineare che le proprietà aggiunte di recente a uno script già inizializzato verranno automaticamente impostate sul valore specificato nel plugin, quindi è necessario modificare solo le proprietà esistenti.
Lavorare con le missioni
Una volta che una missione è in esecuzione (non solo visibile nel diario), le sue fasi, le proprietà dello script e gli alias diventano fissi. Ecco come gestirlo:
-
Alias: Facilmente aggiornabili utilizzando la funzione
ForceRefTo
. Aggiungi il nuovo riferimento come proprietà dello script nella tua logica di aggiornamento/installazione e utilizzaForceRefTo
per puntare il tuo alias ad esso. -
Fasi della missione:
- Evita modifiche non necessarie: Idealmente, mantieni la sequenza di indici di fase originale. Progetta la tua missione con ID fase sufficienti per accogliere aggiunte future.
- Considera la sostituzione della missione: Per revisioni importanti, termina la missione originale utilizzando
Stop
e introduci una nuova missione. - Ricostruzione della missione: Se devi ricostruire una missione esistente utilizzando lo stesso modulo, utilizza
Stop
,Reset
eSetStage
per guidare il giocatore allo stato desiderato dopo l’aggiornamento.
Gestione dei riferimenti agli oggetti
Le mod che alterano il mondo di gioco possono causare conflitti di posizionamento degli oggetti, spesso portando gli autori a richiedere un nuovo salvataggio. Questo perché i riferimenti persistenti hanno le loro posizioni salvate.
Ricorda, solo i riferimenti agli oggetti persistenti sono un problema. Gli oggetti temporanei si aggiorneranno automaticamente alle loro nuove posizioni poiché non vengono salvati.
-
Oggetti mobili: La maggior parte degli oggetti persistenti come Attivatori, Contenitori, MovableStatics e Marcatori possono essere spostati utilizzando gli script. La funzione
MoveToMyEditorLocation
è particolarmente utile per questo. -
Oggetti immobili: Alberi, Flora, Statics e Mobili non possono essere spostati tramite script. Ecco un paio di soluzioni:
- Disabilita e sostituisci: Se l’oggetto non viene utilizzato da altre mod, disabilita quello vecchio e aggiungine uno nuovo nella posizione desiderata. Assicurati che tutti gli alias delle missioni o le proprietà dello script che fanno riferimento a questi oggetti vengano aggiornati di conseguenza.
- Requisito Save Unbaker: Aggiungi la mod Save Unbaker come requisito. Questo strumento sposta automaticamente questi oggetti nelle loro nuove posizioni.
Altri record persistenti
Tieni presente questi record aggiuntivi che persistono nei salvataggi:
-
Ranghi fazione: Modificabili con
SetFactionRank
,AddToFaction
eRemoveFromFaction
. -
Ranghi relazione: Regolabili utilizzando
SetRelationshipRank
. -
Abiti NPC: Modificabili con
SetOutfit
.
Esempio: script di aggiornamento retroattivo
ScriptName RetroactiveFixAlias Extends ReferenceAlias
MyQuestScript Property myQuest Auto
ObjectReference Property myQuestProperty1Ref Auto
ObjectReference Property myQuestProperty2Ref Auto
ReferenceAlias Property myAlias1 Auto
ReferenceAlias Property myAlias2 Auto
ObjectReference Property myAlias1Ref Auto
ObjectReference Property myAlias2Ref Auto
ObjectReference Property myRef1 Auto
ObjectReference Property myRef2 Auto
ObjectReference Property myActor1 Auto
Outfit Property myActor1Outfit Auto
int currentVersion = -1
Event OnInit()
HandleInstallOrUpdates()
EndEvent
Event OnPlayerLoadGame()
HandleInstallOrUpdates()
EndEvent
Function HandleInstallOrUpdates()
If currentVersion != 2
myQuest.myQuestProperty1 = myQuestProperty1Ref
myQuest.myQuestProperty2 = myQuestProperty2Ref
myAlias1.ForceRefTo(myAlias1Ref)
myAlias2.ForceRefTo(myAlias2Ref)
myRef1.MoveToMyEditorLocation()
myRef2.MoveToMyEditorLocation()
myActor1.SetOutfit(myActor1Outfit)
currentVersion = 2
EndIf
EndFunction
Esempio: correzione di un ObjectReference dopo il caricamento della cella
ScriptName RetroactiveFixObjectReference extends ObjectReference
int currentVersion = -1
ObjectReference Property myRef Auto
FormList Property myRefTypes Auto
Event OnInit()
; Inizializzato nella versione 2, nessuna correzione necessaria
currentVersion = 2
EndEvent
Event OnCellAttach()
If currentVersion != 2
myRef = Game.FindClosestReferenceOfAnyTypeInListFromRef(myRefTypes, self, 100.0)
currentVersion = 2
EndIf
EndEvent
Conclusione
Sebbene questa guida non copra tutti gli scenari, fornisce una solida base per rendere la tua mod di Skyrim più accessibile e intuitiva. Ricorda, sebbene ottenere una perfetta compatibilità a metà partita possa essere impegnativo, anche piccoli passi in quella direzione possono migliorare significativamente l’esperienza per i tuoi utenti.