Пример #1
0
        //called from GameControl when a unit is destroyed
        public void UnitDestroyed(Unit unit)
        {
            if(unit==null) return;

            //remove the destroyed unit from unitList
            unitList.Remove(unit);

            //if the unit's prefab is in prefabList, increase the corresponding kill count
            for(int i=0; i<prefabList.Count; i++){
                if(unit.prefabID==prefabList[i].prefabID){
                    prefabKillCountList[i]+=1;
                    break;
                }
            }

            //if unitList is cleared, check if objective is complete
            if(unitList.Count==0) CheckObjectiveComplete();
        }
Пример #2
0
 public AimInfo(Unit tgt)
 {
     //for a specific target (used by AI unit)
     unit=tgt;
     hitPoint=unit.thisT.position;
     targetT=unit.thisT;
     collider=unit.GetCollider();
 }
Пример #3
0
 public AimInfo(RaycastHit hit)
 {
     //from the raycast from the cursor used to aim at the target
     hitPoint=hit.point;
     targetT=hit.transform;
     collider=hit.collider;
     unit=targetT!=null ? hit.transform.GetComponent<Unit>() : null;
 }
Пример #4
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());
        }
Пример #5
0
        // Update is called once per frame
        void Update()
        {
            //if the shootobject is not in the shot state, dont continue
            if(type!=_SOType.Beam && state!=_State.Shot) return;

            float travelDistance=GetRangePerFrame();	//get the distance the shootobject travelled in this frame

            //do a sphere-cast to limit the travel distance in this frame so we dont over-shoot anything the shootobject might hit
            RaycastHit hit;
            if(Physics.SphereCast(thisT.position, hitRadius, thisT.forward, out hit, travelDistance, mask)){
                travelDistance=Vector3.Distance(thisT.position, hit.point);
            }

            if(type==_SOType.Simple){
                travelledDistance+=travelDistance;
                thisT.Translate(Vector3.forward * travelDistance);
                if(Time.time-shootTime>destroyTime) Hit();
                if(travelledDistance>srcRange) OnTriggerEnter(null);
            }
            if(type==_SOType.Homing){
                if(targetUnit!=null){
                    targetPos=targetUnit.thisT.position;

                    Vector3 thisTempPos=thisT.position;
                    thisTempPos.y=targetPos.y;
                    Quaternion tgtRot=Quaternion.LookRotation(targetPos-thisTempPos);

                    //if the target is too far off angle
                    if(Mathf.Abs(thisT.rotation.eulerAngles.y-tgtRot.eulerAngles.y)>65){
                        targetPos=thisT.TransformPoint(0, 0, speed);
                        targetPos.y=targetUnit.thisT.position.y;
                        targetUnit=null;
                    }
                    else if(Time.time-shootTime>trackingDuration){
                        targetUnit=null;
                        targetPos+=new Vector3(Random.value-0.5f, 0, Random.value-0.5f)*2*spread/2;
                    }
                }

                float currentDist=Vector3.Distance(thisT.position, targetPos);

                float timeMultipler=(speed/initialDist)*0.125f;
                curveMod+=Time.deltaTime*timeMultipler;
                timeSinceFire+=Time.deltaTime*timeMultipler;

                dummyPos=Vector3.Lerp(dummyPos, targetPos, timeSinceFire);

                Quaternion wantedRot=Quaternion.LookRotation(dummyPos-thisT.position);
                thisT.rotation=Quaternion.Slerp(thisT.rotation, wantedRot, Time.deltaTime*speed*(1.5f+curveMod));

                thisT.Translate(Vector3.forward * travelDistance);

                if(currentDist<hitRadius) OnTriggerEnter(null);
            }
            else if(type==_SOType.Beam){
                if(shootThrough) travelDistance=GetRangePerFrame();

                if(line!=null){
                    line.SetPosition(0, new Vector3(0, 0, 0));
                    line.SetPosition(1, new Vector3(0, 0, travelDistance));
                }

                if(!shootThrough){
                    if(hit.collider!=null){
                        if(Time.time-lastHitCD>0.2f){
                            if(state==_State.Shot) HitEffect(hit.point);
                            OnTriggerEnter(hit.collider);
                            lastHitCD=Time.time;
                        }
                        if(continousEffect) state=_State.Shot;
                    }
                }
                else{
                    if(Time.time-lastHitCD>0.1f){
                        lastHitCD=Time.time;
                        RaycastHit[] hitList=Physics.SphereCastAll(thisT.position, hitRadius, thisT.forward, travelDistance);

                        for(int i=0; i<hitList.Length; i++){
                            if(state==_State.Shot) HitEffect(hitList[i].point);
                            state=_State.Shot;
                            if(hitList[i].collider!=null) OnTriggerEnter(hitList[i].collider);
                        }

                        if(continousEffect) state=_State.Shot;
                    }
                }
            }
        }
Пример #6
0
        private Wave waveE = null; //the current wave used in endless mode

        #endregion Fields

        #region Methods

        //track unit
        public void AddUnit(Unit unitInstance)
        {
            //set destroy callback for the unit
            unitInstance.SetDestroyCallback(this.UnitDestroy);
            spawnCount+=1;
            activeCount+=1;
        }
Пример #7
0
 //called from unit to add the new SpawnUponDestroy unit to the parent unit's wave
 public void AddUnitToWave(Unit unitInstance)
 {
     waveList[unitInstance.waveID].activeUnitCount+=1;
     AddUnit(unitInstance);
 }
Пример #8
0
        protected Vector2 DrawUnitBaseStats(float startX, float startY, Unit unit, bool isPlayer)
        {
            TDSEditorUtility.DrawSprite(new Rect(startX, startY, 60, 60), unit.icon);
            startX+=65;

            float offsetY=TDSEditor.IsPrefab(unit.gameObject) ? 5 : 0 ;

            cont=new GUIContent("Name:", "The unit name to be displayed in game");
            EditorGUI.LabelField(new Rect(startX, startY+=offsetY, width, height), cont);
            unit.unitName=EditorGUI.TextField(new Rect(startX+spaceX-65, startY, width-5, height), unit.unitName);

            cont=new GUIContent("Icon:", "The unit icon to be displayed in game, must be a sprite");
            EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
            unit.icon=(Sprite)EditorGUI.ObjectField(new Rect(startX+spaceX-65, startY, width-5, height), unit.icon, typeof(Sprite), false);

            if(TDSEditor.IsPrefab(unit.gameObject)){
                cont=new GUIContent("Prefab:", "The prefab object of the unit\nClick this to highlight it in the ProjectTab");
                EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
                EditorGUI.ObjectField(new Rect(startX+spaceX-65, startY, width-5, height), unit.gameObject, typeof(GameObject), false);
            }
            else{
                EditorGUI.HelpBox(new Rect(startX, startY+=spaceY, width+spaceX-65, height+5), "The unit being edited is not a prefab", MessageType.Warning);
                startY+=5;
            }

            startX-=65;
            startY+=spaceY;

            EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), "Basic Stats", headerStyle);

            startY+=5;

            cont=new GUIContent("Hit Point:", "The hit-point capacity of the unit");
            EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
            unit.hitPointFull=EditorGUI.FloatField(new Rect(startX+spaceX, startY, 40, height), unit.hitPointFull);

            unit.startHitPointAtFull=EditorGUI.Toggle(new Rect(startX+spaceX+50, startY, 40, height), unit.startHitPointAtFull);
            EditorGUI.LabelField(new Rect(startX+spaceX+65, startY, width, height), " - start at full");

            cont=new GUIContent("Hit Point Regen:", "The amount of hit-point regenerated per second");
            EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
            unit.hpRegenRate=EditorGUI.FloatField(new Rect(startX+spaceX, startY, 40, height), unit.hpRegenRate);

            cont=new GUIContent("Hit Point Stagger:", "The duration in second in which the hit-point regen would stop after the unit being hit");
            EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
            if(unit.hpRegenRate>0) unit.hpRegenStagger=EditorGUI.FloatField(new Rect(startX+spaceX, startY, 40, height), unit.hpRegenStagger);
            else EditorGUI.LabelField(new Rect(startX+spaceX, startY, 40, height), "-");

            if(isPlayer){
                startY+=10;

                cont=new GUIContent("Energy:", "The energy capacity of the unit");
                EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
                unit.energyFull=EditorGUI.FloatField(new Rect(startX+spaceX, startY, 40, height), unit.energyFull);

                unit.startEnergyAtFull=EditorGUI.Toggle(new Rect(startX+spaceX+50, startY, 40, height), unit.startEnergyAtFull);
                EditorGUI.LabelField(new Rect(startX+spaceX+65, startY, width, height), " - start at full");

                cont=new GUIContent("Energy Rate:", "The rate (per second) in which the energy will recharge");
                EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
                unit.energyRate=EditorGUI.FloatField(new Rect(startX+spaceX, startY, 40, height), unit.energyRate);
            }

            startY+=10;

            cont=new GUIContent("Armor Type:", "The armor type of the unit\nArmor type can be configured in Damage Armor Table Editor");
            EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
            if(armorTypeLabel.Length>0)
                unit.armorType=EditorGUI.Popup(new Rect(startX+spaceX, startY, width, height), unit.armorType, armorTypeLabel);
            else{
                if(GUI.Button(new Rect(startX+spaceX, startY, 83, height-2), "Add Type")){
                    DamageTableEditorWindow.Init();
                }
            }

            return new Vector2(startX, startY);
        }
Пример #9
0
 public static void NewUnit(Unit unit)
 {
     if(onNewUnitE!=null) onNewUnitE(unit);
 }
Пример #10
0
 void Awake()
 {
     instance = (Unit)target;
     LoadDB();
 }
Пример #11
0
        protected Vector2 DrawDestroyEffectObj(float startX, float startY, Unit unit)
        {
            cont=new GUIContent("DestroyCamShake:", "The camera shake magnitude whenever the unit is destroyed");
            EditorGUI.LabelField(new Rect(startX, startY, width, height), cont);
            unit.destroyCamShake=EditorGUI.FloatField(new Rect(startX+spaceX, startY, 40, height), unit.destroyCamShake);

            startY+=10;

            cont=new GUIContent("DestroyedEffectObj:", "The object to be spawned when the unit is destroyed (optional)");
            EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
            unit.destroyedEffectObj=(GameObject)EditorGUI.ObjectField(new Rect(startX+spaceX, startY, width, height), unit.destroyedEffectObj, typeof(GameObject), false);

            cont=new GUIContent("AutoDestroy Effect:", "Check if the effect object needs to be removed from the game");
            EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
            if(unit.destroyedEffectObj!=null){
                unit.autoDestroyDObj=EditorGUI.Toggle(new Rect(startX+spaceX, startY, 40, height), unit.autoDestroyDObj);

                if(unit.autoDestroyDObj){
                    cont=new GUIContent(" - Duration:", "The delay in seconds before the effect object is destroyed");
                    EditorGUI.LabelField(new Rect(startX+spaceX+15, startY, width, height), cont);
                    unit.dObjActiveDuration=EditorGUI.FloatField(new Rect(startX+spaceX+width-58, startY, 40, height), unit.dObjActiveDuration);
                }
            }
            else EditorGUI.LabelField(new Rect(startX+spaceX, startY, 40, height), "-");

            return new Vector2(startX, startY);
        }
Пример #12
0
        public bool isAOE = false; //marked if the attack is AOE

        #endregion Fields

        #region Constructors

        //create a new attackInstance, given the AttackStats (the set of stats for the attack unit or ability)
        public AttackInstance(Unit src=null, AttackStats aSt=null)
        {
            aStats=aSt;
        }
Пример #13
0
 //remove unit from tracker (call by every hostile unit upon deactivation)
 public static void RemoveUnit(Unit unit)
 {
     allUnitList.Remove(unit);
 }
Пример #14
0
 //add unit to be tracked (called by every hostile unit upon activation)
 public static void AddUnit(Unit unit)
 {
     if(allUnitList.Contains(unit)) return;
     allUnitList.Add(unit);
 }
Пример #15
0
 public void _UnitDestroyed(Unit unit)
 {
     if(objective!=null) objective.UnitDestroyed(unit);
 }
Пример #16
0
 //call to inform objective that a unit has been destroyed
 public static void UnitDestroyed(Unit unit)
 {
     if(instance!=null) instance._UnitDestroyed(unit);
 }