Exemplo n.º 1
0
        private bool TryCollideWithRoof(IntVec3 cell)
        {
            if (!cell.Roofed(Map))
            {
                return(false);
            }

            var bounds = CE_Utility.GetBoundsFor(cell, cell.GetRoof(Map));

            float dist;

            if (!bounds.IntersectRay(ShotLine, out dist))
            {
                return(false);
            }
            if (dist * dist > ExactMinusLastPos.sqrMagnitude)
            {
                return(false);
            }

            var point = ShotLine.GetPoint(dist);

            ExactPosition = point;
            landed        = true;

            if (DebugViewSettings.drawInterceptChecks)
            {
                MoteMaker.ThrowText(cell.ToVector3Shifted(), Map, "x", Color.red);
            }

            Impact(null);
            return(true);
        }
Exemplo n.º 2
0
        public float AdjustShotHeight(Thing caster, LocalTargetInfo target, ref float shotHeight)
        {
            /* TODO:  This really should determine how much the shooter needs to rise up for a *good* shot.
             * If we're shooting at something tall, we might not need to rise at all, if we're shooting at
             * something short, we might need to rise *more* than just above the cover.  This at least handles
             * cases where we're below cover, but the taret is taller than the cover */
            GetHighestCoverAndSmokeForTarget(target, out Thing cover, out float smoke);
            var shooterHeight         = CE_Utility.GetBoundsFor(caster).max.y;
            var coverHeight           = CE_Utility.GetBoundsFor(cover).max.y;
            var centerOfVisibleTarget = (CE_Utility.GetBoundsFor(target.Thing).max.y - coverHeight) / 2 + coverHeight;

            if (centerOfVisibleTarget > shotHeight)
            {
                if (centerOfVisibleTarget > shooterHeight)
                {
                    centerOfVisibleTarget = shooterHeight;
                }
                float distance = target.Thing.Position.DistanceTo(caster.Position);
                // float wobble = Mathf.Atan2(UnityEngine.Random.Range(shotHeight-centerOfVisibleTarget, centerOfVisibleTarget - shotHeight), distance);
                float triangleHeight = centerOfVisibleTarget - shotHeight;
                float wobble         = -Mathf.Atan2(triangleHeight, distance);
                // TODO: Add inaccuracy for not standing in as natural a position
                shotHeight = centerOfVisibleTarget;
                return(wobble);
            }
            return(0);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Tries to impact the thing based on whether it intersects the given flight path. Trees have RNG chance to not collide even on intersection.
        /// </summary>
        /// <param name="thing">What to impact</param>
        /// <returns>True if impact occured, false otherwise</returns>
        private bool TryCollideWith(Thing thing)
        {
            if (thing == launcher && !canTargetSelf)
            {
                return(false);
            }

            var   bounds = CE_Utility.GetBoundsFor(thing);
            float dist;

            if (!bounds.IntersectRay(ShotLine, out dist))
            {
                return(false);
            }
            if (dist * dist > ExactMinusLastPos.sqrMagnitude)
            {
                return(false);
            }

            // Trees and bushes have RNG chance to collide
            var plant = thing as Plant;

            if (plant != null)
            {
                //TODO: Remove fillPercent dependency because all fillPercents on trees are 0.25
                //Prevents trees near the shooter (e.g the shooter's cover) to be hit
                float chance = thing.def.fillPercent * ((thing.Position - OriginIV3).LengthHorizontal / 40);
                if (Controller.settings.DebugShowTreeCollisionChance)
                {
                    MoteMaker.ThrowText(thing.Position.ToVector3Shifted(), thing.Map, chance.ToString());
                }
                if (!Rand.Chance(chance))
                {
                    return(false);
                }
            }

            var point = ShotLine.GetPoint(dist);

            if (!point.InBounds(this.Map))
            {
                Log.Error("TryCollideWith out of bounds point from ShotLine: obj " + thing.ThingID + ", proj " + this.ThingID + ", dist " + dist + ", point " + point);
            }

            ExactPosition = point;
            landed        = true;

            if (DebugViewSettings.drawInterceptChecks)
            {
                MoteMaker.ThrowText(thing.Position.ToVector3Shifted(), thing.Map, "x", Color.red);
            }

            Impact(thing);
            return(true);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Tries to impact the thing based on whether it intersects the given flight path. Trees have RNG chance to not collide even on intersection.
        /// </summary>
        /// <param name="thing">What to impact</param>
        /// <returns>True if impact occured, false otherwise</returns>
        private bool TryCollideWith(Thing thing)
        {
            if (thing == launcher && !canTargetSelf)
            {
                return(false);
            }

            var bounds = CE_Utility.GetBoundsFor(thing);

            if (!bounds.IntersectRay(ShotLine, out var dist))
            {
                return(false);
            }
            if (dist * dist > ExactMinusLastPos.sqrMagnitude)
            {
                return(false);
            }

            // Trees and bushes have RNG chance to collide
            if (thing is Plant)
            {
                //Prevents trees near the shooter (e.g the shooter's cover) to be hit
                var accuracyFactor = def.projectile.alwaysFreeIntercept ? 1 : (thing.Position - OriginIV3).LengthHorizontal / 40 * AccuracyFactor;
                var chance         = thing.def.fillPercent * accuracyFactor;
                if (Controller.settings.DebugShowTreeCollisionChance)
                {
                    MoteMaker.ThrowText(thing.Position.ToVector3Shifted(), thing.Map, chance.ToString());
                }
                if (!Rand.Chance(chance))
                {
                    return(false);
                }
            }

            var point = ShotLine.GetPoint(dist);

            if (!point.InBounds(Map))
            {
                Log.Error("TryCollideWith out of bounds point from ShotLine: obj " + thing.ThingID + ", proj " + ThingID + ", dist " + dist + ", point " + point);
            }

            ExactPosition = point;
            landed        = true;

            if (Controller.settings.DebugDrawInterceptChecks)
            {
                MoteMaker.ThrowText(thing.Position.ToVector3Shifted(), thing.Map, "x", Color.red);
            }

            Impact(thing);
            return(true);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Tries to impact the thing based on whether it intersects the given flight path. Trees have RNG chance to not collide even on intersection.
        /// </summary>
        /// <param name="thing">What to impact</param>
        /// <param name="shotLine">Projectile's path of travel</param>
        /// <returns>True if impact occured, false otherwise</returns>
        private bool TryCollideWith(Thing thing, Ray shotLine)
        {
            if (thing == launcher && !canTargetSelf)
            {
                return(false);
            }

            // Trees have RNG chance to collide
            if (thing.IsTree())
            {
                float chance = thing.def.fillPercent * ((thing.Position - OriginIV3).LengthHorizontal / 40);
                if (Controller.settings.DebugShowTreeCollisionChance)
                {
                    MoteMaker.ThrowText(thing.Position.ToVector3Shifted(), thing.Map, chance.ToString());
                }
                if (!Rand.Chance(chance))
                {
                    return(false);
                }
            }
            else
            {
                var bounds = CE_Utility.GetBoundsFor(thing);
                if (!bounds.IntersectRay(shotLine))
                {
                    return(false);
                }
            }


            if (DebugViewSettings.drawInterceptChecks)
            {
                MoteMaker.ThrowText(thing.Position.ToVector3Shifted(), thing.Map, "x", Color.red);
            }
            Impact(thing);
            return(true);
        }
Exemplo n.º 6
0
        // Added targetThing to parameters so we can calculate its height
        private bool CanHitCellFromCellIgnoringRange(Vector3 shotSource, IntVec3 targetLoc, Thing targetThing = null)
        {
            // Vanilla checks
            if (verbProps.mustCastOnOpenGround && (!targetLoc.Standable(caster.Map) || caster.Map.thingGrid.CellContains(targetLoc, ThingCategory.Pawn)))
            {
                return(false);
            }
            if (verbProps.requireLineOfSight)
            {
                // Calculate shot vector
                Vector3 targetPos;
                if (targetThing != null)
                {
                    Vector3 targDrawPos = targetThing.DrawPos;
                    targetPos = new Vector3(targDrawPos.x, new CollisionVertical(targetThing).Max, targDrawPos.z);
                    var targPawn = targetThing as Pawn;
                    if (targPawn != null)
                    {
                        targetPos += targPawn.Drawer.leaner.LeanOffset * 0.6f;
                    }
                }
                else
                {
                    targetPos = targetLoc.ToVector3Shifted();
                }
                Ray shotLine = new Ray(shotSource, (targetPos - shotSource));

                // Create validator to check for intersection with partial cover
                var aimMode = CompFireModes?.CurrentAimMode;

                Predicate <IntVec3> CanShootThroughCell = (IntVec3 cell) =>
                {
                    Thing cover = cell.GetFirstPawn(caster.Map) ?? cell.GetCover(caster.Map);

                    if (cover != null && cover != ShooterPawn && cover != caster && cover != targetThing && !cover.IsPlant() && !(cover is Pawn && cover.HostileTo(caster)))
                    {
                        // Skip this check entirely if we're doing suppressive fire and cell is adjacent to target
                        if ((VerbPropsCE.ignorePartialLoSBlocker || aimMode == AimMode.SuppressFire) && cover.def.Fillage != FillCategory.Full)
                        {
                            return(true);
                        }

                        Bounds bounds = CE_Utility.GetBoundsFor(cover);

                        // Simplified calculations for adjacent cover for gameplay purposes
                        if (cover.def.Fillage != FillCategory.Full && cover.AdjacentTo8WayOrInside(caster))
                        {
                            // Sanity check to prevent stuff behind us blocking LoS
                            var cellTargDist = cell.DistanceTo(targetLoc);
                            var shotTargDist = shotSource.ToIntVec3().DistanceTo(targetLoc);

                            if (shotTargDist > cellTargDist)
                            {
                                return(cover is Pawn || bounds.size.y < shotSource.y);
                            }
                        }

                        // Check for intersect
                        if (bounds.IntersectRay(shotLine))
                        {
                            if (Controller.settings.DebugDrawPartialLoSChecks)
                            {
                                caster.Map.debugDrawer.FlashCell(cell, 0, bounds.extents.y.ToString());
                            }
                            return(false);
                        }

                        if (Controller.settings.DebugDrawPartialLoSChecks)
                        {
                            caster.Map.debugDrawer.FlashCell(cell, 0.7f, bounds.extents.y.ToString());
                        }
                    }

                    return(true);
                };

                // Add validator to parameters
                foreach (IntVec3 curCell in SightUtility.GetCellsOnLine(shotSource, targetLoc.ToVector3(), caster.Map))
                {
                    if (Controller.settings.DebugDrawPartialLoSChecks)
                    {
                        caster.Map.debugDrawer.FlashCell(curCell, 0.4f);
                    }
                    if (curCell != shotSource.ToIntVec3() && curCell != targetLoc && !CanShootThroughCell(curCell))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
        // Added targetThing to parameters so we can calculate its height
        private bool CanHitCellFromCellIgnoringRange(IntVec3 sourceSq, IntVec3 rootCell, IntVec3 targetLoc, Thing targetThing = null, bool includeCorners = false)
        {
            // Vanilla checks
            if (this.verbProps.mustCastOnOpenGround && (!targetLoc.Standable(this.caster.Map) || this.caster.Map.thingGrid.CellContains(targetLoc, ThingCategory.Pawn)))
            {
                return(false);
            }
            if (this.verbProps.requireLineOfSight)
            {
                // Calculate shot vector
                Vector3 shotSource = ShotSource;

                Vector3 targetPos;
                if (targetThing != null)
                {
                    Vector3 targDrawPos = targetThing.DrawPos;
                    targetPos = new Vector3(targDrawPos.x, new CollisionVertical(targetThing).Max, targDrawPos.z);
                    var targPawn = targetThing as Pawn;
                    if (targPawn != null)
                    {
                        targetPos += targPawn.Drawer.leaner.LeanOffset * 0.5f;
                    }
                }
                else
                {
                    targetPos = targetLoc.ToVector3Shifted();
                }
                Ray shotLine = new Ray(shotSource, (targetPos - shotSource));

                // Create validator to check for intersection with partial cover
                var aimMode = CompFireModes?.CurrentAimMode;
                Func <IntVec3, bool> validator = delegate(IntVec3 cell)
                {
                    // Skip this check entirely if we're doing suppressive fire and cell is adjacent to target
                    if (VerbPropsCE.ignorePartialLoSBlocker || aimMode == AimMode.SuppressFire)
                    {
                        return(true);
                    }

                    Thing cover = cell.GetFirstPawn(caster.Map);

                    if (cover == null)
                    {
                        cover = cell.GetCover(caster.Map);
                    }

                    if (cover != null && cover != ShooterPawn && cover != caster && cover != targetThing && !cover.IsPlant())
                    {
                        //    var tr = cover.Position.AdjacentTo8Way(sourceSq);
                        //    Log.Message("cover: " + cover.ToString() + " value: " + tr.ToString());

                        if (VerbPropsCE.verbClass == typeof(Verb_ShootCEOneUse) && cover.def.fillPercent < 0.8)
                        {
                            return(true);
                        }

                        Bounds bounds = CE_Utility.GetBoundsFor(cover);
                        // Check for intersect
                        if (bounds.IntersectRay(shotLine))
                        {
                            if (Controller.settings.DebugDrawPartialLoSChecks)
                            {
                                caster.Map.debugDrawer.FlashCell(cell, 0, bounds.size.y.ToString());
                            }
                            return(false);
                        }
                        else if (Controller.settings.DebugDrawPartialLoSChecks)
                        {
                            caster.Map.debugDrawer.FlashCell(cell, 0.7f, bounds.size.y.ToString());
                        }

                        if (cover.def.fillPercent > 0.99)
                        {
                            return(false);
                        }
                    }
                    return(true);
                };
                // Add validator to parameters

                /*
                 * if (!includeCorners)
                 * {
                 *  if (!GenSight.LineOfSight(sourceSq, targetLoc, this.caster.Map, true, validator, 0, 0))
                 *  {
                 *      Log.Message("4.1 CanHitCellFromCellIgnoringRange: false");
                 *      return false;
                 *  }
                 * }
                 * else if (!GenSight.LineOfSightToEdges(sourceSq, targetLoc, this.caster.Map, true, validator))
                 * {
                 *  Log.Message("4.2 CanHitCellFromCellIgnoringRange: false");
                 *  return false;
                 * }
                 */
                var exactTargetSq = targetPos.ToIntVec3();
                foreach (IntVec3 curCell in GenSight.PointsOnLineOfSight(sourceSq, exactTargetSq))
                {
                    if (curCell != sourceSq && curCell != exactTargetSq && !validator(curCell))
                    {
                        return(false);
                    }
                }
                int c = 0;
                foreach (IntVec3 curCell2 in GenSight.PointsOnLineOfSight(rootCell, exactTargetSq))
                {
                    if (curCell2 != rootCell && curCell2 != exactTargetSq && !validator(curCell2))
                    {
                        c++;
                    }
                    if (c >= 2)
                    {
                        if (rootCell.z == exactTargetSq.z || rootCell.x == exactTargetSq.x)
                        {
                            return(false);
                        }
                    }
                }
            }
            return(true);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Tries to impact the thing based on whether it intersects the given flight path. Trees have RNG chance to not collide even on intersection.
        /// </summary>
        /// <param name="thing">What to impact</param>
        /// <returns>True if impact occured, false otherwise</returns>
        private bool TryCollideWith(Thing thing)
        {
            if (thing == launcher && !canTargetSelf)
            {
                return(false);
            }

            var   bounds = CE_Utility.GetBoundsFor(thing);
            float dist;

            if (!bounds.IntersectRay(ShotLine, out dist))
            {
                return(false);
            }
            if (dist * dist > ExactMinusLastPos.sqrMagnitude)
            {
                return(false);
            }

            // Trees and bushes have RNG chance to collide
            var plant = thing as Plant;

            if (plant != null)
            {
                //TODO: Remove fillPercent dependency because all fillPercents on trees are 0.25
                //Prevents trees near the shooter (e.g the shooter's cover) to be hit

                //Dependence to catch the tree from armorPenetration. Large calibers have less chance.
                var   propsCE               = def.projectile as ProjectilePropertiesCE;
                float penetrationAmount     = propsCE == null ? 0.1f : propsCE.armorPenetration;                            //Every projectile, which not use flyoverhead, require armorPenetration stat for calculating collision.
                float penetrationmultiplier = Mathf.Clamp(((thing.def.fillPercent * 3.2f) - penetrationAmount), 0.05f, 1f); // 2.5-3.5 good values for 0.20-0.30 fillpercent.
                float rangemultiplier       = ((thing.Position - OriginIV3).LengthHorizontal / 15);                         // 10-20 is fine for prevent to shoot near tree.
                float chance = penetrationmultiplier * (rangemultiplier < 1f ? rangemultiplier : 1f);                       // when projectile reach 15 cells distance, we set limit for multiplier bcs chances to hit greatly increased.
                if (Controller.settings.DebugShowTreeCollisionChance)
                {
                    MoteMaker.ThrowText(thing.Position.ToVector3Shifted(), thing.Map, chance.ToString());
                }
                if (!Rand.Chance(chance))
                {
                    return(false);
                }
            }

            var point = ShotLine.GetPoint(dist);

            if (!point.InBounds(this.Map))
            {
                Log.Error("TryCollideWith out of bounds point from ShotLine: obj " + thing.ThingID + ", proj " + this.ThingID + ", dist " + dist + ", point " + point);
            }

            ExactPosition = point;

            if (intendedTarget != null)
            {
                var fulldistance         = (intendedTarget.Position - OriginIV3).LengthHorizontalSquared;
                var traveleddistance     = (thing.Position - OriginIV3).LengthHorizontalSquared;
                var requireddisttotarget = fulldistance - traveleddistance;
                if (thing is Building && thing.def.fillPercent > 0.5f)
                {
                    //    Log.Message("fulldist: " + fulldistance.ToString() + " traveled: " + traveleddistance.ToString() + " required: " + requireddisttotarget.ToString());
                    if (traveleddistance < requireddisttotarget)
                    {
                        return(false);
                    }
                }
            }

            landed = true;

            //    if (Controller.settings.DebugDrawInterceptChecks) MoteMaker.ThrowText(thing.Position.ToVector3Shifted(), thing.Map, "x", Color.red);

            Impact(thing);
            return(true);
        }
Exemplo n.º 9
0
        public virtual void RayCast(Thing launcher, VerbProperties verbProps, Vector2 origin, float shotAngle, float shotRotation, float shotHeight = 0f, float shotSpeed = -1f, float spreadDegrees = 0f, float aperatureSize = 0.03f, Thing equipment = null)
        {
            float magicSpreadFactor        = Mathf.Sin(0.06f / 2 * Mathf.Deg2Rad) + aperatureSize;
            float magicLaserDamageConstant = 1 / (magicSpreadFactor * magicSpreadFactor * 3.14159f);

            ProjectilePropertiesCE pprops = def.projectile as ProjectilePropertiesCE;

            shotRotation = Mathf.Deg2Rad * shotRotation + (float)(3.14159 / 2.0f);
            Vector3 direction   = new Vector3(Mathf.Cos(shotRotation) * Mathf.Cos(shotAngle), Mathf.Sin(shotAngle), Mathf.Sin(shotRotation) * Mathf.Cos(shotAngle));
            Vector3 origin3     = new Vector3(origin.x, shotHeight, origin.y);
            Map     map         = launcher.Map;
            Vector3 destination = direction * verbProps.range + origin3;

            this.shotAngle    = shotAngle;
            this.shotHeight   = shotHeight;
            this.shotRotation = shotRotation;
            this.launcher     = launcher;
            this.origin       = origin;
            equipmentDef      = equipment?.def ?? null;
            Ray   ray          = new Ray(origin3, direction);
            var   lbce         = this as LaserBeamCE;
            float spreadRadius = Mathf.Sin(spreadDegrees / 2.0f * Mathf.Deg2Rad);

            LaserGunDef defWeapon = equipmentDef as LaserGunDef;
            Vector3     muzzle    = ray.GetPoint((defWeapon == null ? 0.9f : defWeapon.barrelLength));
            var         it_bounds = CE_Utility.GetBoundsFor(intendedTarget);

            for (int i = 1; i < verbProps.range; i++)
            {
                float spreadArea = (i * spreadRadius + aperatureSize) * (i * spreadRadius + aperatureSize) * 3.14159f;
                if (pprops.damageFalloff)
                {
                    lbce.DamageModifier = 1 / (magicLaserDamageConstant * spreadArea);
                }

                Vector3 tp = ray.GetPoint(i);
                if (tp.y > CollisionVertical.WallCollisionHeight)
                {
                    break;
                }
                if (tp.y < 0)
                {
                    destination   = tp;
                    landed        = true;
                    ExactPosition = tp;
                    Position      = ExactPosition.ToIntVec3();
                    break;
                }
                foreach (Thing thing in Map.thingGrid.ThingsListAtFast(tp.ToIntVec3()))
                {
                    if (this == thing)
                    {
                        continue;
                    }
                    var bounds = CE_Utility.GetBoundsFor(thing);
                    if (!bounds.IntersectRay(ray, out var dist))
                    {
                        continue;
                    }
                    if (i < 2 && thing != intendedTarget)
                    {
                        continue;
                    }

                    if (thing is Plant plant)
                    {
                        if (!Rand.Chance(thing.def.fillPercent * plant.Growth))
                        {
                            continue;
                        }
                    }
                    else if (thing is Building)
                    {
                        if (!Rand.Chance(thing.def.fillPercent))
                        {
                            continue;
                        }
                    }
                    ExactPosition = tp;
                    destination   = tp;
                    landed        = true;
                    LastPos       = destination;
                    ExactPosition = destination;
                    Position      = ExactPosition.ToIntVec3();

                    lbce.SpawnBeam(muzzle, destination);

                    lbce.Impact(thing, muzzle);

                    return;
                }
            }
            if (lbce != null)
            {
                lbce.SpawnBeam(muzzle, destination);
                Destroy(DestroyMode.Vanish);
                return;
            }
        }
        // Added targetThing to parameters so we can calculate its height
        private bool CanHitCellFromCellIgnoringRange(IntVec3 sourceSq, IntVec3 targetLoc, Thing targetThing = null, bool includeCorners = false)
        {
            // Vanilla checks
            if (this.verbProps.mustCastOnOpenGround && (!targetLoc.Standable(this.caster.Map) || this.caster.Map.thingGrid.CellContains(targetLoc, ThingCategory.Pawn)))
            {
                return(false);
            }
            if (this.verbProps.requireLineOfSight)
            {
                // Calculate shot vector
                Vector3 shotSource = ShotSource;

                Vector3 targetPos;
                if (targetThing != null)
                {
                    Vector3 targDrawPos = targetThing.DrawPos;
                    targetPos = new Vector3(targDrawPos.x, new CollisionVertical(targetThing).Max, targDrawPos.z);
                }
                else
                {
                    targetPos = targetLoc.ToVector3Shifted();
                }
                Ray shotLine = new Ray(shotSource, (targetPos - shotSource));

                // Create validator to check for intersection with partial cover
                var aimMode = CompFireModes?.CurrentAimMode;
                Func <IntVec3, bool> validator = delegate(IntVec3 cell)
                {
                    // Skip this check entirely if we're doing suppressive fire and cell is adjacent to target
                    if (VerbPropsCE.ignorePartialLoSBlocker || aimMode == AimMode.SuppressFire)
                    {
                        return(true);
                    }

                    Thing cover = cell.GetFirstPawn(caster.Map);
                    if (cover == null)
                    {
                        cover = cell.GetCover(caster.Map);
                    }
                    if (cover != null && !cover.IsTree() && !cover.Position.AdjacentTo8Way(sourceSq))
                    {
                        Bounds bounds = CE_Utility.GetBoundsFor(cover);

                        // Check for intersect
                        if (bounds.IntersectRay(shotLine))
                        {
                            if (Controller.settings.DebugDrawPartialLoSChecks)
                            {
                                caster.Map.debugDrawer.FlashCell(cell, 0, bounds.size.y.ToString());
                            }
                            return(false);
                        }
                        else if (Controller.settings.DebugDrawPartialLoSChecks)
                        {
                            caster.Map.debugDrawer.FlashCell(cell, 0.7f, bounds.size.y.ToString());
                        }
                    }
                    return(true);
                };
                // Add validator to parameters
                if (!includeCorners)
                {
                    if (!GenSight.LineOfSight(sourceSq, targetLoc, this.caster.Map, true, validator, 0, 0))
                    {
                        return(false);
                    }
                }
                else if (!GenSight.LineOfSightToEdges(sourceSq, targetLoc, this.caster.Map, true, validator))
                {
                    return(false);
                }
            }
            return(true);
        }