init new repos
This commit is contained in:
807
Assets/Code/ScriptVM.cs
Normal file
807
Assets/Code/ScriptVM.cs
Normal file
@@ -0,0 +1,807 @@
|
||||
using NUnit.Framework.Internal;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
public class ScriptVM : MonoBehaviour
|
||||
{
|
||||
private Script _currentScript;
|
||||
private ExecutionContext _mainContext;
|
||||
private Dictionary<int, ExecutionContext> _activeSubroutines = new Dictionary<int, ExecutionContext>();
|
||||
private Dictionary<int, GameObject> _modelTempRegistry = new Dictionary<int, GameObject>();
|
||||
private Dictionary<int, GameObject> _objectRegistry = new Dictionary<int, GameObject>();
|
||||
|
||||
private int selectionVariable;
|
||||
|
||||
// Jump Table <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
private Dictionary<uint, Action<ExecutionContext, ScriptCommand>> _opCodeHandlers;
|
||||
|
||||
public bool IsRunning => _mainContext != null && !_mainContext.IsFinished;
|
||||
|
||||
//SCRIPT LOGGING
|
||||
void OnGUI()
|
||||
{
|
||||
GUILayout.BeginArea(new Rect(10, 10, 400, 600));
|
||||
|
||||
if (_mainContext != null)
|
||||
{
|
||||
GUILayout.Label($"MAIN: PC={_mainContext.ProgramCounter:X4} CMD=0x{GetCurrentCommand(_mainContext)?.OpCode:X4}");
|
||||
GUILayout.Label($"Status: {(IsRunning ? "Running" : "Stopped")}");
|
||||
GUILayout.Label($"Paused: {(_mainContext.IsPaused ? "+" : "-")} RemSec: -{_mainContext.PauseTimeRemaining}");
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
var currentCmd = GetCurrentCommand(_mainContext);
|
||||
if (currentCmd != null)
|
||||
{
|
||||
GUILayout.Label($"Params: {string.Join(", ", currentCmd.Params)}");
|
||||
}
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
GUILayout.Label($"Subroutines: {_activeSubroutines.Count}");
|
||||
foreach (var kvp in _activeSubroutines)
|
||||
{
|
||||
var context = kvp.Value;
|
||||
GUILayout.Label($"SUB[{kvp.Key:X2}] {context.ContextName}: PC={context.ProgramCounter:X4} CMD=0x{GetCurrentCommand(context)?.OpCode:X4}");
|
||||
GUILayout.Label($" Paused: {(context.IsPaused ? "+" : "-")} RemSec: -{context.PauseTimeRemaining}");
|
||||
}
|
||||
|
||||
GUILayout.EndArea();
|
||||
}
|
||||
|
||||
void Awake()
|
||||
{
|
||||
InitializeJumpTable();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (_mainContext == null) return;
|
||||
|
||||
if (_mainContext.IsPaused && _mainContext.PauseTimeRemaining > 0)
|
||||
{
|
||||
_mainContext.PauseTimeRemaining -= Time.deltaTime;
|
||||
if (_mainContext.PauseTimeRemaining <= 0)
|
||||
{
|
||||
_mainContext.PauseTimeRemaining = 0;
|
||||
_mainContext.IsPaused = false;
|
||||
_mainContext.ProgramCounter++;
|
||||
MarkCurrentCommandCompleted(_mainContext); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
}
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if (!_mainContext.IsWaiting && !_mainContext.IsPaused)
|
||||
{
|
||||
ExecuteStep(_mainContext);
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
foreach (var context in _activeSubroutines.Values)
|
||||
{
|
||||
if (context.IsPaused && context.PauseTimeRemaining > 0)
|
||||
{
|
||||
context.PauseTimeRemaining -= Time.deltaTime;
|
||||
if (context.PauseTimeRemaining <= 0)
|
||||
{
|
||||
context.PauseTimeRemaining = 0;
|
||||
context.IsPaused = false;
|
||||
context.ProgramCounter++;
|
||||
MarkCurrentCommandCompleted(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
foreach (var context in _activeSubroutines.Values)
|
||||
{
|
||||
if (!context.IsWaiting && !context.IsPaused)
|
||||
{
|
||||
ExecuteStep(context);
|
||||
}
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
_activeSubroutines = _activeSubroutines.Where(kvp => !kvp.Value.IsFinished).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||
}
|
||||
|
||||
public void LoadAndRunScript(Script script)
|
||||
{
|
||||
_currentScript = script;
|
||||
_mainContext = new ExecutionContext(0, "MAIN", null);
|
||||
_activeSubroutines.Clear();
|
||||
_objectRegistry.Clear();
|
||||
|
||||
Debug.Log($"Script loaded with {script.Commands.Count} commands");
|
||||
}
|
||||
|
||||
public void StartSubroutine(ushort subId)
|
||||
{
|
||||
if (_currentScript != null && _currentScript.SubroutineTable.TryGetValue(subId, out Subroutine sub))
|
||||
{
|
||||
var newContext = new ExecutionContext(sub.Address, sub.Name, new ScriptCommand {OpCode = 999});
|
||||
_activeSubroutines[subId] = newContext;
|
||||
Debug.Log($"Started independent subroutine {subId} at address {sub.Address:X4}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Cannot start subroutine {subId}: script not loaded or subroutine not found");
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsCommandCompleted(uint commandId)
|
||||
{
|
||||
if (commandId < _currentScript.Commands.Count)
|
||||
{
|
||||
return _currentScript.Commands[(int)commandId].executedStatus == 3;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// WaitTo - stops thread and check command status at address
|
||||
private void Handle_WaitTo(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
uint targetCommandId = (uint)GetParam(cmd, 0);
|
||||
|
||||
if (IsCommandCompleted(targetCommandId))
|
||||
{
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void ExecuteStep(ExecutionContext context)
|
||||
{
|
||||
if (context.ProgramCounter >= _currentScript.Commands.Count)
|
||||
{
|
||||
context.IsFinished = true;
|
||||
if (context == _mainContext) Debug.Log("Main script finished");
|
||||
return;
|
||||
}
|
||||
|
||||
ScriptCommand cmd = _currentScript.Commands[(int)context.ProgramCounter];
|
||||
cmd.executedStatus = 0; //cleaning status for command restart and proper wait
|
||||
if (_opCodeHandlers.TryGetValue(cmd.OpCode, out var handler))
|
||||
{
|
||||
try
|
||||
{
|
||||
handler(context, cmd);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"Error executing command 0x{cmd.OpCode:X8}: {ex.Message}");
|
||||
// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
cmd.executedStatus = 3;
|
||||
context.ProgramCounter++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Unknown OpCode: 0x{cmd.OpCode:X8} at PC={context.ProgramCounter:X4}");
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
cmd.executedStatus = 3;
|
||||
context.ProgramCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeJumpTable()
|
||||
{
|
||||
_opCodeHandlers = new Dictionary<uint, Action<ExecutionContext, ScriptCommand>>
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{ 0x00000007, Handle_JumpTo },
|
||||
{ 0x00000001, Handle_If1Go },
|
||||
{ 0x00000002, Handle_If0Go },
|
||||
{ 0x00000004, Handle_IfNotEqualGo },
|
||||
{ 0x0000000D, Handle_GoSub },
|
||||
{ 0x0000000E, Handle_Return },
|
||||
{ 0x00000012, Handle_WaitTo },
|
||||
|
||||
{ 0x0000001A, Handle_GetInput },
|
||||
|
||||
{ 0x0000002C, Handle_SetCamXY }, // Set Camera
|
||||
|
||||
//Characters commands
|
||||
{ 0x00000030, Handle_CharLoad }, // CharLoad
|
||||
{ 0x00000031, Handle_CharInit }, // CharInit
|
||||
{ 0x000000D0, Handle_CharInit }, // Another CharInit???
|
||||
{ 0x00000034, Handle_CharMoveTo }, // CanWait
|
||||
{ 0x00000037, Handle_CharAnimate }, // CanWait
|
||||
{ 0x00000038, Handle_CharAnimate2 }, // CanWait
|
||||
|
||||
{ 0x00000041, Handle_PlayerInit }, // Create player char at camera set
|
||||
|
||||
{ 0x000000D2, Handle_CharGlowShow }, // CharInitWithGlow
|
||||
|
||||
{ 0x0000003E, Handle_WaitCharAnimEnd }, // Wait by char id
|
||||
|
||||
{ 0x00000046, Handle_CharSetSubroutine }, // Set blockcharacter subroutine
|
||||
|
||||
|
||||
//Pause
|
||||
{ 0x0000005C, Handle_PausInit }, // PausInit
|
||||
{ 0x0000005D, Handle_PauseFr }, // PauseFr_
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{ 0x00000008, Handle_SetTemp },
|
||||
{ 0x00000009, Handle_CopyVar },
|
||||
{ 0x00000060, Handle_GetVar },
|
||||
{ 0x0000005E, Handle_VarTrue },
|
||||
{ 0x0000005F, Handle_VarFlse },
|
||||
{ 0x00000073, Handle_VarDec },
|
||||
{ 0x00000074, Handle_VarSet },
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{ 0x00000043, Handle_CtrlLock },
|
||||
{ 0x00000044, Handle_CtrUnlck },
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{ 0x00000051, Handle_DungLoad },
|
||||
{ 0x00000052, Handle_EventLoad },
|
||||
{ 0x00000053, Handle_CityLoad },
|
||||
{ 0x000000ED, Handle_BattleLoad },
|
||||
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD>
|
||||
{ 0x00000059, Handle_VideoPly },
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{ 0x00000092, Handle_ScrnFade },
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
{ 0x00000024, Handle_WindOpen },
|
||||
{ 0x00000013, Handle_TextShow },
|
||||
{ 0x00000025, Handle_WindClose }
|
||||
};
|
||||
}
|
||||
|
||||
// ========== <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ==========
|
||||
|
||||
private void Handle_JumpTo(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
uint jumpAddress = (uint)GetParam(cmd, 0);
|
||||
ctx.ProgramCounter = jumpAddress;
|
||||
cmd.executedStatus = 3; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
}
|
||||
|
||||
private void Handle_If1Go(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int varAddress = GetParam(cmd, 0);
|
||||
uint jumpAddress = (uint)GetParam(cmd, 1);
|
||||
|
||||
if (GetLocalVariable(ctx, varAddress) == 1)
|
||||
ctx.ProgramCounter = jumpAddress;
|
||||
else
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_If0Go(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int varAddress = GetParam(cmd, 0);
|
||||
uint jumpAddress = (uint)GetParam(cmd, 1);
|
||||
|
||||
if (GetLocalVariable(ctx, varAddress) == 0)
|
||||
ctx.ProgramCounter = jumpAddress;
|
||||
else
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_IfNotEqualGo(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int varAddress = GetParam(cmd, 0);
|
||||
int compareValue = GetParam(cmd, 1);
|
||||
uint jumpAddress = (uint)GetParam(cmd, 2);
|
||||
|
||||
if (GetLocalVariable(ctx, varAddress) != compareValue)
|
||||
ctx.ProgramCounter = jumpAddress;
|
||||
else
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_GoSub(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
ushort subId = (ushort)GetParam(cmd, 0);
|
||||
|
||||
if (_currentScript.SubroutineTable.TryGetValue(subId, out Subroutine sub))
|
||||
{
|
||||
var newContext = new ExecutionContext(sub.Address, sub.Name, cmd);
|
||||
_activeSubroutines[subId] = newContext;
|
||||
}
|
||||
ctx.ProgramCounter++;
|
||||
}
|
||||
|
||||
private void Handle_Return(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
if (ctx.ExecutedByCmd != null) //main thread has ExecutedByCmd = null
|
||||
{
|
||||
// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
ctx.ExecutedByCmd.executedStatus = 3;
|
||||
ctx.IsFinished = true;
|
||||
}
|
||||
|
||||
}
|
||||
private void Handle_GetInput(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int varAddress = GetParam(cmd, 0);
|
||||
SetLocalVariable(ctx, varAddress, selectionVariable);
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>:
|
||||
private void Handle_PausInit(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
ctx.PauseTimeRemaining = 0;
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_PauseFr(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int framesToPause = GetParam(cmd, 0);
|
||||
|
||||
ctx.PauseTimeRemaining = ctx.PauseTimeRemaining = framesToPause * (1f / App.Ps1FPS); //Ps1 FPS Compability
|
||||
ctx.IsPaused = true; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||||
}
|
||||
|
||||
private void Handle_SetTemp(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int varAddress = GetParam(cmd, 0);
|
||||
int value = GetParam(cmd, 1);
|
||||
SetLocalVariable(ctx, varAddress, value);
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_CopyVar(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int srcAddress = GetParam(cmd, 0);
|
||||
int dstAddress = GetParam(cmd, 1);
|
||||
int value = GetLocalVariable(ctx, srcAddress);
|
||||
SetLocalVariable(ctx, dstAddress, value);
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_GetVar(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int localVarAddress = GetParam(cmd, 0);
|
||||
int globalVarAddress = GetParam(cmd, 1);
|
||||
int value = App.GameState.GetGlobalVariable(globalVarAddress);
|
||||
SetLocalVariable(ctx, localVarAddress, value);
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_VarTrue(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int globalVarAddress = GetParam(cmd, 0);
|
||||
App.GameState.SetGlobalVariable(globalVarAddress, 1);
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_VarFlse(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int globalVarAddress = GetParam(cmd, 0);
|
||||
App.GameState.SetGlobalVariable(globalVarAddress, 0);
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_VarSet(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int globalVarAddress = GetParam(cmd, 0);
|
||||
int value = GetParam(cmd, 1);
|
||||
App.GameState.SetGlobalVariable(globalVarAddress, value);
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_VarDec(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int globalVarAddress = GetParam(cmd, 0);
|
||||
int currentValue = App.GameState.GetGlobalVariable(globalVarAddress);
|
||||
App.GameState.SetGlobalVariable(globalVarAddress, currentValue - 1);
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_CtrlLock(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
Debug.Log("Controls Locked");
|
||||
App.GameState.IsPlayerControlLocked = true;
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_CtrUnlck(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
Debug.Log("Controls Unlocked");
|
||||
App.GameState.IsPlayerControlLocked = false;
|
||||
|
||||
if (_objectRegistry.TryGetValue(1, out GameObject playerObj))
|
||||
{
|
||||
ControlsController.Instance?.SetControlledObject(playerObj);
|
||||
}
|
||||
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_SetCamXY(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
uint rot = (uint)GetParam(cmd, 0);
|
||||
uint x = (uint)GetParam(cmd, 1);
|
||||
uint y = (uint)GetParam(cmd, 2);
|
||||
uint z = (uint)GetParam(cmd, 3);
|
||||
|
||||
App.CameraController.SetCamTargetXY(rot, x, y, z);
|
||||
Debug.Log($"Camera position set {x}.{y}.{z}. Rot - {rot}");
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_TextShow(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int textOffset = GetParam(cmd, 0);
|
||||
|
||||
var textTokens = TextUtils.ParseText(_currentScript.TextData, textOffset);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> UI <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
App.TextManager.ShowText(textTokens, cmd);
|
||||
|
||||
ctx.ProgramCounter++;
|
||||
}
|
||||
|
||||
private void Handle_WindOpen(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
App.UI.ShowMessageWindow();
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_WindClose(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
App.UI.HideMessageWindow(ctx);
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
//CHARACTERS SECTION
|
||||
|
||||
private void Handle_CharLoad(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
//Old PS1 method for loading sprite sheet in VRAM
|
||||
//Now we simply creating disabled char model on scene
|
||||
int modelId = GetParam(cmd, 0);
|
||||
if (!_modelTempRegistry.ContainsKey(modelId))
|
||||
{
|
||||
GameObject model = App.ResourceManager.CharLoad(modelId);
|
||||
_modelTempRegistry[modelId] = model;
|
||||
}
|
||||
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_CharInit(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: id, model_id, x, y, z, turn, dummy
|
||||
int objectId = GetParam(cmd, 0);
|
||||
int modelId = GetParam(cmd, 1);
|
||||
uint posX = (uint)GetParam(cmd, 2);
|
||||
uint posY = (uint)GetParam(cmd, 3);
|
||||
uint posZ = (uint)GetParam(cmd, 4);
|
||||
uint rotation = (uint)GetParam(cmd, 5);
|
||||
int dummy = GetParam(cmd, 6); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
if (!_modelTempRegistry.TryGetValue(modelId, out GameObject templateModel))
|
||||
{
|
||||
Debug.LogWarning($"Model {modelId} not loaded, creating...");
|
||||
templateModel = App.ResourceManager.CharLoad(modelId);
|
||||
_modelTempRegistry[modelId] = templateModel;
|
||||
}
|
||||
|
||||
if (_objectRegistry.TryGetValue(objectId, out GameObject existingModel))
|
||||
{
|
||||
Destroy(existingModel);
|
||||
_objectRegistry.Remove(objectId);
|
||||
}
|
||||
|
||||
GameObject characterInstance = App.ResourceManager.CharInit(templateModel, objectId, posX, posY, posZ, rotation);
|
||||
|
||||
_objectRegistry[objectId] = characterInstance;
|
||||
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
// Activate player object at camera spot position and link controls
|
||||
private void Handle_PlayerInit(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int rotation = GetParam(cmd, 0);
|
||||
|
||||
if (!_modelTempRegistry.TryGetValue(1, out GameObject templateModel))
|
||||
{
|
||||
Debug.LogWarning($"Player Model not loaded, creating...");
|
||||
templateModel = App.ResourceManager.CharLoad(1);
|
||||
_modelTempRegistry[1] = templateModel;
|
||||
}
|
||||
|
||||
if (_objectRegistry.TryGetValue(1, out GameObject existingModel))
|
||||
{
|
||||
Destroy(existingModel);
|
||||
_objectRegistry.Remove(1);
|
||||
}
|
||||
|
||||
CameraController sceneCamera = App.CameraController;
|
||||
GameObject character = App.ResourceManager.CharInit(templateModel, 1, sceneCamera.sourceX, sceneCamera.sourceY, sceneCamera.sourceZ, (uint)rotation);
|
||||
|
||||
_objectRegistry[1] = character;
|
||||
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_CharGlowShow(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: id, x, y, z, glow, dummy
|
||||
int charId = GetParam(cmd, 0);
|
||||
uint posX = (uint)GetParam(cmd, 1);
|
||||
uint posY = (uint)GetParam(cmd, 2);
|
||||
uint posZ = (uint)GetParam(cmd, 3);
|
||||
uint glow = (uint)GetParam(cmd, 4);
|
||||
int dummy = GetParam(cmd, 5);
|
||||
|
||||
if (_objectRegistry.TryGetValue(charId, out GameObject characterObj))
|
||||
{
|
||||
|
||||
App.ResourceManager.CharInit(characterObj, charId, posX, posY, posZ, glow); //TODO: Async GLOW
|
||||
}
|
||||
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_CharMoveTo(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int charId = GetParam(cmd, 0);
|
||||
uint destX = (uint)GetParam(cmd, 1);
|
||||
uint destZ = (uint)GetParam(cmd, 2);
|
||||
uint endAction = (uint)GetParam(cmd, 3);
|
||||
uint speed = (uint)GetParam(cmd, 4);
|
||||
|
||||
if (_objectRegistry.TryGetValue(charId, out GameObject characterObj) && characterObj is GameObject character)
|
||||
{
|
||||
var controller = character.GetComponent<CharacterController>();
|
||||
if (controller != null)
|
||||
{
|
||||
//async move
|
||||
controller.MoveToGameCoordinates(destX, destZ, endAction, speed);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_CharAnimate(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int charId = GetParam(cmd, 0);
|
||||
uint animationId = (uint)GetParam(cmd, 1);
|
||||
uint repeatNum = (uint)GetParam(cmd, 2);
|
||||
|
||||
if (_objectRegistry.TryGetValue(charId, out GameObject characterObj) && characterObj is GameObject character)
|
||||
{
|
||||
var controller = character.GetComponent<CharacterController>();
|
||||
if (controller != null)
|
||||
{
|
||||
controller.PlayAnimation((int)animationId, (int)Mathf.Max(1, repeatNum));
|
||||
}
|
||||
}
|
||||
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
private void Handle_CharAnimate2(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
Handle_CharAnimate(ctx, cmd);
|
||||
}
|
||||
|
||||
private void Handle_WaitCharAnimEnd(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int charId = GetParam(cmd, 0);
|
||||
|
||||
if (_objectRegistry.TryGetValue(charId, out GameObject characterObj) && characterObj is GameObject character)
|
||||
{
|
||||
var controller = character.GetComponent<CharacterController>();
|
||||
if (controller != null && !controller.IsMoving)
|
||||
{
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
}
|
||||
|
||||
private void Handle_CharSetSubroutine(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int charId = GetParam(cmd, 0);
|
||||
int subId = GetParam(cmd, 1);
|
||||
|
||||
_objectRegistry.TryGetValue(charId, out GameObject characterObj);
|
||||
characterObj.GetComponent<CharacterController>().blockSubroutine = subId;
|
||||
Debug.Log($"Sub {subId} set to char {charId}");
|
||||
ctx.ProgramCounter++;
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
|
||||
|
||||
// SCENERY LOADERS
|
||||
private void Handle_CityLoad(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int districtId = GetParam(cmd, 0);
|
||||
int y = GetParam(cmd, 1);
|
||||
int x = GetParam(cmd, 2);
|
||||
App.SceneLoader.LoadCity(districtId, y, x);
|
||||
_mainContext = null; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
}
|
||||
private void Handle_BattleLoad(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int battleId = GetParam(cmd, 0);
|
||||
App.SceneLoader.LoadBattle(battleId);
|
||||
_mainContext = null; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
}
|
||||
private void Handle_DungLoad(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int dungeonId = GetParam(cmd, 0);
|
||||
App.SceneLoader.LoadDungeon(dungeonId);
|
||||
_mainContext = null; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
}
|
||||
private void Handle_EventLoad(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int hzId = GetParam(cmd, 0);
|
||||
int eventId = GetParam(cmd, 1);
|
||||
App.SceneLoader.LoadEvent(eventId, hzId);
|
||||
_mainContext = null; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
}
|
||||
|
||||
private void Handle_VideoPly(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int videoId = GetParam(cmd, 0);
|
||||
App.VideoPlayer.PlayVideo(videoId, cmd);
|
||||
PauseContext(cmd);
|
||||
}
|
||||
|
||||
private void Handle_ScrnFade(ExecutionContext ctx, ScriptCommand cmd)
|
||||
{
|
||||
int fadeType = GetParam(cmd, 0);
|
||||
int duration = GetParam(cmd, 1);
|
||||
//App.UI.ScreenFade(fadeType, duration, () => {
|
||||
// ctx.ProgramCounter++;
|
||||
//});
|
||||
ctx.ProgramCounter++;
|
||||
}
|
||||
|
||||
public void PauseContext(ScriptCommand cmd)
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if (_mainContext != null && GetCurrentCommand(_mainContext) == cmd)
|
||||
{
|
||||
_mainContext.IsPaused = true;
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var context in _activeSubroutines.Values)
|
||||
{
|
||||
if (GetCurrentCommand(context) == cmd)
|
||||
{
|
||||
context.IsPaused = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ResumeContext(ScriptCommand cmd)
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||||
if (_mainContext != null && GetCurrentCommand(_mainContext) == cmd)
|
||||
{
|
||||
_mainContext.IsPaused = false;
|
||||
_mainContext.ProgramCounter++; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var context in _activeSubroutines.Values)
|
||||
{
|
||||
if (GetCurrentCommand(context) == cmd)
|
||||
{
|
||||
context.IsPaused = false;
|
||||
context.ProgramCounter++; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ==========
|
||||
|
||||
private ScriptCommand GetCurrentCommand(ExecutionContext ctx)
|
||||
{
|
||||
if (ctx.ProgramCounter < _currentScript.Commands.Count)
|
||||
return _currentScript.Commands[(int)ctx.ProgramCounter];
|
||||
return null;
|
||||
}
|
||||
|
||||
private int GetParam(ScriptCommand cmd, int index)
|
||||
{
|
||||
return index < cmd.Params.Length ? cmd.Params[index] : 0;
|
||||
}
|
||||
|
||||
private int GetLocalVariable(ExecutionContext ctx, int address)
|
||||
{
|
||||
return ctx.LocalVariables.TryGetValue(address, out int value) ? value : 0;
|
||||
}
|
||||
|
||||
private void SetLocalVariable(ExecutionContext ctx, int address, int value)
|
||||
{
|
||||
ctx.LocalVariables[address] = value;
|
||||
}
|
||||
|
||||
|
||||
public void SetSelectionVariable(int value) //external after selection variable set
|
||||
{
|
||||
selectionVariable = value;
|
||||
}
|
||||
|
||||
public void MarkCommandCompleted(ScriptCommand cmd)
|
||||
{
|
||||
cmd.executedStatus = 3;
|
||||
ResumeContext(cmd);
|
||||
}
|
||||
|
||||
private void MarkCurrentCommandCompleted(ExecutionContext ctx)
|
||||
{
|
||||
if (ctx.ProgramCounter > 0 && ctx.ProgramCounter - 1 < _currentScript.Commands.Count)
|
||||
{
|
||||
ScriptCommand cmd = _currentScript.Commands[(int)(ctx.ProgramCounter - 1)];
|
||||
cmd.executedStatus = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ExecutionContext
|
||||
{
|
||||
public ScriptCommand ExecutedByCmd { get; set; }
|
||||
public string ContextName { get; set; }
|
||||
public uint ProgramCounter { get; set; }
|
||||
public Dictionary<int, int> LocalVariables { get; set; }
|
||||
public bool IsWaiting { get; set; }
|
||||
public bool IsPaused { get; set; }
|
||||
public bool IsFinished { get; set; }
|
||||
public float PauseTimeRemaining { get; set; }
|
||||
|
||||
public ExecutionContext(uint startAddress, string name, ScriptCommand cmd)
|
||||
{
|
||||
ContextName = name;
|
||||
ExecutedByCmd = cmd;
|
||||
ProgramCounter = startAddress;
|
||||
LocalVariables = new Dictionary<int, int>();
|
||||
PauseTimeRemaining = 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user