Graal Forums

Graal Forums (https://forums.graalonline.com/forums/index.php)
-   Code Gallery (https://forums.graalonline.com/forums/forumdisplay.php?f=179)
-   -   onWall3() (https://forums.graalonline.com/forums/showthread.php?t=134268653)

Angel_Light 08-22-2013 05:20 AM

onWall3()
 
1 Attachment(s)
Just a make shift version of the onWall2() function that checks the tilelayers on serverside, which currently isn't implemented in-game yet.

Use :
onWall3( x, y, w, h, level, layerscount);
  • x - The level's X coordinate to check (integer)
  • y - The level's Y coordinate to check (integer)
  • w - The width of tiles to check (integer)
  • h - The height of tiles to check (integer)
  • level - The name of the level to check (string)
  • layerscount - The number of layers to check from layer 0 (integer)

Installation :
Simply add the following code to a class, then join that class to whatever you need it for serverside. Also upload the 'tiledata.nw' file to your levels/ folder and I guess make sure the NPC server has read rights to the levels/ folder

PHP Code:

public function onWall3( temp.lvl_x, temp.lvl_y, temp.w, temp.h, temp.lvl, temp.lvl_c)
{

  
temp.file_data.loadLines( "levels/" @ temp.lvl);
  
  
this.delete_rest = false;
  
  
temp.file_lines = temp.level_data.size();

  for ( 
temp.a : temp.file_data)
  {
  
    
temp.tokens = temp.a.tokenize();

    if ( 
temp.tokens[ 0] == "BOARD")
      
temp.level_data.add( temp.tokens);

  }
  
  for ( 
temp.c = 0; temp.c < temp.w; temp.c ++;)
  {
  
    for ( 
temp.b = 0; temp.b < temp.h; temp.b ++;)
    {
    
      for ( 
temp.a = 0; temp.a < temp.lvl_c; temp.a ++;)
      {

        
temp.tile_loc = getTileLocation( base64ToTile( temp.level_data[( temp.b + temp.lvl_y) + ( temp.a * 64)][ 5].substring(( temp.c + temp.lvl_x) * 2, 2)));
    
        if ( 
findLevel( "tiledata.nw").onwall( temp.tile_loc[ 0] % 64, temp.tile_loc[ 1] + ( 32 * temp.tile_loc[ 0] > 64? 1 : 0)))
        {
    
          
temp.isBlocking = true;
          break;
  
        }
      }
      
      if ( 
temp.isBlocking)
        break;
        
    }
    
    if ( 
temp.isBlocking)
      break;
        
  }
  
  return 
float( temp.isBlocking);
  
}



function 
Base64ToTile( temp.t) // Big thank you to Dusty for this function 
{
  
temp.base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  
  if ( 
temp.t.type() == 1) 
  {
  
    return 
temp.base64.pos( temp.t.substring( 0, 1)) * 64 + temp.base64.pos( temp.t.substring( 1, 1));
  } 
  
  else if ( 
temp.t.type() == 3) 
  {
  
    
temp.decodearray = new[ 0];
    
    for ( 
temp.i : temp.t) 
      
temp.decodearray.add( temp.base64.pos( temp.i.substring( 0, 1)) * 64 + temp.base64.pos( temp.i.substring( 1, 1))); 
    
    return 
temp.decodearray;
  } 
  
  else 
    return -
1;

}

function 
getTileLocation( temp.tileNum) //Returns tileset coordinate from hexa/decimal
{

  
temp.tileX = int( temp.tileNum / 512) * 16 + ( temp.tileNum % 16);
  
temp.tileY = int( temp.tileNum / 16) % 32; 
  return { 
temp.tileX, temp.tileY}; 

} 

Example :
Make a weapon, add this code to it, and then add it to yourself. It will then check a 2x2 square if the tiles are blocking.

PHP Code:

function onCreated()
{

  
this.join( "core");

}

function 
onActionServerside()
{

  if ( 
params[ 0] == "onWall3")
    echo( 
onWall3( params[ 1], params[ 2], params[ 3], params[ 4], params[ 5], params[ 6]));

}

//#CLIENTSIDE

function GraalControl.onMouseDown()
{

  
triggerServer( "weapon", this.name, "onWall3", int( mousex), int( mousey), 2, 2, player.level.name, tilelayercount);
  
showimg( 1, "block.png", int( mousex), int( mousey));
   
} 

Also, I'm pretty sure there are several way to make this more efficient, if so please correct my method.

Also figured I should attach this for getting the actual level name and not gmap name serverside, credit goes to cbk1994 for the code. -Thank you. =]
PHP Code:

public function getPreciseLevelName() {
  if (
this.level.name.ends(".gmap")) {
    return 
this.level.getmappartfile(this.x, this.y);
  }
  
  return 
this.level.name;
} 


maximus_asinus 08-22-2013 03:13 PM

very nice, I would have loved this a year ago when I tried to convince Thor to use tilelayers on Classic.

xXziroXx 08-22-2013 04:26 PM

What is tiledata.nw supposed to be?

Angel_Light 08-22-2013 04:55 PM

Quote:

Originally Posted by xXziroXx (Post 1721913)
What is tiledata.nw supposed to be?

Gah sorry, uploaded it. tiledata.nw is just how I checked which tiles on the tileset that are blocking or not. Uploaded it now.

fowlplay4 08-22-2013 11:12 PM

You would be better off determining all the blocking areas, caching the blocking data, and then referencing your cache (perhaps in a level var) instead of reloading and parsing the direct level data every time.

Tricxta 08-23-2013 03:46 AM

Quote:

Originally Posted by fowlplay4 (Post 1721927)
You would be better off determining all the blocking areas, caching the blocking data, and then referencing your cache (perhaps in a level var) instead of reloading and parsing the direct level data every time.

So then you'd need to rework weapons(e.g. the hammer) that change tiles to refresh the cache I guess? Seems like a bit of a hassle, besides... when was efficiency ever a major concern in graal development to the common developer?

Angel_Light 08-28-2013 08:06 AM

Bit modified version that is taking lot less CPU. Changed it so a 'block map' of a level is created and I reference that instead of loading the level each time and looking at it. Probably be better to use level.vars instead of a db_npc, but I can't get level vars to work for me properly. :/ Also haven't added gmap support for building block maps. Feel free to modify/add to the script if you want.

Now with this method you personally have to build the block map by saying a command on RC

RC Command
/npc blockmap <level_name.nw> <# of layers>

Use
onWall3( x, y, w, h);

Installation

In your Control-NPC add this :
PHP Code:

function onRCChat()
{

  if ( 
params[ 0] == "blockmap")
  {

    if ( !
levelExists( params[ 1]))
    {
  
      echo( 
"Control-NPC : Could not find" SPC params[ 1] @ "!");
      return;
  
    }

    
this.lvl        = params[ 1];
    
this.layers     = params[ 2]; 
    
temp.file_data.loadLines( "levels/" @ this.lvl);
    echo( 
"Control-NPC : Building block map for" SPC this.lvl @ ".");

    for ( 
temp.a : temp.file_data)
    {
    
      
temp.tokens = temp.a.tokenize();
    
      if ( 
temp.tokens[ 0] == "BOARD")
        
this.level_data.add( temp.tokens);
  
    }

    
onStartCount(); 

  }
}


function 
onStartCount()
{

  for ( 
temp.b = 0; temp.b < 64; temp.b ++;) // width
  
{

    
temp.isBlocking = false;
    
    for ( 
temp.a = 0; temp.a < this.layers; temp.a ++;) // layer
    
{

      
temp.tile_loc = getTileLocation( base64ToTile( this.level_data[ this.count + ( temp.a * 64)][ 5].substring( temp.b * 2, 2)));
      
      
      if ( 
findLevel( "tiledata.nw").onwall( temp.tile_loc[ 0] % 64, temp.tile_loc[ 1] + ( 32 * ( temp.tile_loc[ 0] > 64? 1 : 0))))
      {
      
        
temp.isBlocking = true;
        break
        
      }    
    }

    
temp.data0.add( temp.isBlocking);

  }

  
this.data1.add( temp.data0);
  
  if ( 
this.count < 63)
  {
  
    
this.count ++;
    
scheduleEvent( 0.1, "onStartCount"); //Only way I could figure to avoid the maxlooplimit if you are doing several layers.
    
  
}
  
  else
  {
  
    
this.( @ "level_" @ this.lvl.substring( 0, this.lvl.length() - 3)) = this.data1;
    echo( 
"Control-NPC : Block map for" SPC this.lvl @ ", has been built.");
    
this.count = this.data1 = this.layers = this.level_data = this.lvl = NULL;
    
  }
}

function 
Base64ToTile( temp.t) // Big thank you to Dusty for this function 
{
  
temp.base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  
  if ( 
temp.t.type() == 1) 
  {
  
    return 
temp.base64.pos( temp.t.substring( 0, 1)) * 64 + temp.base64.pos( temp.t.substring( 1, 1));
  } 
  
  else if ( 
temp.t.type() == 3) 
  {
  
    
temp.decodearray = new[ 0];
    
    for ( 
temp.i : temp.t) 
      
temp.decodearray.add( temp.base64.pos( temp.i.substring( 0, 1)) * 64 + temp.base64.pos( temp.i.substring( 1, 1))); 
    
    return 
temp.decodearray;
  } 
  
  else 
    return -
1;

}

function 
getTileLocation( temp.tileNum) //Returns tileset coordinate from decimal
{

  
temp.tileX = int( temp.tileNum / 512) * 16 + ( temp.tileNum % 16);
  
temp.tileY = int( temp.tileNum / 16) % 32; 
  return { 
temp.tileX, temp.tileY}; 

} 

Next in a class put this.

PHP Code:

public function getPreciseLevelName()  // Thank you cbk1994
{

  if ( 
this.level.name.ends( ".gmap"))
    return 
this.level.getmappartfile( this.x, this.y);

  return 
this.level.name;
  
} 

public function 
onWall3( temp.lvl_x, temp.lvl_y, temp.w, temp.h)
{
  
  
temp.check = findNPC( "Control-NPC").( "level_" @ getPreciseLevelName().substring( 0, getPreciseLevelName().length() - 3));
  
  for ( 
temp.a = 0; temp.a < temp.h; temp.a ++;)
  {
  
    for ( 
temp.b = 0; temp.b < temp.w; temp.b ++;)
    {
   
      if (  
temp.check[ temp.lvl_y + temp.a][ temp.lvl_x + temp.b] == 1)
        return 
true;
    
    }
  }
  
  return 
false;
  
} 

Then in your baddie script or whatever, add the class with that script in it and just replace where ever you put onWall2, with onWall3.

I know this is more efficient due the /stats telling me, my baddie class CPU usage went from 1.784367163 % to 0.651127497 %. Although it does seem to spike from time to time. :/

e. May of had to do with other parts of the script for the high cpu usage, after rewriting a good portion to be cleaner and more efficient, the time is down to 0.063054958 %, but that is showing how efficient it is still.


All times are GMT +2. The time now is 08:13 PM.

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