Go Back   EQEmulator Home > EQEmulator Forums > Quests > Quests::Custom

Quests::Custom Custom Quests here

Reply
 
Thread Tools Display Modes
  #1  
Old 06-18-2021, 06:04 PM
NatedogEZ's Avatar
NatedogEZ
Developer
 
Join Date: Dec 2012
Posts: 502
Default Some useful scripts for Devs out there.

Test script for basic soulbinding that removes the cost and items directly from the player so you can make extremely complex turnins or very simple turnins. Players will no longer have to hand items to NPCS so all NPCs can just return items!

Code:
plugin::collect_quest($client, 1001 => 5, 1002 => 2, "platinum" => 1, "gold" => 5, "silver" => 5, "copper" => 5); #can have a 20 item turn in if you wish
plugin::DiaWind2(); #Added button responses look at original diawind for other options
plugin::summon_into_inventory($client, 1001, 10); #Example summon 10 items of ID 1001 directly into the players inventory
Code:
sub EVENT_SAY {
	if ($text=~/hail/i) {
		plugin::DiaWind2("Would you like to donate one {orange}Stone of Binding~ and {orange}10 platinum~ to have your soul bound to this area? popupid:69 popupid:70 wintype:1", "Donate", "No thanks");
	}
}

sub EVENT_POPUPRESPONSE {
	if ($popupid == 69) {
		if (plugin::collect_quest($client, 1001 => 1, "platinum" => 10)) { #Takes 1 item and 10 platinum directly from player no turn in required
			plugin::DiaWind("Thank you for the donation! Have some fresh water!");
			$client->SetBindPoint($zoneid, 0, -49, 513, 2); $client->Message(15, "You are now bound to this plane.");
			plugin::summon_into_inventory($client,1028,20); #20 waters.. (custom item)
		} else {
			#Failed turnin missing items or money
			plugin::DiaWind2("You seem to be missing the requirements for me to cast this spell.");
		}
	} elsif($popupid == 70) {
		plugin::DiaWind("Farewell, maybe next time sir!");
	}
}


sub EVENT_ITEM {
	plugin::return_items(\%itemcount);
}


If you are looking for more examples I can post more later on how its used, or just message me on the EQEMU discord.



Required plugins for this to work.. is a modified DiaWind... just added DiaWind2 to make it have multiple options for popupid.


Code:
sub summon_into_inventory {
	my $client = $_[0];
	my $itemid = $_[1];
	my $amount = $_[2];
	
	my $aug1 = $_[3] ? $_[3] : 0;
	my $aug2 = $_[4] ? $_[4] : 0;
	my $aug3 = $_[5] ? $_[5] : 0;
	my $aug4 = $_[6] ? $_[6] : 0;
	my $aug5 = $_[7] ? $_[7] : 0;
	
	my $stackable = $client->GetItemStat($itemid, "stackable");
	my $stack_size = $client->GetItemStat($itemid, "stacksize");
	my $item_charges = 0;
	
	my @slots = (quest::getinventoryslotid("general.begin") .. quest::getinventoryslotid("general.end"),
				quest::getinventoryslotid("generalbags.begin") .. quest::getinventoryslotid("generalbags.end"));
	
	#If stackable.. lets find spots where it will fit current stacks already in place...
	if($stackable) {
		foreach $slot (@slots) {
			if ($client->GetItemIDAt($slot) == $itemid) {
				#stackable items must remove charges...
					$item_charges = $client->GetItemAt($slot)->GetCharges();
					if ($item_charges < $stack_size) {
						my $stack_diff = $stack_size - $item_charges; #How many can fit in this current stack...
						my $added_amount = 0;
						
						if ($amount > $stack_diff) {
							$added_amount = $stack_diff;
						} else {
							$added_amount = $amount;
						}
						#SummonItem(THIS, item_id, charges=0, attune=0, aug1=0, aug2=0, aug3=0, aug4=0, aug5=0, slot_id=30)
						$client->SummonItem($itemid, $item_charges + $added_amount, 0, 0, 0, 0, 0, 0, $slot);
						$amount -= $added_amount;
					}
			}
			if($amount <= 0) { #We finished brah
				return;
			}
		}
	}
	
	#Now we place the rest of the items into open slots..
	my $bag_begin = quest::getinventoryslotid("general1bag.begin"); #very first bag slot
	my $first_bag = quest::getinventoryslotid("general.begin");
	my %first_slot = (
		$first_bag => $bag_begin,
		$first_bag+1 => $bag_begin+10,
		$first_bag+2 => $bag_begin+20,
		$first_bag+3 => $bag_begin+30,
		$first_bag+4 => $bag_begin+40,
		$first_bag+5 => $bag_begin+50,
		$first_bag+6 => $bag_begin+60,
		$first_bag+7 => $bag_begin+70,
		$first_bag+8 => $bag_begin+80,
		$first_bag+9 => $bag_begin+90
		);
	
	foreach $slot (@slots) {
		my $check_bag = 0;
		#Slots 251 -330 require a bag in the correct slot..
		#quest::getinventoryslotid("general.begin") .. quest::getinventoryslotid("general.end"),
				#quest::getinventoryslotid("generalbags.begin") .. quest::getinventoryslotid("generalbags.end")
		if ($slot >= quest::getinventoryslotid("general1bag.begin") && $slot <= quest::getinventoryslotid("general1bag.end")) {
			$check_bag = quest::getinventoryslotid("general.begin");
		} elsif ($slot >= quest::getinventoryslotid("general2bag.begin") && $slot <= quest::getinventoryslotid("general2bag.end")) {
			$check_bag = quest::getinventoryslotid("general.begin")+1;
		} elsif ($slot >= quest::getinventoryslotid("general3bag.begin") && $slot <= quest::getinventoryslotid("general3bag.end")) {
			$check_bag = quest::getinventoryslotid("general.begin")+2;
		} elsif ($slot >= quest::getinventoryslotid("general4bag.begin") && $slot <= quest::getinventoryslotid("general4bag.end")) {
			$check_bag = quest::getinventoryslotid("general.begin")+3;
		} elsif ($slot >= quest::getinventoryslotid("general5bag.begin") && $slot <= quest::getinventoryslotid("general5bag.end")) {
			$check_bag = quest::getinventoryslotid("general.begin")+4;
		} elsif ($slot >= quest::getinventoryslotid("general6bag.begin") && $slot <= quest::getinventoryslotid("general6bag.end")) {
			$check_bag = quest::getinventoryslotid("general.begin")+5;
		} elsif ($slot >= quest::getinventoryslotid("general7bag.begin") && $slot <= quest::getinventoryslotid("general7bag.end")) {
			$check_bag = quest::getinventoryslotid("general.begin")+6;
		} elsif ($slot >= quest::getinventoryslotid("general8bag.begin") && $slot <= quest::getinventoryslotid("general8bag.end")) {
			$check_bag = quest::getinventoryslotid("general.begin")+7;
		} elsif ($slot >= quest::getinventoryslotid("general9bag.begin") && $slot <= quest::getinventoryslotid("general9bag.end")) {
			$check_bag = quest::getinventoryslotid("general.begin")+8;
		} elsif ($slot >= quest::getinventoryslotid("general10bag.begin") && $slot <= quest::getinventoryslotid("general10bag.end")) {
			$check_bag = quest::getinventoryslotid("general.begin")+9;
		}
		
		if ($check_bag > 0) {
			#$client->Message(335, "Test - $check_bag - ". $client->GetItemIDAt($check_bag));
			if ($client->GetItemIDAt($check_bag) == -1) {
				#$client->Message(335, "No Bag here skipping... $check_bag");
				next;
			} else {
				#There is an item here.. check if its a bag..
				my $bag_slots = $client->GetItemStat($client->GetItemIDAt($check_bag), "bagslots");
				if ($bag_slots > 0) {
					#This is a bag.. zomg.. see if the slot is valid..
					#my $max_slot = (($check_bag * 10) + 30) + $bag_slots;
					my $max_slot = $first_slot{$check_bag}+$bag_slots;
					
					#$client->Message(335, "$slot > $max_slot");
					
					if ($slot > $max_slot) {
						
						next; #This slot is not valid with this bag size...
					} else {
						#We are in a valid slot... check bag size...
						my $bag_size = $client->GetItemStat($client->GetItemIDAt($check_bag), "bagsize");
						my $item_size = $client->GetItemStat($itemid, "size");
						if ($item_size > $bag_size) {
							next; #This slit is not valid.. as this bag is too small
						}
					}
				} else {
					#$client->Message(335, "$slot---> not a bag");
					next; #This item is not a bag.. do not check this slot..
				}
			}
		}
		
		if ($client->GetItemIDAt($slot) == -1) {
			if ($stackable) {
				if ($stack_size > $amount) {
					$client->SummonItem($itemid, $amount, 0, 0, 0, 0, 0, 0, $slot);
					$amount = 0;
				} elsif ($amount >= $stack_size) {
					$client->SummonItem($itemid, $stack_size, 0, 0, 0, 0, 0, 0, $slot);
					$amount -= $stack_size;
				}
			} else {
				#$client->Message(335, "Summoning item into... $slot");
				#SummonItem(THIS, item_id, charges=0, attune=0, aug1=0, aug2=0, aug3=0, aug4=0, aug5=0, slot_id=30)
				$client->SummonItem($itemid, 1, 0, $aug1, $aug2, $aug3, $aug4, $aug5, $slot);  #Charged items.. would have to be handled differently..
				$amount--;
			}
		}
		if($amount <= 0) { #We finished brah
				return;
		}
	}
	
	#NO MORE VALID SLOTS... time to summon the rest to cursor...
	if ($amount > 0) {
		while ($amount > 0) {
			if ($stackable) {
				if ($stack_size > $amount) {
					$client->SummonItem($itemid, $amount);
					$amount = 0;
				} elsif ($amount >= $stack_size) {
					$client->SummonItem($itemid, $stack_size);
					$amount -= $stack_size;
				}
			} else {
				$client->SummonItem($itemid, 1, 0, $aug1, $aug2, $aug3, $aug4, $aug5);
				$amount--;
			}
		}
	}
	return;
}

#plugin::collect_quest($client, itemid => count, itemid => count)
#Can do money amount as well.. example...
# ... plugin::collect_quest($client, 1001 => 5, 1002 => 2, "platinum" => 1, "gold" => 5, "silver" => 5, "copper" => 5)
# ...
#THE TAKEMONEYFROM PP ONLY WORKS UP TO 2,147,000~ platinum.. so be aware!

sub collect_quest {
    my $client = shift;
	my %required = @_;
	my $count_total = 0;
	my $stackable = 0;
	my $money_total = 0;
	
	my @slots = (quest::getinventoryslotid("general.begin") .. quest::getinventoryslotid("general.end"),
				quest::getinventoryslotid("generalbags.begin") .. quest::getinventoryslotid("generalbags.end"));
	
	foreach my $req (keys %required) {
		$count_total = 0;
		
		if ($req =~/platinum/i) {
			$money_total += $required{$req} * 1000;
			next;
		} elsif ($req=~/gold/i) {
			$money_total += $required{$req} * 100;
			next;
		} elsif ($req =~/silver/i) {
			$money_total += $required{$req} * 10;
			next;
		}  elsif ($req =~/copper/i) {
			$money_total += $required{$req};
			next;
		}
		
		foreach $slot (@slots) {
			if ($client->GetItemIDAt($slot) == $req) {
				$stackable = $client->GetItemStat($req, "stackable");
				if($stackable) {
					$count_total+= $client->GetItemAt($slot)->GetCharges();
				} else {
					$count_total++;
				}
				
				#We have enough of this item.. stop checking..
				if($count_total >= $required{$req}) {
					last;
				}
			}
		}
		if ($count_total < $required{$req} || $count_total == 0) {
			#We failed this check.. return 0
			plugin::collect_quest_failed($client, %required);
			return 0;
		}
	}
	
	if ($money_total > 0) {
		if ($client->TakeMoneyFromPP($money_total, 1)) {
			plugin::collect_quest_remove($client, %required);
			return 1;
		} else {
			plugin::Whisper("You do not have enough money for this hand in!");
			return 0;
		}
	} else {
		plugin::collect_quest_remove($client, %required);
		return 1;
	}
}

sub collect_quest_remove {
    my $client = shift;
	my %required = @_;
	my $count_total = 0;
	my $stackable = 0;
	my $item_charges = 0;
	
	my @slots = (quest::getinventoryslotid("general.begin") .. quest::getinventoryslotid("general.end"),
				quest::getinventoryslotid("generalbags.begin") .. quest::getinventoryslotid("generalbags.end"));
	
	foreach my $req (keys %required) {
		$count_total = 0;
		if ($req =~/platinum|gold|silver|copper/i) {
			next;
		}
		
		foreach $slot (@slots) {
			if ($client->GetItemIDAt($slot) == $req) {
				$stackable = $client->GetItemStat($req, "stackable");
				
				if($stackable) {
					$item_charges = $client->GetItemAt($slot)->GetCharges();
					if ($item_charges >= $required{$req}) {
						$client->DeleteItemInInventory($slot, $required{$req}, 1);
						$required{$req} = 0;
					}
					elsif($item_charges < $required{$req} && $item_charges > 0) {
						$client->DeleteItemInInventory($slot, $item_charges, 1);
						$required{$req}-= $item_charges;
					}
				} else {
				#non-stackable items must be 0 charges to remove the entire item
					$item_charges = 1;
					$client->DeleteItemInInventory($slot, 0, 1);
					$required{$req}-= $item_charges;
				}
				
				#We removed enough of the item.. jump to next item!
				if ($required{$req} <= 0) {
					last;
				}
			}
		}
	}
}

#Called when they are missing required items...
sub collect_quest_failed {
	my $client = shift;
	my %required = @_;
	my $count_total = 0;
	my $stackable = 0;
	
	my @slots = (quest::getinventoryslotid("general.begin") .. quest::getinventoryslotid("general.end"),
				quest::getinventoryslotid("generalbags.begin") .. quest::getinventoryslotid("generalbags.end"));
	
	$client->Message(335, "Missing required items!");
	foreach my $req (keys %required) {
		$count_total = 0;
		
		if ($req =~/platinum|gold|silver|copper/i) {
			next;
		}
		
		foreach $slot (@slots) {
			if ($client->GetItemIDAt($slot) == $req) {
				$stackable = $client->GetItemStat($req, "stackable");
				if($stackable) {
					$count_total+= $client->GetItemAt($slot)->GetCharges();
				} else {
					$count_total++;
				}
				
				#We have enough of this item.. stop checking..
				if($count_total >= $required{$req}) {
					last;
				}
			}
		}
		
		if ($count_total < $required{$req} || $count_total == 0) {
			$client->Message(335,"" . $required{$req} . "x " . quest::varlink($req) . " you have  " . $count_total);
		}
	}
}

#Added by Natedog to make use of Popup2 add to DiaWind.pl in plugins modified version of Akkadius' DiaWind
sub DiaWind2 { 
	my $Text = $_[0]; my $npc = plugin::val('$npc'); $client = plugin::val('$client'); $name = plugin::val('$name');
    my $Opt = 0;
	if(!$PopId){ $PopId = 999; } 
	if(!$PopId2){ $PopId2 = 0; }
	$Text=~ s/~/<\/c>/g;
	$Text=~ s/\{y\}/<c \"#CCFF33\">/g;
	$Text=~ s/\{lb\}/<c \"#00FFFF\">/g;
	$Text=~ s/\{r}/<c \"#FF0000\">/g;
	$Text=~ s/\{g}/<c \"#00FF00\">/g;
	$Text=~ s/\{gold}/<c \"#FFFF66\">/g;
	$Text=~ s/\{orange}/<c \"#FFA500\">/g;
	$Text=~ s/\{gray}/<c \"#808080\">/g;
	$Text=~ s/\{tan}/<c \"#daa520\">/g;
	$Text=~ s/\{bullet}//g;
	$Text=~ s/\$name/$name/g;
	$Text=~ s/\{linebreak}/--------------------------------------------------------------------/g;
	$Text=~ s/\{rowpad}/<tr><td>{tdpad}<\/td><td>{tdpad}<\/td><\/tr>/g; 
	$Text=~ s/\{tdpad}/----------------------/g; 
	$Text=~ s/\{in}/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/g;
	my ($mvoice) = $Text =~ s/mysterious//g;
	my ($achievement) = $Text =~ s/achievement//g;
	my ($noquotes) = $Text =~ s/noquotes//g; if($noquotes){ $quo = ""; } else{ $quo = "'"; }
	my ($nobracket) = $Text =~ s/nobracket//g;
	my ($nosound) = $Text =~ s/nosound//g;
	my ($cname) = $Text =~ /{(.*)\>/; if ($cname) { $Text =~ s/{$cname\>//g; }
	my $Button0 = $_[1] ? $_[1] : "Yes";
	my $Button1 = $_[2] ? $_[2] : "No";
	my $soundcontrol = $_[3] ? $_[3] : 0;
	if(!$nobracket){
		($bracket) = $Text =~ /\[([^\]]+)\].*/;
		($bracket2) = $Text =~ /\[(.*)\>/;
	}

	my ($anim) = $Text =~ /\+(.*)\+/; if ($anim) { $Text=~ s/\+$anim\+//g; }
	my ($Timer) = $Text =~ /\=(.*)\=/; if ($Timer) { $Text=~ s/\=$Timer\=//g; }
	my $response = ""; my $ClickQueue = ""; my $Options = "";
	my @popupid = $Text =~ /popupid\:(\d+)/g;
	if($popupid[0]){ $PopId = $popupid[0]; my $string = "popupid:" . $popupid[0]; $Text=~ s/$string//g; }
	if($popupid[1]){ $PopId2 = $popupid[1]; my $string = "popupid:" . $popupid[1]; $Text=~ s/$string//g; }
	my @wintype = $Text =~ /wintype\:(\d+)/g;
	if($wintype[0]){ if($wintype[0] == 1){ $Opt = 1; }; my $string = "wintype:" . $wintype[0]; $Text=~ s/$string//g; }
	if(!$nobracket){
		if($bracket){ $response = $bracket; 	}
		if($bracket2){ $response = $bracket2; 	}
		@data = ($Text =~ m/\[([^\]]+)\]/g);
		foreach $val (@data){ $Options .= "" . quest::saylink($val, 1) . " - ";}
		if($data[1]){ $client->Message(15, " --- Select Response from Options --- "); $client->Message(0, "[" . substr ($Options, 0, -3) . "]"); }
	}
	if($anim){ if($anim > 0){ quest::doanim($anim); } else{ plugin::DoAnim($anim);} }
	#my $string = quotemeta("[" . $bracket2 . ">"); $Text=~ s/$string//g;
	if($Timer && $Timer > 0){ $ClickQueue = "<c \"#F07F00\">This message will disappear in " . $Timer . " second(s)...</c>"; }
	elsif($response ne ""){ $client->SetEntityVariable("npcresponse", $response); 
		if($Opt == 1 && $Button0 ne "Yes"){ $ClickQueue = "<c \"#F07F00\">Click '$Button0' to continue'...</c>";  }
		elsif($Opt == 1){ $ClickQueue = "<c \"#F07F00\">Click 'Yes' to continue'...</c>"; }
		else{ $ClickQueue = "<c \"#F07F00\">Click 'OK' to respond with '" . $response . "'...</c>"; }
	}else{ $client->SetEntityVariable("npcresponse", ""); 
		if($Opt == 1 && $Button0 ne "Yes"){ $ClickQueue = "<c \"#F07F00\">Click '$Button0' to continue...</c>";  }
		elsif($Opt == 1){ $ClickQueue = "<c \"#F07F00\">Click 'Yes' to continue...</c>";}
		else{ $ClickQueue = "<c \"#F07F00\">Click 'OK' to continue...</c>"; }
	}
	if($achievement){} elsif($cname){ $Speaking = $cname . " says"; } elsif($mvoice){ $Speaking = "A Mysterious Voice says"; } else{ if($npc){ $Speaking = $npc->GetCleanName() . ' says'; } }
	if($achievement){ $Title = "New Achievment!"; } else{ $Title = "Dialogue: " . $Speaking; }
	if($achievement){ $Timer = 5; $client->Popup2($Title,  $Text . "" . $ClickQueue . "", $PopId, 0, $Opt, $Timer); }
	else{ $client->Popup2($Title, "<c \"#CCFF33\">" . $Speaking . "</c><br><br>" . $quo . "" . $Text . "" . $quo . "" . "<br><br>" . $ClickQueue . "", $PopId, $PopId2, $Opt, $Timer, $Button0, $Button1, $soundcontrol); }
	$PopId = undef; $achievement = undef;
} 

1;

Last edited by NatedogEZ; 06-18-2021 at 06:14 PM..
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 12:32 AM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3