1.2.3.b2
This commit is contained in:
parent
0e86f54e0a
commit
98f6e65b01
98 changed files with 3391 additions and 397 deletions
|
|
@ -65,6 +65,12 @@ namespace src.utils
|
|||
|
||||
public static int GetTrackedCount(uint playerIndex) => GetPlayerEntities(playerIndex).Count;
|
||||
|
||||
public static uint? GetEntityOwner(uint entityIndex)
|
||||
{
|
||||
if (!trackedEntities.TryGetValue(entityIndex, out var data)) return null;
|
||||
return data.PlayerIndex == SystemOwnerIndex ? null : data.PlayerIndex;
|
||||
}
|
||||
|
||||
public static (int totalTracked, int ownerCount) GetStatistics()
|
||||
{
|
||||
return (trackedEntities.Count, trackedEntities.Values.Select(e => e.PlayerIndex).Distinct().Count());
|
||||
|
|
|
|||
|
|
@ -22,10 +22,33 @@ namespace src.utils
|
|||
|
||||
private static string defaultLangCode = "en";
|
||||
|
||||
private static readonly Dictionary<Skills, string> skillKeys = BuildSkillKeys("");
|
||||
private static readonly Dictionary<Skills, string> skillDescKeys = BuildSkillKeys("_desc");
|
||||
private static readonly Dictionary<Skills, string> skillDesc2Keys = BuildSkillKeys("_desc2");
|
||||
|
||||
private static Dictionary<Skills, string> BuildSkillKeys(string suffix)
|
||||
{
|
||||
var map = new Dictionary<Skills, string>();
|
||||
foreach (Skills skill in Enum.GetValues<Skills>())
|
||||
map[skill] = skill.ToString().ToLowerInvariant() + suffix;
|
||||
return map;
|
||||
}
|
||||
|
||||
private static string SkillKey(Skills skill) => skillKeys.TryGetValue(skill, out var k) ? k : skill.ToString().ToLowerInvariant();
|
||||
private static string SkillDescKey(Skills skill) => skillDescKeys.TryGetValue(skill, out var k) ? k : skill.ToString().ToLowerInvariant() + "_desc";
|
||||
private static string SkillDesc2Key(Skills skill) => skillDesc2Keys.TryGetValue(skill, out var k) ? k : skill.ToString().ToLowerInvariant() + "_desc2";
|
||||
|
||||
private static readonly ConcurrentDictionary<(Skills Skill, string Lang, double Chance), string> _skillNameCache = [];
|
||||
private static readonly ConcurrentDictionary<(Skills Skill, string Lang, double Chance), string> _skillDescCache = [];
|
||||
|
||||
private const double NoChance = double.NegativeInfinity;
|
||||
|
||||
public static void Load()
|
||||
{
|
||||
_translations.Clear();
|
||||
_playersLanguage.Clear();
|
||||
_skillNameCache.Clear();
|
||||
_skillDescCache.Clear();
|
||||
SetLangCode();
|
||||
LoadAllLanguages();
|
||||
LoadPlayersLanguage();
|
||||
|
|
@ -77,9 +100,26 @@ namespace src.utils
|
|||
public static string GetSkillName(this CCSPlayerController player, Skills skill, float? chance = null)
|
||||
{
|
||||
string langCode = GetLangCode(player);
|
||||
|
||||
bool cacheable = !Illiterate.CheckIlliterateSkill(player);
|
||||
var cacheKey = (skill, langCode, chance == null ? NoChance : Math.Round((double)chance, 2));
|
||||
|
||||
if (cacheable && _skillNameCache.TryGetValue(cacheKey, out var cached))
|
||||
return cached;
|
||||
|
||||
string result = BuildSkillName(player, skill, chance, langCode);
|
||||
|
||||
if (cacheable)
|
||||
_skillNameCache[cacheKey] = result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string BuildSkillName(CCSPlayerController player, Skills skill, float? chance, string langCode)
|
||||
{
|
||||
if (chance == null)
|
||||
{
|
||||
var translation = GetTranslation(skill.ToString().ToLowerInvariant(), langCode);
|
||||
var translation = GetTranslation(SkillKey(skill), langCode);
|
||||
if (!translation.Contains("{0}"))
|
||||
return translation;
|
||||
|
||||
|
|
@ -92,7 +132,7 @@ namespace src.utils
|
|||
}
|
||||
|
||||
var value = Math.Round((double)(chance ?? 1), 2);
|
||||
var skillNameText = GetTranslation(skill.ToString().ToLowerInvariant(), langCode, player, value);
|
||||
var skillNameText = GetTranslation(SkillKey(skill), langCode, player, value);
|
||||
if (skillNameText.Contains('%')) skillNameText = skillNameText.Replace(value.ToString(), Math.Round(value * 100, 0).ToString());
|
||||
return skillNameText;
|
||||
}
|
||||
|
|
@ -100,9 +140,26 @@ namespace src.utils
|
|||
public static string GetSkillDescription(this CCSPlayerController player, Skills skill, float? chance = null)
|
||||
{
|
||||
string langCode = GetLangCode(player);
|
||||
|
||||
bool cacheable = !Illiterate.CheckIlliterateSkill(player);
|
||||
var cacheKey = (skill, langCode, chance == null ? NoChance : Math.Round((double)chance, 2));
|
||||
|
||||
if (cacheable && _skillDescCache.TryGetValue(cacheKey, out var cached))
|
||||
return cached;
|
||||
|
||||
string result = BuildSkillDescription(player, skill, chance, langCode);
|
||||
|
||||
if (cacheable)
|
||||
_skillDescCache[cacheKey] = result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string BuildSkillDescription(CCSPlayerController player, Skills skill, float? chance, string langCode)
|
||||
{
|
||||
if (chance == null)
|
||||
{
|
||||
var translation = GetTranslation($"{skill.ToString().ToLowerInvariant()}_desc", langCode);
|
||||
var translation = GetTranslation(SkillDescKey(skill), langCode);
|
||||
if (!translation.Contains("{0}"))
|
||||
return translation;
|
||||
|
||||
|
|
@ -114,12 +171,12 @@ namespace src.utils
|
|||
return string.Join(' ', filtered);
|
||||
}
|
||||
|
||||
var skillName = $"{skill.ToString().ToLowerInvariant()}_desc2";
|
||||
var skillName = SkillDesc2Key(skill);
|
||||
var value = Math.Round((double)(chance ?? 1), 2);
|
||||
var desc2 = GetTranslation(skillName, langCode, player, value);
|
||||
|
||||
var skilLDescription = desc2 == skillName
|
||||
? player.GetTranslation($"{skill.ToString().ToLowerInvariant()}_desc")
|
||||
? player.GetTranslation(SkillDescKey(skill))
|
||||
: desc2.Contains('%') ? desc2.Replace(value.ToString(), Math.Round(value * 100, 0).ToString()) : desc2;
|
||||
return skilLDescription;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ namespace src.utils
|
|||
|
||||
private static int cachedTick = int.MinValue;
|
||||
private static List<CCSPlayerController> cachedControllers = [];
|
||||
|
||||
private static int cachedBombTick = int.MinValue;
|
||||
private static CC4? cachedBomb;
|
||||
|
||||
private static void EnsureTickCache()
|
||||
|
|
@ -20,7 +22,6 @@ namespace src.utils
|
|||
if (tick == cachedTick) return;
|
||||
cachedTick = tick;
|
||||
cachedControllers = Utilities.GetPlayers();
|
||||
cachedBomb = Utilities.FindAllEntitiesByDesignerName<CC4>("weapon_c4").FirstOrDefault();
|
||||
}
|
||||
|
||||
public static List<CCSPlayerController> GetTickPlayers()
|
||||
|
|
@ -31,7 +32,13 @@ namespace src.utils
|
|||
|
||||
public static CC4? GetTickBomb()
|
||||
{
|
||||
EnsureTickCache();
|
||||
int tick = Server.TickCount;
|
||||
if (tick != cachedBombTick)
|
||||
{
|
||||
cachedBombTick = tick;
|
||||
cachedBomb = Utilities.FindAllEntitiesByDesignerName<CC4>("weapon_c4").FirstOrDefault();
|
||||
}
|
||||
|
||||
return cachedBomb != null && cachedBomb.IsValid ? cachedBomb : null;
|
||||
}
|
||||
|
||||
|
|
@ -62,7 +69,7 @@ namespace src.utils
|
|||
if (!player.ControllingBot)
|
||||
return player;
|
||||
|
||||
return Utilities.GetPlayers().FirstOrDefault(p =>
|
||||
return GetTickPlayers().FirstOrDefault(p =>
|
||||
p != null &&
|
||||
p.IsValid &&
|
||||
p.IsBot &&
|
||||
|
|
@ -78,7 +85,7 @@ namespace src.utils
|
|||
if (!player.IsBot)
|
||||
return player;
|
||||
|
||||
return Utilities.GetPlayers().FirstOrDefault(p =>
|
||||
return GetTickPlayers().FirstOrDefault(p =>
|
||||
p != null &&
|
||||
p.IsValid &&
|
||||
!p.IsBot &&
|
||||
|
|
@ -91,43 +98,6 @@ namespace src.utils
|
|||
return playersByIndex.Values;
|
||||
}
|
||||
|
||||
public static IEnumerable<jSkill_PlayerInfo> GetAlivePlayers()
|
||||
{
|
||||
return playersByIndex.Values.Where(p =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var controller = Utilities.GetPlayerFromIndex((int)p.PlayerIndex);
|
||||
return controller != null && controller.IsValid && controller.PawnIsAlive;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static IEnumerable<jSkill_PlayerInfo> GetPlayersByTeam(CsTeam team)
|
||||
{
|
||||
return playersByIndex.Values.Where(p =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var controller = Utilities.GetPlayerFromIndex((int)p.PlayerIndex);
|
||||
return controller != null && controller.IsValid && controller.Team == team;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static int GetTeamPlayerCount(CsTeam team)
|
||||
{
|
||||
return GetPlayersByTeam(team).Count();
|
||||
}
|
||||
|
||||
public static int GetPlayerCountBySkill(Skills skills)
|
||||
{
|
||||
return playersByIndex.Values.Count(p => p.Skill == skills);
|
||||
|
|
|
|||
|
|
@ -322,7 +322,31 @@ namespace src.utils
|
|||
return !ff && !tae; // same team + FF off -> engine will zero this damage
|
||||
}
|
||||
|
||||
public static bool TakeHealth(CCSPlayerPawn? pawn, int damage)
|
||||
private static readonly ConcurrentDictionary<uint, (uint AttackerIndex, string? Weapon, int ExpiryTick)> pendingKillCredits = [];
|
||||
|
||||
public static void RegisterKillCredit(uint victimIndex, uint attackerIndex, string? weapon = null)
|
||||
{
|
||||
pendingKillCredits[victimIndex] = (attackerIndex, weapon, Server.TickCount + 64);
|
||||
}
|
||||
|
||||
public static bool TryConsumeKillCredit(uint victimIndex, out uint attackerIndex, out string? weapon)
|
||||
{
|
||||
attackerIndex = 0;
|
||||
weapon = null;
|
||||
if (!pendingKillCredits.TryRemove(victimIndex, out var credit)) return false;
|
||||
if (credit.ExpiryTick < Server.TickCount) return false;
|
||||
|
||||
attackerIndex = credit.AttackerIndex;
|
||||
weapon = credit.Weapon;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void ClearKillCredits()
|
||||
{
|
||||
pendingKillCredits.Clear();
|
||||
}
|
||||
|
||||
public static bool TakeHealth(CCSPlayerPawn? pawn, int damage, CCSPlayerController? damageAttacker = null, string? damageWeapon = null)
|
||||
{
|
||||
if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE)
|
||||
return false;
|
||||
|
|
@ -363,6 +387,10 @@ namespace src.utils
|
|||
|
||||
if (pawn.Health <= 0)
|
||||
{
|
||||
if (damageAttacker != null && damageAttacker.IsValid && victim != null && victim.IsValid
|
||||
&& damageAttacker.Index != victim.Index)
|
||||
RegisterKillCredit(victim.Index, damageAttacker.Index, damageWeapon);
|
||||
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (pawn == null || !pawn.IsValid) return;
|
||||
|
|
@ -374,6 +402,29 @@ namespace src.utils
|
|||
return true;
|
||||
}
|
||||
|
||||
public static void HideCarriedEntities(CCheckTransmitInfo info, CCSPlayerPawn? pawn)
|
||||
{
|
||||
if (pawn == null || !pawn.IsValid) return;
|
||||
|
||||
var weaponServices = pawn.WeaponServices;
|
||||
if (weaponServices == null) return;
|
||||
|
||||
var activeWeapon = weaponServices.ActiveWeapon?.Value;
|
||||
if (activeWeapon != null && activeWeapon.IsValid && info.TransmitEntities.Contains(activeWeapon.Index))
|
||||
info.TransmitEntities.Remove(activeWeapon.Index);
|
||||
|
||||
if (weaponServices.MyWeapons == null) return;
|
||||
|
||||
foreach (var handle in weaponServices.MyWeapons)
|
||||
{
|
||||
var weapon = handle?.Value;
|
||||
if (weapon == null || !weapon.IsValid) continue;
|
||||
|
||||
if (info.TransmitEntities.Contains(weapon.Index))
|
||||
info.TransmitEntities.Remove(weapon.Index);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ResetPrintHTML(CCSPlayerController? player)
|
||||
{
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue