/// <summary>
        /// This function links to a NWScript function within a given script
        /// object.  The script must be compiled with debug symbols, and the
        /// function needs to have been actually instantiated into the target
        /// script.  Calling the function within NWScript code, inside the
        /// target script, will ensure that the function was instantiated.
        /// </summary>
        /// <param name="ScriptObject">Supplies the script object to get the
        /// target function from.</param>
        /// <param name="ScriptFunctionName">Supplies the name of the NWScript
        /// native function to get.</param>
        /// <returns>The function method is returned.  On failure, an exception
        /// is raised.</returns>
        public static MethodInfo GetScriptFunction(IGeneratedScriptProgram ScriptObject, string ScriptFunctionName)
        {
            MethodInfo Method = ScriptObject.GetType().GetMethod("NWScriptSubroutine_" + ScriptFunctionName);

            if (Method == null)
            {
                throw new ApplicationException("Unable to find script function " + ScriptFunctionName + " on script " + ScriptObject.GetType().FullName);
            }

            return(Method);
        }
        /// <summary>
        /// This method sets the user's script object to delegate unrecognized
        /// script situations to the NWScript library script, allowing a delay
        /// continuation started by called NWScript code to function properly.
        /// </summary>
        /// <param name="DelegateScript"></param>
        private void RegisterScriptSituationDelegate(IGeneratedScriptProgram DelegateScript)
        {
            //
            // Dispatch delay continuations from the DBLibraryScript over to
            // NWScript code.
            //

            if (Script.DelegateScriptObject != DelegateScript)
            {
                if (Script.DelegateScriptObject != null)
                {
                    throw new ApplicationException("Duplicate delegate script registration.");
                }

                Script.DelegateScriptObject = DelegateScript;
            }
        }
        /// <summary>
        /// This method performs demand initialization of the database system
        /// on the first database call.
        /// </summary>
        private void DemandInitialize()
        {
            if (DBLibraryScript != null)
            {
                RegisterScriptSituationDelegate(DBLibraryScript);
                return;
            }

            //
            // Link to the module load script, as it will always be already
            // loaded, and it references database functions.
            //

            IGeneratedScriptProgram ScriptObject = ScriptLoader.LoadScript("acf_mod_onmoduleload", false, Script);

            ACR_AsyncSQLQueryEx_Method              = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_AsyncSQLQueryEx");
            ACR_GetPersistentString_Method          = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_GetPersistentString");
            ACR_GetServerAddressFromDatabase_Method = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_GetServerAddressFromDatabase");
            ACR_SetPersistentString_Method          = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_SetPersistentString");
            ACR_DeletePersistentVariable_Method     = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_DeletePersistentVariable");
            ACR_SQLQuery_Method           = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_SQLQuery");
            ACR_FlushQueryQueue_Method    = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_FlushQueryQueue");
            ACR_PPSValidatePC_Method      = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_PPSValidatePC");
            ACR_PCUpdateStatus_Method     = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_PCUpdateStatus");
            ACR_RestOnClientEnter_Method  = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_RestOnClientEnter");
            ACR_XPOnClientLoaded_Method   = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_XPOnClientLoaded");
            ACR_PCSave_Method             = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_PCSave");
            ACR_GetVersion_Method         = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_GetVersion");
            ACR_GetBuildDate_Method       = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_GetBuildDate");
            ACR_GetHAKVersion_Method      = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_GetHAKVersion");
            ACR_GetHAKBuildDate_Method    = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_GetHAKBuildDate");
            ACR_IncrementStatistic_Method = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_IncrementStatistic");
            ACR_RunScriptOnServer_Method  = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_RunScriptOnServer");
            ACR_LogEvent_Method           = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_LogEvent");
            ACR_GetIsMember_Method        = ScriptLoader.GetScriptFunction(ScriptObject, "ACR_GetIsMember");

            DBLibraryScript = ScriptObject;

            RegisterScriptSituationDelegate(ScriptObject);
        }
        /// <summary>
        /// This methods generates a default argument array for a script object
        /// and returns it.  All arguments have empty values.
        /// </summary>
        /// <param name="ScriptObject">Supplies the script object of the script
        /// to generate default arguments for.</param>
        /// <param name="CallerScript">Supplies the script object owned by the
        /// caller.</param>
        /// <returns>The argument array is returned.</returns>
        public static object[] GetDefaultParametersForScript(IGeneratedScriptProgram ScriptObject, CLRScriptBase CallerScript)
        {
            Type      ScriptObjectType = ScriptObject.GetType();
            FieldInfo ParametersField  = ScriptObjectType.GetField("ScriptParameterTypes");

            Type[]   ParameterTypes;
            object[] DefaultParameters;

            if (ParametersField == null)
            {
                return new object[] { }
            }
            ;

            ParameterTypes = (Type[])ParametersField.GetValue(ScriptObject);

            DefaultParameters = new object[ParameterTypes.Length];

            //
            // Construct a default argument for each parameter to the script's
            // main function.
            //

            for (int i = 0; i < ParameterTypes.Length; i += 1)
            {
                if (ParameterTypes[i] == typeof(string))
                {
                    DefaultParameters[i] = "";
                }
                else if (ParameterTypes[i] == typeof(Int32))
                {
                    DefaultParameters[i] = (Int32)0;
                }
                else if (ParameterTypes[i] == typeof(UInt32))
                {
                    DefaultParameters[i] = CLRScriptBase.OBJECT_INVALID;
                }
                else if (ParameterTypes[i] == typeof(Single))
                {
                    DefaultParameters[i] = (Single)0.0f;
                }
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure0))
                {
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure0();
                }
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure1))
                {
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure1();
                }
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure2))
                {
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure2();
                }
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure3))
                {
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure3();
                }
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure4))
                {
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure4();
                }
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure5))
                {
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure5();
                }
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure6))
                {
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure6();
                }
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure7))
                {
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure7();
                }
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure8))
                {
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure8();
                }
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure9))
                {
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure9();
                }
                else
                {
                    throw new ApplicationException("Script takes invalid arguments to ExecuteScript entrypoint.");
                }
            }

            return(DefaultParameters);
        }
        /// <summary>
        /// This method sets the user's script object to delegate unrecognized
        /// script situations to the NWScript library script, allowing a delay
        /// continuation started by called NWScript code to function properly.
        /// </summary>
        /// <param name="DelegateScript"></param>
        private void RegisterScriptSituationDelegate(IGeneratedScriptProgram DelegateScript)
        {
            //
            // Dispatch delay continuations from the DBLibraryScript over to
            // NWScript code.
            //

            if (Script.DelegateScriptObject != DelegateScript)
            {
                if (Script.DelegateScriptObject != null)
                    throw new ApplicationException("Duplicate delegate script registration.");

                Script.DelegateScriptObject = DelegateScript;
            }

        }
        /// <summary>
        /// This function links to a NWScript function within a given script
        /// object.  The script must be compiled with debug symbols, and the
        /// function needs to have been actually instantiated into the target
        /// script.  Calling the function within NWScript code, inside the
        /// target script, will ensure that the function was instantiated.
        /// </summary>
        /// <param name="ScriptObject">Supplies the script object to get the
        /// target function from.</param>
        /// <param name="ScriptFunctionName">Supplies the name of the NWScript
        /// native function to get.</param>
        /// <returns>The function method is returned.  On failure, an exception
        /// is raised.</returns>
        public static MethodInfo GetScriptFunction(IGeneratedScriptProgram ScriptObject, string ScriptFunctionName)
        {
            MethodInfo Method = ScriptObject.GetType().GetMethod("NWScriptSubroutine_" + ScriptFunctionName);

            if (Method == null)
                throw new ApplicationException("Unable to find script function " + ScriptFunctionName + " on script " + ScriptObject.GetType().FullName);

            return Method;
        }
        /// <summary>
        /// This methods generates a default argument array for a script object
        /// and returns it.  All arguments have empty values.
        /// </summary>
        /// <param name="ScriptObject">Supplies the script object of the script
        /// to generate default arguments for.</param>
        /// <param name="CallerScript">Supplies the script object owned by the
        /// caller.</param>
        /// <returns>The argument array is returned.</returns>
        public static object[] GetDefaultParametersForScript(IGeneratedScriptProgram ScriptObject, CLRScriptBase CallerScript)
        {
            Type ScriptObjectType = ScriptObject.GetType();
            FieldInfo ParametersField = ScriptObjectType.GetField("ScriptParameterTypes");
            Type[] ParameterTypes;
            object[] DefaultParameters;

            if (ParametersField == null)
                return new object[] { };

            ParameterTypes = (Type[])ParametersField.GetValue(ScriptObject);

            DefaultParameters = new object[ParameterTypes.Length];

            //
            // Construct a default argument for each parameter to the script's
            // main function.
            //

            for (int i = 0; i < ParameterTypes.Length; i += 1)
            {
                if (ParameterTypes[i] == typeof(string))
                    DefaultParameters[i] = "";
                else if (ParameterTypes[i] == typeof(Int32))
                    DefaultParameters[i] = (Int32)0;
                else if (ParameterTypes[i] == typeof(UInt32))
                    DefaultParameters[i] = CLRScriptBase.OBJECT_INVALID;
                else if (ParameterTypes[i] == typeof(Single))
                    DefaultParameters[i] = (Single)0.0f;
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure0))
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure0();
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure1))
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure1();
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure2))
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure2();
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure3))
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure3();
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure4))
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure4();
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure5))
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure5();
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure6))
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure6();
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure7))
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure7();
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure8))
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure8();
                else if (ParameterTypes[i] == typeof(NWScriptEngineStructure9))
                    DefaultParameters[i] = CallerScript.ScriptHost.Intrinsics.Intrinsic_CreateEngineStructure9();
                else
                    throw new ApplicationException("Script takes invalid arguments to ExecuteScript entrypoint.");
            }

            return DefaultParameters;
        }