private bool CheckKillDistance(PlantRule rule, int x, int y, NatureCube cube)
        {
            if (rule.KillDistance <= 0)
            {
                return(true);
            }

            var globalX = x + cube._area.X1;
            var globalY = y + cube._area.Y1;
            var size    = _zone.Size;

            for (var j = globalY - rule.KillDistance; j < globalY + rule.KillDistance; j++)
            {
                for (var i = globalX - rule.KillDistance; i < globalX + rule.KillDistance; i++)
                {
                    //exit if outside of the map
                    if (i < 0 || i >= size.Width || j < 0 || j >= size.Height)
                    {
                        continue;
                    }

                    PlantType plantType;
                    if (cube._area.Contains(i, j))
                    {
                        //sample from the cube, convert back the coordinate to cube local
                        var cx = i - cube._area.X1;
                        var cy = j - cube._area.Y1;

                        plantType = cube.GetPlantInfo(cx, cy).type;
                    }
                    else
                    {
                        //sample from the real map
                        plantType = _zone.Terrain.Plants.GetValue(i, j).type;
                    }

                    if (plantType == rule.Type && IsCloserThan(globalX, globalY, i, j, rule.KillDistance))
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
        private int GetHarvestedAmountPerCycle(PlantRule plantRule)
        {
            double amount;

            switch (plantRule.Type)
            {
            case PlantType.SlimeRoot:
            case PlantType.ElectroPlant:
            case PlantType.RustBush:
            case PlantType.TreeIron:
            {
                var m = _materialHelper.GetMaterialInfo(plantRule.FruitMaterialName.ToMaterialType());
                amount = m.Amount;
                break;
            }

            default:
                throw new PerpetuumException(ErrorCodes.PlantNotHarvestable);
            }

            return((int)(amount * _amountModifier));
        }
        /// <summary>
        /// Checks variuos zone and plantrule conditions to plant
        /// </summary>
        /// <param name="zone"></param>
        /// <param name="player"></param>
        public override void Deploy(IZone zone, Player player)
        {
            //plant it under the player
            _targetPosition = player.CurrentPosition;

            //this item will plant this plant
            _targetPlantType = GetTargetPlantType();

            _plantRule = zone.Configuration.PlantRules.GetPlantRule(_targetPlantType);
            if (_plantRule == null)
            {
                //the desired plantrule was not found on zone

#if DEBUG
                Logger.Error("consistency error. no plantrule found for seed:" + Definition + " planttype:" + _targetPlantType);
#endif
                //different errormessage for concrete placing
                _targetPlantType.ThrowIfEqual(PlantType.Devrinol, ErrorCodes.ZoneNotTerraformable);

                throw new PerpetuumException(ErrorCodes.PlantNotFertileOnThisZone);
            }

            //copy units to local for many iterations
            _currentUnits = zone.Units.ToArray();

            //save the players corporationeid to check beta and gamma conditions
            _corporationEid = player.CorporationEid;


            if (!_plantRule.PlacesConcrete)
            {
                CheckNonConcreteAndThrow(zone);
            }

            //these plants can't be placed on alpha
            if (zone.Configuration.IsAlpha)
            {
                (_targetPlantType == PlantType.Devrinol).ThrowIfTrue(ErrorCodes.OnlyUnProtectedZonesAllowed);
            }
            else
            {
                //on beta and gamma we need corporationeid to match with stuff
                DefaultCorporationDataCache.IsCorporationDefault(_corporationEid).ThrowIfTrue(ErrorCodes.CharacterMustBeInPrivateCorporation);
            }

            if (_targetPlantType == PlantType.Wall)
            {
                PBSHelper.CheckWallPlantingAndThrow(zone, _currentUnits, _targetPosition, _corporationEid);
            }


            if (_plantRule.PlacesConcrete)
            {
                zone.Configuration.Terraformable.ThrowIfFalse(ErrorCodes.ZoneNotTerraformable);
                PlaceConcreteOrThrow(zone);
            }
            else
            {
                PutPlantOrThrow(zone, _targetPosition.intX, _targetPosition.intY);
            }

            var b = TransactionLogEvent.Builder().SetTransactionType(TransactionType.ItemDeploy).SetCharacter(player.Character).SetItem(Definition, 1);
            player.Character.LogTransaction(b);
        }
        public static void PutPlant(this ITerrain terrain, int x, int y, byte state, PlantType plantType, PlantRule plantRule)
        {
            terrain.Plants.UpdateValue(x, y, pi =>
            {
                pi.SetPlant(state, plantType);
                pi.health = plantRule.Health[state];
                return(pi);
            });

            if (plantRule.IsBlocking(state))
            {
                terrain.Blocks.UpdateValue(x, y, bi =>
                {
                    bi.Plant  = true;
                    bi.Height = plantRule.GetBlockingHeight(state);
                    return(bi);
                });
            }

            if (plantRule.PlacesConcrete)
            {
                terrain.Controls.UpdateValue(x, y, ci =>
                {
                    if (FastRandom.NextDouble() > 0.5)
                    {
                        ci.ConcreteA = true;
                    }
                    else
                    {
                        ci.ConcreteB = true;
                    }

                    return(ci);
                });
            }
        }