Иконка ресурса

FREE BeastBoss : 0.4.0 0.4.0

Нет прав для скачивания
C#:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using Oxide.Core;
using Oxide.Core.Plugins;
using UnityEngine;
using Rust; // DamageType, MapMarkerGenericRadius, etc.
using Oxide.Game.Rust.Cui;

namespace Oxide.Plugins
{
    [Info("BeastBoss", "Somescrub", "0.4.0")]
    [Description("BossMonster-style animal bosses with tiers, lockouts, spawnpoints, events and a boss health HUD")]
    public class BeastBoss : RustPlugin
    {
        [PluginReference("ImageLibrary")]
        private Plugin ImageLibrary;
        #region Config

        internal ConfigData _config;

        public class ConfigData
        {
            public Dictionary<string, BeastDef> Beasts = new Dictionary<string, BeastDef>
            {
                ["bear"] = new BeastDef
                {
                    DisplayName = "Dire Bear",
                    TierId = "T1",
                    Theme = "fire",
                    Prefab = "assets/rust.ai/agents/bear/bear.prefab",
                    BaseHealth = 2500f,
                    DamageMultiplier = 1.5f,
                    InitialScale = 1.2f,
                    EnragedScale = 1.5f,

                    PhaseScales = new List<PhaseScale>
                    {
                        new PhaseScale { HealthFraction = 0.75f, Scale = 1.3f },
                        new PhaseScale { HealthFraction = 0.50f, Scale = 1.4f },
                        new PhaseScale { HealthFraction = 0.25f, Scale = 1.5f }
                    },

                    AbilityRoar = new RoarSettings
                    {
                        Enabled = true,
                        Interval = 12f,
                        Radius = 10f,
                        Damage = 10f,
                        Bleed = 10f,
                        ScreenShake = 2.0f
                    },

                    AbilityCharge = new ChargeSettings
                    {
                        Enabled = true,
                        Interval = 20f,
                        Range = 25f,
                        ImpactRadius = 3.0f,
                        ImpactDamage = 40f,
                        ChargeForce = 13f
                    },

                    AbilityFrostAura = new FrostAuraSettings
                    {
                        Enabled = false,
                        Interval = 18f,
                        Radius = 9f,
                        Duration = 4f,
                        TickRate = 1f,
                        DamagePerTick = 4f,
                        ColdPerTick = 10f
                    },

                    AbilityCubSummon = new CubSummonSettings
                    {
                        Enabled = true,
                        TriggerHealthFraction = 0.5f,
                        Count = 3,
                        Prefab = "assets/rust.ai/agents/wolf/wolf.prefab",
                        Radius = 6f
                    },

                    AbilityEnrage = new EnrageSettings
                    {
                        Enabled = true,
                        TriggerHealthFraction = 0.3f,
                        DamageMultiplier = 1.6f,
                        SpeedMultiplier = 1.4f,
                        EffectPrefab = null
                    },

                    AbilityFireTrail = new FireTrailSettings
                    {
                        Enabled = true,
                        Interval = 16f,
                        Duration = 5f,
                        Step = 0.7f,
                        Radius = 3f,
                        DamagePerStep = 6f
                    },

                    Loot = new List<LootEntry>
                    {
                        new LootEntry { ShortName = "hq.metal.ore", Amount = 200, Skin = 0 },
                        new LootEntry { ShortName = "bearmeat", Amount = 15, Skin = 0 },
                        new LootEntry { ShortName = "scrap", Amount = 150, Skin = 0 }
                    }
                },

                ["wolf"] = new BeastDef
                {
                    DisplayName = "Nightfang",
                    TierId = "T1",
                    Theme = "frost",
                    Prefab = "assets/rust.ai/agents/wolf/wolf.prefab",
                    BaseHealth = 1500f,
                    DamageMultiplier = 1.3f,
                    InitialScale = 1.1f,
                    EnragedScale = 1.4f,

                    PhaseScales = new List<PhaseScale>
                    {
                        new PhaseScale { HealthFraction = 0.50f, Scale = 1.2f },
                        new PhaseScale { HealthFraction = 0.25f, Scale = 1.3f }
                    },

                    AbilityRoar = new RoarSettings
                    {
                        Enabled = true,
                        Interval = 14f,
                        Radius = 8f,
                        Damage = 7f,
                        Bleed = 7f,
                        ScreenShake = 1.2f
                    },

                    AbilityCharge = new ChargeSettings
                    {
                        Enabled = true,
                        Interval = 16f,
                        Range = 20f,
                        ImpactRadius = 2.5f,
                        ImpactDamage = 30f,
                        ChargeForce = 15f
                    },

                    AbilityFrostAura = new FrostAuraSettings
                    {
                        Enabled = true,
                        Interval = 16f,
                        Radius = 10f,
                        Duration = 4f,
                        TickRate = 1f,
                        DamagePerTick = 5f,
                        ColdPerTick = 15f
                    },

                    AbilityCubSummon = new CubSummonSettings
                    {
                        Enabled = true,
                        TriggerHealthFraction = 0.4f,
                        Count = 4,
                        Prefab = "assets/rust.ai/agents/wolf/wolf.prefab",
                        Radius = 8f
                    },

                    AbilityEnrage = new EnrageSettings
                    {
                        Enabled = true,
                        TriggerHealthFraction = 0.25f,
                        DamageMultiplier = 1.7f,
                        SpeedMultiplier = 1.5f,
                        EffectPrefab = null
                    },

                    AbilityFireTrail = new FireTrailSettings
                    {
                        Enabled = false,
                        Interval = 18f,
                        Duration = 4f,
                        Step = 0.7f,
                        Radius = 3f,
                        DamagePerStep = 5f
                    },

                    Loot = new List<LootEntry>
                    {
                        new LootEntry { ShortName = "leather", Amount = 100, Skin = 0 },
                        new LootEntry { ShortName = "wolfmeat", Amount = 10, Skin = 0 },
                        new LootEntry { ShortName = "scrap", Amount = 80, Skin = 0 }
                    }
                },

                ["storm_wolf"] = new BeastDef
                {
                    DisplayName = "Stormfang Alpha",
                    TierId = "T2",
                    Theme = "storm",
                    Prefab = "assets/rust.ai/agents/wolf/wolf.prefab",
                    BaseHealth = 2200f,
                    DamageMultiplier = 1.45f,
                    InitialScale = 1.0f,
                    EnragedScale = 1.0f,

                    PhaseScales = new List<PhaseScale>
                    {
                        new PhaseScale { HealthFraction = 0.50f, Scale = 1.0f },
                        new PhaseScale { HealthFraction = 0.25f, Scale = 1.0f }
                    },

                    AbilityRoar = new RoarSettings
                    {
                        Enabled = true,
                        Interval = 12f,
                        Radius = 10f,
                        Damage = 9f,
                        Bleed = 6f,
                        ScreenShake = 1.6f
                    },

                    AbilityCharge = new ChargeSettings
                    {
                        Enabled = true,
                        Interval = 14f,
                        Range = 26f,
                        ImpactRadius = 2.8f,
                        ImpactDamage = 38f,
                        ChargeForce = 16f
                    },

                    AbilityFrostAura = new FrostAuraSettings
                    {
                        Enabled = false,
                        Interval = 16f,
                        Radius = 9f,
                        Duration = 4f,
                        TickRate = 1f,
                        DamagePerTick = 0f,
                        ColdPerTick = 0f
                    },

                    AbilityCubSummon = new CubSummonSettings
                    {
                        Enabled = true,
                        TriggerHealthFraction = 0.45f,
                        Count = 2,
                        Prefab = "assets/rust.ai/agents/wolf/wolf.prefab",
                        Radius = 8f
                    },

                    AbilityEnrage = new EnrageSettings
                    {
                        Enabled = true,
                        TriggerHealthFraction = 0.30f,
                        DamageMultiplier = 1.8f,
                        SpeedMultiplier = 1.55f,
                        EffectPrefab = null
                    },

                    AbilityFireTrail = new FireTrailSettings
                    {
                        Enabled = false,
                        Interval = 18f,
                        Duration = 4f,
                        Step = 0.7f,
                        Radius = 3f,
                        DamagePerStep = 0f
                    },

                    Loot = new List<LootEntry>
                    {
                        new LootEntry { ShortName = "scrap", Amount = 180, Skin = 0 },
                        new LootEntry { ShortName = "metal.fragments", Amount = 350, Skin = 0 },
                        new LootEntry { ShortName = "wolfmeat", Amount = 15, Skin = 0 }
                    }
                },

                ["plague_boar"] = new BeastDef
                {
                    DisplayName = "Plague Tusk",
                    TierId = "T2",
                    Theme = "toxic",
                    Prefab = "assets/rust.ai/agents/boar/boar.prefab",
                    BaseHealth = 2000f,
                    DamageMultiplier = 1.35f,
                    InitialScale = 1.0f,
                    EnragedScale = 1.0f,

                    PhaseScales = new List<PhaseScale>
                    {
                        new PhaseScale { HealthFraction = 0.60f, Scale = 1.0f },
                        new PhaseScale { HealthFraction = 0.30f, Scale = 1.0f }
                    },

                    AbilityRoar = new RoarSettings
                    {
                        Enabled = true,
                        Interval = 16f,
                        Radius = 9f,
                        Damage = 8f,
                        Bleed = 8f,
                        ScreenShake = 1.2f
                    },

                    AbilityCharge = new ChargeSettings
                    {
                        Enabled = true,
                        Interval = 18f,
                        Range = 22f,
                        ImpactRadius = 3.2f,
                        ImpactDamage = 34f,
                        ChargeForce = 14f
                    },

                    AbilityFrostAura = new FrostAuraSettings
                    {
                        Enabled = true,
                        Interval = 16f,
                        Radius = 10f,
                        Duration = 5f,
                        TickRate = 1f,
                        DamagePerTick = 6f,
                        ColdPerTick = 0f
                    },

                    AbilityCubSummon = new CubSummonSettings
                    {
                        Enabled = true,
                        TriggerHealthFraction = 0.50f,
                        Count = 2,
                        Prefab = "assets/rust.ai/agents/boar/boar.prefab",
                        Radius = 7f
                    },

                    AbilityEnrage = new EnrageSettings
                    {
                        Enabled = true,
                        TriggerHealthFraction = 0.28f,
                        DamageMultiplier = 1.75f,
                        SpeedMultiplier = 1.45f,
                        EffectPrefab = null
                    },

                    AbilityFireTrail = new FireTrailSettings
                    {
                        Enabled = false,
                        Interval = 18f,
                        Duration = 4f,
                        Step = 0.7f,
                        Radius = 3f,
                        DamagePerStep = 0f
                    },

                    Loot = new List<LootEntry>
                    {
                        new LootEntry { ShortName = "scrap", Amount = 150, Skin = 0 },
                        new LootEntry { ShortName = "leather", Amount = 140, Skin = 0 },
                        new LootEntry { ShortName = "boarmeat", Amount = 18, Skin = 0 }
                    }
                },

                ["shade_stag"] = new BeastDef
                {
                    DisplayName = "Shadehorn",
                    TierId = "T2",
                    Theme = "shadow",
                    Prefab = "assets/rust.ai/agents/stag/stag.prefab",
                    BaseHealth = 1800f,
                    DamageMultiplier = 1.25f,
                    InitialScale = 1.0f,
                    EnragedScale = 1.0f,

                    PhaseScales = new List<PhaseScale>
                    {
                        new PhaseScale { HealthFraction = 0.50f, Scale = 1.0f },
                        new PhaseScale { HealthFraction = 0.20f, Scale = 1.0f }
                    },

                    AbilityRoar = new RoarSettings
                    {
                        Enabled = true,
                        Interval = 18f,
                        Radius = 11f,
                        Damage = 6f,
                        Bleed = 10f,
                        ScreenShake = 1.8f
                    },

                    AbilityCharge = new ChargeSettings
                    {
                        Enabled = true,
                        Interval = 16f,
                        Range = 24f,
                        ImpactRadius = 3.0f,
                        ImpactDamage = 28f,
                        ChargeForce = 15f
                    },

                    AbilityFrostAura = new FrostAuraSettings
                    {
                        Enabled = false,
                        Interval = 16f,
                        Radius = 9f,
                        Duration = 4f,
                        TickRate = 1f,
                        DamagePerTick = 0f,
                        ColdPerTick = 0f
                    },

                    AbilityCubSummon = new CubSummonSettings
                    {
                        Enabled = true,
                        TriggerHealthFraction = 0.45f,
                        Count = 3,
                        Prefab = "assets/rust.ai/agents/wolf/wolf.prefab",
                        Radius = 9f
                    },

                    AbilityEnrage = new EnrageSettings
                    {
                        Enabled = true,
                        TriggerHealthFraction = 0.22f,
                        DamageMultiplier = 1.6f,
                        SpeedMultiplier = 1.6f,
                        EffectPrefab = null
                    },

                    AbilityFireTrail = new FireTrailSettings
                    {
                        Enabled = false,
                        Interval = 18f,
                        Duration = 4f,
                        Step = 0.7f,
                        Radius = 3f,
                        DamagePerStep = 0f
                    },

                    Loot = new List<LootEntry>
                    {
                        new LootEntry { ShortName = "scrap", Amount = 130, Skin = 0 },
                        new LootEntry { ShortName = "cloth", Amount = 120, Skin = 0 },
                        new LootEntry { ShortName = "deermeat.raw", Amount = 14, Skin = 0 }
                    }
                }
            };

            public Dictionary<string, TierConfig> Tiers = new Dictionary<string, TierConfig>
            {
                ["T1"] = new TierConfig
                {
                    DisplayName = "Tier 1 Beasts",
                    LockoutMinutes = 60.0,
                    AutoSpawn = false,
                    AutoRespawnMinutes = 30.0
                }
            };

            public float GlobalIncomingDamageMultiplier = 0.8f;
            public float GlobalOutgoingDamageMultiplier = 1.0f;
            public float AnnounceRadius = 80f;
            public string ChatPrefix = "<color=#d57b00>[Beast]</color> ";
            public string PermissionAdmin = "beastboss.admin";

            public float EventCheckIntervalSeconds = 60f;

            // Enable entity scaling via EntityScaleManager plugin.
            // If false, no scaling occurs. If true, requires EntityScaleManager to be installed.
            public bool UseScaling = false;

            // Enable phase-based scaling (beasts scale as health drops to phases).
            // If false, only InitialScale and EnragedScale are applied.
            public bool UsePhaseScaling = false;

            // Enable debug logging for boss lifecycle events (spawn, enrage, summon, etc).
            public bool Debug = false;

            // Boss HUD config (roughly compatible look with TargetHealthHUD)
            public UiConfig Ui = new UiConfig();

            // Chat announcements on boss spawn/enrage/death
            public AnnouncementSettings Announcements = new AnnouncementSettings();

            // World map markers that follow active bosses
            public MarkerSettings Markers = new MarkerSettings();

            // Proximity-based warnings to nearby players
            public ProximityWarningSettings ProximityWarnings = new ProximityWarningSettings();

            // Boss leash system: soft reset when kiting too far
            public LeashSettings Leash = new LeashSettings();

            // Weather-enhanced ability procs (lightning strikes, etc.)
            public WeatherProcSettings WeatherProcs = new WeatherProcSettings();

            // Timed world events that spawn bosses automatically
            public WorldEventSettings WorldEvents = new WorldEventSettings();

            // Per-player tier escalation: each player progresses through tiers based on their kill counts
            public PlayerTierEscalationSettings TierEscalation = new PlayerTierEscalationSettings();

            // Mythic variants: rare boss versions with special FX and loot
            public MythicSettings Mythic = new MythicSettings();

            // Boss title plate (CUI overlay at top-center showing boss name + subtitle)
            public TitlePlateSettings TitlePlate = new TitlePlateSettings();

            // Enrage countdown indicator shown in title plate
            public EnrageIndicatorSettings EnrageIndicator = new EnrageIndicatorSettings();

            /*
             * FX Library keys and usage:
             *  - "roar_blast"   : Used by DoRoar() for the main roar visual + optional impact FX.
             *  - "fire_trail"   : Used by DoFireTrail() for the trail FX behind fire-themed beasts.
             *  - "frost_aura"   : Used by DoFrostAura() as the primary cold aura visual.
             *  - "toxic_aura"   : Optional alternative to frost_aura for poison-themed beasts.
             *  - "ground_impact": Used by DoRoar() and other impact-style abilities for ground shock FX.
             *  - "enrage_burst" : Used by TriggerEnrage() for the enrage burst visual.
             *  - "enrage_aura"  : Used by TriggerEnrage() for the repeating aura during enrage.
             *  - "summon_burst" : Used by DoCubSummon() when spawning minions.
             *
             * These keys are defined in ConfigData.FxLibrary and can be customized in BeastBoss.json
             * without changing code.
             */
            public Dictionary<string, List<string>> FxLibrary = new Dictionary<string, List<string>>
            {
                // Generic categories used by abilities
                ["roar_blast"] = new List<string>
                {
                    "assets/bundled/prefabs/fx/player/howl.prefab",
                    "assets/bundled/prefabs/fx/impacts/additive/explosion.prefab"
                },
                ["fire_trail"] = new List<string>
                {
                    "assets/bundled/prefabs/fx/fire/fire_v2.prefab",
                    "assets/bundled/prefabs/fx/fire/fire_v3.prefab"
                },
                ["frost_aura"] = new List<string>
                {
                    "assets/bundled/prefabs/fx/smoke/generator_smoke.prefab"
                },
                ["toxic_aura"] = new List<string>
                {
                    "assets/bundled/prefabs/fx/smoke_cover_full.prefab"
                },
                ["ground_impact"] = new List<string>
                {
                    "assets/bundled/prefabs/fx/explosions/explosion_01.prefab",
                    "assets/bundled/prefabs/fx/impacts/blunt/dirt/dirt1.prefab"
                },
                ["enrage_burst"] = new List<string>
                {
                    "assets/bundled/prefabs/fx/explosions/explosion_core_flash.prefab",
                    "assets/bundled/prefabs/fx/explosions/explosion_02.prefab"
                },
                ["enrage_aura"] = new List<string>
                {
                    "assets/bundled/prefabs/fx/fire/fire_v2.prefab",
                    "assets/bundled/prefabs/fx/smoke_signal.prefab"
                },
                ["summon_burst"] = new List<string>
                {
                    "assets/bundled/prefabs/fx/impacts/additive/fire.prefab",
                    "assets/bundled/prefabs/fx/explosions/explosion_01.prefab"
                },
                ["lightning_strike"] = new List<string>
                {
                    "assets/bundled/prefabs/fx/player/electrocute.prefab",
                    "assets/bundled/prefabs/fx/impacts/additive/explosion.prefab"
                }
            };
        }

        public class UiConfig
        {
            public bool Enabled = true;
            public string Style = "top detailed";
            public string TextFormat = "{0} {1}/{2} HP";
            public int ActiveDuration = 10; // seconds to keep HUD after last hit

            public string TextColor = "1 1 1 1";
            public string PrimaryColor = "0.7058824 0.07843138 0.07843138 1";
            public string SecondaryColor = "1 0.1960784 0.1960784 1";
            public string BorderColor = "0 0 0 0.9";  // dark outline so it reads over red fill
            public int BorderPx = 2;                     // pixel thickness

            // Slightly below your TargetHealthHUD default so they don't overlap perfectly
            public string AnchorMin = "0.3297916 0.88";
            public string AnchorMax = "0.6683334 0.91";
        }

        public class AnnouncementSettings
        {
            public bool Enabled = true;
            public bool AnnounceSpawn = true;
            public bool AnnounceEnrage = true;
            public bool AnnounceDeath = true;

            public string SpawnMessage = "<color=#ffcc00>[BeastBoss]</color> <color=#ff5555>{name}</color> has appeared at <color=#aaddff>{grid}</color>!";
            public string EnrageMessage = "<color=#ffcc00>[BeastBoss]</color> <color=#ff5555>{name}</color> is <color=#ff0000>ENRAGED</color>!";
            public string DeathMessage = "<color=#ffcc00>[BeastBoss]</color> <color=#ff5555>{name}</color> was defeated by <color=#aaffaa>{killer}</color>!";
        }

        public class MarkerSettings
        {
            public bool Enabled = true;
            public float Radius = 0.25f;
            public float Alpha = 0.65f;
            public string Color = "#ff4444";
            public bool ShowLabel = true;
            public float UpdateIntervalSeconds = 3f;
        }

        public class ProximityWarningSettings
        {
            public bool Enabled = true;
            public float RadiusMeters = 120f;

            public bool WarnOnSpawn = true;
            public bool WarnOnEnrage = true;
            public bool WarnOnDeath = false;

            public string SpawnMessage = "<color=#ffcc00>[Warning]</color> A BeastBoss (<color=#ff5555>{name}</color>) has spawned nearby!";
            public string EnrageMessage = "<color=#ffcc00>[Warning]</color> <color=#ff5555>{name}</color> is <color=#ff0000>ENRAGED</color> nearby!";
            public string DeathMessage = "<color=#ffcc00>[Info]</color> Nearby BeastBoss (<color=#ff5555>{name}</color>) has been defeated.";

            public float PlayerCooldownSeconds = 20f;
        }

        public class LeashSettings
        {
            public bool Enabled = true;

            // Primary leash radius from the boss spawn point (meters).
            public float RadiusMeters = 80f;

            // If boss exceeds this distance, it resets immediately (safety mechanism).
            // Set to 0 to disable. Recommended: RadiusMeters * 1.25
            public float HardResetRadiusMeters = 120f;

            // If boss remains outside RadiusMeters for this long (seconds), it will reset.
            public float ResetAfterSecondsOutside = 8f;

            // Heal fraction on reset (1.0 = full heal).
            public float ResetHealFraction = 1.0f;

            // Incoming damage multiplier when boss is outside RadiusMeters.
            // Example: 0.25 reduces player damage to 25% while boss is outside leash.
            public float OutsideIncomingDamageMultiplier = 0.25f;

            // Return-to-spawn walk behavior
            public bool WalkBackToSpawn = true;
            public float ReturnStopDistanceMeters = 6f;     // how close is "back home"
            public float ReturnMaxSeconds = 30f;            // fail-safe: if stuck too long, fallback to teleport OR force-reset in place
            public bool FallbackTeleportIfStuck = true;     // if true, teleport to spawn after ReturnMaxSeconds
            public float ReturnDestinationRefreshSeconds = 2f; // how often to re-issue destination while returning

            // Optional messaging on reset
            public bool AnnounceResetToChat = true;
            public string ResetMessage = "<color=#ffcc00>[BeastBoss]</color> <color=#ff5555>{name}</color> has retreated and recovered!";
        }

        public class WeatherProcSettings
        {
            public bool Enabled = true;
            public bool StormThemeOnly = true;
            public bool RequireBadWeather = false; // if true, only proc during rain/fog
            public float ProcChancePerCheck = 0.15f;
            public float ProcCheckIntervalSeconds = 3f;
            public float ProcRadiusMeters = 4f;
            public float ProcDamage = 12f; // set 0 for FX only
        }

        public class WorldEventSettings
        {
            public bool Enabled = false;

            // Example: every 60–90 minutes, pick one boss and spawn it at a spawnpoint group.
            public float MinMinutesBetweenEvents = 60f;
            public float MaxMinutesBetweenEvents = 90f;

            public string SpawnpointGroup = "default"; // reuse your BotReSpawn-like manual spawnpoint grouping
            public List<string> AllowedBeastKeys = new List<string>(); // empty => all
        }

        public class PlayerTierEscalationSettings
        {
            public bool Enabled = true;
            public float ResetAfterHours = 0f; // 0 = disabled
            public bool CycleEnabled = false;
            public string CycleAtTierId = "T3";
            public string CycleToTierId = "T1";
            public List<PlayerTierRule> Rules = new List<PlayerTierRule>
            {
                new PlayerTierRule { FromTierId = "T1", KillsToAdvance = 10, ToTierId = "T2" },
                new PlayerTierRule { FromTierId = "T2", KillsToAdvance = 10, ToTierId = "T3" }
            };
            public bool KillerOnly = true;
        }

        public class PlayerTierRule
        {
            public string FromTierId;
            public int KillsToAdvance;
            public string ToTierId;
        }

        public class PlayerTierProgress
        {
            public string CurrentTierId = "T1";
            public Dictionary<string, int> KillsByTier = new Dictionary<string, int>();
            public double LastProgressUtc = 0;
        }

        public class MythicSettings
        {
            public bool Enabled = true;
            public float Chance = 0.05f;

            public string NamePrefix = "Mythic ";
            public string NameSuffix = "";
            public string ThemeOverride = ""; // optional, empty => keep original

            public string SpawnFxKey = "enrage_burst";
            public string EnrageFxKey = "enrage_aura";
            public string DeathFxKey = "explosion_big"; // if missing, reuse "enrage_burst"

            public float LootMultiplier = 1.5f; // multiply amounts; do not change items
        }

        public class TitlePlateSettings
        {
            public bool Enabled = true;
            public float ShowWithinMeters = 120f;
            public float UpdateIntervalSeconds = 1.0f;

            public string PanelAnchorMin = "0.325 0.85";
            public string PanelAnchorMax = "0.675 0.90";
            public string PanelColor = "0.2 0.02 0.02 0.75";

            public int FontSize = 18;
            public string TextColor = "1 1 1 1";
            public string OutlineColor = "0 0 0 0.8";

            // Tier-colored border configuration
            public float BorderThickness = 0.006f; // Anchor units, clamped 0.001-0.05
            public Dictionary<string, string> TierBorderColors = new Dictionary<string, string>
            {
                ["T1"] = "#ffcc00",  // Gold
                ["T2"] = "#66ccff",  // Cyan
                ["T3"] = "#cc66ff",  // Magenta
                ["T4"] = "#ff4444",  // Red
                ["T5"] = "#ffffff"   // White
            };

            // Mythic border overrides
            public string MythicBorderColor = "#ffd700";   // gold
            public bool MythicBorderOverridesTier = true;  // if true, use mythic color instead of tier color
            public bool MythicPulseOverrides = true;
            public float MythicPulseSpeedMultiplier = 1.35f; // pulse slightly faster than normal
            public float MythicPulseAlphaBoost = 0.08f;       // increases max alpha slightly (still subtle)

            // Title format tokens:
            // {name} -> boss display name (supports mythic override)
            // {subtitle} -> generated subtitle based on Theme/TierId
            public string TitleFormat = "{name}, {subtitle}";

            // Optional mini health bar rendered INSIDE the title plate (bottom strip)
            public bool ShowHealthBar = true;
            public string HealthBarAnchorMin = "0.02 0.05";
            public string HealthBarAnchorMax = "0.98 0.22";
            public string HealthBarBackColor = "0 0 0 0.35";
            public string HealthBarFillColor = "0.8 0.1 0.1 0.9";
            public float HealthBarBorderThickness = 0.06f; // relative to bar height (0..0.2)
        }

        public class EnrageIndicatorSettings
        {
            public bool Enabled = true;
            public string TextColor = "1 0.2 0.2 1";
            public int FontSize = 14;

            // Position BELOW the title plate panel (as a separate UI element)
            public string AnchorMin = "0.0 0.0";
            public string AnchorMax = "1.0 0.0";
            public string OffsetMin = "0 -18";
            public string OffsetMax = "0 -4";
            public string Format = "ENRAGED: {seconds}s";
        }

        public class TierConfig
        {
            public string DisplayName;
            public double LockoutMinutes;
            public bool AutoSpawn;
            public double AutoRespawnMinutes;
        }

        public class BeastDef
        {
            public string DisplayName;
            public string TierId;
            public string Theme;
            public string Prefab;
            public float BaseHealth;
            public float DamageMultiplier;
            public float InitialScale = 1f;
            public float EnragedScale = 1f;

            public RoarSettings AbilityRoar = new RoarSettings();
            public ChargeSettings AbilityCharge = new ChargeSettings();
            public FrostAuraSettings AbilityFrostAura = new FrostAuraSettings();
            public CubSummonSettings AbilityCubSummon = new CubSummonSettings();
            public EnrageSettings AbilityEnrage = new EnrageSettings();
            public FireTrailSettings AbilityFireTrail = new FireTrailSettings();

            public List<LootEntry> Loot = new List<LootEntry>();
            public List<PhaseScale> PhaseScales = new List<PhaseScale>();
        }

        public class RoarSettings
        {
            public bool Enabled;
            public float Interval;
            public float Radius;
            public float Damage;
            public float Bleed;
            public float ScreenShake;
        }

        public class ChargeSettings
        {
            public bool Enabled;
            public float Interval;
            public float Range;
            public float ImpactRadius;
            public float ImpactDamage;
            public float ChargeForce;
        }

        public class FrostAuraSettings
        {
            public bool Enabled;
            public float Interval;
            public float Radius;
            public float Duration;
            public float TickRate;
            public float DamagePerTick;
            public float ColdPerTick;
        }

        public class CubSummonSettings
        {
            public bool Enabled;
            public float TriggerHealthFraction;
            public int Count;
            public string Prefab;
            public float Radius;
        }

        public class EnrageSettings
        {
            public bool Enabled;
            public float TriggerHealthFraction;
            public float DamageMultiplier;
            public float SpeedMultiplier;
            public string EffectPrefab = null;  // Falls back to FxLibrary "enrage_burst" if null
            public float Duration = 10f;  // Duration of enrage effect in seconds
        }

        public class FireTrailSettings
        {
            public bool Enabled;
            public float Interval;
            public float Duration;
            public float Step;
            public float Radius;
            public float DamagePerStep;
        }

        public class PhaseScale
        {
            // Health fraction at or below which this phase is triggered (0-1, e.g. 0.75 = 75% HP).
            public float HealthFraction;

            // Scale to apply when this phase triggers (e.g. 1.1, 1.3, 1.5).
            public float Scale;
        }

        public class LootEntry
        {
            public string ShortName;
            public int Amount;
            public ulong Skin;
        }

        protected override void LoadDefaultConfig()
        {
            _config = new ConfigData();
            SaveConfig();
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                _config = Config.ReadObject<ConfigData>();
                if (_config == null) throw new Exception();
            }
            catch
            {
                PrintWarning("Invalid config, generating new one.");
                LoadDefaultConfig();
            }
        }

        protected override void SaveConfig() => Config.WriteObject(_config, true);

        #endregion

        #region Data & State

        private class Vector3Serializable
        {
            public float x;
            public float y;
            public float z;

            public Vector3 ToVector3() => new Vector3(x, y, z);

            public static Vector3Serializable FromVector3(Vector3 v) =>
                new Vector3Serializable { x = v.x, y = v.y, z = v.z };
        }

        private class SpawnPoint
        {
            public Vector3Serializable Position;
            public float Weight = 1f;
        }

        private class StoredData
        {
            public Dictionary<string, List<Vector3Serializable>> TierSpawns =
                new Dictionary<string, List<Vector3Serializable>>();

            public Dictionary<string, List<SpawnPoint>> Spawnpoints =
                new Dictionary<string, List<SpawnPoint>>();

            public Dictionary<string, Dictionary<ulong, double>> TierLockouts =
                new Dictionary<string, Dictionary<ulong, double>>();

            // Per-player tier progression (replaces global TierKills)
            public Dictionary<ulong, PlayerTierProgress> PlayerProgress =
                new Dictionary<ulong, PlayerTierProgress>();
        }

        private StoredData _data;

        private const string ExternalHudPermission = "targethealthhud.use";

        // Players for whom we've temporarily revoked TargetHealthHUD permission
        private readonly HashSet<ulong> _suspendedExternalHud = new HashSet<ulong>();

        private readonly HashSet<BaseEntity> _bosses = new HashSet<BaseEntity>();
        private readonly Dictionary<ulong, float> _damageMeter = new Dictionary<ulong, float>();
        private readonly Dictionary<uint, BeastDef> _beastDefs = new Dictionary<uint, BeastDef>();
        private readonly Dictionary<uint, float> _bossDamageMultipliers = new Dictionary<uint, float>();

        private readonly Dictionary<string, BaseEntity> _activeBossByTier = new Dictionary<string, BaseEntity>();
        private readonly Dictionary<uint, string> _bossTierById = new Dictionary<uint, string>();
        private readonly Dictionary<string, double> _tierLastDeathTime = new Dictionary<string, double>();
        private readonly Dictionary<uint, MapMarkerGenericRadius> _bossMarkers =
            new Dictionary<uint, MapMarkerGenericRadius>();

        // HUD tracking: player -> boss & timers
        private readonly Dictionary<ulong, BaseCombatEntity> _hudBossTargets = new Dictionary<ulong, BaseCombatEntity>();
        private readonly Dictionary<ulong, Timer> _hudUpdateTimers = new Dictionary<ulong, Timer>();
        private readonly Dictionary<ulong, Timer> _hudExpireTimers = new Dictionary<ulong, Timer>();

        // Marker update timer and proximity warning cooldowns
        private Timer _markerUpdateTimer;
        private Timer _worldEventTimer;
        private readonly Dictionary<ulong, float> _proximityCooldown = new Dictionary<ulong, float>();

        // Boss component lookup for leash system and spawn point retrieval
        private readonly Dictionary<uint, BeastComponent> _bossComponents = new Dictionary<uint, BeastComponent>();

        // Mythic boss tracking
        private readonly HashSet<uint> _mythicBossIds = new HashSet<uint>();

        // Runtime name and theme overrides (for mythic variants)
        private readonly Dictionary<uint, string> _runtimeBossName = new Dictionary<uint, string>();
        private readonly Dictionary<uint, string> _runtimeBossTheme = new Dictionary<uint, string>();

        // Last attacker tracking for target acquisition (when npc.Target unavailable)
        private readonly Dictionary<uint, ulong> _lastAttacker = new Dictionary<uint, ulong>();
        private readonly Dictionary<uint, float> _lastAttackerAt = new Dictionary<uint, float>();

        // Title plate (CUI overlay) timer
        private Timer _titlePlateTimer;

        private const string TitlePlateUi = "BeastBoss_TitlePlateUI";

        private void LoadData()
        {
            try
            {
                _data = Interface.Oxide.DataFileSystem.ReadObject<StoredData>("BeastBossData");
            }
            catch
            {
                _data = new StoredData();
            }

            if (_data.TierSpawns == null)
                _data.TierSpawns = new Dictionary<string, List<Vector3Serializable>>();
            if (_data.Spawnpoints == null)
                _data.Spawnpoints = new Dictionary<string, List<SpawnPoint>>();
            if (_data.TierLockouts == null)
                _data.TierLockouts = new Dictionary<string, Dictionary<ulong, double>>();
            if (_data.PlayerProgress == null)
                _data.PlayerProgress = new Dictionary<ulong, PlayerTierProgress>();
        }

        private void SaveData()
        {
            Interface.Oxide.DataFileSystem.WriteObject("BeastBossData", _data);
        }

        #endregion

        #region Constants

        private const string TIER_FRAME_BASE_URL = "https://raw.githubusercontent.com/jmg5215/BeastBosses/main/assets/ui_images/";
        private const float HUD_MAX_DISTANCE = 80f; // Max distance for HUD visibility before removal

        #endregion

        #region Hooks

        private void OnServerInitialized()
        {
            RegisterTierFrameImages();
        }

        private void Init()
        {
            permission.RegisterPermission(_config.PermissionAdmin, this);
            LoadData();
            StartAutoSpawnTimer();

            // Start marker update timer
            if (_markerUpdateTimer == null && _config.Markers.Enabled)
                _markerUpdateTimer = timer.Every(Mathf.Max(1f, _config.Markers.UpdateIntervalSeconds), UpdateBossMarkers);

            // Start title plate update timer
            if (_titlePlateTimer == null && _config.TitlePlate.Enabled)
                _titlePlateTimer = timer.Every(Mathf.Max(0.5f, _config.TitlePlate.UpdateIntervalSeconds), UpdateTitlePlates);

            // Schedule world events
            if (_config.WorldEvents.Enabled)
                ScheduleNextWorldEvent();
        }

        private void Unload()
        {
            foreach (var boss in _bosses.ToList())
            {
                if (boss == null) continue;
                var comp = boss.GetComponent<BeastComponent>();
                if (comp != null) UnityEngine.Object.Destroy(comp);
            }

            foreach (var marker in _bossMarkers.Values)
            {
                if (marker != null && !marker.IsDestroyed)
                    marker.Kill();
            }

            foreach (var player in BasePlayer.activePlayerList)
            {
                RemoveHud(player);
                DestroyTitlePlate(player);
            }

            _bosses.Clear();
            _beastDefs.Clear();
            _bossDamageMultipliers.Clear();
            _activeBossByTier.Clear();
            _bossTierById.Clear();
            _bossMarkers.Clear();
            _proximityCooldown.Clear();
            _bossComponents.Clear();
            _mythicBossIds.Clear();
            _runtimeBossName.Clear();
            _runtimeBossTheme.Clear();
            _lastAttacker.Clear();
            _lastAttackerAt.Clear();

            if (_markerUpdateTimer != null)
            {
                _markerUpdateTimer.Destroy();
                _markerUpdateTimer = null;
            }

            if (_titlePlateTimer != null)
            {
                _titlePlateTimer.Destroy();
                _titlePlateTimer = null;
            }

            if (_worldEventTimer != null)
            {
                _worldEventTimer.Destroy();
                _worldEventTimer = null;
            }

            foreach (var userId in _suspendedExternalHud.ToList())
            {
                RestoreExternalHud(userId);
            }
            _suspendedExternalHud.Clear();

            SaveData();
        }

        private void StartAutoSpawnTimer()
        {
            if (_config.EventCheckIntervalSeconds <= 0f)
                _config.EventCheckIntervalSeconds = 60f;

            timer.Every(_config.EventCheckIntervalSeconds, CheckAutoSpawns);
        }

        private void CheckAutoSpawns()
        {
            var now = Interface.Oxide.Now;

            foreach (var kv in _config.Tiers)
            {
                var tierId = kv.Key;
                var tier = kv.Value;

                if (!tier.AutoSpawn)
                    continue;

                if (_activeBossByTier.TryGetValue(tierId, out var existing) &&
                    existing != null && !existing.IsDestroyed)
                    continue;

                _tierLastDeathTime.TryGetValue(tierId, out var lastDeath);
                var respawnDelaySeconds = Math.Max(0, tier.AutoRespawnMinutes) * 60;
                if (now - lastDeath < respawnDelaySeconds)
                    continue;

                if (!_data.TierSpawns.TryGetValue(tierId, out var spawns) || spawns.Count == 0)
                    continue;

                var beastsInTier = _config.Beasts.Values
                    .Where(b => string.Equals(b.TierId, tierId, StringComparison.OrdinalIgnoreCase))
                    .ToList();

                if (beastsInTier.Count == 0)
                    continue;

                var spawn = spawns.GetRandom();
                var pos = spawn.ToVector3();
                pos.y = TerrainMeta.HeightMap.GetHeight(pos);

                var def = beastsInTier.GetRandom();
                SpawnBeast(def, pos);
            }
        }

        private string GetMythicDisplayName(BeastDef def)
        {
            return _config.Mythic.NamePrefix + def.DisplayName + _config.Mythic.NameSuffix;
        }

        private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
        {
            if (entity == null || info == null) return;

            // Outgoing damage from boss
            if (info.Initiator != null && _bosses.Contains(info.Initiator))
            {
                uint initiatorId = NetId(info.Initiator);
                float mult = 1f;
                if (_bossDamageMultipliers.TryGetValue(initiatorId, out var m))
                    mult = m;

                info.damageTypes.ScaleAll(_config.GlobalOutgoingDamageMultiplier * mult);
            }

            // Incoming damage to boss
            if (_bosses.Contains(entity))
            {
                BeastDef def;
                uint bossId = NetId(entity);
                _beastDefs.TryGetValue(bossId, out def);
                var tierId = def != null ? def.TierId : null;

                var initiatorPlayer = info.InitiatorPlayer;
                
                // Track last attacker for target acquisition fallback
                if (bossId != 0 && initiatorPlayer != null)
                {
                    _lastAttacker[bossId] = initiatorPlayer.userID;
                    _lastAttackerAt[bossId] = Time.realtimeSinceStartup;
                }
                
                if (initiatorPlayer != null && !string.IsNullOrEmpty(tierId))
                {
                    if (IsPlayerLockedOut(initiatorPlayer.userID, tierId, out var remainingSeconds))
                    {
                        info.damageTypes.ScaleAll(0f);
                        var mins = Mathf.CeilToInt((float)(remainingSeconds / 60d));
                        initiatorPlayer.Ch
// ... [Code preview truncated due to length. Full source in attached file] ...

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху