30 Commits

Author SHA1 Message Date
3151db5430 fix precedence error 2025-05-31 22:27:03 -07:00
2964159858 fix offset, try but fail to fix variants 2025-05-31 22:19:35 -07:00
95d4b6eb37 what the hell was I thinking when I wrote this 2025-05-31 22:06:48 -07:00
96312e3adf fix offset bugs 2025-05-31 22:05:47 -07:00
bf9a45d87e fix gframe unit 2025-05-31 21:55:21 -07:00
36f7c6572f fix ship spawning 2025-05-31 21:54:02 -07:00
45b70d3aca did you know that 4 is not 1? mindboggling! 2025-05-31 21:43:51 -07:00
35980d801a forgot my increments! 2025-05-31 21:40:17 -07:00
734811bd62 math works better when you return your values 2025-05-31 21:33:06 -07:00
4fddbea82c use the right loader 2025-05-31 21:31:20 -07:00
f675e31967 oops, I accidentally 2025-05-31 21:30:30 -07:00
0bd1463416 replace demo level with infinite copies of flotilla 0 2025-05-31 21:29:54 -07:00
267f8a3667 actually add ships we keep 2025-05-31 21:02:26 -07:00
fa206c37c5 "redistribute"-type flotilla: update 2025-05-31 21:00:27 -07:00
928e7f7418 prototype flotilla loader 2025-05-31 20:39:07 -07:00
2439fda068 ship prototype tweaks 2025-05-31 20:38:59 -07:00
d13290f438 placeholder flotilla ships 2025-05-31 19:03:38 -07:00
e3a2810f0a Prototype a flotilla template. 2025-05-25 21:03:51 -07:00
3764063b20 abandon "offset" sprites, use "row tier" sprites 2025-05-25 20:49:27 -07:00
90f6df2922 flotilla notes and sprites 2025-05-25 19:11:44 -07:00
b7c3e6ee92 adjust menu renderer 2025-05-03 17:26:48 -07:00
c91e5f4bd1 shorten RATE message
not enough room to describe "fractions add up" -- maybe I can just fit
in the "remainder" to hint that it will be considered in future
upgrades?
2025-05-03 17:19:33 -07:00
ea2ddadb15 oops, method call syntax is special 2025-05-03 17:12:20 -07:00
9333c03bf3 add main gun rate upgrade to ship pool 2025-05-03 17:11:47 -07:00
1b45bd3dc3 fix rate formatting 2025-05-03 17:11:35 -07:00
71a7351d77 oops, miscalculated box width 2025-05-03 17:04:29 -07:00
80bb848468 options work better when I return them 2025-05-03 16:51:59 -07:00
b227844d12 Restyle ship stat upgrades. 2025-05-03 16:48:18 -07:00
ce14d03669 offer gun upgrades 2025-05-03 16:38:39 -07:00
ccd2c64103 update gun pick description style 2025-05-03 16:38:26 -07:00

View File

@ -127,7 +127,6 @@ function _init()
mode = game_mode mode = game_mode
init_blip_pals() init_blip_pals()
wipe_game() -- redundant? wipe_game() -- redundant?
load_level(example_level_csv)
game_state = game game_state = game
pal(2,129) pal(2,129)
pal() pal()
@ -171,6 +170,10 @@ function wipe_game()
new_events = linked_list.new() new_events = linked_list.new()
primary_ship.main_gun = zap_gun_p.new() primary_ship.main_gun = zap_gun_p.new()
primary_ship.main_gun:peel() primary_ship.main_gun:peel()
gframe = 0
interlude = 0
waves_complete = 0
current_wave = nil
end end
function _update60() function _update60()
@ -185,12 +188,44 @@ function call_move(x)
return x:move() return x:move()
end end
function ones(n)
local ret = 0
while n != 0 do
if (n&0x0.0001) ret += 1
n >>= 1
end
return ret
end
function updategame() function updategame()
if (primary_ship.xp >= primary_ship.xptarget) and (lframe - primary_ship.last_xp_frame > 0x0.000f) and (not primary_ship.dead) then if (primary_ship.xp >= primary_ship.xptarget) and (gframe - primary_ship.last_xp_frame > 0x0.000f) and (not primary_ship.dead) then
mode = rearm_mode.new() mode = rearm_mode.new()
return _update60() return _update60()
end end
leveldone = level_frame() gframe += 0x0.0001
if current_wave then
if current_wave:update() then
-- end of stage
waves_complete += 1
current_wave = nil
if waves_complete < 32767 then
interlude = 59 -- plus one dead frame with load_level but no update
else
-- you maxed out the level
-- counter. what the fuck
-- is wrong with you?
-- go outside.
--
-- do not spawn more levels.
interlude = 32767
end
end
elseif interlude > 0 then
interlude -= 1
else
current_wave = flotilla.new()
current_wave:load(0, 0, min(ones(waves_complete)\2, 4))
end
events:vore(new_events) events:vore(new_events)
events:strip(call_move) events:strip(call_move)
for _, lst in ipairs{intangibles_bg, pships, eships, pbullets, ebullets} do for _, lst in ipairs{intangibles_bg, pships, eships, pbullets, ebullets} do
@ -254,7 +289,7 @@ function updategame()
intangibles_fg:strip(call_move) intangibles_fg:strip(call_move)
if leveldone and not eships.next and not ebullets.next and not events.next then if waves_complete == 32767 and not eships.next and not ebullets.next and not events.next then
game_state = win game_state = win
end end
if (not pships.next) game_state = lose if (not pships.next) game_state = lose
@ -466,6 +501,14 @@ end
-->8 -->8
--ship behavior --ship behavior
-- generic full sprite hurtbox
box8 = {
x_off = 0,
y_off = 1,
width = 8,
height = 8
}
scrollrate = 0.25 --in px/frame scrollrate = 0.25 --in px/frame
ship_m = mknew{ ship_m = mknew{
@ -611,7 +654,7 @@ end
function ship_m:hitsomething(dmg) function ship_m:hitsomething(dmg)
if (dmg <= 0) return false if (dmg <= 0) return false
self.shield_refresh_ready = lframe + self.shieldpenalty self.shield_refresh_ready = gframe + self.shieldpenalty
if self.shield > 0 then if self.shield > 0 then
self.shield -= dmg self.shield -= dmg
if self.shield > 0 then if self.shield > 0 then
@ -633,10 +676,10 @@ end
function ship_m:refresh_shield() function ship_m:refresh_shield()
if (self.shield >= self.maxshield) return if (self.shield >= self.maxshield) return
if (lframe < self.shield_refresh_ready) return if (gframe < self.shield_refresh_ready) return
self.shield += 1 self.shield += 1
self.shield = min(self.shield, self.maxshield) self.shield = min(self.shield, self.maxshield)
self.shield_refresh_ready = lframe + self.shieldcooldown self.shield_refresh_ready = gframe + self.shieldcooldown
end end
-->8 -->8
@ -730,7 +773,7 @@ function gun_base:ammo_upgrade_opt()
return { return {
icon=self.icon, icon=self.icon,
hdr=self.hdr, hdr=self.hdr,
body=[[----------AMMO body=[[--------AMMO
more shots more shots
before you before you
@ -754,20 +797,20 @@ function gun_base:rate_upgrade_opt()
return { return {
icon=self.icon, icon=self.icon,
hdr=self.hdr, hdr=self.hdr,
body=[[----------RATE body=[[--------RATE
reduce delay reduce delay
between shots between each
in frames. shot when
firing.
fractions is: ]]..tostr(c)..[[f
add up across minus: ]]..tostr(c-newc)..[[f
upgrades.
is: ]]..tostr(c)..[[
minus: ]]..tostr(c-newc)..[[
---------- ----------
total: ]]..tostr(newc), total: ]]..tostr(newc)..[[f
remainder:
]]..sub(tostr(newc-rawnewc),0,5),
action=function() action=function()
self.cooldown=newc>>16 self.cooldown=newc>>16
self.cd_remainder=newc-rawnewc self.cd_remainder=newc-rawnewc
@ -805,12 +848,12 @@ function bullet_base:spawn_at(x, y)
end end
function gun_base:shoot(x, y) function gun_base:shoot(x, y)
if (lframe < self.shoot_ready) return false if (gframe < self.shoot_ready) return false
if self.ammo then if self.ammo then
if (self.ammo <= 0) return false if (self.ammo <= 0) return false
self.ammo -= 1 self.ammo -= 1
end end
self.shoot_ready = lframe + self.cooldown self.shoot_ready = gframe + self.cooldown
self:actually_shoot(x, y) self:actually_shoot(x, y)
return true return true
end end
@ -916,10 +959,12 @@ blast_gun = mknew(gun_base.new{
maxammo = 5, maxammo = 5,
munition = blast, munition = blast,
hdr = "bLASTER", hdr = "bLASTER",
body= [[plasma orb body= [[---------GUN
plasma orb
cuts through cuts through
enemies. enemies.
slow. slow.
ammo: 5 ammo: 5
rate: 1/2sec rate: 1/2sec
@ -988,9 +1033,11 @@ protron_gun_p = mknew(protron_gun_e.new{
maxammo = 20, maxammo = 20,
cooldown = 0x0.0018, cooldown = 0x0.0018,
hdr = "pROTRON", hdr = "pROTRON",
body = [[spray shots body = [[---------GUN
in a dense
arc. spray shots
in a dense
arc.
ammo: 20 ammo: 20
rate: 2/sec rate: 2/sec
@ -1049,9 +1096,10 @@ vulcan_gun_p = mknew(vulcan_gun_e.new{
munition=vulcan_p, munition=vulcan_p,
maxammo = 100, maxammo = 100,
hdr = "vULCAN", hdr = "vULCAN",
body = [[rapid fire body = [[---------GUN
in a v
shape. rapidly fire
in a v.
ammo: 100 ammo: 100
rate: 20/sec rate: 20/sec
@ -1142,7 +1190,11 @@ function player:small_upgrade_opts()
local ret = {{ local ret = {{
icon=53, icon=53,
hdr="hull", hdr="hull",
body=[[ armor body=[[--------SHIP
survive more
unshielded
hits.
+2 hp]], +2 hp]],
action=function() action=function()
@ -1151,8 +1203,13 @@ function player:small_upgrade_opts()
end, end,
},{ },{
icon=52, icon=52,
hdr="shield", hdr="capacity",
body=[[ capacity body=[[------SHIELD
shield can
absorb more
hits before
recharging.
+1 hp]], +1 hp]],
action=function() action=function()
@ -1162,10 +1219,11 @@ function player:small_upgrade_opts()
},{ },{
icon=1, icon=1,
hdr="thrusters", hdr="thrusters",
body=[[performance body=[[--------SHIP
move faster, move faster,
steer faster]], steer more
sharply.]],
action=function() action=function()
--maxspd thrust drag --maxspd thrust drag
self.maxspd += 0.5 self.maxspd += 0.5
@ -1174,22 +1232,29 @@ steer faster]],
end, end,
},{ },{
icon=20, icon=20,
hdr="hull", hdr="magnet",
body=[[ magnet body=[[--------SHIP
pick up xp pick up xp
from further from further
away]], away.]],
action=function () action=function ()
self.magnet += 2 self.magnet += 2
end, end,
}} },
self.main_gun:rate_upgrade_opt(),
}
if cdr > 0 then if cdr > 0 then
add(ret, { add(ret, {
icon = 6, icon = 6,
hdr = "shield", hdr = "recharge",
body=[[charge rate body=[[------SHIELD
shield will
recharge at
a faster
pace.
]] .. tostr(ceil(100 * cdr / self.shieldcooldown)) .. "% faster", ]] .. tostr(ceil(100 * cdr / self.shieldcooldown)) .. "% faster",
action = function() action = function()
@ -1201,8 +1266,15 @@ from further
if pr > 0 then if pr > 0 then
add(ret, { add(ret, {
icon = 6, icon = 6,
hdr = "shield", hdr = "recovery",
body=[[disruption body=[[------SHIELD
reduce the
delay after
a hit before
shield will
start to
recharge.
]] .. tostr(ceil(100 * pr / self.shieldpenalty)) .. "% shorter", ]] .. tostr(ceil(100 * pr / self.shieldpenalty)) .. "% shorter",
action = function() action = function()
@ -1214,81 +1286,10 @@ from further
return ret return ret
end end
frownie = mknew(ship_m.new{ -- original prototype leftover;
--shape -- likely to be the basis of a
sprite = 3, --index of ship sprite -- standard raider type, so
size = 1, --all ships are square; how many 8x8 sprites? -- i am keeping it around
hurt = { -- hurtbox - where this ship can be hit
x_off = 0, -- upper left corner
y_off = 1, -- relative to ship ulc
width = 8,
height = 6
},
sparks = smokespark,
sparkodds = 8,
hp = 0.5, -- enemy ships need no max hp
xp = 0x0.0001,
-- position
x=60, -- x and y are for upper left corner
y=8,
xmomentum = 0,
ymomentum = 0,
maxspd = 2, -- momentum cap
thrust = 0.12, -- momentum added from button
drag = 0.07, -- momentum lost per frame
slip = true,
act = function(self)
local tstate,dx = (1 + flr(4*t() + 0.5)) % 6,0
if (tstate==1 or tstate==2) dx=-self.thrust
if (tstate>=4) dx=self.thrust
return dx,0,false,false
end,
})
blocky = mknew(frownie.new{
sprite = 10,
hp = 1.5,
xp = 0x0.0002,
hurt = {
x_off = 0,
y_off = 0,
width = 8,
height = 7
},
ow = function(self)
if self.hp < 1 then
self.sprite = 11
else
self.sprite = 10
end
ship_m.ow(self)
end
})
spewy = mknew(frownie.new{
sprite=26,
xp = 0x0.0003,
hurt = {
x_off=0,
y_off=1,
width=8,
height=5
},
hp=0.5,
fire_off_x=4,
fire_off_y=7,
act=function(self)
local dx,dy,shoot_spec=frownie.act(self)
return dx, dy, shoot_spec, self.y > 10
end,
init = function(ship)
ship.main_gun=ship.main_gun or protron_gun_e.new{}
end
})
chasey = mknew(ship_m.new{ chasey = mknew(ship_m.new{
sprite = 5, sprite = 5,
xp = 0x0.0004, xp = 0x0.0004,
@ -1318,7 +1319,6 @@ chasey = mknew(ship_m.new{
end end
}) })
-- todo: use constraints
function chasey:act() function chasey:act()
self.xmin = max(primary_ship.x-8, 0) self.xmin = max(primary_ship.x-8, 0)
self.xmax = min(primary_ship.x + 8, 112 - 8*self.size) self.xmax = min(primary_ship.x + 8, 112 - 8*self.size)
@ -1356,6 +1356,53 @@ xl_chasey=mknew(chasey.new{
end, end,
}) })
-- flotilla ships
ship_f = mknew(ship_m.new{
-- sprite required
size = 1,
hurt = box8,
-- no sparks
hp = 0.5,
xp = 0x0.0001,
maxspd = 3,
thrust = 0.1,
drag = 0.05,
slip = false,
act = function(self)
local wx,wy=self.want_x,self.want_y
self.xmin,self.xmax,self.ymin,self.ymax = wx,wx,wy,wy
return 0,0,false,false
end,
})
ship_mook = mknew(ship_f.new{
sprite=103
})
ship_defender = mknew(ship_f.new{
sprite=105,
hp = 2.5,
xp = 0x0.0003,
})
ship_turret = mknew(ship_f.new{
sprite=106,
xp = 0x0.0002,
})
ship_skirmisher = mknew(ship_f.new{
sprite=107,
xp = 0x0.0004,
spark = smokespark,
sparkodds = 4,
})
function rnd_spawn_loc()
local x,y = flr(rnd(304)), flr(rnd(32))
if (x<184) return x-40,-y-8
if (x<244) return -y-8,x-184
return 112+y, x-244
end
-->8 -->8
-- collisions -- collisions
@ -1420,242 +1467,163 @@ function collider:get_collisions(item)
end end
return found return found
end end
-->8 -->8
-- level and event system -- flotillas
-- a level is a map from -- a template for a wave, read
-- effective frame number to -- from the map. each ship can
-- a list of actions for that -- alternate between "attack"
-- frame. an action is a -- and "formation" modes, like
-- method name and its args. -- galaxian or galaga. ships
-- with different roles have
-- different rules for becoming
-- aggressive, but aggression
-- ramps up during the wave.
-- effective frame number stops -- flotilla placeholders are
-- when freeze count is nonzero -- defined by sprite flags.
-- see obsidian vault for
-- full docs.
-- a level is won when it hits flotilla = mknew{
-- the end-of-level sentinel use_var = 0x1111,
-- and there are no more opt_odds = split"0.5,0.5,0.5,0.5",
-- tracked enemies. init=function(this)
-- lost when there are no this.ship_bases={
-- player ships left. [0]=mknew(ship_mook.new{ship_t=0}),
[1]=mknew(ship_mook.new{ship_t=1, sprite=104}),
-- effective frame [4]=mknew(ship_defender.new{ship_t=4}),
distance = 0 [5]=mknew(ship_defender.new{ship_t=5, sprite=10}),
-- actual frame count since [8]=mknew(ship_turret.new{ship_t=8}),
-- start of level times 0x0.0001 [9]=mknew(ship_turret.new{ship_t=9, sprite=4}),
lframe = 0 [12]=mknew(ship_skirmisher.new{ship_t=12}),
[13]=mknew(ship_skirmisher.new{ship_t=13, sprite=26}),
-- do not advance distance when }
-- nonzero end,
freeze = 0
eol = {}
function load_level(levelfile)
distance = 0
lframe = 0
freeze = 0
leveldone = false
current_level = {}
local found_eol = false
if (type(levelfile)=="string") levelfile = csv(levelfile)
for row in all(levelfile) do
local x = current_level[row[1]]
if row[2] == "eol" then
found_eol = true
assert(x==nil, "events on eol frame")
current_level[row[1]] = eol
else
row.next = x
current_level[row[1]]=row
end
end
assert(found_eol)
end
function level_frame()
lframe += 0x0.0001
if (current_level == nil) return true
if freeze == 0 then
distance += 1
local cbs = current_level[distance]
if cbs ~= nil then
if cbs == eol then
current_level = nil
return true
else
while cbs do
assert(cbs[1] == distance)
local f = _ENV[cbs[2]]
assert(type(f) == "function", cbs[2].." at "..distance.." is not a function")
f(unpack(cbs, 3))
cbs=cbs.next
end
end
end
end
return false
end
-->8
-- example level
function spawn_blocking_rnd_x(typ)
freeze += 1
s = typ.new{
x = rnd(104),
y = -7,
ice = 1,
orig_die = typ.die,
die = function(self)
freeze -= self.ice
self.ice = 0
self:orig_die()
end,
}
eships:push_back(s)
return s
end
function spawn_frownie()
return spawn_rnd(frownie)
end
function spawn_blocking_frownie()
spawn_blocking_rnd_x(frownie)
end
function spawn_blocky()
spawn_rnd(blocky)
end
function spawn_blocking_blocky()
spawn_rnd(blocky, 1)
end
function spawn_spewy()
return spawn_rnd(spewy)
end
function spawn_chasey()
return spawn_rnd(chasey)
end
function spawn_blocking_spewy()
freeze += 1
local s = spawn_spewy()
s.ice = 1
s.die = function(self)
freeze -= self.ice
self.ice = 0
frownie.die(self)
end
end
function spawn_vulcan_chasey()
local c = spawn_chasey()
c.main_gun=vulcan_gun_e.new{enemy=true}
c.sprite=4
return c
end
helpers = {
spawn_frownie,
spawn_frownie,
spawn_frownie,
spawn_blocky,
spawn_blocky,
spawn_chasey,
spawn_spewy,
} }
function spawn_blocking_boss_chasey() function flotilla:load(ulc_cx, ulc_cy, lvl)
local c = spawn_rnd(xl_chasey, 1) local rows,cy,uv,counts={},ulc_cy,self.use_var,{
local nextspawn = lframe + 0x0.0080 [0]=0,
events:push_back{move=function() [1]=0,
if lframe >= nextspawn then [4]=0,
helpers[flr(rnd(#helpers))+1]() [5]=0,
nextspawn += 0x0.0040 [8]=0,
end [9]=0,
return c.dead [12]=0,
end} [13]=0,
return c
end
function std_spawn(tnm, n, blocking, goodie,altspr)
local typ = _ENV[tnm]
assert(typ and typ.new, tostr(tnm).." not a class")
for i=1,(n or 1) do
spawn_rnd(typ, blocking, goodie,altspr)
end
end
-- blocking: 1 or 0
function spawn_rnd(typ, blocking, goodie,altspr)
blocking = blocking or 0
freeze += blocking
s = typ.new{
x = rnd(104),
y = -(typ.size * 8 - 1),
ice=blocking,
die=function(self)
freeze -= self.ice
self.ice=0
typ.die(self)
end,
} }
if (altspr) s.spr = altspr repeat
eships:push_back(s) local row,cx,opt,f,mode= {},ulc_cx,{},0,0
return s for i,v in ipairs(self.opt_odds) do
end opt[i*4-4]=rnd()<v
function multi(times, interval, fnm, ...)
local f,irm,vargs = _ENV[fnm],interval,pack(...)
assert(type(f) == "function", fnm.." not a function")
f(...)
events:push_back{move=function()
irm-=1
if irm <= 0 then
irm=interval
times-=1
f(unpack(vargs))
return times <= 1
end end
end} repeat
f=fget(mget(cx, cy))
-- bits 0x03: control mark or ship?
mode = f&0x03
if mode==2 then
-- bits 0x0c: ship class
local ship_t = f&0x0c
-- bit 0x20: optional?
if f&0x20 == 0 or opt[ship_t] then
-- bit 0x10: alternate ship?
-- increment ship id if
-- alternate is requested
-- and we allow alternates
-- for this type of ship
ship_t+=(uv>>ship_t&0x1)&((f&0x10)>>4)
add(row, self.ship_bases[ship_t].new{col=cx-ulc_cx})
end
end
cx += 1
until mode==1
-- mode 1: end of line control mark
-- bits 0x18: what size flotilla is this row used for?
if (f&0x18)>>3 <= lvl then
-- keep the row; count it
for s in all(row) do
counts[s.ship_t] += 1
s.x,s.y=rnd_spawn_loc()
eships:push_back(s)
end
add(rows, row)
end
cy += 1
-- control mark bit 0x04: end of flotilla
until f&0x04 > 0
self.rows=rows
self:statisfy(counts)
end end
-- then convert sample_level to csv. function flotilla:statisfy(counts)
-- spawn_spec_gun_at and spawn_main_gun_at will need parsed forms. -- TODO: now that we know how
-- the boss also needs to be reachable, but one-off is fine. -- many ships of each kind
-- each row of level csv is offset,event,event-args... -- exist, build ships to match
-- where offset,eol is a special case. -- difficulty target
--
-- no difficulty model is yet
-- implemented, though, so
-- just use base ships only
-- for this prototype
end
example_level_csv=[[1,spawn_frownie function flotilla:update()
60,spawn_vulcan_chasey -- algorithm: redistribute
61,spawn_blocky -- TODO: alternate flotilla movement algorithms
85,spawn_spewy
115,spawn_spewy -- find effective width and height
130,spawn_frownie local min_col,max_col,live_rows=999,0,0
145,spawn_frownie for row in all(self.rows) do
180,spawn_spewy local row_alive=false
230,spawn_chasey for ship in all(row) do
250,spawn_blocking_blocky if not ship.dead then
310,spawn_blocking_blocky row_alive=true
310,spawn_blocking_blocky local col=ship.col
310,spawn_blocking_blocky if (col < min_col) min_col = col
311,spawn_frownie if (col > max_col) max_col = col
401,spawn_frownie end
420,spawn_blocking_frownie end -- scanned row
430,spawn_vulcan_chasey if (row_alive) live_rows += 1
450,spawn_frownie end -- extent search
465,spawn_frownie
480,spawn_chasey if (live_rows == 0) return true -- done
500,multi,20,12,spawn_blocking_blocky
501,spawn_frownie -- distribute across box:
620,spawn_blocking_blocky -- x = [4, 100)
630,spawn_vulcan_chasey -- y = [4, 60)
720,spawn_blocking_boss_chasey
721,eol]] local x_interval,x_offset = 0,52
if min_col < max_col then
x_interval=96/(max_col-min_col)
x_offset = 4-min_col*x_interval
end
local y_interval,y_offset=0,40
if live_rows > 1 then
y_interval=52/(live_rows-1)
y_offset=4-y_interval
end
-- now assign target locations
local real_row=0
for row in all(self.rows) do
local row_alive = false
for ship in all(row) do
if not ship.dead then
if not row_alive then
real_row += 1
row_alive = true
end
ship.want_x = ship.col * x_interval + x_offset
ship.want_y = real_row * y_interval + y_offset
end -- ship updated
end -- row updated
end -- table updated
return false -- some ships remain
end
-->8 -->8
-- standard events -- standard events
@ -1763,10 +1731,10 @@ function xp_gem:draw()
-- sprite map position: -- sprite map position:
-- sprite id to x and y, -- sprite id to x and y,
-- offset shifts specific low -- offset shifts specific low
-- bits of lframe up to the the -- bits of gframe up to the the
-- bit with value 4 as a cheap -- bit with value 4 as a cheap
-- way to pick an anim frame -- way to pick an anim frame
if (lframe&0x0.003 == 0) qx, qy = (lframe&0x0.0004)<<16, (lframe&0x0.0008)<<15 if (gframe&0x0.003 == 0) qx, qy = (gframe&0x0.0004)<<16, (gframe&0x0.0008)<<15
sspr( sspr(
(s%16<<3)+qx, (s%16<<3)+qx,
(s\16<<3)+qy, (s\16<<3)+qy,
@ -1792,7 +1760,7 @@ end
function xp_gem:hitship(ship) function xp_gem:hitship(ship)
if (ship ~= primary_ship or primary_ship.dead) return false if (ship ~= primary_ship or primary_ship.dead) return false
primary_ship.xp += self.val primary_ship.xp += self.val
primary_ship.last_xp_frame = lframe primary_ship.last_xp_frame = gframe
return true return true
end end
@ -1863,7 +1831,12 @@ end
-- ordinary upgrades -- ordinary upgrades
function small_opts() function small_opts()
-- todo: include gun opts -- todo: include gun opts
return pick(primary_ship:small_upgrade_opts(), 2) if(not primary_ship.special_guns) return pick(primary_ship:small_upgrade_opts(), 2)
local opts = {rnd(primary_ship:small_upgrade_opts())}
for g in all(primary_ship.special_guns) do
add(opts, rnd(g:small_upgrade_opts()))
end
return pick(opts, 2)
end end
-->8 -->8
@ -1872,7 +1845,7 @@ end
rearm_mode = mknew{ rearm_mode = mknew{
sel=1, sel=1,
bfm=1, bfm=1,
crt_frm = 1, crt_frm = 0,
pos=-1, pos=-1,
init=function(this) init=function(this)
poke(0x5f5c, 255) --no btnp repeat poke(0x5f5c, 255) --no btnp repeat
@ -1887,7 +1860,7 @@ function rearm_mode:glow_box(x0, y0, x1, y1, c, cf)
i -= 1 i -= 1
rect(x0+i,y0+i,x1-i,y1-i,v) rect(x0+i,y0+i,x1-i,y1-i,v)
end end
fillp(crt[self.crt_frm&0xff]) fillp(crt[1+(self.crt_frm&7)])
rectfill(x0+4, y0+4, x1-4, y1-4, cf) rectfill(x0+4, y0+4, x1-4, y1-4, cf)
fillp() fillp()
end end
@ -1919,7 +1892,7 @@ end
function rearm_mode:draw_option(id) function rearm_mode:draw_option(id)
local rec = self.options[id] local rec = self.options[id]
self:glow_box(0,0,55,100,self:frame_col(self.sel == id),1) self:glow_box(0,0,55,101,self:frame_col(self.sel == id),1)
spr(rec.icon,5, 5) spr(rec.icon,5, 5)
print(rec.hdr, 13, 8, 7) print(rec.hdr, 13, 8, 7)
print(rec.body, 5, 15, 6) print(rec.body, 5, 15, 6)
@ -1955,9 +1928,9 @@ function rearm_mode:draw()
camera(frac * -128 + (1-frac) * -56, 0) camera(frac * -128 + (1-frac) * -56, 0)
self:draw_option(2) self:draw_option(2)
camera(0, -28 * frac) camera(0, -28 * frac)
self:glow_box(0,101,111,127,self:frame_col(self.sel < 0),1) self:glow_box(0,102,111,127,self:frame_col(self.sel < 0),1)
spr(96,15,107,4,2) spr(96,15,107,4,2)
print("full ammo\nfull shield\n+50% health",54, 106, 6) print("full ammo\nfull shield\n+50% health",54, 107, 6)
end end
function rearm_mode:update_pos() function rearm_mode:update_pos()
@ -1977,6 +1950,7 @@ function rearm_mode:update_pos()
end end
function rearm_mode:update() function rearm_mode:update()
self.crt_frm+=0.25
self:update_pos() self:update_pos()
if self.pos > 1 then if self.pos > 1 then
mode = game_mode mode = game_mode
@ -2071,21 +2045,21 @@ cddddddddddd0000cddddddddddd0000cddddddddddd0000cddddddddddd0000cddddddddddd0000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
04444400044444440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 044444000444444400000000000000000000000000000000000000000000000000000000000000000000000000000000000bb000000aa0000009900000088000
447777700477777a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 447777700477777a0000000000000000000000000000000000000000000666000077700008888800000ab00006000060000bb000000aa0000009900000088000
477aaa7a0477aaaa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 477aaa7a0477aaaa0000000000000000000000000000000000000000006ddd5007fff70008eeee20000ab00006c006d0000bb000000aa0000009900000088000
47a0047a047a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 47a0047a047a0000000000000000000000000000000000000000000006dd7d5007ffff4008eeee200aaabbb006ccccd0000bb000000aa0000009900000088000
47a0447a047a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 47a0447a047a0000000000000000000000000000000000000000000006d7dd5007ffff4008eeee200bbb333006ccccd0000bb000000aa0000009900000088000
47a4477a047a44400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 47a4477a047a4440000000000000000000000000000000000000000006ddd500004fff4008eeee20000b300006d00cd0000bb000000aa0000009900000088000
477777a00477777a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 477777a00477777a0000000000000000000000000000000000000000005550000004440002222200000b30000d0000d0000bb000000aa0000009900000088000
477770000422aaaa2222000200000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 477770000422aaaa22220002000002000000000000000000000000000000000000000000000000000000000000000000000bb000000aa0000009900000088000
47a77700022ee0002eeee002e00022e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 47a77700022ee0002eeee002e00022e00000000000000000000000000000000000000000000000000000000000000000000bb000000aa0000009900000088000
47a4777002ea2e002e002e02ee022ee0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 47a4777002ea2e002e002e02ee022ee00000000000000000000000000005600000474000028282000004b000060000000bbbbbb00aaaaaa00999999008888880
47a0477a22ea2e002e002e02e2e2e2e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 47a0477a22ea2e002e002e02e2e2e2e0000000000000000000000000005d0d0004f0f400080e0e00000a000000c000d00b0000b00a0000a00900009008000080
47a0047a2e2222e02e222e02e02e02e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 47a0047a2e2222e02e222e02e02e02e000000000000000000000000005d07050070f0f2002e0e02004a0b0b0060c0c000b0bb0b00a0aa0a00909909008088080
47a0047a2eeeeeea2eeee002e02e02e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 47a0047a2eeeeeea2eeee002e02e02e000000000000000000000000006070d1004f0f040080e0e000b0b035000c0c0d00b0bb0b00a0aa0a00909909008088080
0aa000aa2e7aa2ea2e00e002e02e02e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0aa000aa2e7aa2ea2e00e002e02e02e000000000000000000000000000d0d100002f0f2002e0e0200000300006000c000b0000b00a0000a00900009008000080
000000002e0002e02e002e02e02e02e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000002e0002e02e002e02e02e02e0000000000000000000000000000510000002420002020200000b5000000000d00bbbbbb00aaaaaa00999999008888880
000000000e0000e00e000e00e00e00e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000e0000e00e000e00e00e00e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
__label__ __label__
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007777777777777777 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007777777777777777
@ -2217,3 +2191,12 @@ __label__
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666666666666665 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666666666666665
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007555555555555555 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007555555555555555
__gff__
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000212060a0e01091119000000000000002232363a3e050d151d
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
__map__
00006b6b00006f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
7b6a00006a7b6e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
7778686878776c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
6767777767676c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
7877676777787d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000