-
Notifications
You must be signed in to change notification settings - Fork 2
/
FrequencyWalkie.cs
165 lines (145 loc) · 7.87 KB
/
FrequencyWalkie.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using BepInEx;
using GameNetcodeStuff;
using HarmonyLib;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
using Object = UnityEngine.Object;
namespace FrequencyWalkie
{
enum RpcExecStage
{
None,
Server,
Client,
}
[BepInPlugin("larko.frequencywalkie", "FrequencyWalkie", "1.3.1")]
public class FrequencyWalkie : BaseUnityPlugin
{
// A hash map of all walkie talkies and their selected frequency
// the key is the walkie talkie's gameobject instance ID
// the value is the frequency index
public static Dictionary<int, int> walkieTalkieFrequencies = new Dictionary<int, int>();
public static List<string> frequencies = new List<string> {"BR.d", "18.3", "19.5", "21.7", "23.3", "25.0", "27.9", "29.3", "31.3", "33.6", "35.4", "36.8", "37.7", "38.6", "39.4",
"40.2", "42.3", "43.8", "44.5", "45.1", "46.9", "47.2", "47.8", "48.1", "48.5"};
public static string tooltip = "[R] Increase frequency\n[F] Decrease frequency";
void Awake()
{
Harmony harmony = new Harmony("larko.frequencywalkie");
Patches.ApplyPatches(harmony);
}
public static T GetResource<T>(string objName) where T : Object
{
T[] objects = Resources.FindObjectsOfTypeAll<T>();
foreach (T obj in objects)
{
if (obj.name == objName)
{
return obj;
}
}
return null;
}
public static IEnumerator OnFrequencyChanged(WalkieTalkie walkie, bool increased)
{
var canvas = walkie.gameObject.GetComponent<Canvas>();
var text = canvas.GetComponentInChildren<Text>();
text.text = $"<b><size=40>{frequencies[walkieTalkieFrequencies[walkie.GetInstanceID()]]}</size><i><size=30>MHz</size></i></b>";
MethodInfo SendWalkieTalkieStartTransmissionSFX = AccessTools.Method(typeof(WalkieTalkie), "SendWalkieTalkieStartTransmissionSFX");
SendWalkieTalkieStartTransmissionSFX.Invoke(walkie, new object[] {(int)walkie.playerHeldBy.playerClientId});
// we show the broadcast icon if frequency is 0 (broad)
if (walkieTalkieFrequencies[walkie.GetInstanceID()] == 0)
{
canvas.transform.GetChild(canvas.transform.childCount - 4).gameObject.SetActive(true);
}
else
{
canvas.transform.GetChild(canvas.transform.childCount - 4).gameObject.SetActive(false);
}
if (increased)
canvas.transform.GetChild(canvas.transform.childCount - 2).gameObject.SetActive(false);
else
canvas.transform.GetChild(canvas.transform.childCount - 1).gameObject.SetActive(false);
yield return new WaitForSeconds(0.5f);
canvas.transform.GetChild(canvas.transform.childCount - 1).gameObject.SetActive(true);
canvas.transform.GetChild(canvas.transform.childCount - 2).gameObject.SetActive(true);
}
public static void SetPlayerSpeakingOnWalkieTalkieServerRpc(WalkieTalkie instance, int playerId, int frequency)
{
NetworkManager networkManager = instance.NetworkManager;
if (networkManager == null || !networkManager.IsListening)
{
return;
}
var rpc_exec_stage = (int)AccessTools.Field(typeof(WalkieTalkie), "__rpc_exec_stage").GetValue(instance);
MethodInfo beginSendServerRpc = AccessTools.Method(typeof(WalkieTalkie), "__beginSendServerRpc");
MethodInfo endSendServerRpc = AccessTools.Method(typeof(WalkieTalkie), "__endSendServerRpc");
if (rpc_exec_stage != (int)RpcExecStage.Server && (networkManager.IsClient || networkManager.IsHost))
{
if (instance.OwnerClientId != networkManager.LocalClientId)
{
if (networkManager.LogLevel <= LogLevel.Normal)
{
Debug.LogError("Only the owner can invoke a ServerRpc that requires ownership!");
}
return;
}
ServerRpcParams serverRpcParams = default;
FastBufferWriter writer = (FastBufferWriter)beginSendServerRpc.Invoke(instance, new object[] {64994802U, serverRpcParams, RpcDelivery.Reliable});
BytePacker.WriteValueBitPacked(writer, playerId);
BytePacker.WriteValueBitPacked(writer, frequency);
// maybe ref bug - writer will get cloned?
endSendServerRpc.Invoke(instance, new object[] {writer, 64994802U, serverRpcParams, RpcDelivery.Reliable});
}
if (rpc_exec_stage != (int)RpcExecStage.Server || (!networkManager.IsServer && !networkManager.IsHost))
{
return;
}
SetPlayerSpeakingOnWalkieTalkieClientRpc(instance, playerId, frequency);
}
public static void SetPlayerSpeakingOnWalkieTalkieClientRpc(WalkieTalkie instance, int playerId, int frequency)
{
NetworkManager networkManager = instance.NetworkManager;
if (networkManager == null || !networkManager.IsListening)
return;
var rpc_exec_stage = (int)AccessTools.Field(typeof(WalkieTalkie), "__rpc_exec_stage").GetValue(instance);
MethodInfo beginSendClientRpc = AccessTools.Method(typeof(WalkieTalkie), "__beginSendClientRpc");
MethodInfo endSendClientRpc = AccessTools.Method(typeof(WalkieTalkie), "__endSendClientRpc");
MethodInfo SendWalkieTalkieStartTransmissionSFX = AccessTools.Method(typeof(WalkieTalkie), "SendWalkieTalkieStartTransmissionSFX");
if (rpc_exec_stage != (int)RpcExecStage.Client && (networkManager.IsServer || networkManager.IsHost))
{
ClientRpcParams clientRpcParams = default;
FastBufferWriter bufferWriter = (FastBufferWriter) beginSendClientRpc.Invoke(instance, new object[] {2961867446U, clientRpcParams, RpcDelivery.Reliable});
BytePacker.WriteValueBitPacked(bufferWriter, playerId);
BytePacker.WriteValueBitPacked(bufferWriter, frequency);
// maybe ref bug - writer will get cloned?
endSendClientRpc.Invoke(instance, new object[] {bufferWriter, 2961867446U, clientRpcParams, RpcDelivery.Reliable});
}
if (rpc_exec_stage != (int)RpcExecStage.Client || !networkManager.IsClient && !networkManager.IsHost)
return;
// update the frequency on the incoming walkie talkie
for (int i = 0; i < WalkieTalkie.allWalkieTalkies.Count; i++)
{
if ((int)WalkieTalkie.allWalkieTalkies[i].playerHeldBy.playerClientId == playerId)
{
walkieTalkieFrequencies[WalkieTalkie.allWalkieTalkies[i].GetInstanceID()] = frequency;
// update text
instance.StartCoroutine(OnFrequencyChanged(WalkieTalkie.allWalkieTalkies[i], false));
break;
}
}
if (walkieTalkieFrequencies[instance.GetInstanceID()] != frequency && frequency != 0)
return;
StartOfRound.Instance.allPlayerScripts[playerId].speakingToWalkieTalkie = true;
instance.clientIsHoldingAndSpeakingIntoThis = true;
SendWalkieTalkieStartTransmissionSFX.Invoke(instance, new object[] {playerId});
StartOfRound.Instance.UpdatePlayerVoiceEffects();
}
}
}