PDA

View Full Version : Damned's Init/Combat tracker questions



Trenloe
November 30th, 2014, 02:30
sadly my code looks completely different... im still stumped.
It should look very similar - put rMessage.type = "dice"; in your onRoll() result handler for your initiative action manager. Put it after rMessage is created and before Comm.deliverChatMessage is called.

I'm curious as to why you want to enable dragging of initiative when the last initiative action you were writing stored the result in the correct place as part of the onRoll result handler.

MODERATOR: Moved to it's own thread.

damned
November 30th, 2014, 02:32
Hi Trenloe - when you drag a character to the CT its INIT is correctly pulled from Character Sheet.
I cant seem to find how to update the INIT at the start of the round or when INIT changes on Character Sheet.

Trenloe
November 30th, 2014, 02:52
Hi Trenloe - when you drag a character to the CT its INIT is correctly pulled from Character Sheet.
I cant seem to find how to update the INIT at the start of the round or when INIT changes on Character Sheet.
Assuming that the Init score in the character sheet and the Init total on the combat tracker are different fields in the database then you will need to write a database onUpdate event handler against the database field in the character sheet that will be triggered when the field changes. See "Handler Functions" at the bottom of this page: https://www.fantasygrounds.com/modguide/scripting.xcp

But, in the end, there is really no need to store Initiative in the character sheet - it really should be stored against the record in the combat tracker as this is the place where it takes effect and has any meaning. Storing it directly in the combat tracker will mean there is no need for any onUpdate event handlers from the character sheet, and will put the result directly where it needs to be. Look at the Castles and Crusades scripts\manager_action_init.lua file - this uses the notifyApplyInit function at the end of the result handler onResolve to send the init result to the GM (via OOB messaging) to be added to the combat tracker initresult field using DB.setValue(ActorManager.getCTNode(rSource), "initresult", "number", nTotal);

DMFirmy
November 30th, 2014, 03:07
@damned: I just shot you an email... I think you will be pleased with the contents. 11 lines of Lua goodness that gets you up and running.

damned
November 30th, 2014, 03:10
You are absolutely correct - I *am* storing the INIT twice - I didnt really think about that - and that is silly, pointless and over complicating things in the long run.

Would it not be more correct to store it in the Character Sheet and have the CT use the Character Sheet record?
Because your Character may roll INIT before being added to the CT?

Let me explore that further.

damned
November 30th, 2014, 03:11
@DMFirmy - thank you too! Im looking at your code right now.

damned
November 30th, 2014, 03:17
@Trenloe - I need to explore this whole thing further because I want to also add the following fields to the CT:

Endurance (from record_char_main.xml)
Wounds (from record_char_combat.xml)
Armour Rating (from record_char_combat.xml)

So I will want to be looking them up from the DB - and the Wounds also needs to update as it changes...

DMFirmy
November 30th, 2014, 03:18
Also @damned... Love the theme you used for your ruleset!

damned
November 30th, 2014, 03:20
Thanks @DMFirmy - I gotta few things to go before its ready for use :)

Trenloe
November 30th, 2014, 03:34
@Trenloe - I need to explore this whole thing further because I want to also add the following fields to the CT:

Endurance (from record_char_main.xml)
Wounds (from record_char_combat.xml)
Armour Rating (from record_char_combat.xml)

So I will want to be looking them up from the DB - and the Wounds also needs to update as it changes...
In the Castles and Crusades ruleset see ct\scripts\ct_entry.lua - the linkPCFields() function defines the database links in the charsheet record and ties these with the relevant controls in the combat tracker - the controls have to be defined using the <number_ct_crosslink> template - see the entries in ct\ct_host.xml. Once these links are defined then if the linked field in the database changes then the field in the linked control will be updated.


Would it not be more correct to store it in the Character Sheet and have the CT use the Character Sheet record?
Because your Character may roll INIT before being added to the CT?
That's not how it's done in any of the main FG rulesets (3.5e, Pathfinder, C&C, etc.). Having an initiative total on the character sheet is a waste of space on the character sheet as it is only relevant to an entry in the combat tracker. Yes, a player may roll INIT before being placed in the combat tracker, but this would be a rare occasion - just get them to roll again or manually populate it with the original roll once the PC record is in the combat tracker; this is what all the other main rulesets do.

damned
November 30th, 2014, 03:40
In the Castles and Crusades ruleset see ct\scripts\ct_entry.lua - the linkPCFields() function defines the database links in the charsheet record and ties these with the relevant controls in the combat tracker - the controls have to be defined using the <number_ct_crosslink> template - see the entries in ct\ct_host.xml. Once these links are defined then if the linked field in the database changes then the field in the linked control will be updated.

Is the <number_ct_crosslink> template usable for multiple datasources? eg I can use it for Wounds and Armour Rating?


That's not how it's done in any of the main FG rulesets (3.5e, Pathfinder, C&C, etc.). Having an initiative total on the character sheet is a waste of space on the character sheet as it is only relevant to an entry in the combat tracker. Yes, a player may roll INIT before being placed in the combat tracker, but this would be a rare occasion - just get them to roll again or manually populate it with the original roll once the PC record is in the combat tracker; this is what all the other main rulesets do.

You are correct - you roll from the Character Sheet but its not storing it there.
So if I change that Im going to have to unpick some of what we did last time maybe...
I have to work out how the Character Sheet can connect to the right Actor in the Combat Tracker....

Trenloe
November 30th, 2014, 03:49
Is the <number_ct_crosslink> template usable for multiple datasources? eg I can use it for Wounds and Armour Rating?
Yes. Look at the linkPCFields() function I reference above.




You are correct - you roll from the Character Sheet but its not storing it there.
So if I change that Im going to have to unpick some of what we did last time maybe...
I have to work out how the Character Sheet can connect to the right Actor in the Combat Tracker....
See what I say in post #36 above.

damned
November 30th, 2014, 11:43
I have started to redo the Initiative based on the C&C version. As you said it does not store INIT in the Character Sheet side of the DB. It works in that INIT rolls automatically update the CT. I changed the Dice to roll 2d10 instead of 1d10.

Im really stuck with the syntax to reference the Characters SPEED-TEMP and ARMOUR-PENALTY from the Character Sheet. Previously we ran the INIT script inside the record_char_combat.xml so we could reference window records. Now I need to reference the database for records belonging to the current actor and Im lost.

Ive rolled record_char_combat.xml back to:

<number_charinit name="initiative" source="initiative.total">
<anchored to="initframe" position="insidetopleft" offset="85,17" width="32" height="20" />
</number_charinit>

And pretty much cut and paste into template_char.xml

<!-- Begin Init Roll -->
<template name="number_charinit">
<number_chartotal>
<rollable />
<displaysign />
<tooltip><text>Initiative. Double Click to Roll. 2d10+Speed. Highest Initiative Acts First.</text></tooltip>
<modifiersize>mini</modifiersize>
<description textres="initiative" />
<modifierfield>initiative.temporary</modifierfield>
<source><name>initiative.misc</name><op>+</op></source>
<script>
function action(draginfo)
local rActor = ActorManager.getActor("pc", window.getDatabaseNode());
ActionInit.performRoll(draginfo, rActor);

return true;
end

function onDragStart(button, x, y, draginfo)
return action(draginfo);
end

function onDoubleClick(x,y)
return action();
end
</script>
</number_chartotal>
</template>
<!-- End Init Roll -->

and then in manager_action_init.lua we have lots of stuff...
I adjusted the dice here but based on what we did last time I need to retrieve SPEED-TEMP and ARMOUR-PENALTY from the DB and set nMod or rRoll.nMod = nSpeedTemp - nArmourPenalty
But first I need to retrieve those.

Looking at linkPCFields() in CoreRPG there is only 1 entry:

function linkPCFields()
local nodeChar = link.getTargetDatabaseNode();
if nodeChar then
name.setLink(nodeChar.createChild("name", "string"), true);
end
end


whilst in Castles&Crusades there are a dozen...

function linkPCFields()
local nodeChar = link.getTargetDatabaseNode();
if nodeChar then
name.setLink(nodeChar.createChild("name", "string"), true);

hp.setLink(nodeChar.createChild("hp.total", "number"));
hptemp.setLink(nodeChar.createChild("hp.temporary", "number"));
nonlethal.setLink(nodeChar.createChild("hp.nonlethal", "number"));
wounds.setLink(nodeChar.createChild("hp.wounds", "number"));

init.setLink(nodeChar.createChild("initiative.total", "number"), true);
move.setLink(nodeChar.createChild("speed.total", "number"), true);
bth.setLink(nodeChar.createChild("attackbonus.base", "number"), true);

ac_final.setLink(nodeChar.createChild("ac.totals.general", "number"), true);
ac_flatfooted.setLink(nodeChar.createChild("ac.totals.flatfooted", "number"), true);
ac_touch.setLink(nodeChar.createChild("ac.totals.touch", "number"), true);

sr.setLink(nodeChar.createChild("defenses.sr.total", "number"), true);
end
end

Do I need to add my own in here - what is the Syntax? Its quite opaque to me!

ct-name.setLink(nodeChar.createChild("db.xml entry", "number"));

If so Ive added these thee lines


-- Damian Values
armourrating.setLink(nodeChar.createChild("ac.totals.penalty", "number"));
speedtemp.setLink(nodeChar.createChild("speed.temp", "number"));
mywounds.setLink(nodeChar.createChild("wounds.wtotal", "number"));

Ahhh.... Im so bloody lost!

Trenloe
November 30th, 2014, 15:44
Do one thing at a time. Forget about the linked fields for now they have nothing to do with rolling INIT.

In the C&C manager_action_init.lua file, look at the performRoll function. The lines after -- Determine the modifier to use for this roll get the relevant fields from the character sheet section of the database to be applied as a modifier. Change these entries to use the database fields and logic required from your ruleset.

damned
November 30th, 2014, 20:52
Ok - so those strings are only doing the Linking/Monitoring...

I need a pointer on accessing the DB values for the characters:

this uses the notifyApplyInit function at the end of the result handler onResolve to send the init result to the GM (via OOB messaging) to be added to the combat tracker initresult field using DB.setValue(ActorManager.getCTNode(rSource), "initresult", "number", nTotal);


I can see an example fo a DB.getValue here:

local sAbility = DB.getValue(vSkill, "attribute", "");

How do I *know* what to use in place of vSkill? in place of attibute?
Im after an attribute - speed-temp - is this correct in that situation?

local sSpeed = DB.getValue(vSkill, "speed.temp", "");

Trenloe
December 1st, 2014, 01:05
DB.getValue is described here: https://www.fantasygrounds.com/refdoc/DB.xcp#getValue

You'll need to look at your database structure to find out exactly what you need to use for the subpath parameter. The best way to do this is to create a couple of PCs in a campaign and open the campaign db.xml file and look under <charsheet> for example records.

If you have the source actor record (say this is stored in nodeActgor), then you should be able to use DB.getValue(nodeActor, <Name of the database field>, 0); to get the value of the <name of the database field> from your <charsheet><id-0000X> character sheet database record.

This is shown in the performRoll function in the C&C manager_action_init.lua script, as mentioned in one of my posts above.

damned
December 1st, 2014, 01:22
I know... Im just pretty thick when it comes to this programming thingamyjig.
I have that page in my list of Start pages in my browser.

In the DB the record looks like this:

<speed>
<holder name="Dark Dweller" owner="true" />
<score type="number">40</score>
<temp type="number">44</temp>
<used type="number">0</used>
</speed>


so it should be speed.temp or does it need more....


<abilities>
<speed>
<holder name="Dark Dweller" owner="true" />
<score type="number">40</score>
<temp type="number">44</temp>
<used type="number">0</used>
</speed>
</abilities>


and so... abilities.speed.temp

I would use local nSpeed = DB.getValue(nodeActor, "abilities.speed.temp", 0)?

Trenloe
December 1st, 2014, 01:42
I would use local nSpeed = DB.getValue(nodeActor, "abilities.speed.temp", 0)?
Based off the data you've shown, yes.

damned
December 1st, 2014, 01:50
ok.... so next dumb question... how do I execute this?

I tried just inserting the following code into manager_action_init.lua inside function performroll where other actions were taking place:

local sSpeed = DB.getValue(nodeActor, "abilities.speed.temp", 0)
Debug.console("sSpeed = " .. sSpeed);
but I dont get any output or errors...

Trenloe
December 1st, 2014, 03:15
Assuming that manager_action_init.lua is registered as a global script called "ActionInit" then it will be executed with: ActionInit.performRoll(draginfo, rActor);

damned
December 1st, 2014, 03:29
Doh! What does that even mean! My head hurts....

Ok - searching for actioninit reveals - base.xml

<script name="ActionInit" file="scripts/manager_action_init.lua" />

searching for performroll reveals - template_char.xml
with 2 results

<!-- Begin Init Roll -->
<template name="number_charinit">
<number_chartotal>
<rollable />
<displaysign />
<tooltip><text>Initiative. Double Click to Roll. 2d10+Speed. Highest Initiative Acts First.</text></tooltip>
<modifiersize>mini</modifiersize>
<description textres="initiative" />
<modifierfield>initiative.temporary</modifierfield>
<source><name>initiative.misc</name><op>+</op></source>
<script>
function action(draginfo)
local rActor = ActorManager.getActor("pc", window.getDatabaseNode());
ActionInit.performRoll(draginfo, rActor);

return true;
end

function onDragStart(button, x, y, draginfo)
return action(draginfo);
end

function onDoubleClick(x,y)
return action();
end
</script>
</number_chartotal>
</template>
<!-- End Init Roll -->

and



<template name="number_charinit">
<number_chartotal>
<rollable />
<displaysign />
<modifiersize>mini</modifiersize>
<description textres="initiative" />
<modifierfield>initiative.temporary</modifierfield>
<source><name>initiative.misc</name><op>+</op></source>
<script>
function action(draginfo)
local rActor = ActorManager.getActor("pc", window.getDatabaseNode());
ActionInit.performRoll(draginfo, rActor);

return true;
end

function onDragStart(button, x, y, draginfo)
return action(draginfo);
end

function onDoubleClick(x,y)
return action();
end
</script>
</number_chartotal>
</template>

Which is probably a problem - they look identical bar the description - so now there is one entry...

but back on track - I believe that that syntax should execute the whole function which includes the lines:


local sSpeed = DB.getValue(nodeActor, "abilities.speed.temp", 0)
Debug.console("sSpeed = " .. sSpeed);

but it doesnt appear to execute them...


function performRoll(draginfo, rActor, bSecretRoll)
local rRoll = {};
rRoll.sType = "init";

rRoll.sDesc = "[INIT 2d10 + Speed - Armour Penalty] result ";

rRoll.bSecret = bSecretRoll;

-- Determine the die to use
rRoll.aDice = { "d10","d10" };

-- Determine the modifier to use for this roll
local sSpeed = DB.getValue(nodeActor, "abilities.speed.temp", 0)
Debug.console("sSpeed = " .. sSpeed);
local nSpeed = tonumber("sSpeed");
Debug.console("nSpeed = " .. nSpeed);

rRoll.nMod = nSpeed;

local sActorType, nodeActor = ActorManager.getTypeAndNode(rActor);
if nodeActor then
if sActorType == "pc" then
rRoll.nMod = DB.getValue(nodeActor, "initiative.total", 0);
else
rRoll.nMod = DB.getValue(nodeActor, "init", 0);
end
end

ActionsManager.performAction(draginfo, rActor, rRoll);
end

damned
December 1st, 2014, 03:46
i lied.
one of these changes has caused the debug to go off...

Runtime Notice: s'L53: sSpeed = 0'
Runtime Notice: s'L55: nSpeed = ' | nil

so obviously the lookup is not working or there is not enough info to get the right record or actor...

Trenloe
December 1st, 2014, 04:06
nodeActor doesn't exist at the point you're trying to use it. You need to code after it is created: local sActorType, nodeActor = ActorManager.getTypeAndNode(rActor);

damned
December 1st, 2014, 06:07
Wow. So that *did* make sense.
Why was I running it where I was running it? I wanted to modify nMod and thought that was the best spot.
After making the change I have gone back and ripped out a bunch of changes in that file and simplified it.


function performRoll(draginfo, rActor, bSecretRoll)
local rRoll = {};
rRoll.sType = "init";

rRoll.sDesc = " result ";

rRoll.bSecret = bSecretRoll;

-- Determine the die to use
rRoll.aDice = { "d10","d10" };

-- Determine the modifier to use for this roll
rRoll.nMod = 0;
local sActorType, nodeActor = ActorManager.getTypeAndNode(rActor);

-- Determine the modifier to use for this roll
local nSpeed = DB.getValue(nodeActor, "abilities.speed.temp", 0);
Debug.console("nSpeed = " .. nSpeed);

if nodeActor then
if sActorType == "pc" then
[I]-- rRoll.nMod = DB.getValue(nodeActor, "initiative.total", 0);
rRoll.nMod = DB.getValue(nodeActor, "abilities.speed.temp", 0);
else
rRoll.nMod = DB.getValue(nodeActor, "init", 0);
end
end


ActionsManager.performAction(draginfo, rActor, rRoll);
end

damned
December 1st, 2014, 06:24
but of course... this leads on to at least one more question...

I need to add a secondary modifier to this - Ive added the current speed value (abilities.speed.temp) but I also need to detract the current armour penalty value (ac.totals.penalty).
Grabbing that should be straight forward now...


local nPenalty = DB.getValue(nodeActor, "ac.totals.penalty", 0);
Debug.console("nPenalty = " .. nPenalty);

Works.

Taking a punt here...


if nodeActor then
if sActorType == "pc" then
-- rRoll.nMod = DB.getValue(nodeActor, "initiative.total", 0);
rRoll.nMod = nSpeed - nPenalty;
else
rRoll.nMod = DB.getValue(nodeActor, "init", 0);
end
end

works! so perhaps I wont ask that question... :)

Now to work out how to replicate this to the other new fields in the Combat Tracker... END WNDS AR...

8186

Trenloe
December 1st, 2014, 15:37
Now to work out how to replicate this to the other new fields in the Combat Tracker... END WNDS AR...

8186
As mentioned in post#10 above, the best way to do this is to use the the linkPCFields() function tied with <number_ct_crosslink> controls - see the C&C files ct\scripts\ct_entry.lua and ct\ct_host.xml, respectively.

One line from the linkPCFields() function is:

hp.setLink(nodeChar.createChild("hp.total", "number"));

This is of the form: <control name>.setLink(nodeChar.createChild("<charsheet DB field>", "number"));

<charsheet DB field> is the database field in the <charsheet><id-XXXXX> character sheet entry in the campaign database.


The control has to be of type <number_ct_crosslink> and this has been defined in ct_host.xml as:


<number_ct_crosslink name="hp">
<anchored to="rightanchor" width="30" height="20">
<top />
<right anchor="left" relation="relative" offset="-10" />
</anchored>
<tabtarget prev="initresult" next="hptemp" />
<script>
function update()
window.onHealthChanged();
end
</script>
</number_ct_crosslink>

So, hp.setLink(nodeChar.createChild("hp.total", "number")); links the hp <number_ct_crosslink> control with the character sheet hp.total database entry.

Follow the syntax used in the C&C ruleset for similar fields in the combat tracker.

Note: Use the above <number_ct_crosslink> controls only in the ct_host.xml file, for the PC side, use <number_ct_static>, for example from the C&C ct_client.xml:


<number_ct_static name="hp">
<anchored to="rightanchor" width="30" height="20">
<top />
<right anchor="left" relation="relative" offset="-10" />
</anchored>
<script>
function onValueChanged()
window.onHealthChanged();
end
</script>
</number_ct_static>