Esempio n. 1
0
    public SodaScriptTrigger AddDefaultTrigger()
    {
        SodaScriptTrigger dt = AddTrigger(SodaScriptTarget.ENEMY, SodaScriptCondition.WEAKEST);

        dt.SetSkill(SodaScriptSkillCategory.DEFAULT);
        return(dt);
    }
Esempio n. 2
0
    public SodaScriptTrigger AddTrigger(SodaScriptTarget inTarget, SodaScriptCondition inCondition, SodaScriptComparison inComparison = SodaScriptComparison.EQUALS, string inCompareValue = "")
    {
        SodaScriptTrigger t = new SodaScriptTrigger(inTarget, inCondition, inComparison, inCompareValue);

        triggers.Add(t);
        return(t);
    }
Esempio n. 3
0
    public void DeleteTrigger(SodaScriptTrigger inTrigger)
    {
        if (!triggers.Contains(inTrigger))
        {
            throw new Exception("Soda script does not contain requested trigger");
        }

        triggers.Remove(inTrigger);
    }
Esempio n. 4
0
    public float GetNormalizedListPositionForTrigger(SodaScriptTrigger inTrigger)
    {
        float triggerIndex = GetTriggerIndex(inTrigger);

        if (triggerIndex == 0)
        {
            return(0);
        }

        return((triggerIndex + 1) / triggers.Count);
    }
Esempio n. 5
0
    //Validate ensures that the chosen combination of target, condition, comparison, value, and skill all make sense.
    //In the case of an invalid combination, default values are chosen
    public void ValidateTrigger(SodaScriptTrigger inTrigger)
    {
        if (!triggers.Contains(inTrigger))
        {
            throw new Exception("Soda script was asked to validate a trigger it doesn't contain");
        }

        //VALIDATE PRIMARY CONDITION
        if (!IsAllowedConditionForTarget(inTrigger.condition, inTrigger.target))
        {
            inTrigger.condition = GetDefaultConditionForTarget(inTrigger.target);
        }

        if (ConditionRequiresAComparison(inTrigger.condition))
        {
            if (!IsAllowedComparisonForCondition(inTrigger.comparison, inTrigger.condition))
            {
                inTrigger.comparison = GetDefaultComparisonForCondition(inTrigger.condition);
            }

            if (!IsAllowedComparisonValueForCondition(inTrigger.compareValue, inTrigger.condition))
            {
                inTrigger.compareValue = GetDefaultCompareValueForCondition(inTrigger.condition);
            }
        }

        //VALIDATE SECONDARY CONDITION
        if (!IsAllowedConditionForTarget(inTrigger.secondaryCondition, inTrigger.target))
        {
            inTrigger.secondaryCondition = GetDefaultConditionForTarget(inTrigger.target);
        }

        if (ConditionRequiresAComparison(inTrigger.secondaryCondition))
        {
            if (!IsAllowedComparisonForCondition(inTrigger.secondaryComparison, inTrigger.secondaryCondition))
            {
                inTrigger.secondaryComparison = GetDefaultComparisonForCondition(inTrigger.secondaryCondition);
            }

            if (!IsAllowedComparisonValueForCondition(inTrigger.secondaryCompareValue, inTrigger.secondaryCondition))
            {
                inTrigger.secondaryCompareValue = GetDefaultCompareValueForCondition(inTrigger.secondaryCondition);
            }
        }

        //VALIDATE CHOSEN SKILL ID (IF THERE IS ONE)
        if (inTrigger.skillCategory == SodaScriptSkillCategory.SPECIFIC)
        {
            if (!IsAllowedSkillIdForTarget(inTrigger.skillId, inTrigger.target))
            {
                inTrigger.skillId = GetDefaultSkillIdForTarget(inTrigger.target);
            }
        }
    }
Esempio n. 6
0
    private int GetTriggerIndex(SodaScriptTrigger inTrigger)
    {
        for (int i = 0; i < triggers.Count; i++)
        {
            if (triggers[i] == inTrigger)
            {
                return(i);
            }
        }

        throw new Exception("Soda script does not contain requested trigger");
    }
Esempio n. 7
0
    public SodaScriptTrigger GetCopy()
    {
        SodaScriptTrigger sst = new SodaScriptTrigger(target, condition, comparison, compareValue);

        sst.skillCategory    = skillCategory;
        sst.skillId          = skillId;
        sst.percentageChance = percentageChance;

        if (hasSecondaryCondition)
        {
            sst.hasSecondaryCondition = hasSecondaryCondition;
            sst.secondaryCondition    = secondaryCondition;
            sst.secondaryComparison   = secondaryComparison;
            sst.secondaryCompareValue = secondaryCompareValue;
        }

        return(sst);
    }
Esempio n. 8
0
    public void MoveTriggerDown(SodaScriptTrigger inTrigger)
    {
        if (!triggers.Contains(inTrigger))
        {
            throw new Exception("Soda script does not contain requested trigger");
        }

        if (triggers.Count == 1)
        {
            return;
        }

        int triggerIndex = GetTriggerIndex(inTrigger);

        if (triggerIndex == triggers.Count - 1)
        {
            return;
        }

        triggers.Remove(inTrigger);
        triggers.Insert(triggerIndex + 1, inTrigger);
    }
Esempio n. 9
0
    private bool EvalTrigger(SodaScriptTrigger inTrigger, SkillCommand inCommandToPopulate)
    {
        //is this a trigger with a percentage chance? if so start with that since it can save us processing time
        if (inTrigger.percentageChance < 100)
        {
            if (!Utils.PercentageChance(inTrigger.percentageChance))
            {
                return(false);
            }
        }

        potentialTargets.Clear();
        culledTargets.Clear();

        CharacterData curTarget = null;

        if (inTrigger.target == SodaScriptTarget.SELF)
        {
            potentialTargets.Add(activeCharacter);
        }
        else if (inTrigger.target == SodaScriptTarget.ALLY)
        {
            for (int i = 0; i < ownTeam.members.Count; i++)
            {
                curTarget = ownTeam.members[i];
                if (!curTarget.dead && curTarget != activeCharacter)
                {
                    potentialTargets.Add(curTarget);
                }
            }
        }
        else if (inTrigger.target == SodaScriptTarget.ENEMY)
        {
            for (int i = 0; i < opposingTeam.members.Count; i++)
            {
                curTarget = opposingTeam.members[i];
                if (!curTarget.dead)
                {
                    potentialTargets.Add(curTarget);
                }
            }
        }

        //we might not even have a list of *potential* targets! (this would happen in a case when we try target an ally but we're the only member on the team)
        if (potentialTargets.Count == 0)
        {
            return(false);
        }

        //eval the condition on our list
        if (inTrigger.condition == SodaScriptCondition.ANY)
        {
            curTarget = potentialTargets.GetRandomElement();
            potentialTargets.Clear();
            potentialTargets.Add(curTarget);
        }
        else
        {
            //default to a normal eval
            EvalCondition(inTrigger.condition, inTrigger.comparison, inTrigger.compareValue, potentialTargets);
        }

        //exit if no potentials found yet
        if (potentialTargets.Count == 0)
        {
            return(false);
        }

        //do we have to check a secondary condition?
        if (inTrigger.hasSecondaryCondition)
        {
            EvalCondition(inTrigger.secondaryCondition, inTrigger.secondaryComparison, inTrigger.secondaryCompareValue, potentialTargets);
        }

        //did we find a valid target? if not, return false
        if (potentialTargets.Count == 0)
        {
            return(false);
        }

        //fix some issues when targetting self and requesting certain skill categories, turn into strongest *self* heal (avoids issues with first aid)
        if (inTrigger.target == SodaScriptTarget.SELF)
        {
            if (inTrigger.skillCategory == SodaScriptSkillCategory.STRONGEST_HEAL)
            {
                inTrigger.skillCategory = SodaScriptSkillCategory.STRONGEST_SELF_HEAL;
            }

            if (inTrigger.skillCategory == SodaScriptSkillCategory.ANY_BUFF)
            {
                inTrigger.skillCategory = SodaScriptSkillCategory.ANY_SELF_BUFF;
            }
        }

        //is the skill also valid? if not, return false
        if (inTrigger.skillCategory == SodaScriptSkillCategory.DEFAULT)
        {
            potentialSkill = activeCharacter.GetDefaultSkill();
        }
        else if (inTrigger.skillCategory == SodaScriptSkillCategory.SPECIFIC)
        {
            potentialSkill = Skill.GetSkill(inTrigger.skillId);
        }
        else if (inTrigger.skillCategory == SodaScriptSkillCategory.ANY_NON_FRIENDLY_THAT_CONSUMES_MP)
        {
            potentialSkill = activeCharacter.GetAnyNonFriendlySkillThatUsesMP();
        }
        else if (inTrigger.skillCategory == SodaScriptSkillCategory.ANY_NON_FRIENDLY_THAT_DOESNT_CONSUME_MP)
        {
            potentialSkill = activeCharacter.GetAnyNonFriendlySkillThatDoesntUseMP();
        }
        else if (inTrigger.skillCategory == SodaScriptSkillCategory.ANY)
        {
            potentialSkill = activeCharacter.GetRandomUsableSkill();
        }
        else if (inTrigger.skillCategory == SodaScriptSkillCategory.STRONGEST_SELF_HEAL)
        {
            potentialSkill = activeCharacter.GetStrongestUsableHealSkill(false, true);
        }
        else if (inTrigger.skillCategory == SodaScriptSkillCategory.STRONGEST_HEAL)
        {
            potentialSkill = activeCharacter.GetStrongestUsableHealSkill(false, false);
        }
        else if (inTrigger.skillCategory == SodaScriptSkillCategory.STRONGEST_GROUP_HEAL)
        {
            potentialSkill = activeCharacter.GetStrongestUsableHealSkill(true, false);
        }
        else if (inTrigger.skillCategory == SodaScriptSkillCategory.STRONGEST_ATTACK)
        {
            potentialSkill = activeCharacter.GetStrongestUsableDamageSkill(false);
        }
        else if (inTrigger.skillCategory == SodaScriptSkillCategory.STRONGEST_GROUP_ATTACK)
        {
            potentialSkill = activeCharacter.GetStrongestUsableDamageSkill(true);
        }
        else if (inTrigger.skillCategory == SodaScriptSkillCategory.STRONGEST_SINGLE_TARGET_ATTACK)
        {
            potentialSkill = activeCharacter.GetStrongestUsableDamageSkill(false, true);
        }
        else if (inTrigger.skillCategory == SodaScriptSkillCategory.ANY_BUFF)
        {
            potentialSkill = activeCharacter.GetAnySkillThatBuffs();
        }
        else if (inTrigger.skillCategory == SodaScriptSkillCategory.ANY_SELF_BUFF)
        {
            potentialSkill = activeCharacter.GetAnySkillThatSelfBuffs();
        }
        else if (inTrigger.skillCategory == SodaScriptSkillCategory.ANY_DEBUFF)
        {
            potentialSkill = activeCharacter.GetAnySkillThatDebuffs();
        }
        else
        {
            throw new Exception("Skill category " + inTrigger.skillCategory + " is not supported");
        }

        if (potentialSkill == null)
        {
            return(false);
        }

        if (!activeCharacter.CanUseSkill(potentialSkill.id))
        {
            return(false);
        }


        //make sure we're not using a friendly skill on an enemy (unless it is DEFEND)
        if (inTrigger.target == SodaScriptTarget.ENEMY && potentialSkill.isFriendly && potentialSkill.id != SkillId.DEFEND)
        {
            return(false);
        }

        //make sure we're not using a damage skill on self or ally
        if ((inTrigger.target == SodaScriptTarget.ALLY || inTrigger.target == SodaScriptTarget.SELF) && !potentialSkill.isFriendly)
        {
            return(false);
        }

        //make sure if targeting self, chosen skill is allowed to self target
        if (inTrigger.target == SodaScriptTarget.SELF && !potentialSkill.allowsSelfTarget)
        {
            return(false);
        }

        //make sure not stealing from someone who has already been stolen from
        if ((potentialSkill.id == SkillId.PILFER || potentialSkill.id == SkillId.RANSACK) && potentialTargets[0].hasBeenStolenFrom)
        {
            return(false);
        }

        //don't try to transmute a target after we've already hit the limit of 1 successful transmute per battle (or if not a common enemy)
        if (potentialSkill.id == SkillId.TRANSMUTE)
        {
            bool battleIsBossOrMiniboss = (adventure.battleNumBasedOn10 == 5 || adventure.battleNumBasedOn10 == 10);
            if (adventure.battleManager.CurBattleTransmuteLimitReached() || battleIsBossOrMiniboss)
            {
                return(false);
            }
        }
        else if (potentialSkill.id == SkillId.FORETELL)
        {
            //don't try to foretell if the "force warp" flag is active for the current adventure
            if (adventure.forceWarpAtNextPaths)
            {
                return(false);
            }
        }

        //make sure an arena npc isn't using a banned skill
        if (activeCharacter.isArenaNpc && !potentialSkill.allowedForArenaNpcs)
        {
            return(false);
        }

        //make sure this team hasn't tried to heal itself too many times in a row
        if (potentialSkill.isHealing && ownTeam.HasReachedConsecutiveHealLimit())
        {
            return(false);
        }

        //if we found a valid target and skill, populate the commmand and return true
        inCommandToPopulate.Reset(potentialSkill, activeCharacter);
        inCommandToPopulate.AddTarget(potentialTargets[0]);
        return(true);
    }
Esempio n. 10
0
    public static void CreateScripts()
    {
        scripts = new List <SodaScript>();

        SodaScript        script;
        SodaScriptTrigger trigger;

        //ENEMY
        script             = new SodaScript(SCRIPT_DEFAULT_ENEMY);
        script._isReadonly = true;

        //testing trigger, use this to force a skill
        //trigger = script.AddTrigger(SodaScriptTarget.ENEMY, SodaScriptCondition.ANY);
        //trigger.SetSkill(SodaScriptSkillCategory.SPECIFIC, SkillId.STUN);

        trigger = script.AddTrigger(SodaScriptTarget.SELF, SodaScriptCondition.HP, SodaScriptComparison.LESS_THAN, "50");
        trigger.SetSkill(SodaScriptSkillCategory.STRONGEST_HEAL);
        trigger.percentageChance = 70;

        trigger = script.AddTrigger(SodaScriptTarget.ALLY, SodaScriptCondition.HP, SodaScriptComparison.LESS_THAN, "60");
        trigger.SetSkill(SodaScriptSkillCategory.STRONGEST_HEAL);
        trigger.percentageChance = 90;

        trigger = script.AddTrigger(SodaScriptTarget.SELF, SodaScriptCondition.STATUS, SodaScriptComparison.NOT_EQUALS, StatusEffectCategory.POSITIVE.ToString());
        trigger.SetSkill(SodaScriptSkillCategory.ANY_SELF_BUFF);
        trigger.percentageChance = 70;

        //we can use this to attempt debuffs specifically, but any debuff is included in "any non friendly that consumes mp" trigger
        //trigger = script.AddTrigger(SodaScriptTarget.ENEMY, SodaScriptCondition.STATUS, SodaScriptComparison.NOT_EQUALS, StatusEffectCategory.NEGATIVE.ToString());
        //trigger.SetSkill(SodaScriptSkillCategory.ANY_DEBUFF);

        trigger = script.AddTrigger(SodaScriptTarget.ENEMY, SodaScriptCondition.ANY);
        trigger.SetSkill(SodaScriptSkillCategory.ANY_NON_FRIENDLY_THAT_CONSUMES_MP);
        trigger.percentageChance = 25;

        trigger = script.AddTrigger(SodaScriptTarget.ENEMY, SodaScriptCondition.ANY);
        trigger.SetSkill(SodaScriptSkillCategory.ANY_NON_FRIENDLY_THAT_DOESNT_CONSUME_MP);

        trigger = script.AddTrigger(SodaScriptTarget.ENEMY, SodaScriptCondition.ANY);
        trigger.SetSkill(SodaScriptSkillCategory.DEFAULT);
        scripts.Add(script);

        //PLAYER
        script             = new SodaScript(SCRIPT_DEFAULT_PLAYER);
        script._isReadonly = true;

        //testing trigger, use this to force a skill
        //trigger = script.AddTrigger(SodaScriptTarget.ENEMY, SodaScriptCondition.ANY);
        //trigger.SetSkill(SodaScriptSkillCategory.SPECIFIC, SkillId.STUN);

        trigger = script.AddTrigger(SodaScriptTarget.SELF, SodaScriptCondition.HP, SodaScriptComparison.LESS_THAN, "60");
        trigger.SetSkill(SodaScriptSkillCategory.STRONGEST_HEAL);

        trigger = script.AddTrigger(SodaScriptTarget.ALLY, SodaScriptCondition.HP, SodaScriptComparison.LESS_THAN, "60");
        trigger.SetSkill(SodaScriptSkillCategory.STRONGEST_HEAL);

        trigger = script.AddTrigger(SodaScriptTarget.ENEMY, SodaScriptCondition.TEAM_ALIVE, SodaScriptComparison.GREATER_THAN, "2");
        trigger.SetSkill(SodaScriptSkillCategory.STRONGEST_GROUP_ATTACK);

        //50% chance to use a debuff skill on character with no debuffs
        trigger = script.AddTrigger(SodaScriptTarget.ENEMY, SodaScriptCondition.STATUS, SodaScriptComparison.NOT_EQUALS, StatusEffectCategory.NEGATIVE.ToString());
        trigger.SetSkill(SodaScriptSkillCategory.ANY_DEBUFF);
        trigger.percentageChance = 50;

        trigger = script.AddTrigger(SodaScriptTarget.ENEMY, SodaScriptCondition.RANK, SodaScriptComparison.GREATER_THAN, EnemyRank.MBOS.ToString());
        trigger.SetSecondaryCondition(SodaScriptCondition.HP, SodaScriptComparison.GREATER_THAN, "50");
        trigger.SetSkill(SodaScriptSkillCategory.STRONGEST_SINGLE_TARGET_ATTACK);

        trigger = script.AddTrigger(SodaScriptTarget.ENEMY, SodaScriptCondition.ISNT_ORE);
        trigger.SetSecondaryCondition(SodaScriptCondition.WEAKEST);
        trigger.SetSkill(SodaScriptSkillCategory.DEFAULT);
        scripts.Add(script);

        //default trigger that will mostly be used by player scripts
        defaultTrigger = new SodaScriptTrigger(SodaScriptTarget.ENEMY, SodaScriptCondition.WEAKEST);
        defaultTrigger.SetSkill(SodaScriptSkillCategory.DEFAULT);

        //create some lists to limit user input to logically correct values
        USER_ALLOWED_TARGETS = new SodaScriptTarget[]
        {
            SodaScriptTarget.ENEMY,
            SodaScriptTarget.ALLY,
            SodaScriptTarget.SELF
        };

        allowedConditionsForTarget = new Dictionary <SodaScriptTarget, SodaScriptCondition[]>();
        allowedConditionsForTarget[SodaScriptTarget.ENEMY] = new SodaScriptCondition[]
        {
            SodaScriptCondition.WEAKEST,
            SodaScriptCondition.HP,
            SodaScriptCondition.MP,
            SodaScriptCondition.TEAM_ALIVE,
            SodaScriptCondition.TEAM_HP,
            SodaScriptCondition.RANK,
            SodaScriptCondition.IS_ORE,
            SodaScriptCondition.ISNT_ORE,
            SodaScriptCondition.BACK_IS_TURNED,
            SodaScriptCondition.BACK_ISNT_TURNED,
            SodaScriptCondition.STATUS,
            SodaScriptCondition.HAS_ESSENCE,
            SodaScriptCondition.NO_ESSENCE,
            SodaScriptCondition.IS_JANITOR,
            SodaScriptCondition.ISNT_JANITOR,
            SodaScriptCondition.ANY
        };

        allowedConditionsForTarget[SodaScriptTarget.ALLY] = new SodaScriptCondition[]
        {
            SodaScriptCondition.WEAKEST,
            SodaScriptCondition.HP,
            SodaScriptCondition.MP,
            SodaScriptCondition.TEAM_ALIVE,
            SodaScriptCondition.TEAM_HP,
            SodaScriptCondition.STATUS,
            SodaScriptCondition.POSITION,
            SodaScriptCondition.ANY
        };

        allowedConditionsForTarget[SodaScriptTarget.SELF] = new SodaScriptCondition[]
        {
            SodaScriptCondition.HP,
            SodaScriptCondition.MP,
            SodaScriptCondition.TEAM_ALIVE,
            SodaScriptCondition.TEAM_HP,
            SodaScriptCondition.STATUS
        };

        conditionsThatRequireAComparison = new SodaScriptCondition[] {
            SodaScriptCondition.HP,
            SodaScriptCondition.MP,
            SodaScriptCondition.TEAM_ALIVE,
            SodaScriptCondition.TEAM_HP,
            SodaScriptCondition.RANK,
            SodaScriptCondition.STATUS,
            SodaScriptCondition.POSITION
        };

        allComparisons              = new SodaScriptComparison[] { SodaScriptComparison.GREATER_THAN, SodaScriptComparison.LESS_THAN, SodaScriptComparison.EQUALS, SodaScriptComparison.NOT_EQUALS };
        justEqualsComparison        = new SodaScriptComparison[] { SodaScriptComparison.EQUALS, SodaScriptComparison.NOT_EQUALS };
        greaterOrLessThanComparison = new SodaScriptComparison[] { SodaScriptComparison.LESS_THAN, SodaScriptComparison.GREATER_THAN };


        /**********************************************************************************************************************
         * DATA AND LABELS FOR COMPARISON VALUES THAT BELONG TO SPECIFIC CONDITIONS
         * ******************************************************************************************************************** */
        string[] zeroToOneHundred = GenerateNumericDataList(0, 100, 5);
        string[] zeroToSix        = GenerateNumericDataList(0, 6, 1);
        string[] oneToSix         = GenerateNumericDataList(1, 6, 1);

        comparisonValuesForCondition = new Dictionary <SodaScriptCondition, string[]>();

        comparisonValuesForCondition[SodaScriptCondition.HP]         = zeroToOneHundred;
        comparisonValuesForCondition[SodaScriptCondition.MP]         = zeroToOneHundred;
        comparisonValuesForCondition[SodaScriptCondition.TEAM_ALIVE] = zeroToSix;
        comparisonValuesForCondition[SodaScriptCondition.POSITION]   = oneToSix;
        comparisonValuesForCondition[SodaScriptCondition.TEAM_HP]    = zeroToOneHundred;

        EnemyRank[] ranks = new EnemyRank[] { EnemyRank.NORM, EnemyRank.MBOS, EnemyRank.BOSS, EnemyRank.DBOS };
        comparisonValuesForCondition[SodaScriptCondition.RANK] = ranks.Select(d => d.ToString()).ToArray <string>();

        StatusEffectCategory[] effectCategories = new StatusEffectCategory[] { StatusEffectCategory.POSITIVE, StatusEffectCategory.NEGATIVE, StatusEffectCategory.NONE };
        comparisonValuesForCondition[SodaScriptCondition.STATUS] = effectCategories.Select(d => d.ToString()).ToArray <string>();

        /**********************************************************************************************************************
         * SKILL CATEGORIES AND IDS
         * ******************************************************************************************************************** */
        USER_ALLOWED_SKILL_CATEGORIES = new SodaScriptSkillCategory[]
        {
            SodaScriptSkillCategory.DEFAULT,
            SodaScriptSkillCategory.STRONGEST_ATTACK,
            SodaScriptSkillCategory.STRONGEST_GROUP_ATTACK,
            SodaScriptSkillCategory.STRONGEST_SINGLE_TARGET_ATTACK,
            SodaScriptSkillCategory.STRONGEST_HEAL,
            SodaScriptSkillCategory.STRONGEST_GROUP_HEAL,
            SodaScriptSkillCategory.ANY_BUFF,
            SodaScriptSkillCategory.ANY_DEBUFF,
            SodaScriptSkillCategory.ANY,
            SodaScriptSkillCategory.SPECIFIC
        };

        //this array is locally scoped, we only use it to derive more specific lists
        //defend is not included here, it is a special case added later
        string[] userAllowedSkillIds = new string[]
        {
            SkillId.SWIFT_METAL,
            SkillId.BIOHAZARD,
            SkillId.FIRST_AID,
            SkillId.HEAL
        };

        allowedSkillIdsForTarget = new Dictionary <SodaScriptTarget, string[]>();

        //build out the lists/arrays
        Skill         curSkill;
        List <string> allowedEnemySkillIds = new List <string>();
        List <string> allowedAllySkillIds  = new List <string>();
        List <string> allowedSelfSkillIds  = new List <string>();

        for (int i = 0; i < userAllowedSkillIds.Length; i++)
        {
            curSkill = Skill.GetSkill(userAllowedSkillIds[i]);

            if (curSkill.isFriendly)
            {
                allowedAllySkillIds.Add(curSkill.id);

                if (curSkill.allowsSelfTarget)
                {
                    allowedSelfSkillIds.Add(curSkill.id);
                }
            }
            else
            {
                allowedEnemySkillIds.Add(curSkill.id);
            }
        }

        //make sure to add "defend" for all categories
        allowedEnemySkillIds.Add(SkillId.DEFEND);
        allowedAllySkillIds.Add(SkillId.DEFEND);
        allowedSelfSkillIds.Add(SkillId.DEFEND);

        allowedSkillIdsForTarget[SodaScriptTarget.ENEMY] = allowedEnemySkillIds.ToArray <string>();
        allowedSkillIdsForTarget[SodaScriptTarget.ALLY]  = allowedAllySkillIds.ToArray <string>();
        allowedSkillIdsForTarget[SodaScriptTarget.SELF]  = allowedSelfSkillIds.ToArray <string>();
    }