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.

Messages - HE-JAY

Pages: [1] 2 3 ... 9
1
General Discussion / Re: HSEIDemo.dll loading issue
« on: May 08, 13, 12:32:50 PM »
Thanks for bringing up this issue. It turns out the documentation for the HSEI had not been updated to reflect changes in naming conventions.

To resolve the issue, we've:
  • Updated the HeroScript Extension Interface wiki page with the correct information
  • Made the appropriate changes to the HSEIDemo.zip archive found on the downloads page

The specific change was to the signatures of the exported functions in the plugin to both 'get' and 'release' the HSEI interface.

The new signatures are:
Code: [Select]
extern "C" {

__declspec(dllexport) __cdecl HSEI::HeroScriptExtensionInterface * getHSLInterface(int version_number);

__declspec(dllexport) __cdecl int releaseHSLInterface(HSEI::HeroScriptExtensionInterface * aInterface);

}

Making the above modification to your own HSEI plugins will result in the LoadPlugin external function call succeeding where it had previously failed.

Hope this helps!

2
The upgrade to Sapphire.L has now been completed and all worlds have been returned to service.

3
Package applications for Stage One have now begun for all regions.

4
For HeroCloud worlds created prior to the release of HeroEngine 2 (i.e. this only applies to worlds that already existed prior to Dec. 5th, 2012), the following fix has been issued:

Problem
The prop spec named "Fading Prop" (specID=1 in the _PropSpecOracle) did not write itself to the repository during world creation.  As a result, attempts to reference the prop on the client (by calling requestSpecByKey) will fail and generate a script error.

Solution
In order to coerce the prop spec into writing out the appropriate repository file, perform the following steps:
  • Open the _PropSpecOracle from the 'Tool's tab of the Utilities Interface (F5 menu).
  • Select the "Fading Prop" spec and click 'Edit'.
  • Click 'OK' to force the spec to be saved; this will trigger a repository file write.
  • Verify the file '1._PropSpec' exists in the ScriptData folder using your Repository Browser

Do I need this fix?
You can verify that this fix applies to you by checking for the existence of the repository file '/ScriptData/1._PropSpec'.  If this file does not exist in your repository (use your Repository Browser to check), then you should perform the steps outlined above to resolve the issue.

5
General Discussion / Re: [Queued] Player Account SAS Awareness
« on: Dec 18, 12, 02:00:31 PM »
With the Sapphire release, we made several improvements to the way seamless transitions are handled.  One such change is a more efficient method of handling situations in which an area is seamlessly linked to both the source and destination areas of a seamless transition.  To facilitate this change, we moved the subscription/unsubscription of a player to edit queues and spatial awareness systems to a set of new methods in _AccountClassMethods.  You'll find the new code in _AccountClassMethods::_SubscribeAccountToSpatialAwarenessForArea.

In order to help developers make better use of the new methods, we decided to expose four new overrides that can be used to extend or override the default functionality.  These overrides did not go out with the initial Sapphire release, so I've provided instructions on how to add them manually (we will of course push these changes out to everyone in the next package release).

Instructions:
1. In _MethodCallbacksClassMethods (server), add the following definitions to the tail of the file:
Code: [Select]
method HE_SubscribeClientToAreaEditQueues( account_id as ID ) as Boolean
  return false
.

method HE_UnsubscribeClientFromAreaEditQueues( account_id as ID ) as Boolean
  return false
.

method HE_SubscribeAccountToSpatialAwarenessForArea(accountID as ID, areaID as ID, instanceID as ID) as Boolean
  return false
.

method HE_UnsubscribeAccountFromSpatialAwarenessForArea(accountID as ID, areaID as ID, instanceID as ID) as Boolean
  return false
.
2. In _AccountClassMethods, replace these four methods (located roughly at line 248 and ending roughly at line 379) with the following code (note: the only changes to these methods are the additions of calls to the HE_ overrides):
Code: [Select]
method _SubscribeClientToAreaEditQueues( account_id as ID )
  handled as Boolean
  if hasMethod( me, "HE_SubscribeClientToAreaEditQueues" )
    handled = me.HE_SubscribeClientToAreaEditQueues(account_ID)
  .
  if not handled
    connection as NodeRef of Class _PlayerConnection = GetPlayerConnectionNode(account_id)
    areaID as ID = GetAreaNumber()
    instanceID as ID = GetInstanceNumber()
 
    //Deliver edit command queue subscription event for current area
    connection._OnPlayerSubscribeToEditCommandQueue(areaID, instanceID)
 
    client_reference_token as String = GetPlayerReferenceToken( account_id )
    area_node as NodeRef of Class AreaNode = $AREA._GetAreaNode()
 
    currentSubscriptions as LookupList indexed by ID of List of ID
   
    foreach linked_area in area_node._areaSeamlessLinks
      add back instanceID to currentSubscriptions[linked_area]
    .
   
    oldSubscriptions as LookupList indexed by ID of List of ID
    //add the area we just came from to the old list, provided the value is initialized to something other than the world server
    if connection._playerConnectionTraveledFrom.AreaID != 0
      add back connection._playerConnectionTraveledFrom.AreaInstanceNumber to oldSubscriptions[connection._playerConnectionTraveledFrom.AreaID]
    .
    //add each area instance to which our previous area was seamlessly connected to the old list
    foreach oldSeamlessLink in connection._playerConnectionTraveledSeamlessLinks
      add back oldSeamlessLink.AreaInstanceNumber to oldSubscriptions[oldSeamlessLink.AreaID]
    .
 
   
    //For each potential new subscription, subscribe the client if it wasn't already subscribed
    foreach potentialSubscription in currentSubscriptions
      if not (connection._playerConnectionTraveledSeamlessly and oldSubscriptions has potentialSubscription)
        $EDIT._SubscribeClientToEditQueueByToken( account_id, potentialSubscription, instanceID, client_reference_token )
        connection._OnPlayerSubscribeToEditCommandQueue(potentialSubscription, instanceID)
        $ACCOUNT._SubscribeAccountToSpatialAwarenessForArea(account_id, potentialSubscription, instanceID)
      .
    .
   
    //Add current area to prevent its removal as stale
    add back instanceID to currentSubscriptions[areaID]
   
    //subscribe to the current area's sas since we haven't done that yet
    $ACCOUNT._SubscribeAccountToSpatialAwarenessForArea(account_id, areaID, instanceID)
   
    //For each old subscription, unsubscribe the client if it isn't still important
    //allSubscriptions as LookupList indexed by ID of List of ID = connection._GetPlayerSubscribedEditCommandQueues()
    staleSubscriptions as LookupList indexed by ID of List of ID
    if connection._playerConnectionTraveledSeamlessly
      foreach potentialUnsubscription in oldSubscriptions
        if not (currentSubscriptions has potentialUnsubscription)
          add back instanceID to staleSubscriptions[potentialUnsubscription]
        .
      .
    .
   
    foreach staleSubscription in staleSubscriptions
      $ACCOUNT._UnsubscribeAccountFromSpatialAwarenessForArea(account_id, staleSubscription, instanceID)
      $EDIT._UnsubscribeClientFromEditQueue( connection._accountID, staleSubscription, instanceID)
      connection._OnPlayerUnsubscribeFromEditCommandQueue(staleSubscription, instanceID)
    . 
  .
.

method _UnsubscribeClientFromAreaEditQueues( account_id as ID )
  handled as Boolean
  if hasMethod( me, "HE_UnsubscribeClientFromAreaEditQueues" )
    handled = me.HE_UnsubscribeClientFromAreaEditQueues(account_id)
  .
  if not handled
    connection as NodeRef of Class _PlayerConnection = GetPlayerConnectionNode(account_id)
    areaID as ID = GetAreaNumber()
    instanceID as ID = GetInstanceNumber()
    $EDIT._UnsubscribeClientFromEditQueue( account_id, areaID, instanceID)
    connection._OnPlayerUnsubscribeFromEditCommandQueue(areaID, instanceID)
    $ACCOUNT._UnsubscribeAccountFromSpatialAwarenessForArea(account_id, areaID, instanceID)
   
   
    area_node as NodeRef of Class AreaNode = $AREA._GetAreaNode()
   
    foreach linked_area in area_node._areaSeamlessLinks
      $EDIT._UnsubscribeClientFromEditQueue( account_id, linked_area, instanceID)
      connection._OnPlayerUnsubscribeFromEditCommandQueue(linked_area, instanceID)
    .
  .
.

remote method _SubscribeAccountToSpatialAwarenessForArea(accountID as ID, areaID as ID, instanceID as ID)
  handled as Boolean
  if hasMethod( me, "HE_SubscribeAccountToSpatialAwarenessForArea" )
    handled = me.HE_SubscribeAccountToSpatialAwarenessForArea(accountID, areaID, instanceID)
  .
  if not handled
    thisAreaID as ID = GetAreaNumber()
    thisInstanceID as ID = GetInstanceNumber()
    if thisAreaID != areaID or thisInstanceID != instanceID
      call area areaID instance instanceID $ACCOUNT._SubscribeAccountToSpatialAwarenessForArea(accountID, areaID, instanceID)
      return
    .
    account as NodeRef of Class _PlayerAccount = accountID
   
    e as Class _SAS_EntityInformation
    // Use the range of 70 meters as the awareness range
    e._SAS_EI_awareness = 7.0
    if account != None
      e._SAS_EI_position = account.GetPosition()
    .
    add back accountID to e._SAS_EI_event_receiving_nodes
    $SPATIALAWARENESS_AREA._SAS_AddEntity(accountID, e)
    subjects as List of ID
    subject as NodeRef of Class _PlayerAccount
    $SPATIALAWARENESS_AREA._SAS_QueryByEntity(accountID, subjects)
    if account != None
      foreach subj in subjects
        account._SO_Entered($SPATIALAWARENESS_AREA, account, subj)
        subject = subj
        if subject != None
          subject._SO_Entered($SPATIALAWARENESS_AREA, subj, account)
        .
      .
    .
  .
.

remote method _UnsubscribeAccountFromSpatialAwarenessForArea(accountID as ID, areaID as ID, instanceID as ID)
  handled as Boolean
  if hasMethod( me, "HE_UnsubscribeAccountFromSpatialAwarenessForArea" )
    handled = me.HE_UnsubscribeAccountFromSpatialAwarenessForArea(accountID, areaID, instanceID)
  .
  if not handled
    thisAreaID as ID = GetAreaNumber()
    thisInstanceID as ID = GetInstanceNumber()
    if thisAreaID != areaID or thisInstanceID != instanceID
      call area areaID instance instanceID $ACCOUNT._UnsubscribeAccountFromSpatialAwarenessForArea(accountID, areaID, instanceID)
      return
    .
    account as NodeRef of Class _PlayerAccount = accountID
    if account != None
      // query what I observe
      subjects as List of ID
      subject as NodeRef of Class _PlayerAccount
      $SPATIALAWARENESS_AREA._SAS_QueryByEntity(account, subjects)
      foreach subj in subjects
        account._SO_departed($SPATIALAWARENESS_AREA, account, subj)
        subject = subj
        if subject != None
          subject._SO_departed($SPATIALAWARENESS_AREA, subj, account)
        .
      .
    .
    $SPATIALAWARENESS_AREA._SAS_RemoveEntity(accountID)
  .
.
3. Follow the instructions on Adapting Clean Engine to add a game-specific override to the $ACCOUNT system node and add your own custom code (e.g. your modification of the spatial awareness range) to the proper override (making sure to 'return true' from the method in order to prevent the original code from negating your override).

Now - during a seamless transition - your new override's code will be executed! You can repeat this procedure for any of the other overrides in order to custom-tailor the subscription/unsubscription process.

This change will allow you to leverage these overrides before they become an official part of the product; once officially deployed to the cloud, these changes will then become available to all developers in HeroCloud worlds (no need to undo your manual changes, as this will be done automatically for you).

Enjoy!

6
Scripting & Programming / Re: proxy nodes
« on: Jul 23, 12, 10:36:09 AM »
System areas (http://hewiki.heroengine.com/wiki/System_Areas) - by virtue of being registered to receive player updates - have access to all currently-logged-in players' reference tokens (http://hewiki.heroengine.com/wiki/Player_Reference_Token). This allows the system area to communicate directly with the player, regardless of which area they're in.  From such a system area, you can freely replicate and remote-call to a client, bypassing the need to replicate first to their area and then to their client. You could - alternatively - use proxies to replicate first to their area and then to their client, but that would entail additional bookkeeping.

7
Could someone please explain or point me to the correct wiki page, tutorial or whatever as to what I need to do to get a class I have created to attach to an object and stay persistent?

I have been going in circles trying to get my class functional outside of adding it manually every time I log in.

Thanks

Can you provide a more specific use case? There are many ways in which you can persist data (http://hewiki.heroengine.com/wiki/Data_storage_options), and there are several ways to create a node from a particular class or add a class to an already persistent node (http://hewiki.heroengine.com/wiki/Node_Persistence) (http://hewiki.heroengine.com/wiki/Nodes_and_Classes).

In order for a node to get loaded in from the database, it must either be hard-associated (http://hewiki.heroengine.com/wiki/Associations) to a root node (such as the area root, account root, character root) or it must be an arbitrary root node (http://hewiki.heroengine.com/wiki/Arbitrary_Root_Node).

9
Scripting & Programming / Re: FPS Reference
« on: Jun 28, 12, 10:05:20 AM »
All important player actions in the FPS are directed by the client and mediated by the server.  Attacking with a weapon, for example, uses reverse replication to send events to the server and then to other players connected in the area. This logic starts in the client-side method FPS_Weapon::FPS_WeaponAttack, follows into FPS_Weapon::FPS_WeaponAttackDelayed, and then finishes with $FPS_EVENT.FPS_SendPlayerAttackEvent and $FPS_EVENT.FPS_SendPlayerHitEvent. These events are received in other clients' client-side scripts FPS_EventPlayerHitClassMethods and FPS_EventPlayerAttackClassMethods, respectively.

10
Two things:
  • In order to access a field on the current node from within a method, you need to reference it with the 'me' keyword (http://hewiki.heroengine.com/wiki/ME#The_me_Node_2). In your case, 'me.myTimer.timerData'
  • When a timer ticks, it will either call the 'method' on the node to which it belongs (in your case, that would be the genericTimer) or it will call the 'function' in the script specified by the 'script' field. Before starting the timer, you'll need to set that script field to be the scriptref of the script in which your callback function resides

An example:
Code: [Select]
method myMethod()
  me.myTimer.script = SYSTEM.EXEC.THISSCRIPT
  me.myTimer.fireRate = 00:00:01
  me.myTimer.start()
.

function myTimer_tick()
  println("Tick!")
.

Also, there are several ways to reference the owner of the timer; one is to store a reference to the node in the timerData field; another is to use associations to link the node which contains the timer to another node (http://hewiki.heroengine.com/wiki/Associations); a third  is to use 'me' (which - in a timer callback - will refer to the node which contains the timer) to find your source node:
Code: [Select]
function myTimer_tick()
  where me is kindof MyNodeClass
    me.myOtherMethod("Tick!")
  .
.

11
When a secondary node is replicated to the client, the method _OnReplicationNodeAdded will be called on the primary node in the replication group. If you want to keep references to these objects on the client, you'll want to respond to that event by storing their IDs or noderefs in whatever manner you deem appropriate (e.g. associations, list of noderef, fields, etc).

So, for example:
Code: [Select]
method _OnReplicationNodeAdded(addedNode as NodeRef)
  where addedNode is kindof NodeClassICareAbout
    AddAssociation(me, "MyGameSpecificSoftAssociation", addedNode)
  .
.

12
Design & World Building / Re: Room Visibility problem
« on: Jun 14, 12, 03:21:37 PM »
I misspoke slightly (:  To move instances from one seamlessly connected area to another, the procedure is as follows:
  • Stand in the destination area (the area you want to move the instances to) such that the destination area is shown at the bottom-right of the HeroBlade window
  • Hop into FLY mode and select the assets you want to snag
  • Open the Area panel and expand the Seamless Links subpanel
  • Click the 'Bring Instances Here' button and watch as the blue bounding boxes (which indicate the instances are in a different area) turn yellow and their properties reflect their new location.

13
Design & World Building / Re: Room Visibility problem
« on: Jun 14, 12, 09:40:33 AM »
To be doubly sure, check the properties "Room" and "AreaNumber"/"AreaName" in the properties panel while your tree is selected.  Know that when you create an asset instance in the world, it will 'always always always' belong to the area displayed in the lower-right-hand corner of HeroBlade and to the room currently active. You can of course move the instance using the Assets panel to either a different room or different area, but by default it will always appear in the area and room your character is standing in.

14
General Discussion / Re: what can be made a stateful object?
« on: Jun 12, 12, 05:02:32 PM »
The current implementation of area states only allows for the creation and modification of area states on the server.  While code does exist on the client to create nodes which reflect data about the server-side states, you cannot create an area state on the client by hand. It sounds like what you want to do is create your area state on the server, create a trigger or some other mechanism which will toggle your state, and then make a call on the server to modify the state object.

All tutorials, example code and demo code that make use of area states are exclusively on the server.

15
General Discussion / Re: what can be made a stateful object?
« on: Jun 12, 12, 10:16:40 AM »
You guys have correctly identified an omission in the current version of script distributed with HeroCloud. We've corrected the issue for the next package release, but - until then - here's how you can restore access to the client-side methods that are throwing script errors:
  • Create a new association definition in the client DOM named 'E_StateRootAssoc' and give it the properties 'Unique=yes', 'Unique Source=yes', 'Unique Target=yes' and 'Hardness=soft'
  • Change line 216 of client-side script '_StatesClassMethods' to read 'foreach a in QueryAssociation($STATES, "E_StateRootAssoc", 0)'
  • Change line 228 of client-side script '_StatesClassMethods' to read 'AddAssociation($STATES, "E_StatesRootAssoc", StateRoot)'
  • compile and submit

When the next package release is distributed, the script will be overwritten with our new version and a definition for _StateRootAssoc will be created. This will maintain the above patch permanently.

Please Note: It's important that you do 'not' create a definition for _StateRootAssoc on your own, as this will conflict with any future update we make to the system; please use the name E_StateRootAssoc and modify the script mentioned above.

Hopefully this will solve any issues with client-side area state scripts; if not, feel free to follow up.

Pages: [1] 2 3 ... 9