DuskEngine Devlog 6 - Town Extension Edition
Most of the work this past month has been done on the gameplay side of things, rather than the engine. Here's all the new stuff from my not yet announced RPG.
The Town of Kukelberg Got an Extension
There's now a proper town square. Here's a before & after:
The central area buildings are all made of modular pieces. I think I'll make it so when the player is inside a building, the second floor and roof get hidden, so you can see inside the building properly.
Dialogues and the First Quest
NPCs can now be talked to. I implemented a basic dialogue system with options, and with it, the first ever quest.
Maki, our placeholder NPC, asks you for several items that just happen to lie around the town (two eggs, two healing plants and two mana plants, if you're curious).
Getting ready to turn the items in.
Here's the code (Lua) behind Maki's dialogue and quest operations:
View Code
CharaDialogue_Maki = {}
function CharaDialogue_Maki:PlayerHasPlantQuestItems(player)
return player.ItemInventory:HasItem(InventoryItems.HealthPlant, 2)
and player.ItemInventory:HasItem(InventoryItems.ManaPlant, 2)
and player.ItemInventory:HasItem(InventoryItems.RawEgg, 2)
end
function CharaDialogue_Maki:GivePlantQuestItems(player, character)
return {
Text = { "Thanks!" },
OnFinishedTelling = function()
if self:PlayerHasPlantQuestItems(player) then
player.ItemInventory:RemoveItem(InventoryItems.HealthPlant, 2)
player.ItemInventory:RemoveItem(InventoryItems.ManaPlant, 2)
player.ItemInventory:RemoveItem(InventoryItems.RawEgg, 2)
StoryVars.CompleteQuest(Quests.MakisPlants)
end
end,
GetOptions = function()
return self:MakeBaseOptions(player, character)
end
}
end
function CharaDialogue_Maki:MakeBaseOptions(player, character)
local options = {}
if not StoryVars.PlayerKnowsCharacter(NPCData.npc_kukelberg_maki) then
table.insert(options,
{
Label = "What's your name?",
OnChosen = function()
return self.TellName
end
})
elseif StoryVars.QuestNotYetStarted(Quests.MakisPlants) then
table.insert(options,
{
Label = "Do you need help with anything?",
OnChosen = function()
return self.TellAboutPlantQuest
end
})
end
if StoryVars.QuestIsInProgress(Quests.MakisPlants)
and self:PlayerHasPlantQuestItems(player) then
table.insert(options,
{
Label = "I've got your items.",
OnChosen = function()
return self.GivePlantQuestItems
end
})
end
return options
end
function CharaDialogue_Maki:PlantQuestAccepted(player, character)
return {
Text = {
"Great, do hurry now."
},
GetOptions = function()
return self:MakeBaseOptions(player, character)
end
}
end
function CharaDialogue_Maki:PlantQuestRefused(player, character)
return {
Text = {
"What, you don't like doing chores for free?"
},
GetOptions = function()
return self:MakeBaseOptions(player, character)
end
}
end
function CharaDialogue_Maki:TellAboutPlantQuest(player, character)
return {
Text = {
"I do need some help.",
"There are some healing and magic plants around here somewhere.",
"Bring me two of each, please.",
"And a couple of eggs too."
},
DisallowExit = true,
GetOptions = function()
return {
{
Label = "Guess I'll do it...",
OnChosen = function()
StoryVars.StartQuest(Quests.MakisPlants)
return self.PlantQuestAccepted
end
},
{
Label = "Nah, not interested.",
OnChosen = function()
return self.PlantQuestRefused
end
}
}
end
}
end
function CharaDialogue_Maki:TellName(player, character)
return {
Text = { "My name is Maki." },
OnFinishedTelling = function()
StoryVars.MakeCharacterKnown(NPCData.npc_kukelberg_maki)
end,
GetOptions = function()
return self:MakeBaseOptions(player, character)
end
}
end
function CharaDialogue_Maki:GetStartState(player, character)
local text = "Hello."
if StoryVars.PlayerKnowsCharacter(NPCData.npc_kukelberg_maki) then
text = "Nice to see you again."
end
if StoryVars.QuestIsInProgress(Quests.MakisPlants) then
text = "Have you brought the items?"
end
return {
Text = { text },
GetOptions = function()
return self:MakeBaseOptions(player, character)
end
}
end
I'm not entirely sure if I want to go with a data driven approach for this (such as encoding dialogues in XML or some other third party tool). I quite like the ability to run arbitrary Lua as the dialogue progresses.
However, the dialogue lines themselves will have to be moved somewhere else, for localization purposes.
Dynamic Parties
The player's party used to be hardcoded for testing purposes, but now it's dynamic, NPCs can join and leave whenever the player wishes. It happens via the dialogue system, right now.
It works like this...
Also noticeable in the video is the fact that Rina's (the NPC) name is shown as "Townsperson" until the player asks for her name. This will apply to all NPCs.
New Sitting Animation and Character Routines
I modeled a bench and added a sitting animation. This, paired with resurrecting the old NPC routine code (its first usage can be seen in this older bsky post), means NPCs can walk around the town and sit on benches to take breaks.
There's a lack of unique NPCs so I copy pasted some.
A Chest You can Open
The first openable and usable container! A chest with items inside. The panel showing the items inside is using the newly added support for Grid Layouts in the gameplay UI system. All item container type UIs use such a grid layout, now.
Calendar in the Diary
This is also using a Grid Layout.
It's quite barren right now, but as the game progresses, the plan for it is to contain character birthdays, important events as well as quest deadlines, if any.
The entire diary UI, not just the calendar, will receive extra attention in the near future...
Finally, DuskEngine Improvements
-
The pathfinding system now generates better looking paths, it has been upgraded from A* to Theta*
-
Certain elements of the gameplay UI now support scrolling
-
Grid layout support has been added to the gameplay UI system, used for inventory panels as well as the calendar in the diary
-
Big optimizations on the renderer side (around 30% FPS improvement in what I measured to be the worst case), by reducing the number of writes done to an SSBO, every frame. Still a lot of improvement possible in this area...
For any questions or feedback, find me on BlueskyFirefly in the Dusk🌙



