/// <summary> /// UESP states this power has no effect in classic. /// This implementation simply adds +5 damage to receiving entity on strike. /// Minor potency is better than nothing. Can be researched and improved later. /// </summary> void PotentVs(DaggerfallEnchantment enchantment, DaggerfallEntityBehaviour receiver) { // Check this is an enemy type EnemyEntity enemyEntity = null; if (receiver.EntityType == EntityTypes.EnemyMonster || receiver.EntityType == EntityTypes.EnemyClass) { enemyEntity = receiver.Entity as EnemyEntity; } else { return; } PotentVsTypes type = (PotentVsTypes)enchantment.param; if (type == PotentVsTypes.Undead && enemyEntity.MobileEnemy.Affinity == MobileAffinity.Undead || type == PotentVsTypes.Daedra && enemyEntity.MobileEnemy.Affinity == MobileAffinity.Daedra || type == PotentVsTypes.Humanoid && enemyEntity.MobileEnemy.Affinity == MobileAffinity.Human || type == PotentVsTypes.Animals && enemyEntity.MobileEnemy.Affinity == MobileAffinity.Animal) { receiver.Entity.CurrentHealth -= potentVsDamage; //Debug.LogFormat("Applied +{0} potent vs damage to {1}.", potentVsDamage, type.ToString()); } }
/// <summary> /// Regenerates health in a manner similar to career special. /// Classic will regenerate 15 health per hour, stacked per item with enchanement. /// </summary> void RegenerateHealth(DaggerfallEnchantment enchantment) { // This special only triggers once every regeneratePerRounds if (GameManager.Instance.EntityEffectBroker.MagicRoundsSinceStartup % regeneratePerRounds != 0) { return; } // Check for regenerate conditions bool regenerate = false; RegenerateTypes type = (RegenerateTypes)enchantment.param; switch (type) { case RegenerateTypes.AllTheTime: regenerate = true; break; case RegenerateTypes.InDarkness: regenerate = DaggerfallUnity.Instance.WorldTime.Now.IsNight || GameManager.Instance.PlayerEnterExit.WorldContext == WorldContext.Dungeon; break; case RegenerateTypes.InSunlight: regenerate = DaggerfallUnity.Instance.WorldTime.Now.IsDay && GameManager.Instance.PlayerEnterExit.WorldContext != WorldContext.Dungeon; break; } // Tick regeneration when conditions are right if (regenerate) { entityBehaviour.Entity.IncreaseHealth(regenerateAmount); } }
void IncreasedWeightAllowance(DaggerfallEnchantment enchantment) { switch ((IncreasedWeightAllowanceTypes)enchantment.param) { case IncreasedWeightAllowanceTypes.OneQuarterExtra: entityBehaviour.Entity.SetIncreasedWeightAllowanceMultiplier(0.25f); break; case IncreasedWeightAllowanceTypes.OneHalfExtra: entityBehaviour.Entity.SetIncreasedWeightAllowanceMultiplier(0.5f); break; } }
/// <summary> /// Adds +75 to maximum spell points when certain conditions are met. /// </summary> void ExtraSpellPoints(DaggerfallEnchantment enchantment) { const int maxIncrease = 75; bool apply = false; ExtraSpellPtTypes type = (ExtraSpellPtTypes)enchantment.param; // Seasonal params are 0-3 if (enchantment.param < 4) { DaggerfallDateTime.Seasons currentSeason = DaggerfallUnity.Instance.WorldTime.Now.SeasonValue; if (type == ExtraSpellPtTypes.DuringWinter && currentSeason == DaggerfallDateTime.Seasons.Winter || type == ExtraSpellPtTypes.DuringSpring && currentSeason == DaggerfallDateTime.Seasons.Spring || type == ExtraSpellPtTypes.DuringSummer && currentSeason == DaggerfallDateTime.Seasons.Summer || type == ExtraSpellPtTypes.DuringFall && currentSeason == DaggerfallDateTime.Seasons.Fall) { apply = true; } } // Moon params are 4-6 if (enchantment.param >= 4 && enchantment.param <= 6) { if (type == ExtraSpellPtTypes.DuringFullMoon && IsFullMoon() || type == ExtraSpellPtTypes.DuringHalfMoon && IsHalfMoon() || type == ExtraSpellPtTypes.DuringNewMoon && IsNewMoon()) { apply = true; } } // Nearby params are 7-10) // Core tracks nearby objects at low frequencies and nearby lookup is only checking a managed list using Linq if (enchantment.param > 6) { if (type == ExtraSpellPtTypes.NearUndead && IsNearUndead() || type == ExtraSpellPtTypes.NearDaedra && IsNearDaedra() || type == ExtraSpellPtTypes.NearHumanoids && IsNearHumanoids() || type == ExtraSpellPtTypes.NearAnimals && IsNearAnimals()) { apply = true; } } // Apply extra spell points when conditions are met if (apply) { entityBehaviour.Entity.ChangeMaxMagickaModifier(maxIncrease); } }
/// <summary> /// Testing classic yields the following results: /// - Only equipped items will receive repairs, items just stored in inventory are not repaired. /// - Repair will happen whether player is resting or just standing around while game time passes. /// - Repair does not happen when player is fast travelling (possibly game balance reasons?). /// The following assumptions have been made from observation: /// - Items are repaired 1 hit point every 4 minutes. Takes around 8-9 hours for a Dwarven Dagger to go from "battered" to "new" in classic and DFU with this timing. /// - Uncertain if not repairing during travel is intended or not - it doesn't seem to make sense for a passive enchantment that works all other times. /// - Not doing anything around this right now so that repair ticks work consistently with other passive enchantment effects. /// - Assuming only a single item is repaired per tick. Priority is based on equip order enumeration. /// </summary> void RepairItems(DaggerfallEnchantment enchantment) { // Only works on player entity if (entityBehaviour.EntityType != EntityTypes.Player) { return; } // This special only triggers once every conditionPerRounds if (GameManager.Instance.EntityEffectBroker.MagicRoundsSinceStartup % conditionPerRounds != 0) { return; } // Get equipped items DaggerfallUnityItem[] equippedItems = GameManager.Instance.PlayerEntity.ItemEquipTable.EquipTable; if (equippedItems == null || equippedItems.Length == 0) { return; } // Improve condition of a single items not at max condition for (int i = 0; i < equippedItems.Length; i++) { DaggerfallUnityItem item = equippedItems[i]; if (item != null && equippedItems[i].currentCondition < equippedItems[i].maxCondition) { // Do not repair magic items unless settings allow it if (item.IsEnchanted && !DaggerfallUnity.Settings.AllowMagicRepairs) { continue; } // Improve condition of item and exit item.currentCondition += conditionAmount; //Debug.LogFormat("Improved condition of item {0} by {1} points", item.LongName, conditionAmount); return; } } }
/// <summary> /// Vampirically drain health from target equal to damage delivered. /// Was not able to fully confirm this how effect works, but seems close from observation alone. /// Not sure if only base weapon should be delivered (e.g. exclude factors like critical strike). /// TODO: This will likely need more research and refinement. /// </summary> void VampiricEffectWhenStrikes(DaggerfallEnchantment enchantment, DaggerfallEntityBehaviour receiver, int damage) { // Must be correct vampiric effect type VampiricEffectTypes type = (VampiricEffectTypes)enchantment.param; if (type != VampiricEffectTypes.WhenStrikes) { return; } // Check this is an enemy type EnemyEntity enemyEntity = null; if (receiver.EntityType == EntityTypes.EnemyMonster || receiver.EntityType == EntityTypes.EnemyClass) { enemyEntity = receiver.Entity as EnemyEntity; } // Drain target entity by damage amount and heal this entity by same amount enemyEntity.CurrentHealth -= damage; entityBehaviour.Entity.CurrentHealth += damage; //Debug.LogFormat("Entity {0} drained {1} health by striking {2}", entityBehaviour.Entity.Name, damage, enemyEntity.Name); }
/// <summary> /// Vampirically drains health from nearby enemies. /// Classic seems to follow the 15 health per hour rule (or 1 health per 4 game minutes) at very close range. /// While exact range is unknown, testing in classic shows that player needs to be roughly within melee distance or no effect. /// </summary> void VampiricEffectRanged(DaggerfallEnchantment enchantment) { // Must be correct vampiric effect type VampiricEffectTypes type = (VampiricEffectTypes)enchantment.param; if (type != VampiricEffectTypes.AtRange) { return; } // This special only triggers once every regeneratePerRounds if (GameManager.Instance.EntityEffectBroker.MagicRoundsSinceStartup % regeneratePerRounds != 0) { return; } // Drain all enemies in range List <PlayerGPS.NearbyObject> nearby = GameManager.Instance.PlayerGPS.GetNearbyObjects(PlayerGPS.NearbyObjectFlags.Enemy, vampiricDrainRange); if (nearby != null && nearby.Count > 0) { foreach (PlayerGPS.NearbyObject enemy in nearby) { // Get entity behaviour from found object DaggerfallEntityBehaviour enemyBehaviour = (enemy.gameObject) ? enemy.gameObject.GetComponent <DaggerfallEntityBehaviour>() : null; if (!enemyBehaviour) { continue; } // Transfer health from remote entity to this one enemyBehaviour.Entity.CurrentHealth -= regenerateAmount; entityBehaviour.Entity.CurrentHealth += regenerateAmount; //Debug.LogFormat("Entity {0} drained {1} health from nearby {2}", entityBehaviour.Entity.Name, regenerateAmount, enemyBehaviour.Entity.Name); } } }