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

Author Topic: [Resolved] Player Account SAS Awareness  (Read 2151 times)

FI-ScottZ

  • General Accounts
  • *
  • Posts: 1407
    • View Profile
    • Forever Interactive, Inc.
[Resolved] Player Account SAS Awareness
« on: Dec 09, 12, 04:57:20 AM »

For the Idea Fabrik engineers:
In resolving some of the script changes for 2.0 with our previous changes, I noticed that in server script _PlayerAccountClassMethods the bodies of the methods proxyLocal method _OnReplicationGroupAdded() and proxyLocal method _OnReplicationNodeRelease() have been cleared out.

Previously, _OnReplicationGroupAdded set e._SAS_EI_awareness = 7.0, which we had changed to a different value.  I simply scanned the scripts and changed everywhere that the awareness range was set.  Now that it no longer sets that, I am not sure of the implications within this class.  Does removing that code mean the setting of the SAS entity no longer matters, or should I still set the awareness range there?
« Last Edit: Dec 21, 12, 11:16:22 AM by HE-Cooper »
Logged
Scott Zarnke
Lead Programmer, Visions of Zosimos
CTO, Forever Interactive, Inc.

HE-Cooper

  • *****
  • Posts: 2221
    • View Profile
Re: [Queued] Player Account SAS Awareness
« Reply #1 on: Dec 18, 12, 09:54:07 AM »

This is on engineering's plate to investigate.
Logged

HE-JAY

  • HeroEngine
  • *****
  • Posts: 122
    • View Profile
Re: [Queued] Player Account SAS Awareness
« Reply #2 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!
« Last Edit: Dec 18, 12, 02:12:31 PM by HE-Jay »
Logged

AWW_boss

  • General Accounts
  • *
  • Posts: 846
  • gdfgd
    • View Profile
Re: [Resolved] Player Account SAS Awareness
« Reply #3 on: Jan 03, 13, 06:41:44 AM »

I noticed the awareness range is also set in _ACCControllerOwners method _RegisterACCCWithSpatialAwareness and _nonPlayerCharacters method  _OnReplicationGroupAdded. I am planning to build my stealth system based exclusively on spatial awareness (that would mean that players would have awareness range higher or lower depending on some skill modifier), and i would like if someone with better knowledge could explain what is the meaning of these 3 different settings:

1. E_Account: HE_SubscribeAccountToSpatialAwarenessForArea
e._SAS_EI_awareness = 7.0

2. _ACCControllerOwner: _RegisterACCCWithSpatialAwareness
e._SAS_EI_awareness = 7.0

3. _nonPlayerCharacter: _OnReplicationGroupAdded
e._SAS_EI_awareness = 7.0


« Last Edit: Jan 03, 13, 06:43:49 AM by AWW_boss »
Logged

FI-ScottZ

  • General Accounts
  • *
  • Posts: 1407
    • View Profile
    • Forever Interactive, Inc.
Re: [Resolved] Player Account SAS Awareness
« Reply #4 on: Jan 10, 13, 06:36:05 PM »

Thanks for the info, Jay.  I had forgotten about this post until wonky behavior began where our NPC would disappear.  I realized I hadn't gotten around to putting in these methods for increasing the awareness range.  Now it works again. :D

Boss brings up a good point: hopefully you will add HE_ override methods for the other places that awareness range is set, and perhaps have them be methods just for setting that value so we don't need to replicate the entire method.
Logged
Scott Zarnke
Lead Programmer, Visions of Zosimos
CTO, Forever Interactive, Inc.

AWW_boss

  • General Accounts
  • *
  • Posts: 846
  • gdfgd
    • View Profile
Re: [Resolved] Player Account SAS Awareness
« Reply #5 on: Jan 16, 13, 03:03:28 PM »

Can I get some help on this? What are those two used for and are you planning to give them overrides just like the one in _Account:

2. _ACCControllerOwner: _RegisterACCCWithSpatialAwareness
e._SAS_EI_awareness = 7.0

3. _nonPlayerCharacter: _OnReplicationGroupAdded
e._SAS_EI_awareness = 7.0
 
The problem is that everytime you roll script changes, this values get reset to 7.0. It's not something mission critical, but would like to know if it's going to be changed in the long run.
Cheers!
Logged