PDA

View Full Version : Converting OSR to lape



rj
03-03-2014, 03:53 AM
I am working on converting OSR to lape.


Yes it will be like SRL-6. Yes it will have lots of dots, that is the point(pun intended)

Anybody want to help? You can pick it up at: https://github.com/officerBarbrady/SRL-OSR-lape

Unfold
03-05-2014, 02:32 AM
What's so special about Lape? Like Pascal is fine tbh

rj
03-05-2014, 02:47 AM
What's so special about Lape? Like Pascal is fine tbh

Sooo many more things and features you can do.. also it runs much faster. Theres no point in staying in the past

Sk1nyNerd
03-05-2014, 02:54 AM
What's so special about Lape? Like Pascal is fine tbh

cause we get to use dope stuff like this :f: http://villavu.com/forum/showthread.php?t=107572. ive been dying to use a form in a script

rj
03-05-2014, 03:01 AM
cause we get to use dope stuff like this :f: http://villavu.com/forum/showthread.php?t=107572. ive been dying to use a form in a script

pascalscript had much better support for forms actually :s

Sk1nyNerd
03-05-2014, 03:10 AM
pascalscript had much better support for forms actually :s

from what ive done with them they were a mess. i could make a fancy looking one and get all the buttons to work and create a player file but i couldnt load or save players from/to the form for the life of me. not to mention the 100s of lines the form required to make and work. im pretty stoked if i get to use the form posted above

Coh3n
03-05-2014, 03:28 AM
from what ive done with them they were a mess. i could make a fancy looking one and get all the buttons to work and create a player file but i couldnt load or save players from/to the form for the life of me. not to mention the 100s of lines the form required to make and work. im pretty stoked if i get to use the form posted aboveThe same can be done in PS (it was actually, years ago), I just wrote it for SRL-6 which happens to be in Lape. I'm glad you're using it, though! I wasn't sure anyone would.

Officer Barbrady; What is your plan of action for this? Are you taking the existing SRL-OSR and converting it to Lape, starting from scratch SRL-6 style, or something else?

My suggestion would be to literally copy SRL-6 and make it work with SRL-OSR. Better yet, we have an SRL-6-OSR branch in git (assuming everything goes well). ;)

rj
03-05-2014, 03:43 AM
The same can be done in PS (it was actually, years ago), I just wrote it for SRL-6 which happens to be in Lape. I'm glad you're using it, though! I wasn't sure anyone would.

Officer Barbrady; What is your plan of action for this? Are you taking the existing SRL-OSR and converting it to Lape, starting from scratch SRL-6 style, or something else?

My suggestion would be to literally copy SRL-6 and make it work with SRL-OSR. Better yet, we have an SRL-6-OSR branch in git (assuming everything goes well). ;)

My plan was to make it as close to SRL-6 as possible

I also wanted to re-do how the inventory functions worked. I like explode box is a better approach because it makes it much easier to add new functions.. and isn't a complete mind f***

But if Flight; is doing something then I don't want to start anything

Coh3n
03-05-2014, 03:45 AM
I also wanted to re-do how the inventory functions worked. I like explode box is a better approach because it makes it much easier to add new functions.. and isn't a complete mind f*** Can you elaborate? What do you mean explode box? And what's confusing about the current system? I'm just curious.

rj
03-05-2014, 03:47 AM
Can you elaborate? What do you mean explode box? And what's confusing about the current system? I'm just curious.

Explode box is similar to Grid, (buy Janilabo) Pretty much give it the bounds of the inventory then the rows and columns and you're set

function explodeBox(bx: TBox; rows, columns: integer): TBoxArray;
var
r, c, w, h, ew, eh, ow, oh, i, x, y: integer;
begin
if ((rows > 0) and (columns > 0) and (bx.X1 <= bx.X2) and (bx.Y1 <= bx.Y2)) then
begin
w := ((bx.X2 - bx.X1) + 1);
h := ((bx.Y2 - bx.Y1) + 1);
if (rows < 1) then
rows := 1
else
if (rows > h) then
rows := h;
if (columns < 1) then
columns := 1
else
if (columns > w) then
columns := w;
w := (w div columns);
h := (h div rows);
ew := (((bx.X2 - bx.X1) + 1) - (w * columns));
eh := (((bx.Y2 - bx.Y1) + 1) - (h * rows));
SetLength(result, (rows * columns));
y := bx.Y1;
for r := 0 to (rows - 1) do
begin
x := bx.X1;
if ((eh > 0) and (r < eh)) then
oh := 1
else
oh := 0;
for c := 0 to (columns - 1) do
begin
if ((ew > 0) and (c < ew)) then
ow := 1
else
ow := 0;
i := ((r * columns) + c);
result[i].X1 := x;
result[i].X2 := (x + (w - 1) + ow);
result[i].Y1 := y;
result[i].Y2 := (y + (h - 1) + oh);
x := (Result[i].X2 + 1);
end;
y := (result[i].Y2 + 1);
end;
end else
SetLength(result, 0);
end;


Making functions for the inventory is soo simple using a TBox array:

(from my RSPS include) {$include_once mouse.simba}
{$include_once gametab.simba}

(*
File name: inventory.simba
Description: Contains functions that return information about the inventory
Authors: Janilabo, Officer Barbrady
*)

type
rsps_inventory = record(rsps_interface)
slots:TboxArray;
outline:Integer;
end;

var
inventory:rsps_inventory;

(*
Author: Janilabo
Description: Returns the center of a box
*)

function rsps_inventory.boxCenter(bx: TBox): TPoint;
begin
if ((bx.X1 > bx.X2) or (bx.Y1 > bx.Y2)) then
begin
if (bx.X1 > bx.X2) then
Swap(bx.X1, bx.X2);
if (bx.Y1 > bx.Y2) then
Swap(bx.Y1, bx.Y2);
end;
Result := Point(Round(bx.X1 + ((bx.X2 - bx.X1) div 2)), Round(bx.Y1 + ((bx.Y2 - bx.Y1) div 2)));
end;

(*
Author: Janilabo
Description: Returns an array of boxes based off the bounds of a box and the rows
and columns inputed
*)

function rsps_inventory.explodeBox(bx: TBox; rows, columns: integer): TBoxArray;
var
r, c, w, h, ew, eh, ow, oh, i, x, y: integer;
begin
if ((rows > 0) and (columns > 0) and (bx.X1 <= bx.X2) and (bx.Y1 <= bx.Y2)) then
begin
w := ((bx.X2 - bx.X1) + 1);
h := ((bx.Y2 - bx.Y1) + 1);
if (rows < 1) then
rows := 1
else
if (rows > h) then
rows := h;
if (columns < 1) then
columns := 1
else
if (columns > w) then
columns := w;
w := (w div columns);
h := (h div rows);
ew := (((bx.X2 - bx.X1) + 1) - (w * columns));
eh := (((bx.Y2 - bx.Y1) + 1) - (h * rows));
SetLength(result, (rows * columns));
y := bx.Y1;
for r := 0 to (rows - 1) do
begin
x := bx.X1;
if ((eh > 0) and (r < eh)) then
oh := 1
else
oh := 0;
for c := 0 to (columns - 1) do
begin
if ((ew > 0) and (c < ew)) then
ow := 1
else
ow := 0;
i := ((r * columns) + c);
result[i].X1 := x;
result[i].X2 := (x + (w - 1) + ow);
result[i].Y1 := y;
result[i].Y2 := (y + (h - 1) + oh);
x := (Result[i].X2 + 1);
end;
y := (result[i].Y2 + 1);
end;
end else
SetLength(result, 0);
end;

(*
Author: Officer Barbrady
Description: Returns the inventory array of boxes to be used
*)

procedure rsps_inventory.setUp(b:tbox);
begin
self.bounds := b;
self.slots := self.explodeBox(b, 7, 4);
end;

(*
Author: Officer Barbrady
Description: Sets up the information to be used for the inventory based off
the server revision
*)

procedure rsps_inventory.Init(rev:Integer);
begin
case rev of
317..507:
with self do
begin
outline := 65536;
setUp(IntToBox(563, 214, 720, 460));
bounds := intToBox(0, 0, 0, 0);
name := '317 inventory';
end;
507..719:
with self do
begin
outline := 65536;
setUp(IntToBox(563, 214, 720, 460));
bounds := intToBox(0, 0, 0, 0);
name := '508 inventory';
end;
720..800:
with self do
begin
outline := 131072;
setUp(IntToBox(568, 213, 717, 458));
bounds := intToBox(568, 213, 717, 458);
name := '724 inventory';
end;
end;
end;

(*
Author: Officer Barbrady
Description: Checks if a slot in the inventory is full
*)

function rsps_inventory.slotFull(slot:Integer):Boolean;
var
x, y:Integer;
begin //65536
if FindColor(x, y, self.outline, self.slots[slot].x1, self.slots[slot].y1, self.slots[slot].x2, self.slots[slot].y2) or
FindColor(x, y, 65536, self.slots[slot].x1, self.slots[slot].y1, self.slots[slot].x2, self.slots[slot].y2) then
result := true;
end;

(*
Author: Officer Barbrady
Description: Returns how many items are in the inventory
*)

function rsps_inventory.count:Integer;
var
i:Integer;
begin
for i := 0 to high(self.slots) do
if self.slotFull(i) then
result := result + 1;
end;

(*
Author: Officer Barbrady
Description: Returns whether the inventory is full or not
*)

function rsps_inventory.full:Boolean;
begin
result := false;
exit(self.count = 28);
end;

(*
Author: Officer Barbrady
Description: Interacts with an item in the inventory
*)

procedure rsps_inventory.interactItem(slot:Integer; Button:Integer);
begin
mouse(self.boxCenter(self.slots[slot]).x, self.boxCenter(self.slots[slot]).y, 0, 0, BUTTON);
end;

(*
Author: Officer Barbrady
Description: Interacts with an item in the inventory
*)

procedure rsps_inventory.mouseItem(slot:Integer);
begin
mmouse(self.boxCenter(self.slots[slot]).x, self.boxCenter(self.slots[slot]).y, 0, 0);
end;

(*
Author: Officer Barbrady
Description: Returns true if a bitmap Exists in a slot
*)

function rsps_inventory.bitmapExists(bmp, slot, tol:integer):boolean;
var
x, y:integer;
begin
result := FindBitmaptoleranceIn(bmp, x, y, self.slots[slot].X1, self.slots[slot].y1, self.slots[slot].x2, self.slots[slot].y2, tol);
end;

(*
Author: Officer Barbrady
Description: Searches for a bitmap in the inventory
*)

function rsps_inventory.searchBitmap(BMPSearch, tol:Integer;click, cont:Boolean):Boolean;
var
i:Integer;
begin
result := false;
for i := 0 to high(self.slots) do
begin
If self.bitmapExists(bmpSearch, i, tol) then
begin
result := true;
if click then
self.interactItem(i, left);
if not cont then
exit;
end;
end;
end;

(*
Author: Officer Barbrady
Description: Counts number of bitmaps in the inventory
*)

function rsps_inventory.countBitmap(bmpSearch, tol:Integer):Integer;
var
i:Integer;
begin
for i := 0 to high(self.slots) do
if (self.bitmapExists(bmpSearch, i, tol)) then
result := result + 1;
end;

(*
Author: Officer Barbrady
Description: Returns true if a DTM Exists in a slot
*)

function rsps_inventory.DTMExists(DTM, slot:integer):boolean;
var
x, y:integer;
begin
result := findDTM(DTM, x, y, self.slots[slot].X1, self.slots[slot].y1, self.slots[slot].x2, self.slots[slot].y2);
end;

(*
Author: Officer Barbrady
Description: Counts number of DTMs in the inventory
*)

function rsps_inventory.countDTM(DTMSearch:Integer):Integer ;
var
i:Integer;
begin
for i := 0 to high(self.slots) do
if (self.DTMExists(dtmSearch, i)) then
result := result + 1;
end;

(*
Author: Officer Barbrady
Description: Searches for a DTM in the inventory
*)

function rsps_inventory.searchDTM(DTMSearch:Integer;click, cont:Boolean;button:Integer):Boolean;
var
i:Integer;
begin
for i := 0 to high(self.slots) do
begin
if self.DTMExists(dtmSearch, i) then
begin
result := true;
if click then
self.interactItem(i, left);
if not cont then
exit;
end;
end;
end;

(*
Author: Officer Barbrady
Description: Searches for a DTM in the inventory, clicks by defualt
*)

function rsps_inventory.searchDTM(DTMSearch:Integer;cont:Bo olean;button:Integer):Boolean; overload;
var
I:Integer;
begin
result := false;
for i := 0 to high(self.slots) do
begin
if self.DTMExists(dtmSearch, i) then
begin
result := true;
self.interactItem(i, left);
if not cont then
exit;
end;
end;
end;

(*
Author: Officer Barbrady
Description: Searches for a DTM in the inventory, clicks by defualt and exits
*)

function rsps_inventory.searchDTM(DTMSearch:Integer;button: Integer):Boolean; overload;
var
I, x, y:Integer;
begin
result := false;
for i := 0 to high(self.slots) do
begin
if self.DTMExists(dtmSearch, i) then
begin
self.interactItem(i, button);
exit(true);
end;
end;
end;

(*
Author: Officer Barbrady
Description: Returns amount of item in a slot
*)

function rsps_inventory.itemAmount(slot:integer):integer;
begin
if (not gameTab(TAB_INV)) then
gameTab(TAB_INV);
result := getAmountBox(self.slots[slot]);
end;

(*
Author: Officer Barbrady
Description: Returns total count of all items
*)

function rsps_inventory.totalItemAmount:Int64;
var
i:integer;
begin
if (not gameTab(TAB_INV)) then
gameTab(TAB_INV);
for i := 0 to 27 do
result := result + self.itemAmount(i);
end;

(*
Author: Officer Barbrady
Description: Returns where in the inventory a dtm is
*)

function rsps_inventory.DTMPosition(model:integer):integer;
var
i, x, y:integer;
begin
if (not gameTab(TAB_INV)) then
gameTab(TAB_INV);
for i := 0 to 27 do
if self.DTMExists(model, i) then
exit(i);
end;

(*
Author: Officer Barbrady
Description: Returns where in the inventory a bitmap is
*)

function rsps_inventory.DTMPositionMulti(DTM:integer):TInte gerArray;
var
i, x, y:integer;
begin
if (not gameTab(TAB_INV)) then
gameTab(TAB_INV);
for i := 0 to 27 do
if DTMExists(DTM, i) then
result.append(i);
end;

(*
Author: Officer Barbrady
Description: Returns where in the inventory a bitmap is
*)

function rsps_inventory.DTMPositionMulti(DTM:TIntegerarray) :TIntegerArray; overload;
var
i, k:integer;
begin
if (not gameTab(TAB_INV)) then
gameTab(TAB_INV);
for k := 0 to high(DTM) do
for i := 0 to 27 do
if DTMExists(DTM[k], i) then
result.append(i);
end;

(*
Author: Officer Barbrady
Description: Returns where in the inventory a bitmap is
*)

function rsps_inventory.bitmapPosition(bmp, tol:integer):integer;
var
i:integer;
begin
if (not gameTab(TAB_INV)) then
gameTab(TAB_INV);
for i := 0 to 27 do
if self.bitmapExists(bmp, i, tol) then
exit(i);
end;

(*
Author: Officer Barbrady
Description: Returns where in the inventory a bitmap is
*)

function rsps_inventory.bitmapPositionMulti(bmp, tol:integer):TIntegerArray;
var
i:integer;
begin
if (not gameTab(TAB_INV)) then
gameTab(TAB_INV);
for i := 0 to 27 do
if bitMapExists(bmp, i, tol) then
result.append(i);
end;

(*
Author: Officer Barbrady
Description: Returns where in the inventory a bitmap is
*)

function rsps_inventory.bitmapPositionMulti(bmp, tol:TIntegerarray):TIntegerArray; overload;
var
i, k:integer;
begin
if (length(bmp) <> length(tol)) then
exit();
if (not gameTab(TAB_INV)) then
gameTab(TAB_INV);
for k := 0 to high(bmp) do
for i := 0 to 27 do
if bitMapExists(bmp[k], i, tol[k]) then
result.append(i);
end;

(*
Author: Officer Barbrady
Description: Gets the name of an item in a slow
*)

function rsps_inventory.getItemName(slot:integer):string;
var
p:TPoint;
begin
if (not self.slotFull(slot)) then
exit('')
else
begin
p := boxCenter(self.slots[slot]);
mmouse(p.x, p.y, 0, 0);
result := getSimpleText([4231423], 7, 62, 255, 77, 'upchars07');
end;
end;

(*
Author: Officer Barbrady
Description: Drops item in a slot
*)

function _rsps_server.dropItem(slot:integer):boolean;
begin
if not inventory.slotFull(slot) then
exit(true)
else begin
inventory.interactItem(slot, mouse_right);
exit(self.waitOption('rop', 200));
end;
end;

(*
Author: Officer Barbrady
Description: Drops all items
*)

function _rsps_server.dropAll:boolean;
var
i, c, k:integer;
begin
c := inventory.count();
if (c = 0) then
exit(true);
for i := 0 to 27 do
if self.dropItem(i) then
k := k + 1;
exit(k = c);
end;

(*
Author: Officer Barbrady
Description: Drops all items in a pattern
*)

function _rsps_server.dropAll(pattern:TIntegerArray):boolea n; overload;
var
i, c, k:integer;
begin
c := inventory.count();
if (c = 0) then
exit(true);
for i := 0 to high(pattern) do
if self.dropItem(i) then
k := k + 1;
exit(k = c);
end;

(*
Author: Officer Barbrady
Description: Drops all items except slots
*)

procedure _rsps_server.dropAllExcept(slots:TIntegerArray);
var
i, k:integer;
begin
for i := 0 to 27 do
for k := 0 to high(slots) do
if (i <> slots[k]) then
self.dropItem(i);
end;

(*
Author: Officer Barbrady
Description: Drops all items that don't contain a uptext
*)

procedure _rsps_server.dropAllButUptext(text:TStringArray);
var
i:integer;
begin
for i := 0 to 27 do
if inventory.slotFull(i) then
begin
inventory.mouseItem(i);
if not self.waitUpTextMulti(text, 120) then
self.dropItem(i);
end;
end;

(*
Author: Officer Barbrady
Description: Drops all items that are not a item
*)

procedure _rsps_server.dropAllButBitmap(bmp, tol:integer);
var
i:integer;
begin
for i := 0 to 27 do
if not inventory.bitmapExists(bmp, i, tol) then
self.dropItem(i);
end;

(*
Author: Officer Barbrady
Description: Drops all items that are not a item
*)

procedure _rsps_server.dropAllButBitmap(bmp, tol:TIntegerArray);overload;
var
i, k:integer;
begin
if (length(bmp) <> length(tol)) then
exit();
for i := 0 to 27 do
for k := 0 to high(bmp) do
if not inventory.bitmapExists(bmp[k], i, tol[k]) then
self.dropItem(i);
end;

(*
Author: Officer Barbrady
Description: Drops all items that are not a item
*)

procedure _rsps_server.dropAllBitmap(bmp, tol:integer);
var
i:integer;
begin
for i := 0 to 27 do
if inventory.bitmapExists(bmp, i, tol) then
self.dropItem(i);
end;

(*
Author: Officer Barbrady
Description: Drops all items that are not a item
*)

procedure _rsps_server.dropBitmap(bmp, tol:TIntegerArray);overload;
var
i, k:integer;
begin
if (length(bmp) <> length(tol)) then
exit();
for i := 0 to 27 do
for k := 0 to high(bmp) do
if inventory.bitmapExists(bmp[k], i, tol[k]) then
self.dropItem(i);
end;

(*
Author: Officer Barbrady
Description: Drops all items that are not a item DTM
*)

procedure _rsps_server.dropAllButDTM(DTM:integer);
var
i:integer;
begin
for i := 0 to 27 do
if not inventory.DTMExists(DTM, i) then
self.dropItem(i);
end;

(*
Author: Officer Barbrady
Description: Drops all items that are not a item DTM
*)

procedure _rsps_server.dropAllButDTM(DTM:TIntegerArray);over load;
var
i, k:integer;
begin
for i := 0 to 27 do
for k := 0 to high(DTM) do
if not inventory.DTMExists(DTM[k], i) then
self.dropItem(i);
end;

(*
Author: Officer Barbrady
Description: Drops all items that are not a item DTM
*)

procedure _rsps_server.dropAllDTM(DTM:integer);
var
i:integer;
begin
for i := 0 to 27 do
if inventory.DTMExists(DTM, i) then
self.dropItem(i);
end;

(*
Author: Officer Barbrady
Description: Drops all items that are not a item DTM
*)

procedure _rsps_server.dropDTM(DTM:TIntegerArray);overload;
var
i, k:integer;
begin
for i := 0 to 27 do
for k := 0 to high(DTM) do
if inventory.DTMExists(DTM[k], i) then
self.dropItem(i);
end;

Most of them would be much simplar but they where designed to be dynamic and edited for multiple revision of RS

Flight
03-05-2014, 03:49 AM
But if Flight; is doing something then I don't want to start anything

I am indeed, but mine isn't just a simple conversion or even OSRS-version of SRL-6, it's somewhere between the two with so much built from scratch. I'd like to release what I have so far but I've not even started on the documentation nor an automatic update checker for the include, which is crucial.

Before it can be released I need a way to actively inform users of recent changes to AeroLib; does anyone have suggestions for this?

rj
03-05-2014, 03:54 AM
I am indeed, but mine isn't just a simple conversion or even OSRS-version of SRL-6, it's somewhere between the two with so much built from scratch. I'd like to release what I have so far but I've not even started on the documentation nor an automatic update checker for the include, which is crucial.

Before it can be released I need a way to actively inform users of recent changes to AeroLib; does anyone have suggestions for this?

Meh I just have a pastebin:

http://pastebin.com/u/barbrady

Does a getpage of raw Script version (http://pastebin.com/raw.php?i=yf87fYMd near instant) and if it needs update it does a getpage of the script

It's kinda bad for anything beyond a script though :S

I guess it would be more complicated with multiple files though and uploading stuff to pastebin is a pain in the ass

Sk1nyNerd
03-05-2014, 04:00 AM
Before it can be released I need a way to actively inform users of recent changes to AeroLib; does anyone have suggestions for this?

make a function in aerolib so when a user starts a script with the include it reads a pastbin raw page or google doc and has simba write a line of what the document contains?

begin //Start-Up
ClearDebug;
DeclarePlayer;
SetupSRL;
SetupAeroLib; //Something like this?

Kyle
03-05-2014, 04:03 AM
I am indeed, but mine isn't just a simple conversion or even OSRS-version of SRL-6, it's somewhere between the two with so much built from scratch. I'd like to release what I have so far but I've not even started on the documentation nor an automatic update checker for the include, which is crucial.

Before it can be released I need a way to actively inform users of recent changes to AeroLib; does anyone have suggestions for this?

Well if you host it on googlecode you can use the raw text for an updater. If you look at our reflection include you can see how Meerkat made it so it will update multiple files quite easily just by adding an entry. I'm sure you could make a PHP script that would take the commit comments and show them on a live image that could be posted here.

Turpinator
03-05-2014, 06:50 AM
Can you elaborate? What do you mean explode box? And what's confusing about the current system? I'm just curious.

Ahh explodebox by jani... the one func RJJ seems to have a boner for...

Olly
03-05-2014, 02:37 PM
Ahh explodebox by jani... the one func RJJ seems to have a boner for...

GridBox is far better... :)

Turpinator
03-05-2014, 02:56 PM
GridBox is far better... :)

Surely fully static tboxes would be more computationally efficient than using explodebox. Hell, we could even go so simple has to have a base plus and offset to mimic this...

Olly
03-05-2014, 03:08 PM
Surely fully static tboxes would be more computationally efficient than using explodebox. Hell, we could even go so simple has to have a base plus and offset to mimic this...

invslots: TBoxArray := [[1, 1, 2, 2], [3, 3, 4, 4]];

You are right, that would be the best way!

rj
03-05-2014, 08:08 PM
invslots: TBoxArray := [[1, 1, 2, 2], [3, 3, 4, 4]];

You are right, that would be the best way!

So.. essentially you are saving .05 ms on start-up time by not using the explode box in the setup.


GridBox is far better...


...Explode box does the same thing except the params are more understandable.


Surely fully static tboxes would be more computationally efficient than using explodebox. Hell, we could even go so simple has to have a base plus and offset to mimic this...


>> Didn't read code
>> inventory is a global tboxarray which is declated on setupSRL;

Janilabo
03-05-2014, 09:16 PM
So.. essentially you are saving .05 ms on start-up time by not using the explode box in the setup.



...Explode box does the same thing except the params are more understandable.



>> Didn't read code
>> inventory is a global tboxarray which is declated on setupSRL;GridBox is actually A LOT better for RuneScape inventory, because with it you can use custom size (dimensions) for the slots (TBoxArray). Exploding method doesn't support custom dimensions and it never allows you to have any space between the slots, whereas grid method does. That is the big difference...

Yes, exploding probably is maybe just a little easier to use (grid has few more parameters), but they are both pretty simple to use really. :)

Olly
03-05-2014, 09:41 PM
http://i.imgur.com/uIWgdNP.png < the problem with explode box.