Graal Forums  

Go Back   Graal Forums > Development Forums > NPC Scripting > Code Gallery
FAQ Members List Calendar Today's Posts

Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old 04-04-2007, 08:03 PM
Gambet Gambet is offline
Registered User
Join Date: Oct 2003
Posts: 2,712
Gambet is on a distinguished road
Point and Copy: Cloning Device

PHP Code:
//Point and Copy: Cloning Device
//By: Gambet

//#CLIENTSIDE
function onKeyPressed(keycode)
{
 if (
keycode == 305//Press and hold shift then press 1
  
{
    
this.cloner_on = !this.cloner_on;
    
player.chat "Outfit Cloner: " @ (this.cloner_on "On" "Off");  
  }
}

function 
onMouseDown(button)
{
 if (
button == "double")
  {
   if (
this.cloner_on)
    {
     if (
timevar2 >= this.cooldown)
      {
       for (
pplayers)
        {
         if (
mousex in |p.x,p.x+1.5| && mousey in |p.y,p.y+2|)
          {
           for (
t=0t<5t++)
            {
             
player.colors[t] = p.colors[t];
            }
            
player.headimg p.headimg;
            
player.shieldimg p.shieldimg;
            
player.bodyimg p.bodyimg;
            
player.chat "Cloning Successful!";
            
this.cooldown int(timevar2 10);
          }
        }
       for (
nnpcs)
        {
         if (
mousex in |n.x,n.x+1.5| && mousey in |n.y,n.y+2|)
          {
           for (
u=0u<5u++)
            {
             
player.colors[u] = n.colors[u];
            }
            
player.headimg n.headimg;
            
player.shieldimg n.shieldimg;
            
player.bodyimg n.bodyimg;
            
player.chat "Cloning Successful!";
            
this.cooldown int(timevar2 10);
          }
        }
      }
     else
      {
       
player.chat "You must wait " abs(int(timevar2 this.cooldown)) @ " more seconds!";
      }  
    }
  }



I havn't tested it, but it should work.


Now, from the looks of it, it's a simple NPC, yes, but it's good enough for the new scripters to learn some of the basics.


Let me break it down:


This NPC shows a good way of using the keypressed function as a source for finding keycodes by designating such in the functions parameters. I used a weird combination to show that it's possible to use key combinations to perform different tasks.

This NPC also shows a good way of setting up a variable to be defined as the mouse button that the player presses in the mousedown function. You can basically put anything inside the parameters and use it to read if the player has pressed the "left" mouse button, "right" mouse button, "double" mouse button (I.E double click), and "middle" mouse button (I.E pressed on the scroll ball). Once you define this, reading what mouse button the player clicked is easy, as displayed above.

This NPC also shows a good way of using timevar2 as a cooldown device, without the need of using a timeout. You can use timevar2 for most cooldown systems as an alternative to timeouts, which will decrease the amount of CPU time that your system takes. As you see here, I created a cooldown system without the need of a timeout, which is more efficient when it comes to lag.

This NPC also shows a way of looping through all of the players and NPCs in order to perform certain tasks that you'd wish to designate.

This NPC also shows how you can manipulate certain events that will in turn cause an NPC and/or player to act as you'd like. In this case, I check to see if when the player double clicks their mouse, if their mouse position is within a certain range of a player or NPC, then the person will end up copying the outfit of the player or NPC. You can use this method to perform plenty of tasks, not just copying attire.

And finally, this NPC also shows a good way of using a loop to loop through a player/npcs clothes colors without the need of separate this.colors[0], this.colors[1], etc. lines. You can use loops to do a lot of things much faster and more efficiently, such as when reading what keys the player pressed and so forth.


Though it is simple to those experienced, it can actually teach the newer scripters quite a few things on how to work with several functions and so forth to make scripting a bit easier and more efficient. I scripted this NPC simply for educational purposes, though it can also be used for what it is, which is a cloning device.


NOTE: If the designated NPC is not a character, then your outfit will be set to the default noob outfit.



Hope this helps,


Enjoy

Last edited by Gambet; 04-04-2007 at 09:12 PM..
Reply With Quote
  #2  
Old 04-04-2007, 08:46 PM
Skyld Skyld is offline
Script-fu
Skyld's Avatar
Join Date: Jan 2002
Location: United Kingdom
Posts: 3,914
Skyld has much to be proud ofSkyld has much to be proud ofSkyld has much to be proud ofSkyld has much to be proud ofSkyld has much to be proud ofSkyld has much to be proud of
Send a message via AIM to Skyld
Just at a quick glance:
PHP Code:
   if (!this.cloner_on)
    {
     
this.cloner_on true;
     
player.chat "Outfit Cloner: On";
    }
   else
    {
     
this.cloner_on false;
     
player.chat "Outfit Cloner: Off";
    } 
... had might as well be:
PHP Code:
this.cloner_on = !this.cloner_on;
player.chat "Outfit Cloner: " @ (this.cloner_on "On" "Off"); 
Also.
PHP Code:
       for (pplayers)
        {
         for (
nnpcs)
          { 
Do you need to scan every NPC for every player? Can't you just scan them once?

Finally, can't you prefix your temp vars with temp.?
__________________
Skyld
Reply With Quote
  #3  
Old 04-04-2007, 08:51 PM
Gambet Gambet is offline
Registered User
Join Date: Oct 2003
Posts: 2,712
Gambet is on a distinguished road
Quote:
Originally Posted by Skyld View Post
... had might as well be:
PHP Code:
this.cloner_on = !this.cloner_on;
player.chat "Outfit Cloner: " @ (this.cloner_on "On" "Off"); 
I'd actually appreciate it if you'd explain that to me since I never understood how that worked.

Quote:
Originally Posted by Skyld View Post
Also.
PHP Code:
       for (pplayers)
        {
         for (
nnpcs)
          { 
Do you need to scan every NPC for every player? Can't you just scan them once?
It scans all of the players in the level and all of the npcs in the level if you have the npc on and you double click. It does this to be able to compare the person that triggered its mouse position to see if it falls within the range to clone the object.

I don't seem to be understanding where you're coming from, mind elaborating a bit?

Quote:
Originally Posted by Skyld View Post
Finally, can't you prefix your temp vars with temp.?
I guess

But does it make a difference? From my experience this. temp vars can be used throughout the NPC whereas temp vars can't unless you send them over through the parameters of a function.
Reply With Quote
  #4  
Old 04-04-2007, 08:58 PM
Skyld Skyld is offline
Script-fu
Skyld's Avatar
Join Date: Jan 2002
Location: United Kingdom
Posts: 3,914
Skyld has much to be proud ofSkyld has much to be proud ofSkyld has much to be proud ofSkyld has much to be proud ofSkyld has much to be proud ofSkyld has much to be proud of
Send a message via AIM to Skyld
Quote:
Originally Posted by Gambet View Post
I'd actually appreciate it if you'd explain that to me since I never understood how that worked.
Sure.
temp.var = !temp.var;
If you are working with just true and false, then this is basically a switch. Because temp.var uninitialized is 0 (false), then !0 is 1 (true), therefore !temp.var == true. Now, if temp.var is 1 (true), then !1 is 0 (false), therefore !temp.var == false.

echo(temp.foo ? "bar" : "baz");
This basically just checks if temp.foo (or any expression, even player.chat == "foo" or so) is true, and returns "bar" if it's true, and "baz" if it isn't.
Quote:
Originally Posted by Gambet
It scans all of the players in the level and all of the npcs in the level if you have the npc on and you double click. It does this to be able to compare the person that triggered its mouse position to see if it falls within the range to clone the object.

I don't seem to be understanding where you're coming from, mind elaborating a bit?
Well, your loop appears to be scanning every NPC in the level for every player in the level.

Say me, you and Stefan are in the level. It'll first pick me up, and scan every NPC. It'll then move on to you, and scan every NPC. It'll finally move onto Stefan and scan every NPC.

I don't think you need to scan the NPCs as many times as there are players in the level.
Quote:
Originally Posted by Gambet
I guess

But does it make a difference? From my experience this. temp vars can be used throughout the NPC whereas temp vars can't unless you send them over through the parameters of a function.
this. variables are accessible in the NPC, and temp. variables are destroyed at the end of the function. If you don't need the variable after the end of the function, then just use temp.
__________________
Skyld
Reply With Quote
  #5  
Old 04-04-2007, 09:04 PM
Gambet Gambet is offline
Registered User
Join Date: Oct 2003
Posts: 2,712
Gambet is on a distinguished road
Quote:
Originally Posted by Skyld View Post
Sure.
temp.var = !temp.var;
If you are working with just true and false, then this is basically a switch. Because temp.var uninitialized is 0 (false), then !0 is 1 (true), therefore !temp.var == true. Now, if temp.var is 1 (true), then !1 is 0 (false), therefore !temp.var == false.

echo(temp.foo ? "bar" : "baz");
This basically just checks if temp.foo (or any expression, even player.chat == "foo" or so) is true, and returns "bar" if it's true, and "baz" if it isn't.

Ah, thanks. Will try to keep that in mind from now on.


Quote:
Originally Posted by Skyld View Post
Well, your loop appears to be scanning every NPC in the level for every player in the level.

Say me, you and Stefan are in the level. It'll first pick me up, and scan every NPC. It'll then move on to you, and scan every NPC. It'll finally move onto Stefan and scan every NPC.

I don't think you need to scan the NPCs as many times as there are players in the level.

How would you recommend doing it then? Separating the loops?
Reply With Quote
  #6  
Old 04-04-2007, 09:05 PM
Skyld Skyld is offline
Script-fu
Skyld's Avatar
Join Date: Jan 2002
Location: United Kingdom
Posts: 3,914
Skyld has much to be proud ofSkyld has much to be proud ofSkyld has much to be proud ofSkyld has much to be proud ofSkyld has much to be proud ofSkyld has much to be proud of
Send a message via AIM to Skyld
Quote:
Originally Posted by Gambet View Post
How would you recommend doing it then?
Well, presumably you would want to run over the players once, and THEN over the NPCs in the level, so you could have your player loop processing players, and then your NPC loop afterwards processing NPCs.
__________________
Skyld
Reply With Quote
  #7  
Old 04-04-2007, 09:42 PM
Kristi Kristi is offline
Bowie's Deciple
Kristi's Avatar
Join Date: Dec 2003
Location: Boston, MA
Posts: 748
Kristi has a spectacular aura aboutKristi has a spectacular aura about
Send a message via AIM to Kristi Send a message via MSN to Kristi
Skyld threw in his critques but ill put mine in anyway
PHP Code:
//Point and Copy: Cloning Device
//By: Gambet
//Notes by Hell Raven

//#CLIENTSIDE
function onKeyPressed(keycode) {
  if (
keycode == 305) {
    
// If possible, we do not want to test unneccessary conditions
    // !true = false, and !false = true, so this will make if the opposite
    // of what it is.
    
this.cloner_on = !this.cloner_on;

    
// Now we are setting the player's chat to Outfit Cloner: Off or On
    // We have an array containing {"Off","On"}, where off is
    // element 0, and on is element 1. False = 0 and True = 1,
    // so this works.
    
player.chat "Outfit Cloner:" SPC ({"Off","On"})[this.cloner_on];
  }
}

function 
onMouseDown(button) {
  
// Condition really belongs on one line
  // Check the most likely false condition first
  // To optimize resources.
  
if (button == "double" && this.cloner_on) {

    
// Cut short if we have not "cooled down" yet.
    
if(timevar2 this.cooldown) {
      
player.chat "You must wait " abs(int(timevar2 this.cooldown)) @ " more seconds!";
      return; 
//Exit function
    
}
    
    
// You originally had the npc loop nested inside the player loop.
    // That means you checked all the npcs again everytime
    // you switched to a different player. That is bad :x
    
    // See if any player is in clone range
    
for (pplayers)
      if (
mousex in |p.x,p.x+1.5| && mousey in |p.y,p.y+2|) {
        
cloneobj(player,p);
        
this.cooldown timevar2 10;
        
player.chat "Cloning Successful!";
        return; 
// We have cloned so we do not need to look anymore.
      
}
    
    
// See if any npc is in clone range 
    // note, we check for ani so we do not clone npcs that aren't showchars.   
    
for (nnpcs)
      if (
n.ani != null && mousex in |n.x,n.x+1.5| && mousey in |n.y,n.y+2|) {
        
cloneobj(player,n);
        
this.cooldown timevar2 10;
        
player.chat "Cloning Successful!" n.ani;
        return; 
// We have cloned so we do not need to look anymore
      
}
  }
}

function 
cloneObj(copycat,original) {
  
// makes copycat look like original :D

  // the colors array cannot be set at once, for some reason
  
for(temp.0temp.<=5temp.i++)
    
copycat.colors[temp.i] = original.colors[temp.i];

  
copycat.head   original.head;
  
copycat.sword  original.sword;
  
copycat.body   original.body;
  
copycat.shield original.shield;

You should make functions for certain things, like a player clone. honestly it should be a class attacked to a player, to do player.clone(obj), but we are keeping it in one weapon.

The nested loop was something i pointed out to skyld. isntead of
for(players) {
for(npcs) {
}
}
we want
for (players) {
}
for (npcs) {
}

We want to return when we have achieved our goal, so we are not achieving it multiple times (in my opinion).

Also, i threw in a check to make sure the npc was a character.

The rest of my notes are in the script.
__________________
Reply With Quote
  #8  
Old 04-04-2007, 09:04 PM
Rapidwolve Rapidwolve is offline
Registered User
Join Date: Jul 2006
Posts: 1,241
Rapidwolve is an unknown quantity at this point
PHP Code:
echo(temp.foo "bar" "baz"
that is a called conditional.
if-then-else

So if temp.foo is true, then that code will output "bar" else it will output "baz"
Reply With Quote
  #9  
Old 04-04-2007, 10:07 PM
Gambet Gambet is offline
Registered User
Join Date: Oct 2003
Posts: 2,712
Gambet is on a distinguished road
"Conditions belong on one line" is completely opinion based and it all depends on the scripters style.


I, for one, find it more efficient to style as I do simply because it's easy to go back and edit things or add on things if needed. If you put the condition bracket on the same line then you fall in risk of losing your bracket positioning and possibly missing brackets or having too many.

Plus, this way looks a lot more clean IMO.


As for the character check for the NPCs, it doesn't really matter, since if it's not a character it'll set you to the default noob body, which isn't exactly a problem or anything. It's a fast way to get the noob body on for people that want it, though


Also, I try to separate condition statements for a reason. I don't really care about line length, moreso I care about flexibility. By separating your condition statements, it makes it easy to add else checks later on if you need to, without having to separate it at a later date and re-align the entire script just because you wanted to save a few lines in the beginning. It's not really lengthy at all with the way I style since everything is clearly presented. It's just easier to manage if you need to go back to it later on and fix or add-on anything.
Reply With Quote
  #10  
Old 04-04-2007, 10:09 PM
Kristi Kristi is offline
Bowie's Deciple
Kristi's Avatar
Join Date: Dec 2003
Location: Boston, MA
Posts: 748
Kristi has a spectacular aura aboutKristi has a spectacular aura about
Send a message via AIM to Kristi Send a message via MSN to Kristi
I guess nested Ifs come down to mere preference, I like not tabbing my code that far over.
__________________
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 10:56 PM.


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