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 - _Omzy_

Pages: [1]
1
I was struggling with this issue all day and figured out why this shared function wasn't being called despite setting appropriate replication parameters for the noderef and its fields and assuring the replication group was working with the correct client destinations. In the end, it turned out that my noderef inherited from multiple classes and one of the other inherited class method scripts had the shared function _OnReplicationFieldUpdated.

Lesson:
If your _OnReplicationFieldUpdated function is not being called, be sure that your noderef doesn't have any other inherited shared functions of the same type (check all parent class method scripts). There can only be one!

EDIT: Jrome pointed out the _OnReplicationFieldUpdated entry on this wiki page holds the answer: http://hewiki.heroengine.com/wiki/Replication_Script_Interface

Quote
Called on ClassMethods scripts for classes (OR the first ancestor class that implements it) on the node that contain the field. Only called when the source field definition has Change Callback set to true. These callbacks happen for value changes after _OnReplicationNodeAdded (i.e. they are not called for Initial Set updates) is called and will happen no more than 1 time per class that makes up the node (i.e. the base class and each GLOMmed class assuming they or one of their ancestors implements the function).

2
The new material overrides functionality is very useful and speeds up development. I am requesting the following 4 functions be added to further add to our arsenal and speed up art pipelining. These functions are mostly already available for terrain texturing:

1) UV Scale slider
2) Normal map slider
3) Specular map slider
4) Tint masking each texture

The current workflow when we need to alter any of these parameters is to re-open the max file and make manual adjustments, or edit the textures and refresh them in the repo. This takes considerable time and would be insanely faster with sliders. We build some of our structures using modular building kits in Unity and then export them as single building objects into the engine. It would be nice to scale these UVs quickly in the engine (like a rectangular prism of wall or roof that has been stretched). If we decide to use a single wall asset but create different sized walls, this stretching occurs in the engine, which would require us to create multiple different models with different Hero materials, but if we had sliders, we could use the same object with different instance properties and save the player some lag. Additionally, it would be very useful to be able to apply a diffuse/tint color to any of the textures. Obvious utility would be importing a grayscale roof shingles texture and tinting it red, blue, green, or any other color to have a multitude of available roof colors for structures with only a single object import.

Thanks for reading!

3
General Discussion / NavMesh & Pathing Issues
« on: May 23, 15, 01:54:35 PM »
Hi guys,
Forgive me if some of these things have been posted before--I searched but didn't find anything related except some recent problems with paths ignoring models. I'm not sure if these are new since the recent update, are intended functionality with an explanation, or are actual bugs. Without further ado:

1) The navmesh doesn't seem 'complete'. When I turn on the visualizer, it looks riddled with holes like this one that seem non-intuitive. Surely this would have consequences in plotting a path down this actual path? I've given the PathMaker plenty of time to generate this area's paths as I've not modified the dat in days, allowed the world to sleep 2-3 times, and I see no dirty regions.

EDIT: Found this line under Path Planning panel:
WU_TestArea  (+): TaskNumber 11, BUILDING: status: BackLinking node 38702 of 49026. : /world/areas/9223372057044021587/area.dat

Would it really take this long to build the navmesh on such a small terrain? Its just a small testing area.



2) Using the default clean engine implementation of E_AIStateWander, E_PathingHelper, which utilizes its PathToPoint method, which calls '$PathSystem._PathSystemGetPath( me, me.E_phParameterSet, start, point )', these mobs are moving from random point to random point. You can see that they seem to float and sink into the ground as they path between points. Why are they not using the points from the navmesh to determine where the ground is?

EDIT: Upon turning on cached path visualization, all of the paths are straight lines instead of paths following the navmesh points




3) Using the default clean engine implementation of E_AIStatePursue, E_PathingHelper, which utilizes its PathToPoint method, which calls '$PathSystem._PathSystemGetPath( me, me.E_phParameterSet, start, point )', I ran into this mob's aggression radius, he followed me to my stopping point and accurately made it within combat range. However, his path was very erratic, and he turned multiple times before settling on a final point and heading towards my character. Is there a way to smooth this out?


Just now getting into this part of AI, so thank you for any responses!

4
General Discussion / Dynamic detail bug since Quartz.d
« on: May 14, 15, 09:32:07 PM »
We've noticed some glitches in the dynamic detail since Quartz.d. It seems the order of rendering is off, so that dynamic detail layers closer to the camera are rendering behind other objects, including other dynamic detail, and bodies of water. Hair seems to be affected similarly. This was tested in a seamless environment and reproducible under any circumstances--not simply those mentioned in this previous bug report: https://community.heroengine.com/forums/index.php?topic=4285.0




5
Hi there,
One of my developers was unable to login following todays update for the authentication servers, however my admin account logged in just fine. His error said "Login Failed. You may have entered an incorrect username or password, or your connection to the server may have been lost." He didn't change anything and had auto-login on, tried restarting Heroblade and his PC with no effect. So, me, being the quick-fixit man decided to play around with his permissions in the dashboard to try and reset his account somehow and accidentally ticked the 'Active' box, which immediately removed his name from the list of existing users. I am unable to view his name and see no options to show inactive users or reinstate them. I tried re-adding him, and it says his email already exists in the list...Help please!

 :P

6
General Discussion / New DOM Suggestions (Quartz.d)
« on: May 06, 15, 12:44:12 PM »
There have been a few threads around with DOM glitches since the latest update. Let me add a few other DOM suggestions that I've been brooding over. These are not meant as complaints, just suggestions to improve workflows:

  • New DOM requires client refresh after every Copy to Client command (old DOM auto-refreshed client) -- slows workflow significantly
  • New DOM does not save panel layout as the new DOM windows are not considered panels, slows startup
  • Also these new DOM windows, not being panels, aren't dockable to each other or other panels, impairs aesthetics and flexibility
  • Resizable elements, especially field box for classes (I know this issue has already been mentioned and scheduled for the next update), impairs aesthetics and slows workflow
  • Default archetype should be set to data rather than empty, like the old DOM. Now you have to select archetype for every single class definition, every spec, every dec, dec helper, etc. Significantly slows workflow
  • Read Only checkbox should only need to be unchecked once (currently has to be unchecked on server and client, which is different from before update), slows startup
  • Loading bar now replaces text in search box which is a bit disorienting, especially after long hours when you forgot what you typed, impairs aesthetics
  • After creating/updating definitions, there is more lag than before, or at least it appears that way. I'm not sure if code has become less optimized or algorithms have been swapped out, but it is definitely noticeable--I used to not have to wait after creation to start editing, significantly slows workflow
  • Copy to Client/Server should allow a 'forced' update even if destination classes/fields already exist, rather than just supporting creating new field/class definitions. For example, if I create a spec decorator on the server and prematurely copy it while empty, then add 10 fields to the server definition and try to Copy to Client again, I get an error that this is not possible. I'm sure this is intentionally designed to prevent overwriting existing data. There should be a checkbox with a checkmark allowing forced update (default unchecked) in this scenario so I don't have to manually add every field twice. This could prompt the user for verification and could either copy the entire class/field or just add fields that are non-existant in the destination but exist in the source, which is a compromise that avoids the issue of overwriting data altogether.  significantly slows workflow

Thanks for reading!

7
Design & World Building / Bugs in Merge/Re-grid Tool?
« on: Apr 09, 15, 01:48:16 PM »
Hey guys,

I've been having issues with the merge/regrid tool. If I've got a mesh thats, say 192x192 standard res made up of 36 nodes (6x6), each 32x32 verts, and merge regrid it with a node size of 192, it should create a single node from them that is size 192x192. However, it is creating one that is 187x187.

Additionally, when doing the opposite conversion, from a single 192x192 to a 6x6 of 32x32's, it doesn't split up evenly and actually makes a mesh thats like 194x194, leaving slivers of 2x32's along 2 of the sides.

Has anyone experienced or is able to reproduce this issue, and are they bugs?

Thanks

Edit:
One more possible bug: using the merge/regrid on nodes that are not at standard resolution does not result in the desired behavior. If you are trying to regrid a terrain at HALF res, it is necessary to convert to standard first and re-align and re-height all nodes in the group before using the tool, which can take loads of time if you have 3x2 areas, each of which is 6x6 blocks of 32x32 verts. Thats 216 blocks i have to line up and re-height =(

Perhaps this can be fixed by writing an algorithm that scales the entire terrain (all nodes) down or up when changing resolution rather than it scaling each node individually, or at least an added tick-box to add that possible behavior in case this was intentional design.

8
Our team has been working on seamless terrain with a node size of 32x32 at HALF res. We've run into a little issue where the westernmost nodes of each imported and regridded heightmap aren't lighted properly in the default setup. The meshes are fine, its just the way the light hits them. This is most evident when zoomed out but is still obvious close-up. It persists when different textures are added. We've tried shutting down the edit instance and bringing it back up. If anyone has run into this issue and has a solution, please chime in. Here's a pic with 4 seamless areas stitched together, note the westernmost blocks of each area:



Thanks in advance!

9
Scripting & Programming / Area of Effect Abilities
« on: Jan 17, 15, 12:53:30 PM »
We've been discussing how to implement area of effect abilities in the Skype group for a couple of days and although there are several good ideas that have been mentioned, I'm still unsure of the best approach that is authoritative, lightweight, and syncs with Fx on the client.

Initially, I was going to fire Fx off on the client and use the OnTargetAchieved for the Fx to make a server script callback to apply the effect to the target. Then I realized that is placing a lot of trust that the client doesn't alter the Fx and send its own callbacks.

Next, Keeper mentioned the use of NPCs as effects, spawning a simple invisible box/sphere and sending it out, detecting collision, and perhaps playing Fx on the object for a visual. That sounded like a decent idea, but potentially resource intensive as it requires a lot of character code that is not used.

Additionally, we discussed how timers for every effect and ability's targeting system (like an aoe expanding away from the character at a velocity and detecting targets as it enlarges) would strain the server if run on the server. This is why cooldowns are best managed by sending timestamp information to the client instead of running a timer on the server. Running a timer on the client where every tick might detect new targets, however, seems to be trusting the client too much when compared to validating cooldown information. It is not really the same scenario.

Then, I looked into the area awareness functions on this page http://hewiki.heroengine.com/wiki/Area_Awareness_Functions. As someone in the Skype group pointed out, this post suggest that they shouldn't be used for these types of abilities: https://community.heroengine.com/forums/index.php/topic,164.msg580.html#msg580.

However, when I looked into HJRef this morning, I found that it uses these area awareness functions in conjunction with server timers. The load notes say that the combat system is outdated but that the ability system is a good example. So, I am wondering what the consensus on this is. It is arguably one of the most client<>server intensive processes in any game, so its important to get it right so that combat doesn't lag everyone out.

Here's an excerpt from HJRef's ActivationRingDataClassMethods illustrating the use of timers on the server, calling an area awareness function every tick, using a player for the coordinate reference.

Code: [Select]
      where mySpec is kindof AbilityExpandRingOnTickDec
        where ParentAbility is kindof DurationAbility   
          if ParentAbility.abilityCurrentTick = 1
            me.rdInnerRadius = me.rdInnerRadius + (mySpec.erExpansionPerTick * (ParentAbility.abilityCurrentTick -1))
          else
            me.rdInnerRadius = me.rdOuterRadius + (mySpec.erExpansionPerTick * (ParentAbility.abilityCurrentTick -2))
          .
          me.rdOuterRadius = me.rdOuterRadius + (mySpec.erExpansionPerTick * (ParentAbility.abilityCurrentTick-1))
        .
      .
    .
    if me.rdInnerRadius < .01
      me.rdInnerRadius = .01
    .
    var defenders = GetTargetsInSphericalAnnulus(true, true, me.cdCenter, me.rdOuterRadius, me.rdInnerRadius)

10
This tutorial will allow you to create a spec oracle property editor that supports spec selector fields and list of custom class fields. These controls are often necessary components of a sophisticated and flexible system design. If you have not yet learned how to create a spec oracle with spec decorators, make sure to master that first.

*See the 10 Step Spec Checklist and the 10 Step Spec Dec Checklist first!

Advanced Spec Oracle Property Editor Tutorial



This tutorial assumes that you have created a working spec (FooSpec) with:
* a decorator class (FooBarDec) with a field (FooBarList) that is a list of a class (FooBarItem) which is composed of non-class fields (FooBarItemField1-5)
* a decorator class (FooBar2Dec) with fields (FooBar2Field1-2)

The hierarchy for the default system should look like this:
___*FooSpec (spec)
______*FooBarDec (spec decorator containing custom class list)
_________*FooBarList (list of class FooBarItem)
____________*FooBarItem (class)
_______________*FooBarItemField1 (id, for spec dropdown)
_______________*FooBarItemField2 (string, for spec dropdown)
_______________*FooBarItemField3 (enum Field3Enum)
_______________*FooBarItemField4 (float)
_______________*FooBarItemField5 (enum Field5Enum)
______*FooBar2Dec (spec decorator invoking spec selector)
_________*FooBar2Field1 (id)
_________*FooBar2Field2 (name)
______*FooBar3Dec (simple spec decorator)
_________*FooBar3Field1 (float)
_________*FooBar3Field2 (timerinterval)
_________*FooBar3Field3 (string)
______.
______.
______etc (more decorators)
___*FooSpecOraclePropertyEditor (property editor)
______*Foo1Foo2SpecList (list of string, Foo1 is just Foo from above)



From HJRef
Follow this section once per world:
1. Copy the following clientside scripts from HJRef: GUIutils, GUIFormHandling
2. Copy the following clientside classes (and ALL of their unique fields) from HJRef: GUIForm, GUIFormData, GUIFormRow, selectBoxItem
4. Copy the following guicontrols from HJRef: form, _submitButton (remove the animation property to prevent a script error)

Your World
Follow this section for each spec oracle that you create (rinse and repeat):
1. Create FooSpecOraclePropertyEditor(C) as guicontrol data type with parent as SpecOraclePropertyEditor(C).
2. Make a GUI prototype using the following XML which inherits from the SpecOraclePropertyEditor prototype but uses the FooSpecOraclePropertyEditor class
Code: [Select]
<createControlType inheritFrom='SpecOraclePropertyEditor' type='FooSpecOraclePropertyEditor' description='Property editor for foo spec' treePath='BuildingBlocks\Windows' name="FooSpecOraclePropertyEditor" glomClass="FooSpecOraclePropertyEditor">
</createControlType>
3. Add a Foo1Foo2SpecList list of string field to your FooSpecOraclePropertyEditor (this caches the spec names and id’s for your field which invokes the spec selector, hence the Foo1Foo2, e.g. if you have an Effect spec that grabs a Stat spec, it would be EffectStatSpecList)
4. Copy the clientside template class method scripts below to your FooSpec(C) and FooSpecOraclePropertyEditor(C) classes
5. Replace all strings containing ‘REPLACE’ with yours. E.g. REPLACEDefault1Helper1 with FooBar, REPLACEDefault1Helper1ItemField1 with FooBarItem<yourfield>, etc (see the instructions at the top of each script for more detailed instructions on replacement).
6. Go function by function and follow the commented instructions above each function to customize your property editor to your spec structure

Default Spec Prototype (optional)
Follow this section if you want the spec property editor to pre-populate with a set of default values upon adding a new spec entry (rinse and repeat for each spec dec):
1. For each spec decorator, you must create a new prototype with the name FooSpecDecOnGLOMDefaultValues. This is a special name that will be checked by the engine before GLOM’ing the dec to the spec entry
2. To do this type into the console (*spaces are important):
___a. \cpfc FooSpecDec, FooSpecDecOnGLOMDefaultValues; description=”Default values prototype for FooSpecDec”
___b. \mp FooSpecDecOnGLOMDefaultValues; Field1=”myvalue” Field2=45 Field3=FALSE
3. Tailor the above commands to your spec decorator's field structure. Repeat these commands with ‘|’ to add the values to the client as well.
4. To set up default values for a custom class, add a list of string field named FooSpecListDefaults to the server and clientside spec decorator class. You can use the \MLP command to modify this custom class' defaults list. See the MLP command. The syntax is "\mlp FooSpecDecOnGLOMDefaultValues FooSpecListDefaults;insert 1 "2:Fireball,harmful,5", for example, if your custom class references the 2nd spec entry named Fireball which is harmful and has a damage of 5. These obviously depend on the custom class structure you've setup. This FooSpecListDefaults list must be parsed when your spec decorator is GLOM'd and requires that you add the following code snippet to your FooSpecDecClassMethods script and change the strings to fit your custom class:

Code: [Select]
shared function _OnGlomClass( n as NodeRef ) //Add default values from FooSpecListDefaults
  where n is kindof FooSpecDec
    foreach itemString in n.FooSpecListDefaults
      if itemString <> ""
        itemFields as List of String
        SplitBy( itemString, ",", itemFields )
        i as Integer
        foreach itemField in itemFields
          i+=1
          specSeparator as Integer = FindString( itemField, ":" )
          if specSeparator > 0
            specFields as List of String
            SplitBy( itemField, ":", specFields )
            remove itemFields at i
            insert specFields[2] to itemFields at i //Name
            insert specFields[1] to itemFields at i //ID
          .
        .
        item as Class FooSpecItem //Make sure to modify these to fit your custom class structure
        item.FooSpecItemSpecID = itemFields[1]
        item.FooSpecItemSpecName = itemFields[2]
        item.FooSpecItemType = itemFields[3]
        item.FooSpecItemDmg = itemFields[4]
        add back item to n.FooSpecList //Note this is different from the FooSpecListDefaults list
      .
    .
  .
.



TemplateSpecClassMethods(c)
-->Download<--

TemplateSpecOraclePropertyEditorClassMethods(c)
-->Download (update3)<--

11
Volume 2/2, hope this helps more people understand the spec system enough to be able to use it. It really is logical and time efficient once you get going.

*Use the 10 Step Spec Checklist first!

10 Step Spec Dec Checklist
For your first spec, See Spec System - Basic Usage, Spec System - Advanced Usage, Creating a New Spec Oracle (Step by Step), HeroEngine Data Storage Tutorial - Spec System 3, and HeroEngine Data Storage Tutorial - Spec System 4

I highly suggest creating TemplateSpecDecoratorClassMethods, TemplateSpecDecoratorHelperClassMethods, TemplateSpecAnchorClassMethods, and TemplateSpecManagerClassMethods scripts after following the video series above.
1. (Optional) If you want to use the anchor<>manager setup as described in the videos, continue here. If not, jump to step 7.
2. Create the manager and anchor classes on both the server and client (FooManager and FooAnchor). You may choose to reflect both by setting Destination Classes
3. Create fooAnchorRef fields on the server and client as NodeRefs of Class FooAnchor
4. Add the fooAnchorRef field to the manager on server and client
5. Make FooManager a parent of the class that you wish to anchor Foo (this gives that node control of its own specDerivedObject and decorator helpers after instantiation)
6. Open both class methods scripts (s only) using the matching templates that you created from the videos. Fix default strings to include Foo, compile and submit

7. Using the DOM editor, create the spec decorator and decorator helper classes (FooBar for instantiated nodes only) on both the server and client (FooBarDec and FooBar)
8. Add FooBarDec as a parent of FooBar only if you want it to have access to FooBarDec’s immutable fields
9. Open both (or only FooBarDec’s) class methods scripts (s only) using the matching templates that you created from the videos. Fix default strings to include FooBar, ‘add back’ FooBarDec to getSpecDecoratorClasses() in FooSpecOracleClassMethods (s only), compile and submit
10. If you chose to give your decorator helper a shared OnActivate method, ensure that it is activated from your manager's AddFoo method if you have one

Happy system building!

*Move on to the Advanced Spec Oracle Property Editor Tutorial!

Edit: Bonus templates for all! ( thank Christopher for these, they are modified from his videos :D )
*Replace 'REPLACEDefault' with Foo, 'REPLACEdefault' with foo, 'Helper' with Bar*

TemplateSpecDecoratorClassMethods(s) (update1)
Code: [Select]
shared function OnInstantiationFromSpec( derivedObject as NodeRef )
// Shared function called in the base and decorator classes of a spec when an object is instantiated
//   do any initialization/setup required by the decorator class
  if not ( derivedObject is kindof REPLACEDefaultHelper )
    GlomClass( "REPLACEDefaultHelper", derivedObject )
    //other construction stuff here
    where derivedObject is kindof REPLACEDefaultHelper
      mySpec as NodeRef of Class REPLACEDefaultHelperDec = derivedObject.GetMySpec()
      //init mutable AND immutable values here
    .
  .
.

TemplateSpecDecoratorHelperClassMethods(s)
Code: [Select]
//Call this from scripts to actually engage the helper for the glommed character type
method ActivateREPLACEDefaultHelper()
  //This code runs every activator, use in conjunction with activation in manager if you wish
  //decorators as List of ScriptRef = QueryNodeScriptsWithFunction(me, "OnActivate")
 
  //foreach d in decorators
  //  d:OnActivate( me )
  //. Use the next line if not using this block
  OnActivate ( me )
.

//Implement in helper classes to respond to activation event
shared function OnActivate ( REPLACEdefault as NodeRef of Class REPLACEDefault )
  //Activation code
.

TemplateSpecAnchorClassMethods(s)
Code: [Select]
method AddREPLACEDefaultToAnchor (REPLACEdefault as NodeRef of Class REPLACEDefault) as Boolean
  if me.AnchorHasREPLACEDefault(REPLACEdefault.SpecKey) //Prevents duplicate
    ScriptError ( "Anchor already had REPLACEdefault!" )
    return false
  .
 
  AddAssociation( me, "base_hard_association", REPLACEdefault )
  return true
.

method RemoveREPLACEDefaultFromAnchor (REPLACEdefault as NodeRef of Class REPLACEDefault) as Boolean

  if not me.AnchorHasREPLACEDefault(REPLACEdefault.SpecKey)
    ScriptError ( "Anchor didn't have REPLACEdefault to remove" )
    return false
  .

//$CHAT.ChatArea("game" , "[Script] Removed REPLACEdefault with spec_key: " + REPLACEdefault.SpecKey + " from anchor " + me )   
  DestroyNode( REPLACEdefault )
  return true
.

method AnchorHasREPLACEDefault (spec_key as ID) as Boolean
  foreach REPLACEdefault in QueryAssociationTargetsByClass(me, "base_hard_association", "REPLACEDefault")
    where REPLACEdefault is kindof REPLACEDefault
      if REPLACEdefault.SpecKey = spec_key
        return true
      .
    .
  .
 
  return false
.

TemplateSpecManagerClassMethods(s) (update1)
Code: [Select]
method GetREPLACEDefaultAnchor() as NodeRef of Class REPLACEDefaultAnchor
  REPLACEdefault_anchor as NodeRef of Class REPLACEDefaultAnchor
 
  if me.REPLACEdefaultAnchorRef != None
    REPLACEdefault_anchor = me.REPLACEdefaultAnchorRef
  else
    REPLACEdefault_anchor = QueryAssociationOneTargetByClass( me, "base_hard_association", "REPLACEDefaultAnchor")
  .
 
  // none created, so create one
  if REPLACEdefault_anchor = None
    REPLACEdefault_anchor = CreateNodeFromClass ("REPLACEDefaultAnchor")
    AddAssociation(me, "base_hard_association", REPLACEdefault_anchor)
    me.REPLACEdefaultAnchorRef = REPLACEdefault_anchor
  .
 
  return REPLACEdefault_anchor
.

method AddREPLACEDefault ( spec_key as ID ) as NodeRef of Class REPLACEDefault
  REPLACEdefault as NodeRef of Class REPLACEDefault
  oracle as NodeRef of Class REPLACEDefaultSpecOracle = getprototype ("REPLACEDefaultSpecOracle")
  spec as NodeRef of Class REPLACEDefaultSpec = oracle.GetSpecByKey( spec_key )
 
  if spec != None
    REPLACEdefault = spec.CreateFromSpec()
  .
 
  REPLACEdefault_anchor as NodeRef of Class REPLACEDefaultAnchor = me.GetREPLACEDefaultAnchor()
  if not REPLACEdefault_anchor.AddREPLACEDefaultToAnchor( REPLACEdefault )
    ScriptError( "Unable to add REPLACEdefault!" )
  else
    where REPLACEdefault is kindof REPLACEDefaultHelper //Activatable Spec Decs here
      REPLACEdefault.ActivateREPLACEDefaultHelper()
    .   
  .
 
  return REPLACEdefault
.

method RemoveREPLACEDefault ( spec_key as ID ) as Boolean
  REPLACEdefault as NodeRef of Class REPLACEDefault = me.GetREPLACEDefaultByKey( spec_key )
  REPLACEdefault_anchor as NodeRef of Class REPLACEDefaultAnchor = me.GetREPLACEDefaultAnchor()
  if REPLACEdefault != None
     return REPLACEdefault_anchor.RemoveREPLACEDefaultFromAnchor ( REPLACEdefault )
  else
     ScriptError ( "Caller did not have REPLACEdefault to remove" )
     return false
  .
 
  ScriptError ( "Unable to remove REPLACEdefault!" )
  return false
.


//returns the REPLACEdefault if it exists or None
method GetREPLACEDefaultByKey ( spec_key as ID ) as NodeRef of Class REPLACEDefault
  REPLACEdefault_anchor as NodeRef of Class REPLACEDefaultAnchor = me.GetREPLACEDefaultAnchor()
  foreach REPLACEdefault in QueryAssociationTargetsByClass( REPLACEdefault_anchor, "base_hard_association", "REPLACEDefault")
    if REPLACEdefault.GetMySpecKey() = spec_key
      return REPLACEdefault
    .
  .
  return None
.

12
Developer Created Tutorials / 10 Step Spec Checklist (A Summary)
« on: Dec 23, 14, 01:03:50 AM »
I created this for myself after going through the available resources carefully. I thought it might be of some use to those starting out. I think it would also be a great future addition to the engine if we were able to automate these steps by simply typing in the name of the spec and a few parameters. It could save a lot of time if you've got 100+ specs. Thoughts?

10 Step Spec Checklist
For your first spec, See Spec System - Basic Usage, Spec System - Advanced Usage, Creating a New Spec Oracle (Step by Step) and HeroEngine Data Storage Tutorial - Spec System 2

If you’ve followed all steps in the above tutorials correctly, for every spec thereafter just use this checklist:
1. Using the DOM, create the spec oracle, spec base, and spec derived object classes (spec derived object for instantiated nodes only) on both the client and server (FooSpecOracle, FooSpec, Foo).
2. Add parent fields to all
___a. Spec oracle parents: SpecOracle (s&c), CollectionOrderedSet (c only), ObsSubject (c only)
___b. Spec base parents: baseSpec (s&c)
___c. Spec derived object parents: specDerivedObject (s&c)
3. Open all 6 (or 4 if no spec derived object) class methods scripts using the matching templates. Fix default strings to include Foo, ‘add back’ FooSpec to getValidBaseClasses() in FooSpecOracleClassMethods (s only), compile and submit
4. Create server prototype from console with \cpfc FooSpecOracle, FooSpecOracle; description=”Foo Spec Oracle”   *Spaces are important in command
5. To clientside MyGame_SpecOracleUtilsClassMethods script, add a singleton getter method, an ‘add back’ to HE_GetAllSpecOracles(), and a lowercase condition check to HE_GetSpecOracleByClass(), compile and submit
6. To add GUI fields for the spec, in both server and client FooSpec on the DOM, add Field->displayName and Field->DisplayDescription
7. Then, open spec by typing in chat /HEORACLE open FooSpecOracle
8. Right click the prototype header and ->Edit Headers to modify the headers
9. To add the Spec Oracle to the HotSpot GUI, duplicate the _CollapsableCategoryItem under the correct _CollapsableCategory in MyGame_HotSpotGUI.xml and change the strings within to Foo
10. Lastly press F5 in the viewport and Commands->HeroBlade->Rebuild HotSpot Interface

*Move on to the 10 Step Spec Dec Checklist!

Cheers!

13
Developer Introductions / A World Untold
« on: Dec 23, 14, 12:48:22 AM »
Hello everyone!

I'm a newcomer to HeroEngine and would like to introduce myself. I've been designing my game (temporarily titled A World Untold) for the past 5 months. It will be a prototypical medieval fantasy MMO with a focus on solid social gameplay mechanics and lore. I've finally made it to the core system implementation and I'm excited to join this community. I've been reading about the scripting language for the past month so perhaps I'll be able to contribute something here or there.  For now, it's just me and I'll be building a small team of 3-5 over the next year.

Thanks for reading!
Omzy

Pages: [1]