• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!
  • 2026 staff recruitment is open! Check it out and consider applying!

Lua Quest Log with multiple storages [## out of ## found]

Extrodus

|| Blazera.net ||
Joined
Dec 22, 2008
Messages
2,691
Solutions
7
Reaction score
549
Location
Canada
So I'm messing around with this Fast Travel System to make an RPG and I was wondering if any of you may be able to lend a hand with something.

I want to start a quest log system for the player to keep track of how many shrines are left to unlock in each area and since I'm not the greatest with this stuff I was wondering how we might do something like that.

I have already started by modifying quests.xml,

Code:
<quests>
   <quest name="The Path of Aragon" startstorageid="1001" startstoragevalue="1">
     <mission name="[Act I]" storageid="1001" startvalue="1" endvalue="3">
       <missionstate id="1" description="You have arrived on Gryngor, find and activate the Trolls Teleport Shrine."/>
       <missionstate id="2" description="Find and activate the Amazons Teleport Shrine."/>
       <missionstate id="3" description="Find and activate the Cyclops Teleport Shrine."/>
     </mission>
     <mission name="[Act II]" storageid="1001" startvalue="4" endvalue="5">
       <missionstate id="4" description="You have arrived at the Lost Plains Temporal Shrine, find and active the Guardians Watch Shrine."/>
       <missionstate id="5" description="Find and activate the Giant Spiders Shrine."/>
     </mission>
   </quest>
</quests>

But it seems like this will be a very inefficient way to do it and would force the player to go in a specific order for the quest log to work. So I was thinking something like this might be better.

Code:
<quests>
   <quest name="The Path of Aragon" startstorageid="1001" startstoragevalue="1">
     <mission name="[Act I]" storageid="1001" startvalue="1" endvalue="2">
       <missionstate id="1" description="You have arrived on Gryngor, find and activate the Teleport Shrines to continue. You have found ## out of ## shrines."/>
       <missionstate id="2" description="You have found all the shrines, report back to Aragon Temple and proceed to Act II."/>
     </mission>
     <mission name="[Act II]" storageid="1001" startvalue="3" endvalue="4">
       <missionstate id="3" description="You have arrived at the Lost Plains Temporal Shrine, find and active the Teleport Shrines to continue. You have found ## out of ## shrines."/>
       <missionstate id="4" description="You have found all the shrines, report back to Aragon Temple and proceed to Act III."/>
     </mission>
   </quest>
</quests>

Currently Act I's storages are 37112-37118 and Act II's storages are 37121-37128; so I'm really confused how I would go about doing this and getting that configuration to show.

If any of you know how to do this type of thing, I am open to learn!
 
I';m not sure but i think you can't split missions with ID, each mission starts at id 1 or 0 even.

About storages, let's take your second quest as example:
<quest name="The Path of Aragon" startstorageid="1001" startstoragevalue="1">
Right now you have to have storage id 1001 value set as 1 to show the quest in quest log.

<mission name="[Act I]" storageid="1001" startvalue="1" endvalue="2">
For first mission to appear, you have to have storage id 1001 value set as 1, and storage id 2 to have mission completed.

I think you should figure it out - the rest.
 
Well, the quest log will only show the description given for that exact missionstate (value of player's storage key).
Since you're not able to pass any values from the lua system to the XML (at least that I know of), you can't send an dynamic number to the quest log.
If there is a way to do that, I'd like to learn it as well, so if anyone knows - please do share that info :O

You could perhaps rewrite the quest log itself (if you are using OTC) to a lua-based one that would be able to accept and display such variables, or if using the regular tibia client, rewrite it in form of a modal window based panel of selections (which would be quests), where each selection opens up a text dialogue (similar to when you open a book ingame) that shows the quest's description.

The only other way you can do it is to have a single storage value for every possible combination and write that down into missionstates then set them to player accordingly as he progresses. This is way too tedious of a task if you're working with any more than 3-4 combinations, so I personally avoid writing such details in the quest log.

There is also an alternative where you make a talkaction like (e.g.) !checkquest, and this one gives all these details to the player, since it will be much easier to code that in lua - and have the quest log tell the player to type that command if he wants to check all shrines he's unlocked so far.
 
@Shadowsong
You do have a point with the talk action idea, that would be much easier! I suppose if I did want to use quest logs I would have to spread it out like this,

Code:
<quests>
   <quest name="The Path of Aragon" startstorageid="1001" startstoragevalue="1">
     <mission name="[Act I]" storageid="1001" startvalue="1" endvalue="4">
       <missionstate id="1" description="You have arrived on Gryngor, find and activate the Teleport Shrines to continue. You have found 1 out of 3 shrines."/>
       <missionstate id="2" description="You have arrived on Gryngor, find and activate the Teleport Shrines to continue. You have found 2 out of 3 shrines."/>
       <missionstate id="3" description="You have arrived on Gryngor, find and activate the Teleport Shrines to continue. You have found 3 out of 3 shrines."/>
       <missionstate id="4" description="You have found all the shrines, report back to Aragon Temple and proceed to Act II."/>
     </mission>
   </quest>
</quests>

But even then, with the storage values all being different numbers; I dont think it would be possible.. So, yeah; a talk action may have to be used for this one.
 
Since you're not able to pass any values from the lua system to the XML (at least that I know of), you can't send an dynamic number to the quest log.
If there is a way to do that, I'd like to learn it as well, so if anyone knows - please do share that info :O
There is a way for that. Just lookup how Killing in the name of (tasks by grizzly adams) is done :)
 
@Shadowsong
You do have a point with the talk action idea, that would be much easier! I suppose if I did want to use quest logs I would have to spread it out like this,

Code:
<quests>
   <quest name="The Path of Aragon" startstorageid="1001" startstoragevalue="1">
     <mission name="[Act I]" storageid="1001" startvalue="1" endvalue="4">
       <missionstate id="1" description="You have arrived on Gryngor, find and activate the Teleport Shrines to continue. You have found 1 out of 3 shrines."/>
       <missionstate id="2" description="You have arrived on Gryngor, find and activate the Teleport Shrines to continue. You have found 2 out of 3 shrines."/>
       <missionstate id="3" description="You have arrived on Gryngor, find and activate the Teleport Shrines to continue. You have found 3 out of 3 shrines."/>
       <missionstate id="4" description="You have found all the shrines, report back to Aragon Temple and proceed to Act II."/>
     </mission>
   </quest>
</quests>

But even then, with the storage values all being different numbers; I dont think it would be possible.. So, yeah; a talk action may have to be used for this one.

I faced the same problem when I made a mission where you have to kill several kinds of monsters, but wanted it all to be displayed in a single quest description, like:
"You killed 3 out of 10 Amazons, 4 out of 15 Valkyries"

Then I realized it would be impossible without having at least 150 different states, so I dropped that idea and made it happen in an onKill script that simply sends you a notification every time you kill one of those, telling you how many are left for each monster. Works much easier, saves a lot more time. I'd go with the talkaction idea as well if I were you.
 
I'm not sure tho if it's just in Lua - i guess not. But it's working as you probably know :). I just wish Mark could move some more stuff from C# to LUA :s

I suppose it had to have some connection with LUA. Maybe there's a way to connect LUA to XML that I don't know of (not too eager to go exploring the internet right now, got too much stuff on my plate).
I can imagine the strings for descriptions being generated via a lua script then passed to XML via some parser.

I remember that, when I worked on my other project with Dante, we had the same problem with spellbook and we had a dilemma of making a spellbook load description values from the XML itself, or making a spellbook entirely in LUA, and we chose the latter which has proven to be a good choice because it allowed us to dynamically display the amount of damage a spell will do, its exact costs, etc.

At the end of the day, whatever you can do in LUA instead of XML, do it, because it just opens up many more possibilities.
 
@Shadowsong
PHP:
    <quest name="Killing in the Name of..." startstorageid="100157" startstoragevalue="1">
        <mission name="Paw and Fur - Hunting Elite" storageid="2500" startvalue="0" endvalue="999" description="You joined the 'Paw and Fur - Hunting Elite'. Ask Grizzly Adams for some hunting tasks. You already gained |STATE| points." />
    
    <!--s for level 6 to 49 -->
        <mission name="Edron City: Trolls" storageid="1501" startvalue="0" endvalue="100" description="You already hunted |STATE|/100 trolls." />
        <mission name="Edron City: Goblins" storageid="1502" startvalue="0" endvalue="150" description="You already hunted |STATE|/150 goblins." />
        <mission name="Paw and Fur: Trolls" storageid="65001" startvalue="0" endvalue="100" description="You already hunted |STATE|/100 trolls." />
        <mission name="Paw and Fur: Globins" storageid="65002" startvalue="0" endvalue="150" description="You already hunted |STATE|/150 globins." />
        <mission name="Paw and Fur: Crocodiles" storageid="65003" startvalue="0" endvalue="300" description="You already hunted |STATE|/300 crocodiles." />
        <mission name="Paw and Fur: Badgers" storageid="65004" startvalue="0" endvalue="3" description="You already hunted |STATE|/3 badgers." />
        <mission name="Paw and Fur: Tarantulas" storageid="65005" startvalue="0" endvalue="300" description="You already hunted |STATE|/300 tarantulas." />
        <mission name="Paw and Fur: Carniphilas" storageid="65006" startvalue="0" endvalue="150" description="You already hunted |STATE|/150 carniphilas." />
        <mission name="Paw and Fur: Stone Golems" storageid="65007" startvalue="0" endvalue="200" description="You already hunted |STATE|/200 stone golems." />
        <mission name="Paw and Fur: Mammoths" storageid="65008" startvalue="0" endvalue="300" description="You already hunted |STATE|/300 mammoths." />
        <mission name="Paw and Fur: Gnarlhounds" storageid="65009" startvalue="0" endvalue="300" description="You already hunted |STATE|/300 gnarlhounds." />
        <mission name="Paw and Fur: Terramites" storageid="65010" startvalue="0" endvalue="300" description="You already hunted |STATE|/300 terramites." />
        <mission name="Paw and Fur: Apes" storageid="65011" startvalue="0" endvalue="300" description="You already hunted |STATE|/300 apes." />
        <mission name="Paw and Fur: Thornback Tortoises" storageid="65012" startvalue="0" endvalue="300" description="You already hunted |STATE|/300 thornback tortoises." />
        <mission name="Paw and Fur: Gargoyles" storageid="65013" startvalue="0" endvalue="300" description="You already hunted |STATE|/300 gargoyles." />
    
        <!--Tasks for level 50 to 79 -->
        <mission name="Paw and Fur: Ice Golems" storageid="65014" startvalue="0" endvalue="300" description="You already hunted |STATE|/300 ice golems." />
        <mission name="Paw and Fur: Quara Scouts" storageid="65015" startvalue="0" endvalue="400" description="You already hunted |STATE|/400 quara scouts." />
        <mission name="Paw and Fur: Mutated Rats" storageid="65016" startvalue="0" endvalue="400" description="You already hunted |STATE|/400 mutated rats." />
        <mission name="Paw and Fur: Ancient Scarabs" storageid="65017" startvalue="0" endvalue="250" description="You already hunted |STATE|/250 ancient scarabs." />
        <mission name="Paw and Fur: Wyverns" storageid="65018" startvalue="0" endvalue="300" description="You already hunted |STATE|/300 wyverns." />
        <mission name="Paw and Fur: Lancer Beetles" storageid="65019" startvalue="0" endvalue="300" description="You already hunted |STATE|/300 lancer beetles." />
        <mission name="Paw and Fur: Wailing Widows" storageid="65020" startvalue="0" endvalue="400" description="You already hunted |STATE|/300 wailing widows." />
        <mission name="Paw and Fur: Killer Caimans" storageid="65021" startvalue="0" endvalue="250" description="You already hunted |STATE|/300 killer caimans." />
        <mission name="Paw and Fur: Bonebeasts" storageid="65022" startvalue="0" endvalue="300" description="You already hunted |STATE|/300 bonebeasts." />
        <mission name="Paw and Fur: Crystal Spiders" storageid="65023" startvalue="0" endvalue="300" description="You already hunted |STATE|/300 crystal spiders." />
        <mission name="Paw and Fur: Mutated Tigers" storageid="65024" startvalue="0" endvalue="300" description="You already hunted |STATE|/300 mutated tigers." />
    
        <!--s for level 80 to 129 -->
        <mission name="Paw and Fur: Underwater Quara" storageid="65025" startvalue="0" endvalue="600" description="You already hunted |STATE|/600 underwater quara." />
        <mission name="Paw and Fur: Giant Spiders" storageid="65026" startvalue="0" endvalue="500" description="You already hunted |STATE|/500 giant spiders." />
        <mission name="Paw and Fur: Werewolves" storageid="65027" startvalue="0" endvalue="300" description="You already hunted |STATE|/300 werewolves." />
        <mission name="Paw and Fur: Nightmares" storageid="65028" startvalue="0" endvalue="400" description="You already hunted |STATE|/400 nightmares." />
        <mission name="Paw and Fur: Hellspawns" storageid="65029" startvalue="0" endvalue="600" description="You already hunted |STATE|/600 hellspawns." />
        <mission name="Paw and Fur: High Class Lizards" storageid="65030" startvalue="0" endvalue="800" description="You already hunted |STATE|/800 high class lizards." />
        <mission name="Paw and Fur: Stampors" storageid="65031" startvalue="0" endvalue="600" description="You already hunted |STATE|/600 stampors." />
        <mission name="Paw and Fur: Brimstone Bugs" storageid="65032" startvalue="0" endvalue="500" description="You already hunted |STATE|/500 brimstone bugs." />
        <mission name="Paw and Fur: Mutated Bats" storageid="65033" startvalue="0" endvalue="400" description="You already hunted |STATE|/400 mutated bats." />
    
        <!--s for level 130+ -->   
        <mission name="Paw and Fur: Hydras" storageid="65034" startvalue="0" endvalue="650" description="You already hunted |STATE|/650 hydras." />
        <mission name="Paw and Fur: Serpent Spawns" storageid="65035" startvalue="0" endvalue="800" description="You already hunted |STATE|/800 serpent spawns." />
        <mission name="Paw and Fur: Medusas" storageid="65036" startvalue="0" endvalue="500" description="You already hunted |STATE|/500 medusas." />   
        <mission name="Paw and Fur: Behemoths" storageid="65037" startvalue="0" endvalue="700" description="You already hunted |STATE|/700 behemoths." />
        <mission name="Paw and Fur: Sea Serpents and Young Sea Serpents" storageid="65038" startvalue="0" endvalue="900" description="You already hunted |STATE|/900 sea serpents and young sea serpents." />   
        <mission name="Paw and Fur: Hellhounds" storageid="65039" startvalue="0" endvalue="250" description="You already hunted |STATE|/250 hellhounds." />
        <mission name="Paw and Fur: Ghastly Dragons" storageid="65040" startvalue="0" endvalue="500" description="You already hunted |STATE|/500 ghastly dragons." />
        <mission name="Paw and Fur: Drakens" storageid="65041" startvalue="0" endvalue="900" description="You already hunted |STATE|/900 drakens." />
        <mission name="Paw and Fur: Destroyers" storageid="65042" startvalue="0" endvalue="650" description="You already hunted |STATE|/650 destroyers." />
        <mission name="Paw and Fur: Undead Dragons" storageid="65043" startvalue="0" endvalue="400" description="You already hunted |STATE|/400 undead dragons." />
    
        <!-- Specials -->
        <mission name="Paw and Fur: Demons" storageid="65044" startvalue="0" endvalue="6666" description="You already hunted |STATE|/6666 demons." />
    <mission name="Paw and Fur: Dragon Lords" storageid="65045" startvalue="0" endvalue="100" description="You already hunted |STATE|/100 dragon lords. When you finish killing all the dragon lords reporting to Grizzly Adams and get access to kill the boss Demodras." />

    <!-- Task Custom -->
        <mission name="Paw and Fur: Minotaurs" storageid="14004" startvalue="0" endvalue="5000" description="You already hunted |STATE|/5000 minotaurs." />
    <mission name="Paw and Fur: Necromancers and Priestesses" storageid="14003" startvalue="0" endvalue="4000" description="You already hunted |STATE|/4000 necromancers and priestesses." />

    </quest>

That's how it's in quests.xml in TFS 1.0

And below what i've found in quests.cpp

PHP:
std::string Mission::getDescription(Player* player) const
{
    int32_t value;
    player->getStorageValue(storageID, value);

    if (mainState) {
        std::string desc = mainState->getMissionDescription();
        replaceString(desc, "|STATE|", std::to_string(value));
        replaceString(desc, "\\n", "\n");
        return desc;
    }

    int32_t current = endValue;

    if (ignoreEndValue) {
        while (current >= startValue) {
            if (value >= current) {
                auto sit = state.find(current);
                if (sit != state.end()) {
                    return sit->second.getMissionDescription();
                }
            }

            current--;
        }
    } else {
        while (current >= startValue) {
            if (value == current) {
                auto sit = state.find(current);
                if (sit != state.end()) {
                    return sit->second.getMissionDescription();
                }
            }

            current--;
        }
    }

    return "An error has occurred, please contact a gamemaster.";
}
 
@Shadowsong - Agreed, I am going in both routes. The talk action will have more detail while the quest log will just be for basic details.

Code:
<quests>
    <quest name="[Gryngor - Act I]" startstorageid="37111" startstoragevalue="1">
        <mission name="[Trolls]" storageid="37112" startvalue="1" endvalue="1">
            <missionstate id="1" description="You have found the Trolls Teleport Shrine, say !shrines for more information."/>
        </mission>
        <mission name="[Amazons]" storageid="37113" startvalue="1" endvalue="1">
            <missionstate id="1" description="You have found the Amazons Teleport Shrine, say !shrines for more information."/>
        </mission>
    </quest>
</quests>

Just messing around with it and this is working so far to atleast give the player a basic quest log, so hizzah to that lol!

@olszak94 - Ah, probably uses a creaturescript for onKill to update the storage. Works because it would be updating its storage number for each monster. All my shrines are different storages so I guess I'm pooped on this one.
 
@olszak94
I see, yeah. Seems like there's a string parser from the engine to the XML that contains the numeric value that we want to display. Unfortunately, I can't code for shit in c++ so making custom stuff for this is out of question for me right now. :(
But good to know! I'm sure somebody else will find this information useful as well.
 
@olszak94
I see, yeah. Seems like there's a string parser from the engine to the XML that contains the numeric value that we want to display. Unfortunately, I can't code for shit in c++ so making custom stuff for this is out of question for me right now. :(
But good to know! I'm sure somebody else will find this information useful as well.
Are you using TFS or modified engine / your own ? This function is by default in TFS 1.0 +
 
Are you using TFS or modified engine / your own ? This function is by default in TFS 1.0 +
A modified version of TFS issued a few years ago (0.3.6), but even if it is there, it doesn't help the case where different storage values are used for a same quest. However, it will be useful in cases of making a quest similar to Grizzly Addams.
(Notice how that quest always has you kill exactly 1 type of monster per mission, so that this system can be used. If you chose to apply those to my amazon+valkyrie concept, it would be a bit inconvenient.)
 
A modified version of TFS issued a few years ago (0.3.6), but even if it is there, it doesn't help the case where different storage values are used for a same quest. However, it will be useful in cases of making a quest similar to Grizzly Addams.
(Notice how that quest always has you kill exactly 1 type of monster per mission, so that this system can be used. If you chose to apply those to my amazon+valkyrie concept, it would be a bit inconvenient.)
You would have to check few first lines of quests.cpp file to check it if exists in there. And also for you task for amazon+valkyrie you could just use onKill function and check if someone has started quest/task, then just add those 2 monsters to onKill and set 1 storage id for them. I would eventually find a way to make it work as RL tibia (with few monsters in desc. but no time for now to do that :P )
 
You would have to check few first lines of quests.cpp file to check it if exists in there. And also for you task for amazon+valkyrie you could just use onKill function and check if someone has started quest/task, then just add those 2 monsters to onKill and set 1 storage id for them. I would eventually find a way to make it work as RL tibia (with few monsters in desc. but no time for now to do that :p )

You're right. But like you said, no time for that. It's easier just to make a notification in an onKill script, and the players seem to like it as well so I won't go inventing warm water (for now :D).
 

Similar threads

Back
Top