Graal Forums

Graal Forums (https://forums.graalonline.com/forums/index.php)
-   NPC Scripting (https://forums.graalonline.com/forums/forumdisplay.php?f=8)
-   -   Iteration on an array of objects (https://forums.graalonline.com/forums/showthread.php?t=134262181)

AlexanderK 02-21-2011 12:46 PM

Iteration on an array of objects
 
Up to now, I have been using a hitbox-based sword system, like explained in this thread by adam: http://forums.graalonline.com/forums...hp?t=134258416.
It was way too slow though, my bush classes didn't really react to being cut quickly enough, so I thought I'd try out what xXziroXx said.
Quote:

We've been using a system like this on Maloria for quite a while. We first do the box detection clientside, and if there's any eligble target(s), proceed to serverside where it will just make sure that said target(s) are still within the box and take action accordingly.
So that's what I'm trying to do now.

On the clientside, if the sword key is pressed, I display the gani and use the findThings() function:
PHP Code:

function findThings() {
  
temp.objlist = {};
  for (
temp.objfindAreaPlayers(player.clientr.hbox[player.dir][0], player.clientr.hbox[player.dir][1], clientr.hbox[player.dir][2], clientr.hbox[player.dir][3], player.account)) {
    
temp.objlist.add(temp.obj);
  }
  for (
temp.objfindAreaNpcs(player.clientr.hbox[player.dir][0], player.clientr.hbox[player.dir][1], clientr.hbox[player.dir][2], clientr.hbox[player.dir][3])) {
    
temp.objlist.add(temp.obj);
  }
  if (@
temp.objlist != null)
    
triggerServer("gui"this.name"hitthings"temp.objlist);


And this is what my ActionServerSide looks like:
PHP Code:

function onActionServerside() {
  if (
params[0] == "hitthings") {
    
player.chat "hit:"params[1];
    for (
temp.objparams[1]) {
      
temp.obj.chat="hit";
      
temp.obj.hurt(clientr.sweapon.damageplayer.accountplayer.dir clientr.sweapon.typusclientr.sweapon.typus2);
    }
  }


That doesn't work... Neither does the NPC chat anything, nor does the hurt functon hurt the NPC, like it did when I did everything serverside.
Also, when there are NPCs to be hit, the player chats something like " hit:"","", "

My guess is that I cant iterate over the array with for like that and expect the elements to be objects.

How can I fix this?

I also wouldn't mind some hints on how to get my sword system faster. Right now it seems like it takes the player about half a second to chat "hit...".

Demisis_P2P 02-21-2011 01:01 PM

What is your latency?
Half a second seems about normal for serverside hit detection.
Doing the clientside check first doesn't seem like it would actually make it any faster, just more resource efficient for the server, I guess.

ffcmike 02-21-2011 01:09 PM

You can't pass clientside objects to the server like this, what we do on Classic is a similar area NPCs trigger but on both clientside and serverside, this also creates the illusion of no lag.

AlexanderK 02-21-2011 01:54 PM

Quote:

Originally Posted by Demisis_P2P (Post 1632350)
What is your latency?
Half a second seems about normal for serverside hit detection.
Doing the clientside check first doesn't seem like it would actually make it any faster, just more resource efficient for the server, I guess.

No idea about my latency. How do I find out? :D
I guess making it more resource efficient for the server would be a good idea, too. In the thread I mentioned in the first post, someone said something about the script lagging the server.
Quote:

Originally Posted by ffcmike (Post 1632351)
You can't pass clientside objects to the server like this, what we do on Classic is a similar area NPCs trigger but on both clientside and serverside, this also creates the illusion of no lag.

So the problem is that I can't handle Clientside objects on the Serverside?

If I used two checks like you described, I would need to hurt funcitons, one for Clientside and one for Serverside, right? And the bushes' hurt function would need to be clientside? There would still be some lag though as the bushes need to be hidden for everyone if they are slashed, which would need a trigger to the Serverside.

Man, this is really confusing. >_<

What about xXziroXx's quote? There surely must be some way to check for the objects clientside and then pass them to the serverside.

ffcmike 02-21-2011 11:07 PM

It's much better to use the trigger function for this type of thing as opposed to public functions:

obj.trigger("Hit", param1);

As this would automatically be making the check as to whether the function "onHit" actually exists.

But yes you would need to do this both clientside (to make it appear instant to yourself), and serverside (for it to show to other players), for everyone else though this would be synced with your player, it's not a problem.

What I meant regarding the clientside objects is simply that the object on your client is not the same as the object on the server, for this type of thing to work you'd have to try something such as passing the name of the npc (if it was a local npc) or the coordinates of the npc to use with testnpcs(x, y);, which isn't really reliable.

cbk1994 02-21-2011 11:08 PM

Your latency is pretty high; you're in Germany and the servers are in Texas.

Here's how I would do it:
PHP Code:

// Weapon -Swords
function onActionServerSide(cmdsxsy) {
  if (
cmd == "slash") {
    
// security check: is the player too far away?
    
if (getDist(player.xplayer.ysxsy) > 4) {
      return; 
// player is too far away from the hit location
    
}
    
    
// security check: when was the last time they hit?
    
if (timevar2 player.lastHit 0.5) {
      return; 
// player last hit less than half a second ago
    
}

    
temp.radius 0.1;
    
temp.npcs player.level.findAreaNPCs(sx radiussy radiusradius 2radius 2);
    
    for (
temp.npc npcs) {
      
// it's good practice to pass the player object rather than
      // the account—it's just the object-oriented thing to do
      
npc.trigger("hitByPlayer"player);
    }
  }
}

function 
getDist(x1y1x2y2) {
  return (((
x1 x2) ^ 2) + ((y2 y1) ^ 2)) ^ 0.5;
}

//#CLIENTSIDE
function slashObjects(sxsy) {
  
temp.radius 0.1;
  
  for (
temp.npc findAreaNPCs(sx radiuxsy radiusradius 2radius 2)) {
    
npc.trigger("hitByPlayer"null); // second parameter is only needed for v5
  
}
  
  
triggerServer("gui"this.name"slash"sxsy);


This way, you don't have to worry about players tampering with a list of NPCs (it's also a pain to make that list since there's no easy way of identifying an NPC on clientside and serverside unless it's a putnpc2 or DB NPC; level NPCs don't have names and the IDs differ from clientside to serverside.)

AlexanderK 02-22-2011 03:17 AM

Thanks a lot you two! Very helpful.
I'll try doing it that way tomorrow.


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

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