View Full Version : WindowList - Doesn't store & Can't Delete
LordEntrails
May 28th, 2025, 03:19
So I've created a window list for storing user entered values that do not link to an object type. i.e. NPC attacks that are manually entered into the NPC record. I've got two problems with this windowlist that I'm not seeing in other windowlists (that are object based).
1) The values are not being stored. i.e. after entering values and either /reload or upon restarting FG, the entered data is not recalled. I'm sure this is something to do with my datasource. But where else or how else do I need to define this?
2) I've added an iadd button and it works fine, but the iedit button fails to show the delete button. I'm not sure were to look for this one.
I think all the relevant code is below, but I've attached the xml file in case their are other references that pertain.
<windowlist name="attacklist">
<frame name="frame_windowlist" />
<bounds>7,60,-8,55</bounds>
<class>npc_attack_row</class>
<datasource>.attacklist</datasource>
<allowcreate />
<allowdelete />
<columns>
<width>330</width>
<filldown />
</columns>
</windowlist>
<button_iadd name="attacklist_iadd">
<bounds>-48,44,15,15</bounds>
<icon normal="button_add" />
<font>button-white</font>
<target>attacklist</target>
</button_iadd>
<button_iedit name="attacklist_iedit">
<bounds>-32,44,15,15</bounds>
<icon normal="button_edit" />
<font>button-white</font>
<target>attacklist</target>
</button_iedit>
Moon Wizard
May 28th, 2025, 05:44
It's really hard to tell without having something more concrete to run. Here are some things to check:
Does "sub_minor_npc" window instance have a database node? (Can check using Debug.chat in window class onInit)
Does the list have a database node? (Can check using Debug.chat in window list onInit)
Do the other fields store at that level? (Such as "score", "bodypoints", etc.)
Do the windows show up in the list when you use the iadd button?
Do the child window instance of the list (npc_attack_row) have a database node? (Can check using Debug.chat in window class onInit)
Do you have other code accessing the list that might be deleting/changing it on load?
Regards,
JPG
LordEntrails
May 28th, 2025, 16:55
Thanks. Will have to check the db node suggestions (I suspect the answer is no). Other window lists on on similar sub windows store and allow edit/delete (there are no other lists in this sub_window), but they are to things like skills and items so I know the db exists. Using iadd works, it gives me a new line to enter the value. And no other code accessing the list.
Any advice on where to add the debug statements?
I have not yet added these lists to the sub_major_npc as I wanted to get them working in one place first. But you can see the Security Bot has the skills and benefits lists that work, though those are populated from dragging from the skills and benefits library lists.
64472
Trenloe
May 28th, 2025, 16:57
Can you post the windowclass definition for npc_attack_row ?
LordEntrails
May 28th, 2025, 17:02
Of course:
<?xml version="1.0" encoding="utf-8"?>
<root>
<windowclass name="npc_attack_row">
<placement>
<size height="25" width="330" />
</placement>
<sizelimits resize="both">
<dynamic />
</sizelimits>
<sheetdata>
<stringfield name="name">
<bounds>4,5,85,20</bounds>
<default textres="npc_attack_row_name_DefaultText" />
<controlline />
<lineoffset>-2</lineoffset>
</stringfield>
<number name="hitpercent">
<frame name="fielddark" />
<bounds>90,2,45,25</bounds>
<min>0</min>
<description textres="npc_attack_row_hitpercent_DescriptionText" />
<script>
function onDoubleClick(x, y)
return action();
end
function action(dragInfo)
DiceRollString = "1d100";
DiceRollDescription = "{name} Attack";
GameSystem.actions["hitpercentRollAction"] = { }
ActionsManager.registerResultHandler("hitpercentRollAction", managerRolls.StatRoll);
DiceRollAdditionalInfo = {};
DiceRollAdditionalInfo["stat"] = "{self}";
if onBeforeDiceRoll then if onBeforeDiceRoll(dragInfo) == false then return; end; end;
local windataref = window.getDatabaseNode();
if windataref == nil then windataref = window; end;
RulesetWizardDiceRoller.Roll(dragInfo, windataref,"hitpercentRollAction", DiceRollDescription, DiceRollString, getValue(), DiceRollAdditionalInfo);
if onAfterDiceRoll then onAfterDiceRoll(); end;
return true;
end
</script>
</number>
<simpledice name="damage_dr">
<frame name="fielddark" offset="7,5,7,5" />
<bounds>139,7,31,15</bounds>
<script>
function onDoubleClick(x, y)
return action();
end
function action(dragInfo)
DiceRollString = StringManager.convertDiceToString(getDice()).. "";
DiceRollDescription = "";
GameSystem.actions["damage_drRollAction"] = { bUseModStack = "true" }
DiceRollAdditionalInfo = {};
if onBeforeDiceRoll then if onBeforeDiceRoll(dragInfo) == false then return; end; end;
local windataref = window.getDatabaseNode();
if windataref == nil then windataref = window; end;
RulesetWizardDiceRoller.Roll(dragInfo, windataref,"damage_drRollAction", DiceRollDescription, DiceRollString, 0, DiceRollAdditionalInfo);
if onAfterDiceRoll then onAfterDiceRoll(); end;
return true;
end
</script>
</simpledice>
<stringfield name="range">
<bounds>179,5,45,20</bounds>
<center />
<default textres="npc_attack_row_range_DefaultText" />
<controlline />
<lineoffset>-2</lineoffset>
</stringfield>
<stringfield name="notes">
<bounds>230,5,-6,20</bounds>
<default textres="npc_attack_row_notes_DefaultText" />
<controlline />
<lineoffset>-2</lineoffset>
<script>
function onDoubleClick(x, y)
return action();
end
function action(dragInfo)
DiceRollString = "{self}10";
DiceRollDescription = "Damage";
GameSystem.actions["damage"] = { bUseModStack = "true" }
DiceRollAdditionalInfo = {};
DiceRollAdditionalInfo["damage"] = "{self}";
if onBeforeDiceRoll then if onBeforeDiceRoll(dragInfo) == false then return; end; end;
local windataref = window.getDatabaseNode();
if windataref == nil then windataref = window; end;
RulesetWizardDiceRoller.Roll(dragInfo, windataref,"damage", DiceRollDescription, DiceRollString, getValue(), DiceRollAdditionalInfo);
if onAfterDiceRoll then onAfterDiceRoll(); end;
return true;
end
</script>
</stringfield>
</sheetdata>
</windowclass>
</root>
LordEntrails
May 28th, 2025, 17:06
If it's of any use, here's the npc_main which calls the sub_noc_minor and itself is called from the standard CoreRPG npc
<?xml version="1.0" encoding="utf-8"?>
<root>
<windowclass name="npc_main">
<frame>utilitybox2</frame>
<placement>
<size height="375" width="360" />
</placement>
<script>function onLockChanged()
if sub_minor and sub_minor.subwindow then
sub_minor.subwindow.update();
end
if sub_major and sub_major.subwindow then
sub_major.subwindow.update();
end
if sub_creature and sub_creature.subwindow then
sub_creature.subwindow.update();
end
local bReadOnly = WindowManager.getReadOnlyState(getDatabaseNode());
name.setReadOnly(bReadOnly);
-- cost.setReadOnly(bReadOnly);
-- item_type.setReadOnly(bReadOnly);
end
</script>
<sheetdata>
<rsw_combobox name="npc_type">
<frame name="fielddark" offset="8,0,8,0" />
<bounds>54,3,54,30</bounds>
<listdirection>down</listdirection>
<script>function onInit()
super.onInit();
onValueChanged();
super.onInit();
add("minor","Minor");
add("major","Major");
add("creature","Creature");
end
function onValueChanged()
-- Debug.chat(getValue());
if getValue() == '' then
setValue("Minor");
end
getValue()
if getValue() == 'Minor' then
window.sub_minor.setVisible(true);
window.sub_major.setVisible(false);
window.sub_creature.setVisible(false);
elseif getValue() == 'Major' then
window.sub_minor.setVisible(false);
window.sub_major.setVisible(true);
window.sub_creature.setVisible(false);
elseif getValue() == 'Creature' then
window.sub_minor.setVisible(false);
window.sub_major.setVisible(false);
window.sub_creature.setVisible(true);
end
-- Debug.chat("Return sub Window statuses")
-- Debug.chat(window.sub_minor.isVisible());
-- Debug.chat(window.sub_major.isVisible());
end
</script>
</rsw_combobox>
<stringfield name="species">
<frame name="fielddark" />
<bounds>167,3,94,30</bounds>
<center />
</stringfield>
<number name="rank">
<frame name="fielddark" />
<bounds>-34,3,30,30</bounds>
<min>0</min>
<max>99</max>
<default>0</default>
</number>
<stringcontrol name="type_label">
<bounds>14,8,35,20</bounds>
<static textres="npc_main_type_label_LabelCaption" />
<font>reference-b</font>
<readonly />
</stringcontrol>
<stringcontrol name="species_label">
<bounds>120,8,47,20</bounds>
<static textres="npc_main_species_label_LabelCaption" />
<font>reference-b</font>
<readonly />
</stringcontrol>
<stringcontrol name="rank_label">
<bounds>-66,9,31,20</bounds>
<color>#FFF5F5F5</color>
<static textres="npc_main_rank_label_LabelCaption" />
<font>reference-b</font>
<readonly />
</stringcontrol>
<stringcontrol name="senses_label">
<bounds>12,36,45,20</bounds>
<static textres="npc_main_senses_label_LabelCaption" />
<readonly />
</stringcontrol>
<stringfield name="senses">
<bounds>62,38,200,20</bounds>
<controlline />
<lineoffset>-2</lineoffset>
</stringfield>
<stringcontrol name="size_label">
<bounds>271,37,25,20</bounds>
<static textres="npc_main_size_label_LabelCaption" />
<readonly />
</stringcontrol>
<number name="size">
<frame name="fielddark" />
<bounds>301,32,31,30</bounds>
</number>
<subwindow name="sub_minor">
<anchored>
<left offset="4" />
<right offset="-6" />
<top offset="65" />
</anchored>
<class>sub_npc_minor</class>
<activate />
<fastinit />
</subwindow>
<subwindow name="sub_major">
<anchored>
<left offset="4" />
<right offset="-6" />
<top offset="65" />
</anchored>
<invisible />
<class>sub_npc_major</class>
<activate />
<fastinit />
</subwindow>
<subwindow name="sub_creature">
<anchored>
<left offset="4" />
<right offset="-6" />
<top offset="65" />
</anchored>
<invisible />
<class>sub_npc_creature</class>
<activate />
<fastinit />
</subwindow>
</sheetdata>
</windowclass>
</root>
Moon Wizard
May 28th, 2025, 18:36
I didn't see anything stand out in any of that code you provided. I usually stick Debug calls in the onInit statements; unless I need to capture different events (clicks, etc.).
Also, I noticed you were using a layout for NPCs that won't work well with themes.
https://fantasygroundsunity.atlassian.net/wiki/spaces/FGCP/pages/2172420127/UI+Standards+-+Rulesets+and+Extensions
Take a look at "Floating Window Frames", "Specific Asset Definitions (Per Frame)", "Top Level Layout Template Usage".
You'd want to use recordsheet as the frame and all the various top-level templates that match to work easily with all the official themes. You can even inherit from "record_window_tabbed", like 5E does.
Regards,
JPG
bayne7400
May 28th, 2025, 21:07
Your iedit and iadd are not displaying either and they are set by bounds. So that tells me your subwindow is not displaying. Look at the update script and make sure it is setting it to be visible.
This is a guess. If you send me all the XML and lua files associated with this I will look. Can do it on discord if youw ant.
LordEntrails
May 28th, 2025, 22:07
Thank you all.
MW I need to look into this. This ruleset started development years ago and my plan was once I got the core functions working I would look into updating to current templates. Will that approach cause problems with any data type issues with current products? (This is the FrontierSpace ruleset that is on the Forge; FG Forge - View Item (https://forge.fantasygrounds.com/shop/items/2176/view)
I'll see if I can track down Bayne. I think this will go much quicker in person.
Note, the RSW files are here: LordEntrails/FrontierSpace: FrontierSpace Ruleset for Fantasy Grounds VTT (https://github.com/LordEntrails/FrontierSpace)
LordEntrails
May 28th, 2025, 23:49
Thanks to Bayne, the unable to delete was simply that the windowclass for the rows (npc_attack_row) did not have an idelete button. And the not retaining data was because I had not entered values and was just testing with the field default values.
Powered by vBulletin® Version 4.2.1 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.