Skip to content

Instantly share code, notes, and snippets.

@eevee
Created June 20, 2016 23:04
Show Gist options
  • Save eevee/d90b29891c53b016aba2b2672089be46 to your computer and use it in GitHub Desktop.
Save eevee/d90b29891c53b016aba2b2672089be46 to your computer and use it in GitHub Desktop.
some thoughts on augmenting zdoom's DECORATE with lua
ZombieMan = define_actor{
name = "ZombieMan",
health = 20,
radius = 20,
height = 56,
speed = 8,
-- Why is this an integer out of 256 instead of just a float chance?
pain_chance = 0.78125,
monster, -- TODO These property bundles are really weird
floorclip = true,
see_sound = "grund/sight",
attack_sound = "grunt/attack",
pain_sound = "grunt/pain",
death_sound = "grunt/death",
active_sound = "grunt/active",
obituary = "$OB_ZOMBIE",
drop_items = {
-- Note that these get their own namespace! You can probably use a
-- string if you really want to, to avoid circular dependency problems,
-- but this is a little more typo-proof.
{ actor_classes.Clip },
},
states = {
-- Obviously it's not particularly nice to define an entire actor like
-- this; just saying, it's a thing that could be done. There'll have
-- to be a delay mechanism for ACS, anyway, so it might as well work
-- here too.
-- Major non-obvious downside is that you can't put a label in the
-- middle of this function or do jumps with numbers of states.
spawn = function()
while true do
for _, frame in ipairs{"A", "B"} do
self:set_sprite("POSS", frame)
self:look()
coroutine.yield(10)
end
end
end,
},
}
-- Alternatively, you might want to preserve the DECORATE style but put your
-- more complex code in Lua. Let's say you're implementing ZombieMan, which
-- has a frame like this:
--
-- POSS F 8 A_PosAttack
--
-- A_PosAttack is just a combination of two other action functions. So let's
-- do this instead:
--
-- POSS F 8 self:missile_attack()
--
-- And now in Lua, we just have to define that method (or we'll get an error):
function actor_classes.ZombieMan:missile_attack()
A_PlaySound("grunt/attack") -- or self.attack_sound
-- Look, ma, named arguments!
A_CustomBulletAttack{
horz_spread = 22.5,
vert_spread = 0,
num_bullets = 1,
damage = random(1, 5) * 3,
pufftype = actor_classes.BulletPuff,
-- And no flags with piles of constants!
random_damage = false,
}
-- My thinking here is that the action functions can take an extra argument
-- that's a table containing named arguments, so that COULD have been
-- written:
A_CustomBulletAttack(22.5, 0, 1, random(1,5) * 3, "BulletPuff", 0, A_CustomBulletAttack.NORANDOM)
-- Or:
A_CustomBulletAttack(22.5, 0, 1, random(1,5) * 3, "BulletPuff", { random_damage = false })
-- Or however else you like.
end
-- Some other thoughts:
-- * These aren't mutually exclusive ideas; there's no reason you couldn't
-- still have DECORATE, /and/ be able to call lua functions directly, /and/
-- be able to have those functions be coroutines, /and/ be able to declare
-- actor classes from scratch...
--
-- * I used `self:look()` in the first example, but `A_PlaySound` in the
-- second. It seems like action functions are somewhat method-ish, since
-- they're things the actors do, but there are also a preposterous number of
-- them. Maybe they should just always take the actor as the first argument
-- (which would also remove the need for actor pointer constants in a lot of
-- cases).
--
-- * Can you define new actor classes at runtime? During a map? Can you
-- modify actor classes on the fly? Would any of this actually work?
--
-- * Can an actor method like `missile_attack` yield? If not, how would you
-- create a "hybrid" class that's defined in DECORATE but has some fancy Lua
-- coro stuff tacked on?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment