Skip to content

Commit

Permalink
0.15.25
Browse files Browse the repository at this point in the history
  • Loading branch information
crnormand committed Jan 16, 2023
1 parent 8e2456b commit 3631344
Show file tree
Hide file tree
Showing 12 changed files with 168 additions and 43 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

If you can't access the Google doc, here is a [PDF](https://github.com/crnormand/gurps/raw/main/docs/Guide%20for%20GURPS%204e%20on%20Foundry%20VTT.pdf) of the latest version.

# Current Release Version 0.15.24 (compatible with FoundryVTT v10.x)
# Current Release Version 0.15.25 (compatible with FoundryVTT v10.x)

With support for the [Nordlondr Ovinabokin: Bestiary and Enemies module](https://foundryvtt.com/packages/nordlond-bestiary)!

Expand Down
7 changes: 6 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
### [Users Guide](https://bit.ly/2JaSlQd) for GURPS 4e Game Aid for Foundry VTT

Release 0.15.24
Release 0.15.25 01/16/2023

- Fix Add OTF support for GM Notes module ;-)
- Added (and defaulted to) DFRPG Slam calculation

Release 0.15.24 01/11/2023

- Remove the leading + from Accuracy bonus on the character sheets. (In preparation to handle accuracy mods like "5+2"..."+5+2" just looks too weird.)
- Add OTF support for GM Notes module
Expand Down
3 changes: 2 additions & 1 deletion lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,8 @@
"GURPS.slamRelativeVelocity": "Relative Velocity",
"GURPS.slams": "slams",
"GURPS.slamShieldDB": "Shield DB",
"GURPS.slamVelocity": "Velocity",
"GURPS.slamVelocity": "Hexes moved",
"GURPS.slamDFRPGRules": "Use the Dungeon Fantasy RPG rules",
"__Status/Conditions__": "=========",
"GURPS.STATUSAgony": "Agony",
"GURPS.STATUSAim": "Aiming",
Expand Down
3 changes: 2 additions & 1 deletion lib/ranges.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,9 @@ class SizeAndSpeedRangeTable {

// pass in distance in yards, get back the furthest distance that has the same modifier
ceil(yards) {
return this._table.ceil(measure)
return this._table.ceil(yards)
}
}

const SSRT = new SizeAndSpeedRangeTable()
Hooks.on('ready', () => GURPS.SSRT = SSRT)
51 changes: 29 additions & 22 deletions module/actor/actor.js
Original file line number Diff line number Diff line change
Expand Up @@ -2922,28 +2922,35 @@ export class GurpsActor extends Actor {
// Looking for OTFs in text. ex: c:[/qty -1] during:[/anim healing c]
_removeOtf(key, text) {
if (!text) return [text, null]
var start
let patstart = text.toLowerCase().lastIndexOf(key[0] + ':[')
if (patstart < 0) {
patstart = text.toLowerCase().lastIndexOf(key + ':[')
if (patstart < 0) return [text, null]
else start = patstart + key.length + 2
} else start = patstart + 3
let cnt = 1
let i = start
if (i >= text.length) return [text, null]
do {
let ch = text[i++]
if (ch == '[') cnt++
if (ch == ']') cnt--
} while (i < text.length && cnt > 0)
if (cnt == 0) {
let otf = text.substring(start, i - 1)
let front = text.substring(0, patstart)
let end = text.substr(i)
if ((front == '' || front.endsWith(' ')) && end.startsWith(' ')) end = end.substring(1)
return [front + end, otf]
} else return [text, null]
let otf = null
let found = true
while (found) {
found = false
var start
let patstart = text.toLowerCase().indexOf(key[0] + ':[')
if (patstart < 0) {
patstart = text.toLowerCase().indexOf(key + ':[')
if (patstart < 0) return [text, otf]
else start = patstart + key.length + 2
} else start = patstart + 3
let cnt = 1
let i = start
if (i >= text.length) return [text, otf]
do {
let ch = text[i++]
if (ch == '[') cnt++
if (ch == ']') cnt--
} while (i < text.length && cnt > 0)
if (cnt == 0) {
found = true
otf = text.substring(start, i - 1)
let front = text.substring(0, patstart)
let end = text.substr(i)
if ((front == '' || front.endsWith(' ')) && end.startsWith(' ')) end = end.substring(1)
text = front + end
} else return [text, otf]
}
return [text, otf]
}

/**
Expand Down
2 changes: 1 addition & 1 deletion module/actor/effect-modifier-popout.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export class EffectModifierPopout extends Application {
let add = ''
if (!!dragData.otf) {
let action = parselink(dragData.otf)
if (action.action?.type == 'modifier')
if (action.action?.type == 'modifier' || action.action?.type == 'damage')
add = dragData.otf
}
if (!!dragData.bucket) {
Expand Down
69 changes: 59 additions & 10 deletions module/chat/slam-calc.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,51 @@ export class SlamCalculator {
let rawDamageTarget = (data.targetHp * data.relativeSpeed) / 100
let targetDice = this._getDicePlusAdds(rawDamageTarget)

let attackerAdds = (data.isAoAStrong ? 2 : 0) + (data.shieldDB || 0)
let targetAdds = -(data.shieldDB || 0)

let velocityAdd = 0

if (data.useDFRPGRules) {
let thr = data.attackerThr
let diceMatch = thr.match(/(\d+)d(.*)/i)
if (!diceMatch) {
ui.notifications.warn("Attacker Thrust damage (" + thr + ") does not include 'd'")
return
}
attackerDice = { dice: +diceMatch[1], adds: +diceMatch[2] || 0 }
thr = data.targetThr
diceMatch = thr.match(/(\d+)d(.*)/i)
if (!diceMatch) {
ui.notifications.warn("Target Thrust damage (" + thr + ") does not include 'd'")
return
}
targetDice = { dice: +diceMatch[1], adds: +diceMatch[2] || 0 }
velocityAdd = -2 // combined speed 1
if (data.relativeSpeed >= 2)
velocityAdd = -GURPS.SSRT.getModifier(data.relativeSpeed) // convert range mod to size mod
attackerAdds += velocityAdd * attackerDice.dice
targetAdds += velocityAdd * targetDice.dice
}

let attackerRoll = Roll.create(diceToFormula(attackerDice, `[Slam Attacker's roll]`, true))
await attackerRoll.evaluate({ async: true })

let adds = (data.isAoAStrong ? 2 : 0) + (data.shieldDB || 0)
let attackerResult = Math.max(attackerRoll.total + adds, 1)
let attackerMin = false
let attackerResult = attackerRoll.total + attackerAdds
if (attackerResult < 1) {
attackerResult = 1
attackerMin = true
}

let targetRoll = Roll.create(diceToFormula(targetDice, `[Slam Defender's roll]`, true))
await targetRoll.evaluate({ async: true })
let targetResult = Math.max(targetRoll.total, 1)
let targetMin = false
let targetResult = targetRoll.total + targetAdds
if (targetResult < 1) {
targetResult = 1
targetMin = true
}

let resultData = {
effect: effects.unaffected,
Expand Down Expand Up @@ -102,20 +138,21 @@ export class SlamCalculator {
attackerRaw: rawDamageAttacker,
attackerDice: attackerDice,
attackerResult: attackerResult,
attackerExplain: this.explainDieRoll(attackerRoll, data.isAoAStrong, data.shieldDB),
attackerExplain: this.explainDieRoll(attackerRoll, data.isAoAStrong, data.shieldDB, velocityAdd * attackerDice.dice, attackerMin),
// ---
target: data.targetToken.name,
targetHp: data.targetHp,
targetRaw: rawDamageTarget,
targetDice: targetDice,
targetResult: targetResult,
targetExplain: this.explainDieRoll(targetRoll),
targetExplain: this.explainDieRoll(targetRoll, false, -data.shieldDB, velocityAdd * targetDice.dice, targetMin),
// ---
effect: resultData.effect,
isAoAStrong: data.isAoAStrong,
relativeSpeed: data.relativeSpeed,
result: result,
shieldDB: data.shieldDB,
useDFRPGRules: data.useDFRPGRules
})

// const speaker = { alias: attacker.name, _id: attacker._id, actor: attacker }
Expand All @@ -128,7 +165,16 @@ export class SlamCalculator {
sound: this.rollThemBones([targetRoll]),
}

ChatMessage.create(messageData)
ChatMessage.create(messageData).then(async () => {
let targets = []
game.user.targets.forEach(t => targets.push(t))
game.user.targets.clear()
await GURPS.executeOTF(`/r [${attackerResult} cr @${data.targetToken.name}]`)
GURPS.LastActor = data.targetToken.actor
await GURPS.executeOTF(`/r [${targetResult} cr @${data.attackerToken.name}]`)
GURPS.LastActor = data.attackerToken.actor
targets.forEach(t => game.user.targets.add(t))
})
}

targetFallsDown(attackerResult, targetResult) {
Expand All @@ -140,7 +186,7 @@ export class SlamCalculator {
}

targetDXCheck(attackerResult, targetResult) {
return attackerResult >= targetResult && !this.targetFallsDown(attackerResult, targetResult)
return attackerResult > targetResult && !this.targetFallsDown(attackerResult, targetResult)
}

/**
Expand Down Expand Up @@ -201,17 +247,20 @@ export class SlamCalculator {
}
}

explainDieRoll(roll, isAoAStrong = false, shieldDB = 0) {
explainDieRoll(roll, isAoAStrong = false, shieldDB = 0, velocity = 0, min = false) {
let diceArray = roll.dice
let resultsArray = diceArray.flatMap(it => it.results)
let results = resultsArray.map(it => it.result)

let explanation =
roll.terms.length > 1 ? `${i18n('GURPS.rolled')} (${results})` : `${i18n('GURPS.rolled')} ${results}`
if (roll.terms[2] !== '0') explanation += `${roll.terms[1].formula}${roll.terms[2].formula}`
if (roll.terms[2]?.number !== '0') explanation += `${roll.terms[1].formula}${roll.terms[2].formula}`

if (!!isAoAStrong) explanation += ` + 2 (${i18n('GURPS.slamAOAStrong')})`
if (!!shieldDB) explanation += ` + ${shieldDB} (${i18n('GURPS.slamShieldDB')})`
let sign = shieldDB >= 0 ? '+' : '-'
if (!!shieldDB) explanation += ` ${sign} ${math.abs(shieldDB)} (${i18n('GURPS.slamShieldDB')})`
if (!!velocity) explanation += ` + ${velocity} ${i18n('GURPS.slamRelativeVelocity')}`
if (min) explanation += ` (${i18n('GURPS.minimum')} 1)`
return explanation
}
}
22 changes: 21 additions & 1 deletion module/chat/slam.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,12 @@ class SlamCalculatorForm extends FormApplication {

this._targetHp = !!target ? target.actor.system.HP.max : 10
this._targetSpeed = 0

this._attackerThr = !!attacker ? attacker.actor.system.thrust : '1d-5'
this._targetThr = !!target ? target.actor.system.thrust : '1d-5'

this._isAoAStrong = false
this._useDFRPGRules = true
this._shieldDB = 0
}

Expand Down Expand Up @@ -104,12 +108,15 @@ class SlamCalculatorForm extends FormApplication {

data.targetHp = this._targetHp
data.targetSpeed = this._targetSpeed

data.attackerThr = this._attackerThr
data.targetThr = this._targetThr

data.relativeSpeed = this.relativeSpeed

data.isAoAStrong = this._isAoAStrong
data.shieldDB = this._shieldDB

data.useDFRPGRules = this._useDFRPGRules
return data
}

Expand All @@ -129,6 +136,11 @@ class SlamCalculatorForm extends FormApplication {
this._isAoAStrong = $(ev.currentTarget).is(':checked')
})

html.find('#dfrpgrules').click(ev => {
this._useDFRPGRules = $(ev.currentTarget).is(':checked')
setTimeout(() => this.render(true), 10)
})

html.find('#db').change(ev => {
this._shieldDB = parseInt(ev.currentTarget.value)
})
Expand All @@ -150,5 +162,13 @@ class SlamCalculatorForm extends FormApplication {
html.find('#target-hp').change(ev => {
this._targetHp = parseInt(ev.currentTarget.value)
})

html.find('#attacker-thr').change(ev => {
this._attackerThr = ev.currentTarget.value
})

html.find('#target-thr').change(ev => {
this._targetThr = ev.currentTarget.value
})
}
}
6 changes: 6 additions & 0 deletions module/gurps.js
Original file line number Diff line number Diff line change
Expand Up @@ -2495,6 +2495,12 @@ if (!globalThis.GURPS) {
return doc;
}
}])

Hooks.on('renderGMNote', (app, html, options) => {
let h = html.find('[data-edit')
h[0].innerHTML = gurpslink(h[0].innerHTML)
GurpsWiring.hookupAllEvents(html)
})

// End of system "READY" hook.
Hooks.call('gurpsready')
Expand Down
4 changes: 2 additions & 2 deletions system.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"id": "gurps",
"title": "GURPS 4e Game Aid (Unofficial)",
"description": "A game aid to help play GURPS 4e for Foundry VTT",
"version": "0.15.24",
"version": "0.15.25",
"authors": [
{
"name": "Chris Normand",
Expand Down Expand Up @@ -81,7 +81,7 @@
"secondaryTokenAttribute": "FP",
"url": "https://github.com/crnormand/gurps",
"manifest": "https://raw.githubusercontent.com/crnormand/gurps/release/system.json",
"download": "https://github.com/crnormand/gurps/archive/0.15.24.zip",
"download": "https://github.com/crnormand/gurps/archive/0.15.25.zip",
"socket": true,
"license": "LICENSE.txt"
}
14 changes: 14 additions & 0 deletions templates/slam-calculator.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,20 @@ <h2>
<i>{{i18n "GURPS.slams"}} <i class="subtle fas fa-align-right"></i><i class="fas fa-running"></i></i>
{{targetToken.name}}
</h2>
<div style="display: flex; justify-content: center; align-items: stretch; align-self: center; ">
<span><label for="dfrpgrules">{{i18n "GURPS.slamDFRPGRules"}}:</label>
<input id="dfrpgrules" type="checkbox" {{#if useDFRPGRules}}checked{{/if}}/></span>
</div>
<div class="gga-group inputs" style="height: unset; border: none">
<h4>{{attackerToken.name}}</h4>
<div class="label-value-row">
{{#if useDFRPGRules}}
<label>{{i18n "GURPS.thrust"}}:</label>
<div><input id="attacker-thr" type="text" value="{{attackerThr}}" data-dtype="String"/></div>
{{else}}
<label>{{i18n "GURPS.HP"}}:</label>
<div><input id="attacker-hp" type="text" value="{{attackerHp}}" data-dtype="Number" /></div>
{{/if}}
<label>{{i18n "GURPS.slamVelocity"}}:</label>
<div><input id="attacker-speed" type="text" value="{{attackerSpeed}}" data-dtype="Number" /></div>
<label for="aoa">{{i18n "GURPS.slamAOAStrong"}}:</label>
Expand All @@ -20,8 +29,13 @@ <h4>{{attackerToken.name}}</h4>
<div class="gga-group inputs" style="height: unset; border: none; padding-top: 0.5em">
<h4>{{targetToken.name}}</h4>
<div class="label-value-row">
{{#if useDFRPGRules}}
<label>{{i18n "GURPS.thrust"}}:</label>
<div><input id="target-thr" type="text" value="{{targetThr}}" data-dtype="String"/></div>
{{else}}
<label>{{i18n "GURPS.HP"}}:</label>
<input id="target-hp" type="text" value="{{targetHp}}" data-dtype="Number" />
{{/if}}
<label>{{i18n "GURPS.slamVelocity"}}:</label>
<div><input id="target-speed" type="text" value="{{targetSpeed}}" data-dtype="Number" /></div>
</div>
Expand Down
Loading

0 comments on commit 3631344

Please sign in to comment.