How Do I Subscribe To The Event "OnTrade"?

Discuss modding questions and implementation details.
User avatar
Magicono43
Posts: 1141
Joined: Tue Nov 06, 2018 7:06 am

How Do I Subscribe To The Event "OnTrade"?

Post by Magicono43 »

I've been trying for hours to figure this out, but I don't know what to try next.

I simply want to run a block of code when the "OnTrade" event is raised from either buying or selling an item. But I don't know how to properly subscribe to this specific event from outside the parent class "DaggerfallTradeWindow", and there are no examples I can find of this being done outside of this class, or in other mods.

The only time I have been able to get this event to work is if I edit the "DaggerfallTradeWindow" script itself, and change:

Code: Select all

// OnTrade event. (value=0:steal, numItems=0:caught)
        public delegate void OnTradeHandler(WindowModes mode, int numItems, int value);
        public event OnTradeHandler OnTrade;    <-------------
        protected virtual void RaiseOnTradeHandler(int numItems, int value)
        {
            if (OnTrade != null)
                OnTrade(WindowMode, numItems, value);
        }
To this:

Code: Select all

// OnTrade event. (value=0:steal, numItems=0:caught)
        public delegate void OnTradeHandler(WindowModes mode, int numItems, int value);
        public static event OnTradeHandler OnTrade;    <----------------
        protected virtual void RaiseOnTradeHandler(int numItems, int value)
        {
            if (OnTrade != null)
                OnTrade(WindowMode, numItems, value);
        }
And subscribe to it like this:

Code: Select all

DaggerfallTradeWindow.OnTrade += Testing_OnTrade;

That's not going to work though, since I don't want to edit the code-base just for a quick fix for my problem. So my latest attempt at trying to subscribe to this properly is this:

Code: Select all

void Start()
        {
            PlayerEnterExit.OnTransitionInterior += Testing_OnTransitionInterior;
            GameManager.Instance.PlayerEffectManager.OnNewReadySpell += Testing_OnNewReadySpell;

            UserInterfaceManager uiManager = DaggerfallUI.Instance.UserInterfaceManager;
            DaggerfallTradeWindow testing = new DaggerfallTradeWindow(uiManager, null, DaggerfallTradeWindow.WindowModes.Buy, null);
            testing.OnTrade += Testing_OnTrade;
        }
So this does not have any compile errors and can be built, but the event happening does not run my block of code. So this is where I am lost. I can subscribe to the also non-static event "OnNewReadySpell" and it works without issue, since it has an object instance from GameManager, I guess. If I try something similar with "OnTrade" though, it does not work, since there is no object instance I can get from a parent of "DaggerfallTradeWindow", I guess. That's why I tried to create a new instance of "DaggerfallTradeWindow", but that did not seem to do anything that I was expecting.

Anyway, hopefully I've done my due diligence here and am not wasting anyone's time with a poorly made question, thanks.


Edit 1: This is what my block of code looks like:

Code: Select all

private static void Testing_OnTrade(DaggerfallTradeWindow.WindowModes mode, int numItems, int value)
        {
            Debug.Log("You just traded something.");
            return;
        }

User avatar
BadLuckBurt
Posts: 948
Joined: Sun Nov 05, 2017 8:30 pm

Re: How Do I Subscribe To The Event "OnTrade"?

Post by BadLuckBurt »

By no means am I claiming this is the right way to do it but it works. If I am doing anything wrong I kindly ask that someone who knows more about it, please points it out :)

One thing I have noticed from the Debug.Log is that the BUY option seems to trigger the event twice?

Anyway, In the initialisation of your mod's code, hook into the OnWindowChange event of the UIManager:

Code: Select all

IUserInterfaceManager uiManager = DaggerfallUI.UIManager;
uiManager.OnWindowChange += WindowChanged;
This is the code for WindowChanged:

Code: Select all

public static void WindowChanged(object sender, EventArgs e) {
	UserInterfaceManager uiManager = sender as UserInterfaceManager;
	DaggerfallTradeWindow window = uiManager.TopWindow as DaggerfallTradeWindow;
	if(window != null) {
		Type windowType = window.GetType();
		Debug.Log("Custom activation - Window of type: " + windowType.Name);
		window.OnTrade += Trading;
	}
}
Just for the sake of completion, as you already have your own method ready:

Code: Select all

public static void Trading(DaggerfallTradeWindow.WindowModes mode, int numItems, int value) {
	Debug.Log("Here be custom trade event handling\nItems: " + numItems.ToString() + " - value: " + value.ToString());
}
DFU on UESP: https://en.uesp.net/w/index.php?title=T ... fall_Unity
DFU Nexus Mods: https://www.nexusmods.com/daggerfallunity
My github repositories with mostly DFU related stuff: https://github.com/BadLuckBurt

.

User avatar
Magicono43
Posts: 1141
Joined: Tue Nov 06, 2018 7:06 am

Re: How Do I Subscribe To The Event "OnTrade"?

Post by Magicono43 »

Thank you very much, your solution worked for getting the event to at least trigger like I expect it to. I'll keep updating this in case anyone else has the same quarry at some point.

User avatar
numidium3rd
Posts: 187
Joined: Sun Mar 25, 2018 12:34 am
Location: United States

Re: How Do I Subscribe To The Event "OnTrade"?

Post by numidium3rd »

You can also use Hazelnut's handy UIWindowFactory class to access the trade window directly.

Code: Select all

var tradeWindow = (DaggerfallTradeWindow)UIWindowFactory.GetInstance(UIWindowType.Trade, uiManager);
tradeWindow.OnTrade += MyVoidMethod;
EDIT: forgot type cast
Last edited by numidium3rd on Mon Apr 13, 2020 9:45 pm, edited 1 time in total.

User avatar
Magicono43
Posts: 1141
Joined: Tue Nov 06, 2018 7:06 am

Re: How Do I Subscribe To The Event "OnTrade"?

Post by Magicono43 »

numidium3rd wrote: Mon Apr 13, 2020 9:41 pm You can also use Hazelnut's handy UIWindowFactory class to access the trade window directly.

Code: Select all

var tradeWindow = UIWindowFactory.GetInstance(UIWindowType.Trade, uiManager);
tradeWindow.OnTrade += MyVoidMethod;
If this works, i'm going to be kicking myself hard, lol.

User avatar
Magicono43
Posts: 1141
Joined: Tue Nov 06, 2018 7:06 am

Re: How Do I Subscribe To The Event "OnTrade"?

Post by Magicono43 »

numidium3rd wrote: Mon Apr 13, 2020 9:41 pm You can also use Hazelnut's handy UIWindowFactory class to access the trade window directly.

Code: Select all

var tradeWindow = (DaggerfallTradeWindow)UIWindowFactory.GetInstance(UIWindowType.Trade, uiManager);
tradeWindow.OnTrade += MyVoidMethod;
EDIT: forgot type cast
It compiled fine, but when it was initialized it threw this exception in Unity:
error
error
Capture22.JPG (75.83 KiB) Viewed 1284 times
Code Used:

Code: Select all

IUserInterfaceManager uiManager = DaggerfallUI.UIManager;
var tradeWindow = (DaggerfallTradeWindow)UIWindowFactory.GetInstance(UIWindowType.Trade, uiManager);
tradeWindow.OnTrade += Trading;

User avatar
numidium3rd
Posts: 187
Joined: Sun Mar 25, 2018 12:34 am
Location: United States

Re: How Do I Subscribe To The Event "OnTrade"?

Post by numidium3rd »

My mistake - looks like you need to need to pass an array of objects. Okay, instead of calling GetInstance try this one instead

Code: Select all

var tradeWindow = (DaggerfallTradeWindow)UIWindowFactory.GetInstanceWithArgs(UIWindowType.Trade, new object[] { uiManger });
And if that fails try populating the array like this:

Code: Select all

var tradeWindow = (DaggerfallTradeWindow)UIWindowFactory.GetInstanceWithArgs(UIWindowType.Trade, new object[] { uiManager, this, DaggerfallTradeWindow.WindowModes.Sell, null  }); // "this" refers to the previous window. Replace it with null if you're not calling from a window.
Last edited by numidium3rd on Mon Apr 13, 2020 11:09 pm, edited 1 time in total.

User avatar
Magicono43
Posts: 1141
Joined: Tue Nov 06, 2018 7:06 am

Re: How Do I Subscribe To The Event "OnTrade"?

Post by Magicono43 »

I'll give it a shot, will update in a couple minutes.

User avatar
Magicono43
Posts: 1141
Joined: Tue Nov 06, 2018 7:06 am

Re: How Do I Subscribe To The Event "OnTrade"?

Post by Magicono43 »

numidium3rd wrote: Mon Apr 13, 2020 11:02 pm My mistake - looks like you need to need to pass an array of objects. Okay, instead of calling GetInstance try this one instead

Code: Select all

var tradeWindow = (DaggerfallTradeWindow)UIWindowFactory.GetInstanceWithArgs(UIWindowType.Trade, new object[] { uiManger });
And if that fails try populating the array like this:

Code: Select all

var tradeWindow = (DaggerfallTradeWindow)UIWindowFactory.GetInstanceWithArgs(UIWindowType.Trade, new object[] { uiManager, this, DaggerfallTradeWindow.WindowModes.Sell, null  }); // "this" refers to the previous window. Replace it with null if you're not calling from a window.
Alright, so your second example had no errors on initialization, but the event was not being detected unfortunately.
Here is what the code looks like:

Code: Select all

void Start()
        {
            PlayerEnterExit.OnTransitionInterior += Testing_OnTransitionInterior;
            GameManager.Instance.PlayerEffectManager.OnNewReadySpell += Testing_OnNewReadySpell;

            UserInterfaceManager uiManager = DaggerfallUI.Instance.UserInterfaceManager;
            var tradeWindow = (DaggerfallTradeWindow)UIWindowFactory.GetInstanceWithArgs(UIWindowType.Trade, new object[] { uiManager, null, DaggerfallTradeWindow.WindowModes.Sell, null });
            tradeWindow.OnTrade += Trading;
        }
        
        
        private static void Trading(DaggerfallTradeWindow.WindowModes mode, int numItems, int value)
        {
            Debug.Log("You just traded something.");
            return;
        }
I changed the "this" to a "null" as your comment said to.

This seems similar to the issue I was having in my original post it seems, where it compiles, but does not actually detect when the event happens.

User avatar
numidium3rd
Posts: 187
Joined: Sun Mar 25, 2018 12:34 am
Location: United States

Re: How Do I Subscribe To The Event "OnTrade"?

Post by numidium3rd »

I tested it out myself and it appears that a new instance of DaggerfallTradeWindow is created every time you use UIWindowFactory... meaning that the event you set is lost every time. Should've figured. This is a strong case for having that event be static in the codebase in my opinion. I'll have to see what Hazelnut thinks.

Anyway, BadLuckBurt's solution seems fine for the time being. Sorry for wasting your time.

Post Reply