Graal Forums

Graal Forums (https://forums.graalonline.com/forums/index.php)
-   NPC Scripting (https://forums.graalonline.com/forums/forumdisplay.php?f=8)
-   -   Tips and tricks! (https://forums.graalonline.com/forums/showthread.php?t=134257978)

DustyPorViva 02-11-2010 09:17 PM

Tips and tricks!
 
Post various things not exactly documented. I know there is a page on the wiki about it, but all it does is link to various forum threads.


Comparing arrays! You can easily compare two arrays without having to run a loop, provided the two arrays are exactly the same, in the same order. This is good... for example, comparing tiles. Props go to Skyld for teaching me this one, I believe.

if (@this.arrayOne == @this.arrayTwo) // YAY!
or
if (@this.arrayOne == @{0,0,1,1}) // YAY!


This works by converting the arrays into strings, in which Graal simply compares them, much like "foo" == "foo".


Another one that's been floating around is the ability to setAni to specific frames. This is useful sometimes when you need a specific frame of a gani(like a single sword frame), or perhaps scripting your own looping system where you can control the speed of a gani by script. You can use this to duplicate the old player.sprite system.

setAni("sword[3]",null); // MAKE SURE THE VALUE IS PART OF THE STRING!
setAni("walk[" @ foo @ "]",null);
setAni("def[" @ spritenum @ "]",null); // WILL MIMIC player.sprite FROM GS1



Forming dynamic variable names! Probably something anyone who's been scripting for a while knows how to do, but I think is useful for those who are newer to the GS2 scene. You can use variable values to create new variable names.

temp.foo = 1;
temp.var = 2;
client.("data_" @ foo) = "test";
("client.data_" @ var) = "hmm";


What makes this even more powerful is the ability to capture all variables that begin with a certain string:

temp.prefix = "client.data_";
for (temp.i : getstringkeys(prefix) {
..// WILL ECHO THE NAME OF THE VAR AND ITS VALUE
..echo((prefix @ i) @ " : " @ makevar(prefix @ i));
}


For more information on this, the original post may help: http://forums.graalonline.com/forums...70&postcount=6


You can also pass parameters along with attributes. The process is fairly easy:

player.attr[5] = "scriptgani.gani,foo";
player.attr[5] = "scriptgani.gani,foo,hmm";
player.attr[5] = "scriptgani.gani," @ temp.var;
player.attr[5] = "scriptgani.gani," @ temp.var @ "," @ temp.foo;


The original post from Stefan is here: http://forums.graalonline.com/forums...61&postcount=3
Be aware though, that parameters do not update until the attribute is cleared and then reset. This makes it somewhat useless for attributes that are constant(like an HP bar).


This is all I have for now, though it was never even intended to be this long. I'd love to see more posts written that share some more unknown information so we can get it organized and hopefully easy-to-read. Maybe eventually it can be converted into a wiki page in itself(I can't edit the wiki though).

Soala 02-11-2010 09:45 PM

You can make a weapon invisible in your classic inventory (if you don't want to change it) by putting a - before its name, like:

-Playerstuffs

Do I recall correctly ? Been ages I didn't use this duh

Crow 02-11-2010 10:39 PM

That's right Soala, and a * as a prefix will make it show up, but you won't be able to delete in.

Immolate 02-11-2010 11:02 PM

Quote:

Originally Posted by Crow (Post 1555689)
That's right Soala, and a * as a prefix will make it show up, but you won't be able to delete in.

Also bare in mind, although the above techniques are very useful if you keep the default weapon system and inventory GUI, they'll be redundant if you use a customised item and inventory system. Probably better to use your own preferred markers for items that you can't see or delete.

Tigairius 02-12-2010 02:00 AM

+Rep

DustyPorViva 02-12-2010 02:05 AM

Quote:

Originally Posted by Immolate (Post 1555695)
Also bare in mind, although the above techniques are very useful if you keep the default weapon system and inventory GUI, they'll be redundant if you use a customised item and inventory system. Probably better to use your own preferred markers for items that you can't see or delete.

Default Inventory Prefixes:
- : hides the inventory
* : can't be deleted by player
category/itemname : Organizes the weapons in category names.

However, these aren't exactly script functions, so much as client features :)

WhiteDragon 02-12-2010 02:07 AM

Quote:

Originally Posted by DustyPorViva (Post 1555673)
Comparing arrays! You can easily compare two arrays without having to run a loop, provided the two arrays are exactly the same, in the same order.

Although this may be more concise, it also hides what ends up happening. The engine will have to do a loop in order to concatenate the array together, therefore it is still technically a O(n) operation.

DustyPorViva 02-12-2010 02:09 AM

Quote:

Originally Posted by WhiteDragon (Post 1555735)
Although this may be more concise, it also hides what ends up happening. The engine will have to do a loop in order to concatenate the array together, therefore it is still technically a O(n) operation.

Better done by the engine than by script.

fowlplay4 02-12-2010 02:14 AM

Dynamic function calling.

I.e:
PHP Code:

function onCreated() {
  
temp.func "dispWorld";
  
temp.parm "Hello";
  (@
temp.func)(temp.parm);
}

function 
dispWorld(greeting) {
  echo(
format("%s World!"greeting)); // Echos "Hello World!"



Crow 02-12-2010 04:01 PM

Another handy thing is assigning WNPCs to vars. Let's say you got the following in -System/Inventory:
PHP Code:

//#CLIENTSIDE
function onCreated() {
  
inventory this;
  
// more stuff..
}

public function 
Toggle() {
  
// toggle


Then you could do something like this in -System/InputHandler:
PHP Code:

//#CLIENTSIDE
function HandleKey(key) {  // careful, I made this one up, assuming it was implemented in the WNPC earlier
  
if (key == "q")
    
inventory.Toggle();
  
// probably more stuff..



12171217 02-12-2010 05:41 PM

It was playersprite, not player.sprite :0

DustyPorViva 02-12-2010 05:47 PM

Quote:

Originally Posted by 12171217 (Post 1555807)
It was playersprite, not player.sprite :0

Well it's player.sprite now :P

calani 02-14-2010 10:21 AM

Quote:

Originally Posted by Crow
stuff

Handy.
I see uses.

Deas_Voice 05-30-2010 03:21 AM

bump for requesting stickythready.

adam 05-30-2010 03:30 AM

Quote:

Originally Posted by Deas_Voice (Post 1579334)
bump for requesting stickythready.

I second.

cbk1994 05-30-2010 03:52 AM

Tips for creating resizable GUI controls

The variables "vertSizing" and "horizSizing" let you easily make GUI controls that resize when the parent control resizes.

vertSizing is usually either "height" or "top". A value of "height" will change the height of the control as the height of the parent control changes. A value of "top" will move the control down as the parent control's height changes.

horizSizing is usually either "width" or "height". A value of "width" will change the width of the control as the width of the parent control changes. A value of "left" will move the control to the right as the width of the parent control changes.

These can be combined to do most kinds of resizing schemes.

PHP Code:

//#CLIENTSIDE
function onCreated() {
  new 
GuiWindowCtrl("Test_Window") {
    
profile GuiBlueWindowProfile;
    
    
clientRelative true;
    
    
clientWidth 300;
    
clientHeight 300;
    
    
= (GraalControl.width width) / 2;
    
= (GraalControl.height height) / 2;
    
    
text "Test Window";
    
    new 
GuiControl("Test_Object1") {
      
useOwnProfile true;
      
      
profile.opaque true;
      
profile.fillColor = {100100100};
      
      
width 100;
      
height 215;
      
      
5;
      
5;
      
      
// do nothing as the window grows wider
      
horizSizing "";
      
      
// grow taller as the window grows taller
      
vertSizing "height";
    }
    
    new 
GuiControl("Test_Object2") {
      
useOwnProfile true;
      
      
profile.opaque true;
      
profile.fillColor = {150100200};
      
      
width 185;
      
height 215;
      
      
110;
      
5;
      
      
// grow wider as the window grows wider
      
horizSizing "width";
      
      
// grow taller as the window grows taller
      
vertSizing "height";
    }
    
    new 
GuiControl("Test_Object3") {
      
useOwnProfile true;
      
      
profile.opaque true;
      
profile.fillColor = {150100100};
      
      
width 290;
      
height 70;
      
      
5;
      
225;
      
      
// grow wider as the window grows wider
      
horizSizing "width";
      
      
// move down as the window grows taller
      
vertSizing "top";
    }
  }


produces this:

http://img85.imageshack.us/img85/6418/guiexamples.png

There are also other values for vertSizing and horizSizing, but I have never needed to use them. Their names should be self-explanatory.

Quote:

GuiControl.horizsizing - string - specifies the horizontal resizing behaviour when the parent control is resized: right, width, left, center or relative
GuiControl.vertsizing - string - specifies the vertical resizing behaviour when the parent control is resized: bottom, height, top, center or relative


Creating custom objects types
While it's not really possible to create custom object types, you can use a few tricks to replicate the functionality.

For example, let's say you're making a mail system for players to send mail back and forth, but also for scripts to send mail to players. You could do this by joining a class to every script that needs to send mail or by using a public function, but there's an even cleaner way.

First, you will need a database NPC to make the object.

PHP Code:

// database NPC "Mail"
function onCreated() {
  
MailMessage = new TStaticVar();
  
MailMessage.join("mail_message");
}

// recreate the object when the server restarts
function onInitialized() {
  
this.onCreated();


What this does is makes a global object with the name "MailMessage" and joins it to the class "mail_message". Inside the class "mail_message" we can have functions.

PHP Code:

public function send() {
  
// replace this with the code to store the message
  
printf("Sending a message to '%s' from '%s' with subject '%s' and message '%s'."thisrecipientthis.senderthis.subjectthis.text);


Now, from any script you can do the following to send a mail message:

PHP Code:

temp.msg = new MailMessage();

msg.recipient "cbk1994";
msg.sender "(npcserver)";
msg.subject "Hello world!";
msg.text "Did it work?";

msg.send(); 

This technique can be used both serverside and clientside. It is especially useful for cases where passing parameters as an array would be inconvenient. I wrote a custom projectile script a few weeks back that used the same syntax as the mail message script above for parameters like "angle". It's a lot more coder-friendly than "shoot(32, 42, 0.4, 0, 0, ...)"

Cloven 05-30-2010 04:03 AM

Nice job. :)

DustyPorViva 05-30-2010 04:23 AM

Those gui sizings are pretty awesome :)

adam 05-30-2010 07:02 AM

Nice work man. I am very pleased!

xAndrewx 05-30-2010 11:13 AM

Haha, on my mail system I've done exactly the same as you, weird :p

Good job, learned about the re-sizing :) (would rep but can't)

Deas_Voice 05-31-2010 03:01 PM

nice, didn't know about the re-sizing stuff.

why haven't this thread been stickied yet? )=

Deas_Voice 09-13-2010 05:58 PM

bump, still not stickied! :\

Jiroxys7 09-13-2010 10:29 PM

Quote:

Originally Posted by DustyPorViva (Post 1555734)
Default Inventory Prefixes:
- : hides the inventory
* : can't be deleted by player
category/itemname : Organizes the weapons in category names.

However, these aren't exactly script functions, so much as client features :)

I've seen people using + and $ too. does this actually provide any features? or was it probably just used for other scripting purposes?

DustyPorViva 09-13-2010 10:33 PM

Quote:

Originally Posted by Jiroxys7 (Post 1600578)
I've seen people using + and $ too. does this actually provide any features? or was it probably just used for other scripting purposes?

They're either using it for their own scripting purposes, or doing so to manipulate the alphabetical order of the weapon list. Using certain characters at the beginning of the weapon name will ensure a WNPC is at the top of the weapon list in RC, usually for organizational purposes(easier to find more important weapons). Otherwise people tend to use special characters to denote various scripted organization of items. For example, if they use a custom MUD inventory, they may prefix items with +, weapons with $ and so on.

Deas_Voice 01-21-2011 10:38 PM

WHY haven't this awesome thread been stickied yet?!

fowlplay4 01-21-2011 11:30 PM

Quote:

Originally Posted by Deas_Voice (Post 1624687)
WHY haven't this awesome thread been stickied yet?!

Not enough tips n tricks, and you keep bumping it anyway.

I still think someone needs to compile all the documentation on the forums and populate the Wiki(s) with it.

First step: Compile list of helpful posts. (Any reply in the NPC-Scripting forum with [PHP] or [HTML] tags by someone who knows what they're doing usually)

cbk1994 01-22-2011 01:12 AM

Quote:

Originally Posted by fowlplay4 (Post 1624690)
Compile list of helpful posts. (Any reply in the NPC-Scripting forum with [PHP] or [HTML] tags by someone who knows what they're doing usually)

Here's an incomplete list of helpful posts, in no particular order:

Again, this is an incomplete list. The only reason there are so many of mine is because I tend to bookmark posts I make that I think I might need again.

oo_jazz_oo 01-22-2011 01:39 AM

After Tig said about the new playerlist having pm windows open in the middle of the screen, I asked him how he did this. Apparently Stefan had said how to at some point?
But it went unnoticed (to me at least). I think some people will find it helpful.

PHP Code:

externalwindow.x
externalwindow
.

Inside the gui control, of course. :)

(However, it seems when the window is initially created, it ignores the external.x/y position...and you need to set those after the window is visisble)

Found the post! http://forums.graalonline.com/forums...&postcount=746

fowlplay4 01-22-2011 02:10 AM

Quote:

Originally Posted by oo_jazz_oo (Post 1624719)
PHP Code:

externalwindow.x
externalwindow
.

Inside the gui control, of course. :)

(However, it seems when the window is initially created, it ignores the external.x/y position...and you need to set those after the window is visisble)

Found the post! http://forums.graalonline.com/forums...&postcount=746


Just thought I'd elaborate on your example there:

PHP Code:

//#CLIENTSIDE

function onCreated() {
  
createGUI();
}

function 
createGUI() {
  
// Destroy Existing Window for Testing purposes
  
if (isObject("HelloExample")) {
    
HelloExample.destroy();
  }
  
// Create Window
  
new GuiWindowCtrl("HelloExample") {
    
0;
    
0;
    
width 200;
    
height 200;
    
text "Hello World!";
    
profile GuiBlueWindowProfile;
    
isexternal true;
    
visible true;
    
externalwindow.30;
    
externalwindow.30;
  }
  
// Update Windows External X, Y
  // Work-around for current bug that causes it to ignore
  // external window values when created.
  
this.trigger("UpdateWindow""");
}

function 
onUpdateWindow() {
  
with (HelloExample) {
    
with (externalwindow) {
      
// Centers GUI in middle of screen.
      
= (screenwidth width) / 2;
      
= (screenheight height) / 2;
    }
  }



Cubical 02-11-2011 12:39 PM

Quote:

Originally Posted by cbk1994 (Post 1624710)
Here's an incomplete list of helpful posts, in no particular order:

Again, this is an incomplete list. The only reason there are so many of mine is because I tend to bookmark posts I make that I think I might need again.

This should be reposted and stickied with the addition of a few of Dusty and WhiteDragons post.

cbk1994 09-28-2011 07:29 AM

I've moved the list of helpful posts to the wiki, added some new links, and categorized them. It'd be nice if new useful posts were added to this list in the future.

If anybody would like to add, please just edit the page. If you don't have wiki access, I'll be happy to make the edits for you (post here or PM me).

scriptless 10-03-2011 03:45 AM

I found this helpfull, also thanks cbk1994 I need to study the wiki some more.

DustyPorViva 06-22-2013 05:18 AM

On the clientside, using the setshape2 value of 5 lets you define NPCs with a shape that can be interacted with but doesn't block the player.

PHP Code:

setshape2(4,4,{
  
5,5,5,5,
  
5,5,5,5,
  
5,5,5,5,
  
5,5,5,5,
}); 

Not insanely useful, but I found it useful when you want NPCs to interact with touching/hitting without necessarily blocking the player(like baddies, doors and such).

scriptless 06-22-2013 08:20 PM

Quote:

Originally Posted by DustyPorViva (Post 1719512)
On the clientside, using the setshape2 value of 5 lets you define NPCs with a shape that can be interacted with but doesn't block the player.

PHP Code:

setshape2(4,4,{
  
5,5,5,5,
  
5,5,5,5,
  
5,5,5,5,
  
5,5,5,5,
}); 

Not insanely useful, but I found it useful when you want NPCs to interact with touching/hitting without necessarily blocking the player(like baddies, doors and such).

Is there any documentation, good documentation on setshape2()? I always have troubles using it due to lack of understanding what all the numbers are for.

cbk1994 06-22-2013 08:59 PM

Quote:

Originally Posted by scriptless (Post 1719559)
Is there any documentation, good documentation on setshape2()? I always have troubles using it due to lack of understanding what all the numbers are for.

Same numbers as tiletype: http://www.graal.net/index.php/Creat...tions/tiletype

scriptless 06-23-2013 02:43 AM

Quote:

Originally Posted by cbk1994 (Post 1719560)

Oh, so I think I understand now. You set a height and width in a grid and then assign a value to each. Always wondered about that. Thanks!!

Chompy 06-26-2013 04:46 PM

Here's a little tip for understanding the options part of move(), showstats(), enablefeatures() etc and how it works:

If these functions are known to you, you might have noticed the build up of the options going like this

1 + 2 + 4 + 8 + 16 + 32 + 64 + 128 + 256 + 512 + 1024 + 2048 ETC ETC

Basically you can create any numbers using the numbers given above

31 = 1 + 2 + 4 + 8 + 16
30 = 2 + 4 + 8 + 16
29 = 1 + 4 + 8 + 16

Following? Now, why are those functions using numbers like that? Why not use normal numbers from 1 to 10 for example? To answer that, let me set an example up:

PHP Code:

/*
  createNPC(x, y, type, options)
  options:
    1 = randomized look?
    2 = roam around
    3 = hunt and hurt players
*/
function onCreated() {
  
createNPC(xy"baddy"2); // randomized look + roam around

  
createNPC(xy"baddy"3); // function as enemy to the player, hunt & kill
}

function 
createNPC(npcxnpcynpctypeoptions) {
  
// how to tell the difference between 1+2 (randomized look + roam around)
  // and 3 (hunt players and hurt them
  
  
temp.npc putnpc2(npcxnpcy"");
  if (
options == 1+2) {
    
// just give up here and start over., ok?
    //the script can't tell the difference between 1+2 and 3



Now, how can it be done instead? Well, yeah, you use the numbers given further up this post and do like this:

PHP Code:

/*
  createNPC(x, y, type, options)
  options:
    1 = randomized look?
    2 = roam around
    4 =  function as enemy to the player
*/
function onCreated() {
  
createNPC(xy"baddy"2); // randomized look + roam around

  
createNPC(xy"baddy"4); // function as enemy to the player, hunt & kill
}

function 
createNPC(npcxnpcynpctypeoptions) {
  
temp.npc putnpc2(npcxnpcy"");
  
temp.npc.join("npc_"npctype); // would join npc_baddy
  
temp.npc.type npctype;

  if (
options&1temp.npc.join("npc_module_randomizedlook");
  if (
options&2temp.npc.join("npc_module_roam");
  if (
options&4temp.npc.join("npc_module_enemyai");


By using the & operator you can simply check if a bit value exists within the specified bit value given.

so instead of doing something like createNPC(x, y, type, true, true, false);, or set up predefined options, use this method instead! :)


All times are GMT +2. The time now is 07:31 AM.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2026, vBulletin Solutions Inc.
Copyright (C) 1998-2019 Toonslab All Rights Reserved.