Skip to content

Instantly share code, notes, and snippets.

@robertz
Created August 24, 2018 23:41
Show Gist options
  • Save robertz/af1c19f3123f1af51c3909a51271d4ae to your computer and use it in GitHub Desktop.
Save robertz/af1c19f3123f1af51c3909a51271d4ae to your computer and use it in GitHub Desktop.
import { mapState } from 'vuex'
import mobData from '../5e-SRD-Monsters.json'
import gameData from '../gameData.json'
export default {
name: 'combat',
data () {
return {
mobs: mobData.filter((mob) => { return ('name' in mob) }),
alive: true,
mobsAlive: false,
rounds: 0,
hasInitiative: false,
opponents: [],
combatLog: []
}
},
methods: {
pcAttack: function () {
let pcAtk = this.roll('1d20')
switch (pcAtk) {
case 1:
this.combatLog.push('You rolled a 1 for attack roll. You missed!')
break
case 20:
this.combatLog.push('You rolled a 20 for attack roll. Critical Hit!')
let baseDmg = this.roll('1d6', true) + this.modifier(this.character.stats.str)
this.combatLog.push(`You hit the ${this.opponents[0].name} for ${baseDmg} points of damage.`)
this.opponents[0]._hit_points -= baseDmg
break
default:
let doesHit = pcAtk + this.modifier(this.character.stats.str) + this.byLevel.proficiency > this.opponents[0].armor_class
if (doesHit) {
let baseDmg = this.roll('1d6') + this.modifier(this.character.stats.str)
this.combatLog.push(`You hit the ${this.opponents[0].name} for ${baseDmg} points of damage.`)
this.opponents[0]._hit_points -= baseDmg
} else {
this.combatLog.push(`You attack the ${this.opponents[0].name}, but miss!`)
}
break
}
},
npcAttack: function () {
// calculate attack for each opponent
for (let m = 0; m < this.opponents.length; m++) {
if (this.character.current.hp > 0) { // if alive and opponents alive
let npcAtk = this.roll('1d20')
let validActions = this.opponents[m].actions.filter((action) => { return ('damage_dice' in action) }) || []
let selectedAction = validActions[ Math.floor(Math.random() * validActions.length) ]
let attackBonus = ('attack_bonus' in selectedAction) ? selectedAction.attack_bonus : 0
let damageBonus = ('damage_bonus' in selectedAction) ? selectedAction.damage_bonus : 0
let baseDmg = 0
switch (npcAtk) {
case 1:
this.combatLog.push(this.opponents[m].name + ' rolled a 1 for attack roll. It missed!')
break
case 20:
this.combatLog.push(this.opponents[m].name + ' rolled a 20 for attack roll. Critical Hit!')
baseDmg = this.roll(selectedAction.damage_dice, true) + this.modifier(this.opponents[m].strength) + damageBonus
this.combatLog.push(`${this.opponents[m].name}: ${selectedAction.name} for ${baseDmg} points of damage.`)
this.character.current.hp -= baseDmg
break
default:
baseDmg = this.roll(selectedAction.damage_dice) + damageBonus
let doesHit = npcAtk + this.modifier(this.opponents[m].strength) + attackBonus > this.character.attr.ac
if (doesHit) {
this.combatLog.push(`${this.opponents[m].name}: ${selectedAction.name} for ${baseDmg} points of damage.`)
this.character.current.hp -= baseDmg
} else {
this.combatLog.push(`${this.opponents[m].name}: ${selectedAction.name}, but misses!`)
}
}
}
}
},
eventLoop: function () {
if (this.rounds === 0) {
this.hasInitiative = this.character.stats.dex + this.modifier(this.character.stats.dex) > this.opponents[0].dexterity + this.modifier(this.opponents[0].dexterity)
this.opponents[0]._hit_points = this.opponents[0].hit_points
}
this.rounds++
this.mobsAlive = this.opponents.filter((op) => { return op._hit_points > 0 }).length > 0
// if hasInit player goes first, otherwise opponents go first
if (this.hasInitiative) {
this.pcAttack()
this.mobsAlive = this.opponents.filter((op) => { return op._hit_points > 0 }).length > 0
if (this.mobsAlive) {
this.npcAttack()
}
} else {
// calculate attack for each opponent
this.npcAttack()
if (this.character.current.hp > 0) {
this.pcAttack()
}
}
this.alive = this.character.current.hp > 0
this.mobsAlive = this.opponents.filter((op) => { return op._hit_points > 0 }).length > 0
// All opponents are dead and pc is alive
if (!this.mobsAlive && this.alive) {
this.combatLog.push('You have won!!!!')
for (let i = 0; i < this.opponents.length; i++) {
this.character.attr.xp += gameData.experience.filter((cr) => { return cr.challenge_rating === this.opponents[i].challenge_rating })[0].xp
}
this.$store.commit('SET_CHARACTER', this.character)
this.saveCharacter(this.character)
}
// DED
if (this.mobsAlive && !this.alive) {
this.combatLog.push('You have died!!!!')
}
},
modifier: function (value) {
return Math.floor((parseInt(value) - 10) / 2)
},
restart: function () {
this.$store.dispatch('refreshCharacter')
this.character.current.hp = this.character.attr.hp
this.rounds = 0
this.opponents = []
this.combatLog = []
let isValid = false
let op
// Not all monsters have damage rolls... this weeds out any bad data (i.e., Sprite)
while (!isValid) {
op = this.mobs[ Math.floor(Math.random() * this.mobs.length) ]
isValid = op.actions.filter((action) => { return ('damage_dice' in action) }).length > 0
}
this.opponents.push(op)
// this.opponents.push(this.mobs.filter((mob) => { return mob.name === 'Sprite' })[0])
for (let i = 0; i < this.opponents.length; i++) {
this.opponents[i]._hit_points = this.opponents[i].hit_points
}
this.alive = true
this.mobsAlive = true
},
roll: function (dice, critical = false) {
let rolls = dice.split('+')
let result = 0
for (let r = 0; r < rolls.length; r++) {
// critical roles should roll double ie 1d6 becomes 2d6
let count = critical ? rolls[r].split('d')[0] * 2 : rolls[r].split('d')[0]
let die = rolls[r].split('d')[1]
for (let i = 0; i < count; i++) {
result += Math.floor(Math.random() * die) + 1
}
}
return parseInt(result)
},
saveCharacter: function () {
localStorage.setItem('character', JSON.stringify(this.character))
this.$store.dispatch('refreshCharacter')
}
},
filters: {
plussed: function (value) {
return parseInt(value) >= 0 ? '+' + value : value
},
modifier: function (value) {
return Math.floor((parseInt(value) - 10) / 2)
}
},
computed: {
byLevel: function () {
return gameData.advancement.filter((data) => { return data.level === this.character.attr.lvl })[0]
},
...mapState(['character'])
}
}
@edm00se
Copy link

edm00se commented Aug 29, 2018

I came across this gist from the medium post, a nice read. For the love of syntax highlighting, please change your file extension to .js.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment