edited July 2016 in General Discussion
I have begun work on a full integration between ORK Framework and Opsive's Third Person Controller. The integration package provided by Opsive allows ORK to block player and camera controls, but it doesn't go beyond that. So I'm going to build an integration framework that bridges the two assets as seamlessly as possible.

Opsive's Third Person Controller is a popular choice with ORK users; after a quick search I count at least a dozen people here using it in their projects. I've been helping a couple of people integrate it into their own projects and I've also been answering quite a few questions that people have regarding integrating TPC with ORK. And I've also decided to use it in one of my own projects.

So it makes sense to me to make this more of a community effort and get all of the ORK-TPC users here involved. Most importantly in helping me determine exactly what this integration needs to accomplish. I already have a mental list of everything that I need for my game, but that may be very different from what all of you need for your games. So please make requests in this thread, as it will help me get a better idea as to what the most sought-after features will be.

And when this integration is "done" and it is successfully working in several of our projects, I will pass it on to Justin at Opsive for inclusion in his official ORK integration package.

The next several posts will briefly outline several use cases that I have already thought of and/or started working on. Please feel free to contribute your own if I have missed anything.

I use these definitions in the following scenarios:

Direct Control: The direction and magnitude of the player's input determines the character's movement. Essentially, this is gamepad control or WASD + mouselook.

Indirect Control: The player's input determines the character's destination. This could be the point-and-click style typical of many PC RPGs (where you click a location on the screen and your character starting moving there using pathfinding), but it could also be what you see in strategy RPGs like Fire Emblem where you select a grid cell with a gamepad and then your character moves there.

Post edited by Keldryn on
  • edited July 2016
    Scenario 1: Turn-Based Combat, Direct Control

    This is the conventional console RPG style, which the real-time combat in the ORK demo is based upon. You move your character around the world via direct control, and the game switches into turn-based mode when combat begins. Combat could be menu-based or it could even be grid-based as you do not directly control your character's movement in battle.

    This also includes active time battles and phase battles, as there is no real difference in terms of how movement is handled.

    Scenario 2: Turn-Based Combat, Indirect Control

    This is the conventional PC RPG style in which you click on where you want your character(s) to move and the game's pathfinding system then controls the actual movement. Combat could be menu-based or grid-based, as with the above.

    This would be games like Fallout 1 & 2, Divinity: Original Sin, Wasteland 2, and the like.
    Post edited by Keldryn on
  • edited July 2016
    Scenario 3: Real-Time Combat, Direct Control

    This is where it is critical to get a seamless bridge between ORK and TPC. In this use case, you are always in direct control of your character during gameplay and there is generally no distinct shift between exploration and combat modes of play.

    In terms of combat, there are two ways in which it could be approached (and both methods may be used in a single game).

    3A: Attacks initiated by ORK
    This would be the most "pure" approach; ORK handles the input for attacks and it works in the usual way: press a key/button, which uses an Ability, which launches a Battle Event. Damage Dealers and Damage Zones are used pretty much as described in the tutorial series.

    3B: Attacks Initiated by TPC
    TPC handles the input for attacks as well as the hit detection. When a hit is registered, instead of applying damage to the CharacterHeath component, we use the attacker's ability on the target combatant via script, which will then calculate the damage and effects normally.

    Either approach might be appropriate, depending on the needs of your game. 3A is good for fairly simple melee attacks, but if your game needs to have precise windows of opportunity for chaining together combo attacks, it might prove difficult to get all of the moving parts working together. 3B is probably the best approach for ranged weapons on the whole, as it uses raycasts for hit detection rather than spawning projectiles and moving them at the target.
    Post edited by Keldryn on
  • edited July 2016
    Documentation

    The documentation is also a work in progress, but I will start explaining how the integration works in this post. Keep checking back here for updates.

    The CombatantController

    The CombatantController component sits at the core of this integration. It is essentially an abstraction layer around ORK's Combatant component. When the CombatantController starts up, it launches a coroutine that will attempt to get the Combatant until it either succeeds or it times out (I specified 1s). I've found that I can't always rely on a component successfully getting the Combatant reference in the Start() method, so this ensures that we have the reference.

    Once it acquires the reference, it get references to the default attack abilities and registers event handlers for several of the "Changed" events:
                this.Combatant.Abilities.AbilitiesChanged += Abilities_AbilitiesChanged;
    this.Combatant.Equipment.Changed += Equipment_Changed;
    this.Combatant.Inventory.Changed += Inventory_Changed;
    Rather than having other ORKsive components directly adding event handlers to these events, I set up the event handlers on CombatantController to broadcast the event message using TPC's EventHandler.ExecuteEvent(). This way all of the messaging between ORKsive components is consistent, plus none of the other components need to go through the hassle of checking for a valid Combatant before performing any operations on it.

    The Vitals property is an instance of the CombatantVitals class (which is not a Monobehaviour). This class is a wrapper around status values with Max and Consumable pairs. Right now it's hard-coded to include Health, Stamina, and Mana, but you can modify this if you like. It uses constant values generated by the ORKConstantsGenerator class, which is included in the package. Just make sure you regenerate the constants file whenever you add, remove, or re-order you data lists in ORK.

    I could re-work the class so that you can choose which status values it will include via a custom inspector, but that's a lot more work than just editing the file and changing the status values. :-) If I get enough requests to do this, I'll consider it.

    The Variables property is an instance of the CombatantVariables class (also not a Monobehaviour), which is a simple wrapper around the Combatant.Variables methods. It won't throw an exception if Combatant is null though, which can eliminate some repetitive null checks. I just noticed that it currently only has Set methods for bool, string, and float values and no Get methods. I'll add those in the next version. :-) These were the only types that I needed during development.

    The ORKEquipmentSlotController and ORKInventoryBridge

    These classes work together and attempt to solve the problem of keeping the inventory and equipment in sync between ORK and TPC. All of the bugs are not worked out of this yet. ;-)

    ORKInventoryBridge is fairly straightforward: it listens for events sent by an ORKEquipmentSlotController component and then adds or removes the item from TPC's Inventory component. The current paradigm that I'm using is that items are only in TPC's Inventory if they are equipped in ORK. There should be some changes coming to Items in TPC that will make it possible to create them at run-time (instead of requiring them to be set up on the character at design time) which will streamline this whole aspect significantly.

    ORKEquipmentSlotController is an abstract class with two current implentations, one for the Weapon (right hand) slot, and one for the Shield (left hand) slot. Those aren't the final names, as I do intend to get it working with dual wielded weapons. I've been creating an empty GameObject named "Equipment Slot Setup" and parenting it to the root of the Player prefab, but it could go anywhere on the prefab; the root is pretty cluttered already, so I wanted to tidy it up a bit. This component uses a custom inspector:

    image

    Each component monitors a specific Equipment Part for changes, and if it detects that there has been a change, it sends an event that is handled by the ORKInventoryBridge. Each component also maintains a list that associates a TPC PrimaryItemType with a specific weapon from ORK's database. Currently, this means that each ORK weapon needs to have its own PrimaryItemType weapon set up on each character that will possibly be able to use it. Also, we're not using Equipment Viewers for weapons at this point in time.

    However, you can simply copy and paste these components between characters, so you only need to set up the association list for each component once.

    ORKMeleeWeapon and ORKShootableWeapon

    These two classes are derived from TPC's MeleeWeapon and ShootableWeapon components. I will create custom Item Builders for these, but for now you can just follow the standard Item Builder instructions. When you're done, just go to the inspector for that weapon and change the Script to the corresponding customized version:

    image

    If you're setting up your own character model, I've found that I can safely copy component settings from MeleeWeapon and ShootableWeapon (and their derived classes) and paste the settings into the same component on another character. Well, I haven't noticed any problems yet. :-) You need to adjust the positioning, but this is quicker than having to set up all of the Character Animation Options each time. So you can copy the settings off of the Dom_Player prefab.

    If either item type is used via an Event Step, the Ability being used by the Combatant will be passed in and ultimately used as the basis for the damage calculations. If the item is not being used via an Event Step, then it will use the Combatant's default BaseAttack ability instead. Generally, this would be the case if you have TPC handling all of the player input directly instead of having ORK handle the player's input. These two classes ensure that we do have an Ability for our calculations, and this gets passed down to our customized CharacterHealth component:

    The ORKHealth component

    This derives from TPC's CharacterHealth component and overrides the Damage() methods to allow ORK to calculate damage and effects using its abilities and formulas. The SetCurrentAction(BaseAction action) method is used to set a reference to the current Action (which contains a reference to the Combatant Ability being used). ORKMeleeWeapon and ORKShootableWeapon just pass this in via a Damage() overload, but in some cases I needed to just set it as a property instead so as to avoid having to re-write a significant chunk of Opsive's code.

    I think this covers most of the important components. I will eventually provide some less technical documentation, but at this current stage, you do need to get into the technical details in order to set things up.

    Post edited by Keldryn on
  • edited July 2016
    Oh, I'm pretty excited for this!
    Post edited by Griffin on
  • Hi Keldryn,
    I'm using Turn Based-Direct Control. I haven't gotten into the animations of the player that need to be controlled by Ork yet, so I'm not sure how that is going to affect me.

    So far the provided integration is working, but I'm not sure what might be problematic in furture. I'll let you know if what challenges arise for me and how I resolve them.

    I appreciate your work on the these two great packages.

    Byron
  • Real Time direct control integrated into Ork as outlined in the 3b example would be a massive improvement. If any of you have tried using projectiles and spawning and moving them to a target, you know what i'm talking about.
  • Hi Keldryn,

    Awesome work mate, 3b is what I'm most keen for really :) let me know what I can do to help, if anything...

    Dean
  • The main requirement for Scenario 1 is something that is needed by for all of the others as well: an effective means of being able to use an Ability on the RigidBodyController from ORK's Event System and of being notified when the ability or animation is complete.

    I'm building an ability derived from Generic that is intended to be used for handling all of the "play animation X" situations. There is no meaningful ability attached, you just want to play an animation state and then know when it's done. We don't want a stack of Genetic Abilities on the controller either.

    3b is most likely what I'm going to use and the good news is that it's already working. :-). So is 3a for that matter.

    However, there are a boatload of corner cases where they break, so I'm still working on them. But the basic approach is sound and as I said, already working.
  • That's very good news!. Currently not able to pick up TPS at full price yet. Hopefully within the next week or so. Can't wait to start working with it!
  • One thing I haven't decided with regards to 3b is how to hook up sound effects, particle effects, etc to the attacks. It could be done via TPC's MeleeWeapon and ShootableWeapon components (technically it will be custom components derived from those two), or it could be handled in a Battle Event. The Battle Event gives a bit more flexibility, but in my initial tests the audio and visual effects tended to noticeably lag behind the actual hit detection. I didn't conduct extensive enough tests to be able to make an informed decision. TPC's weapons do let you call a delegate function on another component to handle additional effects when hit, however.

    Also, I oversimplified 3a and 3b a little bit. There is essentially a 2x2 matrix to consider here:.

    1. ORK responds to input -> activate Combatant Ability -> Battle Event activates TPC Item/Ability

    2. TPC responds to input -> activates it's own Item/Ability -> if a hit is detected, use Combatant's ability on the target but just run the calculation

    A. Hit detection determined by ORK Damage Dealers and Damage Zones

    B. Hit detection determined by TPC; collisions for melee and either collisions or raycast for ranged

    (1) pretty much has to be supported in order for ORK's BattleAI to be able to function.

    (2) will split some abilities into Player and AI versions as they'll need to be handled differently -- unless one is using a tool like Behavior Designer, Node Canvas, or ICE for AI.

    I think that each of the four combinations need at nominal support, in order to be of use to the greatest number of developers.
  • Hey @Keldryn, Thanks for including me in this thread. I'm grateful for your work. I'm no programmer so I can't help with code related stuff, but I can buy/donate towards your work :)

    Looking forward to the integration! Also keen on 3B
  • Easiest way to switch between using an ability's action (i.e. controlled by the battle system and using battle events) and just doing the calculation would be using the AbilityShortcut of the ability and call its Use function. The useAction parameter determines if only the calculation will be done or an actual action will be fired.
    If you're enjoying my products, free updates and support, please consider supporting me on patreon.com!
  • @gamingislove - yup, already doing that for the "3b" scenario. :-).

    I've subclassed the TPC weapon classes and overridden their methods that get called when a successful hit is registered. I just get the Combatant from the root game object of the collider that was hit, and my custom weapon classes already have a reference to the Combatant wielding them. Use the combatant's ability on the target with doAction = false and it works beautifully!

    Except in the situation where there are use costs associated with the ability. This is one area that I haven't quite figured out the best approach. I could brute force it and get the costs from the weapon settings or variables set on the weapon and then modify the appropriate status values, items, etc via script. But that seems both inelegant and a royal pain in the backside.

    I don't suppose there is a way of applying an ability's use costs without calculating the target effects is there?
  • edited July 2016
    Am also interested in 3B because I like chaining combo attacks, which I haven't used yet but want to. Use costs associated with an ability is a little bit important. Because you might have a way to reduce or increase those by using an item or some other way. Not sure if you can do this in ORK but I would like to.

    Also how does all this work on mobile?
    Post edited by Catacomber on
  • Hey Keldryn,

    I would recommend setting up states for each scenario. This would allow you to build out each without interfering with one another. Also, it would be nice to have a Github set up so that people can fork and branch off to help out with bugs/issues/etc.
Sign In or Register to comment.