コード例 #1
0
        private void AddSlainBountyTargetToLedger(BountyInfo bounty, string monsterID, bool isAdd)
        {
            if (!Common.Utils.IsServer())
            {
                return;
            }

            if (BountyLedger == null)
            {
                EpicLoot.LogError("[BountyLedger] Server tried to add kill log to bounty ledger but BountyLedger was null");
                return;
            }

            if (Player.m_localPlayer != null && Player.m_localPlayer.GetPlayerID() == bounty.PlayerID)
            {
                EpicLoot.Log($"[BountyLedger] This player ({bounty.PlayerID}) is the local player");
                return;
            }

            var characterZdos  = ZNet.instance.GetAllCharacterZDOS();
            var playerIsOnline = characterZdos.Select(zdo => zdo.GetLong("playerID")).Any(playerID => playerID == bounty.PlayerID);

            if (playerIsOnline)
            {
                EpicLoot.Log($"[BountyLedger] This player ({bounty.PlayerID}) is connected to server, don't log the kill, they'll get the RPC");
                return;
            }

            BountyLedger.AddKillLog(bounty.PlayerID, bounty.ID, monsterID, isAdd);
            SaveBountyLedger();
        }
コード例 #2
0
        public static void CheckAndDoLifeSteal(HitData hit)
        {
            try
            {
                if (!hit.HaveAttacker())
                {
                    return;
                }

                var attacker = hit.GetAttacker() as Humanoid;
                if (attacker == null)
                {
                    return;
                }

                // TODO track actual weapon which made a hit for better life-steal calculation
                var weapon = attacker.GetCurrentWeapon();

                // in case weapon's durability is destroyed after hit?
                // OR in case damage is delayed and player hides weapon - see to-do above
                if (weapon == null || !weapon.IsMagic() || !(attacker is Player player))
                {
                    return;
                }

                var lifeStealMultiplier = 0f;
                ModifyWithLowHealth.Apply(player, MagicEffectType.LifeSteal, effect => lifeStealMultiplier += player.GetTotalActiveMagicEffectValue(effect, 0.01f));

                if (lifeStealMultiplier == 0)
                {
                    return;
                }

                var healOn = hit.m_damage.GetTotalDamage() * lifeStealMultiplier;

                EpicLoot.Log("lifesteal " + healOn);
                var healFromQueue = false;
                if (attacker.IsPlayer())
                {
                    var healingQueue = attacker.GetComponent <HealingQueueMono>();
                    if (healingQueue)
                    {
                        healFromQueue = true;
                        healingQueue.HealRequests.Add(healOn);
                    }
                }

                if (!healFromQueue)
                {
                    // mostly for NPC with lifeSteal weapon
                    attacker.Heal(healOn);
                }
            }
            catch (Exception e)
            {
                EpicLoot.LogError(e.Message);
            }
        }
コード例 #3
0
 public static void RPC_AddKnownRecipe(long sender, string recipe)
 {
     if (!PlayerKnownRecipes.TryGetValue(sender, out var knownRecipes))
     {
         EpicLoot.LogWarning($"PlayerKnownManager.RPC_AddKnownRecipe: hashset is null for peer {sender}");
         return;
     }
     knownRecipes.Add(recipe);
     EpicLoot.Log($"Received add known recipe from peer {sender}: {recipe}");
 }
コード例 #4
0
 public static void RPC_AddKnownMaterial(long sender, string material)
 {
     if (!PlayerKnownMaterial.TryGetValue(sender, out var knownMaterial))
     {
         EpicLoot.LogWarning($"PlayerKnownManager.RPC_AddKnownMaterial: hashset is null for peer {sender}");
         return;
     }
     knownMaterial.Add(material);
     EpicLoot.Log($"Received add known material from peer {sender}: {material}");
 }
コード例 #5
0
        private static void OnBountyTargetSlain(string bountyID, string monsterID, bool isAdd)
        {
            var player = Player.m_localPlayer;

            if (player == null)
            {
                return;
            }

            var saveData   = player.GetAdventureSaveData();
            var bountyInfo = saveData.GetBountyInfoByID(bountyID);

            if (bountyInfo == null || bountyInfo.PlayerID != player.GetPlayerID())
            {
                // Someone else's bounty
                return;
            }

            if (!saveData.HasAcceptedBounty(bountyInfo.Interval, bountyInfo.ID) || bountyInfo.State != BountyState.InProgress)
            {
                return;
            }

            EpicLoot.Log($"Bounty Target Slain: bounty={bountyInfo.ID} monsterId={monsterID} ({(isAdd ? "add" : "main target")})");

            if (!isAdd && bountyInfo.Target.MonsterID == monsterID)
            {
                bountyInfo.Slain = true;
                player.SaveAdventureSaveData();
            }

            if (isAdd)
            {
                foreach (var addConfig in bountyInfo.Adds)
                {
                    if (addConfig.MonsterID == monsterID && addConfig.Count > 0)
                    {
                        addConfig.Count--;
                        player.SaveAdventureSaveData();
                        break;
                    }
                }
            }

            var isComplete = bountyInfo.Slain && bountyInfo.Adds.Sum(x => x.Count) == 0;

            if (isComplete)
            {
                MessageHud.instance.ShowBiomeFoundMsg("$mod_epicloot_bounties_completemsg", true);
                bountyInfo.State = BountyState.Complete;
                player.SaveAdventureSaveData();
            }
        }
コード例 #6
0
 public static void OnPeerDisconnect(ZNetPeer peer)
 {
     EpicLoot.Log($"Removing known for peer {peer.m_uid}");
     if (PlayerKnownRecipes.ContainsKey(peer.m_uid))
     {
         PlayerKnownRecipes.Remove(peer.m_uid);
     }
     if (PlayerKnownMaterial.ContainsKey(peer.m_uid))
     {
         PlayerKnownMaterial.Remove(peer.m_uid);
     }
 }
コード例 #7
0
        public static bool Prefix(Humanoid __instance, ref bool __result, bool secondaryAttack)
        {
            if (!secondaryAttack)
            {
                return(true);
            }

            __instance.AbortEquipQueue();
            if (__instance.InAttack() && !__instance.HaveQueuedChain() || __instance.InDodge() || !__instance.CanMove() || __instance.IsKnockedBack() || __instance.IsStaggering() || __instance.InMinorAction())
            {
                return(true);
            }

            var currentWeapon = __instance.GetCurrentWeapon();

            if (currentWeapon == null || currentWeapon.m_dropPrefab == null)
            {
                EpicLoot.Log("Weapon or weapon's dropPrefab is null");
                return(true);
            }

            if (!currentWeapon.IsMagic() || !currentWeapon.GetMagicItem().HasEffect(MagicEffectType.Throwable))
            {
                return(true);
            }

            var spearPrefab = ObjectDB.instance?.GetItemPrefab("SpearFlint");

            if (spearPrefab == null)
            {
                return(true);
            }

            if (__instance.m_currentAttack != null)
            {
                __instance.m_currentAttack.Stop();
                __instance.m_previousAttack = __instance.m_currentAttack;
                __instance.m_currentAttack  = null;
            }

            var attack = spearPrefab.GetComponent <ItemDrop>().m_itemData.m_shared.m_secondaryAttack.Clone();

            if (!attack.Start(__instance, __instance.m_body, __instance.m_zanim, __instance.m_animEvent, __instance.m_visEquipment, currentWeapon, __instance.m_previousAttack, __instance.m_timeSinceLastAttack, __instance.GetAttackDrawPercentage()))
            {
                return(false);
            }

            __instance.m_currentAttack   = attack;
            __instance.m_lastCombatTimer = 0.0f;
            __result = true;
            return(false);
        }
コード例 #8
0
        public static string PrintBounties(string label, List <BountyInfo> results)
        {
            var sb = new StringBuilder();

            sb.AppendLine(label);
            for (var index = 0; index < results.Count; index++)
            {
                var bountyInfo = results[index];
                sb.AppendLine($"{index} - {bountyInfo.Interval}, {bountyInfo.Biome}, {bountyInfo.TargetName}, ID={bountyInfo.ID}, state={bountyInfo.State}");
            }

            EpicLoot.Log(sb.ToString());
            return(sb.ToString());
        }
コード例 #9
0
        public static void ClientSendKnownRecipes()
        {
            var player = Player.m_localPlayer;

            if (player == null)
            {
                EpicLoot.LogWarning("PlayerKnownManager.ClientSendKnown: m_localPlayer == null");
                return;
            }

            var pkg = new ZPackage();

            WriteKnownRecipes(player.m_knownRecipes, pkg);

            EpicLoot.Log($"Sending known: {player.m_knownRecipes.Count} recipes");
            ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, Name_RPC_ClientKnownRecipes, pkg);
        }
コード例 #10
0
        public static void Postfix(Container __instance, long uid, bool granted)
        {
            var zdo = __instance.m_nview.GetZDO();

            if (zdo == null || !zdo.IsValid())
            {
                return;
            }

            var hasAlreadyBeenFound = zdo.GetBool("TreasureMapChest.HasBeenFound");

            if (hasAlreadyBeenFound)
            {
                return;
            }

            var player = Player.m_localPlayer;

            if (granted && player != null)
            {
                var treasureMapChest = __instance.GetComponent <TreasureMapChest>();
                if (treasureMapChest != null)
                {
                    EpicLoot.Log($"Player is opening treasure map chest ({treasureMapChest.Biome}, {treasureMapChest.Interval})!");
                    var saveData = player.GetAdventureSaveData();
                    if (saveData.FoundTreasureChest(treasureMapChest.Interval, treasureMapChest.Biome))
                    {
                        player.SaveAdventureSaveData();
                    }

                    zdo.Set("TreasureMapChest.HasBeenFound", true);

                    __instance.m_privacy = Container.PrivacySetting.Public;

                    MessageHud.instance.ShowBiomeFoundMsg("Treasure Found!", true);

                    Object.Destroy(treasureMapChest.GetComponent <Beacon>());
                    Object.Destroy(treasureMapChest.GetComponent <Rigidbody>());
                }
            }
        }
コード例 #11
0
        public static void Postfix(Attack __instance)
        {
            if (__instance.m_weapon.m_lastProjectile != null && __instance.m_weapon.IsMagic() && __instance.m_weapon.GetMagicItem().HasEffect(MagicEffectType.Throwable))
            {
                var existingMesh = __instance.m_weapon.m_lastProjectile.transform.Find("spear");
                if (existingMesh != null)
                {
                    Object.Destroy(existingMesh.gameObject);
                }

                var weaponMesh = __instance.m_weapon.m_dropPrefab.transform.Find("attach");
                if (weaponMesh == null)
                {
                    EpicLoot.Log("Could not find 'attach' object");
                    return;
                }

                var newMesh = Object.Instantiate(weaponMesh.gameObject, __instance.m_weapon.m_lastProjectile.transform, false);
                newMesh.AddComponent <Spinny>();
            }
        }
コード例 #12
0
        protected static IEnumerator GetRandomPointInBiome(Heightmap.Biome biome, AdventureSaveData saveData, Action <bool, Vector3, Vector3> onComplete)
        {
            const int maxRangeIncreases = 10;
            const int maxPointsInRange  = 15;

            MerchantPanel.ShowInputBlocker(true);

            var rangeTries  = 0;
            var radiusRange = GetTreasureMapSpawnRadiusRange(biome, saveData);

            while (rangeTries < maxRangeIncreases)
            {
                rangeTries++;

                var tries = 0;
                while (tries < maxPointsInRange)
                {
                    tries++;

                    var randomPoint = UnityEngine.Random.insideUnitCircle;
                    var mag         = randomPoint.magnitude;
                    var normalized  = randomPoint.normalized;
                    var actualMag   = Mathf.Lerp(radiusRange.Item1, radiusRange.Item2, mag);
                    randomPoint = normalized * actualMag;
                    var spawnPoint = new Vector3(randomPoint.x, 0, randomPoint.y);

                    var zoneId = ZoneSystem.instance.GetZone(spawnPoint);
                    while (!ZoneSystem.instance.SpawnZone(zoneId, ZoneSystem.SpawnMode.Client, out _))
                    {
                        EpicLoot.LogWarning($"Spawning Zone ({zoneId})...");
                        yield return(null);
                    }

                    ZoneSystem.instance.GetGroundData(ref spawnPoint, out var normal, out var foundBiome, out _, out _);
                    var groundHeight = spawnPoint.y;

                    EpicLoot.Log($"Checking biome at ({randomPoint}): {foundBiome} (try {tries})");
                    if (foundBiome != biome)
                    {
                        // Wrong biome
                        continue;
                    }

                    var solidHeight      = ZoneSystem.instance.GetSolidHeight(spawnPoint);
                    var offsetFromGround = Math.Abs(solidHeight - groundHeight);
                    if (offsetFromGround > 5)
                    {
                        // Don't place too high off the ground (on top of tree or something?
                        EpicLoot.Log($"Spawn Point rejected: too high off of ground (groundHeight:{groundHeight}, solidHeight:{solidHeight})");
                        continue;
                    }

                    // But also don't place inside rocks
                    spawnPoint.y = solidHeight;

                    var placedNearPlayerBase = EffectArea.IsPointInsideArea(spawnPoint, EffectArea.Type.PlayerBase, AdventureDataManager.Config.TreasureMap.MinimapAreaRadius);
                    if (placedNearPlayerBase)
                    {
                        // Don't place near player base
                        EpicLoot.Log("Spawn Point rejected: too close to player base");
                        continue;
                    }

                    EpicLoot.Log($"Wards: {PrivateArea.m_allAreas.Count}");
                    var tooCloseToWard = PrivateArea.m_allAreas.Any(x => x.IsInside(spawnPoint, AdventureDataManager.Config.TreasureMap.MinimapAreaRadius));
                    if (tooCloseToWard)
                    {
                        EpicLoot.Log("Spawn Point rejected: too close to player ward");
                        continue;
                    }

                    var waterLevel = ZoneSystem.instance.m_waterLevel;
                    if (waterLevel > groundHeight + 1.0f)
                    {
                        // Too deep, try again
                        EpicLoot.Log($"Spawn Point rejected: too deep underwater (waterLevel:{waterLevel}, groundHeight:{groundHeight})");
                        continue;
                    }

                    EpicLoot.Log($"Success! (ground={groundHeight} water={waterLevel} placed={spawnPoint.y})");

                    onComplete?.Invoke(true, spawnPoint, normal);
                    MerchantPanel.ShowInputBlocker(false);
                    yield break;
                }

                radiusRange = new Tuple <float, float>(radiusRange.Item1 + 500, radiusRange.Item2 + 500);
            }

            onComplete?.Invoke(false, new Vector3(), new Vector3());
            MerchantPanel.ShowInputBlocker(false);
        }
コード例 #13
0
        public static void RPC_ClientKnownRecipes(long sender, ZPackage pkg)
        {
            var recipeCount = LoadKnownRecipes(sender, pkg, PlayerKnownRecipes);

            EpicLoot.Log($"Received known from peer {sender}: {recipeCount} recipes");
        }
コード例 #14
0
        public static void RPC_ClientKnownMats(long sender, ZPackage pkg)
        {
            var materialCount = LoadKnownMats(sender, pkg, PlayerKnownMaterial);

            EpicLoot.Log($"Received known from peer {sender}: {materialCount} materials");
        }