private Vector3 pathDynamicOffset; // offset with origin cell public override void Awake() { SetSubClass(this); base.Awake(); maskTarget = 1 << LayerManager.LayerTower(); if (thisObj.GetComponent <Collider>() == null) { thisObj.AddComponent <SphereCollider>(); } }
public IEnumerator ScanForTargetRoutine() { if (subClass == _UnitSubClass.Tower) { if (unitT.targetMode == _TargetMode.Hybrid) { LayerMask mask1 = 1 << LayerManager.LayerCreep(); LayerMask mask2 = 1 << LayerManager.LayerCreepF(); maskTarget = mask1 | mask2; } else if (unitT.targetMode == _TargetMode.Air) { maskTarget = 1 << LayerManager.LayerCreepF(); } else if (unitT.targetMode == _TargetMode.Ground) { maskTarget = 1 << LayerManager.LayerCreep(); } } else if (subClass == _UnitSubClass.Creep) { maskTarget = 1 << LayerManager.LayerTower(); } //initiate scan direction //if(directionalTargeting){ // if(IsCreep()) dirScanRot=thisT.rotation; // else dirScanRot=thisT.rotation*Quaternion.Euler(0f, dirScanAngle, 0f); //} while (true) { ScanForTarget(); yield return(new WaitForSeconds(0.1f)); if (GameControl.ResetTargetAfterShoot()) { while (turretOnCooldown) { yield return(null); } } } //yield return null; }
public static UnitTower Select(Vector3 pointer) { int layer = LayerManager.LayerTower(); LayerMask mask = 1 << layer; Ray ray = Camera.main.ScreenPointToRay(pointer); RaycastHit hit; if (!Physics.Raycast(ray, out hit, Mathf.Infinity, mask)) { return(null); } SelectTower(hit.transform.GetComponent <UnitTower>()); return(instance.selectedTower); }
//apply the ability effect, damage, stun, buff and so on IEnumerator ApplyAbilityEffect(Ability ab, Vector3 pos, Unit tgtUnit = null) { yield return(new WaitForSeconds(ab.effectDelay)); LayerMask mask1 = 1 << LayerManager.LayerTower(); LayerMask mask2 = 1 << LayerManager.LayerCreep(); LayerMask mask3 = 1 << LayerManager.LayerCreepF(); LayerMask mask = mask1 | mask2 | mask3; List <Unit> creepList = new List <Unit>(); List <Unit> towerList = new List <Unit>(); if (tgtUnit == null) { float radius = ab.requireTargetSelection ? ab.GetAOERadius() : Mathf.Infinity; Collider[] cols = Physics.OverlapSphere(pos, radius, mask); if (cols.Length > 0) { for (int i = 0; i < cols.Length; i++) { Unit unit = cols[i].gameObject.GetComponent <Unit>(); if (unit.unitC != null) { creepList.Add(unit.unitC); } if (unit.unitT != null) { towerList.Add(unit.unitT); } } } } else { creepList.Add(tgtUnit); towerList.Add(tgtUnit); } AbilityEffect eff = ab.GetActiveEffect(); for (int n = 0; n < creepList.Count; n++) { if (eff.damageMax > 0) { creepList[n].ApplyDamage(Random.Range(eff.damageMin, eff.damageMax)); } else if (eff.stunChance > 0 && eff.duration > 0) { if (Random.Range(0f, 1f) < eff.stunChance) { creepList[n].ApplyStun(eff.duration); } } else if (eff.slow.IsValid()) { creepList[n].ApplySlow(eff.slow); } else if (eff.dot.GetTotalDamage() > 0) { creepList[n].ApplyDot(eff.dot); } } for (int n = 0; n < towerList.Count; n++) { if (eff.duration > 0) { if (eff.damageBuff > 0) { towerList[n].ABBuffDamage(eff.damageBuff, eff.duration); } else if (eff.rangeBuff > 0) { towerList[n].ABBuffRange(eff.rangeBuff, eff.duration); } else if (eff.cooldownBuff > 0) { towerList[n].ABBuffCooldown(eff.cooldownBuff, eff.duration); } } else if (eff.HPGainMax > 0) { towerList[n].RestoreHP(Random.Range(eff.HPGainMin, eff.HPGainMax)); } } }
public static NodeTD[] GenerateNode(PlatformTD platform, float heightOffset) { if (instance == null) { Init(); } Transform platformT = platform.thisT; float gridSize = BuildManager.GetGridSize(); float scaleX = platform.thisT.localScale.x; float scaleZ = platform.thisT.localScale.z; int countX = (int)(scaleX / gridSize); int countZ = (int)(scaleZ / gridSize); float x = -scaleX / 2 / scaleX; float z = -scaleZ / 2 / scaleZ; Vector3 point = platformT.TransformPoint(new Vector3(x, 0, z)); thisT.position = point; thisT.rotation = platformT.rotation; thisT.position = thisT.TransformPoint(new Vector3(gridSize / 2, heightOffset, gridSize / 2)); NodeTD[] nodeGraph = new NodeTD[countZ * countX]; int counter = 0; for (int i = 0; i < countZ; i++) { for (int j = 0; j < countX; j++) { Vector3 pos = thisT.position; pos.y = pos.y + 5000; LayerMask mask = 1 << LayerManager.LayerTower(); RaycastHit hit1; if (Physics.Raycast(pos, Vector3.down, out hit1, Mathf.Infinity, ~mask)) { nodeGraph[counter] = new NodeTD(new Vector3(pos.x, hit1.point.y + heightOffset, pos.z), counter); } else { nodeGraph[counter] = new NodeTD(pos, counter); nodeGraph[counter].walkable = false; } counter += 1; thisT.position = thisT.TransformPoint(new Vector3(gridSize, 0, 0)); } thisT.position = thisT.TransformPoint(new Vector3(-(countX) * gridSize, 0, gridSize)); } thisT.position = Vector3.zero; thisT.rotation = Quaternion.identity; counter = 0; foreach (NodeTD cNode in nodeGraph) { if (cNode.walkable) { //check if there's anything within the point LayerMask mask = 1 << LayerManager.LayerPlatform(); mask |= 1 << LayerManager.LayerTower(); if (LayerManager.LayerTerrain() >= 0) { mask |= 1 << LayerManager.LayerTerrain(); } Collider[] cols = Physics.OverlapSphere(cNode.pos, gridSize * 0.45f, ~mask); if (cols.Length > 0) { cNode.walkable = false; counter += 1; } } } float neighbourDistance = 0; float neighbourRange; if (instance.connectDiagonalNeighbour) { neighbourRange = gridSize * 1.5f; } else { neighbourRange = gridSize * 1.1f; } counter = 0; //assign the neighouring node for each node in the grid foreach (NodeTD currentNode in nodeGraph) { //only if that node is walkable if (currentNode.walkable) { //create an empty array List <NodeTD> neighbourNodeList = new List <NodeTD>(); List <float> neighbourCostList = new List <float>(); NodeTD[] neighbour = new NodeTD[8]; int id = currentNode.ID; if (id > countX - 1 && id < countX * countZ - countX) { //print("middle rows"); if (id != countX) { neighbour[0] = nodeGraph[id - countX - 1]; } neighbour[1] = nodeGraph[id - countX]; neighbour[2] = nodeGraph[id - countX + 1]; neighbour[3] = nodeGraph[id - 1]; neighbour[4] = nodeGraph[id + 1]; neighbour[5] = nodeGraph[id + countX - 1]; neighbour[6] = nodeGraph[id + countX]; if (id != countX * countZ - countX - 1) { neighbour[7] = nodeGraph[id + countX + 1]; } } else if (id <= countX - 1) { //print("first row"); if (id != 0) { neighbour[0] = nodeGraph[id - 1]; } if (nodeGraph.Length > id + 1) { neighbour[1] = nodeGraph[id + 1]; } if (countZ > 0) { if (nodeGraph.Length > id + countX - 1) { neighbour[2] = nodeGraph[id + countX - 1]; } if (nodeGraph.Length > id + countX) { neighbour[3] = nodeGraph[id + countX]; } if (nodeGraph.Length > id + countX + 1) { neighbour[4] = nodeGraph[id + countX + 1]; } } } else if (id >= countX * countZ - countX) { //print("last row"); neighbour[0] = nodeGraph[id - 1]; if (id != countX * countZ - 1) { neighbour[1] = nodeGraph[id + 1]; } if (id != countX * (countZ - 1)) { neighbour[2] = nodeGraph[id - countX - 1]; } neighbour[3] = nodeGraph[id - countX]; neighbour[4] = nodeGraph[id - countX + 1]; } //scan through all the node in the grid foreach (NodeTD node in neighbour) { //if this the node is not currentNode if (node != null && node.walkable) { //if this node is within neighbour node range neighbourDistance = GetHorizontalDistance(currentNode.pos, node.pos); if (neighbourDistance < neighbourRange) { //if nothing's in the way between these two LayerMask mask = 1 << LayerManager.LayerPlatform(); mask |= 1 << LayerManager.LayerTower(); if (!Physics.Linecast(currentNode.pos, node.pos, ~mask)) { //if the slop is not too steep //if(Mathf.Abs(GetSlope(currentNode.pos, node.pos))<=maxSlope){ //add to list //if(!node.walkable) Debug.Log("error"); neighbourNodeList.Add(node); neighbourCostList.Add(neighbourDistance); //}//else print("too steep"); } //else print("something's in the way"); } //else print("out of range "+neighbourDistance); } //else print("unwalkable"); } //set the list as the node neighbours array currentNode.SetNeighbour(neighbourNodeList, neighbourCostList); //if(neighbourNodeList.Count==0) //Debug.Log("no heighbour. node number "+counter+" "+neighbourNodeList.Count); } counter += 1; } return(nodeGraph); }
public IEnumerator SupportRoutine() { supportRoutineRunning = true; LayerMask maskTarget = 0; if (subClass == _UnitSubClass.Tower) { maskTarget = 1 << LayerManager.LayerTower(); } else if (subClass == _UnitSubClass.Creep) { LayerMask mask1 = 1 << LayerManager.LayerCreep(); LayerMask mask2 = 1 << LayerManager.LayerCreepF(); maskTarget = mask1 | mask2; } while (true) { yield return(new WaitForSeconds(0.1f)); if (!dead) { List <Unit> tgtList = new List <Unit>(); Collider[] cols = Physics.OverlapSphere(thisT.position, GetRange(), maskTarget); if (cols.Length > 0) { for (int i = 0; i < cols.Length; i++) { Unit unit = cols[i].gameObject.GetComponent <Unit>(); if (!unit.dead) { tgtList.Add(unit); } } } for (int i = 0; i < buffedUnit.Count; i++) { Unit unit = buffedUnit[i]; if (unit == null || unit.dead) { buffedUnit.RemoveAt(i); i -= 1; } else if (!tgtList.Contains(unit)) { unit.UnBuff(GetBuff()); buffedUnit.RemoveAt(i); i -= 1; } } for (int i = 0; i < tgtList.Count; i++) { Unit unit = tgtList[i]; if (!buffedUnit.Contains(unit)) { unit.Buff(GetBuff()); buffedUnit.Add(unit); } } } } }
//Call by inherited class UnitTower, caching inherited UnitTower instance to this instance public void SetSubClass(UnitTower unit) { unitT = unit; subClass = _UnitSubClass.Tower; gameObject.layer = LayerManager.LayerTower(); }
//called in every frame, execute if there's an ability is selected and pending target selection //use only mouse input atm. void SelectAbilityTarget() { if (selectedAbilityID < 0) { return; } //only cast on terrain and platform LayerMask mask = 1 << LayerManager.LayerPlatform(); int terrainLayer = LayerManager.LayerTerrain(); if (terrainLayer >= 0) { mask |= 1 << terrainLayer; } Ability ability = abilityList[selectedAbilityID]; if (ability.singleUnitTargeting) { if (ability.targetType == Ability._TargetType.Hybrid) { mask |= 1 << LayerManager.LayerTower(); mask |= 1 << LayerManager.LayerCreep(); } else if (ability.targetType == Ability._TargetType.Friendly) { mask |= 1 << LayerManager.LayerTower(); } else if (ability.targetType == Ability._TargetType.Hostile) { mask |= 1 << LayerManager.LayerCreep(); } } #if UNITY_IPHONE || UNITY_ANDROID || UNITY_WP8 Unit targetUnit = null; if (Input.touchCount >= 1) { Camera mainCam = Camera.main; if (mainCam != null) { Ray ray = mainCam.ScreenPointToRay(Input.touches[0].position); RaycastHit hit; if (Physics.Raycast(ray, out hit, Mathf.Infinity, mask)) { currentIndicator.position = hit.point + new Vector3(0, 0.1f, 0); validTarget = true; if (ability.singleUnitTargeting) { targetUnit = hit.transform.GetComponent <Unit>(); if (targetUnit != null) { currentIndicator.position = targetUnit.thisT.position; } else { validTarget = false; } } } else { validTarget = false; } } } else { if (validTarget) { ActivateAbility(ability, currentIndicator.position, targetUnit); } else { GameControl.DisplayMessage("Invalid target for ability"); } ClearSelectedAbility(); } #else Camera mainCam = Camera.main; if (mainCam != null) { Ray ray = mainCam.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit, Mathf.Infinity, mask)) { currentIndicator.position = hit.point + new Vector3(0, 0.1f, 0); Unit targetUnit = null; validTarget = true; if (ability.singleUnitTargeting) { targetUnit = hit.transform.GetComponent <Unit>(); if (targetUnit != null) { currentIndicator.position = targetUnit.thisT.position; } else { validTarget = false; } } if (Input.GetMouseButtonDown(0)) { if (validTarget) { ActivateAbility(ability, currentIndicator.position, targetUnit); ClearSelectedAbility(); } else { GameControl.DisplayMessage("Invalid target for ability"); } } } } if (Input.GetMouseButtonDown(1)) { ClearSelectedAbility(); } #endif }
//called by any external component to build tower, uses buildInfo public static string BuildTower(UnitTower tower) { if (buildInfo == null) { return("Select a Build Point First"); } UnitTower sampleTower = GetSampleTower(tower); /***/ // check if there's energy reciving tower if (tower.electricityNeeded && !tower.electricityReciever && !tower.electricityFacility) { LayerMask maskTarget = 1 << LayerManager.LayerTower(); Collider[] cols = Physics.OverlapSphere(buildInfo.position, 1000 /*GetRange()*/, maskTarget); if (cols.Length > 0) { tower.electicitySources.Clear(); // find all electric facility for (int i = 0; i < cols.Length; i++) { // if it's not electric reciever skip if (!cols[i].gameObject.GetComponent <UnitTower>().electricityReciever) { continue; } //float test = cols[i].gameObject.GetComponent<UnitTower>().GetRange(); //float test2 = Vector3.Distance(cols[i].gameObject.GetComponent<UnitTower>().transform.position, buildInfo.position); // if this tower is in range of electricityReciever if (Vector3.Distance(cols[i].gameObject.GetComponent <UnitTower>().transform.position, buildInfo.position) <= cols[i].gameObject.GetComponent <UnitTower>().GetRange()) { tower.electicitySources.Add(cols[i].gameObject.GetComponent <UnitTower>()); } } if (tower.electicitySources.Count == 0) { // set electricity source for tower weapon return("There is not enough electricity"); } } else { return("There is not enough electricity"); } } /***/ //check if there are sufficient resource List <int> cost = sampleTower.GetCost(); int suffCost = ResourceManager.HasSufficientResource(cost); if (suffCost == -1) { ResourceManager.SpendResource(cost); GameObject towerObj = (GameObject)Instantiate(tower.gameObject, buildInfo.position, buildInfo.platform.thisT.rotation); UnitTower towerInstance = towerObj.GetComponent <UnitTower>(); towerInstance.InitTower(instance.towerCount += 1, buildInfo.platform); towerInstance.Build(); // if new electricity reciver is placed search for all towers in it's range and add itself as electricity source if (tower.electricityReciever) { LayerMask maskTarget = 1 << LayerManager.LayerTower(); Collider[] cols = Physics.OverlapSphere(buildInfo.position, tower.GetRange(), maskTarget); if (cols.Length > 0) { UnitTower tmp_tow; for (int i = 0; i < cols.Length; i++) { tmp_tow = cols[i].gameObject.GetComponent <UnitTower>(); if (tmp_tow.electricityReciever || tmp_tow.electricityFacility) { continue; } tmp_tow.electicitySources.Add(towerInstance); } } } //clear the build info and indicator for build manager ClearBuildPoint(); return(""); } return("Insufficient Resource"); }