Пример #1
0
        /// <summary>
        /// Selects a touch spell from this enemy's list and returns true if it can be cast.
        /// </summary>
        bool CanCastTouchSpell()
        {
            if (entity.CurrentMagicka <= 0)
            {
                return(false);
            }

            EffectBundleSettings[]      spells      = entity.GetSpells();
            List <EffectBundleSettings> rangeSpells = new List <EffectBundleSettings>();
            int count = 0;

            foreach (EffectBundleSettings spell in spells)
            {
                // Classic AI considers ByTouch and CasterOnly here
                if (!DaggerfallUnity.Settings.EnhancedCombatAI)
                {
                    if (spell.TargetType == TargetTypes.ByTouch ||
                        spell.TargetType == TargetTypes.CasterOnly)
                    {
                        rangeSpells.Add(spell);
                        count++;
                    }
                }
                else // Enhanced AI considers ByTouch and AreaAroundCaster. TODO: CasterOnly logic
                {
                    if (spell.TargetType == TargetTypes.ByTouch ||
                        spell.TargetType == TargetTypes.AreaAroundCaster)
                    {
                        rangeSpells.Add(spell);
                        count++;
                    }
                }
            }

            if (count == 0)
            {
                return(false);
            }

            EffectBundleSettings selectedSpellSettings = rangeSpells[Random.Range(0, count)];

            selectedSpell = new EntityEffectBundle(selectedSpellSettings, entityBehaviour);

            int totalGoldCostUnused;
            int readySpellCastingCost;

            Formulas.FormulaHelper.CalculateTotalEffectCosts(selectedSpell.Settings.Effects, selectedSpell.Settings.TargetType, out totalGoldCostUnused, out readySpellCastingCost);
            if (entity.CurrentMagicka < readySpellCastingCost)
            {
                return(false);
            }

            if (EffectsAlreadyOnTarget(selectedSpell))
            {
                return(false);
            }

            return(true);
        }
        public void SetSpell(int index, EffectBundleSettings spell)
        {
            if (index < 0 || index > spellbook.Count - 1)
            {
                return;
            }

            spellbook[index] = spell;
        }
Пример #3
0
 public bool GetSpell(int index, out EffectBundleSettings spell)
 {
     if (index < 0 || index > spellbook.Count - 1)
     {
         spell = new EffectBundleSettings();
         return(false);
     }
     else
     {
         spell = spellbook[index];
         return(true);
     }
 }
Пример #4
0
        /// <summary>
        /// Selects a ranged spell from this enemy's list and returns true if it can be cast.
        /// </summary>
        bool CanCastRangedSpell()
        {
            if (entity.CurrentMagicka <= 0)
            {
                return(false);
            }

            EffectBundleSettings[]      spells      = entity.GetSpells();
            List <EffectBundleSettings> rangeSpells = new List <EffectBundleSettings>();
            int count = 0;

            foreach (EffectBundleSettings spell in spells)
            {
                if (spell.TargetType == TargetTypes.SingleTargetAtRange ||
                    spell.TargetType == TargetTypes.AreaAtRange)
                {
                    rangeSpells.Add(spell);
                    count++;
                }
            }

            if (count == 0)
            {
                return(false);
            }

            EffectBundleSettings selectedSpellSettings = rangeSpells[Random.Range(0, count)];

            selectedSpell = new EntityEffectBundle(selectedSpellSettings, entityBehaviour);

            int totalGoldCostUnused;
            int readySpellCastingCost;

            Formulas.FormulaHelper.CalculateTotalEffectCosts(selectedSpell.Settings.Effects, selectedSpell.Settings.TargetType, out totalGoldCostUnused, out readySpellCastingCost);
            if (entity.CurrentMagicka < readySpellCastingCost)
            {
                return(false);
            }

            if (EffectsAlreadyOnTarget(selectedSpell))
            {
                return(false);
            }

            return(true);
        }
Пример #5
0
        /// <summary>
        /// 9
        /// Creates spell. Use Action's index to get the spell by index from Spells.STD
        /// </summary>
        /// <param name="triggerObj"></param>
        /// <param name="thisAction"></param>
        public static void CastSpell(GameObject triggerObj, DaggerfallAction thisAction)
        {
            thisAction.Cooldown -= 45.454546f; // Approximates classic based on observation
            if (thisAction.Cooldown <= 0)
            {
                SpellRecord.SpellRecordData spell;
                if (GameManager.Instance.EntityEffectBroker.GetClassicSpellRecord(thisAction.Index, out spell))
                {
                    // Create effect bundle settings from classic spell
                    EffectBundleSettings bundleSettings;
                    if (GameManager.Instance.EntityEffectBroker.ClassicSpellRecordDataToEffectBundleSettings(spell, BundleTypes.Spell, out bundleSettings))
                    {
                        if (bundleSettings.TargetType == TargetTypes.CasterOnly)
                        {
                            // Spell is readied on player for free
                            GameManager.Instance.PlayerEffectManager.SetReadySpell(thisAction.Index, true);
                        }
                        else
                        {
                            // Spell is fired at player, at strength of player level, from triggering object
                            DaggerfallMissile missile = GameManager.Instance.PlayerEffectManager.InstantiateSpellMissile(bundleSettings.ElementType);
                            missile.Payload = new EntityEffectBundle(bundleSettings);
                            Vector3 customAimPosition = thisAction.transform.position;
                            customAimPosition.y       += 40 * MeshReader.GlobalScale;
                            missile.CustomAimPosition  = customAimPosition;
                            missile.CustomAimDirection = Vector3.Normalize(GameManager.Instance.PlayerObject.transform.position - thisAction.transform.position);

                            // If action spell payload is "touch" then set to "target at range" (targets player position as above)
                            if (missile.Payload.Settings.TargetType == TargetTypes.ByTouch)
                            {
                                EffectBundleSettings settings = missile.Payload.Settings;
                                settings.TargetType      = TargetTypes.SingleTargetAtRange;
                                missile.Payload.Settings = settings;
                            }
                        }
                    }
                }

                //Reset cooldown
                thisAction.Cooldown = 1000;
            }
        }
Пример #6
0
 public void AddSpell(EffectBundleSettings spell)
 {
     // Just add spell to end of list for now
     // When implemented, the real collection class will allow for custom sorting
     spellbook.Add(spell);
 }
 public void AddSpell(EffectBundleSettings spell)
 {
     spellbook.Add(spell);
 }
        private void BuyButton_OnMouseClick(BaseScreenComponent sender, Vector2 position)
        {
            const int notEnoughGold = 1702;
            //const int noSpellBook = 1703;
            const int youMustChooseAName    = 1704;
            const int spellHasBeenInscribed = 1705;

            DaggerfallUI.Instance.PlayOneShot(SoundClips.ButtonClick);

            /*// Presence of spellbook is also checked earlier
             * if (!GameManager.Instance.PlayerEntity.Items.Contains(Items.ItemGroups.MiscItems, (int)Items.MiscItems.Spellbook))
             * {
             *  DaggerfallUI.MessageBox(noSpellBook);
             *  return;
             * }*/

            // Spell must have at least one effect - adding custom message
            List <EffectEntry> effects = GetEffectEntries();

            if (effects.Count == 0)
            {
                DaggerfallUI.MessageBox(TextManager.Instance.GetLocalizedText("noEffectsError"));
                return;
            }

            // Enough money?
            var moneyAvailable = GameManager.Instance.PlayerEntity.GetGoldAmount();

            if (moneyAvailable < totalGoldCost)
            {
                DaggerfallUI.MessageBox(notEnoughGold);
                return;
            }

            // Spell must have a name; Only bother the player if everything else is correct
            if (string.IsNullOrEmpty(spellNameLabel.Text))
            {
                DaggerfallUI.MessageBox(youMustChooseAName);
                return;
            }

            GameManager.Instance.PlayerEntity.DeductGoldAmount(totalGoldCost);

            // Create effect bundle settings
            EffectBundleSettings spell = new EffectBundleSettings();

            spell.Version     = EntityEffectBroker.CurrentSpellVersion;
            spell.BundleType  = BundleTypes.Spell;
            spell.TargetType  = selectedTarget;
            spell.ElementType = selectedElement;
            spell.Name        = spellNameLabel.Text;
            spell.IconIndex   = selectedIcon.index;
            spell.Icon        = selectedIcon;
            spell.Effects     = effects.ToArray();

            // Add to player entity spellbook
            GameManager.Instance.PlayerEntity.AddSpell(spell);

            DaggerfallUI.Instance.PlayOneShot(inscribeGrimoire);

            // Notify player and exit when this messagebox is dismissed
            DaggerfallMessageBox mbComplete = DaggerfallUI.MessageBox(spellHasBeenInscribed);

            mbComplete.ClickAnywhereToClose = true;
            mbComplete.PreviousWindow       = this;
            mbComplete.OnClose += SpellHasBeenInscribed_OnClose;
            mbComplete.Show();
        }
Пример #9
0
        private void BuyButton_OnMouseClick(BaseScreenComponent sender, Vector2 position)
        {
            //const int notEnoughGold = 1702;
            //const int noSpellBook = 1703;
            const int youMustChooseAName    = 1704;
            const int spellHasBeenInscribed = 1705;

            DaggerfallUI.Instance.PlayOneShot(SoundClips.ButtonClick);

            // TODO:
            //   Implement costs and remove gold from player and block if user does not have enough gold (message 1702)
            //   Spells will be free (both gold and spell points) during build-out of effect system.

            // NOTES:
            //  In classic, player must have a spellbook item in their inventory (message 1703).
            //  In Daggerfall Unity, the spellbook is a permanent item that all players own and cannot be removed.
            //  This is to prevent player accidentally dropping or selling their spellbook.
            //  So not performing spellbook check at this time and 1703 is never shown.

            // Spell must have at least one effect - adding custom message
            List <EffectEntry> effects = GetEffectEntries();

            if (effects.Count == 0)
            {
                DaggerfallMessageBox mbNoEffects = DaggerfallUI.MessageBox(TextManager.Instance.GetText("SpellmakerUI", "noEffectsError"));
                mbNoEffects.ClickAnywhereToClose = true;
                mbNoEffects.PreviousWindow       = this;
                mbNoEffects.Show();
                return;
            }

            // Spell must have a name
            if (string.IsNullOrEmpty(spellNameLabel.Text))
            {
                DaggerfallMessageBox mbNoName = DaggerfallUI.MessageBox(youMustChooseAName);
                mbNoName.ClickAnywhereToClose = true;
                mbNoName.PreviousWindow       = this;
                mbNoName.Show();
                return;
            }

            // Create effect bundle settings
            EffectBundleSettings spell = new EffectBundleSettings();

            spell.Version     = EntityEffectBroker.CurrentSpellVersion;
            spell.BundleType  = BundleTypes.Spell;
            spell.TargetType  = selectedTarget;
            spell.ElementType = selectedElement;
            spell.Name        = spellNameLabel.Text;
            spell.IconIndex   = selectedIcon.index;
            spell.Icon        = selectedIcon;
            spell.Effects     = effects.ToArray();

            // Add to player entity spellbook
            GameManager.Instance.PlayerEntity.AddSpell(spell);

            DaggerfallUI.Instance.PlayOneShot(inscribeGrimoire);

            // Notify player and exit when this messagebox is dismissed
            DaggerfallMessageBox mbComplete = DaggerfallUI.MessageBox(spellHasBeenInscribed);

            mbComplete.ClickAnywhereToClose = true;
            mbComplete.PreviousWindow       = this;
            mbComplete.OnClose += SpellHasBeenInscribed_OnClose;
            mbComplete.Show();
        }
Пример #10
0
        /// <summary>
        /// Selects a ranged spell from this enemy's list and returns true if it can be cast.
        /// </summary>
        bool CanCastRangedSpell()
        {
            if (entity.CurrentMagicka <= 0)
            {
                return(false);
            }

            EffectBundleSettings[]      spells      = entity.GetSpells();
            List <EffectBundleSettings> rangeSpells = new List <EffectBundleSettings>();
            int count = 0;

            foreach (EffectBundleSettings spell in spells)
            {
                if (spell.TargetType == TargetTypes.SingleTargetAtRange ||
                    spell.TargetType == TargetTypes.AreaAtRange)
                {
                    rangeSpells.Add(spell);
                    count++;
                }
            }

            if (count == 0)
            {
                return(false);
            }

            EffectBundleSettings selectedSpellSettings = rangeSpells[Random.Range(0, count)];

            selectedSpell = new EntityEffectBundle(selectedSpellSettings, entityBehaviour);

            int totalGoldCostUnused;
            int readySpellCastingCost;

            Formulas.FormulaHelper.CalculateTotalEffectCosts(selectedSpell.Settings.Effects, selectedSpell.Settings.TargetType, out totalGoldCostUnused, out readySpellCastingCost);
            if (entity.CurrentMagicka < readySpellCastingCost)
            {
                return(false);
            }

            if (EffectsAlreadyOnTarget(selectedSpell))
            {
                return(false);
            }

            // Check that there is a clear path to shoot a spell
            float   spellMovementSpeed = 15; // All range spells are currently 15 speed
            Vector3 sphereCastDir      = senses.PredictNextTargetPos(spellMovementSpeed);

            if (sphereCastDir == EnemySenses.ResetPlayerPos)
            {
                return(false);
            }

            float sphereCastDist = (sphereCastDir - transform.position).magnitude;

            sphereCastDir = (sphereCastDir - transform.position).normalized;

            RaycastHit hit;

            if (Physics.SphereCast(transform.position, 0.45f, sphereCastDir, out hit, sphereCastDist))
            {
                DaggerfallEntityBehaviour hitTarget = hit.transform.GetComponent <DaggerfallEntityBehaviour>();

                // Clear path to target
                if (hitTarget == senses.Target)
                {
                    return(true);
                }

                // Something in the way
                return(false);
            }

            // Clear path to predicted target position
            return(true);
        }