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(); }
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); } }
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}"); }
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}"); }
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(); } }
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); } }
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); }
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()); }
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); }
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>()); } } }
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>(); } }
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); }
public static void RPC_ClientKnownRecipes(long sender, ZPackage pkg) { var recipeCount = LoadKnownRecipes(sender, pkg, PlayerKnownRecipes); EpicLoot.Log($"Received known from peer {sender}: {recipeCount} recipes"); }
public static void RPC_ClientKnownMats(long sender, ZPackage pkg) { var materialCount = LoadKnownMats(sender, pkg, PlayerKnownMaterial); EpicLoot.Log($"Received known from peer {sender}: {materialCount} materials"); }