PDA

View Full Version : Modifying the dice roll



Lithl
June 11th, 2009, 00:52
This is how the nWoD ruleset applies the modifier stack to a die roll (n+roll dice, rather than roll dice+n):
function applyModifierStackToRoll(draginfo)
if ModifierStack.isEmpty() then
--[[ do nothing ]]

else
local dicelist;
local originalnumber = draginfo.getNumberData();
local numstr = originalnumber;
local dicecount = ModifierStack.getSum();
local dice={};

if originalnumber > 0 then
numstr = "+" .. originalnumber;
end

for i = 1, draginfo.getSlotCount() do
draginfo.setSlot(i);
dicelist = {};
dicecount = dicecount + table.maxn(draginfo.getDieList());

for c = 1, dicecount do
table.insert(dicelist, "d10");
end

draginfo.setDieList(dicelist);

if draginfo.getDescription() == "" then
draginfo.setDescription(ModifierStack.getDescripti on(true));
else
draginfo.setDescription(draginfo.getDescription() .. " " .. numstr .. " (" .. ModifierStack.getDescription(true) .. ")");
end
end
end


ModifierStack.reset();
end

The problem is that while the results in the chat box are correct, the visual dice are not. Instead of rolled dice + modifier die appearing on screen, (rolled dice) x 2 + modifier appear. The dice which you actually rolled (rather than the dice that appeared automatically) are not counted towards the result in the chat box.

If the line:

dicecount = dicecount + table.maxn(draginfo.getDieList());
is removed, the correct number of dice appear on-screen, but only [ModifierSum] dice are calculated into the result.

The problem appears to be that even though setDieList() correctly sets the chatbox result set, it doesn't do anything to the physics dice that you've rolled. If that's correct, then either setDieList() needs to clear the physics dice as well as the result list that it uses to calculate the rolls in the chat window, or there needs to be an addToDieList() method which adds a list of die types to the existing list.

Unless someone else knows some other way to achieve what I want?

I realize it's not exactly a huge issue, since the results in chat are correct, but it's distracting to roll 1 die with +1 modifier, and see 3 dice appear (etc.)

Moon Wizard
June 11th, 2009, 02:42
The next question I have is where you are calling applyModifierStackToRoll from.? In the d20 ruleset, it was called after the physics dice had landed, which seems like it wouldn't work for nWoD.

The doubling dice issue seems familiar, since that is what happens when dice rolls are made when dropping on the combat tracker in my ruleset. The drop code takes the dropped dice, and calls throwDice() function. I wonder if its related somehow.

Also, there is a ChatManager.convertVariableToString function that I use to inspect variables when trying new code. It's in both the d20_JPG and 4E_JPG rulesets. You might try dropping in the function to see what you are getting, vs. what you are setting. I know that there is also a result field for each dice entry returned by draginfo.getDieList() in the final draginfo received after the physics dice are rolled.

Cheers,
JPG

Foen
June 11th, 2009, 06:24
Adding extra dice using onDiceLanded is going to be difficult, as JPG mentions, because that event only happens after the first dice have been resolved, and it isn't possible to amend the outcome to insert extra dice results. You might want to try this:

In onDiceLanded, save the first results in a custom data table, and call throwDice for the extra dice, with the custom data in it.
When the extra dice land and onDiceLanded is invoked a second time, examine the custom data and create a new list of both dice results.
Write the dice results manually to the chat box, and return 'true' from onDiceLanded to prevent the FG engine automatically generating the (wrong) results message.

Hope that makes sense!

Foen

joshuha
June 11th, 2009, 14:40
Adding extra dice using onDiceLanded is going to be difficult, as JPG mentions, because that event only happens after the first dice have been resolved, and it isn't possible to amend the outcome to insert extra dice results. You might want to try this:

In onDiceLanded, save the first results in a custom data table, and call throwDice for the extra dice, with the custom data in it.
When the extra dice land and onDiceLanded is invoked a second time, examine the custom data and create a new list of both dice results.
Write the dice results manually to the chat box, and return 'true' from onDiceLanded to prevent the FG engine automatically generating the (wrong) results message.

Hope that makes sense!

Foen

If you have purchased the Savage Worlds ruleset that has exploding dice inline with the correct results you can see how I did it there but the process is essentially what was done above.

Lithl
June 11th, 2009, 17:40
Adding extra dice using onDiceLanded is going to be difficult, as JPG mentions, because that event only happens after the first dice have been resolved, and it isn't possible to amend the outcome to insert extra dice results. You might want to try this:

In onDiceLanded, save the first results in a custom data table, and call throwDice for the extra dice, with the custom data in it.
When the extra dice land and onDiceLanded is invoked a second time, examine the custom data and create a new list of both dice results.
Write the dice results manually to the chat box, and return 'true' from onDiceLanded to prevent the FG engine automatically generating the (wrong) results message.

Hope that makes sense!

Foen
Okay. I don't have the code in from of me right now, but I think the apply is being called from onDrop, rather than onDiceLanded. I didn't find a throwDice method in the documentation; is that in the draginfo?

Foen
June 11th, 2009, 18:18
Using onDrop won't let you test to see if you need to roll additional dice (from a natural 10) and I'm not sure how any changes you make to the draginfo are carried through by the FG engine. Try it and see!

The throwDice function is exposed by the chat window (chat_chat.lua, I think).

Foen

Lithl
June 11th, 2009, 23:13
Okay, I was correct in that applyModifierStackToRoll is called from onDrop.


Using onDrop won't let you test to see if you need to roll additional dice (from a natural 10)Exalted rolling doesn't give you extra dice with a natural 10; a 10 is just 2 successes for most rolls (7-9 is one success, barring certain things Sidereals can do with Fate), but only 1 success for damage.


I'm not sure how any changes you make to the draginfo are carried through by the FG engine.in applyModifierStackToRoll, getDieList returns an indeger-indexed list of tables, each table containing type = "dX" (d10 in my case, since I'm only rolling d10s). Passing an integer-indexed list of strings "dX" to setDieList sets the dice to roll, but doesn't get rid of the normal dice that you're rolling. When the control flow reaches onDiceLanded, getDieList resturns the same tables as before, but now eachtable also contains result = n.


The throwDice function is exposed by the chat window (chat_chat.lua, I think).Not in my copy of it, apparently (all code above is in chat_chat.lua) =/

I'll check the d20 ruleset to see if I can find it.

Lithl
June 13th, 2009, 12:21
Okay, it seems that I've gotten this working correctly for all cases. (When you've got a negative modifier, the normal dice you rolled still show up, but I seriously doubt that's fixable)


local initialRoll = nil;
local negativemod = 0;

function applyModifierStackToRoll(draginfo)
if ModifierStack.isEmpty() or ModifierStack.getSum() < 0 then
--[[ do nothing ]]

else
local dicelist;
local originalnumber = draginfo.getNumberData();
local numstr = originalnumber;
local dicecount = ModifierStack.getSum();
local dice = {};

if originalnumber > 0 then
numstr = "+" .. originalnumber;
end

for i = 1, draginfo.getSlotCount() do
draginfo.setSlot(i);
dicelist = {};

for c = 1, dicecount do
table.insert(dicelist, "d10");
end

draginfo.setDieList(dicelist);

if draginfo.getDescription() == "" then
draginfo.setDescription(ModifierStack.getDescripti on(true));
else
draginfo.setDescription(draginfo.getDescription() .. " " .. numstr .. " (" .. ModifierStack.getDescription(true) .. ")");
end
end
end


ModifierStack.reset();
end

function scriptRoll(draginfo)
for i = 1, draginfo.getSlotCount() do
draginfo.setSlot(i);
dicelist = draginfo.getDieList() or {};

for i = 1,#(initialRoll or {}) do
table.insert(dicelist, initialRoll[i]);
end

local tmp = {};
for i = negativemod + 1,#dicelist do
table.insert(tmp, dicelist[i]);
end
dicelist = tmp;

local entry = {};
entry.font = "systemfont";
entry.icon = "indicator_casterprep";

if dicelist and #dicelist > 0 then
local dicecount = table.maxn(dicelist);
local successes = 0;
local tens = {};
local nines = {};
local eights = {};
local sevens = {};
local sixes = {};
local fives = {};
local fours = {};
local threes = {};
local twos = {};
local ones = {};

local reform = {};

for c = 1, dicecount do
if dicelist[c].result == 10 then
successes = successes + 2;
table.insert(tens, c);
elseif dicelist[c].result == 9 then
successes = successes + 1;
table.insert(nines, c);
elseif dicelist[c].result == 8 then
successes = successes + 1;
table.insert(eights,c);
elseif dicelist[c].result == 7 then
successes = successes + 1;
table.insert(sevens, c);
elseif dicelist[c].result == 6 then
table.insert(sixes, c);
elseif dicelist[c].result == 5 then
table.insert(fives, c);
elseif dicelist[c].result == 4 then
table.insert(fours, c);
elseif dicelist[c].result == 3 then
table.insert(threes, c);
elseif dicelist[c].result == 2 then
table.insert(twos, c);
elseif dicelist[c].result == 1 then
table.insert(ones, c);
end
end

for c = 1, table.maxn(tens) do
table.insert(reform,dicelist[tens[c]]);
end
for c = 1, table.maxn(nines) do
table.insert(reform,dicelist[nines[c]]);
end
for c = 1, table.maxn(eights) do
table.insert(reform,dicelist[eights[c]]);
end
for c = 1, table.maxn(sevens) do
table.insert(reform,dicelist[sevens[c]]);
end
for c = 1, table.maxn(sixes) do
table.insert(reform,dicelist[sixes[c]]);
end
for c = 1, table.maxn(fives) do
table.insert(reform,dicelist[fives[c]]);
end
for c = 1, table.maxn(fours) do
table.insert(reform,dicelist[fours[c]]);
end
for c = 1, table.maxn(threes) do
table.insert(reform,dicelist[threes[c]]);
end
for c = 1, table.maxn(twos) do
table.insert(reform,dicelist[twos[c]]);
end
for c = 1, table.maxn(ones) do
table.insert(reform,dicelist[ones[c]]);
end

if successes > 0 then
entry.text = "Success: " .. successes;
else
if table.maxn(ones) > 0 then -- Botch
entry.text = "BOTCH: "..table.maxn(ones);
else -- Simple fail
entry.text = "Failed";
end
end
entry.dice = reform;

if User.isHost() then
entry.sender = GmIdentityManager.getCurrent();
else
entry.sender = User.getIdentityLabel();
end
else
entry.text = "No dice left to roll.";
end

initialRoll = nil;
negativemod = 0;
deliverMessage(entry);
return true;
end -- end: for
end

function onDiceLanded(draginfo)
if draginfo.isType("dice") then
if initialRoll == nil and ModifierStack.getSum() >= 0 then
-- Manual roll
initialRoll = draginfo.getDieList();
draginfo.setDieList({});
local dice = {};
local desc = ModifierStack.getDescription(false);
applyModifierStackToRoll(draginfo);
local n = #(draginfo.getDieList() or {});

if n == 0 then
return scriptRoll(draginfo);
end

for i = 1,n do
table.insert(dice, draginfo.getDieList()[i].type);
end

window.chat.throwDice("dice", dice, 0, desc);
return true;
else
-- Modifier roll
ModifierStack.reset();
return scriptRoll(draginfo);
end -- end: if initialRoll
end -- end: if dice
end

function onDrop(x, y, draginfo)
if draginfo.isType("dice") and ModifierStack.getSum() < 0 then
negativemod = math.abs(ModifierStack.getSum());
end
end

Modifier =0: Dice rolled normally
Modifier >0: Dice rolled normally, then [Modifier] dice rolled as well, before displaying the complete result in chat
Modifier <0: Dice rolled normally, then the last [Dice] - [Modifier] results appear in chat

Moon Wizard
June 14th, 2009, 08:03
I think your solution is probably going to be the best for all scenarios.

Another option that would change the number of dice before rolling. You would need to:
* Whenever rolls are dragged or double-clicked from a window, you would need to add the modifier stack in the onDrag or onDoubleClick event.
* Then, you would clear the modifier stack either when you apply the modifier or when the dice landed.

Not sure if this would work for rolling the dice off the desktop directly, not sure there is a hook there. Also, if you clear the modifier stack when applied and you didn't end up rolling, then you would have to re-add modifiers. If you clear on landing, then you could potentially make multiple rolls using the same modifiers (since onDiceLanded is not called until dice are finished rolling).

Cheers,
JPG