Daimonin
Members login
Sign Up!      problems?
N F
* Daimonin Forum
Home Help Search Calendar

Welcome Guest, you have to register to post here.
Search

News

Stats
75655 Posts in 6829 Topics by 8142 Members
Latest Member: mattj
Daimonin Forum  |  Development  |  Scripts  |  Topic: quest_builder.lua « previous next »
Pages: 1 2 3 [4] Go Down Print
Topic: quest_builder.lua  (Read 2638 times)
Torchwood
MapMaster
*
*
*


Karma: +35/-5
Posts: 968



View Profile
« Reply #45 on: April 21, 2008, 06:31:22 am »

Quote
I'll update the wiki doc

(And fix the IE display problems as well I hope?)
Logged

smacky
Administrator
*
*
*
*


Karma: +120/-101
Posts: 5381



View Profile
« Reply #46 on: April 21, 2008, 11:57:17 am »

Still not sure I really understand why you don't just return the quest number and allow QSTAT_DISALLOW ...
That'd mean:
Code:
if questnr = 1 and qb:GetStatus(1) == game.QSTAT_DISALLOW then

Whereas with negatives you just do:
Code:
if questnr == -1 then
To add to this, you can always call qb:GetStatus(questnr) to get the game.QSTAT_FOO for that quest (questnr can be negative or positive, though if negative we already know it is DISALLOW so the call is pointless).

As explained above, questnr will never be DONE (because when a quest is done we go to the next quest or nil). But you can call qb:GetStatus() on a constant if you like to get that quests's status, done or not ('if questnr == nil or questnr > n' if the same as 'if qb:GetStatus(n) == game.QSTAT_DONE').
Logged

smacky
Administrator
*
*
*
*


Karma: +120/-101
Posts: 5381



View Profile
« Reply #47 on: April 25, 2008, 01:18:18 am »

Quote
smacky * r3441 /trunk/maps/lua/quest_builder.lua:
 * RemoveQuestItems() is called automatically from qb:Finish()
 * Add goal and reward parameters to qb:AddQuest(),
  These are optional functions which are defined in the talk script.
  If specified they are called automarically by qb:RegisterQuest() (goal) and qb:Finish() (reward),
  allowing the talk script to cleanly separate 'do' code (creating objects, etc) from 'tell' code (ib, etc).
The first change means qb:RemoveQuestItems() is redundant. Unless someone can think of a reason scripters need to call it/it shouldn't be called automatically, I'll actually remove it from qb.lua.

The second change allows you to more clearly 'group' your code according to purpose.
For example, with goal and reward functions Fanrir's script is like this (I'll just do one quest):
Code:
require("quest_builder")
local qb = QuestBuilder()
local questnr
local function questGoals()
    ---------
    -- "Mouse Hunt"
    ---------
    elseif questnr == 3 then
        qb:AddQuestTarget(3, 2, 2, "mouse", "Mouse"):AddQuestItem(2, "quest_object", "tail_rat.101", "Mouse tail")
        local ds = DataStore("fanrir", player)
        if not ds:Get("weapon given") then
            ds:Set("weapon given", true)
            ds:WasChanged()
            local weaponarch = {
                [game:GetSkillNr("slash weapons") ] = "shortsword",
                [game:GetSkillNr("impact weapons")] = "mstar_small",
                [game:GetSkillNr("cleave weapons")] = "axe_small",
                [game:GetSkillNr("pierce weapons")] = "dagger_large"
            }
            for k, v in pairs(weaponarch) do
                skill = player:FindSkill(k)
                if skill and skill.experience == 0 and not player:GetEquipment(game.EQUIP_WEAPON1) then
                    local weapon = player:CreateObjectInsideEx(v, 1, game.IDENTIFIED)
                    assert(weapon, "Could not create weapon!")
                    player:Apply(weapon, game.APPLY_ALWAYS)
                    player:Write(npc.name .. " says: Here, take this weapon for the task.")
                    break
                end
            end
        end
    end
end
local function questRewards()
    ---------
    -- "Mouse Hunt"
    ---------
    elseif questnr == 3 then
        player:AddMoney(10, 0, 0, 0)
    end
end
qb:AddQuest("Mouse Hunt", game.QUEST_KILLITEM, nil, nil, nil, nil, questGoals, questRewards)
questnr = qb:Build(player)
-- ...
local function topic_questAccept()
    ---------
    -- Player is eligible for a quest.
    ---------
    else
        ib:SetTitle(qb:GetName(questnr))
        ---------
        -- "Mouse Hunt"
        ---------
        elseif questnr == 3 then
            ib:SetMsg("|Hint -- Attacking mobs|\n")
            ib:AddMsg("\n'~Mobs~' is just another word for monsters and monsters are anything alive (or later on, undead too!) " ..
                      "that is your enemy. So mice are monsters are mobs.\n")
            ib:AddMsg("\nOK, now that introductions are over, the important question: how do you attack them? " ..
                      "There are three steps to attacking a mob:\n")
            ib:AddMsg("\n~(1)~ turn on combat mode -- do this by pressing ~C~ " ..
                     "(pressing it a second time turns combat mode off again -- you can see which mode you are in by looking at " ..
                     "the icon in the lower left part of the screen);\n")
            ib:AddMsg("\n~(2)~ target a mob -- do this by pressing ~X~ " ..
                      "(this will actually cycle through all visible mobs so you might need to " ..
                      "repeat this step several times to get the right one); and\n")
            ib:AddMsg("\n~(3)~ stand next to the mob and you will automatically attack him.\n")
            ib:AddMsg("\nDon't forget, most mobs fight back!")
            ib:SetDesc("Return to Fanrir's larder and exterminate some of the mice down there for him.\n\n" ..
                       "Bring back two mouse tails to prove your valour.", 10, 0, 0, 0)
            qb:RegisterQuest(3, ib)
-- ...
local function topic_questComplete()
    ---------
    -- Quest really is complete.
    ---------
    else
        ---------
        -- "Mouse Hunt"
        ---------
        elseif questnr == 3 then
            ib:SetMsg("Many thanks! That should slow them down a bit.\n")
            ib:AddMsg("\nWell, that deserves a reward. Here you go.")
            ib:SetDesc("", 10, 0, 0, 0)
            qb:Finish(3, "10 copper coins")
The drawbacks are that (a) questnr needs to be declared before it is used in the goal/reward functions but is assigned by qb:Build() which must be called after all the qb:AddQuest() calls which reference the goal/reward functions which must be already defined... and (b) all the nil arguments to qb:AddQuest().

We're stuck with (a). It's easy to work around by delaring questnr before the function definitions, and just assigning it from qb:Build() (as above). Just a little messy-looking.

(b) is certainly fixable with a bit of parameter-juggling, though this is a fiddly and boring process for me to script so I haven't done it yet. Also, I'm not sure it is a worthwhile thing to have happen every runtime just for very slightly easier to write scripts.

Anyway, comments?
Logged

Torchwood
MapMaster
*
*
*


Karma: +35/-5
Posts: 968



View Profile
« Reply #48 on: April 25, 2008, 06:30:25 am »


I agree with the principle - in fact was going to suggest something similar ... i.e. get all the quest mechanics out of the IB stuff - so yes, agree.

I don't think the code looks too bad ... haven't got a problem with nil parameters ...
Logged

smacky
Administrator
*
*
*
*


Karma: +120/-101
Posts: 5381



View Profile
« Reply #49 on: April 25, 2008, 12:28:49 pm »

The drawbacks are that (a) questnr needs to be declared before it is used in the goal/reward functions but is assigned by qb:Build() which must be called after all the qb:AddQuest() calls which reference the goal/reward functions which must be already defined...

We're stuck with (a). It's easy to work around by delaring questnr before the function definitions, and just assigning it from qb:Build() (as above). Just a little messy-looking.
It just occurred to me that this can be worked around even now and there is also a tweak I can make to qb.lua.

The current workaround is to have each quest call a specific goal/reward function. So checking questnr is redundant. But I personally don't like loads of highly specialised functions and this woulcn't fit with the conventions used throughout the script (ie, other functions do query questnr to find out the current quest).

The tweak is to change the lines which call the functions from, eg, 'self[nr].goal()' to, eg, 'self[nr].goal(nr)'. The talk script can then define 'local function questGoal(questnr)', meaning that when the function refers to questnr it is talking about the parameter, not the main chunk variable (and as questnr should never be written to, except for the initial assignment by qb:Build() there shouldn't be any possibility of confusion (the paranoid can always use a different parameter name),
Logged

Pages: 1 2 3 [4] Go Up Print 
Daimonin Forum  |  Development  |  Scripts  |  Topic: quest_builder.lua « previous next »
Jump to:  

Page created in 0.114 seconds with 17 queries.
Powered by SMF 1.1.4 | SMF © 2006-2007, Simple Machines LLC
Seo4Smf v0.2 © Webmaster's Talks
Copyright 2008 Daimonin MMORPG  •  Terms of Service  •  XHTML  •  Daimonin sourceforge open source project