Perekyp/Assets/Scripts/Player/Tools/PlayerToolManager.cs

172 lines
5.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using TMPro;
using UnityEngine;
// Порядок важен: он совпадает с порядком секторов в ToolRadialMenu (индекс = номер сектора)
public enum ToolType { Hands, RustCleaner, Putty, Sander, SprayCan }
public class PlayerToolManager : MonoBehaviour
{
[Header("Инструмент")]
public ToolType currentTool = ToolType.Hands;
[Header("Луч инструмента")]
[SerializeField] private float toolRange = 2.5f;
[SerializeField] private LayerMask interactableLayer;
[Header("Время полной обработки детали, сек")]
[SerializeField] private float cleanTime = 5f;
[SerializeField] private float puttyTime = 3f;
[SerializeField] private float sandTime = 4f;
[SerializeField] private float paintTime = 3f;
[Header("Перекраска целой детали")]
[SerializeField] private Color sprayPaintColor = new Color(0.1f, 0.4f, 0.8f);
[Header("Подсказка о состоянии детали (необязательно)")]
[Tooltip("Если не задан - текст рисуется простым OnGUI по центру экрана")]
[SerializeField] private TextMeshProUGUI statusText;
private Camera playerCam;
private string status = "";
private GUIStyle guiStyle;
private void Awake()
{
playerCam = GetComponentInChildren<Camera>();
if (playerCam == null) playerCam = Camera.main;
}
private void Update()
{
// Пока выбираем инструмент (Tab) или в руках ничего нет - инструменты не работают
if (currentTool == ToolType.Hands || Input.GetKey(KeyCode.Tab))
{
SetStatus("");
return;
}
CarPartVisuals visuals = FindTarget();
if (visuals == null)
{
SetStatus("");
return;
}
string text = $"{StageText(visuals.Stage)}";
if (visuals.Stage != RepairStage.Healthy && visuals.Stage != RepairStage.Repaired)
text += $" {Mathf.RoundToInt(visuals.StageProgress * 100f)}%";
if (Input.GetMouseButton(0))
{
if (!UseTool(visuals)) text = HintFor(visuals.Stage);
}
SetStatus(text);
}
private CarPartVisuals FindTarget()
{
if (playerCam == null) return null;
Ray ray = new Ray(playerCam.transform.position, playerCam.transform.forward);
// Ignore: зоны монтажа - это триггеры на том же слое, луч не должен в них упираться
if (!Physics.Raycast(ray, out RaycastHit hit, toolRange, interactableLayer, QueryTriggerInteraction.Ignore))
return null;
return hit.collider.GetComponentInParent<CarPartVisuals>();
}
private bool UseTool(CarPartVisuals visuals)
{
float dt = Time.deltaTime;
switch (currentTool)
{
case ToolType.RustCleaner:
// TODO: частицы искр / щётки и звук
return visuals.CleanRust(dt / cleanTime);
case ToolType.Putty:
return visuals.ApplyPutty(dt / puttyTime);
case ToolType.Sander:
return visuals.Sand(dt / sandTime);
case ToolType.SprayCan:
// Ремонтная покраска идёт цветом детали, чтобы заплатка слилась с кузовом.
// Целую деталь баллончик перекрашивает в выбранный цвет.
if (visuals.Stage == RepairStage.Sanded) return visuals.PaintRepair(dt / paintTime);
return visuals.Recolor(sprayPaintColor);
default:
return false;
}
}
public void SelectTool(ToolType newTool)
{
currentTool = newTool;
}
public void SetSprayColor(Color color)
{
sprayPaintColor = color;
}
// ---------- Тексты ----------
private static string StageText(RepairStage stage)
{
switch (stage)
{
case RepairStage.Healthy: return "Деталь целая";
case RepairStage.Rusted: return "Ржавчина";
case RepairStage.Cleaned: return "Зачищено, нужна шпаклёвка";
case RepairStage.Puttied: return "Зашпаклёвано, нужна шлифовка";
case RepairStage.Sanded: return "Отшлифовано, нужна покраска";
default: return "Отремонтировано";
}
}
private static string HintFor(RepairStage stage)
{
switch (stage)
{
case RepairStage.Rusted: return "Сначала счистите ржавчину (зачистка)";
case RepairStage.Cleaned: return "Нужна шпаклёвка (шпатель)";
case RepairStage.Puttied: return "Нужна шлифовка";
case RepairStage.Sanded: return "Нужна покраска (баллончик)";
default: return "Этот инструмент здесь не нужен";
}
}
// ---------- Вывод ----------
private void SetStatus(string value)
{
status = value;
if (statusText != null)
{
statusText.text = value;
statusText.gameObject.SetActive(!string.IsNullOrEmpty(value));
}
}
private void OnGUI()
{
if (statusText != null || string.IsNullOrEmpty(status)) return;
if (guiStyle == null)
{
guiStyle = new GUIStyle(GUI.skin.label)
{
alignment = TextAnchor.MiddleCenter,
fontSize = 22
};
}
GUI.Label(new Rect(Screen.width * 0.5f - 300f, Screen.height * 0.62f, 600f, 40f), status, guiStyle);
}
}