feat: game content doc generation

This commit is contained in:
Daniel Schmidt 2024-01-18 20:25:23 +01:00
parent 39185079fd
commit dd0c00bec1
7 changed files with 595 additions and 109 deletions

116
cmd/internal/docs/api.go Normal file
View File

@ -0,0 +1,116 @@
package main
import (
"fmt"
"github.com/BigJk/end_of_eden/game"
"github.com/BigJk/end_of_eden/internal/lua/ludoc"
"github.com/samber/lo"
"regexp"
"sort"
"strings"
)
const globTemplate = `<details> <summary><b><code>%s</code></b> </summary> <br/>
%s
</details>
`
const fnTemplate = `<details> <summary><b><code>%s</code></b> </summary> <br/>
%s
**Signature:**
%s
</details>
`
var linkPattern = regexp.MustCompile("[^a-zA-Z\\d\\s:-]")
func functionToMd(fn ludoc.Function) string {
signature := fmt.Sprintf("%s(%s) -> %s", fn.Name, strings.Join(fn.Args, ", "), lo.Ternary(len(fn.Return) == 0, "None", fn.Return))
return fmt.Sprintf(fnTemplate, fn.Name, fn.Description, "```\n"+signature+"\n```")
}
func globToMd(glob ludoc.Global) string {
return fmt.Sprintf(globTemplate, glob.Name, glob.Description)
}
func buildAPIDocs() {
docs := game.NewSession().LuaDocs()
// Fetch the globals and functions keys
globals := lo.Keys(docs.Globals)
functions := lo.Keys(docs.Functions)
// Sort them
sort.Strings(globals)
sort.Strings(functions)
// Get the sorted categories
cats := lo.Keys(docs.Categories)
sort.SliceStable(cats, func(i, j int) bool {
return docs.Categories[cats[i]].Order < docs.Categories[cats[j]].Order
})
// Build index
builder := strings.Builder{}
builder.WriteString("# End Of Eden Lua Docs\n")
builder.WriteString("## Index\n\n")
for _, key := range cats {
cat := docs.Categories[key]
builder.WriteString(fmt.Sprintf("- [%s](#%s)\n", cat.Name, linkPattern.ReplaceAllString(strings.ToLower(strings.ReplaceAll(cat.Name, " ", "-")), "")))
}
builder.WriteString("\n")
// Build docs
for _, key := range cats {
cat := docs.Categories[key]
builder.WriteString("## " + cat.Name + "\n\n")
builder.WriteString(cat.Description + "\n\n")
builder.WriteString("### Globals\n")
hasGlobals := false
for _, key := range globals {
glob := docs.Globals[key]
if glob.Category != cat.Name {
continue
}
builder.WriteString(globToMd(glob))
hasGlobals = true
}
if !hasGlobals {
builder.WriteString("\nNone\n\n")
}
builder.WriteString("### Functions\n")
hasFunctions := false
for _, key := range functions {
fn := docs.Functions[key]
if fn.Category != cat.Name {
continue
}
builder.WriteString(functionToMd(fn))
hasFunctions = true
}
if !hasFunctions {
builder.WriteString("\nNone\n\n")
}
}
// Output docs
fmt.Print(builder.String())
}

View File

@ -0,0 +1,325 @@
package main
import (
"fmt"
"github.com/BigJk/end_of_eden/game"
"github.com/acarl005/stripansi"
"github.com/alexeyco/simpletable"
"github.com/samber/lo"
"regexp"
"sort"
"strings"
)
func stripSpecial(s string) string {
// 1. collapse consecutive newlines
newlineRegex := regexp.MustCompile(`\n+`)
s = newlineRegex.ReplaceAllString(s, " - ")
// 2. replace [ with **
return strings.ReplaceAll(strings.ReplaceAll(s, "[", "**"), "]", "**")
}
func makeCode(s string) string {
return "``" + s + "``"
}
func makeCodes(s []string) string {
return strings.Join(lo.Map(s, func(s string, i int) string {
return makeCode(s)
}), ", ")
}
func makeCodeBlock(s string) string {
return "<code style='white-space: pre;'>" + strings.ReplaceAll(strings.ReplaceAll(s, "\n", "</br>"), "\\", "\\\\") + " </code>"
}
func buildGameContentDocs() {
res := game.NewSession().GetResources()
fmt.Println("# Game Content")
fmt.Println(`This document contains all game content that is available in the game. It is automatically generated and may be out of date.
Content that is dynamically generated at runtime is not included in this document, only content that is registered at the beginning of a session.
`)
// Stats
fmt.Println("\n\n## Stats\n")
statsTable := simpletable.New()
statsTable.Header = &simpletable.Header{
Cells: []*simpletable.Cell{
{Align: simpletable.AlignCenter, Text: "Type"},
{Align: simpletable.AlignCenter, Text: "Count"},
},
}
statsTable.SetStyle(simpletable.StyleMarkdown)
countArtifacts := len(res.Artifacts)
countCards := len(res.Cards)
countStatusEffects := len(res.StatusEffects)
countEnemies := len(res.Enemies)
countEvents := len(res.Events)
statsTable.Body.Cells = append(statsTable.Body.Cells, []*simpletable.Cell{
{Text: "Artifacts"},
{Text: fmt.Sprint(countArtifacts)},
})
statsTable.Body.Cells = append(statsTable.Body.Cells, []*simpletable.Cell{
{Text: "Cards"},
{Text: fmt.Sprint(countCards)},
})
statsTable.Body.Cells = append(statsTable.Body.Cells, []*simpletable.Cell{
{Text: "Status Effects"},
{Text: fmt.Sprint(countStatusEffects)},
})
statsTable.Body.Cells = append(statsTable.Body.Cells, []*simpletable.Cell{
{Text: "Enemies"},
{Text: fmt.Sprint(countEnemies)},
})
statsTable.Body.Cells = append(statsTable.Body.Cells, []*simpletable.Cell{
{Text: "Events"},
{Text: fmt.Sprint(countEvents)},
})
statsTable.Println()
// Artifacts
artifactTable := simpletable.New()
artifactTable.Header = &simpletable.Header{
Cells: []*simpletable.Cell{
{Align: simpletable.AlignCenter, Text: "ID"},
{Align: simpletable.AlignCenter, Text: "Name"},
{Align: simpletable.AlignCenter, Text: "Description"},
{Align: simpletable.AlignCenter, Text: "Price"},
{Align: simpletable.AlignCenter, Text: "Tags"},
{Align: simpletable.AlignCenter, Text: "Test Present"},
},
}
artifactTable.SetStyle(simpletable.StyleMarkdown)
artifacts := lo.Values(res.Artifacts)
sort.SliceStable(artifacts, func(i, j int) bool {
return artifacts[i].Price < artifacts[j].Price
})
for _, v := range artifacts {
r := []*simpletable.Cell{
{Text: "``" + v.ID + "``"},
{Text: v.Name},
{Text: stripSpecial(stripansi.Strip(v.Description))},
{Text: fmt.Sprint(v.Price)},
{Text: strings.Join(v.Tags, ", ")},
{Text: lo.Ternary(v.Test != nil, ":heavy_check_mark:", ":no_entry_sign:")},
}
artifactTable.Body.Cells = append(artifactTable.Body.Cells, r)
}
fmt.Println("\n\n## Artifacts\n")
artifactTable.Println()
// Cards
cardTable := simpletable.New()
cardTable.Header = &simpletable.Header{
Cells: []*simpletable.Cell{
{Align: simpletable.AlignCenter, Text: "ID"},
{Align: simpletable.AlignCenter, Text: "Name"},
{Align: simpletable.AlignCenter, Text: "Description"},
{Align: simpletable.AlignCenter, Text: "Action Points"},
{Align: simpletable.AlignCenter, Text: "Exhaust"},
{Align: simpletable.AlignCenter, Text: "Consumable"},
{Align: simpletable.AlignCenter, Text: "Max Level"},
{Align: simpletable.AlignCenter, Text: "Price"},
{Align: simpletable.AlignCenter, Text: "Tags"},
{Align: simpletable.AlignCenter, Text: "Color"},
{Align: simpletable.AlignCenter, Text: "Used Callbacks"},
{Align: simpletable.AlignCenter, Text: "Test Present"},
},
}
cardTable.SetStyle(simpletable.StyleMarkdown)
actionPoints := make(map[int]int)
cardType := make(map[string]int)
cards := lo.Values(res.Cards)
sort.SliceStable(cards, func(i, j int) bool {
return cards[i].Price < cards[j].Price
})
for _, v := range cards {
actionPoints[v.PointCost]++
if v.DoesExhaust {
cardType["Exhaust"]++
} else if v.DoesConsume {
cardType["Consume"]++
} else {
cardType["Normal"]++
}
r := []*simpletable.Cell{
{Text: "``" + v.ID + "``"},
{Text: v.Name},
{Text: stripSpecial(stripansi.Strip(v.Description))},
{Text: fmt.Sprint(v.PointCost)},
{Text: lo.Ternary(v.DoesExhaust, ":heavy_check_mark:", ":no_entry_sign:")},
{Text: lo.Ternary(v.DoesConsume, ":heavy_check_mark:", ":no_entry_sign:")},
{Text: fmt.Sprint(v.MaxLevel)},
{Text: fmt.Sprint(v.Price)},
{Text: strings.Join(v.Tags, ", ")},
{Text: v.Color},
{Text: makeCodes(lo.Keys(v.Callbacks))},
{Text: lo.Ternary(v.Test != nil, ":heavy_check_mark:", ":no_entry_sign:")},
}
cardTable.Body.Cells = append(cardTable.Body.Cells, r)
}
fmt.Println("\n\n## Cards\n")
cardTable.Println()
fmt.Println("\n\n### Action Points\n")
fmt.Println(fmt.Sprintf("´´´mermaid\npie title Action Points\n%s\n´´´\n\n", strings.Join(lo.Map(lo.Entries(actionPoints), func(e lo.Entry[int, int], i int) string {
return fmt.Sprintf("%d AP: %d", e.Key, e.Value)
}), "\n")))
fmt.Println("\n\n### Card Types\n")
fmt.Println(fmt.Sprintf("´´´mermaid\npie title Card Types\n%s\n´´´\n\n", strings.Join(lo.Map(lo.Entries(cardType), func(e lo.Entry[string, int], i int) string {
return fmt.Sprintf("%s: %d", e.Key, e.Value)
}), "\n")))
// Status Effects
statusEffectTable := simpletable.New()
statusEffectTable.Header = &simpletable.Header{
Cells: []*simpletable.Cell{
{Align: simpletable.AlignCenter, Text: "ID"},
{Align: simpletable.AlignCenter, Text: "Name"},
{Align: simpletable.AlignCenter, Text: "Description"},
{Align: simpletable.AlignCenter, Text: "Look"},
{Align: simpletable.AlignCenter, Text: "Foreground"},
{Align: simpletable.AlignCenter, Text: "Can Stack"},
{Align: simpletable.AlignCenter, Text: "Decay"},
{Align: simpletable.AlignCenter, Text: "Rounds"},
{Align: simpletable.AlignCenter, Text: "Used Callbacks"},
{Align: simpletable.AlignCenter, Text: "Test Present"},
},
}
statusEffectTable.SetStyle(simpletable.StyleMarkdown)
statusEffects := lo.Values(res.StatusEffects)
sort.SliceStable(statusEffects, func(i, j int) bool {
return statusEffects[i].Order < statusEffects[j].Order
})
for _, v := range statusEffects {
r := []*simpletable.Cell{
{Text: "``" + v.ID + "``"},
{Text: v.Name},
{Text: stripSpecial(stripansi.Strip(v.Description))},
{Text: v.Look},
{Text: v.Foreground},
{Text: lo.Ternary(v.CanStack, ":heavy_check_mark:", ":no_entry_sign:")},
{Text: string(v.Decay)},
{Text: fmt.Sprint(v.Rounds)},
{Text: makeCodes(lo.Keys(v.Callbacks))},
{Text: lo.Ternary(v.Test != nil, ":heavy_check_mark:", ":no_entry_sign:")},
}
statusEffectTable.Body.Cells = append(statusEffectTable.Body.Cells, r)
}
fmt.Println("\n\n## Status Effects\n")
statusEffectTable.Println()
// Enemies
enemyTable := simpletable.New()
enemyTable.Header = &simpletable.Header{
Cells: []*simpletable.Cell{
{Align: simpletable.AlignCenter, Text: "ID"},
{Align: simpletable.AlignCenter, Text: "Name"},
{Align: simpletable.AlignCenter, Text: "Description"},
{Align: simpletable.AlignCenter, Text: "Initial HP"},
{Align: simpletable.AlignCenter, Text: "Max HP"},
{Align: simpletable.AlignCenter, Text: "Look"},
{Align: simpletable.AlignCenter, Text: "Color"},
{Align: simpletable.AlignCenter, Text: "Used Callbacks"},
{Align: simpletable.AlignCenter, Text: "Test Present"},
},
}
enemyTable.SetStyle(simpletable.StyleMarkdown)
enemies := lo.Values(res.Enemies)
sort.SliceStable(enemies, func(i, j int) bool {
return enemies[i].Name < enemies[j].Name
})
for _, v := range enemies {
r := []*simpletable.Cell{
{Text: "``" + v.ID + "``"},
{Text: v.Name},
{Text: stripSpecial(stripansi.Strip(v.Description))},
{Text: fmt.Sprint(v.InitialHP)},
{Text: fmt.Sprint(v.MaxHP)},
{Text: makeCodeBlock(v.Look)},
{Text: v.Color},
{Text: makeCodes(lo.Keys(v.Callbacks))},
{Text: lo.Ternary(v.Test != nil, ":heavy_check_mark:", ":no_entry_sign:")},
}
enemyTable.Body.Cells = append(enemyTable.Body.Cells, r)
}
fmt.Println("\n\n## Enemies\n")
enemyTable.Println()
// Events
eventTable := simpletable.New()
eventTable.Header = &simpletable.Header{
Cells: []*simpletable.Cell{
{Align: simpletable.AlignCenter, Text: "ID"},
{Align: simpletable.AlignCenter, Text: "Name"},
{Align: simpletable.AlignCenter, Text: "Description"},
{Align: simpletable.AlignCenter, Text: "Tags"},
{Align: simpletable.AlignCenter, Text: "Choices"},
{Align: simpletable.AlignCenter, Text: "Test Present"},
},
}
eventTable.SetStyle(simpletable.StyleMarkdown)
events := lo.Values(res.Events)
sort.SliceStable(events, func(i, j int) bool {
return events[i].Name < events[j].Name
})
for _, v := range events {
r := []*simpletable.Cell{
{Text: "``" + v.ID + "``"},
{Text: v.Name},
{Text: stripSpecial(stripansi.Strip(v.Description))},
{Text: strings.Join(v.Tags, ", ")},
{Text: makeCodes(lo.Map(v.Choices, func(c game.EventChoice, i int) string {
return stripansi.Strip(c.Description)
}))},
{Text: lo.Ternary(v.Test != nil, ":heavy_check_mark:", ":no_entry_sign:")},
}
eventTable.Body.Cells = append(eventTable.Body.Cells, r)
}
fmt.Println("\n\n## Events\n")
eventTable.Println()
}

View File

@ -1,116 +1,22 @@
package main
import (
"fmt"
"github.com/BigJk/end_of_eden/game"
"github.com/BigJk/end_of_eden/internal/lua/ludoc"
"github.com/samber/lo"
"regexp"
"sort"
"strings"
import "flag"
const (
TypeAPI = "api"
TypeGameContent = "game_content"
)
const globTemplate = `<details> <summary><b><code>%s</code></b> </summary> <br/>
%s
</details>
`
const fnTemplate = `<details> <summary><b><code>%s</code></b> </summary> <br/>
%s
**Signature:**
%s
</details>
`
var linkPattern = regexp.MustCompile("[^a-zA-Z\\d\\s:-]")
func functionToMd(fn ludoc.Function) string {
signature := fmt.Sprintf("%s(%s) -> %s", fn.Name, strings.Join(fn.Args, ", "), lo.Ternary(len(fn.Return) == 0, "None", fn.Return))
return fmt.Sprintf(fnTemplate, fn.Name, fn.Description, "```\n"+signature+"\n```")
}
func globToMd(glob ludoc.Global) string {
return fmt.Sprintf(globTemplate, glob.Name, glob.Description)
}
func main() {
docs := game.NewSession().LuaDocs()
t := flag.String("type", "api", "api,game_content")
flag.Parse()
// Fetch the globals and functions keys
globals := lo.Keys(docs.Globals)
functions := lo.Keys(docs.Functions)
// Sort them
sort.Strings(globals)
sort.Strings(functions)
// Get the sorted categories
cats := lo.Keys(docs.Categories)
sort.SliceStable(cats, func(i, j int) bool {
return docs.Categories[cats[i]].Order < docs.Categories[cats[j]].Order
})
// Build index
builder := strings.Builder{}
builder.WriteString("# End Of Eden Lua Docs\n")
builder.WriteString("## Index\n\n")
for _, key := range cats {
cat := docs.Categories[key]
builder.WriteString(fmt.Sprintf("- [%s](#%s)\n", cat.Name, linkPattern.ReplaceAllString(strings.ToLower(strings.ReplaceAll(cat.Name, " ", "-")), "")))
switch *t {
case TypeAPI:
buildAPIDocs()
case TypeGameContent:
buildGameContentDocs()
default:
panic("unknown type")
}
builder.WriteString("\n")
// Build docs
for _, key := range cats {
cat := docs.Categories[key]
builder.WriteString("## " + cat.Name + "\n\n")
builder.WriteString(cat.Description + "\n\n")
builder.WriteString("### Globals\n")
hasGlobals := false
for _, key := range globals {
glob := docs.Globals[key]
if glob.Category != cat.Name {
continue
}
builder.WriteString(globToMd(glob))
hasGlobals = true
}
if !hasGlobals {
builder.WriteString("\nNone\n\n")
}
builder.WriteString("### Functions\n")
hasFunctions := false
for _, key := range functions {
fn := docs.Functions[key]
if fn.Category != cat.Name {
continue
}
builder.WriteString(functionToMd(fn))
hasFunctions = true
}
if !hasFunctions {
builder.WriteString("\nNone\n\n")
}
}
// Output docs
fmt.Print(builder.String())
}

127
docs/GAME_CONTENT_DOCS.md Normal file
View File

@ -0,0 +1,127 @@
# Game Content
This document contains all game content that is available in the game. It is automatically generated and may be out of date.
Content that is dynamically generated at runtime is not included in this document, only content that is registered at the beginning of a session.
## Stats
| Type | Count |
|----------------|-------|
| Artifacts | 10 |
| Cards | 18 |
| Status Effects | 8 |
| Enemies | 4 |
| Events | 16 |
## Artifacts
| ID | Name | Description | Price | Tags | Test Present |
|---------------------|-----------------|-----------------------------------------------------------------------------------------------------|-------|----------------|--------------------|
| ``CROWBAR`` | Crowbar | A crowbar. It's a bit rusty, but it should still be useful! Can be used in your hand. | 80 | ATK, M, T, HND | :no_entry_sign: |
| ``COMBAT_GLASSES`` | Combat Glasses | Whenever you play a **Ranged (R)** card, deal **1 additional damage** | 100 | _ACT_0 | :heavy_check_mark: |
| ``PORTABLE_BUFFER`` | PRTBL Buffer | Start each turn with 1 **Block** | 100 | _ACT_0 | :no_entry_sign: |
| ``SPEED_ENHANCER`` | Speed Enhancer | Start with a additional card at the beginning of combat. | 100 | _ACT_0 | :no_entry_sign: |
| ``COMBAT_GLOVES`` | Combat Gloves | Whenever you play a **Meele (M)** card, deal **1 additional damage** | 100 | _ACT_0 | :heavy_check_mark: |
| ``VIBRO_KNIFE`` | VIBRO Knife | A VIBRO knife. Uses ultrasonic vibrations to cut through almost anything. Can be used in your hand. | 180 | ATK, M, T, HND | :no_entry_sign: |
| ``INTERVA_JUICER`` | Interval Juicer | **Heal 2** at the beginning of combat | 200 | _ACT_0 | :no_entry_sign: |
| ``ARM_MOUNTED_GUN`` | Arm Mounted Gun | Weapon that is mounted on your arm. It is very powerful. | 250 | ARM | :no_entry_sign: |
| ``LZR_PISTOL`` | LZR Pistol | A LZR pistol. Fires a concentrated beam of light. Can be used in your hand. | 280 | ATK, R, T, HND | :no_entry_sign: |
| ``HAR_II`` | HAR-II | A HAR-II. A heavy assault rifle with a high rate of fire. Can be used in your hand. | 380 | ATK, R, T, HND | :no_entry_sign: |
## Cards
| ID | Name | Description | Action Points | Exhaust | Consumable | Max Level | Price | Tags | Color | Used Callbacks | Test Present |
|------------------------|--------------------|--------------------------------------------------------------------------------------------------------|---------------|--------------------|--------------------|-----------|-------|----------------|---------|----------------|--------------------|
| ``ARM_MOUNTED_GUN`` | Arm Mounted Gun | Exhaust. Use your arm mounted gun to deal 15 (+3 for each upgrade) damage. | 3 | :heavy_check_mark: | :no_entry_sign: | 1 | -1 | ATK, R, T, ARM | #2f3e46 | ``OnCast`` | :heavy_check_mark: |
| ``KNOCK_OUT`` | Knock Out | Inflicts **Knock Out** on the target, causing them to miss their next turn. | 2 | :no_entry_sign: | :no_entry_sign: | 0 | -1 | CC | #725e9c | ``OnCast`` | :no_entry_sign: |
| ``MELEE_HIT`` | Melee Hit | Use your bare hands to deal 1 (+1 for each upgrade) damage. | 1 | :no_entry_sign: | :no_entry_sign: | 1 | -1 | ATK, M, HND | #2f3e46 | ``OnCast`` | :heavy_check_mark: |
| ``KILL`` | Kill | Debug Card | 0 | :no_entry_sign: | :no_entry_sign: | 0 | -1 | | #2f3e46 | ``OnCast`` | :no_entry_sign: |
| ``CROWBAR`` | Crowbar | Use to deal 2 (+3 for each upgrade) damage. | 1 | :no_entry_sign: | :no_entry_sign: | 3 | 0 | ATK, M, T, HND | #2f3e46 | ``OnCast`` | :heavy_check_mark: |
| ``VIBRO_KNIFE`` | VIBRO Knife | Use to deal 3 (+3 for each upgrade) damage. | 1 | :no_entry_sign: | :no_entry_sign: | 3 | 0 | ATK, M, T, HND | #2f3e46 | ``OnCast`` | :heavy_check_mark: |
| ``LZR_PISTOL`` | LZR Pistol | Use to deal 4 (+3 for each upgrade) damage. | 1 | :no_entry_sign: | :no_entry_sign: | 3 | 0 | ATK, R, T, HND | #2f3e46 | ``OnCast`` | :heavy_check_mark: |
| ``HAR_II`` | HAR-II | Use to deal 5 (+3 for each upgrade) damage. | 1 | :no_entry_sign: | :no_entry_sign: | 3 | 0 | ATK, R, T, HND | #2f3e46 | ``OnCast`` | :heavy_check_mark: |
| ``BLOCK`` | Block | Shield yourself and gain 5 **block**. | 1 | :no_entry_sign: | :no_entry_sign: | 1 | 50 | DEF | #219ebc | ``OnCast`` | :no_entry_sign: |
| ``ENERGY_DRINK`` | ENRGY Drink X91 | **One-Time** - Gain 1 action point. | 0 | :no_entry_sign: | :heavy_check_mark: | 0 | 150 | UTIL, _ACT_0 | #fb5607 | ``OnCast`` | :heavy_check_mark: |
| ``FLASH_SHIELD`` | Flash Shield | **One-Time** - Deploy a temporary shield. **Negates** the next attack. | 0 | :no_entry_sign: | :heavy_check_mark: | 0 | 150 | DEF, _ACT_0 | #219ebc | ``OnCast`` | :no_entry_sign: |
| ``NANO_CHARGER`` | Nano Charger | **One-Time** - Supercharge your next attack. Deals **Double** damage. | 0 | :no_entry_sign: | :heavy_check_mark: | 0 | 150 | BUFF, _ACT_0 | #c1121f | ``OnCast`` | :heavy_check_mark: |
| ``STIM_PACK`` | Stim Pack | **One-Time** - Restores **5** HP. | 0 | :no_entry_sign: | :heavy_check_mark: | 0 | 150 | HEAL, _ACT_0 | #219ebc | ``OnCast`` | :heavy_check_mark: |
| ``BOUNCE_SHIELD`` | Bounce Shield | **One-Time** - Deploy a temporary shield. **Negates** bounces the damage back, but still takes damage. | 0 | :no_entry_sign: | :heavy_check_mark: | 0 | 150 | DEF, _ACT_0 | #219ebc | ``OnCast`` | :no_entry_sign: |
| ``FLASH_BANG`` | Flash Bang | **One-Time** - Inflicts **Blinded** on the target, causing them to deal less damage. | 0 | :no_entry_sign: | :heavy_check_mark: | 0 | 150 | CC, _ACT_0 | #725e9c | ``OnCast`` | :no_entry_sign: |
| ``ENERGY_DRINK_2`` | ENRGY Drink X92 | **One-Time** - Gain 2 action points. | 0 | :no_entry_sign: | :heavy_check_mark: | 0 | 250 | UTIL, _ACT_0 | #fb5607 | ``OnCast`` | :heavy_check_mark: |
| ``ULTRA_FLASH_SHIELD`` | Ultra Flash Shield | **One-Time** - Deploy a temporary shield. **Negates** all attack this turn. | 3 | :no_entry_sign: | :heavy_check_mark: | 0 | 250 | DEF, _ACT_0 | #219ebc | ``OnCast`` | :no_entry_sign: |
| ``ENERGY_DRINK_3`` | ENRGY Drink X93 | **One-Time** - Gain 3 action points. | 0 | :no_entry_sign: | :heavy_check_mark: | 0 | 350 | UTIL, _ACT_0 | #fb5607 | ``OnCast`` | :heavy_check_mark: |
### Action Points
´´´mermaid
pie title Action Points
0 AP: 9
3 AP: 2
2 AP: 1
1 AP: 6
´´´
### Card Types
´´´mermaid
pie title Card Types
Exhaust: 1
Normal: 8
Consume: 9
´´´
## Status Effects
| ID | Name | Description | Look | Foreground | Can Stack | Decay | Rounds | Used Callbacks | Test Present |
|------------------------|--------------------|---------------------------------------------------|------|------------|--------------------|-----------|--------|------------------|--------------------|
| ``KNOCK_OUT`` | Knock Out | Can't act | KO | #725e9c | :heavy_check_mark: | DecayOne | 1 | ``OnTurn`` | :no_entry_sign: |
| ``CHARGED`` | Charged | Attacks will deal more damage per stack. | CHRG | #207BE7 | :heavy_check_mark: | DecayNone | 0 | ``OnDamageCalc`` | :no_entry_sign: |
| ``FLASH_BANG`` | Blinded | Causing **25%** less damage. | FL | #725e9c | :heavy_check_mark: | DecayOne | 1 | ``OnDamageCalc`` | :heavy_check_mark: |
| ``BLOCK`` | Block | Decreases incoming damage for each stack | B | #219ebc | :heavy_check_mark: | DecayAll | 1 | ``OnDamageCalc`` | :heavy_check_mark: |
| ``BOUNCE_SHIELD`` | Bounce Shield | Bounces back the next damage. Still takes damage. | BS | #219ebc | :no_entry_sign: | DecayAll | 1 | ``OnDamageCalc`` | :heavy_check_mark: |
| ``FLASH_SHIELD`` | Flash Shield | Negates the next attack. | FS | #219ebc | :no_entry_sign: | DecayAll | 1 | ``OnDamageCalc`` | :heavy_check_mark: |
| ``NANO_CHARGER`` | Nano Charge | Next attack deals **Double** damage. | NC | #c1121f | :no_entry_sign: | DecayAll | 1 | ``OnDamageCalc`` | :heavy_check_mark: |
| ``ULTRA_FLASH_SHIELD`` | Ultra Flash Shield | Negates all attacks. | UFS | #219ebc | :no_entry_sign: | DecayAll | 1 | ``OnDamageCalc`` | :heavy_check_mark: |
## Enemies
| ID | Name | Description | Initial HP | Max HP | Look | Color | Used Callbacks | Test Present |
|------------------|--------------|--------------------------------------|------------|--------|------------------------------------------------------------------|---------|------------------------------|-----------------|
| ``CYBER_SPIDER`` | CYBER Spider | It waits for its prey to come closer | 8 | 8 | <code style='white-space: pre;'>/\\o^o/\\ </code> | #ff4d6d | ``OnTurn`` | :no_entry_sign: |
| ``CLEAN_BOT`` | Cleaning Bot | It never stopped cleaning... | 13 | 13 | <code style='white-space: pre;'> \\_/</br>(* *)</br> )#( </code> | #32a891 | ``OnTurn``, ``OnPlayerTurn`` | :no_entry_sign: |
| ``DUMMY`` | Dummy | End me... | 100 | 100 | <code style='white-space: pre;'>DUM </code> | #deeb6a | ``OnTurn`` | :no_entry_sign: |
| ``RUST_MITE`` | Rust Mite | A small robot that eats metal. | 12 | 12 | <code style='white-space: pre;'>/v\\ </code> | #e6e65a | ``OnTurn`` | :no_entry_sign: |
## Events
| ID | Name | Description | Tags | Choices | Test Present |
|------------------------------|------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------|--------------------------------------------------------------------------------------------------------|-----------------|
| ``GAIN_GOLD_ACT_0`` | | ... - | _ACT_0 | ``Take it! [Gain 20 Gold]``, ``Leave!`` | :no_entry_sign: |
| ``MERCHANT`` | A strange figure | !!merchant.jpg - - The merchant is a tall, lanky figure draped in a long, tattered coat made of plant fibers and animal hides. Their face is hidden behind a mask made of twisted roots and vines, giving them an unsettling, almost alien appearance. - Despite their strange appearance, the merchant is a shrewd negotiator and a skilled trader. They carry with them a collection of bizarre and exotic items, including plant-based weapons, animal pelts, and strange, glowing artifacts that seem to pulse with an otherworldly energy. - The merchant is always looking for a good deal, and they're not above haggling with potential customers... | _ACT_0, _ACT_1, _ACT_2, _ACT_3 | ``Trade``, ``Pass`` | :no_entry_sign: |
| ``CLEAN_BOT`` | Corpse. Clean. Engage. | !!clean_bot.jpg - While exploring the facility you hear a strange noise. Suddenly a strange robot appears from one of the corridors. - It seems to be cleaning up the area, but it's not working properly anymore and you can see small sparks coming out of it. - It looks at you and says "Corpse. Clean. Engage.". - **You're not sure what it means, but it doesn't seem to be friendly!** - | _ACT_0_FIGHT | ``Fight!`` | :no_entry_sign: |
| ``GAMBLE_1_ACT_0`` | Electro Barrier | You find a room with a strange device in the middle. It seems to be some kind of electro barrier protecting a storage container. You can either try to disable the barrier or leave. - | _ACT_0 | ``50% [Gain Artifact & Consumeable] 50% [Take 5 damage]``, ``Leave!`` | :no_entry_sign: |
| ``CROWBAR`` | Found: Crowbar | !!red_room.jpg - **You found something!** A crowbar. It's a bit rusty, but it should still be useful! - **Important:** If you already carry a artifact in your hand, you will have to drop it and related cards to pick up the new one. | _ACT_0 | ````, ``Leave...`` | :no_entry_sign: |
| ``HAR_II`` | Found: HAR-II | !!artifact_chest.jpg - **You found something!** A HAR-II. A heavy assault rifle with a high rate of fire. - **Important:** If you already carry a artifact in your hand, you will have to drop it and related cards to pick up the new one. | _ACT_1 | ````, ``Leave...`` | :no_entry_sign: |
| ``LZR_PISTOL`` | Found: LZR Pistol | !!artifact_chest.jpg - **You found something!** A LZR pistol. Fires a concentrated beam of light. - **Important:** If you already carry a artifact in your hand, you will have to drop it and related cards to pick up the new one. | _ACT_1 | ````, ``Leave...`` | :no_entry_sign: |
| ``VIBRO_KNIFE`` | Found: VIBRO Knife | !!artifact_chest.jpg - **You found something!** A VIBRO knife. Uses ultrasonic vibrations to cut through almost anything. - **Important:** If you already carry a artifact in your hand, you will have to drop it and related cards to pick up the new one. | _ACT_0 | ````, ``Leave...`` | :no_entry_sign: |
| ``GOLD_TO_HP_ACT_0`` | Old Vending Machine | You find an old vending machine, it seems to be still working. You can either pay 20 Gold to get 5 HP or leave. - | _ACT_0 | ``Pay [20 Gold] [Gain 5 HP]``, ``Leave!`` | :no_entry_sign: |
| ``RANDOM_ARTIFACT_ACT_0`` | Random Artifact | !!artifact_chest.jpg - You found a chest with a strange symbol on it. The chest is protected by a strange barrier. You can either open it and take some damage or leave. - | _ACT_0 | ``Random Artifact [Gain 1 Artifact] [Take 5 damage]``, ``Leave!`` | :no_entry_sign: |
| ``RANDOM_CONSUMEABLE_ACT_0`` | Random Consumeable | !!artifact_chest.jpg - You found a chest with a strange symbol on it. The chest is protected by a strange barrier. You can either open it and take some damage or leave. - | _ACT_0 | ``Random Artifact [Gain 1 Consumeable] [Take 2 damage]``, ``Leave!`` | :no_entry_sign: |
| ``MAX_LIFE_ACT_0`` | Symbiotic Parasite | You find a strange creature, it seems to be a symbiotic parasite. It offers to increase your max HP by 5. You can either accept or leave. - | _ACT_0 | ``Accept it! [Gain 5 Max HP]``, ``Leave!`` | :no_entry_sign: |
| ``RUST_MITE`` | Tasty metals... | !!rust_mite.jpg - You are walking through the facility hoping to find a way out. After a few turns you hear a strange noise. You look around and come across a strange being. - It seems to be eating the metal from the walls. It looks at you and after a few seconds it rushes towards you. - **It seems to be hostile!** - | _ACT_0_FIGHT | ``Fight!`` | :no_entry_sign: |
| ``UPRAGDE_CARD_ACT_0`` | Upgrade Station | You find a old automatic workstation. You are able to get it working again. You can either upgrade a random card or leave. - | _ACT_0 | ``Upgrade a card [Upgrade a card] [Take 5 damage]``, ``Leave!`` | :no_entry_sign: |
| ``START`` | Waking up... | !!cryo_start.jpg - You wake up in a dimly lit room, the faint glow of a red emergency light casting an eerie hue over the surroundings. The air is musty and stale, the metallic scent of the cryo-chamber still lingering in your nostrils. You feel groggy and disoriented, your mind struggling to process what's happening. - As you try to sit up, you notice that your body is stiff and unresponsive. It takes a few moments for your muscles to warm up and regain their strength. Looking around, you see that the walls are made of a dull gray metal, covered in scratches and scuff marks. There's a faint humming sound coming from somewhere, indicating that the facility is still operational. - You try to remember how you ended up here, but your memories are hazy and fragmented. The last thing you recall is a blinding flash of light and a deafening boom. You must have been caught in one of the nuclear explosions that devastated the world. - As you struggle to gather your bearings, you notice a blinking panel on the wall, with the words *"Cryo Sleep Malfunction"* displayed in bold letters. It seems that the system has finally detected the error that caused your prolonged slumber and triggered your awakening. - **Shortly after you realize that you are not alone...** | | ``Try to find a weapon. [Find meele weapon] [Take 4 damage]``, ``Gather your strength and attack it!`` | :no_entry_sign: |
| ``CYBER_SPIDER`` | What is this thing at the ceiling? | !!cyber_spider.jpg - You come around a corner and see a strange creature hanging from the ceiling. It looks like a spider, but it's made out of metal. - It seems to be waiting for its prey to come closer and there is no way around it. - | _ACT_0_FIGHT | ``Fight!`` | :no_entry_sign: |

4
go.mod
View File

@ -31,7 +31,7 @@ require (
github.com/lrstanley/bubblezone v0.0.0-20230303230241-08f906ff62a9
github.com/lucasb-eyer/go-colorful v1.2.0
github.com/maruel/panicparse/v2 v2.3.1
github.com/mattn/go-runewidth v0.0.14
github.com/mattn/go-runewidth v0.0.15
github.com/mitchellh/mapstructure v1.5.0
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6
github.com/muesli/reflow v0.3.0
@ -52,8 +52,10 @@ require (
cdr.dev/slog v1.4.2-0.20221206192828-e4803b10ae17 // indirect
cloud.google.com/go/logging v1.7.0 // indirect
github.com/PuerkitoBio/goquery v1.8.1 // indirect
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/alecthomas/chroma v0.10.0 // indirect
github.com/alecthomas/chroma/v2 v2.5.0 // indirect
github.com/alexeyco/simpletable v1.0.0 // indirect
github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
github.com/anthonynsimon/bild v0.13.0 // indirect

6
go.sum
View File

@ -64,6 +64,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw=
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM=
github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink=
@ -74,6 +76,8 @@ github.com/alecthomas/chroma/v2 v2.5.0 h1:CQCdj1BiBV17sD4Bd32b/Bzuiq/EqoNTrnIhyQ
github.com/alecthomas/chroma/v2 v2.5.0/go.mod h1:yrkMI9807G1ROx13fhe1v6PN2DDeaR73L3d+1nmYQtw=
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/alexeyco/simpletable v1.0.0 h1:ZQ+LvJ4bmoeHb+dclF64d0LX+7QAi7awsfCrptZrpHk=
github.com/alexeyco/simpletable v1.0.0/go.mod h1:VJWVTtGUnW7EKbMRH8cE13SigKGx/1fO2SeeOiGeBkk=
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
@ -324,6 +328,8 @@ github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRC
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mazznoer/csscolorparser v0.1.3 h1:vug4zh6loQxAUxfU1DZEu70gTPufDPspamZlHAkKcxE=
github.com/mazznoer/csscolorparser v0.1.3/go.mod h1:Aj22+L/rYN/Y6bj3bYqO3N6g1dtdHtGfQ32xZ5PJQic=
github.com/mewkiz/flac v1.0.7/go.mod h1:yU74UH277dBUpqxPouHSQIar3G1X/QIclVbFahSd1pU=

View File

@ -4,6 +4,10 @@ echo "Updating docs..."
go run ./cmd/internal/docs > ./docs/LUA_API_DOCS.md
echo "Done!"
echo "Updating game docs..."
go run ./cmd/internal/docs -type game_content > ./docs/GAME_CONTENT_DOCS.md
echo "Done!"
echo "Updating definitions..."
go run ./cmd/internal/definitions > ./assets/scripts/definitions/api.lua
echo "Done!"