DFU PlayerEnterExit.cs possible issue

Post here if you need help getting started with Daggerfall Unity or just want to clarify a potential bug. Questions about playing or modding classic Daggerfall should be posted to Community.
User avatar
King of Worms
Posts: 4753
Joined: Mon Oct 17, 2016 11:18 pm
Location: Scourg Barrow (CZ)
Contact:

DFU PlayerEnterExit.cs possible issue

Post by King of Worms »

Hi, 1st, Im not a coder, but the person I cooperate with actually is - we are expanding the dynamic backgrounds script and noticed that "IsPlayerInsideOpenShop" & "IsPlayerInsideTavernfunction" don't work properly, so I want to bring it to your attention to consider it:
When the player enters a shop or tavern, there is a true/false code check that gets triggered to "true" when player is in a shop/tavern (interior). The problem is when the player leaves a shop/tavern this code check should switch to "false" but it DOESN'T so it remains "true" even if the player is outside.

Functions that are affected with this bug are:

IsPlayerInsideOpenShop
IsPlayerInsideTavern

and they are located in "PlayerEnterExit.cs" DFU source code files.
Is this a feature or a oversight? I know it took him many hours to pinpoint this, so Im reporting, eventho I dont truly understand it.

Thanks for looking at it.

User avatar
Interkarma
Posts: 7247
Joined: Sun Mar 22, 2015 1:51 am

Re: DFU PlayerEnterExit.cs possible issue

Post by Interkarma »

These building-specific flags are set on entry and only valid when player is inside an interior.

The correct way to check:

Code: Select all

if (playerEnterExit.IsPlayerInside && playerEnterExit.IsPlayerInsideTavern) // Player inside a tavern
if (playerEnterExit.IsPlayerInside && playerEnterExit.IsPlayerInsideOpenShop ) // Player inside an open shop
These secondary flags are updated anytime player enters a new interior and pertain only to the current interior. If player isn't inside, these flags don't mean anything.

Granted, these could be clearer and more user friendly. But that's how they're meant to be used. :)

User avatar
King of Worms
Posts: 4753
Joined: Mon Oct 17, 2016 11:18 pm
Location: Scourg Barrow (CZ)
Contact:

Re: DFU PlayerEnterExit.cs possible issue

Post by King of Worms »

Thanks for a reply Interkarma, I forwarded the reply and got this :) I believe its worth checking
Ok, thanks for the explanation of functions - amazing work on DFU by the way. I'm using them in the exact way you stated. The problem is not the functions themselves but their true/false states. Let's explain my problem like this:

1. First, game gets loaded with the player outside the shop, both functions will be false:
IsPlayerInside == false
IsPlayerInsideOpenShop == false

2. Second, player enters the open shop (midday ingame time). Both are now set to true:
IsPlayerInside == true
IsPlayerInsideOpenShop == true

3. Third, player exits the shop, now comes the issue, "IsPlayerInside" will correctly revert to false, but "IsPlayerInsideOpenShop" WILL REMAIN STUCK TO TRUE (same for tavern):

IsPlayerInside == false
IsPlayerInsideOpenShop == true

So the issue is why does "IsPlayerInsideOpenShop" remain true when player is outside of a shop or a tavern. Is there some point to this or is it a bug/oversight. I think that "PlayerEnterExit.cs" should have additional check that sets "IsPlayerInsideOpenShop" and "IsPlayerInsideTavern" to false when "IsPlayerInside" is false. This was messing with DREAM dynamic bg script and took me a week to even noticed this issue. I fixed the script already by adding the extra "IsPlayerInside" check under the "if" condition - just like you said in the forum reply.

User avatar
Interkarma
Posts: 7247
Joined: Sun Mar 22, 2015 1:51 am

Re: DFU PlayerEnterExit.cs possible issue

Post by Interkarma »

It's neither a bug nor an oversight. These flags are set true/false every time the player enters a building. If the player is not inside, these flags have no meaning as I said above.

If it helps make things clearer, I can lower those flags on transition to exit also. Edit: done.

User avatar
King of Worms
Posts: 4753
Joined: Mon Oct 17, 2016 11:18 pm
Location: Scourg Barrow (CZ)
Contact:

Re: DFU PlayerEnterExit.cs possible issue

Post by King of Worms »

Thank you for the explanation and the change, it helps with modding the dynamic paperdoll backgrounds :) Honestly cant wait for the new backgrounds to be released, there are currently over 200 of those.. this was made with a help of Zoran from Nexus, he helped me tremendously lately
Spoiler!
DaggerfallUnity 2023-02-16 02-28-56.jpg
DaggerfallUnity 2023-02-16 02-28-56.jpg (768.39 KiB) Viewed 914 times

User avatar
Interkarma
Posts: 7247
Joined: Sun Mar 22, 2015 1:51 am

Re: DFU PlayerEnterExit.cs possible issue

Post by Interkarma »

That looks beautiful! Gives me proper old-school fantasy vibes, like reading a book and turning the page to a find a colour plate of the character's world at that point in the story. Have no doubts a lot of people will enjoy this.

User avatar
King of Worms
Posts: 4753
Joined: Mon Oct 17, 2016 11:18 pm
Location: Scourg Barrow (CZ)
Contact:

Re: DFU PlayerEnterExit.cs possible issue

Post by King of Worms »

Thank you! I have one question but I really dont want to bother u with stuff :X but I must ask - feel free to dismiss it, it would be totally understandable ;)

The paperdoll backgrounds seem to be rendered with point filtering ingame, no matter the ingame "GUI filter" settings or Unity inspector settings of said HD background images. I think its because u wanted to have the vanilla backgrounds rendered in s sharp pixelated manner? But for HD backgrounds its not ideal in some cases.

Would it be possible to enable bi/trilinear filtering of these backgrounds if the player enables that option in the "Video/GUI filter" settings?

OR maybe a better way


Allow to apply the Unity inspector filter mode settings - its most likely disabled now, that would solve it as well without interfering with the base game?

Thank you and sorry for bothering u with this :oops:

User avatar
Interkarma
Posts: 7247
Joined: Sun Mar 22, 2015 1:51 am

Re: DFU PlayerEnterExit.cs possible issue

Post by Interkarma »

I just had a look and can confirm the default classes don't consider filter mode. The way we'd go about this depends on a couple factors.

How does your mod assign these textures to the paper doll - is it done by sending back string of filename to load or assigning a texture reference?

User avatar
King of Worms
Posts: 4753
Joined: Mon Oct 17, 2016 11:18 pm
Location: Scourg Barrow (CZ)
Contact:

Re: DFU PlayerEnterExit.cs possible issue

Post by King of Worms »

Thank you :)

I think easiest way to explain how the backgrounds are handled is by posting the script itself, as I have no idea how the process used is called :oops: Im sure u will see it in a second. Backgrounds have names in CAPITAL. If it is not clear from script, I will ask the person who wrote it (edit: already did, just waiting for a reply)

Code: Select all

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;

using DaggerfallConnect.Arena2;
using DaggerfallConnect.Utility;

using DaggerfallWorkshop;
using DaggerfallWorkshop.Game;
using DaggerfallWorkshop.Game.Entity;
using DaggerfallWorkshop.Game.MagicAndEffects.MagicEffects;
using DaggerfallWorkshop.Game.Serialization;
using DaggerfallWorkshop.Game.UserInterface;
using DaggerfallWorkshop.Game.UserInterfaceWindows;
using DaggerfallWorkshop.Game.Utility.ModSupport;
using DaggerfallWorkshop.Game.Utility.ModSupport.ModSettings;
using DaggerfallWorkshop.Game.Weather;
using DaggerfallWorkshop.Utility;
using DaggerfallWorkshop.Utility.AssetInjection;

using UnityEngine;

namespace SpellcastStudios.TODBackgrounds
{
    public class TODBackgrounds : MonoBehaviour
    {
		// MOD SETTINGS
		static TODBackgrounds instance;
		public static TODBackgrounds Instance { get { return instance ?? (instance = FindObjectOfType<TODBackgrounds>()); } }			
		public static Mod mod { get; private set; }
		
		[SerializeField] private bool dreamGeoBackgrounds = true;
		[SerializeField] private bool cityBackgrounds = true;
		[SerializeField] private bool extraInteriors = true;
		[SerializeField] private bool mainStoryDungeons = true;
		[SerializeField] private bool dungeonTypes = true;
		private string dreamGeoBG = "";
		private int locationBG = 0;
		private int locationPlayer = 0;
		
		PlayerGPS playerGPS = GameManager.Instance.PlayerGPS;
		
		private void LoadSettings()
		{
			var settings = mod.GetSettings();
			dreamGeoBackgrounds = settings.GetBool("Options", "DreamGeoBackgrounds");
			cityBackgrounds = settings.GetBool("Options", "CityBackgrounds");
			extraInteriors = settings.GetBool("Options", "ExtraInteriors");
			mainStoryDungeons = settings.GetBool("Options", "MainStoryDungeons");
			dungeonTypes = settings.GetBool("Options", "DungeonTypes");
			
			if (dreamGeoBackgrounds == false) cityBackgrounds = false;
		}
		//		
		void Update()
		{
			// Track player by storing the Map location ID
			locationPlayer = (int)GameManager.Instance.PlayerGPS.CurrentMapID;
			
			// Geographic Backgrounds DREAM version	(only used when GeoBck is Enabled in DFU Settings)
			if ((DaggerfallUnity.Settings.EnableGeographicBackgrounds) && (instance.dreamGeoBackgrounds))
			{
				// Check if the player is in a City (True only when in a Large Settlement ID=0 ; IsPlayerInTown check is nececeary!)
				bool InCity = false;
				bool CityBG = instance.cityBackgrounds;
				if ((playerGPS.IsPlayerInTown(true)) && ((int)GameManager.Instance.PlayerGPS.CurrentLocationType == 0))
					InCity = true; 
						else InCity = false;
								
				// Set Backgrounds based on climate zones or city climate type (Temperate=01, Desert=02, Mountain=03)
				switch (playerGPS.CurrentClimateIndex)
				{
					// Desert Regions
					case (int)MapsFile.Climates.Desert:
					case (int)MapsFile.Climates.Desert2:
						{ if ((InCity) && (CityBG)) dreamGeoBG = "TOWN02.IMG"; else dreamGeoBG = "SCBG01I0.IMG"; } break;
					
					//Subtropical Regions
					case (int)MapsFile.Climates.Subtropical:
						{ if ((InCity) && (CityBG)) dreamGeoBG = "TOWN02.IMG"; else dreamGeoBG = "SCBG06I0.IMG"; } break;
					
					// Mountain Regions 
					case (int)MapsFile.Climates.Mountain:
					case (int)MapsFile.Climates.MountainWoods:
						{ if ((InCity) && (CityBG)) dreamGeoBG = "TOWN03.IMG"; else dreamGeoBG = "SCBG02I0.IMG"; } break;
					
					// Rainforest Regions
					case (int)MapsFile.Climates.Rainforest:
						{ if ((InCity) && (CityBG)) dreamGeoBG = "TOWN01.IMG"; else dreamGeoBG = "SCBG05I0.IMG"; } break;
					
					// Ocean Region (Player's Ship Exterior or Iliac Bay Region when player is at open sea)
					case (int)MapsFile.Climates.Ocean:
						{ if (((int)GameManager.Instance.PlayerGPS.CurrentLocationType == 14) && (GameManager.Instance.PlayerGPS.IsPlayerInLocationRect))
							dreamGeoBG = "SHIP.IMG"; else dreamGeoBG = "OCEAN.IMG"; } break;
				
					// Swamp Region
					case (int)MapsFile.Climates.Swamp:
						{ if ((InCity) && (CityBG)) dreamGeoBG = "TOWN02.IMG"; else dreamGeoBG = "SCBG07I0.IMG"; } break;
					
					// Temperate Woodlands Regions
					case (int)MapsFile.Climates.Woodlands:
						{ if ((InCity) && (CityBG)) dreamGeoBG = "TOWN01.IMG"; else dreamGeoBG = "SCBG04I0.IMG"; } break;
					
					// Haunted Woodlands and Hill Regions
					case (int)MapsFile.Climates.HauntedWoodlands:
						{ if ((InCity) && (CityBG)) dreamGeoBG = "TOWN03.IMG"; else dreamGeoBG = "SCBG00I0.IMG"; } break;		
				}
				
				// Alternative Graveyard Background
				if (((int)GameManager.Instance.PlayerGPS.CurrentLocationType == 12) && (GameManager.Instance.PlayerGPS.IsPlayerInLocationRect))
					dreamGeoBG = "CEMETERY.IMG";
			}		
		}
		
        private class BackgroundScreen
       	{
            //TODO: Use reflection instead of hardcoding it here
            const int paperDollWidth = 110;
            const int paperDollHeight = 184;
            readonly DFSize backgroundFullSize = new DFSize(125, 198);
            readonly Rect backgroundSubRect = new Rect(8, 7, paperDollWidth, paperDollHeight);

            public UserInterfaceWindow window;
            public PaperDoll paperDoll;
            public Panel backgroundPanel;

            public Texture2D lastSetBackground;
            public List<string> lastTags;

            public BackgroundScreen(UserInterfaceWindow window, PaperDoll paperDoll)
            {
                UpdateWindow(window, paperDoll);
            }

            public void UpdateWindow(UserInterfaceWindow window, PaperDoll paperDoll)
            {
                this.window = window;
                this.paperDoll = paperDoll;

                if (paperDoll != null)
                    this.backgroundPanel = (Panel)GetFieldValue("backgroundPanel", paperDoll);
            }

            private bool RequiresChange()
            {
                if (lastTags == null)
                    return false;

                var newTags = GetTags();

                for (int i = 0; i < lastTags.Count; i++)
                {
                    if (newTags[i] != lastTags[i])
                        return true;
                }
                return false;
            }

            private List<string> GetTags()
            {
                string custom = "";

                bool isPlayerInSnowyRegion = false;
                switch (instance.playerGPS.CurrentClimateIndex)
                {
                    case (int)MapsFile.Climates.Woodlands:
                    case (int)MapsFile.Climates.HauntedWoodlands:
                    case (int)MapsFile.Climates.MountainWoods:
                    case (int)MapsFile.Climates.Mountain:
                        isPlayerInSnowyRegion = true;
                        break;
                }

                if (PlayerIsInFactionBuilding(templeFactions))
                    custom = "_TEMPLE";

                else if (GameManager.Instance.PlayerEnterExit.IsPlayerInsideDungeonCastle)
                    custom = "_CASTLE";

                else if (GameManager.Instance.PlayerEnterExit.IsPlayerInsideDungeon)
                    custom = "_DUNGEON";

                else if ((GameManager.Instance.PlayerEnterExit.IsPlayerInsideOpenShop) && (GameManager.Instance.IsPlayerInside))
					custom = "_OPENSHOP";

                else if ((GameManager.Instance.PlayerEnterExit.IsPlayerInsideTavern) && (GameManager.Instance.IsPlayerInside))
                    custom = "_TAVERN";				
				
                else if (GameManager.Instance.PlayerEnterExit.IsPlayerInside)
                    custom = "_BUILDING";
				
				
				if ((instance.extraInteriors) && (GameManager.Instance.PlayerEnterExit.IsPlayerInside))
				{
					// Backgrounds for Guilds and Knightly Orders
					if (PlayerIsInFactionBuilding(knightFactions)) custom = "_GUILDHALL";		// Fighters Guild & All Knightly Orders
					if (PlayerIsInFactionBuilding(mageFactions)) custom = "_MAGEHALL";			// Mages Guild Unique BG
					if (PlayerIsInFactionBuilding(crimeFactions)) custom = "_UNDERWORLD";		// Thieves Guild & Dark Brotherhood

					// Extra Building Interior Backgrounds			
					switch ((int)GameManager.Instance.PlayerEnterExit.BuildingType)
					{
						case 0: custom = "_ALCHEMIST"; break;   		// Alchemist
						case 2: custom = "_BLACKSMITH"; break;			// Armor Shop
						case 3: custom = "_BANK"; break;   				// Bank
						case 5: custom = "_LIBRARY"; break;				// Library
						case 10: custom = "_LIBRARY"; break; 			// Bookseller
						case 13: custom = "_BLACKSMITH"; break;   		// Weapon Shop				
						case 16: custom = "_PALACE"; break;				// Non-Unique City Palace
					}		
					
					// Player's Ship Interior (Exterior of the ship is shared with the ocean climate background)
					if ((int)GameManager.Instance.PlayerGPS.CurrentLocationType == 14 ) custom = "_SHIP";

					// Player House (Poor Home)
					//if ((int)GameManager.Instance.PlayerGPS.CurrentLocationType == 11 ) custom = "_HOUSE";
					
					// Player House (Wealthy Home)
					//if ((int)GameManager.Instance.PlayerGPS.CurrentLocationType == 8 ) custom = "_MANOR";
				}	
			
				// DREAM Dungeon Backgrounds
				if (GameManager.Instance.PlayerEnterExit.IsPlayerInsideDungeon)
					{				
						// New Backgrounds based on Dungeon Type					
						if (instance.dungeonTypes) switch ((int)GameManager.Instance.PlayerGPS.CurrentLocation.MapTableData.DungeonType)
						{
							case 0: custom = "_DUNGEON"; break;		// Crypt
							case 1: custom = "_ORC"; break;			// Orc Stronghold
							case 2: custom = "_HUMAN"; break;		// Human Stronghold
							case 3: custom = "_PRISON"; break;		// Prison
							case 4: custom = "_DTEMPLE"; break;		// Desecrated Temple
							case 5: custom = "_MINE"; break;		// Mine
							case 6: custom = "_CAVE"; break;		// Natural Cave
							case 7: custom = "_COVEN"; break;		// Coven
							case 8: custom = "_VAMPIRE"; break;		// Vampire Haunt
							case 9: custom = "_LABORATORY"; break;	// Laboratory
							case 10: custom = "_HARPY"; break;		// Harpy Nest
							case 11: custom = "_RCASTLE"; break;	// Ruined Castle
							case 12: custom = "_SPIDER"; break;		// Spider Nest
							case 13: custom = "_GIANT"; break;		// Giant Stronghold
							case 14: custom = "_DRAGON"; break;		// Dragon's Den
							case 15: custom = "_BARBARIAN"; break;	// Barbarian Stronghold
							case 16: custom = "_VOLCANIC"; break;	// Volcanic Caves
							case 17: custom = "_SCORPION"; break;	// Scorpion Nest
							case 18: custom = "_CEMETERY"; break;	// Cemetery
						}
						
						// Main Story Unique Dungeon Backgrounds
						if (instance.mainStoryDungeons) switch (GameManager.Instance.PlayerGPS.CurrentMapID)
						{
							case 187853213: custom = "_DUNGEON"; break;   		// Daggerfall/Privateer's Hold
							case 630439035: custom = "_WAYREST"; break;   		// Wayrest/Wayrest
							case 1291010263: custom = "_DAGGERFALL"; break;  	// Daggerfall/Daggerfall
							case 6634853: custom = "_SENTINEL"; break;     		// Sentinel/Sentinel
							case 19021260: custom = "_ORSINIUM"; break;    		// Orsinium Area/Orsinium
							case 728811286: custom = "_SHEDUNGENT"; break;   	// Wrothgarian Mountains/Shedungent
							case 701948302: custom = "_SBARROW"; break;    		// Dragontail Mountains/Scourg Barrow
							case 83032363: custom = "_WOODBORNE"; break;   	 	// Wayrest/Woodborne Hall
							case 1001: custom = "_CRUX"; break;        			// High Rock sea coast/Mantellan Crux
							case 207828842: custom = "_TOMB"; break;   			// Menevia/Lysandus' Tomb
							case 9570447: custom = "_NECRO"; break;     		// Daggerfall/Castle Necromoghan
							case 2352284: custom = "_TRISTORE"; break;     		// Betony/Tristore Laboratory
							case 336619236: custom = "_BLADES"; break;   		// Ykalon/Castle Llugwych
							case 43196334: custom = "_TOWER"; break;    		// Isle of Balfiera/Direnni Tower
						}
					}
				
                string weather = "";
                var weatherType = GameManager.Instance.WeatherManager.PlayerWeather.WeatherType;

                if ((DaggerfallUnity.Instance.WorldTime.Now.SeasonName == "Winter") && isPlayerInSnowyRegion)
                    weather = "_WINTER";

                else if (weatherType == WeatherType.Rain || weatherType == WeatherType.Rain_Normal)
                    weather = "_RAIN";

                else if (weatherType == WeatherType.Thunder)
                    weather = "_STORM";

                else if (weatherType == WeatherType.Fog)
                    weather = "_FOG";

                else if (weatherType == WeatherType.Overcast)
                    weather = "_OVERCAST";

                string time = "";

                if (DaggerfallUnity.Instance.WorldTime.DaggerfallDateTime.IsNight)
                    time = "_NIGHT";

                return new List<string> { custom, weather, time };
            }

            public void UpdateCurrentTexture()
            {
                string vanillaName = null;

                //Apply builtin racial effect names
                vanillaName = TryGetVampirismTextureName();
                vanillaName = TryGetLycanthropyTextureName();

                //Get vanilla image string
                if (vanillaName == null)
					{
						vanillaName = (string)RunMethod("GetPaperDollBackground", paperDoll, GameManager.Instance.PlayerEntity);
					}

				if (vanillaName == null)
				{
                    Debug.LogError("Could not find vanilla background");
                    return;
				}
				
                string modVanillaName = vanillaName;
				
				// Check if the Player is in the Beast Form and if not use Normal Backgrounds (IMPORTANT PART OF THE CODE)
				if (GameManager.Instance.PlayerEntity.IsInBeastForm == false)
				{
					if (GameManager.Instance.IsPlayerInside) modVanillaName = "interior.IMG"; 
						else if (instance.dreamGeoBackgrounds) modVanillaName = instance.dreamGeoBG;
				}
				//
				
                Texture2D texture = TryFindTexture(modVanillaName, "");

                var tags = GetTags();

                for (int i = 0; i < tags.Count; i++)
                {
                    for (int k = 0; k < tags.Count; k++)
                    {
                        if (i == k)
                            continue;

                        string tagi = tags[i];
                        string tagk = tags[k];
                        Debug.Log(string.Format("{0} {1}", tagi, tagk));

                        if (tagi == "" && tagk == "")
                            continue;

                        var nt = TryFindTexture(modVanillaName, tagi + tagk);

                        if (nt != null)
                            texture = nt;
                    }
                }
				
                if (texture == null)
                    texture = TryFindTexture(modVanillaName, tags[0]);

                //Failed to find texture, so pick vanilla texture
                if (texture == null)
                    texture = ImageReader.GetTexture(vanillaName, 0, 0, false);

                //Apply to background panel
                backgroundPanel.BackgroundTexture = ImageReader.GetSubTexture(texture, backgroundSubRect, backgroundFullSize);
                backgroundPanel.Size = new Vector2(paperDollWidth, paperDollHeight);

                //Save last update
                lastSetBackground = backgroundPanel.BackgroundTexture;
                lastTags = tags;				
            }

            private Texture2D TryFindTexture(string vanillaName, string postfix)
            {
                //Note removal of IMG. this is to get around a DFU bug
                var newTexture = Path.GetFileNameWithoutExtension(vanillaName) + postfix + Path.GetExtension(vanillaName);

                Debug.Log("Trying to find " + newTexture);

                Texture2D output;

                if (TextureReplacement.TryImportImage(newTexture, false, out output))
                    return output;
                return null;
            }

            //Hardcoded grab of varmpirism background
            private string TryGetVampirismTextureName()
            {
                VampirismEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect() as VampirismEffect;

                if (racialOverride == null)
                    return null;

					return "SCBG08I0.IMG";
            }

            //Hardcoded grab of lycanthropy background
            private string TryGetLycanthropyTextureName()
            {
                const string werewolfBackground = "WOLF00I0.IMG";
                const string wereboarBackground = "BOAR00I0.IMG";

                LycanthropyEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect() as LycanthropyEffect;

                if (racialOverride == null)
                    return null;

                // Do nothing if not transformed
                if (!racialOverride.IsTransformed)
                    return null;

                // Get source texture based on lycanthropy type
                string filename;
                switch (racialOverride.InfectionType)
                {
                    case LycanthropyTypes.Werewolf:
                        filename = werewolfBackground;
                        break;
                    case LycanthropyTypes.Wereboar:
                        filename = wereboarBackground;
                        break;
                    default:
                        return null;
                }
                return filename;
            }

            public void Update()
            {
                if (window == null || !window.Enabled)
                    return;

                if (backgroundPanel.BackgroundTexture != lastSetBackground || RequiresChange())
                    UpdateCurrentTexture();
            }
            private static bool PlayerIsInFactionBuilding(List<FactionFile.FactionIDs> factionIds)//, DaggerfallInterior interior)
            {
                var interior = GameManager.Instance.PlayerEnterExit.Interior;

                if (interior == null)
                    return false;

                return factionIds.Contains((FactionFile.FactionIDs)interior.BuildingData.FactionId);
            }
        }

        private BackgroundScreen inventoryBackgroundScreen;
        private BackgroundScreen characterSheetBackgroundScreen;
        private BackgroundScreen tradeBackgroundScreen;

        private UserInterfaceManager uiManager;
        public static List<FactionFile.FactionIDs> templeFactions;
		public static List<FactionFile.FactionIDs> knightFactions;
		public static List<FactionFile.FactionIDs> mageFactions;
		public static List<FactionFile.FactionIDs> crimeFactions;

        public void Awake()
        {
			if (mod != null) LoadSettings();	
			
            templeFactions = new List<FactionFile.FactionIDs>
            {
                FactionFile.FactionIDs.The_Akatosh_Chantry,
                FactionFile.FactionIDs.Akatosh,
                FactionFile.FactionIDs.The_Order_of_Arkay,
                FactionFile.FactionIDs.Arkay,
                FactionFile.FactionIDs.The_House_of_Dibella,
                FactionFile.FactionIDs.Dibella,
                FactionFile.FactionIDs.The_Schools_of_Julianos,
                FactionFile.FactionIDs.Julianos,
                FactionFile.FactionIDs.The_Temple_of_Kynareth,
                FactionFile.FactionIDs.Kynareth,
                FactionFile.FactionIDs.The_Benevolence_of_Mara,
                FactionFile.FactionIDs.Mara,
                FactionFile.FactionIDs.The_Temple_of_Stendarr,
                FactionFile.FactionIDs.Stendarr,
                FactionFile.FactionIDs.The_Resolution_of_Zen,
                FactionFile.FactionIDs.Zen
            };
			
			mageFactions = new List<FactionFile.FactionIDs>
            {
                FactionFile.FactionIDs.The_Mages_Guild
            };
			
			crimeFactions = new List<FactionFile.FactionIDs>
            {
                FactionFile.FactionIDs.The_Thieves_Guild,
				FactionFile.FactionIDs.The_Dark_Brotherhood
            };
			
			knightFactions = new List<FactionFile.FactionIDs>
            {
				FactionFile.FactionIDs.The_Fighters_Guild,
                FactionFile.FactionIDs.The_Host_of_the_Horn,
                FactionFile.FactionIDs.The_Knights_of_the_Dragon,
				FactionFile.FactionIDs.The_Knights_of_the_Flame,
				FactionFile.FactionIDs.The_Knights_of_the_Hawk,
				FactionFile.FactionIDs.The_Knights_of_the_Owl,
				FactionFile.FactionIDs.The_Knights_of_the_Rose,
				FactionFile.FactionIDs.The_Knights_of_the_Wheel,
				FactionFile.FactionIDs.The_Order_of_the_Candle,
				FactionFile.FactionIDs.The_Order_of_the_Raven,
				FactionFile.FactionIDs.The_Order_of_the_Scarab
            };			
        }

        [Invoke(StateManager.StateTypes.Start, 0)]
        public static void Init(InitParams initParams)
        {
            mod = initParams.Mod;

            var go = new GameObject(mod.Title);
            instance = go.AddComponent<TODBackgrounds>();
			mod.IsReady = true;
        }

        private void Start()
        {
            var inventoryWindow = (DaggerfallInventoryWindow)GetFieldValue("dfInventoryWindow", DaggerfallUI.Instance);
            var inventoryPaperDoll = (PaperDoll)GetFieldValue("paperDoll", inventoryWindow);

            inventoryBackgroundScreen = new BackgroundScreen(inventoryWindow, inventoryPaperDoll);

            var characterSheetWindow = (DaggerfallCharacterSheetWindow)GetFieldValue("dfCharacterSheetWindow", DaggerfallUI.Instance);
            var characterSheetPaperDoll = (PaperDoll)GetFieldValue("characterPortrait", characterSheetWindow);

            characterSheetBackgroundScreen = new BackgroundScreen(characterSheetWindow, characterSheetPaperDoll);

            uiManager = (UserInterfaceManager)GetFieldValue("uiManager", DaggerfallUI.Instance);
            uiManager.OnWindowChange += OnWindowChange;

            //Create container for trade window
            tradeBackgroundScreen = new BackgroundScreen(null, null);
        }

        //Detect when window changes and see if it's the trade menu
		// IMPORTANT: This part of the code needs to be like this in order to add compatibility with mods that use dll files !!!
        private void OnWindowChange(object sender, System.EventArgs e)
        {
            var tradeWindow = uiManager.TopWindow as DaggerfallTradeWindow;
            var inventoryWindow = uiManager.TopWindow as DaggerfallInventoryWindow;
            var characterSheetWindow = uiManager.TopWindow as DaggerfallCharacterSheetWindow;

			if ((tradeWindow != null) && (tradeBackgroundScreen.window != tradeWindow))
				{
					var tradePaperDoll = (PaperDoll)GetFieldValue("paperDoll", tradeWindow);
					tradeBackgroundScreen.UpdateWindow(tradeWindow, tradePaperDoll);
					tradeBackgroundScreen.UpdateCurrentTexture();
				}
			
			// CAUTION: These functions add compatibility between DREAM GeoBG system, other mods and DFU Fast Travel system
			if (((inventoryWindow != null) && (inventoryBackgroundScreen.window != inventoryWindow) && (tradeWindow == null)) || (locationBG != locationPlayer))
				{
					var inventoryPaperDoll = (PaperDoll)GetFieldValue("paperDoll", inventoryWindow);
					inventoryBackgroundScreen.UpdateWindow(inventoryWindow, inventoryPaperDoll);
					inventoryBackgroundScreen.UpdateCurrentTexture();
				}
				
			if (((characterSheetWindow != null) && (characterSheetBackgroundScreen.window != characterSheetWindow) && (tradeWindow == null)) || (locationBG != locationPlayer))
				{
					var characterSheetPaperDoll = (PaperDoll)GetFieldValue("characterPortrait", characterSheetWindow);
					characterSheetBackgroundScreen.UpdateWindow(characterSheetWindow, characterSheetPaperDoll);
					characterSheetBackgroundScreen.UpdateCurrentTexture();
				}
			
			// Save the last map location ID in which inv or char sheet is opened (used by functions above to fix fast travel issue)
			if (locationBG != locationPlayer) locationBG = locationPlayer;
        }	
		
        private void LateUpdate()
        {
            inventoryBackgroundScreen.Update();
            characterSheetBackgroundScreen.Update();
            tradeBackgroundScreen.Update();
        }
		
        private static object RunMethod(string method, object fromObject, params object[] parameters)
        {
            var flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
            return (fromObject?.GetType()?.GetMethod(method, flags))?.Invoke(fromObject, parameters);
        }
        private static object GetFieldValue(string field, object fromObject)
        {
            var flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
            return (fromObject?.GetType()?.GetField(field, flags))?.GetValue(fromObject);
        }
    }
}

User avatar
Interkarma
Posts: 7247
Joined: Sun Mar 22, 2015 1:51 am

Re: DFU PlayerEnterExit.cs possible issue

Post by Interkarma »

Cheers. Looks like you're loading the Texture2D object in mod and setting direct to paper doll background. It's your texture object, you have control over filterMode without any changes needed in core.

After a quick read, I'd suggest trying the following. First, locate the below line towards end of UpdateCurrentTexture() method.

Code: Select all

//Apply to background panel
backgroundPanel.BackgroundTexture = ImageReader.GetSubTexture(texture, backgroundSubRect, backgroundFullSize);
This is snipping out a sub-texture and applying to paper doll's backgroundPanel.BackgroundTexture. As GetSubTexture instantiates a new Texture2D instance, it won't have any special filtering properties. You can set this by adding a line like below.

Code: Select all

//Apply to background panel
backgroundPanel.BackgroundTexture = ImageReader.GetSubTexture(texture, backgroundSubRect, backgroundFullSize);
backgroundPanel.BackgroundTexture.filterMode = (FilterMode)DaggerfallUnity.Settings.GUIFilterMode;
The above will set based on GUIFilterMode in settings. Or to inherit the from the original texture use the following instead (assuming source texture has the filterMode you want).

Code: Select all

//Apply to background panel
backgroundPanel.BackgroundTexture = ImageReader.GetSubTexture(texture, backgroundSubRect, backgroundFullSize);
backgroundPanel.BackgroundTexture.filterMode = texture.filterMode;

Post Reply