Lone Wolf Development Forums  

Go Back   Lone Wolf Development Forums > Hero Lab Forums > HL - Authoring Kit

Notices

Reply
 
Thread Tools Display Modes
Duggan
Senior Member
Volunteer Data File Contributor
 
Join Date: Nov 2009
Posts: 981

Old September 5th, 2017, 04:42 PM
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>

Last edited by Duggan; September 6th, 2017 at 04:54 PM. Reason: Interchanged quote blocks for code blocks
Duggan is online now   #1 Reply With Quote
Duggan
Senior Member
Volunteer Data File Contributor
 
Join Date: Nov 2009
Posts: 981

Old September 5th, 2017, 04:47 PM
I know I have a wall of text here, but I really wasn't certain what to leave off. Right now, I'm displaying specialties in two places, a separate Specialties tab and on the Skills panel. The edit is a form invoke on the Skills tab. If you'd like, I can provide the code for that.

I'm fairly certain I'm missing some small step here, but I can't seem to make the leap on my own.
Duggan is online now   #2 Reply With Quote
TCArknight
Senior Member
 
Join Date: Jan 2007
Posts: 798

Old September 8th, 2017, 07:29 AM
I think this is where missing something:

You've got:
Quote:
candidatepick="SpecHelp"
candidatefield="SpecExpr"
addpick="">
My DW Gadget form is:
Quote:
<table_dynamic
component="Ability"
showtemplate="tmpShowGad"
choosetemplate="tmpPickGad"
scrollable="yes"
alwaysupdate="yes"
candidatepick="GadgetHelp"
candidatefield="GadgetExpr"
addpick="GadgetHelp"
headerpick="GadgetHelp">
Try adding SpecHelp to the addpick and see if that helps...
TCArknight is offline   #3 Reply With Quote
Duggan
Senior Member
Volunteer Data File Contributor
 
Join Date: Nov 2009
Posts: 981

Old September 8th, 2017, 09:47 AM
I tried that. I was getting the error you posted about in your thread with the quadruple checkmark to which Matthias suggested the empty string.
Duggan is online now   #4 Reply With Quote
RavenX
Senior Member
Volunteer Data File Contributor
 
Join Date: Jan 2011
Location: Nowhere, Virginia
Posts: 3,422

Old September 10th, 2017, 07:56 AM
Quote:
Originally Posted by Duggan View Post
I tried that. I was getting the error you posted about in your thread with the quadruple checkmark to which Matthias suggested the empty string.
This is the most challenging part to learn, but once you get through it, life will be good. You will need gizmos on weapons if you want to track ammunition each weapon uses.

Make sure on your helper object you define a candidate tag expression field, thats the purpose of candidatefield="". You have to define the candidate field if you use this. This will come in handy for many things later on.

Make sure the headerpick is on there too.

RavenX

Currently working on the Exalted 2e datafiles.
RavenX is offline   #5 Reply With Quote
Duggan
Senior Member
Volunteer Data File Contributor
 
Join Date: Nov 2009
Posts: 981

Old September 18th, 2017, 05:37 PM
I worked on some other bits while trying to wrap my head around this. I'm still getting the "Attempt to retrieve candidate tagexpr from non-existent pick 'SpecHelp'" message even though I added an addpick expression:

Code:
<portal
  id="prtSpec"
  style="tblNormal">
  <table_dynamic
    component="Specialty"
    showtemplate="tmpSpec"
    choosetemplate="tmpSpec"
    scrollable="yes"
    alwaysupdate="yes"
    candidatepick="SpecHelp"
    candidatefield="SpecExpr"
    addpick="SpecHelp">
    
    <titlebar><![CDATA[
      @text = "Add a Specialty"
      ]]></titlebar>
    <headertitle><![CDATA[
      @text = "Specialty"
      ]]></headertitle>
    <additem><![CDATA[
      @text = "Add Specialty"
      ]]>
      </additem>
    </table_dynamic>      
  </portal>
I'm actually starting to wonder if maybe the expression isn't being set. I know that it's determined inside SetSpcExpr because the debug statement puts out the right values. And I've verified, through the "Debug Gizmo Pick List" that the helper is present. But how do I get insight as to whether that helper indeed has the expression set?

Possibly relevant, I was trying to add the code to assign a "User.HasSpec" tag to the parent skill, as per the Doctor Who code, but I get an error saying that I'm trying to access a non-existent parent pick for a top-level container on that "assign" bit, which makes me think that I'm still not adding this in the right place.

Code:
<!-- Track the ability on the actor -->
<eval index="1" phase="Setup" priority="5000"><![CDATA[
  perform forward[Specialty.?]
  perform parent.assign[User.HasSpec]
  ]]></eval>

Last edited by Duggan; September 18th, 2017 at 05:52 PM.
Duggan is online now   #6 Reply With Quote
Duggan
Senior Member
Volunteer Data File Contributor
 
Join Date: Nov 2009
Posts: 981

Old September 18th, 2017, 06:45 PM
OK, I figured out part of what I was doing wrong. I was using the "Form" action instead of "Edit". Now I'm just down to
Quote:
Attempt to use a 'headertitle' script within a table with no valid 'headerthing' for portal 'tmpSpec'
- - -
Attempt to use a 'headertitle' script within a table with no valid 'headerthing' for portal 'tmpSpec'
Also, my code for charging appropriate CP for the specialties isn't quite working right yet, and the header is wrong, but this was a huge step for me.
Duggan is online now   #7 Reply With Quote
Duggan
Senior Member
Volunteer Data File Contributor
 
Join Date: Nov 2009
Posts: 981

Old September 20th, 2017, 05:03 PM
Oh, and I "fixed" the "headertitle" error by removing the heading of the table until I understand that correctly. CP charging works.

Now, I've got the trickier bit. A character can have only as many specialties as they have ranks in the skill. I plan to add that to the validation logic, because it's useful for the user to be able to edit it to remove items or change the domain of the two skills. The condition for not showing the Edit button for the Specialties are if the user has no ranks in the skill, and no specialties, which I know how to check for, and whether there exist Specialties that correspond to the skill (there are a handful where you can't get a Specialty currently) and I just can't seem to wrap my brain how to write the condition. I know how to iterate through the values and display the matching items, but is there a way to just get a count of matching items? Or the existence thereof?

Code:
var myId as string
myId = tagids[Skill.sk?," & "]

debug "myID: " & myId
foreach thing in Specialty where myId
  debug "id: " & eachthing.idstring
  nexteach
Duggan is online now   #8 Reply With Quote
Duggan
Senior Member
Volunteer Data File Contributor
 
Join Date: Nov 2009
Posts: 981

Old September 20th, 2017, 05:25 PM
Currently, the following code works in the Skill Component, but seems slightly wasteful:

Code:
<!-- Set the value for whether to display the specialty button -->
<eval index="5" phase="Setup" priority="10000"><![CDATA[
  var myId as string
  myId = tagids[Skill.sk?," & "]
  
  var specMatch as number
  specMatch = 0
  foreach thing in Specialty where myId
    specMatch += 1
    nexteach
  debug "specMatch: " & specMatch
  
  if (specMatch <> 0) then
    if (field[trtUser].value > 0) then
      perform assign[Helper.AllowSpec]
      endif
      
    if (tagis[Specialty.?] <> 0) then
      perform assign[Helper.AllowSpec]
      endif
    endif
  ]]></eval>
Duggan is online now   #9 Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -8. The time now is 04:43 AM.


Powered by vBulletin® - Copyright ©2000 - 2017, vBulletin Solutions, Inc.
wolflair.com copyright ©1998-2016 Lone Wolf Development, Inc. View our Privacy Policy here.