From GamingWiki
(11 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | {{Documentation}} | + | {{Documentation}}<!-- |
− | {| | + | -->{{#if: {{#vardefineecho: debug | }} | debug mode enabled <br />}}<!-- |
− | < | ||
-->{{#vardefine: cols | {{{columns|6}}} }}<!-- | -->{{#vardefine: cols | {{{columns|6}}} }}<!-- | ||
− | debug: hard-code it for now. | + | --> |
+ | <onlyinclude><!-- | ||
+ | |||
+ | debug: hard-code some of it for now. | ||
− | + | @todo: implement skill point expenditure | |
− | |||
− | |||
− | |||
-->{{#hashdefine: sectionParams}}<!-- | -->{{#hashdefine: sectionParams}}<!-- | ||
Line 18: | Line 17: | ||
-->{{#hashinclude: sectionParams | -->{{#hashinclude: sectionParams | ||
| columns = {{#var:cols}} | | columns = {{#var:cols}} | ||
+ | | subhead = {{{label|Skill modes}}} | ||
| labelclass1 = label | | labelclass1 = label | ||
| llabel1 = | | llabel1 = | ||
Line 25: | Line 25: | ||
| llabel5 = Fair (+2) | | llabel5 = Fair (+2) | ||
| llabel6 = Average (+1) | | llabel6 = Average (+1) | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
}}<!-- end section | }}<!-- end section | ||
− | -->{{#arraydefine:modeArray|{{#ask: [[is a :: skill]] [[ | + | TERMINOLOGY: |
− | |? | + | * Rank: position on the adjective ladder. May be divided into rankName and rankVal |
− | |? | + | * Level: skill level, i.e, untrained, trained, focused or specialized |
− | | format=array | + | |
− | }}}}<!-- | + | -->{{#vardefine:modeGood|{{{skill mode good|Banter}}}}}<!-- |
+ | -->{{#vardefine:modeFair|{{{skill mode fair|Space}}}}}<!-- | ||
+ | -->{{#vardefine:modeAverage|{{{skill mode average|Action}}}}}<!-- | ||
+ | |||
+ | --><includeonly><!-- | ||
+ | -->{{#set: | ||
+ | | has good skill mode = {{#var:modeGood}} | ||
+ | | has fair skill mode = {{#var:modeFair}} | ||
+ | | has average skill mode = {{#var:modeAverage}} | ||
+ | }}<!-- | ||
+ | --></includeonly><!-- | ||
+ | |||
+ | -->{{#if: {{#var: debug}} | | ||
+ | '''debug''' Setting modes to: | ||
+ | * good = {{#vardefineecho:modeGood|Banter}} | ||
+ | * fair = {{#vardefineecho:modeFair|Space}} | ||
+ | * average = {{#vardefineecho:modeAverage|Action}} | ||
+ | }}<!-- | ||
+ | |||
+ | Some initial arrays and hashes: | ||
+ | * modeArray lists the three modes in ascending rank | ||
+ | * levelArray lists all four levels in ascending order | ||
+ | * levelSubArray is like levelArray, without "untrained". | ||
+ | * modeHash is to be populated later. The eventual structure will be: | ||
+ | * keys are mode names | ||
+ | * values are hashtables, defined as: | ||
+ | * keys are levels | ||
+ | * values are arrays of skill names | ||
+ | |||
+ | -->{{#arraydefine: modeArray | {{#var: modeAverage}}, {{#var: modeFair}}, {{#var: modeGood}} | , }}<!-- | ||
+ | -->{{#arraydefine: levelArray | untrained, trained, focused, specialized | , }}<!-- | ||
+ | -->{{#arrayslice: levelSubarray | levelArray | 1 }}<!-- | ||
+ | -->{{#hashdefine: modeHash}}<!-- | ||
+ | -->{{#arrayprint: modeArray | | <mode> | <!-- | ||
+ | -->{{#hashinclude: modeHash | <mode> = {{#arrayprint: levelSubArray | <LEVELSEP> | <level> | <level><LEVELVAL>}} }}<!-- | ||
+ | -->}}<!-- | ||
+ | |||
+ | -->{{#if: {{#var: debug}} |<nowiki /> | ||
+ | {{#ask: [[is a::skill mode]] [[campaign::Humans are the Worst]] [[mode name :: {{#arrayprint: modeArray | {{!}}{{!}} }}]] | ||
+ | |?mode name | ||
+ | |?Includes skill | ||
+ | }} | ||
+ | }}<!-- | ||
+ | |||
+ | Query all skills found belonging to our three modes. | ||
+ | -->{{#hashdefine:skillModeHash | | ||
+ | {{#ask: [[is a::skill mode]] [[campaign::Humans are the Worst]] [[name :: {{#arrayprint: modeArray | {{!}}{{!}} }}]] | ||
+ | |?Mode name | ||
+ | |?Includes skill | ||
+ | |format=array | ||
+ | |mainlabel=- | ||
+ | }} | ||
+ | | , | ||
+ | | <PROP> | ||
+ | }}<!-- | ||
+ | |||
+ | -->{{#if: {{#var: debug}} |<nowiki /> | ||
− | + | '''debug''' query result (skillModeHash): {{#hashprint: skillModeHash | | <modename> | <modeskills> | <modename>=<modeskills><br/>}} | |
− | + | }}<!-- | |
− | -->{{#hashdefine: | + | |
− | -->{{# | + | Now that we have all the skill mode details, we put them into a hashTable |
− | -->{{# | + | that maps each skill to the modes it is found in: |
− | -->{{# | + | |
− | + | -->{{#hashdefine: skillHash}}<!-- | |
− | + | -->{{#hashprint: skillModeHash | | <modename> | <modeskills> | <!-- | |
− | + | -->{{#arraydefine: modeSkills | <modeskills> | <MANY> | unique}}<!-- | |
− | -->{{#hashinclude: | + | -->{{#arrayprint: modeSkills | | <skillname> | <!-- |
− | + | -->{{#arraydefine: skillModes | {{#hashvalue: skillHash | <skillname>}} <MANY> <modename> | <MANY> | unique,sort=asc}}<!-- | |
+ | -->{{#hashinclude: skillHash | <skillname>={{#arrayprint: skillModes | <MANY>}} }}<!-- | ||
-->}}<!-- | -->}}<!-- | ||
− | -->{{# | + | -->}}<!-- |
− | + | ||
− | + | -->{{#if: {{#var: debug}} |<nowiki /> | |
− | -->|}}<!-- | + | |
− | + | '''debug''' skillHash: {{#hashprint: skillHash | | <skillname> | <skillmodes> | <skillname>=<skillmodes><br/>}} | |
− | -->{{# | + | }}<!-- |
− | + | ||
+ | |||
+ | Apply skill point bumps | ||
+ | @todo: The next step is to apply spent skill points. We'll do some error-checking here. | ||
+ | |||
+ | -->{{#vardefine:skillPointsUsed|0}}<!-- | ||
+ | -->{{#vardefine:pointBuy|point buy}}<!-- | ||
+ | |||
+ | -->{{#vardefine: skillBumps | {{{skill bump|}}} }}<!-- | ||
+ | |||
+ | --></onlyinclude><!-- | ||
+ | -->{{#vardefine: skillBumps | Gunnery, Gunnery, Will, Notice, Fight, Notice }}<!-- | ||
+ | --><onlyinclude><!-- | ||
+ | |||
+ | -->{{#arraydefine: skillBumpArray | {{#var:skillBumps}} }}<!-- | ||
+ | -->{{#arrayprint: skillBumpArray ||<skill>|<!-- | ||
+ | -->{{#hashinclude: skillHash | <skill> = {{#hashvalue: skillHash | <skill>}}<MANY>{{#var:pointBuy}} }}<!-- | ||
+ | -->}}<!-- | ||
+ | |||
+ | -->{{#arraydefine: skillArray | {{#hashprint: skillHash |,| <skillname> | <skillmodes> | <skillname><PROP><skillmodes>}} }}<!-- | ||
+ | |||
+ | -->{{#if: {{#var: debug}} |<nowiki /> | ||
+ | |||
+ | '''debug''' skillArray: {{#arrayprint: skillArray | <br/> }} | ||
+ | }}<!-- | ||
+ | |||
+ | Now iterate over all the skills returned from our query | ||
+ | |||
+ | -->{{#hashprint: skillHash | | <skillname> | <skillmodes> | <!-- | ||
+ | |||
+ | -->{{#hashdefine: currentSkill}}<!-- | ||
+ | |||
+ | -->{{#vardefine: currentSkillName | <skillname> }}<!-- | ||
+ | |||
+ | -->{{#if: {{#var: debug}} |<nowiki /> | ||
+ | |||
+ | '''debug''' currentSkillName: {{#var: currentSkillName }} | ||
+ | }}<!-- | ||
+ | |||
+ | First we create an array containing all the modes the current skill | ||
+ | belongs to. Then we use that array as a filter so we end up with the | ||
+ | intersection of the skill's modes and the character's modes -- i.e, all | ||
+ | the character's modes that contain the current skill. This final array | ||
+ | is currentSkillModes. | ||
+ | -->{{#arraydefine: currentSkillAllModes | <skillmodes> | <MANY> }}<!-- | ||
+ | -->{{#arraysearcharray: currentSkillModes | modeArray | /^{{#arrayprint: currentSkillAllModes | {{!}} }}$/ }}<!-- | ||
+ | |||
+ | -->{{#if: {{#var: debug}} |<nowiki /> | ||
+ | '''debug''' currentSkillAllModes: {{#arrayprint: currentSkillAllModes | , }} | ||
+ | '''debug''' currentSkillModes: {{#arrayprint: currentSkillModes | , }} | ||
+ | }}<!-- | ||
+ | |||
+ | Now the number of entries in currentSkillModes is the number of the | ||
+ | character's modes the current skill appears in. This also happens to be | ||
+ | the bonus the skill has as a result of skill reinforcement [FSTK 30]. | ||
+ | And the last element of currentSkillModes should be the character's | ||
+ | highest-ranked mode for this skill. | ||
+ | -->{{#vardefine: currentSkillPrimaryMode | {{#arrayindex: currentSkillModes | -1 }} }}<!-- | ||
+ | -->{{#vardefine: synergySkillLevel | {{#arraysize: currentSkillModes}} }}<!-- | ||
+ | -->{{#vardefine: totalSkillLevel | {{#arraysize: currentSkillAllModes}} }}<!-- | ||
+ | -->{{#ifexpr: {{#var: totalSkillLevel}} > 3 | {{#vardefine: totalSkillLevel | 3}} }}<!-- | ||
+ | -->{{#vardefine: pointBuyBumps | {{#expr: {{#var:totalSkillLevel}} - {{#var:synergySkillLevel}} }} }}<!-- | ||
+ | -->{{#vardefine: pointsSpent | {{#expr: {{#var:synergySkillLevel}} * {{#var:pointBuyBumps}} + {{#var:pointBuyBumps}} * ( {{#var:pointBuyBumps}} - 1 ) / 2 }} }}<!-- | ||
+ | -->{{#vardefine: skillPointsUsed | {{#expr: {{#var:skillPointsUsed}} + {{#var:pointsSpent}} }} }}<!-- | ||
+ | -->{{#vardefine: currentSkillLevel | {{#arrayindex: levelArray | {{#var: totalSkillLevel}} }} }}<!-- | ||
+ | |||
+ | Hash of all the levels of the primary mode, keyed by level name. We're | ||
+ | going to append the current skill to it and then put it back in modeHash. | ||
+ | -->{{#hashdefine: levelsOfPrimaryMode | {{#hashvalue: modeHash | {{#var: currentSkillPrimaryMode}} }} | <LEVELSEP> | <LEVELVAL> }}<!-- | ||
+ | |||
+ | -->{{#if: {{#var: debug}} |<nowiki /> | ||
+ | '''debug''' currentSkillPrimaryMode: {{#var: currentSkillPrimaryMode }} | ||
+ | '''debug''' synergySkillLevel: {{#var: synergySkillLevel }} | ||
+ | '''debug''' totalSkillLevel: {{#var: totalSkillLevel }} | ||
+ | '''debug''' pointBuyBumps: {{#var: pointBuyBumps }} | ||
+ | '''debug''' pointsSpent: {{#var: pointsSpent }} | ||
+ | '''debug''' skillPointsUsed: {{#var: skillPointsUsed }} | ||
+ | '''debug''' currentSkillLevel: {{#var: currentSkillLevel }} | ||
+ | '''debug''' levelsOfPrimaryMode: {{#hashprint: levelsOfPrimaryMode | <br/> | <level> | <skills> | <level> = <skills> }} | ||
+ | }}<!-- | ||
+ | |||
+ | Array of the skills defined for the primary mode, at this level. Here we | ||
+ | append the current skill along with a separator. The first time we do | ||
+ | this for any given mode-level combination we'll get an empty element, so | ||
+ | we ensure that the elements are unique. We also sort them because | ||
+ | sorting is nice :) | ||
+ | -->{{#arraydefine: modeSkillsAtLevel <!-- | ||
+ | -->| {{#hashvalue: levelsOfPrimaryMode | {{#var: currentSkillLevel }} }} <LEVELSKILL> {{#var: currentSkillName}} <!-- | ||
+ | -->| <LEVELSKILL> | unique,sort=asc <!-- | ||
-->}}<!-- | -->}}<!-- | ||
− | + | Now we reassemble the original hash: | |
− | + | -->{{#hashinclude: levelsOfPrimaryMode | {{#var: currentSkillLevel }} = {{#arrayprint: modeSkillsAtLevel | <LEVELSKILL> }} }}<!-- | |
− | + | -->{{#hashinclude: modeHash | <!-- | |
− | + | --> {{#var: currentSkillPrimaryMode}} = {{#hashprint: levelsOfPrimaryMode | <LEVELSEP> | <K> | <V> | <K><LEVELVAL><V> }} <!-- | |
− | --> | ||
− | |||
− | |||
-->}}<!-- | -->}}<!-- | ||
+ | |||
+ | -->{{#arrayreset: modeSkillsAtLevel | currentSkillAllModes | currentSkillModes }}<!-- | ||
+ | -->{{#hashreset: currentSkill | levelsOfPrimaryMode }}<!-- | ||
+ | |||
-->}}<!-- | -->}}<!-- | ||
− | + | Once the above loop is done modeHash should have the desired structure. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | -->{{# | + | -->{{#if: {{#var: debug}} |<nowiki /> |
− | + | modeHash: {{#hashprint: modeHash | | <modename> | <levels> | <br/> <modename> = <levels> }} | |
+ | }}<!-- | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Process and print all three modes: | |
− | |||
− | |||
− | |||
− | + | Each element of modeLoopArray is composed of a rank name, the prefix of the | |
− | -->{{# | + | fields each mode should use, and the index of the field that should contain the |
− | -->{{# | + | "trained" level skills. |
− | -->{{# | + | -->{{#arraydefine: modeLoopArray | Good;ldata;4, Fair;cdata;5, Average;rdata;6}}<!-- |
− | -->{{# | + | -->{{#arrayprint: modeLoopArray | | <currentModeArray> |<!-- |
− | + | ||
− | -->{{# | + | -->{{#vardefine: currentModeRank | {{#explode: <currentModeArray> | ; | 0 }} }}<!-- |
− | -->{{# | + | -->{{#vardefine: currentFieldPrefix | {{#explode: <currentModeArray> | ; | 1 }} }}<!-- |
− | -->{{# | + | -->{{#vardefine: currentTrainedIndex | {{#explode: <currentModeArray> | ; | 2 }} }}<!-- |
− | + | -->{{#vardefine: currentModeName | {{#var: mode{{#var:currentModeRank}} }} }}<!-- | |
− | + | ||
− | -->{{# | + | Head each column with a mode name |
− | -->{{# | + | -->{{#hashinclude: sectionParams | {{#var: currentFieldPrefix}}1 = {{#var:currentModeName}} }}<!-- |
− | + | ||
− | | | + | Create a hash, currentModeHash, to contain all the information we need about |
− | }}<!-- | + | the current mode's skills. |
+ | -->{{#hashdefine: currentModeHash | {{#hashValue: modeHash | {{#var: currentModeName}} }} | <LEVELSEP> | <LEVELVAL> }}<!-- | ||
+ | |||
+ | Iterate over the indices of our parameter fields to populate our param | ||
+ | hash with skill names. | ||
+ | -->{{#loop: fieldIndex | 6 | -5 | <!-- | ||
+ | -->{{#vardefine: fieldName | {{#var: currentFieldPrefix}}{{#var: fieldIndex}} }}<!-- | ||
+ | -->{{#vardefine: fieldClass | {{#var: currentFieldPrefix}}class{{#var: fieldIndex}} }}<!-- | ||
+ | |||
+ | Map the elements of our list of levels onto the indices of our fields. | ||
+ | This means that for the Good mode, trained skills will go in field 4, | ||
+ | focused in field 3 and specialized in field 2. | ||
+ | -->{{#vardefine: currentLevelIndex | {{#expr: {{#var: currentTrainedIndex}} - {{#var: fieldIndex}} }} }}<!-- | ||
+ | -->{{#vardefine: currentLevel | <!-- | ||
+ | -->{{#ifexpr: ( {{#var: currentLevelIndex}} >= 0 ) and ( {{#var: currentLevelIndex}} < {{#arraysize: levelSubarray}}) <!-- | ||
+ | -->| {{#arrayindex: levelSubarray | {{#var: currentLevelIndex}} }}<!-- | ||
+ | -->| <!-- | ||
+ | -->}}<!-- | ||
-->}}<!-- | -->}}<!-- | ||
− | -->}}<!-- | + | |
− | -->}}<!-- | + | By default, give all fields a non-breaking space for content and the |
+ | "shaded" class: | ||
+ | -->{{#hashinclude: sectionParams | {{#var: fieldName}} = | {{#var: fieldClass}} = shaded }}<!-- | ||
+ | -->{{#if: {{#var: currentLevel}} |<!-- | ||
+ | |||
+ | -->{{#if: {{#var: debug}} |<nowiki /> | ||
+ | |||
+ | currentModeName: {{#var: currentModeName}} | ||
+ | currentLevel: {{#var: currentLevel }} | ||
+ | }}<!-- | ||
+ | |||
+ | Here the current loop index corresponds to a level. We set the | ||
+ | appropriate CSS class and look for skills at this level. | ||
+ | |||
+ | -->{{#hashinclude: sectionParams | {{#var: fieldClass}} = {{#var: currentLevel}} skill }}<!-- | ||
+ | |||
+ | Now look for skills and print them, if any | ||
+ | |||
+ | -->{{#arraydefine: levelSkills | {{#hashvalue: currentModeHash | {{#var: currentLevel}} }} | <LEVELSKILL> }}<!-- | ||
+ | -->{{#if: {{#arrayprint: levelSkills}} | <!-- | ||
− | + | -->{{#if: {{#var: debug}} |<nowiki /> | |
− | -->{{# | + | '''debug''' levelSkills: {{#arrayprint: levelSkills}} |
− | + | }}<!-- | |
− | |||
− | + | If a skill belongs to more than one mode, we note it with an <abbr> tag: | |
− | |||
− | |||
− | |||
− | |||
− | + | -->{{#arraydefine: levelSkillsPrintable | <!-- | |
− | -->{{# | + | -->{{#arrayprint: levelSkills | , | <skillname> | <!-- |
+ | -->{{#arraydefine: currentSkillAllModes | {{#hashvalue: skillHash | <skillname> }} | <MANY> | unique }}<!-- | ||
+ | -->{{#ifeq: {{#arraysize: currentSkillAllModes}} | 1 <!-- | ||
+ | -->| <skillname> <!-- | ||
+ | -->| <abbr title="{{#arrayprint:currentSkillAllModes}}"><skillname></abbr> <!-- | ||
+ | -->}}<!-- | ||
+ | --><includeonly><!-- | ||
+ | -->{{#set: has {{#var: currentLevel }} skill = <skillname> }}<!-- | ||
+ | --></includeonly><!-- | ||
+ | -->}}<!-- | ||
+ | -->}}<!-- | ||
− | + | -->{{#if: {{#var: debug}} |<nowiki /> | |
− | -->{{# | + | '''debug''' levelSkillsPrintable: {{#arrayprint: levelSkillsPrintable}} |
− | + | }}<!-- | |
− | |||
− | + | There are skills at this level. Save them to the param hash. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | -->{{#hashinclude: sectionParams | {{#var: fieldName}} = {{#arrayprint: levelSkillsPrintable}} }}<!-- | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
-->}}<!-- | -->}}<!-- | ||
-->}}<!-- | -->}}<!-- | ||
− | -->}}<!-- | + | -->}}<!-- end loop |
− | -->}}<!-- end | + | |
+ | End mode processing. | ||
+ | |||
+ | -->}}<!-- end arrayprint | ||
+ | |||
− | + | -->{{#if: {{#var: debug}} |<nowiki /> | |
− | -->{{# | ||
− | |||
− | |||
− | + | '''debug''' sectionParams: {{#hashprint: sectionParams | | <key> | <value> | <br/> <key> = <value> }} | |
− | + | }}<!-- | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | }}<!-- | ||
− | + | --></onlyinclude><nowiki /> | |
− | --> | + | {| class="infobox" |
− | + | <onlyinclude><!-- | |
− | + | ||
− | + | Now print the table section | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | -->{{#hashtotemplate: Character sheet/section | sectionParams }}<!-- | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Print the section footer. This contains a summary of advancement points available and spent. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | -->{{#vardefine:skillsAllowed|7}}<!-- | |
− | -->{{# | + | -->{{Character sheet/section |
− | {{Character sheet/section | ||
| columns = {{#var:cols}} | | columns = {{#var:cols}} | ||
− | | llabel1 = | + | | llabel1 = bonus points | ldata1 = {{#var:skillsAllowed}} |
− | | label1 = | + | | label1 = used | data1 = {{#var:skillPointsUsed}} |
− | | rlabel1 = | + | | rlabel1 = remaining | rdata1 = {{#expr: {{#var:skillsAllowed}} - {{#var:skillPointsUsed}} }} |
}}<!-- end section | }}<!-- end section | ||
-->}}<!-- end if | -->}}<!-- end if | ||
− | --> | + | --></onlyinclude><nowiki /> |
− | + | |} | |
+ | <onlyinclude><!-- | ||
+ | |||
--></onlyinclude> | --></onlyinclude> | ||
− |
Latest revision as of 02:36, 29 July 2014
[create]
Error creating thumbnail: File missing
Template documentation Editors can experiment in this template's sandbox (create) and testcases (create) pages. Please add categories and interwikis to the /doc subpage. Subpages of this template. |
Skill modes | |||||
Banter | Space | Action | |||
Superb (+5) | Gunnery, Notice | ||||
Great (+4) | Fight, Will | ||||
Good (+3) | |||||
Fair (+2) | |||||
Average (+1) | |||||
bonus points | 7 | used | -4 | remaining | 11 |