PDA

View Full Version : Effect Modification Extension



SolomonGrim
April 10th, 2024, 17:35
Good morning everyone,

I'm currently working on a small extension, and one of its features involves adding a button to the Combat Tracker. This button allows users to "unprone" and "un-unconscious" themselves if they receive healing. So far, I've managed to implement the code to remove these effects, but here's the catch: it currently affects all people in the Combat Tracker.

I would greatly appreciate any help or tips on how to restrict this function to only modify the character that is selected by the person pressing the button via filtering for a selected token or something like that.



function rise()
for _, vChild in pairs(CombatManager.getCombatantNodes()) do
for _, nodeEffect in ipairs(DB.getChildList(vChild, "effects")) do
local label = DB.getValue(nodeEffect, "label", "")
if label:match("Prone") or label:match("Unconscious") then
DB.deleteNode(nodeEffect)
end
end
end
end


Thanks in advance.

Moon Wizard
April 10th, 2024, 17:49
In your example, you are specifically iterating over all combatant nodes; so, the result you are getting would be expected.

Are these buttons on the individual combatant windows? If so, you'd need to grab the databasenode of the record you are on, probably using window.getDatabaseNode(). Then, you can just cycle through the effects on that combatant node.

If this button is just on the overall combat tracker window, how do you know which combatant to apply to?

Regards,
JPG

Mike Serfass
April 12th, 2024, 03:19
You're iterating over all combatants in the CT, and you need the specific character the button belongs to.
Have you tried calling getDatabaseNode from the button? That should reference a specific character.

SolomonGrim
April 12th, 2024, 13:52
How to i call the button in the onButtonPress function with in the xml?

If i understand your suggestion right, i would have to call my rise function with a (button) paramter.


<buttoncontrol name="button_rise">
<anchored position="insidebottomright" offset="105,5" width="55" height="55" />
<icon normal="rise" pressed="rise_p" />
<script>
<script>
function onButtonPress()
main.rise(BUTTON VARIABLE)
end
</script>
</script>
</buttoncontrol>

Or something similar to that ? So to water this down to my question, what is the Global Variable to get the pressed Button ?

EDIT: Is it self, it looks like it could be just self ?

Mike Serfass
April 12th, 2024, 14:23
You can put the code inside the onButtonPress function.
Remove the vChild in pairs loop. Replace that with

getDatabaseNode()
or

window.getDatabaseNode()
One of those should give you the node of the specific combatant the button is on. Then you'll enumerate through just that character's effects

If you want to keep the rise function where it is, you declare the file it's in as a manager in extension.xml like so

<script name="main" file="scripts/file_with_rise_function.lua" />
Set name to whatever name you want, just make sure to rename file_with_rise_function.lua properly.

Inside your button's onButtonPress call

main.rise(getDatabaseNode())

Change the signature of rise() to accept the database node.

You could also create a button.lua file with that code in it, in which case you just move the rise function there.



<buttoncontrol name="button_rise">
<anchored position="insidebottomright" offset="105,5" width="55" height="55" />
<icon normal="rise" pressed="rise_p" />
<script file="scripts/button_rise.lua" />
</buttoncontrol>


Inside button_rise.lua


function onButtonPress()
... rise code here
end


Or keep rise in main and do


<buttoncontrol name="button_rise">
<anchored position="insidebottomright" offset="105,5" width="55" height="55" />
<icon normal="rise" pressed="rise_p" />
<script>
function onButtonPress()
main.rise(getDatabaseNode())
end
</script>
</buttoncontrol>


And remove the extra layer of <script> tags, whichever approach you use.

SolomonGrim
April 12th, 2024, 14:38
I think i see my problem now, my button is attached to the combatTracker but i must attach it to the combatants for it to be able to refrence to one.
In my current idea it wont work even if i implement your approach, because the DB Node is the whole Combattracker.

EDIT: Works like a charm if i include the button to ct entrys, thank you kindly

Mike Serfass
April 12th, 2024, 17:29
Nice!
Do you mind sharing some code for reference for anyone reading this thread?
It would be nice to see the end, working result. I think it will be a good example of working with the CT.

SolomonGrim
April 12th, 2024, 17:39
In my recent work, I extended the "ct_entry" XML for the Host view and "ct_client_entry" XML for the client view by utilizing the merge attribute in the windowclass tag.
This extension includes the addition of two buttons as follows:



<?xml version="1.0" encoding="iso-8859-1"?>

<root>
<windowclass name="ct_entry" merge="merge">
<sheetdata>
<buttoncontrol name="button_rise">
<anchored position="insidebottomright" offset="330,1" width="40" height="35" />
<icon normal="rise" pressed="rise_p" />
<script>
function onButtonPress()
main.rise(getDatabaseNode(),window.getDatabaseNode ())
end
</script>
</buttoncontrol>
<buttoncontrol name="button_wakeup">
<anchored position="insidebottomright" offset="375,5" width="25" height="25" />
<icon normal="wakeup" pressed="wakeup_p" />
<script>
function onButtonPress()
main.wakeup(getDatabaseNode(),window.getDatabaseNo de())
end
</script>
</buttoncontrol>
</sheetdata>
</windowclass>
</root>


The code itself is straightforward. I chose to split the functions into two for potential future customizations, though a parameter could have served the purpose in this case.



function rise(dbN, wdbN)
local database = dbN or wdbN

if not database then
return
end

for _, nodeEffect in ipairs(DB.getChildList(database, "effects")) do
local label = DB.getValue(nodeEffect, "label", "")
if label:match("Prone") then
DB.deleteNode(nodeEffect)
end
end
end



function wakeup(dbN, wdbN)
local database = dbN or wdbN

if not database then
return
end

for _, nodeEffect in ipairs(DB.getChildList(database, "effects")) do
local label = DB.getValue(nodeEffect, "label", "")
if label:match("Unconscious") then
DB.deleteNode(nodeEffect)
end
end
end


Giving us my current state :

60530

augustgames
April 19th, 2024, 22:59
Thanks for this. Helped. I got mine working.