Beispiel #1
0
        public AttackInstance Clone()
        {
            AttackInstance aInstance=new AttackInstance();

            aInstance.isAOE=isAOE;
            aInstance.aoeDistance=aoeDistance;
            aInstance.aStats=aStats.Clone();

            return aInstance;
        }
Beispiel #2
0
        //function call to fire the object
        public void Shoot(int srcL, float srcR, Transform shootPoint, AttackInstance aInstance=null, AimInfo aimInfo=null)
        {
            Init();

            thisObj.SetActive(true);

            //cached all the passed information lcoally
            attInstance=aInstance;
            srcLayer=srcL;	//the layer of the shooting unit (so we know it's from player or AI)
            srcRange=srcR;	//the range of the shooting unit (so we know when to stop)

            state=_State.Shot;
            shootTime=Time.time;	//to track how long the shoot object is has been
            travelledDistance=0;	//to track how far the shoot object is has been fired

            //if there's any hideObject, set it to true (it's probably set to false when the shoot-object last hit something)
            if(hideObject!=null) hideObject.SetActive(true);

            //instantiate the shoot effect
            ShootEffect(thisT.position, thisT.rotation);

            if(type==_SOType.Simple || type==_SOType.Homing){
                //if(aInstance!=null && thisCollider.enabled){
                    //~ Physics.IgnoreCollision(aInstance.srcUnit.GetCollider(), thisObj.GetComponent<Collider>(), true);
                    //Debug.Log("collision avoidance with shooter unresolved");
                    //Physics.IgnoreCollision(srcCollider, thisCollider, true);
                //}

                // for homing shootobject, the shootobject needs to be aiming at some position, or a specific unit
                if(type==_SOType.Homing){
                    if(aimInfo.targetT!=null) targetUnit=aimInfo.unit;

                    targetPos=aimInfo.hitPoint+new Vector3(Random.value-0.5f, 0, Random.value-0.5f)*2*spread;
                    initialPos=shootPoint.position;
                    initialDist=Vector3.Distance(targetPos, initialPos);

                    curveMod=Random.Range(0, 2f);
                    dummyPos=thisT.TransformPoint(Vector3.forward*speed*5);
                    dummyPos=(targetPos+dummyPos)/2;
                }
            }
            else if(type==_SOType.Beam){
                //if(attachedToShootPoint) transform.parent=shootPoint;
                thisT.parent=shootPoint;
                ObjectPoolManager.Unspawn(thisObj, beamDuration-.01f);
            }
            else if(type==_SOType.Point){
                StartCoroutine(PointRoutine(aimInfo));
            }

            //update the layermask used to do the hit detection in accordance to rules set in GameControl
            UpdateSphereCastMask(!GameControl.SOHitFriendly(), !GameControl.SOHitShootObject(), !GameControl.SOHitCollectible());
        }
Beispiel #3
0
        //~ 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;
            }
        }
Beispiel #4
0
        //applies the effect of an attack
        public void ApplyAttack(AttackInstance attInstance)
        {
            //if unit is invincible, do nothing
            if(IsInvincible()){
                Debug.Log("Immuned");
                Vector3 osPos=new Vector3(0, Random.value+0.5f, 0);
                new TextOverlay(thisT.position+osPos, "Immuned");
                return;
            }

            AttackStats aStats=attInstance.aStats;

            //check if the attack is an aoe and modify the damage value is dimishingAOE is enabled
            float damage=Random.Range(aStats.damageMin, aStats.damageMax);
            if(attInstance.isAOE && aStats.dimishingAOE){
                damage*=Mathf.Clamp(1-attInstance.aoeDistance/aStats.aoeRadius, 0, 1);
            }

            //check for cirtical and modify the damage based on critical multiplier
            bool critical=Random.value<aStats.critChance;
            if(critical) damage*=aStats.critMultiplier;

            //modify the damage based on damage and armor type
            damage*=DamageTable.GetModifier(armorType, aStats.damageType);

            //if damage is valid, modify the hit point
            if(damage>0){
                //show the overlay (for UI)
                Vector3 offsetPos=new Vector3(0, Random.value+0.5f, 0);
                if(!critical) new TextOverlay(thisT.position+offsetPos, damage.ToString("f0"));
                else new TextOverlay(thisT.position+offsetPos, damage.ToString("f0"), new Color(1f, 0.9f, 0.9f, 1f), 1.5f);

                //if the unit is player, fire event to inform UI
                if(thisObj.layer==TDS.GetLayerPlayer()) TDS.PlayerDamaged(damage);

                //register the stagger
                hpRegenStaggerCounter=hpRegenStagger;

                hitPoint-=damage;	//damage the hitpoint
                if(hitPoint<=0) Destroyed();

                if(hitPoint>0 && uAnimation!=null) uAnimation.Hit();
            }

            //apply effect if there's any
            if(aStats.effect!=null) ApplyEffect(aStats.effect);
        }
Beispiel #5
0
        IEnumerator _ShootTarget(float targetDist)
        {
            if(targetDist>GetRange()) yield break;	//if target is out of range, dont continue

            currentCD=cooldown;	//set the cooldown

            if(uAnimation!=null) uAnimation.AttackRange();	//play the attack animation

            List<Collider> soColliderList=new List<Collider>();	//colliders of all the shoot-objs fired, used to tell each so to ignore each other

            //loop through the shoot-points, fire an shoot-object for each of them
            for(int i=0; i<shootPointList.Count; i++){
                //create a new attak instance for the attack
                AttackInstance attInstance=new AttackInstance(this, ModifyAttackStatsToExistingEffect(attackStats.Clone()));

                //record the target position, in case the target get destroyed before all shoot point has fired
                if(target!=null) targetLastPos=target.thisT.position;

                //create an aimInfo instance for the shootObject
                ShootObject.AimInfo aimInfo=target!=null ? new ShootObject.AimInfo(target) : new ShootObject.AimInfo(targetLastPos);

                //get the shoot rotation
                Quaternion shootRot=shootPointList[i].rotation;
                if(alwaysShootTowardsTarget && target!=null) shootRot=Quaternion.LookRotation(target.thisT.position-thisT.position);

                //spawn the shootobject
                GameObject soObj=ObjectPoolManager.Spawn(shootObject, shootPointList[i].position, shootRot);

                ShootObject soInstance=soObj.GetComponent<ShootObject>();

                //inform the shootobject to ignore the certain collider
                soInstance.IgnoreCollider(GetCollider());
                for(int n=0; n<soColliderList.Count; n++) soInstance.IgnoreCollider(soColliderList[n]);
                if(soInstance.GetCollider()!=null) soColliderList.Add(soInstance.GetCollider());

                //fire the shootobject
                soInstance.Shoot(thisObj.layer, GetRange(), shootPointList[i], attInstance, aimInfo);

                //delay a bit before the next shoot point, if a delay has been specified
                if(shootPointDelay>0) yield return new WaitForSeconds(shootPointDelay);
            }

            yield return null;
        }
Beispiel #6
0
        //function call when the unit collide with a player unit, for contact(melee) attack
        void OnPlayerContact()
        {
            if(!enableContactAttack) return;

            if(contactCurrentCD>0) return;		//if attack is still on cd

            if(uAnimation!=null) uAnimation.AttackMelee();	//play attack animation

            contactCurrentCD=contactCooldown;	//set the cooldown

            //create an attack instance and attack the player unit
            AttackInstance attInstance=new AttackInstance(this, ModifyAttackStatsToExistingEffect(contactAttackStats.Clone()));
            GameControl.GetPlayer().ApplyAttack(attInstance);
        }
Beispiel #7
0
        //apply effect to all active hostile unit
        void ApplyEffectAll()
        {
            //get all active hostile unit from UnitTracker
            List<Unit> unitList=UnitTracker.GetAllUnitList();

            for(int i=0; i<unitList.Count; i++){
                //clone the attack stats so that the original value wont get modified when making further calculation
                AttackInstance aInstance=new AttackInstance();
                aInstance.aStats=aStats.Clone();
                unitList[i].ApplyAttack(aInstance);
            }
        }
Beispiel #8
0
        //apply effect to all hostile unit surrounding the player
        void ApplyEffectAOE(Collider playerCollider)
        {
            float aoeRadius=aStats.aoeRadius;

            if(aoeRadius>0){
                Collider[] cols=Physics.OverlapSphere(transform.position, aoeRadius);	//get all the collider in range
                for(int i=0; i<cols.Length; i++){
                    if(cols[i]==playerCollider) continue;

                    //clone the attack stats so that the original value wont get modified when making further calculation
                    AttackInstance aInstance=new AttackInstance(null, aStats);
                    aInstance.isAOE=true;
                    aInstance.aoeDistance=Vector3.Distance(transform.position, cols[i].transform.position);

                    Unit unitInstance=cols[i].gameObject.GetComponent<Unit>();
                    if(unitInstance!=null) unitInstance.ApplyAttack(aInstance);
                }
            }

            //since this is aoe effect, explosion force applies
            TDSPhysics.ApplyExplosionForce(transform.position, aStats, true);
        }
Beispiel #9
0
        //launch the ability, at the position given
        public void Activate(Vector3 pos=default(Vector3))
        {
            currentCD=cooldown;							//set the cooldown
            GameControl.GetPlayer().energy-=cost;	//deduct player energy by the ability cost

            AudioManager.PlaySound(launchSFX);

            //instantiate the launch object, if there's any
            if(launchObj!=null){
                GameObject obj=(GameObject)MonoBehaviour.Instantiate(launchObj, pos, Quaternion.identity);
                if(autoDestroyLaunchObj) MonoBehaviour.Destroy(obj, launchObjActiveDuration);
            }

            //for aoe ability
            if(type==_AbilityType.AOE || type==_AbilityType.AOESelf){
                //get all the collider in range
                Collider[] cols=Physics.OverlapSphere(pos, aStats.aoeRadius);
                for(int i=0; i<cols.Length; i++){
                    Unit unitInstance=cols[i].gameObject.GetComponent<Unit>();

                    //only continue if the collider is a unit and is not player
                    if(unitInstance!=null && unitInstance!=GameControl.GetPlayer()){
                        //create an AttackInstance and mark it as AOE attack
                        AttackInstance aInstance=new AttackInstance();
                        aInstance.aStats=aStats.Clone();
                        aInstance.isAOE=true;
                        aInstance.aoeDistance=Vector3.Distance(pos, cols[i].transform.position);
                        //apply the AttackInstance
                        unitInstance.ApplyAttack(aInstance);
                    }
                }

                //apply explosion force
                TDSPhysics.ApplyExplosionForce(pos, aStats);
            }

            //for ability that affects all hostile unit in game
            else if(type==_AbilityType.All){
                //get all hostile unit for unit tracker
                List<Unit> unitList=new List<Unit>( UnitTracker.GetAllUnitList() );
                //loop through all unit, create an AttackInstance and apply the attack
                for(int i=0; i<unitList.Count; i++){
                    AttackInstance aInstance=new AttackInstance();
                    aInstance.aStats=aStats.Clone();
                    unitList[i].ApplyAttack(aInstance);
                }
            }

            //for ability that meant to be cast on player unit
            else if(type==_AbilityType.Self){
                //apply the attack on player
                AttackInstance aInstance=new AttackInstance();
                aInstance.aStats=aStats.Clone();
                GameControl.GetPlayer().ApplyAttack(aInstance);
            }

            //for ability that fires a shoot object
            else if(type==_AbilityType.Shoot){
                //get the position and rotation to fire the shoot object from
                Transform srcT=GetShootObjectSrcTransform();
                Vector3 shootPos=srcT.TransformPoint(shootPosOffset);
                pos.y=shootPos.y;
                Quaternion shootRot=Quaternion.LookRotation(pos-shootPos);

                //create the AttackInstance
                AttackInstance aInstance=new AttackInstance();
                aInstance.aStats=aStats.Clone();

                //Instantiate the shoot-object and fires it
                GameObject soObj=(GameObject)MonoBehaviour.Instantiate(shootObject, shootPos, shootRot);
                ShootObject soInstance=soObj.GetComponent<ShootObject>();
                soInstance.Shoot(GameControl.GetPlayer().thisObj.layer, range, srcT, aInstance);
            }
        }