Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Server Code Submissions

 
 
Thread Tools Display Modes
Prev Previous Post   Next Post Next
  #1  
Old 08-23-2012, 08:40 AM
image
Demi-God
 
Join Date: Jan 2002
Posts: 1,290
Default COMMITTED: Classic Multiquest Support

All of this code will redesign the sub function check_handin so that before we call EVENT_ITEM we keep all items turned in by players into the NPC's memory.

Then when check_handin is called we feed the item id and count back into C++ to see if the NPC has received that item before (or just now). If not we break out and return false because all items are not yet available to complete a quest.

questmgr.h (in public section above protected):
Code:
	// KaB - Red69 - Zek / Adding multiquest support
	bool TurnInItem(int32 itm, int charges);
	void CompleteHandIn();
	void ResetHandIn();
questmgr.cpp (end of file)

Code:
bool QuestManager::TurnInItem(int32 itm, int charges)
{
	if ( owner && owner->IsNPC() )
	{
		if ( owner->CastToNPC()->DoesQuestItemExist(itm, charges, true) )
			return true;
	}

	return false;
}

void QuestManager::CompleteHandIn()
{
	if ( owner && owner->IsNPC() )
	{
		owner->CastToNPC()->RemoveQuestDeleteItems();
	}
}

void QuestManager::ResetHandIn()
{
	if ( owner && owner->IsNPC() )
	{
		owner->CastToNPC()->ResetQuestDeleteList();
	}
}

perlparser.cpp (new quest:: commands to add)
Look for:
newXS(strcpy(buf, "voicetell"), XS__voicetell, file);
newXS(strcpy(buf, "LearnRecipe"), XS__LearnRecipe, file);
(this is just the end of EXTERN_C XS(boot_quest))
add:

Code:
		// KaB - Zek - Red69 / Addition for multiquest
        newXS(strcpy(buf, "handleturnin"), XS__handleturnin, file);
        newXS(strcpy(buf, "completehandin"), XS__completehandin, file);
        newXS(strcpy(buf, "resethandin"), XS__resethandin, file);
Add these above that function that loads all the command names:
Code:
XS(XS__handleturnin); // prototype to pass -Wmissing-prototypes
XS(XS__handleturnin) {
	dXSARGS;
	
	if (items != 2)
		Perl_croak(aTHX_ "Usage: handleturnin(itemid, itemcharges)");
	int	itemid = (int)SvIV(ST(0));
	int	charges = (int)SvIV(ST(1));

	bool returnVal = quest_manager.TurnInItem(itemid,charges);
	
	ST(0) = boolSV(returnVal);
	sv_2mortal(ST(0));
	XSRETURN(1);
}

XS(XS__completehandin); // prototype to pass -Wmissing-prototypes
XS(XS__completehandin) {
	dXSARGS;
	
	if (items != 0)
		Perl_croak(aTHX_ "Usage: completeturnin()");

	quest_manager.CompleteHandIn();
	
	XSRETURN_EMPTY;
}

XS(XS__resethandin); // prototype to pass -Wmissing-prototypes
XS(XS__resethandin) {
	dXSARGS;
	
	if (items != 0)
		Perl_croak(aTHX_ "Usage: resetturnin()");

	quest_manager.ResetHandIn();
	
	XSRETURN_EMPTY;
}
npc.h (protected area above private):
Code:
	LinkedList<ItemInst*> questItems;
	LinkedList<ItemInst*> questDeletionItems;
npc.h (public area, above protected):
Code:
	// KaB - Zek - Red69 / Multiquest additions
	void AddQuestItem(ItemInst* inst) { questItems.Insert(inst); }

	void ClearQuestLists()
	{
		ClearQuestItems(true);
		ClearQuestDeleteItems(true);
	}

	void ResetQuestDeleteList()
	{
		ClearQuestDeleteItems(true);
	}
	
	
	void ClearQuestItems(bool delete_=false)
	{
		LinkedListIterator<ItemInst*> iterator(questItems);
		iterator.Reset();
		while(iterator.MoreElements())
		{
			ItemInst* inst = iterator.GetData();
			iterator.RemoveCurrent(delete_);
		}

		questItems.Clear();
	}

	void ClearQuestDeleteItems(bool delete_=false)
	{
		LinkedListIterator<ItemInst*> iterator(questDeletionItems);
		iterator.Reset();
		while(iterator.MoreElements())
		{
			ItemInst* inst = iterator.GetData();
			iterator.RemoveCurrent(delete_);
		}

		questDeletionItems.Clear();
	}
	
	ItemInst* FindQuestItemByID(int32 itmID, int charges, bool flagItemForDeletion=false)
	{
		LinkedListIterator<ItemInst*> iterator(questItems);
		iterator.Reset();
		int totalCharges = 0;
		while(iterator.MoreElements())
		{
			if ( iterator.GetData()->GetItem()->ID == itmID )
			{
				totalCharges += 1;

				if ( flagItemForDeletion )
					questDeletionItems.Insert(iterator.GetData()->Clone());
				if ( charges > totalCharges )
				{
					iterator.Advance();
					continue;
				}

				return iterator.GetData();
			}
			iterator.Advance();
		}
		return NULL;
	}

	bool DoesQuestItemExist(int32 itmID, int charges, bool flagItemForDeletion=false) { 	
		ItemInst* inst = FindQuestItemByID(itmID,charges,flagItemForDeletion);
		if ( inst != NULL )
		{
			return true;
		}
		else
			return false;
	}

	void ClearQuestItem(ItemInst* inst, bool delete_=true)
	{
		LinkedListIterator<ItemInst*> iterator(questItems);
		iterator.Reset();

		while(iterator.MoreElements())
		{
			if ( iterator.GetData ()->GetItem()->ID == inst->GetItem()->ID )
			{
				iterator.RemoveCurrent(delete_);
				break;
			}
			iterator.Advance();
		}
	}

	void RemoveQuestDeleteItems()
	{
		LinkedListIterator<ItemInst*> iterator(questDeletionItems);
		iterator.Reset();
		while(iterator.MoreElements())
		{
			ClearQuestItem(iterator.GetData(),true);
			iterator.RemoveCurrent(true);
		}

		questDeletionItems.Clear();
	}

	void PrintOutQuestItems(Client* c);
npc.cpp:

Add a new function in the NPC deconstructor to clear out their multiquest items
Code:
NPC::~NPC()
{
	// KaB - Red69 - Zek / Multiquest addition
	ClearQuestLists();

Add a new function to npc.cpp that will allow us to peek into the items the npc has:

Code:
void NPC::PrintOutQuestItems(Client* c){
		c->Message(4,"Quest Items currently awaiting completion on %s",GetName());

		LinkedListIterator<ItemInst*> iterator(questItems);
		iterator.Reset();

		while(iterator.MoreElements())
		{
			c->Message(5,"ItemName: %s (%d) | Charges: %i",iterator.GetData()->GetItem()->Name,iterator.GetData()->GetItem()->ID,iterator.GetData()->GetCharges());
			iterator.Advance();
		}

		c->Message(4,"End of quest items list.");
}

client.h (public function)

Code:
	bool	StoreTurnInItems(Mob* with);
trading.cpp

Code:
// KaB - Red69 - Zek / Aug 22 2012.  Rework on trade/quest turn in of items
bool Client::StoreTurnInItems(Mob* tradingWith) {
	
	if ( !tradingWith || !tradingWith->IsNPC() )
		return false;

				for (sint16 i=3000; i<=3003; i++) {
					const ItemInst* inst = m_inv[i];
					if (inst) {
						database.logevents(AccountName(),AccountID(),admin,GetName(),tradingWith->GetName(),"Quest Turn In Attempt",inst->GetItem()->Name,22,GetX(),
						GetY(),GetZ(), (char*)database.GetZoneName(GetZoneID(), GetPP().zoneInstance, true),tradingWith->GetX(),tradingWith->GetY(),tradingWith->GetZ());

						tradingWith->CastToNPC()->AddQuestItem(inst->Clone());
					}
				}

	return true;
}
trading.cpp in Client::FinishTrade(Mob* tradingWith) add store call StoreTurnInItems when we confirm it is a quest npc.

Code:
#ifdef EMBPERL
		if(((PerlembParser *)parse)->HasQuestSub(tradingWith->GetNPCTypeID(), "EVENT_ITEM")) {
#else
		if(parse->HasQuestFile(tradingWith->GetNPCTypeID())) {
#endif
			// This is a quest NPC
			quest_npc = true;
			
			// KaB - Red69 - Zek / Aug 22 2012.  Rework on trade/quest turn in of items
			StoreTurnInItems(tradingWith);
		}

command.cpp (new print quest items command):

command_init

Code:
		command_add("printquestitems","Returns available quest items for multiquesting currently on the target npc.",200,command_printquestitems) ||
Code:
void command_printquestitems(Client *c, const Seperator *sep)
{
	if (c->GetTarget() != 0)
	{
		if ( c->GetTarget()->IsNPC() )
			c->GetTarget()->CastToNPC()->PrintOutQuestItems(c);
		else
			c->Message(13,"Pick a NPC target.");
	}
	else
			c->Message(13,"Pick a NPC target.");
}
command.h:

Code:
void command_printquestitems(Client *c, const Seperator *sep);
plugins/check_handin.pl
Code:
sub check_handin {
    my $hashref = shift;
    my %required = @_;
    	quest::resethandin();
    foreach my $req (keys %required) {
	$charges = $required{$req};
	if ( !quest::handleturnin($req,$charges) )
	{
		return(0);
	}
    }
	quest::completehandin();
     return 1;
}
__________________
www.eq2emu.com
EQ2Emu Developer
Former EQEMu Developer / GuildWars / Zek Seasons Servers
Member of the "I hate devn00b" club.
Reply With Quote
 


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 10:34 PM.


 

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 - 2025, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3