summaryrefslogtreecommitdiff
path: root/npc/000-2-1/peter.txt
diff options
context:
space:
mode:
Diffstat (limited to 'npc/000-2-1/peter.txt')
-rw-r--r--npc/000-2-1/peter.txt302
1 files changed, 302 insertions, 0 deletions
diff --git a/npc/000-2-1/peter.txt b/npc/000-2-1/peter.txt
new file mode 100644
index 00000000..499304c4
--- /dev/null
+++ b/npc/000-2-1/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
+// "000-2-2" - map with mobs.
+
+000-2-1,72,34,0 script AreaNPC NPC_HIDDEN,0,1,{
+ end;
+OnTouch:
+ doevent "Peter::OnPeterMain";
+ close;
+}
+
+000-2-1,70,35,0 script Peter 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() ~= "000-2-1") || (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("000-2-2", .@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::OnLowTime");
+ addtimer(140000, "Peter::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() ~= "000-2-2") && !(getmap() ~= "nard*"))
+ end;
+ warp "000-2-1", 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/000-2-2/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 "000-2-1", 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::OnLowTime");
+ deltimer("Peter::OnTimeout");
+ @peter=0;
+ close;
+
+
+OnInit:
+ .distance = 3;
+ end;
+}