my picotron drive, to be shared across my devices
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.
picotron/atelier2.p64

1195 lines
37 KiB

picotron cartridge // www.picotron.net
version 2
:: gfx/
:: map/
:: sfx/
:: conversation.lua
--[[pod_format="raw",created="2024-04-03 02:38:22",modified="2024-04-10 14:42:28",revision=642]]
default_script = {
{"welcome to Atelier Hester!", talk_sprite}
}
Conversation = {}
function Conversation:new(script, final)
local c = {script=script or default_script, final=final or function() end, index=1}
setmetatable(c, self)
self.__index = self
return c
end
function Conversation:before()
self.behind = scene
self.before = function() end -- only ddo othis the firstt time this scene is played
end
function Conversation:update()
local now = self.script[self.index]
if now.during ~= nil then now.during() end
if btnp(4) or btnp(5) then
if now.after ~= nil then now.after() end
if self.index < #self.script then
self.index += 1
else
--self:after()
end
end
end
function Conversation:draw()
self.behind:draw()
ragged_box(30, 100, 240-30, 130)
color(0)
print(self.script[self.index][1], 34, 104)
end
function Conversation:after()
self.final()
--change_scene(self.behind)
end
:: screen_drawer.lua
--[[pod_format="raw",created="2024-04-05 00:59:25",modified="2024-04-05 00:59:26",revision=1]]
:: shop.lua
--[[pod_format="raw",created="2024-03-29 01:14:51",modified="2024-04-05 14:54:05",revision=1117]]
-- this manages the main shop interface, where you look at the cupboard and plantss
-- and sstuff.
include("art.lua")
include("fairy.lua")
include("cabinet.lua")
cabinet = Cabinet:new(40, 10, 2)
fairy = Fairy:new()
alchemist_sprite = 192
alchemist_bob = 0
customer_sprite = 0
customer_bob = 0
customer_visible = false
door_open = 0
shop_screen = {}
function shop_screen.draw()
cls()
cabinet:draw()
-- alchemist!
bob(alchemist_sprite, 0, 7, 96, 128, alchemist_bob)
fairy:draw()
-- countertop!
draw_counter(14)
if customer_visible then
bob(customer_sprite, 240-96, 7, 96, 128, customer_bob)
end
draw_door(door_open)
end
function draw_counter(height)
rectfill(0, 135-height, 240, 135, 4)
for i=1,height do
rectfill(0,135-height, 0.5*i*i, 135-i, 4+16)
rectfill(240,135-height, 240-0.5*i*i, 135-i, 4+16)
end
line(0,135-height, 240, 135-height, 4+16)
end
function shop_screen.update()
fairy:move()
cabinet:update(fairy.x, fairy.y)
if btnp(4) then
local drawer = cabinet:drawer_at(fairy.x, fairy.y)
if drawer then change_scene(DrawerScene:new(drawer)) end
end
end
function draw_door(open)
palt(0x00, true)
if open >=0.0 then fillp(0b1111111111111111) end
if open > 0.1 then fillp(0b1011010111100101) end
if open > 0.2 then fillp(0b1010010110100101) end
if open > 0.4 then fillp(0b1010000110100100) end
if open > 0.7 then fillp(0x0000) end
rectfill(240-(96*open), 135-128, 240, 135, 0x00)
sspr(200, 0,0,96,128, 240-(96*open), 135-128, 96*open, 128)
palt()
fillp()
end
:: art.lua
--[[pod_format="raw",created="2024-03-31 01:52:08",modified="2024-04-12 14:41:51",revision=629]]
function bob(s, x, y, w, h, t)
sspr(s, 0, 0, w, h, x+t/2, y-t/2, w-t, h+t)
end
function ragged_box(x1, y1, x2, y2)
ragged_box_color(x1, y1, x2, y2, 15)
end
function ragged_box_color(x1, y1, x2, y2, bgcolor)
rectfill(x1+1, y1+1, x2, y2, bgcolor)
sspr(004, 0,0, 8,2, x1+1, y1, x2-x1, 2)
sspr(004, 0,0, 8,2, x1+1, y2, x2-x1, 2)
sspr(004, 0,0, 2,4, x1, y1, 2, y2-y1)
sspr(004, 0,0, 2,4, x2, y1+2, 2, y2-y1)
end
function easeTrig(t)
if t<0 then return 0 end
if t>1 then return 1 end
return 0.5-0.5*cos(t/2)
end
function easeAccelerate(t)
if t<0 then return 0 end
if t>1 then return 1 end
return t*t
end
function easeDecelerate(t)
if t<0 then return 0 end
if t>1 then return 1 end
return 1-(1-t)*(1-t)
end
function easeSine(t)
if t<0 then return 0 end
if t>1 then return 1 end
return sin(t/4)
end
-- add newlines to a string to fit it into lines.
function wrap(str, line_length)
-- thanks to https://stackoverflow.com/questions/17586/best-word-wrap-algorithm, i did not feel like thinking this out myself
local words = split(str, " ", false)
local output = ""
local c = 0
for w in all(words) do
while sub(w, 1, 1) == "\n" do
output = output .. "\n"
c = 0
w = sub(w, 2)
end
if c + print(w,0,-10) > line_length then
if c > 0 then
output = output .. "\n"
c = 0
end
end
output = output .. w .. " "
c += print(w,0,-10) + print(" ", 0, -10)
end
return output
end
function collides(position, object)
return position.x < object.right and position.x > object.left and position.y > object.top and position.y < object.bottom
end
:: cabinet.lua
--[[pod_format="raw",created="2024-04-03 19:46:51",modified="2024-04-14 02:34:28",revision=631]]
Cabinet = {}
function Cabinet:new(x, y, gaps)
local c = {
x=40,
y=10,
drawers = {},
shelves = {},
hover_plant = nil,
height = 4*(gaps+16)
}
-- populate the big drawers
local xoff = x
for i=0,0 do
for j=0,1 do
add(c.drawers,
Drawer:new(xoff + gaps + i*(gaps+32), y + gaps + j*(gaps+32), 009, 32))
end
end
xoff += gaps + (gaps + 32)
-- populate ssmall drawers
for i=0,3 do
for j=0,3 do
add(c.drawers,
Drawer:new(xoff + gaps + i*(gaps+16), y + gaps + j*(gaps+16), 008, 16))
end
end
xoff += gaps + 4*(gaps+16)
local s = Shelf:new(xoff+gaps, y + gaps, 76, 32)
add(s.plants, {13, 4})
add(s.plants, {14, 14})
add(c.shelves, s)
local s = Shelf:new(xoff+gaps, y + 3*gaps + 32, 76, 32)
add(s.plants, {15, 10})
add(c.shelves, s)
setmetatable(c, self)
self.__index = self
return c
end
function Cabinet:draw()
-- cabinet!
rectfill(self.x, self.y, 230, self.y + self.height, 2)
-- drawers
for a in all(self.drawers) do
a:draw()
end
-- plant shelves
for s in all(self.shelves) do s:draw(self.hover_plant) end
end
function Cabinet:update(x,y)
for d in all(self.drawers) do
if d:contains(x,y) then
d.offset = 4
else
d.offset = 0
end
end
local closest_distance = 1000
local closest_plant = nil
for s in all(self.shelves) do
for p in all(s.plants) do
local dist = abs(p[2] + s.x - x+16) + abs(s.y + 24 - y)
if dist < closest_distance then
closest_distance = dist
closest_plant = p
end
end
end
if closest_distance < 32 then self.hover_plant = closest_plant
else self.hover_plant = nil end
end
function Cabinet:drawer_at(x, y)
for d in all(self.drawers) do
if d:contains(x,y) then
return d
end
end
return nil
end
Drawer = {}
function Drawer:new(x, y, sprite, size)
local c = {x=x, y=y, sprite=sprite, size=size, offset=0}
setmetatable(c, self)
self.__index = self
return c
end
function Drawer:draw()
rectfill(self.x+2, self.y+2, self.x+self.size-3, self.y+self.size-3, 0)
spr(self.sprite, self.x, self.y+self.offset)
end
function Drawer:contains(x, y)
return x >= self.x and
x <= self.x + self.size and
y >= self.y and
y <= self.y + self.size
end
Shelf = {}
function Shelf:new(x, y, width, height)
local c = {x=x, y=y, width=width, height=height, plants={}}
setmetatable(c, self)
self.__index = self
return c
end
function Shelf:draw(highlighted)
rectfill(self.x, self.y, self.x + self.width, self.y + self.height, 0)
for p in all(self.plants) do
if highlighted ~= p then
palt(0, true)
palt(10, true)
end
spr(p[1], self.x+p[2], self.y + self.height - 32+2)
palt(10, false)
palt(0, true)
end
end
:: fairy.lua
--[[pod_format="raw",created="2024-04-03 17:32:32",modified="2024-04-10 01:58:59",revision=384]]
Fairy = {
velocity = 1,
accel_frames = 20,
min_velocity = 0,
max_velocity = 3,
f = false
}
function Fairy:new(ff)
local f = ff or {x=120, y=68}
setmetatable(f, self)
self.__index = self
return f
end
function Fairy:draw()
if flr(30*t()) % 2 == 0 then
spr(5, self.x-8, self.y-8, self.f)
else
spr(6, self.x-8, self.y-8, self.f)
end
end
function Fairy:move()
if self.velocity < self.max_velocity then
self.velocity += (self.max_velocity - self.min_velocity) / self.accel_frames
end
if btn(0) and self.x > 0 then self.x -= self.velocity end
if btn(1) and self.x < 240 then self.x += self.velocity end
if btn(2) and self.y > 0 then self.y -= self.velocity end
if btn(3) and self.y < 135 then self.y += self.velocity end
if not (btn(0) or btn(1) or btn(2) or btn(3)) then
self.velocity = self.min_velocity
end
if btn(1) then self.f = false end
if btn(0) then self.f = true end
end
Glow = {}
function Glow:new(x,y)
local g = {x=x, y=y, t=0, length=0.7, radius=10, start_color=8, end_color=9}
setmetatable(g, self)
self.__index = self
return g
end
function Glow:draw()
for i=0,4 do
local eff_radius = self.t*self.radius / self.length
if eff_radius - i >= 0 then
local c = self.start_color
if i < (self.t/self.length)*4 then
c = self.end_color
end
circ(self.x, self.y, eff_radius-i, c)
end
end
end
function Glow:update()
self.t += 1/30.0
return self.t < self.length
end
:: gfx/0.gfx
b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTI5IDAxOjE0OjUxIixtb2RpZmllZD0iMjAyNC0w
NC0xNCAwMzoyMjo1NiIscmV2aXNpb249MTEyMF1dbHo0AJgZAABjXQAA8Rp7WzBdPXtibXA9cHh1
AEMgEBAE8PAsZmxhZ3M9MCxwYW5feD0wLjM3NQwA_wJ5PS0wLjEyNSx6b29tPTV9LDoAkCR6cAoP
HU8eCgcAcD8ODx4KYBoJAP8CDRpQCh8dPw4dClAKDx1fDg0IAAT-Aw8eClAKDl8ODgpQCn4KUJrw
A4sAJqUGOrAKHxMKsAoeBADwAKAaHhqQCgMOEQqQCgMPEgcAPQ4dAQYArw4KkAo_CpBa8AV9ACYQ
Jn0AER1xAP8GYDoPFy46MAo9HxweHxIKMAodbxwPCAACIF8cIAD-ARodPxwODxIaQBpeGmB68ASE
ACJRCAgECQACABIQCAAfGQ4AFh8J9QAm-yAQLxyQPgAuUC4AHiAuEC4gLjAOEA4wHgBeEF5ALBos
YDwaPFAcEAogHIAa0ArwOWgAJccgLDAsUAwADDAMAAwIADAcEBwIABEQAgD-EVAcAAwQDAAcYCwQ
LIAcGhyQHxwaHpAeCgAegB4aEB6QfwAl8EnIZATw-7X-Dw-wG47wNf8YHf4V-RL_Bv0mcP0a-hn9
D-4P-R9w-Rb_Hv0M-hr9FnD9D-4m-Qj_Je0_rXD9B-4w-QT_O51wnVf_Od3_QI1wnQf_P73_Qhdd
CgDyAECd-kQHXXCd-kJtDx-_RQsAYg0PFj0vHxkAaAf_Qh8WXw0ARW8f-kMNAE9-H-5CDQBeCYIA
Dw0AFAnDAA8NACETTx8BDw0AWk8-H-5GDQAqDlsADw0AwC-_QwwAT2FfH_7H-igOADAm594QAGGu
R74n-iUSAHAhV94Xbgc_FgBxfjf_Ayf_IhcAcBxXfieeF54XAHFeJ-4IJ-4gFwCQGEduZx4nfheO
GQBxThf_DCf_HhkAkBRHXleeJ24XfhkAcT4X-hA3-hoZAKARN15H-gIHbhduGgCRLhdu9wOuR-4V
HACQCPcE-gcXXhdeGwCyHhdON-4CN65X-hAmAaABZz5X-hEnThdOzwDBHhdOF25HvjfOR-4MIACx
TsdOV-4Hx04XPhe_APA_F04XXicuN75H3jf_CAddcK0uJ26n-gdXvhc_Fx4dFy4PFm8fBz4nXhd_
J_433mf_AQddcL2ON-4Jh-4IBw49TlwOB84HvkfOR-4A9wDVAPspzT49Lv0Ap-0XLh087hcerT5n
nkf_DX1w-VMevQ4HHv0HV35n-gaNcP2BBz2eh86dcP2Zjt1w-bADAF-w----3z0FFBwxvAVQ-xQB
1B4CALAEuQQeBAk-Dxk9CQkAGp0GADEPFQ4IAIcMDgS5BAwO1AMAH_y4BSKfICAE-xQR9A4eAwAC
wDT5BjQeNAl-Dzl9CQkAMY0ZjQgAL-0EBwALMg8VDgkAHgwIAH-5BjQMDvQOBAASPx78DtYAJXLU
DxTwAdQOBAD-EsQe8AHEDvACtB7wAqQe8AOUHvAEdC7wBVQu8Adu8P--q2YAJf8J_TAg_gqA_QTQ
_gDwAdnwAtnwA7nw---8UAAlAEQCH-M9ACfwCKIq8A0KAwrwDBoDCvAISgMACvAICgMgCAAjBToI
AFAKAxADAAIAZBrwBAoAAwIAHwoOAApEAToAAwIA8A5KwAr-EgEKwCrOKuAKzgrwARquGvACCq4K
8AMajlUAb44K8AWqoMYAJ8AAOvAMCh8TGvAIOi7BAPAiHgAuOvAFCi4AThrwAiouJD4K8AIKFA4A
DgQQHgAa4DoALgAEDxQzCvAACi4AHiQNPgoAUQAuEAMkCgDgICQQFBAq8AAKHhQANCOwAKBeJBAa
8AEKfhQeSgAhLkAIANIaYBQQSuAK7xgK4ArsBAChGswa8AAKzArwAQUAfxqsGvACypDZACfwDl1K
8AZaLxMK8AYKTgQeCvAGGh4TBBMq8AUKIA5DOgHwByAeBD4a8AMKLhAELgAOCvADCkMkEwCdABAw
ugBAAgoOQ7sAsAIKDgMODxQuFA4AdQEwEB0QwgDTBAogDRAUEDrwAQrGCgUAIBqmLgAQpiYAEIZh
ABCGAQIfhqABJ-1iYGAE-x4P-xUS-x4j-xUo-x4R-xU2-x4G-xU_3x7-FUZ-Hv8VSj8e-xUM8Bj_
Cg8e-gHwMP4FBT7wPD4FnhUO8EAOFZ518DZ1rvUE8Bz1BM71Qv4A9T7_BPU6-gv1MP4c9Rj_Ch3_
Th3_Ti3_TE3_Sl0DAE9N-kw9AwAEES05AAUDADAN-v8BACQ1DREABVkABTIAAmIAQW3_SH0DAPtY
jf5Gnf5Grf5Ezf5C3f5C7f5A-QH_Pv0C-j79A-48-QX_Ov0H-jj9Cf42-Qv_NP0N-jL9D-4w-RH_
Lv0T-iz9Ff4q-Rj_Jv0b-iT9Hv4g-SH_Hv0k-hr9Kf4U-S7_EP00-gj9Pd79GXoBdC01LjE1ODMB
AASEAVcxNC44MBcAAY4BGTOOAfB0QEAE8P9bPxjwJq7wIe7wHf4E8Bj_BCge8BL_BEhe8Ar_Bziu
8AX_B0j_APAB-gVI-gbg-gFIfni_0M44ToheGL7AfkhOSO4YrsBOKH4oPvgBvrDemL4YDhi_oM44
7kgeGM6QLgeOCB4YrjheCO6ALgd_GC4Yfih_GO6ALg8PB24IThg5ALD_AIAuBw1_CE4YHg4A8BkC
gC4dB24IXjhuOP4DoB4NBw1uGF4YLlj_AgcdwB4dB27I-gMHPRfAGgDyBP4UBy03HcAuHQf_Dwc9
Nw0aFw4YAHANLUcdSi6wGQCRCB8OHUctah7QGQDwCAVsFy0nDkoO8AEeHQf_AD1cLRdOKvAEHADw
Bc4tNywtF37wBy4dfgc9Vy0nfvALGABgPgctBxs3DwAQDg8AQAc9B1sNAPAdEh4tJ3snfvAVHg1H
e37wGC4NJx1bXvAbPgcdFyte8B8uF47wIq7wJm7wKx6YBS--5DMDCRYxMwMfNKUBF5Bu8An_BzjO
8AOlASAC4KQB8SAIwP4BSP4OsM44zri_kH5IfpheWL6ATiieOG6oDhjOcO44HnheGC4Y3nDOeK4o
PqQBAJgBUJ4oTijeDACiCF4IbhhOOM4XoKUB8A5uGB4oLkjOR6AuBw0HXjheiN53oC4dF46I-gKX
sBEBsxf_EMfAHh0n-gunlwFCF-4Ht5gBhif_AycfDmctmwFUJ943XBeeAUY3jmdsnQFGN06nfJ4B
KPcBnQEWx50BF4ecARlHmwEvFy2bAV7wJtlvG-AZ-gjwEv4O8A3_FPAI-hjwBv4Mem7wBO7a-gDw
A35q-g7wAv4f8AD_IeAOCv4Hev4ACADxIABqXgr_AtAOCv4BGn4a-gPQCv4EGk4K-gbACv4GGh4K
-giwCv4IGv4JsAoOCv4hBgD2CiKgHgr_EXqOoA4K-gPq-gGgDgquev4QoA4jACAgwAYAQBoHHgdl
APAHDvcC4AoOCk73A-8PB9AKDgoe-Qb3BhMAcA73Bv0I0BoQABAH3AYg9x0GAPEK-R7gCi73Gx7w
AF6H-gHXLuD_IfAA-gKA-loIT----30pASbwLxc-G-ApfvAj3vAe-gPwGP4AKl7wEv4BOo7wDv4B
Ot7wCu5K-gPwB846-gnwBZ46-g3wBW4q-gAq7vAD-gVaJwFh8AH_AjpuCQDwAw4KziqeCv4D8AAO
Cu46Xgr_BAoAgf4DOh4K-gXgOAHQBuAK-hYqftAK-hFKrvsAUf4LOv4BHgHwBQZK-gXAHgr_AUr_
CdAOCt46-gg3QABhrir_BqfgTQFRDPcB8AAsACD3CC8Br-4A9w7gDgqu9xVQAXEhYBBAAPsLcP8S
GPAc-jDwCv488AL_QPAF-jbwF-4c8GlWAHYtMC4wMjUwAQAUNGMANDIuM2MAHzNjAAf-Be4-Hf4d
8Ar_BT3_Ez2_8AL_Lj3ebQBA8AYSDx0AHgAO4F8e8DP-EgZ-Hp8SAA4CAP8d8BZNDx5tDi0OHQ7N
DlwO-QbwCo1MfQ79Al6tDh0eHQ6d8AL9QPAF-TbwF-2RADfxD6cPHvBPDiAO8EcOIA4QDvBJDnAO
8Cg_8BIO8CheIBkB-xYtXv0n8AqdPq1ufXL9DPAC-QEy-QVyXVL9AvAF-SJyvfAX-RZSkQA2ESaR
APA1EA7wTw7wSA4QDxIgDvBIHg1wDvBDDUAdIA4ADcBN8DQeHQANII0u-QwQTfAVTQAOzU79F-AK
nQ4NHj0SXU6Nkm0S-QGqAP8KIv0Ekk1y-QHwBZ0S-RUSHgIuEq3wF-0VYrAANvAK-1gvHvARFvAp
TvBDDxJQHgc_TfA9bW79CpoA8RotMh0SjU5NQi1CbR698Ap9wl0uTTIN0h0eAg1CrfACzYJdQm2S
TSIeIqIAjyL9B0Itcj4iogA78EhzHx5wHvBGDvAUJvAdLvAdJvAfDvADDvBMPvAJFvAiHlAu8EYe
MC8SDg2QHvADFvAiDVAOLQ4NDk3wPc0OHSJNYl0_AE3wFaINIo0Osg1iLV4ibSAi8ATMAPMREi0O
8gJegh1C8AKNsi49cg0ukk0CXlK98AWdMl0CvXLNAH89Mk1SHYJt0gA2oZom8E0m8K4W8EYsAvFL
QBbwKjIPEvAJDvApDQDSLQBSMCIOMELQMvATfaJNYh0OAh0yAB0ugCLwABJQsg4iLdIeIg3yAy49
EELwAfIBTkI-EyItEj5SPvIJ8AKN8gs8Yjw9cg4yHVI9yAD-AhKtci0iPgIOUj0eTfAXPfIKyQAz
DysZK-8KPg8e4A6gDiAOsA7wBP8SEC59Qq1C-RDwAFIAeB-wOgD-------------------------
----------------------9M8CNggATw-yS-FPBA-gLwPP4G8Dk-Ff4E8Dc9-gXwNU3_B-AzTf4I
8DJN-grwME3_C-AvXQUA_ABN-gzwLl3_DfAtTf4N8C4FADMM8C8FADELDw8HABA8JgDwDAk88Cwc
Tf4IPPAuHD3_BywPF-AxTf4FCxwLDAkA8KwEDAsMCwzwM02_LS4PGRwLHPAzXY49Lho88DVdTm0e
KjzwNv0BSjzwN816LPA5Ck3aHPA7_gMM8DuaDIrwO2psevA6Wnx68DlaHxwMaWrwOFqpWjnwNFrJ
SjnwNEoA6SpJ8DMqIJkvDCkKWfA0CkhJ_ATwMPgR8C5oDwr4DPAraBcoJ-gH8Cn4Azc4F6jwKCf4
DAe48CIH_BIniPAh_BYHiPAg_BgHePAg_BknOPAf_CHwH-gi8B34IAcYBgDxBxcY8Bz4IQco8Bv4
JfAb_CbwGigJ_CIGAPAjDgn4BPAaGAn4DhkoCfgA8BkYCfgPGRgJmAdY8BgIGfgQCSgJiAdY8BkJ
_BEZKAkYCVgZAFQJ_BIpOAsA8QIUGRgZWBdY8BcJ_BUZCBloBwsAgRgZ6PAWCfgZPgBkFBn4FRkY
CwBQFAk4GegJABAacgCCExn4GhmIFzgJAEb4APASCAARG4gAgREJ_BwJqAdICQAkGZgJALD4AfAQ
GfgbKagHOAkAphwZuAc48A8J_B0JAKHIBxjwEAn4HCnYTgAgKchlADATqbh9APABD0l4GajwFRn4
Dhm4GYjwF0IA8gEIIBjwGin4GxkI8B8p_BwJBwAQGQYA8CMaOQjwHin4GFkI8B8Z_BdpLfAdGfgU
aQgJTfAcGfgReQht8B4J_A6ZbRXwHhn4CpmNJQgAUAapGG1VCQDyQgK5GH2F8B4ZyMkIjcXwHgmY
uc3V8B8JWKnd9QLwH8kIzfUFAAXwHpkVjfUN8B5prfUPAAXwHQ0ZvfUV8Bvd9RjwGY0FDfUc8Bkt
9STwGT0FDQIAovUc8Bgt9SbwFy0QAEMFDfUdEgAGJACkHvAVPfUo8BQtFRIAhiDwFC31KvASJACF
IvASLfUs8BASAAEUAIUQLfUsAAXwD14AABYAiQbwDz31KgAVFwADVwCLDy31LQAF8AztA24tMjku
MTC4M0gzOC43zzMP8DkAAQIE8S3--8NvFPBF7vA8PxV_KV7wOF2OKV7wNz0OSW4JbvA2PQ5Z7vA1
PQ5pbgpu8DQdPmnu8DQNTln_APA0bkkGAPCEKW6vGfA03tzwNBmO-AHwNBlu-AMQHw-wMBle-AMQ
G-AxGV78AgsAK-Axbpzb8DFujNvwMl6Mmx8fK-AyXnyLKDvwMl5sSwgbKCcb8DNeXCs4Sx8OBwvw
NF4sHxcbKEsIGx8OK-AzHnsfFxgLFw8OKxhb8DMOmw8XCycfDjsYS-AzHksfF0sXHw5LCEvwMz4r
Lxe7FgDwJw1ODAsWuwhb8DM9HizrGCvwMz0OHAAsqyg78DMtDmyLKEsfHPA1jGsYWwYPDB8c8DSM
AMsGLwoA8kkyrKsWBT8MFfAxDAB8qwYbRCXwMJzbRBUU8C_sy0QllPAnjEWLFSRFpPAkjAU0FXsl
BAX0AfAifBVEJXsl9AEV8CB8BYQFayX0AwXwIGwFlAVrGvQF8CBcCgDxQAbwH1wFlBVrCgX0BvAe
TAAFlBVbBAoF9AfwHiwAJXQFBBU7FBr0B-AhFQQVZAUUBUoFGqQFtPAfFQoUJUQFFBpUCqQFxPAc
FQQKRCUkBaQOAPAGGhUECnQlBAW0CpQF1PAYFcQlxAqECgBQBQQKxBUMAPAK5PAWBQQK9BcF9ADw
FQUK9BgV9ADwExX0GggAYBIF9BIKhAoA8wARBfQTCnQABfQC8A8F9BQLAHAOBfQVCmQQCwAQDQsA
EXQLAEEMBfQWIQA0A-ALCwChBPAKBfQfABX0AwkAEBAdADIK9CAIAFDUFfQQEBsA8gEIBeQF9AgK
ZCAV9ALwCPQADQAyJfQBDQCFCQpEEBUUJeQOAEEAFUQFDgBgFfQICkQAOQEwCPQBGwAfNA0AAsEV
9A0ABfQF8Aj0AwULADME8AkLAFAEKtTwCwwAgAwgGgQatPAMDADACAokEAo0GpTwDfQCYwCgJAAK
VAqE8A70AlcAAA4AQBpk8A8OAJIKCiQVVApU8BANAGE0BVQaNAUOAPEEBHX0AQo0BWQKJAXwEeRV
ZAX0AA8AgRQF8BL0DQXkDQBwBAXwEwX0DBwAsyQFZAoF8BQF9AsVDgDB8BUF9Awa5AokBQpUDQBw
Czr0AnrwF2kAYBRaROvwGAoAUmQaFOsWCwCAdAoE2wYr8BmlAFSECusWGxcAQcsGKwYNAFEJCnQK
2w0AEhclAAANADEL8BgMAIRrPwU7BhsGCykAMUtjKw8AAVAARFQaK4MPAFHUtVrjGwwAYhoFZHXz
DhgA8hIbZW3zDjsGCwMb8BqNAw3zEisGC0PwGS3zHAtj8Bk9Aw0CABDzRgVS8yXwGC0QAIADDfMe
8Bct80YFAhAAARIAMBU980YFFBMSAABGBRDzRgUCEAAwAw3zRgUQ80YFJwMNFABlEC3zLvAPXACf
Aw3zJPAOPfMuJwUsD50JJw_FCv8gIP8UwTTxAXz0P-4BBP8VPQT_AQT9PA4HACA7HgcAQS30Ny4I
AE8E-jUECgD-NARSASH0OGIBMR30OnEBcg30Pf4B9D_xPDH--_iUAR-9kwH-dh9cYgMUHzLlCQHy
KxjfFvBALr8PHvA9Lu0e8Dse-QIO8Doe-QMe8DkO-QMfEQ4N8DUcHs18DhzwMRwAHA7dDA0cDVzw
MUwKAPYGHA0MDgzwMQwgHv0BDD0MDvA2Dv0IBgBgLU4dTm0uDwCwBR4NDvA3Dl0O-QAIAEBNHv0B
IQBRPR49Ds0qAFAeTQ69HgkAUA5dDp0KLQDwDR4dPi0OjQou8DgOTU6dCg7wOR79BA7wOg5NPq0H
APGALQ5tDm0e8DsOHR5NHl0_8DoeHX5NHh0u8Dk_QH5NHvBBHs0ODQLwPx7NDxhi8DourQtyG-A5
Dp0bYjvwNAs_nQtiGw0r8DICCw0enRtSGz0CC-AwEgu9G1IbXQIL8CwNCyIbrQtSG30CC-AqHQsy
G30rQhudAgsC8CgdC1IrPRtiC70bAvAnHQtyW2IbzQsLAPIA8gQb3RvwJi0L8gMb7QILCgCwC-0A
G-AlPQvyAhsKAPAEAggX8BA9C-IBG-0CC-ACCDfwDg4A8QAL-QML8AMIN-ANPQvyABsOAEAYR-AL
DgBQC-0CDg0eAGAHGDfwCU0SADFNDr0TAEwYBxgnEwBIAFfwCBIAYQQIEFfwBxIAIz0eEgByIEcA
LxXwAxUAIg7NFQA5MEcpEwCwAvADCDA3KQ3wAl2UABUtFQBwQAdJHfABXbcAUB0ezQ4bPABBWa0g
vREAIQ7dEQBJIEn9DBAAMCn9DhAA0hIO3Q4CC-AK-Q8L8gQMADoL-Q4MABEFCwBUDI0g-QENAPQK
DW3wBBvyBc0eAgvwDk3wBQvyBs0OEgvwKAkAcB0OvfIFvR4KAPACXhBObcLNDiIL8CANAG69ct0L
APEMGmVuC-0RHiIL8BYVDkVOEC4L-REOMgvwFYWeCgDwTfAWhU4AHhAL-RAeIvAXhW4tC-0PHjIA
C-AV1R0Q-REOQivwFLVgC-0NLjJL8BNlECVgCxL9CS6SK-AShYALMv0EPtIb8BFVsAti3T7yAhvw
EFWwC-ICPvIGK-AOCwAiHRsIAEAeG-ANCAAgHwsIAKbyIBvwDFWg8iILBwBgsPIhG-ALJABnIBvw
C2WgCAA-C-AMCAABAEwAAAgAYR4L8A9VoGwAAQgAEByHAPAAoAvyGxvwEUXAC-IZG-ASCABAGBvw
EwgAQBcb8BQIAEEVK-AVCAA-C-AXCAANITXQCABvFkXgC-IUCAAUIxMbCABPCxLwFQkADR8bRAAA
YvAA8hTwFwcAHwPyBBUPyAgnDzoA---------------3UG09NX19
:: gfx/.info.pod
b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTI5IDAxOjE0OjUxIixzdG9yZWQ9IjIwMjQtMDMt
MjkgMDE6MTQ6NTEiXV1sejQABAAAAAMAAAAwbmls
:: library.lua
--[[pod_format="raw",created="2024-04-10 00:24:20",modified="2024-04-10 01:58:59",revision=35]]
plant_descriptions = {
[-1]={{"i don't know what that is. where did you find this?"}},
[14]={{"this is foxglove"}},
}
function get_conversation(plant)
local id = plant[1]
return plant_descriptions[id] or plant_descriptions[-1]
end
:: main.lua
--[[pod_format="raw",created="2024-04-02 02:59:37",modified="2024-04-14 03:22:56",revision=1000]]
-- this is atelier hester!
-- except for the one line in _init that does change_screen(shop_screen)
-- this is just a file that sets up the framework we're using:
-- change_scene to change the displayed sscene
-- _update and _draw to run the current scene
-- and some stuff for setting animations.
include("art.lua")
include("script.lua")
include("s_title.lua")
include("s_shop.lua")
include("s_conversation.lua")
include("s_drawer.lua")
include("s_book.lua")
DEBUG = true
scene = {
before=function() end,
draw=function() end,
update=function() end
}
previous_scene = scene
animations = {}
script = {}
function _init()
vid(3)
change_scene(title_screen)
end
function _draw()
scene:draw()
for anim in all(animations) do
if anim.draw ~= nil then anim:draw() end
end
if DEBUG then
rectfill(0,0,90,10, 7)
print("animations: "..#animations, 0,0,0)
rectfill(0,10,90,20,7)
print("script nodes: "..#script, 0,10, 0)
end
end
function _update()
if #script == 0 or not script[1].blocking then
scene:update()
end
local new_animations = {}
for anim in all(animations) do
local result = anim:update()
if result then
add(new_animations, anim)
end
end
animations = new_animations
if #script > 0 then
local result = script[1]:update()
if not result then
deli(script, 1)
end
end
end
function change_scene(new_scene)
if new_scene.before ~= nil then
new_scene:before()
end
scene = new_scene
end
function play_script(s)
for action in all(s) do
add(script, action)
end
end
:: map/0.map
b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTI5IDAxOjE0OjUxIixtb2RpZmllZD0iMjAyNC0w
NC0wNSAxMzo1NDowNiIscmV2aXNpb249NjgzXV1sejQAaAAAAFgQAADwCHt7Ym1wPXVzZXJkYXRh
KCJpMTYiLDMyAwAvIjABAP--------------------vxCCIpLGhpZGRlbj1mYWxzZSxwYW5feD0w
CADSeT0wLHRpbGVfaD0xNgoAEHcKAIB6b29tPTF9fQ==
:: map/.info.pod
b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTI5IDAxOjE0OjUxIixzdG9yZWQ9IjIwMjQtMDMt
MjkgMDE6MTQ6NTEiXV1sejQABAAAAAMAAAAwbmls
:: s_book.lua
--[[pod_format="raw",created="2024-04-14 02:34:41",modified="2024-04-14 03:22:56",revision=27]]
BookScene = {
extension = 0,
behind = nil,
inset = 60,
}
function BookScene:new(background)
c = {height=0, behind=nil, background=background}
setmetatable(c, self)
self.__index = self
return c
end
function BookScene:before()
self.behind = scene
play_script({
Script.len(function(s)
self.height = 115*easeDecelerate(s.timer/s.length)
end, 0.5)
})
self.before = function() end
end
function BookScene:update()
if btnp(5) then play_script({
Script.len(function(s)
self.height = 115*(1-easeAccelerate(s.timer/s.length))
end, 0.5),
Script.once(function(s) change_scene(self.behind) end)
}) end
end
function BookScene:draw()
self.behind:draw()
spr(007, 20, 135-self.height)
end
:: s_conversation.lua
--[[pod_format="raw",created="2024-04-05 14:55:45",modified="2024-04-14 02:34:19",revision=129]]
default_script = {
{"welcome to Atelier Hester!", talk_sprite}
}
Conversation = {}
function Conversation:new(script, final)
local c = {script=script or default_script, final=final or function() end, index=1}
setmetatable(c, self)
self.__index = self
return c
end
function Conversation:before()
self.behind = scene
self.before = function() end -- only ddo othis the firstt time this scene is played
end
function Conversation:update()
local now = self.script[self.index]
if now.during ~= nil then now.during() end
if btnp(4) or btnp(5) then
if now.after ~= nil then now.after() end
if self.index < #self.script then
self.index += 1
else
self:after()
end
end
end
function Conversation:draw()
self.behind:draw()
ragged_box(30, 100, 240-30, 130)
color(0)
print(wrap(self.script[self.index][1], 240-68), 34, 104)
end
function Conversation:after()
self:final()
change_scene(self.behind)
end
:: s_drawer.lua
--[[pod_format="raw",created="2024-04-05 00:59:36",modified="2024-04-14 03:22:56",revision=281]]
DrawerScene = {
extension = 0,
behind = nil,
inset = 60,
}
function DrawerScene:new(drawer)
c = {extension=0, behind=nil, inset=60}
if drawer.size > 16 then c.inset=30 end
setmetatable(c, self)
self.__index = self
return c
end
function DrawerScene:before()
self.behind = scene
play_script({
Script.len(function(s)
self.extension = 115*easeDecelerate(s.timer/s.length)
end, 0.5)
})
self.before = function() end
end
function DrawerScene:update()
if btnp(5) then play_script({
Script.len(function(s)
self.extension = 115*(1-easeAccelerate(s.timer/s.length))
end, 0.5),
Script.once(function(s) change_scene(self.behind) end)
}) end
end
function DrawerScene:draw()
self.behind:draw()
draw_drawer(self.extension, self.inset)
end
function draw_drawer(distance, inset)
rectfill(inset, -1, 240-inset, distance, 20)
fillp(0b1010110110110101)
rectfill(inset, -1, inset+40, distance, 20 | 21<<8)
fillp()
for i=1,4 do
rect(inset-i, -i, 240-inset+i, distance+i, 4)
end
rectfill(inset-10, distance, 240-inset+10, distance+10, 4)
rect(inset-10, distance+10, 240-inset+10, distance+10, 20)
spr(10, inset-10-32, distance, true)
spr(10, 240-inset+10, distance)
rectfill(inset+10, distance+10+1, 240-inset-10, distance+10+2, 9)
spr(11, 120-16, distance+10+1)
end
:: s_shop.lua
--[[pod_format="raw",created="2024-04-05 14:55:27",modified="2024-04-14 03:22:56",revision=205]]
-- this manages the main shop interface, where you look at the cupboard and plantss
-- and sstuff.
include("art.lua")
include("fairy.lua")
include("cabinet.lua")
include("library.lua")
cabinet = Cabinet:new(40, 10, 2)
fairy = Fairy:new()
alchemist_sprite = 192
alchemist_bob = 0
customer_sprite = 0
customer_bob = 0
customer_visible = false
door_open = 0
book_1 = {left=10, right=74, top=100, bottom=164}
book_2 = {left=80, right=144, top=100, bottom=164}
shop_screen = {}
function shop_screen:draw()
cls()
cabinet:draw()
-- alchemist!
bob(alchemist_sprite, 0, 7, 96, 128, alchemist_bob)
palt(30, true)
palt(0, false)
spr(16, 240-110, 135-36)
palt(30, false)
palt(0, true)
spr(21+flr(2*t()%8), 240-110, 135-39)
-- countertop!
draw_counter(14)
if collides(fairy, book_1) then spr(18, book_1.left, book_1.top)
else spr(17, book_1.left, book_1.top) end
if collides(fairy, book_2) then spr(20, book_2.left, book_2.top)
else spr(19, book_2.left, book_2.top) end
if customer_visible then
bob(customer_sprite, 240-96, 7, 96, 128, customer_bob)
end
fairy:draw()
draw_door(door_open)
end
function draw_counter(height)
rectfill(0, 135-height, 240, 135, 4)
for i=1,height do
rectfill(0,135-height, 0.5*i*i, 135-i, 4+16)
rectfill(240,135-height, 240-0.5*i*i, 135-i, 4+16)
end
line(0,135-height, 240, 135-height, 4+16)
end
function shop_screen:update()
fairy:move()
cabinet:update(fairy.x, fairy.y)
if btnp(4) then
local glow = Glow:new(fairy.x, fairy.y)
glow.start_color = 7
glow.end_color = 12
add(animations, glow)
local drawer = cabinet:drawer_at(fairy.x, fairy.y)
if drawer then change_scene(DrawerScene:new(drawer)) end
if collides(fairy, book_1) then change_scene(BookScene:new(007)) end
if collides(fairy, book_2) then change_scene(BookScene:new(007)) end
end
if btnp(5) then
add(animations, Glow:new(fairy.x, fairy.y))
if cabinet.hover_plant ~= nil then
change_scene(Conversation:new(get_conversation(cabinet.hover_plant)))
end
end
end
function draw_door(open)
palt(0x00, true)
if open >=0.0 then fillp(0b1111111111111111) end
if open > 0.1 then fillp(0b1011010111100101) end
if open > 0.2 then fillp(0b1010010110100101) end
if open > 0.4 then fillp(0b1010000110100100) end
if open > 0.7 then fillp(0x0000) end
rectfill(240-(96*open), 135-128, 240, 135, 0x00)
sspr(200, 0,0,96,128, 240-(96*open), 135-128, 96*open, 128)
palt()
fillp()
end
:: s_title.lua
--[[pod_format="raw",created="2024-04-10 01:43:09",modified="2024-04-10 15:04:40",revision=101]]
title_screen = {
continue=false
}
function title_screen:update()
if btnp(2) or btnp(3) then self.continue = not self.continue end
if btnp(4) and not self.continue then
change_scene(shop_screen)
play_script(the_script)
end
end
function title_screen:draw()
cls()
print("Atelier Hester ", 120-(68/2), 50, 7)
print("Start", 120-25/2, 70, 7)
print("Continue", 120-39/2, 90, 7)
local y = 70
if self.continue then y=90 end
rect(120-50/2, y-5, 120+50/2-1, y+7+5, 7)
end
:: script.lua
--[[pod_format="raw",created="2024-04-04 01:01:55",modified="2024-04-14 03:09:34",revision=554]]
Script = {}
-- sscriptanim generates animation functions and adds the boilerplate we want
-- can track time, but generally the ssystem we're working with is that
-- animations are objects which repeatedly get :update() called on them
-- they run at least once, every frame, *until they return false*.
-- so keep returning true to keep playing, rerturn false to end
-- the blocking argument determines whether update() is called on the underlying
-- scene, i think.
-- the ScriptAnim.len variant will take nil returnss as carte blanche to keep
-- running, checking for exactly the value false to cancel out.
function Script.len(func, len, blocking)
local b = blocking
if b == nil then b = true end
return {
timer = 0,
length=len,
blocking=b,
update=function(self)
-- we wrap the function we got passsed so that it'll update the timer
-- and end appropriately
self.timer += 1/60.0
if func(self) == false then return false end
return self.timer < self.length
end
}
end
-- ScriptAnim.once is cnofusingly named, and will call func(self) every frame
-- until it returns false.
function Script.once(func, blocking)
local b = blocking
if b == nil then b = true end
return {
timer=0,
blocking=b,
update=function(self)
self.timer += 1/60.0
return func(self)
end
}
end
-- stay in this script node until func(self) sets self.done to true
function Script.waitTilAfter(func, blocking)
local b = blocking
if b == nil then b = true end
return {
first=true,
done=false,
timer=0,
blocking=b,
update=function(self)
if self.first then
func(self)
self.first = not self.first
end
return not self.done
end
}
end
-- functions for making a cnoversation script line that bobs the alchemist or the
-- custmoer respectively
function A(arg)
arg.during=function() alchemist_bob=abs(5*sin(3*t())) end
arg.after=function() alchemist_bob=0 end
return arg
end
function B(arg)
arg.during=function() customer_bob=abs(5*sin(3*t())) end
arg.after=function() customer_bob=0 end
return arg
end
-- here's a sample script for a guy walking in and asking for flibbertygibbets
the_script = {
Script.len(function(s) -- open door
door_open = easeTrig(s.timer/s.length)
end, 0.5),
Script.once(function() -- person appearss
alchemist_sprite = 193
customer_visible = true
customer_sprite = 201
return false
end),
Script.len(function(s) -- door closes
door_open = easeTrig(1-(s.timer/s.length))
end, 0.5),
Script.waitTilAfter(function(s) -- cnoversation starts
change_scene(Conversation:new({
A{"Welcome to Atelier Hester!"},
B{"hey do yuo have flibbertygibbetss"},
A{"Fresh out, sorry."}
}, function() s.done = true end))
end, false),
Script.len(function(s) -- open door
door_open = easeTrig(s.timer/s.length)
end, 0.5),
Script.once(function() -- person appearss
alchemist_sprite = 192
customer_visible = false
return false
end),
Script.len(function(s) -- door closes
door_open = easeTrig(1-(s.timer/s.length))
end, 0.5),
}
:: sfx/0.sfx
b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTI5IDAxOjE0OjUxIixtb2RpZmllZD0iMjAyNC0w
NC0wNSAxMzo1NDowNiIscmV2aXNpb249NjY4XV1sejQAEAEAAFEHAADwJ3B4dQADKAAAAwAED0AQ
Ag4AAaABIAKgDgAPEAAN8MoBAgMEBQYHAA--kAgJCgsPDA8NDw4PDxAA8AANDxEPEg8TDxQPFQ8W
DxcTAPEBDxgPGQ8aDxsPHA8dDx4PHxQA8QAgDyEPIg8jDyQPJQ8mDycUAPEAKA8pDyoPKw8sDy0P
Lg8vFADxADAPMQ8yDzMPNA81DzYPNxQA-wU4DzkPOg87DzwPPQ8_Dz8AD--w-wEA6-8nWgEQBg8g
EAEgASAB8AACEAIMEAEgDyEgATAPQPDDDygP--DGD-gKD-8PgA-3Dw0B8AkBEAYMMAD-OR--AQDc
v-gPQAANQP--sPBwCgD--2Qf-wEAl1D-----Hw==
:: sfx/.info.pod
b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTI5IDAxOjE0OjUxIixzdG9yZWQ9IjIwMjQtMDMt
MjkgMDE6MTQ6NTEiXV1sejQABAAAAAMAAAAwbmls
:: story.txt
--[[pod_format="raw",created="2024-03-30 15:58:22",modified="2024-04-11 01:41:32",revision=208]]
ATELIER HESTER
welcome to atelier phoebe 2! this is my document for
recording story ideas! please don't read this; it is
all the spoilers! if you want to know what happens
i recommend playing the game, that is the proper
way to experience this :)
--------------
main gameplay interface, you're shown a gridd of
cubbiess which contain various ingredients
you look at the things in the cubbies and label them?
labeling could be hard with just o/x
you have twwo books, one of recipes and one of
ingredients?
drag a label from the book to the drawer/plant?
--------------
plot ddetails follow!!!
main character amnesia from alchemy gone wrong.
main character badly in debt to loan shark
everyone in town has some debt and don't talk about it
most people don't like main character
mc has to mend relationships with everyone in order
to gather everyone together to defeat loan shark
player controls a fairy assistant for alchemy
possibly fairy is new to the atelier?
early dialog esstablishes it's common knowledge that
fairies can blink white (o) to confirm things or
red (x) to be uncertain / ask a question
maybe other colors at other timess but you get it,
those are our two verbs - ask about something and
suggest something
interface is an apothecary cabinet you can open
the drawerss of and ask about. you have to suggest
ingredients to mix together for the cauldron
at the beginning MC is unsure and doesn't know about
your suggestions - "i guess i can look that up?",
"maybe i'll try this?" because the player is guiding
them. towards the end MC responds as though teaching
the player fairy, like "that's right, that'll work!"
and "good job, yeah!" to communicate that the MC
is more confident and getting their mlemory of
alchemy back
the town generally ddoesn't like the alchemisst just
because she's been kindda nasty and rude at times,
just petty disagreements that have boiled over.
she's known to be a decent alchemist though i guesss
endgame is that you rally the town together to break
free of the loan shark; it's hard too convince
townsfolk both because they don't like you at first
and also because the loans ARE legitimate. but it
turnss out that the rest of the town also has debt
to the shark and if you convince everyone you can both
1. achieve independence from the supplies he sells
(maybe he's the intermediary with the trader? or buys
and ressells everything at a markup?)
2. convince people to just reject the loanss/debt;
quesstion here of whether they do this by force,
whether cops exist, idk, this is explicitly passtoral
fantasy. maybe at the end the player will muse about
whether it's good to have mob rule, "no one in toown
liked me, what if they threatened to burn down my
shop?" "yeah, that would suck. maybe we could build
something. but right now rule by mob is better than
rule by loan shark!" idk this feels overly didactic
but you get the idea
this is really getting into the weeds of how we view
the justice system but maybe he threatens to say
"i'll send for the king's knights!" and the crowd is
like "you can do that if you want, but by the time
they get here your house will be burned down.
alternately, you can keep your house and try to
be friendly. maybe even contribute to the town. it's
up to you. burn down your storehouse or genuinely
connect with people?"
definitely overly preachy but i like that
------------------
script!!!!!!!!!!!!
------------------
title screen
new game or load?
new game ->
hester with her back to cauldrron holding a little fairy doll in pieces
fairy shakes and then comes to life
hester: "ahhh, the synthesis wworked! ... i think"
hester: "a fairy like you should be a good help around the shop."
hester: "you might noot be able to speak but you can flash white for yes and red for not sure"
the whole time there's more and more bubbling in the cauldron
hester: "you can be my hands across the atelier!"
explosion!
soot-covered hester stands up
"what just happened."
"wait a second. who am i."
"alchemy books? a cauldron?"
outside view of shop, Atelier Hester on the sign
"Hester..."
back inside
"i must be an alchemist..."
loan shark arrives
"hester! you got the latest payment for me, girlie?"
"i'm afraid i don't knwo who i am - can you help me?"
"nice try. remember you owe me 4000Z by the end of the month. have a nice day!!!"
loan shark leaves
(SAVE POINT)
"am i... in debt?"
"i don't know hwo to do alchemy... but maybe these books..."
(player opens books)
"it looks like this one has recipes... this one has infoormation about ingredients... my head..."
(when quit uot of both books, old man comes in)
"hey, hester. can i get that purified water?"
"i don't knwo who i am"
"sorry, i can't hear so good these days - purified water? my usual order?"
(moves on when you've crafted purified water)
"thank you, hester. this will help me out. here's your payment."
(old man leaves)
"i guess i'll just try to... be an alchemist and pay off my debts..."
(SAVE POINT)
at the beginning MC is unsure and doesn't know about
your suggestions - "i guess i can look that up?",
"maybe i'll try this?" because the player is guiding
them. towards the end MC responds as though teaching
the player fairy, like "that's right, that'll work!"
and "good job, yeah!" to communicate that the MC
is more confident and getting their mlemory of
alchemy back
the town generally ddoesn't like the alchemisst just
because she's been kindda nasty and rude at times,
just petty disagreements that have boiled over.
she's known to be a decent alchemist though i guesss
endgame is that you rally the town together to break
free of the loan shark; it's hard too convince
townsfolk both because they don't like you at first
and also because the loans ARE legitimate. but it
turnss out that the rest of the town also has debt
to the shark and if you convince everyone you can both
1. achieve independence from the supplies he sells
(maybe he's the intermediary with the trader? or buys
and ressells everything at a markup?)
2. convince people to just reject the loanss/debt;
quesstion here of whether they do this by force,
whether cops exist, idk, this is explicitly passtoral
fantasy. maybe at the end the player will muse about
whether it's good to have mob rule, "no one in toown
liked me, what if they threatened to burn down my
shop?" "yeah, that would suck. maybe we could build
something. but right now rule by mob is better than
rule by loan shark!" idk this feels overly didactic
but you get the idea
this is really getting into the weeds of how we view
the justice system but maybe he threatens to say
"i'll send for the king's knights!" and the crowd is
like "you can do that if you want, but by the time
they get here your house will be burned down.
alternately, you can keep your house and try to
be friendly. maybe even contribute to the town. it's
up to you. burn down your storehouse or genuinely
connect with people?"
definitely overly preachy but i like that
:: .info.pod
b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTA0LTEyIDE2OjM3OjU3IixydW50aW1lPTUsc3RvcmVk
PSIyMDI0LTA0LTE0IDAzOjIyOjU3Iix3b3Jrc3BhY2VzPXt7bG9jYXRpb249Im1haW4ubHVhIzE1
Iix3b3Jrc3BhY2VfaW5kZXg9MX0se2xvY2F0aW9uPSJzX3Nob3AubHVhIzM4Iix3b3Jrc3BhY2Vf
aW5kZXg9MX0se2xvY2F0aW9uPSJzX2RyYXdlci5sdWEjMSIsd29ya3NwYWNlX2luZGV4PTF9LHts
b2NhdGlvbj0ic19ib29rLmx1YSMzOSIsd29ya3NwYWNlX2luZGV4PTF9LHtsb2NhdGlvbj0iZ2Z4
LzAuZ2Z4Iix3b3Jrc3BhY2VfaW5kZXg9Mn19XV1sejQABAAAAAMAAAAwbmls
:: [eoc]