5E Character Create Playlist
  1. #1

    Effect Modification Extension

    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.

    Code:
    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.

  2. #2
    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

  3. #3

    Join Date
    Sep 2020
    Location
    Ballston Lake, NY
    Posts
    600
    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.

  4. #4
    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.

    Code:
    <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 ?
    Last edited by SolomonGrim; April 12th, 2024 at 14:03.

  5. #5

    Join Date
    Sep 2020
    Location
    Ballston Lake, NY
    Posts
    600
    You can put the code inside the onButtonPress function.
    Remove the vChild in pairs loop. Replace that with
    Code:
    getDatabaseNode()
    or
    Code:
    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
    Code:
    <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
    Code:
    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.

    Code:
    <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
    Code:
    function onButtonPress()
    	... rise code here
    end
    Or keep rise in main and do
    Code:
    <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.

  6. #6
    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
    Last edited by SolomonGrim; April 12th, 2024 at 14:49.

  7. #7

    Join Date
    Sep 2020
    Location
    Ballston Lake, NY
    Posts
    600
    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.

  8. #8
    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:

    Code:
    <?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.getDatabaseNode())
    						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.

    Code:
    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 :

    Animation.gif

  9. #9
    Thanks for this. Helped. I got mine working.
    Daniel A George

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
5E Product Walkthrough Playlist

Log in

Log in