Scripted module not working! Appalling!
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.
- The folder I had to put it was:
$HOME/Library/Application Support/com.FreeholdGames.CavesOfQud/Mods/JohnWick
(the documentation was not very helpful) - 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 - 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.
-
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)
-
-
See https://wiki.cavesofqud.com/wiki/Modding:Adding_Code_to_the_Player for more information on how you can do that.
-
repo owner - changed status to open
-
repo owner -
assigned issue to
-
assigned issue to
-
repo owner -
assigned issue to
-
assigned issue to
-
reporter oh wow, thanks @Ray let me double check this right now
-
reporter YEEEEEEES! THANKS SOOOOOOOO MUCH Ray!
-
reporter - changed status to resolved
The issue was that I was not attaching the part to the player
-
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); } } } } }
-
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. } } }
- Log in to comment
Have you added the TimePassageTest part anywhere? The part won’t run if it’s not attached to anything.