Topic readme.md

Readme, explanation & example

Introduction

This page/document should hopefully help explain how the host handles various bits and pieces relevant to quests. It includes explanations and a fully working Gerenium Quest example which will be live (or already is) on the test server and subsequently main server. It will be updated as the live script is updated to give an idea of how to make a quest.

NOTE: In the code blocks containing definitions, x4 spaces represent a tab. This is an issue with LDoc replacing tab characters with a fixed number of spaces. It is stressed that for any definitions, tabs rather than spaces are used.

Tools

Lua Documentation
Item Generator

Files

A quest comprises of two files.

  • A zone/map file
  • A lua script

Zone/Map File explanation

A zone/map file (they're the same thing, the terms are interchangable) defines a map on the server, it represents one quadrant on the map either in space or the underspace. Cythris, TYV, Starbase etc are each defined in separate zone files. In a zone file, the majority of content for a zone is defined - items, mobs, tiles, fields.

Valid definitions

Zone files can have a number of definitions for different objects ingame. Allowed definitions include:

  • #DEF_ITEM
  • #DEF_QUEST
  • #DEF_COMBINE
  • #DEF_MOBILE

The format for these is as followed with x4 spaces replaced with \t (tab). The initial field is case-insensitive.

 #DEF_COMBINE    FINAL_ITEM_ID    SKILL_REQUIRED    LEVEL    ITEM_REQUIRED_ID    ITEM_REQUIRED_ID    ITEM_REQUIRED_ID    ITEM_REQUIRED_ID    ITEM_REQUIRED_ID    ITEM_REQUIRED_ID    ITEM_REQUIRED_ID    ITEM_REQUIRED_ID    ITEM_REQUIRED_ID

 #DEF_QUEST    STARTMOB    FILENAME    LEVEL

Both #DEF_ITEM, #DEF_COMBINE, please use the web tools provided to generate definitions for these.

IDs

The host uses IDs to identify everything however there are a few "special" ranges. Any ID below 10000 is absolute - it will not be changed, it will stick with what it's been given. These are reserved for very common or global items such as ores - Silver, Gold etc. Any ID above 10000 inside a zone file will be modified to a calculated offset for that zone. This means that it is possible to have relative IDs in zonefiles eliminating the need to have to keep track of what item numbers do what. For example, we may have a zonefile Cythris.txt:

 #DEF_ITEM    10001    WEAP    TestWeapon    5    7    0    2    1    0    20    0    2    4    0    30    5000

It is then possible in the Lua file to find TestWeapon by using the item(id) function which handles fixing up offsets for you, e.g:

 local testweaponid = item(1)

For all quests it is necessary to use IDs beginning from 10000.

Lua file

The lua file is the quest script and has to implement at a minimum, 3 functions.

Each quest script must implement the following functions.

 function init()

 end

 function update()

 end

Without these, the script will fail to load. In addition to these, a quest MUST call

 set_start()

and

 set_finish() 

at some point. Whether based on something in the update() function or it calls it in a function of the callback it doesn't matter.

 add_talk_to_mob_callback(startmob,"start","Thankyou %P for starting the quest.",0,"start")

 function start()
     set_start()
 end

The server will run the init function once when the script is definition is read at startup. It can be used for things such as adding chat to mob and creating the start callback as seen in the Gerenium example further down.

Limitations/Workflow

Currently quests are player oriented although global and group accomodations are planned for quests such as planet mining or Defense Nexus.
The general workflow is

  • Player talks to mob
  • Player activates quest
  • Player does some action or collection of actions
  • Player returns to mob
  • Player finishes quest, gets experience, money or items
    OR
  • Player aborts the quest, gets nothing

Gerenium Quest Example

StarbaseL1.txt

 #DEF_ZONETITLE    Starbase Level 1

 #DEF_ITEM    10001    QUEST    Gerenium Ore    26    24    1    0    0    0    0    0    0    0    0    0    1
 #DEF_ITEM    10002    QUEST    Gerenium Container    1    26    1    0    0    0    0    0    0    0    0    0    1
 #DEF_ITEM    10003    QUEST    Contained Gerenium    1    10    1    0    0    0    0    0    0    0    0    0    1

 #Def_Item    10004    SYSTEM    Gerenium Plate    33    26    0    3    4    10    3    0    0    0    0    1    250
 #Def_Item    10005    SYSTEM    Gerenium Plate    34    26    0    3    4    10    3    0    0    0    0    2    250
 #Def_Item    10006    SYSTEM    Gerenium Plate    35    26    0    3    3    10    3    0    0    0    0    3    250
 #Def_Item    10007    SYSTEM    Gerenium Plate    36    26    0    3    3    10    3    0    0    0    0    4    250

 #DEF_COMBINE    10003    0    0    10001    10001    10001    10001    10001    10001    10002    0    0    0

 #Def_Quest    gerenium.lua    10002    Gerenium Quest

Gerenium.lua

 local fes_rebels = 0

 function init(startmob)

     -- Set up all the chat messages for Fes Rebels
     add_talk_to_mob(startmob,"[CLICK]","Hello there, %P, I am the famous and immobile %N. Do you need a [job]?")

     add_talk_to_mob(startmob,"job","Great, I think I'm going to be able to help you. A slight distance away in the west lay the Scythe fleet.")
     add_talk_to_mob(startmob,"job","They hold a rare ore called [gerenium]")

     add_talk_to_mob(startmob,"gerenium","Yes, by combining SIX (6) gerenium in a container, it will produce a strong compound used for armor.")
     add_talk_to_mob(startmob,"gerenium","Would you like to [start] this quest?")

     add_talk_to_mob_callback(startmob,"start","Good. I can provide you with a [container] if needs be. I look forward to seeing you later.", 0, "start")

     add_talk_to_mob_callback(startmob,"container","Here is one container. Fabricate it (/fabricate) it with 6 Gerenium Ore to create Contained Gerenium.",1 , "giveContainer")
     add_talk_to_mob(startmob,"container","Once you have Contained Gerenium, come back and ask me for a [Fore],[Aft],[Port] or [sb] plate.",1)

     --allow the player to manually try to finish
     add_talk_to_mob_callback(startmob,"finish","I hope we meet again.",1,"finish")

     add_talk_to_mob_callback(startmob,"fore","Let me check if you have the ore.",1,"handleFore")
     add_talk_to_mob_callback(startmob,"port","Let me check if you have the ore.",1,"handlePort")
     add_talk_to_mob_callback(startmob,"aft","Let me check if you have the ore.",1,"handleAft")
     add_talk_to_mob_callback(startmob,"sb","Let me check if you have the ore.",1,"handleSb")

     -- Save his ID to a global variable so we don't have to run a search for him again
     fes_rebels = startmob
 end

 function start()
     --This activates the quest on the player
     set_start()
 end

 function handleFore()
     --Call handleplate with ID of a Fore gerenium plate and the prefix
     handlePlate(item(4), "fore")
 end

 function handleAft()
     --Call handleplate with ID of an Aft gerenium plate and the prefix
     handlePlate(item(5), "aft")
 end

 function handlePort()
     --Call handleplate with ID of a Port gerenium plate and the prefix
     handlePlate(item(6), "port")
 end

 function handleSb()
     --Call handleplate with ID of a Starboard gerenium plate and the prefix
     handlePlate(item(7), "sb")
 end

 --Handle plate function, will check for an ID and give an item if the player has contained gerenium
 function handlePlate(id, side)
     --check if they've got a contained gerenium
     if(check_item(item(3)) == 1) then
         create_chat_from_mob(fes_rebels, "Here you go sir.")
         --remove a contained gerenium
         remove_item(item(3))
         --give the item an id
         give_item(id)
         if(load_param("geren_"..side) ~= "y") then
             save_param("geren_"..side, "y")
             give_xp()
         end
     else
         --tell the user the problem
         create_chat_from_mob(fes_rebels, "Unfortunately I cannot supply a ".. side .. " plate without a Contained Gerenium.")
     end
 end


 function giveContainer()
     --Give the item a container
     give_item(item(2))
 end


 function update()
     --Get the id of the mob the player killed last
     local last_killed_id = get_player_last_killed()
     --stop it executing here to prevent unnecessary checks
     if(last_killed_id == 0) then
         return
     end
     --Get the name of the mob
     local last_killed_name = find_mob_name_by_id(last_killed_id)
     --Make sure the mob exists
     if(string.len(last_killed_name) > 0) then
         if(string.match(last_killed_name,"Scythe") ~= nil) then
             --50% chance to give the player a gerenium ore
             if(math.random(0,99) < 50) then
                 give_item(item(1))
                 write_text_to_screen("You found a Gerenium Ore!",29)
             end
         end
     end
     --automatically check if the player has finished
     checkIfFinished()
 end

 --Unset the parameters for each plate from the player.
 --This allows the quest to be done more than once, but experience
 --to only be given for one cycle
 local function unsetPlateParameters()
     unset_param("geren_fore")
     unset_param("geren_aft")
     unset_param("geren_port")
     unset_param("geren_sb")
 end

 --function to check if the player has satisfied all of the requirements
 local function checkIfFinished()
     local fore = false
     local aft = false
     local port = false
     local sb = false

     --Check which of the plates the player has created
     if(load_param("geren_fore") == "y") then
         fore = true
     end
     if(load_param("geren_aft") == "y") then
         aft = true
     end
     if(load_param("geren_port") == "y") then
         port = true
     end
     if(load_param("geren_sb") == "y") then
         sb = true
     end

     --if they have made a complete set
     if(fore == true and aft == true and port == true and sb == true) then
         --check if the player has already finished the quest before
         local alreadyFinished = load_param("geren_finish")
         --if not, give them some experience and set that they have as a parameter
         if(alreadyFinished ~= "y") then
             give_xp()
             save_param("geren_finish","y")
         end
         --create a message from Fes
         create_chat_from_mob(fes_rebels, "Well done for completing the quest. Good luck in your future endeavors.")
         --reset the status of the plates so the quest can be done again
         unsetAllPlateParameters()
         --deactivate the quest from the player
         set_finish()
     end
 end

 function finish()
     --set the quest finished on the player, this means update() no longer runs for this player
     checkIfFinished()
 end
generated by LDoc 1.2