Graal Forums

Graal Forums (https://forums.graalonline.com/forums/index.php)
-   Code Gallery (https://forums.graalonline.com/forums/forumdisplay.php?f=179)
-   -   Hit Players and NPC's with ease. (https://forums.graalonline.com/forums/showthread.php?t=134258416)

adam 03-17-2010 07:46 AM

Hit Players and NPC's with ease.
 
1 Attachment(s)
Specify Width*Height to create a set of co-ordinates for a Hitbox in front of the player. Additionally specify x and y offsets if directly in front of the player isn't what your going for.

Usage.
PHP Code:

temp.box = {2,3,1,0};
temp.hitbox getHitBox(player.dir,player.x,player.y,temp.box); 

PHP Code:

function onActionServerside(){
  if (
params[0] == "hitthings"){
    
temp.box = {2,3,1,0}; // The weapon's Box, Plus any needed offsets. Ignore if not needed.
    
temp.hbox getHitBox(player.dir,player.x,player.y,temp.box);
    
temp.list = findAreaPlayers(temp.hbox[0],temp.hbox[1],temp.hbox[2],temp.hbox[3],player.account);
    
//triggerClient("gui",this.name,"showbox",temp.hbox);//so we can see the box
    
for (temp.objtemp.list){
      
temp.obj.ani "hurt";
      
// call your public Hit the players functiosn here, based on whatever other params you send.
    
}
    
temp.list = findAreaNpcs(temp.hbox[0],temp.hbox[1],temp.hbox[2],temp.hbox[3]);
    for (
temp.objtemp.list){
      
temp.obj.ani "hurt";
      
//call your public Hit the npc functions here. based on whatever other params you send.
    
}
  }
}

// A find area players function! Account should be your own to avoid hitting yourself by mistake.
// Checks at the base of the player, not the top left, where the x,y usually is considered
function findAreaPlayers(x,y,w,h,account){
  for (
temp.pl findNearestPlayers(x+w/2,y+h/2)){
    if (
temp.pl.account != account){
      if (
temp.pl.x+1.5 in |x,x+w| && temp.pl.2 in |y,y+h|){
        
temp.list.add(temp.pl);
      }
    }
  }
  return 
temp.list;
}

//Direction, X, Y, BOX = {width,height,offsetx,offsety};
//Returns co-ordinates for rectnagular hit checking in front of X,Y offset by an X,Y of shape W,H oriented by Dir
function getHitBox(d,x,y,box){
  
temp.wi = (d in {1,3}) ? box[1]:box[0];// swap width/height if direction is different.
  
temp.hi = (d in {1,3}) ? box[0]:box[1];
  
temp.ox = {box[2],box[3],-box[2],-box[3]};//created custom arrays for the offsets 
  
temp.oy = {box[3],-box[2],-box[3],box[2]};// because it was getting confusing otherwise. 
  
temp.+= 1.5 wi/vecx(d)*(wi/2) - ox[d]; // the magic happening here also.
  
temp.+= hi/2  vecy(d)*(hi/2) - oy[d];
  return {
x,y,wi,hi};
}

//#CLIENTSIDE

function onWeaponFired(){
  
triggerServer("gui",this.name,"hitthings");
}

//Just so we can see where the box is exactly on screen, for testing.
function onActionClientside(){
  if (
params[0] == "showbox"){
    
temp.params[1];
    
showpoly(0,{b[0],b[1],b[0],b[1]+b[3],b[0]+b[2],b[1]+b[3],b[0]+b[2],b[1]});
  }
  
settimer(2);
}
function 
onTimeout()hideimg(0); 


adam 03-18-2010 08:34 AM

It will be better overall to use this function to pre-calculate the hit box's instead of calling it everytime. Like

PHP Code:

    temp.box = {2,4,1,1};
    
player.hbox null;
    for (
temp.i=0;temp.i<4;temp.i++){
      
player.hbox.add(getHitBox(temp.i,0,0,temp.box));
    } 

Later I'll redo the function for exactly that.
This way the function adds almost zero time to finding players in the box serverside.

jkldogg 03-18-2010 12:54 PM

what does this "box" do?

adam 03-20-2010 07:07 AM

The getHitBox() function now only requires you call it whenever you want to change
your hitbox size||position. This is a far better way to go than my first example.

getHitBox( box, offset x, offset y)
box is a 4 element array, { width, height, offset x, offset y}
all these are re-oriented depending on the way the player is facing.
ie, if you offset the hitbox so it always hits on the players right,
it will always be on the players right, no matter how your facing.

The function returns a 2d where hbox =
{{x,y,w,h},{x,y,w,h},{x,y,w,h},{x,y,w,h}};
where each set of coordinates represents the 4 directions the player/npc is facing.
This way instead of running the function whenever the player changes directions,
it can just lookup the proper coordinates we stored here.

For use with players, you will want to add offset x/y as 1.5,2 to account for the fact the
players x and y are at his top left. You can also leave it blank, this is optional. If you use it
with an npc you may want to adjust this to center the box on your npc.

As for the speed of this script, I'd say it can't get much faster serverside. Certainly only running getHitBox()
once isn't slowing things down at all. Only way to increase the speed of this script seems to be bringing
the player/npc detection to the client. The way it is now might get laggy with 50 players or more
pking constantly. Hard to say without some more experienced insights.

PHP Code:

//Use to generate coordinates for a HitBox centered around x,y + offx,offy 
//box = {w,h,offx,offy} which are all adjusted by direction
function getHitBox(box,offx,offy){
  
temp.hbox = new[4];
  
temp.ox = {box[2],box[3],-box[2],-box[3]};//created custom arrays for the offsets 
  
temp.oy = {box[3],-box[2],-box[3],box[2]};// because it was getting confusing otherwise. 
  
for (temp.d=0;temp.d<4;temp.d++){
    
temp.wi = (d in {1,3}) ? box[1]:box[0];// swap width/height if direction is different.
    
temp.hi = (d in {1,3}) ? box[0]:box[1];
    
temp.offx wi/vecx(d)*(wi/2) - ox[d]; // the magic happening here also.
    
temp.offy hi/2  vecy(d)*(hi/2) - oy[d];
    
temp.hbox[d] = {x,y,wi,hi};
  }
  return 
temp.hbox;


PHP Code:

//add the functions to the script with join, or just put them in the script I suppose.
function onCreated(){
  
this.join("public_adam_func");
}
function 
onActionServerside(){// Make sure we got a hitbox set.
  
if (params[0] == "newhbox"){
    
player.hbox getHitBox({2,4,0,0},1.5,2);
  }
  if (
params[0] == "hitthings"){
  
// use player.dir as the paramater of the hbox array. and  0,1,2,3 in place of x,y,w,h.  Be sure and add the players x,y to the hbox's x,y.  
    
for (temp.objfindAreaPlayers(player.player.hbox[player.dir][0],player.player.hbox[player.dir][1],player.hbox[player.dir][2],player.hbox[player.dir][3],player.account)){
      
//do stuff with the players you hit here!
    
}
    for (
temp.objfindAreaNpcs(player.player.hbox[player.dir][0],player.player.hbox[player.dir][1],player.hbox[player.dir][2],player.hbox[player.dir][3])){
      
// Do stuff with the NPC's you hit here!
    
}
  }
}
//#CLIENTSIDE
function onCreated(){
  
triggerServer("gui",this.name,"newhbox");
}
function 
onWeaponFired(){
  
triggerServer("gui",this.name,"hitthings");



Also, the "box" itself doesn't do anything except be a well placed, direction oriented box. This function just takes the need to do any calculating out of your hands, and generates the coordinates for a good hitbox for you.
You could use the box for various random things, but it was initially intended for a fully custom melee dmg system. With various shaped hitbox's for different shaped/size melee weapons. Daggers, staves, swords, etc... punch. kick. Left handed daggers, right handed daggers, that not only look different, but hit differently.

fowlplay4 03-20-2010 05:15 PM

Personally I'd check if they were in the hit-box on the client-side then pass that list to the server, and do level/distance checks with a slight amount of leeway and hit them accordingly.

We had a system like this on Zodiac a year or two ago and our sword users would lag the server to hell because of the unoptimized script.

adam 03-20-2010 10:27 PM

Quote:

Originally Posted by fowlplay4 (Post 1563684)
Personally I'd check if they were in the hit-box on the client-side then pass that list to the server, and do level/distance checks with a slight amount of leeway and hit them accordingly.

We had a system like this on Zodiac a year or two ago and our sword users would lag the server to hell because of the unoptimized script.

That's that's pretty much exactly what I needed to know. It'd be nice to be able to do it all serverside, but it's just not quick enough.

xXziroXx 07-16-2010 11:11 AM

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.


All times are GMT +2. The time now is 07:42 PM.

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