Saltar al contenido principal

CommandGraph

El sistema de scripting visual basado en nodos que dirige el comportamiento de NPCs y eventos: dialogos, ramas, entrega de objetos/dinero, teletransportes, combates, misiones y mas. Cada actor interactuable posee un ActorCommandGraph; el grafo se edita en el editor y se ejecuta como una corrutina en tiempo de ejecucion.

Namespace: OpenMon.MCE.Actors.CommandGraph

Se edita en el editor, se ejecuta en runtime

Normalmente construis los grafos de comandos en el editor visual (ver la guia de CommandGraph), no desde C#. La superficie de runtime de abajo es la que tocas al extender el sistema con un nodo personalizado o al ejecutar un grafo programaticamente. Los tipos de nodo (ShowDialog, GivePlayerItem, TeleportPlayer, …) son assets editados: sus campos se serializan en el inspector, no son una API para codigo.

ActorCommandGraph​

El contenedor del grafo de un actor.

[Serializable]
public class ActorCommandGraph
{
public bool IsRunning { get; }

[SerializeReference] public CommandNode RootNode;
[SerializeReference] public List<CommandNode> Nodes;

public bool IsGraphEmpty { get; }

public IEnumerator Run(CommandParameterData parameterData,
Action<bool> onLoopRunningUpdatedCallback = null);

public CommandNode CreateNode(Type type, Vector2 position = default);
public void DeleteNode(CommandNode node);
public void ConnectNodes(CommandNode parent, CommandNode child, int parentIndex);
public void RemoveConnection(CommandNode parent, CommandNode child, int parentIndex);
public List<CommandNode> GetChildren(CommandNode node);
}

IsRunning​

Si este grafo se esta ejecutando actualmente.

Tipo: bool (solo lectura)

RootNode​

El CommandNode de entrada (un RootNode) desde el que arranca la ejecucion. Serializado por referencia para que los tipos polimorficos de nodo persistan correctamente.

Tipo: CommandNode

Nodes​

Todos los nodos del grafo, incluidos los no alcanzables desde RootNode (se guardan para que el editor pueda persistir nodos huerfanos/desconectados).

Tipo: List<CommandNode>

IsGraphEmpty​

true cuando no hay nodo raiz o la raiz no tiene hijos.

Tipo: bool (solo lectura)

Run(CommandParameterData parameterData, Action<bool> onLoopRunningUpdatedCallback = null)​

Ejecuta el grafo. Pone IsRunning, luego corre RootNode.RunCommandAndContinue, hilando un CommandParameterData de contexto por cada nodo.

Devuelve: IEnumerator — cedelo (yield) desde una corrutina.

CreateNode(Type type, Vector2 position = default) / DeleteNode / ConnectNodes / RemoveConnection​

Mutacion del grafo para el editor: instanciar un nodo de una subclase de CommandNode, eliminarlo, y conectar/desconectar relaciones padre→hijo por indice de puerto de salida.

CommandNode​

La clase base abstracta de la que deriva cada tipo de nodo.

[Serializable]
public abstract class CommandNode : MonsterDatabaseData<CommandNode>
{
public bool IsRunning { get; }
public string name;
public string GUID;
public Vector2 Position;
public Action OnPortsUpdated;

public virtual IEnumerator RunCommandAndContinue(CommandParameterData parameterData);

protected abstract IEnumerator Run(CommandParameterData parameterData,
Action<CommandParameterData> callback);

public abstract List<string> GetInputPorts();
public abstract List<string> GetOutputPorts();
public abstract void AddChild(CommandNode child, int index);
public abstract void RemoveChild(CommandNode child, int index);
public abstract List<CommandNode> GetChildren();
public abstract List<CommandNode> GetIndexedChildren();
}

RunCommandAndContinue(CommandParameterData parameterData)​

Ejecuta este nodo (via el Run abstracto) y luego continua hacia sus hijos. Maneja el bloqueo por bucle cuando el grafo corre en loop.

Run(CommandParameterData parameterData, Action<CommandParameterData> callback)​

protected abstract — el trabajo real del nodo. Sobrescribilo en un nodo propio. Llama a callback con los datos de parametros (posiblemente modificados) al terminar.

GetInputPorts() / GetOutputPorts()​

Los puertos de entrada/salida con nombre que el nodo expone al grafo del editor. Un nodo lineal tiene un unico puerto sin nombre en cada lado; un nodo de rama expone una salida por rama.

Devuelve: List<string>.

SingleExecutionPathCommandNode​

La mayoria de los nodos deriva de SingleExecutionPathCommandNode, un CommandNode con exactamente un puerto de salida (NextCommand). Los nodos de rama (If…, Switch…, While…) exponen en cambio multiples puertos de salida.

public abstract class SingleExecutionPathCommandNode : CommandNode
{
public CommandNode NextCommand;
// GetOutputPorts() => un puerto sin nombre; AddChild asigna NextCommand.
}

CommandParameterData​

El contexto de ejecucion hilado por cada nodo durante una corrida: la superficie que un nodo propio lee y escribe.

public class CommandParameterData
{
public ActorCommandGraph Graph;
public GameObject Owner;
public Actor Actor;
public MCECharacterController.Direction PlayerDirection;
public PlayerCharacter PlayerCharacter;
public GlobalGameData GlobalGameData;
public MCESettings MCESettings;
public MonsterDatabaseInstance MonsterDatabase;
public IBattleLauncher BattleLauncher;
public ILocalizer Localizer;
public IConfigurationManager ConfigurationManager;
public IInputManager InputManager;
public PlayerTeleporter Teleporter;
public SavegameManager SavegameManager;
public MapSceneLauncher MapSceneLauncher;
public TimeManager TimeManager;
public QuestManager QuestManager;
public TradeManager TradeManager;
public bool UsingMove;
public MonsterInstance MoveUser;
public Move Move;
public bool IsRunningOnLoop;
public ICommandParameter[] ExtraParams;
public Action<CommandCallbackParams> Callback;
}

Categorias de nodos integrados​

Los nodos se agrupan por carpeta bajo Actors/CommandGraph/. Tipos representativos:

CategoriaNodos de ejemplo
DialogsShowDialog, ShowChoiceDialog, ShowSignDialog, NextDialog
ItemsGivePlayerItem, GivePlayerMoney, IfPlayerHasItem, ChooseItemDialog
MonstersGiveMonsters, HealPlayerRoster, ChooseMonsterDialog, ChangeMonsterNickname
BattlesSingleWildFight, SingleTrainerFight, DoubleWildFight, StartTowerRun
BadgesGiveBadge, IfPlayerHasBadge
DexGiveDex, RegisterMonsterAsSeen, IfDexIsComplete
QuestsStartQuest, CompleteQuest, ProgressQuestObjective, IfCompletedQuest
VariablesSetBoolVariable, SetIntVariable, IfBool, IfCondition, WhileBool
UtilsTeleportPlayer, WaitTime, AutoSaveIfEnabled, SwitchTimeOfDay
AnimationsMove, Look, LookAtPlayer, WalkToPlayer, FadeScreenToBlack
Shops / TradeBuyInShop, SellInShop, TradeSelectedMonster

Escribir un nodo personalizado​

using System;
using System.Collections;
using System.Collections.Generic;
using OpenMon.MCE.Actors.CommandGraph;

namespace MyGame.Events
{
[Serializable]
public class LogStepsTaken : SingleExecutionPathCommandNode
{
protected override IEnumerator Run(CommandParameterData parameterData,
Action<CommandParameterData> callback)
{
// Lee del contexto compartido hilado por el grafo.
uint steps = parameterData.GlobalGameData.StepsTaken;
UnityEngine.Debug.Log($"Player has taken {steps} steps.");

callback(parameterData);
yield break;
}
}
}