Page 1 of 1

Usecode to find item carrier?

Posted: Tue Dec 20, 2016 10:54 pm
by Knight Captain
How can I use Usecode to find who is holding an item? Let's say I want to find a bag with a specific quality, how would I do that in SI? The command get_cont_items does not work with PARTY.

Re: Usecode to find item carrier?

Posted: Tue Dec 20, 2016 10:54 pm
by Knight Captain
I want to find the specific NPC.

Re: Usecode to find item carrier?

Posted: Thu Dec 22, 2016 2:08 pm
by marzo
Read the description of get_cont_items; does it sound like what you need? No, it does not.

Now check get_container. I suppose this one should be changed to say it gets the immediate container; but in any event, you can loop it until you get an object without a container. This is common enouh that the original games had a function to do it; I think it is called getOuterContainer, and it is defined in headers/si_externals.uc.

Re: Usecode to find item carrier?

Posted: Sun Dec 25, 2016 2:54 pm
by Knight Captain
How do I check that getOuterContainer has given the outermost container?

Re: Usecode to find item carrier?

Posted: Mon Dec 26, 2016 10:45 am
by marzo
... that is what the function does... if it fails to give the outermost container, then something is VERY wrong, and you should just close Exult and start it again. And if it keeps happening, file a bug report. Seriously, you don't need to check it; it returns either zero if the object is directly in the map or the container that sits directly in the map which contains the item. It never fails.

If you want tto know how it works, on the other hand, it loops over the get_container intrinsic until it finds a zero, and retur s the last nonzero container.

Re: Usecode to find item carrier?

Posted: Mon Dec 26, 2016 2:41 pm
by Knight Captain
Ah, I was thinking it would return the NPC value if that is what was holding the container. It doesn't seem like there's a way to determine which party NPC is holding something?

Re: Usecode to find item carrier?

Posted: Mon Dec 26, 2016 6:51 pm
by Donfrow
Would it work if you used UI_get_party_list to get an array of all the party members, and then loop through each element in the array and use UI_count_objects? That way you could check every party member one by one, and if you get a return on UI_count_objects > 0 (or whatever count criteria you need) you would know the element value(party member) has the object with the desired frame and quality?

Re: Usecode to find item carrier?

Posted: Mon Dec 24, 2018 2:45 am
by Knight Captain
The command get_cont_items not working with PARTY bit me again today. I'm going to write my own function to return an array of the items.

Funny that it's almost exactly 2 years later, thread-wise.

Re: Usecode to find item carrier?

Posted: Mon Dec 24, 2018 2:59 am
by Knight Captain
I've put in a bug for having UCC warn on this illegal command:
https://sourceforge.net/p/exult/bugs/2032/

Re: Usecode to find item carrier?

Posted: Mon Dec 24, 2018 6:03 am
by Knight Captain
Here's the fix via Usecode:

Code: Select all

/*
 *	The standard UI_get_cont_items command cannot be used to search the entire Party.
 *	This is problematic if you wish to get an array of each of a shape carried by the Party,
 *	using a single command.
 *
 *	2018-12-23 Knight Captain
 */

var getPartyItems 0x9D8 (var shape, var quality, var frame)
{
	var count;
	var party;
	var each_member;
	var index;
	var max;
	var member_name;
	var found;

	// Check if the party has any of the item. If not, there is no need to continue.
	count = UI_count_objects(PARTY, shape, quality, frame);
	if (count == 0)
	{
		UI_error_message("getPartyItems The Party has none of Shape ", shape, " Quality ", quality, " Frame ", frame, ".");
		return 0;
	}

	// Documentation does not describe a difference between versions list and list2.
	party = UI_get_party_list();

	UI_error_message("getPartyItems counted ", count, " of Shape ", shape, " Quality ", quality, " Frame ", frame, " in the Party.");
	
	for (each_member in party with index to max)
	{
		member_name = UI_get_npc_name(each_member);
		count = UI_count_objects(each_member, shape, quality, frame);
		if (count == 0)
		{
			UI_error_message("getPartyItems ", member_name, " has none.");
		}
		else
		{
			UI_error_message("getPartyItems ", member_name, " has ", count, ".");
			// This check is necessary to prevent a non-existent "found" being counted by UI_get_array_size below.
			if (found == 0)
				found = (UI_get_cont_items(each_member, shape, quality, frame));
			else
				found = (found & UI_get_cont_items(each_member, shape, quality, frame));
		}
	}

	count = UI_get_array_size(found);
	if (quality == -359)
		quality = "ANY";
	if (frame == -359)
		frame = "ANY";
	UI_error_message("getPartyItems has ", count, " of Shape ", shape, " Quality ", quality, " Frame ", frame, " in the array.");
	
	return found;
}