C# - Fallout4的四条龙 - 绕过未处理的例外?

时间:2015-12-24 11:02:53

标签: c# windows-7 64-bit

Previous thread,如果你们都好奇的话。

背景信息:Four Dragon是Fallout 4的C#包装器,允许使用C#脚本修改游戏,并允许在相同的C#中使用Papyrus(Skyrim和Fallout 4的脚本语言)函数脚本。潜力!可能性!

我编写了一个运行Papyrus函数GetPlayerGrabbedRef()SetMotionType的脚本,用于使游戏中的对象冻结到位。感谢Metro Smurf,脚本更容易阅读。

然而,有一个相当......明显的问题。脚本注册F6和F7键,但是当按下F6并调用GetPlayerGrabbedRef()函数时,当玩家没有抓取引用(可移动的游戏内对象)时,输出以下异常,导致游戏迅速退出:

FATAL ERROR Unhandled exception while executing FyTyTest.FreezeObject Void OnStaticTick()

现在,我已经完成了如何处理未处理异常的一些阅读,允许程序(在这种情况下为Fallout 4游戏)继续操作,而不通过trycatch函数关闭,但我没有任何成功;异常仍然发生,导致游戏在单击“确定”时退出。

唉,输出的各种.log文件没有问题;好像一切都运转正常。

以下是该剧本的最新版本:

using System;
using System.Collections.Generic;
using Fallout;

public class FreezeObject : ScriptObject
{
public FreezeObject() { }

bool bGotObject = false;
ObjectReference ItemReference;
ObjectReference EmptyReference;
int itemValue;


public override void OnStaticTick()
{
    base.OnStaticTick();

    bool isF6 = Fallout.Keyboard.IsKeyJustUp(System.Windows.Forms.Keys.F6);
    bool isF7 = Fallout.Keyboard.IsKeyJustUp(System.Windows.Forms.Keys.F7);

    if(isF6)
    {
        try
        {
            ItemReference = Game.GetPlayerGrabbedRef();
            itemValue = ItemReference.GetGoldValue();
            if(ItemReference = EmptyReference)
            {
                // nothing else to do if we have a null reference
                return;
            }
        }

        catch
        {
            ItemReference = EmptyReference;
            itemValue = -1;
            return;
        }

    if (itemValue > -1)
    {
        bGotObject = true;
    }
            // nothing else to do; the next block is for F7
    return;
    }

    if(isF7 && bGotObject && ItemReference != EmptyReference && itemValue > -1)
    {
        ItemReference.SetMotionType(2, true);
        bGotObject = false;
    }
}
}

所以。如何阻止未处理的异常导致游戏崩溃?或者这是不可能的?

编辑:按照Corey的建议,我将try...catch函数放在所有函数代码周围......没有骰子;异常仍然出现,一旦异常消息关闭就关闭游戏。

这是新脚本:

using System;
using System.Collections.Generic;
using Fallout;

public class FreezeObject : ScriptObject
{
public FreezeObject() { }
bool bGotObject = false;
ObjectReference ItemReference;
ObjectReference EmptyReference;
int itemValue;


public override void OnStaticTick()
{try
{

    base.OnStaticTick();

    bool isF6 = Fallout.Keyboard.IsKeyJustUp(System.Windows.Forms.Keys.F6);
    bool isF7 = Fallout.Keyboard.IsKeyJustUp(System.Windows.Forms.Keys.F7);

    if(isF6)
    {
        ItemReference = Game.GetPlayerGrabbedRef();
        itemValue = ItemReference.GetGoldValue();
        if(ItemReference == EmptyReference)
        {
            // nothing else to do if we have a null reference
            return;
        }

    if (itemValue > -1)
    {
        bGotObject = true;
    }
            // nothing else to do; the next block is for F7
    return;
    }

    if(isF7 && bGotObject && ItemReference != EmptyReference && itemValue > -1)
    {
        ItemReference.SetMotionType(2, true);
        bGotObject = false;
    }
    }
catch
{
}
}
}

1 个答案:

答案 0 :(得分:0)

Four Dragon拥有自己的AppDomain,用于加载和执行用户脚本。我没有很多机会使用自定义主机,所以我不确定,但我相信主机可以控制异常处理行为。假设我是对的,我猜这是造成你奇怪的异常处理问题的原因。

您最好的办法是解决异常的实际原因。在您的代码中,在您尝试访问对象上的方法之后,您将检查空引用。你可能想试试这个:

if(isF6)
{
    ItemReference = Game.GetPlayerGrabbedRef();
    if(ItemReference != null && ItemReference.HandleExists())
    {
        itemValue = ItemReference.GetFormID();
        if (itemValue != 0)
        {
            bGotObject = true;
        }
    }

    // nothing else to do; the next block is for F7
    return;
}

我将GetGoldValue()来电更改为GetFormID(),因为您正在使用它来确定您是否拥有有效的ObjectReference

如果您仍有问题,我会尝试存储表单ID并使用Game.GetForm(formid)重新获取F7块中的对象引用。您依赖于假设对象引用在调用OnStaticTick之间保持有效,这可能不一定是这种情况。 (仍在挖掘Four Dragon的实施,所以我仍然不确定)

编辑:忽略 - 对象引用显然在事件之间保持有效。