View Full Version : Learning Combat Tracker Extension - Ruleset Wizard
augustgames
October 6th, 2025, 09:50
I am learning how to use Ruleset Wizard to make my own combat Tracker for my own system (built on CoreRPG). Last year, I just edited the CoreRPG file directly to make the changes but I have since realized that with the newestup update, those changes stopped working. So I have decided to use a Ruleset Wizard extensions to re-do. Correct me if this is not the best way to do it..
1. I starting with the basics so I made a copy of CombatTracker template.rwp and made a few small change for testing.
65569
2. I loaded the extension into my sytem in Fantasy Grounds
65568
3. The Combat Tracker is not changed and uses the CoreRPG Combat Tracket.
65570
Obviously I am missing a step. Can somebody give me some links or guidence on how to make these extensions work?
Thanks
augustgames
October 6th, 2025, 15:50
Ok, I figured it out. I did not see the MERGE field options. Back to the grind.
LordEntrails
October 6th, 2025, 16:19
Did you look at the example here: Examples Library – Ruleset Wizard (https://www.rulesetwizard.com/examples-library/)
There are also these videos that may help (I don't learn well from videos, but you might):
Ruleset Wizard Extension Tutorial - YouTube (https://www.youtube.com/playlist?list=PLsgd1zJLdiKW27cTSdswgTXITEo7xKvGz)
templateTemplate - Ruleset Wizard for Fantasy Grounds Video 00 - Game Zero Introduction (https://www.youtube.com/playlist?list=PLdNTLeOzaWPsvJacBBGA62ZWJFD3Jf_eb)
Ruleset Wizard Tutorials - YouTube (https://www.youtube.com/playlist?list=PLSaS6dEtuko9b9rxIC_Xvgfk616me59yE)
I know most of those are a bit old.
For my own verification of what I've learned so far I'll see if I can reproduce this with with step-by-steps, but that might be a day or three.
One thing I will say is do you want to overwrite the very base CT window? If you do this, you will not get any updates and will have to always keep things in sync. You can just replace the sub windows that you want to update. AS well, you can do a Merge = join so you get core updates (though this may break what you've done). It's a trade off, risk breaking vs lose any core updates.
augustgames
October 6th, 2025, 17:01
Thanks. I am moving right along quickly. I came tot he same conclusiong I have decided not Overwrite the CT window itself, just the ct_entry and sub items. I really appreciate you taking the time to answer. Wish me luck. I will not be shy to post questions if I have any.
RosenMcStern
October 7th, 2025, 09:08
Guys, do not forget that you can also extend windows and templates, not just overwrite them. In this way you are still benefiting from future enhancements, while adding your own features.
augustgames
October 7th, 2025, 14:40
Ok, So I got my initial combat tracker working but I have a WHY Question. I have NPC (npc) and Character (charsheet) records. Both have a common set of fields used in the combat tracker. Initially I updated the combat tracker sample provided by Ruleset Wizard and only the NPC populated. The Character did not. I resolved it by updating the linkPCFields function.
--Link Fields============================================ ================================================== ===============
function linkPCFields()
local nodeChar = link.getTargetDatabaseNode();
if nodeChar then
name.setLink(nodeChar.createChild("name", "string"), true);
init_value.setLink(nodeChar.createChild("init_value", "number"), true);
resolve_value.setLink(nodeChar.createChild("resolve_value", "number"), true);
hp_value.setLink(nodeChar.createChild("hp_value", "number"), true);
mana_value.setLink(nodeChar.createChild("mana_value", "number"), true);
karma_value.setLink(nodeChar.createChild("karma_value", "number"), true);
speed_value.setLink(nodeChar.createChild("speed_value", "number"), true);
speed_crawl_value.setLink(nodeChar.createChild("speed_crawl_value", "number"), true);
speed_climb_value.setLink(nodeChar.createChild("speed_climb_value", "number"), true);
speed_swim_value.setLink(nodeChar.createChild("speed_swim_value", "number"), true);
speed_jump_value.setLink(nodeChar.createChild("speed_jump_value", "number"), true);
speed_fly_value.setLink(nodeChar.createChild("speed_fly_value", "number"), true);
end
end
Why did the NPC work and not the Chararcter without updating linkPCFields(). I know it works, but I am REALLY curious as to what I am missing.
Here is the entire CT Entry Lua script.
function onInit()
-- Set the displays to what should be shown
setTargetingVisible();
setSpacingVisible();
setEffectsVisible();
--setAttacksVisible();
setDefenseVisible();
-- Acquire token reference, if any
self.linkToken();
-- Set up the PC links
self.onLinkChanged();
self.onFactionChanged();
-- Register the deletion menu item for the host
registerMenuItem(Interface.getString("list_menu_deleteitem"), "delete", 6);
registerMenuItem(Interface.getString("list_menu_deleteconfirm"), "delete", 6, 7);
end
function onMenuSelection(selection, subselection)
if selection == 6 and subselection == 7 then
self.delete();
end
end
function onLinkChanged()
-- If a PC, then set up the links to the char sheet
if self.isPC() then
self.linkPCFields();
name.setLine(false);
end
self.onIDChanged();
end
function onIDChanged()
local nodeRecord = getDatabaseNode();
local sClass = link.getValue();
local sRecordType = LibraryData.getRecordTypeFromDisplayClass(sClass);
local bID = LibraryData.getIDState(sRecordType, nodeRecord, true);
name.setVisible(bID);
nonid_name.setVisible(not bID);
isidentified.setVisible(LibraryData.getIDMode(sRec ordType));
end
function onFactionChanged()
-- Update the entry frame
self.updateDisplay();
-- If not a friend, then show visibility toggle
if friendfoe.getStringValue() == "friend" then
tokenvis.setVisible(false);
else
tokenvis.setVisible(true);
end
end
function onVisibilityChanged()
TokenManager.updateVisibility(getDatabaseNode());
windowlist.onVisibilityToggle();
end
function updateDisplay()
local sFaction = friendfoe.getStringValue();
if DB.getValue(getDatabaseNode(), "active", 0) == 1 then
name.setFont("sheetlabel");
nonid_name.setFont("sheetlabel");
if sFaction == "friend" then
setFrame("ctentrybox_friend_active");
elseif sFaction == "neutral" then
setFrame("ctentrybox_neutral_active");
elseif sFaction == "foe" then
setFrame("ctentrybox_foe_active");
else
setFrame("ctentrybox_active");
end
else
name.setFont("sheettext");
nonid_name.setFont("sheettext");
if sFaction == "friend" then
setFrame("ctentrybox_friend");
elseif sFaction == "neutral" then
setFrame("ctentrybox_neutral");
elseif sFaction == "foe" then
setFrame("ctentrybox_foe");
else
setFrame("ctentrybox");
end
end
end
function linkToken()
local imageinstance = token.populateFromImageNode(tokenrefnode.getValue( ), tokenrefid.getValue());
if imageinstance then
TokenManager.linkToken(getDatabaseNode(), imageinstance);
end
end
function delete()
local node = getDatabaseNode();
if not node then
close();
return;
end
-- Clear any effects first, so that saves aren't triggered when initiative advanced
DB.deleteChildren(node, "effects");
-- Clear NPC wounds, so that ruleset turn end dying checks aren't triggered when initiative advanced
if wounds and not self.isPC() then
DB.setValue(node, "wounds", "number", 0);
end
-- Move to the next actor, if this CT entry is active
if self.isActive() then
CombatManager.nextActor();
end
-- Delete the database node and close the window
local cList = windowlist;
node.delete();
-- Update list information (global subsection toggles)
cList.onVisibilityToggle();
end
--Link Fields============================================ ================================================== ===============
function linkPCFields()
local nodeChar = link.getTargetDatabaseNode();
if nodeChar then
name.setLink(nodeChar.createChild("name", "string"), true);
init_value.setLink(nodeChar.createChild("init_value", "number"), true);
resolve_value.setLink(nodeChar.createChild("resolve_value", "number"), true);
hp_value.setLink(nodeChar.createChild("hp_value", "number"), true);
mana_value.setLink(nodeChar.createChild("mana_value", "number"), true);
karma_value.setLink(nodeChar.createChild("karma_value", "number"), true);
speed_value.setLink(nodeChar.createChild("speed_value", "number"), true);
speed_crawl_value.setLink(nodeChar.createChild("speed_crawl_value", "number"), true);
speed_climb_value.setLink(nodeChar.createChild("speed_climb_value", "number"), true);
speed_swim_value.setLink(nodeChar.createChild("speed_swim_value", "number"), true);
speed_jump_value.setLink(nodeChar.createChild("speed_jump_value", "number"), true);
speed_fly_value.setLink(nodeChar.createChild("speed_fly_value", "number"), true);
end
end
--
-- HELPERS
--
function isRecordType(s)
local sClass = link.getValue();
local sRecordType = LibraryData.getRecordTypeFromDisplayClass(sClass);
return (sRecordType == s);
end
function isPC()
return self.isRecordType("charsheet");
end
function isActive()
return (active.getValue() == 1);
end
--
-- SECTION VISIBILITY FUNCTIONS
--
function setTargetingVisible()
local v = false;
if activatetargeting.getValue() == 1 then
v = true;
end
targetingicon.setVisible(v);
sub_targeting.setVisible(v);
target_summary.onTargetsChanged();
end
function setSpacingVisible()
local v = false;
if activatespacing.getValue() == 1 then
v = true;
end
spacingicon.setVisible(v);
sub_spacing.setVisible(v);
end
function setEffectsVisible()
local v = false;
if activateeffects.getValue() == 1 then
v = true;
end
effecticon.setVisible(v);
sub_effects.setVisible(v);
if sub_effects.subwindow then
sub_effects.subwindow.setEffectsVisible(v);
end
effect_summary.onEffectsChanged();
end
--function setAttacksVisible()
-- local v = false;
-- if activateattacks.getValue() == 1 then
-- v = true;
-- end
-- attacksicon.setVisible(v);
-- sub_attacks.setVisible(v);
--end
function setDefenseVisible()
local v = false;
if activatedefense.getValue() == 1 then
v = true;
end
defenseicon.setVisible(v);
sub_defense.setVisible(v);
end
augustgames
October 7th, 2025, 15:05
Ok, So I got my initial combat tracker working but I have a WHY Question. I have NPC (npc) and Character (charsheet) records. Both have a common set of fields used in the combat tracker. Initially I updated the combat tracker sample provided by Ruleset Wizard and only the NPC populated. The Character did not. I resolved it by updating the linkPCFields function.
--Link Fields============================================ ================================================== ===============
function linkPCFields()
local nodeChar = link.getTargetDatabaseNode();
if nodeChar then
name.setLink(nodeChar.createChild("name", "string"), true);
init_value.setLink(nodeChar.createChild("init_value", "number"), true);
resolve_value.setLink(nodeChar.createChild("resolve_value", "number"), true);
hp_value.setLink(nodeChar.createChild("hp_value", "number"), true);
mana_value.setLink(nodeChar.createChild("mana_value", "number"), true);
karma_value.setLink(nodeChar.createChild("karma_value", "number"), true);
speed_value.setLink(nodeChar.createChild("speed_value", "number"), true);
speed_crawl_value.setLink(nodeChar.createChild("speed_crawl_value", "number"), true);
speed_climb_value.setLink(nodeChar.createChild("speed_climb_value", "number"), true);
speed_swim_value.setLink(nodeChar.createChild("speed_swim_value", "number"), true);
speed_jump_value.setLink(nodeChar.createChild("speed_jump_value", "number"), true);
speed_fly_value.setLink(nodeChar.createChild("speed_fly_value", "number"), true);
end
end
Why did the NPC work and not the Chararcter without updating linkPCFields(). I know it works, but I am REALLY curious as to what I am missing.
Here is the entire CT Entry Lua script.
function onInit()
-- Set the displays to what should be shown
setTargetingVisible();
setSpacingVisible();
setEffectsVisible();
--setAttacksVisible();
setDefenseVisible();
-- Acquire token reference, if any
self.linkToken();
-- Set up the PC links
self.onLinkChanged();
self.onFactionChanged();
-- Register the deletion menu item for the host
registerMenuItem(Interface.getString("list_menu_deleteitem"), "delete", 6);
registerMenuItem(Interface.getString("list_menu_deleteconfirm"), "delete", 6, 7);
end
function onMenuSelection(selection, subselection)
if selection == 6 and subselection == 7 then
self.delete();
end
end
function onLinkChanged()
-- If a PC, then set up the links to the char sheet
if self.isPC() then
self.linkPCFields();
name.setLine(false);
end
self.onIDChanged();
end
function onIDChanged()
local nodeRecord = getDatabaseNode();
local sClass = link.getValue();
local sRecordType = LibraryData.getRecordTypeFromDisplayClass(sClass);
local bID = LibraryData.getIDState(sRecordType, nodeRecord, true);
name.setVisible(bID);
nonid_name.setVisible(not bID);
isidentified.setVisible(LibraryData.getIDMode(sRec ordType));
end
function onFactionChanged()
-- Update the entry frame
self.updateDisplay();
-- If not a friend, then show visibility toggle
if friendfoe.getStringValue() == "friend" then
tokenvis.setVisible(false);
else
tokenvis.setVisible(true);
end
end
function onVisibilityChanged()
TokenManager.updateVisibility(getDatabaseNode());
windowlist.onVisibilityToggle();
end
function updateDisplay()
local sFaction = friendfoe.getStringValue();
if DB.getValue(getDatabaseNode(), "active", 0) == 1 then
name.setFont("sheetlabel");
nonid_name.setFont("sheetlabel");
if sFaction == "friend" then
setFrame("ctentrybox_friend_active");
elseif sFaction == "neutral" then
setFrame("ctentrybox_neutral_active");
elseif sFaction == "foe" then
setFrame("ctentrybox_foe_active");
else
setFrame("ctentrybox_active");
end
else
name.setFont("sheettext");
nonid_name.setFont("sheettext");
if sFaction == "friend" then
setFrame("ctentrybox_friend");
elseif sFaction == "neutral" then
setFrame("ctentrybox_neutral");
elseif sFaction == "foe" then
setFrame("ctentrybox_foe");
else
setFrame("ctentrybox");
end
end
end
function linkToken()
local imageinstance = token.populateFromImageNode(tokenrefnode.getValue( ), tokenrefid.getValue());
if imageinstance then
TokenManager.linkToken(getDatabaseNode(), imageinstance);
end
end
function delete()
local node = getDatabaseNode();
if not node then
close();
return;
end
-- Clear any effects first, so that saves aren't triggered when initiative advanced
DB.deleteChildren(node, "effects");
-- Clear NPC wounds, so that ruleset turn end dying checks aren't triggered when initiative advanced
if wounds and not self.isPC() then
DB.setValue(node, "wounds", "number", 0);
end
-- Move to the next actor, if this CT entry is active
if self.isActive() then
CombatManager.nextActor();
end
-- Delete the database node and close the window
local cList = windowlist;
node.delete();
-- Update list information (global subsection toggles)
cList.onVisibilityToggle();
end
--Link Fields============================================ ================================================== ===============
function linkPCFields()
local nodeChar = link.getTargetDatabaseNode();
if nodeChar then
name.setLink(nodeChar.createChild("name", "string"), true);
init_value.setLink(nodeChar.createChild("init_value", "number"), true);
resolve_value.setLink(nodeChar.createChild("resolve_value", "number"), true);
hp_value.setLink(nodeChar.createChild("hp_value", "number"), true);
mana_value.setLink(nodeChar.createChild("mana_value", "number"), true);
karma_value.setLink(nodeChar.createChild("karma_value", "number"), true);
speed_value.setLink(nodeChar.createChild("speed_value", "number"), true);
speed_crawl_value.setLink(nodeChar.createChild("speed_crawl_value", "number"), true);
speed_climb_value.setLink(nodeChar.createChild("speed_climb_value", "number"), true);
speed_swim_value.setLink(nodeChar.createChild("speed_swim_value", "number"), true);
speed_jump_value.setLink(nodeChar.createChild("speed_jump_value", "number"), true);
speed_fly_value.setLink(nodeChar.createChild("speed_fly_value", "number"), true);
end
end
--
-- HELPERS
--
function isRecordType(s)
local sClass = link.getValue();
local sRecordType = LibraryData.getRecordTypeFromDisplayClass(sClass);
return (sRecordType == s);
end
function isPC()
return self.isRecordType("charsheet");
end
function isActive()
return (active.getValue() == 1);
end
--
-- SECTION VISIBILITY FUNCTIONS
--
function setTargetingVisible()
local v = false;
if activatetargeting.getValue() == 1 then
v = true;
end
targetingicon.setVisible(v);
sub_targeting.setVisible(v);
target_summary.onTargetsChanged();
end
function setSpacingVisible()
local v = false;
if activatespacing.getValue() == 1 then
v = true;
end
spacingicon.setVisible(v);
sub_spacing.setVisible(v);
end
function setEffectsVisible()
local v = false;
if activateeffects.getValue() == 1 then
v = true;
end
effecticon.setVisible(v);
sub_effects.setVisible(v);
if sub_effects.subwindow then
sub_effects.subwindow.setEffectsVisible(v);
end
effect_summary.onEffectsChanged();
end
--function setAttacksVisible()
-- local v = false;
-- if activateattacks.getValue() == 1 then
-- v = true;
-- end
-- attacksicon.setVisible(v);
-- sub_attacks.setVisible(v);
--end
function setDefenseVisible()
local v = false;
if activatedefense.getValue() == 1 then
v = true;
end
defenseicon.setVisible(v);
sub_defense.setVisible(v);
end
Also, is there a better way to do what I did? I notice this will not work with Subwindows in the CT. Any links would be appreciated.
Thanks
RosenMcStern
October 7th, 2025, 15:07
Hehe, mysteries of Fantasy grounds :)
NPCs are copies of the original NPC entries that are inserted in the combat tracker. They are born and live there, all info about them is there.
PCs on the other hand have a master copy in the charsheet list. The official info about them is there, not in the ct. The data in the combat tracker must be kept in synch with that on the character sheet via the linkPCFields function, otherwise it will be blank or outdated. Once you call the linkPCFields function, the fields specified there will be kept synched automatically.
augustgames
October 7th, 2025, 16:09
Hehe, mysteries of Fantasy grounds :)
NPCs are copies of the original NPC entries that are inserted in the combat tracker. They are born and live there, all info about them is there.
PCs on the other hand have a master copy in the charsheet list. The official info about them is there, not in the ct. The data in the combat tracker must be kept in synch with that on the character sheet via the linkPCFields function, otherwise it will be blank or outdated. Once you call the linkPCFields function, the fields specified there will be kept synched automatically.
Thank you RosenMcStern. That makes sense. I noticed the linkPCFields fuction do not populate the subWindows in the combat tracker. I have been trying to find the syntax but have not ran accross anything yet. Advice or links?
--Link Fields============================================ ================================================== ===============
function linkPCFields()
local nodeChar = link.getTargetDatabaseNode();
if nodeChar then
name.setLink(nodeChar.createChild("name", "string"), true);
init_value.setLink(nodeChar.createChild("init_value", "number"), true);
resolve_value.setLink(nodeChar.createChild("resolve_value", "number"), true);
hp_value.setLink(nodeChar.createChild("hp_value", "number"), true);
mana_value.setLink(nodeChar.createChild("mana_value", "number"), true);
karma_value.setLink(nodeChar.createChild("karma_value", "number"), true);
--sub_spacing subWindow
--speed_value.setLink(nodeChar.createChild("speed_value", "number"), true);
--speed_crawl_value.setLink(nodeChar.createChild("speed_crawl_value", "number"), true);
--speed_climb_value.setLink(nodeChar.createChild("speed_climb_value", "number"), true);
--speed_swim_value.setLink(nodeChar.createChild("speed_swim_value", "number"), true);
--speed_jump_value.setLink(nodeChar.createChild("speed_jump_value", "number"), true);
--speed_fly_value.setLink(nodeChar.createChild("speed_fly_value", "number"), true);
--sub_defense SubWindow
--ap_value.setLink(nodeChar.createChild("ap_value", "number"), true);
--ap_value_hard.setLink(nodeChar.createChild("ap_value_hard", "number"), true);
--ep_value.setLink(nodeChar.createChild("ep_value", "number"), true);
--ep_value_hard.setLink(nodeChar.createChild("ep_value_hard", "number"), true);
--protection_cold.setLink(nodeChar.createChild("protection_cold.", "number"), true);
--protection_hot.setLink(nodeChar.createChild("protection_hot", "number"), true);
end
end
RosenMcStern
October 7th, 2025, 17:05
I use the following trick, based on the fact that you are not actually linking the field, but the underlying database node. I define invisible fields in the main ct entry window (hsx for strings and hnx for nnumbers) and link those in linkPCFields. This has no effect on the main window as the controls are invisible, but since the subwindows share the database node, once you open the subwindow you will find all controls with the same name populated with data.
So for instance in your main ct entry you would put
<hnx name="ap_value" />
<hnx name="ap_value_hard" />
and in your linkPCFields
ap_value.setLink(nodeChar.createChild("ap_value", "number"), true);
ap_value_hard.setLink(nodeChar.createChild("ap_value_hard", "number"), true);
LordEntrails
October 7th, 2025, 17:14
Guys, do not forget that you can also extend windows and templates, not just overwrite them. In this way you are still benefiting from future enhancements, while adding your own features.
Extending is done with a Merge=Join right?
Hehe, mysteries of Fantasy grounds :)
NPCs are copies of the original NPC entries that are inserted in the combat tracker. They are born and live there, all info about them is there.
PCs on the other hand have a master copy in the charsheet list. The official info about them is there, not in the ct. The data in the combat tracker must be kept in synch with that on the character sheet via the linkPCFields function, otherwise it will be blank or outdated. Once you call the linkPCFields function, the fields specified there will be kept synched automatically.
This ^
If you want to see my some of my struggles with it can be seen in this thread: https://www.fantasygrounds.com/forums/showthread.php?85929-Putting-NPC-Attributes-into-the-Combat-Tracker-Entry
augustgames
October 7th, 2025, 18:20
Giving it a try - Thanks
RosenMcStern
October 7th, 2025, 18:36
No, in the XML.
augustgames
October 7th, 2025, 18:41
I use the following trick, based on the fact that you are not actually linking the field, but the underlying database node. I define invisible fields in the main ct entry window (hsx for strings and hnx for nnumbers) and link those in linkPCFields. This has no effect on the main window as the controls are invisible, but since the subwindows share the database node, once you open the subwindow you will find all controls with the same name populated with data.
So for instance in your main ct entry you would put
<hnx name="ap_value" />
<hnx name="ap_value_hard" />
and in your linkPCFields
ap_value.setLink(nodeChar.createChild("ap_value", "number"), true);
ap_value_hard.setLink(nodeChar.createChild("ap_value_hard", "number"), true);
BRILLIANT! It works. Really clever. I can so so many uses for this trick as I use a lot of SubWindows. Thank you so much!!
65598
RosenMcStern
October 7th, 2025, 18:41
Extending is done with a Merge=Join right?
Yep.
augustgames
October 7th, 2025, 20:54
Yep.
The last thing I am figuring out is allowing me to change those stats in the Combat Tracker. It works for the NPC but not the character. Not a big deal but It would be nice. Been looking online. I don't see anything. Ideas?
augustgames
October 7th, 2025, 22:33
The last thing I am figuring out is allowing me to change those stats in the Combat Tracker. It works for the NPC but not the character. Not a big deal but It would be nice. Been looking online. I don't see anything. Ideas?
I ended up finding an answer.
--Link Fields============================================ ================================================== ===============
function linkPCFields()
local nodeChar = link.getTargetDatabaseNode()
if not nodeChar then return end
local function rw(ctrl, path, typ) -- editable in CT
if not ctrl then return end
ctrl.setLink(DB.createChild(nodeChar, path, typ), false)
if ctrl.setReadOnly then ctrl.setReadOnly(false) end
end
local function ro(ctrl, path, typ) -- read-only in CT
if not ctrl then return end
ctrl.setLink(DB.createChild(nodeChar, path, typ), true)
if ctrl.setReadOnly then ctrl.setReadOnly(true) end
end
-- name: VIEW ONLY
ro(name, "name", "string")
-- editable fields
rw(init_value, "init_value", "number")
rw(resolve_value, "resolve_value", "number")
rw(hp_value, "hp_value", "number")
rw(mana_value, "mana_value", "number")
rw(karma_value, "karma_value", "number")
rw(speed_value, "speed_value", "number")
rw(speed_crawl_value, "speed_crawl_value", "number")
rw(speed_climb_value, "speed_climb_value", "number")
rw(speed_swim_value, "speed_swim_value", "number")
rw(speed_jump_value, "speed_jump_value", "number")
rw(speed_fly_value, "speed_fly_value", "number")
rw(ap_value, "ap_value", "number")
rw(ap_value_hard, "ap_value_hard", "number")
rw(ep_value, "ep_value", "number")
rw(ep_value_hard, "ep_value_hard", "number")
rw(protection_cold, "protection_cold", "number")
rw(protection_hot, "protection_hot", "number")
end
LordEntrails
October 8th, 2025, 05:19
If it helps anyone, I'm going through and documenting the CT for my own learning. Will probably do a thread on what I learn, but this graphic might help others at this point.
65600
pindercarl
October 8th, 2025, 05:53
If it helps anyone, I'm going through and documenting the CT for my own learning. Will probably do a thread on what I learn, but this graphic might help others at this point.
65600
It may be helpful to know that if you turn on the debug display ("/debug on" in the chat), some debug information is displayed in the upper left-hand corner. For the position under the mouse pointer, it displays the type of control, the parent window, the name of the control, and the frame.
65601
RosenMcStern
October 8th, 2025, 09:50
I ended up finding an answer.
While this will undoubtedly work, I do not recommend that you set ro/rw in the linkPCFields function. It's not designed for that purpose.
If your controls are always ro or rw, then it is better to set the value of the <readonly /> or <disabled /> tag in the XML. Static configuration is supposed to be managed in a markup language, not an imperative language.
If your controls can change state, then you should set their readOnly state in an update() or onStatusChanged() function that is called when certain events take place. For any window or component that can change state, you should have such a function. You can find a gazillion examples in CoreRPG or 5E or PFRPG.
augustgames
October 9th, 2025, 13:00
While this will undoubtedly work, I do not recommend that you set ro/rw in the linkPCFields function. It's not designed for that purpose.
If your controls are always ro or rw, then it is better to set the value of the <readonly /> or <disabled /> tag in the XML. Static configuration is supposed to be managed in a markup language, not an imperative language.
If your controls can change state, then you should set their readOnly state in an update() or onStatusChanged() function that is called when certain events take place. For any window or component that can change state, you should have such a function. You can find a gazillion examples in CoreRPG or 5E or PFRPG.
Thanks - I appreciate it. I am having a good time learing this. My level of experience in XML and Lua is low (I am a db admin in my day job).
Powered by vBulletin® Version 4.2.1 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.