Jump to content
  • 0

NPC Instance Manager


mizanyan

Question


  • Group:  Members
  • Topic Count:  4
  • Topics Per Day:  0.01
  • Content Count:  9
  • Reputation:   0
  • Joined:  06/11/23
  • Last Seen:  

Hello rAthena. I was searching for a NPC that can start any instance in the game without the need to go through all the required quest, just click and go! More or less like the warper npc but for instances only. Of course with the cooldown to enter the instance again and all. I lack the knowledge to make one from scratch, I just need a base to work on. If anyone could help me it would be lovely, thanks in advance.

Link to comment
Share on other sites

3 answers to this question

Recommended Posts

  • 0

  • Group:  Members
  • Topic Count:  1
  • Topics Per Day:  0.00
  • Content Count:  235
  • Reputation:   87
  • Joined:  06/30/18
  • Last Seen:  

There is a sample in the docs under doc/samples/instancing.txt. Please note the comment that says you need to add the instance to the database, for the script to work. It is in the old format, but you shouldn't have issues to convert it to the yaml version. 

//===== rAthena Script =======================================
//= Sample: Instancing
//===== By: ==================================================
//= Euphy
//===== Last Updated: ========================================
//= 20140129
//===== Description: ========================================= 
//= Contains elements of a basic instance script.
//============================================================

// Before running this script, add the entry below to
// 'db/(pre-)re/instance_db.txt':
// 100,Abyss Lake Instance,3600,300,abyss_03,160,155

// Instance Creation
//============================================================
prontera,151,190,6	script	Sample Instance	101,{
	.@instance$ = "Abyss Lake Instance";

	if (instance_live_info(ILI_NAME, instance_id(IM_PARTY)) == .@instance$) {  // the instance "Abyss Lake Instance" is running
		mes "[Sample Instance]";
		mes "You are already part of an instance.";
		next;
		switch(select("Enter Instance.:Cancel.")) {
		case 1:
			break;
		case 2:
			mes "[Sample Instance]";
			mes "You don't want to try again?";
			emotion ET_CRY;
			close;
		}
	}
	else if (instance_id(IM_PARTY)) {	// another instance is running
		mes "[Sample Instance]";
		mes "You are part of the instance " + instance_live_info(ILI_NAME, instance_id(IM_PARTY)) + ".";
		close;
	}
	else {
		mes "[Sample Instance]";
		mes "Would you like to try the sample instance in Abyss Lake 3?";
		next;
		switch(select("Create Instance.:Cancel.")) {
		case 1:
			.@create = instance_create(.@instance$);
			if (.@create < 0) {
				mes "[Sample Instance]";
				switch (.@create) {
					case -1: mes "ERROR: Invalid type."; break;
					case -2: mes "ERROR: Party not found."; break;
					case -3: mes "ERROR: Instance already exists."; break;
					case -4: mes "ERROR: No free instances."; break;
				}
				mes " ";
				mes "Instance creation ^FF0000failed^000000.";
				emotion ET_HUK;
				close;
			}
			mes "[Sample Instance]";
			mes "Instance created.";
			mes " ";
			mes "Now entering the instance...";
			next;
			break;
		case 2:
			mes "[Sample Instance]";
			mes "Okay. Maybe next time!";
			close;
		}
	}
	.@enter = instance_enter(.@instance$);
	if (.@enter != 0) {
		mes "[Sample Instance]";
		switch (.@enter) {
			case 1: mes "ERROR: Party not found."; break;
			case 2: mes "ERROR: Party does not have an instance."; break;
			case 3: mes "ERROR: Unknown error."; break;
		}
		mes " ";
		mes "Instance entry ^FF0000failed^000000.";
		emotion ET_HUK;
		close;
	}
	close;
}

// Instance Scripts
//============================================================
abyss_03,154,159,6	script	Instance NPC#start	101,{
	mes "[Instance NPC]";
	mes "Are you ready to begin?";
	next;
	switch(select("Yes.:No.")) {
	case 1:
		mes "[Instance NPC]";
		mes "Good luck.";
		close2;
		donpcevent instance_npcname("#ins_abyss03_mobs")+"::OnEnable";
		delwaitingroom;
		disablenpc instance_npcname(strnpcinfo(0));
		end;
	case 2:
		mes "[Instance NPC]";
		mes "Take your time.";
		close;
	}
	end;

OnInit:  // hide the NPC on the normal map
	disablenpc strnpcinfo(0);
	end;
OnInstanceInit:  // initialize the NPC when the instance is created
	disablenpc instance_npcname("abysslakedunwarp004");  // disable original warp portal (currently buggy)
	waitingroom "Click here to start!",0;
	end;
}

abyss_03,0,0,0	script	#ins_abyss03_mobs	-1,{
	end;
OnEnable:
	initnpctimer;
	end;
OnTimer1000:  //strnpcinfo(4) will retrieve the instanced map name
	mapannounce strnpcinfo(4),"Instance NPC: The Abyss Lake instance has begun.",bc_all;
	end;
OnTimer4000:
	mapannounce strnpcinfo(4),"Instance NPC: Smash the Treasure Chest in the center of the map for a prize.",bc_all;
	end;
OnTimer5000:
	stopnpctimer;

	// spawn mobs
	.@map$        = instance_mapname("abyss_03");
	.@label$      = instance_npcname(strnpcinfo(0))+"::OnMyMobDead";
	.@label_boss$ = instance_npcname(strnpcinfo(0))+"::OnMyBossDead";
	monster .@map$,0,0,"Huge Poring",1002,20,.@label$,2;
	monster .@map$,0,0,"Huge Drops",1113,15,.@label$,2;
	monster .@map$,0,0,"Huge Poporing",1031,10,.@label$,2;
	monster .@map$,0,0,"Huge Marin",1242,10,.@label$,2;
	monster .@map$,0,0,"Tiny Zombie",1015,30,.@label$,1;
	monster .@map$,0,0,"Huge Mime Monkey",1585,2,.@label$,2;
	monster .@map$,97,102,"Treasure Chest",1732,1,.@label_boss$,2;
	end;
OnMyMobDead:  // normal mobs
	dispbottom "What am I doing? I should be attacking the Treasure Chest!";
	viewpoint 0,97,102,0,0xFF0000;
	switch (rand(6)) {  // for fun (:
		case 0: sc_start SC_STONE,5000,0; break;
		case 1: sc_start SC_FREEZE,5000,0; break;
		case 2: sc_start SC_STUN,5000,0; break;
		case 3: sc_start SC_SLEEP,5000,0; break;
		case 4: sc_start SC_CONFUSION,5000,0; break;
		case 5: sc_start SC_BLIND,5000,0; break;
	}
	end;
OnMyBossDead:  // treasure chest
	specialeffect2 EF_MVP;
	getitem 512,1; //Apple

	// trigger other events
	.@map$   = instance_mapname("abyss_03");
	.@label$ = instance_npcname(strnpcinfo(0))+"::OnMyMobDead";
	killmonster .@map$,.@label$;
	mapannounce .@map$,"Instance NPC: Good work! Please speak to me as soon as possible.",bc_all;
	donpcevent instance_npcname("Instance NPC#finish")+"::OnEnable";
	end;
}

abyss_03,97,102,4	script	Instance NPC#finish	101,{
	mes "[Instance NPC]";
	mes "Congratulations! You've finished the instance.";
	mes "I'll send you back to town now.";
	emotion ET_BEST;
	close2;
	warp "prontera",156,191;
	instance_destroy();
	end;

OnInit:
	disablenpc strnpcinfo(0);
	end;
OnInstanceInit:
	disablenpc instance_npcname(strnpcinfo(0));
	end;
OnEnable:
	enablenpc instance_npcname(strnpcinfo(0));
	specialeffect EF_HIDING;
	end;
}

abyss_03,115,26,0	script	#ins_abyss03_warp	45,5,5,{
	end;
OnTouch:
	mes "Are you sure you want to leave?";
	next;
	switch(select("Leave.:Stay.")) {
	case 1:
		warp "prontera",156,191;
		break;
	case 2:
		warp strnpcinfo(4),160,155;
		break;
	}
	close;
OnInit:
	disablenpc strnpcinfo(0);
	end;
}

 

  • Upvote 1
Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  4
  • Topics Per Day:  0.01
  • Content Count:  9
  • Reputation:   0
  • Joined:  06/11/23
  • Last Seen:  

12 hours ago, Winterfox said:

There is a sample in the docs under doc/samples/instancing.txt. Please note the comment that says you need to add the instance to the database, for the script to work. It is in the old format, but you shouldn't have issues to convert it to the yaml version. 

//===== rAthena Script =======================================
//= Sample: Instancing
//===== By: ==================================================
//= Euphy
//===== Last Updated: ========================================
//= 20140129
//===== Description: ========================================= 
//= Contains elements of a basic instance script.
//============================================================

// Before running this script, add the entry below to
// 'db/(pre-)re/instance_db.txt':
// 100,Abyss Lake Instance,3600,300,abyss_03,160,155

// Instance Creation
//============================================================
prontera,151,190,6	script	Sample Instance	101,{
	.@instance$ = "Abyss Lake Instance";

	if (instance_live_info(ILI_NAME, instance_id(IM_PARTY)) == .@instance$) {  // the instance "Abyss Lake Instance" is running
		mes "[Sample Instance]";
		mes "You are already part of an instance.";
		next;
		switch(select("Enter Instance.:Cancel.")) {
		case 1:
			break;
		case 2:
			mes "[Sample Instance]";
			mes "You don't want to try again?";
			emotion ET_CRY;
			close;
		}
	}
	else if (instance_id(IM_PARTY)) {	// another instance is running
		mes "[Sample Instance]";
		mes "You are part of the instance " + instance_live_info(ILI_NAME, instance_id(IM_PARTY)) + ".";
		close;
	}
	else {
		mes "[Sample Instance]";
		mes "Would you like to try the sample instance in Abyss Lake 3?";
		next;
		switch(select("Create Instance.:Cancel.")) {
		case 1:
			.@create = instance_create(.@instance$);
			if (.@create < 0) {
				mes "[Sample Instance]";
				switch (.@create) {
					case -1: mes "ERROR: Invalid type."; break;
					case -2: mes "ERROR: Party not found."; break;
					case -3: mes "ERROR: Instance already exists."; break;
					case -4: mes "ERROR: No free instances."; break;
				}
				mes " ";
				mes "Instance creation ^FF0000failed^000000.";
				emotion ET_HUK;
				close;
			}
			mes "[Sample Instance]";
			mes "Instance created.";
			mes " ";
			mes "Now entering the instance...";
			next;
			break;
		case 2:
			mes "[Sample Instance]";
			mes "Okay. Maybe next time!";
			close;
		}
	}
	.@enter = instance_enter(.@instance$);
	if (.@enter != 0) {
		mes "[Sample Instance]";
		switch (.@enter) {
			case 1: mes "ERROR: Party not found."; break;
			case 2: mes "ERROR: Party does not have an instance."; break;
			case 3: mes "ERROR: Unknown error."; break;
		}
		mes " ";
		mes "Instance entry ^FF0000failed^000000.";
		emotion ET_HUK;
		close;
	}
	close;
}

// Instance Scripts
//============================================================
abyss_03,154,159,6	script	Instance NPC#start	101,{
	mes "[Instance NPC]";
	mes "Are you ready to begin?";
	next;
	switch(select("Yes.:No.")) {
	case 1:
		mes "[Instance NPC]";
		mes "Good luck.";
		close2;
		donpcevent instance_npcname("#ins_abyss03_mobs")+"::OnEnable";
		delwaitingroom;
		disablenpc instance_npcname(strnpcinfo(0));
		end;
	case 2:
		mes "[Instance NPC]";
		mes "Take your time.";
		close;
	}
	end;

OnInit:  // hide the NPC on the normal map
	disablenpc strnpcinfo(0);
	end;
OnInstanceInit:  // initialize the NPC when the instance is created
	disablenpc instance_npcname("abysslakedunwarp004");  // disable original warp portal (currently buggy)
	waitingroom "Click here to start!",0;
	end;
}

abyss_03,0,0,0	script	#ins_abyss03_mobs	-1,{
	end;
OnEnable:
	initnpctimer;
	end;
OnTimer1000:  //strnpcinfo(4) will retrieve the instanced map name
	mapannounce strnpcinfo(4),"Instance NPC: The Abyss Lake instance has begun.",bc_all;
	end;
OnTimer4000:
	mapannounce strnpcinfo(4),"Instance NPC: Smash the Treasure Chest in the center of the map for a prize.",bc_all;
	end;
OnTimer5000:
	stopnpctimer;

	// spawn mobs
	.@map$        = instance_mapname("abyss_03");
	.@label$      = instance_npcname(strnpcinfo(0))+"::OnMyMobDead";
	.@label_boss$ = instance_npcname(strnpcinfo(0))+"::OnMyBossDead";
	monster .@map$,0,0,"Huge Poring",1002,20,.@label$,2;
	monster .@map$,0,0,"Huge Drops",1113,15,.@label$,2;
	monster .@map$,0,0,"Huge Poporing",1031,10,.@label$,2;
	monster .@map$,0,0,"Huge Marin",1242,10,.@label$,2;
	monster .@map$,0,0,"Tiny Zombie",1015,30,.@label$,1;
	monster .@map$,0,0,"Huge Mime Monkey",1585,2,.@label$,2;
	monster .@map$,97,102,"Treasure Chest",1732,1,.@label_boss$,2;
	end;
OnMyMobDead:  // normal mobs
	dispbottom "What am I doing? I should be attacking the Treasure Chest!";
	viewpoint 0,97,102,0,0xFF0000;
	switch (rand(6)) {  // for fun (:
		case 0: sc_start SC_STONE,5000,0; break;
		case 1: sc_start SC_FREEZE,5000,0; break;
		case 2: sc_start SC_STUN,5000,0; break;
		case 3: sc_start SC_SLEEP,5000,0; break;
		case 4: sc_start SC_CONFUSION,5000,0; break;
		case 5: sc_start SC_BLIND,5000,0; break;
	}
	end;
OnMyBossDead:  // treasure chest
	specialeffect2 EF_MVP;
	getitem 512,1; //Apple

	// trigger other events
	.@map$   = instance_mapname("abyss_03");
	.@label$ = instance_npcname(strnpcinfo(0))+"::OnMyMobDead";
	killmonster .@map$,.@label$;
	mapannounce .@map$,"Instance NPC: Good work! Please speak to me as soon as possible.",bc_all;
	donpcevent instance_npcname("Instance NPC#finish")+"::OnEnable";
	end;
}

abyss_03,97,102,4	script	Instance NPC#finish	101,{
	mes "[Instance NPC]";
	mes "Congratulations! You've finished the instance.";
	mes "I'll send you back to town now.";
	emotion ET_BEST;
	close2;
	warp "prontera",156,191;
	instance_destroy();
	end;

OnInit:
	disablenpc strnpcinfo(0);
	end;
OnInstanceInit:
	disablenpc instance_npcname(strnpcinfo(0));
	end;
OnEnable:
	enablenpc instance_npcname(strnpcinfo(0));
	specialeffect EF_HIDING;
	end;
}

abyss_03,115,26,0	script	#ins_abyss03_warp	45,5,5,{
	end;
OnTouch:
	mes "Are you sure you want to leave?";
	next;
	switch(select("Leave.:Stay.")) {
	case 1:
		warp "prontera",156,191;
		break;
	case 2:
		warp strnpcinfo(4),160,155;
		break;
	}
	close;
OnInit:
	disablenpc strnpcinfo(0);
	end;
}

 

Hello, I made it work with your sample, thank you very much. But there's still a problem that I can't solve. As is, the player can enter the instances anytime without limit, how can I set a cooldown so the player must wait to enter again? Based on the instance quest that the normal npcs give, like quest 16400 for Edda Biolab for example. image.png.c4b02b505798d8ca7e63dc9c1b9186f8.png

Here is the npc I made:

prontera,151,190,6	script	Sample Instance	101,{
// Define the instance names in a dynamic array
setarray .@instance_ids$[1], "Edda Bio", "Old Glast Heim", "Endless Tower";

// Show the list of instances to the player and get the selected index
.@selected_index = select("Edda Bio", "Old Glast Heim", "Endless Tower");
.@instance$ = .@instance_ids$[.@selected_index]; // Get the corresponding instance name from the array

if (instance_id(IM_PARTY)) {
	// Check if the party is already part of an instance
	if (instance_live_info(ILI_NAME, instance_id(IM_PARTY)) == .@instance$) {
		mes "[Sample Instance]";
		mes "Your party is already part of the "+.@instance$+" instance.";
		close;
	} else {
		mes "[Sample Instance]";
		mes "Your party is already part of an instance.";
		close;
	}
}

mes "[Sample Instance]";
mes "Would you like to try the "+.@instance$+" instance?";
next;
switch(select("Create Instance.:Cancel.")) {
	case 1:
		// Check if a valid instance name is chosen
		if (.@instance$ != "") {
			.@create = instance_create(.@instance$);
			if (.@create < 0) {
				mes "[Sample Instance]";
				switch (.@create) {
					case -1: mes "ERROR: Invalid type."; break;
					case -2: mes "ERROR: Party not found."; break;
					case -3: mes "ERROR: Instance already exists."; break;
					case -4: mes "ERROR: No free instances."; break;
				}
				mes " ";
				mes "Instance creation ^FF0000failed^000000.";
				emotion ET_HUK;
				close;
			}
			mes "[Sample Instance]";
			mes "Instance created.";
			mes " ";
			mes "Now entering the instance...";
			next;
			.@enter = instance_enter(.@instance$);
			if (.@enter != 0) {
				mes "[Sample Instance]";
				switch (.@enter) {
					case 1: mes "ERROR: Party not found."; break;
					case 2: mes "ERROR: Party does not have an instance."; break;
					case 3: mes "ERROR: Unknown error."; break;
				}
				mes " ";
				mes "Instance entry ^FF0000failed^000000.";
				emotion ET_HUK;
				close;
			}
			close;
		} else {
			mes "[Sample Instance]";
			mes "ERROR: Invalid instance selection.";
			emotion ET_HMM;
			close;
		}
		break;
	case 2:
		mes "[Sample Instance]";
		mes "Okay. Maybe next time!";
		close;
}
close;
}

 

Edited by mizanyan
Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  1
  • Topics Per Day:  0.00
  • Content Count:  235
  • Reputation:   87
  • Joined:  06/30/18
  • Last Seen:  

These cooldowns are made with the quest commands. It works by giving the player a quest that has an expiration time.
Here is a small example: 
 

prontera,124,201,1	script	Example NPC	726,{
	// Check if the time limit is still running.
	if(checkquest(200000, PLAYTIME) == 0) {
		mes "Example";
		mes "I am still preparing the cake, please wait!";
		close;
	}

	// Check if the time limit expired.
	if(checkquest(200000, PLAYTIME) == 2) {
		mes "Example";
		mes "Finally! Here is your cake!";
		erasequest(200000);
		getitem(12062, 1);
		close;
	}

	// Give the quest with the time limit
	mes "Example";
	mes "Hello, how may i help you?";
	mes "Oh, a free special cake?";
	mes "Sure, i will bake you a fresh one.";
	mes "Please come back in 5 minutes!";
	setquest(200000);
	close;
}

The actual quest and time limit is defined in the quest_db.yml. For the Example NPC the entry would look like this:
 

  - Id: 200000
    Title: "Example Cake Timer"
    TimeLimit: +5mn

If you want to show the quest info in the client like in your screenshot, you need to edit the System/OngoingQuestInfoList_True_EN.lub.
For the quest in the example, the entry could look like this:
 

	[200000] = {
		Title = "Example Cake Timer",
		Description = {
			"Wait for Example to prepare your cake."
		},
		Summary = ""
	}

 

Edited by Winterfox
  • Upvote 1
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...