Lone Wolf Development Forums  

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

Notices

Reply
 
Thread Tools Display Modes
Mathias
Senior Member
Lone Wolf Staff
 
Join Date: May 2005
Posts: 13,207

Old December 6th, 2020, 03:59 PM
No, tables on the hero, just on a normal tab, where the user adds each career choice pick. All of those are set up with gizmos, so the user then clicks the button to open the customization form, and within that form, they choose their two skills, choose a specialty, and fill in a box for how many years they spent on that one.
Mathias is online now   #11 Reply With Quote
TCArknight
Senior Member
 
Join Date: Jan 2007
Location: NW Arkansas
Posts: 1,321

Old December 7th, 2020, 01:35 PM
Thanks Mathias!

That pointed me in the right direction. I have a Lifepath component with a child entity, lpCustom using the LifepathHelper (a thing based on the LifepathHelper component).
Code:
  <!-- Lifepath Module -->
  <!-- form="lifepathgiz"> -->
  <entity
    id="lpCustom"
    form="lifepathgiz">
    <bootstrap thing="LifepathHelper"/>
    </entity>

  <component
    id="LifepathHelper"
    name="Lifepath Helper">
	  
    <field
      id="lpSpecExpr"
      name="Specialty Expression"
      type="derived"
	  maxlength="500"
	  defvalue="TRUE">
	  </field>
    
    <!-- build the expression strings based on tags -->
    <eval index="1" phase="Render" priority="5000"><![CDATA[
	  var expr as string

      ~ get the tags from the container for what Specialties are available	  
	  expr = container.tagids[Specialty.?,"|"]
	  expr = replace(expr, "Specialty", "thingid", 0)
	  
      field[lpSpecExpr].text = expr
	  
      ]]></eval>
    </component>
This seems to work fine. When I add a module (Street Kid), the lifepathgiz form pops up with the table to select the Specialty (and the list is correct based on the tags on the Street Kid module).

When a Specialty is selected (doing an autotag with Helper.Shadow) this error pops up:
Quote:
Live state of gizmo 'lpCustom' is being tested during phase 'Initialization' at priority 10000 by pick 'Runner' (spcT2KRunner) before live state of parent pick 'lpT2KStreetKid' is resolved
The phase being tested is apparently on the SpecialTab component. When I remove that from the Specialty compset though, it pops the same aerror with a different "tested during" timing.

Is there something I'm missing or how is this handled for SR5 and the Life Modules?

Working on -
  • (SWADE) WIP Savage Rifts
  • Savage Rifts (Deluxe): Update link in This post
  • Star Trek Adventures: Update link in This post
TCArknight is online now   #12 Reply With Quote
Mathias
Senior Member
Lone Wolf Staff
 
Join Date: May 2005
Posts: 13,207

Old December 7th, 2020, 02:53 PM
To see that, use the "debug selection tasks" to examine when the very first task is on the lpT2KStreetKid pick is - it'll be after Initialization/10000, and it needs to be at or before that time. A blank script works to solve this:

Code:
<eval index="1" phase="Initialization" priority="9500">
   <before name="the script on lpCustom that's at 10000"/><![CDATA[
   ~empty script, but earlier than scripts on the picks in this gizmo
   ]]></eval>
Mathias is online now   #13 Reply With Quote
TCArknight
Senior Member
 
Join Date: Jan 2007
Location: NW Arkansas
Posts: 1,321

Old December 7th, 2020, 03:35 PM
Worked perfectly.

I can add the specialty to the gizmo with no issue.

However, even though the Specialty pick is on the gizmo with the Helper.Shadow tag, it's not reflecting on the hero.

Is there something I need to implement to have that reflect on the actor itself? or would that need to be a Displace?

EDIT: I found it. needed to add this to the Specialty component definition.
Code:
    <shadow target="hero">Helper.Shadow</shadow>

Working on -
  • (SWADE) WIP Savage Rifts
  • Savage Rifts (Deluxe): Update link in This post
  • Star Trek Adventures: Update link in This post

Last edited by TCArknight; December 7th, 2020 at 03:42 PM.
TCArknight is online now   #14 Reply With Quote
TCArknight
Senior Member
 
Join Date: Jan 2007
Location: NW Arkansas
Posts: 1,321

Old December 8th, 2020, 05:05 AM
Second part of the Lifepath gizmo question -

For example, there are a small number of skills (and they are defined as unique) in the system so they are all bootstrapped to the hero from the beginning.

If I want to make a selection of a skill in the lifepath module and the table has an autotag entry so that the selected skill gets a particular tag (SkillRankIncrease), it appears that the skill is copied to the gizmo and that copy is tagged instead of the skill already existing on the hero.

Making the skill Shadow to the hero results in a new copy of the Skill, one with the SkillRankIncrease tag, and one without. Is this what you were referring to about having to pick a Master and hide any other copies?

Working on -
  • (SWADE) WIP Savage Rifts
  • Savage Rifts (Deluxe): Update link in This post
  • Star Trek Adventures: Update link in This post
TCArknight is online now   #15 Reply With Quote
Mathias
Senior Member
Lone Wolf Staff
 
Join Date: May 2005
Posts: 13,207

Old December 8th, 2020, 07:57 AM
Yep - even if they're unique, you'll need to use useronce uniqueness to make this work - then, yeah, shadow them to the hero, and then you need to set up scripts that can make one copy the main copy, and add together each one's bonuses to get a final value that's from all your lifepaths.


Here are the relevant scripts in SR5, although you'll have to wade through a lot of code relating to skill groups and skillsofts that are shadowrun-specific, and probably not something you have to worry about. So you'll want to pull all that out. I'm afraid I don't remember right now what caused us to have to split "Shadowed skills find their normal versions" into two scripts, and whether you'll need to retain that.


Code:
    <eval index="3" phase="Initialize" priority="29999" name="Determine FirstCopy"><![CDATA[
      ~if we're not user once unique, then every copy is the FirstCopy
      if (tagis[User.Unique] = 0) then
        perform assign[Helper.FirstCopy]
        done
        endif

      if (quickadd <> 0) then
        perform assign[Helper.FirstCopy]
        endif
      ]]></eval>

    <eval index="4" phase="Initialize" priority="30000" name="Not FirstCopy"><![CDATA[
      if (tagis[Helper.FirstCopy] = 0) then
        perform quickfind.redirect
        perform assign[Hide.Skill]
        endif
      ]]></eval>
Code:
    <eval index="8" phase="Traits" priority="8500" name="Shadowed skills find their normal versions">
      <before name="Calc trtFinal Final"/>
      <after name="Calc grRating #3"/><![CDATA[
      ~this only applies to shadowed skills
      ~those will be the ones added as skillsofts
      doneif (shadowed + tagexpr[SkillHelp.Autosoft | SkillHelp.Personafix] = 0)

      ~exclude new skill advancements
      doneif (tagis[Advance.Gizmo] <> 0)

      ~if we have a root pick, and our root pick is an advancement, stop now
      if (isroot <> 0) then
        doneif (root.tagis[Advance.Gizmo] <> 0)

        ~if that root pick has a root, and that's an advancement, stop now
        ~(this happens when Drake is added as an advancement - the Elemental
        ~Attack skill is two bootstraps down from the actual pick)
        if (root.isroot <> 0) then
          doneif (root.root.tagis[Advance.Gizmo] <> 0)
          endif
        endif

      ~handling for if we're added by a life module
      if (parent.tagis[component.LifeModule] <> 0) then
        ~no special handling needed in this case

      ~if we weren't added by a life module, and we're a skill group, stop now
      elseif (tagis[component.SkillGroup] <> 0) then
        done

      ~if we're a skillsoft/autosoft, our rating is our parent's rating
      elseif (parent.tagis[component.Gear] <> 0) then
        ~our replacement value is the rating of the program that added us
        field[trtReplace].value = parent.field[grRating].value

        ~if we're attached to the targeting autosoft, we'll need to grab some
        ~tags in order for the weapons to find us
        perform parent.pulltags[AutosoType.Targeting]
        perform parent.pulltags[ExoticProf.?]

        ~if we're not in a device, or not running, hide ourselves and don't
        ~proceed to looking for existing copies of the skill to replace
        if (hero.tagexpr[Hero.MatrixOnly | Hero.Vehicle] <> 0) then
          if (parent.field[grIsEquip].value = 0) then
            perform assign[Hide.Skill]
            perform assign[Helper.Disable]
            done
            endif
        elseif (tagis[SkillHelp.Personafix] <> 0) then
          ~nothing we need to do in this case
        elseif (tagis[SkillHelp.Autosoft] <> 0) then
          if (hero.tagis[Hero.Vehicle] = 0) then
            perform assign[Hide.Skill]
            perform assign[Helper.Disable]
            done
            endif
        elseif (parent.tagis[Equipment.KnowInfus] <> 0) then
          perform field[trtBase].modify[+,1,"Knowledge Infusion"]
          perform assign[SkillHelp.KnowInfus]
        elseif (parent.tagis[Equipment.GearSkill] <> 0) then
          if (parent.field[grIsEquip].value = 0) then
            perform assign[Hide.Skill]
            perform assign[Helper.Disable]
            done
            endif
        elseif (parent.container.ishero = 0) then
          if (container.parent.field[grIsEquip].value = 0) then
            perform assign[Hide.Skill]
            perform assign[Helper.Disable]
            done
            endif
        else
          perform assign[Hide.Skill]
          perform assign[Helper.Disable]
          done
          endif

        ~if the thing we're bootstrapped by requires activation, but it's not
        ~active, then we're hidden
        if (parent.tagis[User.Activation] <> 0) then
          if (parent.field[abilActive].value = 0) then
            perform assign[Hide.Skill]
            perform assign[Helper.Disable]
            done
            endif
          endif


      ~if we're a skill that came from a possessing spirit, there are some
      ~changes that need to be applied
      elseif (parent.tagis[component.Adjustment] <> 0) then
        if (hero.tagis[Hero.Channeling] <> 0) then
          perform assign[Hide.Skill]
          done
          endif

        perform assign[SkillHelp.FixSkill]
        perform assign[SkillHelp.NoSpecial]
        perform assign[SkillHelp.SpiritSkl]

        ~if our parent isn't activated, we're hidden.  We also don't want to run
        ~the rest of this script, since that's when our value is added to the
        ~regular version of our skill
        if (parent.activated = 0) then
          perform assign[Hide.Skill]
          done
          endif

        ~normally, this is an overriding value
        perform field[trtOver].modify[=,container.child[attrFor].field[trtFinal].value,"Possessing Spirit's Force"]
        endif

      var ismatch as number
      var cantest as number

      ~now, check to see if a non-skillsoft copy of this skill is present on the hero
      foreach pick in hero from Skill where "!Hide.Skill & " & tagids[thingid.?]
        ismatch = 0
        cantest = 0

        ~if the skill we found is shadowed, then we can only make use of it if
        ~we're a skill from a life module, and it's also from a life module
        if (eachpick.shadowed <> 0) then

          ~if it's shadowed because it was originally added as an advancement,
          ~then that's OK - we can use that copy
          if (eachpick.tagis[Advance.Gizmo] <> 0) then
            cantest = 1
          elseif (tagis[SkillHelp.LifeSkill] <> 0) then
            if (eachpick.tagexpr[SkillHelp.LifeSkill & !SkillHelp.LaterLMSkl] <> 0) then
              cantest = 1
              endif
            endif
        else
          cantest = 1
          endif

        ~if the skill we found is ourself, discard it as an option
        if (eachpick.uniqindex = uniqindex) then
          cantest = 0
          endif

        if (cantest <> 0) then
          ~if we need a menu selection, make sure that the target's menu
          ~menu selection is the same as ours
          if (field[usrCandid1].isempty = 0) then
            if (field[usrChosen1].ischosen <> 0) then
              if (eachpick.field[usrChosen1].ischosen <> 0) then
                if (compare(eachpick.field[usrChosen1].chosen.idstring, field[usrChosen1].chosen.idstring) = 0) then
                  ismatch = 1
                  endif
                endif
              endif
          elseif (tagis[User.NeedDomain] <> 0) then
            if (eachpick.field[domDomain].isempty = 0) then
              if (field[domDomain].isempty = 0) then
                if (compare(eachpick.field[domDomain].text,field[domDomain].text) = 0) then
                  ismatch = 1
                  endif
                endif
              endif
          else
            ismatch = 1
            endif

          ~for a knowledge skill, make sure that the knowledge skill categories
          ~are the same.  For example, the Academic Knowledge: Buildings skill
          ~from a university architecture module would not stack with the
          ~Professional Knowledge: Buildings from a Trade school architecture
          ~life module
          if (tagis[component.SkillKnow] <> 0) then
            if (eachpick.field[sklKnowCat].value <> field[sklKnowCat].value) then
              ismatch = 0
              endif
            endif
          endif

        if (ismatch <> 0) then
          if (field[trtOver].value >= 0) then
            eachpick.field[trtOver].value = maximum(eachpick.field[trtOver].value,field[trtOver].value)
            perform eachpick.assign[SkillHelp.DisableSpc]
            endif
          eachpick.field[trtReplace].value = maximum(eachpick.field[trtReplace].value,field[trtReplace].value)
          perform assign[Hide.Skill]
          perform assign[SkillHelp.LaterLMSkl]
          endif
        nexteach
      ]]></eval>

    <eval index="9" phase="Traits" priority="950" name="Shadowed skills find their normal versions - early changes">
      <before name="Bound trtUser"/><![CDATA[
      ~this only applies to shadowed skills
      ~those will be the ones added as skillsofts
      doneif (shadowed + tagexpr[SkillHelp.Autosoft | SkillHelp.Personafix] = 0)

      ~exclude new skill advancements
      doneif (tagis[Advance.Gizmo] <> 0)

      ~if we have a root pick, and our root pick is an advancement, stop now
      if (isroot <> 0) then
        doneif (root.tagis[Advance.Gizmo] <> 0)

        ~if that root pick has a root, and that's an advancement, stop now
        ~(this happens when Drake is added as an advancement - the Elemental
        ~Attack skill is two bootstraps down from the actual pick)
        if (root.isroot <> 0) then
          doneif (root.root.tagis[Advance.Gizmo] <> 0)
          endif
        endif

      ~this script is specific to those added as life modules
      doneif (parent.tagis[component.LifeModule] = 0)

      perform assign[SkillHelp.LifeSkill]

      var ismatch as number
      var cantest as number

      ~now, check to see if a non-skillsoft copy of this skill is present on the hero
      foreach pick in hero from Skill where tagids[thingid.?]
        ismatch = 0
        cantest = 0

        ~if the skill we found is shadowed, then we can only make use of it if
        ~we're a skill from a life module, and it's
        if (eachpick.shadowed <> 0) then
          if (tagis[SkillHelp.LifeSkill] <> 0) then
            if (eachpick.tagis[SkillHelp.LifeSkill] <> 0) then
              cantest = 1
              endif
            endif
        else
          cantest = 1
          endif

        ~if the skill we found is ourself, discard it as an option
        if (eachpick.uniqindex = uniqindex) then
          cantest = 0
          endif

        if (cantest <> 0) then
          ~if we need a menu selection, make sure that the target's menu
          ~menu selection is the same as ours
          if (field[usrCandid1].isempty = 0) then
            if (field[usrChosen1].ischosen <> 0) then
              if (eachpick.field[usrChosen1].ischosen <> 0) then
                if (compare(eachpick.field[usrChosen1].chosen.idstring, field[usrChosen1].chosen.idstring) = 0) then
                  ismatch = 1
                  endif
                endif
              endif
          elseif (tagis[User.NeedDomain] <> 0) then
            if (eachpick.field[domDomain].isempty = 0) then
              if (field[domDomain].isempty = 0) then
                if (compare(eachpick.field[domDomain].text,field[domDomain].text) = 0) then
                  ismatch = 1
                  endif
                endif
              endif
          else
            ismatch = 1
            endif

          ~for a knowledge skill, make sure that the knowledge skill categories
          ~are the same.  For example, the Academic Knowledge: Buildings skill
          ~from a university architecture module would not stack with the
          ~Professional Knowledge: Buildings from a Trade school architecture
          ~life module
          if (tagis[component.SkillKnow] <> 0) then
            if (eachpick.field[sklKnowCat].value <> field[sklKnowCat].value) then
              ismatch = 0
              endif
            endif
          endif

        if (ismatch <> 0) then
          ~what we're going to do here is make sure that both copies - ourselves
          ~and the copy we found - have identical trtInitial fields - both the
          ~value and the history should be the same.  So, we start by recording
          ~the history that's currently in eachpick's field, then add our value
          ~to the copy we found, and then set our own value = to the new total,
          ~but we only add the history we recorded to our own history, meaning
          ~that at the end, from either copy, you'll see each thing that
          ~contributed to the history recorded here.

          if (field[trtLifMod].value <> 0) then
            perform eachpick.field[trtInitial].modify[+,field[trtLifMod].value,"Life Module: " & parent.field[name].text]
            endif
          if (eachpick.field[trtLifMod].value <> 0) then
            perform field[trtInitial].modify[+,eachpick.field[trtLifMod].value,"Life Module: " & eachpick.parent.field[name].text]
            endif
          endif
        nexteach
      ]]></eval>
Mathias is online now   #16 Reply With Quote
TCArknight
Senior Member
 
Join Date: Jan 2007
Location: NW Arkansas
Posts: 1,321

Old December 8th, 2020, 12:34 PM
Thanks Mathias, I'll dive into this to see what works best and simplest.

Working on -
  • (SWADE) WIP Savage Rifts
  • Savage Rifts (Deluxe): Update link in This post
  • Star Trek Adventures: Update link in This post

Last edited by TCArknight; December 8th, 2020 at 02:21 PM.
TCArknight is online now   #17 Reply With Quote
TCArknight
Senior Member
 
Join Date: Jan 2007
Location: NW Arkansas
Posts: 1,321

Old December 9th, 2020, 02:03 PM
New question.

I've gotten the Skill selection/improvement process working where if the skill is selected for a module, it improves the version of itself on the hero which has the Helper.MasterSkill tag I've added.

I'm using a table_dynamic for the selections of the skill. However, I've found that (when I have multiple selections available) if I add a skill to the list the first time, that is isn't available to select a second time (or more).

In order to have the skill available for multiple selections, would I need to have the skills set as not unique? What impact would that have on the quickadd process?

Working on -
  • (SWADE) WIP Savage Rifts
  • Savage Rifts (Deluxe): Update link in This post
  • Star Trek Adventures: Update link in This post
TCArknight is online now   #18 Reply With Quote
Mathias
Senior Member
Lone Wolf Staff
 
Join Date: May 2005
Posts: 13,207

Old December 9th, 2020, 03:19 PM
This is for something along the lines of knowledge skills in PF, where you need to fill in some text or make a choice in a menu? If so, then check out all of the rows dealing with the ismatch variable in the SR5 examples - that's where it's looking to make sure the same text is filled in, both on the copy on the master, and on the copy in the module, or if it's a drop-down, that the same choice was made on both. But yeah, those skills would not be unique.
Mathias is online now   #19 Reply With Quote
TCArknight
Senior Member
 
Join Date: Jan 2007
Location: NW Arkansas
Posts: 1,321

Old December 13th, 2020, 10:05 AM
Mathias,

I appreciate all the help on this.

Is it possible to bootstrap a Resource on the gizmo child that can be used to keep track of the number of selections of that type that are available?

I have the Lifepath module with this as the child:
Code:
  <!-- Lifepath Module -->
  <!-- form="lifepathgiz"> -->
  <entity
    id="lpCustom"
    form="lifepathgiz">
    <bootstrap thing="LifepathHelper"/>
    </entity>
LifepathHelper has a bootstrap of resLPSpecialty. It also has this on the script:
Code:
	  
	  foreach bootstrap in this where "thingid.resLPSpecialty"
	    eachthing.field[resMax].value += parent.field[lpNumSpec].value
		nexteach
This is the portal on the lifepathgiz form where I'm trying to display the resLPSpecialty summary:
Code:
  <portal
    id="lpSpecialty"
    style="tblNormal">
    <table_dynamic
      component="Specialty"
      showtemplate="SimpleItem"
      choosetemplate="SimpleItem"
      alwaysupdate="yes"
      scrollable="yes"
      addpick="LifepathHelper"
      headerpick="LifepathHelper"
      candidatepick="LifepathHelper"
	  candidatefield="lpSpecExpr">
      <autotag group="Helper" tag="Shadow"/>
      <headertitle><![CDATA[
        @text = parent.tagnames[LifepathCat.?,","] &" (" & parent.field[name].text & ") Specialty - " & container.childfound[resLPSpecialty].field[resShort].text
        ]]></headertitle>
      <additem><![CDATA[
        @text = "Select Specialty"
        ]]></additem>
      </table_dynamic>
    </portal>
The summary is always showing a 0 of 0 value however. Am I missing timings or something?

Working on -
  • (SWADE) WIP Savage Rifts
  • Savage Rifts (Deluxe): Update link in This post
  • Star Trek Adventures: Update link in This post
TCArknight is online now   #20 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 09:23 AM.


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