Merge branch 'dev-hazim' into dev-ali

dev-main
Ali Sharoz 1 week ago
commit 752c59fd4b

@ -16,7 +16,7 @@ MonoBehaviour:
abilityName: Crows Foresight
abilityRadius: 10
abilityMagnitude: 10
abilityDuration: 30
abilityDuration: 10
abilityCooldownTime: 10
abilityApplicationRadius: 20
prefab: {fileID: 0}
prefab: {fileID: 6129284537519539166, guid: 2054403c32efac24999b3167985d56f2, type: 3}

@ -89,3 +89,8 @@ MonoBehaviour:
SourcePrefabToOverride: {fileID: 0}
SourceHashToOverride: 0
OverridingTargetPrefab: {fileID: 0}
- Override: 0
Prefab: {fileID: 6129284537519539166, guid: 2054403c32efac24999b3167985d56f2, type: 3}
SourcePrefabToOverride: {fileID: 0}
SourceHashToOverride: 0
OverridingTargetPrefab: {fileID: 0}

@ -0,0 +1,69 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &6129284537519539166
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1069926530772311797}
- component: {fileID: 8893380544067200444}
- component: {fileID: 1316219484843411118}
m_Layer: 0
m_Name: CrowsForesightPrefab
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1069926530772311797
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6129284537519539166}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8893380544067200444
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6129284537519539166}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
m_Name:
m_EditorClassIdentifier:
GlobalObjectIdHash: 17096565
InScenePlacedSourceGlobalObjectIdHash: 0
AlwaysReplicateAsRoot: 0
SynchronizeTransform: 1
ActiveSceneSynchronization: 0
SceneMigrationSynchronization: 1
SpawnWithObservers: 1
DontDestroyWithOwner: 0
AutoObjectParentSync: 1
--- !u!114 &1316219484843411118
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6129284537519539166}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 24b344d29ff558b4197f1bb01ec11343, type: 3}
m_Name:
m_EditorClassIdentifier:
Ability: {fileID: 11400000, guid: 6b4485e4bc8be814db7fc22a6778fbd5, type: 2}

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2054403c32efac24999b3167985d56f2
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

@ -391,7 +391,10 @@ public class AbilitySystem : NetworkBehaviour
abilitiesOnCooldown.Add(ability);
Debug.Log($"{ability.abilityName} is now on cooldown for {ability.abilityCooldownTime} seconds.");
var abilityUI = abilitiesUI.FirstOrDefault(a => a.key == ability.abilityKey);
abilityUI.StopWatchFiller(ability.abilityCooldownTime);
if (abilityUI)
{
abilityUI.StopWatchFiller(ability.abilityCooldownTime);
}
yield return new WaitForSeconds(ability.abilityCooldownTime);
abilitiesOnCooldown.Remove(ability);

@ -50,7 +50,7 @@ public class CrowManager : NetworkBehaviour
/// <summary>
/// Determines which player should be the crow.
/// </summary>
int unoccupiedPlayers = 0;
int unoccupiedPlayers = 0;
private void DetermineCrow()
{
@ -136,12 +136,27 @@ public class CrowManager : NetworkBehaviour
}
else
{
// If a player was the crow but is now losing it, request foresight removal
if (player.IsCrow)
{
Debug.Log($"[CrowManager] {player.name} is no longer the Crow. Requesting foresight removal.");
if (IsServer)
{
var foresightPrefab = FindObjectOfType<CrowsForesightPrefab>();
if (foresightPrefab)
{
foresightPrefab.DespawnForesight();
}
}
}
player.SetAsCrow(false);
player.SwitchToPlayerModel();
}
}
}
/// <summary>
/// Adds a character to the players list.
/// </summary>
@ -191,4 +206,103 @@ public class CrowManager : NetworkBehaviour
return currentCrow;
}
public void NotifyForesightSwap(ulong senderId, ulong receiverId, Vector3 senderPos, Vector3 receiverPos)
{
Debug.Log($"[CrowManager] NotifyForesightSwap called - Sender: {senderId}, Receiver: {receiverId}, SenderPos: {senderPos}, ReceiverPos: {receiverPos}");
if (currentCrow)
{
Debug.Log($"[CrowManager] Sending foresight swap notification to the Crow: {currentCrow.OwnerClientId}");
NotifySwapForesightClientRpc(senderId, receiverId, senderPos, receiverPos);
}
else
{
Debug.LogWarning("[CrowManager] No current crow found to receive the foresight swap update.");
}
}
public void NotifyForesightSwapDecision(ulong senderId, Vector3 receiverPos, bool isAccepted)
{
if (currentCrow)
{
NotifySwapForesightDecisionClientRpc(senderId, receiverPos, isAccepted);
}
}
[Rpc(SendTo.Everyone)]
private void NotifySwapForesightDecisionClientRpc(ulong senderId, Vector3 receiverPos, bool isAccepted)
{
if (currentCrow && currentCrow.clientCharacter)
{
if (isAccepted)
{
FindObjectOfType<CrowsForesightPrefab>().OnSwapAccepted(senderId, receiverPos);
}
else
{
FindObjectOfType<CrowsForesightPrefab>().OnSwapRejected(senderId, receiverPos);
}
}
}
[Rpc(SendTo.Everyone)]
private void NotifySwapForesightClientRpc(ulong senderId, ulong receiverId, Vector3 senderPos, Vector3 receiverPos)
{
Debug.Log($"[CrowManager] NotifySwapForesightClientRpc received - Sender: {senderId}, Receiver: {receiverId}, SenderPos: {senderPos}, ReceiverPos: {receiverPos}");
if (currentCrow == null)
{
Debug.LogError("[CrowManager] Error: Current Crow is null!");
return;
}
if (currentCrow.clientCharacter == null)
{
Debug.LogError("[CrowManager] Error: Current Crow clientCharacter is null!");
return;
}
var foresightPrefab = FindObjectOfType<CrowsForesightPrefab>();
if (foresightPrefab == null)
{
Debug.LogError("[CrowManager] Error: CrowsForesightPrefab not found on Crow!");
return;
}
foresightPrefab.OnSwapRequested(senderId, receiverId, senderPos, receiverPos);
}
[Rpc(SendTo.Everyone)]
private void NotifySwapForesightAcceptedClientRpc(ulong senderId, Vector3 receiverPos)
{
Debug.Log($"[CrowManager] NotifySwapForesightAcceptedClientRpc received - Sender: {senderId}, ReceiverPos: {receiverPos}");
if (currentCrow == null)
{
Debug.LogError("[CrowManager] Error: Current Crow is null!");
return;
}
if (currentCrow.clientCharacter == null)
{
Debug.LogError("[CrowManager] Error: Current Crow clientCharacter is null!");
return;
}
var foresightPrefab = FindObjectOfType<CrowsForesightPrefab>();
if (foresightPrefab == null)
{
Debug.LogError("[CrowManager] Error: CrowsForesightPrefab not found on Crow!");
return;
}
foresightPrefab.OnSwapAccepted(senderId, receiverPos);
}
}

@ -1,13 +1,30 @@
using System.Collections;
using System.Collections.Generic;
using Unity.BossRoom.Gameplay.GameplayObjects.Character;
using Unity.Netcode;
using UnityEngine;
using Unity.BossRoom.Gameplay.GameplayObjects.Character;
[CreateAssetMenu(menuName = "Abilities/CrowsForesight")]
public class CrowsForesightAbility : Ability
{
public override void Execute(ServerCharacter character, Vector3 targetPosition, Vector3 targetRotation)
{
throw new System.NotImplementedException();
if (!NetworkManager.Singleton.IsServer)
{
Debug.LogError("[CrowsForesightAbility] Execute should only be called on the server.");
return;
}
Debug.Log($"[CrowsForesightAbility] Spawning foresight prefab for Crow {character.OwnerClientId}");
GameObject foresightInstance = Instantiate(GetPrefab(), character.transform.position, Quaternion.identity);
NetworkObject netObj = foresightInstance.GetComponent<NetworkObject>();
if (netObj)
{
netObj.Spawn();
CrowsForesightPrefab foresightPrefab = foresightInstance.GetComponent<CrowsForesightPrefab>();
foresightPrefab.Initialize(CrowManager.Instance.GetCurrentCrow().OwnerClientId);
Debug.Log($"[CrowsForesightAbility] Assigned foresight prefab to Crow {character.OwnerClientId}");
}
}
}

@ -0,0 +1,142 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;
public class CrowsForesightPrefab : NetworkBehaviour
{
private Dictionary<ulong, LineRenderer> foresightLines = new Dictionary<ulong, LineRenderer>();
private ulong crowClientId;
private Coroutine destroyCoroutine;
private void Start()
{
if (IsServer)
{
Debug.Log("[CrowsForesightPrefab] Starting auto-destroy coroutine.");
destroyCoroutine = StartCoroutine(DelayedDestroy());
}
}
public void Initialize(ulong crowId)
{
crowClientId = crowId;
}
public override void OnNetworkSpawn()
{
Debug.Log($"[CrowsForesightPrefab] OnNetworkSpawn called - LocalClientId: {NetworkManager.Singleton.LocalClientId}, crowClientId: {crowClientId}");
if (NetworkManager.Singleton.LocalClientId != CrowManager.Instance.GetCurrentCrow().OwnerClientId && !NetworkManager.Singleton.IsServer)
{
gameObject.SetActive(false); // Hide from non-crow clients
}
}
private IEnumerator DelayedDestroy(float time = 10)
{
yield return new WaitForSeconds(time); // Adjust according to abilityDuration
if (IsServer)
{
Debug.Log("[CrowsForesightPrefab] Ability duration expired. Despawning on server.");
DespawnForesight();
}
}
public void DespawnForesight()
{
if (!IsServer) return;
Debug.Log("[CrowsForesightPrefab] Destroying foresight effect and clearing all lines.");
// Remove all foresight lines before despawning
foreach (var line in foresightLines.Values)
{
if (line != null)
{
Destroy(line.gameObject);
}
}
foresightLines.Clear();
if (NetworkObject.IsSpawned)
{
Debug.Log("[CrowsForesightPrefab] Despawning network object.");
NetworkObject.Despawn(true);
}
else
{
Debug.LogWarning("[CrowsForesightPrefab] WARNING: Tried to despawn, but NetworkObject was already despawned or missing!");
}
}
public void OnSwapRequested(ulong senderId, ulong receiverId, Vector3 senderPos, Vector3 receiverPos)
{
Debug.Log($"[CrowsForesightPrefab] OnSwapRequested - Sender: {senderId}, Receiver: {receiverId}, SenderPos: {senderPos}, ReceiverPos: {receiverPos}");
if (!foresightLines.ContainsKey(senderId))
{
Debug.Log($"[CrowsForesightPrefab] Creating foresight line for swap request {senderId} -> {receiverId}");
foresightLines[senderId] = CreateLine();
}
foresightLines[senderId].SetPosition(0, senderPos);
foresightLines[senderId].SetPosition(1, Vector3.Lerp(senderPos, receiverPos, 0.5f));
Debug.Log($"[CrowsForesightPrefab] Halfway foresight line drawn from {senderPos} to midpoint.");
}
public void OnSwapAccepted(ulong senderId, Vector3 receiverPos)
{
Debug.Log($"[CrowsForesightPrefab] OnSwapAccepted - Sender: {senderId}, ReceiverPos: {receiverPos}");
if (!foresightLines.ContainsKey(senderId))
{
Debug.LogError($"[CrowsForesightPrefab] ERROR: No foresight line found for sender {senderId} when swap was accepted!");
return;
}
foresightLines[senderId].SetPosition(1, receiverPos);
if (foresightLines.ContainsKey(senderId))
{
// Destroy the line associated with the sender
Destroy(foresightLines[senderId].gameObject ,1f);
foresightLines.Remove(senderId);
Debug.Log($"[CrowsForesightPrefab] Removed foresight line for rejected swap request from {senderId}.");
}
Debug.Log($"[CrowsForesightPrefab] Foresight line completed from sender {senderId} to {receiverPos}.");
}
public void OnSwapRejected(ulong senderId, Vector3 receiverPos)
{
Debug.Log($"[CrowsForesightPrefab] OnSwapRejected - Sender: {senderId}, ReceiverPos: {receiverPos}");
if (foresightLines.ContainsKey(senderId))
{
// Destroy the line associated with the sender
Destroy(foresightLines[senderId].gameObject);
foresightLines.Remove(senderId);
Debug.Log($"[CrowsForesightPrefab] Removed foresight line for rejected swap request from {senderId}.");
}
else
{
Debug.LogWarning($"[CrowsForesightPrefab] WARNING: No foresight line found for sender {senderId}. Swap rejection may have happened before drawing.");
}
}
private LineRenderer CreateLine()
{
GameObject lineObj = new GameObject("ForesightLine");
LineRenderer line = lineObj.AddComponent<LineRenderer>();
line.startWidth = 0.1f;
line.endWidth = 0.1f;
line.material = new Material(Shader.Find("Sprites/Default"));
line.transform.SetParent(transform);
return line;
}
}

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 24b344d29ff558b4197f1bb01ec11343
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -391,41 +391,47 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects.Character
[Rpc(SendTo.Server, RequireOwnership = false)]
public void NotifySwapRequestRpc(ulong initiatingPlayerId,string name)
public void NotifySwapRequestRpc(ulong senderId, string senderName)
{
PendingSwapRequest = initiatingPlayerId;
PendingSwapRequest = senderId;
ShowSwapConfirmationPanelClientRpc(senderName);
// Notify all clients except the server, filtered by target
ShowSwapConfirmationPanelClientRpc(name);
if (NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(senderId, out var senderObj) &&
senderObj.TryGetComponent(out ServerCharacter senderChar))
{
Vector3 senderPos = senderChar.transform.position;
Vector3 receiverPos = transform.position;
Debug.Log($"Swap request received from Player {initiatingPlayerId}. Waiting for confirmation.");
CrowManager.Instance.NotifyForesightSwap(senderChar.OwnerClientId, OwnerClientId, senderPos, receiverPos);
}
}
[Rpc(SendTo.Server, RequireOwnership = false)]
public void NotifySwapDecisionRpc(bool isAccepted)
{
if (!PendingSwapRequest.HasValue) return;
ulong initiatingPlayerId = PendingSwapRequest.Value;
if (isAccepted)
if (NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(initiatingPlayerId, out var initiatingPlayerObj) &&
initiatingPlayerObj.TryGetComponent(out ServerCharacter initiatingPlayer))
{
if (NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(initiatingPlayerId, out var initiatingPlayerObj) &&
initiatingPlayerObj.TryGetComponent(out ServerCharacter initiatingPlayer))
Vector3 receiverPos = transform.position;
CrowManager.Instance.NotifyForesightSwapDecision(initiatingPlayerObj.OwnerClientId, receiverPos, isAccepted);
if (isAccepted)
{
InitiateSwap(initiatingPlayer, this);
Debug.Log($"Swap confirmed: {initiatingPlayer.name} and {this.name} are swapping.");
}
}
else
{
Debug.Log($"Swap request denied by {this.name}.");
}
PendingSwapRequest = null;
}
public void InitiateSwap(ServerCharacter initiatingPlayer, ServerCharacter targetPlayer)
{
var initiatingPlatform = PlatformManager.Instance.GetPlatformOccupiedByPlayer(initiatingPlayer);

@ -572,6 +572,16 @@ namespace Unity.BossRoom.Gameplay.UserInput
}
ActivateAbilityIfAllowed(GameDataSource.Instance.TheExecutionerKey);
}
if (Input.GetKeyDown(KeyCode.V)) // Crow's Foresight
{
if (!m_ServerCharacter.IsCrow)
{
m_UIMessageFeed.DisplayMessage("You must be the Crow to activate this ability");
return;
}
ActivateAbilityIfAllowed(GameDataSource.Instance.CrowsForesightKey);
}
}

Loading…
Cancel
Save