Skip to content
Snippets Groups Projects
Commit 19c8caaa authored by dg's avatar dg
Browse files

quests !

git-svn-id: http://svn.net-core.org/repos/t-engine4@380 51575b47-30f0-44d4-a5cc-537603b46e54
parent 159667df
No related branches found
No related tags found
No related merge requests found
Showing
with 340 additions and 62 deletions
......@@ -18,6 +18,13 @@ defineAction{
name = "Use talents",
}
defineAction{
default = { "sym:113:true:false:false:false" },
type = "SHOW_QUESTS",
group = "actions",
name = "Show quests",
}
defineAction{
default = { "uni:R" },
type = "REST",
......
......@@ -175,8 +175,9 @@ Mouse: #00FF00#Left click#FFFFFF# to increase a stat; #00FF00#right click#FFFFFF
end
local lines = self.list[self.sel].desc:splitLines(self.iw / 2 - 10, self.font)
local r, g, b
for i = 1, #lines do
s:drawColorString(self.font, lines[i], self.iw / 2 + 5, 2 + (i + #birthhelp + 1) * self.font:lineSkip())
r, g, b = s:drawColorString(self.font, lines[i], self.iw / 2 + 5, 2 + (i + #birthhelp + 1) * self.font:lineSkip(), r, g, b)
end
-- Stats
......
require "engine.class"
module(..., package.seeall, class.make)
PENDING = 0
COMPLETED = 1
DONE = 100
FAILED = 101
function _M:init(q)
for k, e in pairs(q) do
self[k] = e
end
self.status = PENDING
self.objectives = {}
end
--- Checks if the quest (or sub-objective) is complete
-- @param sub a subobjective id or nil for the whole quest
-- @return true or false
function _M:isCompleted(sub)
if sub then
if self.objectives[sub] and self.objectives[sub] == COMPLETED then return true else return false end
end
if self.status == COMPLETED then return true else return false end
end
--- Checks if the quest is ended (DONE or FAILED)
-- @return true or false
function _M:isEnded()
if self.status == DONE or self.status == FAILED then return true else return false end
end
--- Check for an quest property
-- If not a function it returns it directly, otherwise it calls the function
-- with the extra parameters
-- @param prop the property name to check
function _M:check(prop, ...)
if type(self[prop]) == "function" then return self[prop](self, ...)
else return self[prop]
end
end
--- Sets the quets status or sub-objective status
-- @param status one of the possible quest status (PENDING, COMPLETED, DONE, FAILED)
function _M:setStatus(status, sub, who)
if sub then
if self.objectives[sub] == status then return false end
self.objectives[sub] = status
self:check("on_status_change", who, status, sub)
return true
else
if self.status == status then return false end
self.status = status
self:check("on_status_change", who, status)
return true
end
end
......@@ -3,3 +3,54 @@ colors = {}
function defineColor(name, r, g, b, br, bg, bb)
colors[name] = {r=r, g=g, b=b, br=br, bg=bg, bb=bb}
end
defineColor('WHITE', 0xFF, 0xFF, 0xFF)
defineColor('SLATE', 0x8C, 0x8C, 0x8C)
defineColor('ORANGE', 0xFF, 0x77, 0x00)
defineColor('RED', 0xC9, 0x00, 0x00)
defineColor('GREEN', 0x00, 0x86, 0x45)
defineColor('BLUE', 0x00, 0x00, 0xE3)
defineColor('UMBER', 0x8E, 0x45, 0x00)
defineColor('LIGHT_DARK', 0x50, 0x50, 0x50)
defineColor('LIGHT_SLATE', 0xD1, 0xD1, 0xD1)
defineColor('VIOLET', 0xC0, 0x00, 0xAF)
defineColor('YELLOW', 0xFF, 0xFF, 0x00)
defineColor('LIGHT_RED', 0xFF, 0x00, 0x68)
defineColor('LIGHT_GREEN', 0x00, 0xFF, 0x00)
defineColor('LIGHT_BLUE', 0x51, 0xDD, 0xFF)
defineColor('LIGHT_UMBER', 0xD7, 0x8E, 0x45)
defineColor('ROYAL_BLUE', 65, 105, 225)
defineColor('AQUAMARINE', 127, 255, 212)
defineColor('CADET_BLUE', 95, 158, 160)
defineColor('STEEL_BLUE', 70, 130, 180)
defineColor('TEAL', 0, 128, 128)
defineColor('LIGHT_STEEL_BLUE', 176, 196, 222)
defineColor('PINK', 255, 192, 203)
defineColor('GOLD', 255, 215, 0)
defineColor('FIREBRICK', 178, 34, 34)
defineColor('DARK_RED', 100, 0, 0)
defineColor('CRIMSON', 220, 20, 60)
defineColor('MOCCASIN', 255, 228, 181)
defineColor('KHAKI', 240, 230, 130)
defineColor('SANDY_BROWN', 244, 164, 96)
defineColor('SALMON', 250, 128, 114)
defineColor('DARK_ORCHID', 153, 50, 204)
defineColor('ORCHID', 218, 112, 214)
defineColor('PURPLE', 128, 0, 139)
defineColor('CHOCOLATE', 210, 105, 30)
defineColor('DARK_KHAKI', 189, 183, 107)
defineColor('TAN', 210, 180, 140)
defineColor('HONEYDEW', 240, 255, 240)
defineColor('ANTIQUE_WHITE', 250, 235, 215)
defineColor('OLD_LACE', 253, 245, 230)
defineColor('DARK_SLATE_GRAY', 47, 79, 79)
defineColor('OLIVE_DRAB', 107, 142, 35)
defineColor('DARK_SEA_GREEN', 143, 188, 143)
defineColor('YELLOW_GREEN', 154, 205, 50)
defineColor('DARK_GREEN', 50, 77, 12)
require "engine.class"
require "engine.Dialog"
module(..., package.seeall, class.inherit(engine.Dialog))
function _M:init(actor)
self.actor = actor
actor.hotkey = actor.hotkey or {}
engine.Dialog.init(self, "Quest Log for "..actor.name, game.w, game.h)
self:generateList()
self.sel = 1
self.scroll = 1
self.max = math.floor((self.ih - 5) / self.font_h) - 1
self:keyCommands({
_t = function()
self.sel = 1
self.scroll = 1
self.show_ended = not self.show_ended
self:generateList()
self.changed = true print("plop")
end,
},{
MOVE_UP = function() self.sel = util.boundWrap(self.sel - 1, 1, #self.list) self.scroll = util.scroll(self.sel, self.scroll, self.max) self.changed = true end,
MOVE_DOWN = function() self.sel = util.boundWrap(self.sel + 1, 1, #self.list) self.scroll = util.scroll(self.sel, self.scroll, self.max) self.changed = true end,
EXIT = function() game:unregisterDialog(self) end,
})
self:mouseZones{
{ x=2, y=5, w=350, h=self.font_h*self.max, fct=function(button, x, y, xrel, yrel, tx, ty)
self.sel = util.bound(self.scroll + math.floor(ty / self.font_h), 1, #self.list)
if button == "left" then
elseif button == "right" then
end
end },
}
end
function _M:generateList()
-- Makes up the list
local list = {}
for id, q in pairs(self.actor.quests or {}) do
if not q:isEnded() or self.show_ended then
list[#list+1] = { name=q.name, quest=q, color = q:isCompleted() and {0,255,0} or nil }
end
end
if game.turn then
table.sort(list, function(a, b) return a.quest.gained_turn < b.quest.gained_turn end)
else
table.sort(list, function(a, b) return a.quest.name < b.quest.name end)
end
self.list = list
end
function _M:drawDialog(s)
-- Description part
self:drawHBorder(s, self.iw / 2, 2, self.ih - 4)
local r, g, b
local help = [[Keyboard: #00FF00#up key/down key#FFFFFF# to select a stat; #00FF00#t#FFFFFF# to toggle finished quests.
]]
local talentshelp = help:splitLines(self.iw / 2 - 10, self.font)
local lines = {}
if self.list[self.sel] then
lines = self.list[self.sel].quest:desc(self.actor):splitLines(self.iw / 2 - 10, self.font)
end
local h = 2
for i = 1, #talentshelp do
s:drawColorString(self.font, talentshelp[i], self.iw / 2 + 5, h)
h = h + self.font:lineSkip()
end
h = h + self.font:lineSkip()
self:drawWBorder(s, self.iw / 2 + self.iw / 6, h - 0.5 * self.font:lineSkip(), self.iw / 6)
for i = 1, #lines do
r, g, b = s:drawColorString(self.font, lines[i], self.iw / 2 + 5, 2 + h, r, g, b)
h = h + self.font:lineSkip()
end
-- Talents
self:drawSelectionList(s, 2, 5, self.font_h, self.list, self.sel, "name", self.scroll, self.max)
end
......@@ -49,6 +49,11 @@ function _M:takeHit(value, src)
end
end
--- Called when died
function _M:die(src)
self:check("on_die", src)
end
--- Actor is being attacked!
-- Module authors should rewrite it to handle combat, dialog, ...
-- @param target the actor attacking us
......
require "engine.class"
--- Handles actors quests
module(..., package.seeall, class.make)
_M.quest_class = "engine.Quest"
--- Grants a quest to an actor from the given quest definition
function _M:grantQuest(quest)
if type(quest) == "string" then
local f = loadfile("/data/quests/"..quest..".lua")
local ret = {}
setfenv(f, setmetatable(ret, {__index=_G}))
f()
ret.id = ret.id or quest
quest = ret
end
if not quest.id then quest.id = quest.name end
if self:hasQuest(quest.id) then return end
assert(quest.name, "no quest name")
assert(quest.desc, "no quest desc")
self.quests = self.quests or {}
self.quests[quest.id] = require(_M.quest_class).new(quest)
self.quests[quest.id].gained_turn = game.turn
print("[QUEST] given to", self, quest.id)
self:check("on_quest_grant", quest)
end
--- Sets the status of a quest for an actor
-- If the actor does not have the quest, does nothing
function _M:setQuestStatus(quest, status, sub)
print("[QUEST] try update status on", self.name, quest, status, sub, "::", self.quests[quest])
if not self.quests then return end
local q = self.quests[quest]
if not q then return end
if q:setStatus(status, sub, self) then
self:check("on_quest_status", q, status, sub)
end
end
--- Checks if the actor has this quest
function _M:hasQuest(id)
if not self.quests then return false end
return self.quests[id] and true or false
end
......@@ -93,6 +93,11 @@ function string.splitLine(str, max_width, font)
local color_w = font:size(color)
w = w - color_w
end
local _, _, color = v:find("(#[A-Z_]+#)")
if color then
local color_w = font:size(color)
w = w - color_w
end
if cur_size + space_w + w < max_width then
cur_line = cur_line..(cur_size==0 and "" or " ")..v
......@@ -181,20 +186,24 @@ end
local tmps = core.display.newSurface(1, 1)
getmetatable(tmps).__index.drawColorString = function(s, font, str, x, y, r, g, b)
local list = str:split("#%x%x%x%x%x%x#", true)
local list = str:split("#[a-zA-Z0-9_]+#", true)
r = r or 255
g = g or 255
b = b or 255
for i, v in ipairs(list) do
local _, _, nr, ng, nb = v:find("^#(%x%x)(%x%x)(%x%x)#")
local _, _, col = v:find("^#([A-Z_]+)#")
if nr and ng and nb then
r, g, b = nr:parseHex(), ng:parseHex(), nb:parseHex()
elseif col then
r, g, b = colors[col].r, colors[col].g, colors[col].b
else
local w, h = font:size(v)
s:drawString(font, v, x, y, r, g, b)
x = x + w
end
end
return r, g, b
end
getmetatable(tmps).__index.drawColorStringCentered = function(s, font, str, dx, dy, dw, dh, r, g, b)
......
......@@ -8,6 +8,7 @@ require "engine.interface.ActorLevel"
require "engine.interface.ActorStats"
require "engine.interface.ActorTalents"
require "engine.interface.ActorResource"
require "engine.interface.ActorQuest"
require "engine.interface.BloodyDeath"
require "mod.class.interface.Combat"
local Map = require "engine.Map"
......@@ -22,6 +23,7 @@ module(..., package.seeall, class.inherit(
engine.interface.ActorStats,
engine.interface.ActorTalents,
engine.interface.ActorResource,
engine.interface.ActorQuest,
engine.interface.BloodyDeath,
mod.class.interface.Combat
))
......@@ -258,6 +260,8 @@ function _M:onTakeHit(value, src)
end
function _M:die(src)
engine.interface.ActorLife.die(self, src)
-- Gives the killer some exp for the kill
if src then
src:gainExp(self:worthExp(src))
......
......@@ -80,7 +80,6 @@ function _M:run()
end
function _M:newGame()
self.zone = Zone.new("wilderness")
self.player = Player.new{name=self.player_name}
Map:setViewerActor(self.player)
self:setupDisplayMode()
......@@ -88,10 +87,11 @@ function _M:newGame()
local birth = Birther.new(self.player, {"base", "race", "subrace", "sex", "class", "subclass" }, function()
self.player.wild_x, self.player.wild_y = self.player.default_wilderness[2], self.player.default_wilderness[3]
self.player.current_wilderness = self.player.default_wilderness[1]
self:changeLevel(1)
self:changeLevel(1, self.player.starting_zone)
self.player:resolve()
self.player:resolve(nil, true)
self.player:playerLevelup()
self.player:grantQuest(self.player.starting_quest)
end)
self:registerDialog(birth)
end
......@@ -474,6 +474,10 @@ function _M:setupCommands()
self:saveGame()
end,
SHOW_QUESTS = function()
self:registerDialog(require("engine.dialogs.ShowQuests").new(self.player))
end,
-- Show time
SHOW_TIME = function()
self.log(self.calendar:getTimeDate(self.turn))
......
......@@ -298,3 +298,21 @@ function _M:playerLevelup()
game:registerDialog(dt)
end
end
------ Quest Events
function _M:on_quest_grant(quest)
game.logPlayer(self, "#LIGHT_GREEN#Accepted quest '%s'!", quest.name)
end
function _M:on_quest_status(quest, status, sub)
if sub then
game.logPlayer(self, "#LIGHT_GREEN#Quest '%s' status updated!", quest.name)
elseif status == engine.Quest.COMPLETED then
game.logPlayer(self, "#LIGHT_GREEN#Quest '%s' completed!", quest.name)
elseif status == engine.Quest.DONE then
game.logPlayer(self, "#LIGHT_GREEN#Quest '%s' is done!", quest.name)
elseif status == engine.Quest.FAILED then
game.logPlayer(self, "#LIGHT_RED#Quest '%s' is failed!", quest.name)
end
end
defineColor('WHITE', 0xFF, 0xFF, 0xFF)
defineColor('SLATE', 0x8C, 0x8C, 0x8C)
defineColor('ORANGE', 0xFF, 0x77, 0x00)
defineColor('RED', 0xC9, 0x00, 0x00)
defineColor('GREEN', 0x00, 0x86, 0x45)
defineColor('BLUE', 0x00, 0x00, 0xE3)
defineColor('UMBER', 0x8E, 0x45, 0x00)
defineColor('LIGHT_DARK', 0x50, 0x50, 0x50)
defineColor('LIGHT_SLATE', 0xD1, 0xD1, 0xD1)
defineColor('VIOLET', 0xC0, 0x00, 0xAF)
defineColor('YELLOW', 0xFF, 0xFF, 0x00)
defineColor('LIGHT_RED', 0xFF, 0x00, 0x68)
defineColor('LIGHT_GREEN', 0x00, 0xFF, 0x00)
defineColor('LIGHT_BLUE', 0x51, 0xDD, 0xFF)
defineColor('LIGHT_UMBER', 0xD7, 0x8E, 0x45)
defineColor('ROYAL_BLUE', 65, 105, 225)
defineColor('AQUAMARINE', 127, 255, 212)
defineColor('CADET_BLUE', 95, 158, 160)
defineColor('STEEL_BLUE', 70, 130, 180)
defineColor('TEAL', 0, 128, 128)
defineColor('LIGHT_STEEL_BLUE', 176, 196, 222)
defineColor('PINK', 255, 192, 203)
defineColor('GOLD', 255, 215, 0)
defineColor('FIREBRICK', 178, 34, 34)
defineColor('DARK_RED', 100, 0, 0)
defineColor('CRIMSON', 220, 20, 60)
defineColor('MOCCASIN', 255, 228, 181)
defineColor('KHAKI', 240, 230, 130)
defineColor('SANDY_BROWN', 244, 164, 96)
defineColor('SALMON', 250, 128, 114)
defineColor('DARK_ORCHID', 153, 50, 204)
defineColor('ORCHID', 218, 112, 214)
defineColor('PURPLE', 128, 0, 139)
defineColor('CHOCOLATE', 210, 105, 30)
defineColor('DARK_KHAKI', 189, 183, 107)
defineColor('TAN', 210, 180, 140)
defineColor('HONEYDEW', 240, 255, 240)
defineColor('ANTIQUE_WHITE', 250, 235, 215)
defineColor('OLD_LACE', 253, 245, 230)
defineColor('DARK_SLATE_GRAY', 47, 79, 79)
defineColor('OLIVE_DRAB', 107, 142, 35)
defineColor('DARK_SEA_GREEN', 143, 188, 143)
defineColor('YELLOW_GREEN', 154, 205, 50)
defineColor('DARK_GREEN', 50, 77, 12)
......@@ -34,6 +34,6 @@ load("/data/birth/sexes.lua")
-- Classes
load("/data/birth/warrior.lua")
load("/data/birth/rogue.lua")
load("/data/birth/archer.lua")
load("/data/birth/rogue.lua")
load("/data/birth/mage.lua")
......@@ -28,7 +28,9 @@ newBirthDescriptor{
},
copy = {
type = "humanoid", subtype="dwarf",
default_wilderness = {"wilderness/main", 41, 18},
default_wilderness = {"wilderness/main", 39, 19},
starting_zone = "tower-amon-sul",
starting_quest = "start-dunadan",
life_rating=12,
},
experience = 1.1,
......
......@@ -23,7 +23,9 @@ newBirthDescriptor{
},
copy = {
type = "humanoid", subtype="elf",
default_wilderness = {"wilderness/main", 41, 18},
default_wilderness = {"wilderness/main", 39, 19},
starting_zone = "tower-amon-sul",
starting_quest = "start-dunadan",
},
experience = 1.05,
}
......
......@@ -38,7 +38,9 @@ newBirthDescriptor{
copy = {
type = "humanoid", subtype="hobbit",
life_rating = 12,
default_wilderness = {"wilderness/main", 41, 18},
default_wilderness = {"wilderness/main", 39, 19},
starting_zone = "tower-amon-sul",
starting_quest = "start-dunadan",
},
}
......
......@@ -36,7 +36,9 @@ newBirthDescriptor
"Humans hailing from the northen town of Bree. A common kind of man, unremarkable in all respects.",
},
copy = {
default_wilderness = {"wilderness/main", 41, 18},
default_wilderness = {"wilderness/main", 39, 19},
starting_zone = "tower-amon-sul",
starting_quest = "start-dunadan",
},
}
......@@ -56,7 +58,9 @@ newBirthDescriptor
[ActorTalents.T_DUNADAN_HEAL]=1,
},
copy = {
default_wilderness = {"wilderness/main", 41, 18},
default_wilderness = {"wilderness/main", 39, 19},
starting_zone = "tower-amon-sul",
starting_quest = "start-dunadan",
},
}
--[[
......
-- Quest for Trollshaws & Amon Sul
name = "Of trolls and damp caves"
desc = function(self, who)
local desc = {}
desc[#desc+1] = "Explore the caves below the tower of Amon Sûl and the trollshaws in search of treasure and glory!\n"
if self:isCompleted("amon-sul") then
desc[#desc+1] = "#LIGHT_GREEN#* You have explored Amon Sûl and vanquished the Shade of Angmar.#WHITE#"
else
desc[#desc+1] = "#SLATE#* You must explore Amon Sûl and find out what lurks there and what treasures are to be gained!#WHITE#"
end
if self:isCompleted("trollshaws") then
desc[#desc+1] = "#LIGHT_GREEN#* You have explored the Trollshaws and vanquished the Bill the Stone Troll.#WHITE#"
else
desc[#desc+1] = "#SLATE#* You must explore the Trollshaws and find out what lurks there and what treasures are to be gained!#WHITE#"
end
return table.concat(desc, "\n")
end
on_status_change = function(self, who, status, sub)
if sub then
if self:isCompleted("amon-sul") and self:isCompleted("trollshaws") then
who:setQuestStatus(self.id, engine.Quest.FINISHED)
end
end
end
......@@ -17,8 +17,8 @@ newEntity{ define_as = "THE_MASTER",
body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1, NECK=1, },
equipment = resolvers.equip{
{type="weapon", subtype="greatsword"},
{type="armor", subtype="heavy"},
{type="weapon", subtype="greatsword", ego_chance=100},
{type="armor", subtype="heavy", ego_chance=50},
{type="jewelry", subtype="amulet", defined="AMULET_DREAD"},
},
resolvers.drops{chance=100, nb=5, {ego_chance=100} },
......
......@@ -29,4 +29,8 @@ newEntity{ define_as = "SHADE_OF_ANGMAR",
autolevel = "warriormage",
ai = "dumb_talented_simple", ai_state = { talent_in=4, },
on_die = function(self, who)
who:setQuestStatus("start-dunadan", engine.Quest.COMPLETED, "amon-sul")
end,
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment