//~ IEnumerator ShootRoutine(RaycastHit hit=default(RaycastHit)){ IEnumerator ShootRoutine(ShootObject.AimInfo aimInfo=null) { if(uAnimation!=null) uAnimation.AttackRange(); AttackStats aStats=ModifyAttackStatsToExistingEffect(weaponList[weaponID].CloneStats()); AttackInstance aInstance=new AttackInstance(this, aStats); int weapID=weaponID; //to prevent weapon switch and state change while delay and firing multiple so int spread=weaponList[weapID].spread; if(spread>1){ aInstance.aStats.damageMin/=spread; aInstance.aStats.damageMax/=spread; } float startAngle=spread>1 ? -weaponList[weapID].spreadAngle/2f : 0 ; float angleDelta=spread>1 ? weaponList[weapID].spreadAngle/(spread-1) : 0 ; List<Collider> soColliderList=new List<Collider>(); //colliders of all the so fired, used to tell each so to ignore each other for(int i=0; i<weaponList[weapID].shootPointList.Count; i++){ Transform shootPoint=weaponList[weapID].shootPointList[i]; float recoilSign=(Random.value<recoilSignTH ? -1 : 1); recoilSignTH=Mathf.Clamp(recoilSignTH+(recoilSign>0 ? 0.25f : -0.25f), 0, 1); float recoilValue=recoilSign*Random.Range(0.1f, 1f)*GetRecoil(); Quaternion baseShootRot=shootPoint.rotation*Quaternion.Euler(0, recoilValue, 0); for(int m=0; m<Mathf.Max(1, spread); m++){ Vector3 shootPos=shootPoint.position; if(spread>1) shootPos=shootPoint.TransformPoint(new Vector3(0, 0, Random.Range(-1.5f, 1.5f))); Quaternion shootRot=baseShootRot*Quaternion.Euler(0, startAngle+(m*angleDelta), 0); //GameObject soObj=(GameObject)Instantiate(weaponList[weapID].shootObject, shootPos, shootRot); GameObject soObj=ObjectPoolManager.Spawn(weaponList[weapID].shootObject, shootPos, shootRot); ShootObject soInstance=soObj.GetComponent<ShootObject>(); soInstance.IgnoreCollider(GetCollider()); for(int n=0; n<soColliderList.Count; n++) soInstance.IgnoreCollider(soColliderList[n]); if(soInstance.GetCollider()!=null) soColliderList.Add(soInstance.GetCollider()); soInstance.Shoot(thisObj.layer, GetRange(), shootPoint, aInstance.Clone(), aimInfo); //soInstance.Shoot(thisObj.layer, GetRange(), shootPoint, aInstance.Clone(), hit); } TDS.CameraShake(weaponList[weapID].recoilCamShake); if(weaponList[weapID].shootPointDelay>0) yield return new WaitForSeconds(weaponList[weapID].shootPointDelay); if(weapID>=weaponList.Count) break; } }
IEnumerator ShootRoutine(ShootObject.AimInfo aimInfo = null) { if (uAnimation != null) { uAnimation.AttackRange(); } AttackStats aStats = ModifyAttackStatsToLevel(weaponList[weaponID].GetRuntimeAttackStats()); aStats = ModifyAttackStatsToExistingEffect(aStats); //aStats=ModifyAttackStatsToExistingEffect(weaponList[weaponID].GetRuntimeAttackStats()); AttackInstance aInstance = new AttackInstance(this, aStats); int weapID = weaponID; //to prevent weapon switch and state change while delay and firing multiple so int spread = weaponList[weapID].spread; if (spread > 1) { aInstance.aStats.damageMin /= spread; aInstance.aStats.damageMax /= spread; } float startAngle = spread > 1 ? -weaponList[weapID].spreadAngle / 2f : 0; float angleDelta = spread > 1 ? weaponList[weapID].spreadAngle / (spread - 1) : 0; List <Collider> soColliderList = new List <Collider>(); //colliders of all the so fired, used to tell each so to ignore each other for (int i = 0; i < weaponList[weapID].shootPointList.Count; i++) { Transform shootPoint = weaponList[weapID].shootPointList[i]; float recoilSign = (Random.value < recoilSignTH ? -1 : 1); recoilSignTH = Mathf.Clamp(recoilSignTH + (recoilSign > 0 ? 0.25f : -0.25f), 0, 1); float recoilValue = recoilSign * Random.Range(0.1f, 1f) * GetRecoil(); Quaternion baseShootRot = shootPoint.rotation * Quaternion.Euler(0, recoilValue, 0); for (int m = 0; m < Mathf.Max(1, spread); m++) { Vector3 shootPos = shootPoint.position; if (spread > 1) { shootPos = shootPoint.TransformPoint(new Vector3(0, 0, Random.Range(-1.5f, 1.5f))); } Quaternion shootRot = baseShootRot * Quaternion.Euler(0, startAngle + (m * angleDelta), 0); //GameObject soObj=(GameObject)Instantiate(weaponList[weapID].shootObject, shootPos, shootRot); GameObject soObj = ObjectPoolManager.Spawn(weaponList[weapID].shootObject, shootPos, shootRot); ShootObject soInstance = soObj.GetComponent <ShootObject>(); soInstance.IgnoreCollider(GetCollider()); for (int n = 0; n < soColliderList.Count; n++) { soInstance.IgnoreCollider(soColliderList[n]); } if (soInstance.GetCollider() != null) { soColliderList.Add(soInstance.GetCollider()); } soInstance.Shoot(thisObj.layer, GetRange(), shootPoint, aInstance.Clone(), aimInfo); //soInstance.Shoot(thisObj.layer, GetRange(), shootPoint, aInstance.Clone(), hit); } TDS.CameraShake(weaponList[weapID].recoilCamShake); if (weaponList[weapID].shootPointDelay > 0) { yield return(new WaitForSeconds(weaponList[weapID].shootPointDelay)); } if (weapID >= weaponList.Count) { break; } } }
//called when shootobject hit something void OnTriggerEnter(Collider col) { if (state == _State.Hit) { return; //if the shootobject has hit something before this, return } //if the shootobject hits another shootobject from friendly unit if (!GameControl.SOHitFriendly() && col != null) { if (srcLayer == col.gameObject.layer) { return; } } //register the state of the shootobject as hit state = _State.Hit; TDS.CameraShake(impactCamShake); //when hit a shootObject if (col != null && col.gameObject.layer == TDS.GetLayerShootObject()) { //if this is a beam shootobject, inform the other shootobject that it has been hit (beam doesnt use a collider) if (type == _SOType.Beam) { col.gameObject.GetComponent <ShootObject>().Hit(); } } //when hit a collectible, destroy the collectible if (col != null && col.gameObject.layer == TDS.GetLayerCollectible()) { ObjectPoolManager.Unspawn(col.gameObject); return; } //if there's a attack instance (means the shootobject has a valid attacking stats and all) if (attInstance != null) { float aoeRadius = attInstance.aStats.aoeRadius; //for area of effect hit if (aoeRadius > 0) { Unit unitInstance = null; //get all the potental target in range Collider[] cols = Physics.OverlapSphere(thisT.position, aoeRadius); for (int i = 0; i < cols.Length; i++) { //if the collider in question is the collider the shootobject hit in the first place, apply the full attack instance if (cols[i] == col) { unitInstance = col.gameObject.GetComponent <Unit>(); if (unitInstance != null) { unitInstance.ApplyAttack(attInstance.Clone()); } continue; } //no friendly fire, then skip if the target is a friendly unit if (!GameControl.SOHitFriendly()) { if (cols[i].gameObject.layer == srcLayer) { continue; } } unitInstance = cols[i].gameObject.GetComponent <Unit>(); //create a new attack instance and mark it as aoe attack, so diminishing aoe can be applied if enabled AttackInstance aInstance = attInstance.Clone(); aInstance.isAOE = true; aInstance.aoeDistance = Vector3.Distance(thisT.position, cols[i].transform.position); //apply the attack if (unitInstance != null) { unitInstance.ApplyAttack(aInstance); } } } else { if (col != null) { //get the unit and apply the attack Unit unitInstance = col.gameObject.GetComponent <Unit>(); if (unitInstance != null) { unitInstance.ApplyAttack(attInstance); } } } if (col != null) { //apply impact force to the hit object Vector3 impactDir = Quaternion.Euler(0, thisT.eulerAngles.y, 0) * Vector3.forward; TDSPhysics.ApplyAttackForce(thisT.position, impactDir, col.gameObject, attInstance.aStats); } } //add collider to the condition so the shootobject wont split if the shootObject didnt hit anything (it could have just reach the range limit) if (splitUponHit && col != null) { Split(col); } Hit(); }