feat: correct seeding

This commit is contained in:
Daniel Schmidt 2024-08-27 23:14:00 +02:00
parent 98da619522
commit 275460002e
18 changed files with 198 additions and 71 deletions

View File

@ -12,13 +12,13 @@ end
---highlight_warn some value with warning colors ---highlight_warn some value with warning colors
---@param val any ---@param val any
function highlight_warn(val) function highlight_warn(val)
return text_underline(text_bold(_escape_color("38;5;161") .. "[" .. tostring(val) .. "]" .. string.char(27) .. "[0m")) return text_underline(text_bold(_escape_color("38;5;161") .. "[" .. tostring(val) .. "]" .. string.char(27) .. "[0m"))
end end
---highlight_success some value with success colors ---highlight_success some value with success colors
---@param val any ---@param val any
function highlight_success(val) function highlight_success(val)
return text_underline(text_bold(_escape_color("38;5;119") .. "[" .. tostring(val) .. "]" .. string.char(27) .. "[0m")) return text_underline(text_bold(_escape_color("38;5;119") .. "[" .. tostring(val) .. "]" .. string.char(27) .. "[0m"))
end end
---choose_weighted chooses an item from a list of choices, with a weight for each item. ---choose_weighted chooses an item from a list of choices, with a weight for each item.
@ -33,7 +33,7 @@ function choose_weighted(choices, weights)
total_weight = total_weight + weight total_weight = total_weight + weight
end end
local random = math.random() * total_weight local random = random() * total_weight
for i, weight in ipairs(weights) do for i, weight in ipairs(weights) do
random = random - weight random = random - weight
if random <= 0 then if random <= 0 then
@ -83,27 +83,39 @@ end
---@param tags string[] ---@param tags string[]
---@return artifact[] ---@return artifact[]
function find_artifacts_by_tags(tags) function find_artifacts_by_tags(tags)
return find_by_tags(registered.artifact, tags) local found = find_by_tags(registered.artifact, tags)
table.sort(found, function(a, b) return a.id:upper() < b.id:upper() end)
return found
end end
---find_cards_by_tags find all cards with the given tags. ---find_cards_by_tags find all cards with the given tags.
---@param tags string[] ---@param tags string[]
---@return card[] ---@return card[]
function find_cards_by_tags(tags) function find_cards_by_tags(tags)
return find_by_tags(registered.card, tags) local found = find_by_tags(registered.card, tags)
table.sort(found, function(a, b) return a.id:upper() < b.id:upper() end)
return found
end end
---find_events_by_tags find all events with the given tags. ---find_events_by_tags find all events with the given tags.
---@param tags string[] ---@param tags string[]
---@return event[] ---@return event[]
function find_events_by_tags(tags) function find_events_by_tags(tags)
return find_by_tags(registered.event, tags) local found = find_by_tags(registered.event, tags)
--table.sort(found, function(a, b) return a.id:upper() < b.id:upper() end)
return found
end end
---choose_weighted_by_price choose a random item from the given list, weighted by price. ---choose_weighted_by_price choose a random item from the given list, weighted by price.
---@param items artifact|card ---@param items artifact|card
---@return string ---@return string
function choose_weighted_by_price(items) function choose_weighted_by_price(items)
table.sort(items, function(a, b)
if a.id == nil then
return a.type_id < b.type_id
end
return a.id < b.id
end)
return choose_weighted( return choose_weighted(
fun.iter(items):map(function(item) return item.id or item.type_id end):totable(), fun.iter(items):map(function(item) return item.id or item.type_id end):totable(),
fun.iter(items):map(function(item) return item.price end):totable() fun.iter(items):map(function(item) return item.price end):totable()

View File

@ -41,6 +41,16 @@ function fetch(key) end
---@return guid ---@return guid
function guid() end function guid() end
--- Returns a random number between 0 and 1
---@return number
function random() end
--- Returns a random number between min and max
---@param min number
---@param max number
---@return number
function random_int(min, max) end
--- Stores a persistent value for this run that will be restored after a save load. Can store any lua basic value or table. --- Stores a persistent value for this run that will be restored after a save load. Can store any lua basic value or table.
---@param key string ---@param key string
---@param value any ---@param value any

View File

@ -6,7 +6,7 @@ function cast_random(guid, target)
if #cards == 0 then if #cards == 0 then
print("can't cast_random with zero cards available!") print("can't cast_random with zero cards available!")
else else
cast_card(cards[math.random(#cards)], target) cast_card(cards[random_int(0, #cards)], target)
end end
end end

View File

@ -40,7 +40,7 @@ register_enemy("CYBER_SLIME", {
add_actor_by_enemy("CYBER_SLIME_MINION") add_actor_by_enemy("CYBER_SLIME_MINION")
add_actor_by_enemy("CYBER_SLIME_MINION") add_actor_by_enemy("CYBER_SLIME_MINION")
if math.random() < 0.25 then if random() < 0.25 then
add_actor_by_enemy("CYBER_SLIME_MINION") add_actor_by_enemy("CYBER_SLIME_MINION")
end end
return nil return nil

View File

@ -13,10 +13,10 @@ It seems to be eating the metal from the walls. It looks at you and after a few
description = "Fight!", description = "Fight!",
callback = function() callback = function()
add_actor_by_enemy("RUST_MITE") add_actor_by_enemy("RUST_MITE")
if math.random() < 0.25 then if random() < 0.25 then
add_actor_by_enemy("RUST_MITE") add_actor_by_enemy("RUST_MITE")
end end
if math.random() < 0.15 then if random() < 0.15 then
add_actor_by_enemy("REPAIR_DRONE") add_actor_by_enemy("REPAIR_DRONE")
end end
return GAME_STATE_FIGHT return GAME_STATE_FIGHT
@ -41,10 +41,10 @@ It looks at you and says "Corpse. Clean. Engage.".
description = "Fight!", description = "Fight!",
callback = function() callback = function()
add_actor_by_enemy("CLEAN_BOT") add_actor_by_enemy("CLEAN_BOT")
if math.random() < 0.25 then if random() < 0.25 then
add_actor_by_enemy("CLEAN_BOT") add_actor_by_enemy("CLEAN_BOT")
end end
if math.random() < 0.15 then if random() < 0.15 then
add_actor_by_enemy("REPAIR_DRONE") add_actor_by_enemy("REPAIR_DRONE")
end end
return GAME_STATE_FIGHT return GAME_STATE_FIGHT
@ -66,10 +66,10 @@ It seems to be waiting for its prey to come closer and there is no way around it
description = "Fight!", description = "Fight!",
callback = function() callback = function()
add_actor_by_enemy("CYBER_SPIDER") add_actor_by_enemy("CYBER_SPIDER")
if math.random() < 0.25 then if random() < 0.25 then
add_actor_by_enemy("CYBER_SPIDER") add_actor_by_enemy("CYBER_SPIDER")
end end
if math.random() < 0.15 then if random() < 0.15 then
add_actor_by_enemy("REPAIR_DRONE") add_actor_by_enemy("REPAIR_DRONE")
end end
return GAME_STATE_FIGHT return GAME_STATE_FIGHT
@ -93,10 +93,10 @@ As you explore the facility, you hear a high-pitched whirring sound. A drone equ
description = "Fight!", description = "Fight!",
callback = function() callback = function()
add_actor_by_enemy("LASER_DRONE") add_actor_by_enemy("LASER_DRONE")
if math.random() < 0.10 then if random() < 0.10 then
add_actor_by_enemy("LASER_DRONE") add_actor_by_enemy("LASER_DRONE")
end end
if math.random() < 0.15 then if random() < 0.15 then
add_actor_by_enemy("REPAIR_DRONE") add_actor_by_enemy("REPAIR_DRONE")
end end
return GAME_STATE_FIGHT return GAME_STATE_FIGHT
@ -120,7 +120,7 @@ As you delve deeper into the facility, you notice a bright glow emanating from a
description = "Fight!", description = "Fight!",
callback = function() callback = function()
add_actor_by_enemy("PLASMA_GOLEM") add_actor_by_enemy("PLASMA_GOLEM")
if math.random() < 0.05 then if random() < 0.05 then
add_actor_by_enemy("REPAIR_DRONE") add_actor_by_enemy("REPAIR_DRONE")
end end
return GAME_STATE_FIGHT return GAME_STATE_FIGHT
@ -144,7 +144,7 @@ As you explore the facility, you come across a strange cybernetic slime. It seem
description = "Fight!", description = "Fight!",
callback = function() callback = function()
add_actor_by_enemy("CYBER_SLIME") add_actor_by_enemy("CYBER_SLIME")
if math.random() < 0.10 then if random() < 0.10 then
add_actor_by_enemy("REPAIR_DRONE") add_actor_by_enemy("REPAIR_DRONE")
end end
return GAME_STATE_FIGHT return GAME_STATE_FIGHT

View File

@ -183,7 +183,7 @@ You find a room with a strange device in the middle. It seems to be some kind of
:filter(function(card) :filter(function(card)
return card.does_consume return card.does_consume
end):totable() end):totable()
if math.random() < 0.5 then if random() < 0.5 then
local choosen = choose_weighted_by_price(possible_artifacts) local choosen = choose_weighted_by_price(possible_artifacts)
if choosen then if choosen then
give_artifact(choosen, PLAYER_ID) give_artifact(choosen, PLAYER_ID)
@ -232,7 +232,7 @@ You find a old automatic workstation. You are able to get it working again. You
return nil return nil
end end
local choosen = cards[math.random(#cards)] local choosen = cards[random_int(0, #cards)]
upgrade_card(choosen) upgrade_card(choosen)
deal_damage(PLAYER_ID, PLAYER_ID, 2, true) deal_damage(PLAYER_ID, PLAYER_ID, 2, true)

View File

@ -82,7 +82,7 @@ local string_gen = function(param, state)
return state, r return state, r
end end
local ipairs_gen = ipairs({}) -- get the generating function from ipairs local ipairs_gen = ipairs({}) -- get the generating function from ipairs
local pairs_gen = pairs({ a = 0 }) -- get the generating function from pairs local pairs_gen = pairs({ a = 0 }) -- get the generating function from pairs
local map_gen = function(tab, key) local map_gen = function(tab, key)
@ -262,11 +262,11 @@ end
exports.ones = ones exports.ones = ones
local rands_gen = function(param_x, _state_x) local rands_gen = function(param_x, _state_x)
return 0, math.random(param_x[1], param_x[2]) return 0, random_int(param_x[1], param_x[2])
end end
local rands_nil_gen = function(_param_x, _state_x) local rands_nil_gen = function(_param_x, _state_x)
return 0, math.random() return 0, random()
end end
local rands = function(n, m) local rands = function(n, m)

View File

@ -30,13 +30,17 @@ register_story_teller("_ACT_0", {
if #possible == 0 then if #possible == 0 then
possible = find_events_by_tags({ "_ACT_0_FIGHT" }) possible = find_events_by_tags({ "_ACT_0_FIGHT" })
end end
set_event(possible[math.random(#possible)].id)
local choosen = possible[random_int(0, #possible)]
if choosen ~= nil then
set_event(choosen.id)
end
-- if we cleared a stage, give the player a random artifact -- if we cleared a stage, give the player a random artifact
local last_stage_count = fetch("last_stage_count") local last_stage_count = fetch("last_stage_count")
local current_stage_count = get_stages_cleared() local current_stage_count = get_stages_cleared()
if last_stage_count ~= current_stage_count then if last_stage_count ~= current_stage_count then
local gets_random_artifact = math.random() < 0.25 local gets_random_artifact = random() < 0.25
if gets_random_artifact then if gets_random_artifact then
local player_artifacts = fun.iter(get_actor(PLAYER_ID).artifacts):map(function(id) local player_artifacts = fun.iter(get_actor(PLAYER_ID).artifacts):map(function(id)

View File

@ -78,6 +78,8 @@ func initSystems(hasAudio bool) {
} }
func main() { func main() {
os.Setenv("EOE_IMG_TRUECOLOR", "1")
testArgs := testargs.New() testArgs := testargs.New()
flag.Parse() flag.Parse()

View File

@ -65,10 +65,10 @@ Content that is dynamically generated at runtime is not included in this documen
```mermaid ```mermaid
pie pie
title Action Points title Action Points
"3 AP" : 2
"0 AP" : 12 "0 AP" : 12
"2 AP" : 1 "2 AP" : 1
"1 AP" : 6 "1 AP" : 6
"3 AP" : 2
``` ```
@ -107,7 +107,7 @@ title Card Types
| ID | Name | Description | Initial HP | Max HP | Color | Used Callbacks | Test Present | | ID | Name | Description | Initial HP | Max HP | Color | Used Callbacks | Test Present |
|------------------------|-----------------------|-------------------------------------------------------------------|------------|--------|---------|------------------------------|-----------------| |------------------------|-----------------------|-------------------------------------------------------------------|------------|--------|---------|------------------------------|-----------------|
| ``CYBER_SPIDER`` | CYBER Spider | It waits for its prey to come closer | 8 | 8 | #ff4d6d | ``OnTurn`` | :no_entry_sign: | | ``CYBER_SPIDER`` | CYBER Spider | It waits for its prey to come closer | 8 | 8 | #ff4d6d | ``OnTurn`` | :no_entry_sign: |
| ``CLEAN_BOT`` | Cleaning Bot | It never stopped cleaning... | 13 | 13 | #32a891 | ``OnTurn``, ``OnPlayerTurn`` | :no_entry_sign: | | ``CLEAN_BOT`` | Cleaning Bot | It never stopped cleaning... | 13 | 13 | #32a891 | ``OnPlayerTurn``, ``OnTurn`` | :no_entry_sign: |
| ``CYBER_SLIME`` | Cyber Slime | A cybernetic slime that splits into smaller slimes when defeated. | 10 | 10 | #00ff00 | ``OnTurn``, ``OnActorDie`` | :no_entry_sign: | | ``CYBER_SLIME`` | Cyber Slime | A cybernetic slime that splits into smaller slimes when defeated. | 10 | 10 | #00ff00 | ``OnTurn``, ``OnActorDie`` | :no_entry_sign: |
| ``CYBER_SLIME_MINION`` | Cyber Slime Offspring | A smaller version of the Cyber Slime. | 4 | 4 | #00ff00 | ``OnTurn`` | :no_entry_sign: | | ``CYBER_SLIME_MINION`` | Cyber Slime Offspring | A smaller version of the Cyber Slime. | 4 | 4 | #00ff00 | ``OnTurn`` | :no_entry_sign: |
| ``DUMMY`` | Dummy | End me... | 100 | 100 | #deeb6a | ``OnTurn`` | :no_entry_sign: | | ``DUMMY`` | Dummy | End me... | 100 | 100 | #deeb6a | ``OnTurn`` | :no_entry_sign: |
@ -122,21 +122,21 @@ title Card Types
| ID | Name | Description | Tags | Choices | Test Present | | ID | Name | Description | Tags | Choices | Test Present |
|------------------------------|---------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------|----------------------------------------------------------------------------------------------------------------------------------|-----------------| |------------------------------|---------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------|----------------------------------------------------------------------------------------------------------------------------------|-----------------|
| ``GAIN_GOLD_ACT_0`` | | ... - | _ACT_0 | <ul><li>``Take it! [Gain 20 Gold]``</li> <li>``Leave!``</li></ul> | :no_entry_sign: | | ``GAIN_GOLD_ACT_0`` | | ... - | _ACT_0 | <ul><li>``Take it! [Gain 20 Gold]``</li> <li>``Leave!``</li></ul> | :no_entry_sign: |
| ``PLASMA_GOLEM`` | A glowing figure emerges... | As you delve deeper into the facility, you notice a bright glow emanating from a nearby chamber. A massive golem made of pure plasma energy steps into view. - **It looks ready to unleash its power!** - | _ACT_0_FIGHT | <ul><li>``Fight!``</li></ul> | :no_entry_sign: | | ``PLASMA_GOLEM`` | A glowing figure emerges... | !!plasma_golem.jpg - As you delve deeper into the facility, you notice a bright glow emanating from a nearby chamber. A massive golem made of pure plasma energy steps into view. - **It looks ready to unleash its power!** - | _ACT_0_FIGHT | <ul><li>``Fight!``</li></ul> | :no_entry_sign: |
| ``LASER_DRONE`` | A menacing drone appears... | As you explore the facility, you hear a high-pitched whirring sound. A drone equipped with a powerful laser cannon appears in front of you. - **It looks ready to attack!** - | _ACT_0_FIGHT | <ul><li>``Fight!``</li></ul> | :no_entry_sign: | | ``LASER_DRONE`` | A menacing drone appears... | !!laser_drone.jpg - As you explore the facility, you hear a high-pitched whirring sound. A drone equipped with a powerful laser cannon appears in front of you. - **It looks ready to attack!** - | _ACT_0_FIGHT | <ul><li>``Fight!``</li></ul> | :no_entry_sign: |
| ``CYBER_SLIME`` | A strange cybernetic slime appears... | As you explore the facility, you come across a strange cybernetic slime. It seems to be pulsating with energy and looks hostile. - **Prepare for a fight!** - | _ACT_0_FIGHT | <ul><li>``Fight!``</li></ul> | :no_entry_sign: | | ``CYBER_SLIME`` | A strange cybernetic slime appears... | !!cyber_slime.jpg - As you explore the facility, you come across a strange cybernetic slime. It seems to be pulsating with energy and looks hostile. - **Prepare for a fight!** - | _ACT_0_FIGHT | <ul><li>``Fight!``</li></ul> | :no_entry_sign: |
| ``MERCHANT`` | A strange figure | !!merchant.jpg - - 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... | _ACT_0, _ACT_1, _ACT_2, _ACT_3 | <ul><li>``Trade``</li> <li>``Pass``</li></ul> | :no_entry_sign: | | ``MERCHANT`` | A strange figure | !!merchant.jpg - - 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... | _ACT_0, _ACT_1, _ACT_2, _ACT_3 | <ul><li>``Trade``</li> <li>``Pass``</li></ul> | :no_entry_sign: |
| ``CLEAN_BOT`` | Corpse. Clean. Engage. | !!clean_bot.jpg - While exploring the facility you hear a strange noise. Suddenly a strange robot appears from one of the corridors. - It seems to be cleaning up the area, but it's not working properly anymore and you can see small sparks coming out of it. - It looks at you and says "Corpse. Clean. Engage.". - **You're not sure what it means, but it doesn't seem to be friendly!** - | _ACT_0_FIGHT | <ul><li>``Fight!``</li></ul> | :no_entry_sign: | | ``CLEAN_BOT`` | Corpse. Clean. Engage. | !!clean_bot.jpg - While exploring the facility you hear a strange noise. Suddenly a strange robot appears from one of the corridors. - It seems to be cleaning up the area, but it's not working properly anymore and you can see small sparks coming out of it. - It looks at you and says "Corpse. Clean. Engage.". - **You're not sure what it means, but it doesn't seem to be friendly!** - | _ACT_0_FIGHT | <ul><li>``Fight!``</li></ul> | :no_entry_sign: |
| ``GAMBLE_1_ACT_0`` | Electro Barrier | You find a room with a strange device in the middle. It seems to be some kind of electro barrier protecting a storage container. You can either try to disable the barrier or leave. - | _ACT_0 | <ul><li>``50% [Gain Artifact & Consumeable] 50% [Take 5 damage]``</li> <li>``Leave!``</li></ul> | :no_entry_sign: | | ``GAMBLE_1_ACT_0`` | Electro Barrier | !!electro_barrier.jpg - You find a room with a strange device in the middle. It seems to be some kind of electro barrier protecting a storage container. You can either try to disable the barrier or leave. - | _ACT_0 | <ul><li>``50% [Gain Artifact & Consumeable] 50% [Take 2 damage]``</li> <li>``Leave!``</li></ul> | :no_entry_sign: |
| ``CROWBAR`` | Found: Crowbar | !!red_room.jpg - **You found something!** A crowbar. It's a bit rusty, but it should still be useful! - **Important:** If you already carry a artifact in your hand, you will have to drop it and related cards to pick up the new one. | _ACT_0 | <ul><li>````</li> <li>``Leave...``</li></ul> | :no_entry_sign: | | ``CROWBAR`` | Found: Crowbar | !!red_room.jpg - **You found something!** A crowbar. It's a bit rusty, but it should still be useful! - **Important:** If you already carry a artifact in your hand, you will have to drop it and related cards to pick up the new one. | _ACT_0 | <ul><li>````</li> <li>``Leave...``</li></ul> | :no_entry_sign: |
| ``HAR_II`` | Found: HAR-II | !!artifact_chest.jpg - **You found something!** A HAR-II. A heavy assault rifle with a high rate of fire. - **Important:** If you already carry a artifact in your hand, you will have to drop it and related cards to pick up the new one. | _ACT_1 | <ul><li>````</li> <li>``Leave...``</li></ul> | :no_entry_sign: | | ``HAR_II`` | Found: HAR-II | !!artifact_chest.jpg - **You found something!** A HAR-II. A heavy assault rifle with a high rate of fire. - **Important:** If you already carry a artifact in your hand, you will have to drop it and related cards to pick up the new one. | _ACT_1 | <ul><li>````</li> <li>``Leave...``</li></ul> | :no_entry_sign: |
| ``LZR_PISTOL`` | Found: LZR Pistol | !!artifact_chest.jpg - **You found something!** A LZR pistol. Fires a concentrated beam of light. - **Important:** If you already carry a artifact in your hand, you will have to drop it and related cards to pick up the new one. | _ACT_1 | <ul><li>````</li> <li>``Leave...``</li></ul> | :no_entry_sign: | | ``LZR_PISTOL`` | Found: LZR Pistol | !!artifact_chest.jpg - **You found something!** A LZR pistol. Fires a concentrated beam of light. - **Important:** If you already carry a artifact in your hand, you will have to drop it and related cards to pick up the new one. | _ACT_1 | <ul><li>````</li> <li>``Leave...``</li></ul> | :no_entry_sign: |
| ``VIBRO_KNIFE`` | Found: VIBRO Knife | !!artifact_chest.jpg - **You found something!** A VIBRO knife. Uses ultrasonic vibrations to cut through almost anything. - **Important:** If you already carry a artifact in your hand, you will have to drop it and related cards to pick up the new one. | _ACT_0 | <ul><li>````</li> <li>``Leave...``</li></ul> | :no_entry_sign: | | ``VIBRO_KNIFE`` | Found: VIBRO Knife | !!artifact_chest.jpg - **You found something!** A VIBRO knife. Uses ultrasonic vibrations to cut through almost anything. - **Important:** If you already carry a artifact in your hand, you will have to drop it and related cards to pick up the new one. | _ACT_0 | <ul><li>````</li> <li>``Leave...``</li></ul> | :no_entry_sign: |
| ``GOLD_TO_HP_ACT_0`` | Old Vending Machine | You find an old vending machine, it seems to be still working. You can either pay 20 Gold to get 5 HP or leave. - | _ACT_0 | <ul><li>``Pay [20 Gold] [Gain 5 HP]``</li> <li>``Leave!``</li></ul> | :no_entry_sign: | | ``GOLD_TO_HP_ACT_0`` | Old Vending Machine | You find an old vending machine, it seems to be still working. You can either pay 20 Gold to get 5 HP or leave. - | _ACT_0 | <ul><li>``Pay [20 Gold] [Gain 5 HP]``</li> <li>``Leave!``</li></ul> | :no_entry_sign: |
| ``RANDOM_ARTIFACT_ACT_0`` | Random Artifact | !!artifact_chest.jpg - You found a chest with a strange symbol on it. The chest is protected by a strange barrier. You can either open it and take some damage or leave. - | _ACT_0 | <ul><li>``Random Artifact [Gain 1 Artifact] [Take 5 damage]``</li> <li>``Leave!``</li></ul> | :no_entry_sign: | | ``RANDOM_ARTIFACT_ACT_0`` | Random Artifact | !!artifact_chest.jpg - You found a chest with a strange symbol on it. The chest is protected by a strange barrier. You can either open it and take some damage or leave. - | _ACT_0 | <ul><li>``Random Artifact [Gain 1 Artifact] [Take 2 damage]``</li> <li>``Leave!``</li></ul> | :no_entry_sign: |
| ``RANDOM_CONSUMEABLE_ACT_0`` | Random Consumeable | !!artifact_chest.jpg - You found a chest with a strange symbol on it. The chest is protected by a strange barrier. You can either open it and take some damage or leave. - | _ACT_0 | <ul><li>``Random Artifact [Gain 1 Consumeable] [Take 2 damage]``</li> <li>``Leave!``</li></ul> | :no_entry_sign: | | ``RANDOM_CONSUMEABLE_ACT_0`` | Random Consumeable | !!artifact_chest.jpg - You found a chest with a strange symbol on it. The chest is protected by a strange barrier. You can either open it and take some damage or leave. - | _ACT_0 | <ul><li>``Random Artifact [Gain 1 Consumeable] [Take 2 damage]``</li> <li>``Leave!``</li></ul> | :no_entry_sign: |
| ``MAX_LIFE_ACT_0`` | Symbiotic Parasite | You find a strange creature, it seems to be a symbiotic parasite. It offers to increase your max HP by 5. You can either accept or leave. - | _ACT_0 | <ul><li>``Accept it! [Gain 5 Max HP]``</li> <li>``Leave!``</li></ul> | :no_entry_sign: | | ``MAX_LIFE_ACT_0`` | Symbiotic Parasite | !!symbiotic_parasite.jpg - You find a strange creature, it seems to be a symbiotic parasite. It offers to increase your max HP by 5. You can either accept or leave. - | _ACT_0 | <ul><li>``Accept it! [Gain 5 Max HP]``</li> <li>``Leave!``</li></ul> | :no_entry_sign: |
| ``RUST_MITE`` | Tasty metals... | !!rust_mite.jpg - You are walking through the facility hoping to find a way out. After a few turns you hear a strange noise. You look around and come across a strange being. - It seems to be eating the metal from the walls. It looks at you and after a few seconds it rushes towards you. - **It seems to be hostile!** - | _ACT_0_FIGHT | <ul><li>``Fight!``</li></ul> | :no_entry_sign: | | ``RUST_MITE`` | Tasty metals... | !!rust_mite.jpg - You are walking through the facility hoping to find a way out. After a few turns you hear a strange noise. You look around and come across a strange being. - It seems to be eating the metal from the walls. It looks at you and after a few seconds it rushes towards you. - **It seems to be hostile!** - | _ACT_0_FIGHT | <ul><li>``Fight!``</li></ul> | :no_entry_sign: |
| ``UPRAGDE_CARD_ACT_0`` | Upgrade Station | You find a old automatic workstation. You are able to get it working again. You can either upgrade a random card or leave. - | _ACT_0 | <ul><li>``Upgrade a card [Upgrade a card] [Take 5 damage]``</li> <li>``Leave!``</li></ul> | :no_entry_sign: | | ``UPRAGDE_CARD_ACT_0`` | Upgrade Station | !!upgrade_station.jpg - You find a old automatic workstation. You are able to get it working again. You can either upgrade a random card or leave. - | _ACT_0 | <ul><li>``Upgrade a card [Upgrade a card] [Take 2 damage]``</li> <li>``Leave!``</li></ul> | :no_entry_sign: |
| ``START`` | Waking up... | !!cryo_start.jpg - You wake up in a dimly lit room, the faint glow of a red emergency light casting an eerie hue over the surroundings. The air is musty and stale, the metallic scent of the cryo-chamber still lingering in your nostrils. You feel groggy and disoriented, your mind struggling to process what's happening. - As you try to sit up, you notice that your body is stiff and unresponsive. It takes a few moments for your muscles to warm up and regain their strength. Looking around, you see that the walls are made of a dull gray metal, covered in scratches and scuff marks. There's a faint humming sound coming from somewhere, indicating that the facility is still operational. - You try to remember how you ended up here, but your memories are hazy and fragmented. The last thing you recall is a blinding flash of light and a deafening boom. You must have been caught in one of the nuclear explosions that devastated the world. - 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...** | | <ul><li>``Try to find a weapon. [Find melee weapon] [Take 4 damage]``</li> <li>``Gather your strength and attack it!``</li></ul> | :no_entry_sign: | | ``START`` | Waking up... | !!cryo_start.jpg - You wake up in a dimly lit room, the faint glow of a red emergency light casting an eerie hue over the surroundings. The air is musty and stale, the metallic scent of the cryo-chamber still lingering in your nostrils. You feel groggy and disoriented, your mind struggling to process what's happening. - As you try to sit up, you notice that your body is stiff and unresponsive. It takes a few moments for your muscles to warm up and regain their strength. Looking around, you see that the walls are made of a dull gray metal, covered in scratches and scuff marks. There's a faint humming sound coming from somewhere, indicating that the facility is still operational. - You try to remember how you ended up here, but your memories are hazy and fragmented. The last thing you recall is a blinding flash of light and a deafening boom. You must have been caught in one of the nuclear explosions that devastated the world. - 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...** | | <ul><li>``Try to find a weapon. [Find melee weapon] [Take 4 damage]``</li> <li>``Gather your strength and attack it!``</li></ul> | :no_entry_sign: |
| ``CYBER_SPIDER`` | What is this thing at the ceiling? | !!cyber_spider.jpg - You come around a corner and see a strange creature hanging from the ceiling. It looks like a spider, but it's made out of metal. - It seems to be waiting for its prey to come closer and there is no way around it. - | _ACT_0_FIGHT | <ul><li>``Fight!``</li></ul> | :no_entry_sign: | | ``CYBER_SPIDER`` | What is this thing at the ceiling? | !!cyber_spider.jpg - You come around a corner and see a strange creature hanging from the ceiling. It looks like a spider, but it's made out of metal. - It seems to be waiting for its prey to come closer and there is no way around it. - | _ACT_0_FIGHT | <ul><li>``Fight!``</li></ul> | :no_entry_sign: |

View File

@ -1,4 +1,5 @@
# End Of Eden Lua Docs # End Of Eden Lua Docs
## Index ## Index
- [Game Constants](#game-constants) - [Game Constants](#game-constants)
@ -23,6 +24,7 @@
General game constants. General game constants.
### Globals ### Globals
<details> <summary><b><code>DECAY_ALL</code></b> </summary> <br/> <details> <summary><b><code>DECAY_ALL</code></b> </summary> <br/>
Status effect decays by all stacks per turn. Status effect decays by all stacks per turn.
@ -67,7 +69,7 @@ Represents the random game state in which the active story teller will decide wh
<details> <summary><b><code>PLAYER_ID</code></b> </summary> <br/> <details> <summary><b><code>PLAYER_ID</code></b> </summary> <br/>
Player actor id for use in functions where the guid is needed, for example: ``deal_damage(PLAYER_ID, enemy_guid, 10)``. Player actor id for use in functions where the guid is needed, for example: `deal_damage(PLAYER_ID, enemy_guid, 10)`.
</details> </details>
@ -84,6 +86,7 @@ General game constants.
None None
### Functions ### Functions
<details> <summary><b><code>fetch</code></b> </summary> <br/> <details> <summary><b><code>fetch</code></b> </summary> <br/>
Fetches a value from the persistent store Fetches a value from the persistent store
@ -108,6 +111,30 @@ guid() -> guid
</details> </details>
<details> <summary><b><code>random</code></b> </summary> <br/>
Returns a random number between 0 and 1
**Signature:**
```
random() -> number
```
</details>
<details> <summary><b><code>random_int</code></b> </summary> <br/>
Returns a random number between min and max
**Signature:**
```
random_int(min : number, max : number) -> number
```
</details>
<details> <summary><b><code>store</code></b> </summary> <br/> <details> <summary><b><code>store</code></b> </summary> <br/>
Stores a persistent value for this run that will be restored after a save load. Can store any lua basic value or table. Stores a persistent value for this run that will be restored after a save load. Can store any lua basic value or table.
@ -129,6 +156,7 @@ Helper functions for text styling.
None None
### Functions ### Functions
<details> <summary><b><code>text_bg</code></b> </summary> <br/> <details> <summary><b><code>text_bg</code></b> </summary> <br/>
Makes the text background colored. Takes hex values like #ff0000. Makes the text background colored. Takes hex values like #ff0000.
@ -186,6 +214,7 @@ Various logging functions.
None None
### Functions ### Functions
<details> <summary><b><code>log_d</code></b> </summary> <br/> <details> <summary><b><code>log_d</code></b> </summary> <br/>
Log at **danger** level to player log. Log at **danger** level to player log.
@ -255,9 +284,10 @@ Audio helper functions.
None None
### Functions ### Functions
<details> <summary><b><code>play_audio</code></b> </summary> <br/> <details> <summary><b><code>play_audio</code></b> </summary> <br/>
Plays a sound effect. If you want to play ``button.mp3`` you call ``play_audio("button")``. Plays a sound effect. If you want to play `button.mp3` you call `play_audio("button")`.
**Signature:** **Signature:**
@ -269,7 +299,7 @@ play_audio(sound : string) -> None
<details> <summary><b><code>play_music</code></b> </summary> <br/> <details> <summary><b><code>play_music</code></b> </summary> <br/>
Start a song for the background loop. If you want to play ``song.mp3`` you call ``play_music("song")``. Start a song for the background loop. If you want to play `song.mp3` you call `play_music("song")`.
**Signature:** **Signature:**
@ -288,6 +318,7 @@ Functions that modify the general game state.
None None
### Functions ### Functions
<details> <summary><b><code>get_action_points_per_round</code></b> </summary> <br/> <details> <summary><b><code>get_action_points_per_round</code></b> </summary> <br/>
get the number of action points per round. get the number of action points per round.
@ -441,6 +472,7 @@ Functions that modify or access the actors. Actors are either the player or enem
None None
### Functions ### Functions
<details> <summary><b><code>actor_add_hp</code></b> </summary> <br/> <details> <summary><b><code>actor_add_hp</code></b> </summary> <br/>
Increases the hp value of a actor by a number. Can be negative value to decrease it. This won't trigger any on_damage callbacks Increases the hp value of a actor by a number. Can be negative value to decrease it. This won't trigger any on_damage callbacks
@ -491,7 +523,7 @@ actor_set_max_hp(guid : guid, amount : number) -> None
<details> <summary><b><code>add_actor_by_enemy</code></b> </summary> <br/> <details> <summary><b><code>add_actor_by_enemy</code></b> </summary> <br/>
Creates a new enemy fighting against the player. Example ``add_actor_by_enemy("RUST_MITE")``. Creates a new enemy fighting against the player. Example `add_actor_by_enemy("RUST_MITE")`.
**Signature:** **Signature:**
@ -515,7 +547,7 @@ get_actor(guid : guid) -> actor
<details> <summary><b><code>get_opponent_by_index</code></b> </summary> <br/> <details> <summary><b><code>get_opponent_by_index</code></b> </summary> <br/>
Get opponent (actor) by index of a certain actor. ``get_opponent_by_index(PLAYER_ID, 2)`` would return the second alive opponent of the player. Get opponent (actor) by index of a certain actor. `get_opponent_by_index(PLAYER_ID, 2)` would return the second alive opponent of the player.
**Signature:** **Signature:**
@ -527,7 +559,7 @@ get_opponent_by_index(guid : guid, index : number) -> actor
<details> <summary><b><code>get_opponent_count</code></b> </summary> <br/> <details> <summary><b><code>get_opponent_count</code></b> </summary> <br/>
Get the number of opponents (actors) of a certain actor. ``get_opponent_count(PLAYER_ID)`` would return 2 if the player had 2 alive enemies. Get the number of opponents (actors) of a certain actor. `get_opponent_count(PLAYER_ID)` would return 2 if the player had 2 alive enemies.
**Signature:** **Signature:**
@ -539,7 +571,7 @@ get_opponent_count(guid : guid) -> number
<details> <summary><b><code>get_opponent_guids</code></b> </summary> <br/> <details> <summary><b><code>get_opponent_guids</code></b> </summary> <br/>
Get the guids of opponents (actors) of a certain actor. If the player had 2 enemies, ``get_opponent_guids(PLAYER_ID)`` would return a table with 2 strings containing the guids of these actors. Get the guids of opponents (actors) of a certain actor. If the player had 2 enemies, `get_opponent_guids(PLAYER_ID)` would return a table with 2 strings containing the guids of these actors.
**Signature:** **Signature:**
@ -551,7 +583,7 @@ get_opponent_guids(guid : guid) -> guid[]
<details> <summary><b><code>get_player</code></b> </summary> <br/> <details> <summary><b><code>get_player</code></b> </summary> <br/>
Get the player actor. Equivalent to ``get_actor(PLAYER_ID)`` Get the player actor. Equivalent to `get_actor(PLAYER_ID)`
**Signature:** **Signature:**
@ -582,6 +614,7 @@ Functions that modify or access the artifacts.
None None
### Functions ### Functions
<details> <summary><b><code>get_artifact</code></b> </summary> <br/> <details> <summary><b><code>get_artifact</code></b> </summary> <br/>
Returns the artifact definition. Can take either a guid or a typeId. If it's a guid it will fetch the type behind the instance. Returns the artifact definition. Can take either a guid or a typeId. If it's a guid it will fetch the type behind the instance.
@ -651,6 +684,7 @@ Functions that modify or access the status effects.
None None
### Functions ### Functions
<details> <summary><b><code>add_status_effect_stacks</code></b> </summary> <br/> <details> <summary><b><code>add_status_effect_stacks</code></b> </summary> <br/>
Adds to the stack count of a status effect. Negative values are also allowed. Adds to the stack count of a status effect. Negative values are also allowed.
@ -744,6 +778,7 @@ Functions that modify or access the cards.
None None
### Functions ### Functions
<details> <summary><b><code>cast_card</code></b> </summary> <br/> <details> <summary><b><code>cast_card</code></b> </summary> <br/>
Tries to cast a card with a guid and optional target. If the cast isn't successful returns false. Tries to cast a card with a guid and optional target. If the cast isn't successful returns false.
@ -849,6 +884,7 @@ Functions that deal damage or heal.
None None
### Functions ### Functions
<details> <summary><b><code>deal_damage</code></b> </summary> <br/> <details> <summary><b><code>deal_damage</code></b> </summary> <br/>
Deal damage from one source to a target. If flat is true the damage can't be modified by status effects or artifacts. Returns the damage that was dealt. Deal damage from one source to a target. If flat is true the damage can't be modified by status effects or artifacts. Returns the damage that was dealt.
@ -918,6 +954,7 @@ Functions that are related to the player.
None None
### Functions ### Functions
<details> <summary><b><code>finish_player_turn</code></b> </summary> <br/> <details> <summary><b><code>finish_player_turn</code></b> </summary> <br/>
Finishes the player turn. Finishes the player turn.
@ -999,6 +1036,7 @@ Functions that are related to the merchant.
None None
### Functions ### Functions
<details> <summary><b><code>add_merchant_artifact</code></b> </summary> <br/> <details> <summary><b><code>add_merchant_artifact</code></b> </summary> <br/>
Adds another random artifact to the merchant Adds another random artifact to the merchant
@ -1037,7 +1075,7 @@ get_merchant() -> merchant_state
<details> <summary><b><code>get_merchant_gold_max</code></b> </summary> <br/> <details> <summary><b><code>get_merchant_gold_max</code></b> </summary> <br/>
Returns the maximum value of artifacts and cards that the merchant will sell. Good to scale ``random_card`` and ``random_artifact``. Returns the maximum value of artifacts and cards that the merchant will sell. Good to scale `random_card` and `random_artifact`.
**Signature:** **Signature:**
@ -1056,6 +1094,7 @@ Functions that help with random generation.
None None
### Functions ### Functions
<details> <summary><b><code>gen_face</code></b> </summary> <br/> <details> <summary><b><code>gen_face</code></b> </summary> <br/>
Generates a random face. Generates a random face.
@ -1101,10 +1140,11 @@ Functions that help with localization.
None None
### Functions ### Functions
<details> <summary><b><code>l</code></b> </summary> <br/> <details> <summary><b><code>l</code></b> </summary> <br/>
Returns the localized string for the given key. Examples on locals definition can be found in `/assets/locals`. Example: `` Returns the localized string for the given key. Examples on locals definition can be found in `/assets/locals`. Example: `
l('cards.MY_CARD.name', "English Default Name")`` l('cards.MY_CARD.name', "English Default Name")`
**Signature:** **Signature:**
@ -1123,6 +1163,7 @@ These functions are used to define new content in the base game and in mods.
None None
### Functions ### Functions
<details> <summary><b><code>delete_base_game</code></b> </summary> <br/> <details> <summary><b><code>delete_base_game</code></b> </summary> <br/>
Deletes all base game content. Useful if you don't want to include base game content in your mod. Deletes all base game content. Useful if you don't want to include base game content in your mod.
@ -1343,7 +1384,7 @@ register_event("SOME_EVENT",
description = "Go...", description = "Go...",
callback = function() callback = function()
-- If you return nil on_end will decide the next game state -- If you return nil on_end will decide the next game state
return nil return nil
end end
}, },
{ {
@ -1353,7 +1394,7 @@ register_event("SOME_EVENT",
}, },
on_enter = function() on_enter = function()
play_music("energetic_orthogonal_expansions") play_music("energetic_orthogonal_expansions")
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("MELEE_HIT", PLAYER_ID)
@ -1435,7 +1476,7 @@ register_story_teller("STORY_TELLER_XYZ", {
end end
-- Fight against rust mites or clean bots -- Fight against rust mites or clean bots
local d = math.random(2) local d = random_int(0, 2)
if d == 1 then if d == 1 then
add_actor_by_enemy("RUST_MITE") add_actor_by_enemy("RUST_MITE")
elseif d == 2 then elseif d == 2 then
@ -1454,4 +1495,3 @@ register_story_teller(id : type_id, definition : story_teller) -> None
``` ```
</details> </details>

View File

@ -88,6 +88,20 @@ fun = require "fun"
d.Category("Utility", "General game constants.", 1) d.Category("Utility", "General game constants.", 1)
d.Function("random", "Returns a random number between 0 and 1. Prefer this function over math.random(), as this is seeded for the session.", "number")
l.SetGlobal("random", l.NewFunction(func(state *lua.LState) int {
state.Push(lua.LNumber(session.rand.Float64()))
return 1
}))
d.Function("random_int", "Returns a random number between min and max. Prefer this function over math.random(), as this is seeded for the session.", "number", "min : number", "max : number")
l.SetGlobal("random_int", l.NewFunction(func(state *lua.LState) int {
min := state.ToInt(1)
max := state.ToInt(2)
state.Push(lua.LNumber(session.rand.IntN(max-min) + min))
return 1
}))
d.Function("guid", "returns a new random guid.", "guid") d.Function("guid", "returns a new random guid.", "guid")
l.SetGlobal("guid", l.NewFunction(func(state *lua.LState) int { l.SetGlobal("guid", l.NewFunction(func(state *lua.LState) int {
state.Push(lua.LString(NewGuid("LUA"))) state.Push(lua.LString(NewGuid("LUA")))

View File

@ -1,6 +1,9 @@
package game package game
import "encoding/gob" import (
"encoding/gob"
"math/rand/v2"
)
func init() { func init() {
gob.Register(SavedState{}) gob.Register(SavedState{})
@ -10,6 +13,8 @@ func init() {
// runtime or other pointer. // runtime or other pointer.
type SavedState struct { type SavedState struct {
State GameState State GameState
Seed uint64
Rand *rand.PCG
Actors map[string]Actor Actors map[string]Actor
Instances map[string]any Instances map[string]any
StagesCleared int StagesCleared int

View File

@ -8,7 +8,7 @@ import (
"fmt" "fmt"
"io" "io"
"log" "log"
"math/rand" "math/rand/v2"
"path/filepath" "path/filepath"
"runtime" "runtime"
"sort" "sort"
@ -102,6 +102,9 @@ type Session struct {
log *log.Logger log *log.Logger
luaState *lua.LState luaState *lua.LState
luaDocs *ludoc.Docs luaDocs *ludoc.Docs
seed uint64
randSrc *rand.PCG
rand *rand.Rand
resources *ResourcesManager resources *ResourcesManager
state GameState state GameState
@ -128,9 +131,14 @@ type Session struct {
// NewSession creates a new game session. // NewSession creates a new game session.
func NewSession(options ...func(s *Session)) *Session { func NewSession(options ...func(s *Session)) *Session {
seed := uint64(time.Now().UnixMilli())
randSrc := rand.NewPCG(seed, 1337)
session := &Session{ session := &Session{
log: log.New(io.Discard, "", 0), log: log.New(io.Discard, "", 0),
state: GameStateEvent, seed: seed,
randSrc: randSrc,
rand: rand.New(randSrc),
state: GameStateEvent,
actors: map[string]Actor{ actors: map[string]Actor{
PlayerActorID: NewActor(PlayerActorID), PlayerActorID: NewActor(PlayerActorID),
}, },
@ -163,10 +171,13 @@ func NewSession(options ...func(s *Session)) *Session {
session.log.Println("Session started!") session.log.Println("Session started!")
session.log.Println("Seed:", session.seed)
session.Log(LogTypeSuccess, fmt.Sprintf("Seed: %d", seed))
session.UpdatePlayer(func(actor *Actor) bool { session.UpdatePlayer(func(actor *Actor) bool {
actor.HP = 80 actor.HP = 100
actor.MaxHP = 80 actor.MaxHP = 100
actor.Gold = 50 + rand.Intn(50) actor.Gold = 0
return true return true
}) })
@ -201,6 +212,26 @@ func WithMods(mods []string) func(s *Session) {
} }
} }
// WithSeed sets the seed for the random number generator.
func WithSeed(seed uint64) func(s *Session) {
return func(s *Session) {
s.seed = seed
s.randSrc.Seed(seed, 1337)
}
}
// WithSeedString sets the seed for the random number generator based on a string.
func WithSeedString(seed string) func(s *Session) {
return func(s *Session) {
generatedSeed := uint64(0)
for i, c := range seed {
generatedSeed += uint64(c) + uint64(i)
}
s.seed = generatedSeed
s.randSrc.Seed(generatedSeed, 1337)
}
}
// WithOnLuaError sets the function that will be called when a lua error happens. // WithOnLuaError sets the function that will be called when a lua error happens.
func WithOnLuaError(fn func(file string, line int, callback string, typeId string, err error)) func(s *Session) { func WithOnLuaError(fn func(file string, line int, callback string, typeId string, err error)) func(s *Session) {
return func(s *Session) { return func(s *Session) {
@ -242,6 +273,8 @@ func (s *Session) LuaErrors() chan LuaError {
func (s *Session) ToSavedState() SavedState { func (s *Session) ToSavedState() SavedState {
return SavedState{ return SavedState{
State: s.state, State: s.state,
Seed: s.seed,
Rand: s.randSrc,
Actors: s.actors, Actors: s.actors,
Instances: s.instances, Instances: s.instances,
StagesCleared: s.stagesCleared, StagesCleared: s.stagesCleared,
@ -261,6 +294,8 @@ func (s *Session) ToSavedState() SavedState {
// should be loaded or the state could be corrupted. // should be loaded or the state could be corrupted.
func (s *Session) LoadSavedState(save SavedState) { func (s *Session) LoadSavedState(save SavedState) {
s.state = save.State s.state = save.State
s.seed = save.Seed
s.randSrc = save.Rand
s.actors = lo.MapValues(save.Actors, func(item Actor, key string) Actor { s.actors = lo.MapValues(save.Actors, func(item Actor, key string) Actor {
return item.Sanitize() return item.Sanitize()
}) })

4
go.mod
View File

@ -1,8 +1,6 @@
module github.com/BigJk/end_of_eden module github.com/BigJk/end_of_eden
go 1.21 go 1.23.0
toolchain go1.21.6
replace github.com/containerd/console => github.com/containerd/console v1.0.4-0.20230706203907-8f6c4e4faef5 replace github.com/containerd/console => github.com/containerd/console v1.0.4-0.20230706203907-8f6c4e4faef5

View File

@ -50,7 +50,7 @@ func buildOption(options ...Option) (Options, []imeji.Option) {
data.tag += os.Getenv("EOE_IMG_PATTERN") data.tag += os.Getenv("EOE_IMG_PATTERN")
} }
if runtime.GOOS == "js" { if runtime.GOOS == "js" || os.Getenv("EOE_IMG_TRUECOLOR") == "1" {
imejiOptions = append(imejiOptions, imeji.WithTrueColor()) imejiOptions = append(imejiOptions, imeji.WithTrueColor())
data.tag += "truecolor" data.tag += "truecolor"
} else { } else {

View File

@ -15,13 +15,14 @@ import (
type Choice string type Choice string
const ( const (
ChoiceWaiting = Choice("WAITING") ChoiceWaiting = Choice("WAITING")
ChoiceContinue = Choice("CONTINUE") ChoiceContinue = Choice("CONTINUE")
ChoiceNewGame = Choice("NEW_GAME") ChoiceNewGame = Choice("NEW_GAME")
ChoiceAbout = Choice("ABOUT") ChoiceNewGameSOD = Choice("NEW_GAME_SOD")
ChoiceSettings = Choice("SETTINGS") ChoiceAbout = Choice("ABOUT")
ChoiceMods = Choice("MODS") ChoiceSettings = Choice("SETTINGS")
ChoiceExit = Choice("EXIT") ChoiceMods = Choice("MODS")
ChoiceExit = Choice("EXIT")
) )
type choiceItem struct { type choiceItem struct {
@ -45,6 +46,7 @@ func NewChoicesModel(zones *zone.Manager, hideSettings bool) ChoicesModel {
choices := []list.Item{ choices := []list.Item{
choiceItem{zones, "Continue", "Ready to continue dying?", ChoiceContinue}, choiceItem{zones, "Continue", "Ready to continue dying?", ChoiceContinue},
choiceItem{zones, "New Game", "Start a new try.", ChoiceNewGame}, choiceItem{zones, "New Game", "Start a new try.", ChoiceNewGame},
choiceItem{zones, "New Game: Seed of the Day", "Start a new try with the daily seed.", ChoiceNewGameSOD},
choiceItem{zones, "About", "Want to know more?", ChoiceAbout}, choiceItem{zones, "About", "Want to know more?", ChoiceAbout},
choiceItem{zones, "Settings", "Other settings won't let you survive...", ChoiceSettings}, choiceItem{zones, "Settings", "Other settings won't let you survive...", ChoiceSettings},
choiceItem{zones, "Mods", "Make the game even more fun!", ChoiceMods}, choiceItem{zones, "Mods", "Make the game even more fun!", ChoiceMods},

View File

@ -2,6 +2,11 @@ package mainmenu
import ( import (
"fmt" "fmt"
"log"
"os"
"strings"
"time"
"github.com/BigJk/end_of_eden/game" "github.com/BigJk/end_of_eden/game"
"github.com/BigJk/end_of_eden/internal/fs" "github.com/BigJk/end_of_eden/internal/fs"
"github.com/BigJk/end_of_eden/system/audio" "github.com/BigJk/end_of_eden/system/audio"
@ -20,10 +25,6 @@ import (
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
zone "github.com/lrstanley/bubblezone" zone "github.com/lrstanley/bubblezone"
"github.com/samber/lo" "github.com/samber/lo"
"log"
"os"
"strings"
"time"
) )
type Model struct { type Model struct {
@ -119,6 +120,8 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
} }
} }
case ChoiceNewGameSOD:
fallthrough
case ChoiceNewGame: case ChoiceNewGame:
audio.Play("btn_menu") audio.Play("btn_menu")
@ -133,12 +136,14 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return fmt.Sprintf("./mods/%s/images/", item) return fmt.Sprintf("./mods/%s/images/", item)
})...) })...)
isSOD := m.choices.selected == ChoiceNewGameSOD
m.choices = m.choices.Clear() m.choices = m.choices.Clear()
return m, tea.Sequence( return m, tea.Sequence(
cmd, cmd,
root.Push(gameview.New(m, m.zones, game.NewSession( root.Push(gameview.New(m, m.zones, game.NewSession(
game.WithLogging(log.New(f, "SESSION ", log.Ldate|log.Ltime|log.Lshortfile)), game.WithLogging(log.New(f, "SESSION ", log.Ldate|log.Ltime|log.Lshortfile)),
game.WithMods(m.settings.GetStrings("mods")), game.WithMods(m.settings.GetStrings("mods")),
lo.Ternary(isSOD, game.WithSeedString(time.Now().Format(time.DateOnly)), nil),
lo.Ternary(os.Getenv("EOE_DEBUG") == "1", game.WithDebugEnabled(8272), nil), lo.Ternary(os.Getenv("EOE_DEBUG") == "1", game.WithDebugEnabled(8272), nil),
))), ))),
) )