I'm working on integrating the Ability Combat Toolkit with Ork 3 and I could use a little help.

I need to connect the Ork stats to the ABC, and I'm trying to figure out the best way to do so. The code to do so is fairly straightforward, Mozza pointed out examples of what to call through the API.
ABC_IEntity abcEntity = ABC_Utilities.GetStaticABCEntity(gameObject); // character, enemy etc

abcEntity.TriggerAbility("Fireball"); //activate ability using name
abcEntity.TriggerAbility(123456); //activate ability using ID

abcEntity.EquipWeapon("1H Sword"); //equip weapon using name
abcEntity.EquipWeapon(1234567); //equip weapon using ID

abcEntity.AdjustMaxHealth(500); //Adjust max health
abcEntity.AdjustStatValue("Strength", -30); //Adjust Stat
At first, I was thinking about using a schematic in the stat itself to call AdjustStatValue to set it to the current value, but I couldn't see a way to do that via schematics. It wants you to set the actual value right there when I'm looking for it to be updated dynamically.

FYI, my aim is to have ABC handle the creation and execution of abilities (I know Ork can make abilities, I just really like the workflow of ABC, as well as its animation override system), and have Ork handle stats, stat calculation, and everything else.

The final option would be to write an integration/plugin/bridge to connect the ABC stats to Ork. I'd take his Game Creator integration script and duplicate one of the lines for Ork commands.

image
Currently making: Real-Time Diablo-like ARPG
  • edited May 2022
    I'm not really sure what exactly you need or your goal is - do you want to forward ORK status changes to ACT or the other way (or both)?

    Generally, you can easily get the combatant of a game object like this:
    Combatant combatant = ORKComponentHelper.GetCombatant(this.gameObject);

    With the combatant, you have access to the combatan's status values (getting values, setting/changing them, etc.) and can also register to get notified when they change, e.g.:
    int value = combatant.Status[index].GetValue();
    This gets you the current value of a status value based on the index in the editor (e.g. 0 for the first stat).
    Post edited by gamingislove on
    Please consider rating/reviewing my products on the Asset Store (hopefully positively), as that helps tremendously with getting found.
    If you're enjoying my products, updates and support, please consider supporting me on patreon.com!
  • gamingislove said: I'm not really sure what exactly you need or your goal is - do you want to forward ORK status changes to ACT or the other way (or both)?
    My goal is to have ORK forward status changes to ABC as it doesn't have its own stat system so you tell it what stats to use to determine damage and such.

    This is a screenshot Mozza sent me this screenshot to show me how ABC calls stuff.

    image

    And this is what he had to say about Ork Integration.
    So you have 2 choices to add ORK integration yourself, you can either modify the 'IEntityBase' or modify the component the IEntityBase uses.

    My personal recommendation would be to extend the entity base as seen in the attached file:
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public partial class ABC_IEntity {

    //Initially this will error as the methods already exist in the ABC_IEntity file. All you need to do is follow the errors and delete the ones in original file as you have replaced them in this file
    //You are able to modify the code directly in the ABC_IEntity file however any changes you do will be overwritten on future updates. Using this new file you can keep track of methods you have modified and in future
    //if you update ABC you will always know from this file what you have changed and all you have to do on update is simply follow the errors again deleting the duplicates from the original ABC_IEntity file

    // I have provided some examples below of everything you will need to change to integrate with your own health/mana/stat component but use what you wish and delete what you don't need :)
    // It's quite process intensive to get component each call so you might want to create a new property which just stores the component when it's accessed similar to this:


    private STATCOMPONENT _myStats;


    public STATCOMPONENT myStats {
    get {

    //If ani runner is null for any reason then reassign the component
    if (this._myStats == null)
    this._myStats = this.gameObject.GetComponent<STATCOMPONENT>();

    return this._myStats;
    }
    }


    // and then you can override the following methods (deleting them in the original file) to connect to your component


    /// <summary>
    /// Returns entities Current Health Value
    /// </summary>
    public float healthValue {
    get {
    return myStats.Health;
    }

    }

    /// <summary>
    /// Returns entites Max Health Value
    /// </summary>
    public float maxHealthValue {
    get {
    return myStats.MaxHealth;
    }

    }

    /// <summary>
    /// Returns entities Max Mana Value
    /// </summary>
    public float maxManaValue {

    get {

    return myStats.maxMana;
    }

    }


    /// <summary>
    /// Returns entities Current Health Value
    /// </summary>
    public float manaValue {
    get {

    return myStats.Mana;
    }

    }

    /// <summary>
    /// Will Adjust the entities health
    /// </summary>
    /// <param name="Potency">Amount to adjust health by (can be positive or negative)</param>
    public void AdjustHealth(float Potency) {


    myStats.AdjustHealth(Potency);

    }


    /// <summary>
    /// Will Adjust the entities mana
    /// </summary>
    /// <param name="Potency">Amount to adjust mana by (can be positive or negative)</param>
    public void AdjustMana(float Potency) {


    myStats.AdjustMana(Potency);
    }


    /// <summary>
    /// Will increase max health
    /// </summary>
    /// <param name="Amount">Amount to increase max health by</param>
    /// <param name="RestoreHealth">If true then health will be restored to full</param>
    public void AdjustMaxHealth(float Amount, bool RestoreHealth = false) {



    myStats.AdjustMaxHealth(Amount);
    }

    /// <summary>
    /// Will adjust max Mana
    /// </summary>
    /// <param name="Amount">Amount to adjust max Mana by</param>
    /// <param name="RestoreHealth">If true then Mana will be restored to full</param>
    public void AdjustMaxMana(float Amount, bool RestoreMana = false) {



    myStats.AdjustMaxMana(Amount);
    }

    /// <summary>
    /// Will adjust health regen rate
    /// </summary>
    /// <param name="Amount">Amount to adjust regen by</param>
    public void AdjustHealthRegen(float Amount) {



    myStats.AdjustHealthRegen(Amount);

    }

    /// <summary>
    /// Will adjust mana regen rate
    /// </summary>
    /// <param name="Amount">Amount to adjust regen by</param>
    public void AdjustManaRegen(float Amount) {



    myStats.AdjustManaRegen(Amount);

    }



    /// <summary>
    /// Will return the stat value asked for in the parameter
    /// </summary>
    /// <param name="StatName">Stat to find value for</param>
    /// <param name="IntegrationType">The integration type for stat functionality - if ABC is picked then normal stat functionality is used else stat from another integration system i.e game creator is used</param>>
    /// <returns>Value of the stat</returns>
    public float GetStatValue(string StatName, ABCIntegrationType IntegrationType = ABCIntegrationType.ABC) {


    myStats.GetStat(StatName);

    }




    /// <summary>
    /// Will modify a stats value by the amount provided
    /// </summary>
    /// <param name="StatName">Stat which will have its value modified</param>
    /// <param name="Amount">Amount to increase or decrease the stat value by</param>
    public void AdjustStatValue(string StatName, float Amount) {


    myStats.AdjustStatValue(StatName, Amount);

    }


    }
    This will override the ABC_IEntity base so whenever ABC asks for max health it will instead call any other component you extended in this new file
    The benefit of this also is any updates to ABC won't overwrite your changes as you have this extended file which ABC won't modify on update
    Hope that helps with the ORK integration
    So with all that said, I'm basically trying to figure out the best/cleanest approach to this. As a code noob, I'm trying to figure out the best way to do this.

    As far as the code you mentioned above, how would I best apply it? Should I try and make a plugin? Or just a script I attach to the combatant as a bridge?
    Currently making: Real-Time Diablo-like ARPG
  • If it's just to forward ORK status changes, I'd recommend using a custom component to bridge between ORK and ATB.

    Register to the combatant's status value changes in the component's Start function. You can register like this:
    combatant.Status[index].SimpleChanged += StatusValueChanged;
    StatusValueChanged would be a function in the class:
    public void StatusValueChanged()

    The function will be called whenever the status value you registered to changes - e.g. get the value from the combatant (as shown above) and forward it to ATB.
    Please consider rating/reviewing my products on the Asset Store (hopefully positively), as that helps tremendously with getting found.
    If you're enjoying my products, updates and support, please consider supporting me on patreon.com!
  • edited May 2022
    So I've been working on the integration script, and while I get no errors in the IDE, in play I get a Null Reference Error on this line;

    public override float manaValue => _Combatant.Status[(int)OrkStatusValue.ETHER].GetValue(); //Assumes Index 3 is Ork Mana Value


    It seems like I'm not getting the correct reference?

    This is the full script atm. I just want to make sure I"m pointing to the right thing in Ork.

    using GamingIsLove.ORKFramework;

    public partial class ABC_IEntity
    {

    private Combatant combatant;

    public void Start()
    {

    //Registers to the combatant's status value changes
    combatant.Status[0].SimpleChanged += StatusValueChanged;
    combatant.Status[1].SimpleChanged += StatusValueChanged;
    combatant.Status[2].SimpleChanged += StatusValueChanged;
    combatant.Status[3].SimpleChanged += StatusValueChanged;
    combatant.Status[4].SimpleChanged += StatusValueChanged;
    combatant.Status[5].SimpleChanged += StatusValueChanged;
    combatant.Status[10].SimpleChanged += StatusValueChanged;
    combatant.Status[11].SimpleChanged += StatusValueChanged;
    combatant.Status[12].SimpleChanged += StatusValueChanged;
    combatant.Status[13].SimpleChanged += StatusValueChanged;
    combatant.Status[14].SimpleChanged += StatusValueChanged;
    combatant.Status[15].SimpleChanged += StatusValueChanged;
    combatant.Status[16].SimpleChanged += StatusValueChanged;
    combatant.Status[17].SimpleChanged += StatusValueChanged;
    combatant.Status[18].SimpleChanged += StatusValueChanged;
    combatant.Status[19].SimpleChanged += StatusValueChanged;
    combatant.Status[20].SimpleChanged += StatusValueChanged;
    combatant.Status[26].SimpleChanged += StatusValueChanged;

    }

    public void StatusValueChanged() //Function to be called whenever registered status effects change
    {

    }

    public Combatant OrkStats

    {

    get
    {
    //If ani runner is null for any reason then reassign the component
    if (this.combatant == null)
    {
    _ = ORKComponentHelper.GetCombatant(this.gameObject); //Gets Combatant from a game object
    }

    return this.combatant;
    }
    }

    #region ABC TO ORK STATS
    /// <summary>
    /// Ork Framework 3 doesn't have predefined Stats, aka Status Values. So the name/ID of the Health, Mana and the rest, can be anything. I generally try to keep my stats in the character sheet type minor to make it easier to tell where the stats are.
    ///
    /// ORK USES INT VALUES SO EACH FUNCTION USES CASTING
    ///
    /// </summary>


    /// <summary>
    /// Returns entities Current Health Value
    /// </summary>
    public override float healthValue => combatant.Status[(int)OrkStatusValue.LIFEFORCE].GetValue(); //Assumes Index 1 as Ork Health Value

    /// <summary>
    /// Returns entities Max Health Value
    /// </summary>
    public override float maxHealthValue => combatant.Status[(int)OrkStatusValue.BRINK].GetValue(); //Assumes Index 0 as ORK MaxHealth

    /// <summary>
    /// Returns entities Max Mana Value
    /// </summary>
    public override float maxManaValue => combatant.Status[(int)OrkStatusValue.MAXETHER].GetValue(); //Assumes Index 2 as Ork MaxMana

    /// <summary>
    /// Returns entities Current Mana Value
    /// </summary>

    public override float manaValue => combatant.Status[(int)OrkStatusValue.ETHER].GetValue(); //Assumes Index 3 is Ork Mana Value

    /// <summary>
    /// Will Adjust the entities health
    /// </summary>
    /// <param name="Potency">Amount to adjust health by (can be positive or negative)</param>
    public override void AdjustHealth(float Potency) => combatant.Status[(int)OrkStatusValue.LIFEFORCE].SetValue((int)Potency,
    false,
    true,
    true,
    false,
    false,
    null);

    /// <summary>
    /// Will Adjust the entities mana
    /// </summary>
    /// <param name="Potency">Amount to adjust mana by (can be positive or negative)</param>
    public override void AdjustMana(float Potency) => combatant.Status[(int)OrkStatusValue.ETHER].SetValue((int)Potency,
    false,
    true,
    true,
    false,
    false,
    null);

    /// <summary>
    /// Will increase max health
    /// </summary>
    /// <param name="Amount">Amount to increase max health by</param>
    /// <param name="RestoreHealth">If true then health will be restored to full</param>
    public override void AdjustMaxHealth(float Amount, bool RestoreHealth = false)
    {
    if (RestoreHealth)
    {
    combatant.Status[(int)OrkStatusValue.BRINK].SetValue((int)Amount,
    false,
    true,
    true,
    false,
    false,
    null);
    }
    else
    {
    combatant.Status[(int)OrkStatusValue.BRINK].SetBaseValue((int)Amount);
    }

    }

    /// <summary>
    /// Will adjust max Mana
    /// </summary>
    /// <param name="Amount">Amount to adjust max Mana by</param>
    /// <param name="RestoreMana">If true then Mana will be restored to full</param>
    public override void AdjustMaxMana(float Amount, bool RestoreMana = false)
    {
    if (RestoreMana)
    {

    combatant.Status[(int)OrkStatusValue.MAXETHER].SetValue((int)Amount,
    false,
    true,
    true,
    false,
    false,
    null);
    }
    else
    {
    combatant.Status[(int)OrkStatusValue.MAXETHER].SetBaseValue((int)Amount);
    }
    }

    /// <summary>
    /// Will adjust health regen rate
    /// </summary>
    /// <param name="Amount">Amount to adjust regen by</param>
    public override void AdjustHealthRegen(float Amount)
    {
    //In ORK regeneration is handled by Ork Status Effects

    //combatant.AdjustHealthRegen(Amount);

    }

    /// <summary>
    /// Will adjust mana regen rate
    /// </summary>
    /// <param name="Amount">Amount to adjust regen by</param>
    public override void AdjustManaRegen(float Amount)
    {

    //In Ork regeneration is handled by Ork Status Effects

    //combatant.AdjustManaRegen(Amount);

    }

    /// <summary>
    /// Will return the stat value asked for in the parameter
    /// </summary>
    /// <param name="StatName">Stat to find value for</param>
    /// <param name="IntegrationType">The integration type for stat functionality - if ABC is picked then normal stat functionality is used else stat from another integration system i.e game creator is used</param>>
    /// <returns>Value of the stat</returns>
    public float GetStatValue(string StatName, ABCIntegrationType IntegrationType = ABCIntegrationType.Ork3Framework)
    {
    float returnValue = 0;
    StatusValue theStatus = GetORKStatByName(StatName);
    if (theStatus != null)
    {
    returnValue = theStatus.GetValue();
    }
    return returnValue;

    }

    /// <summary>
    /// Will modify a stats value by the amount provided
    /// </summary>
    /// <param name="StatName">Stat which will have its value modified</param>
    /// <param name="Amount">Amount to increase or decrease the stat value by</param>
    public void AdjustStatValue(string StatName, float Amount)
    {
    _ = GetORKStatByName(StatName);
    }

    // Maybe is not good idea to return just the statusvalue and
    // and we might need to repeat the code in both methods above
    private StatusValue GetORKStatByName(string statName)
    {
    StatusValue returnValue = null;
    int numberOfStats = ORK.StatusValues.Count;
    for (int i = 0; i <= numberOfStats; ++i)
    {
    if (combatant.Status[i].GetName().Equals(statName))
    {
    returnValue = combatant.Status[i];
    break;
    }
    }
    return returnValue;
    }
    #endregion


    #region INTEGRATION OVERRIDES

    /// <summary>
    /// Additional partial class overrides for ABCIntegration to smoothline it
    /// </summary>

    public enum ABCIntegrationType
    {
    ABC = 0,
    GameCreator = 1,
    EmeraldAI = 2,
    GameCreator2 = 3,
    Ork3Framework = 4,
    }
    #endregion

    #region ORK STAT ENUMS

    //
    //These ENUMs were created to just add more human language to the output and make it easier to debug. I used my own custom stats for my game, but any Ork Status Value can be replaced.
    //

    public enum OrkStatusValue
    {
    BRINK = 0, //Maximum Health
    LIFEFORCE = 1, //Current Health
    MAXETHER = 2, //Maximum Mana
    ETHER = 3, //Current Mana
    MAXSTAMINA = 4, //Maximum Stamina
    STAMINA = 5, //Current Stamina
    EXP = 6, //Character Experience
    PEXP = 7, //Profession/Class Experience
    CP = 8, //Character Points (For Character upgrades)
    TP = 9, //Technique Points (For Ability Upgrades)
    LOGIC = 10, //Character Stat for Ether Damage
    AURA = 11, //Character Stat for force of Personality
    CUNNING = 12, //Character stat for crits, stealth and shady things
    AWARENESS = 13, //Character stat for physical awareness and senses
    POWER = 14, //Character stat for Attack
    SPEED = 15, //Character stat for physical speed and dodging
    DETERMINATION = 16, //Character stat for mental willpower and using Hekan Arts
    FORTITUDE = 17, //Character stat for physical defense
    HEKANARTS = 18, //Character stat for using Hekan Arts
    ATKSPD = 19, //Character stat for increasing speed of Attacks
    CASTSPD = 20, //Character stat for increasing speed of Hekan Arts
    ATTACK = 21, //Damage Stat
    WEAPONDMG = 22, //Increased Attack with a Weapon
    ETHERIALDMG = 23, //Increased Attack with Etherial attacks
    SOAK = 24, //Character Attack Defense
    ARMOR = 25, //Equipment Defense
    DEFENSE = 26, //Total Attack Defense
    ETHERIALDEFENSE = 27, //Total Etherial Defense
    THORNS = 28, //Amount of Attack Damage done on Hit
    CRITHITMOD = 29, //Increases Chance to Hit with Critical
    CRITPOWER = 30, //Increases Critical Damage
    CRITDEFENSE = 31, //Increases Defense against Critical Attacks
    BLOCKCHANCE = 32, //Chance to Block Attacks
    BLOCKMOD = 33, //Increases amount of Attack Blocked
    ACCMOD = 34, //Increases accuracy of Attacks
    DODGE = 35, //Chance to Dodge Attacks
    DODGEMOD = 36, //Increases chance to Dodge
    AOERADIUS = 37, //Increases radius of Attacks
    CCPOWER = 38, //Chance to land a Crowd Control effect
    CCRESIST = 39, //Increases chance to resist a Crowd Control effect
    SOCIALSKILL = 40, //Increases chance of success in Social events
    MOVESPEED = 41, //Increases movement speed of player
    CHANCETOBLEED = 42, //Chance to hit with Bleed effect
    CHANCETODISADV = 43, //Chance to hit with Disadvantage
    CHANCETOKNOCKBACK = 44, //Chance to Knockback enemy
    CHANCETOPOISON = 45, //Chance to poison enemy
    CHANCETOROOT = 46, //Chance to root enemy in place
    CHANCETOSILENCE = 47, //Chance to cease enemy from casting Hekan Arts
    CHANCETOSLEEP = 48, //Chance to put enemy to sleep
    CHANCETOSTAGGER = 49, //Chance to stagger enemy on hit
    CHANCETOSTUN = 50, //Chance to Stun enemy on hit
    CHANCETOADV = 51, //Chance too hit with Advantage
    DOTBONUS = 52, //Increases Damage over Time effects
    ETHEREGENONKILL = 53, //Increases Ether Regeneration on Kill
    HOTBONUS = 54, //Increases Heal over Time effects
    HEALTHONBLOCK = 55, //Amount of Health returned on Block
    HEALTHONKILL = 56, //Amount of Health regained on killing an enemy
    HEALTHREGEN = 57, //Amount of Health regnerated per second
    LIFESTEAL = 58, //Amount of Health stolen fron enemy on Attack
    LOOTCHANCE = 59, //Increases chance for a roll on the Loot Table
    PROJECTILECOUNT = 60, //Increases number of projectiles on a projectile Attack
    PROJECTILERANGE = 61, //Increases the range of projectiles
    PROJECTILESPEED = 62, //Increases the Speed of a projectile
    MINIONBRINK = 63, //Minion Maximum Health
    MINIONLIFEFORCE = 64, //Minion Current Health
    MINIONMAXETHER = 65, //Minion Maximum Ether
    MINIONETHER = 66, //Minion Current Ether
    MINIONMAXSTAMINA = 67, //Minion Maximum Stamina
    MINIONSTAMINA = 68, //Minion Current Stamina
    MINIONCRITCHANCE = 69, //Minion Critical Chance
    MINIONCRITPOWER = 70, //Minion Critical Power
    MINIONATTACK = 71, //Minion Attack
    MINIONWEAPONDAMAGE = 72, //Increases Minion Weapon Damage
    MINIONETHERIALDMG = 73, //Increases Minion Etherial Damage
    MINIONDEFENSE = 74, //Minion Total Defense
    MINIONDURATION = 75, //Minion Summoning Duration
    MINIONLIFESTEAL = 76, //Minions amount of life stolen on hit
    MINIONTHORNS = 77, //Minion Thorns
    MINIONCOUNT = 78 //Number of Minions that can be summoned at once
    }
    }
    #endregion


    Post edited by Solkyoshiro on
    Currently making: Real-Time Diablo-like ARPG
  • edited May 2022
    Problem solved.

    I had to move the script from the asset folder to outside to Resources and fix the whole private/public variable mess.
    Post edited by Solkyoshiro on
    Currently making: Real-Time Diablo-like ARPG
Sign In or Register to comment.