1424 lines
69 KiB
C#
1424 lines
69 KiB
C#
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using Mirror;
|
|
|
|
/// <summary>
|
|
/// PlayerInteraction.cs - v6.13 Multijoueur
|
|
///
|
|
/// v6.13 : Fix des syncs manquantes en multijoueur
|
|
/// BUG 1 : La pile de ZoneLivraison ne se reorganise pas cote autres clients
|
|
/// quand un joueur ramasse un article (le client qui ramasse reorganise
|
|
/// en local, les autres ne voient rien bouger).
|
|
/// Fix : CmdReorganiserZoneLivraison envoie la reorganisation au serveur,
|
|
/// qui modifie les positions des articles -> Mirror sync via NetworkTransform.
|
|
///
|
|
/// BUG 2 : Les equipements poses sur le chariot "volent" quand l'autre
|
|
/// joueur pilote. Mirror ne sync pas le SetParent, donc seul le client qui
|
|
/// a pose voit les equipements parentes au chariot. Les autres les voient
|
|
/// a leur position monde figee au moment de la pose.
|
|
/// Fix : CmdParenterAuChariot + RpcParenterAuChariot pour broadcaster le
|
|
/// SetParent a tous les clients (chacun fait SetParent local). Idem pour
|
|
/// le detachement au ramassage (CmdDetacherDuChariot + RpcDetacherDuChariot).
|
|
///
|
|
/// v6.12 : Transfert d'autorite pour le pilotage du chariot en multijoueur
|
|
/// v6.11 : Pose/retrait des torons sur les axes lateraux du chariot
|
|
/// v6.10 : Fix critique - objets qui flottent apres avoir ete poses sur le chariot
|
|
/// v6.9 : Integration du systeme de pose plateau / etagere basse du Chariot v7.x
|
|
/// - Detection des zones de pose via RaycastAll + tri par distance
|
|
/// - Distinction automatique zonePosePlateau vs zonePoseEtagere
|
|
/// - Affichage du fantome a la bonne position via AfficherFantomePose(tailleU, surEtagereBasse)
|
|
/// - Cachage des fantomes quand on quitte le chariot du regard ou qu'on pose
|
|
/// - Pose sur etagere basse via PoserEquipementSurEtagere
|
|
/// - Ramassage depuis etagere basse (via equipementsSurEtagere.Contains)
|
|
///
|
|
/// v6.8 : Systeme d'assise sur les chaises
|
|
/// v6.7 : Placement local client pour supports muraux
|
|
/// v6.5 : Remise de PDU sur SupportPDU
|
|
/// v6.4 : Portage toron "dans les mains"
|
|
/// v6.3 : Placement precis toron sur axe cible
|
|
/// v6.2 : Remise de toron sur SupportTorons
|
|
/// </summary>
|
|
public class PlayerInteraction : NetworkBehaviour
|
|
{
|
|
[Header("Interaction")]
|
|
public float porteeInteraction = 4f;
|
|
public KeyCode toucheInteraction = KeyCode.E;
|
|
public KeyCode toucheConfiguration = KeyCode.F;
|
|
|
|
[Header("Performance")]
|
|
[Range(1, 5)]
|
|
public int detectInterval = 2;
|
|
public bool detecterTriggers = false;
|
|
|
|
[Header("Transport")]
|
|
public float distanceTransport = 1.5f;
|
|
public float hauteurTransport = 0.6f;
|
|
public float decalageHorizontal = 0f;
|
|
public float vitesseSuivi = 15f;
|
|
|
|
[Header("Transport — Toron (v6.4)")]
|
|
public float distanceTransportToron = 0.85f;
|
|
public float hauteurTransportToron = 0.15f;
|
|
public float decalageHorizontalToron = 0.35f;
|
|
public Vector3 rotationEulerToron = new Vector3(0f, 90f, 0f);
|
|
|
|
[Header("Remise sur supports muraux (v6.2/6.5)")]
|
|
public float distanceDetectionSupport = 3.5f;
|
|
public float angleDetectionSupport = 35f;
|
|
|
|
private Camera _camera;
|
|
private Interactable _objetSurvole;
|
|
private Interactable _objetEnMain;
|
|
private Rigidbody _rbEnMain;
|
|
private Vector3 _cibleTransport;
|
|
private Quaternion _rotationOffsetTransport = Quaternion.identity;
|
|
|
|
private RackSlot _slotSurvole;
|
|
private Chariot _chariotPilote;
|
|
private Chariot _chariotVise;
|
|
private bool _visePoignee = false;
|
|
// v6.9 : distinction zone plateau/etagere du chariot vise
|
|
private bool _chariotZoneEtagereVisee = false;
|
|
// v6.11 : index de l'axe toron cible sur le chariot (0=Gauche, 1=Droit, -1=aucun)
|
|
private int _chariotAxeToronCibleIndex = -1;
|
|
|
|
private EmplacementBaie _emplacementVise;
|
|
private EmplacementPDU _emplacementPDUVise;
|
|
private PorteBaie _porteVisee;
|
|
|
|
private PriseC13 _priseSurvolee;
|
|
private BoutonPower _boutonPowerVise;
|
|
|
|
// v6.8 : système d'assise
|
|
private ChaiseSiege _chaiseSiegeVisee;
|
|
private ChaiseSiege _chaiseSiegeActuelle;
|
|
|
|
private List<Collider> _collisionsIgnorees = new List<Collider>();
|
|
private EmplacementBaie[] _tousEmplacements;
|
|
private bool _emplacementsVisibles = false;
|
|
private bool _emplacementsPDUVisibles = false;
|
|
|
|
private int _detectFrame = 0;
|
|
|
|
private MenuPause _cachedPause;
|
|
private MenuPrincipal _cachedMenu;
|
|
private bool _cacheInitialized = false;
|
|
|
|
// v6.2 : axe cible courant sur SupportTorons
|
|
private int _axeSupportCibleLigne = -1;
|
|
private int _axeSupportCibleColonne = -1;
|
|
|
|
// v6.5 : emplacement cible courant sur SupportPDU
|
|
private int _emplacementSupportPDUCibleLigne = -1;
|
|
private int _emplacementSupportPDUCibleColonne = -1;
|
|
|
|
[SyncVar(hook = nameof(OnObjetPorteChange))]
|
|
private uint _objetPorteNetId = 0;
|
|
|
|
private GameObject _objetPorteDistant;
|
|
|
|
public Interactable ObjetEnMain => _objetEnMain;
|
|
|
|
void Start()
|
|
{
|
|
_camera = GetComponentInChildren<Camera>();
|
|
if (_camera == null) _camera = Camera.main;
|
|
}
|
|
|
|
private bool _popupEtaitOuvert = false;
|
|
|
|
void Update()
|
|
{
|
|
if (!isLocalPlayer) return;
|
|
|
|
// v6.8 : mode assis — seul [E] pour se lever est actif
|
|
if (_chaiseSiegeActuelle != null)
|
|
{
|
|
if (Input.GetKeyDown(toucheInteraction))
|
|
{
|
|
_chaiseSiegeActuelle.SeLever();
|
|
_chaiseSiegeActuelle = null;
|
|
HUDManager hud = GetComponent<HUDManager>();
|
|
if (hud != null) hud.SetInfoEquipement("");
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (_camera == null) _camera = Camera.main;
|
|
|
|
if (UIConfigurationEquipement.Instance != null && UIConfigurationEquipement.Instance.EstOuvert())
|
|
{
|
|
_popupEtaitOuvert = true;
|
|
return;
|
|
}
|
|
|
|
if (_popupEtaitOuvert)
|
|
{
|
|
_popupEtaitOuvert = false;
|
|
Cursor.lockState = CursorLockMode.Locked;
|
|
Cursor.visible = false;
|
|
var playerInput = GetComponent<UnityEngine.InputSystem.PlayerInput>();
|
|
if (playerInput != null) playerInput.enabled = true;
|
|
var fpc = GetComponent<StarterAssets.FirstPersonController>();
|
|
if (fpc != null) fpc.enabled = true;
|
|
}
|
|
|
|
if (Cursor.visible && _objetEnMain == null)
|
|
{
|
|
if (!_cacheInitialized || _cachedPause == null) { _cachedPause = FindObjectOfType<MenuPause>(); _cachedMenu = FindObjectOfType<MenuPrincipal>(); if (_cachedPause != null) _cacheInitialized = true; }
|
|
bool pauseOuverte = (_cachedPause != null && _cachedPause.estEnPause);
|
|
bool menuOuvert = (_cachedMenu != null && _cachedMenu.EstAffiche());
|
|
MonitoringDatacenter monitoring = FindObjectOfType<MonitoringDatacenter>();
|
|
bool monitoringOuvert = (monitoring != null && monitoring.EstAffiche());
|
|
PlanSalle plan = FindObjectOfType<PlanSalle>();
|
|
bool planOuvert = (plan != null && plan.EstOuvert());
|
|
UIBoutique boutique = FindObjectOfType<UIBoutique>();
|
|
bool boutiqueOuverte = (boutique != null && boutique.panneauPrincipal != null && boutique.panneauPrincipal.activeSelf);
|
|
UIConfigurationEquipement configPopup = UIConfigurationEquipement.Instance;
|
|
bool configOuverte = (configPopup != null && configPopup.EstOuvert());
|
|
UITickets tickets = UITickets.Instance;
|
|
bool ticketsOuverts = (tickets != null && tickets.EstAffiche());
|
|
|
|
if (!pauseOuverte && !menuOuvert && !monitoringOuvert && !planOuvert && !boutiqueOuverte && !configOuverte && !ticketsOuverts)
|
|
{
|
|
Cursor.lockState = CursorLockMode.Locked;
|
|
Cursor.visible = false;
|
|
var fpc2 = GetComponent<StarterAssets.FirstPersonController>();
|
|
if (fpc2 != null) fpc2.enabled = true;
|
|
var pi2 = GetComponent<UnityEngine.InputSystem.PlayerInput>();
|
|
if (pi2 != null) pi2.enabled = true;
|
|
}
|
|
}
|
|
|
|
if (_objetEnMain == null)
|
|
{
|
|
if (Time.frameCount % detectInterval == 0)
|
|
DetecterObjet();
|
|
if (_emplacementsVisibles) { SetEmplacementsVisibles(false); _emplacementsVisibles = false; }
|
|
if (_emplacementsPDUVisibles) { SetEmplacementsPDUVisibles(false); _emplacementsPDUVisibles = false; }
|
|
if (_axeSupportCibleLigne >= 0) QuitterSurvolSupport();
|
|
if (_emplacementSupportPDUCibleLigne >= 0) QuitterSurvolSupportPDU();
|
|
// v6.9 : cacher les fantomes du chariot quand on n'a plus rien en main
|
|
CacherFantomesChariotTous();
|
|
}
|
|
else
|
|
{
|
|
DetecterCiblePose();
|
|
bool portePDU = _objetEnMain.GetComponent<PDU>() != null;
|
|
if (portePDU && !_emplacementsPDUVisibles) { SetEmplacementsPDUVisibles(true); _emplacementsPDUVisibles = true; }
|
|
if (!portePDU && _emplacementsPDUVisibles) { SetEmplacementsPDUVisibles(false); _emplacementsPDUVisibles = false; }
|
|
if (_emplacementsVisibles) { SetEmplacementsVisibles(false); _emplacementsVisibles = false; }
|
|
}
|
|
|
|
if (Input.GetKeyDown(toucheInteraction))
|
|
{
|
|
// v6.8 : s'asseoir si on vise une chaise et pas d'objet en main
|
|
if (_chaiseSiegeVisee != null && _objetEnMain == null)
|
|
{
|
|
if (_chaiseSiegeVisee.Asseoir(gameObject))
|
|
{
|
|
_chaiseSiegeActuelle = _chaiseSiegeVisee;
|
|
_chaiseSiegeVisee = null;
|
|
HUDManager hud = GetComponent<HUDManager>();
|
|
if (hud != null) hud.SetInfoEquipement("[E] Se lever");
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (_boutonPowerVise != null && _objetEnMain == null) { CmdAppuyerBoutonPower(_boutonPowerVise.GetComponentInParent<NetworkIdentity>().netId); return; }
|
|
if (_priseSurvolee != null && _priseSurvolee.estConnectee && _objetEnMain == null) { CmdBasculerInterrupteur(_priseSurvolee.GetComponentInParent<NetworkIdentity>().netId); return; }
|
|
if (_porteVisee != null && _objetEnMain == null)
|
|
{
|
|
NetworkIdentity porteNetId = _porteVisee.GetComponentInParent<NetworkIdentity>();
|
|
if (porteNetId != null) CmdTogglePorte(porteNetId.netId, _porteVisee.gameObject.name);
|
|
return;
|
|
}
|
|
|
|
if (_chariotPilote != null && _objetEnMain == null && _visePoignee)
|
|
{
|
|
LacherChariot();
|
|
QuitterSurvol();
|
|
return;
|
|
}
|
|
|
|
if (_objetEnMain == null && _objetSurvole != null) Ramasser();
|
|
else if (_objetEnMain != null) Poser();
|
|
}
|
|
|
|
if (Input.GetKeyDown(toucheConfiguration) && _objetEnMain == null && _objetSurvole != null)
|
|
{
|
|
RackSlot slotConfig = TrouverSlotDeEquipement(_objetSurvole);
|
|
if (slotConfig != null)
|
|
{
|
|
ConfigurationEquipement config = _objetSurvole.GetComponent<ConfigurationEquipement>();
|
|
if (config == null) config = _objetSurvole.gameObject.AddComponent<ConfigurationEquipement>();
|
|
if (UIConfigurationEquipement.Instance != null)
|
|
{ UIConfigurationEquipement.Instance.Ouvrir(config, premiereOuverture: false); QuitterSurvol(); }
|
|
}
|
|
}
|
|
|
|
if (Input.GetKeyDown(KeyCode.F5) && isServer && SaveManager.Instance != null)
|
|
{
|
|
if (SaveManager.Instance.SauvegardeRapide())
|
|
Debug.Log("[QuickSave] Sauvegarde rapide effectuée !");
|
|
}
|
|
}
|
|
|
|
void FixedUpdate()
|
|
{
|
|
if (!isLocalPlayer) return;
|
|
|
|
if (_objetEnMain != null && _rbEnMain != null)
|
|
{
|
|
Vector3 dir = new Vector3(_camera.transform.forward.x, 0, _camera.transform.forward.z).normalized;
|
|
|
|
bool estToron = _objetEnMain.GetComponent<ToronProcedural>() != null;
|
|
float dist = estToron ? distanceTransportToron : distanceTransport;
|
|
float hauteur = estToron ? hauteurTransportToron : hauteurTransport;
|
|
float decalage = estToron ? decalageHorizontalToron : decalageHorizontal;
|
|
|
|
_cibleTransport = transform.position + dir * dist
|
|
+ Vector3.up * hauteur + _camera.transform.right * decalage;
|
|
Vector3 direction = _cibleTransport - _rbEnMain.position;
|
|
Vector3 desiredVelocity = direction * vitesseSuivi;
|
|
if (direction.magnitude > 0.05f)
|
|
{
|
|
RaycastHit hit;
|
|
int excludeMask = ~LayerMask.GetMask("Joueur", "Equipement", "Sol", "Baie", "Default", "Emplacement");
|
|
if (Physics.SphereCast(_rbEnMain.position, 0.15f, direction.normalized, out hit, direction.magnitude, excludeMask))
|
|
if (!EstColliderIgnore(hit.collider) && hit.distance < 0.15f)
|
|
desiredVelocity = Vector3.ProjectOnPlane(desiredVelocity, hit.normal);
|
|
}
|
|
_rbEnMain.velocity = desiredVelocity;
|
|
|
|
if (estToron)
|
|
_rbEnMain.rotation = Quaternion.LookRotation(dir) * Quaternion.Euler(rotationEulerToron);
|
|
else
|
|
_rbEnMain.rotation = Quaternion.LookRotation(dir) * _rotationOffsetTransport;
|
|
|
|
CmdUpdateTransportPosition(_rbEnMain.position, _rbEnMain.rotation);
|
|
}
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════
|
|
// COMMANDS
|
|
// ══════════════════════════════════════════════════════════
|
|
|
|
[Command]
|
|
void CmdRamasser(uint objetNetId)
|
|
{
|
|
if (!NetworkServer.spawned.ContainsKey(objetNetId)) return;
|
|
_objetPorteNetId = objetNetId;
|
|
var obj = NetworkServer.spawned[objetNetId];
|
|
Rigidbody rb = obj.GetComponent<Rigidbody>();
|
|
if (rb != null) { rb.isKinematic = false; rb.useGravity = false; rb.freezeRotation = true; }
|
|
RpcOnRamasser(objetNetId);
|
|
}
|
|
|
|
[Command]
|
|
void CmdPoser(uint objetNetId, Vector3 position, Quaternion rotation, bool avecGravite, bool estRacke)
|
|
{
|
|
if (!NetworkServer.spawned.ContainsKey(objetNetId)) return;
|
|
_objetPorteNetId = 0;
|
|
var obj = NetworkServer.spawned[objetNetId];
|
|
obj.transform.position = position;
|
|
obj.transform.rotation = rotation;
|
|
Rigidbody rb = obj.GetComponent<Rigidbody>();
|
|
if (rb != null)
|
|
{
|
|
if (estRacke) { if (!rb.isKinematic) { rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; } rb.isKinematic = true; }
|
|
else { rb.isKinematic = false; rb.useGravity = avecGravite; rb.velocity = Vector3.zero; rb.freezeRotation = false; rb.interpolation = RigidbodyInterpolation.None; }
|
|
}
|
|
RpcOnPoser(objetNetId, position, rotation, avecGravite, estRacke);
|
|
}
|
|
|
|
[Command]
|
|
void CmdPoserToronSurSupport(uint toronNetId, int ligne, int colonne)
|
|
{
|
|
if (!NetworkServer.spawned.ContainsKey(toronNetId)) return;
|
|
_objetPorteNetId = 0;
|
|
var obj = NetworkServer.spawned[toronNetId];
|
|
if (obj == null) return;
|
|
bool place = false;
|
|
if (SupportTorons.Instance != null)
|
|
{
|
|
if (ligne >= 0 && colonne >= 0) place = SupportTorons.Instance.PoserToronSurAxeSpecifique(obj.gameObject, ligne, colonne);
|
|
if (!place) place = SupportTorons.Instance.PoserToron(obj.gameObject);
|
|
}
|
|
if (place) { RpcOnPoser(toronNetId, obj.transform.position, obj.transform.rotation, false, true); }
|
|
else { Rigidbody rb = obj.GetComponent<Rigidbody>(); if (rb != null) { rb.isKinematic = false; rb.useGravity = true; rb.velocity = Vector3.zero; } RpcOnPoser(toronNetId, obj.transform.position, obj.transform.rotation, true, false); }
|
|
}
|
|
|
|
[Command]
|
|
void CmdPoserPDUSurSupport(uint pduNetId, int ligne, int colonne)
|
|
{
|
|
if (!NetworkServer.spawned.ContainsKey(pduNetId)) return;
|
|
_objetPorteNetId = 0;
|
|
var obj = NetworkServer.spawned[pduNetId];
|
|
if (obj == null) return;
|
|
bool place = false;
|
|
if (SupportPDU.Instance != null)
|
|
{
|
|
if (ligne >= 0 && colonne >= 0) place = SupportPDU.Instance.PoserPDUSurEmplacementSpecifique(obj.gameObject, ligne, colonne);
|
|
if (!place) place = SupportPDU.Instance.PoserPDU(obj.gameObject);
|
|
}
|
|
if (place) { RpcOnPoser(pduNetId, obj.transform.position, obj.transform.rotation, false, true); }
|
|
else { Rigidbody rb = obj.GetComponent<Rigidbody>(); if (rb != null) { rb.isKinematic = false; rb.useGravity = true; rb.velocity = Vector3.zero; } RpcOnPoser(pduNetId, obj.transform.position, obj.transform.rotation, true, false); }
|
|
}
|
|
|
|
[Command(channel = Channels.Unreliable)]
|
|
void CmdUpdateTransportPosition(Vector3 position, Quaternion rotation) { RpcUpdateTransportPosition(position, rotation); }
|
|
|
|
[Command]
|
|
void CmdAppuyerBoutonPower(uint equipNetId)
|
|
{
|
|
if (!NetworkServer.spawned.ContainsKey(equipNetId)) return;
|
|
var obj = NetworkServer.spawned[equipNetId];
|
|
BoutonPower bouton = obj.GetComponentInChildren<BoutonPower>();
|
|
if (bouton != null) { bouton.Appuyer(); RpcSyncBoutonPower(equipNetId, bouton.estAllume); }
|
|
}
|
|
|
|
[ClientRpc]
|
|
void RpcSyncBoutonPower(uint equipNetId, bool estAllume)
|
|
{
|
|
if (!NetworkClient.spawned.ContainsKey(equipNetId)) return;
|
|
var obj = NetworkClient.spawned[equipNetId];
|
|
BoutonPower bouton = obj.GetComponentInChildren<BoutonPower>();
|
|
if (bouton != null && bouton.estAllume != estAllume) bouton.Appuyer();
|
|
}
|
|
|
|
[Command]
|
|
void CmdBasculerInterrupteur(uint pduNetId)
|
|
{
|
|
if (!NetworkServer.spawned.ContainsKey(pduNetId)) return;
|
|
var obj = NetworkServer.spawned[pduNetId];
|
|
PriseC13 prise = obj.GetComponentInChildren<PriseC13>();
|
|
if (prise != null) prise.BasculerInterrupteur();
|
|
}
|
|
|
|
[Command]
|
|
void CmdInstallerPDU(uint pduNetId, Vector3 position, Quaternion rotation)
|
|
{
|
|
if (!NetworkServer.spawned.ContainsKey(pduNetId)) return;
|
|
var obj = NetworkServer.spawned[pduNetId];
|
|
PDU pdu = obj.GetComponent<PDU>();
|
|
if (pdu == null) return;
|
|
PDUNetworkState netState = obj.GetComponent<PDUNetworkState>();
|
|
if (netState != null) netState.ServerSetInstalle(true, (int)pdu.coteInstallation);
|
|
else pdu.estInstalle = true;
|
|
RpcInstallerPDU(pduNetId, position, rotation);
|
|
}
|
|
|
|
[ClientRpc]
|
|
void RpcInstallerPDU(uint pduNetId, Vector3 position, Quaternion rotation)
|
|
{
|
|
if (!NetworkClient.spawned.ContainsKey(pduNetId)) return;
|
|
var obj = NetworkClient.spawned[pduNetId];
|
|
PDU pdu = obj.GetComponent<PDU>();
|
|
if (pdu == null) return;
|
|
pdu.estInstalle = true;
|
|
if (!isLocalPlayer) { obj.transform.position = position; obj.transform.rotation = rotation; Rigidbody rb = obj.GetComponent<Rigidbody>(); if (rb != null) { rb.isKinematic = true; rb.useGravity = false; } }
|
|
}
|
|
|
|
[Command]
|
|
void CmdDesinstallerPDU(uint pduNetId)
|
|
{
|
|
if (!NetworkServer.spawned.ContainsKey(pduNetId)) return;
|
|
var obj = NetworkServer.spawned[pduNetId];
|
|
PDU pdu = obj.GetComponent<PDU>();
|
|
if (pdu == null) return;
|
|
PDUNetworkState netState = obj.GetComponent<PDUNetworkState>();
|
|
if (netState != null) netState.ServerSetInstalle(false);
|
|
else pdu.estInstalle = false;
|
|
RpcDesinstallerPDU(pduNetId);
|
|
}
|
|
|
|
[ClientRpc]
|
|
void RpcDesinstallerPDU(uint pduNetId)
|
|
{
|
|
if (!NetworkClient.spawned.ContainsKey(pduNetId)) return;
|
|
var obj = NetworkClient.spawned[pduNetId];
|
|
PDU pdu = obj.GetComponent<PDU>();
|
|
if (pdu != null) { pdu.estInstalle = false; Rigidbody rb = obj.GetComponent<Rigidbody>(); if (rb != null) { rb.isKinematic = false; rb.useGravity = true; } }
|
|
}
|
|
|
|
[Command]
|
|
void CmdInstallerDansSlot(uint equipNetId, uint baieNetId, int slotIndex)
|
|
{
|
|
if (!NetworkServer.spawned.ContainsKey(equipNetId) || !NetworkServer.spawned.ContainsKey(baieNetId)) return;
|
|
var equipObj = NetworkServer.spawned[equipNetId]; var baieObj = NetworkServer.spawned[baieNetId];
|
|
RackSlot[] slots = baieObj.GetComponentsInChildren<RackSlot>();
|
|
if (slotIndex >= 0 && slotIndex < slots.Length) { RackSlot slot = slots[slotIndex]; if (!slot.estOccupe) { slot.estOccupe = true; slot.equipementInstalle = equipObj.GetComponent<Interactable>(); } }
|
|
RpcInstallerDansSlot(equipNetId, baieNetId, slotIndex);
|
|
}
|
|
|
|
[ClientRpc]
|
|
void RpcInstallerDansSlot(uint equipNetId, uint baieNetId, int slotIndex)
|
|
{
|
|
if (isLocalPlayer) return;
|
|
if (!NetworkClient.spawned.ContainsKey(equipNetId) || !NetworkClient.spawned.ContainsKey(baieNetId)) return;
|
|
var equipObj = NetworkClient.spawned[equipNetId]; var baieObj = NetworkClient.spawned[baieNetId];
|
|
RackSlot[] slots = baieObj.GetComponentsInChildren<RackSlot>();
|
|
if (slotIndex >= 0 && slotIndex < slots.Length) { RackSlot slot = slots[slotIndex]; if (!slot.estOccupe) { slot.estOccupe = true; slot.equipementInstalle = equipObj.GetComponent<Interactable>(); } }
|
|
}
|
|
|
|
[Command]
|
|
void CmdTogglePorte(uint baieNetId, string nomPorte)
|
|
{
|
|
if (!NetworkServer.spawned.ContainsKey(baieNetId)) return;
|
|
var obj = NetworkServer.spawned[baieNetId];
|
|
foreach (PorteBaie porte in obj.GetComponentsInChildren<PorteBaie>())
|
|
if (porte.gameObject.name == nomPorte) { porte.TogglePorte(); RpcTogglePorte(baieNetId, nomPorte); break; }
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════
|
|
// CLIENT RPCs
|
|
// ══════════════════════════════════════════════════════════
|
|
|
|
[ClientRpc]
|
|
void RpcOnRamasser(uint objetNetId)
|
|
{
|
|
if (isLocalPlayer) return;
|
|
if (!NetworkClient.spawned.ContainsKey(objetNetId)) return;
|
|
var obj = NetworkClient.spawned[objetNetId];
|
|
_objetPorteDistant = obj.gameObject;
|
|
Rigidbody rb = obj.GetComponent<Rigidbody>();
|
|
if (rb != null) { rb.isKinematic = true; rb.velocity = Vector3.zero; }
|
|
Interactable inter = obj.GetComponent<Interactable>();
|
|
if (inter != null) inter.estRamasse = true;
|
|
}
|
|
|
|
[ClientRpc]
|
|
void RpcOnPoser(uint objetNetId, Vector3 position, Quaternion rotation, bool avecGravite, bool estRacke)
|
|
{
|
|
if (isLocalPlayer) return;
|
|
if (!NetworkClient.spawned.ContainsKey(objetNetId)) return;
|
|
var obj = NetworkClient.spawned[objetNetId];
|
|
obj.transform.position = position; obj.transform.rotation = rotation;
|
|
Rigidbody rb = obj.GetComponent<Rigidbody>();
|
|
if (rb != null)
|
|
{
|
|
if (estRacke) { if (!rb.isKinematic) { rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; } rb.isKinematic = true; }
|
|
else { rb.isKinematic = false; rb.useGravity = avecGravite; rb.velocity = Vector3.zero; }
|
|
}
|
|
Interactable inter = obj.GetComponent<Interactable>();
|
|
if (inter != null) inter.estRamasse = false;
|
|
_objetPorteDistant = null;
|
|
}
|
|
|
|
[ClientRpc(channel = Channels.Unreliable)]
|
|
void RpcUpdateTransportPosition(Vector3 position, Quaternion rotation)
|
|
{
|
|
if (isLocalPlayer) return;
|
|
if (_objetPorteDistant != null)
|
|
{
|
|
_objetPorteDistant.transform.position = Vector3.Lerp(_objetPorteDistant.transform.position, position, Time.deltaTime * 20f);
|
|
_objetPorteDistant.transform.rotation = Quaternion.Slerp(_objetPorteDistant.transform.rotation, rotation, Time.deltaTime * 20f);
|
|
}
|
|
}
|
|
|
|
[ClientRpc]
|
|
void RpcTogglePorte(uint baieNetId, string nomPorte)
|
|
{
|
|
if (isServer) return;
|
|
if (!NetworkClient.spawned.ContainsKey(baieNetId)) return;
|
|
var obj = NetworkClient.spawned[baieNetId];
|
|
foreach (PorteBaie porte in obj.GetComponentsInChildren<PorteBaie>())
|
|
if (porte.gameObject.name == nomPorte) { porte.TogglePorte(); break; }
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════
|
|
// HOOK SyncVar
|
|
// ══════════════════════════════════════════════════════════
|
|
|
|
void OnObjetPorteChange(uint ancienId, uint nouveauId)
|
|
{
|
|
if (isLocalPlayer) return;
|
|
if (nouveauId == 0) _objetPorteDistant = null;
|
|
else if (NetworkClient.spawned.ContainsKey(nouveauId)) _objetPorteDistant = NetworkClient.spawned[nouveauId].gameObject;
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════
|
|
// HELPERS LOCAUX
|
|
// ══════════════════════════════════════════════════════════
|
|
|
|
private bool EstColliderIgnore(Collider col) { for (int i = 0; i < _collisionsIgnorees.Count; i++) if (_collisionsIgnorees[i] == col) return true; return false; }
|
|
|
|
void SetEmplacementsVisibles(bool visible)
|
|
{
|
|
if (_tousEmplacements == null || _tousEmplacements.Length == 0) _tousEmplacements = FindObjectsOfType<EmplacementBaie>();
|
|
foreach (EmplacementBaie empl in _tousEmplacements) if (empl != null && !empl.estOccupe) empl.SetModeVisible(visible);
|
|
}
|
|
|
|
void SetEmplacementsPDUVisibles(bool visible)
|
|
{
|
|
foreach (EmplacementPDU empl in FindObjectsOfType<EmplacementPDU>()) if (empl != null && !empl.estOccupe) empl.SetModeVisible(visible);
|
|
}
|
|
|
|
// v6.9 : helper pour cacher les fantomes du chariot
|
|
void CacherFantomesChariotTous()
|
|
{
|
|
if (_chariotVise != null) { _chariotVise.CacherFantomes(); }
|
|
if (_chariotPilote != null) { _chariotPilote.CacherFantomes(); }
|
|
// v6.11 : CacherFantomes() inclut deja le fantome toron axe
|
|
// (cf. Chariot.CacherFantomes v7.3) mais on le reappelle explicitement ici
|
|
// au cas ou la version du Chariot n'aurait pas encore ete mise a jour
|
|
if (_chariotVise != null) _chariotVise.CacherFantomeToronAxe();
|
|
if (_chariotPilote != null) _chariotPilote.CacherFantomeToronAxe();
|
|
}
|
|
|
|
// ==================== DETECTION OBJET ====================
|
|
|
|
void DetecterObjet()
|
|
{
|
|
QuitterSurvolSlot(); QuitterSurvolEmplacement(); QuitterSurvolEmplacementPDU();
|
|
QuitterSurvolPrise(); QuitterSurvolBoutonPower();
|
|
_chariotVise = null; _visePoignee = false; _porteVisee = null;
|
|
|
|
if (_camera == null) return;
|
|
|
|
Ray rayon = new Ray(_camera.transform.position, _camera.transform.forward);
|
|
QueryTriggerInteraction triggerMode = detecterTriggers ? QueryTriggerInteraction.Collide : QueryTriggerInteraction.Ignore;
|
|
|
|
int maskObjets = ~LayerMask.GetMask("Joueur", "Baie");
|
|
RaycastHit hitSimple;
|
|
if (Physics.Raycast(rayon, out hitSimple, porteeInteraction, maskObjets, triggerMode))
|
|
{
|
|
if (!EstColliderIgnore(hitSimple.collider))
|
|
if (TraiterHitDetection(hitSimple)) return;
|
|
}
|
|
|
|
int maskBaie = LayerMask.GetMask("Baie");
|
|
if (Physics.Raycast(rayon, out hitSimple, porteeInteraction, maskBaie, triggerMode))
|
|
{
|
|
if (!EstColliderIgnore(hitSimple.collider))
|
|
if (TraiterHitBaie(hitSimple)) return;
|
|
}
|
|
|
|
QuitterSurvol();
|
|
}
|
|
|
|
bool TraiterHitDetection(RaycastHit impact)
|
|
{
|
|
// v6.8 : chaise pour s'asseoir
|
|
ChaiseSiege chaise = impact.collider.GetComponentInParent<ChaiseSiege>();
|
|
if (chaise != null && !chaise.estOccupee && _objetEnMain == null)
|
|
{
|
|
_chaiseSiegeVisee = chaise;
|
|
HUDManager hud = GetComponent<HUDManager>();
|
|
if (hud != null) hud.SetInfoEquipement("[E] S'asseoir");
|
|
QuitterSurvol();
|
|
return true;
|
|
}
|
|
if (_chaiseSiegeVisee != null && chaise == null)
|
|
_chaiseSiegeVisee = null;
|
|
|
|
BoutonPower bouton = impact.collider.GetComponent<BoutonPower>();
|
|
if (bouton != null) { _boutonPowerVise = bouton; bouton.Survoler(true); return true; }
|
|
|
|
PriseC13 prise = impact.collider.GetComponent<PriseC13>();
|
|
if (prise != null) { _priseSurvolee = prise; prise.Survoler(true); return true; }
|
|
|
|
PorteBaie porte = impact.collider.GetComponentInParent<PorteBaie>();
|
|
if (porte != null) { _porteVisee = porte; QuitterSurvol(); return true; }
|
|
|
|
Chariot chariotHit = impact.collider.GetComponentInParent<Chariot>();
|
|
if (chariotHit != null && impact.collider.gameObject.name == "Ch_PoigneeZone")
|
|
{
|
|
_visePoignee = true;
|
|
Interactable ci = chariotHit.GetComponent<Interactable>();
|
|
if (ci != null) SetSurvol(ci);
|
|
return true;
|
|
}
|
|
|
|
MonitoringDatacenter monitoring = impact.collider.GetComponent<MonitoringDatacenter>();
|
|
if (monitoring != null) { Interactable interMon = impact.collider.GetComponent<Interactable>(); if (interMon != null) SetSurvol(interMon); return true; }
|
|
|
|
PDU pduVise = impact.collider.GetComponentInParent<PDU>();
|
|
if (pduVise != null && pduVise.estInstalle) { Interactable interPDU = pduVise.GetComponent<Interactable>(); if (interPDU != null) { SetSurvol(interPDU); return true; } }
|
|
|
|
Interactable obj = impact.collider.GetComponentInParent<Interactable>();
|
|
if (obj != null)
|
|
{
|
|
if (obj.GetComponent<Chariot>() != null && !_visePoignee) { QuitterSurvol(); return true; }
|
|
SetSurvol(obj); return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool TraiterHitBaie(RaycastHit impact)
|
|
{
|
|
if (impact.collider.gameObject.name == "BaieZoneTrigger") return false;
|
|
PorteBaie porte = impact.collider.GetComponent<PorteBaie>();
|
|
if (porte != null) { _porteVisee = porte; QuitterSurvol(); return true; }
|
|
RackSlot slot = impact.collider.GetComponent<RackSlot>();
|
|
if (slot != null && slot.estOccupe && slot.equipementInstalle != null)
|
|
{
|
|
if (!PorteAvantOuverte(slot)) return false;
|
|
BoutonPower boutonRack = slot.equipementInstalle.GetComponentInChildren<BoutonPower>();
|
|
if (boutonRack != null && ViseBouton(boutonRack.transform.position)) { _boutonPowerVise = boutonRack; boutonRack.Survoler(true); return true; }
|
|
SetSurvol(slot.equipementInstalle); return true;
|
|
}
|
|
EmplacementPDU emplPDU = impact.collider.GetComponent<EmplacementPDU>();
|
|
if (emplPDU != null) return false;
|
|
return false;
|
|
}
|
|
|
|
// ==================== DETECTION CIBLE POSE ====================
|
|
|
|
void DetecterCiblePose()
|
|
{
|
|
_porteVisee = null;
|
|
QuitterSurvolSlot(); QuitterSurvolEmplacement(); QuitterSurvolEmplacementPDU();
|
|
|
|
if (_camera == null) return;
|
|
|
|
if (DetecterCibleSupportTorons()) return;
|
|
QuitterSurvolSupport();
|
|
|
|
if (DetecterCibleSupportPDU()) return;
|
|
QuitterSurvolSupportPDU();
|
|
|
|
Ray rayon = new Ray(_camera.transform.position, _camera.transform.forward);
|
|
bool portePDU = _objetEnMain != null && _objetEnMain.GetComponent<PDU>() != null;
|
|
|
|
List<Collider> colsPortes = new List<Collider>();
|
|
if (_objetEnMain != null)
|
|
foreach (Collider c in _objetEnMain.GetComponentsInChildren<Collider>())
|
|
if (c.enabled) { c.enabled = false; colsPortes.Add(c); }
|
|
|
|
int slotMask = LayerMask.GetMask("Baie", "Sol", "Emplacement");
|
|
RaycastHit[] hits = Physics.RaycastAll(rayon, porteeInteraction, slotMask, QueryTriggerInteraction.Collide);
|
|
System.Array.Sort(hits, (a, b) => a.distance.CompareTo(b.distance));
|
|
foreach (Collider c in colsPortes) c.enabled = true;
|
|
|
|
RackSlot slotTouche = null; EmplacementBaie emplTouche = null; EmplacementPDU emplPDUTouche = null;
|
|
|
|
foreach (var hit in hits)
|
|
{
|
|
if (hit.collider.gameObject.name == "BaieZoneTrigger") continue;
|
|
if (portePDU) { EmplacementPDU ep = hit.collider.GetComponent<EmplacementPDU>(); if (ep != null && !ep.estOccupe) { emplPDUTouche = ep; break; } continue; }
|
|
RackSlot s = hit.collider.GetComponent<RackSlot>(); if (s != null) { slotTouche = s; break; }
|
|
EmplacementBaie e = hit.collider.GetComponent<EmplacementBaie>(); if (e != null) { emplTouche = e; break; }
|
|
}
|
|
|
|
if (emplPDUTouche != null)
|
|
{
|
|
if (_emplacementPDUVise != emplPDUTouche) { QuitterSurvolEmplacementPDU(); _emplacementPDUVise = emplPDUTouche; _emplacementPDUVise.SurvolDebut(); }
|
|
HUDManager hud = GetComponent<HUDManager>();
|
|
if (hud != null) hud.SetInfoEquipement("[E] Installer PDU (" + (_emplacementPDUVise.cote == EmplacementPDU.CotePDU.Gauche ? "Gauche" : "Droit") + ")");
|
|
// v6.9 : on a trouve une cible non-chariot -> cacher les fantomes
|
|
CacherFantomesChariotTous();
|
|
_chariotVise = null; _chariotZoneEtagereVisee = false;
|
|
return;
|
|
}
|
|
|
|
if (slotTouche != null)
|
|
{
|
|
bool porteOuverte = PorteAvantOuverte(slotTouche);
|
|
if (_slotSurvole != slotTouche) { QuitterSurvolSlot(); _slotSurvole = slotTouche; if (!slotTouche.estOccupe && porteOuverte) _slotSurvole.SurvolDebut(); }
|
|
if (!slotTouche.estOccupe) { HUDManager hud = GetComponent<HUDManager>(); if (hud != null) hud.SetInfoEquipement(porteOuverte ? "U" + slotTouche.numeroSlot.ToString("D2") + " - [E] Installer ici" : "Ouvrir la porte avant d'abord"); }
|
|
CacherFantomesChariotTous();
|
|
_chariotVise = null; _chariotZoneEtagereVisee = false;
|
|
return;
|
|
}
|
|
|
|
if (emplTouche != null && !emplTouche.estOccupe)
|
|
{ if (_emplacementVise != emplTouche) { QuitterSurvolEmplacement(); _emplacementVise = emplTouche; _emplacementVise.SurvolDebut(); } CacherFantomesChariotTous(); _chariotVise = null; _chariotZoneEtagereVisee = false; return; }
|
|
|
|
HUDManager hudClear = GetComponent<HUDManager>(); if (hudClear != null && _slotSurvole == null) hudClear.SetInfoEquipement("");
|
|
|
|
// ───── v6.11 : Detection zones de pose du chariot (plateau, etagere, axes toron) ─────
|
|
Chariot ancienChariot = _chariotVise;
|
|
_chariotVise = null;
|
|
_chariotZoneEtagereVisee = false;
|
|
_chariotAxeToronCibleIndex = -1;
|
|
|
|
bool porteToron = (_objetEnMain != null && _objetEnMain.GetComponent<ToronProcedural>() != null);
|
|
|
|
int maskChariot = LayerMask.GetMask("Chariot");
|
|
RaycastHit[] hitsChariot;
|
|
if (maskChariot != 0)
|
|
hitsChariot = Physics.RaycastAll(rayon, porteeInteraction, maskChariot, QueryTriggerInteraction.Collide);
|
|
else
|
|
hitsChariot = Physics.RaycastAll(rayon, porteeInteraction, ~LayerMask.GetMask("Joueur", "Equipement", "Sol", "Baie", "Emplacement"), QueryTriggerInteraction.Collide);
|
|
|
|
System.Array.Sort(hitsChariot, (a, b) => a.distance.CompareTo(b.distance));
|
|
|
|
Chariot chariotHit = null;
|
|
int axeToronIdx = -1;
|
|
bool zoneTrouvee = false;
|
|
|
|
foreach (var h in hitsChariot)
|
|
{
|
|
Chariot c = h.collider.GetComponentInParent<Chariot>();
|
|
if (c == null) continue;
|
|
|
|
if (porteToron)
|
|
{
|
|
// Porte un toron : priorite aux axes toron, on ignore plateau/etagere
|
|
if (c.zonesToronAxes != null)
|
|
{
|
|
int iFound = -1;
|
|
for (int i = 0; i < c.zonesToronAxes.Length; i++)
|
|
{
|
|
if (c.zonesToronAxes[i] != null && h.collider.gameObject == c.zonesToronAxes[i])
|
|
{
|
|
// Verifier que l'axe est libre
|
|
bool libre = (c.equipementsToronAxes == null
|
|
|| i >= c.equipementsToronAxes.Count
|
|
|| c.equipementsToronAxes[i] == null);
|
|
if (libre) { iFound = i; break; }
|
|
}
|
|
}
|
|
if (iFound >= 0)
|
|
{
|
|
chariotHit = c;
|
|
axeToronIdx = iFound;
|
|
zoneTrouvee = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Equipement normal : zones plateau/etagere
|
|
bool estZonePlateau = (c.zonePosePlateau != null && h.collider.gameObject == c.zonePosePlateau);
|
|
bool estZoneEtagere = (c.zonePoseEtagere != null && h.collider.gameObject == c.zonePoseEtagere);
|
|
|
|
if (estZonePlateau || estZoneEtagere)
|
|
{
|
|
chariotHit = c;
|
|
_chariotZoneEtagereVisee = estZoneEtagere;
|
|
zoneTrouvee = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Fallback : garder le chariot comme candidat si pas encore trouve de zone
|
|
if (chariotHit == null) chariotHit = c;
|
|
}
|
|
|
|
if (chariotHit != null)
|
|
{
|
|
_chariotVise = chariotHit;
|
|
|
|
if (ancienChariot != null && ancienChariot != chariotHit)
|
|
{
|
|
ancienChariot.CacherFantomes();
|
|
ancienChariot.CacherFantomeToronAxe();
|
|
}
|
|
|
|
if (porteToron && zoneTrouvee && axeToronIdx >= 0)
|
|
{
|
|
_chariotAxeToronCibleIndex = axeToronIdx;
|
|
chariotHit.AfficherFantomeToronAxe(axeToronIdx);
|
|
HUDManager hud = GetComponent<HUDManager>();
|
|
if (hud != null)
|
|
hud.SetInfoEquipement(axeToronIdx == 0
|
|
? "[E] Accrocher le toron sur l'axe gauche"
|
|
: "[E] Accrocher le toron sur l'axe droit");
|
|
}
|
|
else if (!porteToron && zoneTrouvee)
|
|
{
|
|
int tailleU = (_objetEnMain != null && _objetEnMain.tailleU > 0) ? _objetEnMain.tailleU : 1;
|
|
chariotHit.AfficherFantomePose(tailleU, _chariotZoneEtagereVisee);
|
|
HUDManager hud = GetComponent<HUDManager>();
|
|
if (hud != null)
|
|
hud.SetInfoEquipement(_chariotZoneEtagereVisee ? "[E] Poser sur l'etagere basse" : "[E] Poser sur le plateau");
|
|
}
|
|
else
|
|
{
|
|
// Chariot vise mais pas de zone specifique : cacher les fantomes
|
|
chariotHit.CacherFantomes();
|
|
chariotHit.CacherFantomeToronAxe();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ancienChariot != null)
|
|
{
|
|
ancienChariot.CacherFantomes();
|
|
ancienChariot.CacherFantomeToronAxe();
|
|
}
|
|
}
|
|
}
|
|
|
|
// ==================== DÉTECTION SUPPORTS MURAUX ====================
|
|
|
|
bool DetecterCibleSupportTorons()
|
|
{
|
|
if (_objetEnMain == null) return false;
|
|
if (_objetEnMain.GetComponent<ToronProcedural>() == null) return false;
|
|
SupportTorons support = SupportTorons.Instance;
|
|
if (support == null) return false;
|
|
float dist = Vector3.Distance(transform.position, support.transform.position);
|
|
if (dist > distanceDetectionSupport) return false;
|
|
Vector3 dirSupport = (support.transform.position - _camera.transform.position);
|
|
float distCam = dirSupport.magnitude;
|
|
if (distCam < 0.01f) return false;
|
|
dirSupport /= distCam;
|
|
float angle = Vector3.Angle(_camera.transform.forward, dirSupport);
|
|
if (angle > angleDetectionSupport) return false;
|
|
int r, c; Vector3 posAxe;
|
|
if (!support.TrouverAxeLibreLePlusProche(transform.position, out r, out c, out posAxe)) return false;
|
|
support.AfficherSurvolAxe(r, c);
|
|
_axeSupportCibleLigne = r; _axeSupportCibleColonne = c;
|
|
HUDManager hud = GetComponent<HUDManager>();
|
|
if (hud != null) hud.SetInfoEquipement("[E] Remettre le toron sur le support");
|
|
return true;
|
|
}
|
|
|
|
void QuitterSurvolSupport()
|
|
{
|
|
if (_axeSupportCibleLigne < 0) return;
|
|
if (SupportTorons.Instance != null) SupportTorons.Instance.CacherSurvolAxe();
|
|
_axeSupportCibleLigne = -1; _axeSupportCibleColonne = -1;
|
|
}
|
|
|
|
bool DetecterCibleSupportPDU()
|
|
{
|
|
if (_objetEnMain == null) return false;
|
|
PDU pdu = _objetEnMain.GetComponent<PDU>();
|
|
if (pdu == null) return false;
|
|
if (pdu.estInstalle) return false;
|
|
SupportPDU support = SupportPDU.Instance;
|
|
if (support == null) return false;
|
|
float dist = Vector3.Distance(transform.position, support.transform.position);
|
|
if (dist > distanceDetectionSupport) return false;
|
|
Vector3 dirSupport = (support.transform.position - _camera.transform.position);
|
|
float distCam = dirSupport.magnitude;
|
|
if (distCam < 0.01f) return false;
|
|
dirSupport /= distCam;
|
|
float angle = Vector3.Angle(_camera.transform.forward, dirSupport);
|
|
if (angle > angleDetectionSupport) return false;
|
|
int r, c; Vector3 posEmpl;
|
|
if (!support.TrouverEmplacementLibreLePlusProche(transform.position, out r, out c, out posEmpl)) return false;
|
|
support.AfficherSurvolEmplacement(r, c);
|
|
_emplacementSupportPDUCibleLigne = r; _emplacementSupportPDUCibleColonne = c;
|
|
HUDManager hud = GetComponent<HUDManager>();
|
|
if (hud != null) hud.SetInfoEquipement("[E] Remettre le PDU sur le support");
|
|
return true;
|
|
}
|
|
|
|
void QuitterSurvolSupportPDU()
|
|
{
|
|
if (_emplacementSupportPDUCibleLigne < 0) return;
|
|
if (SupportPDU.Instance != null) SupportPDU.Instance.CacherSurvolEmplacement();
|
|
_emplacementSupportPDUCibleLigne = -1; _emplacementSupportPDUCibleColonne = -1;
|
|
}
|
|
|
|
// ==================== SURVOL HELPERS ====================
|
|
|
|
void SetSurvol(Interactable obj) { if (_objetSurvole != obj) { if (_objetSurvole != null) _objetSurvole.SurvoleeFin(); _objetSurvole = obj; _objetSurvole.SurvoleDebut(); } }
|
|
void QuitterSurvol() { if (_objetSurvole != null) { _objetSurvole.SurvoleeFin(); _objetSurvole = null; } }
|
|
void QuitterSurvolSlot() { if (_slotSurvole != null) { _slotSurvole.SurvolFin(); _slotSurvole = null; } }
|
|
void QuitterSurvolEmplacement() { if (_emplacementVise != null) { _emplacementVise.SurvolFin(); _emplacementVise = null; } }
|
|
void QuitterSurvolEmplacementPDU() { if (_emplacementPDUVise != null) { _emplacementPDUVise.SurvolFin(); _emplacementPDUVise = null; } }
|
|
void QuitterSurvolPrise() { if (_priseSurvolee != null) { _priseSurvolee.Survoler(false); _priseSurvolee = null; } }
|
|
void QuitterSurvolBoutonPower() { if (_boutonPowerVise != null) { _boutonPowerVise.Survoler(false); _boutonPowerVise = null; } }
|
|
|
|
// ==================== RAMASSER ====================
|
|
|
|
void Ramasser()
|
|
{
|
|
TerminalCommande terminal = _objetSurvole.GetComponent<TerminalCommande>();
|
|
if (terminal != null) { terminal.Interagir(); QuitterSurvol(); return; }
|
|
MonitoringDatacenter monitoring = _objetSurvole.GetComponent<MonitoringDatacenter>();
|
|
if (monitoring != null) { monitoring.Interagir(); QuitterSurvol(); return; }
|
|
TableauTickets tableau = _objetSurvole.GetComponent<TableauTickets>();
|
|
if (tableau != null) { tableau.Interagir(); QuitterSurvol(); return; }
|
|
AgrandissementSalle agr = _objetSurvole.GetComponentInParent<AgrandissementSalle>();
|
|
if (agr != null && !agr.estAgrandi && !agr.enAnimation) { agr.DemanderAgrandir(); QuitterSurvol(); return; }
|
|
|
|
Chariot chariot = _objetSurvole.GetComponent<Chariot>();
|
|
if (chariot != null && _visePoignee)
|
|
{
|
|
if (_chariotPilote == chariot)
|
|
{
|
|
LacherChariot();
|
|
}
|
|
else
|
|
{
|
|
if (_chariotPilote != null) LacherChariot();
|
|
PrendreChariot(chariot);
|
|
QuitterSurvol();
|
|
}
|
|
return;
|
|
}
|
|
|
|
Chariot chariotParent = _objetSurvole.GetComponentInParent<Chariot>();
|
|
if (chariotParent != null && chariot == null)
|
|
{
|
|
if (chariotParent.estPilote) { QuitterSurvol(); return; }
|
|
|
|
// v6.11 : verifier en PREMIER si le toron survole est accroche sur un axe lateral
|
|
if (chariotParent.equipementsToronAxes != null)
|
|
{
|
|
for (int i = 0; i < chariotParent.equipementsToronAxes.Count; i++)
|
|
{
|
|
if (chariotParent.equipementsToronAxes[i] == _objetSurvole.gameObject)
|
|
{
|
|
GameObject t = chariotParent.RetirerToronDeAxeChariot(i);
|
|
if (t != null)
|
|
{
|
|
PrendreEnMain(t.GetComponent<Interactable>());
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// v6.9 : detecter si l'objet est sur le plateau ou sur l'etagere basse
|
|
bool surEtagere = chariotParent.equipementsSurEtagere != null
|
|
&& chariotParent.equipementsSurEtagere.Contains(_objetSurvole.gameObject);
|
|
|
|
GameObject top = surEtagere
|
|
? chariotParent.RetirerEquipementSurEtagere()
|
|
: chariotParent.RetirerEquipementDuDessus();
|
|
|
|
if (top != null)
|
|
{
|
|
// v6.13 Bug 2 : broadcaster le detachement a tous les clients
|
|
// (sinon sur les autres clients l'objet reste parente au chariot et
|
|
// vole avec lui quand on le lache).
|
|
NetworkIdentity topNetId = top.GetComponent<NetworkIdentity>();
|
|
if (topNetId != null) CmdDetacherDuChariot(topNetId.netId);
|
|
|
|
PrendreEnMain(top.GetComponent<Interactable>());
|
|
return;
|
|
}
|
|
}
|
|
|
|
PDU pdu = _objetSurvole.GetComponent<PDU>();
|
|
if (pdu != null && pdu.estInstalle)
|
|
{
|
|
bool cables = false;
|
|
foreach (var p in pdu.prises) if (p != null && p.estConnectee) { cables = true; break; }
|
|
if (cables) { Debug.LogWarning("Impossible : des cables sont branches !"); QuitterSurvol(); return; }
|
|
pdu.Desinstaller();
|
|
NetworkIdentity pduNetIdentity = pdu.GetComponent<NetworkIdentity>();
|
|
if (pduNetIdentity != null) CmdDesinstallerPDU(pduNetIdentity.netId);
|
|
PrendreEnMain(_objetSurvole);
|
|
return;
|
|
}
|
|
|
|
BaieRack baieRack = _objetSurvole.GetComponent<BaieRack>() ?? _objetSurvole.GetComponentInChildren<BaieRack>();
|
|
if (baieRack != null) { EmplacementBaie empl = TrouverEmplacementDeBaie(_objetSurvole.gameObject); if (empl != null) empl.RetirerBaie(); }
|
|
|
|
RackSlot slotSrc = TrouverSlotDeEquipement(_objetSurvole);
|
|
if (slotSrc != null)
|
|
{
|
|
if (!PorteAvantOuverte(slotSrc)) { HUDManager hud = GetComponent<HUDManager>(); if (hud != null) hud.SetInfoEquipement("Ouvrir la porte avant d'abord"); QuitterSurvol(); return; }
|
|
RackSlot[] slotsArr = ObtenirSlotsParent(slotSrc);
|
|
if (slotsArr != null) slotSrc.Liberer(slotsArr);
|
|
}
|
|
|
|
ZoneLivraison zone = _objetSurvole.GetComponentInParent<ZoneLivraison>();
|
|
if (zone == null) zone = ZoneLivraison.Instance;
|
|
if (zone != null)
|
|
{
|
|
Interactable plusHaut = zone.TrouverPlusHautDansPile(_objetSurvole);
|
|
if (plusHaut == null) plusHaut = _objetSurvole;
|
|
Vector3 pos = plusHaut.transform.position;
|
|
if (plusHaut != _objetSurvole) _objetSurvole.SurvoleeFin();
|
|
plusHaut.transform.SetParent(null);
|
|
IgnorerCollisionsAvecStructure(plusHaut.gameObject, zone.transform, true);
|
|
PrendreEnMain(plusHaut);
|
|
// v6.13 Bug 1 : reorganisation cote SERVEUR pour que les positions
|
|
// soient sync via NetworkTransform a tous les clients.
|
|
CmdReorganiserZoneLivraison(pos);
|
|
return;
|
|
}
|
|
|
|
PrendreEnMain(_objetSurvole);
|
|
}
|
|
|
|
void PrendreEnMain(Interactable obj)
|
|
{
|
|
if (obj == null) return;
|
|
CartonLivraison carton = obj.GetComponent<CartonLivraison>();
|
|
if (carton != null && carton.ContientBaie()) { QuitterSurvol(); carton.OuvrirPlanPlacement(); return; }
|
|
_objetEnMain = obj; _objetSurvole = null;
|
|
_objetEnMain.Ramasser();
|
|
_rbEnMain = _objetEnMain.GetComponent<Rigidbody>();
|
|
if (_rbEnMain != null)
|
|
{
|
|
_rbEnMain.isKinematic = false; _rbEnMain.useGravity = false;
|
|
_rbEnMain.freezeRotation = true;
|
|
_rbEnMain.collisionDetectionMode = CollisionDetectionMode.Continuous;
|
|
_rbEnMain.interpolation = RigidbodyInterpolation.Interpolate;
|
|
Vector3 dirJoueur = new Vector3(_camera.transform.forward.x, 0, _camera.transform.forward.z).normalized;
|
|
Quaternion rotJoueur = Quaternion.LookRotation(dirJoueur);
|
|
_rotationOffsetTransport = Quaternion.Inverse(rotJoueur) * _objetEnMain.transform.rotation;
|
|
}
|
|
NetworkIdentity objNetId = obj.GetComponent<NetworkIdentity>();
|
|
if (objNetId != null) CmdRamasser(objNetId.netId);
|
|
}
|
|
|
|
// ==================== POSER ====================
|
|
|
|
void Poser()
|
|
{
|
|
RestaurerCollisionsIgnorees();
|
|
|
|
if (_axeSupportCibleLigne >= 0 && _objetEnMain != null && _objetEnMain.GetComponent<ToronProcedural>() != null)
|
|
{ PoserSurSupportTorons(); return; }
|
|
|
|
if (_emplacementSupportPDUCibleLigne >= 0 && _objetEnMain != null && _objetEnMain.GetComponent<PDU>() != null)
|
|
{ PoserSurSupportPDU(); return; }
|
|
|
|
// v6.11 : pose d'un toron sur un axe lateral du chariot (prioritaire sur plateau/etagere)
|
|
if (_chariotVise != null && _chariotAxeToronCibleIndex >= 0
|
|
&& _objetEnMain != null && _objetEnMain.GetComponent<ToronProcedural>() != null)
|
|
{
|
|
int indexAxe = _chariotAxeToronCibleIndex;
|
|
if (_chariotVise.PoserToronSurAxeChariot(_objetEnMain.gameObject, indexAxe))
|
|
{
|
|
_chariotVise.CacherFantomeToronAxe();
|
|
Vector3 posT = _objetEnMain.transform.position;
|
|
Quaternion rotT = _objetEnMain.transform.rotation;
|
|
NotifierPoserReseau(false, posT, rotT, estRacke: true);
|
|
|
|
// v6.13 Bug 2 : broadcast parenting a tous les clients
|
|
NetworkIdentity eqNetId = _objetEnMain.GetComponent<NetworkIdentity>();
|
|
NetworkIdentity chNetId = _chariotVise.GetComponent<NetworkIdentity>();
|
|
if (eqNetId != null && chNetId != null)
|
|
CmdParenterAuChariot(eqNetId.netId, chNetId.netId);
|
|
|
|
_objetEnMain.Poser(); _objetEnMain = null; _rbEnMain = null;
|
|
_chariotAxeToronCibleIndex = -1;
|
|
HUDManager hud = GetComponent<HUDManager>();
|
|
if (hud != null) hud.SetInfoEquipement("");
|
|
return;
|
|
}
|
|
}
|
|
|
|
bool estNonRackable = (_objetEnMain.tailleU <= 0 || _objetEnMain.GetComponent<Chariot>() != null);
|
|
bool estCarton = _objetEnMain.GetComponent<CartonLivraison>() != null;
|
|
bool estBaie = _objetEnMain.GetComponent<BaieRack>() != null;
|
|
bool estPDU = _objetEnMain.GetComponent<PDU>() != null;
|
|
|
|
Vector3 posFinal = _objetEnMain.transform.position;
|
|
Quaternion rotFinal = _objetEnMain.transform.rotation;
|
|
bool gravite = true;
|
|
|
|
if (estPDU && _emplacementPDUVise != null && !_emplacementPDUVise.estOccupe)
|
|
{
|
|
PDU pduObj = _objetEnMain.GetComponent<PDU>();
|
|
pduObj.InstallerSurEmplacement(_emplacementPDUVise);
|
|
gravite = false; posFinal = _objetEnMain.transform.position; rotFinal = _objetEnMain.transform.rotation;
|
|
NotifierPoserReseau(gravite, posFinal, rotFinal, estRacke: true);
|
|
NetworkIdentity pduNetId = _objetEnMain.GetComponent<NetworkIdentity>();
|
|
if (pduNetId != null) CmdInstallerPDU(pduNetId.netId, posFinal, rotFinal);
|
|
_objetEnMain.Poser(); _objetEnMain = null; _rbEnMain = null;
|
|
QuitterSurvolEmplacementPDU();
|
|
HUDManager hud = GetComponent<HUDManager>(); if (hud != null) hud.SetInfoEquipement("");
|
|
CacherFantomesChariotTous();
|
|
return;
|
|
}
|
|
if (estPDU)
|
|
{
|
|
PDU pduObj = _objetEnMain.GetComponent<PDU>();
|
|
GestionnaireAlimentation ga = GetComponent<GestionnaireAlimentation>();
|
|
if (ga != null && !pduObj.estInstalle && ga.TenterSnapPDU(pduObj))
|
|
{
|
|
gravite = false; posFinal = _objetEnMain.transform.position; rotFinal = _objetEnMain.transform.rotation;
|
|
NotifierPoserReseau(gravite, posFinal, rotFinal);
|
|
NetworkIdentity pduNetId = _objetEnMain.GetComponent<NetworkIdentity>();
|
|
if (pduNetId != null) CmdInstallerPDU(pduNetId.netId, posFinal, rotFinal);
|
|
_objetEnMain.Poser(); _objetEnMain = null; _rbEnMain = null;
|
|
CacherFantomesChariotTous();
|
|
return;
|
|
}
|
|
}
|
|
if (estCarton)
|
|
{
|
|
CartonLivraison carton = _objetEnMain.GetComponent<CartonLivraison>();
|
|
if (carton != null && carton.ContientEquipement())
|
|
{
|
|
if (_rbEnMain != null) { _rbEnMain.isKinematic = true; _rbEnMain.velocity = Vector3.zero; }
|
|
gravite = false; posFinal = _objetEnMain.transform.position; rotFinal = _objetEnMain.transform.rotation;
|
|
NotifierPoserReseau(gravite, posFinal, rotFinal);
|
|
_objetEnMain.Poser(); _objetEnMain = null; _rbEnMain = null;
|
|
carton.TransformerAuSol();
|
|
CacherFantomesChariotTous();
|
|
return;
|
|
}
|
|
}
|
|
if (!estNonRackable && !estBaie && !estCarton && !estPDU && _slotSurvole != null && !_slotSurvole.estOccupe)
|
|
{
|
|
if (!PorteAvantOuverte(_slotSurvole)) { HUDManager hud = GetComponent<HUDManager>(); if (hud != null) hud.SetInfoEquipement("Ouvrir la porte avant d'abord"); return; }
|
|
RackSlot[] slotsArr = ObtenirSlotsParent(_slotSurvole);
|
|
if (slotsArr != null && _slotSurvole.TenterInstallation(_objetEnMain, slotsArr))
|
|
{
|
|
gravite = false; posFinal = _objetEnMain.transform.position; rotFinal = _objetEnMain.transform.rotation;
|
|
NotifierPoserReseau(gravite, posFinal, rotFinal, estRacke: true);
|
|
NetworkIdentity equipNetId = _objetEnMain.GetComponent<NetworkIdentity>();
|
|
NetworkIdentity baieNetId = _slotSurvole.GetComponentInParent<NetworkIdentity>();
|
|
if (equipNetId != null && baieNetId != null) { RackSlot[] allSlots = baieNetId.GetComponentsInChildren<RackSlot>(); int slotIdx = System.Array.IndexOf(allSlots, _slotSurvole); CmdInstallerDansSlot(equipNetId.netId, baieNetId.netId, slotIdx); }
|
|
_objetEnMain.Poser(); _objetEnMain = null; _rbEnMain = null;
|
|
QuitterSurvolSlot();
|
|
HUDManager hud = GetComponent<HUDManager>(); if (hud != null) hud.SetInfoEquipement("");
|
|
CacherFantomesChariotTous();
|
|
return;
|
|
}
|
|
}
|
|
|
|
// ───── v6.10 : Pose sur chariot (plateau ou etagere basse) ─────
|
|
// IMPORTANT : estRacke=true pour que le serveur mette isKinematic=true.
|
|
// Sinon les objets poses deviennent non-kinematic sans gravite cote serveur
|
|
// et flottent en apesanteur des qu'on en retire un du dessus.
|
|
if (_chariotVise != null && !estNonRackable && !estBaie && !estCarton && !estPDU)
|
|
{
|
|
bool pose = _chariotZoneEtagereVisee
|
|
? _chariotVise.PoserEquipementSurEtagere(_objetEnMain.gameObject)
|
|
: _chariotVise.PoserEquipement(_objetEnMain.gameObject);
|
|
if (pose)
|
|
{
|
|
_chariotVise.CacherFantomes();
|
|
gravite = false; posFinal = _objetEnMain.transform.position; rotFinal = _objetEnMain.transform.rotation;
|
|
NotifierPoserReseau(gravite, posFinal, rotFinal, estRacke: true);
|
|
|
|
// v6.13 Bug 2 : broadcast parenting a tous les clients
|
|
NetworkIdentity eqNetId = _objetEnMain.GetComponent<NetworkIdentity>();
|
|
NetworkIdentity chNetId = _chariotVise.GetComponent<NetworkIdentity>();
|
|
if (eqNetId != null && chNetId != null)
|
|
CmdParenterAuChariot(eqNetId.netId, chNetId.netId);
|
|
|
|
_objetEnMain.Poser(); _objetEnMain = null; _rbEnMain = null;
|
|
return;
|
|
}
|
|
}
|
|
if (_chariotPilote != null && _chariotVise == null && !estNonRackable && !estBaie && !estCarton && !estPDU)
|
|
if (_chariotPilote.PoserEquipement(_objetEnMain.gameObject))
|
|
{
|
|
_chariotPilote.CacherFantomes();
|
|
gravite = false; posFinal = _objetEnMain.transform.position; rotFinal = _objetEnMain.transform.rotation;
|
|
NotifierPoserReseau(gravite, posFinal, rotFinal, estRacke: true);
|
|
|
|
// v6.13 Bug 2 : broadcast parenting a tous les clients
|
|
NetworkIdentity eqNetId = _objetEnMain.GetComponent<NetworkIdentity>();
|
|
NetworkIdentity chNetId = _chariotPilote.GetComponent<NetworkIdentity>();
|
|
if (eqNetId != null && chNetId != null)
|
|
CmdParenterAuChariot(eqNetId.netId, chNetId.netId);
|
|
|
|
_objetEnMain.Poser(); _objetEnMain = null; _rbEnMain = null;
|
|
return;
|
|
}
|
|
|
|
// Drop au sol
|
|
if (_rbEnMain != null) { _rbEnMain.useGravity = true; _rbEnMain.velocity = Vector3.zero; _rbEnMain.interpolation = RigidbodyInterpolation.None; }
|
|
posFinal = _objetEnMain.transform.position; rotFinal = _objetEnMain.transform.rotation;
|
|
NotifierPoserReseau(true, posFinal, rotFinal);
|
|
_objetEnMain.Poser(); _objetEnMain = null; _rbEnMain = null;
|
|
QuitterSurvolSlot(); QuitterSurvolEmplacement(); QuitterSurvolEmplacementPDU();
|
|
QuitterSurvolSupport();
|
|
QuitterSurvolSupportPDU();
|
|
CacherFantomesChariotTous();
|
|
}
|
|
|
|
void PoserSurSupportTorons()
|
|
{
|
|
if (_objetEnMain == null) return;
|
|
int ligneCible = _axeSupportCibleLigne; int colonneCible = _axeSupportCibleColonne;
|
|
NetworkIdentity toronNetId = _objetEnMain.GetComponent<NetworkIdentity>();
|
|
if (toronNetId != null) CmdPoserToronSurSupport(toronNetId.netId, ligneCible, colonneCible);
|
|
if (!isServer && SupportTorons.Instance != null) { bool place = SupportTorons.Instance.PoserToronSurAxeSpecifique(_objetEnMain.gameObject, ligneCible, colonneCible); if (!place) SupportTorons.Instance.PoserToron(_objetEnMain.gameObject); }
|
|
else if (toronNetId == null && SupportTorons.Instance != null) { bool place = SupportTorons.Instance.PoserToronSurAxeSpecifique(_objetEnMain.gameObject, ligneCible, colonneCible); if (!place) SupportTorons.Instance.PoserToron(_objetEnMain.gameObject); }
|
|
_objetEnMain.Poser(); _objetEnMain = null; _rbEnMain = null;
|
|
QuitterSurvolSupport();
|
|
HUDManager hud = GetComponent<HUDManager>(); if (hud != null) hud.SetInfoEquipement("");
|
|
}
|
|
|
|
void PoserSurSupportPDU()
|
|
{
|
|
if (_objetEnMain == null) return;
|
|
int ligneCible = _emplacementSupportPDUCibleLigne; int colonneCible = _emplacementSupportPDUCibleColonne;
|
|
NetworkIdentity pduNetId = _objetEnMain.GetComponent<NetworkIdentity>();
|
|
if (pduNetId != null) CmdPoserPDUSurSupport(pduNetId.netId, ligneCible, colonneCible);
|
|
if (!isServer && SupportPDU.Instance != null) { bool place = SupportPDU.Instance.PoserPDUSurEmplacementSpecifique(_objetEnMain.gameObject, ligneCible, colonneCible); if (!place) SupportPDU.Instance.PoserPDU(_objetEnMain.gameObject); }
|
|
else if (pduNetId == null && SupportPDU.Instance != null) { bool place = SupportPDU.Instance.PoserPDUSurEmplacementSpecifique(_objetEnMain.gameObject, ligneCible, colonneCible); if (!place) SupportPDU.Instance.PoserPDU(_objetEnMain.gameObject); }
|
|
_objetEnMain.Poser(); _objetEnMain = null; _rbEnMain = null;
|
|
QuitterSurvolSupportPDU();
|
|
HUDManager hud = GetComponent<HUDManager>(); if (hud != null) hud.SetInfoEquipement("");
|
|
}
|
|
|
|
void NotifierPoserReseau(bool avecGravite, Vector3 position, Quaternion rotation, bool estRacke = false)
|
|
{
|
|
if (_objetEnMain == null) return;
|
|
NetworkIdentity objNetId = _objetEnMain.GetComponent<NetworkIdentity>();
|
|
if (objNetId != null) CmdPoser(objNetId.netId, position, rotation, avecGravite, estRacke);
|
|
}
|
|
|
|
// ==================== HELPERS ====================
|
|
|
|
bool ViseBouton(Vector3 positionMonde, float seuilPixels = 60f)
|
|
{
|
|
if (_camera == null) return false;
|
|
Vector3 screenPos = _camera.WorldToScreenPoint(positionMonde);
|
|
if (screenPos.z <= 0f) return false;
|
|
return Vector2.Distance(new Vector2(Screen.width / 2f, Screen.height / 2f), new Vector2(screenPos.x, screenPos.y)) < seuilPixels;
|
|
}
|
|
|
|
bool PorteAvantOuverte(RackSlot slot)
|
|
{
|
|
if (slot == null) return true;
|
|
Transform baie = slot.transform.parent; if (baie == null) return true;
|
|
foreach (Transform enfant in baie)
|
|
if (enfant.name == "Pivot_PorteAvant") { PorteBaie porte = enfant.GetComponent<PorteBaie>(); if (porte != null) return porte.estOuverte; }
|
|
return true;
|
|
}
|
|
|
|
RackSlot[] ObtenirSlotsParent(RackSlot slot)
|
|
{
|
|
if (slot == null) return null;
|
|
BaieRack baieRack = slot.GetComponentInParent<BaieRack>(); if (baieRack != null && baieRack.slots != null) return baieRack.slots;
|
|
BaieProcedurale baieProc = slot.GetComponentInParent<BaieProcedurale>(); if (baieProc != null && baieProc.slots != null) return baieProc.slots;
|
|
Transform parent = slot.transform.parent; if (parent != null) return parent.GetComponentsInChildren<RackSlot>();
|
|
return null;
|
|
}
|
|
|
|
private void IgnorerCollisionsAvecStructure(GameObject objet, Transform parent, bool ignorer)
|
|
{
|
|
Collider objCollider = objet.GetComponent<Collider>(); if (objCollider == null) return;
|
|
_collisionsIgnorees.Clear();
|
|
for (int i = 0; i < parent.childCount; i++)
|
|
{
|
|
Transform enfant = parent.GetChild(i); string nom = enfant.name;
|
|
if (nom.StartsWith("Planche_") || nom.StartsWith("Montant_") || nom.StartsWith("Etiquette_"))
|
|
{ Collider sc = enfant.GetComponent<Collider>(); if (sc != null) { Physics.IgnoreCollision(objCollider, sc, ignorer); if (ignorer) _collisionsIgnorees.Add(sc); } }
|
|
Interactable inter = enfant.GetComponent<Interactable>();
|
|
if (inter != null && enfant.gameObject != objet)
|
|
{ Collider ec = enfant.GetComponent<Collider>(); if (ec != null) { Physics.IgnoreCollision(objCollider, ec, ignorer); if (ignorer) _collisionsIgnorees.Add(ec); } }
|
|
}
|
|
}
|
|
|
|
private void RestaurerCollisionsIgnorees()
|
|
{
|
|
if (_objetEnMain == null || _collisionsIgnorees.Count == 0) return;
|
|
Collider objCollider = _objetEnMain.GetComponent<Collider>();
|
|
if (objCollider == null) { _collisionsIgnorees.Clear(); return; }
|
|
foreach (Collider col in _collisionsIgnorees) if (col != null) Physics.IgnoreCollision(objCollider, col, false);
|
|
_collisionsIgnorees.Clear();
|
|
}
|
|
|
|
// v6.12 : gestion pilotage chariot + transfert d'autorite multijoueur
|
|
void PrendreChariot(Chariot chariot)
|
|
{
|
|
if (chariot == null) return;
|
|
_chariotPilote = chariot;
|
|
|
|
// Demander l'autorite au serveur pour pouvoir modifier transform.position
|
|
// via NetworkTransform ClientToServer. Sans ca, Mirror ignore les changements
|
|
// cote client et les autres joueurs ne voient pas le chariot bouger.
|
|
NetworkIdentity ni = chariot.GetComponent<NetworkIdentity>();
|
|
if (ni != null) CmdDemanderAutoriteChariot(ni.netId);
|
|
|
|
chariot.TogglePilotage(transform);
|
|
}
|
|
|
|
void LacherChariot()
|
|
{
|
|
if (_chariotPilote == null) return;
|
|
|
|
NetworkIdentity ni = _chariotPilote.GetComponent<NetworkIdentity>();
|
|
|
|
_chariotPilote.CacherFantomes();
|
|
_chariotPilote.TogglePilotage(transform);
|
|
|
|
// Relacher l'autorite APRES TogglePilotage pour que la position finale
|
|
// soit bien envoyee au serveur avant que le client perde son droit d'ecrire.
|
|
if (ni != null) CmdRelacherAutoriteChariot(ni.netId);
|
|
|
|
_chariotPilote = null;
|
|
}
|
|
|
|
[Command]
|
|
void CmdDemanderAutoriteChariot(uint chariotNetId)
|
|
{
|
|
if (!NetworkServer.spawned.ContainsKey(chariotNetId)) return;
|
|
NetworkIdentity ni = NetworkServer.spawned[chariotNetId];
|
|
if (ni == null) return;
|
|
|
|
// Si un autre client a deja l'autorite, la retirer d'abord
|
|
if (ni.connectionToClient != null && ni.connectionToClient != connectionToClient)
|
|
ni.RemoveClientAuthority();
|
|
|
|
ni.AssignClientAuthority(connectionToClient);
|
|
}
|
|
|
|
[Command]
|
|
void CmdRelacherAutoriteChariot(uint chariotNetId)
|
|
{
|
|
if (!NetworkServer.spawned.ContainsKey(chariotNetId)) return;
|
|
NetworkIdentity ni = NetworkServer.spawned[chariotNetId];
|
|
if (ni == null) return;
|
|
|
|
// Ne retirer l'autorite que si c'est bien ce joueur qui l'a actuellement,
|
|
// pour eviter de voler l'autorite a quelqu'un d'autre par accident.
|
|
if (ni.connectionToClient == connectionToClient)
|
|
ni.RemoveClientAuthority();
|
|
}
|
|
|
|
// ===== v6.13 Bug 1 : reorganisation ZoneLivraison cote serveur =====
|
|
[Command]
|
|
void CmdReorganiserZoneLivraison(Vector3 posRetireeWorld)
|
|
{
|
|
if (ZoneLivraison.Instance != null)
|
|
ZoneLivraison.Instance.ReorganiserNiveauComplet(posRetireeWorld);
|
|
}
|
|
|
|
// ===== v6.13 Bug 2 : sync du parenting equipement <-> chariot =====
|
|
[Command]
|
|
void CmdParenterAuChariot(uint equipNetId, uint chariotNetId)
|
|
{
|
|
if (!NetworkServer.spawned.ContainsKey(equipNetId)) return;
|
|
if (!NetworkServer.spawned.ContainsKey(chariotNetId)) return;
|
|
RpcParenterAuChariot(equipNetId, chariotNetId);
|
|
}
|
|
|
|
[ClientRpc]
|
|
void RpcParenterAuChariot(uint equipNetId, uint chariotNetId)
|
|
{
|
|
if (!NetworkClient.spawned.TryGetValue(equipNetId, out NetworkIdentity eqNi)) return;
|
|
if (!NetworkClient.spawned.TryGetValue(chariotNetId, out NetworkIdentity chNi)) return;
|
|
if (eqNi == null || chNi == null) return;
|
|
|
|
// worldPositionStays=true : conserver la position monde actuelle. L'equipement
|
|
// est deja a la bonne position (via NetworkTransform), on veut juste l'attacher
|
|
// au chariot pour qu'il suive les futurs mouvements.
|
|
eqNi.transform.SetParent(chNi.transform, true);
|
|
}
|
|
|
|
[Command]
|
|
void CmdDetacherDuChariot(uint equipNetId)
|
|
{
|
|
if (!NetworkServer.spawned.ContainsKey(equipNetId)) return;
|
|
RpcDetacherDuChariot(equipNetId);
|
|
}
|
|
|
|
[ClientRpc]
|
|
void RpcDetacherDuChariot(uint equipNetId)
|
|
{
|
|
if (!NetworkClient.spawned.TryGetValue(equipNetId, out NetworkIdentity eqNi)) return;
|
|
if (eqNi == null) return;
|
|
eqNi.transform.SetParent(null, true);
|
|
}
|
|
|
|
EmplacementBaie TrouverEmplacementDeBaie(GameObject baie)
|
|
{
|
|
if (_tousEmplacements == null) _tousEmplacements = FindObjectsOfType<EmplacementBaie>();
|
|
foreach (EmplacementBaie empl in _tousEmplacements) if (empl.estOccupe && empl.baieInstallee == baie) return empl;
|
|
return null;
|
|
}
|
|
|
|
RackSlot TrouverSlotDeEquipement(Interactable equipement)
|
|
{
|
|
if (equipement == null) return null;
|
|
foreach (BaieRack baie in FindObjectsOfType<BaieRack>()) { if (baie.slots == null) continue; foreach (RackSlot s in baie.slots) if (s != null && s.equipementInstalle == equipement) return s; }
|
|
foreach (BaieProcedurale baie in FindObjectsOfType<BaieProcedurale>()) { if (baie.slots == null) continue; foreach (RackSlot s in baie.slots) if (s != null && s.equipementInstalle == equipement) return s; }
|
|
return null;
|
|
}
|
|
} |