/// <summary> /// Constructor for the FSM setting plane affected, the initial position, shop position and final position /// </summary> /// <param name="plane">plane affected by this behavior</param> /// <param name="initialPosition">initial position</param> /// <param name="shotPosition">shot position</param> /// <param name="finalPosition">final position</param> public FSMEnemyGoShotAndLeave(EnemyEntity plane, Vector3 initialPosition, Vector3 shotPosition, Vector3 finalPosition) : base(plane) { // setting var initial position _initialPosition = initialPosition; // setting var shot position _shotPosition = shotPosition; // setting var final position _finalPosition = finalPosition; }
private void MeleeDamage() { if (entityBehaviour) { EnemyEntity entity = entityBehaviour.Entity as EnemyEntity; EnemyEntity targetEntity = null; if (entityBehaviour.Target != null && entityBehaviour.Target != GameManager.Instance.PlayerEntityBehaviour) { targetEntity = entityBehaviour.Target.Entity as EnemyEntity; } // Switch to hand-to-hand if enemy is immune to weapon Items.DaggerfallUnityItem weapon = entity.ItemEquipTable.GetItem(Items.EquipSlots.RightHand); if (weapon != null) { if (targetEntity != null && targetEntity.MobileEnemy.MinMetalToHit > (Items.WeaponMaterialTypes)weapon.NativeMaterialValue) { weapon = null; } } damage = 0; // Are we still in range and facing target? Then apply melee damage. if (entityBehaviour.Target != null && senses.DistanceToTarget < MeleeDistance && senses.TargetInSight) { if (entityBehaviour.Target == GameManager.Instance.PlayerEntityBehaviour) { damage = ApplyDamageToPlayer(weapon); } else { damage = ApplyDamageToNonPlayer(weapon); } } else { sounds.PlayMissSound(weapon); } if (DaggerfallUnity.Settings.CombatVoices && entity.EntityType == EntityTypes.EnemyClass && Random.Range(1, 101) <= 20) { Genders gender; if (mobile.Summary.Enemy.Gender == MobileGender.Male || entity.MobileEnemy.ID == (int)MobileTypes.Knight_CityWatch) { gender = Genders.Male; } else { gender = Genders.Female; } sounds.PlayCombatVoice(gender, true); } } }
private int ApplyDamageToPlayer(Items.DaggerfallUnityItem weapon) { const int doYouSurrenderToGuardsTextID = 15; EnemyEntity entity = entityBehaviour.Entity as EnemyEntity; PlayerEntity playerEntity = GameManager.Instance.PlayerEntity; // Calculate damage damage = FormulaHelper.CalculateAttackDamage(entity, playerEntity, weapon, -1); // Break any "normal power" concealment effects on enemy if (entity.IsMagicallyConcealedNormalPower && damage > 0) { EntityEffectManager.BreakNormalPowerConcealmentEffects(entityBehaviour); } // Tally player's dodging skill playerEntity.TallySkill(DFCareer.Skills.Dodging, 1); if (damage > 0) { if (entity.MobileEnemy.ID == (int)MobileTypes.Knight_CityWatch) { // If hit by a guard, lower reputation and show the surrender dialogue if (!playerEntity.HaveShownSurrenderToGuardsDialogue && playerEntity.CrimeCommitted != PlayerEntity.Crimes.None) { playerEntity.LowerRepForCrime(); DaggerfallMessageBox messageBox = new DaggerfallMessageBox(DaggerfallUI.UIManager); messageBox.SetTextTokens(DaggerfallUnity.Instance.TextProvider.GetRSCTokens(doYouSurrenderToGuardsTextID)); messageBox.ParentPanel.BackgroundColor = Color.clear; messageBox.AddButton(DaggerfallMessageBox.MessageBoxButtons.Yes); messageBox.AddButton(DaggerfallMessageBox.MessageBoxButtons.No); messageBox.OnButtonClick += SurrenderToGuardsDialogue_OnButtonClick; messageBox.Show(); playerEntity.HaveShownSurrenderToGuardsDialogue = true; } // Surrender dialogue has been shown and player refused to surrender // Guard damages player if player can survive hit, or if hit is fatal but guard rejects player's forced surrender else if (playerEntity.CurrentHealth > damage || !playerEntity.SurrenderToCityGuards(false)) { SendDamageToPlayer(); } } else { SendDamageToPlayer(); } } else { sounds.PlayMissSound(weapon); } return(damage); }
protected override void HitTarget(EnemyEntity target) { base.HitTarget(target); if (pierce > 0) { GetNewTarget(target.transform); } }
protected virtual void HitTarget(EnemyEntity target) { target.DamageEntity(damage); pierce--; if (pierce <= 0) { Destroy(gameObject); } }
public void AddEnemyEntity(Cell cell) { ICellEntity ent = new EnemyEntity(cell); entities[cell.GetCellIndexX(), cell.GetCellIndexY()] = ent; GameObject go = Instantiate(prefabs[2], new Vector3(cell.getCenterPosition().x, cell.getCenterPosition().y, -2), Quaternion.identity); ent.gameObject = go; }
void FixedUpdate() { if (Player != null) { Vector3 toPlayer = Player.transform.position - transform.position; directionToPlayer = toPlayer.normalized; distanceToPlayer = toPlayer.magnitude; playerInSight = CanSeePlayer(); if (playerInSight) { detectedPlayer = true; } // Classic stealth mechanics would be interfered with by hearing, so only enable // hearing if the enemy has detected the player. If player has been seen we can omit hearing. if (detectedPlayer && !playerInSight) { playerInEarshot = CanHearPlayer(); } else { playerInEarshot = false; } if ((playerInEarshot || playerInSight) && !hasEncounteredPlayer) { hasEncounteredPlayer = true; // Check appropriate language skill to see if player can pacify enemy DaggerfallEntityBehaviour entityBehaviour = GetComponent <DaggerfallEntityBehaviour>(); EnemyMotor motor = GetComponent <EnemyMotor>(); if (entityBehaviour && motor && (entityBehaviour.EntityType == EntityTypes.EnemyMonster || entityBehaviour.EntityType == EntityTypes.EnemyClass)) { EnemyEntity enemyEntity = entityBehaviour.Entity as EnemyEntity; DFCareer.Skills languageSkill = enemyEntity.GetLanguageSkill(); if (languageSkill != DFCareer.Skills.None) { PlayerEntity player = GameManager.Instance.PlayerEntity; if (FormulaHelper.CalculateEnemyPacification(player, languageSkill)) { motor.IsHostile = false; DaggerfallUI.AddHUDText(HardStrings.languagePacified.Replace("%e", enemyEntity.Name).Replace("%s", languageSkill.ToString()), 5); player.TallySkill(languageSkill, 3); // BCHG: increased skill uses from (assumed) 1 in classic on success to make raising language skills easier } else if (languageSkill != DFCareer.Skills.Etiquette && languageSkill != DFCareer.Skills.Streetwise) { player.TallySkill(languageSkill, 1); } } } } } }
public object GetSaveData() { if (!enemy) { return(null); } // Get entity behaviour DaggerfallEntityBehaviour entityBehaviour = enemy.GetComponent <DaggerfallEntityBehaviour>(); if (!entityBehaviour) { return(null); } // Create save data EnemyEntity entity = entityBehaviour.Entity as EnemyEntity; EnemyMotor motor = enemy.GetComponent <EnemyMotor>(); EnemySenses senses = enemy.GetComponent <EnemySenses>(); DaggerfallMobileUnit mobileEnemy = enemy.GetComponentInChildren <DaggerfallMobileUnit>(); EnemyData_v1 data = new EnemyData_v1(); data.loadID = LoadID; data.gameObjectName = entityBehaviour.gameObject.name; data.currentPosition = enemy.transform.position; data.localPosition = enemy.transform.localPosition; data.currentRotation = enemy.transform.rotation; data.worldContext = entity.WorldContext; data.worldCompensation = GameManager.Instance.StreamingWorld.WorldCompensation; data.entityType = entity.EntityType; data.careerName = entity.Career.Name; data.careerIndex = entity.CareerIndex; data.startingHealth = entity.MaxHealth; data.currentHealth = entity.CurrentHealth; data.currentFatigue = entity.CurrentFatigue; data.currentMagicka = entity.CurrentMagicka; data.isHostile = motor.IsHostile; data.hasEncounteredPlayer = senses.HasEncounteredPlayer; data.isDead = (entity.CurrentHealth <= 0) ? true : false; data.questSpawn = enemy.QuestSpawn; data.mobileGender = mobileEnemy.Summary.Enemy.Gender; data.items = entity.Items.SerializeItems(); data.equipTable = entity.ItemEquipTable.SerializeEquipTable(); data.instancedEffectBundles = GetComponent <EntityEffectManager>().GetInstancedBundlesSaveData(); data.alliedToPlayer = mobileEnemy.Summary.Enemy.Team == MobileTeams.PlayerAlly; // Add quest resource data if present QuestResourceBehaviour questResourceBehaviour = GetComponent <QuestResourceBehaviour>(); if (questResourceBehaviour) { data.questResource = questResourceBehaviour.GetSaveData(); } return(data); }
/// <summary> /// Method to create a new enemy by the prefab from parameter. When a enemy is created, the level is notified about it /// </summary> /// <param name="EnemyPrefab">prefab to be created</param> /// <returns> instance of the enemy created from prefab</returns> public static EnemyEntity CreateEnemy(EnemyEntity EnemyPrefab) { // creating the enemy EnemyEntity newEnemy = Instantiate <EnemyEntity>(EnemyPrefab); // notification for the level manager GameManager.Instance.LevelManager.EnemySpawned(newEnemy); // retruning the new enemy return(newEnemy); }
/// <summary> /// method that create the state machine for the enemy, with the data from enemy spawn info. /// get the data and create the stane machine /// /// the idea is have the data from the enemy spawn info of different way. So here depending how is the info, /// differents state machines will be created so the enemy will have differents behavior /// </summary> /// <param name="enemyBeingSpawn"></param> /// <param name="enemySpawnInfo"></param> /// <returns></returns> private FSMachine CreateEnemyBehaviorFSM(EnemyEntity enemyBeingSpawn, EnemySpawnInfo enemySpawnInfo) { // getting the data for the enemy state machine Vector3 initialWorldPosition = Camera.main.ViewportToWorldPoint(enemySpawnInfo.EnemyViewPortInitialPosition); Vector3 turnWorldPosition = Camera.main.ViewportToWorldPoint(enemySpawnInfo.EnemyViewPortTurnPosition); Vector3 finalWorldPosition = Camera.main.ViewportToWorldPoint(enemySpawnInfo.EnemyViewPortFinalPosition); // creating the FSM with the data from enemy spawn info return(new FSMEnemyGoShotAndLeave(enemyBeingSpawn, initialWorldPosition, turnWorldPosition, finalWorldPosition)); }
/// <summary> /// Determines if enemies are nearby. Uses include whether player is able to rest or not. /// Based on distance to nearest monster, and if monster can actually sense player. /// </summary> /// <param name="resting">Is player initiating or continuing rest?</param> /// <param name="includingPacified">Include pacified enemies in this test?</param> /// <returns>True if enemies are nearby.</returns> public bool AreEnemiesNearby(bool resting = false, bool includingPacified = false) { const float spawnDistance = 1024 * MeshReader.GlobalScale; const float restingDistance = 12f; bool areEnemiesNearby = false; DaggerfallEntityBehaviour[] entityBehaviours = FindObjectsOfType <DaggerfallEntityBehaviour>(); for (int i = 0; i < entityBehaviours.Length; i++) { DaggerfallEntityBehaviour entityBehaviour = entityBehaviours[i]; if (entityBehaviour.EntityType == EntityTypes.EnemyMonster || entityBehaviour.EntityType == EntityTypes.EnemyClass) { EnemySenses enemySenses = entityBehaviour.GetComponent <EnemySenses>(); if (enemySenses) { // Check if enemy can actively target player bool enemyCanSeePlayer = enemySenses.Target == Instance.PlayerEntityBehaviour && enemySenses.TargetInSight; // Allow for a shorter test distance if enemy is unaware of player while resting if (resting && !enemyCanSeePlayer && Vector3.Distance(entityBehaviour.transform.position, PlayerController.transform.position) > restingDistance) { continue; } // Can enemy see player or is close enough they would be spawned in classic? if (enemyCanSeePlayer || enemySenses.WouldBeSpawnedInClassic) { // Is it hostile or pacified? EnemyMotor enemyMotor = entityBehaviour.GetComponent <EnemyMotor>(); EnemyEntity enemyEntity = entityBehaviour.Entity as EnemyEntity; if (includingPacified || (enemyMotor.IsHostile && enemyEntity.MobileEnemy.Team != MobileTeams.PlayerAlly)) { areEnemiesNearby = true; break; } } } } } // Also check for enemy spawners that might emit an enemy FoeSpawner[] spawners = FindObjectsOfType <FoeSpawner>(); for (int i = 0; i < spawners.Length; i++) { // Is a spawner inside min distance? if (Vector3.Distance(spawners[i].transform.position, PlayerController.transform.position) < spawnDistance) { areEnemiesNearby = true; break; } } return(areEnemiesNearby); }
private void Start() { // Get references enemyMobile = GetComponent <DaggerfallMobileUnit>(); enemyEntityBehaviour = GetComponentInParent <DaggerfallEntityBehaviour>(); if (enemyEntityBehaviour && enemyEntityBehaviour.EntityType == EntityTypes.EnemyMonster) { enemyEntity = (EnemyEntity)enemyEntityBehaviour.Entity; enemySenses = enemyEntityBehaviour.GetComponent <EnemySenses>(); } }
public Effect Apply(EnemyEntity enemyEntity) { if (name == "None") { return(null); } Effect effect; OnApply(ref enemyEntity, out effect); return(effect); }
public void SpawnEnemy(TiledObject enemy) { switch (enemy.objectType) { case "Enemy1": EnemyEntity e = new EnemyEntity(_enemyTextures[0], _bulletTextures[0]); e.transform.position = enemy.position; addEntity(e); break; } }
public override void OnHit(Entity target, float damage) { EnemyEntity enemy = (EnemyEntity)target; // safe GameMaster.instance.stats.damageDealt += damage; foreach (Upgrade upgrade in upgrades) { upgrade.OnHit(enemy); } }
private void MeleeDamage() { if (entityBehaviour) { EnemyEntity entity = entityBehaviour.Entity as EnemyEntity; MobileEnemy enemy = entity.MobileEnemy; int damage = 0; // Are we still in range and facing player? Then apply melee damage. if (senses.DistanceToPlayer < MeleeDistance && senses.PlayerInSight) { // Calculate damage damage = Game.Formulas.FormulaHelper.CalculateWeaponDamage(entity, GameManager.Instance.PlayerEntity, null); if (damage > 0) { GameManager.Instance.PlayerObject.SendMessage("RemoveHealth", damage); } // Tally player's dodging skill GameManager.Instance.PlayerEntity.TallySkill(DFCareer.Skills.Dodging, 1); } if (sounds) { Items.DaggerfallUnityItem weapon = entity.ItemEquipTable.GetItem(Items.EquipSlots.RightHand); if (weapon == null) { weapon = entity.ItemEquipTable.GetItem(Items.EquipSlots.LeftHand); } if (damage > 0) { // TODO: Play hit and parry sounds on other AI characters once attacks against other AI are possible DaggerfallAudioSource dfAudioSource = GetComponent <DaggerfallAudioSource>(); if (dfAudioSource) { if (weapon == null) { dfAudioSource.PlayOneShot((int)SoundClips.Hit1 + UnityEngine.Random.Range(2, 4), 0, 1.1f); } else { dfAudioSource.PlayOneShot((int)SoundClips.Hit1 + UnityEngine.Random.Range(0, 5), 0, 1.1f); } } } else { sounds.PlayMissSound(weapon); } } } }
void TargetEnemy() { if (EnemiesIn.Count != 0) { Target = EnemiesIn[0]; CanShoot = true; } else { CanShoot = false; } }
public override PayloadCallbackResults?EnchantmentPayloadCallback(EnchantmentPayloadFlags context, EnchantmentParam?param = null, DaggerfallEntityBehaviour sourceEntity = null, DaggerfallEntityBehaviour targetEntity = null, DaggerfallUnityItem sourceItem = null, int sourceDamage = 0) { base.EnchantmentPayloadCallback(context, param, sourceEntity, targetEntity, sourceItem, sourceDamage); // Validate if (context != EnchantmentPayloadFlags.Strikes || targetEntity == null) { return(null); } // Change target enemy if (targetEntity.Entity is EnemyEntity) { // Get enemy entity - cannot have Wabbajack active already EnemyEntity enemy = (EnemyEntity)targetEntity.Entity; if (enemy == null || enemy.WabbajackActive) { return(null); } // Get new enemy career and transform MobileTypes enemyType = careerIDs[Random.Range(0, careerIDs.Length)]; if ((int)enemyType == enemy.CareerIndex) { enemyType = (MobileTypes)(((int)enemyType + 1) % careerIDs.Length); } Transform parentTransform = targetEntity.gameObject.transform.parent; // Do not disable enemy if in use by the quest system QuestResourceBehaviour questResourceBehaviour = targetEntity.GetComponent <QuestResourceBehaviour>(); if (questResourceBehaviour && !questResourceBehaviour.IsFoeDead) { return(null); } string[] enemyNames = TextManager.Instance.GetLocalizedTextList("enemyNames"); if (enemyNames == null) { throw new System.Exception("enemyNames array text not found"); } // Switch entity targetEntity.gameObject.SetActive(false); GameObject gameObject = GameObjectHelper.CreateEnemy(enemyNames[(int)enemyType], enemyType, targetEntity.transform.localPosition, MobileGender.Unspecified, parentTransform); DaggerfallEntityBehaviour newEnemyBehaviour = gameObject.GetComponent <DaggerfallEntityBehaviour>(); EnemyEntity newEnemy = (EnemyEntity)newEnemyBehaviour.Entity; newEnemy.WabbajackActive = true; newEnemy.CurrentHealth -= enemy.MaxHealth - enemy.CurrentHealth; // carry over damage to new monster } return(null); }
private void EntityBehaviour_OnSetEntity(DaggerfallEntity oldEntity, DaggerfallEntity newEntity) { if (oldEntity != null) { oldEntity.OnDeath -= EnemyEntity_OnDeath; } if (newEntity != null) { enemyEntity = newEntity as EnemyEntity; enemyEntity.OnDeath += EnemyEntity_OnDeath;; } }
public static T CreateCopyOf <T>(string prototypeID) where T : class { if (typeof(T).Equals(typeof(GameObject))) { if (_gameObjectPrototypes.ContainsKey(prototypeID)) { BaseEntity entity = _gameObjectPrototypes[prototypeID].Entity; GameObject obj = null; if (entity.GetType().Equals(typeof(BulletEntity))) { BulletEntity bulletEntity = entity as BulletEntity; obj = Factory.Build <GameObject>((GraphicModule)_gameObjectPrototypes[prototypeID].Graphic.Clone(), (BulletEntity)bulletEntity.Clone()); } if (entity.GetType().Equals(typeof(EnemyEntity))) { EnemyEntity bulletEntity = entity as EnemyEntity; obj = Factory.Build <GameObject>((GraphicModule)_gameObjectPrototypes[prototypeID].Graphic.Clone(), (EnemyEntity)bulletEntity.Clone()); } if (entity.GetType().Equals(typeof(PlayerEntity))) { PlayerEntity bulletEntity = entity as PlayerEntity; obj = Factory.Build <GameObject>((GraphicModule)_gameObjectPrototypes[prototypeID].Graphic.Clone(), (PlayerEntity)bulletEntity.Clone()); } return(obj as T); } } if (typeof(T).Equals(typeof(GraphicModule))) { if (_graphicModulePrototypes.ContainsKey(prototypeID)) { GraphicModule graphic = _graphicModulePrototypes[prototypeID]; GameObject obj = null; if (graphic.GetType().Equals(typeof(TexturedGraphicModule))) { return((TexturedGraphicModule)_graphicModulePrototypes[prototypeID].Clone() as T); } if (graphic.GetType().Equals(typeof(GraphicModule))) { return((GraphicModule)_graphicModulePrototypes[prototypeID].Clone() as T); } } } return(null); }
/// <summary> /// method called when a enemy should be spawn, /// -create the enemy with the enemy factory /// -call the method "CreateEnemyBehaviorFSM" for create the enemy state machine with the spawn info data /// -set the FSM to the enemy /// -add the FSM to the list /// -remove the spawn info from the level spawn info /// </summary> private void processEnemyInfo() { // create the enemy EnemyEntity enemyBeingSpawn = FactoryEnemies.CreateEnemy(_enemiesSpawnInfo[0].EnemyPrefab); // create the FSM for the enemy with the spawn data FSMachine machine = CreateEnemyBehaviorFSM(enemyBeingSpawn, _enemiesSpawnInfo[0]); // set the behavior var for the enemy enemyBeingSpawn.GetComponentInChildren <EnemyBehavior>().Behavior = machine; // adding the enemy to the FSM AddNewEnemyFSM(machine); // remove for the info _enemiesSpawnInfo.RemoveAt(0); }
protected override void Update() { //Do BaseAttacker's Update first base.Update(); //Update bullet UpdateBullet(); //If player inputs the shoot key if (Input.GetMouseButton(0)) { //If player can attack //And cursor is locked to center if (CanAttack && Cursor.lockState == CursorLockMode.Locked) { //Set cooltime SetAttackCooltime(); //Show the bullet shot ShowBullet(); //Play audio fireAudio.Stop(); fireAudio.Play(); //Do a raycast from bullet source RaycastHit hit; if (Physics.Raycast(myCamera.ScreenPointToRay(new Vector3(Screen.width * 0.5f, Screen.height * 0.5f, 0f)), out hit, attackRange, targetLayer.value)) { //Try to get the enemy entity object EnemyEntity enemy = hit.collider.GetComponent <EnemyEntity>(); //If it is a valid enemy if (enemy != null) { //Damage the enemy enemy.DoDamage(damage); } } } } //If player presses the flashlight toggle key if (Input.GetKeyDown(KeyCode.Z)) { //Toggle light enable state flashlight.enabled = !flashlight.enabled; } }
// Player Version public void LoadBattleScene(EnemyEntity enemyEntity) { gridCanvas.enabled = false; gridDirectionalLight.enabled = false; gridSelector.GetSelectedPlayer().hasAttacked = true; targetedEnemy = enemyEntity; if (SceneManager.sceneCount == 1) { SceneManager.sceneLoaded += OnSceneLoaded; SceneManager.LoadScene("BattleScene", LoadSceneMode.Additive); } }
void defend() { var center = GetCenter(); var data = properties.UpgradeData; if (lockOnEnemy != null) { if (lockOnEnemy.IsRemoved) { lockOnEnemy = null; return; } var distance = Vector2.DistanceSquared(center, lockOnEnemy.Position); var min = properties.MinRange * properties.MinRange; var max = data.Range * data.Range; if (distance < min || distance > max) { lockOnEnemy = null; return; } var barrel = position + properties.GridOffset + properties.BarrelOffset; var enemy = lockOnEnemy.GetAttackOffset(); var angle = (float)Math.Atan2(barrel.Y - enemy.Y, barrel.X - enemy.X) + MathHelper.ToRadians(90); setTowerAngle(angle); shootBullet(enemy); } else { var enemies = world.GetEntitiesInRange( center, data.Range, EntityType.AI); if (enemies.Count == 0) { return; } lockOnEnemy = (EnemyEntity)enemies[0]; } }
void Update() { if (GameManager.Instance.DisableAI) { return; } // If a melee attack has reached the damage frame we can run a melee attempt if (mobile.DoMeleeDamage) { MeleeDamage(); mobile.DoMeleeDamage = false; } // If a bow attack has reached the shoot frame we can shoot an arrow else if (mobile.ShootArrow) { ShootBow(); mobile.ShootArrow = false; DaggerfallAudioSource dfAudioSource = GetComponent <DaggerfallAudioSource>(); if (dfAudioSource) { dfAudioSource.PlayOneShot((int)SoundClips.ArrowShoot, 1, 1.0f); } } // Countdown to next melee attack MeleeTimer -= Time.deltaTime; if (MeleeTimer < 0) { MeleeTimer = 0; } EnemyEntity entity = entityBehaviour.Entity as EnemyEntity; int speed = entity.Stats.LiveSpeed; // Note: Speed comparison here is reversed from classic. Classic's way makes fewer attack // attempts at higher speeds, so it seems backwards. if (GameManager.ClassicUpdate && (DFRandom.rand() % speed >= (speed >> 3) + 6 && MeleeTimer == 0)) { if (!MeleeAnimation()) { return; } ResetMeleeTimer(); } }
public override PayloadCallbackResults?EnchantmentPayloadCallback(EnchantmentPayloadFlags context, EnchantmentParam?param = null, DaggerfallEntityBehaviour sourceEntity = null, DaggerfallEntityBehaviour targetEntity = null, DaggerfallUnityItem sourceItem = null, int sourceDamage = 0) { base.EnchantmentPayloadCallback(context, param, sourceEntity, targetEntity, sourceItem, sourceDamage); // Must be Used payload if (context != EnchantmentPayloadFlags.Used) { return(null); } // Must have nearby non-allied enemies List <PlayerGPS.NearbyObject> nearby = GameManager.Instance.PlayerGPS.GetNearbyObjects(PlayerGPS.NearbyObjectFlags.Enemy, enemyRange) .Where(x => ((EnemyEntity)x.gameObject.GetComponent <DaggerfallEntityBehaviour>().Entity).Team != MobileTeams.PlayerAlly).ToList(); MobileTypes nearestType; if (nearby.Count == 0) { ShowSummonFailMessage(); return(null); } else { // Use nearest enemy for cloning PlayerGPS.NearbyObject nearest = nearby[0]; foreach (PlayerGPS.NearbyObject nearbyObject in nearby.Skip(1)) { if (nearbyObject.distance < nearest.distance) { nearest = nearbyObject; } } EnemyEntity enemy = (EnemyEntity)nearest.gameObject.GetComponent <DaggerfallEntityBehaviour>().Entity; if (enemy.Team == MobileTeams.PlayerAlly) { ShowSummonFailMessage(); return(null); } nearestType = (MobileTypes)enemy.MobileEnemy.ID; } // Spawn clone GameObjectHelper.CreateFoeSpawner(foeType: nearestType, spawnCount: 1, alliedToPlayer: true); // Durability loss for this effect return(new PayloadCallbackResults() { durabilityLoss = 100, }); }
public NearbyObjectFlags GetEntityFlags(DaggerfallEntityBehaviour entity) { NearbyObjectFlags result = NearbyObjectFlags.None; if (!entity) { return(result); } if (entity.EntityType == EntityTypes.EnemyClass || entity.EntityType == EntityTypes.EnemyMonster) { result |= NearbyObjectFlags.Enemy; EnemyEntity enemyEntity = entity.Entity as EnemyEntity; switch (enemyEntity.MobileEnemy.Affinity) { case MobileAffinity.Undead: result |= NearbyObjectFlags.Undead; break; case MobileAffinity.Daedra: result |= NearbyObjectFlags.Daedra; break; case MobileAffinity.Human: result |= NearbyObjectFlags.Humanoid; break; case MobileAffinity.Animal: result |= NearbyObjectFlags.Animal; break; } } else if (entity.EntityType == EntityTypes.CivilianNPC) { result |= NearbyObjectFlags.Humanoid; } // Set magic flag // Not completely sure what conditions should flag entity for "detect magic" // Currently just assuming entity has active effects EntityEffectManager manager = entity.GetComponent <EntityEffectManager>(); if (manager && manager.EffectCount > 0) { result |= NearbyObjectFlags.Magic; } return(result); }
public void RestoreSaveData(object dataIn) { if (!enemy) { return; } EnemyData_v1 data = (EnemyData_v1)dataIn; if (data.loadID != LoadID) { return; } DaggerfallEntityBehaviour entityBehaviour = enemy.GetComponent <DaggerfallEntityBehaviour>(); EnemySenses senses = enemy.GetComponent <EnemySenses>(); EnemyMotor motor = enemy.GetComponent <EnemyMotor>(); EnemyEntity entity = entityBehaviour.Entity as EnemyEntity; // Quiesce entity during state restore entity.Quiesce = true; // Restore enemy career or class if different if (entity.EntityType != data.entityType || entity.CareerIndex != data.careerIndex) { SetupDemoEnemy setupEnemy = enemy.GetComponent <SetupDemoEnemy>(); setupEnemy.ApplyEnemySettings(data.entityType, data.careerIndex, data.isHostile); setupEnemy.AlignToGround(); } // Restore enemy position enemy.transform.position = data.currentPosition; enemy.transform.rotation = data.currentRotation; entity.MaxHealth = data.startingHealth; entity.CurrentHealth = data.currentHealth; entity.CurrentFatigue = data.currentFatigue; entity.CurrentMagicka = data.currentMagicka; motor.IsHostile = data.isHostile; senses.HasEncounteredPlayer = true; // Disable dead enemies if (data.isDead) { entityBehaviour.gameObject.SetActive(false); } // Resume entity entity.Quiesce = false; }
public object GetSaveData() { if (!enemy) { return(null); } // Get entity behaviour DaggerfallEntityBehaviour entityBehaviour = enemy.GetComponent <DaggerfallEntityBehaviour>(); if (!entityBehaviour) { return(null); } // Create save data EnemyEntity entity = entityBehaviour.Entity as EnemyEntity; EnemyMotor motor = enemy.GetComponent <EnemyMotor>(); DaggerfallMobileUnit mobileEnemy = enemy.GetComponentInChildren <DaggerfallMobileUnit>(); EnemyData_v1 data = new EnemyData_v1(); data.loadID = LoadID; data.gameObjectName = entityBehaviour.gameObject.name; data.currentPosition = enemy.transform.position; data.currentRotation = enemy.transform.rotation; data.entityType = entity.EntityType; data.careerName = entity.Career.Name; data.careerIndex = entity.CareerIndex; data.startingHealth = entity.MaxHealth; data.currentHealth = entity.CurrentHealth; data.currentFatigue = entity.CurrentFatigue; data.currentMagicka = entity.CurrentMagicka; data.isHostile = motor.IsHostile; data.isDead = (entity.CurrentHealth <= 0) ? true : false; data.questSpawn = enemy.QuestSpawn; data.mobileGender = mobileEnemy.Summary.Enemy.Gender; data.items = entity.Items.SerializeItems(); data.equipTable = entity.ItemEquipTable.SerializeEquipTable(); // Add quest resource data if present QuestResourceBehaviour questResourceBehaviour = GetComponent <QuestResourceBehaviour>(); if (questResourceBehaviour) { data.questResource = questResourceBehaviour.GetSaveData(); } return(data); }
void FixedUpdate() { const int speedFloor = 8; // Unable to attack if AI disabled or paralyzed if (GameManager.Instance.DisableAI || entityBehaviour.Entity.IsParalyzed) { return; } // Unable to attack when playing certain oneshot anims if (mobile && mobile.IsPlayingOneShot() && mobile.OneShotPauseActionsWhilePlaying()) { return; } // Countdown to next melee attack MeleeTimer -= Time.deltaTime; if (MeleeTimer < 0) { MeleeTimer = 0; } // Get entity speed and enforce a lower limit so Drain Speed does not prevent attack ever firing EnemyEntity entity = entityBehaviour.Entity as EnemyEntity; int speed = entity.Stats.LiveSpeed; if (speed < speedFloor) { speed = speedFloor; } // Slow down enemy frame rate based on floored speed value // If enemy is still at maximum speed then divisor is 1 and will experience no change to frame rate mobile.FrameSpeedDivisor = entity.Stats.PermanentSpeed / speed; // Note: Speed comparison here is reversed from classic. Classic's way makes fewer attack // attempts at higher speeds, so it seems backwards. if (GameManager.ClassicUpdate && (DFRandom.rand() % speed >= (speed >> 3) + 6 && MeleeTimer == 0)) { if (!MeleeAnimation()) { return; } ResetMeleeTimer(); } }