Exemple #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);
        }
Exemple #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);
        }
Exemple #3
0
        public static bool Track(this JobDriver_Stumble driver, Zombie zombie, PheromoneGrid grid)
        {
            if (zombie.EveryNTick(NthTick.Every60) || fadeOff == -1)
            {
                fadeOff                = Tools.PheromoneFadeoff();
                wasColonistFadeoff     = fadeOff / 6;
                agitatedFadeoff        = fadeOff / 4;
                checkSmashableFadeoff1 = agitatedFadeoff / 4;
                checkSmashableFadeoff2 = agitatedFadeoff * 3 / 4;
            }

            var trackingMoves = new List <IntVec3>(8);
            var currentTicks  = Tools.Ticks();
            var timeDelta     = long.MaxValue;

            var fmin = long.MaxValue;

            if (zombie.raging == 0)
            {
                for (var i = 0; i < 8; i++)
                {
                    var pos = zombie.Position + GenAdj.AdjacentCells[i];
                    if (zombie.HasValidDestination(pos))
                    {
                        var f     = zombie.wasMapPawnBefore ? wasColonistFadeoff : fadeOff;
                        var tdiff = currentTicks - grid.GetTimestamp(pos);
                        fmin = Math.Min(fmin, tdiff);
                        if (tdiff < f)
                        {
                            trackingMoves.Add(pos);
                        }
                    }
                }
            }

            if (trackingMoves.Count > 0)
            {
                trackingMoves.Sort((p1, p2) => grid.GetTimestamp(p2).CompareTo(grid.GetTimestamp(p1)));
                trackingMoves = trackingMoves.Take(Constants.NUMBER_OF_TOP_MOVEMENT_PICKS).ToList();
                trackingMoves = trackingMoves.OrderBy(p => grid.GetZombieCount(p)).ToList();
                var nextMove = trackingMoves.First();
                timeDelta = currentTicks - (grid.GetTimestamp(nextMove));

                driver.destination = nextMove;
                if (zombie.state == ZombieState.Wandering)
                {
                    Tools.ChainReact(zombie.Map, zombie.Position, nextMove);
                    if (timeDelta <= agitatedFadeoff)
                    {
                        CastBrainzThought(zombie);
                    }
                }
                zombie.state = ZombieState.Tracking;
            }

            if (driver.destination.IsValid == false)
            {
                zombie.state = ZombieState.Wandering;
            }

            if (zombie.wasMapPawnBefore)
            {
                return(true);
            }

            var checkSmashable = timeDelta >= checkSmashableFadeoff1 && timeDelta < checkSmashableFadeoff2;

            if (ZombieSettings.Values.smashOnlyWhenAgitated)
            {
                checkSmashable &= (zombie.state == ZombieState.Tracking || zombie.raging > 0);
            }

            return(checkSmashable);
        }
Exemple #4
0
        public static IEnumerator AssignNewGraphics(Zombie zombie)
        {
            zombie.Drawer.renderer.graphics.ResolveAllGraphics();
            yield return(null);

            var headPath = FixGlowingEyeOffset(zombie);

            if (zombie.IsSuicideBomber)
            {
                zombie.lastBombTick = Find.TickManager.TicksAbs + Rand.Range(0, (int)zombie.bombTickingInterval);
            }

            if (ZombieSettings.Values.useCustomTextures)
            {
                var renderPrecedence = 0;
                var bodyPath         = "Zombie/Naked_" + zombie.story.bodyType.ToString();
                var color            = zombie.isToxicSplasher ? "toxic" : (zombie.isMiner ? "miner" : GraphicToolbox.RandomSkinColorString());
                yield return(null);

                var bodyRequest = new GraphicRequest(typeof(VariableGraphic), bodyPath, ShaderDatabase.CutoutSkin, Vector2.one, Color.white, Color.white, null, renderPrecedence, new List <ShaderParameter>());
                yield return(null);

                var maxStainPoints = ZombieStains.maxStainPoints;
                if (zombie.isMiner)
                {
                    maxStainPoints *= 2;
                }

                var customBodyGraphic = new VariableGraphic {
                    bodyColor = color
                };
                yield return(null);

                customBodyGraphic.Init(VariableGraphic.minimal);
                yield return(null);

                for (var i = 0; i < 4; i++)
                {
                    var j  = 0;
                    var it = customBodyGraphic.InitIterativ(bodyRequest, i, maxStainPoints);
                    while (it.MoveNext())
                    {
                        yield return(null);

                        j++;
                    }
                }
                zombie.Drawer.renderer.graphics.nakedGraphic = customBodyGraphic;

                var headRequest = new GraphicRequest(typeof(VariableGraphic), headPath, ShaderDatabase.CutoutSkin, Vector2.one, Color.white, Color.white, null, renderPrecedence, new List <ShaderParameter>());
                yield return(null);

                var customHeadGraphic = new VariableGraphic {
                    bodyColor = color
                };
                yield return(null);

                customHeadGraphic.Init(VariableGraphic.minimal);
                yield return(null);

                for (var i = 0; i < 4; i++)
                {
                    var j  = 0;
                    var it = customHeadGraphic.InitIterativ(headRequest, i, maxStainPoints);
                    while (it.MoveNext())
                    {
                        yield return(null);

                        j++;
                    }
                }
                zombie.Drawer.renderer.graphics.headGraphic = customHeadGraphic;
            }

            yield return(null);
        }
Exemple #5
0
        private static BodyTypeDef PrepareZombieType(Zombie zombie, ZombieType overwriteType)
        {
            var zombieTypeInitializers = new Pair <float, Func <BodyTypeDef> >[]
            {
                // suicide bomber
                new Pair <float, Func <BodyTypeDef> >(
                    ZombieSettings.Values.suicideBomberChance / 2f,
                    delegate
                {
                    zombie.bombTickingInterval = 60f;
                    zombie.lastBombTick        = Find.TickManager.TicksAbs + Rand.Range(0, (int)zombie.bombTickingInterval);
                    //
                    zombie.gender = Gender.Male;
                    return(BodyTypeDefOf.Hulk);
                }
                    ),

                // toxic splasher
                new Pair <float, Func <BodyTypeDef> >(
                    ZombieSettings.Values.toxicSplasherChance / 2f,
                    delegate
                {
                    zombie.isToxicSplasher = true;
                    //
                    switch (Rand.RangeInclusive(1, 3))
                    {
                    case 1:
                        zombie.gender = Gender.Male;
                        return(BodyTypeDefOf.Male);

                    case 2:
                        zombie.gender = Gender.Female;
                        return(BodyTypeDefOf.Female);

                    case 3:
                        zombie.gender = Gender.Male;
                        return(BodyTypeDefOf.Thin);
                    }
                    return(null);
                }
                    ),

                // tanky operator
                new Pair <float, Func <BodyTypeDef> >(
                    ZombieSettings.Values.tankyOperatorChance / 3f,
                    delegate
                {
                    zombie.hasTankyShield = 1f;
                    zombie.hasTankyHelmet = 1f;
                    zombie.hasTankySuit   = 1f;
                    //
                    zombie.gender = Gender.Male;
                    return(BodyTypeDefOf.Fat);
                }
                    ),

                // miner
                new Pair <float, Func <BodyTypeDef> >(
                    ZombieSettings.Values.minerChance / 2f,
                    delegate
                {
                    zombie.isMiner = true;
                    return(SetRandomBody(zombie));
                }
                    ),

                // default ordinary zombie
                new Pair <float, Func <BodyTypeDef> >(
                    float.MaxValue,
                    delegate
                {
                    return(SetRandomBody(zombie));
                }
                    )
            };

            if (overwriteType != ZombieType.Random)
            {
                var initializer = zombieTypeInitializers[(int)overwriteType];
                return(initializer.Second());
            }

            var         typeChance = Rand.Value;
            BodyTypeDef bodyType   = null;

            foreach (var initializer in zombieTypeInitializers)
            {
                typeChance -= initializer.First;
                if (typeChance < 0f)
                {
                    bodyType = initializer.Second();
                    break;
                }
            }
            return(bodyType);
        }
Exemple #6
0
 public ZombieLeaner(Pawn pawn) : base(pawn)
 {
     zombie = pawn as Zombie;
 }