Skip to content

Dialog Path Loader (script.zScript)

Scott Zimmerman edited this page Feb 3, 2026 · 1 revision

Part 1: The "script.zScript" File

The script.zScript file is responsible for executing the majority of the logic in this port. The logic executed always starts with calling a "key" and comparing it against a value. If the key's value matches the value it is compared to, it will start to run the logic of that line. The takeaway is that every single line starts with a key and a value comparison.

Let's look at a very simple example. Below is the script line for when Link visits a Great Fairy and she heals him. How this line is started is not important just yet, just know that this is what this line does:

fairy:0 -> [update_objects] -> [set:link_direction:1] -> fairy_0

So let's break down what all is going on here.

  • The key fairy is started and compared to the value of 0. When a key has never been "set" before, it always starts at 0.
  • Each arrow (->) means "start" a new command. Three arrows here means three commands are ran in sequence.
  • We can assume fairy will probably always be 0 just so that this line runs every time this path is started.
  • The first command is update_objects. This simply allows objects to continue updating while a textbox is open.
  • The second command sets Link's facing direction north towards the fairy.
  • The third command is just a key. When a key is ran directly as a command, it means to find that key in the language file (dialog_eng.lng) and display the value that precedes the key. If opening the dialog language file, you will find that the key holds the text below.
fairy_0 Let's heal your wounds and get rid of all that stress... Close your eyes and relax...

Another thing to note is that a key can also use the value of another key to know if it should run the logic. By doing this, it doesn't matter what the value of the first key is, only the second key's value actually matters. Only two keys can be chained together like this. Here is an example:

bookcase:has_marin:1 -> npc_house_chest_marin
bookcase:0 -> bookcase

This is ran when Link interacts with a bookcase. Notice the first line checks if the player has_marin which is a check to see if Marin is a follower. The actual value of bookcase does not matter here, only the value of has_marin is checked of whether or not it should run the logic. If Marin is a follower, it will load the value of the key found in dialog_eng.lng and display it as a textbox. If the player does not have Marin as a follower, it will instead go to the next line. Here bookcase is most likely always 0, so it runs the normal dialog line bookcase.

Part 2: The Dialog Path Loader

This part explains how the Dialog Path Loader loads and startes a path via a key in the script file (script.zScript) and executes the actions that follow it. To begin, understanding what it means to "run a dialog" is crucial. I figure the best way to understand it is to start at the beginning. When calling the command:

Game1.GameManager.StartDialogPath("some_key")

It will do one of two things:

  • First it will try to find a corresponding key in script.zScript to start the sequence of events laid out.
  • If a key does not exist, it will check the language file for the currently selected language for the key in dialog_eng.lng where it will use the key to start a new dialog box with the value after the key.

The code to parse the script's "commands" can be found here:

ProjectZ > InGame > SaveLoad > DialogPathLoader
Dialog Path Loader Code
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using Microsoft.Xna.Framework;
using ProjectZ.InGame.Overlay;

namespace ProjectZ.InGame.SaveLoad
{
    class DialogPathLoader
    {
        public static void LoadScripts(string filePath, Dictionary<string, List<DialogPath>> dialogPaths)
        {
            var reader = new StreamReader(filePath);

            // go from line to line
            while (!reader.EndOfStream)
            {
                var strLine = reader.ReadLine().Replace(" ", "");

                // ignore comment
                if (strLine.Length == 0 || strLine.StartsWith("//"))
                    continue;

                var split = strLine.Split(new[] { "->" }, StringSplitOptions.None);

                if (split.Length <= 1) continue;

                var splitKey = split[0].Split(':');

                DialogPath newPath;
                if (splitKey.Length == 2)
                    newPath = new DialogPath(splitKey[0], splitKey[1]);
                else
                    newPath = new DialogPath(splitKey[1], splitKey[2]);

                for (var i = 1; i < split.Length; i++)
                    AddAction(newPath, split[i], splitKey[0]);

                // create dictionary entry or create one
                if (dialogPaths.ContainsKey(splitKey[0]))
                    dialogPaths[splitKey[0]].Add(newPath);
                else
                    dialogPaths.Add(splitKey[0], new List<DialogPath> { newPath });
            }

            reader.Close();
        }

        private static void AddAction(DialogPath path, string split, string key)
        {
            if (!split.Contains('[') && split.Length > 0)
            {
                path.Action.Add(new DialogActionStartDialog(split));
                return;
            }

            var action = split.Replace("[", "").Replace("]", "");
            var stringSplit = action.Split(':');

            if (stringSplit[0] == "path")
            {
                path.Action.Add(new DialogActionStartPath(stringSplit[1]));
            }
            else if (stringSplit[0] == "wait")
            {
                path.Action.Add(new DialogActionWait(stringSplit[1], stringSplit[2]));
            }
            else if (stringSplit[0] == "countdown")
            {
                var time = int.Parse(stringSplit[1]);
                path.Action.Add(new DialogActionCountdown(time));
            }
            else if (stringSplit[0] == "update_objects")
            {
                path.Action.Add(new DialogActionUpdateObjects());
            }
            else if (stringSplit[0] == "freeze" && stringSplit.Length == 2)
            {
                path.Action.Add(new DialogActionFreezePlayerTime(int.Parse(stringSplit[1])));
            }
            else if (stringSplit[0] == "freeze" && stringSplit.Length == 3)
            {
                path.Action.Add(new DialogActionFreezePlayer(stringSplit[1], stringSplit[2]));
            }
            else if (stringSplit[0] == "freeze_skippable")
            {
                path.Action.Add(new DialogActionFreezePlayerSkippable(int.Parse(stringSplit[1])));
            }
            else if (stringSplit[0] == "lock_player" && stringSplit.Length == 2)
            {
                path.Action.Add(new DialogActionLockPlayerTime(int.Parse(stringSplit[1])));
            }
            else if (stringSplit[0] == "lock_player" && stringSplit.Length == 3)
            {
                path.Action.Add(new DialogActionLockPlayer(stringSplit[1], stringSplit[2]));
            }
            else if (stringSplit[0] == "shake" && stringSplit.Length == 6)
            {
                path.Action.Add(new DialogActionShake(
                    int.Parse(stringSplit[1]), int.Parse(stringSplit[2]), int.Parse(stringSplit[3]),
                    float.Parse(stringSplit[4], CultureInfo.InvariantCulture),
                    float.Parse(stringSplit[5], CultureInfo.InvariantCulture)));
            }
            else if (stringSplit[0] == "set")
            {
                if (stringSplit.Length == 2)
                    path.Action.Add(new DialogActionSetVariable(key, stringSplit[1]));
                else
                    path.Action.Add(new DialogActionSetVariable(stringSplit[1], stringSplit[2]));
            }
            else if (stringSplit[0] == "get")
            {
                path.Action.Add(new DialogActionGetVariable(stringSplit[1], stringSplit[2], stringSplit[3]));
            }
            else if (stringSplit[0] == "cloak")
            {
                path.Action.Add(new DialogActionGetCloak(stringSplit[1]));
            }
            else if (stringSplit[0] == "check_item")
            {
                var itemCount = int.Parse(stringSplit[2]);
                path.Action.Add(new DialogActionCheckItem(stringSplit[1], itemCount, stringSplit[3]));
            }
            else if (stringSplit[0] == "cooldown")
            {
                var cooldownTime = int.Parse(stringSplit[1]);
                path.Action.Add(new DialogActionCooldown(cooldownTime, stringSplit[2]));
            }
            else if (stringSplit[0] == "add_item")
            {
                var itemCount = int.Parse(stringSplit[2]);
                path.Action.Add(new DialogActionAddItem(stringSplit[1], itemCount));
            }
            else if (stringSplit[0] == "add_item_amount")
            {
                var itemCount = int.Parse(stringSplit[2]);
                path.Action.Add(new DialogActionAddItemAmount(stringSplit[1], itemCount));
            }
            else if (stringSplit[0] == "remove_item")
            {
                var itemCount = int.Parse(stringSplit[2]);
                path.Action.Add(new DialogActionRemoveItem(stringSplit[1], itemCount, stringSplit[3]));
            }
            else if (stringSplit[0] == "stop_music")
            {
                if (stringSplit.Length == 3)
                    path.Action.Add(new DialogActionStopMusicTime(int.Parse(stringSplit[1]), int.Parse(stringSplit[2])));
                else
                    path.Action.Add(new DialogActionStopMusic());
            }
            else if (stringSplit[0] == "music")
            {
                var songNr = int.Parse(stringSplit[1]);
                var priority = int.Parse(stringSplit[2]);
                path.Action.Add(new DialogActionPlayMusic(songNr, priority));
            }
            else if (stringSplit[0] == "music_speed")
            {
                path.Action.Add(new DialogActionMusicSpeed(
                    float.Parse(stringSplit[1], CultureInfo.InvariantCulture)));
            }
            else if (stringSplit[0] == "sound")
            {
                path.Action.Add(new DialogActionSoundEffect(stringSplit[1]));
            }
            else if (stringSplit[0] == "dialog")
            {
                var choices = new string[stringSplit.Length - 3];
                for (var j = 0; j < stringSplit.Length - 3; j++)
                    choices[j] = stringSplit[j + 3];
                path.Action.Add(new DialogActionDialog(stringSplit[1], stringSplit[2], choices));
            }
            else if (stringSplit[0] == "dialog_close")
            {
                path.Action.Add(new DialogActionClose());
            }
            else if (stringSplit[0] == "buy")
            {
                path.Action.Add(new DialogActionBuyItem(stringSplit[1]));
            }
            else if (stringSplit[0] == "open_book")
            {
                path.Action.Add(new DialogActionOpenBook());
            }
            else if (stringSplit[0] == "start_sequence")
            {
                path.Action.Add(new DialogActionStartSequence(stringSplit[1]));
            }
            else if (stringSplit[0] == "seq_set_position")
            {
                var posX = int.Parse(stringSplit[2]);
                var posY = int.Parse(stringSplit[3]);
                path.Action.Add(new DialogActionSeqSetPosition(stringSplit[1], new Vector2(posX, posY)));
            }
            else if (stringSplit[0] == "seq_lerp")
            {
                var posX = int.Parse(stringSplit[2]);
                var posY = int.Parse(stringSplit[3]);
                var time = float.Parse(stringSplit[4], CultureInfo.InvariantCulture);
                path.Action.Add(new DialogActionSeqLerp(stringSplit[1], new Vector2(posX, posY), time));
            }
            else if (stringSplit[0] == "seq_color")
            {
                var colorR = byte.Parse(stringSplit[2]);
                var colorG = byte.Parse(stringSplit[3]);
                var colorB = byte.Parse(stringSplit[4]);
                var colorA = byte.Parse(stringSplit[5]);
                var time = int.Parse(stringSplit[6]);
                path.Action.Add(new DialogActionSeqColorLerp(stringSplit[1], new Color(colorR, colorG, colorB, colorA), time));
            }
            else if (stringSplit[0] == "seq_play")
            {
                path.Action.Add(new DialogActionSeqPlay(stringSplit[1], stringSplit[2]));
            }
            else if (stringSplit[0] == "seq_finish_animation")
            {
                var stopFrameIndex = int.Parse(stringSplit[2]);
                path.Action.Add(new DialogActionFinishAnimation(stringSplit[1], stopFrameIndex));
            }
            else if (stringSplit[0] == "close_overlay")
            {
                path.Action.Add(new DialogActionCloseOverlay());
            }
            else if (stringSplit[0] == "fill_hearts")
            {
                path.Action.Add(new DialogActionFillHearts());
            }
            else if (stringSplit[0] == "spawn")
            {
                path.Action.Add(new DialogActionSpawnObject(key, stringSplit[1], stringSplit[2]));
            }
            else if (stringSplit[0] == "map_transition")
            {
                path.Action.Add(new DialogActionChangeMap(stringSplit[1], stringSplit[2]));
            }
            else if (stringSplit[0] == "save_history")
            {
                path.Action.Add(new DialogActionSaveHistory(bool.Parse(stringSplit[1])));
            }
            else if (stringSplit[0] == "disable_inventory")
            {
                path.Action.Add(new DialogDisableInventory(bool.Parse(stringSplit[1])));
            }
        }
    }
}

This is where all the commands in script.zScript are translated into "functions" and can be found here:

ProjectZ > InGame > Overlay > DialogPath
Dialog Path Functions
using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.Xna.Framework;
using ProjectZ.InGame.Controls;
using ProjectZ.InGame.GameObjects.Things;
using ProjectZ.InGame.GameSystems;
using ProjectZ.InGame.Map;
using ProjectZ.InGame.SaveLoad;
using ProjectZ.InGame.Things;

namespace ProjectZ.InGame.Overlay
{
    class DialogAction
    {
        public virtual void Init() { }

        public virtual bool Execute()
        {
            return true;
        }
    }

    class DialogActionStartDialog : DialogAction
    {
        private readonly string _key;

        public DialogActionStartDialog(string key)
        {
            _key = key;
        }

        public override bool Execute()
        {
            if (Game1.GameManager.InGameOverlay.TextboxOverlay.IsOpen)
                return false;

            string _setKey = Game1.LanguageManager.CurrentSubLanguageIndex switch
            {
                1 => _key + "_mod",
                2 => _key + "_alt",
                _ => _key
            };
            string testString = Game1.LanguageManager.GetString(_setKey, "noKey");

            if (testString == "noKey")
                Game1.GameManager.StartDialog(_key);
            else
                Game1.GameManager.StartDialog(_setKey);

            return true;
        }
    }

    class DialogActionStartPath : DialogAction
    {
        private readonly string _key;

        public DialogActionStartPath(string key)
        {
            _key = key;
        }

        public override bool Execute()
        {
            if (Game1.GameManager.InGameOverlay.TextboxOverlay.IsOpen)
                return false;

            // add the dialog path as the first element to be executed directly after this dialog
            Game1.GameManager.AddFirstDialogPath(_key);
            return true;
        }
    }

    class DialogActionDialog : DialogAction
    {
        private readonly string _key;
        private readonly string _choiceKey;
        private readonly string[] _choicesKeys;

        public DialogActionDialog(string key, string choiceKey, params string[] choices)
        {
            _key = key;
            _choiceKey = choiceKey;
            _choicesKeys = choices;
        }

        public override bool Execute()
        {
            var choiceHeader = Game1.LanguageManager.GetString(_choiceKey, "error");

            var choices = new string[_choicesKeys.Length];
            for (var i = 0; i < _choicesKeys.Length; i++)
                choices[i] = Game1.LanguageManager.GetString(_choicesKeys[i], "error");

            if (Game1.GameManager.InGameOverlay.TextboxOverlay.IsOpen)
                return false;

            Game1.GameManager.InGameOverlay.TextboxOverlay.StartChoice(_key, choiceHeader, choices);
            return true;
        }
    }

    class DialogActionClose : DialogAction 
    {
        public DialogActionClose() { }

        public override bool Execute() 
        {
            Game1.GameManager.InGameOverlay.TextboxOverlay.IsOpen = false;
            return true;
        }
    }

    class DialogActionSetVariable : DialogAction
    {
        private readonly string _key;
        private readonly string _value;

        public DialogActionSetVariable(string key, string value)
        {
            _key = key;
            _value = value;
        }

        public override bool Execute()
        {
            if (_value == "backupname")
                Game1.GameManager.ThiefState = false;
            else
                Game1.GameManager.SaveManager.SetString(_key, _value);
            return true;
        }
    }

    class DialogActionGetVariable : DialogAction
    {
        private readonly string _key;
        private readonly string _compare;
        private readonly string _resultKey;

        public DialogActionGetVariable(string key, string compare, string resultKey)
        {
            _key = key;
            _compare = compare;
            _resultKey = resultKey;
        }
        
        public override bool Execute()
        {
            bool checkState = false;

            // Determine if it's a boolean by checking the compare values.
            if (_compare == "true" || _compare == "false") 
            {
                bool saveState = (bool)(typeof(GameSettings).GetField(_key, BindingFlags.Public | BindingFlags.Static).GetValue(null));
                checkState = Convert.ToBoolean(_compare) == Game1.GameManager.SaveManager.GetBool(_key, saveState);
            }
            // Otherwise assume we are getting the value of a string field.
            else
            {
                checkState = _key == "savename"
                    ? Game1.GameManager.ThiefState
                    : Game1.GameManager.SaveManager.GetString(_key, "") == _compare;
            }
            Game1.GameManager.SaveManager.SetString(_resultKey, checkState ? "1" : "0");
            return true;
        }
    }

    class DialogActionGetCloak : DialogAction
    {
        private readonly string _compare;

        public DialogActionGetCloak(string compare)
        {
            _compare = compare;
        }
        public override bool Execute()
        {
            Game1.GameManager.SaveManager.SetString(_compare, Game1.GameManager.CloakType.ToString());
            return true;
        }
    }

    class DialogActionUpdateObjects : DialogAction
    {
        public override bool Execute()
        {
            Game1.GameManager.InGameOverlay.TextboxOverlay.UpdateObjects = true;
            return true;
        }
    }

    class DialogActionWait : DialogAction
    {
        private readonly string _key;
        private readonly string _value;

        public DialogActionWait(string key, string value)
        {
            _key = key;
            _value = value;
        }
        public override bool Execute()
        {
            return Game1.GameManager.SaveManager.GetString(_key) == _value;
        }
    }

    /// <summary>
    /// DialogAction used to stop the dialog path for a certain amount of time.
    /// </summary>
    class DialogActionCountdown : DialogAction
    {
        private readonly float Time;
        private float _counter;

        public DialogActionCountdown(float time)
        {
            Time = time;
        }
        public override void Init()
        {
            _counter = Time;
        }
        public override bool Execute()
        {
            _counter -= Game1.DeltaTime;
            return _counter <= 0;
        }
    }

    class DialogActionFreezePlayer : DialogAction
    {
        private readonly string _key;
        private readonly string _value;

        public DialogActionFreezePlayer(string key, string value)
        {
            _key = key;
            _value = value;
        }
        public override bool Execute()
        {
            MapManager.ObjLink.FreezePlayer();
            return Game1.GameManager.SaveManager.GetString(_key) == _value;
        }
    }

    class DialogActionFreezePlayerTime : DialogAction
    {
        private float _counter;
        private readonly float _time;

        public DialogActionFreezePlayerTime(int time)
        {
            _time = time;
        }
        public override void Init()
        {
            _counter = _time;
        }
        public override bool Execute()
        {
            // freeze the player while the time is running
            var finished = _counter <= 0;
            _counter -= Game1.DeltaTime;

            MapManager.ObjLink.FreezePlayer();

            return finished;
        }
    }

    class DialogActionLockPlayerTime : DialogAction
    {
        private float _counter;
        private readonly float _time;

        public DialogActionLockPlayerTime(int time)
        {
            _time = time;
        }
        public override void Init()
        {
            _counter = _time;
        }
        public override bool Execute()
        {
            var finished = _counter <= 0;
            _counter -= Game1.DeltaTime;
            MapManager.ObjLink.SeqLockPlayer();
            return finished;
        }
    }

    class DialogActionFreezePlayerSkippable : DialogAction
    {
        private float _counter;
        private readonly float _time;

        public DialogActionFreezePlayerSkippable(int time)
        {
            _time = time;
        }
        public override void Init()
        {
            _counter = _time;
        }
        public override bool Execute()
        {
            var finished = _counter <= 0;
            _counter -= Game1.DeltaTime;

            if (ControlHandler.ButtonPressed(CButtons.Start))
                return true;

            MapManager.ObjLink.FreezePlayer();
            return finished;
        }
    }

    /// <summary>
    /// Lock the player as long as the key is not yet set to the value
    /// </summary>
    class DialogActionLockPlayer : DialogAction
    {
        private string _key;
        private string _value;

        public DialogActionLockPlayer(string key, string value)
        {
            _key = key;
            _value = value;
        }
        public override bool Execute()
        {
            MapManager.ObjLink.SeqLockPlayer();
            return Game1.GameManager.SaveManager.GetString(_key) == _value;
        }
    }

    class DialogActionShake : DialogAction
    {
        private readonly int _time;
        private readonly int _maxX;
        private readonly int _maxY;
        private readonly float _shakeSpeedX;
        private readonly float _shakeSpeedY;

        public DialogActionShake(int time, int maxX, int maxY, float shakeSpeedX, float shakeSpeedY)
        {
            _time = time;
            _maxX = maxX;
            _maxY = maxY;
            _shakeSpeedX = shakeSpeedX;
            _shakeSpeedY = shakeSpeedY;
        }
        public override bool Execute()
        {
            if (GameSettings.ScreenShake)
                Game1.GameManager.ShakeScreen(_time, _maxX, _maxY, _shakeSpeedX, _shakeSpeedY);
            return true;
        }
    }

    class DialogActionStopMusic : DialogAction
    {
        public override bool Execute()
        {
            Game1.GbsPlayer.Stop();
            return true;
        }
    }

    class DialogActionStopMusicTime : DialogAction
    {
        private readonly int _time;
        private readonly int _priority;

        public DialogActionStopMusicTime(int time, int priority)
        {
            _time = time;
            _priority = priority;
        }
        public override bool Execute()
        {
            Game1.GameManager.StopMusic(_time, _priority);
            return true;
        }
    }

    class DialogActionPlayMusic : DialogAction
    {
        private readonly int _songNr;
        private readonly int _priority;

        public DialogActionPlayMusic(int songNr, int priority)
        {
            _songNr = songNr;
            _priority = priority;
        }
        public override bool Execute()
        {
            if (_priority < 0)
            {
                Game1.GameManager.StopMusic();
                return true;
            }
            if (MapManager.ObjLink.IsTransitioning)
                Game1.GameManager.MapManager.NextMap.MapMusic[_priority] = _songNr;
            else
            {
                Game1.GameManager.SetMusic(_songNr, _priority);
                if (_songNr >= 0)
                    Game1.GbsPlayer.Play();
            }
            return true;
        }
    }

    class DialogActionMusicSpeed : DialogAction
    {
        private readonly float _playbackSpeed;

        public DialogActionMusicSpeed(float playbackSpeed)
        {
            _playbackSpeed = playbackSpeed;
        }
        public override bool Execute()
        {
#if WINDOWS
            Game1.GbsPlayer.Cpu.SetPlaybackSpeed(_playbackSpeed);
#endif
            return true;
        }
    }

    class DialogActionSoundEffect : DialogAction
    {
        private readonly string _soundEffect;

        public DialogActionSoundEffect(string soundEffect)
        {
            _soundEffect = soundEffect;
        }
        public override bool Execute()
        {
            Game1.GameManager.PlaySoundEffect(_soundEffect);
            return true;
        }
    }

    class DialogActionCheckItem : DialogAction
    {
        private readonly string _itemName;
        private readonly string _resultKey;
        private readonly int _count;

        public DialogActionCheckItem(string itemName, int count, string resultKey)
        {
            _itemName = itemName;
            _count = count;
            _resultKey = resultKey;
        }
        public override bool Execute()
        {
            // get the item and check if enough are available
            var item = Game1.GameManager.GetItem(_itemName);
            var checkState = item != null && item.Count >= _count;

            Game1.GameManager.SaveManager.SetString(_resultKey, checkState ? "1" : "0");
            return true;
        }
    }

    class DialogActionCooldown : DialogAction
    {
        private readonly string _resultKey;
        private readonly int _cooldownTime;

        private double _lastExecutionTime;

        public DialogActionCooldown(int cooldownTime, string resultKey)
        {
            _cooldownTime = cooldownTime;
            _resultKey = resultKey;
            _lastExecutionTime = -_cooldownTime;
        }
        public override bool Execute()
        {
            // check when the last time the check was successful
            // this does not work directly after loading the save if it was running shortly after the last save loading
            if (_lastExecutionTime <= Game1.TotalGameTime && Game1.TotalGameTime < _lastExecutionTime + _cooldownTime)
            {
                Game1.GameManager.SaveManager.SetString(_resultKey, "0");
                return true;
            }

            _lastExecutionTime = Game1.TotalGameTime;

            Game1.GameManager.SaveManager.SetString(_resultKey, "1");
            return true;
        }
    }

    class DialogActionAddItem : DialogAction
    {
        private readonly string _itemName;
        private readonly int _amount;

        public DialogActionAddItem(string itemName, int amount)
        {
            _itemName = itemName;
            _amount = amount;
        }
        public override bool Execute()
        {
            if (Game1.GameManager.InGameOverlay.TextboxOverlay.IsOpen)
                return false;

            var item = new GameItemCollected(_itemName);

            // use the set amount or that from the item description
            if (_amount > 0)
                item.Count = _amount;
            else
                item.Count = Game1.GameManager.ItemManager[_itemName].Count;

            MapManager.ObjLink.PickUpItem(item, true);
            return true;
        }
    }

    class DialogActionSeqSetPosition : DialogAction
    {
        private string _animatorId;
        private Vector2 _newPosition;

        public DialogActionSeqSetPosition(string animatorId, Vector2 newPosition)
        {
            _animatorId = animatorId;
            _newPosition = newPosition;
        }
        public override bool Execute()
        {
            var gameSequence = Game1.GameManager.InGameOverlay.GetCurrentGameSequence();

            if (gameSequence == null)
                return false;

            gameSequence.SetPosition(_animatorId, _newPosition);
            return true;
        }
    }

    class DialogActionSeqLerp : DialogAction
    {
        private string _drawableId;
        private Vector2 _targetPosition;
        private float _moveSpeed;

        public DialogActionSeqLerp(string animatorId, Vector2 newPosition, float moveSpeed)
        {
            _drawableId = animatorId;
            _targetPosition = newPosition;
            _moveSpeed = moveSpeed;
        }

        public override bool Execute()
        {
            var gameSequence = Game1.GameManager.InGameOverlay.GetCurrentGameSequence();

            if (gameSequence == null)
                return false;

            gameSequence.StartPositionTransition(_drawableId, _targetPosition, _moveSpeed);
            return true;
        }
    }

    class DialogActionSeqColorLerp : DialogAction
    {
        private string _drawableId;
        private Color _targetColor;
        private int _transitionTime;

        public DialogActionSeqColorLerp(string animatorId, Color targetColor, int transitionTime)
        {
            _drawableId = animatorId;
            _targetColor = targetColor;
            _transitionTime = transitionTime;
        }

        public override bool Execute()
        {
            var gameSequence = Game1.GameManager.InGameOverlay.GetCurrentGameSequence();

            if (gameSequence == null)
                return false;

            gameSequence.StartColorTransition(_drawableId, _targetColor, _transitionTime);
            return true;
        }
    }

    class DialogActionSeqPlay : DialogAction
    {
        private string _animatorId;
        private string _animationId;

        public DialogActionSeqPlay(string animatorId, string animationId)
        {
            _animatorId = animatorId;
            _animationId = animationId;
        }

        public override bool Execute()
        {
            var gameSequence = Game1.GameManager.InGameOverlay.GetCurrentGameSequence();

            if (gameSequence == null)
                return false;

            gameSequence.PlayAnimation(_animatorId, _animationId);
            return true;
        }
    }

    class DialogActionFinishAnimation : DialogAction
    {
        private string _animatorId;
        private int _stopFrameIndex;

        public DialogActionFinishAnimation(string animatorId, int stopFrameIndex)
        {
            _animatorId = animatorId;
            _stopFrameIndex = stopFrameIndex;
        }

        public override bool Execute()
        {
            var gameSequence = Game1.GameManager.InGameOverlay.GetCurrentGameSequence();

            if (gameSequence == null)
                return false;

            gameSequence.FinishAnimation(_animatorId, _stopFrameIndex);
            return true;
        }
    }

    /// <summary>
    /// Only add an amount to an existing item
    /// </summary>
    class DialogActionAddItemAmount : DialogAction
    {
        private readonly string _itemName;
        private readonly int _amount;

        public DialogActionAddItemAmount(string itemName, int amount)
        {
            _itemName = itemName;
            _amount = amount;
        }

        public override bool Execute()
        {
            if (Game1.GameManager.InGameOverlay.TextboxOverlay.IsOpen)
                return false;

            if (Game1.GameManager.GetItem(_itemName) == null)
                return true;

            var item = new GameItemCollected(_itemName);
            if (_amount > 0)
                item.Count = _amount;

            MapManager.ObjLink.PickUpItem(item, false, false, false);
            return true;
        }
    }

    class DialogActionRemoveItem : DialogAction
    {
        private readonly string _itemName;
        private readonly string _resultKey;
        private readonly int _count;

        public DialogActionRemoveItem(string itemName, int count, string resultKey)
        {
            _itemName = itemName;
            _count = count;
            _resultKey = resultKey;
        }

        public override bool Execute()
        {
            // remove the item if possible
            if (Game1.GameManager.RemoveItem(_itemName, _count))
                Game1.GameManager.SaveManager.SetString(_resultKey, "1");
            else
                Game1.GameManager.SaveManager.SetString(_resultKey, "0");

            return true;
        }
    }

    class DialogActionBuyItem : DialogAction
    {
        private readonly string _key;

        public DialogActionBuyItem(string key)
        {
            _key = key;
        }

        public override bool Execute()
        {
            var itemName = Game1.GameManager.SaveManager.GetString("itemShopItem");
            var itemPriceString = Game1.GameManager.SaveManager.GetString("itemShopPrice");
            var itemPrice = int.Parse(itemPriceString);
            var itemCountString = Game1.GameManager.SaveManager.GetString("itemShopCount");
            var itemCount = int.Parse(itemCountString);

            var baseItem = Game1.GameManager.ItemManager[itemName];
            var buyItem = Game1.GameManager.GetItem(baseItem.Name);
            var rubyItem = Game1.GameManager.GetItem("ruby");

            var ownedCount = 0;
            var maxCount = 99;

            // check if the player has the mirror shield
            if (itemName == "arrow")
                buyItem = Game1.GameManager.GetItem("bow");
            if (itemName == "shield" && buyItem == null)
                buyItem = Game1.GameManager.GetItem("mirrorShield");

            if (itemName == "heart")
            {
                ownedCount = Game1.GameManager.CurrentHealth;
                maxCount = Game1.GameManager.MaxHearts * 4;
            }
            else if (buyItem != null)
            {
                ownedCount = buyItem.Count;
                maxCount = Game1.GameManager.ItemManager[buyItem.Name].MaxCount;
            }

            if (buyItem != null && buyItem.Name == "powder" && Game1.GameManager.SaveManager.GetString("upgradePowder") == "1")
                maxCount += 20;
            if (buyItem != null && buyItem.Name == "bomb" && Game1.GameManager.SaveManager.GetString("upgradeBomb") == "1")
                maxCount += 30;
            if (buyItem != null && buyItem.Name == "bow" && Game1.GameManager.SaveManager.GetString("upgradeBow") == "1")
                maxCount += 30;

            // does the player already own the item?
            if (ownedCount >= maxCount)
            {
                Game1.GameManager.SaveManager.SetString(_key, "2");
            }
            // does the player have enough money to buy this item?
            else if (rubyItem != null && rubyItem.Count >= itemPrice)
            {
                var item = new GameItemCollected(itemName);
                item.Count = itemCount;

                // gets picked up
                MapManager.ObjLink.PickUpItem(item, false);

                rubyItem.Count -= itemPrice;

                Game1.GameManager.SaveManager.SetString(_key, "0");
            }
            // player does not have enough money
            else
            {
                Game1.GameManager.SaveManager.SetString(_key, "1");
            }

            return true;
        }
    }

    class DialogActionOpenBook : DialogAction
    {
        public override bool Execute()
        {
            Game1.GameManager.InGameOverlay.OpenPhotoOverlay();
            return true;
        }
    }

    class DialogActionStartSequence : DialogAction
    {
        private readonly string _sequenceName;

        public DialogActionStartSequence(string sequenceName)
        {
            _sequenceName = sequenceName;
        }

        public override bool Execute()
        {
            Game1.GameManager.InGameOverlay.StartSequence(_sequenceName);
            return true;
        }
    }

    class DialogActionCloseOverlay : DialogAction
    {
        public DialogActionCloseOverlay() { }

        public override bool Execute()
        {
            Game1.GameManager.InGameOverlay.CloseOverlay();
            return true;
        }
    }

    class DialogActionFillHearts : DialogAction
    {
        public DialogActionFillHearts() { }

        public override bool Execute()
        {
            var fullHearts = Game1.GameManager.CurrentHealth >= Game1.GameManager.MaxHearts * 4;
            Game1.GameManager.SaveManager.SetString("fullHearts", fullHearts ? "1" : "0");
            Game1.GameManager.HealPlayer(99);
            ItemDrawHelper.EnableHeartAnimationSound();
            return true;
        }
    }

    class DialogActionSpawnObject : DialogAction
    {
        private readonly string _positionKey;
        private readonly string _objectId;
        private readonly string _strParameter;

        public DialogActionSpawnObject(string positionKey, string objectId, string strParameter)
        {
            _positionKey = positionKey;
            _objectId = objectId;
            _strParameter = strParameter;
        }

        public override bool Execute()
        {
            // @HACK: this is not really a good way and could lead to problems
            // a better way would probably be a way to pass parameters into a dialog path so that the actions could read them

            // @HACK: some parameters need the '.' character
            var parameters = _strParameter.Split('.');
            for (var i = 0; i < parameters.Length; i++)
                parameters[i] = parameters[i].Replace("$", ".");

            var objectParameter = MapData.GetParameter(_objectId, parameters);
            objectParameter[0] = ObjPositionDialog.CurrentMap;
            objectParameter[1] = Game1.GameManager.SaveManager.GetInt(_positionKey + "posX");
            objectParameter[2] = Game1.GameManager.SaveManager.GetInt(_positionKey + "posY");

            ObjPositionDialog.CurrentMap.Objects.SpawnObject(_objectId, objectParameter);

            return true;
        }
    }

    class DialogActionChangeMap : DialogAction
    {
        private readonly string _mapName;
        private readonly string _entryName;

        public DialogActionChangeMap(string mapName, string entryName)
        {
            _mapName = mapName;
            _entryName = entryName;
        }

        public override bool Execute()
        {
            var transitionSystem = (MapTransitionSystem)Game1.GameManager.GameSystems[typeof(MapTransitionSystem)];
            transitionSystem.AppendMapChange(_mapName, _entryName, false, false, Color.White, true);
            transitionSystem.SetColorMode(Color.White, 1);

            MapManager.ObjLink.MapTransitionStart = MapManager.ObjLink.EntityPosition.Position;
            MapManager.ObjLink.MapTransitionEnd = MapManager.ObjLink.EntityPosition.Position;
            MapManager.ObjLink.TransitionOutWalking = false;

            return true;
        }
    }

    class DialogActionSaveHistory : DialogAction
    {
        private readonly bool _enable;

        public DialogActionSaveHistory(bool enable)
        {
            _enable = enable;
        }

        public override bool Execute()
        {
            if (_enable && !Game1.GameManager.SaveManager.HistoryEnabled)
            {
                SaveGameSaveLoad.FillSaveState(Game1.GameManager);
                Game1.GameManager.SaveManager.EnableHistory();
            }
            // the history will be cleared by the player
            else if (!_enable && !MapManager.ObjLink.SavePreItemPickup)
            {
                SaveGameSaveLoad.ClearSaveState();
                Game1.GameManager.SaveManager.DisableHistory();
            }

            return true;
        }
    }
    class DialogDisableInventory : DialogAction
    {
        private bool _enable;

        public DialogDisableInventory(bool enable)
        {
            _enable = enable;
        }

        public override bool Execute()
        {
            var enable = Convert.ToInt32(_enable).ToString();
            Game1.GameManager.SaveManager.SetString("disable_inventory", enable);
            return true;
        }
    }

    class DialogPath
    {
        public string VariableKey;
        public string Condition;

        public List<DialogAction> Action = new List<DialogAction>();

        public DialogPath(string variableKey, string condition)
        {
            VariableKey = variableKey;
            Condition = condition;
        }

        public DialogPath(string variableKey)
        {
            VariableKey = variableKey;
        }
    }
}

πŸ“š Documentation Index

🏠 Home

βš™οΈ Engine Reference

πŸ›οΈ File & Data Reference

🎧 Audio Reference

πŸ’Ύ Modification

Clone this wiki locally