PDA

View Full Version : Drag and Drop Race/Class



newcoda
August 2nd, 2008, 05:05
Any examples floating around there how to go about this? I am at a complete loss where to start.

Foen
August 2nd, 2008, 06:59
I'm not sure if there is anything in the wider community, but the d20 ruleset doesn't have this feature.

Perhaps if you give an outline of what you are trying to achieve, then maybe we can help with some coding suggestions?

Foen

newcoda
August 2nd, 2008, 07:11
Thank you for the reply,

I wasn't thinking anything complicated (least in my mind)

Just have the little square/box icon that links to info in the module databse, so I could drag a race onto the char sheet and it would fill the name in, link to the full description. Maybe fill in languages known and any profs the race might have.

same for classes, just simple info (profs etc) - not the complicated stuff

/shrug might not even be possible

Foen
August 2nd, 2008, 07:24
Aye it is possible, I've been working on a ruleset which has a similar feature.

There are three components your need to consider:

- The reference module needs to have the racial adjustments/proficiencies included in the xml of the source (where you drag from), not just in some descriptive text
- The character sheet needs to have separate columns (in skills, abilities, saves etc) to populate the racial adjustments with
- A routine needs to be written on the character sheet to parse the dragged xml record and fill in the target racial adjustment figures, deleting any existing entries before doing so

If you break the job down into these components and attack each one in turn, the task should be more straight-forward.

Stuart

newcoda
August 2nd, 2008, 19:43
Excellent, thank you for the direction. One last request, is there any most basic example of this in the default modules? So I can have some kind of framework example to work from?

Foen
August 3rd, 2008, 06:02
I think the closest you get in the standard d20 ruleset is the ability to drag spells from the reference modules onto the character sheet. I'm not sure it is a good match though, so digging through the code might not be very enlightening.

A good place to look at drag-and-drop code is the combat tracker. In combattracker.lua there is an onDrop handler which then invokes addNpc or addPc and these demonstrate quite a broad range of functionality.

Tenian was recently doing something similar, so you might also want to look at his acceptDrop thread (https://www.fantasygrounds.com/forums/showthread.php?t=8703).

Cheers

Stuart

Tenian
August 3rd, 2008, 22:00
The 4E set does this in a few places dropping powers, weapons, equipment, and now magic items onto various sheets.

Let me know if you still need examples. I can show you where to find them in the 4E code.

newcoda
August 6th, 2008, 19:06
The 4E set does this in a few places dropping powers, weapons, equipment, and now magic items onto various sheets.

Let me know if you still need examples. I can show you where to find them in the 4E code.

I was looking at how they drop feats into the ability section on the 4E sheet. Because thats basically what I want, a dropping of name with a link to the full page of information. Ideally it would also place languages known and the bonuses to skills and defenses, since those are static. I figured though a simple link and name drop would be great and within my ability.

So far it is not, looking at how it works with feats it sort of makes sense, but I cannot get it to work and furthermore I am not even sure you can put script functions on labeledstring areas.

=/

Foen
August 6th, 2008, 22:14
The d20 spells thing drags a name: I'm not sure if it creates a link into the reference modue or copies the underlying data. Maybe someone else can give a clue?

Stuart

Tenian
August 7th, 2008, 00:10
Your question intrigues me....mostly because I'm considering stealing it :)

Since I'm more experienced with the modules of FG the first thing I would do is build a race class and store it in a module. For simplicity sake I'm going to name it referencerace
Now I'd populate it:


<dwarf>
<speed>5</speed>
<will>+2</will>
<traits>
<id-000>
<name type="string">Cast-Iron Stomach</name>
<link type="windowreference">
<class>powerdesc</class>
<recordname>powerdesc.racialpowerCast-IronStomach@4E Players Handbook</recordname>
</link>
</id-000>
<id-001>
<nametype="string">Dwarvem Resilience</name>
<link type="windowreference">
<class>powerdesc</class>
<recordname>powerdesc.racialpowerDwarvenResilience@4E Players Handbook</recordname>
</link>
</id-001>
</traits>
</dwarf>



Next I would decide where I wanted to allow it to be dropped. I could allow it to drop only on the Race input box, or I could allow it to drop on the entire character sheet. I decide to drop it anywhere on the main sheet.

The XML for the character sheet is stored in charsheet_main.xml. Further the sheet itself is stored in the charsheet_main windowclass. I check this windowclass and discover it does not have an associated script.

So I associate a script file with this window class as shown below:


<windowclass name="charsheet_main">
<script file="scripts/charsheet_main.lua" />
.....
</windowclass>


Now I go to my scripts folder and create a new file named charsheet_main.lua

Since my goal is to do something when I drop an item onto the sheet I'm going to build a drop handler. The windowclass has several events. These are fired when the user does something. I am interested in dropping an item and this is the onDrop event.

function onDrop(x, y, draginfo)
if draginfo.isType("shortcut") then
local class, datasource = draginfo.getShortcutData();
local source = draginfo.getDatabaseNode();

if source and class == "referencerace" then
local newentry = addRace(source);
end

return true;
end
end


Okay in simple terms what this does is checks to see what you dropped is a shortcut to something in the database. Since I am dropping a race from our module, it will be.

The next lines go and find the object in the database.

Now once I have the database item I check to see if it is a race and if it is we call a special routine that handles adding the race. It is possible to put all the code to add the racial items right here but because I might want to drop other things in the future (class, paragon?) I break it out into a separate routine. This makes it easier to follow as well.

Next I build the addRace function. This will do the bulk of the copying of source database node into the player database node:


function addRace(source)

-- drop the racial data onto the playersheet
-- Static nodes
local playerwindow = window.getDatabaseNode()
playerwindow.createChild("movement","number").setValue(source.createChild("movement","number").getValue());
playerwindow.createChild("willbonus","number").setValue(source.createChild("willbonus","number").getValue());
playerwindow.createChild("race","string").setValue(source.createChild("name","string").getValue());

---trait list
if source.getChild("traits") then
local newlist = newnode.createChild("specialabilitylist");
for key, oldtrait in pairs(source.getChild("traits").getChildren()) do
copyNode(oldpow, newlist);
end
end


return newentry;
end


The first it gets the database node associated with the playerwindow. It is important that I change the player and not the window (because I want the data to save) Not to mention some of the data may not be on the window I am changing.

Next I copy the easy data the stuff which I will only have one of (movement, stats, the name of the race) You will probably want to have the copy set up for each possible stat bonus. The code (from Foen) is smart enough to create a bonus of 0 if it's not stored in the database.


After this I use a loop to copy the trait data and all it's sub nodes. (credit to Foen for writing this!)

The code for the node copy is as follows


function copyNode(source, targetlist)
-- creates a copy of the source node in the target list
local nodeType = source.getType();
if nodeType=="number" or nodeType=="string" or nodeType=="image" or nodeType=="dice" or nodeType=="windowreference" then
local newnode = targetlist.createChild(source.getName(),nodeType). setValue(source.getValue());
return;
end
-- copying formattedtext isn't supported
if nodeType=="formattedtext" then
-- create the node but don't bother trying to populate it
local newnode = targetlist.createChild(source.getName(),nodeType);
return;
end
-- unknown value?
if nodeType~="node" then
-- don't create anything. Should perhaps throw an error
return;
end
-- must be a complex node, we need to repeat the process on all child nodes.
local newlist = targetlist.createChild(source.getName());
for k,subnode in pairs(source.getChildren()) do
copyNode(subnode,newlist);
end
-- done
end


And if I did everything correct, that would be all you need to do.

Note: I did this off the top of my head, so there are probably syntax errors or incorrect field names (willbonus?). But it should push you in the right direction

newcoda
August 7th, 2008, 03:36
Fantastic sir, I will sit down with this and try to learn a few things. Please feel free to make it yours. I know you do alot with the 4E stuff and its always good.

Thank you very much for the guide, even if I am unsuccessful I am sure I will understand working with modules better.

Foen
August 7th, 2008, 06:22
Good work Tenian, the only thing I'd add is some code to clear existing racial traits: if the user drops 'Elf' onto the character sheet then changes their mind and drops 'Dwarf', the racial traits for both will be added.

This is harder than it looks, as it won't necessarily be easy to determine which traits are racial and which are other traits (unless there are only racial traits, or you add a flag on each trait to identify its source).

Cheers

Stuart

Tenian
August 7th, 2008, 11:27
My initial thought was I could just look up the current race and use that to delete any bonus/skill/traits. However since the race field is open for edit on the character sheet, it's possible a user could change the race after the drop.

I suppose you could switch the race to a non-editable field and still go the look up route, but this would mean end users would be required to have a module with races in order to use the ruleset. With some systems this is probably acceptable. With DND 4E this probably wouldn't work (as some races are most likely covered under IP) because you might not be able to distribute a race module.

The only other way I can think of doing this cleanly is to add additional nodes to the character in the database which store any racial bonus they have received. You would have to keep them separate from the existing nodes because I don't think they are granular enough to determine if the bonus came from race or from some other source. You would then use these nodes to remove the bonus, skills, features, special abilities, etc.

It'd be very nice to have, but I'm not sure I'd go that far. At some point I just give up and trust the GM to check the sheet :)

Foen
August 7th, 2008, 23:07
I think there is an easier way around this issue. When you implement the drag and drop, create a custom node in the new special abilities using createChild("raceability","number").setValue(1).

When you want to clear up previous racial abilities, look for that node/value.

That way you don't have to mess with the underlying racial traits module, as everything is contained in your new code.

Stuart

Tenian
August 8th, 2008, 01:32
This is why you are the master and I am the student!