From 7b825ef1b33f6639fcb5ada9a28a17916682b7ba Mon Sep 17 00:00:00 2001 From: Hazim Bin Ijaz Date: Fri, 29 Nov 2024 19:08:00 +0500 Subject: [PATCH] Added Swap --- Assets/GameData/Action/General/Swap.asset | 43 +++++++ .../GameData/Action/General/Swap.asset.meta | 8 ++ Assets/Scenes/BossRoom.unity | 18 +-- Assets/Scenes/BossRoom/DungeonEntrance.unity | 107 ++++++++++++++++++ .../BossRoom/NavMesh-DungeonNavMesh.asset | Bin 0 -> 7244 bytes .../NavMesh-DungeonNavMesh.asset.meta | 8 ++ Assets/Scenes/Startup.unity | 5 + .../Action/ConcreteActions/SwapAction.cs | 73 ++++++++++++ .../Action/ConcreteActions/SwapAction.cs.meta | 11 ++ .../Gameplay/Action/Input/ActionLogic.cs | 3 +- .../Character/ServerCharacter.cs | 17 +++ .../RuntimeDataContainers/GameDataSource.cs | 6 +- .../Gameplay/UserInput/ClientInputSender.cs | 83 ++++++++++++-- 13 files changed, 360 insertions(+), 22 deletions(-) create mode 100644 Assets/GameData/Action/General/Swap.asset create mode 100644 Assets/GameData/Action/General/Swap.asset.meta create mode 100644 Assets/Scenes/BossRoom/NavMesh-DungeonNavMesh.asset create mode 100644 Assets/Scenes/BossRoom/NavMesh-DungeonNavMesh.asset.meta create mode 100644 Assets/Scripts/Gameplay/Action/ConcreteActions/SwapAction.cs create mode 100644 Assets/Scripts/Gameplay/Action/ConcreteActions/SwapAction.cs.meta diff --git a/Assets/GameData/Action/General/Swap.asset b/Assets/GameData/Action/General/Swap.asset new file mode 100644 index 0000000..a71cdc6 --- /dev/null +++ b/Assets/GameData/Action/General/Swap.asset @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 51bc649ad66145f4f9160e06d4162795, type: 3} + m_Name: Swap + m_EditorClassIdentifier: + Config: + Logic: 18 + Amount: 0 + ManaCost: 0 + Range: 0 + DurationSeconds: 0 + ExecTimeSeconds: 0 + EffectDurationSeconds: 0 + ReuseTimeSeconds: 0 + AnimAnticipation: + Anim: + Anim2: + ReactAnim: + OtherAnimatorVariable: + SplashDamage: 0 + MoveSpeed: 0 + KnockbackSpeed: 0 + KnockbackDuration: 0 + Radius: 0 + ActionInput: {fileID: 0} + ActionInterruptible: 0 + IsInterruptableBy: [] + BlockingMode: 1 + Projectiles: [] + Spawns: [] + IsFriendly: 0 + Icon: {fileID: 0} + DisplayedName: + Description: diff --git a/Assets/GameData/Action/General/Swap.asset.meta b/Assets/GameData/Action/General/Swap.asset.meta new file mode 100644 index 0000000..3cbde86 --- /dev/null +++ b/Assets/GameData/Action/General/Swap.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c55ead416f0a54c4f95b4664d7e5bea1 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/BossRoom.unity b/Assets/Scenes/BossRoom.unity index f3492a0..32db342 100644 --- a/Assets/Scenes/BossRoom.unity +++ b/Assets/Scenes/BossRoom.unity @@ -8240,11 +8240,11 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 1676734515771252668, guid: 0193228de87741d40a42e561901c9083, type: 3} propertyPath: m_LocalRotation.w - value: 0.8529446 + value: 0.85294455 objectReference: {fileID: 0} - target: {fileID: 1676734515771252668, guid: 0193228de87741d40a42e561901c9083, type: 3} propertyPath: m_LocalRotation.x - value: 0.39434478 + value: 0.3943448 objectReference: {fileID: 0} - target: {fileID: 1676734515771252668, guid: 0193228de87741d40a42e561901c9083, type: 3} propertyPath: m_LocalRotation.y @@ -8252,7 +8252,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 1676734515771252668, guid: 0193228de87741d40a42e561901c9083, type: 3} propertyPath: m_LocalRotation.z - value: -0.14352977 + value: -0.14352979 objectReference: {fileID: 0} - target: {fileID: 1676734516302391364, guid: 0193228de87741d40a42e561901c9083, type: 3} propertyPath: m_UpdateMethod @@ -8284,11 +8284,11 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 1676734516695783279, guid: 0193228de87741d40a42e561901c9083, type: 3} propertyPath: m_LocalRotation.y - value: 0.3097298 + value: 0.30972984 objectReference: {fileID: 0} - target: {fileID: 1676734516695783279, guid: 0193228de87741d40a42e561901c9083, type: 3} propertyPath: m_LocalRotation.z - value: -0.14506969 + value: -0.1450697 objectReference: {fileID: 0} - target: {fileID: 1676734516724634599, guid: 0193228de87741d40a42e561901c9083, type: 3} propertyPath: m_LocalPosition.z @@ -8401,15 +8401,15 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 203267159508449512, guid: 36b3ee75677a1544191c0ddaaadd8140, type: 3} propertyPath: m_LocalRotation.x - value: 0.3943448 + value: 0.39434484 objectReference: {fileID: 0} - target: {fileID: 203267159508449512, guid: 36b3ee75677a1544191c0ddaaadd8140, type: 3} propertyPath: m_LocalRotation.y - value: 0.31044644 + value: 0.3104465 objectReference: {fileID: 0} - target: {fileID: 203267159508449512, guid: 36b3ee75677a1544191c0ddaaadd8140, type: 3} propertyPath: m_LocalRotation.z - value: -0.14352976 + value: -0.1435298 objectReference: {fileID: 0} - target: {fileID: 203267159508449512, guid: 36b3ee75677a1544191c0ddaaadd8140, type: 3} propertyPath: m_LocalEulerAnglesHint.x @@ -9672,7 +9672,7 @@ MonoBehaviour: m_OverrideVoxelSize: 0 m_VoxelSize: 0.16666667 m_MinRegionArea: 2 - m_NavMeshData: {fileID: 0} + m_NavMeshData: {fileID: 23800000, guid: cd817e3eace813041ad4d732be64af84, type: 2} m_BuildHeightMesh: 0 --- !u!1001 &3765979715153886892 PrefabInstance: diff --git a/Assets/Scenes/BossRoom/DungeonEntrance.unity b/Assets/Scenes/BossRoom/DungeonEntrance.unity index 9dddfbf..9b19f44 100644 --- a/Assets/Scenes/BossRoom/DungeonEntrance.unity +++ b/Assets/Scenes/BossRoom/DungeonEntrance.unity @@ -804,6 +804,112 @@ MeshFilter: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1146060681} m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1415641637 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1415641641} + - component: {fileID: 1415641640} + - component: {fileID: 1415641639} + - component: {fileID: 1415641638} + m_Layer: 8 + m_Name: Plane + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!64 &1415641638 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1415641637} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 5 + m_Convex: 0 + m_CookingOptions: 30 + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &1415641639 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1415641637} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1415641640 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1415641637} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1415641641 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1415641637} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.58, y: -0.14, z: 1.84} + m_LocalScale: {x: 1.2077, y: 1.2077, z: 1.2077} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1463337822 GameObject: m_ObjectHideFlags: 0 @@ -1070,3 +1176,4 @@ SceneRoots: - {fileID: 2085312387} - {fileID: 949745749} - {fileID: 286165427} + - {fileID: 1415641641} diff --git a/Assets/Scenes/BossRoom/NavMesh-DungeonNavMesh.asset b/Assets/Scenes/BossRoom/NavMesh-DungeonNavMesh.asset new file mode 100644 index 0000000000000000000000000000000000000000..ee181c195adbdce638fb0a1f1aeccd65f6d23375 GIT binary patch literal 7244 zcmbuDe{3AZ702h|vqRbfcA=z6pfwa);u6<)7eXi@IXgDkX>d$zoKix~+P6M$d_Ua1 zy~Iu$*d|RVgf>7R2|v^}YE^_y5h|5X{zzq|f1s*J6;+V>L#pymT9j5*RSBqQh5LOo zZ|-()Z`?>7X=i8NXXd?m@6FDQEkvbUQ)!9iFRS*oTh)8{dCig?$z*$~J((O&h>sQ) z7Gg1wzY|?p_~}31{$T#C_jfkG+4Y;Ti%lzEg!Ih@A(jwExlITkQx;^$m$j^7A|`&) zApD=jgdc~5RMMjh@lT-B6Bj4bT7lBZ1@VI zCjD#iwpf3olvOZjSbvk`eq}(d{-qHf6Ni@w-(~%@hQ-#uEHXd5{*Og?O!UIPIXF%6 z{Wx)-tf+$Z#S(}QJ;W)7v2>6($oQ>-4vNj?#AT%P{04C^=I+8n>%JnwW8xjm?Sq{3 zUx{~%kBUpJ{btBp<~1c-Vf!t_t61`{qEGfo|0jw2)d4XPm-Z(hB7RkbH-`Mbns^!& zmzZb@`Tr@%!}goR58%;`H1$6v)4XMl|F=M4N^ z<~JJnKbhZT;QwL%c>`}kaw)%GsNoHeHUr#*=T5Mj@ihCWxajj`12}zutMSl2(uMdb z?EPNmZ2hXt|-(ujC%-0zBZszRa5~?3n?;Y#3wGU>hU6QSQ$yIPKp}20qC=ZQw=bod#ZF-eur>m~S@leayQJ{1N6o27ZwF zT?YOr^ScfF2=iV8KgyhbN5k<~@jb?Ti-DhD{uKj%f%#Sg{{eH_1NH3xh6#09>8P<+28d23}vOe~e(-=AThzP|?y{9Wcd4g4bW2P0hFul~mVeVw?EiVN}= z!3~E<|GyV`>;=Ur_l&+l<`>rr}&IX-ilfk(tir` zb$l`qH;Y!L%06)&AKSone8wYO*}tqo+0RCJ*goA;7qjmexVDct)y!Aq7bT~Ws?gsO!T3)>9QI#v9sh3_ zxc1+TaAhBVFrILH;`s`3>ghh=J?)JYnEEKHrUSWnZ6f-;40D{i6o1?LTSY+Wu1!9upUEzc_{XP~4x6 zaP{|*KHrZSxVHa{fouEE8u%-)Py6F|gkyck&#U0{{hWyK@cK>~xL)6L2Cmole1ym3 z`Er`q_k!frs^8juk6oJRwmeG=40!H_o{Zxa-JWUBE|i>NVWY^8+~wr#zHT%IEN=o0 zIc~tU$F0%6LdmlVV>S(ARYMqE5`m7?ogb-~$&d6}r3o=Q)!dwO@}nYWXR>y;Tb$xid24!0IX~4o<`zq( zZb!vb0bYqlUQ2HtKm_NOxIJ%?g zPTFosOu2T+c6Zw{TieQB$;sGV#d0B2NuBhy+a4`vD{;tBk2XZkl2K9G^VU>JRGKo| zrLsG2joCxRA=`B=ry%T(4m=4wNjxcGC(uuzpFlr>eiHp8`bqSY=%>(6p`SuOl@gxP zBb7U)?M2V>>VD`aFpKf=D|M>ZpewhJb=yoW}A zF%weOHB1u92E|Y~xZ~tUwvCTdRJS^X$&%g_WAk#RTF1aA9icnbF;hV^%!cCcKRO$l_kFLWdoJAt@~t|MlF&59i%yp za&2*OJ#MfotHT1V3+<^l+||GPRp-AiKYo7Mbt{5?(y;&SC;nf@eh%OFPCDo(&9C}4 zpRR2y-_)2oeqwgqM|DYl(zv*|(dg%{zP~*4@{SK5{=iz+Z@oHkchFDmW6+i`WYOmZAJZ5`J}OdeAe+(sHvQz;_wJ;3c(fnXFVTMi7qHBe literal 0 HcmV?d00001 diff --git a/Assets/Scenes/BossRoom/NavMesh-DungeonNavMesh.asset.meta b/Assets/Scenes/BossRoom/NavMesh-DungeonNavMesh.asset.meta new file mode 100644 index 0000000..98d0fab --- /dev/null +++ b/Assets/Scenes/BossRoom/NavMesh-DungeonNavMesh.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cd817e3eace813041ad4d732be64af84 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 23800000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/Startup.unity b/Assets/Scenes/Startup.unity index 96a6101..b774798 100644 --- a/Assets/Scenes/Startup.unity +++ b/Assets/Scenes/Startup.unity @@ -520,6 +520,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: GlobalObjectIdHash: 2270253351 + InScenePlacedSourceGlobalObjectIdHash: 0 AlwaysReplicateAsRoot: 0 SynchronizeTransform: 0 ActiveSceneSynchronization: 0 @@ -1459,6 +1460,10 @@ PrefabInstance: serializedVersion: 3 m_TransformParent: {fileID: 0} m_Modifications: + - target: {fileID: 370034730102636685, guid: 4512c09d24f3fa147afb198fa90d63c6, type: 3} + propertyPath: m_GeneralSwapActionPrototype + value: + objectReference: {fileID: 11400000, guid: c55ead416f0a54c4f95b4664d7e5bea1, type: 2} - target: {fileID: 1133988469759348351, guid: 4512c09d24f3fa147afb198fa90d63c6, type: 3} propertyPath: m_Name value: GameDataSource diff --git a/Assets/Scripts/Gameplay/Action/ConcreteActions/SwapAction.cs b/Assets/Scripts/Gameplay/Action/ConcreteActions/SwapAction.cs new file mode 100644 index 0000000..6c00ddf --- /dev/null +++ b/Assets/Scripts/Gameplay/Action/ConcreteActions/SwapAction.cs @@ -0,0 +1,73 @@ +using Unity.BossRoom.Gameplay.Actions; +using Unity.BossRoom.Gameplay.GameplayObjects.Character; +using Unity.Netcode; +using UnityEngine; + +[CreateAssetMenu(menuName = "BossRoom/Actions/Swap Action")] +public class SwapAction : Action +{ + private ServerCharacter m_TargetCharacter; // The character to swap with + private Vector3 m_TargetOriginalPosition; // Target's original position + private Vector3 m_ServerCharacterOriginalPosition; // Server character's original position + private bool m_MovementStarted = false; // Ensures movement commands are sent only once + + public override bool OnStart(ServerCharacter serverCharacter) + { + // Validate the target + if (Data.TargetIds == null || Data.TargetIds.Length == 0) + { + Debug.LogError("SwapAction failed: No target specified!"); + return false; // End the action immediately + } + + // Retrieve the target character + if (!NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(Data.TargetIds[0], out var targetObject) || + !targetObject.TryGetComponent(out m_TargetCharacter)) + { + Debug.LogError("SwapAction failed: Target is invalid or missing!"); + return false; // End the action immediately + } + + // Store original positions + m_ServerCharacterOriginalPosition = serverCharacter.physicsWrapper.Transform.position; + m_TargetOriginalPosition = m_TargetCharacter.physicsWrapper.Transform.position; + + // Command both characters to move to each other's original positions + serverCharacter.ServerSendCharacterInputRpc(m_TargetOriginalPosition); + m_TargetCharacter.ServerSendCharacterInputRpc(m_ServerCharacterOriginalPosition); + + Debug.Log("SwapAction: Movement commands sent to both players."); + m_MovementStarted = true; + return true; // Keep the action active + } + + public override bool OnUpdate(ServerCharacter serverCharacter) + { + if (!m_MovementStarted) + { + Debug.LogError("SwapAction OnUpdate called without movement initialization!"); + return false; // Fail-safe: End the action + } + + // Check if both characters have reached their destinations + bool serverCharacterReached = Vector3.Distance(serverCharacter.physicsWrapper.Transform.position, m_TargetOriginalPosition) < 0.1f; + bool targetCharacterReached = Vector3.Distance(m_TargetCharacter.physicsWrapper.Transform.position, m_ServerCharacterOriginalPosition) < 0.1f; + + if (serverCharacterReached && targetCharacterReached) + { + Debug.Log("SwapAction: Both players have swapped positions successfully."); + return false; // End the action + } + + return true; // Continue the action until both characters reach their destinations + } + + public override void Reset() + { + base.Reset(); + m_TargetCharacter = null; + m_TargetOriginalPosition = Vector3.zero; + m_ServerCharacterOriginalPosition = Vector3.zero; + m_MovementStarted = false; + } +} \ No newline at end of file diff --git a/Assets/Scripts/Gameplay/Action/ConcreteActions/SwapAction.cs.meta b/Assets/Scripts/Gameplay/Action/ConcreteActions/SwapAction.cs.meta new file mode 100644 index 0000000..81347a3 --- /dev/null +++ b/Assets/Scripts/Gameplay/Action/ConcreteActions/SwapAction.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 51bc649ad66145f4f9160e06d4162795 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Gameplay/Action/Input/ActionLogic.cs b/Assets/Scripts/Gameplay/Action/Input/ActionLogic.cs index deeaed6..8d7faf9 100644 --- a/Assets/Scripts/Gameplay/Action/Input/ActionLogic.cs +++ b/Assets/Scripts/Gameplay/Action/Input/ActionLogic.cs @@ -24,6 +24,7 @@ namespace Unity.BossRoom.Gameplay.Actions DashAttack, ImpToss, PickUp, - Drop + Drop, + Swap } } diff --git a/Assets/Scripts/Gameplay/GameplayObjects/Character/ServerCharacter.cs b/Assets/Scripts/Gameplay/GameplayObjects/Character/ServerCharacter.cs index 3edac2f..3b559ec 100644 --- a/Assets/Scripts/Gameplay/GameplayObjects/Character/ServerCharacter.cs +++ b/Assets/Scripts/Gameplay/GameplayObjects/Character/ServerCharacter.cs @@ -140,6 +140,10 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects.Character private AIBrain m_AIBrain; NetworkAvatarGuidState m_State; + public ulong? PendingSwapRequest { get; set; } + + + void Awake() { m_ServerActionPlayer = new ServerActionPlayer(this); @@ -148,6 +152,19 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects.Character m_State = GetComponent(); } + [Rpc(SendTo.Server, RequireOwnership = false)] + public void NotifySwapRequestRpc(ulong initiatingPlayerId) + { + PendingSwapRequest = initiatingPlayerId; + Debug.Log($"Swap request received from Player {initiatingPlayerId}. Press 'L' to confirm."); + } + [Rpc(SendTo.Server, RequireOwnership = false)] + public void NotifySwapConfirmedRpc(ulong targetPlayerId) + { + Debug.Log($"Swap request confirmed by Player {targetPlayerId}."); + } + + public override void OnNetworkSpawn() { if (!IsServer) { enabled = false; } diff --git a/Assets/Scripts/Gameplay/GameplayObjects/RuntimeDataContainers/GameDataSource.cs b/Assets/Scripts/Gameplay/GameplayObjects/RuntimeDataContainers/GameDataSource.cs index 5161bae..1b3ef07 100644 --- a/Assets/Scripts/Gameplay/GameplayObjects/RuntimeDataContainers/GameDataSource.cs +++ b/Assets/Scripts/Gameplay/GameplayObjects/RuntimeDataContainers/GameDataSource.cs @@ -24,6 +24,9 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects //Actions that are directly listed here will get automatically assigned ActionIDs and they don't need to be a part of m_ActionPrototypes array [Header("Common action prototypes")] + [SerializeField] + Action m_GeneralSwapActionPrototype; + [SerializeField] Action m_GeneralChaseActionPrototype; @@ -59,6 +62,7 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects private Action[] m_ActionPrototypes; public Action GeneralChaseActionPrototype => m_GeneralChaseActionPrototype; + public Action GeneralSwapActionPrototype => m_GeneralSwapActionPrototype; public Action GeneralTargetActionPrototype => m_GeneralTargetActionPrototype; @@ -148,7 +152,7 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects uniqueActions.Add(StunnedActionPrototype); uniqueActions.Add(DropActionPrototype); uniqueActions.Add(PickUpActionPrototype); - + uniqueActions.Add(GeneralSwapActionPrototype); m_AllActions = new List(uniqueActions.Count); int i = 0; diff --git a/Assets/Scripts/Gameplay/UserInput/ClientInputSender.cs b/Assets/Scripts/Gameplay/UserInput/ClientInputSender.cs index 5dd2f0d..52f0920 100644 --- a/Assets/Scripts/Gameplay/UserInput/ClientInputSender.cs +++ b/Assets/Scripts/Gameplay/UserInput/ClientInputSender.cs @@ -514,6 +514,41 @@ namespace Unity.BossRoom.Gameplay.UserInput { RequestAction(GameDataSource.Instance.Emote4ActionPrototype.ActionID, SkillTriggerStyle.Keyboard); } + if (Input.GetKeyDown(KeyCode.L)) // Press L to confirm the swap + { + if (m_ServerCharacter.PendingSwapRequest.HasValue) + { + ulong initiatingPlayerId = m_ServerCharacter.PendingSwapRequest.Value; + + if (NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(initiatingPlayerId, out var initiatingPlayerObject) && + initiatingPlayerObject.TryGetComponent(out ServerCharacter initiatingPlayer)) + { + // Store positions of both players + Vector3 initiatingPlayerPosition = initiatingPlayer.physicsWrapper.Transform.position; + Vector3 targetPlayerPosition = m_ServerCharacter.physicsWrapper.Transform.position; + + // Execute the swap + initiatingPlayer.ServerSendCharacterInputRpc(targetPlayerPosition); + m_ServerCharacter.ServerSendCharacterInputRpc(initiatingPlayerPosition); + + Debug.Log($"Swap confirmed: {initiatingPlayer.name} swapped with {m_ServerCharacter.name}."); + + // Clear the pending request + m_ServerCharacter.PendingSwapRequest = null; + + // Notify initiating player about confirmation (optional for UI feedback) + initiatingPlayer.NotifySwapConfirmedRpc(m_ServerCharacter.NetworkObjectId); + } + else + { + Debug.LogError("Swap confirmation failed: Initiating player not found."); + } + } + else + { + Debug.Log("No pending swap request to confirm."); + } + } if (!EventSystem.current.IsPointerOverGameObject() && m_CurrentSkillInput == null) { @@ -525,17 +560,43 @@ namespace Unity.BossRoom.Gameplay.UserInput RequestAction(CharacterClass.Skill1.ActionID, SkillTriggerStyle.MouseClick); } - if (Input.GetMouseButtonDown(0)) + if (Input.GetMouseButtonDown(0)) // Left-click triggers the SwapAction request { - RequestAction(GameDataSource.Instance.GeneralTargetActionPrototype.ActionID, SkillTriggerStyle.MouseClick); + var ray = m_MainCamera.ScreenPointToRay(UnityEngine.Input.mousePosition); + int hits = Physics.RaycastNonAlloc(ray, k_CachedHit, k_MouseInputRaycastDistance, m_ActionLayerMask); + + if (hits > 0) + { + for (int i = 0; i < hits; i++) + { + if (k_CachedHit[i].transform.TryGetComponent(out NetworkObject targetNetObj) && + targetNetObj != m_ServerCharacter.NetworkObject) + { + // Retrieve the target character + if (!targetNetObj.TryGetComponent(out ServerCharacter targetCharacter)) + { + Debug.LogError("SwapAction failed: Target is not a valid ServerCharacter!"); + return; + } + + // Notify the target player (send confirmation request) + targetCharacter.NotifySwapRequestRpc(m_ServerCharacter.NetworkObjectId); + + Debug.Log($"SwapAction requested: Waiting for {targetCharacter.name} to confirm."); + return; // Exit loop after sending the request + } + } + } } - else if (Input.GetMouseButton(0)) + + else if(Input.GetMouseButtonDown(0)) { - m_MoveRequest = true; + m_MoveRequest = true; // Set move request for holding left-click } } } + void UpdateAction1() { var isHoldingNetworkObject = @@ -553,19 +614,19 @@ namespace Unity.BossRoom.Gameplay.UserInput actionState1.actionID = GameDataSource.Instance.DropActionPrototype.ActionID; } else if ((m_ServerCharacter.TargetId.Value != 0 - && selection != null - && selection.TryGetComponent(out PickUpState pickUpState)) - ) + && selection != null + && selection.TryGetComponent(out PickUpState pickUpState)) + ) { // special case: targeting a pickup-able item or holding a pickup object actionState1.actionID = GameDataSource.Instance.PickUpActionPrototype.ActionID; } else if (m_ServerCharacter.TargetId.Value != 0 - && selection != null - && selection.NetworkObjectId != m_ServerCharacter.NetworkObjectId - && selection.TryGetComponent(out ServerCharacter charState) - && !charState.IsNpc) + && selection != null + && selection.NetworkObjectId != m_ServerCharacter.NetworkObjectId + && selection.TryGetComponent(out ServerCharacter charState) + && !charState.IsNpc) { // special case: when we have a player selected, we change the meaning of the basic action // we have another player selected! In that case we want to reflect that our basic Action is a Revive, not an attack!