/// <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; }
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); } }
/// <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); }
/// <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; } }
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(); }
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(); }
/// <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); }