private Tile AnalyseCoverSystem(Unit unit, List <Tile> walkableTilesInRange, List <Unit> allHostileInSight) { List <Tile> walkableTilesInRangeAlt = new List <Tile>(); //for cover system, secondary tiles with less cover List <Tile> halfCoveredList = new List <Tile>(); //a list for all the tiles with half Cover List <Tile> fullCoveredList = new List <Tile>(); //a list for all the tiles with full Cover if (allHostileInSight.Count == 0) { fullCoveredList = walkableTilesInRange; } else //if there are hostile in sight //loop through all the walkable, record their score based on { for (int i = 0; i < walkableTilesInRange.Count; i++) { Tile tile = walkableTilesInRange[i]; tile.hostileCount = 0; tile.coverScore = 0; //iterate through all hostile, add the count, and cover type to the tile, this will then be used in tile.GetCoverRating() when this loop is complete for (int n = 0; n < allHostileInSight.Count; n++) { // if the hostile is out of range, ignore it int hostileRange = allHostileInSight[n].GetMoveRange() + allHostileInSight[n].GetAttackRange(); if (GridManager.GetDistance(allHostileInSight[n].tile, tile) > hostileRange) { continue; } tile.hostileCount += 1; CoverSystem._CoverType coverType = CoverSystem.GetCoverType(allHostileInSight[n].tile, walkableTilesInRange[i]); if (coverType == CoverSystem._CoverType.Half) { tile.coverScore += 1; } else if (coverType == CoverSystem._CoverType.Full) { tile.coverScore += 2; } } //get cover rating for the tile //if score is >=2, the tile has full cover from all hostile, so add it to fullCoveredList //if score is >=1 && <2, the tile has half cover from all hostile, so add it to halfCoveredList //if anything <1, the tile is exposed to hostile in some manner if (tile.GetCoverRating() >= 2) { fullCoveredList.Add(tile); } else if (tile.GetCoverRating() >= 1) { halfCoveredList.Add(tile); } } } //if either of the CoveredList is not empty, replace walkableTilesInRange with that since there's no need to consider to move into tiles without cover if (fullCoveredList.Count != 0) { walkableTilesInRange = fullCoveredList; walkableTilesInRangeAlt = halfCoveredList; } else if (halfCoveredList.Count != 0) { walkableTilesInRange = halfCoveredList; } //if there are hostile if (allHostileInSight.Count > 0) { //fill up the walkableTilesInRange hostile list //then filter thru walkableTilesInRange, those that have a hostile in range will be add to a tilesWithHostileInRange List <Tile> tilesWithHostileInRange = new List <Tile>(); GridManager.SetupHostileInRangeforTile(unit, walkableTilesInRange); for (int i = 0; i < walkableTilesInRange.Count; i++) { if (walkableTilesInRange[i].GetHostileInRange().Count > 0) { tilesWithHostileInRange.Add(walkableTilesInRange[i]); } } if (tilesWithHostileInRange.Count == 0) { GridManager.SetupHostileInRangeforTile(unit, walkableTilesInRangeAlt); for (int i = 0; i < walkableTilesInRangeAlt.Count; i++) { if (walkableTilesInRangeAlt[i].GetHostileInRange().Count > 0) { tilesWithHostileInRange.Add(walkableTilesInRangeAlt[i]); } } } //if the tilesWithHostileInRange is not empty after the process, means there's tiles which the unit can move into and attack //return one of those in the tilesWithHostileInRange so the unit can attack if (tilesWithHostileInRange.Count > 0) { //if the unit current tile is one of those tiles with hostile, just stay put and attack if (tilesWithHostileInRange.Contains(unit.tile)) { //randomize it a bit so the unit do move around but not stay in place all the time if (Random.Range(0f, 1f) > 0.25f) { return(unit.tile); } } return(tilesWithHostileInRange[Random.Range(0, tilesWithHostileInRange.Count)]); } } return(null); }
private void CalculateChance() { if (calculated) { return; } calculated = true; float coverDodgeBonus = 0; float exposedCritBonus = 0; //if cover system is enabled, get the dodge and crit bonus if (GameControl.EnableCover()) { coverType = CoverSystem.GetCoverType(srcUnit.tile, tgtUnit.tile); if (coverType == CoverSystem._CoverType.Half) { coverDodgeBonus = CoverSystem.GetHalfCoverDodgeBonus(); } else if (coverType == CoverSystem._CoverType.Full) { coverDodgeBonus = CoverSystem.GetFullCoverDodgeBonus(); } else { exposedCritBonus = CoverSystem.GetExposedCritChanceBonus(); } } //calculate the hit chance float hit = !isMelee?srcUnit.GetHitChance() : srcUnit.GetHitChanceMelee(); float dodge = tgtUnit.GetDodgeChance() + coverDodgeBonus; hitChance = Mathf.Clamp(hit - dodge, 0f, 1f); //calculate the critical chance float critHit = (!isMelee ? srcUnit.GetCritChance() : srcUnit.GetCritChanceMelee()) + exposedCritBonus; float critAvoid = tgtUnit.GetCritAvoidance(); critChance = Mathf.Clamp(critHit - critAvoid, 0f, 1f); //calculate stun chance float stunHit = srcUnit.GetStunChance(); float stunAvoid = tgtUnit.GetStunAvoidance(); stunChance = Mathf.Clamp(stunHit - stunAvoid, 0f, 1f); //calculate silent chance float silentHit = srcUnit.GetSilentChance(); float silentAvoid = tgtUnit.GetSilentAvoidance(); silentChance = Mathf.Clamp(silentHit - silentAvoid, 0f, 1f); if (isOverwatch) { hitChance -= GameControl.GetOverwatchHitPenalty(); critHit -= GameControl.GetOverwatchCritPenalty(); } //check if flanking is enabled an applicable in this instance if (GameControl.EnableFlanking()) { //Vector2 dir=new Vector2(srcUnit.tile.pos.x-tgtUnit.tile.pos.x, srcUnit.tile.pos.z-tgtUnit.tile.pos.z); float angleTH = 180 - Mathf.Min(180, GameControl.GetFlankingAngle()); Quaternion attackRotation = Quaternion.LookRotation(tgtUnit.tile.GetPos() - srcUnit.tile.GetPos()); //Debug.Log(Quaternion.Angle(attackRotation, tgtUnit.thisT.rotation)+" "+angleTH); if (Quaternion.Angle(attackRotation, tgtUnit.thisT.rotation) < angleTH) { flanked = true; } } }