diff --git a/Config/Localization.csv b/Config/Localization.csv index 61036fd..bb45956 100644 --- a/Config/Localization.csv +++ b/Config/Localization.csv @@ -323,7 +323,6 @@ Dört modifikasyon yuvasına takılan kan küreleriyle çalışır: küreler sı 以放入四個改裝槽的血之球為燃料:血之球依次消耗,一顆相當於一滿箱。無法用油桶加油。用骨頭修理(每次50根)。 任一槽中放入血石即可永遠滿箱。" necroBoneSteedNeedBones,UI,Tooltip,,,,You need {0} bones to repair the Bone Steed.,,"Du brauchst {0} Knochen, um das Knochenross zu reparieren.",Necesitas {0} huesos para reparar el Corcel de hueso.,Il te faut {0} os pour réparer le Destrier d'os.,Servono {0} ossa per riparare il Destriero d'ossa.,骨の駿馬の修理には骨が{0}個必要だ。,뼈 군마를 수리하려면 뼈 {0}개가 필요하다.,Do naprawy Kościanego rumaka potrzeba {0} kości.,Você precisa de {0} ossos para reparar o Corcel de osso.,Для ремонта Костяного скакуна нужно {0} костей.,Kemik Atı onarmak için {0} kemik gerekir.,修理骨骸坐骑需要{0}根骨头。,修理骨骸坐騎需要{0}根骨頭。 necroBoneSteed,entityclasses,Entity,,,,Bone Steed,,Knochenross,Corcel de hueso,Destrier d'os,Destriero d'ossa,骨の駿馬,뼈 군마,Kościany rumak,Corcel de osso,Костяной скакун,Kemik At,骨骸坐骑,骨骸坐騎 -zombieEraser,entityclasses,Entity,,,,Eraser,,Radierer,Borrador,Effaceur,Cancellatore,イレイサー,이레이저,Wymazywacz,Apagador,Стиратель,Silici,抹除者,抹除者 necroRemains,entityclasses,Entity,,,,Remains,,Überreste,Restos,Restes,Resti,遺骸,유해,Szczątki,Restos,Останки,Kalıntılar,遗骸,遺骸 necroMemoryBook,blocks,Block,,,,Book of Memory,,Buch der Erinnerung,Libro de la memoria,Livre de la mémoire,Libro della memoria,記憶の書,기억의 책,Księga pamięci,Livro da memória,Книга памяти,Hafıza Kitabı,记忆之书,記憶之書 necroMemoryBookPrompt,blocks,Block,,,,Press {0} to read,,Drücke {0} zum Lesen,Pulsa {0} para leer,Appuyez sur {0} pour lire,Premi {0} per leggere,{0} で読む,{0} 키를 눌러 읽기,"Naciśnij {0}, aby przeczytać",Pressione {0} para ler,"Нажмите {0}, чтобы прочитать",Okumak için {0} tuşuna basın,按 {0} 阅读,按 {0} 閱讀 diff --git a/Config/buffs.xml b/Config/buffs.xml index a3eda9d..7554725 100644 --- a/Config/buffs.xml +++ b/Config/buffs.xml @@ -359,18 +359,4 @@ - - - - diff --git a/Config/entityclasses.xml b/Config/entityclasses.xml index 376761c..d036272 100644 --- a/Config/entityclasses.xml +++ b/Config/entityclasses.xml @@ -451,38 +451,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/HarmonySrc/EraserPatch.cs b/HarmonySrc/EraserPatch.cs deleted file mode 100644 index fc8a940..0000000 --- a/HarmonySrc/EraserPatch.cs +++ /dev/null @@ -1,287 +0,0 @@ -using HarmonyLib; -using UnityEngine; - -namespace NecromancerTome -{ - /// - /// «Стиратель» (указание 02.10) - античит к режиму змеи: если игрок в кровавую луну стал змеёй, - /// в его орде с большой вероятностью приходят Стиратели - маленькие быстрые зомби с - /// нитроглицериновыми вздутиями. Взрываются, когда пытаются сломать блок и когда их разрывает - /// змея; взрыв ломает блоки, ранит тело игрока и соседних зомби, змею не ранит (она бессмертна), - /// а отбрасывает. - /// - /// Сущность - zombieEraser (entityclasses.xml): имя НЕ на necro, иначе IsNecroEntity сочтёт её - /// своей и змея перестанет видеть в ней врага. Параметры взрыва - блок Explosion там же, - /// подрыв - как у ванильного EntityZombieCop: ExplosionServer + SetDead. - /// - public static class EraserPatch - { - public const string EntityClassName = "zombieEraser"; - /// Доля Стирателей в орде игрока-змеи («с большой вероятностью»). - public const float HordeChance = 0.5f; - /// Отброс змеи: дальше этого от взрыва змею не задевает. - public const float KnockRange = 8f; - - static int _classId = -1; - - public static bool IsEraser(Entity _e) - { - if (_e == null) - { - return false; - } - if (_classId == -1) - { - _classId = EntityClass.FromString(EntityClassName); - } - return _e.entityClass == _classId; - } - - static System.Collections.IEnumerator BurstNextFrame(EntityAlive _e) - { - yield return null; - if (_e != null && _e.world != null && _e.world.GetEntity(_e.entityId) != null) - { - NecroBurst.Burst(_e, _e); - } - } - - /// Подрыв на сервере. Возвращает false, если подрывать нечего или не здесь. - public static bool Explode(EntityAlive _e) - { - if (_e == null || _e.IsDead() || _e.world == null || _e.world.IsRemote()) - { - return false; - } - Vector3 pos = _e.GetPosition(); - _e.NotifySleeperDeath(); - _e.SetModelLayer(2); - GameManager.Instance.ExplosionServer(pos, World.worldToBlockPos(pos), _e.transform.rotation, - EntityClass.list[_e.entityClass].explosionData, _e.entityId, 0f, false); - _e.timeStayAfterDeath = 0; - _e.SetDead(); - SnakeControl.Knockback(pos, KnockRange); - // Тела не остаётся (указание 02.10: «после взрыва остаются трупы туристов»): чёрный - // разрыв, как от змеи. Не сразу, а в следующем кадре: подрыв идёт изнутри хода ИИ - // (Attack из задачи), и удаление посреди него роняло EntityAlive.updateTasks (NRE, тест 02.10). - GameManager.Instance.StartCoroutine(BurstNextFrame(_e)); - Debug.Log("[NecromancerTome] EraserPatch: Стиратель " + _e.entityId + " взорвался в " + pos); - return true; - } - } - - /// Стиратель упёрся и начинает ломать блок - вместо удара взрыв. - [HarmonyPatch(typeof(EAIBreakBlock), nameof(EAIBreakBlock.Start))] - public static class Patch_EAIBreakBlock_Start_Eraser - { - public static bool Prefix(EAIBreakBlock __instance) - { - return !(EraserPatch.IsEraser(__instance.theEntity) && EraserPatch.Explode(__instance.theEntity)); - } - } - - /// Любая атака Стирателя - по блоку (BreakBlock, DestroyArea) или по цели - /// (ApproachAndAttackTarget) - идёт через EntityAlive.Attack: взрыв вместо удара (тест 02.10: - /// «взрываются не всегда, хотя атакуют»). - [HarmonyPatch(typeof(EntityAlive), nameof(EntityAlive.Attack))] - public static class Patch_EntityAlive_Attack_Eraser - { - public static bool Prefix(EntityAlive __instance, ref bool __result) - { - if (EraserPatch.IsEraser(__instance) && EraserPatch.Explode(__instance)) - { - __result = false; - return false; - } - return true; - } - } - - // ОТКЛЮЧЕНО 10.10 (новая концепция кровавой луны - «кровавый прилив», SnakeMode.IsBloodTide): в эту ночь - // дух не выходит из тела, а кто был змеёй - выброшен в тело. Игрока-змеи в орде больше не бывает, и - // античит не нужен. Сущность и её вид (выше и ниже) оставлены - вернуть подмешивание можно, сняв комментарий. - /* - /// - /// Подмешивание в орду. Ванильный образец - AIDirectorBloodMoonParty.SpawnZombie: игрок в - /// транспорте получает в орду стервятников с шансом 0.5. Класс зомби там берётся из - /// EntityGroups.GetRandomEntityFromGroupMaxTier; на время SpawnZombie запоминаем цель и, если - /// это игрок в режиме змеи, с шансом подменяем результат на Стирателя. - /// Режим змеи - состояние локального игрока (SnakeControl.Controlling), поэтому работает в - /// одиночной игре и у хоста; змея подключённого клиента орду не меняет. - /// - [HarmonyPatch(typeof(AIDirectorBloodMoonParty), "SpawnZombie")] - public static class Patch_BloodMoonParty_SpawnZombie_Eraser - { - [System.ThreadStatic] public static EntityPlayer Target; - - public static void Prefix(EntityPlayer _target) - { - Target = _target; - } - - public static void Finalizer() - { - Target = null; - } - } - - [HarmonyPatch(typeof(EntityGroups), nameof(EntityGroups.GetRandomEntityFromGroupMaxTier))] - public static class Patch_EntityGroups_GetRandom_Eraser - { - public static void Postfix(ref int __result) - { - EntityPlayer target = Patch_BloodMoonParty_SpawnZombie_Eraser.Target; - if (target == null || __result == -1 || !SnakeControl.Controlling || - !(target is EntityPlayerLocal) || Random.value >= EraserPatch.HordeChance) - { - return; - } - int id = EntityClass.FromString(EraserPatch.EntityClassName); - if (id != -1 && EntityClass.list.ContainsKey(id)) - { - __result = id; - } - } - } - */ - - /// - /// Вид Стирателя (02.10): тело - ванильная модель толстого гавайца (скелет, физика, теги, - /// анимации игры), а раскраска своя. Игра в EModelBase.createModel сама копирует материал тела - /// (ветка MatColor/AltMats); после неё подставляем в материал LOD-рендереров свои текстуры - /// (Resources/Eraser/*.png, нарисованы скриптом по развёртке гавайца): _Albedo, _Normal и _RMOE - /// (шероховатость, металл, затенение, в альфе - маска свечения), свечение - _EmissiveColor. - /// Глаза - отдельные рендереры *Eye* - прячем: на их месте в текстуре чёрные провалы. - /// Ступни босые - пальцы и ногти нарисованы в текстуре (слоновья нога масштабом костей не - /// получилась, 02.10). - /// - [HarmonyPatch(typeof(EModelBase), nameof(EModelBase.createModel))] - public static class Patch_EModelBase_createModel_EraserLook - { - public static readonly Color Emission = new Color(1f, 0.1f, 0.65f) * 2.5f; - - static Texture2D _albedo, _normal, _rmoe; - - /// Своя раскраска на материал тела (только у материалов с _Albedo - тело и куски). - public static void Paint(Renderer _r) - { - // Сначала смотрим общий материал: обращение к .material создаёт копию, и делать её - // у глаз, огня и прочих рендереров без _Albedo незачем. Если копия уже наша - .material - // вернёт её же, повторной копии не будет. Брошенные копии убирает сама игра - // (GameManager: Resources.UnloadUnusedAssets по таймеру). - Material sm = _r.sharedMaterial; - if (sm == null || !sm.HasProperty("_Albedo") || sm.GetTexture("_Albedo") == _albedo && sm.GetColor("_EmissiveColor") == Emission) - { - return; - } - Material m = _r.material; - if (_albedo != null) m.SetTexture("_Albedo", _albedo); - if (_normal != null) m.SetTexture("_Normal", _normal); - if (_rmoe != null) m.SetTexture("_RMOE", _rmoe); - m.SetColor("_EmissiveColor", Emission); - } - static bool _loaded; - - static Texture2D Load(string _file, bool _linear) - { - string path = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(typeof(EraserPatch).Assembly.Location), "Resources", "Eraser", _file); - if (!System.IO.File.Exists(path)) - { - Debug.LogWarning("[NecromancerTome] EraserLook: нет файла " + path); - return null; - } - Texture2D t = new Texture2D(2, 2, TextureFormat.RGBA32, true, _linear); - if (!ImageConversion.LoadImage(t, System.IO.File.ReadAllBytes(path))) - { - return null; - } - t.name = "Eraser_" + _file; - t.Apply(true, true); - return t; - } - - public static void Postfix(EModelBase __instance) - { - Entity e = __instance.entity; - if (!EraserPatch.IsEraser(e)) - { - return; - } - if (!_loaded) - { - _loaded = true; - _albedo = Load("eraser_albedo.png", false); - _normal = Load("eraser_normal.png", true); - _rmoe = Load("eraser_rmoe.png", true); - } - foreach (SkinnedMeshRenderer r in __instance.GetComponentsInChildren(true)) - { - if (r.name.IndexOf("Eye", System.StringComparison.OrdinalIgnoreCase) >= 0) - { - r.enabled = false; - continue; - } - if (!r.CompareTag("LOD")) - { - continue; - } - Paint(r); - } - Debug.Log("[NecromancerTome] EraserLook: вид Стирателя на " + e.entityId); - } - } - - /// - /// Отрубленная конечность (тест 02.10: «если у трупа отрубить руку, он становится туристом»): - /// игра при расчленении подменяет материалы тела и создаёт отлетающий кусок с ванильным - /// материалом гавайца. После RemoveLimb заново красим тело и новые куски. - /// - [HarmonyPatch(typeof(AvatarZombieController), nameof(AvatarZombieController.RemoveLimb))] - public static class Patch_AvatarZombieController_RemoveLimb_EraserLook - { - public static void Prefix(out int __state) - { - __state = DismembermentManager.Instance?.parts.Count ?? 0; - } - - public static void Postfix(AvatarZombieController __instance, int __state) - { - EntityAlive e = Traverse.Create(__instance).Field("entity").GetValue(); - if (!EraserPatch.IsEraser(e) || e.emodel == null) - { - return; - } - foreach (Renderer r in e.emodel.GetComponentsInChildren(true)) - { - Patch_EModelBase_createModel_EraserLook.Paint(r); - } - var parts = DismembermentManager.Instance?.parts; - for (int i = __state; parts != null && i < parts.Count; i++) - { - foreach (Transform t in new[] { parts[i].prefabT, parts[i].detachT }) - { - if (t == null) continue; - foreach (Renderer r in t.GetComponentsInChildren(true)) - { - Patch_EModelBase_createModel_EraserLook.Paint(r); - } - } - } - } - } - - /// Стиратель убит чем угодно (игроком, взрывом соседа, под бафом жертвы) - чёрный - /// разрыв, трупа не остаётся (указание 02.10). Тот же путь, что у змеи: постфикс ClientKill. - [HarmonyPatch(typeof(EntityAlive), nameof(EntityAlive.ClientKill))] - public static class Patch_EntityAlive_ClientKill_EraserBurst - { - public static void Postfix(EntityAlive __instance) - { - if (EraserPatch.IsEraser(__instance) && __instance.IsDead() && __instance.world != null && - __instance.world.GetEntity(__instance.entityId) != null) - { - NecroBurst.Burst(__instance, __instance.entityThatKilledMe != null ? (Entity)__instance.entityThatKilledMe : __instance); - } - } - } -} diff --git a/HarmonySrc/ParticlePatch.cs b/HarmonySrc/ParticlePatch.cs index fbef274..b761803 100644 --- a/HarmonySrc/ParticlePatch.cs +++ b/HarmonySrc/ParticlePatch.cs @@ -77,9 +77,6 @@ namespace NecromancerTome /// светятся сильнее обычного; плотнее и крупнее, чем у девиантов. public static readonly GlowConfig SnakeSightGlow = new GlowConfig { Tint = new Color(1.1f, 1.5f, 0.15f), SizeFactor = 0.4f, AlphaFactor = 1f, DensityFactor = 3f }; public const string SnakeSightBuffName = "buffNecroSnakeSight"; - /// «Стиратель» (02.10): маджента - этим цветом зомби больше никто не светится. - public static readonly GlowConfig EraserGlow = new GlowConfig { Tint = new Color(1f, 0.1f, 0.65f), SizeFactor = 0.4f, AlphaFactor = 1f, DensityFactor = 3f }; - public const string EraserBuffName = "buffNecroEraser"; public static readonly GlowConfig PortalChannelGlow = new GlowConfig { Tint = new Color(0.1f, 0.85f, 0.8f), SizeFactor = 0.9f, AlphaFactor = 0.9f, DensityFactor = 5f }; public static void Postfix(MinEventActionAttachParticleEffectToEntity __instance, MinEventParams _params) @@ -100,8 +97,7 @@ namespace NecromancerTome bool isVictim = entity.Buffs.HasBuff(Patch_EntityAlive_dropItemOnDeath_VictimBag.VictimBuffName); bool isCharm = entity.Buffs.HasBuff(Patch_EntityBuffs_AddBuff_DeviatorCharm.CharmBuffName); bool isSnakeSight = entity.Buffs.HasBuff(SnakeSightBuffName); - bool isEraser = entity.Buffs.HasBuff(EraserBuffName); - if (!isPortalChannel && !isVictim && !isCharm && !isSnakeSight && !isEraser) + if (!isPortalChannel && !isVictim && !isCharm && !isSnakeSight) { return; } @@ -113,10 +109,6 @@ namespace NecromancerTome { config = PortalChannelGlow; } - else if (isEraser) - { - config = EraserGlow; - } else if (isSnakeSight) { config = SnakeSightGlow; diff --git a/HarmonySrc/SnakeControl.cs b/HarmonySrc/SnakeControl.cs index 7d55fb0..19799c6 100644 --- a/HarmonySrc/SnakeControl.cs +++ b/HarmonySrc/SnakeControl.cs @@ -464,11 +464,6 @@ namespace NecromancerTome } _pos = target.position - (flat.sqrMagnitude > 0.0001f ? flat.normalized * DashStop : Vector3.zero); _dashTarget = null; - // Стиратель от разрыва взрывается; отброс змеи - из EraserPatch.Explode. - if (EraserPatch.IsEraser(target) && EraserPatch.Explode(target)) - { - return; - } _freeze = KillFreeze; _killId = target.entityId; NoLoot.Add(target.entityId); @@ -485,32 +480,6 @@ namespace NecromancerTome Debug.Log("[NecromancerTome] SnakeControl: удар по " + target.EntityName + ", " + (target.IsDead() ? "убит" : "ВЫЖИЛ")); } - /// Из EraserPatch.Explode: змею ближе _range от взрыва отбрасывает прочь и вверх. - /// Не ранит - змея бессмертна. - public static void Knockback(Vector3 _from, float _range) - { - if (!Controlling) - { - return; - } - Vector3 away = _pos - _from; - if (away.sqrMagnitude > _range * _range) - { - return; - } - away.y = 0f; - if (away.sqrMagnitude < 0.01f) - { - away = Quaternion.Euler(0f, _yaw, 0f) * Vector3.back; - } - _dashTarget = null; - _kick = away.normalized * KickSpeed; - _vy = KickUp; - _airborne = true; - _freeze = 0.6f; - Debug.Log("[NecromancerTome] SnakeControl: отброшена взрывом Стирателя"); - } - /// Из NecroBurst.OnBurst: наш разрыв - запоминаем частицы, чтобы вести их за змеёй. public static void OnBurst(EntityAlive _victim, Transform _effect) { diff --git a/NecromancerHarmony.dll b/NecromancerHarmony.dll index 08ffcf0..96e4bfd 100644 Binary files a/NecromancerHarmony.dll and b/NecromancerHarmony.dll differ diff --git a/NecromancerHarmony.pdb b/NecromancerHarmony.pdb index 4b6e257..6ffe8ca 100644 Binary files a/NecromancerHarmony.pdb and b/NecromancerHarmony.pdb differ diff --git a/Resources/Eraser/eraser_albedo.png b/Resources/Eraser/eraser_albedo.png deleted file mode 100644 index 1479bbd..0000000 Binary files a/Resources/Eraser/eraser_albedo.png and /dev/null differ diff --git a/Resources/Eraser/eraser_normal.png b/Resources/Eraser/eraser_normal.png deleted file mode 100644 index c5f0d67..0000000 Binary files a/Resources/Eraser/eraser_normal.png and /dev/null differ diff --git a/Resources/Eraser/eraser_rmoe.png b/Resources/Eraser/eraser_rmoe.png deleted file mode 100644 index 98f5785..0000000 Binary files a/Resources/Eraser/eraser_rmoe.png and /dev/null differ