// Check if raycast hit an action door private bool ActionDoorCheck(RaycastHit hitInfo, out DaggerfallActionDoor door) { door = hitInfo.transform.GetComponent<DaggerfallActionDoor>(); if (door == null) return false; return true; }
private bool CanSeePlayer() { bool seen = false; actionDoor = null; distanceToActionDoor = float.MaxValue; if (distanceToPlayer < SightRadius + mobile.Summary.Enemy.SightModifier) { // Check if player in field of view float angle = Vector3.Angle(directionToPlayer, transform.forward); if (angle < FieldOfView * 0.5f) { // Check if line of sight to player RaycastHit hit; Ray ray = new Ray(transform.position, directionToPlayer); if (Physics.Raycast(ray, out hit, SightRadius)) { // Check if hit was player if (hit.transform.gameObject == player) { seen = true; lastKnownPlayerPos = player.transform.position; } // Check if hit was an action door DaggerfallActionDoor door = hit.transform.gameObject.GetComponent<DaggerfallActionDoor>(); if (door != null) { if (!door.IsLocked && !door.IsMagicallyHeld) { actionDoor = door; distanceToActionDoor = Vector3.Distance(transform.position, actionDoor.transform.position); } } } } } return seen; }
void Awake() { actionDoor = GetComponent<DaggerfallActionDoor>(); if (!actionDoor) throw new Exception("DaggerfallActionDoor not found."); }
// Returns true if hit an enemy entity public bool WeaponDamage(RaycastHit hit, Vector3 direction, Collider arrowHitCollider = null, bool arrowHit = false) { DaggerfallUnityItem strikingWeapon = usingRightHand ? currentRightHandWeapon : currentLeftHandWeapon; if (arrowHit) { strikingWeapon = lastBowUsed; } else { // Check if hit has an DaggerfallAction component DaggerfallAction action = hit.transform.gameObject.GetComponent <DaggerfallAction>(); if (action) { action.Receive(player, DaggerfallAction.TriggerTypes.Attack); } // Check if hit has an DaggerfallActionDoor component DaggerfallActionDoor actionDoor = hit.transform.gameObject.GetComponent <DaggerfallActionDoor>(); if (actionDoor) { actionDoor.AttemptBash(true); return(false); } // Check if player hit a static exterior door if (GameManager.Instance.PlayerActivate.AttemptExteriorDoorBash(hit)) { return(false); } } // Set up for use below Transform hitTransform = arrowHit ? arrowHitCollider.gameObject.transform : hit.transform; Vector3 impactPosition = arrowHit ? hitTransform.position : hit.point; DaggerfallEntityBehaviour entityBehaviour = hitTransform.GetComponent <DaggerfallEntityBehaviour>(); DaggerfallMobileUnit entityMobileUnit = hitTransform.GetComponentInChildren <DaggerfallMobileUnit>(); EnemyMotor enemyMotor = hitTransform.GetComponent <EnemyMotor>(); EnemySounds enemySounds = hitTransform.GetComponent <EnemySounds>(); // Check if hit a mobile NPC MobilePersonNPC mobileNpc = hitTransform.GetComponent <MobilePersonNPC>(); if (mobileNpc) { if (!mobileNpc.Billboard.IsUsingGuardTexture) { EnemyBlood blood = hitTransform.GetComponent <EnemyBlood>(); if (blood) { blood.ShowBloodSplash(0, impactPosition); } mobileNpc.Motor.gameObject.SetActive(false); playerEntity.TallyCrimeGuildRequirements(false, 5); playerEntity.CrimeCommitted = PlayerEntity.Crimes.Murder; playerEntity.SpawnCityGuards(true); // Allow custom race handling of weapon hit against mobile NPCs, e.g. vampire feeding or lycanthrope killing if (entityBehaviour) { entityBehaviour.Entity.SetHealth(0); RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect(); if (racialOverride != null) { racialOverride.OnWeaponHitEntity(GameManager.Instance.PlayerEntity, entityBehaviour.Entity); } } } else { playerEntity.CrimeCommitted = PlayerEntity.Crimes.Assault; GameObject guard = playerEntity.SpawnCityGuard(mobileNpc.transform.position, mobileNpc.transform.forward); entityBehaviour = guard.GetComponent <DaggerfallEntityBehaviour>(); entityMobileUnit = guard.GetComponentInChildren <DaggerfallMobileUnit>(); enemyMotor = guard.GetComponent <EnemyMotor>(); enemySounds = guard.GetComponent <EnemySounds>(); } mobileNpc.Motor.gameObject.SetActive(false); } // Check if hit an entity and remove health if (entityBehaviour) { if (entityBehaviour.EntityType == EntityTypes.EnemyMonster || entityBehaviour.EntityType == EntityTypes.EnemyClass) { EnemyEntity enemyEntity = entityBehaviour.Entity as EnemyEntity; // Calculate damage int animTime = (int)(ScreenWeapon.GetAnimTime() * 1000); // Get animation time, converted to ms. int damage = FormulaHelper.CalculateAttackDamage(playerEntity, enemyEntity, entityMobileUnit.Summary.AnimStateRecord, animTime, strikingWeapon); // Break any "normal power" concealment effects on player if (playerEntity.IsMagicallyConcealedNormalPower && damage > 0) { EntityEffectManager.BreakNormalPowerConcealmentEffects(GameManager.Instance.PlayerEntityBehaviour); } // Play arrow sound and add arrow to target's inventory if (arrowHit) { DaggerfallUnityItem arrow = ItemBuilder.CreateItem(ItemGroups.Weapons, (int)Weapons.Arrow); enemyEntity.Items.AddItem(arrow); } // Play hit sound and trigger blood splash at hit point if (damage > 0) { if (usingRightHand) { enemySounds.PlayHitSound(currentRightHandWeapon); } else { enemySounds.PlayHitSound(currentLeftHandWeapon); } EnemyBlood blood = hitTransform.GetComponent <EnemyBlood>(); if (blood) { blood.ShowBloodSplash(enemyEntity.MobileEnemy.BloodIndex, impactPosition); } // Knock back enemy based on damage and enemy weight if (enemyMotor) { if (enemyMotor.KnockbackSpeed <= (5 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10)) && entityBehaviour.EntityType == EntityTypes.EnemyClass || enemyEntity.MobileEnemy.Weight > 0) { float enemyWeight = enemyEntity.GetWeightInClassicUnits(); float tenTimesDamage = damage * 10; float twoTimesDamage = damage * 2; float knockBackAmount = ((tenTimesDamage - enemyWeight) * 256) / (enemyWeight + tenTimesDamage) * twoTimesDamage; float KnockbackSpeed = (tenTimesDamage / enemyWeight) * (twoTimesDamage - (knockBackAmount / 256)); KnockbackSpeed /= (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10); if (KnockbackSpeed < (15 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10))) { KnockbackSpeed = (15 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10)); } enemyMotor.KnockbackSpeed = KnockbackSpeed; enemyMotor.KnockbackDirection = direction; } } if (DaggerfallUnity.Settings.CombatVoices && entityBehaviour.EntityType == EntityTypes.EnemyClass && Dice100.SuccessRoll(40)) { Genders gender; if (entityMobileUnit.Summary.Enemy.Gender == MobileGender.Male || enemyEntity.MobileEnemy.ID == (int)MobileTypes.Knight_CityWatch) { gender = Genders.Male; } else { gender = Genders.Female; } bool heavyDamage = damage >= enemyEntity.MaxHealth / 4; enemySounds.PlayCombatVoice(gender, false, heavyDamage); } } else { if ((!arrowHit && !enemyEntity.MobileEnemy.ParrySounds) || strikingWeapon == null) { ScreenWeapon.PlaySwingSound(); } else if (enemyEntity.MobileEnemy.ParrySounds) { enemySounds.PlayParrySound(); } } // Handle weapon striking enchantments - this could change damage amount if (strikingWeapon != null && strikingWeapon.IsEnchanted) { EntityEffectManager effectManager = GetComponent <EntityEffectManager>(); if (effectManager) { damage = effectManager.DoItemEnchantmentPayloads(EnchantmentPayloadFlags.Strikes, strikingWeapon, GameManager.Instance.PlayerEntity.Items, enemyEntity.EntityBehaviour, damage); } strikingWeapon.RaiseOnWeaponStrikeEvent(entityBehaviour, damage); } // Remove health enemyEntity.DecreaseHealth(damage); // Make foe attack their aggressor // Currently this is just player, but should be expanded later // for a wider variety of behaviours if (enemyMotor) { // Make enemies in an area aggressive if player attacked a non-hostile one. if (!enemyMotor.IsHostile) { GameManager.Instance.MakeEnemiesHostile(); } enemyMotor.MakeEnemyHostileToAttacker(GameManager.Instance.PlayerEntityBehaviour); } if (enemyEntity.MobileEnemy.ID == (int)MobileTypes.Knight_CityWatch && enemyEntity.CurrentHealth <= 0) { playerEntity.TallyCrimeGuildRequirements(false, 1); playerEntity.CrimeCommitted = PlayerEntity.Crimes.Murder; } // Allow custom race handling of weapon hit against enemies, e.g. vampire feeding or lycanthrope killing RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect(); if (racialOverride != null) { racialOverride.OnWeaponHitEntity(GameManager.Instance.PlayerEntity, entityBehaviour.Entity); } return(true); } } return(false); }
private void WeaponDamage(FPSWeapon weapon, out bool hitEnemy) { hitEnemy = false; if (!mainCamera || !weapon) { return; } // Fire ray along player facing using weapon range RaycastHit hit; Ray ray = new Ray(mainCamera.transform.position, mainCamera.transform.forward); if (Physics.SphereCast(ray, SphereCastRadius, out hit, weapon.Reach - SphereCastRadius)) { // Check if hit has an DaggerfallAction component DaggerfallAction action = hit.transform.gameObject.GetComponent <DaggerfallAction>(); if (action) { action.Receive(player, DaggerfallAction.TriggerTypes.Attack); } // Check if hit has an DaggerfallActionDoor component DaggerfallActionDoor actionDoor = hit.transform.gameObject.GetComponent <DaggerfallActionDoor>(); if (actionDoor) { actionDoor.AttemptBash(); return; } // Check if hit an entity and remove health DaggerfallEntityBehaviour entityBehaviour = hit.transform.GetComponent <DaggerfallEntityBehaviour>(); DaggerfallMobileUnit entityMobileUnit = hit.transform.GetComponentInChildren <DaggerfallMobileUnit>(); if (entityBehaviour) { if (entityBehaviour.EntityType == EntityTypes.EnemyMonster || entityBehaviour.EntityType == EntityTypes.EnemyClass) { EnemyEntity enemyEntity = entityBehaviour.Entity as EnemyEntity; // Calculate damage int damage; if (usingRightHand) { damage = FormulaHelper.CalculateAttackDamage(playerEntity, enemyEntity, (int)(EquipSlots.RightHand), entityMobileUnit.Summary.AnimStateRecord); } else { damage = FormulaHelper.CalculateAttackDamage(playerEntity, enemyEntity, (int)(EquipSlots.LeftHand), entityMobileUnit.Summary.AnimStateRecord); } EnemyMotor enemyMotor = hit.transform.GetComponent <EnemyMotor>(); EnemySounds enemySounds = hit.transform.GetComponent <EnemySounds>(); // Play arrow sound and add arrow to target's inventory if (weapon.WeaponType == WeaponTypes.Bow) { enemySounds.PlayArrowSound(); DaggerfallUnityItem arrow = ItemBuilder.CreateItem(ItemGroups.Weapons, (int)Weapons.Arrow); enemyEntity.Items.AddItem(arrow); } // Play hit sound and trigger blood splash at hit point if (damage > 0) { if (usingRightHand) { enemySounds.PlayHitSound(currentRightHandWeapon); } else { enemySounds.PlayHitSound(currentLeftHandWeapon); } EnemyBlood blood = hit.transform.GetComponent <EnemyBlood>(); if (blood) { blood.ShowBloodSplash(enemyEntity.MobileEnemy.BloodIndex, hit.point); } // Knock back enemy based on damage and enemy weight if (enemyMotor) { if (enemyMotor.KnockBackSpeed <= (5 / (PlayerMotor.classicToUnitySpeedUnitRatio / 10)) && entityBehaviour.EntityType == EntityTypes.EnemyClass || enemyEntity.MobileEnemy.Weight > 0) { float enemyWeight = enemyEntity.GetWeightInClassicUnits(); float tenTimesDamage = damage * 10; float twoTimesDamage = damage * 2; float knockBackAmount = ((tenTimesDamage - enemyWeight) * 256) / (enemyWeight + tenTimesDamage) * twoTimesDamage; float knockBackSpeed = (tenTimesDamage / enemyWeight) * (twoTimesDamage - (knockBackAmount / 256)); knockBackSpeed /= (PlayerMotor.classicToUnitySpeedUnitRatio / 10); if (knockBackSpeed < (15 / (PlayerMotor.classicToUnitySpeedUnitRatio / 10))) { knockBackSpeed = (15 / (PlayerMotor.classicToUnitySpeedUnitRatio / 10)); } enemyMotor.KnockBackSpeed = knockBackSpeed; enemyMotor.KnockBackDirection = mainCamera.transform.forward; } } } else { if ((weapon.WeaponType != WeaponTypes.Bow && !enemyEntity.MobileEnemy.ParrySounds) || weapon.WeaponType == WeaponTypes.Melee) { weapon.PlaySwingSound(); } else if (enemyEntity.MobileEnemy.ParrySounds) { enemySounds.PlayParrySound(); } } // Remove health enemyEntity.DecreaseHealth(damage); hitEnemy = true; // Make foe attack their aggressor // Currently this is just player, but should be expanded later // for a wider variety of behaviours if (enemyMotor) { // Make enemies in an area aggressive if player attacked a non-hostile one. if (!enemyMotor.IsHostile) { GameManager.Instance.MakeEnemiesHostile(); } enemyMotor.MakeEnemyHostileToPlayer(gameObject); } } } // Check if hit a mobile NPC MobilePersonNPC mobileNpc = hit.transform.GetComponent <MobilePersonNPC>(); if (mobileNpc) { // TODO: Create blood splash. mobileNpc.Motor.gameObject.SetActive(false); //GameManager.Instance.PlayerEntity.TallyCrimeGuildRequirements(false, 5); } } }
private void WeaponDamage(FPSWeapon weapon, out bool hitEnemy) { hitEnemy = false; if (!mainCamera || !weapon) { return; } // Fire ray along player facing using weapon range RaycastHit hit; Ray ray = new Ray(mainCamera.transform.position, mainCamera.transform.forward); if (Physics.SphereCast(ray, SphereCastRadius, out hit, weapon.Reach - SphereCastRadius)) { // Check if hit has an DaggerfallAction component DaggerfallAction action = hit.transform.gameObject.GetComponent <DaggerfallAction>(); if (action) { action.Receive(player, DaggerfallAction.TriggerTypes.Attack); } // Check if hit has an DaggerfallActionDoor component DaggerfallActionDoor actionDoor = hit.transform.gameObject.GetComponent <DaggerfallActionDoor>(); if (actionDoor) { actionDoor.AttemptBash(); return; } // Check if hit an entity and remove health DaggerfallEntityBehaviour entityBehaviour = hit.transform.GetComponent <DaggerfallEntityBehaviour>(); if (entityBehaviour) { if (entityBehaviour.EntityType == EntityTypes.EnemyMonster || entityBehaviour.EntityType == EntityTypes.EnemyClass) { EnemyEntity enemyEntity = entityBehaviour.Entity as EnemyEntity; // Calculate damage int damage = FormulaHelper.CalculateWeaponDamage(playerEntity, enemyEntity, weapon); // Play hit sound and trigger blood splash at hit point if (damage > 0) { weapon.PlayHitSound(); EnemyBlood blood = hit.transform.GetComponent <EnemyBlood>(); if (blood) { blood.ShowBloodSplash(enemyEntity.MobileEnemy.BloodIndex, hit.point); } } else { if (!enemyEntity.MobileEnemy.ParrySounds || weapon.WeaponType == WeaponTypes.Melee) { weapon.PlaySwingSound(); } else { weapon.PlayParrySound(); } } // Remove health enemyEntity.DecreaseHealth(damage); hitEnemy = true; } } } }
private void Awake() { actionDoor = GetComponentInParent <DaggerfallActionDoor>(); parent = GetComponentInParent <SecretDoorAudioParent>(); }
private void WeaponDamage(FPSWeapon weapon, out bool hitEnemy) { hitEnemy = false; if (!mainCamera || !weapon) { return; } // Fire ray along player facing using weapon range RaycastHit hit; Ray ray = new Ray(mainCamera.transform.position, mainCamera.transform.forward); if (Physics.SphereCast(ray, SphereCastRadius, out hit, weapon.Reach - SphereCastRadius)) { // Check if hit has an DaggerfallAction component DaggerfallAction action = hit.transform.gameObject.GetComponent <DaggerfallAction>(); if (action) { action.Receive(player, DaggerfallAction.TriggerTypes.Attack); } // Check if hit has an DaggerfallActionDoor component DaggerfallActionDoor actionDoor = hit.transform.gameObject.GetComponent <DaggerfallActionDoor>(); if (actionDoor) { actionDoor.AttemptBash(); return; } // Check if hit an entity and remove health DaggerfallEntityBehaviour entityBehaviour = hit.transform.GetComponent <DaggerfallEntityBehaviour>(); if (entityBehaviour) { if (entityBehaviour.EntityType == EntityTypes.EnemyMonster || entityBehaviour.EntityType == EntityTypes.EnemyClass) { EnemyEntity enemyEntity = entityBehaviour.Entity as EnemyEntity; // Calculate damage int damage = FormulaHelper.CalculateWeaponDamage(playerEntity, enemyEntity, weapon); // Play hit sound and trigger blood splash at hit point if (damage > 0) { weapon.PlayHitSound(); EnemyBlood blood = hit.transform.GetComponent <EnemyBlood>(); if (blood) { blood.ShowBloodSplash(enemyEntity.MobileEnemy.BloodIndex, hit.point); } } else { if (!enemyEntity.MobileEnemy.ParrySounds || weapon.WeaponType == WeaponTypes.Melee) { weapon.PlaySwingSound(); } else { weapon.PlayParrySound(); } } // Remove health enemyEntity.DecreaseHealth(damage); hitEnemy = true; // Make foe attack their aggressor // Currently this is just player, but should be expanded later // for a wider variety of behaviours EnemyMotor enemyMotor = hit.transform.GetComponent <EnemyMotor>(); if (enemyMotor) { // Make enemies in an area aggressive if player attacked a non-hostile one. if (!enemyMotor.IsHostile) { GameManager.Instance.MakeEnemiesHostile(); } enemyMotor.MakeEnemyHostileToPlayer(gameObject); } } } // Check if hit a mobile NPC MobilePersonNPC mobileNpc = hit.transform.GetComponent <MobilePersonNPC>(); if (mobileNpc) { // TODO: Create blood splash. weapon.PlayHitSound(); mobileNpc.Motor.gameObject.SetActive(false); //GameManager.Instance.PlayerEntity.TallyCrimeGuildRequirements(false, 5); } } }
private void AddRDBModel(DFBlock.RdbObject obj, out List <StaticDoor> doorsOut, Transform parent) { bool overrideCombine = false; doorsOut = new List <StaticDoor>(); // Get model reference index and id int modelReference = obj.Resources.ModelResource.ModelIndex; uint modelId = blockData.RdbBlock.ModelReferenceList[modelReference].ModelIdNum; // Get rotation angle for each axis float degreesX = -obj.Resources.ModelResource.XRotation / BlocksFile.RotationDivisor; float degreesY = -obj.Resources.ModelResource.YRotation / BlocksFile.RotationDivisor; float degreesZ = -obj.Resources.ModelResource.ZRotation / BlocksFile.RotationDivisor; // Calcuate transform Vector3 position = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; // Calculate matrix Vector3 rx = new Vector3(degreesX, 0, 0); Vector3 ry = new Vector3(0, degreesY, 0); Vector3 rz = new Vector3(0, 0, degreesZ); Matrix4x4 modelMatrix = Matrix4x4.identity; modelMatrix *= Matrix4x4.TRS(position, Quaternion.identity, Vector3.one); modelMatrix *= Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(rz), Vector3.one); modelMatrix *= Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(rx), Vector3.one); modelMatrix *= Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(ry), Vector3.one); // Get model data ModelData modelData; dfUnity.MeshReader.GetModelData(modelId, out modelData); // Discard static exit doors not in starting block // Exit doors are just a model slapped over wall or doorway // This allows Daggerfall to toggle exits on and off if (modelData.DFMesh.ObjectId == 70300) { if (!isStartingBlock) { return; } } // Doors - there are no working static building doors inside dungeons, just the exits and action doors bool isActionDoor = IsActionDoor(blockData, obj, modelReference); if (isActionDoor) { parent = doorsNode.transform; } else if (modelData.Doors != null) { doorsOut.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, 0, modelMatrix)); } // Action records bool hasAction = HasAction(blockData, obj, modelReference); if (hasAction) { parent = actionModelsNode.transform; } // Flags bool isStatic = dfUnity.Option_SetStaticFlags; if (isActionDoor || hasAction) { // Moving objects are never static or combined isStatic = false; overrideCombine = true; } // Add to scene if (dfUnity.Option_CombineRDB && !overrideCombine) { combiner.Add(ref modelData, modelMatrix); } else { // Spawn mesh gameobject GameObject go = GameObjectHelper.CreateDaggerfallMeshGameObject(modelId, parent, isStatic); go.GetComponent <DaggerfallMesh>().SetDungeonTextures(textureTable); // Apply transforms go.transform.Rotate(0, degreesY, 0, Space.World); go.transform.Rotate(degreesX, 0, 0, Space.World); go.transform.Rotate(0, 0, degreesZ, Space.World); go.transform.localPosition = position; // Add action door if (isActionDoor) { DaggerfallActionDoor dfActionDoor = go.AddComponent <DaggerfallActionDoor>(); // Add action door audio if (dfUnity.Option_DefaultSounds) { AddActionDoorAudioSource(go); dfActionDoor.SetDungeonDoorSounds(); } } // Add action component if (hasAction && !isActionDoor) { AddAction(go, blockData, obj, modelReference); } } }