示例#1
0
        static Building CanSmash(Zombie zombie)
        {
            var map                 = zombie.Map;
            var basePos             = zombie.Position;
            var attackColonistsOnly = (ZombieSettings.Values.attackMode == AttackMode.OnlyColonists);
            var playerFaction       = Faction.OfPlayer;

            if (zombie.IsTanky)
            {
                var info = ZombieWanderer.GetMapInfo(map);
                var pos  = info.GetParent(basePos, false);
                if (pos.IsValid == false)
                {
                    pos = info.GetParent(basePos, true);
                }
                if (pos.IsValid && pos.GetEdifice(zombie.Map) is Building building && (building as Mineable) == null && (attackColonistsOnly == false || building.Faction == playerFaction))
                {
                    return(building);
                }
                return(null);
            }

            if (zombie.IsSuicideBomber == false && zombie.IsTanky == false && zombie.wasMapPawnBefore == false)
            {
                if (ZombieSettings.Values.smashMode == SmashMode.Nothing)
                {
                    return(null);
                }
                if (ZombieSettings.Values.smashOnlyWhenAgitated && zombie.state != ZombieState.Tracking && zombie.raging == 0)
                {
                    return(null);
                }
            }

            var nextIndex = Constants.random.Next(4);
            var c         = adjIndex4[prevIndex4];

            adjIndex4[prevIndex4] = adjIndex4[nextIndex];
            adjIndex4[nextIndex]  = c;
            prevIndex4            = nextIndex;

            if (ZombieSettings.Values.smashMode == SmashMode.DoorsOnly && zombie.IsSuicideBomber == false)
            {
                for (var i = 0; i < 4; i++)
                {
                    var pos = basePos + GenAdj.CardinalDirections[adjIndex4[i]];
                    if (pos.InBounds(map) == false)
                    {
                        continue;
                    }

                    if (pos.GetEdifice(map) is Building_Door door && door.Open == false && (attackColonistsOnly == false || door.Faction == playerFaction))
                    {
                        return(door);
                    }
                }
            }

            if (ZombieSettings.Values.smashMode == SmashMode.AnyBuilding || zombie.IsSuicideBomber || zombie.IsTanky)
            {
                var grid = map.thingGrid;
                for (var i = 0; i < 4; i++)
                {
                    var pos = basePos + GenAdj.CardinalDirections[adjIndex4[i]];
                    if (pos.InBounds(map) == false)
                    {
                        continue;
                    }

                    foreach (var thing in grid.ThingsListAtFast(pos))
                    {
                        var building = thing as Building;
                        if (building == null || (building as Mineable) != null)
                        {
                            continue;
                        }

                        var buildingDef      = building.def;
                        var factionCondition = (attackColonistsOnly == false || building.Faction == playerFaction);
                        if (buildingDef.useHitPoints && buildingDef.building.isNaturalRock == false && factionCondition)
                        {
                            if (zombie.IsSuicideBomber)
                            {
                                zombie.bombWillGoOff = true;
                                return(null);
                            }

                            return(building);
                        }
                    }
                }
            }

            return(null);
        }
示例#2
0
        // use rage grid to get to colonists ========================================================
        //
        public static bool RageMove(this JobDriver_Stumble driver, Zombie zombie, PheromoneGrid grid, List <IntVec3> possibleMoves, bool checkSmashable)
        {
            var info   = ZombieWanderer.GetMapInfo(zombie.Map);
            var newPos = info.GetParent(zombie.Position, false);

            if (newPos.IsValid == false)
            {
                // tanky can get directly through walls
                if (zombie.IsTanky)
                {
                    newPos = info.GetParent(zombie.Position, true);
                }

                if (newPos.IsValid == false)
                {
                    // no next move available
                    zombie.raging = 0;
                    return(Smash(driver, zombie, checkSmashable, false));
                }
            }

            // next tanky move is on a building
            if (newPos.GetEdifice(zombie.Map) is Building building && (building as Mineable) == null)
            {
                return(Smash(driver, zombie, checkSmashable, false));
            }

            // next move is on a door
            if (newPos.GetEdifice(zombie.Map) is Building_Door door)
            {
                if (door.Open)
                {
                    driver.destination = newPos;
                    return(false);
                }
                return(Smash(driver, zombie, checkSmashable, false));
            }

            // move into places where there is max 0/1 zombie already
            var destZombieCount = grid.GetZombieCount(newPos);

            if (destZombieCount < (zombie.IsTanky ? 1 : 2))
            {
                driver.destination = newPos;
                return(false);
            }

            // cannot move? lets smash things
            if (Smash(driver, zombie, checkSmashable, false))
            {
                return(true);
            }

            // cannot smash? look for alternative ways to move orthogonal
            if (TryToDivert(ref newPos, grid, zombie.Position, possibleMoves))
            {
                driver.destination = newPos;
                return(false);
            }

            // move to least populated place
            var zCount = possibleMoves.Select(p => grid.GetZombieCount(p)).Min();

            driver.destination = possibleMoves.Where(p => grid.GetZombieCount(p) == zCount).RandomElement();
            return(false);
        }