private void updateViewBlockerCells(bool blockView)
        {
#if InternalProfile
            ProfilingUtils.startProfiling("CompViewBlockerWatcher.updateViewBlockerCells");
#endif
            bool[] viewBlockerCells = mapCompSeenFog.viewBlockerCells;

            int mapSizeZ = map.Size.z;
            int mapSizeX = map.Size.x;

            CellRect occupiedRect = parent.OccupiedRect();
            for (int x = occupiedRect.minX; x <= occupiedRect.maxX; x++)
            {
                for (int z = occupiedRect.minZ; z <= occupiedRect.maxZ; z++)
                {
                    if (x >= 0 && z >= 0 && x <= mapSizeX && z <= mapSizeZ)
                    {
                        viewBlockerCells[(z * mapSizeZ) + x] = blockView;
                    }
                }
            }

            IntVec3 thisPos = parent.Position;
            if (Current.ProgramState == ProgramState.Playing)
            {
                if (map != null)
                {
                    List <CompFieldOfViewWatcher> cmpFovs = mapCompSeenFog.fowWatchers;
                    for (int i = 0; i < cmpFovs.Count; i++)
                    {
                        CompFieldOfViewWatcher cmpFov = cmpFovs[i];
                        int thingSightRange           = cmpFov.lastSightRange;

                        if (thingSightRange > 0)
                        {
                            IntVec3 thingPos = cmpFov.parent.Position;

                            int x = thisPos.x - thingPos.x;
                            int z = thisPos.z - thingPos.z;

                            if (x * x + z * z < thingSightRange * thingSightRange)
                            {
                                cmpFov.refreshFovTarget(ref thisPos);
                            }
                        }
                    }
                }
            }

#if InternalProfile
            ProfilingUtils.stopProfiling("CompViewBlockerWatcher.updateViewBlockerCells");
#endif
        }
        public override void MapComponentTick()
        {
#if InternalProfile
            ProfilingUtils.startProfiling("0-calibration");
            ProfilingUtils.stopProfiling("0-calibration");
#endif

            currentGameTick = Find.TickManager.TicksGame;

            if (!initialized)
            {
                initialized = true;

                init();
            }
        }
Beispiel #3
0
        public override void CompTick()
        {
#if InternalProfile
            ProfilingUtils.startProfiling("CompFieldOfViewWatcher.tick");
#endif
            if (disabled)
            {
                return;
            }

            int currentTick = Find.TickManager.TicksGame;

            if (pawn != null)
            {
                // Update at every position change and then after every 1/2 second from last position change.
                if (pawnPather == null)
                {
                    pawnPather = pawn.pather;
                }
                if (pawnPather != null && pawnPather.Moving)
                {
                    lastMovementTick = currentTick;
                }

                if (lastPosition != iv3Invalid && lastPosition != parent.Position)
                {
                    lastPositionUpdateTick = currentTick;
                    updateFoV();
                }
                else if ((currentTick - lastPositionUpdateTick) % 30 == 0)
                {
                    updateFoV();
                }

                // Non pawns update at most every 30 ticks or when position change.
            }
            else if ((lastPosition != iv3Invalid && lastPosition != parent.Position) || currentTick % 30 == 0)
            {
                updateFoV();
            }

#if InternalProfile
            ProfilingUtils.stopProfiling("CompFieldOfViewWatcher.tick");
#endif
        }
 public static void DoSingleTick_Prefix()
 {
     ProfilingUtils.startProfiling("1-DoSingleTick");
 }
Beispiel #5
0
        public void calculateFoV(Thing thing, int intRadius, bool peek)
        {
            if (!setupDone)
            {
                return;
            }

#if InternalProfile
            ProfilingUtils.startProfiling("CompFieldOfViewWatcher.calculateFoV");
#endif

            int mapSizeX = this.mapSizeX;
            int mapSizeZ = this.mapSizeZ;

            bool[] oldViewMap = viewMapSwitch ? this.viewMap1 : this.viewMap2;
            bool[] newViewMap = viewMapSwitch ? this.viewMap2 : this.viewMap1;

            IntVec3 position          = thing.Position;
            Faction faction           = lastFaction;
            short[] factionShownCells = lastFactionShownCells;

            int peekRadius = (peek ? intRadius + 1 : intRadius);

            // Calculate new view rect.
            CellRect occupedRect     = thing.OccupiedRect();
            int      newViewRectMinX = Math.Min(position.x - peekRadius, occupedRect.minX);
            int      newViewRectMaxX = Math.Max(position.x + peekRadius, occupedRect.maxX);
            int      newViewRectMinZ = Math.Min(position.z - peekRadius, occupedRect.minZ);
            int      newViewRectMaxZ = Math.Max(position.z + peekRadius, occupedRect.maxZ);

            int newViewWidth = newViewRectMaxX - newViewRectMinX + 1;
            int newViewArea  = newViewWidth * (newViewRectMaxZ - newViewRectMinZ + 1);


            int oldViewRectMinZ = viewRect.minZ;
            int oldViewRectMaxZ = viewRect.maxZ;
            int oldViewRectMinX = viewRect.minX;
            int oldViewRectMaxX = viewRect.maxX;

            int oldViewWidth = viewRect.Width;
            int oldViewArea  = viewRect.Area;


            // Create the new view map if needed.
            if (newViewMap == null || newViewMap.Length < newViewArea)
            {
                newViewMap = new bool[(int)(newViewArea * 1.20f)];
                if (viewMapSwitch)
                {
                    this.viewMap2 = newViewMap;
                }
                else
                {
                    this.viewMap1 = newViewMap;
                }
            }


#if InternalProfile
            ProfilingUtils.startProfiling("CompFieldOfViewWatcher.calculateFoV-seen");
#endif
            // Occupied cells are always visible.
            int occupiedX;
            int occupiedZ;
            int oldViewRectIdx;
            for (occupiedX = occupedRect.minX; occupiedX <= occupedRect.maxX; occupiedX++)
            {
                for (occupiedZ = occupedRect.minZ; occupiedZ <= occupedRect.maxZ; occupiedZ++)
                {
                    newViewMap[((occupiedZ - newViewRectMinZ) * newViewWidth) + (occupiedX - newViewRectMinX)] = true;
                    if (oldViewMap == null || occupiedX < oldViewRectMinX || occupiedZ < oldViewRectMinZ || occupiedX > oldViewRectMaxX || occupiedZ > oldViewRectMaxZ)
                    {
                        mapCompSeenFog.incrementSeen(faction, factionShownCells, (occupiedZ * mapSizeX) + occupiedX);
                    }
                    else
                    {
                        oldViewRectIdx = ((occupiedZ - oldViewRectMinZ) * oldViewWidth) + (occupiedX - oldViewRectMinX);
                        ref bool oldViewMapValue = ref oldViewMap[oldViewRectIdx];
                        if (!oldViewMapValue)
                        {
                            // Old cell was not visible. Increment seen counter in global grid.
                            mapCompSeenFog.incrementSeen(faction, factionShownCells, (occupiedZ * mapSizeX) + occupiedX);
                        }
                        else
                        {
                            // Old cell was already visible. Mark it to not be unseen.
                            oldViewMapValue = false;
                        }
                    }
                }
            }
Beispiel #6
0
        public float calcPawnSightRange(IntVec3 position, bool forTargeting, bool shouldMove)
        {
            if (pawn == null)
            {
                Log.Error("calcPawnSightRange performed on non pawn thing");
                return(0);
            }

#if InternalProfile
            ProfilingUtils.startProfiling("CompFieldOfViewWatcher.calcPawnSightRange");
#endif
            float sightRange = 0f;

            initMap();

            bool sleeping = !isMechanoid && pawn.CurJob != null && pawn.jobs.curDriver.asleep;

            if (!shouldMove && !sleeping && (pawnPather == null || !pawnPather.Moving))
            {
                Verb attackVerb = null;
                if (pawn.CurJob != null)
                {
                    JobDef jobDef = pawn.CurJob.def;
                    if (jobDef == JobDefOf.ManTurret)
                    {
                        Building_Turret mannedTurret = pawn.CurJob.targetA.Thing as Building_Turret;
                        if (mannedTurret != null)
                        {
                            attackVerb = mannedTurret.AttackVerb;
                        }
                    }
                    else if (jobDef == JobDefOf.AttackStatic || jobDef == JobDefOf.AttackMelee || jobDef == JobDefOf.Wait_Combat || jobDef == JobDefOf.Hunt)
                    {
                        if (pawn.equipment != null)
                        {
                            ThingWithComps primary = pawn.equipment.Primary;
                            if (primary != null && primary.def.IsRangedWeapon)
                            {
                                attackVerb = primary.GetComp <CompEquippable>().PrimaryVerb;
                            }
                        }
                    }
                }

                if (attackVerb != null && attackVerb.verbProps.range > baseViewRange && attackVerb.verbProps.requireLineOfSight && attackVerb.EquipmentSource.def.IsRangedWeapon)
                {
                    float attackVerbRange = attackVerb.verbProps.range;
                    if (baseViewRange < attackVerbRange)
                    {
                        int ticksStanding = Find.TickManager.TicksGame - lastMovementTick;

                        float statValue     = pawn.GetStatValue(StatDefOf.AimingDelayFactor, true);
                        int   ticksToSearch = (attackVerb.verbProps.warmupTime * statValue).SecondsToTicks() * Mathf.RoundToInt((attackVerbRange - baseViewRange) / 2);

                        if (ticksStanding >= ticksToSearch)
                        {
                            sightRange = attackVerbRange * capacities.GetLevel(PawnCapacityDefOf.Sight);
                        }
                        else
                        {
                            int incValue = Mathf.RoundToInt((attackVerbRange - baseViewRange) * ((float)ticksStanding / ticksToSearch));

                            sightRange = (baseViewRange + incValue) * capacities.GetLevel(PawnCapacityDefOf.Sight);
                        }
                    }
                }
            }

            if (sightRange == 0f)
            {
                sightRange = baseViewRange * capacities.GetLevel(PawnCapacityDefOf.Sight);
            }

            if (!forTargeting && sleeping)
            {
                // Sleeping: sight reduced to 20% (if not for targeting).
                sightRange *= 0.2f;
            }
            // TODO: Apply moving penality?

            /*else if (!calcOnlyBase && pawnPather.Moving) {
             *      // When moving, sight reduced to 90%s.
             *      sightRange *= 0.9f;
             * }
             */

            // Check if standing on an affect view object.
            List <CompAffectVision> compsAffectVision = mapCompSeenFog.compAffectVisionGrid[(position.z * mapSizeX) + position.x];
            int compsCount = compsAffectVision.Count;
            for (int i = 0; i < compsCount; i++)
            {
                sightRange *= compsAffectVision[i].Props.fovMultiplier;
            }

            // Additional dark and weather debuff.
            if (!isMechanoid)
            {
                float currGlow = glowGrid.GameGlowAt(position);
                if (currGlow != 1f)
                {
                    float darkModifier = 0.6f;
                    // Each bionic eye reduce the dark debuff by 20.
                    int hediffsCount = hediffs.Count;
                    for (int i = 0; i < hediffsCount; i++)
                    {
                        if (hediffs[i].def == HediffDefOf.BionicEye)
                        {
                            darkModifier += 0.2f;
                        }
                    }

                    // Apply only if to debuff.
                    if (darkModifier < 1f)
                    {
                        // Adjusted to glow (100% full light - 60% dark).
                        sightRange *= Mathf.Lerp(darkModifier, 1f, currGlow);
                    }
                }

                if (!roofGrid.Roofed(position.x, position.z))
                {
                    float weatherFactor = weatherManager.CurWeatherAccuracyMultiplier;
                    if (weatherFactor != 1f)
                    {
                        // Weather factor is applied by half.
                        sightRange *= Mathf.Lerp(0.5f, 1f, weatherFactor);
                    }
                }
            }

            // Mininum sight.
            if (sightRange < 1f)
            {
                return(1);
            }

#if InternalProfile
            ProfilingUtils.stopProfiling("CompFieldOfViewWatcher.calcPawnSightRange");
#endif
            return(sightRange);
        }
Beispiel #7
0
        public void updateFoV(bool forceUpdate = false)
        {
            if (disabled || !setupDone || Current.ProgramState == ProgramState.MapInitializing)
            {
                return;
            }

#if InternalProfile
            ProfilingUtils.startProfiling("CompFieldOfViewWatcher.updateFoV");
#endif
            ThingWithComps thing       = base.parent;
            IntVec3        newPosition = thing.Position;

            if (thing != null && thing.Spawned && thing.Map != null && newPosition != iv3Invalid)
            {
                initMap();

                Faction newFaction = thing.Faction;

                if (newFaction != null && (pawn == null || !pawn.Dead))
                {
                    // Faction things or alive pawn!

                    if (pawn != null)
                    {
                        // Alive Pawns!

                        int  sightRange;
                        bool isPeeking = false;
                        if (raceProps != null && raceProps.Animal && (pawn.playerSettings == null || pawn.playerSettings.Master == null || pawn.training == null || !pawn.training.HasLearned(TrainableDefOf.Release)))
                        {
                            // If animal, only those with a master set and release training can contribute to the faction FoW.
                            sightRange = -1;
                        }
                        else
                        {
                            sightRange = Mathf.RoundToInt(calcPawnSightRange(newPosition, false, false));

                            if ((pawnPather == null || !pawnPather.Moving) && pawn.CurJob != null)
                            {
                                JobDef jobDef = pawn.CurJob.def;
                                if (jobDef == JobDefOf.AttackStatic || jobDef == JobDefOf.AttackMelee || jobDef == JobDefOf.Wait_Combat || jobDef == JobDefOf.Hunt)
                                {
                                    isPeeking = true;
                                }
                            }
                        }

                        if (!calculated || forceUpdate || newFaction != lastFaction || newPosition != lastPosition || sightRange != lastSightRange || isPeeking != lastIsPeeking)
                        {
                            calculated     = true;
                            lastPosition   = newPosition;
                            lastSightRange = sightRange;
                            lastIsPeeking  = isPeeking;

                            // Faction change. Unseen and clear old seen cells
                            if (lastFaction != newFaction)
                            {
                                if (lastFaction != null)
                                {
                                    unseeSeenCells(lastFaction, lastFactionShownCells);
                                }
                                lastFaction           = newFaction;
                                lastFactionShownCells = mapCompSeenFog.getFactionShownCells(newFaction);
                            }


                            if (sightRange != -1)
                            {
                                calculateFoV(thing, sightRange, isPeeking);
                            }
                            else
                            {
                                unseeSeenCells(lastFaction, lastFactionShownCells);
                            }
                        }
                    }
                    else if (turret != null && compMannable == null)
                    {
                        // Automatic turrets!

                        int sightRange = Mathf.RoundToInt(turret.GunCompEq.PrimaryVerb.verbProps.range);

                        if (Find.Storyteller.difficulty.difficulty >= 4 ||                         // Intense and Extreme difficulties disable FoV from turrets.
                            (compPowerTrader != null && !compPowerTrader.PowerOn) ||
                            (compRefuelable != null && !compRefuelable.HasFuel) ||
                            (compFlickable != null && !compFlickable.SwitchIsOn))
                        {
                            sightRange = 0;
                        }

                        if (!calculated || forceUpdate || newFaction != lastFaction || newPosition != lastPosition || sightRange != lastSightRange)
                        {
                            calculated     = true;
                            lastPosition   = newPosition;
                            lastSightRange = sightRange;

                            // Faction change. Unseen and clear old seen cells
                            if (lastFaction != newFaction)
                            {
                                if (lastFaction != null)
                                {
                                    unseeSeenCells(lastFaction, lastFactionShownCells);
                                }
                                lastFaction           = newFaction;
                                lastFactionShownCells = mapCompSeenFog.getFactionShownCells(newFaction);
                            }

                            if (sightRange != 0)
                            {
                                calculateFoV(thing, sightRange, false);
                            }
                            else
                            {
                                unseeSeenCells(lastFaction, lastFactionShownCells);
                                revealOccupiedCells();
                            }
                        }
                    }
                    else if (compProvideVision != null)
                    {
                        // Vision providers!

                        // TODO: Calculate range applying dark and weather debufs.
                        int sightRange = Mathf.RoundToInt(compProvideVision.Props.viewRadius);

                        if ((compPowerTrader != null && !compPowerTrader.PowerOn) ||
                            (compRefuelable != null && !compRefuelable.HasFuel) ||
                            (compFlickable != null && !compFlickable.SwitchIsOn))
                        {
                            sightRange = 0;
                        }

                        if (!calculated || forceUpdate || newFaction != lastFaction || newPosition != lastPosition || sightRange != lastSightRange)
                        {
                            calculated     = true;
                            lastPosition   = newPosition;
                            lastSightRange = sightRange;

                            // Faction change. Unseen and clear old seen cells
                            if (lastFaction != newFaction)
                            {
                                if (lastFaction != null)
                                {
                                    unseeSeenCells(lastFaction, lastFactionShownCells);
                                }
                                lastFaction           = newFaction;
                                lastFactionShownCells = mapCompSeenFog.getFactionShownCells(newFaction);
                            }

                            if (sightRange != 0)
                            {
                                calculateFoV(thing, sightRange, false);
                            }
                            else
                            {
                                unseeSeenCells(lastFaction, lastFactionShownCells);
                                revealOccupiedCells();
                            }
                        }
                    }
                    else if (building != null)
                    {
                        // Generic building.

                        int sightRange = 0;

                        if (!calculated || forceUpdate || newFaction != lastFaction || newPosition != lastPosition || sightRange != lastSightRange)
                        {
                            calculated     = true;
                            lastPosition   = newPosition;
                            lastSightRange = sightRange;

                            // Faction change. Unseen and clear old seen cells
                            if (lastFaction != newFaction)
                            {
                                if (lastFaction != null)
                                {
                                    unseeSeenCells(lastFaction, lastFactionShownCells);
                                }
                                lastFaction           = newFaction;
                                lastFactionShownCells = mapCompSeenFog.getFactionShownCells(newFaction);
                            }

                            unseeSeenCells(lastFaction, lastFactionShownCells);
                            revealOccupiedCells();
                        }
                    }
                    else
                    {
                        Log.Warning("Non disabled thing... " + parent.ThingID);
                    }
                }
                else if (newFaction != lastFaction)
                {
                    // Faction change (from a faction to nothing). Unseen and clear old seen cells
                    if (lastFaction != null)
                    {
                        unseeSeenCells(lastFaction, lastFactionShownCells);
                    }
                    lastFaction           = newFaction;
                    lastFactionShownCells = mapCompSeenFog.getFactionShownCells(newFaction);
                }
            }

#if InternalProfile
            ProfilingUtils.stopProfiling("CompFieldOfViewWatcher.updateFoV");
#endif
        }
        public static void computeFieldOfViewWithShadowCasting(
            int startX, int startY, int radius,
            bool[] viewBlockerCells, int maxX, int maxY,
            bool handleSeenAndCache, MapComponentSeenFog mapCompSeenFog, Faction faction, short[] factionShownCells,
            bool[] fovGrid, int fovGridMinX, int fovGridMinY, int fovGridWidth,
            bool[] oldFovGrid, int oldFovGridMinX, int oldFovGridMaxX, int oldFovGridMinY, int oldFovGridMaxY, int oldFovGridWidth,
            byte specificOctant = 255,
            int targetX         = -1,
            int targetY         = -1)
        {
#if InternalProfile
            ProfilingUtils.startProfiling("computeFieldOfViewWithShadowCasting");
#endif
            int r_r = radius * radius;

            if (specificOctant == 255)
            {
                for (byte octant = 0; octant < 8; ++octant)
                {
                    computeFieldOfViewInOctantZero(
                        octant,
                        fovGrid,
                        fovGridMinX,
                        fovGridMinY,
                        fovGridWidth,
                        oldFovGrid,
                        oldFovGridMinX,
                        oldFovGridMaxX,
                        oldFovGridMinY,
                        oldFovGridMaxY,
                        oldFovGridWidth,
                        radius,
                        r_r,
                        startX,
                        startY,
                        maxX,
                        maxY,
                        viewBlockerCells,
                        handleSeenAndCache, mapCompSeenFog, faction, factionShownCells,
                        targetX,
                        targetY,
                        0, 1, 1, 1, 0);
                }
            }
            else
            {
                computeFieldOfViewInOctantZero(
                    specificOctant,
                    fovGrid,
                    fovGridMinX,
                    fovGridMinY,
                    fovGridWidth,
                    oldFovGrid,
                    oldFovGridMinX,
                    oldFovGridMaxX,
                    oldFovGridMinY,
                    oldFovGridMaxY,
                    oldFovGridWidth,
                    radius,
                    r_r,
                    startX,
                    startY,
                    maxX,
                    maxY,
                    viewBlockerCells,
                    handleSeenAndCache, mapCompSeenFog, faction, factionShownCells,
                    targetX,
                    targetY,
                    0, 1, 1, 1, 0);
            }

#if InternalProfile
            ProfilingUtils.stopProfiling("computeFieldOfViewWithShadowCasting");
#endif
        }