̬̬̬̈̬̬̬̬̈̬̬̬̬̬̪쬪̬̬̬̪쬪 >~= wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww      wwwwww wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwDwwwwwwwwwwwwwwwwwwwww@DDD  @DDDD       ̪wwwwzwwwzzzzzwzwwwzwwzwzzzwwzzwzwwzwzwwwzwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww  wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwpwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww̜ ̜ ̜ ̜ ̜ ̜̜wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwpwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww   wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww pwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww    , wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww pwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww         wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwpwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww̙wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwpwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwpwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwpwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww`ffffffffffffffffffffffffffffffwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww`ffffffffffffffffffffffffffffff,"`ffffffffffffffffffffffffffffff""  `ffffffllflllffflfffff  ""`fffffllfflllfllflllllfllffff""033`ffffflffllfffllflffff""03333`fffffllfflllfllfllflfllffff `fffffllfflllllflllllllffff `ffffffffffffffffffffffffffffff  0`ffffffffffffffffffffffffffffff  `ffffffffffffffffffffffffffffff`ffffffffffffffffffffffffffffff PV-- title: radgievtardis -- author: J7 -- desc: short description -- site: website link -- license: MIT License (change this to your license of choice) -- version: 0.1 -- script: lua -- TIC-80: Radgie v Tardis -- Controls: Arrow keys move. Z pick up / attack. X toggle tips. -- -- MUSIC NOTE (IMPORTANT): -- This code will PLAY track 0 as the main rave loop, and trigger a "DROP" by switching -- to track 1 when the Bazooka hits, then back to track 0. -- You still need to CREATE the actual music patterns in TIC-80's MUSIC editor -- (track 0 = main loop, track 1 = drop). The game will still run fine if you don't. --================================================== -- PALETTE MAP (EDIT ONLY THIS IF YOUR COLOURS LOOK OFF) --================================================== PAL = { OUTLINE = 0, -- Background / UI BG = 1, FLOOR_A = 8, FLOOR_B = 7, UI_BAR = 0, UI_TEXT = 12, UI_HINT = 10, UI_SOFT = 13, UI_PANEL = 14, -- Tardis TARDIS_BODY = 9, TARDIS_SHADE= 8, TARDIS_SIGN = 12, TARDIS_TEXT = 0, TARDIS_WIN = 11, TARDIS_LIGHT= 12, -- Attack pad PAD_FILL = 6, PAD_BORDER = 0, PAD_TEXT = 12, -- FX colours FX_FLASH = 12, FX_SPARK = 4, FX_BOOM = 3, } WEAPON_COL = { EGGS = 12, KNUCKLES = 13, GOLF = 15, SHEARS = 2, PAINTBALL = 11, CHAINSAW = 4, AK = 3, BAZOOKA = 10, } --================================================== -- Utility --================================================== function clamp(v,a,b) if vb then return b end return v end function dist2(x1,y1,x2,y2) local dx=x2-x1 local dy=y2-y1 return dx*dx+dy*dy end function sign(v) if v<0 then return -1 elseif v>0 then return 1 else return 0 end end --================================================== -- Game constants --================================================== W=240 H=136 CX=W//2 CY=H//2 TARDIS_W=34 TARDIS_H=58 TARDIS_X=CX - TARDIS_W//2 TARDIS_Y=CY - TARDIS_H//2 + 2 -- Attack pad PAD_W=64 PAD_H=14 PAD_X=CX - PAD_W//2 PAD_Y=TARDIS_Y + TARDIS_H + 6 -- UI bars MSG_H=12 TAUNT_H=12 MSG_Y=H-MSG_H TAUNT_Y=H-MSG_H-TAUNT_H -- "ground" line for win FX (top of taunt bar) GROUND_Y = TAUNT_Y - 2 --================================================== -- Weapons -- Changes requested: -- 1) Swap Bazooka to bottom-right (x=220) so it's more likely last. -- 2) Replace Scythe with Garden Shears (dmg=4) at bottom row (x=180). --================================================== weapons={ {name="Eggs", dmg=1, x=18, y=20, col=WEAPON_COL.EGGS}, {name="Knuckles", dmg=2, x=220, y=20, col=WEAPON_COL.KNUCKLES}, {name="Paintball", dmg=5, x=60, y=20, col=WEAPON_COL.PAINTBALL}, {name="Chainsaw", dmg=6, x=180, y=20, col=WEAPON_COL.CHAINSAW}, {name="Golf Club", dmg=3, x=20, y=112, col=WEAPON_COL.GOLF}, {name="Garden Shears", dmg=4, x=180, y=112, col=WEAPON_COL.SHEARS}, -- was Scythe {name="AK-47", dmg=7, x=60, y=112, col=WEAPON_COL.AK}, {name="Bazooka", dmg=8, x=220, y=112, col=WEAPON_COL.BAZOOKA}, -- swapped to bottom-right } --================================================== -- Radgie taunts (weapon index 1..8) --================================================== TAUNTS = { "Howay then, ya little radge packet!", "SMACK! Hahaha", "Come 'ere yi little dafty", "Get this doon ya sneck!", "Am a pua Gangster me like!", "Here man Dr Who, take this ya nacka!", "Whew thats pua edge that like!", "That was lethal that like!" } --================================================== -- MUSIC (track switching for the Bazooka "DROP") -- Track 0: main loop -- Track 1: drop --================================================== function musicStartMain() -- Start main loop (track 0). If your cart has no music data, it will just be silent. music(0) end function musicDrop() -- Switch to drop track (track 1) briefly. music(1) end --================================================== -- State --================================================== game={ mode="title", -- title, play, attack, winfx, win t=0, -- instruction message (bottom bar) msg="", msgTimer=0, -- taunt message (separate bar, persists until next weapon pickup) taunt="", tauntActive=false, tipOn=true, player={x=30,y=68,spd=1.4,face=1}, currentWeapon=0, usedCount=0, tardisHP=0, tardisHPMax=0, attackTimer=0, attackLen=52, attackWpn=0, shake=0, -- WIN FX tardisDestroyed=false, winTimer=0, debris={}, skel={active=false,x=0,y=0,vy=0,landY=0,landed=false}, -- MUSIC STATE musicOn=false, dropTimer=0, -- counts down while drop plays dropLen=55, -- ~ about a second at 60fps } function resetGame() game.mode="play" game.t=0 game.msg="Grab a weapon" game.msgTimer=999999 game.taunt="" game.tauntActive=false game.player.x=30 game.player.y=68 game.player.face=1 game.currentWeapon=0 game.usedCount=0 local hp=0 for i,w in ipairs(weapons) do w.taken=false w.used=false hp=hp + w.dmg end game.tardisHPMax=hp game.tardisHP=hp game.attackTimer=0 game.attackWpn=0 game.shake=0 game.tardisDestroyed=false game.winTimer=0 game.debris={} game.skel={active=false,x=0,y=0,vy=0,landY=0,landed=false} -- start music once per run if not game.musicOn then game.musicOn=true musicStartMain() else -- ensure we're on main track musicStartMain() end game.dropTimer=0 end --================================================== -- Drawing helpers --================================================== function drawTardis(shx,shy) shx=shx or 0 shy=shy or 0 local x=TARDIS_X+shx local y=TARDIS_Y+shy rect(x,y,TARDIS_W,TARDIS_H,PAL.TARDIS_BODY) rectb(x,y,TARDIS_W,TARDIS_H,PAL.OUTLINE) rect(x+2,y+10,5,TARDIS_H-12,PAL.TARDIS_SHADE) rect(x+2,y+2,TARDIS_W-4,7,PAL.TARDIS_SIGN) print("POLICE",x+4,y+3,PAL.TARDIS_TEXT,false,1,true) for r=0,1 do for c=0,1 do rect(x+6+c*14, y+14+r*10, 10, 8, PAL.TARDIS_WIN) rectb(x+6+c*14, y+14+r*10, 10, 8, PAL.OUTLINE) line(x+6+c*14, y+18+r*10, x+15+c*14, y+18+r*10, PAL.OUTLINE) line(x+11+c*14, y+14+r*10, x+11+c*14, y+21+r*10, PAL.OUTLINE) end end line(x+TARDIS_W//2, y+24, x+TARDIS_W//2, y+TARDIS_H-6, PAL.OUTLINE) circ(x+TARDIS_W//2+6, y+38, 1, PAL.TARDIS_SIGN) rect(x+TARDIS_W//2-2, y-4, 4, 4, PAL.TARDIS_LIGHT) rectb(x+TARDIS_W//2-2, y-4, 4, 4, PAL.OUTLINE) end --================================================== -- Radgie sprite (white body w/ black vertical stripes + blue cap) --================================================== function drawRadgie(p) -- BODY (white base) circ(p.x, p.y, 4, 12) -- vertical black stripes line(p.x-1, p.y-3, p.x-1, p.y+3, 0) line(p.x+1, p.y-3, p.x+1, p.y+3, 0) -- HEAD circ(p.x, p.y-3, 3, 12) -- BLUE CAP rect(p.x-3, p.y-7, 6, 2, 9) rect(p.x-4, p.y-6, 8, 2, 9) -- NOSE (directional) local nx = p.x + (p.face * 3) pix(nx, p.y-3, 2) end function drawWeapon(w) if w.used then return end local x,y,col=w.x,w.y,w.col circ(x,y,5,PAL.OUTLINE) circb(x,y,5,PAL.UI_TEXT) if w.name=="Eggs" then circ(x-1,y,2,col); circ(x+2,y-1,1,col) elseif w.name=="Knuckles" then rect(x-3,y-1,6,2,col) circ(x-2,y,1,PAL.UI_TEXT); circ(x,y,1,PAL.UI_TEXT); circ(x+2,y,1,PAL.UI_TEXT) elseif w.name=="Golf Club" then line(x-3,y+2,x+3,y-2,col); rect(x+2,y-3,2,2,col) elseif w.name=="Garden Shears" then -- simple shears icon (two blades + handle loops) line(x-3,y+2,x+2,y-3,col) line(x-2,y-3,x+3,y+2,col) circ(x-2,y+2,1,PAL.UI_TEXT) circ(x+2,y+2,1,PAL.UI_TEXT) elseif w.name=="Paintball" then rect(x-2,y-2,4,4,col); line(x+2,y,x+5,y,col) elseif w.name=="Chainsaw" then rect(x-3,y-1,5,2,col); rect(x+2,y-2,2,4,col); line(x+4,y-2,x+4,y+2,PAL.UI_TEXT) elseif w.name=="AK-47" then rect(x-3,y-1,6,2,col); line(x+3,y,x+6,y,col); line(x,y+1,x+1,y+3,col) elseif w.name=="Bazooka" then rect(x-4,y-1,8,2,col); circ(x+4,y,2,col) end end function drawAttackPad() rect(PAD_X, PAD_Y, PAD_W, PAD_H, PAL.PAD_FILL) rectb(PAD_X, PAD_Y, PAD_W, PAD_H, PAL.PAD_BORDER) print("ATTACK AREA", PAD_X+12, PAD_Y+4, PAL.PAD_TEXT, false, 1, true) end --================================================== -- Win FX: debris + skeleton --================================================== function spawnWinFX() game.tardisDestroyed=true game.winTimer=0 game.debris={} local cx = TARDIS_X + TARDIS_W//2 local cy = TARDIS_Y + TARDIS_H//2 -- Spawn lots of Tardis bits for i=1,36 do local d = { x = cx + math.random(-10,10), y = cy + math.random(-16,16), vx = math.random(-30,30)/10, vy = math.random(-40,-10)/10, s = math.random(1,3), col = (math.random(0,3)==0) and PAL.TARDIS_WIN or PAL.TARDIS_BODY, life = 999999 } game.debris[#game.debris+1]=d end -- Flash bits for i=1,10 do local d = { x = cx + math.random(-8,8), y = cy + math.random(-8,8), vx = math.random(-40,40)/10, vy = math.random(-50,-20)/10, s = 1, col = PAL.FX_FLASH, life = 24 + math.random(0,18) } game.debris[#game.debris+1]=d end -- Skeleton falls out game.skel.active=true game.skel.x = cx game.skel.y = TARDIS_Y + 6 game.skel.vy = 0 game.skel.landY = clamp(TARDIS_Y + TARDIS_H + 18, 20, GROUND_Y-6) game.skel.landed=false game.shake = 18 end function updateWinFX() game.winTimer = game.winTimer + 1 for i=1,#game.debris do local d=game.debris[i] if d.life>0 then d.x = d.x + d.vx d.y = d.y + d.vy d.vy = d.vy + 0.18 if d.y >= GROUND_Y then d.y = GROUND_Y d.vy = -d.vy*0.45 d.vx = d.vx*0.82 if math.abs(d.vy) < 0.25 then d.vy = 0 end end if d.life < 999999 then d.life = d.life - 1 end end end if game.skel.active and (not game.skel.landed) then game.skel.vy = game.skel.vy + 0.22 game.skel.y = game.skel.y + game.skel.vy if game.skel.y >= game.skel.landY then game.skel.y = game.skel.landY game.skel.landed=true game.skel.vy=0 game.shake = 10 end end if game.winTimer > 170 then game.mode="win" setMsg("RADGIE WINS. TARDIS IN BITS.", 999999) end end function drawDebris() for i=1,#game.debris do local d=game.debris[i] if d.life>0 then if d.s==1 then pix(d.x,d.y,d.col) elseif d.s==2 then rect(d.x,d.y,2,2,d.col) else rect(d.x,d.y,3,3,d.col) pix(d.x+1,d.y+1,PAL.OUTLINE) end end end end function drawSkeleton(s) if not s.active then return end local x = s.x local y = s.y if not s.landed then circ(x, y-10, 3, 15) circb(x, y-10, 3, PAL.OUTLINE) pix(x-1,y-11,PAL.OUTLINE); pix(x+1,y-11,PAL.OUTLINE) line(x, y-7, x, y+4, 15) line(x-4, y-4, x+4, y-4, 15) line(x-3, y-2, x+3, y-2, 15) line(x-4, y-4, x-7, y-1, 15) line(x+4, y-4, x+7, y-1, 15) line(x-2, y+4, x+2, y+4, 15) line(x-1, y+4, x-2, y+10, 15) line(x+1, y+4, x+2, y+10, 15) else local ly = y circ(x-8, ly-2, 3, 15) circb(x-8, ly-2, 3, PAL.OUTLINE) pix(x-9,ly-3,PAL.OUTLINE); pix(x-7,ly-3,PAL.OUTLINE) line(x-4, ly, x+10, ly, 15) line(x, ly-3, x+6, ly-3, 15) line(x, ly+3, x+6, ly+3, 15) line(x+2, ly, x+6, ly-6, 15) line(x+2, ly, x+6, ly+6, 15) line(x+10, ly, x+16, ly-5, 15) line(x+10, ly, x+16, ly+5, 15) end end --================================================== -- UI helpers --================================================== function setMsg(s,frames) game.msg=s game.msgTimer=frames or 90 end function setTaunt(s) game.taunt=s game.tauntActive=true end function clearTaunt() game.taunt="" game.tauntActive=false end function anyUnusedWeaponsLeft() for i,w in ipairs(weapons) do if not w.used then return true end end return false end function nextObjectiveText() if game.currentWeapon==0 then return "Grab a weapon" end return "Step into the Attack Area" end --================================================== -- Gameplay logic --================================================== function handleMovement() local p=game.player local dx=0 local dy=0 if btn(2) then dx=dx-1 end if btn(3) then dx=dx+1 end if btn(0) then dy=dy-1 end if btn(1) then dy=dy+1 end if dx~=0 then p.face=sign(dx) end p.x = clamp(p.x + dx*p.spd, 6, W-6) p.y = clamp(p.y + dy*p.spd, 12, H-6) end function tryPickup() if game.currentWeapon~=0 then return end local p=game.player for i,w in ipairs(weapons) do if (not w.used) and (not w.taken) then if dist2(p.x,p.y,w.x,w.y) <= (9*9) then w.taken=true game.currentWeapon=i clearTaunt() setMsg("Picked up: "..w.name.." (one use)", 110) return end end end end function inAttackArea(px,py) return (px>=PAD_X and px<=PAD_X+PAD_W and py>=PAD_Y and py<=PAD_Y+PAD_H) end function startAttack() local idx=game.currentWeapon if idx==0 then return end local w=weapons[idx] if w.used then return end if not inAttackArea(game.player.x, game.player.y) then return end game.mode="attack" game.attackTimer=0 game.attackWpn=idx local t = TAUNTS[((idx-1)%#TAUNTS)+1] setTaunt(t) end function triggerBazookaDrop() -- only trigger if not already dropping if game.dropTimer<=0 then game.dropTimer = game.dropLen musicDrop() end end function updateMusicState() if game.dropTimer > 0 then game.dropTimer = game.dropTimer - 1 if game.dropTimer == 0 then musicStartMain() end end end function finishAttack() local idx=game.attackWpn local w=weapons[idx] if w and (not w.used) then w.used=true game.usedCount = game.usedCount + 1 game.tardisHP = clamp(game.tardisHP - w.dmg, 0, game.tardisHPMax) game.shake = 10 + w.dmg*2 end game.currentWeapon=0 game.attackWpn=0 if game.tardisHP<=0 and (not anyUnusedWeaponsLeft()) then game.mode="winfx" spawnWinFX() setMsg("...", 999999) else game.mode="play" setMsg(nextObjectiveText(), 999999) end end --================================================== -- Attack animation visuals --================================================== function drawAttackFX(idx, t) local prog = t / game.attackLen local tx = CX local ty = CY-4 if (t%6)<3 then circ(tx, ty, 8 + (idx%3), PAL.FX_FLASH) circb(tx, ty, 10 + (idx%3), PAL.OUTLINE) end local px=game.player.x local py=game.player.y if idx==1 then for i=0,3 do local ex = px + (tx-px)*prog + (i-1.5)*3 local ey = py + (ty-py)*prog + (i%2)*2 circ(ex,ey,2,WEAPON_COL.EGGS) end circ(tx-6,ty+4,3,PAL.FX_SPARK); circ(tx+5,ty+2,2,PAL.FX_SPARK) elseif idx==2 then local sx = px + game.player.face*6 local sy = py-3 line(sx,sy, tx,ty, WEAPON_COL.KNUCKLES) for i=0,2 do line(tx-4+i*4,ty-4, tx-2+i*4,ty+4, PAL.FX_FLASH) end elseif idx==3 then local r=18 for a=0,12 do local ang = (a/12)*math.pi local ax = px + math.cos(ang)*r local ay = (py-2) - math.sin(ang)*r pix(ax,ay,WEAPON_COL.GOLF) end line(px,py-2, tx,ty, WEAPON_COL.GOLF) elseif idx==4 then -- garden shears "SNIP" arcs for i=0,10 do pix(tx-10+i, ty-6+(i%2), WEAPON_COL.SHEARS) pix(tx-10+i, ty+6-((i+1)%2), WEAPON_COL.SHEARS) end line(px,py-2, tx,ty, WEAPON_COL.SHEARS) for i=0,6 do pix(tx+(math.random(0,8)-4), ty+(math.random(0,8)-4), PAL.FX_FLASH) end elseif idx==5 then local bx = px + (tx-px)*prog local by = py + (ty-py)*prog circ(bx,by,2,WEAPON_COL.PAINTBALL) for i=0,6 do pix(tx + (i-3), ty + ((i%3)-1), WEAPON_COL.PAINTBALL) end elseif idx==6 then for i=0,10 do local x = px + (tx-px)*(i/10) local y = py + (ty-py)*(i/10) + ((i%2==0) and -1 or 1) pix(x,y,WEAPON_COL.CHAINSAW) end for i=0,8 do pix(tx + (i-4), ty + ((i%2)*4-2), PAL.FX_FLASH) end elseif idx==7 then for i=0,5 do local bx = px + (tx-px)*(i/5) local by = py + (ty-py)*(i/5) pix(bx,by,WEAPON_COL.AK) end for i=0,10 do pix(tx+(math.random(0,10)-5), ty+(math.random(0,10)-5), PAL.FX_FLASH) end elseif idx==8 then -- Bazooka rocket + boom local rx = px + (tx-px)*prog local ry = py + (ty-py)*prog rect(rx-2,ry-1,4,2,WEAPON_COL.BAZOOKA) pix(rx+3,ry,PAL.FX_BOOM) -- Trigger DROP when the rocket reaches the Tardis (about 60% through) if t == math.floor(game.attackLen*0.6) then triggerBazookaDrop() end if t > game.attackLen*0.6 then for r=6,18,3 do circ(tx,ty,r, (r%2==0) and PAL.FX_BOOM or PAL.FX_FLASH) end end end end --================================================== -- Hover label drawing: top row below, bottom row above --================================================== function drawHoverName(w) local name=w.name local tw=#name*6 local lx = clamp(w.x - tw//2, 2, W - tw - 2) local ly if w.y < H/2 then ly = w.y + 10 else ly = w.y - 16 end ly = clamp(ly, 12, TAUNT_Y - 12) rect(lx-2, ly-1, tw+4, 8, PAL.UI_BAR) rectb(lx-2, ly-1, tw+4, 8, PAL.UI_TEXT) print(name, lx, ly, PAL.UI_TEXT, false, 1, true) end --================================================== -- HUD --================================================== function drawHUD() rect(0,0,W,10,PAL.UI_BAR) print("RADGIE v TARDIS", 6, 2, PAL.UI_TEXT, false, 1, true) -- HP bar local bw=80 local bh=5 local bx=W- bw - 6 local by=2 rectb(bx,by,bw,bh,PAL.UI_TEXT) local fill = 0 if game.tardisHPMax>0 then fill = math.floor((game.tardisHP / game.tardisHPMax) * (bw-2)) end rect(bx+1,by+1,fill,bh-2,PAL.TARDIS_BODY) print("TARDIS", bx-36, 2, PAL.UI_TEXT, false, 1, true) -- taunt bar if game.tauntActive and game.taunt~="" then rect(0,TAUNT_Y,W,TAUNT_H,PAL.UI_PANEL) rectb(0,TAUNT_Y,W,TAUNT_H,PAL.UI_TEXT) print(game.taunt, 6, TAUNT_Y+2, PAL.UI_TEXT, false, 1, true) end -- instruction bar rect(0,MSG_Y,W,MSG_H,PAL.UI_BAR) if game.msgTimer>0 then print(game.msg, 6, MSG_Y+2, PAL.UI_TEXT, false, 1, true) end -- current weapon if game.currentWeapon~=0 then local w=weapons[game.currentWeapon] print("Holding: "..w.name, 6, 12, PAL.UI_TEXT, false, 1, true) else print("Holding: nowt", 6, 12, PAL.UI_SOFT, false, 1, true) end print("Used: "..game.usedCount.."/8", 170, 12, PAL.UI_TEXT, false, 1, true) if game.tipOn and game.mode~="title" and game.mode~="winfx" and game.mode~="win" then local tip = (game.currentWeapon==0) and "Tip: Walk up to a weapon & press Z" or "Tip: Stand in ATTACK AREA & press Z" print(tip, 6, 22, PAL.UI_HINT, false, 1, true) end end --================================================== -- TIC --================================================== function TIC() game.t = game.t + 1 -- X toggles tips if btnp(5) then game.tipOn = not game.tipOn end -- Keep music state ticking (handles drop -> back to main) updateMusicState() -- message timer if game.msgTimer>0 and game.msgTimer<999999 then game.msgTimer = game.msgTimer - 1 if game.msgTimer<=0 then game.msgTimer=0 game.msg="" end end cls(PAL.BG) if game.mode=="title" then cls(PAL.FLOOR_A) print("RADGIE v TARDIS", 56, 40, PAL.UI_TEXT, false, 2, true) print("Use ALL 8 weapons to wreck the Tardis.", 34, 70, PAL.UI_TEXT, false, 1, true) print("ARROWS move Z pick/attack X tips", 44, 84, PAL.UI_SOFT, false, 1, true) print("Press Z to start", 78, 102, PAL.UI_TEXT, false, 1, true) if btnp(4) then resetGame() end return end -- screen shake local shx=0 local shy=0 if game.shake>0 then shx = (math.random(0,2)-1) shy = (math.random(0,2)-1) game.shake = game.shake - 1 end -- update if game.mode=="play" then handleMovement() if btnp(4) then if game.currentWeapon==0 then tryPickup() if game.currentWeapon==0 then setMsg("Grab a weapon", 70) else setMsg("Step into the Attack Area", 90) end else if inAttackArea(game.player.x, game.player.y) then startAttack() else setMsg("Step into the Attack Area", 70) end end end elseif game.mode=="attack" then game.attackTimer = game.attackTimer + 1 if game.attackTimer >= game.attackLen then finishAttack() end elseif game.mode=="winfx" then updateWinFX() if btnp(4) then game.mode="win" end elseif game.mode=="win" then if btnp(4) then game.mode="title" end end -- background floor stripes for y=10,TAUNT_Y-2,8 do line(0,y,W,y, (y%16==0) and PAL.FLOOR_A or PAL.FLOOR_B) end drawAttackPad() if not game.tardisDestroyed then drawTardis(shx,shy) else drawDebris() drawSkeleton(game.skel) end -- weapons only while playing/attacking if game.mode=="play" or game.mode=="attack" then for i,w in ipairs(weapons) do if not w.used and not w.taken then drawWeapon(w) end end end drawRadgie(game.player) -- hover labels if game.mode=="play" and game.currentWeapon==0 then local p=game.player for i,w in ipairs(weapons) do if (not w.used) and (not w.taken) and dist2(p.x,p.y,w.x,w.y) <= (9*9) then circb(w.x,w.y,7,PAL.UI_TEXT) drawHoverName(w) break end end end -- attack FX if game.mode=="attack" then drawAttackFX(game.attackWpn, game.attackTimer) end -- win overlay AFTER the animation finishes if game.mode=="win" then rect(20,34,200,68,PAL.UI_BAR) rectb(20,34,200,68,PAL.UI_TEXT) print("RADGIE WINS. TARDIS IN BITS.", 40, 50, PAL.UI_TEXT, false, 1, true) print("Press Z to return to title", 52, 82, PAL.UI_TEXT, false, 1, true) end drawHUD() end -- Boot to title game.mode="title"