30 Commits

Author SHA1 Message Date
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
e5b8a30cb6 cooldown reduction prototype
I decided to keep cooldown in the same unit as the frame counter,
because the extra math when calculating an upgrade is going to happen
much less frequently than actual cooldown checks and calculations, so
leaving the upgrade logic as the less efficient path seems like the
more appropriate choice.
2025-05-03 16:28:54 -07:00
7ed305d2d9 Ammo quantity upgrade prototype
Not yet tested. Will crash until I also get rate_upgrade_opt up.
2025-05-03 16:06:16 -07:00
288b7f64c8 tinker with blip colors, go back to level+1
with the current testing level, level + 1 is necessary to comfortably
get a weapon before the Wall O' Block shows up
2025-01-26 22:32:17 -08:00
aea2a8c481 red blip when shield exhausted 2025-01-26 22:27:14 -08:00
9b24f10c23 inline ow, simplify blip, no shield piercing
* any amount of shielding prevents all HP damage
* when shields are sent to 0, orange blip
* all blips are 3 frames

considering a "shimmy" animation for start of shield recovery. maybe later
2025-01-26 22:25:06 -08:00
511c18f90e remove offset when choosing category of upgrade 2025-01-26 22:15:03 -08:00
142810ee2d scatter xp drops more 2025-01-26 22:11:02 -08:00
50beae1852 don't attract xp when dead 2025-01-26 22:08:16 -08:00
9c95fc1784 suck! suck! suck! suck! suck! suck! suck! suck! 2025-01-26 21:00:39 -08:00
cb2d24c9d0 thrust performance is now also an option 2025-01-26 20:38:31 -08:00
67603f8496 start of normal ship upgrades
todo: thrust upgrade
2025-01-26 20:21:06 -08:00
2cebea663f make stat modifications actually work 2025-01-26 13:14:59 -08:00
eed7b6af87 unique bullet base instances
peel off new copies of ammo when using a new gun so we can upgrade it without screwing up the base stats
2025-01-26 13:07:43 -08:00
26c3a5b91e actually fix starting ammo
also improve box overflow
2025-01-26 12:50:27 -08:00
44c70a028f fix starting ammo 2025-01-26 12:45:43 -08:00
a90caeba85 make level less spewy, finish renaming s to icon 2025-01-26 12:42:57 -08:00
cd5b79ef4a prototype: gun picking 2025-01-26 11:21:32 -08:00
637eed1eb8 autofire and three guns 2025-01-26 01:06:37 -08:00
55ab256539 oh right I changed that name 2025-01-26 00:32:17 -08:00
22d13121a9 placeholders for card draw 2025-01-26 00:30:09 -08:00

View File

@ -126,8 +126,7 @@ end
function _init()
mode = game_mode
init_blip_pals()
wipe_level()
primary_ship.main_gun = zap_gun_p.new() -- redundant?
wipe_game() -- redundant?
load_level(example_level_csv)
game_state = game
pal(2,129)
@ -157,7 +156,7 @@ function init_hpcols()
hpcols = hpcols_lut[min(primary_ship.maxhp,6)]
end
function wipe_level()
function wipe_game()
xpwhoosh = nil
primary_ship = player.new()
init_hpcols()
@ -170,6 +169,8 @@ function wipe_level()
intangibles_bg = linked_list.new()
events = linked_list.new()
new_events = linked_list.new()
primary_ship.main_gun = zap_gun_p.new()
primary_ship.main_gun:peel()
end
function _update60()
@ -363,8 +364,8 @@ function drawhud()
line(127,1,127,127,5)
line(113,127)
draw_gun_info("❎",1,116,3,primary_ship.main_gun)
draw_gun_info("🅾️",1,116,29,primary_ship.special_gun)
draw_gun_info("❎",1,116,3,1)
draw_gun_info("🅾️",1,116,29,2)
inset(114,57,119,118)
rectfill(119,57,124,58,13)
@ -404,25 +405,26 @@ function drawhud()
fillp(0)
end
function draw_gun_info(lbl,fgc,x,y,gun)
function draw_gun_info(lbl,fgc,x,y,gn)
dropshadow(lbl,x,y,fgc)
inset(114,y+7,125,y+18)
inset(114,y+20,125,y+24)
if(gun) then
spr(gun.icon,116,y+9,1,1)
--115 to 124 - ammo bar. round up
if gun.ammo == nil then
fillp(0xa5a5)
rectfill(115,y+21,124,y+23,0xea)
fillp(0)
elseif gun.ammo > 0 then
rectfill(
115,y+21,
115+flr(9*gun.ammo/gun.maxammo),
y+23,10)
else
line(118, y+22, 121, y+22, 2)
end
if (not primary_ship.special_guns) return
local gun = primary_ship.special_guns[gn]
if (not gun) return
spr(gun.icon,116,y+9,1,1)
--115 to 124 - ammo bar. round up
if gun.ammo == nil then
fillp(0xa5a5)
rectfill(115,y+21,124,y+23,0xea)
fillp(0)
elseif gun.ammo > 0 then
rectfill(
115,y+21,
115+flr(9*gun.ammo/gun.maxammo),
y+23,10)
else
line(118, y+22, 121, y+22, 2)
end
end
@ -501,14 +503,14 @@ function ship_m:die()
-- overage XP, min 100
spawn_xp_at(cx, cy, 0, xp-0x0.018f)
xp = 0x0.018f -- dec 399
z += 1
z += 2
end
-- 100, 25, 5, 1
for gsz in all{0x0.0064, 0x0.0019, 0x0.0005, 0x0.0001} do
while xp >= gsz do
spawn_xp_at(cx, cy, z, gsz)
xp -= gsz
z += 1
z += 2
end
end
end
@ -554,11 +556,12 @@ end
function ship_m:move()
self:refresh_shield()
local dx, dy, shoot_spec, shoot_main = self:act()
local dx, dy, shoot_spec1, shoot_spec2 = self:act()
dx = self:constrain(self.x, self.xmomentum, self.xmin, self.xmax, dx)
dy = self:constrain(self.y, self.ymomentum, self.ymin, self.ymax, dy)
if (shoot_main) self:maybe_shoot(self.main_gun)
if (shoot_spec) self:maybe_shoot(self.special_gun)
self:maybe_shoot(self.main_gun)
if (shoot_spec1 and self.special_guns) self:maybe_shoot(self.special_guns[1])
if (shoot_spec2 and self.special_guns) self:maybe_shoot(self.special_guns[2])
if (dx ~= 0 or dy ~= 0) spark(self.sparks, self.x + 4*self.size, self.y + 4*self.size, dx*2.5, dy*2.5, self.sparkodds)
self.xmomentum = self:calc_velocity(self.xmomentum, dx)
self.ymomentum = self:calc_velocity(self.ymomentum, dy)
@ -609,30 +612,25 @@ end
function ship_m:hitsomething(dmg)
if (dmg <= 0) return false
self.shield_refresh_ready = lframe + self.shieldpenalty
if self.shield >= dmg then
if self.shield > 0 then
self.shield -= dmg
self:ow(true)
if self.shield > 0 then
blip(self,12)
else
self.shield = 0
blip(self,7)
end
return false
end
dmg -= self.shield
self.shield = 0
self.hp -= dmg
if self.hp < 0 then
self:die()
return true
end
self:ow(false)
blip(self, self.friendly and 8 or 7)
return false
end
function ship_m:ow(shielded)
if (shielded) then
blip(self,12,3)
return
end
blip(self, 7, 3)
end
function ship_m:refresh_shield()
if (self.shield >= self.maxshield) return
if (lframe < self.shield_refresh_ready) return
@ -678,9 +676,105 @@ bullet_base = mknew{ }
gun_base = mknew{
shoot_ready = -32768,
icon = 20
icon = 20,
ammobonus = 1,
-- fractional frames of
-- cooldown reduction from
-- upgrades, not yet applied
cd_remainder = 0,
}
-- gun_base subtypes are
-- level-up options that,
-- as an action, assign
-- themselves to the player
function gun_base:action()
local item = self.new()
item:peel()
item.ammo = item.maxammo
if not primary_ship.special_guns then
primary_ship.special_guns = {item}
else
add(primary_ship.special_guns, item)
end
end
-- make shot type unique so
-- stat modifications do not
-- damage base data
function gun_base:peel()
self.munition = mknew(self.munition.new())
end
-- default firing behavior:
-- single shot
function gun_base:actually_shoot(x, y)
self.munition.new{}:spawn_at(x, y)
end
-- upgrade
function gun_base:small_upgrade_opts()
local ret = {
self:ammo_upgrade_opt(),
self:rate_upgrade_opt(),
}
local s = self.special_upgrade_opt
if (s) add(ret, s(self))
return ret
end
function gun_base:ammo_upgrade_opt()
local a=self.maxammo
local x=a\10+self.ammobonus
return {
icon=self.icon,
hdr=self.hdr,
body=[[--------AMMO
more shots
before you
run out.
is: ]]..tostr(a)..[[
add: ]]..tostr(x)..[[
----------
total: ]]..tostr(a+x),
action=function()
self.maxammo+=x
self.ammo+=x
end,
}
end
function gun_base:rate_upgrade_opt()
local c=self.cooldown<<16
local rawnewc=0.85*(c-self.cd_remainder)
local newc=ceil(rawnewc)
return {
icon=self.icon,
hdr=self.hdr,
body=[[--------RATE
reduce delay
between each
shot when
firing.
is: ]]..tostr(c)..[[f
minus: ]]..tostr(c-newc)..[[f
----------
total: ]]..tostr(newc)..[[f
remainder:
]]..sub(tostr(newc-rawnewc),0,5),
action=function()
self.cooldown=newc>>16
self.cd_remainder=newc-rawnewc
end,
}
end
function bullet_base:hitship(_)
self:die()
return true
@ -704,14 +798,6 @@ function bullet_base:draw()
spr(self.sprite, self.x, self.y, self.width, self.height)
end
-- An `actually_shoot` factory
-- for trivial guns
function spawn_one(t)
return function(gun, x, y)
t.new{}:spawn_at(x, y)
end
end
function bullet_base:spawn_at(x, y)
self.x = x - self.x_off
self.y = y - self.y_off
@ -763,13 +849,14 @@ zap_p = mknew(zap_e.new{
})
zap_gun_e = mknew(gun_base.new{
cooldown = 0x0.000a, -- frames between shots
ammo = nil, -- unlimited ammo - main gun
actually_shoot = spawn_one(zap_e),
cooldown = 0x0.0020, -- frames between shots
munition = zap_e,
})
zap_gun_p = mknew(zap_gun_e.new{
actually_shoot = spawn_one(zap_p),
icon = 19,
munition = zap_p,
hdr = "mAIN gUN",
})
blast = mknew(bullet_base.new{
@ -788,17 +875,22 @@ blast = mknew(bullet_base.new{
damage = 4,
dx = 0, -- px/frame
dy = -2,
dy = -1,
awaitcancel = false,
-- disable damage for 2 frames
-- disable damage for 4 frames
-- when hitting something
-- todo: rewrite all ship hit
-- logic so i can avoid
-- repeating hits to the
-- same ship instead of
-- using a cooldown
hitship = function(self, _)
if self.damage > 0 and not self.awaitcancel then
self.awaitcancel = true
once_next_frame(function()
new_events:push_back{
wait = 2,
wait = 4,
obj = self,
saved_dmg = self.damage,
move = function(self)
@ -819,10 +911,22 @@ blast = mknew(bullet_base.new{
blast_gun = mknew(gun_base.new{
icon = 13,
cooldown = 0x0.0020, -- frames between shots
cooldown = 0x0.0078, -- 120 frames between shots
ammo = 5,
maxammo = 5,
actually_shoot = spawn_one(blast),
munition = blast,
hdr = "bLASTER",
body= [[---------GUN
plasma orb
cuts through
enemies.
slow.
ammo: 5
rate: 1/2sec
dmg: 4
]],
})
protron_e = mknew(bullet_base.new{
@ -854,7 +958,7 @@ protron_p = mknew(protron_e.new{
protron_gun_e = mknew(gun_base.new{
icon = 25,
cooldown = 0x0.000f, -- frames between shots
cooldown = 0x0.0040, -- frames between shots
ammo = nil,
maxammo = nil,
munition = protron_e
@ -883,6 +987,19 @@ end
protron_gun_p = mknew(protron_gun_e.new{
munition = protron_p,
maxammo = 20,
cooldown = 0x0.0018,
hdr = "pROTRON",
body = [[---------GUN
spray shots
in a dense
arc.
ammo: 20
rate: 2/sec
dmg: 1
]],
})
vulcan_e = mknew(bullet_base.new{
@ -915,7 +1032,7 @@ vulcan_p = mknew(vulcan_e.new{
vulcan_gun_e = mknew(gun_base.new{
icon = 37,
enemy = false,
cooldown = 0x0.0002, -- frames between shots
cooldown = 0x0.0003, -- frames between shots
ammo = nil,
maxammo = nil,
munition=vulcan_e,
@ -934,6 +1051,17 @@ vulcan_gun_e = mknew(gun_base.new{
vulcan_gun_p = mknew(vulcan_gun_e.new{
munition=vulcan_p,
maxammo = 100,
hdr = "vULCAN",
body = [[---------GUN
rapidly fire
in a v.
ammo: 100
rate: 20/sec
dmg: 0.5
]],
})
-->8
@ -943,6 +1071,7 @@ firespark = split"9, 8, 2, 5, 1"
smokespark = split"13, 13, 5, 5"
player = mknew(ship_m.new{
friendly=true,
--shape
sprite = 1, --index of ship sprite
size = 1, --all ships are square; how many 8x8 sprites?
@ -967,10 +1096,11 @@ player = mknew(ship_m.new{
xptarget = 0x0.0004,
last_xp_frame = 0,
level = 1,
magnet = 10,
-- gun
main_gun = nil, -- assign at spawn time
special_gun = nil,
special_guns = nil,
fire_off_x = 4, -- offset where bullets come from
fire_off_y = 0,
@ -979,10 +1109,10 @@ player = mknew(ship_m.new{
y=96,
xmomentum = 0,
ymomentum = 0,
maxspd = 2.5, -- momentum cap
thrust = 0.25, -- momentum added from button
maxspd = 1.5, -- momentum cap
thrust = 0.1875, -- momentum added from button
ymin = 0, ymax = 120, -- stay on screen
drag = 0.125, -- momentum lost per frame
drag = 0.0625, -- momentum lost per frame
slip = false, -- does not slide down screen
act = function(self) -- fetch buttons
local b,th = btn(),self.thrust
@ -1009,6 +1139,110 @@ player = mknew(ship_m.new{
end,
})
function player:small_upgrade_opts()
local cdr, pr = (self.shieldcooldown - 0x0.000f) / 8, (self.shieldpenalty - 0x0.003c) / 9
if (cdr == 0 and self.shieldcooldown > 0x0.000f) cdr = 0x0.0001
if (pr == 0 and self.shieldpenalty > 0x0.003c) pr = 0x0.0001
local ret = {{
icon=53,
hdr="hull",
body=[[--------SHIP
survive more
unshielded
hits.
+2 hp]],
action=function()
self.maxhp += 2
self.hp += 2
end,
},{
icon=52,
hdr="capacity",
body=[[------SHIELD
shield can
absorb more
hits before
recharging.
+1 hp]],
action=function()
self.maxshield += 1
self.shield += 1
end,
},{
icon=1,
hdr="thrusters",
body=[[--------SHIP
move faster,
steer more
sharply.]],
action=function()
--maxspd thrust drag
self.maxspd += 0.5
self.thrust += 0.0625
self.drag += 0.03125
end,
},{
icon=20,
hdr="magnet",
body=[[--------SHIP
pick up xp
from further
away.]],
action=function ()
self.magnet += 2
end,
},
self.main_gun:rate_upgrade_opt(),
}
if cdr > 0 then
add(ret, {
icon = 6,
hdr = "recharge",
body=[[------SHIELD
shield will
recharge at
a faster
pace.
]] .. tostr(ceil(100 * cdr / self.shieldcooldown)) .. "% faster",
action = function()
self.shieldcooldown -= cdr
end
})
end
if pr > 0 then
add(ret, {
icon = 6,
hdr = "recovery",
body=[[------SHIELD
reduce the
delay after
a hit before
shield will
start to
recharge.
]] .. tostr(ceil(100 * pr / self.shieldpenalty)) .. "% shorter",
action = function()
self.shieldpenalty -= pr
end
})
end
return ret
end
frownie = mknew(ship_m.new{
--shape
sprite = 3, --index of ship sprite
@ -1113,6 +1347,7 @@ chasey = mknew(ship_m.new{
end
})
-- todo: use constraints
function chasey:act()
self.xmin = max(primary_ship.x-8, 0)
self.xmax = min(primary_ship.x + 8, 112 - 8*self.size)
@ -1345,32 +1580,9 @@ function spawn_blocking_spewy()
end
end
function spawn_bonus_frownie()
local f = spawn_frownie()
f.sprite = 7
f.die = function(self)
spawn_repair_at(self.x+4, self.y+4)
frownie.die(self)
end
end
function spawn_bonus_vulcan_chasey()
function spawn_vulcan_chasey()
local c = spawn_chasey()
c.main_gun=vulcan_gun_e.new{enemy=true}
c.die = function(self)
spawn_main_gun_at(self.x-1, self.y-1, vulcan_gun_p)
chasey.die(self)
end
c.sprite=4
return c
end
function spawn_bonus_shield_chasey()
local c = spawn_chasey()
c.die = function(self)
spawn_shield_upgrade_at(self.x-1, self.y-1)
chasey.die(self)
end
c.sprite=4
return c
end
@ -1419,7 +1631,6 @@ function spawn_rnd(typ, blocking, goodie,altspr)
freeze -= self.ice
self.ice=0
typ.die(self)
spawn_goodie(goodie, self.x, self.y, self.size)
end,
}
if (altspr) s.spr = altspr
@ -1427,14 +1638,6 @@ function spawn_rnd(typ, blocking, goodie,altspr)
return s
end
-- TODO: spawn_goodie compatible versions of gun drops
-- TODO: goodie table
function spawn_goodie(goodie_name, x, y, sz)
if (not goodie_name or #goodie_name == 0) return
local sh = sz and sz/2 or 0
_ENV[goodie_name].new{}:spawn_at(x+sh,y+sh)
end
function multi(times, interval, fnm, ...)
local f,irm,vargs = _ENV[fnm],interval,pack(...)
assert(type(f) == "function", fnm.." not a function")
@ -1457,31 +1660,29 @@ end
-- where offset,eol is a special case.
example_level_csv=[[1,spawn_frownie
60,spawn_bonus_vulcan_chasey
60,spawn_vulcan_chasey
61,spawn_blocky
85,spawn_spewy
100,spawn_spewy
115,spawn_spewy
130,spawn_bonus_frownie
145,spawn_spewy
200,spawn_bonus_shield_chasey
130,spawn_frownie
145,spawn_frownie
180,spawn_spewy
230,spawn_chasey
250,spawn_blocking_blocky
285,spawn_spec_gun_at,35,-11,blast_gun
310,spawn_blocking_blocky
310,spawn_blocking_blocky
310,spawn_blocking_blocky
311,spawn_frownie
350,spawn_main_gun_at,70,-11,protron_gun_p
401,spawn_frownie
420,spawn_blocking_frownie
430,spawn_bonus_vulcan_chasey
430,spawn_vulcan_chasey
450,spawn_frownie
465,spawn_bonus_frownie
465,spawn_frownie
480,spawn_chasey
500,multi,20,12,spawn_blocking_blocky
501,spawn_bonus_frownie
501,spawn_frownie
620,spawn_blocking_blocky
630,spawn_bonus_shield_chasey
630,spawn_vulcan_chasey
720,spawn_blocking_boss_chasey
721,eol]]
@ -1517,10 +1718,10 @@ function init_blip_pals()
end
end
function blip(obj, col, frames)
function blip(obj, col)
obj.fx_pal = blip_pals[col]
if (obj.___fx_pal_event) obj.___fx_pal_event:abort()
events:push_back(blip_fx.new{frames=frames, obj=obj})
events:push_back(blip_fx.new{frames=3, obj=obj})
end
bossspark = split"7,7,10,10,9,9,9,8,8,8,2,2,5,5"
@ -1603,11 +1804,22 @@ function xp_gem:draw()
)
end
function xp_gem:move()
if not primary_ship.dead and abs(self.x + 1 - primary_ship.x - primary_ship.hurt.x_off) <= primary_ship.magnet and abs(self.y + 1 - primary_ship.y - primary_ship.hurt.y_off) <= primary_ship.magnet then
if (self.x < primary_ship.x + 3) self.x += 1
if (self.x > primary_ship.x + 5) self.x -= 1
if (self.y < primary_ship.y + 3) self.y += 1
if (self.y > primary_ship.y + 5) self.y -= 1
end
return bullet_base.move(self)
end
-- todo: "magnetic" behavior
-- when near player ship
function xp_gem:hitship(ship)
if (ship ~= primary_ship) return false
if (ship ~= primary_ship or primary_ship.dead) return false
primary_ship.xp += self.val
primary_ship.last_xp_frame = lframe
return true
@ -1624,137 +1836,68 @@ function spawn_xp_at(x, y, off, amt)
}:spawn_at(mid(x, 0, 124),mid(y,-4,125))
end
powerup = mknew(bullet_base.new{
-- animated sprite array: "sprites"
-- to draw under or over anim,
-- override draw, draw the
-- under-part, call into
-- powerup.draw(self), then
-- draw the over-part
width = 1,
height = 1,
-- note: make hurtboxes larger
-- than sprite by 2px per side
-- since ship hitbox is tiny
-- but powerups should feel
-- easy to pick up
dx = 0,
dy = 0.75,
category = enemy_blt_cat, -- collides with player ship
damage = 0,
anim_speed = 2,
loop_pause = 30 -- affected by animspeed
})
-->8
-- upgrade options
-- sprite indexes for "sheen" animation
sheen8x8 = split"2,54,55,56,57,58,59,60,61"
-- all these return
-- a [2] of rearm_t:
--
-- icon: sprite id
-- hdr: title text
-- body: text
-- action: callback
-- (method)
function powerup:draw()
spr(self.sprites[max(1,
((lframe<<16)\self.anim_speed)
%(#self.sprites+self.loop_pause)
-self.loop_pause
+1)],
self.x, self.y,
self.width, self.height)
end
repair = mknew(powerup.new{
hurt = {
x_off = -2,
y_off = -2,
width = 12,
height = 12
},
x_off = 4,
y_off = 0,
sprites = sheen8x8,
icon = 53,
hitship = function(self, ship)
if (ship ~= primary_ship) return false
primary_ship.hp = min(primary_ship.maxhp, primary_ship.hp + 1)
return true
end,
draw = function(self)
spr(self.icon, self.x, self.y, self.width, self.height)
powerup.draw(self)
end
})
function spawn_repair_at(x, y)
repair.new():spawn_at(x, y)
end
shield_upgrade = mknew(repair.new{
icon=52
})
function shield_upgrade:hitship(ship)
if (ship ~= primary_ship) return false
primary_ship.maxshield += 1
return true
end
function spawn_shield_upgrade_at(x, y)
shield_upgrade.new():spawn_at(x,y)
end
gun_swap = mknew(powerup.new{
hurt = {
x_off = -2,
y_off = -2,
width = 16,
height = 16
},
-- gun = gun_type.new{}
x_off = 6,
y_off = 0,
width = 2,
height = 2,
sprites = {64, 66, 68, 70, 72, 74, 76, 78},
hitship = function(self, ship)
if (ship ~= primary_ship) return false
ship.main_gun = self.gun
return true
end,
draw = function(self)
powerup.draw(self)
spr(self.gun.icon, self.x+2, self.y+2, 1, 1)
end
})
function spawn_main_gun_at(x, y, gunt)
if (type(gunt)=="string") gunt=_ENV[gunt]
local gun_p = gun_swap.new{
gun = gunt.new()
}
gun_p:spawn_at(x, y)
end
spec_gun_pl = {
[1] = 2,
[14] = 6,
[2] = 14
spec_gunt = {
protron_gun_p,
vulcan_gun_p,
blast_gun,
}
function spawn_spec_gun_at(x, y, gunt)
if (type(gunt)=="string") gunt=_ENV[gunt]
local gun_p = gun_swap.new{
gun = gunt.new(),
hitship = function(self, ship)
if (ship ~= primary_ship) return false
ship.special_gun = self.gun
return true
end,
draw = function(self)
pal(spec_gun_pl)
powerup.draw(self)
pal()
spr(self.gun.icon, self.x+2, self.y+2, 1, 1)
end
}
gun_p:spawn_at(x, y)
-- picks n random items from
-- tbl; permutes tbl, selected
-- items at end
function pick(tbl, n)
local ret, top={}, #tbl
for x=top,top-n,-1 do
local idx = 1+rnd(x)\1
add(ret, tbl[idx])
tbl[idx]=tbl[x]
tbl[x]=ret[#ret]
end
return ret
end
-- add a new gun
function spec_gun_opts()
return pick(spec_gunt, 2)
end
-- major upgrades
function big_opts()
return {{
icon=1,
hdr="placeholder",
body="placeholder",
action = function() end,
},
{
icon=1,
hdr="placeholder",
body="placeholder",
action = function() end,
}}
end
-- ordinary upgrades
function small_opts()
-- todo: include gun opts
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
-->8
@ -1763,7 +1906,7 @@ end
rearm_mode = mknew{
sel=1,
bfm=1,
crt_frm = 1,
crt_frm = 0,
pos=-1,
init=function(this)
poke(0x5f5c, 255) --no btnp repeat
@ -1778,7 +1921,7 @@ function rearm_mode:glow_box(x0, y0, x1, y1, c, cf)
i -= 1
rect(x0+i,y0+i,x1-i,y1-i,v)
end
fillp(crt[self.crt_frm&0xff])
fillp(crt[1+(self.crt_frm&7)])
rectfill(x0+4, y0+4, x1-4, y1-4, cf)
fillp()
end
@ -1810,8 +1953,8 @@ end
function rearm_mode:draw_option(id)
local rec = self.options[id]
self:glow_box(0,0,55,100,self:frame_col(self.sel == id),1)
spr(rec.s,5, 5)
self:glow_box(0,0,55,101,self:frame_col(self.sel == id),1)
spr(rec.icon,5, 5)
print(rec.hdr, 13, 8, 7)
print(rec.body, 5, 15, 6)
end
@ -1828,17 +1971,14 @@ function rearm_mode:shuffle()
-- these will be placeholders
-- until the upgrade deck
-- is a thing that exists
self.options = {{
s=1,
hdr=" hull",
body = "\n +1\n max\n health",
action = function() end,
},{
s=37,
hdr=" vulc",
body = "\nplaceholder",
action = function() end,
}}
local lev = primary_ship.level + 1
if lev == 4 or lev == 12 then
self.options = spec_gun_opts()
elseif lev % 4 == 0 then
self.options = big_opts()
else
self.options = small_opts()
end
end
function rearm_mode:draw()
@ -1849,9 +1989,9 @@ function rearm_mode:draw()
camera(frac * -128 + (1-frac) * -56, 0)
self:draw_option(2)
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)
print("full ammo\nfull shield\n+50% health",54, 106, 6)
print("full ammo\nfull shield\n+50% health",54, 107, 6)
end
function rearm_mode:update_pos()
@ -1871,6 +2011,7 @@ function rearm_mode:update_pos()
end
function rearm_mode:update()
self.crt_frm+=0.25
self:update_pos()
if self.pos > 1 then
mode = game_mode
@ -1894,7 +2035,11 @@ function rearm_mode:update()
-- todo: sound: rearm
primary_ship.shield = primary_ship.maxshield
-- todo: rewrite for three guns
if (primary_ship.special_gun) primary_ship.special_gun.ammo = primary_ship.special_gun.max_ammo
local specs = primary_ship.special_guns
if specs then
specs[1].ammo = specs[1].maxammo
if (specs[2]) specs[2].ammo = specs[2].maxammo
end
primary_ship.hp = min(primary_ship.maxhp, primary_ship.hp + primary_ship.maxhp/2)
primary_ship.xp -= primary_ship.xptarget / 2
else
@ -1921,14 +2066,14 @@ __gfx__
0070070065666765000000000ddddd100b33355009444220c000000c03333350b7000000a800000008888820048488203bbaabb3288aa8820000000000000000
000000006506506500000000001111000b0b5050090920200c0000c00055550037000000a2000000008882000048420003bbbb30028888200000000000000000
00000000650000650000000000000000000b50000009200000c0cc00000000003b00000082000000000820000008200000333300002222000000000000000000
00000000000650000006500000000000b000000b80000000700000000bb0000008800000000000000009200000000000cccccccd000650000000000000000000
0000000000675000000765000000000000bbbb0080000000b0000000b76300008a920000000000009009200200000000c111111d006765000000000000000000
00000000006d6500006d6500000000000b0000b09000000030000000b663000089920000000550009994444200000000c111111d006d65000000000000000000
00000000067c6650067c6650000000000b0bb0b0a000000030000000033000000220000000576d009446544200000000c111111d067c66500000000000000000
00000000067d6650067d6650000000000b0bb0b00000000000000000000000000000000000566d009244442200000000c111111d067d66500000000000000000
000000005666657576667650000000000b0000b000000000000000000000000000000000000dd0009092220200000000c111111d656667650000000000000000
0000000056565066665656500000000000bbbb0000000000000000000000000000000000000000000090020000000000c111111d650650650000000000000000
00000000565000566500065000000000b000000b000000000000000000000000000000000000000000a00a0000000000cddddddd650000650000000000000000
0000000000065000000650000003b0000070070080000000700000000bb0000008800000000000000009200000000000cccccccd000650000000000000000000
000000000067500000076500000370000005500080000000b0000000b76300008a920000000000009009200200000000c111111d006765000000000000000000
00000000006d6500006d6500000b7000700660079000000030000000b663000089920000000550009994444200000000c111111d006d65000000000000000000
00000000067c6650067c6650000b7000056ccd50a000000030000000033000000220000000576d009446544200000000c111111d067c66500000000000000000
00000000067d6650067d6650000b7000056ccd500000000000000000000000000000000000566d009244442200000000c111111d067d66500000000000000000
000000005666657576667650000b7000700dd00700000000000000000000000000000000000dd0009092220200000000c111111d656667650000000000000000
000000005656506666565650000370000005500000000000000000000000000000000000000000000090020000000000c111111d650650650000000000000000
0000000056500056650006500003b00000700700000000000000000000000000000000000000000000a00a0000000000cddddddd650000650000000000000000
060007000600070006600770766c777c0000000000a0008000000000000000000000000000000000000000000000000000000000000000000000000000000000
6cd07cd06cd07cd06ccd7ccd6ccd7ccd000000000090008000000000000000000000000000000000000000000000000000000000000000000000000000000000
0d000d006cd07cd06ccd7ccd6ccd7ccd0000000000800a0000000000000000000000000000000000000000000000000000000000000000000000000000000000