Scripted module not working! Appalling!

Issue #12596 resolved
El Axey created an issue

I am trying to follow all the guidance to create a very simple IPart mechanic to automatically reload my bloody light rail, but here’s the thing:

using System;
using System.Collections.Generic;
using XRL.Core;
using XRL.World;
using XRL.World.Effects;
using XRL.Messages;
using XRL.Language;
using XRL.UI;

namespace Mods
{
    [Serializable]
    public class TimePassageTest : IPart
    {
        public override bool WantEvent(int ID, int cascade)
        {
            return base.WantEvent(ID, cascade)
                || ID == EndTurnEvent.ID
                || ID == EndActionEvent.ID;
        }

        public override bool HandleEvent(EndTurnEvent E)
        {
            // This event occurs after the passage of each "standard turn". If the player's quickness is 100, this
            // event will fire once each time the player takes an action. However, if the player has higher
            // quickness, such as 200, this event will only fire once every time the player takes two actions.
            IComponent<GameObject>.AddPlayerMessage("EndTurn event on TimePassageTest part");
            return base.HandleEvent(E);
        }

        public override bool HandleEvent(EndActionEvent E)
        {
            // This event fires every time the player takes an action, regardless of how long that action takes
            // or how quick the player is.
            IComponent<GameObject>.AddPlayerMessage("EndAction event on TimePassageTest part");
            return base.HandleEvent(E);
        }

    }
}

This doesn’t work!

The mod appears in the mod configuration, despite many issues.

  1. The folder I had to put it was: $HOME/Library/Application Support/com.FreeholdGames.CavesOfQud/Mods/JohnWick (the documentation was not very helpful)
  2. The default .csproj file created contains incorrect QudLibsPath. Here’s the fix:
    <QudLibPath>$HOME/Library/Application Support/Steam/steamapps/common/Caves of Qud/CoQ.app/Contents/Resources/Data/Managed</QudLibPath> (the default path was CavesOfQud, I have a default Steam installation. After the fix vscode + csharp extension now can navigate to the types and do autoimport suggestions, which is nice
  3. However, the bloody code above doesn’t seem to work. (It looks green and enabled in the Mod Manager, I definitely reloaded it, the app crashes very often if you try to start a new game with mod code changed, perhaps something to do with dynamic dll loading, whatever.
  4. There’s CERTAINLY no errors in the log on the run:

    ``` --log start-- [2024-09-24T14:42:57] BuildLogger initialized... [2024-09-24T14:42:57] ==== BUILDING SCRIPT MODS ==== [2024-09-24T14:42:57] Defined symbol: BUILD_2_0_207 [2024-09-24T14:42:57] === JOHNWICK === [2024-09-24T14:42:57] Compiling 1 file... [2024-09-24T14:42:57] Success :) [2024-09-24T14:42:57] Defined symbol: MOD_JOHNWICK [2024-09-24T14:42:57] Location: /Users/blbalblabalbal/Library/Application Support/com.FreeholdGames.CavesOfQud/ModAssemblies/JohnWick.dll

    ```

So, by the looks of it the whole modding thing is broken on mac.

Can this be because the produced dll is not properly signed and notarised?
I really want to have that automatic reload mod!

Thanks in advance. Live and drink, water-sisters!

Comments (10)

  1. Ray

    Have you added the TimePassageTest part anywhere? The part won’t run if it’s not attached to anything.

  2. El Axey reporter

    this code works:

    using System;
    using System.Collections.Generic;
    using XRL.Core;
    using XRL.World;
    using XRL.World.Parts;
    using XRL.World.Effects;
    using XRL.Messages;
    using XRL.UI;
    using XRL.World.Parts.Skill;
    
    namespace Mods
    {
        [Serializable]
        public class JohnWickAutoRecharge : IPart
        {
            private static readonly List<string> messages = new List<string>
            {
                "Your weapon reloads swiftly. John Wick smiles upon you.",
                "As if by magic, your weapon is recharged. Zhyve Belarus!", // You are invincible!
                "The Baba Yaga aids you; your weapon is ready.",
                "Your magazine refills effortlessly. Belarusian efficiency at its finest.",
                "With Belarusian precision, your weapon is recharged.",
                "Your weapon hums with renewed energy. Niama prablemau!", // No problem!
                "Reloaded and ready, like John Wick in action.",
                "Your weapon's charge is restored. Heta lyos.", // It is fate.
                "Energy flows back into your weapon. Glory to Belarus!", // Glory to Belarus!
                "Your weapon recharges, whispering 'Dziakuj John Wick'.", // Thank you, John Wick.
            };
    
            private static readonly Random random = new Random();
    
            public override bool WantEvent(int ID, int cascade)
            {
                return base.WantEvent(ID, cascade)
                    || ID == EndTurnEvent.ID;
                    // || ID == EndActionEvent.ID;
            }
    
            public override bool HandleEvent(EndTurnEvent E)
            {
                // This event occurs after the passage of each "standard turn". If the player's quickness is 100, this
                // event will fire once each time the player takes an action. However, if the player has higher
                // quickness, such as 200, this event will only fire once every time the player takes two actions.
                RechargeEquippedWeapons();
                return base.HandleEvent(E);
            }
    
            private void RechargeEquippedWeapons()
            {
                var body = ParentObject.GetPart<Body>();
                if (body == null)
                    return;
    
                var equippedItems = body.GetEquippedObjects();
                if (equippedItems == null || equippedItems.Count == 0)
                    return;
    
                foreach (var item in equippedItems)
                {
                    // Check if the item is a ranged weapon
                    var weapon = item.GetPart<MissileWeapon>();
                    if (weapon == null)
                    {
                        continue;
                    }
    
                    // Check if the weapon uses energy cells
                    var energyCellSocket = item.GetPart<EnergyCellSocket>();
                    if (energyCellSocket == null || energyCellSocket.Cell== null)
                    {
                        // Popup.ShowAsync("No cell in socket");
                        continue;
                    }
    
                    var energyCell = energyCellSocket.Cell;
    
                    // Get the battery part
                    var battery = energyCell.GetPart<EnergyCell>();
                    if (battery == null)
                    {
                        continue;
                    } 
    
                    if(battery.GetChargePercentage()<25){
                        int index = random.Next(messages.Count);
                        string message = messages[index];
                        ParentObject.GetPart<Tinkering_Tinker1>().Recharge(battery._ParentObject);                    
                        MessageQueue.AddPlayerMessage(message);
                    }
                }
            }
        }
    }
    

  3. El Axey reporter

    But this was what was missing:

    using Mods;
    using XRL; // for HasCallAfterGameLoadedAttribute and CallAfterGameLoadedAttribute
    using XRL.Core; // for XRLCore
    using XRL.World; // for GameObject
    
    [HasCallAfterGameLoadedAttribute]
    public class Attacher
    {
        [CallAfterGameLoadedAttribute]
        public static void MyLoadGameCallback()
        {
            // Called whenever loading a save game
            GameObject player = XRLCore.Core?.Game?.Player?.Body;
            if (player != null)
            {
                player.RequirePart<JohnWickAutoRecharge>(); //RequirePart will add the part only if the player doesn't already have it. This ensures your part only gets added once, even after multiple save loads.
            }
        }
    }
    

  4. Log in to comment