Jump to content
  • 0

Help with making party message


DutchDuck

Question


  • Group:  Members
  • Topic Count:  30
  • Topics Per Day:  0.01
  • Content Count:  64
  • Reputation:   0
  • Joined:  02/23/14
  • Last Seen:  

hello people,

 

i need some help with this script..

 

i got evrething working fine on just 1 thing left..

 

 

I want to let this message be showed in evreone in the party when the monsters got killed..

		mes "[Realm Defender]";
		mes "Finally...";
		mes "";
		mes "You... You and youre friends... helped getting the Realms back from those monsters..";
		mes "for that we cannot thank you enough...";
		mes "Long Ago the Defenders of the Realm engaged a battle they couldnt win...";
		mes "and those demons took over the realm dungeon...";
		mes "";
		mes "they will return... Later or soon but.. ... lets hope there are more brave wariors...";
		mes "who can help us keep the realm safe..";
		mes "";
		mes "here this is for you as a gift... that you helped defend the Realm of Shadows!";
		next;
		getitem 7227, 1;
		next;
		mes "there you go...";
		mes "";
		mes "wear it with pride... let the power of the realms help you in combat...";
		next;
		warp "pallene", 146, 133;
		close;
	end;
}
}

here is the script for this:

// Pallene Shadow Of Realm Dungeon Script
//===================================================
pal_dun01,70,336,4	script	RealmShadowsDungeon	446,{
	if (instance_check_party(getcharid(1),2,150)){
		mes "You made it this far... time to fight the Realm of Shadows Keepers!";
		next;
		warp "pal_dun02", 49, 6;
} 		else {
		mes "Come back when you are Base Level 150+ and in a party with atleast 2 members";
		close;
}}
//============================================================
-	script	MonsterSpawn	-1,{
	OnPCLoadMapEvent:
	mes	"Thank god you made it this far already..!";
	mes	"Please defeat the Realm Keepers before they escape to Pallene!!";
	mes	"Kill 2 of the Realm Keepers Azthor, Othar or Kalnor!";
	mes	"I will take care of the other one! then i can give you something in return for youre help!!";
	.mob = 3;
	monster "pal_dun02",0,0,"Azthor Keeper of the Realms",1708,1,strnpcinfo(1)+"::OnMobKilled";
	monster "pal_dun02",0,0,"Othar Keeper of the Realms",1039,1,strnpcinfo(1)+"::OnMobKilled";
	monster "pal_dun02",0,0,"Kalnor Keeper of the Realms",1917,1,strnpcinfo(1)+"::OnMobKilled";

//===================================================================

	OnMobKilled:
	.mob--;
	if ( !.mob){
		mes "[Realm Defender]";
		mes "Finally...";
		mes "";
		mes "You... You and youre friends... helped getting the Realms back from those monsters..";
		mes "for that we cannot thank you enough...";
		mes "Long Ago the Defenders of the Realm engaged a battle they couldnt win...";
		mes "and those demons took over the realm dungeon...";
		mes "";
		mes "they will return... Later or soon but.. ... lets hope there are more brave wariors...";
		mes "who can help us keep the realm safe..";
		mes "";
		mes "here this is for you as a gift... that you helped defend the Realm of Shadows!";
		next;
		getitem 7227, 1;
		next;
		mes "there you go...";
		mes "";
		mes "wear it with pride... let the power of the realms help you in combat...";
		next;
		warp "pallene", 146, 133;
		close;
	end;
}
}

 at this moment the message only shows to the one who kills the monsters...

 

 

i want it to be showed to evreone in the party but i want the partyleader to get item 7227 10 times

and members get 7227 5 times 

 

is this possible?

 

help please :)

Link to comment
Share on other sites

13 answers to this question

Recommended Posts

  • 0

  • Group:  Members
  • Topic Count:  31
  • Topics Per Day:  0.01
  • Content Count:  283
  • Reputation:   31
  • Joined:  07/08/14
  • Last Seen:  

Hey there!

 

You can attach players of a party by adding this command before the messages:

addrid(2,0,getcharid(1));

You also can use this to only attach the party leader:

.@party_leader_id = getpartyleader(getcharid(1),1);
detachrid;
attachrid(.@party_leader_id); 

Make sure he's logged in to prevent the script from bugging!

 

Or if it's just in order to give items you can use the 'addrid' command and check whether the player is the leader at the moment you give items.

 

 

Sorry but looking at your script there are several things that seems wrong to me, can you tell me a bit more about those?

  • Is it supposed to be an instanced quest? Because if this is one you need to create it and if it's not you need to forbid players from doing it unless the previous party has finished the quest, otherwise there is a chance from monsters to spawn several times.
  • You don't kill the third monster when the quest is completed, is that normal?
  • The 'OnPCLoadMapEvent' label have many errors. You first need to check if the player entering the map is in the party doing the quest. You also have to check if he's in the right map because this label will be triggered on every map that has the 'mf_loadevent' mapflag. Finally you need to spawn the monsters only once because each player entering the map will make 3 monsters spawn.

I can fix those for you but I need you to answer a few questions:

  • Is it supposed to be an instanced quest? Or do you want only one party to be able to do the quest at a time?
  • Is there something that players have to do before being allowed to do the quest? If yes, what?
  • What is the map the 'OnPCLoadMapEvent' label should trigger?
  • Anything else you need me to know? ^^

Also if you want to add any feature don't hesitate to ask, that's what we're here for ^^

 

Take care

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  30
  • Topics Per Day:  0.01
  • Content Count:  64
  • Reputation:   0
  • Joined:  02/23/14
  • Last Seen:  

hello kurofly

 

thanks for youre reply!

 

well let me tell you more about the whole idea...

 

ORIGINAL PLAN:

 

my first plan was...

 

make dungeon F1 acces able for evreone to hunt and farm RoS_Tokens 7227 with a lil story attached to it...

 

then If they want to decide to go to F2 They will need to be lvl 150+ and have a party in order to acces F2..

then upon entering F2 a message shows up ( works) to evreone who enters and 3 MVPS with custom names get spawned ( works )

after defeating the 3 monsters a message had to show up giving the party leader for example 100 apples and the party members 50 apples for assist.(however the message only shows up for the character killing the 3 MVPS ).

 

Then you get warped out and i wanted the Dungeon floor 2 having a cooldown for like 2 hours.. until a new party can start the quest

also the party who started the qeust have 2 hours to finish it..

 

This was my original plan on which im trying to complete it..

 

so yeah it should be part instance sort off and sort off not....

 

awnsers to youre qeustions:

 

  • Is it supposed to be an instanced quest? Because if this is one you need to create it and if it's not you need to forbid players from doing it unless the previous party has finished the quest, otherwise there is a chance from monsters to spawn several times.
    

    * Partly... Only F2

You don't kill the third monster when the quest is completed, is that normal?

* To be honest no its not... i tryed evrething but i cant get it that far that you have to kill all three... 2 works... 3 dont seem to work somehow... :(

The 'OnPCLoadMapEvent' label have many errors. You first need to check if the player entering the map is in the party doing the quest. You also have to check if he's in the right map because this label will be triggered on every map that has the 'mf_loadevent' mapflag. Finally you need to spawn the monsters only once because each player entering the map will make 3 monsters spawn.

yah This is what should be happening though,,, only spawn once per party not per player entering the map... 

Is it supposed to be an instanced quest? Or do you want only one party to be able to do the quest at a time?

to be honest i think seeing f1 is free accesable that one party at the time should do the trick?

Is there something that players have to do before being allowed to do the quest? If yes, what?

they first have to be lvl 150/+  and in a online party of minimum 2 players....  then i'd like them to kill 80 Shinobi and 20 Ancient Tree's in floor 1 in party total... then they can get acces to floor 2...

What is the map the 'OnPCLoadMapEvent' label should trigger?

the map i added this command on is pal_dun02  our custom made dungeon 

 

 

 

 

 

====================

 

To be honest this is my original plan what i was really aiming for step by step haha

 i thought i was heading the good way though XD

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  31
  • Topics Per Day:  0.01
  • Content Count:  283
  • Reputation:   31
  • Joined:  07/08/14
  • Last Seen:  

There's no wrong way, no pain no gain  B)   

 

Just to let you know, the 3 mobs error occurs because the script is not ended before the mob death label.

...
monster "pal_dun02",0,0,"Kalnor Keeper of the Realms",1917,1,strnpcinfo(1)+"::OnMobKilled";
// should be an 'end;' there, otherwise the script continue and the variable '.mob' decrements.
//===================================================================

	OnMobKilled:
	.mob--;
...

Gonna do that either this evening or tomorrow evening, depends on whether I get a call that I really don't wanna get this evening or not ^^

 

I'm not a fan of instances, I find it overly complicated and it's a really bad way to learn things so I'm gonna do it the original way. Don't worry it'll have nothing to envy to instances.

 

Just one last thing, don't you want each party that has done the quest to have a delay of 2 hours instead of all the parties? Because if you ask them to kill mobs for 30 minutes and then the quest becomes unavailable because someone else did it that'd be a shame ^^

 

See you

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  30
  • Topics Per Day:  0.01
  • Content Count:  64
  • Reputation:   0
  • Joined:  02/23/14
  • Last Seen:  

i would say 2 hours for all parties..

 

the mobs they need to hunt down are around 60/80 units in floor 1 at a respawn rate of 1 minute 

 

but i only want the party who want to contineu to F2 to be specified with the killing monsters task.. so other players in the dungeon can still play around there while a party does the quest at the same time

 

The quest to F2 can only be activated by 1 party at the time to avoid that problem i think?

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  31
  • Topics Per Day:  0.01
  • Content Count:  283
  • Reputation:   31
  • Joined:  07/08/14
  • Last Seen:  

Oh yeah I forgot to ask, what's your client date? (wanna put item link ^^)


'Sup there

 

I'm on it,

  • do you want players to receive rewards when they complete the first part? (killing 80 shinobi and 20 ancient trees)
  • do I consider the quest failed when all the players are dead in pal_dun02? If not, do the monsters regain their health when everybody dies?
  • do you want players to be able to go back to pal_dun02 if they die?
  • Is pal_dun02 a big map? If yes do you want players to locate the MVPs on this map?

Wow I just saw the MVPs you spawn, they're gonna have a hard time if they're only 2 in the party xD

 

that's a bit like "hey, you killed some Shinobi, that's great! Now go kill Satan Morocc, Thanatos and Baphomet!"

 

Since there's quite a gap in difficulty between part 1 and 2 don't you want to set the amount of players needed to a higher value? Or change something in the quest?


Still have one question and that should be it.

 

In case you reloadscript when players are doing the quest, do you want to give them the rewards as an apologize? If yes do they need to be at a certain point before getting rewards on reload?

For example I can give rewards if players have already killed one of the MVPs in part 2 when the scripts are reloaded, or even if they killed 10 shinobi I don't know, whatever you want ^^

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  30
  • Topics Per Day:  0.01
  • Content Count:  64
  • Reputation:   0
  • Joined:  02/23/14
  • Last Seen:  

on the client info ill have to search cause i cant remember where to find it ill get back on that later...



do you want players to receive rewards when they complete the first part? (killing 80 shinobi and 20 ancient trees) 

well we could give them white potions or yggdrasil seeds to help survive in f2 ? like 10/20 each player in party

Is pal_dun02 a big map? If yes do you want players to locate the MVPs on this map?

No pal_dun02 is a small/medium sized square map so there wont be any need to use locate items.

do I consider the quest failed when all the players are dead in pal_dun02? If not, do the monsters regain their health when everybody dies?

Well seeing the battle is gonna be hard id suggest that when they die they can just go and re enter the dungeon and the monsters dont regain health.. else they will never be able to finish it i'd rather say lets give them a time schedule for like 2 hours orso to finish the monsters..

do you want players to be able to go back to pal_dun02 if they die?

yes absolutely i dont think theyll be able to do this in one try without a priest who resurrects them haha

Wow I just saw the MVPs you spawn, they're gonna have a hard time if they're only 2 in the party xD
 
that's a bit like "hey, you killed some Shinobi, that's great! Now go kill Satan Morocc, Thanatos and Baphomet!"
 
Since there's quite a gap in difficulty between part 1 and 2 don't you want to set the amount of players needed to a higher value? Or change something in the quest?

hehe yeah its a 250/120 server so i thought lets still keep it with teamplay cause on most of the servers there is no teamplay on higher servers so thats why id say lets make it hard so they have to team up ^^   well we could raise the party amount to 3 or 4  minimum  > so they have to be with 3 people in a party > more is always good  how bigger the party how faster they succeed imo.

In case you reloadscript when players are doing the quest, do you want to give them the rewards as an apologize? If yes do they need to be at a certain point before getting rewards on reload?
For example I can give rewards if players have already killed one of the MVPs in part 2 when the scripts are reloaded, or even if they killed 10 shinobi I don't know, whatever you want ^^

lets say that if they finished the shinobi hunt  and i reload then they can still enter the dungeon f2 without having to redo the killing 

if they have killed an mvp in part 2  and i have to reload script they can get 50 7227 RoS Tokens as a price I dont want them to have the unique item which is a custom that gives +20 stats and 3 slots Item ID ( 20035  this is also the item i want to give to the party leader for leading his party  and the party members get 50 7227 Ros Tokens)

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  31
  • Topics Per Day:  0.01
  • Content Count:  283
  • Reputation:   31
  • Joined:  07/08/14
  • Last Seen:  

Whew ~~

pal_dun01,70,336,4	script	Realm Defender	54,{ function PrintMes ; function SetColor ; function EraseRQuest;

	.@name$ = "[^990000"+strnpcinfo(0)+"^000000]";

	if (!$RQ_PartyId || $RQ_PartyId != getcharid(1)) { // no party doing the quest or player not in it
		.@loop = 1;
		while (.@loop) { // used to loop the menu whithout goto commands (in case the player wants to see the details of the quest, he'll be brought back here after)
		// quest availability
			mes .@name$,"Quest status : "+((gettimetick(2)<$RQ_ResetTime || $RQ_PartyId)?"^ff0000unavailable":"^00ff00available")+"^000000";
			if ($RQ_PartyId) mes "Party ^cc3300"+getpartyname($RQ_PartyId)+"^000000 is currently doing the quest"; // $RQ_PartyId var is set to the id of the party doing the quest, $RQ_PartyId != 0 => party doing the quest
			else if ((.@delay = $RQ_ResetTime-gettimetick(2)) > 0) { // display time left ($RQ_ResetTime is set to gettimetick(2) + .questdelay upon completion of part 2)
				.@hours = .@delay / (60*60) ; .@min = (.@delay - (.@hours*60*60)) / 60 ; .@sec = .@delay - (.@hours*60*60) - (.@min*60);
				if (.@hours) mes "Delay : "+.@hours+" hour"+(.@hours>1?"s":"")+" "+.@min+" minute"+(.@min>1?"s":"")+" "+.@sec+" second"+(.@sec>1?"s":"");
				else if (.@min) mes "Delay : "+.@min+" minute"+(.@min>1?"s":"")+" "+.@sec+" second"+(.@sec>1?"s":"");
				else mes "Delay : "+.@sec+" second"+(.@sec>1?"s":"");
			}
		// rewards infos
			mes "Reward"+(((getarraysize(.rewards)>2)+(.ZenyReward?1:0))?"s :":" :");
			for (.@i = 0 ; .@i < getarraysize(.rewards) ; .@i+=2)
				mes " ~ "+.rewards[.@i+1]+" <ITEMLINK>"+getitemname(.rewards[.@i])+"<INFO>"+.rewards[.@i]+"</INFO></ITEMLINK>";
			if (.ZenyReward) mes " ~ ^ffcc00"+.ZenyReward+"^000000 zeny";
			mes "Party leader reward"+(((getarraysize(.PartyLeaderBonusRewards)>2)+(.PartyLeaderBonusZenyReward?1:0))?"s":"")+" (added to the one"+(((getarraysize(.rewards)>2)+(.ZenyReward?1:0))?"s":"")+" above) :";
			for (.@j = 0 ; .@j < getarraysize(.PartyLeaderBonusRewards) ; .@j+=2)
				mes " ~ "+.PartyLeaderBonusRewards[.@j+1]+" <ITEMLINK>"+getitemname(.PartyLeaderBonusRewards[.@j])+"<INFO>"+.PartyLeaderBonusRewards[.@j]+"</INFO></ITEMLINK>";
			if (.PartyLeaderBonusZenyReward) mes " ~ ^ffcc00"+.PartyLeaderBonusZenyReward+"^000000 zeny";
		// requirements
			mes "Requirements :";
			getpartymember getcharid(1),1 ; getpartymember getcharid(1),2;
			for (.@k = 0 ; .@k < $@partymembercount ; .@k++)
				if (isloggedin($@partymemberaid[.@k]))
					if ((.@x = getvar(BaseLevel,$@partymembercid[.@k])) >= .MinLevel) .@n++; // party member logged and has the required level
			mes " - "+(.@n<.PlayersRequired?"^ff0000":"^00ff00")+"Party of at least "+.PlayersRequired+" level "+.MinLevel+" member"+(.PlayersRequired>1?"s":"")+"^000000";
			mes " - "+(getpartyleader(getcharid(1),1) == getcharid(3)?"^00ff00":"^ff0000")+"You need to be the party leader^000000";
			.@can = 1;
			if (.@delay > 0 || .@n < .PlayersRequired || getpartyleader(getcharid(1),1) != getcharid(3)) { // quest delay, not enough valid members or player isn't the party leader
				.@can = 0; // shorter way to check all the requirements above
				if (select("View details:Leave") == 2) close;
				next;
				PrintMes(1,strnpcinfo(0)); // you can edit the dialogues in this function at the bottom of the script, I bet it'll be easier for you
				if (select("Go back to menu:Leave") == 2) close;
			}
			if (.@can) {
				next;
				if ((.@select = select("Proceed:View details:Leave")) == 3) close;
				if (.@select == 2) {
					PrintMes(1,strnpcinfo(0)); // you can edit the dialogues in this function at the bottom of the script, I bet it'll be easier for you
					if (select("Go back to menu:Leave") == 2) close;
				}
				if (.@select == 1) .@loop = 0; // selected proceed, loop break
			}
		}
	// quest proceeding
		if ($RQ_PartyId) { mes .@name$,"Arg, someone accepted the quest before you ><" ; close; } // in case someone accepts the quest while the player is in the menu
		getpartymember getcharid(1),1 ; getpartymember getcharid(1),2 ; .@n = 0 ; deletearray .PartyAnnounceMember,128;
		for (.@k = 0 ; .@k < $@partymembercount ; .@k++)
			if (isloggedin($@partymemberaid[.@k]))
				if ((.@x = getvar(BaseLevel,$@partymembercid[.@k])) >= .MinLevel) { .@n++ ; setarray .PartyAnnounceMember[getarraysize(.PartyAnnounceMember)] , $@partymemberaid[.@k]; } // keeps a trace of the players who will have to receive the first announces
		if (.@n < .PlayersRequired) { mes .@name$,"Arg, someone disconnected and you don't have enough valid members anymore ><" ; close; } // in case a valid member disconnects meanwhile
		$RQ_PartyId = getcharid(1) ; initnpctimer;
		for (; .@l < getarraysize(.MobsPart1) ; .@l+=2) setd "$RQ_PartyMob"+.MobsPart1[.@l]+"count" , 0; // resets monster kill counters
		announce "Party '"+getpartyname(getcharid(1))+"' accepted the "+strnpcinfo(0)+" quest, wish them good luck!",bc_all,.AnnounceColor;
		close2;
		sleep 5000;
		for (.@i = 0 ; .@i < getarraysize(.PartyAnnounceMember) ; .@i++) // broadcasts to every valid party member (since there's actually no partyannounce command)
			if (attachrid(.PartyAnnounceMember[.@i])) announce "["+strnpcinfo(0)+" Quest] : You sucessfully accepted the "+strnpcinfo(0)+" quest",bc_self,.AnnounceColor;
		sleep 5000;
		.@str$ = ""+.MobsPart1[1]+" "+strmobinfo(1,.MobsPart1); // this part ..
		for (.@m = 2 ; .@m < (getarraysize(.MobsPart1)-2) ; .@m+=2) .@str$ = .@str$ + ", "+.MobsPart1[.@m+1]+" "+strmobinfo(1,.MobsPart1[.@m]);
		.@str$ = .@str$ + " and "+.MobsPart1[.@m+1]+" "+strmobinfo(1,.MobsPart1[.@m]); // .. is used to fill all the monster-to-kill infos in one string so that we don't send multiple announces
		for (.@i = 0 ; .@i < getarraysize(.PartyAnnounceMember) ; .@i++)
			if (attachrid(.PartyAnnounceMember[.@i])) announce "["+strnpcinfo(0)+" Quest info] : You need to kill "+.@str$+" in order to complete the first part of the quest",bc_self,.AnnounceColor;
		sleep 5000;
		for (.@i = 0 ; .@i < getarraysize(.PartyAnnounceMember) ; .@i++)
			if (attachrid(.PartyAnnounceMember[.@i])) announce "["+strnpcinfo(0)+" Quest info] : Remember the party leader can abandon the quest any time by typing '@stopquest'!",bc_self,.AnnounceColor;
		end;
	}

	else if (!$RQ_Part1Complete || !$RQ_Part1Talked) { // part 1 incomplete or not proceeded
	// quest infos
		for (; .@i < getarraysize(.MobsPart1) ; .@i+=2) { .@amount = .@amount + getd("$RQ_PartyMob"+.MobsPart1[.@i]+"count") ; .@total = .@total + .MobsPart1[.@i+1]; }
		mes .@name$,"Quest status : [^0000ff"+(100*.@amount/.@total)+"% done^000000]";
		for (; .@j < getarraysize(.MobsPart1) ; .@j+=2) 
			mes " ~ "+SetColor("kill "+.MobsPart1[.@j+1]+" "+strmobinfo(1,.MobsPart1[.@j]),getd("$RQ_PartyMob"+.MobsPart1[.@j]+"count"),.MobsPart1[.@j+1]); // the 'SetColor' function adds a green and red color depending on the amount of mobs killed (ex: if you killed half of the monsters needed, half of the text will be in green and half in red)
		//the $RQ_Part1Complete variable is set to 1 in the OnNPCKillEvent label when all the monsters required are killed
		if (!$RQ_Part1Complete || getpartyleader($RQ_PartyId,1) != getcharid(3)) close; // player can't proceed if the quest is not completed or he's not the party leader
		next;
		if (select("Proceed:Leave") == 2) close;
		PrintMes(2,.@name$); // you can edit the dialogues in this function at the bottom of the script, I bet it'll be easier for you
		if (select("Go for part 2!:Not yet") == 2) close;
	// quest proceeding
		close2;
		$RQ_Part1Talked = 1;
		for (.@i = 0 ; .@i < getarraysize(.MobsPart1) ; .@i+=2) setd "$RQ_Part1Mob"+.MobsPart1[.@i]+"count" , 0;
		getpartymember getcharid(1),1 ; deletearray .PartyMember,128;
		for (; .@k < $@partymembercount ; .@k++) // gets valid players again in case someone was added to the party (it does not restrain players from warping if they don't have enough valid members because that'd be a pain for them after having done the first part..)
			if (attachrid($@partymemberaid[.@k]))
				if (BaseLevel >= .MinLevel) { setarray .PartyMember[getarraysize(.PartyMember)] , $@partymemberaid[.@k] ; announce "["+strnpcinfo(0)+" Quest] : You will be warped in 5 seconds..",bc_self,.AnnounceColor; }
		sleep 3000;
		for (; .@l < getarraysize(.PartyMember) ; .@l++) // broadcasts to every valid party member
			if (attachrid(.PartyMember[.@l])) { 
				announce "["+strnpcinfo(0)+" Quest] : I wish you a good luck!",bc_self,.AnnounceColor;
				for (.@k = 0 ; .@k < getarraysize(.HelpItems) ; .@k+=2) getitem .HelpItems[.@k],HelpItems[.@k+1];
			}
		sleep 2000;
		for (; .@m < getarraysize(.PartyMember) ; .@m++) // warps valid players to quest map
			if (attachrid(.PartyMember[.@m])) warp .questmap$,.x,.y;
		for (.@i = 0 ; .@i < getarraysize(.MobsPart2) ; .@i+=2) { // spawns part 2 monsters
			deletearray $@mobid,128;
			monster .questmap$,0,0,.MobsPart2Name$[.@i/2],.MobsPart2[.@i],.MobsPart2[.@i+1],strnpcinfo(0)+"::OnMobKilled";
			for (.@j = 0 ; .@j < getarraysize($@mobid) ; .@j++) { // keeps a trace of monster spawned infos, this way we'll be able to spawn them back on reloadscript (they're being spawned back with the amount of HP they had before the reload)
				setd "$RQ_Part2Mob"+$RQ_Part2Mob+"GID" , $@mobid[.@j];
				setd "$RQ_Part2Mob"+$RQ_Part2Mob+"ID" , .MobsPart2[.@i];
				setd "$RQ_Part2Mob"+$RQ_Part2Mob+"Name$" , .MobsPart2Name$[.@i/2];
				setd "$RQ_Part2Mob"+$RQ_Part2Mob+"HP" , strmobinfo(4,.MobsPart2[.@i]);
				$RQ_Part2Mob++; // used in the OnMobKilled label
				$RQ_Part2TotalMobs++; // used on reloadscript
			}
		}
		end;			
	}

	else if ($RQ_Part1Talked) { // part 2 proceeded (means either player died in part 2, warped out or was added to the party meanwhile)
		if (BaseLevel < .MinLevel) { mes .@name$,"You must be at least level "+.MinLevel+" to join the quest.." ; close; }
		mes .@name$,"Don't give up "+strcharinfo(0)+", I know you can make it!" ; next;
		if (select("go to "+.questmap$+":Leave") == 2) close;
		warp .questmap$,.x,.y;
		end;
	}

	else { // not supposed to happen, I just don't wanted to put an 'else' at the last part cause if it does happen it would warp the player to pal_dun02
		mes .@name$,"O_O ??"," ","Sorry but this part of the script is not supposed to trigger, could you contact your administrator please? ><";
		close;
	}

OnNPCKillEvent: // checks whether the part 1 quest is completed (also display infos)
	if (getcharid(1) == $RQ_PartyId && !$RQ_Part1Complete) {
		for (; .@i < getarraysize(.MobsPart1) ; .@i+=2)
			if (.MobsPart1[.@i] == killedrid && getd("$RQ_PartyMob"+killedrid+"count") < .MobsPart1[.@i+1]) {
				setd "$RQ_PartyMob"+killedrid+"count" , getd("$RQ_PartyMob"+killedrid+"count") + 1;
				getpartymember getcharid(1),1;
				for (.@j = 0 ; .@j < $@partymembercount ; .@j++) // broadcasts to every valid party member in the map
					if (attachrid($@partymemberaid[.@j]))
						if (strcharinfo(3) == .map$ && BaseLevel >= .MinLevel) announce "["+strnpcinfo(0)+" Quest] : "+getd("$RQ_PartyMob"+.MobsPart1[.@i]+"count")+"/"+.MobsPart1[.@i+1]+" "+strmobinfo(1,killedrid)+" killed",bc_self,.AnnounceColor;
				for (.@k = 0 ; .@k < getarraysize(.MobsPart1) ; .@k+=2)
					if (getd("$RQ_PartyMob"+.MobsPart1[.@k]+"count") < .MobsPart1[.@k+1]) { .@ko = 1 ; break; }
				if (!.@ko) { announce "Party '"+getpartyname(getcharid(1))+"' has finished the first part of the "+strnpcinfo(0)+" quest!",bc_all,.AnnounceColor ; $RQ_Part1Complete = 1; }
			}
	}
	end;

OnMobKilled: // checks whether the part 2 quest is completed (also display infos)
	$RQ_Part2Mob--;
	getpartymember getcharid(1),2;
	for (; .@i < $@partymembercount ; .@i++)// broadcasts to every valid party member
		if (attachrid($@partymemberaid[.@i]))
			if (BaseLevel >= .MinLevel) {
				if ($RQ_Part2Mob > 1) announce "["+strnpcinfo(0)+" Quest] : "+$RQ_Part2Mob+" Keepers left, keep going!",bc_self,.AnnounceColor;
				else if ($RQ_Part2Mob) announce "["+strnpcinfo(0)+" Quest] : only one Keeper left, you've almost done it!",bc_self,.AnnounceColor;
				else { // quest completed, giving rewards
					announce "["+strnpcinfo(0)+" Quest] : "+strnpcinfo(0)+" quest completed, congratulations! Here are your rewards!",bc_self,.AnnounceColor;
					for (.@j = 0; .@j < getarraysize(.rewards) ; .@j+=2) getitem .rewards[.@j],.rewards[.@j+1];
					Zeny += .ZenyReward;
					if (getpartyleader($RQ_PartyId,1) == $@partymemberaid[.@i]) { // party leader bonus rewards
						for (; .@k < getarraysize(.PartyLeaderBonusRewards) ; .@k+=2) getitem .PartyLeaderBonusRewards[.@k],.PartyLeaderBonusRewards[.@k+1];
						Zeny += .PartyLeaderBonusZenyReward;
					}
				}
			}
	if (!$RQ_Part2Mob) { // quest completed, reseting variables & setting delay
		sleep 3000 ; announce "Party '"+getpartyname($RQ_PartyId)+"' has helped keeping the Realms safe by completing the "+strnpcinfo(0)+" quest! Congratulations!",bc_all,.AnnounceColor ; sleep 3000;
		$RQ_PartyId = 0 ; $RQ_Part1Complete = 0 ; $RQ_Part1Talked = 0 ; $RQ_Part2TotalMobs = 0;
		$RQ_ResetTime = gettimetick(2) + .questdelay;
		stopnpctimer;
		.@hours = .questdelay / (60*60) ; .@min = (.questdelay - (.@hours*60*60)) / 60 ; .@sec = .questdelay - (.@hours*60*60) - (.@min*60);
		if (.@hours) announce "The "+strnpcinfo(0)+" quest will be available again in "+.@hours+" hour"+(.@hours>1?"s":"")+(.@min?" "+.@min+" minute"+(.@min>1?"s":""):"")+(.@sec?" "+.@sec+" second"+(.@sec>1?"s":""):""),bc_all,.AnnounceColor;
		else if (.@min) announce "The "+strnpcinfo(0)+" quest will be available again in "+.@min+" minute"+(.@min>1?"s":"")+(.@sec?" "+.@sec+" second"+(.@sec>1?"s":""):""),bc_all,.AnnounceColor;
		else announce "The "+strnpcinfo(0)+" quest will be available again in "+.@sec+" second"+(.@sec>1?"s":""),bc_all,.AnnounceColor;
	}
	end;

OnTimer5000:
	getpartymember $RQ_PartyId,2;
	if (!$@partymembercount) { // party deleted
		announce "["+strnpcinfo(0)+" Quest Info] : Party '"+getpartyname($RQ_PartyId)+"' has been deleted and the quest has been erased!",bc_all,.AnnounceColor;
		EraseRQuest();
	}

	.InactiveTime+=5;

	if (!$RQ_Part1Talked) { // part 1 inactivity check
		for (; .@i < getarraysize(.MobsPart1) ; .@i++) {
			if (getd("$RQ_PartyMob"+.MobsPart1[.@i]+"count") != getd(".PreviousCount"+.@i)) .InactiveTime = 0;
			setd ".PreviousCount"+.@i , getd("$RQ_PartyMob"+.MobsPart1[.@i]+"count");
		}
	}
	else { // part 2 inactivity check (+ checking when loading map with the 'OnPCLoadMapEvent' label below)
		addrid(0);
		if (.questmap$ == strcharinfo(3) && $RQ_PartyId == getcharid(1)) .InactiveTime = 0;
		detachrid;
	}

	if (.InactiveTime == 300) { // shows warning after being inactive for 5 minutes
		getpartymember $RQ_PartyId,2;
		for (.@i = 0 ; .@i < $@partymembercount ; .@i++)
			if (attachrid($@partymemberaid[.@i])) 
				if (BaseLevel >= .MinLevel) announce "["+strnpcinfo(0)+" Quest Info] : Your party has been inactive for 5 minutes.",bc_self,.AnnounceColor;
		sleep 3000;
		for (.@i = 0 ; .@i < $@partymembercount ; .@i++)
			if (attachrid($@partymemberaid[.@i])) 
				if (BaseLevel >= .MinLevel) announce "["+strnpcinfo(0)+" Quest Info] : If your are still inactive after 5 more minutes, the quest will be erased.",bc_self,.AnnounceColor;
		sleep 3000;
		for (.@i = 0 ; .@i < $@partymembercount ; .@i++)
			if (attachrid($@partymemberaid[.@i])) 
				if (BaseLevel >= .MinLevel) announce "["+strnpcinfo(0)+" Quest Info] : Remember the party leader can type '@stopquest' to abandon the quest.",bc_self,.AnnounceColor;
	}
	if (.InactiveTime >= 600) { // erases quest after being inactive for 10 minutes
		announce "["+strnpcinfo(0)+" Quest Info] : Party '"+getpartyname($RQ_PartyId)+"' has been inactive for 10 minutes and the quest has been erased!",bc_all,.AnnounceColor;
		EraseRQuest();
	}
	

	for (.@i = 0 ; .@i < $RQ_Part2TotalMobs ; .@i++) // update part 2 monsters HP in case of a reloadscript
		if (getd("$RQ_Part2Mob"+.@i+"HP")) { // just to avoid getting warnings every 5 seconds
			deletearray .@data,128;
			getunitdata getd("$RQ_Part2Mob"+.@i+"GID"),.@data; // it will return a warning if it can't find the mob, don't worry that's normal (even though that's boring..)
			setd "$RQ_Part2Mob"+.@i+"HP" , .@data[UMOB_HP];
			if (!.@data[UMOB_HP]) { setd "$RQ_Part2Mob"+.@i+"GID" , 0 ; setd "$RQ_Part2Mob"+.@i+"ID" , 0 ; setd "$RQ_Part2Mob"+.@i+"Name$" , ""; }
		}
	initnpctimer;
	end;

OnPCLogoutEvent:
	if (getpartyleader($RQ_PartyId,1) == getcharid(3)) {
		announce "["+strnpcinfo(0)+" Quest Info] : Party leader of party '"+getpartyname($RQ_PartyId)+"' has logged out!",bc_all,.AnnounceColor;
		EraseRQuest();	
	}
	end;

OnStopQuest:
	if ($RQ_PartyId != getcharid(1)) end;
	if (getpartyleader($RQ_PartyId,1) != getcharid(3)) { dispbottom "["+strnpcinfo(0)+" Quest Info] : Only the part leader can decide to stop the quest." ; end; }
	announce "["+strnpcinfo(0)+" Quest Info] : Party leader of party '"+getpartyname($RQ_PartyId)+"' has abandonned the quest!",bc_all,.AnnounceColor;
	EraseRQuest();
	end;

OnInit:
	.map$ = strnpcinfo(4); // if your npc is on a different map than the mobs in part 1, change '.map$' to the map those monsters are
	.questmap$ = "pal_dun02" ; .x = 49 ; .y = 6; // map, x and y where the players are warped on part 2 quest, also the map in which the part 2 monsters are spawned
	.PlayersRequired = 2; // amount of players required to begin the quest
	.MinLevel = 150; // minimum level required for each player in the party in order to do the quest
	.questdelay = 2*60*60; // delay (s) before any party is allowed to do the quest again 

	setarray .MobsPart1 , 1401,80 , 2019,20; // mobs to kill in part 1
	// setarray .MobsPart1 , <mob id>,<amount>{ , <mob id>,<amount>{ , <mob id>,<amount>{..}}};
	setarray .MobsPart2 , 1708,1 , 1039,1 , 1917,1; // mobs to kill in part 2
	// setarray .MobsPart2 , <mob id>,<amount>{ , <mob id>,<amount>{ , <mob id>,<amount>{..}}};
	setarray .MobsPart2Name$ , "Azthor" , "Othar" , "Kalnor"; // mob names in part 2 (don't put too long names or they won't be fully displayed)
	// setarray .MobsPart2Name$ , <mob 1 name>{ , <mob 2 name>,{ , <mob i3 name>{..}}};

	setarray .rewards , 7227,50; // rewards for every player in the party
	// setarray .rewards , <item id>,<amount>{ , <item id>,<amount>{ , <item id>,<amount>{..}}};
	.ZenyReward = 0; // zeny reward for every player in the party
	setarray .PartyLeaderBonusRewards , 7227,50 , 512,1; // party leader bonus rewards (added to those above)
	// setarray .PartyLeaderBonusRewards , <item id>,<amount>{ , <item id>,<amount>{ , <item id>,<amount>{..}}};
	.PartyLeaderBonusZenyReward = 0; // party leader zeny bonus reward (added to the amount above)
	
	setarray .HelpItems , 608,10; // items given to players to help them in part 2
	// setarray .HelpItems , <item id>,<amount>{ , <item id>,<amount>{ , <item id>,<amount>{..}}};

	.AnnounceColor = 0x00ff00; // color of announces relative to the quest

	setmapflag .map$,mf_loadevent; // used for showing quest availability on the map
	setmapflag .questmap$,mf_loadevent; // used to check players inactivity in part 2
	setmapflag .questmap$,mf_nowarp;
	setmapflag .questmap$,mf_nogo;
	setmapflag .questmap$,mf_noteleport; // not sure you want that one though (disables fly wings)
	setmapflag .questmap$,mf_nomemo;
	bindatcmd "stopquest",strnpcinfo(0)+"::OnStopQuest";
	
	$RQ_Part2Mob = 0;
	for (; .@i < $RQ_Part2TotalMobs ; .@i++) // respawn part 2 monsters if any left to kill
		if (getd("$RQ_Part2Mob"+.@i+"HP")) { // mob not dead on reload
			$RQ_Part2Mob++; // in case a monster died and a reloadscript occured before the 5 seconds delay (the monster is respawned and so the amount of mob needs to be edited)
			monster .questmap$,0,0,getd("$RQ_Part2Mob"+.@i+"Name$"),getd("$RQ_Part2Mob"+.@i+"ID"),1,strnpcinfo(0)+"::OnMobKilled";
			setd "$RQ_Part2Mob"+.@i+"GID" , $@mobid;
			setunitdata $@mobid,UMOB_HP,getd("$RQ_Part2Mob"+.@i+"HP"); // respawn with previous HP
			initnpctimer;
		}


	addrid(1);
OnPCLoadMapEvent:
	if (strcharinfo(3) == .map$ && !$RQ_PartyId) { // shows players who have met the requirements a quest icon on the minimap and above the npc (only party leaders)
		if (getpartyleader(getcharid(1),1) == getcharid(3)) {
			getpartymember getcharid(1),1 ; getpartymember getcharid(1),2;
			for (; .@i < $@partymembercount ; .@i++)
				if (isloggedin($@partymemberaid[.@i]))
					if ((.@x = getvar(BaseLevel,$@partymembercid[.@i])) >= .MinLevel) .@n++;
			if (.@n >= .PlayersRequired) showevent QTYPE_QUEST,2;
		}
	}
	if (strcharinfo(3) == .questmap$ && getcharid(1) == $RQ_PartyId) .InactiveTime = 0;
	end;

function	SetColor	{ // Setcolor("<message>",<amount>,<amount to 100%>);
	.@pos = getstrlen(getarg(0))*getarg(1)/getarg(2);
	return "^00ff00"+substr(getarg(0),0,.@pos-1)+"^000000^ff0000"+substr(getarg(0),.@pos,getstrlen(getarg(0))-1)+"^000000";
}

function	EraseRQuest	{ // EraseRQuest();
	killmonster .questmap$,strnpcinfo(0)+"::OnMobKilled";
	for (; .@i < $RQ_Part2TotalMobs ; .@i++) { setd "$RQ_Part2Mob"+.@i+"HP" , 0 ; setd "$RQ_Part2Mob"+.@i+"GID" , 0 ; setd "$RQ_Part2Mob"+.@i+"ID" , 0 ; setd "$RQ_Part2Mob"+.@i+"Name$" , ""; }
	$RQ_PartyId = 0 ; $RQ_Part1Complete = 0 ; $RQ_Part1Talked = 0 ; $RQ_Part2TotalMobs = 0 ; $RQ_Part2Mob = 0 ; .InactiveTime = 0;
	$RQ_ResetTime = gettimetick(2) + .questdelay;
	stopnpctimer;
	sleep 3000;
	.@hours = .questdelay / (60*60) ; .@min = (.questdelay - (.@hours*60*60)) / 60 ; .@sec = .questdelay - (.@hours*60*60) - (.@min*60);
	if (.@hours) announce "The "+strnpcinfo(0)+" quest will be available again in "+.@hours+" hour"+(.@hours>1?"s":"")+(.@min?" "+.@min+" minute"+(.@min>1?"s":""):"")+(.@sec?" "+.@sec+" second"+(.@sec>1?"s":""):""),bc_all,.AnnounceColor;
	else if (.@min) announce "The "+strnpcinfo(0)+" quest will be available again in "+.@min+" minute"+(.@min>1?"s":"")+(.@sec?" "+.@sec+" second"+(.@sec>1?"s":""):""),bc_all,.AnnounceColor;
	else announce "The "+strnpcinfo(0)+" quest will be available again in "+.@sec+" second"+(.@sec>1?"s":""),bc_all,.AnnounceColor;
	return;
}

function	PrintMes	{ // PrintMes(<part number>,"<npc name>");
	if (getarg(0) == 1) { // messages about the quest when its not started (I was not inspired, you'll have to edit that one ^^)
		mes getarg(1),"part 1.." ; next;
		mes getarg(1),"part 2.." ; next;
		mes getarg(1),"part 3.." ; next;
		mes getarg(1),"..." ; next;
	}
	if (getarg(0) == 2) { // messages shown upon completion of first part (this is only a sample, feel free to edit it)
		mes getarg(1),"Thank god, you made it this far already!" ; next;
		mes getarg(1),"But the Realms are still far from safe..","The Realm Keepers are getting closer to Pallene as we speak." ; next;
		mes getarg(1),"Please defeat the Realm Keepers before they reach Pallene!!" ; next;
	}
	return;
}

} 

So where should I start  /hmm

Ah i know, the initialisation, that's probably what you'd look at first ^^

OnInit:
	.map$ = strnpcinfo(4); // if your npc is on a different map than the mobs in part 1, change '.map$' to the map those monsters are
	.questmap$ = "pal_dun02" ; .x = 49 ; .y = 6; // map, x and y where the players are warped on part 2 quest, also the map in which the part 2 monsters are spawned
	.PlayersRequired = 2; // amount of players required to begin the quest
	.MinLevel = 150; // minimum level required for each player in the party in order to do the quest
	.questdelay = 2*60*60; // delay (s) before any party is allowed to do the quest again 

	setarray .MobsPart1 , 1401,80 , 2019,20; // mobs to kill in part 1
	// setarray .MobsPart1 , <mob id>,<amount>{ , <mob id>,<amount>{ , <mob id>,<amount>{..}}};
	setarray .MobsPart2 , 1708,1 , 1039,1 , 1917,1; // mobs to kill in part 2
	// setarray .MobsPart2 , <mob id>,<amount>{ , <mob id>,<amount>{ , <mob id>,<amount>{..}}};
	setarray .MobsPart2Name$ , "Azthor" , "Othar" , "Kalnor"; // mob names in part 2 (don't put too long names or they won't be fully displayed)
	// setarray .MobsPart2Name$ , <mob 1 name>{ , <mob 2 name>,{ , <mob i3 name>{..}}};

	setarray .rewards , 7227,50; // rewards for every player in the party
	// setarray .rewards , <item id>,<amount>{ , <item id>,<amount>{ , <item id>,<amount>{..}}};
	.ZenyReward = 0; // zeny reward for every player in the party
	setarray .PartyLeaderBonusRewards , 7227,50 , 512,1; // party leader bonus rewards (added to those above)
	// setarray .PartyLeaderBonusRewards , <item id>,<amount>{ , <item id>,<amount>{ , <item id>,<amount>{..}}};
	.PartyLeaderBonusZenyReward = 0; // party leader zeny bonus reward (added to the amount above)
	
	setarray .HelpItems , 608,10; // items given to players to help them in part 2
	// setarray .HelpItems , <item id>,<amount>{ , <item id>,<amount>{ , <item id>,<amount>{..}}};

	.AnnounceColor = 0x00ff00; // color of announces relative to the quest

Set to your liking, I never put as many comments in a script before so that should be self-explanatory ^^

 

You also have to edit this part, I wasn't quite inspired..

function	PrintMes	{ // PrintMes(<part number>,"<npc name>");
	if (getarg(0) == 1) { // messages about the quest when its not started (I was not inspired, you'll have to edit that one ^^)
		mes getarg(1),"part 1.." ; next;
		mes getarg(1),"part 2.." ; next;
		mes getarg(1),"part 3.." ; next;
		mes getarg(1),"..." ; next;
	}
	if (getarg(0) == 2) { // messages shown upon completion of first part (this is only a sample, feel free to edit it)
		mes getarg(1),"Thank god, you made it this far already!" ; next;
		mes getarg(1),"But the Realms are still far from safe..","The Realm Keepers are getting closer to Pallene as we speak." ; next;
		mes getarg(1),"Please defeat the Realm Keepers before they reach Pallene!!" ; next;
	}
	return;
}

Run it once, you'll quicly know what to fill in these

 

So basically players have to kill x and y mobs to get over with part 1, then they're warped to pal_dun02 with 10 ygg seed (can change this in init) and they have to kill the 3 keppers to validate the quest. There's a delay of 2 hours (can change) for every party. They need to be x at minimum level y to accept the quest but there's no further checking of that (I though that if someone disconnects during part 2, that'd not be nice to delete the quest). Upon completion they gain rewards with special party leader rewards (zeny also).

 

Here are a bit of important infos:

  • I put item link, so if your client doesn't support them tell me I'll remove them
  • There is no time limit for the quest, players can abandon it by typing '@stopquest' and it's automatically erased if they're inactive for too long (I still can add a time limit if you want but I'm not a big fan of this because if you need just 5 more minutes to complete the quest you'd feel depressed). The inactive time limit is 10 minutes (warning at 5)
  • Only the party leader can proceed the quests parts, if he's logged out the quest is erased. Also if the party is deleted
  • Only valid members (above level restriction) get rewards and are noticed about the quest. You can add/remove members anytime when doing the quest, every valid member will get rewards.
  • The script is made to run indepandently of reloadscripts, you can reload anytime, you'll still be at the same point of the quest (also MVPs are spawned back with the health they had before the reloadscript). Some global variables are used but they're reseted when the quest is completed (or erased)
    Just one thing regarding this: if you ever change the '.MobsPart2' array, make sure no one is doing the second part of the quest before reloading 

Since you seemed like wanting to learn, I also put a lot of comments everywhere, that should help you understand the way I did it.

 

I tested (almost :P) everything and it seems to work fine, let me know if anything doesn't.

 

Don't hesitate to ask anything else, hope you'll like it! (even though that took longer than expected ^^)

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  30
  • Topics Per Day:  0.01
  • Content Count:  64
  • Reputation:   0
  • Joined:  02/23/14
  • Last Seen:  

Daaamnn  this script is awsome ^^   i tested it now the first part though..  it works even the abandon quest thing

 

My  client doesnt seem to support the itemlink though...  so have to get rid of that i geuss ^^

 

but dude really this with all the comments is very big help for me ^^

 

 

i totally love it!

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  31
  • Topics Per Day:  0.01
  • Content Count:  283
  • Reputation:   31
  • Joined:  07/08/14
  • Last Seen:  

Glad you like it  /no1

 

What's your exe date?

Edited by Kurofly
Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  30
  • Topics Per Day:  0.01
  • Content Count:  64
  • Reputation:   0
  • Joined:  02/23/14
  • Last Seen:  

Hello kurofly

 

sorry for the late response i was on a small vacantion so...

 

 

well i just came back tested the quest full it works awsome..

 

i tryed to get rid of the itemlink but somehow it doenst count down the mobs killed part 1 anymore..

 

so im hoping you can find an solution for this with me :)

 

we are using client date 

 

Wednesday, July 6, 2016, 3:14:40 PM

Lite Installer : 2012-04-10aRagexe / 2013-08-07aRagexe

 

this is according to my mate who runs the server the client date

 

 

EDITE:

 

i waited to see what happends if i stay inactive but instead of sayin the partyname when this happends it just says Null..

 

(second screenshot )

and it keeps spamming over and over.... 

 

 

see screenshot added 

 

 

 

Another EDIT:

 

this happended after he left my party while we already abondened the quest because of inactivity i geuss somehow the quest doesnt end itself after inactivity 

 

 

post-24283-0-34486000-1469120920_thumb.png

post-24283-0-78240600-1469122087_thumb.png

Edited by DutchDuck
Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  31
  • Topics Per Day:  0.01
  • Content Count:  283
  • Reputation:   31
  • Joined:  07/08/14
  • Last Seen:  

Hey there

 

Are you trying the quest with two characters of the same account?

 

If that's the case, that should solve it (don't really know though ^^)

pal_dun01,70,336,4	script	Realm Defender	54,{ function ItemLink ; function PrintMes ; function SetColor ; function EraseRQuest;

	.@name$ = "[^990000"+strnpcinfo(0)+"^000000]";

	if (!$RQ_PartyId || $RQ_PartyId != getcharid(1)) { // no party doing the quest or player not in it
		.@loop = 1;
		while (.@loop) { // used to loop the menu whithout goto commands (in case the player wants to see the details of the quest, he'll be brought back here after)
		// quest availability
			mes .@name$,"Quest status : "+((gettimetick(2)<$RQ_ResetTime || $RQ_PartyId)?"^ff0000unavailable":"^00ff00available")+"^000000";
			if ($RQ_PartyId) mes "Party ^cc3300"+getpartyname($RQ_PartyId)+"^000000 is currently doing the quest"; // $RQ_PartyId var is set to the id of the party doing the quest, $RQ_PartyId != 0 => party doing the quest
			else if ((.@delay = $RQ_ResetTime-gettimetick(2)) > 0) { // display time left ($RQ_ResetTime is set to gettimetick(2) + .questdelay upon completion of part 2)
				.@hours = .@delay / (60*60) ; .@min = (.@delay - (.@hours*60*60)) / 60 ; .@sec = .@delay - (.@hours*60*60) - (.@min*60);
				if (.@hours) mes "Delay : "+.@hours+" hour"+(.@hours>1?"s":"")+" "+.@min+" minute"+(.@min>1?"s":"")+" "+.@sec+" second"+(.@sec>1?"s":"");
				else if (.@min) mes "Delay : "+.@min+" minute"+(.@min>1?"s":"")+" "+.@sec+" second"+(.@sec>1?"s":"");
				else mes "Delay : "+.@sec+" second"+(.@sec>1?"s":"");
			}
		// rewards infos
			mes "Reward"+(((getarraysize(.rewards)>2)+(.ZenyReward?1:0))?"s :":" :");
			for (.@i = 0 ; .@i < getarraysize(.rewards) ; .@i+=2)
				mes " ~ "+.rewards[.@i+1]+" "+ItemLink(.rewards[.@i]);
			if (.ZenyReward) mes " ~ ^ffcc00"+.ZenyReward+"^000000 zeny";
			mes "Party leader reward"+(((getarraysize(.PartyLeaderBonusRewards)>2)+(.PartyLeaderBonusZenyReward?1:0))?"s":"")+" (added to the one"+(((getarraysize(.rewards)>2)+(.ZenyReward?1:0))?"s":"")+" above) :";
			for (.@j = 0 ; .@j < getarraysize(.PartyLeaderBonusRewards) ; .@j+=2)
				mes " ~ "+.PartyLeaderBonusRewards[.@j+1]+" "+ItemLink(.PartyLeaderBonusRewards[.@j]);
			if (.PartyLeaderBonusZenyReward) mes " ~ ^ffcc00"+.PartyLeaderBonusZenyReward+"^000000 zeny";
		// requirements
			mes "Requirements :";
			getpartymember getcharid(1),1 ; getpartymember getcharid(1),2 ; .@n = 0;
			for (.@k = 0 ; .@k < $@partymembercount ; .@k++)
				if (isloggedin($@partymemberaid[.@k],$@partymembercid[.@k]))
					if ((.@x = getvar(BaseLevel,$@partymembercid[.@k])) >= .MinLevel) .@n++; // party member logged and has the required level
			mes " - "+(.@n<.PlayersRequired?"^ff0000":"^00ff00")+"Party of at least "+.PlayersRequired+" level "+.MinLevel+" member"+(.PlayersRequired>1?"s":"")+"^000000";
			mes " - "+(getpartyleader(getcharid(1),1) == getcharid(3)?"^00ff00":"^ff0000")+"You need to be the party leader^000000";
			.@can = 1;
			if (.@delay > 0 || .@n < .PlayersRequired || getpartyleader(getcharid(1),1) != getcharid(3)) { // quest delay, not enough valid members or player isn't the party leader
				.@can = 0; // shorter way to check all the requirements above
				if (select("View details:Leave") == 2) close;
				next;
				PrintMes(1,strnpcinfo(0)); // you can edit the dialogues in this function at the bottom of the script, I bet it'll be easier for you
				if (select("Go back to menu:Leave") == 2) close;
			}
			if (.@can) {
				next;
				if ((.@select = select("Proceed:View details:Leave")) == 3) close;
				if (.@select == 2) {
					PrintMes(1,strnpcinfo(0)); // you can edit the dialogues in this function at the bottom of the script, I bet it'll be easier for you
					if (select("Go back to menu:Leave") == 2) close;
				}
				if (.@select == 1) .@loop = 0; // selected proceed, loop break
			}
		}
	// quest proceeding
		if ($RQ_PartyId) { mes .@name$,"Arg, someone accepted the quest before you ><" ; close; } // in case someone accepts the quest while the player is in the menu
		getpartymember getcharid(1),1 ; getpartymember getcharid(1),2 ; .@n = 0 ; deletearray .PartyAnnounceMember,128;
		for (.@k = 0 ; .@k < $@partymembercount ; .@k++)
			if (isloggedin($@partymemberaid[.@k],$@partymembercid[.@k]))
				if ((.@x = getvar(BaseLevel,$@partymembercid[.@k])) >= .MinLevel) { .@n++ ; setarray .PartyAnnounceMember[getarraysize(.PartyAnnounceMember)] , $@partymemberaid[.@k]; } // keeps a trace of the players who will have to receive the first announces
		if (.@n < .PlayersRequired) { mes .@name$,"Arg, someone disconnected and you don't have enough valid members anymore ><" ; close; } // in case a valid member disconnects meanwhile
		$RQ_PartyId = getcharid(1) ; initnpctimer;
		for (; .@l < getarraysize(.MobsPart1) ; .@l+=2) setd "$RQ_PartyMob"+.MobsPart1[.@l]+"count" , 0; // resets monster kill counters
		announce "Party '"+getpartyname(getcharid(1))+"' accepted the "+strnpcinfo(0)+" quest, wish them good luck!",bc_all,.AnnounceColor;
		close2;
		sleep 5000;
		for (.@i = 0 ; .@i < getarraysize(.PartyAnnounceMember) ; .@i++) // broadcasts to every valid party member (since there's actually no partyannounce command)
			if (attachrid(.PartyAnnounceMember[.@i])) announce "["+strnpcinfo(0)+" Quest] : You sucessfully accepted the "+strnpcinfo(0)+" quest",bc_self,.AnnounceColor;
		sleep 5000;
		.@str$ = ""+.MobsPart1[1]+" "+strmobinfo(1,.MobsPart1); // this part ..
		for (.@m = 2 ; .@m < (getarraysize(.MobsPart1)-2) ; .@m+=2) .@str$ = .@str$ + ", "+.MobsPart1[.@m+1]+" "+strmobinfo(1,.MobsPart1[.@m]);
		.@str$ = .@str$ + " and "+.MobsPart1[.@m+1]+" "+strmobinfo(1,.MobsPart1[.@m]); // .. is used to fill all the monster-to-kill infos in one string so that we don't send multiple announces
		for (.@i = 0 ; .@i < getarraysize(.PartyAnnounceMember) ; .@i++)
			if (attachrid(.PartyAnnounceMember[.@i])) announce "["+strnpcinfo(0)+" Quest info] : You need to kill "+.@str$+" in order to complete the first part of the quest",bc_self,.AnnounceColor;
		sleep 5000;
		for (.@i = 0 ; .@i < getarraysize(.PartyAnnounceMember) ; .@i++)
			if (attachrid(.PartyAnnounceMember[.@i])) announce "["+strnpcinfo(0)+" Quest info] : Remember the party leader can abandon the quest any time by typing '@stopquest'!",bc_self,.AnnounceColor;
		end;
	}

	else if (!$RQ_Part1Complete || !$RQ_Part1Talked) { // part 1 incomplete or not proceeded
	// quest infos
		for (; .@i < getarraysize(.MobsPart1) ; .@i+=2) { .@amount = .@amount + getd("$RQ_PartyMob"+.MobsPart1[.@i]+"count") ; .@total = .@total + .MobsPart1[.@i+1]; }
		mes .@name$,"Quest status : [^0000ff"+(100*.@amount/.@total)+"% done^000000]";
		for (; .@j < getarraysize(.MobsPart1) ; .@j+=2) 
			mes " ~ "+SetColor("kill "+.MobsPart1[.@j+1]+" "+strmobinfo(1,.MobsPart1[.@j]),getd("$RQ_PartyMob"+.MobsPart1[.@j]+"count"),.MobsPart1[.@j+1]); // the 'SetColor' function adds a green and red color depending on the amount of mobs killed (ex: if you killed half of the monsters needed, half of the text will be in green and half in red)
		//the $RQ_Part1Complete variable is set to 1 in the OnNPCKillEvent label when all the monsters required are killed
		if (!$RQ_Part1Complete || getpartyleader($RQ_PartyId,1) != getcharid(3)) close; // player can't proceed if the quest is not completed or he's not the party leader
		next;
		if (select("Proceed:Leave") == 2) close;
		PrintMes(2,.@name$); // you can edit the dialogues in this function at the bottom of the script, I bet it'll be easier for you
		if (select("Go for part 2!:Not yet") == 2) close;
	// quest proceeding
		close2;
		$RQ_Part1Talked = 1;
		for (.@i = 0 ; .@i < getarraysize(.MobsPart1) ; .@i+=2) setd "$RQ_Part1Mob"+.MobsPart1[.@i]+"count" , 0;
		getpartymember getcharid(1),1 ; deletearray .PartyMember,128;
		for (; .@k < $@partymembercount ; .@k++) // gets valid players again in case someone was added to the party (it does not restrain players from warping if they don't have enough valid members because that'd be a pain for them after having done the first part..)
			if (attachrid($@partymemberaid[.@k]))
				if (BaseLevel >= .MinLevel) { setarray .PartyMember[getarraysize(.PartyMember)] , $@partymemberaid[.@k] ; announce "["+strnpcinfo(0)+" Quest] : You will be warped in 5 seconds..",bc_self,.AnnounceColor; }
		sleep 3000;
		for (; .@l < getarraysize(.PartyMember) ; .@l++) // broadcasts to every valid party member
			if (attachrid(.PartyMember[.@l])) { 
				announce "["+strnpcinfo(0)+" Quest] : I wish you a good luck!",bc_self,.AnnounceColor;
				for (.@k = 0 ; .@k < getarraysize(.HelpItems) ; .@k+=2) getitem .HelpItems[.@k],HelpItems[.@k+1];
			}
		sleep 2000;
		for (; .@m < getarraysize(.PartyMember) ; .@m++) // warps valid players to quest map
			if (attachrid(.PartyMember[.@m])) warp .questmap$,.x,.y;
		for (.@i = 0 ; .@i < getarraysize(.MobsPart2) ; .@i+=2) { // spawns part 2 monsters
			deletearray $@mobid,128;
			monster .questmap$,0,0,.MobsPart2Name$[.@i/2],.MobsPart2[.@i],.MobsPart2[.@i+1],strnpcinfo(0)+"::OnMobKilled";
			for (.@j = 0 ; .@j < getarraysize($@mobid) ; .@j++) { // keeps a trace of monster spawned infos, this way we'll be able to spawn them back on reloadscript (they're being spawned back with the amount of HP they had before the reload)
				setd "$RQ_Part2Mob"+$RQ_Part2Mob+"GID" , $@mobid[.@j];
				setd "$RQ_Part2Mob"+$RQ_Part2Mob+"ID" , .MobsPart2[.@i];
				setd "$RQ_Part2Mob"+$RQ_Part2Mob+"Name$" , .MobsPart2Name$[.@i/2];
				setd "$RQ_Part2Mob"+$RQ_Part2Mob+"HP" , strmobinfo(4,.MobsPart2[.@i]);
				$RQ_Part2Mob++; // used in the OnMobKilled label
				$RQ_Part2TotalMobs++; // used on reloadscript
			}
		}
		end;			
	}

	else if ($RQ_Part1Talked) { // part 2 proceeded (means either player died in part 2, warped out or was added to the party meanwhile)
		if (BaseLevel < .MinLevel) { mes .@name$,"You must be at least level "+.MinLevel+" to join the quest.." ; close; }
		mes .@name$,"Don't give up "+strcharinfo(0)+", I know you can make it!" ; next;
		if (select("go to "+.questmap$+":Leave") == 2) close;
		warp .questmap$,.x,.y;
		end;
	}

	else { // not supposed to happen, I just don't wanted to put an 'else' at the last part cause if it does happen it would warp the player to pal_dun02
		mes .@name$,"O_O ??"," ","Sorry but this part of the script is not supposed to trigger, could you contact your administrator please? ><";
		close;
	}

OnNPCKillEvent: // checks whether the part 1 quest is completed (also display infos)
	if (getcharid(1) == $RQ_PartyId && !$RQ_Part1Complete) {
		for (; .@i < getarraysize(.MobsPart1) ; .@i+=2)
			if (.MobsPart1[.@i] == killedrid && getd("$RQ_PartyMob"+killedrid+"count") < .MobsPart1[.@i+1]) {
				setd "$RQ_PartyMob"+killedrid+"count" , getd("$RQ_PartyMob"+killedrid+"count") + 1;
				getpartymember getcharid(1),1;
				for (.@j = 0 ; .@j < $@partymembercount ; .@j++) // broadcasts to every valid party member in the map
					if (attachrid($@partymemberaid[.@j]))
						if (strcharinfo(3) == .map$ && BaseLevel >= .MinLevel) announce "["+strnpcinfo(0)+" Quest] : "+getd("$RQ_PartyMob"+.MobsPart1[.@i]+"count")+"/"+.MobsPart1[.@i+1]+" "+strmobinfo(1,killedrid)+" killed",bc_self,.AnnounceColor;
				for (.@k = 0 ; .@k < getarraysize(.MobsPart1) ; .@k+=2)
					if (getd("$RQ_PartyMob"+.MobsPart1[.@k]+"count") < .MobsPart1[.@k+1]) { .@ko = 1 ; break; }
				if (!.@ko) { announce "Party '"+getpartyname(getcharid(1))+"' has finished the first part of the "+strnpcinfo(0)+" quest!",bc_all,.AnnounceColor ; $RQ_Part1Complete = 1; }
			}
	}
	end;

OnMobKilled: // checks whether the part 2 quest is completed (also display infos)
	$RQ_Part2Mob--;
	getpartymember getcharid(1),2;
	for (; .@i < $@partymembercount ; .@i++)// broadcasts to every valid party member
		if (attachrid($@partymemberaid[.@i]))
			if (BaseLevel >= .MinLevel) {
				if ($RQ_Part2Mob > 1) announce "["+strnpcinfo(0)+" Quest] : "+$RQ_Part2Mob+" Keepers left, keep going!",bc_self,.AnnounceColor;
				else if ($RQ_Part2Mob) announce "["+strnpcinfo(0)+" Quest] : only one Keeper left, you've almost done it!",bc_self,.AnnounceColor;
				else { // quest completed, giving rewards
					announce "["+strnpcinfo(0)+" Quest] : "+strnpcinfo(0)+" quest completed, congratulations! Here are your rewards!",bc_self,.AnnounceColor;
					for (.@j = 0; .@j < getarraysize(.rewards) ; .@j+=2) getitem .rewards[.@j],.rewards[.@j+1];
					Zeny += .ZenyReward;
					if (getpartyleader($RQ_PartyId,1) == $@partymemberaid[.@i]) { // party leader bonus rewards
						for (; .@k < getarraysize(.PartyLeaderBonusRewards) ; .@k+=2) getitem .PartyLeaderBonusRewards[.@k],.PartyLeaderBonusRewards[.@k+1];
						Zeny += .PartyLeaderBonusZenyReward;
					}
				}
			}
	if (!$RQ_Part2Mob) { // quest completed, reseting variables & setting delay
		sleep 3000 ; announce "Party '"+getpartyname($RQ_PartyId)+"' has helped keeping the Realms safe by completing the "+strnpcinfo(0)+" quest! Congratulations!",bc_all,.AnnounceColor ; sleep 3000;
		$RQ_PartyId = 0 ; $RQ_Part1Complete = 0 ; $RQ_Part1Talked = 0 ; $RQ_Part2TotalMobs = 0;
		$RQ_ResetTime = gettimetick(2) + .questdelay;
		stopnpctimer;
		.@hours = .questdelay / (60*60) ; .@min = (.questdelay - (.@hours*60*60)) / 60 ; .@sec = .questdelay - (.@hours*60*60) - (.@min*60);
		if (.@hours) announce "The "+strnpcinfo(0)+" quest will be available again in "+.@hours+" hour"+(.@hours>1?"s":"")+(.@min?" "+.@min+" minute"+(.@min>1?"s":""):"")+(.@sec?" "+.@sec+" second"+(.@sec>1?"s":""):""),bc_all,.AnnounceColor;
		else if (.@min) announce "The "+strnpcinfo(0)+" quest will be available again in "+.@min+" minute"+(.@min>1?"s":"")+(.@sec?" "+.@sec+" second"+(.@sec>1?"s":""):""),bc_all,.AnnounceColor;
		else announce "The "+strnpcinfo(0)+" quest will be available again in "+.@sec+" second"+(.@sec>1?"s":""),bc_all,.AnnounceColor;
	}
	end;

OnTimer5000:
	getpartymember $RQ_PartyId,2;
	if (!$@partymembercount) { // party deleted
		announce "["+strnpcinfo(0)+" Quest Info] : Party '"+getpartyname($RQ_PartyId)+"' has been deleted and the quest has been erased!",bc_all,.AnnounceColor;
		EraseRQuest();
	}

	.InactiveTime+=5;

	if (!$RQ_Part1Talked) { // part 1 inactivity check
		for (; .@i < getarraysize(.MobsPart1) ; .@i++) {
			if (getd("$RQ_PartyMob"+.MobsPart1[.@i]+"count") != getd(".PreviousCount"+.@i)) .InactiveTime = 0;
			setd ".PreviousCount"+.@i , getd("$RQ_PartyMob"+.MobsPart1[.@i]+"count");
		}
	}
	else { // part 2 inactivity check (+ checking when loading map with the 'OnPCLoadMapEvent' label below)
		addrid(0);
		if (.questmap$ == strcharinfo(3) && $RQ_PartyId == getcharid(1)) .InactiveTime = 0;
		detachrid;
	}

	if (.InactiveTime == 300) { // shows warning after being inactive for 5 minutes
		getpartymember $RQ_PartyId,2;
		for (.@i = 0 ; .@i < $@partymembercount ; .@i++)
			if (attachrid($@partymemberaid[.@i])) 
				if (BaseLevel >= .MinLevel) announce "["+strnpcinfo(0)+" Quest Info] : Your party has been inactive for 5 minutes.",bc_self,.AnnounceColor;
		sleep 3000;
		for (.@i = 0 ; .@i < $@partymembercount ; .@i++)
			if (attachrid($@partymemberaid[.@i])) 
				if (BaseLevel >= .MinLevel) announce "["+strnpcinfo(0)+" Quest Info] : If your are still inactive after 5 more minutes, the quest will be erased.",bc_self,.AnnounceColor;
		sleep 3000;
		for (.@i = 0 ; .@i < $@partymembercount ; .@i++)
			if (attachrid($@partymemberaid[.@i])) 
				if (BaseLevel >= .MinLevel) announce "["+strnpcinfo(0)+" Quest Info] : Remember the party leader can type '@stopquest' to abandon the quest.",bc_self,.AnnounceColor;
	}
	if (.InactiveTime >= 600) { // erases quest after being inactive for 10 minutes
		announce "["+strnpcinfo(0)+" Quest Info] : Party '"+getpartyname($RQ_PartyId)+"' has been inactive for 10 minutes and the quest has been erased!",bc_all,.AnnounceColor;
		EraseRQuest();
	}
	

	for (.@i = 0 ; .@i < $RQ_Part2TotalMobs ; .@i++) // update part 2 monsters HP in case of a reloadscript
		if (getd("$RQ_Part2Mob"+.@i+"HP")) { // just to avoid getting warnings every 5 seconds
			deletearray .@data,128;
			getunitdata getd("$RQ_Part2Mob"+.@i+"GID"),.@data; // it will return a warning if it can't find the mob, don't worry that's normal (even though that's boring..)
			setd "$RQ_Part2Mob"+.@i+"HP" , .@data[UMOB_HP];
			if (!.@data[UMOB_HP]) { setd "$RQ_Part2Mob"+.@i+"GID" , 0 ; setd "$RQ_Part2Mob"+.@i+"ID" , 0 ; setd "$RQ_Part2Mob"+.@i+"Name$" , ""; }
		}
	if ($RQ_PartyId) initnpctimer;
	end;

OnPCLogoutEvent:
	if (getpartyleader($RQ_PartyId,1) == getcharid(3)) {
		announce "["+strnpcinfo(0)+" Quest Info] : Party leader of party '"+getpartyname($RQ_PartyId)+"' has logged out!",bc_all,.AnnounceColor;
		EraseRQuest();	
	}
	end;

OnStopQuest:
	if ($RQ_PartyId != getcharid(1)) end;
	if (getpartyleader($RQ_PartyId,1) != getcharid(3)) { dispbottom "["+strnpcinfo(0)+" Quest Info] : Only the part leader can decide to stop the quest." ; end; }
	announce "["+strnpcinfo(0)+" Quest Info] : Party leader of party '"+getpartyname($RQ_PartyId)+"' has abandonned the quest!",bc_all,.AnnounceColor;
	EraseRQuest();
	end;

OnInterIfInit: // deletes all quest data upon map server connection
	query_sql("DELETE FROM `mapreg` WHERE SUBSTR(`varname`,1,4) = '$RQ_'",.@dub);
	end;

OnInit:
	.map$ = strnpcinfo(4); // if your npc is on a different map than the mobs in part 1, change '.map$' to the map those monsters are
	.questmap$ = "pal_dun02" ; .x = 49 ; .y = 6; // map, x and y where the players are warped on part 2 quest, also the map in which the part 2 monsters are spawned
	.PlayersRequired = 2; // amount of players required to begin the quest
	.MinLevel = 150; // minimum level required for each player in the party in order to do the quest
	.questdelay = 2*60*60; // delay (s) before any party is allowed to do the quest again 

	setarray .MobsPart1 , 1401,80 , 2019,20; // mobs to kill in part 1
	// setarray .MobsPart1 , <mob id>,<amount>{ , <mob id>,<amount>{ , <mob id>,<amount>{..}}};
	setarray .MobsPart2 , 1708,1 , 1039,1 , 1917,1; // mobs to kill in part 2
	// setarray .MobsPart2 , <mob id>,<amount>{ , <mob id>,<amount>{ , <mob id>,<amount>{..}}};
	setarray .MobsPart2Name$ , "Azthor" , "Othar" , "Kalnor"; // mob names in part 2 (don't put too long names or they won't be fully displayed)
	// setarray .MobsPart2Name$ , <mob 1 name>{ , <mob 2 name>,{ , <mob i3 name>{..}}};

	setarray .rewards , 7227,50; // rewards for every player in the party
	// setarray .rewards , <item id>,<amount>{ , <item id>,<amount>{ , <item id>,<amount>{..}}};
	.ZenyReward = 0; // zeny reward for every player in the party
	setarray .PartyLeaderBonusRewards , 7227,50 , 512,1; // party leader bonus rewards (added to those above)
	// setarray .PartyLeaderBonusRewards , <item id>,<amount>{ , <item id>,<amount>{ , <item id>,<amount>{..}}};
	.PartyLeaderBonusZenyReward = 0; // party leader zeny bonus reward (added to the amount above)
	
	setarray .HelpItems , 608,10; // items given to players to help them in part 2
	// setarray .HelpItems , <item id>,<amount>{ , <item id>,<amount>{ , <item id>,<amount>{..}}};

	.AnnounceColor = 0x00ff00; // color of announces relative to the quest

	setmapflag .map$,mf_loadevent; // used for showing quest availability on the map
	setmapflag .questmap$,mf_loadevent; // used to check players inactivity in part 2
	setmapflag .questmap$,mf_nowarp;
	setmapflag .questmap$,mf_nogo;
	setmapflag .questmap$,mf_noteleport; // not sure you want that one though (disables fly wings)
	setmapflag .questmap$,mf_nomemo;
	bindatcmd "stopquest",strnpcinfo(0)+"::OnStopQuest";
	
	$RQ_Part2Mob = 0;
	for (; .@i < $RQ_Part2TotalMobs ; .@i++) // respawn part 2 monsters if any left to kill
		if (getd("$RQ_Part2Mob"+.@i+"HP")) { // mob not dead on reload
			$RQ_Part2Mob++; // in case a monster died and a reloadscript occured before the 5 seconds delay (the monster is respawned and so the amount of mob needs to be edited)
			monster .questmap$,0,0,getd("$RQ_Part2Mob"+.@i+"Name$"),getd("$RQ_Part2Mob"+.@i+"ID"),1,strnpcinfo(0)+"::OnMobKilled";
			setd "$RQ_Part2Mob"+.@i+"GID" , $@mobid;
			setunitdata $@mobid,UMOB_HP,getd("$RQ_Part2Mob"+.@i+"HP"); // respawn with previous HP
			initnpctimer;
		}


	addrid(1);
OnPCLoadMapEvent:
	if (strcharinfo(3) == .map$ && !$RQ_PartyId) { // shows players who have met the requirements a quest icon on the minimap and above the npc (only party leaders)
		if (getpartyleader(getcharid(1),1) == getcharid(3)) {
			getpartymember getcharid(1),1 ; getpartymember getcharid(1),2;
			for (; .@i < $@partymembercount ; .@i++)
				if (isloggedin($@partymemberaid[.@i],$@partymembercid[.@i]))
					if ((.@x = getvar(BaseLevel,$@partymembercid[.@i])) >= .MinLevel) .@n++;
			if (.@n >= .PlayersRequired) showevent QTYPE_QUEST,2;
		}
	}
	if (strcharinfo(3) == .questmap$ && getcharid(1) == $RQ_PartyId) .InactiveTime = 0;
	end;

function	ItemLink	{
	if (0) // turn to 1 to enable item link
		return "<ITEMLINK>"+getitemname(getarg(0))+"<INFO>"+getarg(0)+"</INFO></ITEMLINK>";
	else return "^0099ff"+getitemname(getarg(0))+"^000000";
}

function	SetColor	{ // Setcolor("<message>",<amount>,<amount to 100%>);
	.@pos = getstrlen(getarg(0))*getarg(1)/getarg(2);
	return "^00ff00"+substr(getarg(0),0,.@pos-1)+"^000000^ff0000"+substr(getarg(0),.@pos,getstrlen(getarg(0))-1)+"^000000";
}

function	EraseRQuest	{ // EraseRQuest();
	killmonster .questmap$,strnpcinfo(0)+"::OnMobKilled";
	for (; .@i < $RQ_Part2TotalMobs ; .@i++) { setd "$RQ_Part2Mob"+.@i+"HP" , 0 ; setd "$RQ_Part2Mob"+.@i+"GID" , 0 ; setd "$RQ_Part2Mob"+.@i+"ID" , 0 ; setd "$RQ_Part2Mob"+.@i+"Name$" , ""; }
	$RQ_PartyId = 0 ; $RQ_Part1Complete = 0 ; $RQ_Part1Talked = 0 ; $RQ_Part2TotalMobs = 0 ; $RQ_Part2Mob = 0 ; .InactiveTime = 0;
	$RQ_ResetTime = gettimetick(2) + .questdelay;
	stopnpctimer;
	sleep 3000;
	.@hours = .questdelay / (60*60) ; .@min = (.questdelay - (.@hours*60*60)) / 60 ; .@sec = .questdelay - (.@hours*60*60) - (.@min*60);
	if (.@hours) announce "The "+strnpcinfo(0)+" quest will be available again in "+.@hours+" hour"+(.@hours>1?"s":"")+(.@min?" "+.@min+" minute"+(.@min>1?"s":""):"")+(.@sec?" "+.@sec+" second"+(.@sec>1?"s":""):""),bc_all,.AnnounceColor;
	else if (.@min) announce "The "+strnpcinfo(0)+" quest will be available again in "+.@min+" minute"+(.@min>1?"s":"")+(.@sec?" "+.@sec+" second"+(.@sec>1?"s":""):""),bc_all,.AnnounceColor;
	else announce "The "+strnpcinfo(0)+" quest will be available again in "+.@sec+" second"+(.@sec>1?"s":""),bc_all,.AnnounceColor;
	return;
}

function	PrintMes	{ // PrintMes(<part number>,"<npc name>");
	if (getarg(0) == 1) { // messages about the quest when its not started (I was not inspired, you'll have to edit that one ^^)
		mes getarg(1),"part 1.." ; next;
		mes getarg(1),"part 2.." ; next;
		mes getarg(1),"part 3.." ; next;
		mes getarg(1),"..." ; next;
	}
	if (getarg(0) == 2) { // messages shown upon completion of first part (this is only a sample, feel free to edit it)
		mes getarg(1),"Thank god, you made it this far already!" ; next;
		mes getarg(1),"But the Realms are still far from safe..","The Realm Keepers are getting closer to Pallene as we speak." ; next;
		mes getarg(1),"Please defeat the Realm Keepers before they reach Pallene!!" ; next;
	}
	return;
}

} 
Edited by Kurofly
Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  30
  • Topics Per Day:  0.01
  • Content Count:  64
  • Reputation:   0
  • Joined:  02/23/14
  • Last Seen:  

i tested it with my GM account And Legit account and another player then when we were inactive it started spamming..

so might it be a problem in here?
 

	if (!$RQ_Part1Talked) { // part 1 inactivity check
		for (; .@i < getarraysize(.MobsPart1) ; .@i++) {
			if (getd("$RQ_PartyMob"+.MobsPart1[.@i]+"count") != getd(".PreviousCount"+.@i)) .InactiveTime = 0;
			setd ".PreviousCount"+.@i , getd("$RQ_PartyMob"+.MobsPart1[.@i]+"count");
		}
	}
	else { // part 2 inactivity check (+ checking when loading map with the 'OnPCLoadMapEvent' label below)
		addrid(0);
		if (.questmap$ == strcharinfo(3) && $RQ_PartyId == getcharid(1)) .InactiveTime = 0;
		detachrid;
	}

	if (.InactiveTime == 300) { // shows warning after being inactive for 5 minutes
		getpartymember $RQ_PartyId,2;
		for (.@i = 0 ; .@i < $@partymembercount ; .@i++)
			if (attachrid($@partymemberaid[.@i])) 
				if (BaseLevel >= .MinLevel) announce "["+strnpcinfo(0)+" Quest Info] : Your party has been inactive for 5 minutes.",bc_self,.AnnounceColor;
		sleep 3000;
		for (.@i = 0 ; .@i < $@partymembercount ; .@i++)
			if (attachrid($@partymemberaid[.@i])) 
				if (BaseLevel >= .MinLevel) announce "["+strnpcinfo(0)+" Quest Info] : If your are still inactive after 5 more minutes, the quest will be erased.",bc_self,.AnnounceColor;
		sleep 3000;
		for (.@i = 0 ; .@i < $@partymembercount ; .@i++)
			if (attachrid($@partymemberaid[.@i])) 
				if (BaseLevel >= .MinLevel) announce "["+strnpcinfo(0)+" Quest Info] : Remember the party leader can type '@stopquest' to abandon the quest.",bc_self,.AnnounceColor;
	}
	if (.InactiveTime >= 600) { // erases quest after being inactive for 10 minutes
		announce "["+strnpcinfo(0)+" Quest Info] : Party '"+getpartyname($RQ_PartyId)+"' has been inactive for 10 minutes and the quest has been erased!",bc_all,.AnnounceColor;
		EraseRQuest();
	}

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  31
  • Topics Per Day:  0.01
  • Content Count:  283
  • Reputation:   31
  • Joined:  07/08/14
  • Last Seen:  

Oops, gave you the wong version ^^

pal_dun01,70,336,4	script	Realm Defender	54,{ function ItemLink ; function PrintMes ; function SetColor ; function EraseRQuest;

	.@name$ = "[^990000"+strnpcinfo(0)+"^000000]";

	if (!$RQ_PartyId || $RQ_PartyId != getcharid(1)) { // no party doing the quest or player not in it
		.@loop = 1;
		while (.@loop) { // used to loop the menu whithout goto commands (in case the player wants to see the details of the quest, he'll be brought back here after)
		// quest availability
			mes .@name$,"Quest status : "+((gettimetick(2)<$RQ_ResetTime || $RQ_PartyId)?"^ff0000unavailable":"^00ff00available")+"^000000";
			if ($RQ_PartyId) mes "Party ^cc3300"+getpartyname($RQ_PartyId)+"^000000 is currently doing the quest"; // $RQ_PartyId var is set to the id of the party doing the quest, $RQ_PartyId != 0 => party doing the quest
			else if ((.@delay = $RQ_ResetTime-gettimetick(2)) > 0) { // display time left ($RQ_ResetTime is set to gettimetick(2) + .questdelay upon completion of part 2)
				.@hours = .@delay / (60*60) ; .@min = (.@delay - (.@hours*60*60)) / 60 ; .@sec = .@delay - (.@hours*60*60) - (.@min*60);
				if (.@hours) mes "Delay : "+.@hours+" hour"+(.@hours>1?"s":"")+" "+.@min+" minute"+(.@min>1?"s":"")+" "+.@sec+" second"+(.@sec>1?"s":"");
				else if (.@min) mes "Delay : "+.@min+" minute"+(.@min>1?"s":"")+" "+.@sec+" second"+(.@sec>1?"s":"");
				else mes "Delay : "+.@sec+" second"+(.@sec>1?"s":"");
			}
		// rewards infos
			mes "Reward"+(((getarraysize(.rewards)>2)+(.ZenyReward?1:0))?"s :":" :");
			for (.@i = 0 ; .@i < getarraysize(.rewards) ; .@i+=2)
				mes " ~ "+.rewards[.@i+1]+" "+ItemLink(.rewards[.@i]);
			if (.ZenyReward) mes " ~ ^ffcc00"+.ZenyReward+"^000000 zeny";
			mes "Party leader reward"+(((getarraysize(.PartyLeaderBonusRewards)>2)+(.PartyLeaderBonusZenyReward?1:0))?"s":"")+" (added to the one"+(((getarraysize(.rewards)>2)+(.ZenyReward?1:0))?"s":"")+" above) :";
			for (.@j = 0 ; .@j < getarraysize(.PartyLeaderBonusRewards) ; .@j+=2)
				mes " ~ "+.PartyLeaderBonusRewards[.@j+1]+" "+ItemLink(.PartyLeaderBonusRewards[.@j]);
			if (.PartyLeaderBonusZenyReward) mes " ~ ^ffcc00"+.PartyLeaderBonusZenyReward+"^000000 zeny";
		// requirements
			mes "Requirements :";
			getpartymember getcharid(1),1 ; getpartymember getcharid(1),2 ; .@n = 0;
			for (.@k = 0 ; .@k < $@partymembercount ; .@k++)
				if (isloggedin($@partymemberaid[.@k],$@partymembercid[.@k]))
					if ((.@x = getvar(BaseLevel,$@partymembercid[.@k])) >= .MinLevel) .@n++; // party member logged and has the required level
			mes " - "+(.@n<.PlayersRequired?"^ff0000":"^00ff00")+"Party of at least "+.PlayersRequired+" level "+.MinLevel+" member"+(.PlayersRequired>1?"s":"")+"^000000";
			mes " - "+(getpartyleader(getcharid(1),1) == getcharid(3)?"^00ff00":"^ff0000")+"You need to be the party leader^000000";
			.@can = 1;
			if (.@delay > 0 || .@n < .PlayersRequired || getpartyleader(getcharid(1),1) != getcharid(3)) { // quest delay, not enough valid members or player isn't the party leader
				.@can = 0; // shorter way to check all the requirements above
				if (select("View details:Leave") == 2) close;
				next;
				PrintMes(1,strnpcinfo(0)); // you can edit the dialogues in this function at the bottom of the script, I bet it'll be easier for you
				if (select("Go back to menu:Leave") == 2) close;
			}
			if (.@can) {
				next;
				if ((.@select = select("Proceed:View details:Leave")) == 3) close;
				if (.@select == 2) {
					PrintMes(1,strnpcinfo(0)); // you can edit the dialogues in this function at the bottom of the script, I bet it'll be easier for you
					if (select("Go back to menu:Leave") == 2) close;
				}
				if (.@select == 1) .@loop = 0; // selected proceed, loop break
			}
		}
	// quest proceeding
		if ($RQ_PartyId) { mes .@name$,"Arg, someone accepted the quest before you ><" ; close; } // in case someone accepts the quest while the player is in the menu
		getpartymember getcharid(1),1 ; getpartymember getcharid(1),2 ; .@n = 0 ; deletearray .PartyAnnounceMember,128;
		for (.@k = 0 ; .@k < $@partymembercount ; .@k++)
			if (isloggedin($@partymemberaid[.@k],$@partymembercid[.@k]))
				if ((.@x = getvar(BaseLevel,$@partymembercid[.@k])) >= .MinLevel) { .@n++ ; setarray .PartyAnnounceMember[getarraysize(.PartyAnnounceMember)] , $@partymemberaid[.@k]; } // keeps a trace of the players who will have to receive the first announces
		if (.@n < .PlayersRequired) { mes .@name$,"Arg, someone disconnected and you don't have enough valid members anymore ><" ; close; } // in case a valid member disconnects meanwhile
		$RQ_PartyId = getcharid(1) ; initnpctimer;
		for (; .@l < getarraysize(.MobsPart1) ; .@l+=2) setd "$RQ_PartyMob"+.MobsPart1[.@l]+"count" , 0; // resets monster kill counters
		announce "Party '"+getpartyname(getcharid(1))+"' accepted the "+strnpcinfo(0)+" quest, wish them good luck!",bc_all,.AnnounceColor;
		close2;
		sleep 5000;
		for (.@i = 0 ; .@i < getarraysize(.PartyAnnounceMember) ; .@i++) // broadcasts to every valid party member (since there's actually no partyannounce command)
			if (attachrid(.PartyAnnounceMember[.@i])) announce "["+strnpcinfo(0)+" Quest] : You sucessfully accepted the "+strnpcinfo(0)+" quest",bc_self,.AnnounceColor;
		sleep 5000;
		.@str$ = ""+.MobsPart1[1]+" "+strmobinfo(1,.MobsPart1); // this part ..
		for (.@m = 2 ; .@m < (getarraysize(.MobsPart1)-2) ; .@m+=2) .@str$ = .@str$ + ", "+.MobsPart1[.@m+1]+" "+strmobinfo(1,.MobsPart1[.@m]);
		.@str$ = .@str$ + " and "+.MobsPart1[.@m+1]+" "+strmobinfo(1,.MobsPart1[.@m]); // .. is used to fill all the monster-to-kill infos in one string so that we don't send multiple announces
		for (.@i = 0 ; .@i < getarraysize(.PartyAnnounceMember) ; .@i++)
			if (attachrid(.PartyAnnounceMember[.@i])) announce "["+strnpcinfo(0)+" Quest info] : You need to kill "+.@str$+" in order to complete the first part of the quest",bc_self,.AnnounceColor;
		sleep 5000;
		for (.@i = 0 ; .@i < getarraysize(.PartyAnnounceMember) ; .@i++)
			if (attachrid(.PartyAnnounceMember[.@i])) announce "["+strnpcinfo(0)+" Quest info] : Remember the party leader can abandon the quest any time by typing '@stopquest'!",bc_self,.AnnounceColor;
		end;
	}

	else if (!$RQ_Part1Complete || !$RQ_Part1Talked) { // part 1 incomplete or not proceeded
	// quest infos
		for (; .@i < getarraysize(.MobsPart1) ; .@i+=2) { .@amount = .@amount + getd("$RQ_PartyMob"+.MobsPart1[.@i]+"count") ; .@total = .@total + .MobsPart1[.@i+1]; }
		mes .@name$,"Quest status : [^0000ff"+(100*.@amount/.@total)+"% done^000000]";
		for (; .@j < getarraysize(.MobsPart1) ; .@j+=2) 
			mes " ~ "+SetColor("kill "+.MobsPart1[.@j+1]+" "+strmobinfo(1,.MobsPart1[.@j]),getd("$RQ_PartyMob"+.MobsPart1[.@j]+"count"),.MobsPart1[.@j+1]); // the 'SetColor' function adds a green and red color depending on the amount of mobs killed (ex: if you killed half of the monsters needed, half of the text will be in green and half in red)
		//the $RQ_Part1Complete variable is set to 1 in the OnNPCKillEvent label when all the monsters required are killed
		if (!$RQ_Part1Complete || getpartyleader($RQ_PartyId,1) != getcharid(3)) close; // player can't proceed if the quest is not completed or he's not the party leader
		next;
		if (select("Proceed:Leave") == 2) close;
		PrintMes(2,.@name$); // you can edit the dialogues in this function at the bottom of the script, I bet it'll be easier for you
		if (select("Go for part 2!:Not yet") == 2) close;
	// quest proceeding
		close2;
		$RQ_Part1Talked = 1;
		for (.@i = 0 ; .@i < getarraysize(.MobsPart1) ; .@i+=2) setd "$RQ_Part1Mob"+.MobsPart1[.@i]+"count" , 0;
		getpartymember getcharid(1),1 ; deletearray .PartyMember,128;
		for (; .@k < $@partymembercount ; .@k++) // gets valid players again in case someone was added to the party (it does not restrain players from warping if they don't have enough valid members because that'd be a pain for them after having done the first part..)
			if (attachrid($@partymemberaid[.@k]))
				if (BaseLevel >= .MinLevel) { setarray .PartyMember[getarraysize(.PartyMember)] , $@partymemberaid[.@k] ; announce "["+strnpcinfo(0)+" Quest] : You will be warped in 5 seconds..",bc_self,.AnnounceColor; }
		sleep 3000;
		for (; .@l < getarraysize(.PartyMember) ; .@l++) // broadcasts to every valid party member
			if (attachrid(.PartyMember[.@l])) { 
				announce "["+strnpcinfo(0)+" Quest] : I wish you a good luck!",bc_self,.AnnounceColor;
				for (.@k = 0 ; .@k < getarraysize(.HelpItems) ; .@k+=2) getitem .HelpItems[.@k],HelpItems[.@k+1];
			}
		sleep 2000;
		for (; .@m < getarraysize(.PartyMember) ; .@m++) // warps valid players to quest map
			if (attachrid(.PartyMember[.@m])) warp .questmap$,.x,.y;
		for (.@i = 0 ; .@i < getarraysize(.MobsPart2) ; .@i+=2) { // spawns part 2 monsters
			deletearray $@mobid,128;
			monster .questmap$,0,0,.MobsPart2Name$[.@i/2],.MobsPart2[.@i],.MobsPart2[.@i+1],strnpcinfo(0)+"::OnMobKilled";
			for (.@j = 0 ; .@j < getarraysize($@mobid) ; .@j++) { // keeps a trace of monster spawned infos, this way we'll be able to spawn them back on reloadscript (they're being spawned back with the amount of HP they had before the reload)
				setd "$RQ_Part2Mob"+$RQ_Part2Mob+"GID" , $@mobid[.@j];
				setd "$RQ_Part2Mob"+$RQ_Part2Mob+"ID" , .MobsPart2[.@i];
				setd "$RQ_Part2Mob"+$RQ_Part2Mob+"Name$" , .MobsPart2Name$[.@i/2];
				setd "$RQ_Part2Mob"+$RQ_Part2Mob+"HP" , strmobinfo(4,.MobsPart2[.@i]);
				$RQ_Part2Mob++; // used in the OnMobKilled label
				$RQ_Part2TotalMobs++; // used on reloadscript
			}
		}
		end;			
	}

	else if ($RQ_Part1Talked) { // part 2 proceeded (means either player died in part 2, warped out or was added to the party meanwhile)
		if (BaseLevel < .MinLevel) { mes .@name$,"You must be at least level "+.MinLevel+" to join the quest.." ; close; }
		mes .@name$,"Don't give up "+strcharinfo(0)+", I know you can make it!" ; next;
		if (select("go to "+.questmap$+":Leave") == 2) close;
		warp .questmap$,.x,.y;
		end;
	}

	else { // not supposed to happen, I just don't wanted to put an 'else' at the last part cause if it does happen it would warp the player to pal_dun02
		mes .@name$,"O_O ??"," ","Sorry but this part of the script is not supposed to trigger, could you contact your administrator please? ><";
		close;
	}

OnNPCKillEvent: // checks whether the part 1 quest is completed (also display infos)
	if (getcharid(1) == $RQ_PartyId && !$RQ_Part1Complete) {
		for (; .@i < getarraysize(.MobsPart1) ; .@i+=2)
			if (.MobsPart1[.@i] == killedrid && getd("$RQ_PartyMob"+killedrid+"count") < .MobsPart1[.@i+1]) {
				setd "$RQ_PartyMob"+killedrid+"count" , getd("$RQ_PartyMob"+killedrid+"count") + 1;
				getpartymember getcharid(1),1;
				for (.@j = 0 ; .@j < $@partymembercount ; .@j++) // broadcasts to every valid party member in the map
					if (attachrid($@partymemberaid[.@j]))
						if (strcharinfo(3) == .map$ && BaseLevel >= .MinLevel) announce "["+strnpcinfo(0)+" Quest] : "+getd("$RQ_PartyMob"+.MobsPart1[.@i]+"count")+"/"+.MobsPart1[.@i+1]+" "+strmobinfo(1,killedrid)+" killed",bc_self,.AnnounceColor;
				for (.@k = 0 ; .@k < getarraysize(.MobsPart1) ; .@k+=2)
					if (getd("$RQ_PartyMob"+.MobsPart1[.@k]+"count") < .MobsPart1[.@k+1]) { .@ko = 1 ; break; }
				if (!.@ko) { announce "Party '"+getpartyname(getcharid(1))+"' has finished the first part of the "+strnpcinfo(0)+" quest!",bc_all,.AnnounceColor ; $RQ_Part1Complete = 1; }
			}
	}
	end;

OnMobKilled: // checks whether the part 2 quest is completed (also display infos)
	$RQ_Part2Mob--;
	getpartymember getcharid(1),2;
	for (; .@i < $@partymembercount ; .@i++)// broadcasts to every valid party member
		if (attachrid($@partymemberaid[.@i]))
			if (BaseLevel >= .MinLevel) {
				if ($RQ_Part2Mob > 1) announce "["+strnpcinfo(0)+" Quest] : "+$RQ_Part2Mob+" Keepers left, keep going!",bc_self,.AnnounceColor;
				else if ($RQ_Part2Mob) announce "["+strnpcinfo(0)+" Quest] : only one Keeper left, you've almost done it!",bc_self,.AnnounceColor;
				else { // quest completed, giving rewards
					announce "["+strnpcinfo(0)+" Quest] : "+strnpcinfo(0)+" quest completed, congratulations! Here are your rewards!",bc_self,.AnnounceColor;
					for (.@j = 0; .@j < getarraysize(.rewards) ; .@j+=2) getitem .rewards[.@j],.rewards[.@j+1];
					Zeny += .ZenyReward;
					if (getpartyleader($RQ_PartyId,1) == $@partymemberaid[.@i]) { // party leader bonus rewards
						for (; .@k < getarraysize(.PartyLeaderBonusRewards) ; .@k+=2) getitem .PartyLeaderBonusRewards[.@k],.PartyLeaderBonusRewards[.@k+1];
						Zeny += .PartyLeaderBonusZenyReward;
					}
				}
			}
	if (!$RQ_Part2Mob) { // quest completed, reseting variables & setting delay
		sleep 3000 ; announce "Party '"+getpartyname($RQ_PartyId)+"' has helped keeping the Realms safe by completing the "+strnpcinfo(0)+" quest! Congratulations!",bc_all,.AnnounceColor ; sleep 3000;
		$RQ_PartyId = 0 ; $RQ_Part1Complete = 0 ; $RQ_Part1Talked = 0 ; $RQ_Part2TotalMobs = 0;
		$RQ_ResetTime = gettimetick(2) + .questdelay;
		stopnpctimer;
		.@hours = .questdelay / (60*60) ; .@min = (.questdelay - (.@hours*60*60)) / 60 ; .@sec = .questdelay - (.@hours*60*60) - (.@min*60);
		if (.@hours) announce "The "+strnpcinfo(0)+" quest will be available again in "+.@hours+" hour"+(.@hours>1?"s":"")+(.@min?" "+.@min+" minute"+(.@min>1?"s":""):"")+(.@sec?" "+.@sec+" second"+(.@sec>1?"s":""):""),bc_all,.AnnounceColor;
		else if (.@min) announce "The "+strnpcinfo(0)+" quest will be available again in "+.@min+" minute"+(.@min>1?"s":"")+(.@sec?" "+.@sec+" second"+(.@sec>1?"s":""):""),bc_all,.AnnounceColor;
		else announce "The "+strnpcinfo(0)+" quest will be available again in "+.@sec+" second"+(.@sec>1?"s":""),bc_all,.AnnounceColor;
	}
	end;

OnTimer5000:
	if (!$RQ_PartyId) end;
	getpartymember $RQ_PartyId,2;
	if (!$@partymembercount) { // party deleted
		announce "["+strnpcinfo(0)+" Quest Info] : Party '"+getpartyname($RQ_PartyId)+"' has been deleted and the quest has been erased!",bc_all,.AnnounceColor;
		EraseRQuest();
	}

	.InactiveTime+=5;

	if (!$RQ_Part1Talked) { // part 1 inactivity check
		for (; .@i < getarraysize(.MobsPart1) ; .@i++) {
			if (getd("$RQ_PartyMob"+.MobsPart1[.@i]+"count") != getd(".PreviousCount"+.@i)) .InactiveTime = 0;
			setd ".PreviousCount"+.@i , getd("$RQ_PartyMob"+.MobsPart1[.@i]+"count");
		}
	}
	else { // part 2 inactivity check (+ checking when loading map with the 'OnPCLoadMapEvent' label below)
		addrid(0);
		if (.questmap$ == strcharinfo(3) && $RQ_PartyId == getcharid(1)) .InactiveTime = 0;
		detachrid;
	}

	if (.InactiveTime == 300) { // shows warning after being inactive for 5 minutes
		getpartymember $RQ_PartyId,2;
		for (.@i = 0 ; .@i < $@partymembercount ; .@i++)
			if (attachrid($@partymemberaid[.@i])) 
				if (BaseLevel >= .MinLevel) announce "["+strnpcinfo(0)+" Quest Info] : Your party has been inactive for 5 minutes.",bc_self,.AnnounceColor;
		sleep 3000;
		for (.@i = 0 ; .@i < $@partymembercount ; .@i++)
			if (attachrid($@partymemberaid[.@i])) 
				if (BaseLevel >= .MinLevel) announce "["+strnpcinfo(0)+" Quest Info] : If your are still inactive after 5 more minutes, the quest will be erased.",bc_self,.AnnounceColor;
		sleep 3000;
		for (.@i = 0 ; .@i < $@partymembercount ; .@i++)
			if (attachrid($@partymemberaid[.@i])) 
				if (BaseLevel >= .MinLevel) announce "["+strnpcinfo(0)+" Quest Info] : Remember the party leader can type '@stopquest' to abandon the quest.",bc_self,.AnnounceColor;
	}
	if (.InactiveTime >= 600) { // erases quest after being inactive for 10 minutes
		announce "["+strnpcinfo(0)+" Quest Info] : Party '"+getpartyname($RQ_PartyId)+"' has been inactive for 10 minutes and the quest has been erased!",bc_all,.AnnounceColor;
		EraseRQuest();
	}
	

	for (.@i = 0 ; .@i < $RQ_Part2TotalMobs ; .@i++) // update part 2 monsters HP in case of a reloadscript
		if (getd("$RQ_Part2Mob"+.@i+"HP")) { // just to avoid getting warnings every 5 seconds
			deletearray .@data,128;
			getunitdata getd("$RQ_Part2Mob"+.@i+"GID"),.@data; // it will return a warning if it can't find the mob, don't worry that's normal (even though that's boring..)
			setd "$RQ_Part2Mob"+.@i+"HP" , .@data[UMOB_HP];
			if (!.@data[UMOB_HP]) { setd "$RQ_Part2Mob"+.@i+"GID" , 0 ; setd "$RQ_Part2Mob"+.@i+"ID" , 0 ; setd "$RQ_Part2Mob"+.@i+"Name$" , ""; }
		}
	if ($RQ_PartyId) initnpctimer;
	end;

OnPCLogoutEvent:
	if (getpartyleader($RQ_PartyId,1) == getcharid(3)) {
		announce "["+strnpcinfo(0)+" Quest Info] : Party leader of party '"+getpartyname($RQ_PartyId)+"' has logged out!",bc_all,.AnnounceColor;
		EraseRQuest();	
	}
	end;

OnStopQuest:
	if ($RQ_PartyId != getcharid(1)) end;
	if (getpartyleader($RQ_PartyId,1) != getcharid(3)) { dispbottom "["+strnpcinfo(0)+" Quest Info] : Only the part leader can decide to stop the quest." ; end; }
	announce "["+strnpcinfo(0)+" Quest Info] : Party leader of party '"+getpartyname($RQ_PartyId)+"' has abandonned the quest!",bc_all,.AnnounceColor;
	EraseRQuest();
	end;

OnInterIfInitOnce: // deletes all quest data upon map server connection
	query_sql("SELECT `varname` FROM `mapreg` WHERE SUBSTR(`varname`,1,4) = '$RQ_'",.@data$);
	for (; .@d < getarraysize(.@data$) ; .@d++) {
		if (charat(.@data$[.@d],getstrlen(.@data$[.@d])-1) != "$") setd .@data$[.@d] , 0;
		else setd .@data$[.@d] , "";
	}
	end;

OnInit:
	.map$ = strnpcinfo(4); // if your npc is on a different map than the mobs in part 1, change '.map$' to the map those monsters are
	.questmap$ = "pal_dun02" ; .x = 49 ; .y = 6; // map, x and y where the players are warped on part 2 quest, also the map in which the part 2 monsters are spawned
	.PlayersRequired = 2; // amount of players required to begin the quest
	.MinLevel = 150; // minimum level required for each player in the party in order to do the quest
	.questdelay = 2*60*60; // delay (s) before any party is allowed to do the quest again 

	setarray .MobsPart1 , 1401,80 , 2019,20; // mobs to kill in part 1
	// setarray .MobsPart1 , <mob id>,<amount>{ , <mob id>,<amount>{ , <mob id>,<amount>{..}}};
	setarray .MobsPart2 , 1708,1 , 1039,1 , 1917,1; // mobs to kill in part 2
	// setarray .MobsPart2 , <mob id>,<amount>{ , <mob id>,<amount>{ , <mob id>,<amount>{..}}};
	setarray .MobsPart2Name$ , "Azthor" , "Othar" , "Kalnor"; // mob names in part 2 (don't put too long names or they won't be fully displayed)
	// setarray .MobsPart2Name$ , <mob 1 name>{ , <mob 2 name>,{ , <mob i3 name>{..}}};

	setarray .rewards , 7227,50; // rewards for every player in the party
	// setarray .rewards , <item id>,<amount>{ , <item id>,<amount>{ , <item id>,<amount>{..}}};
	.ZenyReward = 0; // zeny reward for every player in the party
	setarray .PartyLeaderBonusRewards , 7227,50 , 512,1; // party leader bonus rewards (added to those above)
	// setarray .PartyLeaderBonusRewards , <item id>,<amount>{ , <item id>,<amount>{ , <item id>,<amount>{..}}};
	.PartyLeaderBonusZenyReward = 0; // party leader zeny bonus reward (added to the amount above)
	
	setarray .HelpItems , 608,10; // items given to players to help them in part 2
	// setarray .HelpItems , <item id>,<amount>{ , <item id>,<amount>{ , <item id>,<amount>{..}}};

	.AnnounceColor = 0x00ff00; // color of announces relative to the quest

	setmapflag .map$,mf_loadevent; // used for showing quest availability on the map
	setmapflag .questmap$,mf_loadevent; // used to check players inactivity in part 2
	setmapflag .questmap$,mf_nowarp;
	setmapflag .questmap$,mf_nogo;
	setmapflag .questmap$,mf_noteleport; // not sure you want that one though (disables fly wings)
	setmapflag .questmap$,mf_nomemo;
	bindatcmd "stopquest",strnpcinfo(0)+"::OnStopQuest";
	
	initnpctimer;
	
	$RQ_Part2Mob = 0;
	for (; .@i < $RQ_Part2TotalMobs ; .@i++) // respawn part 2 monsters if any left to kill
		if (getd("$RQ_Part2Mob"+.@i+"HP")) { // mob not dead on reload
			$RQ_Part2Mob++; // in case a monster died and a reloadscript occured before the 5 seconds delay (the monster is respawned and so the amount of mob needs to be edited)
			monster .questmap$,0,0,getd("$RQ_Part2Mob"+.@i+"Name$"),getd("$RQ_Part2Mob"+.@i+"ID"),1,strnpcinfo(0)+"::OnMobKilled";
			setd "$RQ_Part2Mob"+.@i+"GID" , $@mobid;
			setunitdata $@mobid,UMOB_HP,getd("$RQ_Part2Mob"+.@i+"HP"); // respawn with previous HP
			initnpctimer;
		}


	addrid(1);
OnPCLoadMapEvent:
	if (strcharinfo(3) == .map$ && !$RQ_PartyId) { // shows players who have met the requirements a quest icon on the minimap and above the npc (only party leaders)
		if (getpartyleader(getcharid(1),1) == getcharid(3)) {
			getpartymember getcharid(1),1 ; getpartymember getcharid(1),2;
			for (; .@i < $@partymembercount ; .@i++)
				if (isloggedin($@partymemberaid[.@i],$@partymembercid[.@i]))
					if ((.@x = getvar(BaseLevel,$@partymembercid[.@i])) >= .MinLevel) .@n++;
			if (.@n >= .PlayersRequired) showevent QTYPE_QUEST,2;
		}
	}
	if (strcharinfo(3) == .questmap$ && getcharid(1) == $RQ_PartyId) .InactiveTime = 0;
	end;

function	ItemLink	{
	if (0) // turn to 1 to enable item link
		return "<ITEMLINK>"+getitemname(getarg(0))+"<INFO>"+getarg(0)+"</INFO></ITEMLINK>";
	else return "^0099ff"+getitemname(getarg(0))+"^000000";
}

function	SetColor	{ // Setcolor("<message>",<amount>,<amount to 100%>);
	.@pos = getstrlen(getarg(0))*getarg(1)/getarg(2);
	return "^00ff00"+substr(getarg(0),0,.@pos-1)+"^000000^ff0000"+substr(getarg(0),.@pos,getstrlen(getarg(0))-1)+"^000000";
}

function	EraseRQuest	{ // EraseRQuest();
	killmonster .questmap$,strnpcinfo(0)+"::OnMobKilled";
	for (; .@i < $RQ_Part2TotalMobs ; .@i++) { setd "$RQ_Part2Mob"+.@i+"HP" , 0 ; setd "$RQ_Part2Mob"+.@i+"GID" , 0 ; setd "$RQ_Part2Mob"+.@i+"ID" , 0 ; setd "$RQ_Part2Mob"+.@i+"Name$" , ""; }
	$RQ_PartyId = 0 ; $RQ_Part1Complete = 0 ; $RQ_Part1Talked = 0 ; $RQ_Part2TotalMobs = 0 ; $RQ_Part2Mob = 0 ; .InactiveTime = 0;
	$RQ_ResetTime = gettimetick(2) + .questdelay;
	stopnpctimer;
	sleep 3000;
	.@hours = .questdelay / (60*60) ; .@min = (.questdelay - (.@hours*60*60)) / 60 ; .@sec = .questdelay - (.@hours*60*60) - (.@min*60);
	if (.@hours) announce "The "+strnpcinfo(0)+" quest will be available again in "+.@hours+" hour"+(.@hours>1?"s":"")+(.@min?" "+.@min+" minute"+(.@min>1?"s":""):"")+(.@sec?" "+.@sec+" second"+(.@sec>1?"s":""):""),bc_all,.AnnounceColor;
	else if (.@min) announce "The "+strnpcinfo(0)+" quest will be available again in "+.@min+" minute"+(.@min>1?"s":"")+(.@sec?" "+.@sec+" second"+(.@sec>1?"s":""):""),bc_all,.AnnounceColor;
	else announce "The "+strnpcinfo(0)+" quest will be available again in "+.@sec+" second"+(.@sec>1?"s":""),bc_all,.AnnounceColor;
	return;
}

function	PrintMes	{ // PrintMes(<part number>,"<npc name>");
	if (getarg(0) == 1) { // messages about the quest when its not started (I was not inspired, you'll have to edit that one ^^)
		mes getarg(1),"part 1.." ; next;
		mes getarg(1),"part 2.." ; next;
		mes getarg(1),"part 3.." ; next;
		mes getarg(1),"..." ; next;
	}
	if (getarg(0) == 2) { // messages shown upon completion of first part (this is only a sample, feel free to edit it)
		mes getarg(1),"Thank god, you made it this far already!" ; next;
		mes getarg(1),"But the Realms are still far from safe..","The Realm Keepers are getting closer to Pallene as we speak." ; next;
		mes getarg(1),"Please defeat the Realm Keepers before they reach Pallene!!" ; next;
	}
	return;
}

} 
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...