using System.Collections.Generic;
using System.Reflection;
using HutongGames.PlayMaker;
using MSCO;
using UnityEngine;
[assembly: AssemblyTitle("Show Bolt Size")]
[assembly: AssemblyProduct("Show Bolt Size")]
[assembly: AssemblyDescription("Shows the size of the bolt you look at, so you pick the right wrench.")]
[assembly: AssemblyVersion("1.0.1.0")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
namespace ShowBoltSize
{
///
/// Zeigt unter dem Fadenkreuz die Größe der Schraube, auf die man schaut ("10 mm"). Jede Schraube hat die FSM "Screw"
/// mit der Variable "BoltSize". Deren Kollider sind nur mit Werkzeug in der Hand aktiv - deshalb kein Raycast, sondern:
/// die Schraube, die am nächsten an der Blickrichtung liegt (bis 1,3 m). Nur Anzeige, ändert nichts am Spiel.
///
public class ShowBoltSize : MscoMod
{
public override string ID { get { return "showboltsize"; } }
public override string Name { get { return "Show Bolt Size"; } }
public override string Version { get { return "1.0.1"; } }
public override string Author { get { return "MBM"; } }
const float MaxDistance = 1.3f;
const float BoltRadius = 0.025f; // so groß wirkt eine Schraube beim Zielen
const float ScanInterval = 5f;
sealed class Bolt
{
public Transform Transform;
public FsmFloat SizeF;
public FsmInt SizeI;
}
readonly List bolts = new List();
bool inGame;
float nextScan;
string label;
GUIStyle style;
Camera camera;
bool reported;
public override void OnMenuLoad() { inGame = false; bolts.Clear(); label = null; camera = null; reported = false; }
public override void OnGameLoad() { inGame = true; nextScan = 0f; }
///
/// Spielerkamera: Camera.main gibt es in My Summer Car nicht immer (die Kamera des Spielers ist "FPSCamera").
///
Camera FindCamera()
{
if (camera != null && camera.enabled && camera.gameObject.activeInHierarchy) return camera;
camera = null;
foreach (Camera c in Camera.allCameras)
if (c.name == "FPSCamera") { camera = c; break; }
if (camera == null) camera = Camera.main;
return camera;
}
public override void Update()
{
label = null;
if (!inGame) return;
Camera cam = FindCamera();
if (cam == null) return;
if (Time.realtimeSinceStartup >= nextScan) Scan(cam);
Transform eye = cam.transform;
Vector3 eyePos = eye.position, forward = eye.forward;
Bolt best = null;
float bestAngle = float.MaxValue;
for (int i = 0; i < bolts.Count; i++)
{
Bolt b = bolts[i];
if (b.Transform == null) continue;
Vector3 to = b.Transform.position - eyePos;
float sq = to.sqrMagnitude;
if (sq > MaxDistance * MaxDistance || sq < 0.0025f) continue;
if (!b.Transform.gameObject.activeInHierarchy) continue;
float distance = Mathf.Sqrt(sq);
float angle = Vector3.Angle(forward, to);
float limit = Mathf.Atan2(BoltRadius, distance) * Mathf.Rad2Deg + 0.5f;
if (angle < limit && angle < bestAngle)
{
bestAngle = angle;
best = b;
}
}
if (best != null) label = Describe(best);
}
///
/// Schrauben aus MSCOs gemeinsamer Liste aller FSMs holen (SceneCache) - nicht selbst das ganze Spiel durchsuchen,
/// das ließ das Spiel alle paar Sekunden kurz hängen.
///
void Scan(Camera cam)
{
nextScan = Time.realtimeSinceStartup + ScanInterval;
bolts.Clear();
foreach (PlayMakerFSM fsm in SceneCache.Fsms(30f))
{
if (fsm == null || fsm.FsmName != "Screw") continue;
FsmFloat f = fsm.FsmVariables.FindFsmFloat("BoltSize");
FsmInt i = fsm.FsmVariables.FindFsmInt("BoltSize");
if (f == null && i == null) continue;
bolts.Add(new Bolt { Transform = fsm.transform, SizeF = f, SizeI = i });
}
if (!reported)
{
reported = true;
Log("camera " + cam.name + ", " + bolts.Count + " bolts with a size");
}
}
/// Größe in mm. Das Spiel speichert sie je nach Schraube als 10 oder als 1.0 (= 10 mm).
static string Describe(Bolt b)
{
float value = b.SizeF != null ? b.SizeF.Value : b.SizeI.Value;
if (value <= 0f) return null;
float mm = value < 2.5f ? value * 10f : value;
return Mathf.RoundToInt(mm) + " mm";
}
public override void OnGUI()
{
if (label == null) return;
if (style == null)
{
style = new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleCenter, fontSize = 16, fontStyle = FontStyle.Bold };
style.normal.textColor = Color.white;
}
var r = new Rect(Screen.width / 2f - 50f, Screen.height / 2f + 22f, 100f, 26f);
Color old = GUI.color;
GUI.color = new Color(0f, 0f, 0f, 0.6f);
GUI.DrawTexture(r, Texture2D.whiteTexture);
GUI.color = old;
GUI.Label(r, label, style);
}
}
}