-- Aseprite Lua: player + NPCs + portraits + extras
-- Run: aseprite -b -script scripts/generate_sprites.lua

local function newSprite(w, h)
  local s = Sprite(w, h, ColorMode.RGB)
  app.activeSprite = s
  return s
end

local function clear(img, w, h)
  for y = 0, h - 1 do
    for x = 0, w - 1 do
      img:drawPixel(x, y, app.pixelColor.rgba(0, 0, 0, 0))
    end
  end
end

local function P(img, x, y, r, g, b, a)
  a = a or 255
  if x < 0 or y < 0 then return end
  img:drawPixel(x, y, app.pixelColor.rgba(r, g, b, a))
end

local function fillRect(img, x0, y0, x1, y1, r, g, b)
  for y = y0, y1 do
    for x = x0, x1 do
      P(img, x, y, r, g, b)
    end
  end
end

-- Draw a 16x24 character into img at offset (ox, oy)
-- face: 0 smile, 1 flat, 2 off (eye lower 1px)
local function drawChar(img, ox, oy, bodyR, bodyG, bodyB, headR, headG, headB, face, walkFrame, dir)
  -- shadow
  fillRect(img, ox + 3, oy + 22, ox + 12, oy + 23, 0, 0, 0)
  for x = ox + 3, ox + 12 do
    P(img, x, oy + 22, 0, 0, 0, 50)
    P(img, x, oy + 23, 0, 0, 0, 30)
  end
  -- legs
  local legOff = 0
  if walkFrame == 1 then legOff = 1 end
  if walkFrame == 3 then legOff = -1 end
  fillRect(img, ox + 4, oy + 16, ox + 6, oy + 21, 60, 50, 80)
  fillRect(img, ox + 9, oy + 16, ox + 11, oy + 21, 60, 50, 80)
  if walkFrame == 1 then
    fillRect(img, ox + 4, oy + 16, ox + 6, oy + 21, 0, 0, 0)
    fillRect(img, ox + 3, oy + 16, ox + 5, oy + 21, 60, 50, 80)
  elseif walkFrame == 3 then
    fillRect(img, ox + 9, oy + 16, ox + 11, oy + 21, 0, 0, 0)
    fillRect(img, ox + 10, oy + 16, ox + 12, oy + 21, 60, 50, 80)
  end
  -- body
  fillRect(img, ox + 3, oy + 10, ox + 12, oy + 17, bodyR, bodyG, bodyB)
  -- head
  fillRect(img, ox + 3, oy + 2, ox + 12, oy + 10, headR, headG, headB)
  -- ears/species hint for animals - small top nubs
  if headR > 200 and headG > 180 then
    -- rabbit ears
    fillRect(img, ox + 4, oy + 0, ox + 5, oy + 3, headR, headG, headB)
    fillRect(img, ox + 10, oy + 0, ox + 11, oy + 3, headR, headG, headB)
  end
  -- face
  local eyeY = 5
  local eyeY2 = 5
  if face == 2 then eyeY2 = 6 end -- off: one eye 1px lower
  if dir == 0 then -- down
    P(img, ox + 5, oy + eyeY, 30, 30, 40)
    P(img, ox + 10, oy + eyeY2, 30, 30, 40)
    if face == 0 then
      P(img, ox + 6, oy + 8, 200, 80, 100)
      P(img, ox + 7, oy + 8, 200, 80, 100)
      P(img, ox + 8, oy + 8, 200, 80, 100)
      P(img, ox + 9, oy + 8, 200, 80, 100)
    elseif face == 1 then
      P(img, ox + 6, oy + 8, 80, 60, 70)
      P(img, ox + 7, oy + 8, 80, 60, 70)
      P(img, ox + 8, oy + 8, 80, 60, 70)
      P(img, ox + 9, oy + 8, 80, 60, 70)
    else
      P(img, ox + 6, oy + 8, 200, 80, 100)
      P(img, ox + 7, oy + 8, 200, 80, 100)
      P(img, ox + 8, oy + 8, 200, 80, 100)
      P(img, ox + 9, oy + 9, 200, 80, 100) -- mouth 1px off
    end
  elseif dir == 1 then -- up: no face
    fillRect(img, ox + 3, oy + 2, ox + 12, oy + 6, headR - 10, headG - 10, headB - 10)
  elseif dir == 2 then -- left
    P(img, ox + 5, oy + eyeY, 30, 30, 40)
    if face == 0 then P(img, ox + 4, oy + 8, 200, 80, 100) end
  else -- right
    P(img, ox + 10, oy + eyeY2, 30, 30, 40)
    if face == 0 then P(img, ox + 11, oy + 8, 200, 80, 100) end
  end
end

-- Player sheet: 4 dirs x 4 frames = 16 frames, each 16x24. Layout 4 cols x 4 rows
local pw, ph = 16 * 4, 24 * 4
local ps = newSprite(pw, ph)
local pimg = ps.cels[1].image
clear(pimg, pw, ph)
for dir = 0, 3 do
  for frame = 0, 3 do
    drawChar(pimg, frame * 16, dir * 24, 100, 170, 220, 250, 220, 190, 0, frame, dir)
  end
end
ps:saveAs("public/assets/sprites/player.aseprite")
ps:saveCopyAs("public/assets/sprites/player.png")

-- Player portraits: smile + real face, 32x32 each side by side
local port = newSprite(64, 32)
local po = port.cels[1].image
clear(po, 64, 32)
-- smile portrait
fillRect(po, 4, 4, 27, 28, 250, 220, 190)
P(po, 11, 14, 30, 30, 40)
P(po, 20, 14, 30, 30, 40)
fillRect(po, 12, 20, 19, 21, 200, 80, 100)
-- real tired face
fillRect(po, 36, 4, 59, 28, 240, 210, 185)
P(po, 43, 14, 30, 30, 40)
P(po, 52, 15, 30, 30, 40)
fillRect(po, 44, 21, 51, 21, 100, 80, 90)
P(po, 42, 18, 200, 160, 160)
P(po, 53, 18, 200, 160, 160)
port:saveAs("public/assets/sprites/portraits.aseprite")
port:saveCopyAs("public/assets/sprites/portraits.png")

-- Named NPCs: 7 npcs x 3 faces, each 16x24. Grid: 3 faces per row, 7 rows
local npcs = {
  { name = "afu", br = 200, bg = 160, bb = 100, hr = 180, hg = 130, hb = 70 }, -- dog
  { name = "yuanyuan", br = 255, bg = 200, bb = 210, hr = 255, hg = 230, hb = 230 }, -- rabbit
  { name = "dabao", br = 160, bg = 110, bb = 70, hr = 180, hg = 130, hb = 80 }, -- bear
  { name = "mimi", br = 255, bg = 180, bb = 100, hr = 255, hg = 160, hb = 80 }, -- cat
  { name = "fu", br = 200, bg = 220, bb = 160, hr = 230, hg = 210, hb = 140 }, -- deer
  { name = "twinbirds", br = 100, bg = 180, bb = 220, hr = 255, hg = 220, hb = 80 },
  { name = "gui", br = 100, bg = 150, bb = 90, hr = 120, hg = 160, hb = 100 }, -- turtle
}
local ns = newSprite(16 * 3, 24 * 7)
local ni = ns.cels[1].image
clear(ni, 16 * 3, 24 * 7)
for i, n in ipairs(npcs) do
  for face = 0, 2 do
    drawChar(ni, face * 16, (i - 1) * 24, n.br, n.bg, n.bb, n.hr, n.hg, n.hb, face, 0, 0)
  end
end
ns:saveAs("public/assets/sprites/npcs.aseprite")
ns:saveCopyAs("public/assets/sprites/npcs.png")

-- Twin birds beak anim 2 frames 16x16
local tb = newSprite(32, 16)
local ti = tb.cels[1].image
clear(ti, 32, 16)
-- frame 0 closed
fillRect(ti, 2, 4, 13, 12, 100, 180, 220)
P(ti, 5, 7, 30, 30, 40)
fillRect(ti, 10, 8, 12, 9, 255, 100, 80)
-- frame 1 open
fillRect(ti, 18, 4, 29, 12, 100, 180, 220)
P(ti, 21, 7, 30, 30, 40)
fillRect(ti, 26, 7, 29, 10, 255, 100, 80)
tb:saveAs("public/assets/sprites/birds.aseprite")
tb:saveCopyAs("public/assets/sprites/birds.png")

-- Extras x5, 2 frames each, 16x24
local ex = newSprite(16 * 2, 24 * 5)
local ei = ex.cels[1].image
clear(ei, 32, 120)
local colors = {
  { 200, 140, 80 },
  { 160, 100, 60 },
  { 220, 160, 100 },
  { 180, 120, 70 },
  { 140, 100, 50 },
}
for i = 1, 5 do
  local c = colors[i]
  for f = 0, 1 do
    drawChar(ei, f * 16, (i - 1) * 24, c[1], c[2], c[3], c[1] + 20, c[2] + 20, c[3] + 10, 0, f * 2, 0)
  end
end
ex:saveAs("public/assets/sprites/extras.aseprite")
ex:saveCopyAs("public/assets/sprites/extras.png")

-- Sunflower HUD petals sprite sheet 16x16 x 14 (12 petals + center + seeds)
local sf = newSprite(16 * 14, 16)
local si = sf.cels[1].image
clear(si, 16 * 14, 16)
for i = 0, 11 do
  local ox = i * 16
  fillRect(si, ox + 4, 2, ox + 11, 13, 255, 210, 50)
  fillRect(si, ox + 6, 0, ox + 9, 15, 255, 200, 40)
end
-- center
fillRect(si, 12 * 16 + 4, 4, 12 * 16 + 11, 11, 180, 120, 40)
-- black seeds center
fillRect(si, 13 * 16 + 4, 4, 13 * 16 + 11, 11, 40, 30, 20)
for k = 0, 5 do
  P(si, 13 * 16 + 5 + (k % 3) * 2, 5 + math.floor(k / 3) * 3, 20, 15, 10)
end
sf:saveAs("public/assets/sprites/sunflower.aseprite")
sf:saveCopyAs("public/assets/sprites/sunflower.png")

-- UI dialog panel 320x48
local ui = newSprite(320, 48)
local uiImg = ui.cels[1].image
clear(uiImg, 320, 48)
fillRect(uiImg, 0, 0, 319, 47, 40, 30, 25)
fillRect(uiImg, 2, 2, 317, 45, 250, 240, 220)
fillRect(uiImg, 4, 4, 315, 43, 255, 250, 235)
ui:saveAs("public/assets/sprites/dialog_panel.aseprite")
ui:saveCopyAs("public/assets/sprites/dialog_panel.png")

print("sprites generated")
