HeroEngine Forums

HeroEngine Support => Scripting & Programming => Topic started by: DragonFist on Jul 04, 12, 08:25:05 PM

Title: [Resolved] Raycast3D Usage
Post by: DragonFist on Jul 04, 12, 08:25:05 PM
I'm attempting to use Raycast3D to get targets infront of my camera but I am running into various issues which I am sure are related to not know how it and camera data are used.

For example, the returned camera position of a camera does not seem to include its offests, resulting in the ray not fireing from the camera but the point at which it is attached to the character.  Okay, so for now I get around that by using the FP camera, however, the rays are not shooting in the direction the camera is pointing even those the direction sent is gotten from getcamerarotation.

In the FPS demo, I see in various methods that have adjustments going on for the camera rotation, but I'm missing something on when and why this is being done and simply dropping that code in doesn't result in any better ray direction.

I guess I expected to pass the camera position and its direction and simply get a ray that shot directly from the camera.  However, this is not what shows using:

Code: [Select]
  hit_node = Raycast3D( start_pos, adjusted_rotation, excluded_nodes, distance, intercept, mesh_name )
 
  DrawDebugLineSegment(start_pos, start_pos + (direction * distance), "FF0000", 1.0, false)
  if intercept != (0,0,0)
    DrawDebugPoint(intercept, 0.05, "00FF00", 1.0, true)
  .

The rays shoot in some sort of offset from the actual camera direction resulting in hits from behind or the side depending on current direction.

Is there anyplace I can get documentation beyond the command descriptions in the wiki?  Or can anyone point me to what I might be missing here?
Title: Re: Raycast3D Usage
Post by: Jrome90 on Jul 04, 12, 11:21:36 PM
This seems to work for me
Code: [Select]
method debugDrawCone(nodeToTest as NodeRef of Class HBNode)
  theTimer as NodeRef of Class genericTimer = CreateNodeFromClass("genericTimer")
  thetimer.timerData = nodeToTest
  thetimer.myTimer.script = SYSTEM.EXEC.THISSCRIPT
  theTimer.myTimer.fireRate = 00:00:01.000
  thetimer.myTimer.start()
.
function myTimer_tick()
  timer as NodeRef of Class genericTimer = me

  if $BASECLIENT._GetAreaName() <> "Character Selection" //Quick way to just stop the script if we go to the character selection area
    numLines as Integer = 5
    nodeToTest as NodeRef of Class HBNode = timer.timerData
    cam as NodeRef = GetActiveCamera()
   
 
    distanceFactor as Float = 20
    loop i from 0 to numLines
   
   
      sourcePosVec as Vector3
      sourceRotVec as Vector3
 
      headingVec as Vector3
 
      targetingRay as Vector3
      var angleAround = (i * numLines) / numLines * 4
 
   
      //Get our source node position and rotation
      GetNodePosition(cam,sourcePosVec)
      sourceRotVec = GetNodeRotation(cam)
      sourceRotVec.y = sourceRotVec.y - angleAround + 10
   
   
      headingVec.x = sine(sourceRotVec.y)
      headingVec.z = -cosine(sourceRotVec.y)
      headingVec.y = -sine(sourceRotVec.x)
   
      headingVec *=  distanceFactor
 
      targetingRay = (headingVec)
     
 
      collideIntercept as Vector3
      meshName as String
      exclude_nodes as List of NodeRef
      add back nodeToTest to exclude_nodes
 
      var character  = Raycast3D(sourcePosVec,targetingRay,exclude_nodes,distanceFactor,collideIntercept,meshName)
      if character <> None
        where character
          is kindof _NonPlayerCharacter
         
            $Debug._drawDebugRay(sourcePosVec, collideIntercept, 0.02, "00FF00", "00FF00", 0.3, false)
            sendchat("Your Character sees "+ character.GetMyName(),"GAME")
          .
          is kindof HBNode
            $Debug._drawDebugRay(sourcePosVec, collideIntercept, 0.02, "00FF00", "00FF00", 0.3, false)

          .
          default
            $Debug._drawDebugRay(sourcePosVec, collideIntercept, 0.02, "00FF00", "00FF00", 0.3, false)
          .
        .
      else
      .
    .
  else
    timer.myTimer.stop()
    me.Stop_Selection()
  .
.
method Stop_Selection()
  DestroyNode(me)
.
For me to test this, I just  use the following in "E_CharacterSystemClassMethods"

Code: [Select]
method HE_OnSetControlledCharacter( char as NodeRef of Class HBNode ) as Boolean
  // this was script erroring Cwiss, I am guessing you are still in the middle of this
ss as NodeRef of Class SelectionSystem = CreateNodeFromClass("SelectionSystem")
ss.debugDrawCone(char)
Title: Re: Raycast3D Usage
Post by: DragonFist on Jul 04, 12, 11:43:42 PM
Thank Jrome, I'll check this out.  thanks again.
Title: Re: Raycast3D Usage
Post by: DragonFist on Jul 05, 12, 01:28:18 AM
Thanks a lot.  That code provided much more predictable behavior.  It is still shooting from the characternode rather than the camera itself in over the shoulder but is otherwise acting as expected.

I was further able to address this with the following:

Code: [Select]
      //Get our source node position and rotation
      //GetNodePosition(cam,sourcePosVec)
      sourcePosVec = GetCameraPosition(cam["CameraName"])

This addressed camera position not taking offset into account.

and

Code: [Select]
myPlayer as NodeRef = GetPlayerCharacterNode()
    ACCController as NodeRef of Class _ACCController
    ro as Vector3
    where myPlayer
      is kindof _ACCControllerOwner
       
        ACCController = myPlayer._getACCController()

        if ACCController <> None
          ro = ACCController._getGameCameraRotationalOffset()
        .
      .
    .



      sourceRotVec = GetNodeRotation(cam)
    //  println("rot offset - " + ro.y)
      sourceRotVec.y = sourceRotVec.y - ro.y
      sourceRotVec.y = sourceRotVec.y - angleAround + 5



This applied my camera rotational offsets on the over the shoulder cameras so they weren't shooting off to the left or right.
Title: Re: Raycast3D Usage
Post by: Jrome90 on Jul 05, 12, 01:56:34 AM
Thanks a lot.  That code provided much more predictable behavior.  It is still shooting from the characternode rather than the camera itself in over the shoulder but is otherwise acting as expected.

I am currently still using the default camera. Have yet to try anything else.
Title: Re: Raycast3D Usage
Post by: DragonFist on Jul 05, 12, 02:06:50 AM
No worries, sorted it all out.  Put the changes I made to work with other cameras in an edit of the last post.
Title: Re: Raycast3D Usage
Post by: Jrome90 on Jul 05, 12, 02:16:08 AM
No worries, sorted it all out.  Put the changes I made to work with other cameras in an edit of the last post.

Good to know.
 :)
Title: Re: Raycast3D Usage
Post by: DragonFist on Jul 05, 12, 02:39:39 PM
The raycasting in use:

http://youtu.be/D_6VUk6A6bM

I am currently doing this on the mousemove event but am likely to create a targeting system class with a timer to the major of the handling (though I might still keep/add the selection to mouse move and movement keys as well as "do action" kind of stuff for between tick handling and to attempt to keep selection as up to date as possible.  I'm open to any theory crafting others might have on this.
Title: Re: Raycast3D Usage
Post by: Jrome90 on Jul 05, 12, 02:58:56 PM
The raycasting in use:

http://youtu.be/D_6VUk6A6bM

I am currently doing this on the mousemove event but am likely to create a targeting system class with a timer to the major of the handling (though I might still keep/add the selection to mouse move and movement keys as well as "do action" kind of stuff for between tick handling and to attempt to keep selection as up to date as possible.  I'm open to any theory crafting others might have on this.

looking good

How many rays are you casting?
Title: Re: Raycast3D Usage
Post by: DragonFist on Jul 05, 12, 03:11:45 PM
I'm using the 5 in your code at the moment.  I intend to review that, perhaps do more than just the y axis, and tighten it up a bit more as I plan to have mesh part specific targeting in some instances.  But that is for later.

Mostly, the plan now is to get it into a targeting system that distinguishes friendly targets and interactive objects from opponents, etc. while passing the mesh name in for later use.

Then I'm going to start working on the actual abilities, skills, etc. to apply to targets.  I.e. attacking things, healing, etc. which I plan to do via reverse replication after client side predication of the results with server side processing and correction.
Title: Re: Raycast3D Usage
Post by: Jrome90 on Jul 05, 12, 03:16:22 PM
What happens if you have multiple targets getting hit at once? Are you only selecting the one that is closest to the center raycast?
Title: Re: Raycast3D Usage
Post by: DragonFist on Jul 05, 12, 03:34:56 PM
My intention is to use the first hit, which will usually be on the first raycast with no adjustment, with a few in a cone around it at a tight angle just for some breathing room.

All I'm doing with this and making the selection which will be visible to the player and use that data (I also plan to have it be able to remove selection when nothing selectable is in the raycast.

Server side will do a check for the time of the action with a much broader cone just to ensure the client's data was reasonable at the time of the attack to prevent packet editing programs from telling the server "I made a successful melee attack from the other side of the zone with 5 trees and a rock between me and the target."   As long as the target was reasonably close to weapon range and character direction, we'll assume it is okay to calculate hit and damage based on an RPG ruleset.
Title: Re: Raycast3D Usage
Post by: DragonFist on Jul 07, 12, 02:07:59 AM
More recent video after putting the code on a timer and adding a check for the target being closer than the camera offset to prevent targeting mobs behind the character (which adds the mob too close to the excluded list and tries again).  Also, if there has been no selection for 1 sec, we drop the target.

I plan to give the player a target lock, but other-wise this is the targeting method - no tab targeting.

http://youtu.be/qewo8ziZ6ZU

Title: Re: Raycast3D Usage
Post by: DragonFist on Jul 09, 12, 06:05:04 PM
Okay, this is generally working as expected.  However, every so often, I get rays shot at random angles.  I at first thought it only occurred while moving but that is not the case.  Occasionally, this is accompanied by an error in the console about an invalid ray direction or fxnode.  The result is that one gets random mobs selected that are off-screen, sometimes directly behind the camera, that a moment later revert to the expected selection.

I'm toying with the idea of using one of the other selection methods like nodes in cone or something to verify the validity of the ray, though that seems to be a potential over use of resources that may have performance complications (the reason I don't simply use one of those is that I wish to use the "mesh name" feature to allow attacks to specific body parts).

Any ideas on how to address these errant rays?
Title: Re: Raycast3D Usage
Post by: Jrome90 on Jul 09, 12, 06:16:55 PM

I'm toying with the idea of using one of the other selection methods like nodes in cone


Are you referring to this: http://hewiki.heroengine.com/wiki/Technical:Area_Awareness
Title: Re: Raycast3D Usage
Post by: DragonFist on Jul 09, 12, 06:33:53 PM
Yeah.  Just an idea at the moment.  Not even sure it would be useful, if the problem comes from a bad reported vector from the camera.
Title: Re: Raycast3D Usage
Post by: Jrome90 on Jul 09, 12, 06:39:22 PM
Yeah.  Just an idea at the moment.  Not even sure it would be useful, if the problem comes from a bad reported vector from the camera.

Please read this: https://community.heroengine.com/forums/index.php/topic,164.msg580.html#msg580
Title: Re: Raycast3D Usage
Post by: DragonFist on Jul 09, 12, 06:46:34 PM
Thanks, that rules out using those for this purpose unless I had a means of converting the vector to world.

Still leaves me with the problem of stray rays.  I'm going to probably move on to other systems for the time being, but I'll have to solve this at some point as it gives a bad user experience if selection occasionally randomly changes, especially if it occurs at the moment of using an attack.
Title: Re: Raycast3D Usage
Post by: HE-Cooper on Jul 09, 12, 07:03:02 PM
The FPS ref uses a set of rays for shooting and Alex did a nicely tuned set for the axe swing as well, so that might help you. And the space ref uses the raycast from cursor function I think.
Title: Re: Raycast3D Usage
Post by: Jrome90 on Jul 09, 12, 07:57:21 PM
Alex did a nicely tuned set for the axe swing as well, so that might help you.

It sure seems much better than what I used :)
With some tweaking it should work
Thanks

Just in case anybody is interested, here is a better way to do what the code I posted on the first page does. (Does that make any sense?)

It is much easier to read
Except I can't take credit for this.
Credit goes to HE-Alex(Is that correct?). I just tweaked it a little
Code: [Select]
method RaycastSelection()
  theTimer as NodeRef of Class genericTimer = CreateNodeFromClass("genericTimer")
  thetimer.myTimer.script = SYSTEM.EXEC.THISSCRIPT
  theTimer.myTimer.fireRate = 00:00:01.000
  thetimer.myTimer.start()
.
function myTimer_tick()
  timer as NodeRef of Class genericTimer = me

  if $BASECLIENT._GetAreaName() <> "Character Selection" //Quick way to just stop the script if we go to the character selection area
    cam as NodeRef = GetActiveCamera()
    start_pos as Vector3
    GetNodePosition(cam,start_pos)
    rotation as Vector3 = GetNodeRotation( cam )
 
 
    distance as Float = 20
    intercept as Vector3 = (0,0,0)
    meshName as String = ""
   
 
    adjusted_rotation as Vector3 = rotation
    adjusted_rotation.x *= -1
    adjusted_rotation.y = MungeHeadingDegrees( adjusted_rotation.y )
    adjusted_rotation.y *= -1
 
    direction as Vector3 = RotateVector( (0,0,-1), adjusted_rotation )
 
    excluded_nodes as List of NodeRef
    add back SYSTEM.INFO.PLAYERCHARACTER to excluded_nodes
 
 
    num_rays as Integer = 6
    angle as Vector3 = (0.0, 5.0, 0.0)
    rotation_offset as Vector3 = ((angle.x / 2) * -1, angle.y * -1, (angle.z / 2) * -1)
   
    loop i from 1 to num_rays
        rotation_offset.y += (angle.y / num_rays)
     
     
        adjusted_rotation.x = (rotation.x + rotation_offset.x)
        adjusted_rotation.x *= -1
        adjusted_rotation.y = (rotation.y + rotation_offset.y)
        adjusted_rotation.y = MungeHeadingDegrees( adjusted_rotation.y )
        adjusted_rotation.y *= -1
     
        direction = RotateVector( (0,0,-1), adjusted_rotation )
     
     
     
        rotation_offset.x += angle.x / num_rays
        rotation_offset.y += angle.y / num_rays
        rotation_offset.z += angle.z / num_rays
 
      var character  = Raycast3D(start_pos,direction,excluded_nodes,distance,Intercept,meshName)
      if character <> None
        where character
          is kindof _NonPlayerCharacter
         
            $Debug._drawDebugRay(start_pos, Intercept, 0.02, "00FF00", "00FF00", 0.3, false)
            sendchat("Your Character sees "+ character.GetMyName(),"GAME")
          .
          is kindof HBNode
            $Debug._drawDebugRay(start_pos, Intercept, 0.02, "00FF00", "00FF00", 0.3, false)

          .
          default
            $Debug._drawDebugRay(start_pos, Intercept, 0.02, "00FF00", "00FF00", 0.3, false)
          .
        .
      else
      .
    .
  else
    timer.myTimer.stop()
    me.Stop_Selection()
  .
.
method Stop_Selection()
  DestroyNode(me)
.
Title: Re: Raycast3D Usage
Post by: DragonFist on Jul 10, 12, 05:48:00 AM
Below is my current implementation as a targeting system.  Definitely not getting the random, stray raycasts anymore and that is good.  I'm sure I can clean this up a bit more (excuse the various commented out bits as I played with different settings and debug ray draws.

In addition, I did another video showing it in action, this time with the default attack actions wired up to the mouse buttons to get a little game-play going which can be viewed here (click for youtube video) (http://youtu.be/seu2EdNEycY).


method oncreate()
  me.ZA_targetTimer.script = SYSTEM.EXEC.THISSCRIPT
  me.ZA_targetTimer.fireRate = 00:00:00.001
  me.ZA_targetTimer.start()
 // println("targetTimer Started")
.

function ZA_targetTimer_tick()
 // println("Getting Target")
  me.GetCameraTarget()
.

method StartDelayedTargetDrop()
  if me.Za_targetDropDelayTimer.timerState == ON
    me.Za_targetDropDelayTimer.stop()
  .
  me.Za_targetDropDelayTimer.fireRate = 00:00:00.100
  me.Za_targetDropDelayTimer.script = None
  me.Za_targetDropDelayTimer.start()
.

method StopDelayedTargetDrop()
  me.Za_targetDropDelayTimer.stop()
  //destroynode(me)
.
method Za_targetDropDelayTimer_TICK()
  //---------------------------------------------------------------
  // When this timer fires, Drop the current target
  //---------------------------------------------------------------
//    println( "Stopping previous target: " )
  if me.E_TargetingFX != 0
//    println( "Stopping previous target: " + me.E_TargetingFX )
    sb as NodeRef of Class GUIControl = FindGUIControlByName(0,"game.targetStatusBar")
    if sb != None
      DestroyNode(sb)
    .
    me.E_StopTarget( me.E_TargetingFX )
    me.E_TargetID = 0
      var acct = GetAccountID()
      call server E_playerAccountClassMethods:ClearClickTarget(acct)
  .
.


remote method E_UpdateTargetCircle( targetID as ID )
//  println( "Update targeting circle." )
  if me.E_TargetingFX != 0
//    println( "Stopping previous target: " + me.E_TargetingFX )
    sb as NodeRef of Class GUIControl = FindGUIControlByName(0,"game.targetStatusBar")
    if sb != None
      DestroyNode(sb)
    .
    me.E_StopTarget( me.E_TargetingFX )
  .
  target as NodeRef = targetID
  if target != None
//    println( "Setting new target: " + targetID )
    me.E_TargetID = targetID
    caster as Class _Target
    caster._tgtID = targetID
    me.E_TargetingFX = $FXSYSTEM.PlayFxFromSpec( 4, caster, caster )
    statusbar as NodeRef of Class E_targetStatusBar = CreateNodeFromPrototype("E_targetStatusBar")
    statusbar.name = "targetStatusBar"
    statusbar.build = true
    realtarget as NodeRef of Class E_CommonCharacter
    where target
      is kindof _PlayerAccount
        realtarget = target.GetMyCharacter()
      .
      default
        realtarget = target
      .
    .
    if realtarget != None
      AddAssociation(realtarget,"base_hard_association", statusbar)
      $LightweightEvents.addLightweightEventListener(realtarget, "nameUpdated", statusbar)
      $LightweightEvents.addLightweightEventListener(realtarget, "hpUpdated", statusbar)
      statusbar.SetHP(realtarget.curTotalHitPoints,realtarget.maxTotalHitPoints)
      statusbar.SetName(realtarget.name)
    else
      println(realtarget)
    .
  .
.
public function E_SetTargetCircleFromClient( targetID as ID )
  where me
    is kindof E_TargetCircle
      me.E_SetTargetCircle(targetID)
    .
  .
  //println("Target: " + targetID)
 
.

method E_SetTargetCircle( targetID as ID )
//  println( "Update targeting circle." )
if me.E_TargetID <> targetID
  if me.E_TargetingFX != 0
//    println( "Stopping previous target: " + me.E_TargetingFX )
    sb as NodeRef of Class GUIControl = FindGUIControlByName(0,"game.targetStatusBar")
    if sb != None
      DestroyNode(sb)
    .
    me.E_StopTarget( me.E_TargetingFX )
  .
  target as NodeRef = targetID
  if target != None
//    println( "Setting new target: " + targetID )
    me.E_TargetID = targetID
    caster as Class _Target
    caster._tgtID = targetID
    me.E_TargetingFX = $FXSYSTEM.PlayFxFromSpec( 4, caster, caster )
    statusbar as NodeRef of Class E_targetStatusBar = CreateNodeFromPrototype("E_targetStatusBar")
    statusbar.name = "targetStatusBar"
    statusbar.build = true
    realtarget as NodeRef of Class E_CommonCharacter
    where target
      is kindof _PlayerAccount
        realtarget = target.GetMyCharacter()
      .
      default
        realtarget = target
      .
    .
    if realtarget != None
      AddAssociation(realtarget,"base_hard_association", statusbar)
      $LightweightEvents.addLightweightEventListener(realtarget, "nameUpdated", statusbar)
      $LightweightEvents.addLightweightEventListener(realtarget, "hpUpdated", statusbar)
      statusbar.SetHP(realtarget.curTotalHitPoints,realtarget.maxTotalHitPoints)
      statusbar.SetName(realtarget.name)
    else
      println(realtarget)
    .
  .
.
.
method E_StopTarget( fx as ID )
  fxgroup as NodeRef of Class _FxGroup = $FXSYSTEM._GetFxGroupForHandle(me.E_TargetingFX)
  if fxgroup != None
    fxgroup.StopFxEvent()   
  .
  me.E_TargetID = 0
  me.E_TargetingFX = 0
.

method GetCameraTarget()
 cam as NodeRef = GetActiveCamera()
 camOffset as Float = GetCameraOffset(cam["CameraName"])
 camOffset += 0.05
    myPlayer as NodeRef = GetPlayerCharacterNode()
   
  acct as NodeRef of Class E_playerAccount = GetAccountID()
    ACCController as NodeRef of Class _ACCController
    ro as Vector3
    where myPlayer
      is kindof _ACCControllerOwner
       
        ACCController = myPlayer._getACCController()

        if ACCController <> None
          ro = ACCController._getGameCameraRotationalOffset()
        .
      .
    .

  start_pos as Vector3 = GetCameraPosition( cam["CameraName"] )
  rotation as Vector3 = GetNodeRotation( cam )
 
  rotation.y -= ro.y
//  weapon_spec as NodeRef of Class FPS_WeaponSpec = me._specRef
    distanceFactor as Float = 20 + camOffset
 
 
  intercept as Vector3 = (0,0,0)
  mesh_name as String = ""
  hit_node as NodeRef = None
 
  local_distance as Float = distanceFactor
  local_intercept as Vector3 = (0,0,0)
  local_mesh_name as String = ""
  local_hit_node as NodeRef = None
 
  adjusted_rotation as Vector3 = rotation
  adjusted_rotation.x *= -1
  adjusted_rotation.y = MungeHeadingDegrees( adjusted_rotation.y )
  adjusted_rotation.y *= -1
  direction as Vector3 = RotateVector( (0,0,-1), adjusted_rotation )
 
  excluded_nodes as List of NodeRef
  add back SYSTEM.INFO.PLAYERCHARACTER to excluded_nodes
 
  local_hit_node = Raycast3D( start_pos, direction, excluded_nodes, local_distance, local_intercept, local_mesh_name )
 
  //if nothing was hit or it wasnt a player or wasnt an npc
  if (local_hit_node == None) or (local_hit_node != None and (not (local_hit_node is kindof E_playerCharacter)) and (not (local_hit_node is kindof E_nonplayerCharacter)))
    num_rays as Integer = 4
    attack_angle as Vector3 = (0.0, 30.0, 0.0)
    rotation_offset as Vector3 = ((attack_angle.x / 2) * -1, (attack_angle.y / 2) * -1, (attack_angle.z / 2) * -1)
   
    //fire some more rays at small random rotations
    loop i from 1 to num_rays
      if rotation_offset.y == 0.0
        rotation_offset.y += (attack_angle.y / num_rays)
      .
     
      adjusted_rotation.x = (rotation.x + rotation_offset.x)
      adjusted_rotation.x *= -1
      adjusted_rotation.y = (rotation.y + rotation_offset.y)
      adjusted_rotation.y = MungeHeadingDegrees( adjusted_rotation.y )
      adjusted_rotation.y *= -1
     
      direction = RotateVector( (0,0,-1), adjusted_rotation )
     
      hit_node = Raycast3D( start_pos, direction, excluded_nodes, distanceFactor, intercept, mesh_name )
     
      if (hit_node != None) and ( (hit_node is kindof E_playerCharacter) or (hit_node is kindof E_nonplayerCharacter) )
        return
      .
     
      rotation_offset.x += attack_angle.x / num_rays
      rotation_offset.y += attack_angle.y / num_rays
      rotation_offset.z += attack_angle.z / num_rays
    .
  .
 
  //if none of the spread raycasts hit a player or npc then return what the first raycast did
  distanceFactor = local_distance
  intercept = local_intercept
  mesh_name = local_mesh_name
  hit_node = local_hit_node

      if distanceFactor < camOffset
        add back hit_node to excluded_nodes
//        continue
      .
      if hit_node <> None
       // println("target - " + character.GetMyName())
        where hit_node
          is kindof E_playerCharacter
              me.StopDelayedTargetDrop()
            if hit_node <> me.E_TargetID
    //println("Offset = " + camOffset)
              $E_TargetCircle.E_SetTargetCircle(hit_node)
////              $Debug._drawDebugRay(sourcePosVec, collideIntercept, 0.02, "00FF00", "00FF00", 0.3, false)
             
   call server E_playerAccountClassMethods:remoteSetClickTarget( acct, hit_node )
           .
           return
           // println("target - " + character)
          //  sendchat("Your Character sees "+ character.name,"GAME")
           
          .
          is kindof _NonPlayerCharacter
              me.StopDelayedTargetDrop()
            if hit_node <> me.E_TargetID
              $E_TargetCircle.E_SetTargetCircle(hit_node)
//              $Debug._drawDebugRay(start_pos, intercept, 0.02, "00FF00", "00FF00", 0.3, false)
             
   call server E_playerAccountClassMethods:remoteSetClickTarget( acct, hit_node )
            .
            return
//    println("Offset = " + camOffset)
           // println("target - " + character.GetMyName())
         //            sendchat("Your Character sees "+ character.GetMyName(),"GAME")
          .
          is kindof HBNode
            if me.Za_targetDropDelayTimer.timerState == OFF
//    println("Offset = " + camOffset)
              me.StartDelayedTargetDrop()
            .
            return
//            $Debug._drawDebugRay(sourcePosVec, collideIntercept, 0.02, "00FF00", "00FF00", 0.3, false)

          .
          default
            if me.Za_targetDropDelayTimer.timerState == OFF
              me.StartDelayedTargetDrop()
            .
           // me.E_StopTarget( me.E_TargetingFX )
//            $Debug._drawDebugRay(sourcePosVec, collideIntercept, 0.02, "00FF00", "00FF00", 0.3, false)
          .
        .
      else
        if me.Za_targetDropDelayTimer.timerState == OFF
          me.StartDelayedTargetDrop()
        .
       // me.E_StopTarget( me.E_TargetingFX )
      .
//    .
 
 .
Title: Re: [Solved] Raycast3D Usage
Post by: Trixer on Jul 17, 12, 10:32:22 AM
Really great stuff here guys!

Just wanted to pop in and say thanks, and push this up a bit there were some question regarding raycasting.
Title: Re: [Solved] Raycast3D Usage
Post by: DragonFist on Jul 17, 12, 12:44:24 PM
I've since discovered the per frame event (findable on the wiki) and have moved the firing off of the time in the above code to that handler.  Seems more efficient than keeping a separate timer going.
Title: Re: [Solved] Raycast3D Usage
Post by: PiscoMaN on Dec 22, 12, 07:39:53 PM
Only one question, where did you initialize oncreate method?