Compare commits

...
3 Commits
Author SHA1 Message Date
tangent 8834269fee testing with voices! 2026-09-22 20:36:03 -06:00
tangent 1fac678a79 progress towards character creation 2026-09-22 19:59:54 -06:00
tangent 97b9205954 starting to add data 2026-09-22 19:07:39 -06:00
9 changed files with 431 additions and 25 deletions

No files matched your search

+4 -4
View File
@@ -1,13 +1,16 @@
# nasa-tawa # nasa-tawa
Strange motion. Idle toy inspired by Progress Quest. Strange motion. Idle toy inspired by Progress Quest.
WARNING: Opens a console to LAN which can run *any* code as the user Love2D is
running as! There is no security on this.
## Brainstroming ## Brainstroming
Name the Race. Motto. Name the Race. Motto.
Level Class (xp bar) Level Class (xp bar)
Plot: Description (progress bar) Plot: Description (progress bar)
Quest (progress bar) (quest log?) Quest (progress bar) (quest log?)
Stats: strength, constitution, dexterity, intelligence, wisdom, charisma, health/max, magic/max Stats
Equipment list and stats. Equipment list and stats.
Spell list and levels. Spell list and levels.
@@ -42,8 +45,6 @@ Equipment is generated based on level, but random, so lots of downgrading.
- SpecialItem: InterestingItem of ItemOfs - SpecialItem: InterestingItem of ItemOfs
- InterestingItem: ItemAttrib Specials - InterestingItem: ItemAttrib Specials
Only 100 quests are kept in the log.
special characters: special characters:
- Demi, who does 1 backflip - Demi, who does 1 backflip
- Anti Juandez, who is made-up - Anti Juandez, who is made-up
@@ -70,7 +71,6 @@ Young, no modifiers, messianic, Big, Special.
Quest completion triggers a reward: spell, equipment, stat, item Quest completion triggers a reward: spell, equipment, stat, item
## Tasks ## Tasks
- [x] Push the modifications to timer to the GitHub library!
- [ ] I have to make a stat called consider - [ ] I have to make a stat called consider
- [ ] Progress bars should be set within a manager (like timers) so one global - [ ] Progress bars should be set within a manager (like timers) so one global
draw function draws them all. draw function draws them all.
+4
View File
@@ -0,0 +1,4 @@
{
"current_page":0,
"total_pages":500
}
+86
View File
@@ -0,0 +1,86 @@
{
"Bastard Lunatic":{
"stats":["constitution"],
"tasks":[
[6, "Reading the DSM"]
]
},
"Battle-Felon":{
"stats":["strength"]
},
"Birdrider":{
"stats":["wisdom"],
"tasks":[
[10, "Birdwatching"]
]
},
"Fighter/Organist":{
"stats":["charisma","strength"]
},
"Hunter Strangler":{
"stats":["dexterity","intelligence"],
"tasks":[
[10, "Hunting"]
]
},
"Inner Mason":{
"stats":["constitution"],
"tasks":[
[16, "Meditating"]
]
},
"Lowling":{
"stats":["wisdom"],
"tasks":[
"Hiding"
]
},
"Mage Illusioner":{
"stats":["intelligence","magic"]
},
"Mu-Fu Monk":{
"stats":["dexterity"]
},
"Puma Burgular":{
"stats":["dexterity"],
"tasks":[
[7, "Stalking"]
]
},
"Robot Monk":{
"stats":["strength"],
"tasks":[
[12, "Recharging"]
]
},
"Runeloremaster":{
"stats":["wisdom"],
"tasks":[
"Enthusiastically explaining the applications of runes on trains"
]
},
"Shiv-Knight":{
"stats":["dexterity"],
"tasks":[
"Restocking on shivs"
]
},
"Slow Poisoner":{
"stats":["constitution"]
},
"Tickle-Mimic":{
"stats":["intelligence","wisdom"]
},
"Ur-Paladin":{
"stats":["constitution","wisdom"]
},
"Vermineer":{
"stats":["intelligence"],
"tasks":[
"Reading capitalist propaganda"
]
},
"Voodoo Princess":{
"stats":["charisma","intelligence"]
}
}
+34
View File
@@ -0,0 +1,34 @@
[
"Albert",
"Bad News",
"Bahh",
"Boing",
"Cellos",
"Daniel",
"Wobble",
"Eddy",
"Ellen",
"Flo",
"Fred",
"Good News",
"Grandma",
"Junior",
"Karen",
"Kathy",
"Moira",
"Organ",
"Superstar",
"Ralph",
"Reed",
"Rishi",
"Rocko",
"Samantha",
"Sandy",
"Shelley",
"Tara",
"Tessa",
"Trinoids",
"Whisper",
"Yelda",
"Zarvox"
]
+101
View File
@@ -0,0 +1,101 @@
{
"Battle-Finch":{
"stats":["dexterity","intelligence"],
"tasks":[
"Running from Birdrider"
]
},
"Crested Dwarf":{
"stats":["charisma"]
},
"Demicanadian":{
"stats":["constitution"],
"tasks":[
[2, "Drinking maple syrup"]
]
},
"Double Hobbit":{
"stats":["strength"]
},
"Double Wookiee":{
"stats":["strength"]
},
"Dung Elf":{
"stats":["wisdom"]
},
"Eel Man":{
"stats":["dexterity"]
},
"Enchanted Motorcycle":{
"stats":["magic"],
"tasks":[
[8, "Changing oil"]
]
},
"Gyrognome":{
"stats":["dexterity"],
"tasks":[
"Spinning"
]
},
"Half Halfling":{
"stats":["dexterity"],
"tasks":[
"Protesting how someone renamed their race and then copyrighted it"
]
},
"Half Man":{
"stats":["charisma"],
"tasks":[
"Searching for their other half"
]
},
"Half Orc":{
"stats":["health"]
},
"Hob-Nobbit":{
"stats":["charisma","dexterity"],
"tasks":[
"Protesting how asburd it is for a dead human to own the concept of a race"
]
},
"Land Squid":{
"stats":["health","strength"],
"tasks":[
"Drinking plenty of water"
]
},
"Lesser Dwarf":{
"stats":["constitution"]
},
"Low Elf":{
"stats":["constitution"]
},
"Panda Man":{
"stats":["constitution","strength"]
},
"Skraeling":{
"stats":["wisdom"],
"tasks":[
[10, "Fighting for native peoples' rights"]
]
},
"Talking Pony":{
"stats":["intelligence","magic"],
"tasks":[
[4, "Singing their theme song"]
]
},
"Trans-Kobold":{
"stats":["wisdom"],
"tasks":[
[10, "#TransRights"]
]
},
"Will o' the Wisp":{
"stats":["wisdom"],
"tasks":[
"Looking for lamp oil"
]
}
}
+37
View File
@@ -0,0 +1,37 @@
local constants = require "data.constants"
local utility = require "lib.utility"
local classes = utility.load_data("classes.json")
-- TODO abstract out since this is shared between classes and races
local class_names = {}
for name, data in pairs(classes) do
class_names[#class_names + 1] = name
if type(data.tasks) == "string" then
data.tasks = { data.tasks }
elseif not data.tasks then
data.tasks = {}
end
local tasks = data.tasks
for index, task in ipairs(tasks) do
if type(task) == "string" then
local time = #task * constants.reading_time_multiplier
-- TODO decide on a random amount of extra time to add
tasks[index] = {time, time, task}
elseif #task == 1 then
local time = #task[1] * constants.reading_time_multiplier
-- TODO decide on a random amount of extra time to add
tasks[index] = {time, time, task[1]}
elseif #task == 2 then
local time = tasks[1]
-- TODO decide on a random amount of extra time to add
tasks[index] = {time, time, task[2]}
end
end
end
table.sort(class_names)
return classes, class_names
+4
View File
@@ -0,0 +1,4 @@
return {
progress_bar_height = 30,
reading_time_multiplier = 1 / 12,
}
+37
View File
@@ -0,0 +1,37 @@
local constants = require "data.constants"
local utility = require "lib.utility"
local races = utility.load_data("races.json")
-- TODO abstract out since this is shared between classes and races
local race_names = {}
for name, data in pairs(races) do
race_names[#race_names + 1] = name
if type(data.tasks) == "string" then
data.tasks = { data.tasks }
elseif not data.tasks then
data.tasks = {}
end
local tasks = data.tasks
for index, task in ipairs(tasks) do
if type(task) == "string" then
local time = #task * constants.reading_time_multiplier
-- TODO decide on a random amount of extra time to add
tasks[index] = {time, time, task}
elseif #task == 1 then
local time = #task[1] * constants.reading_time_multiplier
-- TODO decide on a random amount of extra time to add
tasks[index] = {time, time, task[1]}
elseif #task == 2 then
local time = tasks[1]
-- TODO decide on a random amount of extra time to add
tasks[index] = {time, time, task[2]}
end
end
end
table.sort(race_names)
return races, race_names
+124 -21
View File
@@ -1,3 +1,6 @@
local window_width, window_height = love.graphics.getDimensions()
-- local filament = require "lib.filament"
local log = require "lib.log" local log = require "lib.log"
local lovebird = require "lib.lovebird" local lovebird = require "lib.lovebird"
local progress_bar = require "lib.progress_bar" local progress_bar = require "lib.progress_bar"
@@ -7,23 +10,113 @@ local utility = require "lib.utility"
lovebird.whitelist[#lovebird.whitelist + 1] = "192.168.*.*" -- LAN access lovebird.whitelist[#lovebird.whitelist + 1] = "192.168.*.*" -- LAN access
log{ log{
testing = true, debug = true,
} }
-- local json_load_test = utility.load_data("test.json") local constants = require "data.constants"
-- utility.print_table(json_load_test) local classes, class_names = require "data.classes"
local races, race_names = require "data.races"
local voices = utility.load_data("macos_say-en.json")
local voice_int = 0
local send_test_message = function()
-- local selected_voice = voices[math.random(1, #voices)]
voice_int = voice_int + 1
if voice_int > #voices then voice_int = 1 end
local selected_voice = voices[voice_int]
local test_channel = love.thread.getChannel("say")
local line = "Hello, my name is " .. selected_voice .. "."
test_channel:push({
voice = selected_voice:enquote(),
line = line:enquote(),
})
log("debug", selected_voice, line)
end
send_test_message()
-- filament.run(function()
-- local line = "Hello, my name is " .. selected_voice .. "."
-- os.execute("say -v " .. selected_voice:enquote() .. " " .. line:enquote())
-- end)
-- local test_thread = love.thread.newThread([[
-- -- local utility = require "lib.utility"
-- -- local voices = utility.load_data("macos_say-en.json")
-- -- local selected_voice = voices[math.random(1, #voices)]
-- local selected_voice = "Bells"
-- local line = "Hello, my name is " .. selected_voice .. "."
-- os.execute("say -v \"" .. selected_voice .. "\" \"" .. line .. "\"")
-- ]])
local test_thread = love.thread.newThread([[
local channel = love.thread.getChannel("say")
while true do
local message = channel:demand()
if message then
os.execute("say -v " .. message.voice .. " " .. message.line)
end
end
]])
test_thread:start()
local new_character = function(name)
local base_stat_roll = function()
return 3 + math.random(1, 6) + math.random(1, 6) + math.random(1, 6)
end
local random_name = function(length)
local vowels = "aaeeeiioouuy"
local consonants = "bcdfghjklmnpqrstvwxyz"
local text = ""
for i = 1, length do
local c
if i % 2 == 0 then
c = math.random(1, #vowels)
text = text .. vowels:sub(c, c)
else
c = math.random(1, #consonants)
text = text .. consonants:sub(c, c)
end
end
return text
end
name = name or random_name(math.random(3, 9)) -- name not affected by seed
local seed = os.time()
math.randomseed(seed)
local character = {
seed = seed,
name = name,
race = race_names[math.random(1, #race_names)],
class = class_names[math.random(1, #class_names)],
charisma = base_stat_roll(),
constitution = base_stat_roll(),
dexterity = base_stat_roll(),
intelligence = base_stat_roll(),
strength = base_stat_roll(),
wisdom = base_stat_roll(),
level = 1,
experience = 0,
}
character.health = math.random(1, 8) + math.floor(character.constitution / 6)
character.magic = math.random(1, 8) + math.floor(character.intelligence / 6)
math.randomseed(os.time())
return character
end
-- for i = 1, 100 do
-- print(new_character())
-- end
-- os.exit(1)
-- test progress_bar -- test progress_bar
local window_width, window_height = love.graphics.getDimensions() local test_bar = progress_bar(0, window_height - constants.progress_bar_height * 2, window_width, constants.progress_bar_height)
local progress_bar_height = 30 -- TODO should not be hardcoded
local test_bar = progress_bar(0, window_height - progress_bar_height * 2, window_width, progress_bar_height)
local test_message = "This is a test text string of significant length. It exists to test printing over a progress bar." local test_message = "This is a test text string of significant length. It exists to test printing over a progress bar."
log("testing", #test_message)
test_bar:set_text(test_message) test_bar:set_text(test_message)
-- test:set_progress(math.random())
local test_timer = timer.every(#test_message / 12, function() log("testing", "The timer completed.") end) -- TODO consider making timer not need a function; cause I don't here! local test_timer = timer.every(#test_message * constants.reading_time_multiplier, function() log("debug", "The timer completed.") end) -- TODO consider making timer not need a function; cause I don't here!
local task_queue local task_queue
task_queue = { task_queue = {
@@ -32,34 +125,44 @@ task_queue = {
end, end,
} }
local total_pages = 500
local current_page = 0
local pages_progress_bar = progress_bar(0, window_height - progress_bar_height, window_width, progress_bar_height, total_pages / current_page) local book = utility.load_data("book.json")
local update_pages_progress_bar = function(increment) local book_progress = progress_bar(0, window_height - constants.progress_bar_height, window_width, constants.progress_bar_height)
current_page = current_page + (increment or 0) local update_book_progress = function(increment)
pages_progress_bar:set_progress(current_page / total_pages) book.current_page = book.current_page + (increment or 0)
pages_progress_bar:set_text("Reading: Page " .. current_page .. "/" .. total_pages .. " (" .. math.floor(current_page / total_pages * 100 * 10) / 10 .. "%)") book_progress:set_progress(book.current_page / book.total_pages)
book_progress:set_text("Reading: Page " .. book.current_page .. "/" .. book.total_pages .. " (" .. math.floor(book.current_page / book.total_pages * 100 * 10) / 10 .. "%)")
end end
update_pages_progress_bar() update_book_progress()
love.update = function(dt) love.update = function(dt)
lovebird.update() lovebird.update()
timer.update(dt) timer.update(dt)
test_bar:set_progress(test_timer.run_time / test_timer:get_interval()) test_bar:set_progress(test_timer.run_time / test_timer:get_interval())
local thread_error = test_thread:getError()
if thread_error then
log("debug", thread_error)
end
end end
love.draw = function() love.draw = function()
test_bar:draw() test_bar:draw()
pages_progress_bar:draw()
book_progress:draw()
end end
love.keypressed = function(key) love.keypressed = function(key)
if key == "escape" then if key == "escape" then
-- TODO save any remaining log -- TODO save any remaining log
utility.save_data(book)
love.event.quit() love.event.quit()
elseif key == "left" then elseif key == "left" then
update_pages_progress_bar(-1) update_book_progress(-1)
elseif key == "right" then elseif key == "right" then
update_pages_progress_bar(1) update_book_progress(1)
elseif key == "v" then
send_test_message()
end end
end end