HeroEngine Forums
Welcome, Guest. Please login or Register for HeroCloud Account.

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - Thazager

Pages: [1] 2 3 ... 10
Scripting & Programming / Parents replicate for kids?
« on: Jan 30, 20, 03:44:58 PM »
E_commonCharacter is a parent for both E_playerCharacter and E_nonPlayerCharacter

When I add a field to E_playerCharacter class and set it to replicate, it will replicate from server to client side, and it shows in the _OnReplicationFieldUpdated() function.

When I add a field to E_nonPlayerCharacter class it works the same way.

When I add the field to E_commonCharacter (the parent of both) and set it to replicate,  it does not replicate to the child class.

class Buffs has fields in it: displayname, speckey, statsEffected, buffername

BuffSaveList as list of class Buffs, has replication set to client side

This field is added to E_commonCharacter and set to replicate and the BuffSaveList should replicate to clientside
I can see the bufflist on the server side with the buff added, but the buff wont show in the bufflist on the client side.

I have added replicate with the class Buffs to client side also, and the fields in the buffs class.

Still not replicating :(

General Discussion / engine bug
« on: Apr 18, 19, 08:04:42 PM »
starting up the blade, I got an error, then another error popped.

a few seconds later the blade starts, and starts another, and another.

currently seeing about 20 open blades all asking to log in...

once the error is clicked off, they stop adding new ones.
then each can be removed - using cancel.

Scripting & Programming / replication type
« on: Apr 04, 19, 04:02:53 PM »
I'm trying to replicate a lookuplist from server to client. It seems to work partially, as in

it will replicate:

  lookuplist indexed by integer of string             // where values are stored in a string:   "name price"

but will not replicate:

  lookuplist indexed by integer of class auction    // where values are stored in a class:   data.name   data.price

Using the string, I need to Tokenize the string before checking the value, I think the "class" would be faster in this case.  Using the class, the size of list replicates, but the values are all blank.

It does not seem to even recognize list of string

  lookuplist indexed by integer of list of string     // where values are in a list:  data[1]   data[2]

Off Topic / Skype Crash?
« on: Feb 19, 19, 07:55:18 PM »
My Skype keeps disconnecting as soon as it starts up.
Not able to find discord.

edit: just came back, seemed it was temporary.

Developer Created Tutorials / Fixing mob agro
« on: Apr 10, 18, 07:23:58 AM »
Easy tutorial (fix for current code).

I noticed when a player moves by any of the mobs, that they don't attack the player. So, I tried a few things including checking the server side classes on the Node that the mob has as a target. What it does is simply check for either player account or player character. (it doesn't hurt to check both)

In server side script E_AiAgentClassMethods:

In method _AgentBrainTick()

change this:

Code: [Select]
    foreach target in targets
      //  GetTargetsInSphere hands back _playerAccount nodes, but we want the character node
      where target is kindof _PlayerAccount
        pc = target.GetMyChar()
        if pc != None and pc.IsAttackable()
          add back pc to pcTargets

to this:

Code: [Select]
    foreach target in targets
      //  GetTargetsInSphere hands back _playerAccount nodes, but we want the character node
      where target is kindof _PlayerAccount
        pc = target.GetMyChar()
        if pc != None and pc.IsAttackable()
          add back pc to pcTargets
      where target is kindof E_playerCharacter
        if target.IsAttackable()
          add back target to pcTargets

by adding these lines:

Code: [Select]
      where target is kindof E_playerCharacter
        if target.IsAttackable()
          add back target to pcTargets

Here is the server side function for checking classes on the "target" node that the above target is pointing to. It prints the classes in the chat window at bottom of editor.

In server side script MiscUtils:


Code: [Select]
untrusted function getClasses(target as NodeRef)
public function GetNodeClasses(target as NodeRef)
  println("** Server classes on target **")
  if target <> None
    values as List of String = GetClassesOnNode(target)
    foreach val in values
      println("S class on targ "+val)

 This can be called from client using:

Code: [Select]
   call server MiscUtils:getClasses(target)

 or from the server using:  (after the 1st line in foreach loop)

Code: [Select]

Scripting & Programming / Logic question - targeting
« on: Jan 26, 18, 08:11:11 PM »
This code is called when a player dies, and a list of clients is needed to send the FX. (unchanged since 2009 original code)

 Subject is a noderef, yet its added to a list of IDs ?

I am getting an error :   "In function RemoteCallClient: player not found:9223372092080021780", this is because the list returning is not a list of IDs, but a list of noderefs. So, when I check against the player account ID, it wont skip the player because its not storing the actual account ID. Its storing this noderef --> "QueryRemoteInterestSet 9223372088254021580"

(funny thing is it didn't give this error before)

in MiscUtils (server side), written in 2009,

Code: [Select]
public function QueryRemoteInterestSet( subject as NodeRef, interestSet references List of ID )
  // determine the "remote interest set" for the given subject, i.e. the connected players
  // within spatial proximity of the subject and/or other servers with a proxy of this node
  $SPATIALAWARENESS_AREA._SAS_QueryBySubject( subject, interestSet )   
  loop i from interestSet.length to 1 by -1
    observer as NodeRef = interestSet[ i ]
    if( ( observer != None ) and not ( observer is kindof _PlayerAccount ) )
      remove interestSet at i
  where subject is kindof _PlayerAccount
    add back subject to interestSet                        // <---- add noderef to IDs?
    println("QueryRemoteInterestSet "+subject)

In E_commoncharacter (server side), also 2009

Code: [Select]
method ApplyLife() as Boolean
  if not me.E_isDead
    return false
  me.E_isDead = false
  me.E_hitPoints = 100
  me._TeleportCharacter( me.GetRezzPosition(), me.GetRezzRotation() )
  where me is kindof E_playerCharacter
    target as Class _Target
    target._tgtID = me.GetMyAccount()
    clients as List of ID
    MiscUtils:QueryRemoteInterestSet(me.GetInterestSetSubjectNode(), clients)
    foreach c in clients
      $FXSYSTEM.SendFxToClient(c, 10, target, target)
  return true

Scripting & Programming / LOS blocked by bounding box?
« on: Jan 12, 18, 07:43:17 PM »
I have been trying to use the standard raycast to check a hit, but it seems to be hitting the target's bounding box, and gives a result of blocked LOS. I added a debug draw line to show it in the game.

When a wall is in the way, it finds it and marks as "blocked", it finds crates too, but it also finds the bounding box of the target (not sure why - its not a mesh), but gives a result of blocked.

When checking the mesh name for any of the blocked targets, it wont show a value.

Below, the wall blocks the LOS. The red arrow points at the target, using a red line from the player attacking with ranged attack. The green lines are at the point of intersection with the wall. The words in console (of editor) show LOS blocked, and intercept point, the target location, and the meshname = no name.

Below, we have another attack by the player, this time nothing is between the target and player, but the intercept shows at the bounding box, as does the console show the intercept point, the target location, and the meshname (again no name).

Currently, the attack still takes place, the LOS is being tested and just printing out a result.

Developer Created Tutorials / Facing target
« on: Dec 19, 17, 02:09:41 PM »
Sometimes the game needs to check if the player is facing the target or not, and let the player know if they are not. This will add a check for the player facing their target. I found this code in HJRef and modified it to work for the E_ability scripts.

In E_AbilityClassMethods (server side) script, under this code segment:

Code: [Select]
  // check we have a target
  if( me.E_script:GetTargetType() == "Single" )
    if( target == None )
      return ResultUtils:ErrorWithMessage( "Invalid target." )

add this code segment:

Code: [Select]
  // check facing
  if not( CheckFacing(owner, target))
    return ResultUtils:ErrorWithMessage( "Not facing target." )

add this function in the script also.

Code: [Select]
function CheckFacing(owner as NodeRef of Class E_CommonCharacter, target as NodeRef) as Boolean

  if owner is kindof E_playerCharacter
    MyPos as Vector3 = owner.GetPosition()
    MyRot as Vector3 = owner.getRotation()

    targPos as Vector3 = target.GetPosition()
    targRot as Vector3 = target.GetRotation()

    //Determine the angle of the activator (with auto-facing)
    angle as Float = ArcTangent((MyPos.x - targPos.x), (MyPos.z - targPos.z))

    //Adjust angle check to account for looping from -180 to 180 and vice versa
    width as Integer = 90

    Min1 as Float = angle - width
    Min2 as Float = Min1

    Max1 as Float = angle + width
    Max2 as Float = Max1

    if Min1 < -180
      Min2 = Min1 + 360
      Min1 = -180
      Max2 = 180

    if Max1 > 180
      Max2 = Max1 - 360
      Max1 = 180
      Min2 = -180

    if not((MyRot.y >= Min1 and MyRot.y <= Max1) or (MyRot.y >= Min2 and MyRot.y <= Max2))
      return false
  return true

Since the NPCs are usually made to face the target, we only check the player. It will print a small mesg to the chat window.

In the HJRef script, I found the code was using the Target Rotation instead of the User Rotation to check if they were at the right angle. (I don't think it should be checking the target angle.)

Scripting & Programming / [resolved] Online DB only?
« on: Oct 07, 17, 12:52:23 AM »
Working on making 2 messages, 1 for players that are "not" in the database, and 1 for players that are but currently "offline".
How does one know the difference?

I have found that all functions seem to access only the players online, not any of the accounts that exist with chars and names in them.  The function is C++ only as to whether the name can be used or not.

Code: [Select]
external function UpdateCharacterName( character as NodeRef, newName as String ) as Boolean

I was hoping something like $WORLD._knownPlayers or $WORLD._knownNames would be able to give a list, but those are the "online" only functions.

This only checks the online players. If they are not online it returns 0, it also returns 0 if they don't exist. So, no idea which they are.

Code: [Select]
  playerID as ID = $WORLD._FindPlayerByName(player)

This is about the same thing, it only works if the player is online. It cant tell if the player is offline or does not exist.

Code: [Select]
  if not($WORLD._IsPlayerOnline( playerID ))

This function (by the way it looks) should give all names, but it only gives info for the ones "online".

Code: [Select]
//  In E_WorldClassMethods (server)

remote method getPlayerBase()
  value1 as LookupList indexed by ID of Class _KnownPlayerData = $WORLD._knownPlayers
  $CHAT.ChatWorld("","amount of IDs "+value1.length)

  foreach val in value1
    $CHAT.ChatWorld("","ID: "+val)

  value2 as LookupList indexed by String of ID = $WORLD._knownNames
  $CHAT.ChatWorld("","amount of names "+value2.length)

  foreach val in value2
    $CHAT.ChatWorld("","name: "+val)

General Discussion / Login error
« on: Oct 02, 17, 09:26:05 PM »
I am getting this error with every log in. Yes I do get the heroblade to load in, but it seems like something might be messed up when its opening the editor. This error shows even when Skype says everything is fine.

Developer Created Tutorials / States System - movable objects
« on: Aug 10, 17, 08:40:57 AM »
Moderate scripting

This will be 2 part. First part will add the classes, fields and scripts, then second part will create an object using the system. I'm going to add a little more detail here and explain a few things better.

In the DOM (Server side), create a class E_States

The name doesn't matter too much, but this is the name I used. The 2nd function is mostly from the wiki States System . We call it from client giving it the node it needs to make the object. Mostly what this function does is set up the GUI for the dev to use, it pre-sets the values so most of the work is done. The 1st function I made, using some code also from the wiki, but added a few checks. This function called from client, will check that the targeted object is already a State System Object, in order to change its state. Compile the server side script 1st, as the client side calls these functions.

click open script

Code: [Select]
// change the current state of this object
untrusted method ClickyChangeState(objectID as ID, startState as String, endState as String)

  object as NodeRef = objectID
  if object == None
  if not hasmethod(object, "_GetMyStateObject") // make sure it can change
  areaStates as NodeRef of Class _StateObjects = $STATES._GetStatesNodeByClass("_areaStates")
  state as NodeRef of Class _StateObject = object._GetMyStateObject()
  currentState as String = state._GetStateValue()

  if currentState == startState
    println("changing from "+startState+"  to  "+endState)
    println("changing from "+endState+"  to  "+startState)

// make an Object into a Stateful Object
untrusted method MakeStatefulObject(object as NodeRef)
  println("MakeStatefulObject "+object)

  // assume object is a noderef to an asset that is a object we wish to make stateful
  statefulObject as NodeRef = object
  areaStates as NodeRef of Class _StateObjects = $STATES._GetStatesNodeByClass( "_areaStates")
  areaStateName as String = "Obj_"+object
  // Create the AreaState node
  var state = areaSTates._CreateStateObject( areaStateName )
  // GLOM on the stateful object class or one of its children, this supports right-click menus for wiring
  //   finding the object's state and editing the state
  GLOMClass("_statefulObject", statefulObject )

  // Change base_hard_association to link it to the statefulObject, allowing simultaneous deletes
  state._SwapStateBaseHardAssociationToTarget( statefulObject )

// *** these preset the values in the States system right click menu ***
  var values = state._GetStateValidValuesRoot()
  // Set valid values to use for transitions
  values._CreateStateValidValueForValue( "OPENED" )
  values._CreateStateValidValueForValue( "CLOSED" )

  // default state, ie all doors start closed
  state._SetStateDefaultValueByValue( "CLOSED" )

  var actionLists = state._GetStateActionListsRoot()
  // Create the actionList 
  var openActionList = actionLists._GetStateActionListByName( "open" + areaStateName )
  var closeActionList = actionLists._GetStateActionListByName( "close" + areaStateName )
  var initOpenActionlist = actionLists._GetStateActionListByName( "initOpen" + areaStateName )
  var initClosedActionList = actionLists._GetStateActionListByName( "initClose" + areaStateName )

  var transitions = state._GetStateTransitionsRoot()
  // Add Transitions
  var initOpen = transitions._CreateStateTransitionByValues( "NOTSET", "OPENED", "initOpen" + areaStateName )
  var open = transitions._CreateStateTransitionByValues( "CLOSED", "OPENED", "open" + areaStateName )
  var close = transitions._CreateStateTransitionByValues( "OPENED", "CLOSED", "close" + areaStateName )
  var initClose = transitions._CreateStateTransitionByValues( "NOTSET", "CLOSED", "initClose" + areaStateName )

  switchID as NodeRef = statefulObject
  basetime as TimeInterval = 0:00:05.000

  // Add actions to actionlists
  var openTransform = $STATES._StatesObjectCreateStateActionTransform( "_areaStates", switchID, "0,0,0", "0,0,0", "0,0,0", basetime, CLIENT )
  var closeTransForm = $STATES._StatesObjectCreateStateActionTransform( "_areaStates", switchID, "0,0,0", "0,0,0", "0,0,0", basetime, CLIENT )
  closeActionList._AddStateActionToActionList( closeTransForm )
  initClosedActionList._AddStateActionToActionList( closeTransform )
  initOpenActionList._AddStateActionToActionList( openTransform )
  openActionList._AddStateActionToActionList( openTransform )
  // Initialize to the default value
  state._SetStateByValue( "CLOSED" )

In the DOM, look for a (client side) class - HBNode

We are not going to change it, but going add a script for it. When objects are made, NPCs, Player chars, clicky type objects, they use HBnode for a base class.

The 1st function InputMouseEvent() checks for any mouse movement and responds based on what the user did, with hovering over or clicking on the object. There is a check for other type of objects, to see if they need a different response than what we have here. Since we don't want to make player chars into clicky objs, we skip if they are the object targeted. IsHeroBlade() is a check to see if the user is a dev in the editor, if not skip this part so the player won't use it. We don't want to make NPCs into stateful objects, so we skip them too.

When the mouse hovers over the object, we want to know which so we make the object glow with a green pulse, and when we are not over that object we reset it to normal.  On the click, since we don't want this to happen all the time, we check for 2 key presses and the mouse click in order to make our Target object into a Stateful Object which uses the States System. We also will have just a click on the object, to make it respond to the state system, which is usable by the players also. This will check the range (which can be changed from 3.5 meters) to the object, so that we don't effect objects from across the area. Meters are 1/10 the size of Units, which is what the base code is set up to use. Then we call server to make the object change state, or interact with the mouse click.

ShowClasses() is a function I made that will show which classes are on the node, since the control-T does not show classes on all objects, like the NPCs and player chars. GetRangeDistance() will check the range between the player and the targeted node, if the player is not in range it will toss a pup up message mid screen to the user. Next we have the color changes for the object used when mouse hovers over them.

click open script

Code: [Select]
// for the Highlighting of interactive objects in the world
// when the mouse hovers over it.
shared function InputMouseEvent(args references Class _MouseEvent)
  targ as NodeRef of Class HBNode = args.MouseTarget

//  if targ is kindof ClickyObject
//    ClickyObjectClassMethods:InputMouseEvent(args)
//    return
//  .
  if targ is kindof E_playerAccount

  // devs only
  if IsHeroBlade()
    if not (targ is kindof E_nonplayerCharacter)
      when args.MouseEventType
        is Enter
//          showClasses(targ)
        is Leave
        is Click
          if args.leftButton and args._ctrlKey and args._altKey  // special check to avoid mishaps
            object as ID = args.MouseTarget
            println("making "+object+" into StatefulObject ")
            call server E_StatesClassMethods:MakeStatefulObject(object)
  // all players
  when args.MouseEventType
    is Click
      if not (targ is kindof E_nonplayerCharacter)
        if args.leftButton
          var range = getRangeDistance(targ)
          if range < 3.5               // meters
            object as ID = args.MouseTarget
            println("toggle open/close for "+object)
            call server E_StatesClassMethods:ClickyChangeState(object, "CLOSED", "OPENED")

function showClasses(target as NodeRef)
  println("** classes on target **")
  values as List of String = GetClassesOnNode(target)
  foreach val in values
    println("class on targ "+val)

// check for object being out of clicking range
function getRangeDistance(target as NodeRef) as Float
  range as Float

  if not (target is kindof E_nonplayerCharacter)  // skip npcs
    var player = GetPlayerCharacterNode()
    ownerPos as Vector3
    getNodePosition(player, ownerPos)

    targetPos as Vector3
    getNodePosition(target, targetPos)

    range = VectorLength(targetPos - ownerPos) * 10 // in meters
    if range > 3.5
      msg as String = "You are too far away."
      color as Class rgba = MiscUtils:MakeRGBA( 1.0, 0.5, 0.5, 1.0 )
      // addtext: target, text, color, expand, size
      FloatingText:AddText(player, msg, color, false, false)
  return range

// pulse green on mouse hover
method greenPulses(obj as NodeRef of Class HBNode)
  obj["DiffuseColor"] = "[0:#0.0,1.0,0.0,1.0:L][0.25:#0.0,4.0,0.0,1.0:L][0.5:#0.0,10.0,0.0,1.0:L][0.75:#0.0,4.0,0.0,1.0:L][1:#0.0,1.0,0.0,1.0:L]L;1.25 "
  obj["AmbientColor"] = "[0:#0.0,1.0,0.0,1.0:L][0.25:#0.0,4.0,0.0,1.0:L][0.5:#0.0,10.0,0.0,1.0:L][0.75:#0.0,4.0,0.0,1.0:L][1:#0.0,1.0,0.0,1.0:L]L;1.25"
// pulse white normally
method whitePulses(obj as NodeRef of Class HBNode)
  obj["DiffuseColor"] = "[0:#1.0,1.0,1.0,1.0:L][0.25:#4.0,4.0,4.0,1.0:L][0.5:#10.0,10.0,10.0,1.0:L][0.75:#4.0,4.0,4.0,1.0:L][1:#1.0,1.0,1.0,1.0:L]L;1.25 "
  obj["AmbientColor"] = "[0:#1.0,1.0,1.0,1.0:L][0.25:#4.0,4.0,4.0,1.0:L][0.5:#10.0,10.0,10.0,1.0:L][0.75:#4.0,4.0,4.0,1.0:L][1:#1.0,1.0,1.0,1.0:L]L;1.25"
// pulse red on reset
method redPulses(obj as NodeRef of Class HBNode)
  obj["DiffuseColor"] = "[0:#1.0,0.0,0.0,1.0:L][0.25:#4.0,0.0,0.0,1.0:L][0.5:#10.0,0.0,0.0,1.0:L][0.75:#4.0,0.0,0.0,1.0:L][1:#1.0,0.0,0.0,1.0:L]L;1.25"
  obj["AmbientColor"] = "[0:#1.0,0.0,0.0,1.0:L][0.25:#4.0,0.0,0.0,1.0:L][0.5:#10.0,0.0,0.0,1.0:L][0.75:#4.0,0.0,0.0,1.0:L][1:#1.0,0.0,0.0,1.0:L]L;1.25"
// reset to normal value
method noPulses(obj as NodeRef of Class HBNode)
  obj["DiffuseColor"] = "1,1,1,1"
  obj["AmbientColor"] = "1,1,1,1"

Next we will make an Object - simple door.

Scripting & Programming / States System
« on: Aug 04, 17, 09:06:56 PM »
I have been working with the States System and had a question, which might be obvious to someone, or someone else might have already got this part completed.

This turns objects into Stateful Objects, that can move like doors.


at the bottom of the page is the script to use, with 2 lines that had variables that were not included in the script - switchID and CLIENT. I am guessing that client is the players "accountID", sent in with the noderef for aDoor. But what is the switchID?

  // Add actions to actionlists
  var openTransform = $STATES._StatesObjectCreateStateActionTransform( "_areaStates", switchID, "0,0,0", "-45,0,0", "0,0,0", 0:00:05.000, CLIENT )
  var closeTransForm = $STATES._StatesObjectCreateStateActionTransform( "_areaStates", switchID, "0,0,0", "0,0,0", "0,0,0", 0:00:05.000, CLIENT )

Scripting & Programming / any difference in script?
« on: Jun 05, 17, 01:38:15 PM »
curious, is there a difference in the engine for these? Is one of them slower? Or would it be a matter of preference?
(I see these written both ways in so many places)

level = level + 1
level += 1

Scripting & Programming / combat stance
« on: May 19, 17, 08:02:54 PM »
This has probably been noticed by others, and some might have it working. We have it partially working.

When the player character loads in, and some of the other NPCs seem to be in a combat stance, instead of idle. There is a small section that sets this.

in client script E_ACCControlerClassMethods, in method _onPreAnimUpdate() look for:

Code: [Select]
    if GetAnimInput(mychar, "BaseMode") != "Combat"
      SetAnimInput(mychar, "BaseMode", "Combat")

This sets the combat stance. Here is what we have changed it to make it the idle stance. We added a field to the E_CommonCharacter class as Boolean that we could set as the player and NPC entered combat.

First we check if that is "combat" or not, then we set the stance based on its value. Now when the player loads and the NPCs all start in idle stance. When a player attacks the NPCs (monkeytoks), the NPCs change to combat stance. However, the player stays in idle stance, even though its field is changed like the NPCs.

Code: [Select]
  inCombat as Boolean
  where mychar is kindof E_CommonCharacter
    inCombat = mychar.E_InCombat
    println("mychar "+mychar.name+"  combat? "+mychar.E_InCombat)  // info 1
  if inCombat = true
    where mychar is kindof E_CommonCharacter
      println("mychar "+mychar.name+"  combat? "+mychar.E_InCombat)  // info 2
    if GetAnimInput(mychar, "BaseMode") != "Combat"
      SetAnimInput(mychar, "BaseMode", "Combat")
    if GetAnimInput(mychar, "BaseMode") != "Normal"
      SetAnimInput(mychar, "BaseMode", "Normal")

I can see the player character value and the NPC value both set to true, but only the NPC will change to combat stance. Forcing the player to combat by removing the check, I can see the player in combat, so the anim does exist.

adding some code to show info:
Info 1 will show all NPC names, not the player.
Info 2 will show only those effected by the combat stance change.

My thoughts:
Info 1 lets me know the player is either not using this function, or the player character is not a Common Character. Yet, changing the code here to show idle anim, also makes the player character show idle anim. In the DOM, the player character has Common character as a parent, so it has that class. And it changes like the NPCs change, so it is using this function.

I'm missing something to make it work, ideas?

General Discussion / date / time ?
« on: Apr 07, 17, 01:51:21 AM »
I was working on some scripts and noticed the date / time was set server time, yet when I saved the script it was set local time. This time difference seems to be messing with the way scripts are read in. A section that used to work, no longer works the same way, as I changed a script and changed it back, with a different time on it.

Pages: [1] 2 3 ... 10