Graal Forums

Graal Forums (https://forums.graalonline.com/forums/index.php)
-   Code Gallery (https://forums.graalonline.com/forums/forumdisplay.php?f=179)
-   -   Simple Warp/Summon (https://forums.graalonline.com/forums/showthread.php?t=134262611)

PhilSmith 03-29-2011 04:09 PM

Simple Warp/Summon
 
I just created this script and thought it was nice. It is my first actual code so I come here seeking advice, suggestions, and perhaps ways to make the script simpler. I am in no way trying to show off the usefulness of this script, I was merely making it for practice. I know it may be pointless, however, that is not what is in question here. Save yourself some time and a post if you are going to say that :)

Functions:
-Obvious summon and warping ability ("/warp name" or "/summon name")
-Can find players based on partial names (instead of "PhilSmith" it could work with "Phil" or "P")
-when using a partial name, it logs all the names found in an array. If one name is found, it warps/summons. If zero names are found, it says"No Players Found". If more than one name are found, it pms the array to the player.

PHP Code:

// Scripted by Phil Smith
function onActionServerSide(){
//for loop to find all players and their partial nicks
  
for(temp.pl allplayers){
    if(
params[0]==temp.pl.substring(0,params[0].length())|| params[0]==temp.pl.nick.substring(0,params[0].length())){
      if (
temp.pl.level!=NULL){ //if player is not on rc
        
this.fnd=temp.pl;
        
temp.foundplayer.add(temp.pl); //logs the player into the array
      
}
    }
  }
  if (
temp.foundplayer.size()==1){
    
onPlayerFound();
  }
  else if(
temp.playerfound.size==0){
    
player.chat="No Players Found!";
  }
  
//more than one players are found
  
else{ player.chat="More than one player found! Check your PM for options.";
    
player.sendPM(temp.foundplayer.size() SPC "players were found:" NL temp.foundplayer NL "" NL "" NL "Tip: Be sure to type in the player's name/account as specific as possible in order to find them easier!");
  }
}
//carries out the warp/summon
function onPlayerFound(){
  if (
params[1].starts("/summon")){
    
this.fnd.setlevel2(player.level,player.x,player.y);
    
updateboard(0,0,64,64);
    
this.fnd.chat="Summoned!";
  }
  if (
params[1].starts("/warp")){
    
setlevel2(this.fnd.level,this.fnd.x,this.fnd.y);
    
player.chat="Warped!";
  }
}
//#CLIENTSIDE
function onPlayerChats(){
  if(
player.chat.starts("/warp")){
    
tokens=player.chat.substring(6);
    
triggerserver("weapon",this.name,tokens,player.chat);
  }
  if(
player.chat.starts("/summon")){
    
tokens=player.chat.substring(8);
    
triggerserver("weapon",this.name,tokens,player.chat);
  }


Thanks for taking the time to submit useful feedback and suggestions!:D

fowlplay4 03-29-2011 04:25 PM

It's not really a big deal but you can do the "search" processing on the client-side.

Then in the case of multiple results, you can just display a dialog and have the player select who they wanted to summon.

I would suggest using.. string.starts("text") or string.pos("text") for checking for partials. I.e:

PHP Code:

function onCreated() {
  
temp.str "loltextlmao";
  echo(
temp.str.pos("text")); // echos 3 (found == position >= 0)
  
echo(temp.str.pos("rofl")); // echos -1 (not found)
  
echo(temp.str.starts("lol")); // echos 1 (found)
  
echo(temp.str.starts("lmao")); // echos 0 (not found)


Also in your check... you should have community name support as well. Another thing when searching you should probably check them all in lowercase or uppercase. I.e:

PHP Code:

function onCreated() {
  
temp.exact "Phil";
  
temp.cond temp.exact.lower();
  
temp.matches = {};
  for (
aallplayers) {
    
// Skip RCs
    
if (a.level == NULL) continue;
    
// Check for Exact Match
    
if (a.account == temp.exact || a.communityname == temp.exact) {
      
temp.found a.account;
      break;
    }
    
// Check for Partials
    
if (a.account.lower().pos(temp.cond) >= || a.communityname.lower().pos(temp.cond) >= || a.nick.lower().pos(temp.cond) >= 0) {
      
temp.matches.add(a.account);
    } 
  }
  if (
temp.found != "") {
    echo(
"Found... " temp.found);
  } else {
    echo(
"Other matches... " temp.matches);
  }



PhilSmith 03-29-2011 04:35 PM

I did have just the dialog, but the problem was, was that the player.chat reset after like 2 seconds. I thought this was not enough time so i ended up pming it. if there is a way to keep the text from resetting, I'm all ears.

And just after i posted this i realized i forgot community names. I'm working on those :D

WhiteDragon 03-29-2011 04:38 PM

PHP Code:

function onActionServerSide() {
  
temp.foundPlayers = {};
  for (
temp.pl allplayers) {
    if ( (     
params[0] == temp.pl.account.substring(0params[0].length())
            || 
params[0] == temp.pl.nick.substring(0params[0].length())
          ) && 
temp.pl.level != NULL) {
      
temp.foundPlayers.add(temp.pl);
    }
  }
  
temp.temp.foundPlayers.size();
  if (
temp.1) {
    
player.chat "More than one player found! Check your PM for options.";
    
player.sendPM("Multiple players were found:" NL temp.foundPlayers NL "" NL "" NL "Tip: Be sure to type in the player's name/account as specific as possible in order to find them easier!");
  } else if (
temp.== 1) {
    
playerFound(params[1], temp.foundPlayers[0]);
  } else {
    
player.chat "No Players Found!";
  }
}
function 
playerFound(temp.actionTypetemp.pl) {
  if (
temp.actionType == "summon") {
    
temp.pl.setlevel2(player.levelplayer.xplayer.y);
    
updateboard(006464);
    
temp.pl.chat "Summoned!";
  } else if (
temp.actionType == "warp") {
    
setlevel2(temp.pl.leveltemp.pl.xtemp.pl.y);
    
player.chat "Warped!";
  }
}

//#CLIENTSIDE
function onPlayerChats(){
  if (
player.chat.starts("/warp")) {
    
triggerserver("weapon"this.nameplayer.chat.substring(6), "warp");
  } else if (
player.chat.starts("/summon")) {
    
triggerserver("weapon"this.nameplayer.chat.substring(8), "summon");
  }


Here is my "code clarity" edit (I kept the logic the same). Feel free to ask any questions.


Note: interestingly enough, that loop at the beginning of the code has a name: filter. I have wrapped up some common patterns such as filter in this thread. With my code the first loop would simply be:
PHP Code:

  temp.= function (temp.pl) {
    return (
params[0] == temp.pl.account.substring(0params[0].length()) || params[0] == temp.pl.nick.substring(0params[0].length())) && temp.pl.level != NULL;
  };
  
temp.foundPlayers filter(temp.fallplayers); 


cbk1994 03-29-2011 04:41 PM

It's not bad at all, but there are some things that can be improved.

PHP Code:

if(params[0]==temp.pl.substring(0,params[0].length())|| params[0]==temp.pl.nick.substring(0,params[0].length())){ 

There are a couple of issues with this line.

You can improve the substring check by using str.starts(substring). I doubt it's really any more efficient but it's semantically better as it makes your purpose clearer to the reader.

PHP Code:

if(temp.pl.starts(params[0]) || temp.pl.nick.starts(params[0])){ 

The other problem is that temp.pl is referring to the actual player object right now, not their account. The reason it works as-is is that Graal internally converts objects to strings when necessary by using the object's name, which happens to be the player's account name. It's better practice to do it like so (note I'm using temp.pl.communityName):

PHP Code:

temp.pl.communityName.starts(params[0]) 

You should also fix this where you're sending a PM.

It's also better practice to pass parameters to functions instead of setting variables. For example, in your player found function:

PHP Code:

function onPlayerFound(){ 

you would use

PHP Code:

function onPlayerFound(playerFound) { 

When calling it you would pass the player object to it.

PHP Code:

  if (temp.foundplayer.size()==1){ 
    
onPlayerFound(temp.foundplayer[0]); 
  } 

Since setlevel2's first parameter is a level name, not a level object, you should do this (note player.level.name; this is similar to the issue with the account):

PHP Code:

this.fnd.setlevel2(player.level.name,player.x,player.y); 

I would also recommend reorganizing the script so that you're not sending the player's chat but rather the just the command ("summon" or "warp") and the account. Then you would want to do something like this:

PHP Code:

function onActionServerSide(cmdsearch) {
  if (
cmd == "warp") {
    
temp.pl searchForPlayer(search);
    
    if (
pl == null) {
      return 
pl.chat "Found multiple players!"// ends the function
    
}
    
    
player.setlevel2(pl.level.namepl.xpl.y);
  } else if (
cmd =="summon") {
    
temp.pl searchForPlayer(search);
    
    if (
pl == null) {
      return 
pl.chat "Found multiple players!"// ends the function
    
}
    
    
pl.setlevel2(player.level.nameplayer.xplayer.y);
  }
}

function 
searchForPlayer(search) {
  for (
temp.pl allplayers) {
    
// your search code here
  
}
  
  return 
temp.foundPlayer;


Let me know if any of this doesn't make sense.

edit: sorry for the repeats, all of the posts except the OP were while I wrote this :p

There is a way to keep a player's chat from resetting after a few seconds but it can only be done on clientside, so you would have to trigger back.

PHP Code:

shared.chat("chat here"); 


PhilSmith 03-29-2011 04:49 PM

I'm not sure I understand this all right now, but I'll take a few more minutes to read it over and maybe absorb the information. If Ii have questions after that, I'll ask :)

PhilSmith 03-29-2011 07:29 PM

I think i covered most of your edits. I was confused by two of them:

1) check in all lowercase. I'm not really sure what the point of this was. Could you elaborate a little more on its purpose please?

2) the filter. I understand that it is a quicker way of checking than mine, but i just couldnt get it to work.

aside from those, I corrected the other parts and added the community name and clientside shared.chat.

PHP Code:

// Scripted by Phil Smith
function onActionServerSide(searchtemp.action){
//for loop to find all players and their partial nicks
  
temp.foundPlayers.destroy();
  for(
temp.pl allplayers){
    if(
temp.pl.account.starts(search)|| temp.pl.communityName.starts(search) || temp.pl.nick.starts(search)){
      if (
temp.pl.level!=NULL){ //if player is not on rc
        
temp.foundPlayers.add(temp.pl); //logs the player into the array
      
}
    }
  } 
  if (
temp.foundPlayers.size()==1){
    
onPlayerFound(temp.actiontemp.foundPlayers[0]);
  }
  if(
temp.foundPlayers.size()<1){
    
player.chat="No Players Found!";
  }
  if(
temp.foundPlayers.size()>1){
    
triggerclient("weapon",this.name,"NoneFound",temp.foundPlayers);
  }
}
function 
onPlayerFound(temp.functemp.pl){
  if (
temp.func=="summon"){
    
temp.pl.setlevel2(player.level.name,player.x,player.y);
  }
  else if(
temp.func=="warp"){
    
setlevel2(temp.pl.level,temp.pl.x,temp.pl.y);
  }
}
//#CLIENTSIDE
function onActionClientSide(temp.actiontemp.chatarray){
  if(
temp.action=="NoneFound"){
    
shared.chat(temp.chatarray.size() SPC "Players Were Found!:");
    
sleep(2);
    for(
temp.i==0;temp.i<temp.chatarray.size();temp.i++){
      
shared.chat(temp.chatarray[temp.i]);
      
sleep(4);
    }
  }
}
function 
onPlayerChats(){
  if(
player.chat.starts("/warp")){
    
triggerserver("weapon",this.name,player.chat.substring(6),"warp");
  }
  if(
player.chat.starts("/summon")){

    
triggerserver("weapon",this.name,player.chat.substring(8),"summon");
  }



Deas_Voice 03-29-2011 08:14 PM

Thread should be moved from CodeGallery, yes?

PhilSmith 03-29-2011 08:25 PM

It is a working code. I was just asking for thoughts & comments

WhiteDragon 03-29-2011 08:58 PM

Quote:

Originally Posted by PhilSmith (Post 1639927)
[New Version]

Don't be afraid of using } else if {. It is best to be explicit about how your program 'branches' than force whoever is reading it to think about it themselves.

For example, temp.foundPlayers.size()==1 and temp.foundPlayers.size()<1 both clearly can never be true at the same time, but you should always make that clear just in case the conditions are not so clearly disjoint like they are here.


Also, temp.foundPlayers.destroy(); at the start of a function makes no sense. temp.foundPlayers won't even exist then. If you are going to use it as an array, it is best to create one at that point: temp.foundPlayers = {};


Regarding the filter thing, it's just an interesting note. Most people don't program like that in GS2, but I think more people should. The less code you write, the less that can go wrong.

If you're curious about it, let me know what you tried and I can hopefully tell you what went wrong.

PhilSmith 03-29-2011 09:52 PM

First, I normally do use else ifs. I dont know what i was doing with this one, but i must have forgot.
Second, my temp.foundPlayers.destroy() was me being dumb. I looked up on the wiki what i actually needed to put and fixed it. Idk why it is still there in this one...
third, i believe i put something like this:
PHP Code:

temp.= function (temp.pl,search) {
    return (
temp.pl.account.starts(search)|| temp.pl.communityname.starts(search)|| temp.pl.nick.starts(search) && temp.pl.level != NULL;
  };
  
temp.foundPlayers filter(temp.fallplayers); 

search in this case was the string for the substring player.chat. In otherwords, the player i was searching for.

fowlplay4 03-29-2011 10:00 PM

Quote:

Originally Posted by WhiteDragon (Post 1639943)
Regarding the filter thing, it's just an interesting note. Most people don't program like that in GS2, but I think more people should. The less code you write, the less that can go wrong.

I would totally use functions like filter more if they were built-in or at least able to implemented un-obtrusively.


All times are GMT +2. The time now is 01:40 PM.

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