• 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!

[TUTORIAL] Rescue the Princess Quest v2.0

Zyntax

*WannaBe Scripter*
Joined
Jan 27, 2010
Messages
533
Reaction score
40
Location
Lua & XML Section
Hey guys!

It's time to introduce the "Rescue the Princess Quest" to you.

Updates:
v2.0
Code:
Moved the whole tutorial to TFS0.3.5(CD) 
Tested everything, 100% working!
New screenshots added

1) Location
2) Scripts you need (Startup)
2.1) The Princess
2.2) The King Herby NPC
2.3) Summon the Princess Script
2.4) Hidden paths and traps
3) Optional ideas
4) Credits


1) Let's get started! Location

First off all, I'm going to show you where the whole scenario
will take place:

pic5rf.jpg


The first room (upper left side) is the starting room.
The second room (bottom right side) is the ending room.
The path leading from left to right is the secret path, which
will open if you summon the princess after accepting the quest
from the King.

2) Scripts you need (Startup)

First off all you may need the mapArea Iterator (credits to Colandus)
Insert this script into your global.lua / functions.lua

mapArea Iterator
Lua:
-- Area iterator by Colandus @ OTFans.net
function mapArea(fromPos, toPos)
    local x, y, z = fromPos.x, fromPos.y-1, fromPos.z
    return function()
        if (y < toPos.y) then
            y = y+1
        elseif (x <= toPos.x) then
            y = fromPos.y
            x = x+1
        else
            x = fromPos.x
            y = fromPos.y
            z = z+1
        end
        if (x <= toPos.x and y <= toPos.y or z < toPos.z) then
            return x, y, z
        end
    end
end

This script will allow us to use the "mapArea" function which I built into
the KingNPC to check if the princess was actually rescued or not!

2.1) The Princess

I scripted the princess like a monster (monster.xml)
The reason therefor:
If you summon and convince the princess (like a player summon)
then no other player could attack her / neither you.
If you have a No-PvP server then she wouldn't get hit, except for other monsters
if they switch or have some AreaOfEffect spells.

put that script into your %data/monster folder
and name it princess.xml

Lua:
<?xml version="1.0" encoding="UTF-8"?>
<monster name="princess" nameDescription="the princess" race="blood" experience="0" speed="200" manacost="0">
  <health now="100" max="100"/>
  <look type="138" head="0" body="0" legs="80" feet="0" corpse="6081"/>
  <targetchange interval="1000" chance="0"/>
  <strategy attack="10" defense="0"/>
  <flags>
    <flag summonable="0"/>
    <flag attackable="1"/>
    <flag hostile="1"/>
    <flag illusionable="0"/>
    <flag convinceable="0"/>
    <flag pushable="0"/>
    <flag canpushitems="1"/>
    <flag canpushcreatures="1"/>
    <flag targetdistance="0"/>
    <flag staticattack="0"/>
    <flag runonhealth="0"/>
  </flags>
  <attacks>
  </attacks>
  <defenses armor="11" defense="11"/>
  <elements>
	<element physicalPercent="-8"/>
	<element deathPercent="-7"/>
  </elements>
  <immunities>
    <immunity lifedrain="0"/>
    <immunity paralyze="0"/>
    <immunity outfit="0"/>
    <immunity drunk="0"/>
    <immunity invisible="1"/>
  </immunities>
  <voices interval="5000" chance="50">
    <voice sentence="Please save my life!"/>
    <voice sentence="Bring me back to my King!"/>
    <voice sentence="Don't let me die!"/>
    <voice sentence="I'm the Princess! Get on your knees!"/>
  </voices>
  <loot>
  </loot>
<script>
<event name="Princess"/> 
</script>
</monster>

Maybe you noticed the <event name="Princess"/> line, here's the explanation:
If the princess dies then the player should be informed about that.
Therefor the next step is to add a script to notify the player.

Add this line into your %data/creaturescripts.xml

Lua:
<event type="death" name="Princess" event="script" value="princess.lua"/>

Next step is to add the script into your %data/creaturescripts/scripts folder
and name it princess.lua

Lua:
function onDeath(cid, corpse, Killer)
		doCreatureSay(cid, 'You let me die!\n Screw you!', 19)
end

Well, I guess that doesn't need an explanation :thumbup:
(If the sentence "Srew you!" violates any rules on the server
edit it!)

OK, we're done with the princess, let's move to the King Herby NPC.

2.2) The King Herby NPC

It's the starting point in the quest where you talk to him:

npca.jpg


Ofcourse, you can rewrite all the talking lines like you want!

And now the scripts, add this script to your %data/npc folder
and name it King Herby.xml

Lua:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="King Herby" script="daughter.lua" walkinterval="2000" floorchange="0">
	<health now="100" max="100"/>
	<look type="132" head="20" body="39" legs="45" feet="7" addons="0"/>
	<parameters>
	 <parameter key="message_greet" value="Help me |PLAYERNAME|! My little Princess was captured by a magician and sealed in a statue!"/>
	</parameters>
</npc>

Ofcourse, you can rename the script as you wish but remember to
use the same name in the next step:

Add this script into your %data/npc/scripts folder
and name it daughter.lua
(or use the same name as in the King Herby.xml line above!)

Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
local talkState = {}

function onCreatureAppear(cid)			npcHandler:onCreatureAppear(cid)			end
function onCreatureDisappear(cid)		npcHandler:onCreatureDisappear(cid)			end
function onCreatureSay(cid, type, msg)		npcHandler:onCreatureSay(cid, type, msg)		end
function onThink()				npcHandler:onThink()					end

function creatureSayCallback(cid, type, msg)
    if (not npcHandler:isFocused(cid)) then
        return false
    end

	local talkUser = NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT and 0 or cid
	daughter = false
	
	if msgcontains(msg, 'quest') and (getPlayerStorageValue(cid, 20020) == - 1) then
		selfSay('Are you really strong enough to help me?', cid)
		talkState[talkUser] = 1
		
	elseif msgcontains(msg, 'quest') and (getPlayerStorageValue(cid, 20022) == 1) then
		selfSay('Praise you mighty warrior, my daughter is safe!', cid)
		
	elseif (msgcontains(msg, 'yes') and talkState[talkUser] == 1) and (getPlayerStorageValue(cid, 20020 == -1)) then	
		setPlayerStorageValue(cid, 20020, 1)
		selfSay('Mighty warrior, your mission is to rescue my daughter!', cid)
			
	elseif msgcontains(msg, 'quest') and (getPlayerStorageValue(cid, 20020) == 1) then
		selfSay('Did you find her?', cid)
		
	elseif msgcontains(msg, 'yes') and (getPlayerStorageValue(cid, 20021) == 1) and (getPlayerStorageValue(cid, 20022) ~= 1) then
		local fromPos = {x=546, y=529, z=7, stackpos=255}
		local toPos = {x=551, y=532, z=7, stackpos=255}
			for x, y, z in mapArea(fromPos, toPos, 255) do
			local creature = getThingfromPos({x = x, y = y, z = z, stackpos = 255})
				if isMonster(creature.uid) == TRUE and getCreatureName(creature.uid) == 'princess' then
					doRemoveCreature(creature.uid)
					doSendMagicEffect({x = x, y = y, z = z}, CONST_ME_ENERGYAREA)
					selfSay('Thank you mighty warrior, you saved her! Take this as a reward!', cid)
					setPlayerStorageValue(cid, 20022, 1)
					doPlayerAddItem(cid, 5805, 1)	
				break
				end
			end
			
		
	
	else 
		selfSay('Please help me to save my daughter!', cid)
	end

    return true
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())

Confused by the script? I'll explain the important parts:

Every selfSay('...') line will be told by the NPC like i wrote at the beginning
of the King Herby section.
Edit them if you want him to say something else.

"mapArea" function:
Like i wrote in the beginning of the tutorial you have to add the Area Iterator
to your functions, because we will check the area around the NPC if the
princess was actually returned alive and safe!

Additionally, you have to edit the "local frompos ... " and "local topos ..." positions to your actuall map positions!

Near the end of the script it says: doPlayerAddItem(... ,1)
Please adjust this line to the reward you want to give the player!
(Just rewrite the ID of the item)

IMPORTANT:
Please make sure to use some storageValues for this quest!
If you already used mine (20020 - 20022) rewrite them also!

2.3) Summon the Princess Script

Ok, now we script the statue where the princess is sealed!

Add this line into your %data/actions/actions.xml

Lua:
<action uniqueid="4009" event="script" value="quests/daughtersummon.lua"/>

The uniqueid 4009 is the ID i gave my statue in my mapEditor!
Make sure to change it if you already used this ID anywhere!


Well, "daughtersummon" was the dumbest idea I had for the script so,
if you like to rename it then do that, but also remind the new name
in the next step:

Add this script into your %data/actions/quests
and name it daughtersummon.lua
(Or rename it like in the actions.xml above!)

Lua:
local wallpos = {x=529, y=521, z=7, stackpos=1}
local wallid = 1049
local spawnpos = {x=525, y=522, z=7}
local timetoreset = 10000

function onUse(cid, item, fromPosition, itemEx, toPosition)

local getwall = getTileItemById(wallpos, wallid).uid

	if item.itemid == 1448 and item.uid == 4009 and (getPlayerStorageValue(cid, 20020) == 1) then
		doPlayerSendTextMessage(cid, 22, 'My hero has arrived! Please bring me back to my father!')
		setPlayerStorageValue(cid, 20021, 1)
		doSummonCreature("Princess", spawnpos)
		doSendMagicEffect(wallpos, CONST_ME_ENERGYAREA)
		doRemoveItem(getwall)
		addEvent(returnwall, timetoreset)
					
	elseif (getPlayerStorageValue(cid, 20021) == 1) then
		doPlayerSendTextMessage(cid, 22, 'The princess has already been released!')
	end
end

function returnwall()
doCreateItem(wallid, wallpos)
end

IMPORTANT:
Please edit the positions to fit your map positions!
If you don't need a hidden path or something then just erase the lines
where the walls are written.

What's the script doing?
I'll show it to you:

princ1.jpg


Explainings:
This script summons the princess to the written "spawnpos" and removes
the wall to the hidden path.

OK, now to the next step!

2.4) Hidden paths and traps

In this section I'll explain the "traps" which I built in this map.

It looks like this:

princ3eee.jpg


You got 3 tiles to chose from, if you make the wrong decision a monster
will spawn and try to kill you!

For the scripts, I used a movement script.
Before I explain the script, if you don't want any traps or something
then don't mind this section!

Add this line into your %data/movement.xml

Lua:
<movevent type="StepIn" actionid="4016" event="script" value="trap1.lua"/>

It's named "trap1.lua" because I made another script that does exactly the same
(spawn a monster) but on different spawnpositions.

IMPORTANT:
Make sure to set the ACTION ID = 4016 on the specific tile so the script can be
executed if a player steps on it.

Add this script into your %data/movements/scripts
and name it trap1.lua

Lua:
local spawnpos = {x=540, y=521, z=7}

function onStepIn(cid, item, pos, fromPos)

	if item.actionid == 4016 then
	 if isPlayer(cid) then
		doSummonCreature("Hero", spawnpos)
		doSendMagicEffect(spawnpos, CONST_ME_ENERGYAREA)
		doTransformItem(item.uid, item.itemid -1)
		doPlayerSendTextMessage(cid, 22, "You made the wrong choice!\n A guard tries to kill the princess!")
	 end
	end
end

Explanations:
Like the picture above shows, this script spawns a monster if you step on the tile.
Now again, ADJUST THE SPAWNPOSITION and the MONSTER if you want something
else.

Now for the right tiles, this will happen:

princ4.jpg


If you chose the right tile to step on, the hidden path will continue!

Again, a movement script, looks like this

Add this line into your %data/movements.xml

Lua:
<movevent type="StepIn" actionid="4014" event="script" value="secret1.lua"/>

Again, rename "secret1.lua" to the script you will use in the next step:

Add this script into your %data/movements/scripts
and name it secret1.lua

Lua:
local config = {
				wallpos = {x=543, y=524, z=7, stackpos=1},
    			wallid = 1049,
				reset = 10
			   }

function onStepIn(cid, item, pos, fromPos)

    if item.actionid == 4014 then
	 if isPlayer(cid) == TRUE then
		doRemoveItem(getThingFromPos(config.wallpos).uid)
		doTransformItem(item.uid, item.itemid -1)
		doSendMagicEffect(config.wallpos, CONST_ME_ENERGYAREA)
		doPlayerSendTextMessage(cid, 22, "The secret path continues. It will close in 10 seconds.")
		addEvent(resetsecret1, config.reset * 1000, item)
	  end
	end
end

function resetsecret1()
doCreateItem(config.wallid, config.wallpos)
end

This script removes the wall and resets it after 10 seconds.

IMPORTANT:

As always, adjust the positions and wallid to your needs!

If you chose the right tiles, or defeated the horrible monsters and you finally reached
the King, talk to him again.

princ5.jpg


And if you followed the steps above correctly, then this will happen:

princ6.jpg


You did it! Congratulations! :thumbup:

And remind yourself to NEVER let the princess die!
You can UH her, throw a potion at her and so on.. otherwise...

princ8.jpg



3) Optional Ideas

Well, that's the Rescue the Princess Quest!

pic5rf.jpg


As you can see at the picture above, I made this secret path with traps.
If you got any other ideas then please adjust the quest to your needs!
I tried to provide as many scripting ideas as possible
(movement -> summon / movement -> Create/Remove / Action -> Summon / NPC script / ...)
Just use the forum to search for ideas / scripts to make your quest unique!

IMPORTANT TIPS:

I'm not a super-pro-Coder ( :p ) therefor
make sure to add the KingNPC and the princess on the same floorlevel.
The reason is simple, a monster can't follow you Up- and DownStairs!
If you know a way to adjust the princess to follow you up and down feel
free to contact me or post a reply!

ALWAYS make sure to REWRITE all the positions, WallIDs, selfSay, Messages
and so on.

If you get any errors while you adjust your script, then feel free to ask!
I hope I can help you with your problems :D

4) Credits


Since i only used the Area Iterator by Colandus, here ya go:

Credits to Colandus -> Area Iterator

Well, this is my very first tutorial!
Please rate it, comment it, flame it? :eek:

If you find bugs or something which doesn't look right please bring it right up
and post a reply or send me a PM!



So far, thanks for reading ;)

Regards,

Zyntax
 
Last edited:
Wow rep+! great release man, if you dont mind, ill be using it for my WoW server :D like the "escort" quests they have :D very nice release good job!
 
well, I have an idea based on this thing, hardest part is making monster summoned monster follow me on floor change only if its name is Princess or whatever I want(other ones need to be roped)
But I will make it I think
thx man for idea
 
I'm glad that you think about the idea.

If you've found a way to "teleport" the following monster to your upper/lower
floorposition, feel free to contact me, I'll add it and credit you ofcourse ;)
 
I have two ideas: source edit of function"teleport summons always" or something like that(configurable) or maybe more rpg: talkaction active only during this quest, but have to do some checks probably(with wrong config can be abused, also some check setting you failed the mission when princess is too far away)
Talkactions like: "its safe here, come to me princess" ;d
I can try to make it bit later
 
Well, you could also build a prison into the underground.
You have to rescue her from the lowest floor.

If you complete a floorlever then there's an elevator waiting.
Bring her into it, activate an item/onStepIn function -> Teleport Princess+Player upper floor.

Well, that's not so "cool" xD, but very easy to script :D
 
not bad, but works only if its only moment when you have to change floor.
I think about some long way with many floor changes, using hidden passages and caves with bats to bring princess the safe way, not through many monsters, what can be dangerous.
I have exams now, I can start writing all needed scripts not earlier than 20.02 -.-
 
Oh well, since I had a GM char the princess didn't follow me.
I thought it was obvious, I'll update the screenshots.

The Monster will be summoned if you step on a wrong tile,
the princess is still with me though, I'll update it right away.

Thanks for the notice ;)
 
actually, you can combine it with the magic mirror thingy, like king gave you his daughters magic mirror to prove that you want to save her, and you use it to transport her the safe way(maybe looking more dangerous, but noone of kidnappers there)
 
Sure, I could also add my "Annoying Tile Ridle" also.

But the purpose of this tutorial is to inspire the people
to think of something themself.

To be honest, the personal ideas are the most unique and
most exciting ones ;)

(Edit: Update successfull)
 
Last edited:
Princess -> hostile flag? I don't think that princess could attack someone that came to rescue her :<
Make her just follow one person, and without retarget.

About stairs/ladders. Make storage value for player to check if he is rescuing princess at the moment, and action onUse function on stairs. First check if princess is near stairs and then if so, teleport her to player (of course let's say that there's only one princess on the map. But still monsters have their cid... anyway, try to update this script, optimize it and make more "colourful". You will learn alot : p
 
HeyHey!
Thanks for stating the flags ^_^ almost forgot about that!

About the teleport problem:

I could draw a ladder and by using the ladder a function onUse could be
executed, but what if the player walks down the ladder again?

If I would use a normal stair, who would click on a stair? :D
(Or is the script executed when a player actually steps on the stairs?
I guess that's a movevent script then?)

Thanks for your comments though! I'll update the scripts/color as soon as
possible!
 
So I'll draw some stairs, add an actionID to the stairs, add them to movements.xml and write an onStepIn function, if I'm correct.
Shouldn't be that difficult ^_^
 
well, putting aids on all stairs on way can be annoying :d
specially because player can chose sometimes way that you cannot imagine, so no aid on that stairs

the "its safe, come here" talkaction fits my taste better
only you have to make princess disappear if you are too far away(as summon she disappears, if you will make wild monster: some scripting needed)
 
Back
Top