Daggerfall Collectible Card Game

Show off your mod creations or just a work in progress.
User avatar
Macadaynu
Posts: 261
Joined: Sun Mar 07, 2021 1:18 pm

Daggerfall Collectible Card Game

Post by Macadaynu »

One of my favourite things about some other RPGs are the in game collectible card games; like Gwent from Witcher 3, or Triple Triad from FF8.

Does anyone else think it would be sane to try and implement one as a mod in Daggerfall?

I have an idea for the theme / rules and I have attached a mocked up a draft board design (obviously the cards won't look like Hearthstone cards!)

The theme would be Daedric Princes, who use Daggerfall enemy minions/spells/artefacts to battle each other. You would ask innkeepers to play cards, and can build your card collection by beating them. If you beat enough different innkeepers in a region, you get an invite to the capital of that region for a card tournament. Winning that regional tournament gives you a new Daedric Prince to play as. Each region would have a unique Daedric Prince to collect.

I understand this would be a big undertaking, but willing to give it a go and can go into more details on the mechanics if enough people would be interested.
Attachments
Daedric.jpg
Daedric.jpg (767.71 KiB) Viewed 3205 times

FoldedDice
Posts: 8
Joined: Sun Feb 09, 2020 1:32 am

Re: Daggerfall Collectible Card Game

Post by FoldedDice »

The Might and Magic series is another one that did this to great effect with Arcomage. Something like that would definitely fit into Daggerfall well as a side activity.

User avatar
Macadaynu
Posts: 261
Joined: Sun Mar 07, 2021 1:18 pm

Re: Daggerfall Collectible Card Game

Post by Macadaynu »

FoldedDice wrote: Fri May 21, 2021 9:59 pm The Might and Magic series is another one that did this to great effect with Arcomage. Something like that would definitely fit into Daggerfall well as a side activity.
Oh cool I've not heard of Arcomage, I'll check that out

l3lessed
Posts: 1400
Joined: Mon Aug 12, 2019 4:32 pm
Contact:

Re: Daggerfall Collectible Card Game

Post by l3lessed »

I would love this. There is a similar skyrim mod that adds tavern games, including a simple card game. You could do a ton more in unity than SKSE would allow.

This can be done through the canvas screen space unity object. I had to learn how to get in UI overlays for my compass hud, and you cannot import prefabbed canvas through the mod compiler.

However, I constructed a canvas method to pump out a canvas with all the needed attached components. You could use this to setup the base boards and card slots, then use their anchored3d positions and delta sizes to move them and resize them where you want on screen.

Code: Select all

        //Sets up an object class to create a game object that contains the canvas screen space overlay and any sub canvas layers for things like indicators or overlays.
        GameObject CanvasConstructor(bool giveParentContainer, string canvasName, bool canvasScaler, bool canvasRenderer, bool mask, bool rawImage, bool graphicRaycaster, float width, float height, Vector3 positioning, Texture canvasTexture = null, int screenPosition = 0)
        {
            //sets up main canvas screen space overlay for containing all sub-layers.
            //this covers the full screen as an invisible layer to hold all sub ui layers.
            //creates empty objects.
            GameObject canvasContainer = new GameObject();
            if (giveParentContainer)
            {
                //names it/
                canvasContainer.name = "Canvas Screen Space";
                //grabs and adds the canvasd object from unity library.
                canvasContainer.AddComponent<Canvas>();
                //grabs and adds the canvas scaler object from unity library.
                canvasContainer.AddComponent<CanvasScaler>();
                //grabs and adds the graphic ray caster object from unity library.
                canvasContainer.AddComponent<GraphicRaycaster>();
                //grabs the canvas object.
                Canvas containerCanvas = canvasContainer.GetComponent<Canvas>();
                //sets the screen space to full screen overlay.
                containerCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
            }
            else
                Destroy(canvasContainer);


            //sets up sub layer for adding actual ui and and resizing/moving it.
            GameObject newCanvasObject = new GameObject();
            newCanvasObject.name = canvasName;
            newCanvasObject.AddComponent<Canvas>();

            //sets sublayer to child of the above main container.
            if (giveParentContainer)
                newCanvasObject.transform.SetParent(canvasContainer.transform);

            //grabs canvas from child and sets it to screen overlay. It is an overlay of the main above screen overlay.
            Canvas uiCanvas = newCanvasObject.GetComponent<Canvas>();
            uiCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
            //if then ladder for coder to decide what unity objects they want to add to the canvas for using.
            if(canvasScaler)
                newCanvasObject.AddComponent<CanvasScaler>();
            if (canvasRenderer)
                newCanvasObject.AddComponent<CanvasRenderer>();
            if (graphicRaycaster)
                newCanvasObject.AddComponent<GraphicRaycaster>();
            if (mask)
                newCanvasObject.AddComponent<Mask>();
            if (rawImage)
                newCanvasObject.AddComponent<RawImage>();
            if (canvasTexture != null)
                newCanvasObject.GetComponent<RawImage>().texture = canvasTexture;

            //custom screen positioning method. Coder chooses 0 through 1 for differing screen positions.
            //center in screen/container.
            if(screenPosition == 0)
            {
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().sizeDelta = new Vector2(minimapSize * width, minimapSize * height);
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchorMin = new Vector2(.5f, .5f);
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchorMax = new Vector2(.5f, .5f);
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().pivot = new Vector2(.5f, .5f);
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchoredPosition3D = positioning;
            }
            //top right in screen/container.
            else if (screenPosition == 1)
            {
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().sizeDelta = new Vector2(minimapSize * width, minimapSize * height);
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchorMin = new Vector2(1, 1);
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchorMax = new Vector2(1, 1);
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().pivot = new Vector2(.5f, .5f);
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchoredPosition3D = positioning;
            }

            //returns the objects for the cover to drop into an empty object at any place or anytime they want.
            return newCanvasObject;
        }
couple this with a texture loader

Code: Select all

  #region TextureLoader
        //texture loading method. Grabs the string path the developer inputs, finds the file, if exists, loads it,
        //then resizes it for use. If not, outputs error message.
        public Texture2D LoadPNG(string filePath)
        {

            Texture2D tex = null;
            byte[] fileData;

            if (File.Exists(filePath))
            {
                fileData = File.ReadAllBytes(filePath);
                tex = new Texture2D(2, 2);
                tex.LoadImage(fileData); //..this will auto-resize the texture dimensions.
            }
            else
                Debug.Log("FilePath Broken!");

            return tex;
        }
        #endregion
and here is how they are applied in my mod to create the compass overlay at runtime.

Code: Select all

            //sets up minimap canvas, including the screen space canvas container.
            publicMinimap = CanvasConstructor(true, "Minimap Layer", false, false, true, true, false, 1.03f, 1.03f, new Vector3((minimapSize * .455f) * -1, (minimapSize * .455f) * -1, 0), LoadPNG(Application.dataPath + "/StreamingAssets/Textures/Minimap/MinimapMask.png"), 1);
            //sets up minimap render canvas that render camera texture it projected to.
            publicMinimapRender = CanvasConstructor(false, "Rendering Layer", false, false, true, true, false, 1, 1, new Vector3(0, 0, 0), minimapTexture, 0);
            //sets up bearing directions canvas layer.
            publicDirections = CanvasConstructor(false, "Bearing Layer", false, false, true, true, false, .7f, .7f, new Vector3(0, 0, 0), LoadPNG(Application.dataPath + "/StreamingAssets/Textures/Minimap/DirectionalIndicatorsSmallMarkers.png"), 0);
            //sets up the golden compass canvas layer.
            publicCompass = CanvasConstructor(false, "Compass Layer", false, false, true, true, false, 1.03f, 1.13f, new Vector3((minimapSize * .46f) * -1, (minimapSize * .365f) * -1, 0), LoadPNG(Application.dataPath + "/StreamingAssets/Textures/Minimap/pixalatedGoldCompass.png"), 1);
            //attaches rendering canvas to the main minimap mask canvas.
            publicMinimapRender.transform.SetParent(publicMinimap.transform);
            //attaches the bearing directions canvas to the minimap canvas.
            publicDirections.transform.SetParent(publicMinimap.transform);
            //attaches golden compass canvas to main screen layer canvas.
            publicCompass.transform.SetParent(GameObject.Find("Canvas Screen Space").transform);
            //zeros out bearings canvas position so it centers on its parent canvas layer.
            publicDirections.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchoredPosition3D = new Vector3(0, 0, 0);
            //zeros out rendering canvas position so it centers on its parent canvas layer.
            publicMinimapRender.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchoredPosition3D = new Vector3(0, 0, 0);
            //sets the golden compass canvas to the proper screen position on the main screen space layer so it sits right on top of the rendreing canvas.
            publicCompass.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchoredPosition3D = new Vector3((minimapSize * .46f) * -1, (minimapSize * .365f) * -1, 0);
My Daggerfall Mod Github: l3lessed DFU Mod Github

My Beth Mods: l3lessed Nexus Page

Daggerfall Unity mods: Combat Overhaul Mod

Enjoy the free work I'm doing? Consider lending your support.

User avatar
Daniel87
Posts: 391
Joined: Thu Nov 28, 2019 6:25 pm

Re: Daggerfall Collectible Card Game

Post by Daniel87 »

Macadaynu wrote: Fri May 21, 2021 9:53 pm One of my favourite things about some other RPGs are the in game collectible card games; like Gwent from Witcher 3, or Triple Triad from FF8.

Does anyone else think it would be sane to try and implement one as a mod in Daggerfall?

I have an idea for the theme / rules and I have attached a mocked up a draft board design (obviously the cards won't look like Hearthstone cards!)

The theme would be Daedric Princes, who use Daggerfall enemy minions/spells/artefacts to battle each other. You would ask innkeepers to play cards, and can build your card collection by beating them. If you beat enough different innkeepers in a region, you get an invite to the capital of that region for a card tournament. Winning that regional tournament gives you a new Daedric Prince to play as. Each region would have a unique Daedric Prince to collect.

I understand this would be a big undertaking, but willing to give it a go and can go into more details on the mechanics if enough people would be interested.
Sounds good, problem is: There are plenty of ideas out there. It is the implementation of such that lacks.
A small mod is one thing, but a whole different game inside of a game is another. If you have the endurance to keep it up, I would love to see this ingame, but I doubt that you will find someone who will actively help you raise your brain child, as this sounds like it will be involving a painstaking LOT of work, before it even can be tested.

I do NOT want to discourage you at all, but be aware of the scope you picked for your mod.
I don't know your skill set, but I believe this to be an own game in itself. So, if you can create a whole standalone card game in Unity, you should be up for the task.

Creating all card images will already take weeks worth of work for an artist alone. Maybe you could try and implement the HUD for the game first, as l3lessed suggested and make the cards simple white blanks to test implementation. Once drag and drop + snap to grid works, figure out a state machine for the card game stages and a water-proof rule set. Then the fun part of enemy players AI starts as well as implementing the dialogue option into the dialogue gui. In the end all the card graphics need to be created, as well as some particle effects maybe?
I believe this to be an incredible amount of work and only few have the endurance to see it through to the end. I wish you good luck and will assist you with ideas and help wherever I can, but I am even lagging behind finishing my own mod due to technical issues + being swamped with work IRL as well as working on my own couch coop game right now.
In Julianos we Trust.

User avatar
Macadaynu
Posts: 261
Joined: Sun Mar 07, 2021 1:18 pm

Re: Daggerfall Collectible Card Game

Post by Macadaynu »

l3lessed wrote: Sun May 23, 2021 3:51 am I would love this. There is a similar skyrim mod that adds tavern games, including a simple card game. You could do a ton more in unity than SKSE would allow.

This can be done through the canvas screen space unity object. I had to learn how to get in UI overlays for my compass hud, and you cannot import prefabbed canvas through the mod compiler.

However, I constructed a canvas method to pump out a canvas with all the needed attached components. You could use this to setup the base boards and card slots, then use their anchored3d positions and delta sizes to move them and resize them where you want on screen.

Code: Select all

        //Sets up an object class to create a game object that contains the canvas screen space overlay and any sub canvas layers for things like indicators or overlays.
        GameObject CanvasConstructor(bool giveParentContainer, string canvasName, bool canvasScaler, bool canvasRenderer, bool mask, bool rawImage, bool graphicRaycaster, float width, float height, Vector3 positioning, Texture canvasTexture = null, int screenPosition = 0)
        {
            //sets up main canvas screen space overlay for containing all sub-layers.
            //this covers the full screen as an invisible layer to hold all sub ui layers.
            //creates empty objects.
            GameObject canvasContainer = new GameObject();
            if (giveParentContainer)
            {
                //names it/
                canvasContainer.name = "Canvas Screen Space";
                //grabs and adds the canvasd object from unity library.
                canvasContainer.AddComponent<Canvas>();
                //grabs and adds the canvas scaler object from unity library.
                canvasContainer.AddComponent<CanvasScaler>();
                //grabs and adds the graphic ray caster object from unity library.
                canvasContainer.AddComponent<GraphicRaycaster>();
                //grabs the canvas object.
                Canvas containerCanvas = canvasContainer.GetComponent<Canvas>();
                //sets the screen space to full screen overlay.
                containerCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
            }
            else
                Destroy(canvasContainer);


            //sets up sub layer for adding actual ui and and resizing/moving it.
            GameObject newCanvasObject = new GameObject();
            newCanvasObject.name = canvasName;
            newCanvasObject.AddComponent<Canvas>();

            //sets sublayer to child of the above main container.
            if (giveParentContainer)
                newCanvasObject.transform.SetParent(canvasContainer.transform);

            //grabs canvas from child and sets it to screen overlay. It is an overlay of the main above screen overlay.
            Canvas uiCanvas = newCanvasObject.GetComponent<Canvas>();
            uiCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
            //if then ladder for coder to decide what unity objects they want to add to the canvas for using.
            if(canvasScaler)
                newCanvasObject.AddComponent<CanvasScaler>();
            if (canvasRenderer)
                newCanvasObject.AddComponent<CanvasRenderer>();
            if (graphicRaycaster)
                newCanvasObject.AddComponent<GraphicRaycaster>();
            if (mask)
                newCanvasObject.AddComponent<Mask>();
            if (rawImage)
                newCanvasObject.AddComponent<RawImage>();
            if (canvasTexture != null)
                newCanvasObject.GetComponent<RawImage>().texture = canvasTexture;

            //custom screen positioning method. Coder chooses 0 through 1 for differing screen positions.
            //center in screen/container.
            if(screenPosition == 0)
            {
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().sizeDelta = new Vector2(minimapSize * width, minimapSize * height);
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchorMin = new Vector2(.5f, .5f);
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchorMax = new Vector2(.5f, .5f);
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().pivot = new Vector2(.5f, .5f);
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchoredPosition3D = positioning;
            }
            //top right in screen/container.
            else if (screenPosition == 1)
            {
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().sizeDelta = new Vector2(minimapSize * width, minimapSize * height);
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchorMin = new Vector2(1, 1);
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchorMax = new Vector2(1, 1);
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().pivot = new Vector2(.5f, .5f);
                newCanvasObject.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchoredPosition3D = positioning;
            }

            //returns the objects for the cover to drop into an empty object at any place or anytime they want.
            return newCanvasObject;
        }
couple this with a texture loader

Code: Select all

  #region TextureLoader
        //texture loading method. Grabs the string path the developer inputs, finds the file, if exists, loads it,
        //then resizes it for use. If not, outputs error message.
        public Texture2D LoadPNG(string filePath)
        {

            Texture2D tex = null;
            byte[] fileData;

            if (File.Exists(filePath))
            {
                fileData = File.ReadAllBytes(filePath);
                tex = new Texture2D(2, 2);
                tex.LoadImage(fileData); //..this will auto-resize the texture dimensions.
            }
            else
                Debug.Log("FilePath Broken!");

            return tex;
        }
        #endregion
and here is how they are applied in my mod to create the compass overlay at runtime.

Code: Select all

            //sets up minimap canvas, including the screen space canvas container.
            publicMinimap = CanvasConstructor(true, "Minimap Layer", false, false, true, true, false, 1.03f, 1.03f, new Vector3((minimapSize * .455f) * -1, (minimapSize * .455f) * -1, 0), LoadPNG(Application.dataPath + "/StreamingAssets/Textures/Minimap/MinimapMask.png"), 1);
            //sets up minimap render canvas that render camera texture it projected to.
            publicMinimapRender = CanvasConstructor(false, "Rendering Layer", false, false, true, true, false, 1, 1, new Vector3(0, 0, 0), minimapTexture, 0);
            //sets up bearing directions canvas layer.
            publicDirections = CanvasConstructor(false, "Bearing Layer", false, false, true, true, false, .7f, .7f, new Vector3(0, 0, 0), LoadPNG(Application.dataPath + "/StreamingAssets/Textures/Minimap/DirectionalIndicatorsSmallMarkers.png"), 0);
            //sets up the golden compass canvas layer.
            publicCompass = CanvasConstructor(false, "Compass Layer", false, false, true, true, false, 1.03f, 1.13f, new Vector3((minimapSize * .46f) * -1, (minimapSize * .365f) * -1, 0), LoadPNG(Application.dataPath + "/StreamingAssets/Textures/Minimap/pixalatedGoldCompass.png"), 1);
            //attaches rendering canvas to the main minimap mask canvas.
            publicMinimapRender.transform.SetParent(publicMinimap.transform);
            //attaches the bearing directions canvas to the minimap canvas.
            publicDirections.transform.SetParent(publicMinimap.transform);
            //attaches golden compass canvas to main screen layer canvas.
            publicCompass.transform.SetParent(GameObject.Find("Canvas Screen Space").transform);
            //zeros out bearings canvas position so it centers on its parent canvas layer.
            publicDirections.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchoredPosition3D = new Vector3(0, 0, 0);
            //zeros out rendering canvas position so it centers on its parent canvas layer.
            publicMinimapRender.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchoredPosition3D = new Vector3(0, 0, 0);
            //sets the golden compass canvas to the proper screen position on the main screen space layer so it sits right on top of the rendreing canvas.
            publicCompass.GetComponentInChildren<RawImage>().GetComponent<RectTransform>().anchoredPosition3D = new Vector3((minimapSize * .46f) * -1, (minimapSize * .365f) * -1, 0);

Thanks for the help / info l3lessed, I think the first step would be getting a rough prototype built, just to see if I can solve the main problems that need to be solved.

Ps. your minimap mod will become essential I think, looking forward to trying that out :)

User avatar
Macadaynu
Posts: 261
Joined: Sun Mar 07, 2021 1:18 pm

Re: Daggerfall Collectible Card Game

Post by Macadaynu »

Daniel87 wrote: Sun May 23, 2021 5:21 am
Sounds good, problem is: There are plenty of ideas out there. It is the implementation of such that lacks.
A small mod is one thing, but a whole different game inside of a game is another. If you have the endurance to keep it up, I would love to see this ingame, but I doubt that you will find someone who will actively help you raise your brain child, as this sounds like it will be involving a painstaking LOT of work, before it even can be tested.

I do NOT want to discourage you at all, but be aware of the scope you picked for your mod.
I don't know your skill set, but I believe this to be an own game in itself. So, if you can create a whole standalone card game in Unity, you should be up for the task.

Creating all card images will already take weeks worth of work for an artist alone. Maybe you could try and implement the HUD for the game first, as l3lessed suggested and make the cards simple white blanks to test implementation. Once drag and drop + snap to grid works, figure out a state machine for the card game stages and a water-proof rule set. Then the fun part of enemy players AI starts as well as implementing the dialogue option into the dialogue gui. In the end all the card graphics need to be created, as well as some particle effects maybe?
I believe this to be an incredible amount of work and only few have the endurance to see it through to the end. I wish you good luck and will assist you with ideas and help wherever I can, but I am even lagging behind finishing my own mod due to technical issues + being swamped with work IRL as well as working on my own couch coop game right now.
Yep totally aware this is a huge amount of work. In terms of implementation I think my main concern is the time it will take. This might take me an awfully long time, but then again that's the beauty of hobby projects, there is no deadline! And even if I did get burned out I could always make this open source so someone else could pick up where I left off.

Also I am no visual artist, coding wise I could do this, but making it look pretty is something I would either need help with, or learn how to do it as I go.

So that was the reason for this topic, just wanted a sanity check before I poured a lot of time into something that people wouldn't end up using, but feedback seems positive so far.

Thanks for the feedback :)

l3lessed
Posts: 1400
Joined: Mon Aug 12, 2019 4:32 pm
Contact:

Re: Daggerfall Collectible Card Game

Post by l3lessed »

Don't forget, you also have the GUI class to call. It works like an update routine, but for the users current Graphical Interface. This may be the better way to go, as it is more dynamic, and allows for custom GUI style classes, which you could setup for card types or really anything, then just apply them to the GUI/Card objects you want. The hard part is tying and properly resizing the objects using the players dynamic Screen.Width() and Screen.Height(). I found multiplying these by a set percentage tends to be the best way, so if you wanted a card that was a rectangle that resized with the players screen width and height, you would do

Code: Select all

            minimapWidth = Screen.width * .035f;
            minimapHeight = Screen.height * .05f;
Same with their placement on screen. However, once you get the numbers setup where you want, it will scale properly, no matter the users resolution choice.

https://docs.unity3d.com/ScriptReference/GUI.html

I use this to create the quick scroll menu in my mod.

Code: Select all

using System;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.UI;

namespace DaggerfallWorkshop.Game.Minimap
{
    public class MinimapGUI : MonoBehaviour
{
        //Prefab objects.
        private GUIStyle currentStyle;
        private GUIStyle currentToggleStyle;

        private Texture2D compassMenu;       

        public Rect minimapControlsRect = new Rect(20, 20, 120, 50);
        public Rect indicatorControlRect = new Rect(20, 100, 120, 50);

        public Color lastColor;

        public float redValue = Minimap.iconGroupColors[Minimap.MarkerGroups.Shops].r;
        public float blueValue = Minimap.iconGroupColors[Minimap.MarkerGroups.Shops].b;
        public float greenValue = Minimap.iconGroupColors[Minimap.MarkerGroups.Shops].g;
        public float alphaValue = 1f;
        public float blendValue;
        public static Color colorSelector = Minimap.iconGroupColors[Minimap.MarkerGroups.Shops];
        public float lastBlend;
        public float lastAlphaValue;
        public float minimapRotationValue;

        private int selectedIconInt = 0;

        public bool lastIconGroupActive;
        public bool lastLabelActive;
        public bool lastIndicatorActive;
        public bool labelIndicatorActive = true;
        public bool iconsIndicatorActive = true;
        public bool smartViewActive = true;
        public bool autoRotateActive;
        public bool minimapMenuEnabled;
        public bool updateMinimap;
        public bool fullScreenMinimap;

        private string selectedIcon = "Shops";
        public bool realDetectionEnabled = true;
        public bool cameraDetectionEnabled;
        private string viewType;

        private void Start()
        {
            compassMenu = Minimap.MinimapInstance.LoadPNG(Application.dataPath + "/StreamingAssets/Textures/Minimap/ScrollCleaned.png");
        }

        void OnGUI()
        {
            if (!minimapMenuEnabled)
                return;

            if (currentStyle == null)
            {
                currentStyle = new GUIStyle(GUI.skin.box);
                currentStyle.normal.background = compassMenu;
                currentStyle.normal.textColor = Color.black;
                currentStyle.fontStyle = FontStyle.Bold;
                currentStyle.fontSize = 14;
            }

            // Register the window. We create two windows that use the same function
            // Notice that their IDs differ
            
            minimapControlsRect = GUI.Window(0, new Rect(Screen.width * .4f, Screen.height * .25f, 270, 350), MinimapControls, "Enchantment Adjustments", currentStyle);
        }

        // Make the contents of the window
        void MinimapControls(int windowID)
        {
            GUI.contentColor = Color.black;
            if (currentToggleStyle == null)
            {
                GUI.contentColor = Color.black;
                currentToggleStyle = new GUIStyle(GUI.skin.toggle);
                currentToggleStyle.normal.textColor = Color.black;
                currentToggleStyle.fontSize = 14;
                currentToggleStyle.fontStyle = FontStyle.Bold;
            }

            //view size label and buttons below.
            GUI.Label(new Rect(10, 44, 90, 25), "View Size:", currentStyle);

            if (GUI.RepeatButton(new Rect(95, 44, 25, 25), "+", currentStyle))
            {
                if (GameManager.Instance.IsPlayerInside)
                    Minimap.MinimapInstance.minimapViewSize += .1f;
                else
                    Minimap.MinimapInstance.minimapViewSize += 1;
            }

            if (GUI.RepeatButton(new Rect(115, 44, 25, 25), "-", currentStyle) && Minimap.MinimapInstance.minimapCamera.orthographicSize > 0)
            {
                if (GameManager.Instance.IsPlayerInside)
                    Minimap.MinimapInstance.minimapViewSize -= .1f;
                else
                    Minimap.MinimapInstance.minimapViewSize -= 1;
            }

            //map size label and buttons below.
            GUI.Label(new Rect(10, 68, 90, 25), "Map Size:", currentStyle);

            if (GUI.RepeatButton(new Rect(95, 68, 25, 25), "+", currentStyle))
            {
                Minimap.MinimapInstance.minimapSize += Screen.width * .001f;
            }

            if (GUI.RepeatButton(new Rect(115, 68, 25, 25), "-", currentStyle) && Minimap.MinimapInstance.minimapCamera.orthographicSize > 0)
            {
                Minimap.MinimapInstance.minimapSize -= Screen.width * .001f;
            }

            //auto rotate button and rotation value buttons below., which are enabled only when auto rotate is off
            autoRotateActive = GUI.Toggle(new Rect(150, 44, 90, 25), autoRotateActive, "Auto Rotate", currentStyle);

            if (!autoRotateActive)
            {
                if (GUI.RepeatButton(new Rect(170, 68, 25, 25), "+", currentStyle))
                {
                    minimapRotationValue += 1;
                }

                if (GUI.RepeatButton(new Rect(190, 68, 25, 25), "-", currentStyle))
                {
                    minimapRotationValue -= 1;
                }
            }

            //transperency label and value bar.
            GUI.Label(new Rect(10, 90, 115, 25), "Transparency:", currentStyle);
            alphaValue = GUI.HorizontalSlider(new Rect(125, 96, 120, 20), alphaValue, 0, 1);

            //list of general minimap toggle settings.
            labelIndicatorActive = GUI.Toggle(new Rect(15, 110, 60, 25), labelIndicatorActive, "Labels", currentToggleStyle);
            smartViewActive = GUI.Toggle(new Rect(98, 110, 90, 25), smartViewActive, "Smart View", currentToggleStyle);
            iconsIndicatorActive = GUI.Toggle(new Rect(15, 130, 60, 25), iconsIndicatorActive, "Icons", currentToggleStyle);
            realDetectionEnabled = GUI.Toggle(new Rect(98, 130, 150, 25), realDetectionEnabled, "Realistic Detection", currentToggleStyle);

            if(!realDetectionEnabled)
            cameraDetectionEnabled = GUI.Toggle(new Rect(15, 150, 150, 25), cameraDetectionEnabled, "In View Detection", currentToggleStyle);

            if (realDetectionEnabled)
            {
                GUI.Label(new Rect(10, 150, 50, 25), "Area", currentStyle);
                Minimap.minimapSensingRadius = GUI.HorizontalSlider(new Rect(60, 157, 145, 25), Minimap.minimapSensingRadius, 0, 100);
                float.TryParse(GUI.TextField(new Rect(205, 150, 55, 25), Regex.Replace(Math.Round(Mathf.Clamp(Minimap.minimapSensingRadius,0f,100f),1).ToString(), @"^[0-9][0-9][0-9][0-9]", ""), currentStyle), out Minimap.minimapSensingRadius);
            }

            //--->Start of indicator settings area<---\\

            //label and buttons for selecting current indicator type.
            if (GUI.Button(new Rect(25, 178, 25, 25), "<", currentStyle))
            {
                if (selectedIconInt != 0)
                {
                    selectedIconInt = selectedIconInt - 1;
                    selectedIcon = Enum.GetValues(typeof(Minimap.MarkerGroups)).GetValue(selectedIconInt).ToString();
                    redValue = Minimap.iconGroupColors[(Minimap.MarkerGroups)selectedIconInt].r;
                    greenValue = Minimap.iconGroupColors[(Minimap.MarkerGroups)selectedIconInt].g;
                    blueValue = Minimap.iconGroupColors[(Minimap.MarkerGroups)selectedIconInt].b;
                    blendValue = Minimap.iconGroupTransperency[(Minimap.MarkerGroups)selectedIconInt];
                }
            }

            //display current selected indicator group we are adjusting.
            GUI.Box(new Rect(50, 178, 150, 25), selectedIcon, currentStyle);

            //setup next button for indicator selector.
            if (GUI.Button(new Rect(202, 178, 25, 25), ">", currentStyle))
            {
                if (selectedIconInt != Enum.GetValues(typeof(Minimap.MarkerGroups)).Length - 2)
                {
                    selectedIconInt = selectedIconInt + 1;
                    selectedIcon = Enum.GetValues(typeof(Minimap.MarkerGroups)).GetValue(selectedIconInt).ToString();
                    redValue = Minimap.iconGroupColors[(Minimap.MarkerGroups)selectedIconInt].r;
                    greenValue = Minimap.iconGroupColors[(Minimap.MarkerGroups)selectedIconInt].g;
                    blueValue = Minimap.iconGroupColors[(Minimap.MarkerGroups)selectedIconInt].b;
                    blendValue = Minimap.iconGroupTransperency[(Minimap.MarkerGroups)selectedIconInt];
                }

            }

            //setup text fields to label RGB sliders.
            GUI.Label(new Rect(10, 205, 50, 25), "Red", currentStyle);
            GUI.Label(new Rect(10, 228, 50, 25), "Green", currentStyle);
            GUI.Label(new Rect(10, 251, 50, 25), "Blue", currentStyle);
            GUI.Label(new Rect(10, 274, 50, 25), "Clear", currentStyle);

            //setup RGB sliders.
            redValue = GUI.HorizontalSlider(new Rect(60, 210, 145, 25), redValue, 0, 1);
            float.TryParse(GUI.TextField(new Rect(205, 203, 55, 25), Regex.Replace(Math.Round(Mathf.Clamp(redValue, 0f, 1f), 3).ToString(), @"^[0-9][0-9][0-9][0-9]", ""), currentStyle), out redValue);
            greenValue = GUI.HorizontalSlider(new Rect(60, 233, 145, 25), greenValue, 0, 1);
            float.TryParse(GUI.TextField(new Rect(205, 226, 55, 25), Regex.Replace(Math.Round(Mathf.Clamp(greenValue, 0f, 1f), 3).ToString(), @"^[0-9][0-9][0-9][0-9]", ""), currentStyle), out greenValue);
            blueValue = GUI.HorizontalSlider(new Rect(60, 256, 145, 25), blueValue, 0, 1);
            float.TryParse(GUI.TextField(new Rect(205, 249, 55, 25), Regex.Replace(Math.Round(Mathf.Clamp(blueValue, 0f, 1f),3).ToString(), @"^[0-9][0-9][0-9][0-9]", ""), currentStyle), out blueValue);
            blendValue = GUI.HorizontalSlider(new Rect(60, 279, 145, 25), blendValue, 0, 1);
            float.TryParse(GUI.TextField(new Rect(205, 272, 55, 25), Regex.Replace(Math.Round(Mathf.Clamp(blendValue, 0f, 1f), 3).ToString(), @"^[0-9][0-9][0-9][0-9]", ""), currentStyle), out blendValue);
            Minimap.iconGroupActive[(Minimap.MarkerGroups)selectedIconInt] = GUI.Toggle(new Rect(15, 294, 60, 25), Minimap.iconGroupActive[(Minimap.MarkerGroups)selectedIconInt], "Mark", currentToggleStyle);           

            //assign selected color to color selector.
            colorSelector = new Color(redValue, greenValue, blueValue, 1);

            //check if any controls have been updated, and if so, pushed window trigger update.
            if (lastColor != colorSelector || blendValue != lastBlend || alphaValue != lastAlphaValue || labelIndicatorActive != lastLabelActive || iconsIndicatorActive != lastIndicatorActive || lastIconGroupActive != Minimap.iconGroupActive[(Minimap.MarkerGroups)selectedIconInt])
            {
                updateMinimap = true;
            }

            //updates minimap ui by assigning control values and storing for checking for changes.
            if (updateMinimap)
            {
                updateMinimap = false;
                updateMinimapUI();
            }

        }       

        public void updateMinimapUI()
        {
            //sets icon group color and blend/transperency value.
            Minimap.iconGroupColors[(Minimap.MarkerGroups)selectedIconInt] = colorSelector;
            Minimap.iconGroupTransperency[(Minimap.MarkerGroups)selectedIconInt] = blendValue;

            Debug.Log(Minimap.iconGroupColors[(Minimap.MarkerGroups)selectedIconInt]);

            //sets minimap transperency level.
            Minimap.MinimapInstance.publicMinimap.GetComponentInChildren<RawImage>().color = new Color(1, 1, 1, .01f);
            Minimap.MinimapInstance.publicMinimapRender.GetComponentInChildren<RawImage>().color = new Color(1, 1, 1, alphaValue);
            Minimap.MinimapInstance.publicCompass.GetComponentInChildren<RawImage>().color = new Color(1, 1, 1, alphaValue);

            //sets stores current values to check for changes as update loops.
            lastColor = colorSelector;
            lastBlend = blendValue;
            lastAlphaValue = alphaValue;
            lastIconGroupActive = Minimap.iconGroupActive[(Minimap.MarkerGroups)selectedIconInt];
            lastLabelActive = labelIndicatorActive;
            lastIndicatorActive = iconsIndicatorActive;

            //runs indicator code, which destroys and rebuilds indicators to refresh them.
            //need to add a refresh routine, so don't have to keep rebuilding anytime we want to refresh.
            Minimap.MinimapInstance.UpdateBuildingMarkers();
            Minimap.MinimapInstance.SetupPlayerIndicator();
            Minimap.MinimapInstance.SetupNPCIndicators();
            Minimap.MinimapInstance.SetupMinimapCameras();            
            Minimap.MinimapInstance.UpdateNpcMarkers();
        }
    }
}
My Daggerfall Mod Github: l3lessed DFU Mod Github

My Beth Mods: l3lessed Nexus Page

Daggerfall Unity mods: Combat Overhaul Mod

Enjoy the free work I'm doing? Consider lending your support.

User avatar
emmathepony
Posts: 248
Joined: Sat Jun 29, 2019 5:26 pm

Re: Daggerfall Collectible Card Game

Post by emmathepony »

I'd LOVE to see this in the game!

User avatar
Macadaynu
Posts: 261
Joined: Sun Mar 07, 2021 1:18 pm

Re: Daggerfall Collectible Card Game

Post by Macadaynu »

emmathepony wrote: Sat Jun 05, 2021 3:07 pm I'd LOVE to see this in the game!
Thanks, a small progress update regarding this, I've made a basic board and card loader, the art is all placeholder but there's a basic framework to build on:



Bear in mind you won't be able to attack your own minions! Mechanically I have a few different ideas, but wanting to get the basics down first. AI will be fun, not tried that before :lol:

This is going to take me a long time I can tell, but having fun doing it when I can if I get any free time.

Post Reply