Lua formatting.

This commit is contained in:
Daniel Schmidt 2023-05-01 21:22:44 +02:00
parent f968f26135
commit dd2ea203d2
14 changed files with 756 additions and 1834 deletions

32
.lua-format Normal file
View File

@ -0,0 +1,32 @@
column_limit: 140
indent_width: 4
use_tab: false
tab_width: 4
continuation_indent_width: 4
spaces_before_call: 1
keep_simple_control_block_one_line: false
keep_simple_function_one_line: false
align_args: true
break_after_functioncall_lp: false
break_before_functioncall_rp: false
spaces_inside_functioncall_parens: false
spaces_inside_functiondef_parens: false
align_parameter: true
chop_down_parameter: false
break_after_functiondef_lp: false
break_before_functiondef_rp: false
align_table_field: true
break_after_table_lb: true
break_before_table_rb: true
chop_down_table: false
chop_down_kv_table: true
table_sep: ","
column_table_limit: 0
extra_sep_at_table_end: false
spaces_inside_table_braces: true
break_after_operator: true
double_quote_to_single_quote: false
single_quote_to_double_quote: false
spaces_around_equals_in_field: true
line_breaks_after_function_body: 1
line_separator: input

View File

@ -1,167 +1,147 @@
register_artifact("GIGANTIC_STRENGTH",
{
name = "Stone Of Gigantic Strength",
description = "Double all damage dealt.",
price = 250,
order = 0,
callbacks = {
on_damage_calc = function(ctx)
if ctx.target == ctx.owner then
return ctx.damage * 2
end
return nil
end,
}
register_artifact("GIGANTIC_STRENGTH", {
name = "Stone Of Gigantic Strength",
description = "Double all damage dealt.",
price = 250,
order = 0,
callbacks = {
on_damage_calc = function(ctx)
if ctx.target == ctx.owner then
return ctx.damage * 2
end
return nil
end
}
);
});
register_artifact("REPULSION_STONE",
{
name = "Repulsion Stone",
description = "For each damage taken heal for 2",
price = 100,
order = 0,
callbacks = {
on_damage = function(ctx)
if ctx.target == ctx.owner then
heal(ctx.owner, 2)
end
return nil
end,
}
register_artifact("REPULSION_STONE", {
name = "Repulsion Stone",
description = "For each damage taken heal for 2",
price = 100,
order = 0,
callbacks = {
on_damage = function(ctx)
if ctx.target == ctx.owner then
heal(ctx.owner, 2)
end
return nil
end
}
);
});
register_artifact("RADIANT_SEED",
{
name = "Radiant Seed",
description = "A small glowing seed.",
price = 140,
order = 0,
callbacks = {
on_pick_up = function(ctx)
give_card("RADIANT_SEED", ctx.owner)
return nil
end,
}
register_artifact("RADIANT_SEED", {
name = "Radiant Seed",
description = "A small glowing seed.",
price = 140,
order = 0,
callbacks = {
on_pick_up = function(ctx)
give_card("RADIANT_SEED", ctx.owner)
return nil
end
}
);
});
register_artifact("JUICY_FRUIT",
{
name = "Juicy Fruit",
description = "Tastes good and boosts your HP.",
price = 80,
order = 0,
callbacks = {
on_pick_up = function(ctx)
actor_add_max_hp(ctx.owner, 10)
return nil
end,
}
register_artifact("JUICY_FRUIT", {
name = "Juicy Fruit",
description = "Tastes good and boosts your HP.",
price = 80,
order = 0,
callbacks = {
on_pick_up = function(ctx)
actor_add_max_hp(ctx.owner, 10)
return nil
end
}
);
});
register_artifact("DEFLECTOR_SHIELD",
{
name = "Deflector Shield",
description = "Gain 8 block at the start of combat.",
price = 50,
order = 0,
callbacks = {
on_player_turn = function(ctx)
if ctx.round == 0 then
give_status_effect("BLOCK", ctx.owner, 8)
end
return nil
end,
}
register_artifact("DEFLECTOR_SHIELD", {
name = "Deflector Shield",
description = "Gain 8 block at the start of combat.",
price = 50,
order = 0,
callbacks = {
on_player_turn = function(ctx)
if ctx.round == 0 then
give_status_effect("BLOCK", ctx.owner, 8)
end
return nil
end
}
);
});
register_artifact("SHORT_RADIANCE",
{
name = "Short Radiance",
description = "Apply 1 vulnerable at the start of combat.",
price = 50,
order = 0,
callbacks = {
on_player_turn = function(ctx)
if ctx.round == 0 then
each(function(val)
give_status_effect("VULNERABLE", val)
end, pairs(get_opponent_guids(ctx.owner)))
end
return nil
end,
}
register_artifact("SHORT_RADIANCE", {
name = "Short Radiance",
description = "Apply 1 vulnerable at the start of combat.",
price = 50,
order = 0,
callbacks = {
on_player_turn = function(ctx)
if ctx.round == 0 then
each(function(val)
give_status_effect("VULNERABLE", val)
end, pairs(get_opponent_guids(ctx.owner)))
end
return nil
end
}
);
});
register_artifact("BAG_OF_HOLDING",
{
name = "Bag of Holding",
description = "Start with a additional card at the beginning of combat.",
price = 50,
order = 0,
callbacks = {
on_player_turn = function(ctx)
if ctx.owner == PLAYER_ID and ctx.round == 0 then
player_draw_card(1)
end
return nil
end,
}
register_artifact("BAG_OF_HOLDING", {
name = "Bag of Holding",
description = "Start with a additional card at the beginning of combat.",
price = 50,
order = 0,
callbacks = {
on_player_turn = function(ctx)
if ctx.owner == PLAYER_ID and ctx.round == 0 then
player_draw_card(1)
end
return nil
end
}
);
});
register_artifact("SPIKED_PLANT",
{
name = "Spiked Plant",
description = "Deal 2 damage back to enemy attacks.",
price = 50,
order = 0,
callbacks = {
on_damage = function(ctx)
if ctx.source ~= ctx.owner and ctx.owner == ctx.target then
deal_damage(ctx.owner, ctx.source, 2)
end
return nil
end,
}
register_artifact("SPIKED_PLANT", {
name = "Spiked Plant",
description = "Deal 2 damage back to enemy attacks.",
price = 50,
order = 0,
callbacks = {
on_damage = function(ctx)
if ctx.source ~= ctx.owner and ctx.owner == ctx.target then
deal_damage(ctx.owner, ctx.source, 2)
end
return nil
end
}
);
});
register_artifact("GOLD_CONVERTER",
{
name = "Gold Converter",
description = "Gain 10 extra gold for each killed enemy.",
price = 50,
order = 0,
callbacks = {
on_actor_die = function(ctx)
if ctx.owner == PLAYER_ID and ctx.owner == ctx.source then
give_player_gold(10)
end
return nil
end,
}
register_artifact("GOLD_CONVERTER", {
name = "Gold Converter",
description = "Gain 10 extra gold for each killed enemy.",
price = 50,
order = 0,
callbacks = {
on_actor_die = function(ctx)
if ctx.owner == PLAYER_ID and ctx.owner == ctx.source then
give_player_gold(10)
end
return nil
end
}
);
});
register_artifact("HOLY_GRAIL",
{
name = "Holy Grail",
description = "At the start of each turn, heal for 2 HP for each card in your hand.",
price = 150,
order = 100, -- Evaluate late so that other draw artifacts have priority.
callbacks = {
on_player_turn = function(ctx)
local num_cards = #get_cards(ctx.owner)
local heal_amount = num_cards * 2
heal(ctx.owner, ctx.owner, heal_amount)
return nil
end,
}
register_artifact("HOLY_GRAIL", {
name = "Holy Grail",
description = "At the start of each turn, heal for 2 HP for each card in your hand.",
price = 150,
order = 100, -- Evaluate late so that other draw artifacts have priority.
callbacks = {
on_player_turn = function(ctx)
local num_cards = #get_cards(ctx.owner)
local heal_amount = num_cards * 2
heal(ctx.owner, ctx.owner, heal_amount)
return nil
end
}
);
});

View File

@ -2,225 +2,213 @@ function highlight(val)
return text_underline(text_bold("[" .. tostring(val) .. "]"))
end
register_card("KILL",
{
name = "Kill",
description = "Debug Card",
state = function(ctx)
register_card("KILL", {
name = "Kill",
description = "Debug Card",
state = function(ctx)
return nil
end,
max_level = 0,
color = "#2f3e46",
need_target = true,
point_cost = 0,
price = -1,
callbacks = {
on_cast = function(ctx)
deal_damage(ctx.caster, ctx.target, 1000, true)
return nil
end,
max_level = 0,
color = "#2f3e46",
need_target = true,
point_cost = 0,
price = -1,
callbacks = {
on_cast = function(ctx)
deal_damage(ctx.caster, ctx.target, 1000, true)
return nil
end,
}
end
}
);
});
register_card("MELEE_HIT",
{
name = "Melee Hit",
description = "Use your bare hands to deal 5 (+3 for each upgrade) damage.",
state = function(ctx)
return "Use your bare hands to deal " .. highlight(5 + ctx.level * 3) .. " damage."
end,
max_level = 1,
color = "#2f3e46",
need_target = true,
point_cost = 1,
price = 30,
callbacks = {
on_cast = function(ctx)
deal_damage(ctx.caster, ctx.target, 5 + ctx.level * 3)
return nil
end,
}
}
);
register_card("RUPTURE",
{
name = "Rupture",
description = "Inflict your enemy with " .. highlight("Vulnerable") .. ".",
state = function(ctx)
register_card("MELEE_HIT", {
name = "Melee Hit",
description = "Use your bare hands to deal 5 (+3 for each upgrade) damage.",
state = function(ctx)
return "Use your bare hands to deal " .. highlight(5 + ctx.level * 3) .. " damage."
end,
max_level = 1,
color = "#2f3e46",
need_target = true,
point_cost = 1,
price = 30,
callbacks = {
on_cast = function(ctx)
deal_damage(ctx.caster, ctx.target, 5 + ctx.level * 3)
return nil
end,
max_level = 0,
color = "#cf532d",
need_target = true,
point_cost = 1,
price = 30,
callbacks = {
on_cast = function(ctx)
give_status_effect("VULNERABLE", ctx.target)
return nil
end,
}
end
}
);
});
register_card("BLOCK",
{
name = "Block",
description = "Shield yourself and gain 5 " .. highlight("block") .. ".",
state = function(ctx)
return "Shield yourself and gain " .. highlight(5 + ctx.level * 3) .. " block."
end,
max_level = 1,
color = "#219ebc",
need_target = false,
point_cost = 1,
price = 40,
callbacks = {
on_cast = function(ctx)
give_status_effect("BLOCK", ctx.caster, 5 + ctx.level * 3)
return nil
end,
}
register_card("RUPTURE", {
name = "Rupture",
description = "Inflict your enemy with " .. highlight("Vulnerable") .. ".",
state = function(ctx)
return "Inflict your enemy with " .. highlight(tostring(1 + ctx.level) .. " Vulnerable") .. "."
end,
max_level = 3,
color = "#cf532d",
need_target = true,
point_cost = 1,
price = 30,
callbacks = {
on_cast = function(ctx)
give_status_effect("VULNERABLE", ctx.target, 1 + ctx.level)
return nil
end
}
);
});
register_card("BLOCK_SPIKES",
{
name = "Block Spikes",
description = "Transforms " .. highlight("block") .. " to damage.",
state = function(ctx)
-- Fetch all BLOCK instances of owner
local blocks = fun.iter(pairs(get_actor_status_effects(ctx.owner)))
:map(get_status_effect_instance)
:filter(function(val) return val.type_id == "BLOCK" end)
:totable()
register_card("BLOCK", {
name = "Block",
description = "Shield yourself and gain 5 " .. highlight("block") .. ".",
state = function(ctx)
return "Shield yourself and gain " .. highlight(5 + ctx.level * 3) .. " block."
end,
max_level = 1,
color = "#219ebc",
need_target = false,
point_cost = 1,
price = 40,
callbacks = {
on_cast = function(ctx)
give_status_effect("BLOCK", ctx.caster, 5 + ctx.level * 3)
return nil
end
}
});
register_card("BLOCK_SPIKES", {
name = "Block Spikes",
description = "Transforms " .. highlight("block") .. " to damage.",
state = function(ctx)
-- Fetch all BLOCK instances of owner
local blocks = fun.iter(pairs(get_actor_status_effects(ctx.owner))):map(get_status_effect_instance):filter(function(val)
return val.type_id == "BLOCK"
end):totable()
-- Sum stacks to get damage
local damage = fun.iter(pairs(blocks)):reduce(function(acc, val)
return acc + val.stacks
end, 0)
return "Transforms block to " .. highlight(damage) .. " damage."
end,
max_level = 0,
color = "#895cd6",
need_target = true,
point_cost = 1,
price = 100,
callbacks = {
on_cast = function(ctx)
-- Fetch all BLOCK instances of caster
local blocks = fun.iter(pairs(get_actor_status_effects(ctx.caster))):map(get_status_effect_instance):filter(function(val)
return val.type_id == "BLOCK"
end):totable()
-- Sum stacks to get damage
local damage = fun.iter(pairs(blocks))
:reduce(function(acc, val) return acc + val.stacks end, 0)
local damage = fun.iter(pairs(blocks)):reduce(function(acc, val)
return acc + val.stacks
end, 0)
return "Transforms block to " .. highlight(damage) .. " damage."
end,
max_level = 0,
color = "#895cd6",
need_target = true,
point_cost = 1,
price = 100,
callbacks = {
on_cast = function(ctx)
-- Fetch all BLOCK instances of caster
local blocks = fun.iter(pairs(get_actor_status_effects(ctx.caster)))
:map(get_status_effect_instance)
:filter(function(val) return val.type_id == "BLOCK" end)
:totable()
if damage == 0 then
return "No block status effect present!"
end
-- Sum stacks to get damage
local damage = fun.iter(pairs(blocks))
:reduce(function(acc, val) return acc + val.stacks end, 0)
-- Remove BLOCKs
fun.iter(pairs(blocks)):for_each(function(val)
remove_status_effect(val.guid)
end)
if damage == 0 then
return "No block status effect present!"
end
-- Deal Damage
deal_damage(ctx.caster, ctx.target, damage)
-- Remove BLOCKs
fun.iter(pairs(blocks)):for_each(function(val) remove_status_effect(val.guid) end)
-- Deal Damage
deal_damage(ctx.caster, ctx.target, damage)
return nil
end,
}
}
);
register_card("SHIELD_BASH",
{
name = "Shield Bash",
description = "Deal 4 (+2 for each upgrade) damage to the enemy and gain " .. highlight("block") .. " status effect equal to the damage dealt.",
state = function(ctx)
return "Deal " .. highlight(4 + ctx.level * 2) .. " damage to the enemy and gain " .. highlight("block") .. " status effect equal to the damage dealt."
end,
max_level = 1,
color = "#ff5722",
need_target = true,
point_cost = 1,
price = 40,
callbacks = {
on_cast = function(ctx)
local damage = deal_damage(ctx.caster, 4 + ctx.level * 2)
give_status_effect("BLOCK", ctx.caster, damage)
return nil
end,
}
}
);
register_card("FEAR",
{
name = "Fear",
description = "Inflict " .. highlight("fear") .. " on the target, causing them to miss their next turn.",
state = function(ctx)
return nil
end,
max_level = 0,
color = "#725e9c",
need_target = true,
point_cost = 2,
price = 80,
callbacks = {
on_cast = function(ctx)
give_status_effect("FEAR", ctx.target)
return nil
end,
}
end
}
);
});
register_card("RADIANT_SEED",
{
name = "Radiant Seed",
description = "Inflict 10 (+2 for each upgrade) damage to all enemies, but also causes 5 (-2 for each upgrade) damage to the caster.",
state = function(ctx)
return "Inflict " .. highlight(10 + ctx.level * 2) .. " damage to all enemies, but also causes " .. highlight(5 - ctx.level * 2) .. " damage to the caster."
end,
max_level = 1,
color = "#82c93e",
need_target = false,
point_cost = 2,
price = 120,
callbacks = {
on_cast = function(ctx)
-- Deal damage to caster without any modifiers applying
deal_damage(ctx.caster, ctx.caster, 5 - ctx.level * 2, true)
-- Deal damage to opponents
deal_damage_multi(ctx.caster, get_opponent_guids(ctx.caster), 10 + ctx.level * 2)
return nil
end,
}
register_card("SHIELD_BASH", {
name = "Shield Bash",
description = "Deal 4 (+2 for each upgrade) damage to the enemy and gain " .. highlight("block") ..
" status effect equal to the damage dealt.",
state = function(ctx)
return "Deal " .. highlight(4 + ctx.level * 2) .. " damage to the enemy and gain " .. highlight("block") ..
" status effect equal to the damage dealt."
end,
max_level = 1,
color = "#ff5722",
need_target = true,
point_cost = 1,
price = 40,
callbacks = {
on_cast = function(ctx)
local damage = deal_damage(ctx.caster, 4 + ctx.level * 2)
give_status_effect("BLOCK", ctx.caster, damage)
return nil
end
}
);
});
register_card("BERSERKER_RAGE",
{
name = "Berserker Rage",
description = "Gain " .. highlight("3 energy") .. ", but take 30% (-10% per level) of your HP as damage.",
state = function(ctx)
return "Gain " .. highlight("3 energy") .. ", but take " .. highlight(tostring(30 - ctx.level * 10) .. "%") .. " (" .. tostring(get_player().hp * (0.3 - ctx.level * 0.1)) .. ") of your HP as damage."
end,
max_level = 0,
color = "#d8a448",
need_target = false,
point_cost = 0,
price = 100,
callbacks = {
on_cast = function(ctx)
player_give_action_points(3)
deal_damage(ctx.caster, ctx.caster, get_player().hp * (0.3 - ctx.level * 0.1), true)
return nil
end,
}
register_card("FEAR", {
name = "Fear",
description = "Inflict " .. highlight("fear") .. " on the target, causing them to miss their next turn.",
state = function(ctx)
return nil
end,
max_level = 0,
color = "#725e9c",
need_target = true,
point_cost = 2,
price = 80,
callbacks = {
on_cast = function(ctx)
give_status_effect("FEAR", ctx.target)
return nil
end
}
);
});
register_card("RADIANT_SEED", {
name = "Radiant Seed",
description = "Inflict 10 (+2 for each upgrade) damage to all enemies, but also causes 5 (-2 for each upgrade) damage to the caster.",
state = function(ctx)
return "Inflict " .. highlight(10 + ctx.level * 2) .. " damage to all enemies, but also causes " .. highlight(5 - ctx.level * 2) ..
" damage to the caster."
end,
max_level = 1,
color = "#82c93e",
need_target = false,
point_cost = 2,
price = 120,
callbacks = {
on_cast = function(ctx)
-- Deal damage to caster without any modifiers applying
deal_damage(ctx.caster, ctx.caster, 5 - ctx.level * 2, true)
-- Deal damage to opponents
deal_damage_multi(ctx.caster, get_opponent_guids(ctx.caster), 10 + ctx.level * 2)
return nil
end
}
});
register_card("BERSERKER_RAGE", {
name = "Berserker Rage",
description = "Gain " .. highlight("3 energy") .. ", but take 30% (-10% per level) of your HP as damage.",
state = function(ctx)
return "Gain " .. highlight("3 energy") .. ", but take " .. highlight(tostring(30 - ctx.level * 10) .. "%") .. " (" ..
tostring(get_player().hp * (0.3 - ctx.level * 0.1)) .. ") of your HP as damage."
end,
max_level = 0,
color = "#d8a448",
need_target = false,
point_cost = 0,
price = 100,
callbacks = {
on_cast = function(ctx)
player_give_action_points(3)
deal_damage(ctx.caster, ctx.caster, get_player().hp * (0.3 - ctx.level * 0.1), true)
return nil
end
}
});

View File

@ -10,141 +10,130 @@ function cast_random(guid, target)
end
end
register_enemy(
"DUMMY",
{
name = "Dummy",
description = "End me...",
look = "DUM",
color = "#deeb6a",
initial_hp = 100,
max_hp = 100,
callbacks = {
on_turn = function(ctx)
return nil
end
}
register_enemy("DUMMY", {
name = "Dummy",
description = "End me...",
look = "DUM",
color = "#deeb6a",
initial_hp = 100,
max_hp = 100,
callbacks = {
on_turn = function(ctx)
return nil
end
}
)
})
register_enemy(
"RUST_MITE",
{
name = "Rust Mite",
description = "Loves to eat metal.",
look = "/v\\",
color = "#e6e65a",
initial_hp = 22,
max_hp = 22,
gold = 10,
intend = function(ctx)
register_enemy("RUST_MITE", {
name = "Rust Mite",
description = "Loves to eat metal.",
look = "/v\\",
color = "#e6e65a",
initial_hp = 22,
max_hp = 22,
gold = 10,
intend = function(ctx)
if ctx.round % 4 == 0 then
return "Gather strength"
end
return "Deal " .. highlight(6) .. " damage"
end,
callbacks = {
on_turn = function(ctx)
if ctx.round % 4 == 0 then
return "Gather strength"
end
return "Deal " .. highlight(6) .. " damage"
end,
callbacks = {
on_turn = function(ctx)
if ctx.round % 4 == 0 then
give_status_effect("RITUAL", ctx.guid)
else
deal_damage(ctx.guid, PLAYER_ID, 6)
end
return nil
end
}
}
)
register_enemy(
"CLEAN_BOT",
{
name = "Cleaning Bot",
description = "It never stopped cleaning...",
look = [[ \_/
(* *)
)#(]],
color = "#32a891",
initial_hp = 25,
max_hp = 25,
gold = 15,
intend = function(ctx)
local self = get_actor(ctx.guid)
if self.hp <= 8 then
return "Block " .. highlight(4)
end
return "Deal " .. highlight(7) .. " damage"
end,
callbacks = {
on_player_turn = function(ctx)
local self = get_actor(ctx.guid)
if self.hp <= 8 then
give_status_effect("BLOCK", ctx.guid, 4)
end
end,
on_turn = function(ctx)
local self = get_actor(ctx.guid)
if self.hp > 8 then
deal_damage(ctx.guid, PLAYER_ID, 7)
end
return nil
end
}
}
)
register_enemy(
"SHADOW_ASSASSIN",
{
name = "Shadow Assassin",
description = "A master of stealth and deception.",
look = "???",
color = "#6c5b7b",
initial_hp = 20,
max_hp = 20,
gold = 30,
intend = function(ctx)
local bleeds = fun.iter(pairs(get_actor_status_effects(PLAYER_ID)))
:map(get_status_effect_instance)
:filter(function(val) return val.type_id == "BLEED" end)
:totable()
if #bleeds > 0 then
return "Deal " .. highlight(10) .. " damage"
elseif ctx.round % 3 == 0 then
return "Inflict bleed"
give_status_effect("RITUAL", ctx.guid)
else
return "Deal " .. highlight(5) .. " damage"
deal_damage(ctx.guid, PLAYER_ID, 6)
end
return nil
end,
callbacks = {
on_turn = function(ctx)
-- Count bleed stacks
local bleeds = fun.iter(pairs(get_actor_status_effects(PLAYER_ID)))
:map(get_status_effect_instance)
:filter(function(val) return val.type_id == "BLEED" end)
:totable()
if #bleeds > 0 then -- If bleeding do more damage
deal_damage(ctx.guid, PLAYER_ID, 10)
elseif ctx.round % 3 == 0 then -- Try to bleed every 2 rounds with 3 dmg
if deal_damage(ctx.guid, PLAYER_ID, 3) > 0 then
give_status_effect("BLEED", PLAYER_ID, 2)
end
else -- Just hit with 5 damage
deal_damage(ctx.guid, PLAYER_ID, 5)
end
return nil
end
}
end
}
)
})
register_enemy("CLEAN_BOT", {
name = "Cleaning Bot",
description = "It never stopped cleaning...",
look = [[ \_/
(* *)
)#(]],
color = "#32a891",
initial_hp = 25,
max_hp = 25,
gold = 15,
intend = function(ctx)
local self = get_actor(ctx.guid)
if self.hp <= 8 then
return "Block " .. highlight(4)
end
return "Deal " .. highlight(7) .. " damage"
end,
callbacks = {
on_player_turn = function(ctx)
local self = get_actor(ctx.guid)
if self.hp <= 8 then
give_status_effect("BLOCK", ctx.guid, 4)
end
end,
on_turn = function(ctx)
local self = get_actor(ctx.guid)
if self.hp > 8 then
deal_damage(ctx.guid, PLAYER_ID, 7)
end
return nil
end
}
})
register_enemy("SHADOW_ASSASSIN", {
name = "Shadow Assassin",
description = "A master of stealth and deception.",
look = "???",
color = "#6c5b7b",
initial_hp = 20,
max_hp = 20,
gold = 30,
intend = function(ctx)
local bleeds = fun.iter(pairs(get_actor_status_effects(PLAYER_ID))):map(get_status_effect_instance):filter(function(val)
return val.type_id == "BLEED"
end):totable()
if #bleeds > 0 then
return "Deal " .. highlight(10) .. " damage"
elseif ctx.round % 3 == 0 then
return "Inflict bleed"
else
return "Deal " .. highlight(5) .. " damage"
end
return nil
end,
callbacks = {
on_turn = function(ctx)
-- Count bleed stacks
local bleeds = fun.iter(pairs(get_actor_status_effects(PLAYER_ID))):map(get_status_effect_instance):filter(function(val)
return val.type_id == "BLEED"
end):totable()
if #bleeds > 0 then
-- If bleeding do more damage
deal_damage(ctx.guid, PLAYER_ID, 10)
elseif ctx.round % 3 == 0 then
-- Try to bleed every 2 rounds with 3 dmg
if deal_damage(ctx.guid, PLAYER_ID, 3) > 0 then
give_status_effect("BLEED", PLAYER_ID, 2)
end
else
-- Just hit with 5 damage
deal_damage(ctx.guid, PLAYER_ID, 5)
end
return nil
end
}
})

View File

@ -1,39 +1,34 @@
--
-- Base Events
--
register_event(
"MERCHANT",
{
name = "A strange figure",
description = [[The merchant is a tall, lanky figure draped in a long, tattered coat made of plant fibers and animal hides. Their face is hidden behind a mask made of twisted roots and vines, giving them an unsettling, almost alien appearance.
register_event("MERCHANT", {
name = "A strange figure",
description = [[The merchant is a tall, lanky figure draped in a long, tattered coat made of plant fibers and animal hides. Their face is hidden behind a mask made of twisted roots and vines, giving them an unsettling, almost alien appearance.
Despite their strange appearance, the merchant is a shrewd negotiator and a skilled trader. They carry with them a collection of bizarre and exotic items, including plant-based weapons, animal pelts, and strange, glowing artifacts that seem to pulse with an otherworldly energy.
The merchant is always looking for a good deal, and they're not above haggling with potential customers...]],
choices = {
{
description = "Trade",
callback = function()
return GAME_STATE_MERCHANT
end
},
{
description = "Pass",
callback = function()
return GAME_STATE_RANDOM
end
}
},
on_end = function(choice) return nil end,
choices = {
{
description = "Trade",
callback = function()
return GAME_STATE_MERCHANT
end
}, {
description = "Pass",
callback = function()
return GAME_STATE_RANDOM
end
}
)
},
on_end = function(choice)
return nil
end
})
register_event(
"START",
{
name = "Waking up...",
description = [[
register_event("START", {
name = "Waking up...",
description = [[
```
@ -57,74 +52,78 @@ You try to remember how you ended up here, but your memories are hazy and fragme
As you struggle to gather your bearings, you notice a blinking panel on the wall, with the words *"Cryo Sleep Malfunction"* displayed in bold letters. It seems that the system has finally detected the error that caused your prolonged slumber and triggered your awakening.
**Shortly after you realize that you are not alone...**]],
choices = {
{
description = "Try to escape the facility before it finds you...",
callback = function()
-- Try to escape
if math.random() < 0.5 then
set_event("FIRST_OUTSIDE")
return GAME_STATE_EVENT
end
choices = {
{
description = "Try to escape the facility before it finds you...",
callback = function()
-- Try to escape
if math.random() < 0.5 then
set_event("FIRST_OUTSIDE")
return GAME_STATE_EVENT
end
-- Let OnEnd handle the state change
return nil
end
},
{
description = "Gather your strength and attack it!",
callback = function() return nil end
}
},
on_enter = function()
play_music("energetic_orthogonal_expansions")
-- Let OnEnd handle the state change
return nil
end
}, {
description = "Gather your strength and attack it!",
callback = function()
return nil
end
}
},
on_enter = function()
play_music("energetic_orthogonal_expansions")
-- Give the player it's start cards
give_card("MELEE_HIT", PLAYER_ID)
give_card("MELEE_HIT", PLAYER_ID)
give_card("MELEE_HIT", PLAYER_ID)
give_card("RUPTURE", PLAYER_ID)
give_card("BLOCK", PLAYER_ID)
give_artifact(get_random_artifact_type(150), PLAYER_ID)
end,
on_end = function()
return GAME_STATE_RANDOM
end,
}
)
-- Give the player it's start cards
give_card("MELEE_HIT", PLAYER_ID)
give_card("MELEE_HIT", PLAYER_ID)
give_card("MELEE_HIT", PLAYER_ID)
give_card("MELEE_HIT", PLAYER_ID)
give_card("MELEE_HIT", PLAYER_ID)
give_card("RUPTURE", PLAYER_ID)
give_card("BLOCK", PLAYER_ID)
give_card("BLOCK", PLAYER_ID)
give_card("BLOCK", PLAYER_ID)
give_artifact(get_random_artifact_type(150), PLAYER_ID)
end,
on_end = function()
return GAME_STATE_RANDOM
end
})
--
-- Stage 1 Entrance
--
register_event(
"FIRST_OUTSIDE",
{
name = "Outside",
description = [[You finally find a way leading to the outside, a narrow tunnel that winds its way through the thick layer of earth and rock above the facility. The tunnel is cramped and claustrophobic, and you have to crawl on your hands and knees for what feels like hours.
register_event("FIRST_OUTSIDE", {
name = "Outside",
description = [[You finally find a way leading to the outside, a narrow tunnel that winds its way through the thick layer of earth and rock above the facility. The tunnel is cramped and claustrophobic, and you have to crawl on your hands and knees for what feels like hours.
As you near the end of the tunnel, you feel a surge of excitement mixed with fear. What will you find on the other side? Will there be other survivors, or only mutated creatures and plants?
Finally, you emerge into the open air, blinking in the bright sunlight. The landscape that stretches out before you is both familiar and alien, a mix of twisted and mutated plant life, towering rock formations, and ruined remnants of the old world.
You take a deep breath of the fresh air, feeling the warmth of the sun on your face. You know that the journey ahead will be long and perilous, but you're determined to explore this new world and uncover its secrets. **The adventure has only just begun.**]],
choices = {
{
description = "Go...",
callback = function() return nil end
}
},
on_end = function()
return GAME_STATE_RANDOM
end,
}
)
register_event(
"THE_WASTELAND",
choices = {
{
name = "The Wasteland",
description = [[
description = "Go...",
callback = function()
return nil
end
}
},
on_end = function()
return GAME_STATE_RANDOM
end
})
register_event("THE_WASTELAND", {
name = "The Wasteland",
description = [[
```
|==| ~
_.,-*~'^'~*-,._ ( ~ _.,-*~'^'~*-,._ ~ (())
@ -137,23 +136,22 @@ register_event(
You finally find a way leading to the outside, and with a deep breath, you step out into the unforgiving wasteland.
The scorching sun beats down on you as the sand whips against your skin, a reminder of the horrors that have befallen the world. In the distance, the remains of once-great cities jut up from the ground like jagged teeth, now nothing more than crumbling ruins. The air is thick with the acrid smell of decay and the oppressive silence is only broken by the occasional howl of some mutated creature. As you take your first steps into this new world, you realize that survival will not be easy, and that the journey ahead will be fraught with danger at every turn...]],
choices = {
{
description = "Go...",
callback = function() return nil end
}
},
on_end = function()
return GAME_STATE_RANDOM
end,
}
)
register_event(
"THE_CORE",
choices = {
{
name = "The Wasteland",
description = [[
description = "Go...",
callback = function()
return nil
end
}
},
on_end = function()
return GAME_STATE_RANDOM
end
})
register_event("THE_CORE", {
name = "The Wasteland",
description = [[
```
________ ______
/_ __/ /_ ___ / ____/___ ________
@ -165,33 +163,33 @@ register_event(
You finally find a way you thought would lead to the outside, only to discover that you're still inside the massive facility known as "The Core."
As you step out of the cryo facility, the eerie silence is broken by the sound of metal scraping against metal and distant whirring of malfunctioning machinery. The flickering lights and sparks from faulty wires cast a sickly glow on the cold metal walls. You realize that this place is not as deserted as you initially thought, and the unsettling feeling in your gut only grows stronger as you make your way through the dimly lit corridors, surrounded by the echoes of your own footsteps and the sound of flickering computer screens.]],
choices = {
{
description = "Go...",
callback = function() return nil end
}
},
on_end = function()
return GAME_STATE_RANDOM
end,
}
)
register_event(
"BIO_KINGDOM",
choices = {
{
name = "Bio Kingdom",
description = [[You finally find a way leading to the outside, and step out of the cryo facility into a world you no longer recognize.
description = "Go...",
callback = function()
return nil
end
}
},
on_end = function()
return GAME_STATE_RANDOM
end
})
register_event("BIO_KINGDOM", {
name = "Bio Kingdom",
description = [[You finally find a way leading to the outside, and step out of the cryo facility into a world you no longer recognize.
The air is thick with humidity and the sounds of the jungle are overwhelming. Strange, mutated plants tower over you, their vines twisting and tangling around each other in a macabre dance. The colors of the leaves and flowers are sickly, a greenish hue that reminds you of illness rather than life. The ruins of buildings are visible in the distance, swallowed up by the overgrowth. You can hear the chirping and buzzing of insects, but it's mixed with something else - something that sounds almost like whispers or moans. The "jungle" seems to be alive, but not in any way that you would have imagined.]],
choices = {
{
description = "Go...",
callback = function() return nil end
}
},
on_end = function()
return GAME_STATE_RANDOM
end,
choices = {
{
description = "Go...",
callback = function()
return nil
end
}
)
},
on_end = function()
return GAME_STATE_RANDOM
end
})

View File

@ -11,9 +11,11 @@ function create_artifact_choice(artifacts, options)
end
}
end):totable()
choices[#choices+1] = {
choices[#choices + 1] = {
description = "Skip...",
callback = function() return nil end
callback = function()
return nil
end
}
local def = {
@ -22,7 +24,7 @@ function create_artifact_choice(artifacts, options)
choices = choices,
on_end = function()
return GAME_STATE_RANDOM
end,
end
}
if options ~= nil then
@ -57,9 +59,11 @@ function create_card_choice(cards, options)
end
}
end):totable()
choices[#choices+1] = {
choices[#choices + 1] = {
description = "Skip...",
callback = function() return nil end
callback = function()
return nil
end
}
local def = {
@ -68,7 +72,7 @@ function create_card_choice(cards, options)
choices = choices,
on_end = function()
return GAME_STATE_RANDOM
end,
end
}
if options ~= nil then
@ -88,4 +92,4 @@ function create_card_choice(cards, options)
register_event(id, def)
return id
end
end

View File

@ -1,7 +1,6 @@
--
-- Negative Status Effects
--
register_status_effect("WEAKEN", {
name = "Weaken",
description = "Weakens damage for each stack",
@ -19,7 +18,7 @@ register_status_effect("WEAKEN", {
return ctx.damage - ctx.stacks * 2
end
return ctx.damage
end,
end
}
})
@ -40,7 +39,7 @@ register_status_effect("VULNERABLE", {
return ctx.damage * (1.0 + 0.25 * ctx.stacks)
end
return ctx.damage
end,
end
}
})
@ -59,7 +58,7 @@ register_status_effect("BURN", {
on_turn = function(ctx)
deal_damage(ctx.guid, ctx.owner, ctx.stacks * 2, true)
return nil
end,
end
}
})
@ -84,7 +83,7 @@ register_status_effect("STRENGTH", {
return ctx.damage + ctx.stacks
end
return ctx.damage
end,
end
}
})
@ -107,7 +106,7 @@ register_status_effect("BLOCK", {
return ctx.damage - ctx.stacks
end
return ctx.damage
end,
end
}
})
@ -126,7 +125,7 @@ register_status_effect("RITUAL", {
on_player_turn = function(ctx)
local guid = give_status_effect("STRENGTH", ctx.owner)
set_status_effect_stacks(guid, 3 + ctx.stacks)
end,
end
}
})
@ -144,7 +143,7 @@ register_status_effect("FEAR", {
callbacks = {
on_turn = function(ctx)
return true
end,
end
}
})
@ -162,6 +161,6 @@ register_status_effect("BLEED", {
callbacks = {
on_turn = function(ctx)
return true
end,
end
}
})

View File

@ -49,13 +49,7 @@ After some effort, you manage to open the door and find yourself in a small room
-- Stage 1
--
stage_2 = {
fights = {
{ "RUST_MITE", "RUST_MITE", "RUST_MITE" },
{ "SHADOW_ASSASSIN", "SHADOW_ASSASSIN" },
{ "SHADOW_ASSASSIN" }
}
}
stage_2 = { fights = { { "RUST_MITE", "RUST_MITE", "RUST_MITE" }, { "SHADOW_ASSASSIN", "SHADOW_ASSASSIN" }, { "SHADOW_ASSASSIN" } } }
register_story_teller("STAGE_1", {
active = function(ctx)
@ -127,4 +121,4 @@ register_story_teller("STAGE_3", {
return GAME_STATE_FIGHT
end
})
})

5
docs/LIFECYCLE.md Normal file
View File

@ -0,0 +1,5 @@
# Lifecycle
## Round
![Fight](./diagrams/fight.svg)

File diff suppressed because it is too large Load Diff

24
docs/diagrams/fight.d2 Normal file
View File

@ -0,0 +1,24 @@
shape: sequence_diagram
User
Session
Lua
User."Init"
User.t1 -> Session.t1: "SetupFight()"
Session.t1 -> Session.t1: "Create clean fight state"
Session.t1 -> Lua: "Trigger OnPlayerTurn"
User.t1 <- Session.t1
User."Repeat"
User.mid -> Session.mid: "PlayerCastHand() etc."
Session.mid -> Lua: "Trigger OnDamage etc."
User.mid <- Session.mid
User.t2 -> Session.t2: "FinishPlayerTurn()"
Session.t2 -> Lua: "Trigger OnTurn"
Session.t2 -> Session.t2: "Update and remove status effects"
Session.t2 -> Lua: "Trigger OnPlayerTurn"
User.t2 <- Session.t2

110
docs/diagrams/fight.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 25 KiB

6
format-lua.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
for file in ./assets/scripts/*.lua; do
echo "Formatting: $file"
lua-format "$file" -i
done