Acquisition

A curated forum for compatible and maintained mods. Users are unable to create new topics in this forum but can reply to existing topics. Please message a moderator to have your mod moved into this forum area.
Post Reply
User avatar
John Doom
Posts: 126
Joined: Wed Dec 01, 2021 5:59 pm
Location: Italy
Contact:

Acquisition

Post by John Doom »

Mod to acquire shops and taverns.

DOWNLOAD: https://www.nexusmods.com/daggerfallunity/mods/261/

Image
Last edited by John Doom on Sat Jan 22, 2022 12:46 pm, edited 14 times in total.

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

Re: Acquisition

Post by Magicono43 »

Hey, glad somebody is working on this. In terms of my mod Limited Gold Shops, I guess end of the day when this gets to a release state. Can possibly always make a "patched" version that has LGS buried inside of this mod sort of deal for those that want both. At least that would be the best way I could think of to deal with the overriding the same windows issue for now. Keep it up.

User avatar
Shapur
Posts: 154
Joined: Wed Apr 21, 2021 5:11 pm
Location: Czech Republic
Contact:

Re: Acquisition

Post by Shapur »

Looks interesting ;)
Magicono43 wrote: Mon Dec 20, 2021 1:06 pm Hey, glad somebody is working on this. In terms of my mod Limited Gold Shops, I guess end of the day when this gets to a release state. Can possibly always make a "patched" version that has LGS buried inside of this mod sort of deal for those that want both. At least that would be the best way I could think of to deal with the overriding the same windows issue for now. Keep it up.
Yeah, merging the mods sounds like the least headache inducing way of making them compatible.
Link to my github here.
And here is my nexus profile.

User avatar
John Doom
Posts: 126
Joined: Wed Dec 01, 2021 5:59 pm
Location: Italy
Contact:

Re: Acquisition

Post by John Doom »

:) Thanks for your replies.
I've updated my mod with the ability to save to file the acquisitions, so no need to keep them in inventory all the time, but they can't be sold anymore (not that I've ever tried yet, we'll see).
Quetion about DaggerfallUnityItem: I'm trying to make acquisitions into a new kind of item which shows informations when "used"; so I've created a custom class, but after reloading a save it seems the game forgets the item has a custom class and the custom UseItem function isn't called anymore. Any idea? :?:

Code: Select all

using DaggerfallConnect;
using DaggerfallWorkshop;
using DaggerfallWorkshop.Game;
using DaggerfallWorkshop.Game.Items;
using System;
using static DaggerfallWorkshop.PlayerGPS;

[Serializable]
public class AcquisitionContract : DaggerfallUnityItem
{
    public DiscoveredBuilding building;
    public DFLocation location;

    const string TAG = "Acquisition, ";

    public AcquisitionContract(DiscoveredBuilding building, DFLocation location) :
        base(ItemGroups.UselessItems2,
        DaggerfallUnity.Instance.ItemHelper.GetGroupIndex(ItemGroups.UselessItems2, (int)UselessItems2.Parchment))
    {
        this.building = building;
        this.location = location;

        RenameItem(TAG + building.displayName);
        value = (Acquisition.Acquisition.TESTING ? 1 : 10000) * building.quality;
    }

    public override bool UseItem(ItemCollection collection)
    {
        string town = location.Name;
        string region = location.RegionName;

        string text = "Acquisition contract for " + building.displayName + " in " + location.Name;
        if (town != region) text += " (" + region + ")";
        text += ".";

        DaggerfallUI.MessageBox(text);
        return true;
    }

    public static bool GetIsAcquisition(DaggerfallUnityItem item)
    {
        return item.ItemName.Contains(TAG);
    }
}

User avatar
Shapur
Posts: 154
Joined: Wed Apr 21, 2021 5:11 pm
Location: Czech Republic
Contact:

Re: Acquisition

Post by Shapur »

John Doom wrote: Mon Dec 20, 2021 2:35 pm :) Thanks for your replies.
I've updated my mod with the ability to save to file the acquisitions, so no need to keep them in inventory all the time, but they can't be sold anymore (not that I've ever tried yet, we'll see).
Quetion about DaggerfallUnityItem: I'm trying to make acquisitions into a new kind of item which shows informations when "used"; so I've created a custom class, but after reloading a save it seems the game forgets the item has a custom class and the custom UseItem function isn't called anymore. Any idea? :?:

Code: Select all

using DaggerfallConnect;
using DaggerfallWorkshop;
using DaggerfallWorkshop.Game;
using DaggerfallWorkshop.Game.Items;
using System;
using static DaggerfallWorkshop.PlayerGPS;

[Serializable]
public class AcquisitionContract : DaggerfallUnityItem
{
    public DiscoveredBuilding building;
    public DFLocation location;

    const string TAG = "Acquisition, ";

    public AcquisitionContract(DiscoveredBuilding building, DFLocation location) :
        base(ItemGroups.UselessItems2,
        DaggerfallUnity.Instance.ItemHelper.GetGroupIndex(ItemGroups.UselessItems2, (int)UselessItems2.Parchment))
    {
        this.building = building;
        this.location = location;

        RenameItem(TAG + building.displayName);
        value = (Acquisition.Acquisition.TESTING ? 1 : 10000) * building.quality;
    }

    public override bool UseItem(ItemCollection collection)
    {
        string town = location.Name;
        string region = location.RegionName;

        string text = "Acquisition contract for " + building.displayName + " in " + location.Name;
        if (town != region) text += " (" + region + ")";
        text += ".";

        DaggerfallUI.MessageBox(text);
        return true;
    }

    public static bool GetIsAcquisition(DaggerfallUnityItem item)
    {
        return item.ItemName.Contains(TAG);
    }
}
You need to give your item class a GetSaveData() method, like this.

EDIT: For more items related examples, you can look here.
Link to my github here.
And here is my nexus profile.

User avatar
John Doom
Posts: 126
Joined: Wed Dec 01, 2021 5:59 pm
Location: Italy
Contact:

Re: Acquisition

Post by John Doom »

I figured I was missing the template, didn't even know it existed lol
Anyway, I got the custom class to work... except it couldn't save the special parameters. So I've used a trick to save them as enchantment (temporary solution anyway) and now they work.
...
HOWEVER
...
I have problem with broken saves: even when starting with an old unmodded save, it believes I have a contract I did in another save. It's making me crazy :|

UPDATE: it doesn't happen if I make a new character.
UPDATE2: added ability to buy taverns :lol:

Code: Select all

using DaggerfallWorkshop;
using DaggerfallWorkshop.Game;
using DaggerfallWorkshop.Game.Banking;
using DaggerfallWorkshop.Game.Items;
using DaggerfallWorkshop.Game.UserInterface;
using DaggerfallWorkshop.Game.UserInterfaceWindows;
using DaggerfallWorkshop.Game.Utility.ModSupport;
using DaggerfallWorkshop.Utility;
using System;
using System.Collections.Generic;
using UnityEngine;
using static DaggerfallWorkshop.PlayerGPS;

namespace Acquisition
{
    [FullSerializer.fsObject("v1")]
    public class SaveData
    {
        public List<AcquisitionContract> acquisitions;
    }

    public class Acquisition: MonoBehaviour, IHasModSaveData
    {
        static Mod mod;
        static Acquisition instance;
        public static bool TESTING = true;

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

            GameObject go = new GameObject("Acquisition");
            instance = go.AddComponent<Acquisition>();
            mod.SaveDataInterface = instance;

            DaggerfallUnity.Instance.ItemHelper.RegisterCustomItem(AcquisitionContract.TEMPLATE_INDEX, ItemGroups.UselessItems2, typeof(AcquisitionContract));

            if (TESTING) WorldTime.OnNewHour += OnNewMonth; else WorldTime.OnNewMonth += OnNewMonth;
            DaggerfallUI.UIManager.OnWindowChange += OnWindowChange;

            mod.IsReady = true;
        }

        static void OnNewMonth()
        {
            //update profits
            foreach (AcquisitionContract contract in acquisitions)
            {
                //find region
                int regionIndex = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetRegionIndex(contract.GetRegion());

                //add amount to bank
                int amount = contract.value / DaggerfallDateTime.MonthsPerYear;
                GameManager.Instance.PlayerEntity.GoldPieces += amount;
                DaggerfallBankManager.MakeTransaction(TransactionType.Depositing_gold,
                    amount, regionIndex);

                //notify player
                string message = contract.GetBuilding() + "'s profits: +" + amount + " on " + contract.GetRegion() + "'s account.";
                DaggerfallUI.Instance.PlayOneShot(SoundClips.GoldPieces);
                DaggerfallUI.MessageBox(message, true);
            }
        }

        static void OnWindowChange(object sender, EventArgs e)
        {
            IUserInterfaceWindow window = ((UserInterfaceManager)sender).TopWindow;
            if (window.GetType() == typeof(DaggerfallTradeWindow))
            {
                //if trade opened
                DaggerfallTradeWindow tradeWindow = (DaggerfallTradeWindow)window;
                if (tradeWindow.PreviousWindow == null)
                {
                    //if not from sell, register event and fire
                    tradeWindow.OnClose += OnTradeClosed;
                    OnTradeOpened(tradeWindow.MerchantItems);
                }
            }
        }

        static void OnTradeOpened(ItemCollection collection)
        {
            Debug.LogError("opened");
            DiscoveredBuilding building = GameManager.Instance.PlayerEnterExit.BuildingDiscoveryData;

            //remove leftovers
            for (int i = 0; i < collection.Count; i++)
            {
                DaggerfallUnityItem item = collection.GetItem(i);
                if (item.GetType() == typeof(AcquisitionContract))
                {
                    collection.RemoveItem(item);
                    i--;
                }
            }

            //return if owned
            foreach (AcquisitionContract contractOwned in acquisitions)
            {
                if (contractOwned.GetBuilding() == building.displayName)
                    return;
            }

            //add contract
            DaggerfallUnityItem contract = new AcquisitionContract(building,
                GameManager.Instance.PlayerGPS.CurrentLocation);
            collection.AddItem(contract);
        }

        static void OnTradeClosed()
        {
            Debug.LogError("closed");
            ItemCollection items = GameManager.Instance.PlayerEntity.Items;
            for (int i = 0; i < items.Count; i++)
            {
                DaggerfallUnityItem item = items.GetItem(i);
                if (item.GetType() == typeof(AcquisitionContract))
                {
                    AcquisitionContract contract = (AcquisitionContract)item;
                    bool isOld = false;
                    foreach (AcquisitionContract contractOld in acquisitions)
                    {
                        if (contract.GetEqual(contractOld))
                        {
                            isOld = true;
                            break;
                        }
                    }
                    if (!isOld)
                    {
                        //save new contract
                        acquisitions.Add(contract);

                        //improve reputation
                        GameManager.Instance.PlayerEntity.FactionData.ChangeReputation(
                            contract.GetFactionID(),
                            10,
                            true);
                    }
                }
            }
        }


        public static List<AcquisitionContract> acquisitions = new List<AcquisitionContract>();

        public Type SaveDataType
        {
            get { return typeof(SaveData); }
        }

        public object NewSaveData()
        {
            return new SaveData
            {
                acquisitions = new List<AcquisitionContract>()
            };
        }

        public object GetSaveData()
        {
            return new SaveData
            {
                acquisitions = acquisitions
            };
        }

        public void RestoreSaveData(object saveData)
        {
            SaveData data = (SaveData)saveData;
            acquisitions = data.acquisitions;
        }
    }
}

Code: Select all

using DaggerfallConnect;
using DaggerfallWorkshop;
using DaggerfallWorkshop.Game;
using DaggerfallWorkshop.Game.Items;
using DaggerfallWorkshop.Game.MagicAndEffects;
using DaggerfallWorkshop.Game.Serialization;
using System;
using UnityEngine;
using static DaggerfallWorkshop.PlayerGPS;

public class AcquisitionContract : DaggerfallUnityItem
{
    public const int TEMPLATE_INDEX = 1317;
    const char SEPARATOR = '/';

    public AcquisitionContract() :
        base(ItemGroups.UselessItems2, TEMPLATE_INDEX)
    {
    }
    public AcquisitionContract(DiscoveredBuilding building, DFLocation location) :
        base(ItemGroups.UselessItems2, TEMPLATE_INDEX)
    {
        //save data
        CustomEnchantment spell = new CustomEnchantment();
        spell.EffectKey =
            building.displayName + SEPARATOR +
            location.Name + SEPARATOR +
            location.RegionName + SEPARATOR +
            building.factionID;
        customMagic = new CustomEnchantment[] { spell };

        //edit
        shortName = GetName();
        value = (Acquisition.Acquisition.TESTING ? 1 : 10000) * building.quality;
    }

    public override bool UseItem(ItemCollection collection)
    {
        string name = GetBuilding();
        string town = GetTown();
        string region = GetRegion();

        string message = "Acquisition contract for " + name;
        if (name != town) message += " in " + town;
        if (town != region) message += " (" + region + ")";
        message += ".";

        DaggerfallUI.MessageBox(message, true);
        return true;
    }


    string GetData(int ind)
    {
        return customMagic[0].EffectKey.Split(SEPARATOR)[ind];
    }

    public string GetBuilding()
    {
        return GetData(0);
    }

    public string GetTown()
    {
        return GetData(1);
    }

    public string GetRegion()
    {
        return GetData(2);
    }

    public int GetFactionID()
    {
        return int.Parse(GetData(3));
    }

    public bool GetEqual(AcquisitionContract contract)
    {
        return GetBuilding() == contract.GetBuilding();
    }


    public override bool IsEnchanted
    {
        get { return false; }
    }

    public override string ItemName
    {
        get { return GetName(); }
    }

    public override string LongName
    {
        get { return GetName(); }
    }

    string GetName()
    {
        return "Acquisition, " + GetBuilding();
    }

    public override ItemData_v1 GetSaveData()
    {
        ItemData_v1 data = base.GetSaveData();
        data.className = typeof(AcquisitionContract).ToString();
        return data;
    }
}

User avatar
John Doom
Posts: 126
Joined: Wed Dec 01, 2021 5:59 pm
Location: Italy
Contact:

Re: Acquisition

Post by John Doom »

:) Mod updated fixing a couple of bugs. Save corruption didn't occure anymore, go figure :|

User avatar
John Doom
Posts: 126
Joined: Wed Dec 01, 2021 5:59 pm
Location: Italy
Contact:

Re: Acquisition

Post by John Doom »

:) Updated: contract's value gradually changes according to the player's merchantile skill, also fixed bug with Language Skill Overhaul.

andromacus
Posts: 113
Joined: Sat May 23, 2020 9:07 am

Re: Acquisition

Post by andromacus »

Hi John,

thanks for this mod and I hope I'm not bothering you with my recent messages on the forum :)

I was wondering if you would like to consider the following as potential further enhancements for the future; just some ideas:

1. Have the possibility (maybe through a flag, so this could be configurable by the player) to reduce the overall cost of the contracts, bringing it in the order of 100k gold maximum for a shop or tavern. I think this would allow a sort of entrepreneurial gameplay: you take a loan from a bank, purchase a shop or inn, make some money with it, repay the loan, expand furtherly and so on...

The following are not strictly related to the current mode, but maybe a possible expansion

2. The same price reduction mentioned in point 1, but applied for houses (to make them a bit easier to buy...)
3. Possibility to acquire houses also in cities or small towns in which there is not a bank (maybe they could have a lower price than the ones in big cities)
4. Possibility to acquire hovels (as I think you did with farms): I think would be nice to play a kind of "bucolic" gameplay, where the character lives in a small hut in the wilderness (I think this will fit very well with some of the survival mods that are being developed)

Alternative to point 4: kick out the annoying NPC in the hovels, so that if you find one you can settle down here :)

Thanks as usual!

User avatar
John Doom
Posts: 126
Joined: Wed Dec 01, 2021 5:59 pm
Location: Italy
Contact:

Re: Acquisition

Post by John Doom »

Maybe in the future... :?

Post Reply