Go binary/server for helping run/build sessions for the Maze Rats TTRPG
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

310 lines
6.7 KiB

package tables
import (
"fmt"
"mazeratsgen/internal/data"
"mazeratsgen/internal/dice"
"strings"
)
type MonsterTable struct {
Roller *dice.Roller
}
type MonsterStat struct {
Value int
Qualifier string
}
type MonsterStats struct {
Health MonsterStat
Attack MonsterStat
Armor MonsterStat
STR MonsterStat
DEX MonsterStat
WIL MonsterStat
}
type Monster struct {
Base string
Stats MonsterStats
Feature string
Trait string
Ability string
Tactics string
Personality string
Weakness string
Seed int64
}
func (t *MonsterTable) Generate() Monster {
baseRoll, _ := t.Roller.Roll("1d6")
return Monster{
Base: t.Base(baseRoll[0]),
Stats: t.genStats(),
Feature: t.Feature(t.Roller.TableRoll()),
Trait: t.Trait(t.Roller.TableRoll()),
Ability: t.Ability(t.Roller.TableRoll()),
Tactics: t.Tactic(t.Roller.TableRoll()),
Personality: t.Personality(t.Roller.TableRoll()),
Weakness: t.Weakness(t.Roller.TableRoll()),
Seed: t.Roller.Seed,
}
}
func (t *MonsterTable) Template() string {
return strings.TrimSpace(`
Type: {{.Trait}} {{.Base}}
Stats:
Health: {{.Stats.Health.Value}} ({{.Stats.Health.Qualifier}})
Armor: {{.Stats.Armor.Value}} ({{.Stats.Armor.Qualifier}})
Attack: +{{.Stats.Attack.Value}} ({{.Stats.Attack.Qualifier}})
STR: +{{.Stats.STR.Value}} ({{.Stats.STR.Qualifier}})
DEX: +{{.Stats.DEX.Value}} ({{.Stats.DEX.Qualifier}})
WIL: +{{.Stats.WIL.Value}} ({{.Stats.WIL.Qualifier}})
Feature: {{.Feature}}
Ability: {{.Ability}}
Tactics: {{.Tactics}}
Personality: {{.Personality}}
Weakness: {{.Weakness}}
Seed: {{.Seed}}
`)
}
func (t MonsterTable) Weakness(roll [2]int) string {
magicTable := MagicTable{Roller: t.Roller}
treasureTable := TreasureTable{Roller: t.Roller}
switch roll {
case [2]int{3, 5}:
return magicTable.Insanity(t.Roller.TableRoll())
case [2]int{4, 4}:
return "Pick an existing NPC"
case [2]int{4, 6}:
return magicTable.PhysicalElement(t.Roller.TableRoll())
case [2]int{6, 2}:
return treasureTable.ValuableMaterial(t.Roller.TableRoll())
case [2]int{6, 4}:
return treasureTable.WeaponItem(t.Roller.TableRoll())
default:
return data.Tables.Monster.Weakness[roll[0]-1][roll[1]-1]
}
}
func (t MonsterTable) genStats() MonsterStats {
return MonsterStats{
Health: t.genHealth(),
Attack: t.genAttack(),
Armor: t.genArmor(),
STR: t.genSTR(),
DEX: t.genDEX(),
WIL: t.genWIL(),
}
}
func (t MonsterTable) genHealth() MonsterStat {
typeRoll, _ := t.Roller.Roll("1d5")
mStat := MonsterStat{}
switch typeRoll[0] {
case 1:
mStat.Qualifier = "Weak"
case 2:
mStat.Qualifier = "Typical"
case 3:
mStat.Qualifier = "Tough"
case 4:
mStat.Qualifier = "Hulking"
case 5:
mStat.Qualifier = "Colossal"
}
hpRoll, _ := t.Roller.Roll(fmt.Sprintf("%vd6", typeRoll[0]))
hp := 0
for _, hpDie := range hpRoll {
hp += hpDie
}
mStat.Value = hp
return mStat
}
func (t MonsterTable) genArmor() MonsterStat {
typeRoll, _ := t.Roller.Roll("1d5")
mStat := MonsterStat{}
switch typeRoll[0] {
case 1:
mStat.Qualifier = "Unarmored"
mStat.Value = 6
case 2:
mStat.Qualifier = "Light protection"
mStat.Value = 7
case 3:
mStat.Qualifier = "Moderate protection"
mStat.Value = 8
case 4:
mStat.Qualifier = "Heavy protection"
mStat.Value = 9
case 5:
mStat.Value = 10
mStat.Qualifier = "Nigh impervious"
}
return mStat
}
func (t MonsterTable) genAttack() MonsterStat {
typeRoll, _ := t.Roller.Roll("1d5")
mStat := MonsterStat{}
switch typeRoll[0] {
case 1:
mStat.Qualifier = "Untrained"
mStat.Value = 0
case 2:
mStat.Qualifier = "Trained"
mStat.Value = 1
case 3:
mStat.Qualifier = "Dangerous"
mStat.Value = 2
case 4:
mStat.Qualifier = "Masterful"
mStat.Value = 3
case 5:
mStat.Value = 4
mStat.Qualifier = "Lethal"
}
return mStat
}
func (t MonsterTable) genSTR() MonsterStat {
typeRoll, _ := t.Roller.Roll("1d5")
mStat := MonsterStat{}
switch typeRoll[0] {
case 1:
mStat.Qualifier = "Weak"
mStat.Value = 0
case 2:
mStat.Qualifier = "Average"
mStat.Value = 1
case 3:
mStat.Qualifier = "Strong"
mStat.Value = 2
case 4:
mStat.Qualifier = "Powerful"
mStat.Value = 3
case 5:
mStat.Value = 4
mStat.Qualifier = "Monstrous"
}
return mStat
}
func (t MonsterTable) genDEX() MonsterStat {
typeRoll, _ := t.Roller.Roll("1d5")
mStat := MonsterStat{}
switch typeRoll[0] {
case 1:
mStat.Qualifier = "Slow"
mStat.Value = 0
case 2:
mStat.Qualifier = "Average"
mStat.Value = 1
case 3:
mStat.Qualifier = "Nimble"
mStat.Value = 2
case 4:
mStat.Qualifier = "Swift"
mStat.Value = 3
case 5:
mStat.Value = 4
mStat.Qualifier = "Blurred"
}
return mStat
}
func (t MonsterTable) genWIL() MonsterStat {
typeRoll, _ := t.Roller.Roll("1d5")
mStat := MonsterStat{}
switch typeRoll[0] {
case 1:
mStat.Qualifier = "Dimwitted"
mStat.Value = 0
case 2:
mStat.Qualifier = "Average"
mStat.Value = 1
case 3:
mStat.Qualifier = "Clever"
mStat.Value = 2
case 4:
mStat.Qualifier = "Brilliant"
mStat.Value = 3
case 5:
mStat.Value = 4
mStat.Qualifier = "Genius"
}
return mStat
}
func (t MonsterTable) Base(roll int) string {
var base string
switch roll {
case 1, 2:
base = t.AerialAnimals(t.Roller.TableRoll())
case 3, 4:
base = t.TerrestrialAnimals(t.Roller.TableRoll())
case 5, 6:
base = t.AquaticAnimals(t.Roller.TableRoll())
}
return base
}
func (t MonsterTable) AerialAnimals(roll [2]int) string {
return data.Tables.Monster.Aerial[roll[0]-1][roll[1]-1]
}
func (t MonsterTable) TerrestrialAnimals(roll [2]int) string {
return data.Tables.Monster.Terrestrial[roll[0]-1][roll[1]-1]
}
func (t MonsterTable) AquaticAnimals(roll [2]int) string {
return data.Tables.Monster.Aquatic[roll[0]-1][roll[1]-1]
}
func (t MonsterTable) Tactic(roll [2]int) string {
return data.Tables.Monster.Tactics[roll[0]-1][roll[1]-1]
}
func (t MonsterTable) Feature(roll [2]int) string {
return data.Tables.Monster.Features[roll[0]-1][roll[1]-1]
}
func (t MonsterTable) Personality(roll [2]int) string {
return data.Tables.Monster.Personality[roll[0]-1][roll[1]-1]
}
func (t MonsterTable) Ability(roll [2]int) string {
magicTable := MagicTable{Roller: t.Roller}
switch roll {
case [2]int{2, 4}:
return magicTable.EtherealElement(t.Roller.TableRoll())
case [2]int{4, 5}:
return magicTable.PhysicalElement(t.Roller.TableRoll())
default:
return data.Tables.Monster.Abilities[roll[0]-1][roll[1]-1]
}
}
func (t MonsterTable) Trait(roll [2]int) string {
magicTable := MagicTable{Roller: t.Roller}
switch roll {
case [2]int{2, 3}:
return magicTable.EtherealElement(t.Roller.TableRoll())
case [2]int{5, 1}:
return magicTable.PhysicalElement(t.Roller.TableRoll())
default:
return data.Tables.Monster.Traits[roll[0]-1][roll[1]-1]
}
}