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

1332 lines
42 KiB

6 months ago
picotron cartridge // www.picotron.net
version 2
:: gfx/
:: map/
:: sfx/
:: art.lua
--[[pod_format="raw",created="2024-03-31 01:52:08",modified="2024-04-29 15:31:52",revision=710]]
6 months ago
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)
add(collider_renders, object)
return position.x < object.right and
position.x > object.left and
position.y > object.top and
position.y < object.bottom
6 months ago
end
:: cabinet.lua
--[[pod_format="raw",created="2024-04-03 19:46:51",modified="2024-04-23 02:36:18",revision=694]]
6 months ago
Cabinet = {}
function Cabinet:new(x, y, gaps)
local c = {
x=40,
y=10,
drawers = {},
shelves = {},
hover_plant = nil,
height = 4*(gaps+16)
}
6 months ago
-- 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
6 months ago
:: 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
6 months ago
:: fairy.lua
--[[pod_format="raw",created="2024-04-03 17:32:32",modified="2024-04-23 03:08:39",revision=432]]
6 months ago
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(10*t()) % 2 == 0 then
6 months ago
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:update()
6 months ago
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
if btnp(4) then
local glow = Glow:new(self.x, self.y)
glow.start_color = 7
glow.end_color = 12
add(animations, glow)
end
if btnp(5) then
local glow = Glow:new(self.x, self.y)
add(animations, glow)
end
6 months ago
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
NC0yOSAxNzo1MDoyMSIscmV2aXNpb249MTI4Nl1dbHo0AGAeAAAZZwAA8Rp7WzBdPXtibXA9cHh1
6 months ago
AEMgEBAE8PAsZmxhZ3M9MCxwYW5feD0wLjM3NQwA_wJ5PS0wLjEyNSx6b29tPTV9LDoAkCR6cAoP
HU8eCgcAcD8ODx4KYBoJAP8CDRpQCh8dPw4dClAKDx1fDg0IAAT-Aw8eClAKDl8ODgpQCn4KUJrw
A4sAJqUGOrAKHxMKsAoeBADwAKAaHhqQCgMOEQqQCgMPEgcAPQ4dAQYArw4KkAo_CpBa8AV9ACYQ
Jn0AER1xAP8GYDoPFy46MAo9HxweHxIKMAodbxwPCAACIF8cIAD-ARodPxwODxIaQBpeGmB68ASE
6 months ago
ACJRCAgECQACABIQCAAfGQ4AFh8J9QAmshEfHJAeED5QPhBeAgD-CSBOEE5QLBosYDwaPFAcEAog
HIAa0ArwOWIAJtQDLxwwLlAuMC5QPhA_BACRYC4QLoAeGh6QBACfCgAegB4aEB6QaAAl8DHIZATw
-7X-Dw-wG47wOPIa-hXyEv4G8iSgEv8YF-4Z-Q-_D-0dAoAC-RX_Hv0M-hr9FQJwAv0O-ib9CP4l
7T6dDgDwBAb_MP0E-juNAnACjVf_Od3_QH0LAKIH-j_9Dx-_QRdNDgBhQJ0c-kIHDQBG-kJtPAwA
VA0PFj1MDwCGB-5CG3z_QloMAC9BegsALhdqWgBHCg0KLQ8ALwdNDQACP2z_Qw0AHj9c-kQNACs-
TP5FDQAzOB1vDg8ALw2JDQAKMjz_Rg0AKHkHDgAPGwAHHJknAARPAD49SQegAA8NALcv-kMMABpH
HV8LDQ8AKA14DQAXiFkALB14DQBUXO7H-igPALQl594bXK5Hvif_JRMA8QEgV94Xbgc_G1x_N-4D
J-4iGADxBC1o-htXfieeF54bXF4n-ggn-iAYAPMGbRj_GEduZx4nfheOG1xOF-4MJ-4ergDzAxRH
XleeJ24XfhtcPhf_EDf_GhkA8wYRN15H-gIHbhduG1wuF273A65H-hUcAPQHCPcE-gcXXhdeG1we
F043-gI3rlf_EDEB8wkBZz5X-hEnThdOG0weF04Xbke_N85H-gwgAPEMTsdOV-4Hx04XPhc_G1wX
ThdeJy43vkfeN-4IIgDxEJ0uJ26n-gdXvhc_Fx4dFy4LbAc_J14XfifuN95n-gEkAPIKrY43-gmH
-ggHDj1OXA4Hzge_R85H-gD3ANcA8Ai9Pj0u-QCn-RcuHTzuFx6tPmeeR-4NbawE0FIevQ4HHv0H
V35n-ganBHD9gAc9nofOvQRA-ZiOzQcAF64FAPsDgAL9rQKQAv2rArDyq-D----hZwVVMTQuNjJo
BSE0NHYFAWkFHDHRBVD-FAHUHgIAsAS5BB4ECT8PGT0JCQAanQYAMQ8VDggAhwwOBLkEDA7UAwAf
7OQFIp8gIAT-FBH0Dh4DAALANPkGNB40CX8POX0JCQAxjRmNCAAv-QQHAAsyDxUOCQAeDAgAf-kG
NAwO9A4EABI-HvwO1gAlctQPFPAB1A4EAP8SxB7wAcQO8AK0HvACpB7wA5Qe8AR0LvAFVC7wB27w
--_rZgAl-wn5MCD6CoD5BND6APAB2fAC2fADufD---xwBy-zATrzGP4V8xL_BvMj0BP-GxVwB2Mc
A7AD-RNwB2UUE5AD-QxwB1MDkAP9BHAHQwOQA21wBwALAAZwBwIOAANwBwANAARwBwIMAAVwBwIo
AAP6Bg8NABU-gAN9DQBFA2gAAVUHDw0AHAFIBw8NACkBfwUPDQBdAUUHDw0AKQ5bAA8NAMEv-kMM
AAw-oANdDAAsA3EHAQ4AGCZwBwESAB0hbwcBFwAdHG4HARcAD20HAQEZAA9tBwEBGQAPbQcEAeQA
D20HBQImAQ9tBwcBIAAPbQcKTwOQA31tBw1PA5ADjW0HCE8DkAOdbQcDAKkEGVBtBwASABJ_bQcA
CwAwlo7NBwAQrAUA8B6qE6AD-VTzAv0U8wOtE8AD7fMmTfMK8AJTrfMD8AOj8AAjPXPwJkPwIqPw
NDOGByv-ln4FKC0zhwcWMn8FHDLPBfAK8P_iKvANCgMK8AwaAwrwCEoDAArwCAoDIAgAIwU6CABQ
CgMQAwACAGQa8AQKAAMCAB8KDgAKRAE6AAMCAPAOSsAK-xIBCsAqzirgCs4K8AEarhrwAgquCvAD
Go5VAGyOCvAFqqDHAGQ1LjE1ODMBAATQAFcxNC44MBcAAdoAHjPaAMAAOvAMCh8TGvAIOi7VAPAi
HgAuOvAFCi4AThrwAiouJD4K8AIKFA4ADgQQHgAa4DoALgAEDxQzCvAACi4AHiQNPgoAUQAuEAMk
CgDgICQQFBAq8AAKHhQANCPEAKBeJBAa8AEKfhQeSgAhLkAIANIaYBQQSuAK7xgK4ArsBAChGswa
8AAKzArwAQUAfxqsGvACypDtADvwDl1K8AZaLxMK8AYKTgQeCvAGGh4TBBMq8AUKIA5DYgHwByAe
BD4a8AMKLhAELgAOCvADCkMkEwCxABAwzgBAAgoOQ88AsAIKDgMODxQuFA4AnQEwEB0Q1gDTBAog
DRAUEDrwAQrGCgUAIBqmLgAQpiYAEIZhABCGKQIfhsgBQD----NRADbwJ0BABPD-WiIfGPAmQl7w
IEKu8BtC-gHwFjL_AiIe8BBC-gFCXvAKQv4CMq7wBUL_AkL_APABIggA8D0G4P4BQn54vtDOMk6I
Xhi_wH5CTkjuGK7ATiJ_KD74Ab6w3pi_GA4YvqAeAp447kgeGM6QHgIHjggeGK44XgjugB4CB34Y
Lhh_KH4YDQDQDw8HbghOGE4ofij_AB0AYA1_CE4YHg8A8BoCgB4CHQduCF44bjj_A6AeDQcNbhhe
GC5Y-gIHHcAeHQduyP4DBz0XwBoA8gT_FActNx3ALh0H-g8HPTcNGhcOGABwDS1HHUousBkAkQgf
Dh1HLWoe0BkA8AgFbBctJw5KDvABHh0H-gA9XC0XTirwBBwA8AXOLTcsLRd_8AcuHX4HPVctJ37w
CxgAYD4HLQcbNw8AEA4PAEAHPQdbDQDxHRIeLSd7J37wFR4NR3t_8BguDScdW17wGz4HHRcrXvAf
LheO8CKu8CZu8CseqQQf5CcKCRYxqAQfNLUBHTBu8Am1ATHO8AO1ASEC4LQB8iIIwP4BQv4OsM4y
zri_kH5CfpheWL6ATiKeOG6oDhjOcO44HnheGC4Y3nAeAp54rig_tAEApwFRnihOKN4NAKMIXghu
GE44zhegtQGQbhgeKC5IzkegtQHwAwdeOF6I3negHgIdF46I-gKXsCEBsxf_EMfAHh0n-gunpwFC
F-4Ht6gBhif_AycfDmctqwFUJ943XBeuAUY3jmdsrQFGN06nfK4BKPcBrQEWx60BF4esARlHqwEv
Fy2rAV7wJtlvG-AZ-gjwEv4O8A3_FPAI-hjwBv4Mem7wBO7a-gDwA35q-g7wAv4f8AD_IeAOCv4H
ev4ACADxIABqXgr_AtAOCv4BGn4a-gPQCv4EGk4K-gbACv4GGh4K-giwCv4IGv4JsAoOCv4hBgD2
CiKgHgr_EXqOoA4K-gPq-gGgDgquev4QoA4jACAgwAYAQBoHHgdlAPAHDvcC4AoOCk73A-8PB9AK
Dgoe-Qb3BhMAcA73Bv0I0BoQABAH5wUg9x0GAPEK-R7gCi73Gx7wAF6H-gHXLuD_IfAA-gKA-poE
T----30pASbwLxc-G-ApfvAj3vAe-gPwGP4AKl7wEv4BOo7wDv4BOt7wCu5K-gPwB846-gnwBZ46
-g3wBW4q-gAq7vAD-gVaJwFh8AH_AjpuCQDwAw4KziqeCv4D8AAOCu46Xgr_BAoAgf4DOh4K-gXg
OAHQBuAK-hYqftAK-hFKrvsAUf4LOv4BHgHwBQZK-gXAHgr_AUr_CdAOCt46-gg3QABhrir_Bqfg
TQFRDPcB8AAsACD3CC8Br-4A9w7gDgqu9xVQAXEjYBBAABv1PwAnLTQMCTQxLjSREB8zPwB4DucG
Dz0ACh81uwAsDz8A-3UPbxsaDzoA---------wf9YmBgBP8eD-8VEv8eI-8VKP8eEf8VNv8eBv8V
Pt8e-xVGfx7-FUo-Hv8VDPAY-goPHv4B8DD_BQU_8Dw_BZ4VDvBADhWedfA2da71BPAc9QTO9UL_
APU_-gT1Ov4L9TD_HPUY-god-k4d-k4t-kxN-kpdAwBPTf5MPQMABBEtOQAFAwAhDf4pCCQ1DREA
BVkABTIAAmIAQW3_SH0DAP9Yjf5Gnf5Grf5Ezf5C3f5C7f5A-QH_Pv0C-j79A-48-QX_Ov0H-jj9
Cf42-Qv_NP0N-jL9D-4w-RH_Lv0T-iz9Ff4q-Rj_Jv0b-iT9Hv4g-SH_Hv0k-hr9Kf4U-S7_EP00
-gj9Pd79GXoBIw75CA8-AP9VDi4DD3kAHP8LcP8SGPAc-jDwCv488AL_QPAF-jbwF-4c8GlWAC--
Be4-Hf4d8Ar_BT3_Ez2_8AL_Lj3eYAAz8AYSDx0AHgAO4F8e8DP-EgZ-Hp8SAA4CAP8d8BZNDx5t
Di0OHQ7NDlwO-QbwCo1MfQ79Al6tDh0eHQ6d8AL9QPAF-TbwF-2EACrxD6cPHvBPDiAO8EcOIA4Q
DvBJDnAO8Cg_8BIO8CheIP8A-xYtXv0n8AqdPq1ufXL9DPAC-QEy-QVyXVL9AvAF-SJyvfAX-RZS
hAApESaEAPA1EA7wTw7wSA4QDxIgDvBIHg1wDvBDDUAdIA4ADcBN8DQeHQANII0u-QwQTfAVTQAO
zU79F-AKnQ4NHj0SXU6Nkm0S-QGdAP8KIv0Ekk1y-QHwBZ0S-RUSHgIuEq3wF-0VYqMAKfAK-1gv
HvARFvApTvBDDxJQHgc_TfA9bW79Co0A8RotMh0SjU5NQi1CbR698Ap9wl0uTTIN0h0eAg1CrfAC
zYJdQm2STSIeIpUAjyL9B0Itcj4ilQAu8EhzHx5wHvBGDvAUJvAdLvAdJvAfDvADDvBMPvAJFvAi
HlAu8EYeMC8SDg2QHvADFvAiDVAOLQ4NDk3wPc0OHSJNYl0_AE3wFaINIo0Osg1iLV4ibSAi8AS-
APMREi0O8gJegh1C8AKNsi49cg0ukk0CXlK98AWdMl0CvXLAAH89Mk1SHYJtxQApoZom8E0m8K4W
8EYFAvFLQBbwKjIPEvAJDvApDQDSLQBSMCIOMELQMvATfaJNYh0OAh0yAB0ugCLwABJQsg4iLdIe
Ig3yAy49EELwAfIBTkI-EyItEj5SPvIJ8AKN8gs8Yjw9cg4yHVI9uwD-AhKtci0iPgIOUj0eTfAX
PfIKvAAq8Ej6LxbwTS7wrQYF8CIGgAZgPx4wBvANMvAbQkBdYDKABQaQQsAS8AQPEgDSHF3yA7BS
wDLwAC0M8gBdcgwSHHIMMjBC8ABSEKItEgziPRIMTxMtUityDGLJAP8eTUI7EiviPfII8AEMIgwS
HOI7clsiWz2yW2LwBTzyFwzyARwyLPAXEhzyChyywwAo8xMaTx6QHvC7LgAvFvAhXqAO8AMuMC3w
Nh4QDvBEHoAOAE6w3QD0BzAeAA4QDjAGXvAHMsAy0F5QQmAOAB7mAPEPQrB_oi4CDjIOQn5SsFLA
sjAeB14CXvIDDgduYg8S6ADA4o4MYj8ToiuOEmsy5AAg4m7jAPESYisifvIG8AFyG1JOIltSWyI7
XoKLYvAFUjvyAnvyAgtS5wAf8uMEKfE5OAUwBfBLNfBLRfB7Px7wHhXwGq4wBvAKBvAIHxOQTaAu
F25gBuBeoBWgLQINsDKALgeeIELAjjA_wELAQnAeB66CLgIOIl4H2gDggi0A-gPiHgeeAg0yPhLY
APAdws5SPRJtAt4CbTINYvABEi1yrm0SLWItAp5STaLwAXIdMn4CbVJdIj1ego3ZAP4BPQ7yAd2y
DUKd8BdyTfIETToFDzIHGA86AP------------8kAY4d-wAeFzbwCgcwBvALBhAG8AwFAA-wFwsG
MAbwCBZQFvAFBx8ccAbwAwcvGi8cED4G8AEHbxoeTQbwAAfdBQBzHQutBvAABgcA-wgtC50G8AEG
vQbwAwadBvAFFl0W8AhWwBIVJQAuEfF6--r2BvA6Bv8aBAbwORb_BAbwOBb_BQbwNxb_BhbwNRb_
CAbwNBb_CQbwMxb_CwbwMRb_DBbwLib_DhbwLBb_EhbwKCb_FBbwJhb_FxbwJBb_GRbwISb_Gxbw
Hxb_HxbwHBb_ISbwGRb_JBbwFxb_JhbwFRb_KQbwFAb_KhbwEhb_KxbwEQb_LQYGAHYW8A8G-i8G
BgBPMAbwDgYAmVEwnxjwAAkAUw0GUAYNDAASnQgAEGD8ARkDCgASthAAE5AYAE_gBvACCAAII2ZA
EAA-UAYwCgAdUFbwA-Yw8gEfYy8CFB8yXQMnDzoA-----------------9nwI2CABPD-JL8U8ED_
AvA8-gbwOT8V-gTwNz3_BfA1Tf4H8DNN-gjwMk3_CvAwTf4L8C9dBQD4AE3_DPAuXf4N8C1N-g3w
LgUAMwzwLwUAMQsPDwcAEDwmAPAMCTzwLBxN-gg88C4cPf4HLA8X8DFN-gULHAsMCQDwrAQMCwwL
DPAzTb4tLg8ZHAsc8DNdjj0uGjzwNV1ObR4qPPA2-QFKPPA3zXos8DkKTdoc8Dv6AwzwO5oMivA7
amx68DpafHrwOVofHAxpavA4WqlaOfA0WslKOfA0SgDpKknwMyogmS8QKQpZ8DQKSEn4BPAw_BHw
LmgPCvgM8CtoFygn_AfwKfgDNzgXqPAoJ-gMB7jwIgf4EieI8CH4FgeI8CD4GAd48CD4GSc48B-4
IfAf_CLwHfggBxgGAPEHFxjwHPghByjwG-gl8Bv4JvAaKAn4IgYA8CMOCfgE8BoYCfgOGSgJ_ADw
GRgJ_A8ZGAmYB1jwGAgZ_BAJKAmIB1jwGQn4ERkoCRgJWBkAVAn4Eik4CwDxAhQZGBlYF1jwFwn4
FRkIGWgHCwCBGBno8BYJ_Bk_AGQUGfgVGRgLAFAUCTgZ6AkAEBpyAIITGfgaGYgXOAkARvgA8BII
ABEbiACBEQn4HAmoB0gJACQZmAkAsPgB8BAZ_BspqAc4CQCmHBm4BzjwDwn4HQkAocgHGPAQCfgc
KdhOACApyGUAMBOpuH0A8AEPSXgZqPAVGfgOGbgZiPAXQgDyAQggGPAaKfgbGQjwHyn4HAkHABAZ
BgDwJBo5DwzwHin4GFkG8B8Z_BdpLfAdGfgUaQYJTfAcGfgReQZt8B4J_A6ZbRXwHhn4CpmNJQgA
UAapFm1VCQDyQgK5Fn2F8B4ZyMkGjcXwHgmYuc3V8B8JWKnd9QLwH8kGzfUFAAXwHpkVjfUN8B5p
rfUPAAXwHQ0ZvfUV8Bvd9RjwGY0FDfUc8Bkt9STwGT0FDQIAovUc8Bgt9SbwFy0QAEMFDfUdEgAG
JACkHvAVPfUo8BQtFRIAhiDwFC31KvASJACFIvASLfUs8BASAAEUAIUQLfUsAAXwD14AABYAmQ8G
8A899SoAFRgAA1gAiw8t9S0ABfAM7wNuLTI5LjEwHTlIMzguNzQ5D5ZDAAEEBPEt---DbxTwRe7w
PD8Vfile8Dhdjile8Dc9DkluCW7wNj0OWe7wNT0OaW4KbvA0HT5p7vA0DU5Z-gDwNG5JBgDwhClu
rxnwNN7c8DQZjvwB8DQZbvwDEB8P8DAZXvwDEBvwMRle-AILACvwMW6c2-Axbozb8DJejJsfHyvw
Ml58iyg78DJebEsIGygnG-AzXlwrOEsfDgcL8DReLB8XGyhLCBsfDivwMx57HxcYCxcPDisYW-Az
DpsPFwsnHw47GEvwMx5LHxdLFx8OSwhL8DM_Ky8XuxYA8CcNTgwLFrsIW-AzPR4s6xgr8DM9DhwA
LKsoO-AzLQ5siyhLHxzwNYxrGFsGDxAfHPA0jADLBi8KAPJJMqyrFgU-EBXwMQwAfKsGG0Ql8DCc
20QVFPAvrMtEJZTwJ4xFixUkRaTwJIwFNBV7JQQF9AHwInwVRCV7JfQBFfAgfAWEBWsl9AMF8CBs
BZQFaxr0BfAgXAoA8UEG8B9cBZQVawoF9AbwHkwABZQVWw8MCgX0B-AeLAAldAUEFTsTGvQH8CEV
BBVkBRQFSgUapAW08B8VChQlRAUUGlQKpAXE8BwVAwpEJSQFpA4A8AYaFQQKdCUEBbQKlAXU8BgV
xCXECoQKAFAFAwrEFQwA8Ark8BYFAwr0FwX0APAVBQr0GBX0APATFfQaCABgEgX0EgqECgDzABEF
9BMKdAAF9ALwDwX0FAsAcA4F9BUKZBALABANCwARdAsAQQwF9BYhADQD8AsLAKEE8AoF9B8AFfQD
CQAQEB0AMgr0IAgAUNQV9BAQGwDyAQgF5AX0CApkIBX0AvAI9AANADIl9AENAIUJCkQQFRQl5A4A
QQAVRAUOAGAV9AgKRAA6ATAI9AEbAB80DQACwRX0DQAF9AXwCPQDBQsAMwTwCQsAUAQq1PALDACA
DCAaBBq08AwMAMAICiQQCjQalPAN9AJjAKAkAApUCoTwDvQCVwAADgBAGmTwDw4AkgoKJBVUClTw
EA0AYTQFVBo0BQ4A8QQEdfQBCjQFZAokBfAR5FVkBfQADwCBFAXwEvQNBeQNAHAEBfATBfQMHACz
JAVkCgXwFAX0CxUOAMHwFQX0DBrkCiQFClQNAHALOvQCevAXaQBgFFpE6-AYCgBSZBoU6xYLAIB0
CgTbBivwGaUAVIQK6xYbFwBBywYrBg0AUQkKdArbDQASFyUAAA0AMQvwGAwAhGs-BTsGGwYLKQAx
S2IrDwABUABEVBorgg8AUdS1WuIbDABiGgVkdfIOGADyEhtlbfIOOwYLAhvwGo0CDfISKwYLQvAZ
LfIcC2LwGT0CDQIAEPJIBVLyJfAYLRAAgAIN8h7wFy3ySAUCEAABEgAwFT3ySAUUEhIAAEgFEPJI
BQIQADACDfJIBRDySAUnAg0UAGUQLfIu8A9cAJ8CDfIk8A498i4oBSwPoAknD4gK-yAg-xTEGvEB
fPQ--gEE-xU9BP4BBP08DgcAIDseBwBBLfQ3LggATwT_NQQKAP80BFIBIfQ4YgExHfQ6cQFyDfQ9
-gH0P70wMf--6JQBH-2TAf92H1z2GyID5gnyKxjfFvBALr8PHvA9Lu0e8Dse-QIO8Doe-QMe8DkO
-QMfEQ4N8DUcHs18DhzwMRwAHA7dDA0cDVzwMUwKAPYGHA0MDgzwMQwgHv0BDD0MDvA2Dv0IBgBg
LU4dTm0uDwCwBR4NDvA3Dl0O-QAIAEBNHv0BIQBRPR49Ds0qAFAeTQ69HgkAUA5dDp0KLQDwDR4d
Pi0OjQou8DgOTU6dCg7wOR79BA7wOg5NPq0HAPGALQ5tDm0e8DsOHR5NHl0_8DoeHX5NHh0u8Dk_
QH5NHvBBHs0ODQLwPx7NDxhi8DourQtyG-A5Dp0bYjvwNAs_nQtiGw0r8DICCw0enRtSGz0CC-Aw
Egu9G1IbXQIL8CwNCyIbrQtSG30CC-AqHQsyG30rQhudAgsC8CgdC1IrPRtiC70bAvAnHQtyW2Ib
zQsLAPIA8gQb3RvwJi0L8gMb7QILCgCwC-0AG-AlPQvyAhsKAPAEAggX8BA9C-IBG-0CC-ACCDfw
Dg4A8QAL-QML8AMIN-ANPQvyABsOAEAYR-ALDgBQC-0CDg0eAGAHGDfwCU0SADFNDr0TAEwYBxgn
EwBIAFfwCBIAYQQIEFfwBxIAIz0eEgByIEcALxXwAxUAIg7NFQA5MEcpEwCwAvADCDA3KQ3wAl2U
ABUtFQBwQAdJHfABXbcAUB0ezQ4bPABBWa0gvREAIQ7dEQBJIEn9DBAAMCn9DhAA0hIO3Q4CC-AK
-Q8L8gQMADoL-Q4MABEFCwBUDI0g-QENAPQKDW3wBBvyBc0eAgvwDk3wBQvyBs0OEgvwKAkAcB0O
vfIFvR4KAPACXhBObcLNDiIL8CANAG69ct0LAPEMGmVuC-0RHiIL8BYVDkVOEC4L-REOMgvwFYWe
CgDwTfAWhU4AHhAL-RAeIvAXhW4tC-0PHjIAC-AV1R0Q-REOQivwFLVgC-0NLjJL8BNlECVgCxL9
CS6SK-AShYALMv0EPtIb8BFVsAti3T7yAhvwEFWwC-ICPvIGK-AOCwAiHRsIAEAeG-ANCAAgHwsI
AKbyIBvwDFWg8iILBwBgsPIhG-ALJABnIBvwC2WgCAA-C-AMCAABAEwAAAgAYR4L8A9VoGwAAQgA
EByHAPAAoAvyGxvwEUXAC-IZG-ASCABAGBvwEwgAQBcb8BQIAEEVK-AVCAA-C-AXCAANITXQCABv
FkXgC-IUCAAUIxMbCABPCxLwFQkADR8bRAAAYvAA8hTwFwcAHwPyBBUPyAgnDzoA------------
---3UG09NX19
6 months ago
:: gfx/.info.pod
b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTI5IDAxOjE0OjUxIixzdG9yZWQ9IjIwMjQtMDMt
MjkgMDE6MTQ6NTEiXV1sejQABAAAAAMAAAAwbmls
:: library.lua
--[[pod_format="raw",created="2024-04-10 00:24:20",modified="2024-04-29 16:05:11",revision=200]]
6 months ago
plant_descriptions = {
[-1]={{"i don't know what that is. where did you find this?"}},
6 months ago
[13]={{"these are chives. are we sure this is for alchemy?"}},
6 months ago
[14]={{"this is foxglove"}},
}
ingredient_descriptions = {
["reagent green"]={{"blah blah reagent green blah blah"}}
}
6 months ago
function get_conversation(plant)
local id = plant[1]
return plant_descriptions[id] or plant_descriptions[-1]
end
6 months ago
book_pages = {
[1]={
"hester's big book of recipes! alchemists only! dangerous recipes!",
"format: \nrecipe notes \n \ningredient 1 \ningredient 2 \ningredient 3"
},
[2]={
"\nBarthow's Encyclopaedia of Botanicals and Components",
"A comprehensive reference to help identify all ingredients an alchemist needs."
}
}
6 months ago
:: main.lua
--[[pod_format="raw",created="2024-04-02 02:59:37",modified="2024-04-29 15:34:08",revision=1153]]
6 months ago
-- 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")
6 months ago
include("s_book.lua")
6 months ago
DEBUG = true
scene = {
before=function() end,
draw=function() end,
update=function() end
}
previous_scene = scene
animations = {}
script = {}
collider_renders = {}
6 months ago
function _init()
vid(3)
6 months ago
change_scene(shop_screen)
6 months ago
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)
for r in all(collider_renders) do
rect(r.left, r.top, r.right, r.bottom, 9)
end
while #collider_renders > 0 do
deli(collider_renders)
end
6 months ago
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
6 months ago
:: 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-23 02:42:38",revision=126]]
6 months ago
BookScene = {
extension = 0,
behind = nil,
inset = 60,
}
6 months ago
function BookScene:new(background, pages)
c = {height=0, behind=nil, background=background, pages=pages, index=1, fairy=nil}
6 months ago
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
6 months ago
self.fairy = self.behind.fairy
6 months ago
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
6 months ago
self.fairy:update()
6 months ago
end
function BookScene:draw()
6 months ago
self.behind:draw(true)
spr(self.background, 20, 135-self.height)
print(wrap(self.pages[self.index],80), 36, 135-self.height+10, 20)
print(wrap(self.pages[self.index+1],80), 130, 135-self.height+10, 20)
if self.fairy ~= nil then self.fairy:draw() end
6 months ago
end
6 months ago
:: s_conversation.lua
6 months ago
--[[pod_format="raw",created="2024-04-05 14:55:45",modified="2024-04-14 02:34:19",revision=129]]
6 months ago
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-29 15:59:50",revision=379]]
6 months ago
DrawerScene = {
extension = 0,
behind = nil,
inset = 60,
contents = {
title = "reagent green",
small_graphic = 128,
large_graphic = 129,
},
fairy = nil,
interior_collider = {},
contents_collider = {}
6 months ago
}
function DrawerScene:new(drawer)
c = {extension=0, behind=nil, inset=60}
if drawer.size > 16 then c.inset=30 end
6 months ago
setmetatable(c, self)
self.__index = self
c.interior_collider = {left=c.inset, top=0, right=240-c.inset, bottom=c.extension}
c.contents_collider = {
left=120-96/2,
top=10,
right=120+96/2,
bottom=10+96,
}
6 months ago
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
self.fairy = self.behind.fairy
6 months ago
end
function DrawerScene:update()
self.interior_collider.bottom = self.extension
if (btnp(5) or btnp(4)) and not collides(self.fairy, self.interior_collider) 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
if collides(self.fairy, self.contents_collider) then
if btnp(4) then
add(self.behind.tray, {self.contents.small_graphic})
end
if btnp(5) then
change_scene(Conversation:new(ingredient_descriptions[self.contents.title]))
end
end
self.fairy:update()
6 months ago
end
function DrawerScene:draw()
self.behind:draw()
draw_drawer(self.extension, self.inset)
spr(self.contents.large_graphic,
self.contents_collider.left,
self.extension - 115 + self.contents_collider.top)
self.fairy:draw()
6 months ago
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-29 17:50:21",revision=430]]
6 months ago
-- 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()
6 months ago
alchemist_sprite = 192
alchemist_bob = 0
customer_sprite = 0
customer_bob = 0
customer_visible = false
door_open = 0
6 months ago
book_1 = {left=10, right=74, top=100, bottom=164}
6 months ago
book_2 = {left=70, right=134, top=100, bottom=164}
6 months ago
shop_screen = {
fairy = Fairy:new(),
tray = {}, -- list of selected ingredients, up to 3?
tray_slots = {}
}
for i=1,3 do
shop_screen.tray_slots[i] = {
left=108+i*32,
right=108+i*32+32,
top=135-4-32,
bottom=135-4
}
end
function shop_screen:draw()
6 months ago
cls()
cabinet:draw()
-- alchemist!
bob(alchemist_sprite, 0, 7, 96, 128, alchemist_bob)
palt(30, true)
palt(0, false)
spr(64, 240-100, 135-49)
6 months ago
palt(30, false)
palt(0, true)
spr(72+flr(2*t()%11), 240-100, 135-52)
6 months ago
-- countertop!
6 months ago
draw_counter(20)
6 months ago
if collides(self.fairy, book_1) then spr(18, book_1.left, book_1.top)
6 months ago
else spr(17, book_1.left, book_1.top) end
if collides(self.fairy, book_2) then spr(20, book_2.left, book_2.top)
6 months ago
else spr(19, book_2.left, book_2.top) end
for idx, box in ipairs(self.tray_slots) do
local ingredient = self.tray[idx]
if ingredient ~= nil then
spr(ingredient[1], box.left, box.top)
end
end
6 months ago
if customer_visible then
bob(customer_sprite, 240-96, 7, 96, 128, customer_bob)
end
self.fairy:draw()
6 months ago
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
6 months ago
function shop_screen:update()
self.fairy:update()
cabinet:update(self.fairy.x, self.fairy.y)
6 months ago
if btnp(4) then
local drawer = cabinet:drawer_at(self.fairy.x, self.fairy.y)
6 months ago
if drawer then change_scene(DrawerScene:new(drawer)) end
6 months ago
if collides(self.fairy, book_1) then change_scene(BookScene:new(007, book_pages[1])) end
if collides(self.fairy, book_2) then change_scene(BookScene:new(012, book_pages[2])) end
if cabinet.hover_plant ~= nil and #self.tray < #self.tray_slots then
add(self.tray, cabinet.hover_plant)
end
6 months ago
end
if btnp(5) then
add(animations, Glow:new(self.fairy.x, self.fairy.y))
6 months ago
if cabinet.hover_plant ~= nil then
change_scene(Conversation:new(get_conversation(cabinet.hover_plant)))
end
for idx, box in ipairs(self.tray_slots) do
if collides(self.fairy, box) then
deli(self.tray, idx)
end
end
6 months ago
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
6 months ago
:: screen_drawer.lua
--[[pod_format="raw",created="2024-04-05 00:59:25",modified="2024-04-05 00:59:26",revision=1]]
6 months ago
:: script.lua
6 months ago
--[[pod_format="raw",created="2024-04-04 01:01:55",modified="2024-04-14 03:09:34",revision=554]]
6 months ago
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)
6 months ago
end, 0.5),
6 months ago
Script.once(function() -- person appearss
alchemist_sprite = 193
customer_visible = true
customer_sprite = 201
return false
6 months ago
end),
6 months ago
Script.len(function(s) -- door closes
door_open = easeTrig(1-(s.timer/s.length))
6 months ago
end, 0.5),
6 months ago
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
6 months ago
:: shop.lua
--[[pod_format="raw",created="2024-04-23 01:22:37",modified="2024-04-23 01:22:37",revision=0]]
6 months ago
-- 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)
spr(64, 240-96, 135-96)
6 months ago
-- countertop!
draw_counter(14)
if customer_visible then
bob(customer_sprite, 240-96, 7, 96, 128, customer_bob)
end
draw_door(door_open)
fairy:draw()
6 months ago
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
:: 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$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTA0LTIzIDAxOjEzOjI4IixydW50aW1lPTUsc3RvcmVk
PSIyMDI0LTA0LTI5IDE3OjUwOjIxIix3b3Jrc3BhY2VzPXt7bG9jYXRpb249InNfc2hvcC5sdWEj
MSIsd29ya3NwYWNlX2luZGV4PTF9LHtsb2NhdGlvbj0iZ2Z4LzAuZ2Z4Iix3b3Jrc3BhY2VfaW5k
ZXg9Mn19XV1sejQABAAAAAMAAAAwbmls
6 months ago
:: [eoc]