498 lines
22 KiB
C#
498 lines
22 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using TMPro;
|
|
|
|
public class RocketLauncher : MonoBehaviour
|
|
{
|
|
[Header("Ðàêåòà")]
|
|
[SerializeField] private Transform rocketRoot;
|
|
[SerializeField] private Transform[] flameParts;
|
|
[SerializeField] private Button launchButton;
|
|
[SerializeField] private GameObject materialPanel;
|
|
[SerializeField] private GameObject infoPanel;
|
|
[SerializeField] private TextMeshProUGUI infoPanelText;
|
|
|
|
[Header("Âèáóõè")]
|
|
[SerializeField] private GameObject explosionBig;
|
|
[SerializeField] private GameObject explosionMedium;
|
|
[SerializeField] private GameObject explosionSmall;
|
|
[SerializeField] private GameObject debrisPrefab;
|
|
|
|
[Header("Ñåëåêòîðè")]
|
|
[SerializeField] private RocketMaterialSelector materialSelector;
|
|
[SerializeField] private PlanetSelector planetSelector;
|
|
[SerializeField] private FuelSelector fuelSelector;
|
|
|
|
[Header("ϳäñèñòåìè")]
|
|
[SerializeField] private RocketFlightCore flightCore;
|
|
[SerializeField] private RocketCameraController cameraController;
|
|
[SerializeField] private RocketEffectsController effectsController;
|
|
|
|
private bool _isLaunched = false;
|
|
private bool _sonicBoomDone = false;
|
|
private Vector3 _rocketStartPos;
|
|
private Quaternion _rocketStartRot;
|
|
|
|
private static readonly HashSet<string> _explodeOnLaunch = new HashSet<string>
|
|
{ "Ïàï³ð", "Ñí³æîê", "Àâîêàäî", "˳÷³", "Ãóìîâà êà÷å÷êà", "˳ä", "Ñêëî", "Ñêëÿíà áàíêà", "Áëîêíîò", "Ïëàñòèêîâà äîøêà",
|
|
"Öåãëà", "Ãðàí³ò", "Ìàðìóð", "×àâóí", "Ãóìà", "Ïëàñòèê" };
|
|
private static readonly HashSet<string> _explodeSoon = new HashSet<string>
|
|
{ "Äåðåâî", "Àñôàëüò", "Çîëîòî", "Äåðåâ'ÿíà äîøêà", "Êàì³ííÿ ç ìîõîì" };
|
|
private static readonly HashSet<string> _planetExplode = new HashSet<string>
|
|
{ "Âåíåðà", "Þï³òåð" };
|
|
|
|
private static readonly Dictionary<string, string> _materialExplosionReason = new Dictionary<string, string>
|
|
{
|
|
{ "Ïàï³ð", "Ïàï³ð ñïàëàõóº ïðè +233C. Äâèãóíè ðîçæàðþþòüñÿ äî 3000C -- ïàï³ð ïåðåòâîðèâñÿ íà ïîï³ë ùå íà ñòàðò³." },
|
|
{ "Ñí³æîê", "Ñí³ã òàíå ïðè 0C. Ïîëóì'ÿ äâèãóíà ìèòòºâî ïåðåòâîðèëî êîðïóñ íà ïàðó ùå äî â³äðèâó â³ä ïîâåðõí³." },
|
|
{ "Àâîêàäî", "Îðãàí³÷í³ ìàòåð³àëè íå âèòðèìóþòü òåìïåðàòóðè ñòàðòó. Àâîêàäî çàéíÿëîñÿ ùå äî ï³äéîìó." },
|
|
{ "˳÷³", "Ì'ÿêà îðãàí³êà íå çäàòíà âèòðèìàòè òèñê ³ òåìïåðàòóðó íàâ³òü íèæíüîãî øàðó àòìîñôåðè." },
|
|
{ "Ãóìîâà êà÷å÷êà", "Ãóìà ðîçïëàâëÿºòüñÿ ïðè +300C. ³ä òÿãè äâèãóí³â âîíà ðîçòåêëàñü ùå íà ñòàðò³." },
|
|
{ "˳ä", "˳ä òàíå ïðè 0C. Ïîëóì'ÿ äâèãóí³â ïåðåòâîðèëî êîðïóñ íà âîäó ùå äî â³äðèâó â³ä çåìë³." },
|
|
{ "Ñêëî", "Ñêëî êðèõêå ³ íå âèòðèìóº â³áðàö³¿ ïðè ñòàðò³. Òåðì³÷íèé óäàð ðîçòð³ñêóº êîðïóñ ìèòòºâî." },
|
|
{ "Äåðåâî", "Äåðåâî çàéìàºòüñÿ ïðè +300C. Àåðîäèíàì³÷íå íàãð³âàííÿ ïåðåòâîðþº êîðïóñ íà ôàêåë âæå íà âèñîò³ 10 êì." },
|
|
{ "Àñôàëüò", "Àñôàëüò ðîçì'ÿêøóºòüñÿ ïðè +60C. ³ä òåðòÿ ç ïîâ³òðÿì â³í âòðà÷ຠôîðìó ³ ðàêåòà ðóéíóºòüñÿ." },
|
|
{ "Çîëîòî", "Çîëîòî ïëàâèòüñÿ ïðè +1064C. Àåðîäèíàì³÷íå íàãð³âàííÿ äîñÿãຠöüîãî ïîðîãó -- êîðïóñ äåôîðìóâàâñÿ." },
|
|
{ "Öåãëà", "Öåãëà âàæèòü 1800 êã/ì3 -- â 4 ðàçè âàæ÷à çà àëþì³í³é. Äâèãóí ô³çè÷íî íå ï³äíÿâ êîíñòðóêö³þ. Çðóéíóâàëàñü â³ä â³áðàö³¿ íà ñòàðò³." },
|
|
{ "Ãðàí³ò", "Ãðàí³ò âàæèòü 2700 êã/ì3 -- íàéâàæ÷èé ìàòåð³àë â ñïèñêó. Æîäåí ³ñíóþ÷èé äâèãóí íå ï³äí³ìå ðàêåòó ç òàêèì êîðïóñîì." },
|
|
{ "Ìàðìóð", "Ìàðìóð âàæèòü 2700 êã/ì3 ³ êðèõêèé. Ðîçñèïàâñÿ â³ä â³áðàö³¿ äâèãóí³â ùå äî â³äðèâó â³ä çåìë³." },
|
|
{ "×àâóí", "×àâóí âàæèòü 7200 êã/ì3 -- â 2.5 ðàçè âàæ÷èé çà ñòàëü. Êîíñòðóêö³ÿ ðîçëàìàëàñü â³ä âëàñíî¿ âàãè ïðè çàïóñêó äâèãóí³â." },
|
|
{ "Ãóìà", "Ãóìà ïëàâèòüñÿ ïðè +300C. Äâèãóíè äàþòü +3000C -- êîðïóñ ðîçò³êñÿ ùå äî ñòàðòó." },
|
|
{ "Ïëàñòèê", "Ïëàñòèê ïëàâèòüñÿ ïðè +150-300C ³ çàíàäòî ñëàáêèé äëÿ òèñêó ïðè çàïóñêó. Äåôîðìóâàâñÿ ³ çðóéíóâàâñÿ íà ñòàðò³." },
|
|
};
|
|
|
|
private static readonly Dictionary<string, string> _planetFacts = new Dictionary<string, string>
|
|
{
|
|
{ "Çåìëÿ", "Àòìîñôåðà ñÿãຠ100 êì (ë³í³ÿ Êàðìàíà). Òèñê íà ïîâåðõí³ 1 àòì, òåìïåðàòóðà ïàäຠäî -56C íà âèñîò³ 11 êì." },
|
|
{ "Ìàðñ", "Àòìîñôåðà â 100 ðàç³â ð³äê³øà çà çåìíó. Áåç ñêàôàíäðà êðîâ çàêèï³ëà á ìèòòºâî. Ãðàâ³òàö³ÿ 3.7 ì/ñ2." },
|
|
{ "̳ñÿöü", "Áåç àòìîñôåðè òåìïåðàòóðà â³ä +127C âäåíü äî -173C âíî÷³. Ãðàâ³òàö³ÿ 1.6 ì/ñ2 -- â 6 ðàç³â ìåíøå çåìíî¿." },
|
|
{ "Þï³òåð", "Âåëèêèé ×åðâîíèé Ïëÿì -- øòîðì ùî òðèâຠïîíàä 350 ðîê³â. Ãðàâ³òàö³ÿ 24.8 ì/ñ2 -- ó 2.5 ðàçè á³ëüøå çåìíî¿." },
|
|
{ "Âåíåðà", "Îáåðòàºòüñÿ ó çâîðîòíèé á³ê. Õìàðè ç ñ³ð÷àíî¿ êèñëîòè. Òèñê 92 àòì -- ÿê íà ãëèáèí³ 900 ì îêåàíó." },
|
|
{ "Ñàòóðí", "ʳëüöÿ çàâòîâøêè ëèøå 20 ìåòð³â àëå çàâøèðøêè 282000 êì. ³òðè äî 1800 êì/ãîä." },
|
|
{ "Ìåðêóð³é", "гê 88 äí³â àëå äåíü äîâøèé çà ð³ê -- 176 çåìíèõ ä³á. Ãðàâ³òàö³ÿ 3.7 ì/ñ2 ÿê íà Ìàðñ³." },
|
|
{ "Óðàí", "Îáåðòàºòüñÿ ëåæà÷è íà áîö³ -- â³ñü íàõèëåíà íà 98 ãðàäóñ³â. Ãðàâ³òàö³ÿ 8.7 ì/ñ2." },
|
|
{ "Íåïòóí", "Íàéñèëüí³ø³ â³òðè â Ñîíÿ÷í³é ñèñòåì³ -- 2100 êì/ãîä. Ãðàâ³òàö³ÿ 11.2 ì/ñ2." },
|
|
{ "Ïëóòîí", "Ñåðöå Ïëóòîíà -- ð³âíèíà Òîìáî ç ëüîäîâèê³â àçîòó. Ãðàâ³òàö³ÿ ëèøå 0.62 ì/ñ2." }
|
|
};
|
|
|
|
private static readonly Dictionary<string, string> _planetExplosionReason = new Dictionary<string, string>
|
|
{
|
|
{ "Âåíåðà", "Âåíåðà âáèâຠïîòð³éíî: òèñê 92 àòì ðîçäàâëþº êîðïóñ, +465C ïëàâèòü ìåòàëè, õìàðè ñ³ð÷àíî¿ êèñëîòè ðîç'¿äàþòü ðåøòó." },
|
|
{ "Þï³òåð", "Þï³òåð íå ìຠïîâåðõí³ -- ðàêåòà òîíå â àòìîñôåð³. Íà ãëèáèí³ 1000 êì òèñê ïåðåâèùóº 100000 àòì." }
|
|
};
|
|
|
|
private static readonly Dictionary<string, float> _fuelAmounts = new Dictionary<string, float>
|
|
{
|
|
{ "10%", 10f },
|
|
{ "25%", 25f },
|
|
{ "50%", 50f },
|
|
{ "75%", 75f },
|
|
{ "100%", 100f }
|
|
};
|
|
|
|
private void Start()
|
|
{
|
|
if (launchButton != null) launchButton.onClick.AddListener(Launch);
|
|
_rocketStartPos = rocketRoot.position;
|
|
_rocketStartRot = rocketRoot.rotation;
|
|
if (infoPanel != null) infoPanel.SetActive(false);
|
|
flightCore.Initialize();
|
|
cameraController.Initialize(flightCore);
|
|
effectsController.Initialize(flightCore);
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (!_isLaunched || flightCore == null) return;
|
|
|
|
bool shouldExplode, flightFinished;
|
|
flightCore.UpdateFlight(Time.deltaTime, out shouldExplode, out flightFinished);
|
|
|
|
UpdateRocketTransform();
|
|
|
|
if (!_sonicBoomDone && flightCore.AnimTime >= 3.5f && flightCore.GetAtmosphereProgress() < 0.7f)
|
|
{
|
|
_sonicBoomDone = true;
|
|
cameraController.TriggerSonicBoom();
|
|
}
|
|
|
|
if (flightCore.FuelCutoff)
|
|
SetFlamesActive(false);
|
|
|
|
if (shouldExplode) { Explode(); return; }
|
|
|
|
if (flightFinished)
|
|
{
|
|
effectsController.StopFlight();
|
|
cameraController.StopFlight();
|
|
if (flightCore.RocketEscaped)
|
|
StartCoroutine(SpaceDriftAndInfo());
|
|
else
|
|
StartCoroutine(ShowInfoAndReset());
|
|
}
|
|
}
|
|
|
|
private void UpdateRocketTransform()
|
|
{
|
|
float visualH = flightCore.CurrentHeight * Mathf.Lerp(0.00005f, 0.00015f, Mathf.Clamp01(flightCore.AnimTime / 8f));
|
|
rocketRoot.position = _rocketStartPos + Vector3.up * visualH;
|
|
|
|
if (!flightCore.FuelCutoff)
|
|
{
|
|
float tilt = Mathf.Clamp(flightCore.Velocity * 0.002f, -12f, 15f);
|
|
rocketRoot.rotation = Quaternion.Lerp(rocketRoot.rotation,
|
|
_rocketStartRot * Quaternion.Euler(-tilt, 0f, 0f), Time.deltaTime * 4f);
|
|
}
|
|
else
|
|
{
|
|
float cutoffTime = flightCore.GetFuelCutoffTime();
|
|
float gentleTilt = Mathf.Lerp(0f, 6f, Mathf.Clamp01(cutoffTime / 8f));
|
|
float gentleRoll = Mathf.Sin(cutoffTime * 0.3f) * 2f;
|
|
rocketRoot.rotation = Quaternion.Slerp(rocketRoot.rotation,
|
|
_rocketStartRot * Quaternion.Euler(gentleTilt, 0f, gentleRoll), Time.deltaTime * 0.3f);
|
|
}
|
|
}
|
|
|
|
private void Launch()
|
|
{
|
|
if (_isLaunched) return;
|
|
_isLaunched = true;
|
|
_sonicBoomDone = false;
|
|
|
|
if (materialPanel != null) materialPanel.SetActive(false);
|
|
|
|
var mat = materialSelector.GetCurrentMaterial();
|
|
var pd = planetSelector.GetCurrentPlanet();
|
|
string matName = mat.name;
|
|
string planet = pd.name;
|
|
|
|
bool willExplode = _explodeOnLaunch.Contains(matName) || _explodeSoon.Contains(matName) || _planetExplode.Contains(planet);
|
|
float explodeDelay = _explodeOnLaunch.Contains(matName) ? 0.7f : (_explodeSoon.Contains(matName) ? 4.0f : 5.0f);
|
|
if (!willExplode) explodeDelay = 0f;
|
|
|
|
string fuelName = fuelSelector.GetFuelName();
|
|
float fuelAmount = _fuelAmounts.ContainsKey(fuelName) ? _fuelAmounts[fuelName] : 50f;
|
|
|
|
float shakeMultiplier = GetShakeMultiplier(planet);
|
|
|
|
flightCore.StartFlight(
|
|
fuelAmount,
|
|
pd.gravity,
|
|
pd.atmosphereDensity,
|
|
mat.dragCoefficient,
|
|
willExplode,
|
|
explodeDelay);
|
|
|
|
cameraController.StartFlight();
|
|
cameraController.StartIgnitionShake(shakeMultiplier);
|
|
effectsController.StartFlight(planet, fuelSelector.GetFuelLevel(), shakeMultiplier);
|
|
}
|
|
|
|
private static readonly Dictionary<string, string> _materialFacts = new Dictionary<string, string>
|
|
{
|
|
{ "Âóãëåöåâå âîëîêíî", "Ñàìå ç íüîãî ðîáëÿòü êîðïóñè Falcon 9 òà Starship. Ëåãêå ³ ì³öíå -- ³äåàë äëÿ ðàêåò." },
|
|
{ "Òèòàí", "NASA âèêîðèñòîâóº òèòàí äëÿ êîðïóñ³â äâèãóí³â. Âèòðèìóº äî +1650C." },
|
|
{ "Ïîë³ðîâàíà ñòàëü", "Starship â³ä SpaceX çðîáëåíèé ç³ ñòàë³. Ìàñê îáðàâ ñòàëü áî âîíà äåøåâà ³ ì³öíà." },
|
|
{ "Àëþì³í³é", "Apollo ³ Saturn V ìàëè àëþì³í³ºâ³ êîðïóñè. Ëåãêèé àëå ïëàâèòüñÿ ïðè +660C." },
|
|
{ "Êåðàì³êà", "Space Shuttle ìàâ 24000 êåðàì³÷íèõ ïëèòîê äëÿ çàõèñòó â³ä æàðó ïðè ïîñàäö³ (+1600C)." },
|
|
{ "Ñòàëü", "Á³ëüø³ñòü ðàäÿíñüêèõ ðàêåò Ñîþç çðîáëåí³ ç³ ñòàë³. Âàæêà àëå íàä³éíà." },
|
|
{ "̳äü", "̳äü âèêîðèñòîâóþòü ó ñîïëàõ äâèãóí³â -- âîíà äîáðå â³äâîäèòü æàð â³ä çãîðÿííÿ." },
|
|
{ "Ïëàñòèê", "Ïëàñòèê çàíàäòî ëåãêèé ³ ñëàáêèé. Ðåàëüí³ ðàêåòè íå ìàþòü ïëàñòèêîâèõ êîðïóñ³â." },
|
|
{ "Ñêëî", "Ñêëî êðèõêå ïðè â³áðàö³¿ ñòàðòó. Âèêîðèñòîâóºòüñÿ ò³ëüêè ó â³êíàõ êàá³í àñòðîíàâò³â." },
|
|
{ "×àâóí", "×àâóí ó 3 ðàçè âàæ÷èé çà àëþì³í³é. Æîäíà ðåàëüíà ðàêåòà íå çðîáëåíà ç ÷àâóíó." },
|
|
{ "Ìàðìóð", "Ìàðìóð êðèõêèé ³ âàæêèé. Ó êîñìîíàâòèö³ íå âèêîðèñòîâóºòüñÿ âçàãàë³." },
|
|
{ "Ãðàí³ò", "Ãðàí³ò ó 4 ðàçè âàæ÷èé çà àëþì³í³é. Ðàêåòà ç ãðàí³òó íå çëåòèòü ç Çåìë³." },
|
|
{ "Öåãëà", "Öåãëà âàæêà ³ êðèõêà. Ìàêñèìóì ùî ìîæå -- ê³ëüêà ìåòð³â âãîðó äî âèáóõó." },
|
|
{ "Ãóìà", "Ãóìà ïëàâèòüñÿ ïðè +300C. Äâèãóíè äàþòü +3000C -- íå âèòðèìຠíàâ³òü ñåêóíäè." },
|
|
};
|
|
|
|
private float GetRealHeightKm(string planetName, string matName, int fuelLevel)
|
|
{
|
|
float[] baseFuelHeights = { 15f, 100f, 408f, 36000f, 384000f };
|
|
float baseKm = baseFuelHeights[Mathf.Clamp(fuelLevel, 0, 4)];
|
|
|
|
float planetMult = GetPlanetMultiplier(planetName);
|
|
float matMult = GetMaterialMultiplier(matName);
|
|
|
|
return baseKm * planetMult * matMult;
|
|
}
|
|
|
|
private float GetPlanetMultiplier(string planet)
|
|
{
|
|
switch (planet)
|
|
{
|
|
case "̳ñÿöü": return 6.0f;
|
|
case "Ïëóòîí": return 15.0f;
|
|
case "Ìàðñ": return 2.5f;
|
|
case "Ìåðêóð³é": return 2.5f;
|
|
case "Óðàí": return 1.1f;
|
|
case "Çåìëÿ": return 1.0f;
|
|
case "Ñàòóðí": return 0.9f;
|
|
case "Íåïòóí": return 0.85f;
|
|
case "Âåíåðà": return 0.3f;
|
|
case "Þï³òåð": return 0.1f;
|
|
default: return 1.0f;
|
|
}
|
|
}
|
|
|
|
private float GetMaterialMultiplier(string mat)
|
|
{
|
|
switch (mat)
|
|
{
|
|
case "Âóãëåöåâå âîëîêíî": return 1.0f;
|
|
case "Òèòàí": return 0.95f;
|
|
case "Ïîë³ðîâàíà ñòàëü": return 0.9f;
|
|
case "Àëþì³í³é": return 0.88f;
|
|
case "Êåðàì³êà": return 0.75f;
|
|
case "Ñòàëü": return 0.7f;
|
|
case "̳äü": return 0.6f;
|
|
case "Ïëàñòèê": return 0.55f;
|
|
case "Ñêëî": return 0.5f;
|
|
case "×àâóí": return 0.15f;
|
|
case "Ìàðìóð": return 0.45f;
|
|
case "Ãðàí³ò": return 0.35f;
|
|
case "Öåãëà": return 0.25f;
|
|
case "Ãóìà": return 0.2f;
|
|
default: return 0.5f;
|
|
}
|
|
}
|
|
|
|
private string FormatRealHeight(float km)
|
|
{
|
|
if (km < 1f) return (km * 1000f).ToString("F0") + " ì";
|
|
if (km < 1000f) return km.ToString("F0") + " êì";
|
|
if (km < 1000000f) return (km / 1000f).ToString("F1") + " òèñ. êì";
|
|
return (km / 1000000f).ToString("F2") + " ìëí. êì";
|
|
}
|
|
|
|
private string GetHeightContext(float km)
|
|
{
|
|
if (km < 12f) return "Öå âèñîòà ïîëüîòó ïàñàæèðñüêîãî ë³òàêà.";
|
|
if (km < 50f) return "Ñòðàòîñôåðà. Âèùå õìàð àëå ùå íå êîñìîñ.";
|
|
if (km < 100f) return "Ìàéæå ë³í³ÿ Êàðìàíà -- îô³ö³éíà ìåæà êîñìîñó (100 êì).";
|
|
if (km < 408f) return "Îô³ö³éíî â êîñìîñ³! ßê âèñîòà ïîëüîòó Space Shuttle.";
|
|
if (km < 36000f) return "Îðá³òà ÌÊÑ àáî âèùå. Òè ñïðàâæí³é àñòðîíàâò!";
|
|
if (km < 384000f) return "Ãåîñòàö³îíàðíà îðá³òà -- òóò âèñÿòü ñóïóòíèêè GPS ³ òåëåáà÷åííÿ.";
|
|
return "³äñòàíü ÿê äî ̳ñÿöÿ àáî äàë³. ̳æïëàíåòíèé ïðîñò³ð!";
|
|
}
|
|
|
|
private string GetRealFlightTime(float km)
|
|
{
|
|
float speedKmH = 28000f;
|
|
float hours = km / speedKmH;
|
|
|
|
if (hours < 0.017f) return (hours * 3600f).ToString("F0") + " ñåêóíä";
|
|
if (hours < 1f) return (hours * 60f).ToString("F0") + " õâèëèí";
|
|
if (hours < 24f) return hours.ToString("F1") + " ãîäèí";
|
|
if (hours < 720f) return (hours / 24f).ToString("F1") + " ä³á";
|
|
if (hours < 8760f) return (hours / 720f).ToString("F1") + " ì³ñÿö³â";
|
|
return (hours / 8760f).ToString("F1") + " ðîê³â";
|
|
}
|
|
|
|
private float GetShakeMultiplier(string planet)
|
|
{
|
|
switch (planet)
|
|
{
|
|
case "Þï³òåð": return 2.5f;
|
|
case "Âåíåðà": return 1.8f;
|
|
case "Íåïòóí": return 2.0f;
|
|
case "Ñàòóðí": return 1.2f;
|
|
case "Çåìëÿ": return 1.0f;
|
|
case "Óðàí": return 0.8f;
|
|
case "Ìàðñ": return 0.6f;
|
|
case "Ìåðêóð³é": return 0.4f;
|
|
case "̳ñÿöü": return 0.3f;
|
|
case "Ïëóòîí": return 0.2f;
|
|
default: return 1.0f;
|
|
}
|
|
}
|
|
|
|
private void Explode()
|
|
{
|
|
effectsController.StopFlight();
|
|
cameraController.StopFlight();
|
|
|
|
Vector3 pos = rocketRoot.position;
|
|
|
|
MeshRenderer[] meshes = rocketRoot.GetComponentsInChildren<MeshRenderer>();
|
|
Vector3 meshCenter = pos;
|
|
if (meshes.Length > 0)
|
|
{
|
|
meshCenter = Vector3.zero;
|
|
foreach (var mr in meshes) meshCenter += mr.bounds.center;
|
|
meshCenter /= meshes.Length;
|
|
}
|
|
|
|
if (explosionBig != null)
|
|
{
|
|
var big = Instantiate(explosionBig, meshCenter, Quaternion.identity);
|
|
big.transform.localScale = Vector3.one * 5f;
|
|
RemoveMissingScripts(big);
|
|
}
|
|
if (explosionMedium != null)
|
|
{
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
var med = Instantiate(explosionMedium,
|
|
meshCenter + new Vector3(Random.Range(-1.2f, 1.2f), Random.Range(-0.5f, 0.8f), 0f),
|
|
Quaternion.identity);
|
|
med.transform.localScale = Vector3.one * 3f;
|
|
RemoveMissingScripts(med);
|
|
}
|
|
}
|
|
if (explosionSmall != null)
|
|
{
|
|
for (int i = 0; i < 6; i++)
|
|
{
|
|
var sm = Instantiate(explosionSmall,
|
|
meshCenter + new Vector3(Random.Range(-2f, 2f), Random.Range(-1f, 2f), Random.Range(-1f, 1f)),
|
|
Quaternion.identity);
|
|
sm.transform.localScale = Vector3.one * 2.2f;
|
|
RemoveMissingScripts(sm);
|
|
}
|
|
}
|
|
if (debrisPrefab != null)
|
|
{
|
|
var debris = Instantiate(debrisPrefab, meshCenter, Quaternion.identity);
|
|
debris.SetActive(true);
|
|
foreach (var piece in debris.GetComponentsInChildren<DebrisPiece>())
|
|
{
|
|
piece.transform.position = meshCenter + Random.insideUnitSphere * 0.8f;
|
|
piece.Launch(meshCenter, Random.Range(15f, 30f), materialSelector.GetCurrentMaterial().material);
|
|
}
|
|
}
|
|
|
|
SetFlamesActive(false);
|
|
rocketRoot.gameObject.SetActive(false);
|
|
StartCoroutine(ShowInfoAndReset());
|
|
}
|
|
|
|
private void RemoveMissingScripts(GameObject obj)
|
|
{
|
|
foreach (var b in obj.GetComponentsInChildren<MonoBehaviour>())
|
|
if (b == null) DestroyImmediate(b);
|
|
}
|
|
|
|
private IEnumerator SpaceDriftAndInfo()
|
|
{
|
|
cameraController.SwitchToSpaceDrift();
|
|
effectsController.PlaySpaceDriftParticles();
|
|
float driftTime = 0f;
|
|
float driftAngle = 0f;
|
|
Vector3 driftCenter = rocketRoot.position;
|
|
while (driftTime < 3f)
|
|
{
|
|
driftTime += Time.deltaTime;
|
|
driftAngle += Time.deltaTime * 15f;
|
|
rocketRoot.position = driftCenter + new Vector3(
|
|
Mathf.Sin(driftAngle * Mathf.Deg2Rad) * 0.3f,
|
|
Mathf.Cos(driftAngle * Mathf.Deg2Rad * 0.5f) * 0.15f, 0f);
|
|
rocketRoot.rotation = Quaternion.Lerp(rocketRoot.rotation,
|
|
_rocketStartRot * Quaternion.Euler(25f, driftAngle * 0.3f, 10f), Time.deltaTime * 0.5f);
|
|
yield return null;
|
|
}
|
|
SetFlamesActive(false);
|
|
yield return new WaitForSeconds(1.5f);
|
|
rocketRoot.gameObject.SetActive(false);
|
|
effectsController.StopAllParticles();
|
|
StartCoroutine(ShowInfoAndReset());
|
|
}
|
|
|
|
private IEnumerator ShowInfoAndReset()
|
|
{
|
|
yield return new WaitForSeconds(1.5f);
|
|
|
|
int fuelLevel = fuelSelector.GetFuelLevel();
|
|
string planetName = planetSelector.GetCurrentPlanet().name;
|
|
string matName = materialSelector.GetCurrentMaterial().name;
|
|
bool exploded = _explodeOnLaunch.Contains(matName) || _explodeSoon.Contains(matName) || _planetExplode.Contains(planetName);
|
|
|
|
float realKm = GetRealHeightKm(planetName, matName, fuelLevel);
|
|
string realHeightStr = FormatRealHeight(realKm);
|
|
string heightContext = GetHeightContext(realKm);
|
|
|
|
string info;
|
|
if (exploded)
|
|
{
|
|
string reason = _planetExplode.Contains(planetName)
|
|
? (_planetExplosionReason.ContainsKey(planetName) ? _planetExplosionReason[planetName] : "Ïëàíåòà çíèùèëà ðàêåòó.")
|
|
: (_materialExplosionReason.ContainsKey(matName) ? _materialExplosionReason[matName] : "Ìàòåð³àë íå âèòðèìàâ íàâàíòàæåíü ïîëüîòó.");
|
|
string planetInfo = _planetFacts.ContainsKey(planetName) ? _planetFacts[planetName] : "";
|
|
info = "ÐÅÇÓËÜÒÀÒ ÏÎËÜÎÒÓ\n\n"
|
|
+ "Ìàòåð³àë: " + matName + "\nÏëàíåòà: " + planetName + "\n"
|
|
+ "Ïàëüíå: " + fuelSelector.GetFuelName() + "\n\n"
|
|
+ "ÏÐÈ×ÈÍÀ ÊÀÒÀÑÒÐÎÔÈ:\n" + reason + "\n\n"
|
|
+ "ÏÐÎ ÏËÀÍÅÒÓ:\n" + planetInfo;
|
|
}
|
|
else
|
|
{
|
|
string escapeNote = flightCore.RocketEscaped
|
|
? "Ðàêåòà äîñÿãëà äðóãî¿ êîñì³÷íî¿ øâèäêîñò³!\n\n" : "";
|
|
string planetInfo = _planetFacts.ContainsKey(planetName) ? _planetFacts[planetName] : "";
|
|
string matFact = _materialFacts.ContainsKey(matName) ? _materialFacts[matName] : "";
|
|
|
|
string flightTime = GetRealFlightTime(realKm);
|
|
|
|
info = "ÐÅÇÓËÜÒÀÒ ÏÎËÜÎÒÓ\n\n"
|
|
+ "Ìàòåð³àë: " + matName + "\n"
|
|
+ "Ïëàíåòà: " + planetName + "\n"
|
|
+ "Ïàëüíå: " + fuelSelector.GetFuelName() + "\n\n"
|
|
+ escapeNote
|
|
+ "Ó ÐÅÀËÜÍÎÑÒ² ÒÀÊÀ ÐÀÊÅÒÀ ÇËÅÒ²ËÀ Á ÍÀ:\n"
|
|
+ realHeightStr + "\n"
|
|
+ heightContext + "\n"
|
|
+ "×àñ ïîëüîòó: " + flightTime + "\n\n"
|
|
+ "ÔÀÊÒ ÏÐÎ ÌÀÒÅвÀË:\n" + matFact + "\n\n"
|
|
+ "ÏÐÎ ÏËÀÍÅÒÓ:\n" + planetInfo + "\n\n"
|
|
+ "Ö²ÊÀÂÎ: Äî ̳ñÿöÿ 3 äîáè. Äî Íåïòóíà 12 ðîê³â!";
|
|
}
|
|
|
|
if (infoPanelText != null) infoPanelText.text = info;
|
|
if (infoPanel != null) infoPanel.SetActive(true);
|
|
yield return new WaitForSeconds(18f);
|
|
ResetAll();
|
|
}
|
|
|
|
private void ResetAll()
|
|
{
|
|
_isLaunched = false;
|
|
_sonicBoomDone = false;
|
|
|
|
GameObject[] allObjects = GameObject.FindObjectsOfType<GameObject>();
|
|
foreach (var obj in allObjects)
|
|
{
|
|
if (obj != null && obj.name.Contains("(Clone)"))
|
|
Destroy(obj);
|
|
}
|
|
|
|
flightCore.ResetFlight();
|
|
cameraController.ResetCamera();
|
|
rocketRoot.position = _rocketStartPos;
|
|
rocketRoot.rotation = _rocketStartRot;
|
|
rocketRoot.gameObject.SetActive(true);
|
|
SetFlamesActive(true);
|
|
var pd = planetSelector.GetCurrentPlanet();
|
|
effectsController.ResetEffects(new RocketEffectsController.PlanetData
|
|
{
|
|
atmosphereThickness = pd.atmosphereThickness,
|
|
exposure = pd.exposure,
|
|
skyTint = pd.skyTint,
|
|
groundColor = pd.groundColor,
|
|
hasFog = pd.hasFog,
|
|
fogDensity = pd.fogDensity,
|
|
fogColor = pd.fogColor,
|
|
sunLightIntensity = pd.sunLightIntensity
|
|
});
|
|
planetSelector.RestoreCurrentPlanet();
|
|
if (infoPanel != null) infoPanel.SetActive(false);
|
|
if (materialPanel != null) materialPanel.SetActive(true);
|
|
}
|
|
|
|
private void SetFlamesActive(bool active)
|
|
{
|
|
foreach (var flame in flameParts)
|
|
if (flame != null) flame.gameObject.SetActive(active);
|
|
}
|
|
} |