using Facepunch; using Oxide.Core; using Rust; using UnityEngine; using Newtonsoft.Json; using System; using System.Collections.Generic; using UnityEngine; using System.IO; using Oxide.Core.Plugins; using System.Linq; namespace Oxide.Plugins { [Info("AutoTurretTerrain", "Duff", "1.0.3")] [Description("Allows players to place auto turrets on terrain and cliffs with correct rotation and prevents stacking.")] public class AutoTurretTerrain : RustPlugin { private const string permUse = "autoturretterrain.use"; private const float TurretRadius = 3.0f; // Radius around the placement point to check for collisions private const float MaxPlacementDistance = 4f; // Maximum distance to place turret private void Init() { permission.RegisterPermission(permUse, this); } #region OnPlayerInput private void OnPlayerInput(BasePlayer player, InputState input) { if (!input.WasJustReleased(BUTTON.FIRE_SECONDARY)) return; if (!player.svActiveItemID.IsValid || !permission.UserHasPermission(player.UserIDString, permUse)) return; var item = player.GetActiveItem(); if (item == null || !(item.info.shortname.Contains("autoturret") || item.info.shortname.Contains("samsite") || item.info.shortname.Contains("flameturret") || item.info.shortname.Contains("guntrap"))) return; RaycastHit hit; if (!Physics.Raycast(player.eyes.HeadRay(), out hit, 10f, Layers.Mask.World | Layers.Mask.Terrain)) { player.ChatMessage("You must aim at the terrain, rock, or cliff to place the turret or trap."); return; } // Check distance from the player to the hit point float distanceToHit = Vector3.Distance(player.transform.position, hit.point); if (distanceToHit > MaxPlacementDistance) { player.ChatMessage($"You cannot place the turret or trap more than {MaxPlacementDistance} meters away."); return; } Vector3 position = SnapToSurface(hit); if (!IsPlacementValid(position, player)) { // Commented out the invalid placement message // player.ChatMessage("Cannot place turret here; space is occupied or too close to other turrets."); return; } string entityPrefab; if (item.info.shortname == "autoturret") { entityPrefab = "assets/prefabs/npc/autoturret/autoturret_deployed.prefab"; } else if (item.info.shortname == "samsite") { entityPrefab = "assets/prefabs/npc/sam_site_turret/sam_site_turret_deployed.prefab"; } else if (item.info.shortname == "flameturret") { entityPrefab = "assets/prefabs/npc/flame turret/flameturret.deployed.prefab"; } else if (item.info.shortname == "guntrap") { entityPrefab = "assets/prefabs/deployable/single shot trap/guntrap.deployed.prefab"; } else { entityPrefab = string.Empty; // Unsupported item } var turretEntity = GameManager.server.CreateEntity(entityPrefab, position, Quaternion.identity, true); if (turretEntity == null) { player.ChatMessage("Failed to create the turret or trap."); return; } AlignEntityToSurface(turretEntity, position, hit.normal, player); turretEntity.OwnerID = player.userID; turretEntity.Spawn(); turretEntity.SetParent(null, true, false); // Set parent to null or your desired parent entity turretEntity.OnDeployed(null, player, item); // Mark it as deployed with player and item references turretEntity.OnPlaced(player); // Handle the placement logic turretEntity.SetActive(true); // Ensure it's active immediately turretEntity.SendNetworkUpdateImmediate(); // Ensure state updates across clients item.UseItem(1); player.ChatMessage("Turret or Trap successfully placed on the terrain or cliff."); } #endregion #region SnapToSurface private Vector3 SnapToSurface(RaycastHit hit) { return hit.point; } #endregion #region IsPlacementValid private bool IsPlacementValid(Vector3 position, BasePlayer player) { // Check if the player is in a safe zone or monument area if (IsInSafeZone(player) || IsInMonumentArea(position)) { return false; // Placement is not allowed in safe zones or monuments } var colliders = Physics.OverlapSphere(position, TurretRadius, Layers.Mask.Deployed); foreach (var collider in colliders) { var entity = collider.GetComponent(); if (entity != null && (entity.PrefabName.Contains("autoturret") || entity.PrefabName.Contains("guntrap") || entity.PrefabName.Contains("samsite") || entity.PrefabName.Contains("flameturret"))) { player.ChatMessage("Cannot place here; space is occupied by another turret or trap."); // Send message to player return false; // Space is occupied by another turret or trap } } return true; // Space is valid for placement } #endregion #region SafeZone & MonumentCheck private bool IsInSafeZone(BasePlayer player) { // Check if the player has any building privileges var priv = player.GetBuildingPrivilege(); return priv == null; // If there is no privilege, the player is likely in a safe zone } private bool IsInMonumentArea(Vector3 position) { // Placeholder logic; implement actual checks for monument areas as needed return false; // Replace with actual monument check logic } #endregion #region AlignEntityToSurface - Method for how the thing will be aligned and placed private void AlignEntityToSurface(BaseEntity entity, Vector3 hitPoint, Vector3 hitNormal, BasePlayer player) { Vector3 upVector = hitNormal; Vector3 forwardVector = Vector3.Cross(player.transform.right, upVector).normalized; Quaternion surfaceRotation = Quaternion.LookRotation(forwardVector, upVector); entity.transform.position = hitPoint; entity.transform.rotation = surfaceRotation; Vector3 directionToPlayer = (player.transform.position - hitPoint).normalized; Quaternion lookAtPlayerRotation = Quaternion.LookRotation(Vector3.ProjectOnPlane(directionToPlayer, upVector), upVector); entity.transform.rotation = lookAtPlayerRotation; entity.SendNetworkUpdateImmediate(); } #endregion } }