Log in

View Full Version : Appling Source Data To Target(s) - Please Help



dulux-oz
August 2nd, 2015, 03:37
One for the senior Devs, I think:

(As an example - in the 4E Ruleset) How would I go about having a Healing Surge cost being taken off the Target instead of the Source when performing an Action (a Power) such as Lay On Hands?

I know that its got to be done somewhere after the onHeal() function call (from manager_action_heal.lua) as its only after this point that the Target is "known" but I either can't find the correct line(s) and/or I don't understand the data-flow and logic-flow of the code as well as I thought I did :)

Any help would be very greatly appreciated - thanks!

Dakadin
August 3rd, 2015, 07:21
Hi Dulux-oz,

I haven't done 4E in years but I just looked at the code and yes it looks like you need to do it in the onHeal function since you have the target and that is when the heal would be applied. This is just guessing because I don't know if I understand exactly what you are trying to accomplish.

You would likely need to add a variable to the rRoll variable so you know that you need to do the change you want to the target. Then just check for that variable to verify you have the right conditions. Then you can use the target node to track back to the appropriate field on the target and change it. You might also have to make sure you take into account the fact that the initial actor might need there value adjusted back to the original value. If you give me more details on what you want to happen, I will see if I can create a test case on my side.

Dakadin

dulux-oz
August 3rd, 2015, 09:05
Hi Dakadin (& thanks!),

OK, so what I'm trying to do is code for a house rule which says that if a healer has a certain Feat/Talent/Ability (I've yet to actually define this) then the target of the healers heal ability (eg Lay on Hands) will use the target's HealSurge, not the healers.
To do this I've added the following to the char_powerability windowclass from char_powers.xml, which is just as Self/Target targeting button.


<button_iconcycler name="healusesurge" merge="add">
<anchored to="healdetaillabel" position="righthigh" offset="5,5" width="24" height="10" />
<parameters>
<icons>button_toggle_self</icons>
<values>self</values>
<tooltipsres>power_tooltip_selfuserec</tooltipsres>
<defaulticon>button_toggle_trgt</defaulticon>
<defaulttooltipres>power_tooltip_trgtuserec</defaulttooltipres>
</parameters>
</button_iconcycler>

Then I've added the following code to the getAdvancedRollStructures() function of manager_char.lua, to read in the setting of the new targeting button (above). This function is called (eventually) from the onDragStart or onButtonPress of the Power's definition. I put it in this function because all of the other paramenters of a healing power are being set in that function.


rAction.sUseRecovery = DB.getValue(oNodeAbility,"healusesurge","");


And that's when I ran into my brick wall!

As far as I can see a PerformRoll is done right after the above function is called, from which a PerformAction is done which will roll the relevant dice. From there the onHeal is called - BUT I'm not sure how the rAction.sUseRecovery is connected to the onHeal.

Logically, code such as


if rAction.sUseRecovery = "self"then
<do normal Surge Cost Calaculations>
else
<apply Surge Cost to target>
end

would have to be included somewhere.

I hope that makes my thinking clearer, and any help you could give is greately appreciated.

Cheers

Trenloe
August 4th, 2015, 21:48
Assuming this could be a PC applying the surge to another PC (or even an NPC) that they don't own, then you're going to have to package up all of the data (source, target, surge value, etc.) and send it to the GM via OOB messaging. This is needed as a player won't have read access to the database of other PCs or NPCs, whereas the GM will.

This is already done in the onHeal() function via the ActionDamage.notifyApplyDamage call, which kicks off the OOB message process for OOB_MSGTYPE_APPLYDMG. This uses the applyDamage function - which if the type is "heal" (decoded from the damage text) will apply healing against the target (rTarget) using their surge value (trace through the code in applyDamage to see all of this logic).

The key here is that the heal info is decoded from the damage text (roll description) - which is the way most actions pass the majority of data.

Looking at the 4E code you should just be able to change rTarget to the actual target to get the healing to be done on them - and the applyDamage() function works out the healing cost based off their surges.

As I'm not 100% sure exactly the process of your house rule I can't comment in detail, but hopefully this will get you going in the right direction/get over the wall.

dulux-oz
August 5th, 2015, 02:01
Thanks Tren, I'll see how I go :)

dulux-oz
August 5th, 2015, 09:33
OK, so I think I've worked the logic flow properly now (if someone can confirm this it'd be great - thanks)


When the Player Clicks on or Drags the "Healing Button" (from the Power Template) the relevant onClick() or onDrag() function is called.
Both of these then call CharManager.onPowerAbilityAction()
CharManager.onPowerAbilityAction() calls:

CharManager.getAdvancedRollStructures()
ActionHeal.performRoll()

ActionHeal.performRoll() calls:

ActionHeal.getRoll()
ActionsManager.performAction()

ActionsManager.performAction() calls ActionsManager.performMultiAction()
ActionsManager.performMultiAction() calls ActionsManager.encodeActionForDrag()
When the draginfo is dropped onto a target CombatManger.onDrop() is invoked.
CombatManger.onDrop() calls ActionsManager.actionDrop()
ActionsManager.actionDrop() calls ActionsManager.actionRoll()
ActionsManager.actionRoll() calls ActionsManager.applyModifiersAndRoll()
ActionsManager.applyModifiersAndRoll() calls ActionsManager.roll()
The roll cause ActionHeal.onHeal() to be invoked
ActionHeal.onHeal() calls ActionDamage.notifyApplyDamage()
ActionDamage.notifyApplyDamage() calls Comm.deliverOOBMessage()
Comm.deliverOOBMessage causes ActionDamage.handleApplyDamage() to be invoked
ActionDamage.handleApplyDamage calls ActionDamage.applyDamage()

Now at Step 3.1 in the CharManager.getAdvancedRollStructures() function is when I set rAction.sPaysSurge:

aAction.sPaysSurge = DB.getValue(oNodeAbility,"healpayssurge","");
At Step 4.1 in ActionHeal.getRoll() is where I think I need to check for rAction.sPaysSurge and if it is "self" set something like (but I am unsure):

rRoll.bSelfPaysSurge
After Step 6 all the Data is Prepared in a draginfo object, except for the target.
After Step 11 the roll is compete and the results are then applied.
And its in ActionDamage.applyDamage() (Step 16) where I need to recheck for bPaysSurge and apply the special code to make sure the correct Character (the target or the source) uses the Healing Surge.

And here is where I hit my 2nd Wall - the rRoll.bSelfPaysSurge set in Step 4.1 needs to be carried over (somehow) to ActionDamage.applyDamage() (Step16), but in all of the manipulation, coding and decoding that occurs between Step 4.1 and Step 16 I can't figure out how to get this Boolean (or, if necessary, String) value across.

I'm pretty sure I can get it into the draginfo object as a metadata entry (which will get it down to Step 11(ish)) but not any further.

So, am I on the right track or is my design wrong, or is it my logic?

HELP! :)

Thanks guys

Trenloe
August 5th, 2015, 15:36
The things to remember with OOB messaging is that the resulting function is ran on the GM instance, not the player instance. This is the whole reason for OOB messaging.

In step 14, ActionDamage.notifyApplyDamage() constructs the msgOOB table with various data that will be needed later - this is the only way data gets from the player instance to the GM instance.

dulux-oz
August 5th, 2015, 15:54
Thanks for you help Tren.

OK, yeah, I understand that, but how do I get my custom info across from Step 11 to Step 12? As I understand things its got to go via the roll() function, but there's nowhere (or at least I can't work out how) to set custom info in the roll() function's data structure so that it'll be piked up by the Action.onHeal() in Step 12.

Trenloe
August 5th, 2015, 15:57
Post #4 above: "The key here is that the heal info is decoded from the damage text (roll description) - which is the way most actions pass the majority of data."

dulux-oz
August 5th, 2015, 16:49
Sorry, are you saying that custom info has got to go via the roll description - or in other words, be seen by everyone in the Chat Window?

Isn't there any other way which doesn't involve info being displayed this way (eg I thought OOBmessages didn't go via the Chat Window)?

Trenloe
August 5th, 2015, 17:07
Your specific issue - passing data as part of the roll (steps 11 to 12), has nothing to do with OOB messaging at that part. It's the actual process of applying the damage (healing in this case) that uses OOB messaging as the GM needs to apply the damage/heal (step 14+).

As you've mentioned above, the issue you're having is making custom data available to the onHeal function, right? The asynchronous nature of the rolling process means that the resultHandler (onHeal) is kicked off sometime in the future, once the dice have landed and provided a result. The standard mechanism for passing info as part of a damage roll (which is what a heal roll is, essentially) is to do it in the description - usually with the info enclosed in square brackets. Try it - roll some heals/damage in the ruleset and see what FG puts together in the description.

https://dl.dropboxusercontent.com/u/39085830/Screenshots/Fantasy%20Grounds/4E/Healing%20Surge%20Descriptive%20Text.jpg

In the 4E ruleset, manager_action_damage.lua the applyDamage function decodes the damage description with" local rDamageOutput = decodeDamageText(nTotal, sDamage);

dulux-oz
August 6th, 2015, 01:53
OK, thanks, I'll give it a go :)

Edit: OK, got that working :)

Thanks for all of the help guys, both here and via PM - I really, really appreciate it!

Cheers