Still working on Planet Mercenary. I'm back to the Skill Specializations. Almost every skill has a series of Specializations that can be bootstrapped, bought by the user at creation, or bought during advancement. There's some overlap in specializations (Beam can be applied to six of the gun skills. Projectile applies to five of them, for example). A user may buy as many specialties associated with a skill as he has ranks in that skill (so someone with Pistols 2 could buy Beam and Projectile, but not also Non-Lethal). Most specialties are unique, but a few (which require one to apply a custom domain) repeat.
Initially, based on
TCArknight's work on Doctor Who, I assumed that I'd need Gizmos, with the Specialties associated with the Skills, but the Specialties are really on the Hero, right? Or do I still need the Gizmo, since I want to be able to click on a button on the Skill and bring up the dialog to add specialties particular to that Skill?
What I have right now brings up a list of all specialties with the button (with an error message of "Attempt to retrieve candidate tagexpr from non-existent pick 'SpecHelp'" every time I bring up the form or confirm a choice), but it does add the specialty to the Hero such that I can display it in the listing. And I am able to bootstrap the specialty as part of the various Background choices. Still, I'd like to restrict the list to only specialties associated with the skill, not display the dialog if there are no choices that can be made, and at least flag if there are more specialties than ranks. Here is what I believe is the relevant code:
Procedures.dat
Code:
<!-- Script used to set up Specialty selection
-->
<procedure id="SetSpcExpr" context="pick"><![CDATA[
~make sure there's a gizmo to travel to
doneif (isgizmo = 0)
~set up our tag expression for selecting appropriate specialty
var expr as string
var myId as string
expr = "component.Specialty & (User.CustSkill | "
expr &= myId & ")"
gizmo.childfound[SpecHelp].field[SpecExpr].text = expr
]]></procedure>
traits.str (I think maybe only eval 4 and eval 10 are relevant in Skill. Also, I've only included relevant components and compsets)
Code:
<!-- Skill component
Each skill derives from this component
-->
<component
id="Skill"
name="Skill"
autocompset="no"
panellink="skills">
<!-- Net final roll that includes the value of the linked attribute -->
<field
id="sklRoll"
name="Net Skill Roll"
type="derived">
<calculate phase="Final" priority="5000">
<after name="Calc trtFinal"/><![CDATA[
~only access the linkage if the skill is directly on the hero; if not, it is
~likely within an advancement gizmo and no linkage will exist there
if (container.ishero <> 0) then
@value = field[trtFinal].value
endif
]]></calculate>
</field>
<!-- Each skill needs its own identity tag so existing skills can be identified during advancement -->
<identity group="Skill"/>
<!-- Each skill can also be selected as a background/command package/race bonus.
This bonus does count against the maximum at character creation. -->
<identity group="SkillBonus"/>
<!-- Every skill is shown on the "Rolls" mouse-over on the Dashboard/TacCon -->
<tag group="DashTacCon" tag="Rolls"/>
<eval index="1" phase="Initialize" priority="3000"><![CDATA[
field[trtMinimum].value = 0
field[trtMaximum].value = 9
]]></eval>
<!-- Track the skill on the actor -->
<eval index="2" phase="Setup" priority="5000"><![CDATA[
perform forward[Skill.?]
]]></eval>
<!-- Each skill point that is allocated by the user costs 1 CP -->
<eval index="3" phase="Traits" priority="10000">
<before name="Calc resLeft"/>
<after name="Bound trtUser"/><![CDATA[
~if this skill is not added directly to the hero (i.e. an advance), skip it entirely
doneif (origin.ishero = 0)
~adjust the resource appropriately
hero.child[resCP].field[resSpent].value += field[trtUser].value
]]></eval>
<!-- set the appropriate candidate expression -->
<eval index="4" phase="Final" priority="1000" name="SpecHelp Expr">
<![CDATA[
var myId as string
myId = tagids[Skill.sk?," & "]
call SetSpcExpr
]]></eval>
<eval index="10" phase="Initialize" priority="10000"><![CDATA[
~copy our SkillList tags to the gizmo so they can be used for the needtag
if (isgizmo <> 0) then
perform gizmo.pushtags[Skill.?]
~tags added to the gizmo are then automatically added to the parent of
~that gizmo - but that's where those tags were just pushed from, meaning
~that what happens is to duplicate them all. So, delete the ones on
~ourself, then pull the tags from the gizmo.
perform delete[Skill.?]
perform gizmo.pulltags[Skill.?]
endif
]]></eval>
</component>
<component
id="Specialty"
name="Specialization"
autocompset="no"
panellink="skills">
<identity group="Specialty"/>
<tag group="SpecialTab" tag="Specialty"/>
<!-- Track the ability on the actor -->
<eval index="1" phase="Setup" priority="5000"><![CDATA[
perform forward[Specialty.?]
]]></eval>
<!-- Each specialty that is allocated by the user costs 2 CP -->
<eval index="2" phase="Traits" priority="10000">
<before name="Calc resLeft"/>
<after name="Bound trtUser"/><![CDATA[
~if this skill is not added directly to the hero (i.e. an advance), skip it entirely
doneif (origin.ishero = 0)
~adjust the resource appropriately
hero.child[resCP].field[resSpent].value += 2
]]></eval>
</component>
<!-- Specialty Helper component
Each Specialty Gizmo derives from this component
-->
<component
id="SpecHelp"
name="Specialty Helper">
<!-- Selection Tag Expressions -->
<field
id="SpecExpr"
name="Specialization Tag Expression"
type="derived"
maxlength="500">
</field>
</component>
<!-- Skill - all skills derive from this compset -->
<compset
id="Skill"
forceunique="yes">
<compref component="Skill"/>
<compref component="Trait"/>
<compref component="Domain"/>
<compref component="CanAdvance"/>
</compset>
<!-- Specialty - all skill specialties derive from this compset -->
<compset
id="Specialty">
<compref component="Specialty"/>
<compref component="SpecialTab"/>
<compref component="Domain"/>
<compref component="CanAdvance"/>
</compset>
<entity
id="entSpec"
form="frmSpec">
<bootstrap thing="SpecHelp"/>
</entity>
form_Specialty.dat
Code:
<document signature="Hero Lab Data">
<portal
id="prtSpec"
style="tblNormal">
<table_dynamic
component="Specialty"
showtemplate="tmpSpec"
choosetemplate="tmpSpec"
scrollable="yes"
alwaysupdate="yes"
candidatepick="SpecHelp"
candidatefield="SpecExpr"
addpick="">
<titlebar><![CDATA[
@text = "Add a Specialty"
]]></titlebar>
<headertitle><![CDATA[
@text = "Specialty"
]]></headertitle>
<additem><![CDATA[
@text = "Add Specialty"
]]>
</additem>
</table_dynamic>
</portal>
<template
id="tmpSpec"
name="Area of Expertise Pick"
compset="Specialty"
marginhorz="3"
marginvert="1">
<portal
id="name"
style="lblSmall">
<label>
<labeltext><![CDATA[
@text = field[name].text & " (" & this.tagnames[Skill.?," "] & ")"
]]></labeltext>
</label>
</portal>
<portal
id="delete"
style="actDelete"
tiptext="Click to delete this item">
<action
action="delete">
</action>
</portal>
<position><![CDATA[
~set up our height based on our tallest portal
height = portal[name].height
~if this is a "sizing" calculation, we're done
doneif (issizing <> 0)
~position our tallest portal at the top
portal[name].top = 0
portal[name].left = 0
portal[name].width = 250
~center the other portals vertically
perform portal[delete].centervert
~position the delete portal on the far right
perform portal[delete].alignedge[right,0]
]]></position>
</template>
<layout
id="laySpec"
marginvert="4">
<portalref portal="prtSpec" taborder="20"/>
<position><![CDATA[
~perform portal[prtSpec].batchadd
~perform batchplace
~position and size the table to span the full layout
portal[prtSpec].left = 0
portal[prtSpec].width = width
portal[prtSpec].height = 400
]]></position>
</layout>
<form
id="frmSpec"
name="Specialty"
marginhorz="10"
marginvert="5">
<layoutref layout="laySpec"/>
<position><![CDATA[
layout[laySpec].width = 400
perform layout[laySpec].render
width = layout[laySpec].width
height = 400
]]></position>
</form>
</document>
thing_skills.dat (one representative record)
Code:
<!-- Carbine Skill -->
<thing
id="skCarbine"
name="Carbines"
compset="Skill"
isunique="yes"
description="Use your Carbines skill when firing carbine class weapons. As the weapons most commonly issued to infantry, carbines offer versatility and lethality. They are designed for quick carry, ease of use, and close-quarters action">
<fieldval field="trtAbbrev" value="Car"/>
<tag group="Skills" tag="Combat"/>
<child entity="entSpec" />
</thing>
thing_specializations.dat (two representative items)
Code:
<!-- Carbine Beam Skill Specialty -->
<thing
id="spCarbBeam"
name="Beam"
compset="Specialty"
isunique="yes"
description="">
<tag group="Skill" tag="skCarbine"/>
</thing>
<!-- Per World of Origin Skill Specialty -->
<thing
id="spXenoWrld"
name="Per World of Origin"
compset="Specialty"
isunique="no"
description="">
<tag group="Skill" tag="skXeno"/>
<tag group="User" tag="NeedDomain"/>
</thing>