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

Author Topic: [Resolved] GetSpecByKey - from an Ability Icon  (Read 1572 times)

cloudnine

  • General Accounts
  • *
  • Posts: 80
    • View Profile
    • Youtube
[Resolved] GetSpecByKey - from an Ability Icon
« on: Jan 15, 13, 03:02:36 PM »

E_Ability inherits from SpecDerivedObject, ObsListener, _IconSubjectInterface

Clicking on an abilityicon send a request to activate the ability.
But getspecBy key will not work even though the node has a speckey of 1
I can/sn and see  the oracle is AbilitySpecOracle
E_AbilityClassMethods-Client
Code: [Select]
method getMySpec() as NodeRef of Class baseSpec
  // May return none...always check
  println("SOMYSPECKEYIS (" +me.SpecKey +")")                          //(1)
  oracle as NodeRef of Class SpecOracle = me.getMySpecOracle()
  println("ORACLE IS (" +oracle +")")                                  // (1000000989)
  println("ORACLESPECKEY IS (" +oracle.GetSpecByKey(me.SpecKey) +")")  // (0)
  return oracle.GetSpecByKey( me.SpecKey )
.
I also have a privatereplicationgroup that does Requestspecbykey when a node is added.
but that doesnt seem do anything
« Last Edit: Feb 04, 13, 08:37:57 AM by HE-Cooper »
Logged

JoshHalls

  • Founding Professional
  • *****
  • Posts: 335
    • View Profile
    • The Repopulation
Re: GetSpecByKey - from an Ability Icon
« Reply #1 on: Jan 15, 13, 04:21:42 PM »

Not 100% sure if you are aware of it, but GetSpecByKey on the client isn't going to return a result unless you have done a requestSpecByKey call first and it is cached on the client.  We often do this for specs we know are going to be needed or before they might open a GUI as not to deal with the async nature of it (and other times, we deal with it, depends on how it is handled).  It does consume a bit of memory on the client and you don't want to try to load up 2000 specs, but if they are going to need it at some point it is just easier to deal with.  To a point we even precache a few important oracles on first login.

Either way, need to make sure whatever you are referencing if you try to do a request to cache it is actually being called in the first place.  If you are trying to get the spec with GetSpec before it is first called by requestSpec you are doing it wrong.  It is useful to know how to do both of course as there are instances where you need to do it on the fly and the async process and handling the listener process properly is important.
Logged
Co-Owner/Programmer - The Repopulation

cloudnine

  • General Accounts
  • *
  • Posts: 80
    • View Profile
    • Youtube
Re: GetSpecByKey - from an Ability Icon
« Reply #2 on: Jan 16, 13, 07:00:00 AM »

Looking into it more I have a PersonalAccountReplicationGroup association which is a hard association
If I use that I get an error, can't hard associate a node which is indestructible
so I took that out.
What happens is when I learn the ability it Transmits a collection to the client
The client gets it and "unpacks" it then adds

AbilitiesClassMethods - client
Code: [Select]
method AddCollectionElement( element as NodeRef, addBack as Boolean )
  println("ADD a collection ELEMENT!")
  where element is kindof E_Ability
    var oracle = element.GetMySpecOracle()
    println("ELEMENT IS (" +element +")")                     //(9223372063826132827)
    println("ELEMENT KEY IS (" +element.getMySpecKey() +")")  //(1)
    println("ELEMENT SPECKEY IS (" +element.SpecKey +")")  //(1)
    oracle.RequestSpecByKey(element.SpecKey, None)
    println("LOL THE ORACLE SPEC KEY IS (" +oracle.GetSpecByKey(element.SpecKey +")")) //(0)
   
  .
  parentClass::AddCollectionElement(element, addBack)
.
It uses None as the listener, I also tried using element as the listener
If I open the repobrowser in scriptdata there is a 1.AbilitySpec there
Logged

cloudnine

  • General Accounts
  • *
  • Posts: 80
    • View Profile
    • Youtube
Re: GetSpecByKey - from an Ability Icon
« Reply #3 on: Jan 17, 13, 07:30:37 AM »

Well I added another requestspecbykey in E_Ability class
Code: [Select]
method getMySpec() as NodeRef of Class baseSpec
  // May return none...always check
  println("SOMYSPECKEYIS (" +me.SpecKey +")")
  oracle as NodeRef of Class SpecOracle = me.getMySpecOracle()
  println("ORACLE IS (" +oracle +")")
  println("ORACLESPECKEY IS (" +oracle.GetSpecByKey(me.SpecKey) +")")
  oracle.requestSpecByKey(me.SpecKey, me)
  return oracle.GetSpecByKey( me.SpecKey )
.
And Uncommented the #debug in SpecOracle class
Code: [Select]
07:19:05: SCRIPT:[E_AbilityClassMethods]:ClientSaysAbilityCanBeActivated()
07:19:05: SCRIPT:[E_AbilityClassMethods]:9223372063887132860
07:19:05: SCRIPT:[E_AbilityClassMethods]:Clientsaysabilitycanbeactivated
07:19:05: SCRIPT:[E_AbilityClassMethods]:MYORACLEIS (1000003602)
07:19:05: SCRIPT:[E_AbilityClassMethods]:The GETSPECBYKEY is (0)
07:19:05: SCRIPT:[E_AbilityClassMethods]:The GETMYSPECKEY is (1)
07:19:05: SCRIPT:[E_AbilityClassMethods]:SOMYSPECKEYIS (1)
07:19:05: SCRIPT:[E_AbilityClassMethods]:ORACLE is (1000003604)
07:19:05: SCRIPT:[E_AbilityClassMethods]:ORACLESPECKEY is (0)
07:19:05: SCRIPT:[SpecOracleClassMethods]:requestSpecByKey specKey: 1 listener: 9223372063887132860
07:19:05: SCRIPT:[SpecOracleClassMethods]: new spec: 1000003607 created for key: 1
07:19:05: SCRIPT:[SpecOracleClassMethods]:theSpec: 1000003607 loadStatus: NOTREADY
07:19:05: SCRIPT:[E_AbilityClassMethods]:SO GETMYSPEC is (0)
07:19:05: SCRIPT:[E_AbilityClassMethods]:The Ability ID is(1)
07:19:05: SCRIPT:[E_AbilityClassMethods]:MYSPECIS (0)
07:19:05: SCRIPT:[E_AbilityClassMethods]:MYSPEC2IS (0)
07:19:05: !ERROR!HeroScript::HeroMachine::ScriptError:node ID 0 not found
07:19:05: !ERROR!System:SCRIPT ERROR: node ID 0 not found
01/17/2013 07:22:51
call trace:
  Script E_AbilityClassMethods line 149 me[ID=9223372063887132860 Class=E_Ability,PlayerAbility]
  Script E_AbilityClassMethods line 191 me[9223372063887132860]
  Script AbilityIconClassMethods line 26 me[1000003374]
  Script _GUIIconClassMethods line 104 me[1000003374]
starting method/function ONMOUSECLICK
starting me[ID=1000003374 Class=AbilityIcon]
07:19:05: SCRIPT:[SpecOracleClassMethods]:onRepositoryDataDownloaded() name: 1.abilitySpec requestTag: 1000991 successful: true
07:19:05: SCRIPT:[SpecOracleClassMethods]:Had to create new spec: 1000003614 for key: 1
07:19:05: SCRIPT:[SpecOracleClassMethods]:requestSpecByKey specKey: 1 listener: 1000003618
07:19:05: SCRIPT:[SpecOracleClassMethods]:theSpec: 1000001423 loadStatus: READY


Looks Like It redownloads the spec everytime I click on the Icon
Logged

cloudnine

  • General Accounts
  • *
  • Posts: 80
    • View Profile
    • Youtube
Re: GetSpecByKey - from an Ability Icon
« Reply #4 on: Feb 02, 13, 11:30:13 AM »

The Ability Specs are not being cached on the client or they are and get erased or aren't found.
the getspecbykey really just needs check the specs  _speckeymap???

I can do this for Gui and it works fine but not abilities

I presume I can anchor on the server to the character, area, or other
On the client I should use system.info.worldanchor
so on the client I have classes
E_Ability
AbilitySpec
AbilitySpecOracle
AbilityOracle
world_anchor
ClientDataSystem

In E_baseclient
Code: [Select]
wa as NodeRef of Class world_anchor = SYSTEM.INFO.WORLDANCHOR
  wa.getAbilityOracle()

In world_anchor there are two methods for ability
Code: [Select]
method GetAbilityOracle() as NodeRef of Class AbilityOracle
  oracles as List of ID = ClientDataSystem:GetDataForSystem( "OracleAnchor" )
  println("Worldanchor get ability oracle !!!" )
  abilityOracle as NodeRef of Class AbilityOracle
 
  oTest as NodeRef
  foreach o in oracles
    otest = o
    if otest is kindof AbilityOracle
      abilityOracle = otest
    .
  .
 
  if abilityOracle = None
    abilityOracle = CreateNodeFromClass( "AbilityOracle" )
    // add it to the oracleAnchor root of the clientDataSystem
    println("Worldanchor add data to system !!!")
    ClientDataSystem:AddDataToSystem( "OracleAnchor", abilityOracle )
   
    // Create a listener so that events come into the AbilityOracle class methods script
    me.addListener( me.createScriptListener( AbilityOracleClassMethods, false ) )
  .
 
  return abilityOracle
.

method GetAbilitySpecOracle() as NodeRef of Class AbilitySpecOracle
  abilitySpecOracle as NodeRef of Class AbilitySpecOracle = me.GetSpecOracleByClass( "abilitySpecOracle" ) //orig
 
  return abilitySpecOracle
.

I created a test script on the client for checking it has
Code: [Select]
public function findabilityspecoracle ()
  var oracle = $SPECORACLEUTILS.GetAbilitySpecOracle()
  println(Oracle +"!!!!")
  println("Oracle _speckeymap length is(" +oracle._SpecKeyMap.length)
.
public function findworldabilityspecoracle ()
  wa as NodeRef of Class world_anchor = SYSTEM.INFO.WORLDANCHOR
        abilityOracle as NodeRef of Class AbilityOracle = wa.getabilityspecoracle()
        var oracle = abilityoracle
        println(oracle +"!!!!")
        println("Oracle _speckeymap length is(" +oracle._SpecKeyMap.length)
.
Calling these functions using CLI , I get a new ID each time for findabilityspecoracle
And the same Id for findworldspecoracle

In E_Ability I have this but if I use the wa type of finder I can't edit the spec anymore
Code: [Select]
method getMySpecOracle() as NodeRef of Class SpecOracle
  //  #if debug
  //  println("[" + SYSTEM.HSL.LOCATION + "]--" + SYSTEM.EXEC.CALLEDBYSCRIPT + ":" + SYSTEM.EXEC.CALLEDBYFUNCTION)
  //  #endif
  // It is intended that each child class override this method
  return $SPECORACLEUTILS.GetAbilitySpecOracle()
.
method getMySpec() as NodeRef of Class baseSpec
  // May return none...always check
  oracle as NodeRef of Class SpecOracle = me.getMySpecOracle()
  return oracle.GetSpecByKey( me.SpecKey )
.
In AbilitySpec
Code: [Select]
method getMySpecOracle() as NodeRef of Class SpecOracle
// It is intended that each child class override this method
  wa as NodeRef of Class world_anchor = SYSTEM.INFO.WORLDANCHOR
  return wa.GetAbilitySpecOracle()
.
I also have the E_SpecOracleUtils which has methods for getabilityspecoracle

Using this I get println messages from SpecOracleClassMethods in _Requestspecbykeyinanystate
first with a  _speckeymap.length of 0
followed by println in the same method with a _speckeymap.length of 2
Logged

cloudnine

  • General Accounts
  • *
  • Posts: 80
    • View Profile
    • Youtube
Re: GetSpecByKey - from an Ability Icon
« Reply #5 on: Feb 03, 13, 07:42:17 AM »

Looks like its finding the spec cache now.
I changed E_Ability to:
Code: [Select]
method getMySpecOracle() as NodeRef of Class SpecOracle
  //  #if debug
  //  println("[" + SYSTEM.HSL.LOCATION + "]--" + SYSTEM.EXEC.CALLEDBYSCRIPT + ":" + SYSTEM.EXEC.CALLEDBYFUNCTION)
  //  #endif
  // It is intended that each child class override this method
oracle as NodeRef of Class AbilitySpecOracle = $SPECORACLEUTILS._GetSpecOracleByClass( "AbilitySpecOracle" )
  return oracle

.
shared function EventRaisedNotify( obsSubject as NodeRef of Class ObsSubject, obsListener as NodeRef of Class ObsListener, data as NodeRef )
 
  // Data is a reference to the spec, do whatever you need now that it is ready.
 
  // ask the subject to remove the listener because we do not want any further events
  obsSubject.removeListener( obslistener )
.
method getMySpec() as NodeRef of Class baseSpec
  // May return none...always check

  oracle as NodeRef of Class AbilitySpecOracle = $SPECORACLEUTILS._GetSpecOracleByClass( "AbilitySpecOracle" )
  println("ORACLE IS (" +oracle +")")
  println("ORACLESPECByKEY IS (" +oracle.GetSpecByKey(me.SpecKey) +")")
 
 
  var listener = oracle.createScriptListener( SYSTEM.EXEC.THISSCRIPT, false )
  oracle.RequestSpecByKey( me.SpecKey, listener )


  return oracle.GetSpecByKey( me.SpecKey )
.
Logged