Yukiko's, possibly, helpful or, maybe, little known tips.

Sometimes you need to share your knowledge. This is where you can do it. A place for POL and Script guides.
Post Reply
Distro Developer
Posts: 2824
Joined: Thu Feb 02, 2006 1:41 pm
Location: San Antonio, Texas

Yukiko's, possibly, helpful or, maybe, little known tips.

Post by Yukiko » Tue Jul 17, 2018 10:15 pm

I hope this thread will allow me to bring some useful and not-so-obvious tips and tricks to you but as I am not a "super whamo-bango" programmer this thread may be a short list of tips. :D

In this thread I will talk about a few things that may be helpful to new users of POL and eScript. They may also benefit long time users as well if you have never read the documentation for POL's built-in modules. It's easy to fall into the trap of assuming a function does only what you think it does because of its name.

Specifically in this first post I will address the uo.em function TargetCoordinates(). When you look at the name you can infer, correctly I might add, that it returns the coordinates that the user targetted. Since TargetCoordinates() contains the word "Coordinates" you can infer this from the more frequently used function Target() which returns the object reference to the object targetted.

But first I need to define some terms:
Items - These are anything that appears in the game world that is not a NPC, player character (PC), a Multi, or a terrain tile.

Static, Static items, and Statically placed items - These are any item that has an ObjType number in the art tile range that comes preset in the map prior to decorating by a staff member. They cannot be moved or destroyed in-game.

Dynamic, Dynamic items, and Dynamically placed items - These are any items placed in the game world by scripts, staff members using in-game commands or by players using crafting skills or some other scripted means of creating items.

In this post by "in the game world" I mean in the readily visible game either on the ground, in a house or in a shoppe. Anything inside a storage container is a dynamic item but for the purpose of this post is not relevant.

Some time ago, Mon Jun 26, 2006 to be exact, OldnGrey asked to have the realm member added to the returned struct when calling the function TargetCoordinates().

You can read the thread if you want to. I bring-up this old topic to make a point, judging a function by only its name can limit what you can do. If you took TargetCoordinates() at face value you might, being new to POL, assume it just returns the x, y, and z coordinates of the player. However it returns a lot of useful informatation, other than just x, y, z, and, (now) realm.

From core-changes.txt:

Code: Select all

06-27-06 MuadDib
        Added : Realm property to return struct of TargetCoordinates() function. This
                is based off the targeter's realm. Never trust information returned
                by the client for stuff like this.

You will note the feature was added the day after the request was made. Those were the days of fairly rapid POL development. Would that was still the case...

In fact place := TargetCoordinates(player) returns the following information in a struct, or "structured data type":
place.x - The x coordinate.
place.y - The y coordinate.
place.z - The z coordinate.
place.realm - The realm player was in when she single-clicked after receiving the target.
place.objtype - The ObjType of the static object, if present, at the location which player targetted.
place.item - An item reference to the dynamic, or placed item, if present, at the location targetted.
place.mobile - A character reference to a mobile, if present, at the targetted location.
place.multi - A Multi reference if the coordinates are inside of a multi.

That is a wealth of useful information. Some of which I will use to show you a neat trick you can do in scripts.

I do not know when the objtype member, item reference, or mobile reference were added but from core-changes we can see when Turley added the multi reference:

Code: Select all

05-02-2009 Turley:
    Added:   new TargetCoordinates return member "multi" with multiref if coords are inside a multi
So great! We have all of this valuable information. What can we do with it you ask?

I ask you this: Have you ever wanted to make a static item "usable"?

Well, with TargetCoordinates() you can, in a round-about way.

In the current Distro mining package you smelt ore by double-clicking, or "using", it and targetting a forge. It uses the Target() function in the smelting script. So you must have a dynamic or "placed" forge to target but what if you wanted to make it possible for players to be able to use a dynamically placed forge or to take advantage of statically placed forges that are already in the world? if you use TargetCoordinates() you can! This also can reduce decoration time for a shard. If there are static forges already present then that means less forges to be placed. Plus if you are concerned about the item count that's another thing, less forge items in your items.txt file.

This is how I implemented this in the upcoming "new Distro":

Code: Select all

	var forge := TargetCoordinates(who);
	var dist := CoordinateDistance(who.x, who.y, forge.x, forge.y);
	// If there is a dynamic item at the location TargetCoordinates() returns the item reference
	// and we make the variable "forge" equal to that.
	// I have to admit eScript's weak variable typing simplifies this and I took advantage of this :P
		forge := forge.item;
	// If there was no item reference then we are still OK because if there was a static item at the location
	// TargetCoordinates() gives the ObjType number of that static item.
	// So we check to see if the ObjType of either the dynamic item or static item matches the ObjTypes of known forges.
	if((forge.objtype == 0xfb1) || forge.objtype := 0x2DD8|| ((forge.objtype >= CInt(0x197a)) && (forge.objtype <= CInt(0x19a9))))
		// We have to check Line Of Sight (LOS) to the targetted location because TargetCoordinates() has no
		// flags for LOS check as does Target().
		if(!CheckLosBetween( who.x, who.y, who.z, forge.x, forge.y, forge.z, who.realm ))
			SendSysMessageCL(who,500876, {}, 3, 33); // You can't see that.
		// If the distance between the player and the forge is greater than 2 squares
		// send the cliloc message "That is too far away." in font 3 colour red.
		// The empty array in SendSysMessageCL is necessary because some cliloc
		// messages can have text inserted in them. See the cliloc.em documentation
		// for more information.
		if(dist > 2)
		SendSysMessageCL(who, 501975, {}, 3, 33); // That is too far away.
Keep in mind this same method can be applied to other items as well. Pitchers of water can be filled from both static and dynamic water barrels for example.

I hope this is helpful to you in programming in eScript. To be honest I was not aware of all of the info returned by TargetCoordinates() until I looked at the docs about a year ago to see if it had LOS check flags. It was then that I discovered just how useful it was and this is just a small example of its usefulness. It pays to read the Documentation.

On a side note about the POL Docs: When I started down the POL road in 2002 we only had a few text documents and the *.em files for documentation and even then no one told me that the *.em files were simple text files I could view for more information. We had the Distro with its eScript programs to learn from but that along with the few text files was it. Around about the time POL 095 was released Racalac showed me a beta version of his POL Documentation page and honestly it brought tears to my eyes. It was beautiful! Of course you all see it all the time if you go to the POL Documentation page. But imagine if all you had were just 3 or 4 text files explaining only a few of the built-in functions and then you were shown the Docs page. Since then Racalac has moved on and is no longer developing for POL but as new functions and features are added to POL the current, and hopefully future, developers expand the Docs to include these new features. If you ask just about any developer, engineer or designer they will tell you documentation is a PAIN. So once again I want to first thank Racalac for creating the first documentation page and just as important I want to offer my continued thanks to the developers for maintaining it and updating it with new information.

Hopefully I will have some more useful tips to add to this thread soon.

User avatar
New User
Posts: 27
Joined: Mon Apr 23, 2018 1:36 pm
Location: Italy

Re: Yukiko's, possibly, helpful or, maybe, little known tips.

Post by ghibli1983 » Wed Jul 18, 2018 7:52 am

Thank you Yukiko, for me is a very Helpful....
Nice post ....

Have a nice day :bacondance:

Distro Developer
Posts: 2824
Joined: Thu Feb 02, 2006 1:41 pm
Location: San Antonio, Texas

Re: Yukiko's, possibly, helpful or, maybe, little known tips.

Post by Yukiko » Tue Mar 05, 2019 8:52 pm

This tip was pointed out to me today by Turley.

We all are in the practice of writing something such as the following to avoid the "Unused variable..." warning from eCompile:

Code: Select all

program onInsert( mobile, container, move_type, insert_type, adding_item, existing_stack, amount_to_add )

	//Avoid compiler warnings
	mobile := mobile;
	container:= FountainOfLife;
	move_type := move_type;
	insert_type := insert_type;
	adding_item := adding_item;
	existing_stack := existing_stack;
	amount_to_add := amount_to_add;
Thanks to the addition of the unused keyword this is no longer necessary

This code can be shortened to:

Code: Select all

program onInsert( unused mobile, unused container, unused move_type, unused insert_type, unused adding_item, unused existing_stack, unused amount_to_add )
Of course, if your programme does use some of those variables like my recently added packages do you should omit the unused keyword preceding the variables your programme uses.

Some more diligent programmers who read the core-changes.txt file may already know about this. I should have, because last year I read through the entire file but somehow I missed, or do not remember seeing this addition.

Code: Select all

08-27-2015 Bodom:
  Added:   New eScript keyword: unused
           This keyword can now be added before a variable name in function or program block declarations.
           It has no effect on the resulting compiled code, but instructs the compiler not to issue a warning if
           the following variable will not be used. The compiler will instead fire a warning if the interested
           variable will then be used later in the code. Examples:
           program onremovescript( character, container, unused item, unused item_amount, movetype )
               // Here the variables item and item_amount are needed in the program declaration but will not be used,
               // the unused keyword prevents warnings to be triggered
           function myfunc( parameter1, unused parameter_for_future_use )
               // Same as above: parameter_for_future_use is not used and unused prevents the warning message

Post Reply