diff options
Diffstat (limited to 'npc/001-2-22/peter.txt')
-rw-r--r-- | npc/001-2-22/peter.txt | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/npc/001-2-22/peter.txt b/npc/001-2-22/peter.txt new file mode 100644 index 00000000..dce6982d --- /dev/null +++ b/npc/001-2-22/peter.txt @@ -0,0 +1,302 @@ +// Evol scripts. +// Authors: +// 4144 +// Ablu +// Alastrim +// Jesusalva +// Qwerty Dragon +// Reid +// Vasily_Makarov +// Description: +// Rat hunter. +// 4+2 bits array: +// ShipQuests +// Variable: +// ShipQuests_Peter +// Values is a bitmask: +// 0 Doesn't know the quest. +// 1 Task given. (To prevent bugs because zero is a valid instance id) +// 2 Already completed the first stage +// 4 Already completed the second stage +// 8 Already completed the third stage +// ... +// =15 Completed every stage. +// Setq2: +// Number of killed Rattos: +// & 1 - Ratto 1 +// & 2 - Ratto 2 +// & 4 - Ratto 3 +// & 8 - Ratto 4 +// = 15: All rattos killed +// (Adding more monsters etc. is possible, but be careful with the == 15 checks) +// Setq3: +// Instance ID (so we can destroy it later if needed, and check it too) +// Others: +// .@q = Peter variable. +// PETER_TIME = gettimetick(2) for daily +// @peter = Control Variable +// @pt_mob = Control Variable +// @MAP_NAME$ = Control Variable +// "001-2-23" - map with mobs. + +001-2-22,72,34,0 script AreaNPC#Artis NPC_HIDDEN,0,1,{ + end; +OnTouch: + doevent "Peter::OnPeterMain"; + close; +} + +001-2-22,70,35,0 script Peter#Artis NPC_RATTO_SAILOR,{ + goto L_Main; + +OnPeterMain: +L_Main: + .@q = getq(ShipQuests_Peter); + .@q2 = getq2(ShipQuests_Peter); + .@q3 = getq3(ShipQuests_Peter); + if (BaseLevel < 5) goto OnTooWeak; + + if (!.@q || !isinstance(.@q3) || .@q3 <= 0) goto L_Task; + if (.@q2 < 15) goto L_ReturnFail; + dispbottom l("I am broken?! Please report! Debug data: @@ (@@)", .@q, .@q2); + close; + +OnGiveTask: +L_Task: + if (!.@q) + setq ShipQuests_Peter, 1, 0, -1; + mesn; + mesq l("Hey there!"); + next; + mesq l("I need somebody who can rid the hold of the ship of these rattos. Can you help me?"); + next; + + menu + l("Yeah, but what reward will I get?"), L_BonusTask, + l("Why not, I need to train anyway."), L_BonusTask, + l("No, they are way too dangerous for me!"), -; + + mes ""; + mesn; + mesq l("Hehe, hehe. Well, come back if you change your mind."); + + close; + +// Friendly reminder that you have about 20 secs to finish +OnLowTime: + if ((getmap() ~= "001-2-22") || (getmap() ~= "nard*")) + dispbottom l("I'm starting to feel dizzy... I shouldn't stay here much longer."); + end; + +// Minimum Quest Level (any difficulty setting) is on L_Main (and currently is 5) +OnTooWeak: + mesn; + mesq l("I need someone to help me clean the edge of the ship, but you aren't strong enough for now."); + + close; + +/* +OnStop: + slide 72, 36; + + mesn; + mesq l("You can't go there!"); + + close; +*/ + +// This is cast if player dies in Basement, but not automatically (bad design?) +// instance_destroy() is being recklessy called here, some sanity check is good. +OnReturnFail: +L_ReturnFail: + .@q3 = getq3(ShipQuests_Peter); + //instance_destroy(.@q3); // This would allow players to try again at once, but is DANGEROUS! + setq2 ShipQuests_Peter, 0; + setq3 ShipQuests_Peter, -1; + mesn; + mesq l("I see it's not so easy to get rid of these rattos. Do you want to try again?"); + next; + + menu + l("Yeah, but I would like to make sure I get a reward."), L_BonusTask, + l("Why not, I need to train anyway."), L_BonusTask, + l("No, they are way too dangerous for me!"), -; + + mes ""; + mesn; + mesq l("Hehe, hehe. Well, come back if you change your mind."); + + close; + + +L_BonusTask: + mes ""; + mesn; + mesq l("There are three kind of monsters which frequently or seldomly attacks our fair vessel."); + next; + mesn; + .@q = getq(ShipQuests_Peter); + if (!(.@q & 2)) { + mes l("- I currently need your help with @@.", getmonsterlink(Tortuga)); + mes l("I'll give you @@ GP for this job.", 500); + mes ""; + } + if (!(.@q & 4)) { + mes l("- I currently need your help with @@.", getmonsterlink(Ratto)); + mes l("I'll give you @@ GP for this job.", 1000); + mes ""; + } + if (!(.@q & 8)) { + mes l("- I currently need your help with @@.", getmonsterlink(Croc)); + mes l("I'll give you @@ GP for this job.", 1500); + mes ""; + } + // If you already took all three bounties, you can only repeat the quest daily + if (.@q == 15 && PETER_TIME <= gettimetick(2)) { + mes l("- I currently need your help with @@.", getmonsterlink(Ratto)); + mes l("I'll give you @@ GP for this job.", 750); + } else if (.@q == 15) { + mes l("I don't need your help right now, but maybe tomorrow, who knows?"); + close; + } + next; + + select + l("I'm not feeling like it today... Sorry."), + rif(!(.@q & 2), l("I will take the @@ Bounty.", "Tortuga")), + rif(!(.@q & 4), l("I will take the @@ Bounty.", "Ratto")), + rif(!(.@q & 8), l("I will take the @@ Bounty.", "Croc")), + rif(.@q == 15, l("Why not, I need to train anyway.")); + + if (@menu == 1) + close; + + @peter=@menu; + + goto L_Start; + +// In Moubootaur Legends, there's a small tutorial about Hit'n'run here +// I didn't add it here but that can be arranged +L_Start: +// Init Instance +OnStartOutside: + .@ID=getcharid(0); + @MAP_NAME$="nard@"+str(.@ID); // Max 4 chars for map name + .@INSTID = instance_create("ratto@a"+(.@ID), getcharid(3), IOT_CHAR); + .@instanceMapName$ = instance_attachmap("001-2-23", .@INSTID, 0, @MAP_NAME$); + + // Instance already exists, or something went wrong + if (.@instanceMapName$ == "") { + mesn; + mesq l("Actually, you just took a bounty, right?"); + next; + mesn; + mesq l("Why don't you take a break? Breath in some fresh air. The basement is pretty damp."); + close; + } + + setq2 ShipQuests_Peter, 0; + setq3 ShipQuests_Peter, .@INSTID; + + // It'll be self-destroyed when time runs out (3 minutes) + instance_set_timeout(180, 180, .@INSTID); + instance_init(.@INSTID); + + // Save in a less reliable way the challenge you took + if (@peter == 2) { + @peter=2; + @pt_mob=Tortuga; + } else if (@peter == 3) { + @peter=4; + @pt_mob=Ratto; + } else if (@peter == 4) { + @peter=8; + @pt_mob=Croc; + } else { + @peter=0; + @pt_mob=Ratto; + } + + warp @MAP_NAME$, 48, 28; + // Control how much time you have left + addtimer(120000, "Peter#Artis::OnLowTime"); + addtimer(140000, "Peter#Artis::OnTimeout"); + + // Spawn the Monsters + areamonster @MAP_NAME$, 23, 19, 57, 40, strmobinfo(1, @pt_mob), @pt_mob, 1, "RattosControl::OnRatto1Death"; + areamonster @MAP_NAME$, 23, 19, 57, 40, strmobinfo(1, @pt_mob), @pt_mob, 1, "RattosControl::OnRatto2Death"; + areamonster @MAP_NAME$, 23, 19, 57, 40, strmobinfo(1, @pt_mob), @pt_mob, 1, "RattosControl::OnRatto3Death"; + areamonster @MAP_NAME$, 23, 19, 57, 40, strmobinfo(1, @pt_mob), @pt_mob, 1, "RattosControl::OnRatto4Death"; + + dispbottom l("Okay, you can start!"); + closeclientdialog; + close; + +// TODO: This is very reckless, instance_destroy() could possibly affect others +// If you agree with me, we can force player to wait until instance expire on its +// own (3 minutes after start) instead of allowing immediate retry. That's safer, +// and code will end up looking like Mundane (exploiting attach_map failures) + +// (Or if you are set in disregarding this, just uncomment instance_destroy.) +// (Don't blame me if server SIGSEGV's because that, though) +OnTimeout: + if (!(getmap() ~= "001-2-23") && !(getmap() ~= "nard*")) + end; + warp "001-2-22", 72, 36; + .@q3 = getq3(ShipQuests_Peter); + //instance_destroy(.@q3); + setq2 ShipQuests_Peter, 0; + setq3 ShipQuests_Peter, -1; + mesn; + mesq l("Hey! Be careful. You can't stay in this basement for so long, you're going to get sick. Come outside and take a break, maybe you can try again later."); + close; + +// This is called by npc/001-2-23/ratto.txt and completes the quest +// Just like OnReturnFail and OnTimeout, this recklessy destroys the instance +// It's not _buggy_, it is just reckless. I would like a setting to restrict it +// to destroy only instances owned by the char, or to destroy by name :p +OnDone: + warp "001-2-22", 72, 36; + .@q3 = getq3(ShipQuests_Peter); + //instance_destroy(.@q3); + if (@peter) + setq ShipQuests_Peter, getq(ShipQuests_Peter)|@peter, 0, -1; + + .@q = getq(ShipQuests_Peter); + mesn; + mesq l("Good job!") + " " + l("Here's your reward!"); + + + // Before handling the rewards, we should be sure we'll handle daily loop. + // You're already in daily phase if @peter is zero. + // PS. This is not exactly "daily", this is actually a forced 24-hours wait. + if (!@peter) { + PETER_TIME=gettimetick(2)+24*60*60; + @peter=1; // This allows you to get 32 EXP from daily repeat. Tweak as needed. + } + + // You get some EXP based on difficulty taken + getexp @peter*32, @peter; + + // We don't need @peter anymore, so reuse it to give you GP rewards + switch (@peter) { + case 2: @peter=500; break; + case 4: @peter=1000; break; + case 8: @peter=1500; break; + default: @peter=750; break; + } + + Zeny += @peter; + message strcharinfo(0), l("You receive @@ E!", @peter); + + // Some cleanup. Shouldn't cause bugs but it's absence causes a ugly behavior. + deltimer("Peter#Artis::OnLowTime"); + deltimer("Peter#Artis::OnTimeout"); + @peter=0; + close; + + +OnInit: + .distance = 3; + end; +} |