mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-20 01:46:25 +00:00
Prompts, Achievements API, Prevent CNOs on modded servers, Duellist nerf
This commit is contained in:
1 parent
4978ca7a92
commit
ba9059e401
18 files changed
+411
-192
No files matched your search
@@ -407,6 +407,7 @@ public enum CustomRoles
|
||||
// Sub-role after 500
|
||||
NotAssigned = 500,
|
||||
Allergic,
|
||||
Anchor,
|
||||
Antidote,
|
||||
AntiTP,
|
||||
Asthmatic,
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<Description>EHR</Description>
|
||||
<Authors>Gurge44</Authors>
|
||||
<langVersion>preview</langVersion>
|
||||
<AmongUs>E:\Program Files\AmongUs</AmongUs>
|
||||
<AmongUs>D:\AmongUs</AmongUs>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Optimize>True</Optimize>
|
||||
<AssemblyName>$(MSBuildProjectName)</AssemblyName>
|
||||
|
||||
@@ -35,9 +35,10 @@ public class Main : BasePlugin
|
||||
private const string DebugKeyHash = "c0fd562955ba56af3ae20d7ec9e64c664f0facecef4b3e366e109306adeae29d";
|
||||
private const string DebugKeySalt = "59687b";
|
||||
private const string PluginGuid = "com.gurge44.endlesshostroles";
|
||||
public const string PluginVersion = "5.2.0";
|
||||
public const string PluginDisplayVersion = "5.2.0";
|
||||
public const string PluginVersion = "5.3.0";
|
||||
public const string PluginDisplayVersion = "5.3.0";
|
||||
public const bool TestBuild = false;
|
||||
|
||||
public const string NeutralColor = "#ffab1b";
|
||||
public const string ImpostorColor = "#ff1919";
|
||||
public const string CrewmateColor = "#8cffff";
|
||||
|
||||
+64
-3
@@ -1,7 +1,9 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
@@ -109,6 +111,10 @@ public static class Achievements
|
||||
|
||||
const string SaveFilePath = "./EHR_DATA/Achievements.json";
|
||||
|
||||
const string ApiBaseUrl = "https://gurge44.pythonanywhere.com/achievements";
|
||||
const string ApiSaveEndpoint = $"{ApiBaseUrl}/save";
|
||||
const string ApiLoadEndpoint = $"{ApiBaseUrl}/load";
|
||||
|
||||
public static readonly HashSet<Type> WaitingAchievements = [];
|
||||
public static HashSet<Type> CompletedAchievements = [];
|
||||
|
||||
@@ -176,13 +182,68 @@ public static class Achievements
|
||||
{
|
||||
var json = JsonSerializer.Serialize(CompletedAchievements);
|
||||
File.WriteAllText(SaveFilePath, json);
|
||||
|
||||
Main.Instance.StartCoroutine(SendAchievementsToApiAsync());
|
||||
return;
|
||||
|
||||
IEnumerator SendAchievementsToApiAsync()
|
||||
{
|
||||
while (PlayerControl.LocalPlayer == null) yield return null;
|
||||
|
||||
var userId = PlayerControl.LocalPlayer.GetClient().GetHashedPuid();
|
||||
|
||||
var data = new
|
||||
{
|
||||
userId,
|
||||
achievements = CompletedAchievements
|
||||
};
|
||||
|
||||
var payload = JsonSerializer.Serialize(data);
|
||||
|
||||
var request = new UnityWebRequest(ApiSaveEndpoint, UnityWebRequest.kHttpVerbPOST)
|
||||
{
|
||||
uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(payload)),
|
||||
downloadHandler = new DownloadHandlerBuffer()
|
||||
};
|
||||
|
||||
request.SetRequestHeader("Content-Type", "application/json");
|
||||
yield return request.SendWebRequest();
|
||||
|
||||
Logger.Msg(request.result != UnityWebRequest.Result.Success ? $"Error saving achievements: {request.error}" : "Achievements saved successfully", "Achievements.SaveAllData");
|
||||
}
|
||||
}
|
||||
|
||||
public static void LoadAllData()
|
||||
{
|
||||
if (!File.Exists(SaveFilePath)) return;
|
||||
if (File.Exists(SaveFilePath))
|
||||
{
|
||||
var json = File.ReadAllText(SaveFilePath);
|
||||
CompletedAchievements = JsonSerializer.Deserialize<HashSet<Type>>(json);
|
||||
}
|
||||
else
|
||||
{
|
||||
Main.Instance.StartCoroutine(FetchAchievementsFromApiAsync());
|
||||
return;
|
||||
|
||||
var json = File.ReadAllText(SaveFilePath);
|
||||
CompletedAchievements = JsonSerializer.Deserialize<HashSet<Type>>(json);
|
||||
IEnumerator FetchAchievementsFromApiAsync()
|
||||
{
|
||||
while (PlayerControl.LocalPlayer == null) yield return null;
|
||||
|
||||
var userId = PlayerControl.LocalPlayer.GetClient().GetHashedPuid();
|
||||
var url = $"{ApiLoadEndpoint}?userId={userId}";
|
||||
|
||||
var request = UnityWebRequest.Get(url);
|
||||
yield return request.SendWebRequest();
|
||||
|
||||
if (request.result != UnityWebRequest.Result.Success) { Logger.Error($"Error loading achievements: {request.error}", "Achievements.LoadAllData"); }
|
||||
else
|
||||
{
|
||||
var json = request.downloadHandler.text;
|
||||
CompletedAchievements = JsonSerializer.Deserialize<HashSet<Type>>(json);
|
||||
yield return File.WriteAllTextAsync(SaveFilePath, json);
|
||||
Logger.Info("Achievements loaded successfully.", "Achievements.LoadAllData");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+90
-117
@@ -189,7 +189,7 @@ namespace EHR
|
||||
msg.EndMessage();
|
||||
AmongUsClient.Instance.SendOrDisconnect(msg);
|
||||
msg.Recycle();
|
||||
|
||||
|
||||
if (PlayerControl.AllPlayerControls.Contains(playerControl))
|
||||
PlayerControl.AllPlayerControls.Remove(playerControl);
|
||||
|
||||
@@ -327,7 +327,7 @@ namespace EHR
|
||||
|
||||
protected void CreateNetObject(string sprite, Vector2 position)
|
||||
{
|
||||
if (GameStates.IsEnded) return;
|
||||
if (GameStates.IsEnded || GameStates.CurrentServerType == GameStates.ServerType.Modded) return;
|
||||
Logger.Info($" Create Custom Net Object {GetType().Name} (ID {MaxId + 1}) at {position}", "CNO.CreateNetObject");
|
||||
playerControl = Object.Instantiate(AmongUsClient.Instance.PlayerPrefab, Vector2.zero, Quaternion.identity);
|
||||
playerControl.PlayerId = 255;
|
||||
@@ -480,105 +480,102 @@ namespace EHR
|
||||
AllObjects.ToArray().Do(x => x.Despawn());
|
||||
AllObjects.Clear();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.ThrowException(e);
|
||||
}
|
||||
catch (Exception e) { Utils.ThrowException(e); }
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
internal sealed class Explosion : CustomNetObject
|
||||
{
|
||||
private readonly float Duration;
|
||||
|
||||
private readonly float Size;
|
||||
private int Frame;
|
||||
private float Timer;
|
||||
|
||||
public Explosion(float size, float duration, Vector2 position)
|
||||
/*
|
||||
internal sealed class Explosion : CustomNetObject
|
||||
{
|
||||
Size = size;
|
||||
Duration = duration;
|
||||
Timer = -0.1f;
|
||||
Frame = 0;
|
||||
CreateNetObject($"<size={Size}><line-height=67%><font=\"VCR SDF\"><br><#0000>███<#ff0000>█<#0000>███<br><#ff0000>█<#0000>█<#ff0000>███<#0000>█<#ff0000>█<br>█<#ff8000>██<#ffff00>█<#ff8000>██<#ffff00>█<br>██<#ff8000>█<#ffff00>█<#ff8000>█<#ffff00>██<br><#ff8000>█<#ffff80>██<#ffff00>█<#ffff80>██<#ff8000>█<br><#0000>█<#ff8000>█<#ffff80>███<#ff8000>█<#0000>█<br>██<#ff8000>███<#0000>██", position);
|
||||
private readonly float Duration;
|
||||
|
||||
private readonly float Size;
|
||||
private int Frame;
|
||||
private float Timer;
|
||||
|
||||
public Explosion(float size, float duration, Vector2 position)
|
||||
{
|
||||
Size = size;
|
||||
Duration = duration;
|
||||
Timer = -0.1f;
|
||||
Frame = 0;
|
||||
CreateNetObject($"<size={Size}><line-height=67%><font=\"VCR SDF\"><br><#0000>███<#ff0000>█<#0000>███<br><#ff0000>█<#0000>█<#ff0000>███<#0000>█<#ff0000>█<br>█<#ff8000>██<#ffff00>█<#ff8000>██<#ffff00>█<br>██<#ff8000>█<#ffff00>█<#ff8000>█<#ffff00>██<br><#ff8000>█<#ffff80>██<#ffff00>█<#ffff80>██<#ff8000>█<br><#0000>█<#ff8000>█<#ffff80>███<#ff8000>█<#0000>█<br>██<#ff8000>███<#0000>██", position);
|
||||
}
|
||||
|
||||
protected override void OnFixedUpdate()
|
||||
{
|
||||
base.OnFixedUpdate();
|
||||
|
||||
Timer += Time.deltaTime;
|
||||
if (Timer >= Duration / 5f && Frame == 0)
|
||||
{
|
||||
RpcChangeSprite($"<size={Size}><line-height=67%><font=\"VCR SDF\"><br><#0000>█<#ff0000>█<#0000>█<#ff0000>█<#0000>█<#ff0000>█<#0000>█<br><#ff0000>█<#ff8000>█<#ff0000>█<#ff8000>█<#ff0000>█<#ff8000>█<#ff0000>█<br><#ff8000>██<#ffff00>█<#ff8000>█<#ffff00>█<#ff8000>██<br><#ffff00>███████<br><#ff8000>█<#ffff00>█████<#ff8000>█<br>██<#ffff00>█<#ff8000>█<#ffff00>█<#ff8000>██<br><#ff0000>█<#0000>█<#ff8000>█<#ff0000>█<#ff8000>█<#0000>█<#ff0000>█");
|
||||
Frame = 1;
|
||||
}
|
||||
|
||||
if (Timer >= Duration / 5f * 2f && Frame == 1)
|
||||
{
|
||||
RpcChangeSprite($"<size={Size}><line-height=67%><font=\"VCR SDF\"><br><#0000>█<#c0c0c0>█<#ff0000>█<#000000>█<#ff0000>█<#c0c0c0>█<#0000>█<br><#c0c0c0>█<#808080>█<#ff0000>█<#ff8000>█<#ff0000>█<#c0c0c0>██<br><#ff0000>██<#ff8000>█<#ffff00>█<#ff8000>█<#ff0000>██<br><#c0c0c0>█<#ff8000>█<#ffff00>█<#ffff80>█<#ffff00>█<#ff8000>█<#808080>█<br><#ff0000>██<#ff8000>█<#ffff00>█<#ff8000>█<#ff0000>██<br><#c0c0c0>█<#808080>█<#ff0000>█<#ff8000>█<#ff0000>█<#000000>█<#c0c0c0>█<br><#0000>█<#c0c0c0>█<#ff0000>█<#c0c0c0>█<#ff0000>█<#c0c0c0>█<#0000>█");
|
||||
Frame = 2;
|
||||
}
|
||||
|
||||
if (Timer >= Duration / 5f * 3f && Frame == 2)
|
||||
{
|
||||
RpcChangeSprite($"<size={Size}><line-height=67%><font=\"VCR SDF\"><br><#ff0000>█<#ff8000>█<#0000>█<#808080>█<#0000>█<#ff8000>█<#ff0000>█<br><#ff8000>█<#0000>█<#ffff00>█<#c0c0c0>█<#ffff00>█<#0000>█<#ff8000>█<br><#0000>█<#ffff00>█<#c0c0c0>███<#ffff00>█<#0000>█<br><#808080>█<#c0c0c0>█████<#808080>█<br><#0000>█<#ffff00>█<#c0c0c0>███<#ffff00>█<#0000>█<br><#ff8000>█<#0000>█<#ffff00>█<#c0c0c0>█<#ffff00>█<#0000>█<#ff8000>█<br><#ff0000>█<#ff8000>█<#0000>█<#808080>█<#0000>█<#ff8000>█<#ff0000>█");
|
||||
Frame = 3;
|
||||
}
|
||||
|
||||
if (Timer >= Duration / 5f * 4f && Frame == 3)
|
||||
{
|
||||
RpcChangeSprite($"<size={Size}><line-height=67%><font=\"VCR SDF\"><br><#0000>█<#808080>█<#0000>██<#c0c0c0>█<#0000>█<#808080>█<br><#ffff00>█<#0000>██<#c0c0c0>█<#0000>█<#808080>█<#0000>█<br>█<#808080>█<#c0c0c0>████<#0000>█<br>█<#c0c0c0>██████<br>█<#0000>█<#c0c0c0>███<#808080>█<#0000>█<br>█<#c0c0c0>█<#0000>█<#c0c0c0>█<#0000>█<#c0c0c0>██<br><#808080>█<#0000>█<#c0c0c0>█<#0000>█<#808080>█<#0000>█<#ffff00>█");
|
||||
Frame = 4;
|
||||
}
|
||||
|
||||
if (Timer >= Duration && Frame == 4)
|
||||
{
|
||||
Despawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnFixedUpdate()
|
||||
internal sealed class TrapArea : CustomNetObject
|
||||
{
|
||||
base.OnFixedUpdate();
|
||||
private readonly float Size;
|
||||
public readonly List<byte> VisibleList;
|
||||
private readonly float WaitDuration;
|
||||
private int State;
|
||||
private float Timer;
|
||||
|
||||
Timer += Time.deltaTime;
|
||||
if (Timer >= Duration / 5f && Frame == 0)
|
||||
public TrapArea(float radius, float waitDuration, Vector2 position, List<byte> visibleList)
|
||||
{
|
||||
RpcChangeSprite($"<size={Size}><line-height=67%><font=\"VCR SDF\"><br><#0000>█<#ff0000>█<#0000>█<#ff0000>█<#0000>█<#ff0000>█<#0000>█<br><#ff0000>█<#ff8000>█<#ff0000>█<#ff8000>█<#ff0000>█<#ff8000>█<#ff0000>█<br><#ff8000>██<#ffff00>█<#ff8000>█<#ffff00>█<#ff8000>██<br><#ffff00>███████<br><#ff8000>█<#ffff00>█████<#ff8000>█<br>██<#ffff00>█<#ff8000>█<#ffff00>█<#ff8000>██<br><#ff0000>█<#0000>█<#ff8000>█<#ff0000>█<#ff8000>█<#0000>█<#ff0000>█");
|
||||
Frame = 1;
|
||||
VisibleList = visibleList;
|
||||
Size = radius * 25f;
|
||||
Timer = -0.1f;
|
||||
WaitDuration = waitDuration;
|
||||
State = 0;
|
||||
CreateNetObject($"<size={Size}><font=\"VCR SDF\"><#c7c7c769>●", position);
|
||||
Main.AllAlivePlayerControls.ExceptBy(visibleList, x => x.PlayerId).Do(Hide);
|
||||
}
|
||||
|
||||
if (Timer >= Duration / 5f * 2f && Frame == 1)
|
||||
protected override void OnFixedUpdate()
|
||||
{
|
||||
RpcChangeSprite($"<size={Size}><line-height=67%><font=\"VCR SDF\"><br><#0000>█<#c0c0c0>█<#ff0000>█<#000000>█<#ff0000>█<#c0c0c0>█<#0000>█<br><#c0c0c0>█<#808080>█<#ff0000>█<#ff8000>█<#ff0000>█<#c0c0c0>██<br><#ff0000>██<#ff8000>█<#ffff00>█<#ff8000>█<#ff0000>██<br><#c0c0c0>█<#ff8000>█<#ffff00>█<#ffff80>█<#ffff00>█<#ff8000>█<#808080>█<br><#ff0000>██<#ff8000>█<#ffff00>█<#ff8000>█<#ff0000>██<br><#c0c0c0>█<#808080>█<#ff0000>█<#ff8000>█<#ff0000>█<#000000>█<#c0c0c0>█<br><#0000>█<#c0c0c0>█<#ff0000>█<#c0c0c0>█<#ff0000>█<#c0c0c0>█<#0000>█");
|
||||
Frame = 2;
|
||||
}
|
||||
base.OnFixedUpdate();
|
||||
|
||||
if (Timer >= Duration / 5f * 3f && Frame == 2)
|
||||
{
|
||||
RpcChangeSprite($"<size={Size}><line-height=67%><font=\"VCR SDF\"><br><#ff0000>█<#ff8000>█<#0000>█<#808080>█<#0000>█<#ff8000>█<#ff0000>█<br><#ff8000>█<#0000>█<#ffff00>█<#c0c0c0>█<#ffff00>█<#0000>█<#ff8000>█<br><#0000>█<#ffff00>█<#c0c0c0>███<#ffff00>█<#0000>█<br><#808080>█<#c0c0c0>█████<#808080>█<br><#0000>█<#ffff00>█<#c0c0c0>███<#ffff00>█<#0000>█<br><#ff8000>█<#0000>█<#ffff00>█<#c0c0c0>█<#ffff00>█<#0000>█<#ff8000>█<br><#ff0000>█<#ff8000>█<#0000>█<#808080>█<#0000>█<#ff8000>█<#ff0000>█");
|
||||
Frame = 3;
|
||||
}
|
||||
Timer += Time.deltaTime;
|
||||
if (Timer >= WaitDuration * 0.75f && State == 0)
|
||||
{
|
||||
RpcChangeSprite($"<size={Size}><font=\"VCR SDF\"><#fff70069>●");
|
||||
State = 1;
|
||||
}
|
||||
|
||||
if (Timer >= Duration / 5f * 4f && Frame == 3)
|
||||
{
|
||||
RpcChangeSprite($"<size={Size}><line-height=67%><font=\"VCR SDF\"><br><#0000>█<#808080>█<#0000>██<#c0c0c0>█<#0000>█<#808080>█<br><#ffff00>█<#0000>██<#c0c0c0>█<#0000>█<#808080>█<#0000>█<br>█<#808080>█<#c0c0c0>████<#0000>█<br>█<#c0c0c0>██████<br>█<#0000>█<#c0c0c0>███<#808080>█<#0000>█<br>█<#c0c0c0>█<#0000>█<#c0c0c0>█<#0000>█<#c0c0c0>██<br><#808080>█<#0000>█<#c0c0c0>█<#0000>█<#808080>█<#0000>█<#ffff00>█");
|
||||
Frame = 4;
|
||||
}
|
||||
|
||||
if (Timer >= Duration && Frame == 4)
|
||||
{
|
||||
Despawn();
|
||||
if (Timer >= WaitDuration * 0.95f && State == 1)
|
||||
{
|
||||
RpcChangeSprite($"<size={Size}><font=\"VCR SDF\"><#ff000069>●");
|
||||
State = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class TrapArea : CustomNetObject
|
||||
{
|
||||
private readonly float Size;
|
||||
public readonly List<byte> VisibleList;
|
||||
private readonly float WaitDuration;
|
||||
private int State;
|
||||
private float Timer;
|
||||
|
||||
public TrapArea(float radius, float waitDuration, Vector2 position, List<byte> visibleList)
|
||||
{
|
||||
VisibleList = visibleList;
|
||||
Size = radius * 25f;
|
||||
Timer = -0.1f;
|
||||
WaitDuration = waitDuration;
|
||||
State = 0;
|
||||
CreateNetObject($"<size={Size}><font=\"VCR SDF\"><#c7c7c769>●", position);
|
||||
Main.AllAlivePlayerControls.ExceptBy(visibleList, x => x.PlayerId).Do(Hide);
|
||||
}
|
||||
|
||||
protected override void OnFixedUpdate()
|
||||
{
|
||||
base.OnFixedUpdate();
|
||||
|
||||
Timer += Time.deltaTime;
|
||||
if (Timer >= WaitDuration * 0.75f && State == 0)
|
||||
{
|
||||
RpcChangeSprite($"<size={Size}><font=\"VCR SDF\"><#fff70069>●");
|
||||
State = 1;
|
||||
}
|
||||
|
||||
if (Timer >= WaitDuration * 0.95f && State == 1)
|
||||
{
|
||||
RpcChangeSprite($"<size={Size}><font=\"VCR SDF\"><#ff000069>●");
|
||||
State = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
internal sealed class TornadoObject : CustomNetObject
|
||||
{
|
||||
private readonly long SpawnTimeStamp;
|
||||
@@ -607,14 +604,8 @@ namespace EHR
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
try
|
||||
{
|
||||
Despawn();
|
||||
}
|
||||
finally
|
||||
{
|
||||
Gone = true;
|
||||
}
|
||||
try { Despawn(); }
|
||||
finally { Gone = true; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -782,32 +773,14 @@ internal static class RawSetNamePatch
|
||||
|
||||
var exception = false;
|
||||
|
||||
try
|
||||
{
|
||||
__instance.gameObject.name = name;
|
||||
}
|
||||
catch
|
||||
{
|
||||
exception = true;
|
||||
}
|
||||
try { __instance.gameObject.name = name; }
|
||||
catch { exception = true; }
|
||||
|
||||
try
|
||||
{
|
||||
__instance.cosmetics.SetName(name);
|
||||
}
|
||||
catch
|
||||
{
|
||||
exception = true;
|
||||
}
|
||||
try { __instance.cosmetics.SetName(name); }
|
||||
catch { exception = true; }
|
||||
|
||||
try
|
||||
{
|
||||
__instance.cosmetics.SetNameMask(true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
exception = true;
|
||||
}
|
||||
try { __instance.cosmetics.SetNameMask(true); }
|
||||
catch { exception = true; }
|
||||
|
||||
LateTask.New(() =>
|
||||
{
|
||||
|
||||
@@ -1508,6 +1508,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Generator => RoleOptionType.Impostor_Miscellaneous,
|
||||
CustomRoles.Visionary => RoleOptionType.Impostor_Miscellaneous,
|
||||
CustomRoles.Wildling => RoleOptionType.Impostor_Miscellaneous,
|
||||
CustomRoles.DoubleAgent => RoleOptionType.Crewmate_Investigate,
|
||||
_ => role.IsCrewmate() ? RoleOptionType.Crewmate_Miscellaneous : RoleOptionType.Neutral_Benign
|
||||
};
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ public static class DevManager
|
||||
{
|
||||
private static readonly TagInfo DefaultDevUser = new();
|
||||
|
||||
private static int Attempts;
|
||||
|
||||
private static Dictionary<string, TagInfo> Tags { get; set; } = [];
|
||||
|
||||
public static TagInfo GetDevUser(this string code)
|
||||
@@ -20,8 +22,6 @@ public static class DevManager
|
||||
return Tags.GetValueOrDefault(code, DefaultDevUser);
|
||||
}
|
||||
|
||||
private static int Attempts;
|
||||
|
||||
private static IEnumerator FetchTags()
|
||||
{
|
||||
Attempts++;
|
||||
@@ -31,7 +31,7 @@ public static class DevManager
|
||||
Logger.Error($"Failed to fetch tags after {Attempts - 1} attempts.", "DevManager.FetchTags");
|
||||
yield break;
|
||||
}
|
||||
|
||||
|
||||
UnityWebRequest request = UnityWebRequest.Get("https://gurge44.pythonanywhere.com/get_all_tags");
|
||||
yield return request.SendWebRequest();
|
||||
|
||||
@@ -72,6 +72,6 @@ public static class DevManager
|
||||
|
||||
public bool HasTag() => !string.IsNullOrEmpty(tag_name);
|
||||
|
||||
public string GetTag() => !HasTag() ? "" : $"<size=1.4><color={tag_color}>{tag_name}</color></size>\r\n";
|
||||
public string GetTag() => !HasTag() ? "" : $"<size=1.5><color={tag_color}>{tag_name}</color></size>\r\n";
|
||||
}
|
||||
}
|
||||
+23
-7
@@ -78,10 +78,10 @@ public class PlayerState(byte playerId)
|
||||
private readonly byte PlayerId = playerId;
|
||||
public readonly List<CustomRoles> SubRoles = [];
|
||||
public readonly Dictionary<byte, string> TargetColorData = [];
|
||||
public NetworkedPlayerInfo.PlayerOutfit NormalOutfit;
|
||||
public CountTypes countTypes = CountTypes.Crew;
|
||||
public PlainShipRoom LastRoom;
|
||||
public CustomRoles MainRole = CustomRoles.NotAssigned;
|
||||
public NetworkedPlayerInfo.PlayerOutfit NormalOutfit;
|
||||
public (DateTime TimeStamp, byte ID) RealKiller = (DateTime.MinValue, byte.MaxValue);
|
||||
public RoleBase Role = new VanillaRole();
|
||||
|
||||
@@ -502,6 +502,14 @@ public class PlayerVersion(Version ver, string tagStr, string forkId)
|
||||
|
||||
public static class GameStates
|
||||
{
|
||||
public enum ServerType
|
||||
{
|
||||
Vanilla,
|
||||
Modded,
|
||||
Niko,
|
||||
Custom
|
||||
}
|
||||
|
||||
public static bool InGame;
|
||||
public static bool AlreadyDied;
|
||||
public static bool IsModHost => PlayerControl.AllPlayerControls.ToArray().Any(x => x.IsHost() && x.IsModClient());
|
||||
@@ -518,18 +526,26 @@ public static class GameStates
|
||||
|
||||
public static bool IsCountDown => GameStartManager.InstanceExists && GameStartManager.Instance.startState == GameStartManager.StartingStates.Countdown;
|
||||
|
||||
public static bool IsVanillaServer
|
||||
public static ServerType CurrentServerType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsLocalGame && !IsNotJoined) return true;
|
||||
if (IsLocalGame && !IsNotJoined) return ServerType.Vanilla;
|
||||
|
||||
const string domain = "among.us";
|
||||
|
||||
// From Reactor.gg
|
||||
return ServerManager.Instance.CurrentRegion?.TryCast<StaticHttpRegionInfo>() is { } regionInfo &&
|
||||
regionInfo.PingServer.EndsWith(domain, StringComparison.Ordinal) &&
|
||||
regionInfo.Servers.All(serverInfo => serverInfo.Ip.EndsWith(domain, StringComparison.Ordinal));
|
||||
if (ServerManager.Instance.CurrentRegion?.TryCast<StaticHttpRegionInfo>() is { } regionInfo &&
|
||||
regionInfo.PingServer.EndsWith(domain, StringComparison.Ordinal) &&
|
||||
regionInfo.Servers.All(serverInfo => serverInfo.Ip.EndsWith(domain, StringComparison.Ordinal)))
|
||||
return ServerType.Vanilla;
|
||||
|
||||
string regionName = Utils.GetRegionName();
|
||||
|
||||
if (regionName.Contains("Niko", StringComparison.OrdinalIgnoreCase)) return ServerType.Niko;
|
||||
if (regionName.StartsWith('M') && regionName.Length == 3) return ServerType.Modded;
|
||||
|
||||
return ServerType.Custom;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -550,4 +566,4 @@ public static class MeetingStates
|
||||
public static bool IsExistDeadBody => DeadBodies.Length > 0;
|
||||
|
||||
public static NetworkedPlayerInfo ReportTarget { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace EHR.Modules;
|
||||
|
||||
public static class Prompt
|
||||
{
|
||||
private static readonly List<(string Question, Action OnYes, Action OnNo)> Queue = [];
|
||||
|
||||
private static SimpleButton YesButton;
|
||||
private static SimpleButton NoButton;
|
||||
private static string CurrentQuestion = string.Empty;
|
||||
|
||||
public static void Show(string question, Action onYes, Action onNo)
|
||||
{
|
||||
try
|
||||
{
|
||||
HudManager hud = DestroyableSingleton<HudManager>.Instance;
|
||||
|
||||
if (CurrentQuestion != string.Empty || !hud)
|
||||
{
|
||||
if (Queue.All(x => x.Question != question) && CurrentQuestion != question)
|
||||
Queue.Add((question, onYes, onNo));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
CurrentQuestion = question;
|
||||
hud.ShowPopUp(question);
|
||||
|
||||
Action closePromt = () =>
|
||||
{
|
||||
HidePromt();
|
||||
|
||||
CurrentQuestion = string.Empty;
|
||||
hud.Dialogue.Hide();
|
||||
|
||||
if (Queue.Count > 0)
|
||||
{
|
||||
(string q, Action y, Action n) = Queue[0];
|
||||
Queue.RemoveAt(0);
|
||||
LateTask.New(() => Show(q, y, n), 0.01f, log: false);
|
||||
}
|
||||
};
|
||||
|
||||
onYes += closePromt;
|
||||
onNo += closePromt;
|
||||
|
||||
YesButton = new SimpleButton(
|
||||
hud.Dialogue.transform,
|
||||
"PromtYesButton",
|
||||
new(1f, -1.25f),
|
||||
new(0, 255, 165, 255),
|
||||
new(0, 255, 255, 255),
|
||||
onYes,
|
||||
Translator.GetString("Yes"));
|
||||
|
||||
NoButton = new SimpleButton(
|
||||
hud.Dialogue.transform,
|
||||
"PromtNoButton",
|
||||
new(-1f, -1.25f),
|
||||
new(0, 165, 255, 255),
|
||||
new(0, 255, 255, 255),
|
||||
onNo,
|
||||
Translator.GetString("No"));
|
||||
}
|
||||
catch (Exception e) { Utils.ThrowException(e); }
|
||||
}
|
||||
|
||||
private static void HidePromt()
|
||||
{
|
||||
Object.Destroy(YesButton?.Button.gameObject);
|
||||
Object.Destroy(NoButton?.Button.gameObject);
|
||||
|
||||
YesButton = null;
|
||||
NoButton = null;
|
||||
}
|
||||
|
||||
public static void ClearQueue()
|
||||
{
|
||||
Queue.Clear();
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(DialogueBox), nameof(DialogueBox.Hide))]
|
||||
static class DialogueBoxHidePatch
|
||||
{
|
||||
public static void Prefix()
|
||||
{
|
||||
if (CurrentQuestion != string.Empty)
|
||||
{
|
||||
ClearQueue();
|
||||
HidePromt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3306,6 +3306,46 @@ public static class Utils
|
||||
return name;
|
||||
}
|
||||
|
||||
public static void EnterQuickSetupRoles(bool addons)
|
||||
{
|
||||
int all = Options.CustomRoleSpawnChances.Keys.Count(x => addons ? x.IsAdditionRole() : !x.IsAdditionRole());
|
||||
int count = 0;
|
||||
|
||||
foreach ((CustomRoles role, StringOptionItem option) in Options.CustomRoleSpawnChances)
|
||||
{
|
||||
if (addons ? !role.IsAdditionRole() : role.IsAdditionRole() || role.IsVanilla() || role.IsForOtherGameMode()) continue;
|
||||
|
||||
count++;
|
||||
|
||||
string str = GetString($"{role}InfoLong");
|
||||
string infoLong;
|
||||
|
||||
try { infoLong = HnSManager.AllHnSRoles.Contains(role) ? str : str[(str.IndexOf('\n') + 1)..str.Split("\n\n")[0].Length]; }
|
||||
catch { infoLong = str; }
|
||||
|
||||
string rotStr;
|
||||
|
||||
if (!role.IsAdditionRole())
|
||||
{
|
||||
RoleOptionType rot = role.GetRoleOptionType();
|
||||
rotStr = ColorString(rot.GetRoleOptionTypeColor(), GetString($"ROT.{rot}"));
|
||||
}
|
||||
else
|
||||
{
|
||||
AddonTypes at = Options.GroupedAddons.First(x => x.Value.Contains(role)).Key;
|
||||
rotStr = ColorString(at.GetAddonTypeColor(), GetString($"ROT.AddonType.{at}"));
|
||||
}
|
||||
|
||||
Prompt.Show(
|
||||
string.Format(GetString("Promt.EnableRole"), count, all, rotStr, role.ToColoredString(), infoLong),
|
||||
() => option.SetValue(1),
|
||||
() => option.SetValue(0));
|
||||
}
|
||||
|
||||
if (addons) return;
|
||||
Prompt.Show(GetString("Promt.ContinueWithQuickSetupAddons"), () => EnterQuickSetupRoles(true), () => { });
|
||||
}
|
||||
|
||||
private static int PlayersCount(CountTypes countTypes)
|
||||
{
|
||||
var count = 0;
|
||||
|
||||
@@ -335,7 +335,7 @@ internal static class ChatCommands
|
||||
|
||||
private static void CheckAnagramGuess(byte id, string text)
|
||||
{
|
||||
if (text.Contains(CurrentAnagram))
|
||||
if (CurrentAnagram != string.Empty && text.Contains(CurrentAnagram))
|
||||
{
|
||||
Utils.SendMessage("\n", title: string.Format(GetString("Anagram.CorrectGuess"), id.ColoredPlayerName(), CurrentAnagram));
|
||||
CurrentAnagram = string.Empty;
|
||||
@@ -504,7 +504,7 @@ internal static class ChatCommands
|
||||
if (!player.Is(CustomRoles.NoteKiller) || args.Length < 2) return;
|
||||
|
||||
if (!player.IsLocalPlayer()) ChatManager.SendPreviousMessagesToAll();
|
||||
|
||||
|
||||
if (!NoteKiller.CanGuess)
|
||||
{
|
||||
Utils.SendMessage(GetString("DeathNoteCommand.CanNotGuess"), player.PlayerId);
|
||||
@@ -560,7 +560,10 @@ internal static class ChatCommands
|
||||
|
||||
private static void EnableAllRolesCommand(ChatController __instance, PlayerControl player, string text, string[] args)
|
||||
{
|
||||
Options.CustomRoleSpawnChances.Values.DoIf(x => x.GetValue() == 0, x => x.SetValue(1));
|
||||
Prompt.Show(
|
||||
GetString("Promt.EnableAllRoles"),
|
||||
() => Options.CustomRoleSpawnChances.Values.DoIf(x => x.GetValue() == 0, x => x.SetValue(1)),
|
||||
() => Utils.EnterQuickSetupRoles(false));
|
||||
}
|
||||
|
||||
private static void ReadyCheckCommand(ChatController __instance, PlayerControl player, string text, string[] args)
|
||||
@@ -1717,10 +1720,7 @@ internal static class ChatCommands
|
||||
Utils.SendMessage("\n", player.PlayerId, string.Format(GetString("RoleSelected"), resultId.ColoredPlayerName(), roleToSet.ToColoredString()));
|
||||
|
||||
if (roleToSet.OnlySpawnsWithPets() && !Options.UsePets.GetBool())
|
||||
{
|
||||
Options.UsePets.SetValue(1);
|
||||
Utils.SendMessage(GetString("SetRoleUsePetsMessage"), player.PlayerId);
|
||||
}
|
||||
Prompt.Show(GetString("Promt.SetRoleRequiresPets"), () => Options.UsePets.SetValue(1), () => { });
|
||||
}
|
||||
|
||||
private static void UpCommand(ChatController __instance, PlayerControl player, string text, string[] args)
|
||||
|
||||
+8
-29
@@ -173,10 +173,7 @@ public class InnerNetClientPatch
|
||||
{
|
||||
GameManager gameManager = innerNetObject as GameManager;
|
||||
|
||||
if (gameManager != null)
|
||||
{
|
||||
__instance.SendGameManager(clientId, gameManager);
|
||||
}
|
||||
if (gameManager != null) { __instance.SendGameManager(clientId, gameManager); }
|
||||
else
|
||||
{
|
||||
if (innerNetObject is not NetworkedPlayerInfo)
|
||||
@@ -211,10 +208,7 @@ public class InnerNetClientPatch
|
||||
{
|
||||
if (messageWriter.Length > 500) break;
|
||||
|
||||
if (player != null && player.ClientId != clientId && !player.Disconnected)
|
||||
{
|
||||
__instance.WriteSpawnMessage(player, player.OwnerId, player.SpawnFlags, messageWriter);
|
||||
}
|
||||
if (player != null && player.ClientId != clientId && !player.Disconnected) { __instance.WriteSpawnMessage(player, player.OwnerId, player.SpawnFlags, messageWriter); }
|
||||
|
||||
players.Remove(player);
|
||||
}
|
||||
@@ -247,19 +241,10 @@ public class InnerNetClientPatch
|
||||
|
||||
try
|
||||
{
|
||||
if (innerNetObject.Serialize(messageWriter, false))
|
||||
{
|
||||
messageWriter.EndMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
messageWriter.CancelMessage();
|
||||
}
|
||||
if (innerNetObject.Serialize(messageWriter, false)) { messageWriter.EndMessage(); }
|
||||
else { messageWriter.CancelMessage(); }
|
||||
|
||||
if (innerNetObject.Chunked && innerNetObject.IsDirty)
|
||||
{
|
||||
__result = true;
|
||||
}
|
||||
if (innerNetObject.Chunked && innerNetObject.IsDirty) { __result = true; }
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -340,10 +325,7 @@ public class InnerNetClientPatch
|
||||
}
|
||||
}
|
||||
|
||||
if (!__instance.AmHost)
|
||||
{
|
||||
Debug.LogError("Tried to spawn while not host:" + (netObjParent?.ToString()));
|
||||
}
|
||||
if (!__instance.AmHost) { Debug.LogError("Tried to spawn while not host:" + (netObjParent?.ToString())); }
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(InnerNetClient), nameof(InnerNetClient.FixedUpdate))]
|
||||
@@ -372,10 +354,7 @@ public class InnerNetClientPatch
|
||||
|
||||
try
|
||||
{
|
||||
if (player.Serialize(messageWriter, false))
|
||||
{
|
||||
messageWriter.EndMessage();
|
||||
}
|
||||
if (player.Serialize(messageWriter, false)) { messageWriter.EndMessage(); }
|
||||
else
|
||||
{
|
||||
messageWriter.CancelMessage();
|
||||
@@ -417,7 +396,7 @@ internal static class AuthTimeoutPatch
|
||||
// https://github.com/NuclearPowered/Reactor/blob/master/Reactor/Patches/Miscellaneous/CustomServersPatch.cs
|
||||
public static bool CoWaitforNoncePrefix(ref bool __result)
|
||||
{
|
||||
if (GameStates.IsVanillaServer) return true;
|
||||
if (GameStates.CurrentServerType == GameStates.ServerType.Vanilla) return true;
|
||||
|
||||
__result = false;
|
||||
return false;
|
||||
|
||||
+28
-10
@@ -126,22 +126,40 @@ internal static class ControllerManagerUpdatePatch
|
||||
Utils.ShowActiveSettings();
|
||||
}
|
||||
|
||||
if (KeysDown(KeyCode.Delete, KeyCode.LeftControl, KeyCode.LeftShift) && !IsResetting)
|
||||
if (GameStates.IsLobby && KeysDown(KeyCode.Delete, KeyCode.LeftControl, KeyCode.LeftShift) && !IsResetting)
|
||||
{
|
||||
IsResetting = true;
|
||||
Main.Instance.StartCoroutine(Reset());
|
||||
Prompt.Show(GetString("Promt.ResetAllOptions"), ResetAllOptions, () => { });
|
||||
|
||||
IEnumerator Reset()
|
||||
void ResetAllOptions()
|
||||
{
|
||||
for (var index = 0; index < OptionItem.AllOptions.Count; index++)
|
||||
IsResetting = true;
|
||||
Main.Instance.StartCoroutine(Reset());
|
||||
return;
|
||||
|
||||
IEnumerator Reset()
|
||||
{
|
||||
OptionItem option = OptionItem.AllOptions[index];
|
||||
if (option.Id > 0) option.SetValue(option.DefaultValue);
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
|
||||
if (index % 100 == 0) yield return null;
|
||||
DestroyableSingleton<HudManager>.Instance.ShowPopUp(string.Format(GetString("ResettingOptions"), 0, OptionItem.AllOptions.Count));
|
||||
DestroyableSingleton<HudManager>.Instance.Dialogue.BackButton.gameObject.SetActive(false);
|
||||
|
||||
for (var index = 0; index < OptionItem.AllOptions.Count; index++)
|
||||
{
|
||||
OptionItem option = OptionItem.AllOptions[index];
|
||||
if (option.Id > 0) option.SetValue(option.DefaultValue);
|
||||
|
||||
if (index % 10 == 0)
|
||||
{
|
||||
DestroyableSingleton<HudManager>.Instance.Dialogue.target.text = string.Format(GetString("ResettingOptions"), index, OptionItem.AllOptions.Count);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
DestroyableSingleton<HudManager>.Instance.Dialogue.BackButton.gameObject.SetActive(true);
|
||||
DestroyableSingleton<HudManager>.Instance.Dialogue.Hide();
|
||||
|
||||
IsResetting = false;
|
||||
}
|
||||
|
||||
IsResetting = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -17,7 +17,7 @@ internal static class Crowded
|
||||
{
|
||||
private static CreateOptionsPicker Instance;
|
||||
public static readonly int MaxImpostors = GameOptionsManager.Instance.currentHostOptions.MaxPlayers / 2;
|
||||
private static int MaxPlayers => GameStates.IsVanillaServer ? 15 : 127;
|
||||
private static int MaxPlayers => GameStates.CurrentServerType == GameStates.ServerType.Vanilla ? 15 : 127;
|
||||
|
||||
[HarmonyPatch(typeof(CreateOptionsPicker), nameof(CreateOptionsPicker.Awake))]
|
||||
public static class CreateOptionsPickerAwake
|
||||
@@ -27,7 +27,7 @@ internal static class Crowded
|
||||
{
|
||||
Instance = __instance;
|
||||
|
||||
if (GameStates.IsVanillaServer)
|
||||
if (GameStates.CurrentServerType == GameStates.ServerType.Vanilla)
|
||||
{
|
||||
if (GameOptionsManager.Instance.GameHostOptions != null)
|
||||
{
|
||||
@@ -158,7 +158,7 @@ internal static class Crowded
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
public static void Postfix()
|
||||
{
|
||||
if (GameStates.IsVanillaServer)
|
||||
if (GameStates.CurrentServerType == GameStates.ServerType.Vanilla)
|
||||
{
|
||||
if (GameOptionsManager.Instance.GameHostOptions != null && GameOptionsManager.Instance.GameHostOptions.MaxPlayers > 15)
|
||||
GameOptionsManager.Instance.GameHostOptions.SetInt(Int32OptionNames.MaxPlayers, 15);
|
||||
|
||||
@@ -647,9 +647,18 @@ public static class StringOptionPatch
|
||||
if (role.ToString().Contains("GuardianAngel")) role = CustomRoles.GA;
|
||||
|
||||
name = name.RemoveHtmlTags();
|
||||
if (Options.UsePets.GetBool() && role.PetActivatedAbility()) name += Translator.GetString("SupportsPetIndicator");
|
||||
if (!Options.UsePets.GetBool() && role.OnlySpawnsWithPets()) name += Translator.GetString("RequiresPetIndicator");
|
||||
if (role.IsExperimental()) name += Translator.GetString("ExperimentalRoleIndicator");
|
||||
|
||||
switch (Options.UsePets.GetBool())
|
||||
{
|
||||
case false when role.OnlySpawnsWithPets():
|
||||
name += Translator.GetString("RequiresPetIndicator");
|
||||
break;
|
||||
case true when role.PetActivatedAbility():
|
||||
name += Translator.GetString("SupportsPetIndicator");
|
||||
break;
|
||||
}
|
||||
|
||||
if (role.IsExperimental()) name += $"<size=2>{Translator.GetString("ExperimentalRoleIndicator")}</size>";
|
||||
if (role.IsGhostRole()) name += GetGhostRoleTeam(role);
|
||||
|
||||
__instance.TitleText.fontWeight = FontWeight.Black;
|
||||
@@ -751,9 +760,19 @@ public static class StringOptionPatch
|
||||
if (role.ToString().Contains("GuardianAngel")) role = CustomRoles.GA;
|
||||
|
||||
name = name.RemoveHtmlTags();
|
||||
if (Options.UsePets.GetBool() && role.PetActivatedAbility()) name += Translator.GetString("SupportsPetIndicator");
|
||||
if (!Options.UsePets.GetBool() && role.OnlySpawnsWithPets()) name += Translator.GetString("RequiresPetIndicator");
|
||||
if (role.IsExperimental()) name += Translator.GetString("ExperimentalRoleIndicator");
|
||||
|
||||
switch (Options.UsePets.GetBool())
|
||||
{
|
||||
case true when role.PetActivatedAbility():
|
||||
name += Translator.GetString("SupportsPetIndicator");
|
||||
break;
|
||||
case false when role.OnlySpawnsWithPets():
|
||||
name += Translator.GetString("RequiresPetIndicator");
|
||||
Prompt.Show(Translator.GetString("Promt.RequiresPets"), () => Options.UsePets.SetValue(1), () => { });
|
||||
break;
|
||||
}
|
||||
|
||||
if (role.IsExperimental()) name += $"<size=2>{Translator.GetString("ExperimentalRoleIndicator")}</size>";
|
||||
if (role.IsGhostRole()) name += GetGhostRoleTeam(role);
|
||||
|
||||
__instance.TitleText.fontWeight = FontWeight.Black;
|
||||
@@ -1251,7 +1270,7 @@ public class GameSettingMenuPatch
|
||||
ModSettingsButtons = [];
|
||||
ModSettingsTabs = [];
|
||||
|
||||
if ((CustomGameMode.NaturalDisasters.IsActiveOrIntegrated() || CustomGameMode.CaptureTheFlag.IsActiveOrIntegrated()) && !GameStates.IsVanillaServer && GameOptionsMenuPatch.UIReloadTS + 1 < Utils.TimeStamp)
|
||||
if ((CustomGameMode.NaturalDisasters.IsActiveOrIntegrated() || CustomGameMode.CaptureTheFlag.IsActiveOrIntegrated()) && GameStates.CurrentServerType == GameStates.ServerType.Modded && GameOptionsMenuPatch.UIReloadTS + 1 < Utils.TimeStamp)
|
||||
DestroyableSingleton<HudManager>.Instance.ShowPopUp(Translator.GetString("ModdedServerDoesntSupportCNOMessage"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ internal static class OnGameJoinedPatch
|
||||
{
|
||||
JoiningGame = false;
|
||||
|
||||
if (GameStates.IsOnlineGame && GameStates.IsVanillaServer)
|
||||
if (GameStates.IsOnlineGame && GameStates.CurrentServerType is GameStates.ServerType.Vanilla or GameStates.ServerType.Niko)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -371,7 +371,7 @@ internal static class InnerNetClientSpawnPatch
|
||||
{
|
||||
LateTask.New(() =>
|
||||
{
|
||||
if (GameStates.IsLobby && client.Character != null && LobbyBehaviour.Instance != null && GameStates.IsVanillaServer)
|
||||
if (GameStates.IsLobby && client.Character != null && LobbyBehaviour.Instance != null && GameStates.CurrentServerType == GameStates.ServerType.Vanilla)
|
||||
{
|
||||
// Only for vanilla
|
||||
if (!client.Character.IsModClient())
|
||||
|
||||
@@ -3013,6 +3013,12 @@
|
||||
"Back": "Back",
|
||||
"Yes": "Yes",
|
||||
"No": "No",
|
||||
"ResettingOptions": "Resetting Options, hold on.... {0}/{1}",
|
||||
"Promt.EnableRole": "<size=60%>({0}/{1}) {2}\\n</size><size=80%>Enable {3}?</size><size=60%>\\n\\n{4}</size>",
|
||||
"Promt.RequiresPets": "You've enabled a role that requires additional ability triggers (pet/vanish button/unshift button). Would you like to enable the use of the Pet button (setting in Game Modifiers)?",
|
||||
"Promt.ResetAllOptions": "Are you sure you want to reset all options? This action is irreversible and may take few minutes.",
|
||||
"Promt.EnableAllRoles": "Enable all roles and add-ons?<size=80%>\\n\\n<b>Yes</b> - Enable all roles and add-ons\\n<b>No</b> - Enter the quick setup dialog of roles and add-ons</size>",
|
||||
"Promt.ContinueWithQuickSetupAddons": "<b><#00ffa5>You've finished setting up every role!</color></b> Would you like to continue with the quick setup dialog of add-ons?",
|
||||
"RpcAntiBlackOutIgnored": "Because of <b>{0}</b>, an unknown error occurred, RPC will be ignored.",
|
||||
"RpcAntiBlackOutEndGame": "Because of <b>{0}</b>, an unknown error occurred, game will end to prevent black screen.",
|
||||
"RpcAntiBlackOutNotifyInLobby": "Because of <b>{0}</b>, an unknown error occurred, to prevent black screen, turn off [{1}] in settings.",
|
||||
|
||||
@@ -61,6 +61,12 @@ public class Duellist : RoleBase
|
||||
{
|
||||
if (Main.KillTimers[duellist.PlayerId] < 1f) duellist.SetKillCooldown(1f); // Give the other player a chance to kill
|
||||
|
||||
if (DuelPair.TryGetValue(duellist.PlayerId, out var previousTargetId))
|
||||
{
|
||||
var previousTarget = GetPlayerById(previousTargetId);
|
||||
if (previousTarget != null) previousTarget.TPToRandomVent();
|
||||
}
|
||||
|
||||
duellist.TP(pos);
|
||||
DuelPair[duellist.PlayerId] = target.PlayerId;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user