Share-a-function thread

Post your Custom Scripts or Packages.
Post Reply
User avatar
itec
Novice Poster
Posts: 42
Joined: Thu Feb 09, 2006 11:48 pm

Share-a-function thread

Post by itec »

To encourage everyone to give something back to the community, share a small (or big) helper function you are frequently using in your scripting. Maybe some of thease would fit in the distro as well.

To start off, here's two of our item functions.

Code: Select all

/* 
	Reaches

	Checks if player reaches the wanted item.
	
	Params:
		Char		Who uses
		Item		What
		~Integer	Options
		~String		What item name will be messaged, if 0 sends nothing
	
	Returns: true or error
 */

enum OPTIONS
	OPT_UNMOVABLE	:= 0x1		// Allowing unmovables
endenum

function Reaches( who, item, options := 0, what := "item" )
	
	var msg;
	
	if (!Accessible(who, item))
		msg := " is unreachable.";
	elseif (!(options & OPT_UNMOVABLE) && item.movable == 0)
		msg := " is unmovable.";
	elseif (!ReserveItem(item))
		msg := " is already in use.";
	elseif (Distance(who, item) > 2)
		msg := " is too far away.";
	elseif (item.GetProp("Vendored"))
		// Player merchants, remove if not needed
		msg := " is not yours.";
	else
		return 1;
	endif
	
	// Does not reach
	if (what)
		SendSysMessageUC(who, CAscZ("The "+what+msg));
	endif
	
	return 0;
	
endfunction

Code: Select all

/*
	ItemEquip
	
	Acts as EquipItem, but removes weared equipment of the same layer.
	
	Params:
		Char		who
		Item		Equipment to be weared
		~Integer		Options in bit-form
		
			OPT_FORCE			Skip reaches() check
			OPT_LIST_STRIPPED	Lists and returns removed items
	
	Returns:
		item array	if OPT_LIST_STRIPPED is set
		1			if item is equipped
		error		when failed
*/

enum EQUIP_OPTIONS
	OPT_FORCE			:= 1,	
	OPT_LIST_STRIPPED	:= 2
endenum

function ItemEquip( who, itemref, options := 0 )
	
	if (!(options & OPT_FORCE))
		
		var res := Reaches(who, itemref);
		if (res == error)
			return res;
		endif
	endif

	var result := 0;
	var stripped := array;
	
	// Item already equpped (core EquipItem() returns negative if item is already weared)
	if (itemref.container == who)
		
		result := 1;
	elseif (itemref.isa(POLCLASS_EQUIPMENT))
		
		result := EquipItem(who, itemref);
		
		if (!result)
			// Conflicting items are unequipped
			var itemlayer := itemref.layer;
			
			if (itemlayer == 1 || itemlayer == 2)
				// Layer 2 needs layer 1 to be empty and vice versa
				itemlayer := { 1, 2 };
			else
				itemlayer := { itemlayer };
			endif
			
			foreach layer in itemlayer
				var equipped := GetEquipmentByLayer(who, layer);
				
				if (equipped)
					// Moving conflicting equipment to backpack or ground
					if (!MoveItemToContainer(equipped, who.backpack))
						MoveObjectToLocation(equipped, who.x, who.y, who.z, who.realm, MOVEOBJECT_FORCELOCATION);
					endif
					
					if (options & OPT_LIST_STRIPPED)
						stripped.append(equipped);
					endif
				endif
			endforeach
			
			// New try
			result := EquipItem(who, itemref);
		endif
	endif
	
	if (options & OPT_LIST_STRIPPED)
		return stripped;
	endif
	
	return result;
	
endfunction
User avatar
ncrsn
Grandmaster Poster
Posts: 255
Joined: Fri Feb 10, 2006 12:15 am

Post by ncrsn »

Some other item functions.

1. DivideStack

Say, you need to do modify item (change its graphic or something), but it happens to be stackable: an example could be a unlit torch you wish to lit without affecting all n torches.

You could do 'if (item.amount > 1) // Throw error message: too many torches in stack!', but that would be rude and unprofessional; so, instead, write 'DivideStack(item, -1)' and you will get the stack subtracted to just one item, without item's being really taken from player.

Code: Select all

/*
	DivideStack
	
	Divides item stack into defined sized
	stacks.
	
	Params:
		Item	Item stack
		Integer	Size of split stack
	
	Returns:
		Created stack or 0 if failed.
	
	Note:
		If 'amt' is below zero, created
		stack will be sized .amount - amt.
		
		If 'amt' is between 1 and item.amount,
		created stack will be it's size.
		
		Created stack will be placed next to
		the original stack.
*/

function DivideStack( item, amt )
	
	if (amt < 0)
		// User wanted to leave amt items to original stack.
		amt += item.amount;
		
		if (amt < 1)
			// There are too few.
			return 0;
		endif
	elseif (item.amount <= amt)
		// Stack should have amt + 1.
		return 0;
	endif
	
	// Copy into abstract location.
	var newitem := CreateItemCopyAtLocation(1, 1, 1, item, _DEFAULT_REALM);
	
	if (!SubtractAmount(newitem, item.amount - amt))
		// Subtracting required amount from new stack - Failed.
		DestroyItem(newitem);
		return 0;
	elseif (!SubtractAmount(item, amt))
		// Subtracting required amount from original stack - Failed.
		DestroyItem(newitem);
		return 0;
	endif
	
	// Move new item into same location (container or coordinates) the original is.
	MoveItem(newitem, item);
	
	// Reference to created item.
	return newitem;
	
endfunction
2. MoveItem

Move item to another location, were it to be a container or just struct with x, y, z and realm.

Code: Select all

/*
	MoveItem
	
	Moves item into a backpack, container or coordinates. If
	container is full, moves item into container's  container,
	or eventually, onto ground.
	
	Params:
		Item	Item
		Object	Mobile / Container / Coordinates
	
	Returns:
		True or error
	
	Note:
		Coordinates could be just struct, but you have to
		define, not only "x", "y" and "z", but also "realm".
*/

function MoveItem( item, object )
	
	if (object.isa(POLCLASS_MOBILE))
		if (object.backpack)
			// Move into backpack; if there's no backpack, at feet.
			object := object.backpack;
		endif
	endif
	
	if (object.isa(POLCLASS_CONTAINER))
		// Check if container can take this.
		if (MoveItemToContainer(item, object))
			return 1;
		endif
	endif
	
	// Container is full or object is coordinate-struct. Next
	// step is to try object's container; if there is one.
	
	while (object.container)
		
		// Object is now it's container.
		object := object.container;
		
		if (MoveItemToContainer(item, object))
			return 1;
		endif
		
	endwhile
	
	// Every level of container's were full; or there were none.
	// Last try is to move item onto ground level.
	
	return MoveObjectToLocation(item, object.x, object.y, object.z, object.realm, MOVEOBJECT_FORCELOCATION);
	
endfunction
Post Reply