PDA

View Full Version : Question about storing options in DB



Moon Wizard
October 25th, 2007, 21:27
I've been working on setting up a system to allow functionality to be added/removed from my ruleset using slash commands. I got it working using the CampaignRegistry, but I found one option that I want the Host to be able to set for all clients.

In this case, I added an auto-total option to the system, so that the chat control would automatically show a total at the end of the die roll string in the chat window. However, I want this to be a game-wide setting controlled by the host.

So I switched the code to store the setting in the database instead of the registry. However, the clients are not seeing the database node values that I set on the host.

Can anyone give me any ideas on how to get this working using the DB or any other approach?

Thanks,
JPG

Toadwart
October 26th, 2007, 08:02
Maybe the GlobalRegistry ?
https://www.fantasygrounds.com/modguide/scripting.xcp

Moon Wizard
October 26th, 2007, 16:12
According to the docs, it looks like the GlobalRegistry just sets a value used by all campaigns on a single computer. So, it won't propagate to the other clients.

Thanks for the thought,
JPG

Valarian
October 26th, 2007, 16:32
How about storing something in the character section of the db.xml?

I'm not sure how to code this in Lua, but in pseudocode ...
On chatwindow slash command: /totals show
For each user connected, set a parameter in the character id section of the db.xml (e.g. <totals>show</totals> as a child or totals=show as an attribute).
When the user rolls dice, the total parameter is checked and the total displayed.

By the way, how did you get the auto-totals to work?

Moon Wizard
October 26th, 2007, 17:59
Good idea, I'll have to give that a try. I was thinking about a similar idea (i.e. store in a visible window object), but wanted to get some thoughts first.

On the auto-totals, I added some code to the onDiceLanded function in the chat_chat.lua script. You have to add separately for full attack and dice types. My code simply adds a [total] to the end of the description string.

Once I get it all working, I will share on the forums.

Cheers,
JPG

Valarian
October 26th, 2007, 20:07
I wanted to try and do something similar, but I couldn't work out how. I was trying to get the Sum from the radial menu to automatically sum the totals after the dice had been rolled.

joshuha
October 26th, 2007, 21:50
I have been able to set/read variables into the database fine. However, one key thing to note is that until the GM commits a save (either the auto-saves or doing a /save) sometimes the database is out of synch.

You can get around this by setting up event handlers to watch for the node and execute code and seems to work fine for me.

Moon Wizard
October 27th, 2007, 01:42
Hmm, I can write/read the variables from the host just fine, and it saves between sessions. But even after I shut down and reload both host and client, the client is reading an empty value and the host is reading the value I set.

I know that they are both running the same script, since I added some debug output to the script to show the value of the variable. However, the result returned from the DB is different on host vs. client.

Thanks,
JPG

Moon Wizard
October 27th, 2007, 02:41
Just figured it out. Apparently, database nodes are only shared with clients if the user is a "holder" registered with the database node. Once I registered each client as they login, then they are able to correctly see the options nodes I set up.

Cheers,
JPG

Hamish
October 27th, 2007, 12:44
That sounds very interesting, but I don't quite get it. Could you explain with a bit more detail please?

Moon Wizard
October 27th, 2007, 20:03
OK, I'm going from what I have seen, so I'm not sure if I understand it completely, but I will give my assumptions. Since it wasn't clear in the documentation, I could be way off. Maybe one of the devs will comment.

* Every node in the database has a list of holders and an owner. (see databasenode in the ruleset reference) I will hereafter refer to holders as watchers (since it seems easier to understand to me).

* By default, the host is a watcher of all nodes in the database.

* When a client connects to the host, they select 1 or more characters which they take ownership of. Taking ownership also makes that client a watcher of those character database nodes.

* The client will not receive any updates to database nodes for which they are not a watcher. Therefore, changes made by the host to the database are not propagated to the client unless they are also watchers of the nodes changed.

Cheers,
JPG

Hamish
October 28th, 2007, 19:45
Okay... I think I get it.
So what you did is store your variable in the database, and then add

<holder name="xxxx" owner="false" />
for every character that logs on to your campaign, right?

Where did you put this code, and what does it look like? I'm always trying to learn.... :-)

Moon Wizard
October 28th, 2007, 22:58
OK, here is the code I used to get/set the database values. I stuck the code in the chatmanager.lua script.



-- addOptionsWatcher: adds the username to the list of holders for the options node
function addOptionsWatcher (username)
local optnode = DB.findNode("options");
if optnode == nil then
optnode = DB.createNode("options");
end
if optnode ~= nil then
optnode.addHolder(username);
end
end

-- getHostOption: Return the value of the given host-only option
function getHostOption(opt_name)
local optnode = DB.findNode("options");
if optnode == nil then
optnode = DB.createNode("options");
end
if optnode ~= nil then
local opt_child_node = optnode.createChild(opt_name, "string");
if opt_child_node ~= nil then
local val = opt_child_node.getValue();
if val then
return val;
end
end
end
return "";
end

-- setHostOption: Sets the value of the given host-only option
function setHostOption(opt_name, opt_value)
local optnode = DB.findNode("options");
if optnode == nil then
optnode = DB.createNode("options");
end
if optnode ~= nil then
local opt_child_node = optnode.createChild(opt_name, "string");
if opt_child_node ~= nil then
opt_child_node.setValue(opt_value);
end
end
end


And here's the line I added to characterlist.lua for the case where the activated parameter is true.



ChatManager.addOptionsWatcher(username);


Cheers,
JPG

Hamish
October 29th, 2007, 09:26
That makes sense.... one last question: You say you add each client as a watcher as soon as they log in. I understand the code you use, but what event do you use to trigger execution of the code?

Hamish
October 29th, 2007, 09:28
Never mind.... it was staring me in the face but I didn't notice it..... onLogin..... how infuriatingly logical. :)

Moon Wizard
October 29th, 2007, 16:38
I actually added it in onIdentityActivation, but onLogin might be better.

Cheers,
JPG

Hamish
November 6th, 2007, 10:10
After playing around with identities for a while, I think it should be in onIdentityActivation after all. I think onLogin fires once when a player connects to a game, while onIdentityActivation will fire for every character this player launches.

By the way, what was the code you used to achieve the autototal being displayed?

Moon Wizard
November 6th, 2007, 22:18
In the onDiceLanded function of the chat_chat.lua file, I added this code to both if paths:



-- Calculate the total
local total = 0;
for i,d in ipairs(draginfo.getDieList()) do
total = total + d.result;
end
total = total + draginfo.getNumberData();


Then I changed this line in the full attack section:



entry.text = draginfo.getStringData() .. " [" .. total .. "]";


And this line in the dice section:



draginfo.setDescription(draginfo.getDescription() .. " [" .. total .. "]");


I plan to publish all my code with options, totals, client-side init and more; once I can get it all working. Probably a few more weeks.

Cheers,
JPG

NineShadowEyes
November 28th, 2007, 04:30
In the onDiceLanded function of the chat_chat.lua file, I added this code to both if paths:

I don't seem to have a chat_chat.lua file. Is it cause I have ver 2?

Moon Wizard
November 28th, 2007, 04:35
I made all my modifications using v2.1.

You have to follow a few steps to make modifications to rulesets:

* Run the d20unpak.exe file in the main FG2 directory. This creates an examples folder in the FG2 data directory.

* Then, you copy the d20 ruleset folder under the examples directory to the rulesets folder in the main data directory.

* Rename the d20 ruleset folder you just copied to something else (Ex: d20_JPG), so that it does not conflict with the built-in d20 ruleset.

* Next time you run FG2, choose your new ruleset.

Now that you have the ruleset unpacked, you can begin making any changes that you want to the ruleset code, both XML and LUA scripts.

Cheers,
JPG

Foen
November 28th, 2007, 06:16
Just an observation moon_wizard, but the following two code snippets work the same:



local optnode = DB.findNode("options");
if optnode == nil then
optnode = DB.createNode("options");
end


or



local optnode = DB.createNode("options");


createNode only creates a new node if the existing node doesn't exist, otherwise it returns the existing node.

Cheers

Stuart

NineShadowEyes
November 29th, 2007, 04:54
I made all my modifications using v2.1.

You have to follow a few steps to make modifications to rulesets:

Ok, thanks for that. I'll give it a go.

Hawkeyekorrigan
December 4th, 2007, 23:57
Hey guys,

Maybe someone can help me out here. I am a complete novice at scripting and have been trying to add the scripts for the auto dice total. However, I must not be putting the code in the correct place or overwriting the correct lines. Could someone help and tell me the exact place? I know Im probably just missing something easy. Sorry for being a newb, but I am frustrated that I can't get it going:) I did install "the box" ok though:) Thanks again! ~Hawk

NineShadowEyes
January 4th, 2008, 21:16
Maybe someone can help me out here. I am a complete novice at scripting and have been trying to add the scripts for the auto dice total.

I just muddled my way through this so if anyone is having trouble with it here's how to do it:

Look for this:


draginfo.setNumberData(draginfo.getNumberData() + ModifierStack.getSum());
end

local entry = {};
entry.text = draginfo.getStringData();


Mine were on lines 63-68. Yours should be too.

Make it like so:


draginfo.setNumberData(draginfo.getNumberData() + ModifierStack.getSum());
end
-- Calculate the total
local total = 0;
for i,d in ipairs(draginfo.getDieList()) do
total = total + d.result;
end
total = total + draginfo.getNumberData();
local entry = {};
entry.text = draginfo.getStringData() .. " [Total: " .. total .. "]";


Next, look for these lines (lines 87-89):

elseif draginfo.isType("dice") then
applyModifierStackToRoll(draginfo);
end

Change that section so it looks like this:

elseif draginfo.isType("dice") then
applyModifierStackToRoll(draginfo);
-- Calculate the total
local total = 0;
for i,d in ipairs(draginfo.getDieList()) do
total = total + d.result;
end
total = total + draginfo.getNumberData();
draginfo.setDescription(draginfo.getDescription() .. " [Total: " .. total .. "]");
end

Note, my chat-chat.lue file didn't have that last 'draginfo.setDesciption' bit in it at all (maybe because it's the C&C ruleset) so I just dumped it right where you see it and it worked. It may be there for you.

NineShadowEyes
January 5th, 2008, 07:03
Figured it out...