private void DoClawAttack() { //Debug.LogWarning("ClawAttack!"); //do damage to what we know is the target //raycast to see if we actually can hit //only half works unfortunately var itd = ActorController.Target.GetComponent <BaseController>() as ITakeDamage; if (itd != null) { LayerMask lm = WorldUtils.GetAttackLayerMask(); Vector3 vecThisToTarget = ActorController.Target.position - transform.position; if (Physics.Raycast(transform.position, vecThisToTarget, out var raycastHit, 100, lm, QueryTriggerInteraction.Collide)) { var hitController = raycastHit.collider.GetComponentInParent <BaseController>(); if (hitController != null && hitController == (BaseController)itd) { var modHit = ClawHit; var gameplayConfig = ConfigState.Instance.GetGameplayConfig(); modHit.Damage *= gameplayConfig.Difficulty.ActorStrength; modHit.DamagePierce *= gameplayConfig.Difficulty.ActorStrength; modHit.Originator = ActorController; itd.TakeDamage(modHit); if (HitSoundClip != null) { AudioPlayer.Instance.PlaySoundPositional(HitSoundClip, false, ActorController.Target.position); } } } } }
private void DoFlameAttack() { //basically copied from ActorAttackComponent var gameplayConfig = ConfigState.Instance.GetGameplayConfig(); var modHit = FlameHit; modHit.Damage *= gameplayConfig.Difficulty.ActorStrength; modHit.DamagePierce *= gameplayConfig.Difficulty.ActorStrength; modHit.Originator = ActorController; LayerMask lm = WorldUtils.GetAttackLayerMask(); var rc = Physics.RaycastAll(FirePoint.position, FirePoint.forward, FlameRange, lm, QueryTriggerInteraction.Collide); BaseController ac = null; foreach (var r in rc) //TODO move some of this to utils (RaycastForHit?) { var go = r.collider.gameObject; var ahgo = go.GetComponent <ActorHitboxComponent>(); if (ahgo != null) { ac = ahgo.ParentController; break; } var acgo = go.GetComponent <ActorController>(); if (acgo != null) { ac = acgo; break; } } if (ac != null && ac is ITakeDamage dac) { //raycast check for cover Physics.Raycast(FirePoint.position, FirePoint.forward, out var nearestRaycastHit, FlameRange, lm, QueryTriggerInteraction.Collide); var nearestController = nearestRaycastHit.collider.GetComponentInParent <BaseController>(); if (nearestController == null || nearestController != ac) { //nop } else { dac.TakeDamage(modHit); } } }
public void DoAttack() { var target = ActorController.Target; Vector3 aimPoint = target.position; var targetAC = target.GetComponent <ActorController>(); if (targetAC != null && targetAC.TargetPoint != null) { aimPoint = targetAC.TargetPoint.position; } var targetPC = target.GetComponent <PlayerController>(); if (targetPC != null && targetPC.TargetPoint != null) { aimPoint = targetPC.TargetPoint.position; } aimPoint.y += UnityEngine.Random.Range(-AttackSpread, AttackSpread); aimPoint.x += UnityEngine.Random.Range(-AttackSpread, AttackSpread); aimPoint.z += UnityEngine.Random.Range(-AttackSpread, AttackSpread); Vector3 shootPos = ShootPoint == null ? (transform.position + (transform.forward * 0.6f) + (transform.up * 1.25f)) : ShootPoint.position; Vector3 shootVec = (aimPoint - shootPos).normalized; //I screwed this up the first time var modHit = AttackHit; var gameplayConfig = ConfigState.Instance.GetGameplayConfig(); modHit.Damage *= gameplayConfig.Difficulty.ActorStrength; modHit.DamagePierce *= gameplayConfig.Difficulty.ActorStrength; modHit.Originator = ActorController; if (UseMelee) { //melee path (raycast) LayerMask lm = WorldUtils.GetAttackLayerMask(); //TODO 2D/3D attack range, or just increase attack range? var rc = Physics.RaycastAll(shootPos, shootVec, AttackRange, lm, QueryTriggerInteraction.Collide); BaseController ac = null; foreach (var r in rc) { var go = r.collider.gameObject; var ahgo = go.GetComponent <IHitboxComponent>(); if (ahgo != null) { ac = ahgo.ParentController; break; } var acgo = go.GetComponent <ActorController>(); if (acgo != null) { ac = acgo; break; } } if (ac != null) { if (ac is ITakeDamage itd) { itd.TakeDamage(modHit); } } } else if (BulletPrefab != null) { //bullet path (shoot) //var bullet = Instantiate<GameObject>(BulletPrefab, shootPos + (shootVec * 0.25f), Quaternion.identity, transform.root); var bullet = WorldUtils.SpawnEffect(BulletPrefab, shootPos + (shootVec * 0.25f), Vector3.zero, transform.root); var bulletRigidbody = bullet.GetComponent <Rigidbody>(); bulletRigidbody.velocity = (shootVec * BulletSpeed); bullet.GetComponent <BulletScript>().HitInfo = modHit; } else { CDebug.LogEx(string.Format("{0} tried to shoot a bullet, but has no prefab defined!", name), LogLevel.Error, this); } //show the effect, if applicable if (AttackEffectPrefab != null) { WorldUtils.SpawnEffect(AttackEffectPrefab, shootPos, Vector3.zero, (ShootPoint == null ? transform : ShootPoint)); //Instantiate(AttackEffectPrefab, shootPos, Quaternion.identity, (ShootPoint == null ? transform : ShootPoint)); } if (AttackSound != null) { AttackSound.Play(); } DidAttack = true; LastAttackTime = Time.time; }
private void SelectTarget() { var gameplayConfig = ConfigState.Instance.GetGameplayConfig(); if (TotalTickCount % SearchInterval * (1f / gameplayConfig.Difficulty.ActorAggression) != 0) { return; } var detectionDifficultyFactor = 1f / gameplayConfig.Difficulty.ActorPerception; //check player first since it's (relatively) cheap if (FactionModel.GetRelation(Faction, "Player") == FactionRelationStatus.Hostile && !MetaState.Instance.SessionFlags.Contains("NoTarget") && !GameState.Instance.PlayerFlags.Contains(PlayerFlags.NoTarget)) { var playerObj = WorldUtils.GetPlayerObject(); if (playerObj != null && RpgWorldUtils.TargetIsAlive(playerObj.transform)) { PlayerController pc = playerObj.GetComponent <PlayerController>(); if ((playerObj.transform.position - transform.position).magnitude <= SearchRadius && UnityEngine.Random.Range(0f, 1f * detectionDifficultyFactor) <= ((IAmTargetable)pc).Detectability) { if (UseLineOfSight) { //additional check RaycastHit hitinfo; if (Physics.Raycast(transform.position + new Vector3(0, 1.0f, 0), (playerObj.transform.position - transform.position), out hitinfo)) { if (hitinfo.collider.gameObject == playerObj) { Target = playerObj.transform; return; } } } else { //otherwise, close enough Target = playerObj.transform; return; } } } } //if(TargetNpc) { //var sw = System.Diagnostics.Stopwatch.StartNew(); //new code should be faster if n is large but it may not bear out in practice, and it probably allocs more dedotated wam var colliders = Physics.OverlapSphere(transform.position, SearchRadius, WorldUtils.GetAttackLayerMask()); HashSet <IAmTargetable> potentialTargets = new HashSet <IAmTargetable>(); foreach (var collider in colliders) { var baseController = collider.GetComponent <BaseController>(); if (baseController != null) { if (baseController is IAmTargetable iat && iat.ValidTarget) { potentialTargets.Add(iat); } continue; //continue anyway since we've found a base controller and it's either targetable or it's not } var hitboxComponent = collider.GetComponent <IHitboxComponent>(); if (hitboxComponent != null && hitboxComponent.ParentController is IAmTargetable iat2 && iat2.ValidTarget) { potentialTargets.Add(iat2); continue; } } //old stupid code: should work well enough as long as n is small and your computer is fast enough //IEnumerable<ActorController> potentialTargets = transform.root.GetComponentsInChildren<ActorController>(); foreach (var potentialTarget in potentialTargets) { BaseController targetController = potentialTarget as BaseController; if (targetController == null) { continue; } if (RpgWorldUtils.TargetIsAlive(targetController.transform) && (targetController.transform.position - transform.position).magnitude <= SearchRadius && FactionModel.GetRelation(Faction, potentialTarget.Faction) == FactionRelationStatus.Hostile && !(potentialTarget == this)) { //roll some dice if (potentialTarget.Detectability < 1 && UnityEngine.Random.Range(0f, 1f * detectionDifficultyFactor) > potentialTarget.Detectability) //probably correct { continue; } if (UseLineOfSight) { //additional check RaycastHit hitinfo; if (Physics.Raycast(transform.position + new Vector3(0, 1.0f, 0), (targetController.transform.position - transform.position), out hitinfo)) { if (hitinfo.collider.gameObject == targetController.gameObject) { Target = targetController.transform; break; } } } else { //otherwise, close enough Target = targetController.transform; break; } } } //sw.Stop(); //Debug.Log($"Target lookup: {sw.Elapsed.TotalMilliseconds:F4} ms"); } if (!RpgWorldUtils.TargetIsAlive(Target)) { Target = null; } }
private bool CheckLineOfSight(BaseController targetController) { //this will kinda work RaycastHit hitinfo; if (Physics.Raycast(transform.position + new Vector3(0, 1.0f, 0), (targetController.transform.position - transform.position), out hitinfo, SearchRadius, WorldUtils.GetAttackLayerMask(), QueryTriggerInteraction.Ignore)) { //Debug.Log($"LoS raycast hit {hitinfo.collider.gameObject.name}"); if (hitinfo.collider.gameObject == targetController.gameObject || hitinfo.collider.GetComponentInParent <BaseController>() == targetController) { return(true); } } return(false); }
public void DoAttack() { Vector3 shootPos = ShootPoint == null ? (transform.position + (transform.forward * 0.6f) + (transform.up * 1.25f)) : ShootPoint.position; if (UseSuicide) { //ActorController.TakeDamage(new ActorHitInfo(0, Mathf.Min(ActorController.MaxHealth * 100, float.MaxValue), 0, 0, 0, ActorController)); ActorController.Health = 0; } else { var target = ActorController.Target; Vector3 aimPoint = target.position; var targetAC = target.GetComponent <ActorController>(); if (targetAC != null && targetAC.TargetPoint != null) { aimPoint = targetAC.TargetPoint.position; } var targetPC = target.GetComponent <PlayerController>(); if (targetPC != null && targetPC.TargetPoint != null) { aimPoint = targetPC.TargetPoint.position; } aimPoint.y += UnityEngine.Random.Range(-AttackSpread, AttackSpread); aimPoint.x += UnityEngine.Random.Range(-AttackSpread, AttackSpread); aimPoint.z += UnityEngine.Random.Range(-AttackSpread, AttackSpread); Vector3 shootVec = (aimPoint - shootPos).normalized; //I screwed this up the first time float randomFactor = Mathf.Max(0, 1 + UnityEngine.Random.Range(-AttackRandomFactor, AttackRandomFactor)); var modHit = new ActorHitInfo(AttackHit); var gameplayConfig = ConfigState.Instance.GetGameplayConfig(); modHit.Damage *= gameplayConfig.Difficulty.ActorStrength * randomFactor; modHit.DamagePierce *= gameplayConfig.Difficulty.ActorStrength * randomFactor; modHit.Originator = ActorController; if (FriendlyFire == FriendlyFireMode.Always) { modHit.HarmFriendly = true; } else if (FriendlyFire == FriendlyFireMode.Never) { modHit.HarmFriendly = false; } else { modHit.HarmFriendly = GameParams.UseFriendlyFire; } if (string.IsNullOrEmpty(modHit.OriginatorFaction)) { modHit.OriginatorFaction = ActorController.Faction; } modHit.HitFlags = TypeUtils.FlagsFromCollection(AttackHitFlags); if (UseMelee) { if (AutoDamageEffector) { modHit.DamageEffector = (int)DamageEffector.Melee; } //melee path (raycast) LayerMask lm = WorldUtils.GetAttackLayerMask(); //TODO 2D/3D attack range, or just increase attack range? var rc = Physics.RaycastAll(shootPos, shootVec, AttackRange, lm, QueryTriggerInteraction.Collide); BaseController ac = null; foreach (var r in rc) { var go = r.collider.gameObject; var ahgo = go.GetComponent <IHitboxComponent>(); if (ahgo != null) { ac = ahgo.ParentController; break; } var acgo = go.GetComponent <ActorController>(); if (acgo != null) { ac = acgo; break; } } if (ac != null) { if (ac is ITakeDamage itd) { itd.TakeDamage(modHit); } } } else if (BulletPrefab != null) { if (AutoDamageEffector) { modHit.DamageEffector = (int)DamageEffector.Projectile; } //bullet path (shoot) //var bullet = Instantiate<GameObject>(BulletPrefab, shootPos + (shootVec * 0.25f), Quaternion.identity, transform.root); Quaternion bulletRotation = Quaternion.LookRotation(shootVec.normalized, Vector3.up); var bullet = WorldUtils.SpawnEffect(BulletPrefab, shootPos + (shootVec * 0.25f), bulletRotation.eulerAngles, transform.root); var bulletRigidbody = bullet.GetComponent <Rigidbody>(); bulletRigidbody.velocity = (shootVec * BulletSpeed); var bulletScript = bullet.GetComponent <BulletScript>(); bulletScript.HitInfo = modHit; bulletScript.Target = target; } else { CDebug.LogEx(string.Format("{0} tried to shoot a bullet, but has no prefab defined!", name), LogLevel.Error, this); } } //show the effect, if applicable if (!string.IsNullOrEmpty(AttackEffectPrefab)) { WorldUtils.SpawnEffect(AttackEffectPrefab, shootPos, Vector3.zero, ParentAttackEffect ? (ShootPoint == null ? transform : ShootPoint) : null); //Instantiate(AttackEffectPrefab, shootPos, Quaternion.identity, (ShootPoint == null ? transform : ShootPoint)); } if (AttackSound != null) { AttackSound.Play(); } DidAttack = true; LastAttackTime = Time.time; }