Several months later and our next game Dire is soon to release… the planned date is September 4th as long as nothing goes wrong until then. We’re still working on finalizing it, and like with Harvest we’ll have a few months of post release updates with several major free additions that will happen. The price will be higher than the last game, $17.99 this time, 10% off launch discount.
Wishlist total is 3,164. Although I am officially off the Wishlist bandwagon and even Steam/Valve bandwagon (I wrote an angry rant detailing some reasons why https://www.solitaire.io/blog/valve-is-not-your-friend/ ). Wishlists can still be valuable for big games but I feel like it’s a completely bad idea to build wishlists themselves. If that’s not what Steam is supposed to do organically itself then it’s not worth the developer focusing their energy on doing. And furthermore driving sales to Steam as devs should never happen. Devs should always sell directly (if not completely direct itch.io is good enough), and promote their direct purchases/their own newsletter counts, not feed the beast that is Valve’s soft monopoly. So with our next games which we probably still publish on Steam we will try to never link to Steam, we won’t focus on building wishlists, and instead we will focus on only building newsletter subscribers. We will also be pricing all of our direct sales copies of our games ~20-30% less depending on the title than the Steam version going forward as permanent discounts. So the direct purchase price of Dire will probably be $12.99 when we set it up.
With Dire we made several new useful side products. One of them is Stage. Which is a pseudo Visual Novel like scene system. The cool thing about it is that it is super easy to customize everything since it all takes place within GUI scripts. It’s not universally perfect for every use case but for us it is a good simple system.
The above scene is produced by this script:
require("globals")
local stage = require("screens.stage.code.stage")
local broadcast = require("ludobits.m.broadcast")
local richtext = require("richtext.richtext")
local monarch = require("monarch.monarch")
local cursor = require("main.code.cursor")
local stage_handler = require("screens.stage.code.stage_handler")
local audio_manager = require("imports.audio_manager")
stage.routines = {}
function stage.routines.part_1()
local title = "Prologue 1"
local subtitle = "Dreams of Fate"
stage.title = title
stage.subtitle = subtitle
stage.animate_background("bg")
stage.animate_titles(self, title, subtitle)
print_line("START PART 1")
stage.say("<macro=lotus>Jha</macro> dreamt of the <action=particles:text_emitter_green><color=abyssal_green>end of all things</color></action>. This dream was his earliest memory. When he slept he would see emanations of fate, over and over, events that would soon pass, others that could be years away.")
stage.say("He saw a fierce girl with an ethereal sword of <color=sunlight>sunlight</color>, this child would one day be his daughter, he thought.")
stage.say("Menia: ...!")
stage.say("Jha saw Seteri, who had been training Jha to take the oath of the warden and enter the depths of the abyss as an <action=particles:text_emitter_green><color=abyssal_green>undying child</color></action>.")
stage.say("Seteri: You have been chosen. Come with me, Jha.")
stage.say("Jha was 4 when he was taken away from his parents and made to begin training, now he was 15, almost a man. ")
stage.say("He should have already been forced into the abyss and given to the other wardens, but something was wrong with Jha. ")
stage.say("The <action=particles:text_emitter_red><color=lotus_red>breath of the lotus</color></action> would not take, his skin had still not turned to ashy white, he did not fear the sunlight or moonlight or starlight. Yet when visiting the chasm that he would have one day been made to enter, his resilience against the dark was perfect. ")
stage.say("Jha knew that Seteri feared him. He saw Seteri speaking with the other elders of his tribe, mad with fear, that Jha had been given the <action=particles:text_emitter_red><color=lotus_red>drink</color></action> made from the abyssal lotuses, and yet he did not <action=particles:text_emitter_green><color=abyssal_green>turn</color></action>. If Jha were allowed to still join the wardens and complete his training, he would be able to return without fear, and walk under the sun and stars.")
stage.say("It was too much of a risk for Jha to ever enter the abyss. Seteri took a long bone knife and walked to where Jha was sleeping with the intent to kill.")
stage.say("Jha saw a boy from the village who was now, in his dream, some years older, he had taken the oath, and turned. Seteri was behind him, clothed in heavy garb dyed in the colors of the <action=particles:text_emitter_red><color=lotus_red>undying lotus</color></action>.")
stage.say("Seteri: Descend.")
stage.say("The boy looked back at Seteri with fear in his eyes, and shook his head. The chasm tree’s mites swarmed around Seteri, lashing at his face, but did nothing to the boy.")
stage.say("Seteri: This is your duty. The others are waiting for you on the other side. Now go, be brave, take the final step.")
stage.say("Jha saw that there would be hunters sent after him, he saw where the hunters would look, and so he knew where to hide. The elders would send assassins for years, but Jha would kill them.")
stage.say("Jha awoke some time before Seteri would decide that he must die.")
stage.say("Jha carefully took what he would need, and quietly left his village behind, never to become a warden.")
stage.say("He would return one day.")
stage.say("As the divine emperor of all of <action=particles:text_emitter_green><color=abyssal_green>Atlas</color></action>.")
stage.scene_over = true
stage.say()
stage.delay(.6, true, true, false)
stage_handler.go_back()
print_line("END PART 1")
end
function init_actual(self)
stage.init_actual(self)
end
function init(self)
stage.init(self)
end
function final(self)
stage.final(self)
end
function update(self, dt)
stage.update(self, dt)
end
function on_message(self, message_id, message, sender)
stage.on_message(self, message_id, message, sender)
end
function on_input(self, action_id, action)
stage.on_input(self, action_id, action)
end
function on_reload(self)
end
Between any of the stage.say() commands you can put any kind of logic/animations/whatever you want.
Most of the magic is from RichText (with some custom features) and Lua coroutines.
Localization is handled in a similar way to Ren’Py.
This Stage system (along with a nice and complete example project with some extra goodies) will be released in the future for free for any active verifiable sponsor of Defold on Github. The amount doesn’t matter, anyone with an active sponsorship will be able to download it once I release it. Going forward, most of the things I release will be for sponsors of Defold only as a way to incentivize and reward the people who do that. If you’re not a sponsor yet go support Defold here https://github.com/sponsors/defold even $1 adds up if many people do it. Supporting the Defold Foundation is very worth it and is our responsibility to do as devs who use the great software.