Page 1 of 1

New Improved Megacliloc/Tooltip package

Posted: Sun Jan 27, 2013 11:45 pm
by Agata
I was concerned about the size of the packets sent by the Megacliloc package for tooltips, so I rewrote the thing to actually use CliLocs.

Here is the result:

toolTips.src

Code: Select all

/* $Id: toolTips.src 104 2006-05-25 22:14:15Z montuz $
 *	Description: AOS Tooltips. Starter script.
 *	This packet takes awhile to get used to.
 *	HEAVILY modified by Agata
 */

use uo;
use cfgfile;
use polsys;

include "include/skills";
include "include/math";
include "include/itemtypes";

const OFFSET_OBJECT_SERIAL   := 0x05;
const OFFSET_CLILOC_ID       := 0x0F;
const OFFSET_LENGTH_ID       := 0x13;
const OFFSET_UNICODE_TEXT    := 0x14;

program Install()

	 Print("INSTALLING: Outgoing Tooltip PH...");
	 return 1;

endprogram

exported function MegaCliloc( who, byref packet )
	if (who)
	endif

	var xObject := SystemFindObjectBySerial(packet.GetInt32(OFFSET_OBJECT_SERIAL));

	if ( xObject.IsA(POLCLASS_ITEM) )
		packet.SetSize(15);
		
		var Object_Name := xObject.desc;
		Object_Name := CAscZ(Object_Name);
		packet.SetInt32(OFFSET_CLILOC_ID, 1042971);
		packet.SetUnicodeString(OFFSET_UNICODE_TEXT, Object_Name, 1);
		// I've noticed that this packet is only sent if this value has changed
		// from the last time it was checked. And using html to change the size doesn't work
		// for some reason. Maybe a core/client issue?
		packet.SetInt16(OFFSET_LENGTH_ID, Object_Name.Size() * 2);
		
		var xDesc := run_script_to_completion ( ":megacliloc:itemdata", xObject);
		if ( xDesc.Size() > 0 )
			foreach prop in xDesc
				var str := "";
				if (prop.values.size() > 0)
					str := CStr(prop.values[1]);
					var i;
					for (i:=2; i<=prop.values.size(); i:=i+1)
						str += CChr(0x09) + CStr(prop.values[i]);
					endfor
				endif
				str := CAscZ (str);
				packet.SetInt32(packet.GetSize() - 1, prop.clilocid);
				var Length_ID := packet.GetSize();
				packet.SetUnicodeString(packet.GetSize() + 1, str, 1);
				// SetUnicodeString adds 00 BYTE[1] at the start of the Unicode offset, which messes with the length offset.
				// Setting the length of the unicode text below will fix that issue. Same deal as above.
				packet.SetInt16(Length_ID, str.Size() * 2);
			endforeach
		endif
		// End of loop.
		packet.SetInt32(packet.GetSize(), 0);
	elseif (xObject.IsA (POLCLASS_MOBILE))
		// to be added later
		//var xDesc := run_script_to_completion ( ":megacliloc:chardata", xObject);		
	endif
	return 0;
endfunction
Now this is an example itemdata script. I am sure it WON'T compile for you as it contains several shard specific functions you won't have, but serves as a good way to show you how this works.


itemdata.src

Code: Select all

// Item data generator for tooltip packet
//
// Created by Agata
// natalia_buenota@hotmail.com
// The World of Dreams
//

use uo;
use cfgfile;
use polsys;

include "include/skills";
include "include/math";
include "include/itemtypes";

// Charges: 1049116
program itemdata(xObject)
	// Start of Loop.
	
	var allprops := array;
	var prop := struct;
	prop.+ clilocid := 0;
	prop.+ values := array;
	
	var owner := GetObjProperty(xObject, "ownername");
	if (owner)
		prop.clilocid := 1072304;
		prop.values := array {owner};
		allprops.append(prop);
	endif
	owner := GetObjProperty(xObject, "craftername");
	if (owner)
		prop.clilocid := 1050043;
		prop.values := array {owner};
		allprops.append(prop);
	endif
	if ( xObject.newbie )
		prop.clilocid := 1038021;
		prop.values := array {};
		allprops.append (prop);
	endif
	if (xObject.isa(POLCLASS_CONTAINER) and !xObject.isa(POLCLASS_CORPSE) and !(GetObjProperty (xObject, "lockpicking") and xObject.locked))
		if (xObject.objtype == UOBJ_RUNEBOOK)
			// 1049116, 1061837, 1075217, 1076207,
			// 1112590, 
			var charges := GetObjProperty (xObject, "%Charges%");
			prop.clilocid := 1061837;
			prop.values := array {charges.charges, charges.max_charges};
			allprops.append (prop);
//			xDesc := xDesc + Html + CINT ((GetObjProperty (xObject, "%RuneList%")).size()) + " runes<br>";
		else
			prop.clilocid := 1073839;
			prop.values := array {CINT(xObject.item_count-1), xObject.weight};
			allprops.append (prop);
		endif
	elseif (!xObject.isa(POLCLASS_CORPSE) and !IsSign(xObject))
		prop.clilocid := 1072225;
		prop.values := array {xObject.weight};
		allprops.append (prop);
	endif
	if (IsGargishItem (xObject))
		prop.clilocid := 1111709;
		prop.values := array {};
		allprops.append(prop);
	elseif (IsForAnyRace (xObject))
		prop.clilocid := 1070722;
		prop.values := array {"For Any Race"};
		allprops.append(prop);
	endif
	if (GetObjProperty(xObject, "unidentified"))
		prop.clilocid := 1038000;
		prop.values := array {};
		allprops.append(prop);
	else
		if (xObject.isa (POLCLASS_EQUIPMENT))
			if (xObject.isa(POLCLASS_ARMOR))
				var armordesc := GetItemDescriptor(xObject.objtype);
				if (xObject.ar_mod > 0)
					prop.clilocid := 1072382;
					prop.values := array {xObject.ar_mod};
					allprops.append (prop);
					prop.clilocid := 1080361;
					prop.values := array {xObject.ar};
					allprops.append (prop);
				else
					prop.clilocid := 1060448;
					prop.values := array {xObject.ar};
					allprops.append (prop);
				endif
				if (armordesc.strrequired)
					prop.clilocid := 1061170;
					prop.values := array {CINT(armordesc.strrequired/10)};
					allprops.append (prop);
				endif
				// Have to work on this yet...
//				if (armordesc.DexPenalty)
//					xDesc := xDesc + Html + "-" + CINT(armordesc.DexPenalty/10) + " Dexterity" + "<br>";
//				endif
				if (IsMedableArmor (xObject))
					prop.clilocid := 1060437;
					prop.values := array {};
					allprops.append (prop);
				endif
			elseif (xObject.isa (POLCLASS_WEAPON))
				if (GetObjProperty(xObject, "silver"))
					prop.clilocid := 1060479;
					prop.values := array {};
					allprops.append (prop);
				endif
				var weapondesc := GetItemDescriptor(xObject.objtype);
				//Damage
				var damagefactor := (xObject.hp * xObject.quality)/xObject.maxhp;
				if (xObject.dmg_mod > 0)
					prop.clilocid := 1074762;
					prop.values := array {xObject.dmg_mod};
					allprops.append (prop);
				endif
				prop.clilocid := 1061168;
				prop.values := array {CINT((weapondesc.MinDamage + xObject.dmg_mod)*damagefactor), CINT((weapondesc.MaxDamage + xObject.dmg_mod)*damagefactor)};
				allprops.append (prop);
				//Speed
				prop.clilocid := 1061167;
				prop.values := array {weapondesc.Speed};
				allprops.append (prop);
				//Handedness
				if (weapondesc.TwoHanded)
					prop.clilocid := 1061171;
				else
					prop.clilocid := 1061824;
				endif
				prop.values := array {};
				allprops.append (prop);	
				//Mage weapon
				if (weapondesc.BlocksCastingIfInHand == 0)
					prop.clilocid := 1062755;
					prop.values := array {};
					allprops.append (prop);
				endif
				//Skill
				case (lower(xObject.attribute))
					"swordsmanship": prop.clilocid := 1061172;
					"macefighting": prop.clilocid := 1061173;
					"fencing": prop.clilocid := 1061174;
					"archery": prop.clilocid := 1061175;
					"throwing": prop.clilocid := 1112075;
					default: prop.clilocid := 1060400;
				endcase
				prop.values := array {};
				allprops.append(prop);
			
			endif
			var skillid := GetObjProperty(xObject, "skilladv");
			if (GetObjProperty (xObject, "skill"+skillid))
				var skillname := GetSkillName(skillid);
				prop.clilocid := 1060451;
				prop.values := array {skillname, GetObjProperty (xObject, "skill"+skillid)};
				allprops.append (prop);
			endif
			if (xobject.resist_poison)
				prop.clilocid := 1072385;
				prop.values := array {xObject.resist_poison};
				allprops.append (prop);
			endif
			var charges := GetObjProperty(xObject, "charges");
			if (charges)
				var spell := "";
				if (xobject.resist_fire)
					prop.clilocid := 1072383;
					prop.values := array {xObject.resist_fire};
					allprops.append (prop);
					spell := "f";
				endif
				if (xobject.resist_cold)
					prop.clilocid := 1072384;
					prop.values := array {xObject.resist_cold};
					allprops.append (prop);
					spell := "c";
				endif
				if (xobject.resist_energy)
					prop.clilocid := 1072386;
					prop.values := array {xObject.resist_energy};
					allprops.append (prop);
					spell := "e";
				endif
				if (spell == "")
					// 1017324-1017371, 1049116, 1060487-1060492, 1061837,
					// 1062412-1062416, 1072852-1072853, 1075217, 1076207,
					// 1112590, 
					spell := GetObjProperty(xObject, "itemspellname");
					if (!spell)
						prop.clilocid := 1075217;
						prop.values := array {charges + " Spell"};
						allprops.append (prop);
					else
						case (lower (spell))
							"clumsiness":
								prop.clilocid := 1017326;
							"feeblemindedness":
								prop.clilocid := 1017327;
							"weakness":
								prop.clilocid := 1017328;
							"harming":
								prop.clilocid := 1017334;
							"cursing":
								prop.clilocid := 1017335;
							"draining":
								prop.clilocid := 1017339;
							"paralyzation":
								prop.clilocid := 1017340;
							"dispelling":
								prop.clilocid := 1060417;
							"flametongue":
								prop.clilocid := 1060487;
							"lightning":
								prop.clilocid := 1060491;
							default:
								prop.clilocid := 1075217;
						endcase
						if (prop.clilocid == 1075217)
							prop.values := array {charges + " " + spell};
						else
							prop.values := array {charges};
						endif
						allprops.append (prop);
					endif
				endif
			endif
			//Durability
			prop.clilocid := 1060639;
			prop.values := array {xObject.hp, xObject.maxhp};
			allprops.append (prop);
		elseif (IsMusicalInstrument(xObject))
			var skillbonus := GetObjProperty(xObject, "skillbonus");
			if (skillbonus)
				prop.clilocid := 1060451;
				prop.values := array {"Barding Skills", skillbonus};
				allprops.append (prop);
			endif
		elseif (IsJewelry(xObject))
		//1060485, 1060409, 1060432, 1075846, 1075842, 1075844
			var stat_bonus := GetObjProperty (xObject, "str");
			if (stat_bonus)
				prop.clilocid := 1060485;
				prop.values := array {stat_bonus};
				allprops.append (prop);
			endif
			stat_bonus := GetObjProperty (xObject, "dex");
			if (stat_bonus)
				prop.clilocid := 1060409;
				prop.values := array {stat_bonus};
				allprops.append (prop);
			endif
			stat_bonus := GetObjProperty (xObject, "int");
			if (stat_bonus)
				prop.clilocid := 1060432;
				prop.values := array {stat_bonus};
				allprops.append (prop);
			endif
		elseif (xObject.isa(POLCLASS_SPELLBOOK))
			prop.clilocid := 1042886;
			prop.values := array {xObject.spells().size()};
			allprops.append (prop);
		elseif (xObject.objtype == 0xA100)
			prop.clilocid := 1042886;
			prop.values := array {NecroSpellCount(xObject)};
			allprops.append (prop);
		elseif (xObject.objtype == 0x1706b)
			prop.clilocid := 1042886;
			prop.values := array {DruidSpellCount(xObject)};
			allprops.append (prop);
		elseif (IsSign(xObject))
			owner := GetObjProperty (xObject, "lastownername");
			if (owner)
				prop.clilocid := 1041602;
				prop.values := array {owner};
				allprops.append (prop);
			endif
		endif
	endif
	return allprops;

endprogram

function NecroSpellCount(book)
	var GreaterFlag := CINT (GetObjProperty (book, "Greater"));
	var LesserFlag := CINT (GetObjProperty (book, "Lesser"));
	var spellcount := 0;
	for i := 1 to 8
		if (FlagCheck (LesserFlag, i))
			spellcount := spellcount + 1;
		endif
		if (FlagCheck (GreaterFlag, i))
			spellcount := spellcount + 1;
		endif
	endfor
	return spellcount;
endfunction

function DruidSpellCount(bag)
	var runes := GetObjProperty (bag, "runes");
	if (runes)
		return runes.size();
	endif
	return 0;
endfunction

function IsSign (item)
	case (item.objtype)
		0xb95:
		0xb96:
		0xbd0:
		0xbd2:
		0xc43:
		0xc44:
		0x1f28:
		0x1f29:
		0x17060:
		0x1708a:
			return 1;
	endcase
	if (item.objtype >= 0xba3 and item.objtype <= 0xc0e)
		return 1;
	elseif (item.objtype >= 0x1297 and item.objtype <= 0x129e)
		return 1;
	endif
	return 0;
endfunction


Re: New Improved Megacliloc/Tooltip package

Posted: Mon Jan 28, 2013 5:07 am
by Yukiko
Agata,
How does one use the itemdata script? In other words, how do I attach it to a specific item so that it is called for that item and what player action causes it to be called?

Thanks in advance for the info.

Re: New Improved Megacliloc/Tooltip package

Posted: Mon Jan 28, 2013 8:04 am
by Agata
You don't need to attach it to anything, the itemdata script is called by the toolTips script, which is a PacketHook SendFunction for packet 0xD6. Download the attached Zip files and look at the uopacket.cfg file.

If you look at toolTips.src file on line 45 you will see the following:
var xDesc := run_script_to_completion ( ":megacliloc:itemdata", xObject);

And the next lines are the ones that put the data into the packet.

As for what action triggers this whole thing, hover the mouse pointer over the item.

Re: New Improved Megacliloc/Tooltip package

Posted: Tue Jan 29, 2013 5:50 am
by Yukiko
Ah. Thanks.

Guess I was being lazy. I should have read itemdata.src. Very nice!

Thanks again.

Re: New Improved Megacliloc/Tooltip package

Posted: Tue Jan 29, 2013 10:43 pm
by Agata
Maybe I should have mentioned that I broke it into two scripts, the toolTips.src and itemdata.src so the second can be recompiled and unloaded quickly and safely for live testing.

Re: New Improved Megacliloc/Tooltip package

Posted: Wed Oct 30, 2013 11:47 am
by Harley
Agata wrote:Maybe I should have mentioned that I broke it into two scripts, the toolTips.src and itemdata.src so the second can be recompiled and unloaded quickly and safely for live testing.
Agata, can u upload your cliloc.enu file? With best regards.

Re: New Improved Megacliloc/Tooltip package

Posted: Wed Apr 02, 2014 10:25 am
by Harley
Agata, thanks for your megacliloc! It's great!
Tell me please, did you finish a chardata or you didn't do this?

Re: New Improved Megacliloc/Tooltip package

Posted: Tue Nov 25, 2014 7:11 am
by Agata
I started work on a "chardata" script, and since I wanted to implement custom selectable titles, title styles and other things, I stopped working on it until I finish designing the Titles System