static bool Prefix(MonsterAI __instance, float dt, ref ZNetView ___m_nview, ref Character ___m_character, ref float ___m_timeSinceHurt, ref float ___m_jumpInterval, ref float ___m_jumpTimer, ref float ___m_randomMoveUpdateTimer, ref bool ___m_alerted) { if (!___m_nview.IsValid()) { return(true); } var uniqueId = ___m_nview.GetZDO().GetString(Constants.Z_CharacterId); if (string.IsNullOrEmpty(uniqueId)) { return(true); } if (!MobManager.IsRegisteredMob(uniqueId)) { return(true); } var mobAI = GetOrCreateMob(uniqueId, __instance, ___m_nview); if (null == mobAI) { return(true); } if (!___m_nview.IsOwner()) { return(false); } if (__instance.IsSleeping()) { Invoke(__instance, "UpdateSleep", new object[] { dt }); Common.Dbgl($"{___m_character.GetHoverName()}: Sleep updated"); return(false); } BaseAI_UpdateAI_ReversePatch.UpdateAI(__instance, dt, ___m_nview, ref ___m_jumpInterval, ref ___m_jumpTimer, ref ___m_randomMoveUpdateTimer, ref ___m_timeSinceHurt, ref ___m_alerted); mobAI.UpdateAI(dt); return(false); }
static bool Prefix(MonsterAI __instance, float dt, ref ZNetView ___m_nview, ref Character ___m_character, ref float ___m_fleeIfLowHealth, ref float ___m_timeSinceHurt, ref string ___m_aiStatus, ref Vector3 ___arroundPointTarget, ref float ___m_jumpInterval, ref float ___m_jumpTimer, ref float ___m_randomMoveUpdateTimer, ref bool ___m_alerted, ref Tameable ___m_tamable) { if (!___m_nview.IsOwner()) { return(false); } if (!___m_character.IsTamed()) { return(true); } if (!__instance.name.Contains("Greyling")) { return(true); } if (__instance.IsSleeping()) { Invoke(__instance, "UpdateSleep", new object[] { dt }); Dbgl($"{___m_character.GetHoverName()}: Sleep updated"); return(false); } BaseAI_UpdateAI_ReversePatch.UpdateAI(__instance, dt, ___m_nview, ref ___m_jumpInterval, ref ___m_jumpTimer, ref ___m_randomMoveUpdateTimer, ref ___m_timeSinceHurt, ref ___m_alerted); int instanceId = InitInstanceIfNeeded(__instance); Dbgl("GetInstanceID ok"); ___m_aiStatus = ""; Vector3 greylingPosition = ___m_character.transform.position; if (___m_timeSinceHurt < 20f) { __instance.Alert(); var fleeFrom = m_attacker == null ? ___m_character.transform.position : m_attacker.transform.position; Invoke(__instance, "Flee", new object[] { dt, fleeFrom }); ___m_aiStatus = UpdateAiStatus(___m_nview, "Got hurt, flee!"); return(false); } else { m_attacker = null; Invoke(__instance, "SetAlerted", new object[] { false }); } if ((bool)__instance.GetFollowTarget()) { Invoke(__instance, "Follow", new object[] { __instance.GetFollowTarget(), dt }); ___m_aiStatus = UpdateAiStatus(___m_nview, "Follow"); Invoke(__instance, "SetAlerted", new object[] { false }); m_assignment[instanceId].Clear(); m_fetchitems[instanceId].Clear(); m_assigned[instanceId] = false; m_spottedItem[instanceId] = null; m_containers[instanceId].Clear(); m_searchcontainer[instanceId] = false; m_stateChangeTimer[instanceId] = 0; return(false); } if (AvoidFire(__instance, dt, m_assigned[instanceId] ? m_assignment[instanceId].Peek().Position : __instance.transform.position)) { ___m_aiStatus = UpdateAiStatus(___m_nview, "Avoiding fire"); if (m_assignment[instanceId].Any() && m_assignment[instanceId].Peek().IsClose(___m_character.transform.position)) { m_assigned[instanceId] = false; } return(false); } if (!__instance.IsAlerted() && (bool)Invoke(__instance, "UpdateConsumeItem", new object[] { ___m_character as Humanoid, dt })) { ___m_aiStatus = UpdateAiStatus(___m_nview, "Consume item"); return(false); } if (___m_tamable.IsHungry()) { ___m_aiStatus = UpdateAiStatus(___m_nview, "Is hungry, no work a do"); if (m_searchcontainer[instanceId] && m_containers[instanceId].Any()) { bool containerIsInvalid = m_containers[instanceId].Peek()?.GetComponent <ZNetView>()?.IsValid() == false; if (containerIsInvalid) { m_containers[instanceId].Pop(); m_searchcontainer[instanceId] = false; return(false); } bool isCloseToContainer = Vector3.Distance(greylingPosition, m_containers[instanceId].Peek().transform.position) < 1.5; if (!isCloseToContainer) { Invoke(__instance, "MoveAndAvoid", new object[] { dt, m_containers[instanceId].Peek().transform.position, 0.5f, false }); return(false); } else { ItemDrop foodItem = __instance.m_consumeItems.ElementAt <ItemDrop>(0); ItemDrop.ItemData item = m_containers[instanceId].Peek()?.GetInventory()?.GetItem(foodItem.m_itemData.m_shared.m_name); if (item == null) { ___m_aiStatus = UpdateAiStatus(___m_nview, "No Resin in chest"); Container nearbyChest = FindRandomNearbyContainer(greylingPosition, m_containers[instanceId]); if (nearbyChest != null) { m_containers[instanceId].Push(nearbyChest); m_searchcontainer[instanceId] = true; return(false); } else { m_containers[instanceId].Clear(); m_searchcontainer[instanceId] = false; return(false); } } else { ___m_aiStatus = UpdateAiStatus(___m_nview, "Resin in chest"); m_containers[instanceId].Peek().GetInventory().RemoveItem(item, 1); typeof(Container).GetMethod("Save", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(m_containers[instanceId].Peek(), new object[] { }); typeof(Inventory).GetMethod("Changed", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(m_containers[instanceId].Peek().GetInventory(), new object[] { }); __instance.m_onConsumedItem(foodItem); ___m_aiStatus = UpdateAiStatus(___m_nview, "Consume item"); m_assigned[instanceId] = false; m_spottedItem[instanceId] = null; m_searchcontainer[instanceId] = false; m_stateChangeTimer[instanceId] = 0; return(false); } } } else { Container nearbyChest = FindRandomNearbyContainer(greylingPosition, m_containers[instanceId]); if (nearbyChest != null) { m_containers[instanceId].Push(nearbyChest); m_searchcontainer[instanceId] = true; return(false); } else { m_searchcontainer[instanceId] = false; return(false); } } } // Here starts the fun. //Assigned timeout-function m_assignedTimer[instanceId] += dt; if (m_assignedTimer[instanceId] > GreylingsConfig.TimeLimitOnAssignment.Value) { m_assigned[instanceId] = false; } //Assignment timeout-function foreach (Assignment assignment in m_assignment[instanceId]) { assignment.AssignmentTime += dt; int multiplicator = 1; if (assignment.TypeOfAssignment.ComponentType == typeof(Fireplace)) { multiplicator = 3; } if (assignment.AssignmentTime > GreylingsConfig.TimeBeforeAssignmentCanBeRepeated.Value * multiplicator) { ___m_aiStatus = UpdateAiStatus(___m_nview, $"removing outdated Assignment of {m_assignment[instanceId].Count()}"); m_assignment[instanceId].Remove(assignment); ___m_aiStatus = UpdateAiStatus(___m_nview, $"remaining Assignments {m_assignment[instanceId].Count()}"); if (!m_assignment[instanceId].Any()) { m_assigned[instanceId] = false; } break; } } //stateChangeTimer Updated m_stateChangeTimer[instanceId] += dt; if (m_stateChangeTimer[instanceId] < 1) { return(false); } if (!m_assigned[instanceId]) { if (FindRandomNearbyAssignment(instanceId, greylingPosition)) { ___m_aiStatus = UpdateAiStatus(___m_nview, $"Doing assignment: {m_assignment[instanceId].Peek().TypeOfAssignment.Name}"); return(false); } else { //___m_aiStatus = UpdateAiStatus(___m_nview, $"No new assignments found"); m_assignment[instanceId].Clear(); } } if (m_assigned[instanceId]) { var humanoid = ___m_character as Humanoid; Assignment assignment = m_assignment[instanceId].Peek(); bool assignmentIsInvalid = assignment?.AssignmentObject?.GetComponent <ZNetView>()?.IsValid() == false; if (assignmentIsInvalid) { m_assignment[instanceId].Pop(); m_assigned[instanceId] = false; return(false); } bool knowWhattoFetch = m_fetchitems[instanceId].Any(); bool isCarryingItem = m_carrying[instanceId] != null; if ((!knowWhattoFetch || isCarryingItem) && !assignment.IsClose(greylingPosition)) { ___m_aiStatus = UpdateAiStatus(___m_nview, $"Move To Assignment: {assignment.TypeOfAssignment.Name} "); Invoke(__instance, "MoveAndAvoid", new object[] { dt, assignment.Position, 0.5f, false }); if (m_stateChangeTimer[instanceId] < 30) { return(false); } } bool isLookingAtAssignment = (bool)Invoke(__instance, "IsLookingAt", new object[] { assignment.Position, 20f }); if (isCarryingItem && assignment.IsClose(greylingPosition) && !isLookingAtAssignment) { ___m_aiStatus = UpdateAiStatus(___m_nview, $"Looking at Assignment: {assignment.TypeOfAssignment.Name} "); humanoid.SetMoveDir(Vector3.zero); Invoke(__instance, "LookAt", new object[] { assignment.Position }); return(false); } if (isCarryingItem && assignment.IsCloseEnough(greylingPosition)) { humanoid.SetMoveDir(Vector3.zero); var needFuel = assignment.NeedFuel; var needOre = assignment.NeedOre; bool isCarryingFuel = m_carrying[instanceId].m_shared.m_name == needFuel?.m_shared?.m_name; bool isCarryingMatchingOre = needOre?.Any(c => m_carrying[instanceId].m_shared.m_name == c?.m_shared?.m_name) ?? false; if (isCarryingFuel) { ___m_aiStatus = UpdateAiStatus(___m_nview, $"Unload to {assignment.TypeOfAssignment.Name} -> Fuel"); assignment.AssignmentObject.GetComponent <ZNetView>().InvokeRPC("AddFuel", new object[] { }); humanoid.GetInventory().RemoveOneItem(m_carrying[instanceId]); } else if (isCarryingMatchingOre) { ___m_aiStatus = UpdateAiStatus(___m_nview, $"Unload to {assignment.TypeOfAssignment.Name} -> Ore"); assignment.AssignmentObject.GetComponent <ZNetView>().InvokeRPC("AddOre", new object[] { GetPrefabName(m_carrying[instanceId].m_dropPrefab.name) }); humanoid.GetInventory().RemoveOneItem(m_carrying[instanceId]); } else { ___m_aiStatus = UpdateAiStatus(___m_nview, Localization.instance.Localize($"Dropping {m_carrying[instanceId].m_shared.m_name} on the ground")); humanoid.DropItem(humanoid.GetInventory(), m_carrying[instanceId], 1); } humanoid.UnequipItem(m_carrying[instanceId], false); m_carrying[instanceId] = null; m_fetchitems[instanceId].Clear(); m_stateChangeTimer[instanceId] = 0; return(false); } if (!knowWhattoFetch && assignment.IsCloseEnough(greylingPosition)) { humanoid.SetMoveDir(Vector3.zero); ___m_aiStatus = UpdateAiStatus(___m_nview, "Checking assignment for task"); var needFuel = assignment.NeedFuel; var needOre = assignment.NeedOre; Dbgl($"Ore:{needOre.Join(j => j.m_shared.m_name)}, Fuel:{needFuel?.m_shared.m_name}"); if (needFuel != null) { m_fetchitems[instanceId].Add(needFuel); ___m_aiStatus = UpdateAiStatus(___m_nview, Localization.instance.Localize($"Adding {needFuel.m_shared.m_name} to search list")); } if (needOre.Any()) { m_fetchitems[instanceId].AddRange(needOre); ___m_aiStatus = UpdateAiStatus(___m_nview, Localization.instance.Localize($"Adding {needOre.Join(o => o.m_shared.m_name)} to search list")); } if (!m_fetchitems[instanceId].Any()) { m_assigned[instanceId] = false; } m_stateChangeTimer[instanceId] = 0; return(false); } bool hasSpottedAnItem = m_spottedItem[instanceId] != null; bool searchForItemToPickup = knowWhattoFetch && !hasSpottedAnItem && !isCarryingItem && !m_searchcontainer[instanceId]; if (searchForItemToPickup) { ___m_aiStatus = UpdateAiStatus(___m_nview, "Search the ground for item to pickup"); ItemDrop spottedItem = GetNearbyItem(greylingPosition, m_fetchitems[instanceId], GreylingsConfig.ItemSearchRadius.Value); if (spottedItem != null) { m_spottedItem[instanceId] = spottedItem; m_stateChangeTimer[instanceId] = 0; return(false); } ___m_aiStatus = UpdateAiStatus(___m_nview, "Trying to remeber content of known Chests"); foreach (Container chest in m_containers[instanceId]) { foreach (var fetchItem in m_fetchitems[instanceId]) { ItemDrop.ItemData item = chest?.GetInventory()?.GetItem(fetchItem.m_shared.m_name); if (item == null) { continue; } else { ___m_aiStatus = UpdateAiStatus(___m_nview, "Item found in old chest"); m_containers[instanceId].Remove(chest); m_containers[instanceId].Push(chest); m_searchcontainer[instanceId] = true; m_stateChangeTimer[instanceId] = 0; return(false); } } } ___m_aiStatus = UpdateAiStatus(___m_nview, "Search for nerby Chests"); Container nearbyChest = FindRandomNearbyContainer(greylingPosition, m_containers[instanceId]); if (nearbyChest != null) { ___m_aiStatus = UpdateAiStatus(___m_nview, "Chest found"); m_containers[instanceId].Push(nearbyChest); m_searchcontainer[instanceId] = true; m_stateChangeTimer[instanceId] = 0; return(false); } } if (m_searchcontainer[instanceId]) { bool containerIsInvalid = m_containers[instanceId].Peek()?.GetComponent <ZNetView>()?.IsValid() == false; if (containerIsInvalid) { m_containers[instanceId].Pop(); m_searchcontainer[instanceId] = false; return(false); } bool isCloseToContainer = Vector3.Distance(greylingPosition, m_containers[instanceId].Peek().transform.position) < 1.5; if (!isCloseToContainer) { ___m_aiStatus = UpdateAiStatus(___m_nview, "Heading to Container"); Invoke(__instance, "MoveAndAvoid", new object[] { dt, m_containers[instanceId].Peek().transform.position, 0.5f, false }); return(false); } else { humanoid.SetMoveDir(Vector3.zero); ___m_aiStatus = UpdateAiStatus(___m_nview, $"Chest inventory:{m_containers[instanceId].Peek()?.GetInventory().GetAllItems().Join(i => i.m_shared.m_name)} from Chest "); var wantedItemsInChest = m_containers[instanceId].Peek()?.GetInventory()?.GetAllItems()?.Where(i => m_fetchitems[instanceId].Contains(i)); foreach (var fetchItem in m_fetchitems[instanceId]) { ItemDrop.ItemData item = m_containers[instanceId].Peek()?.GetInventory()?.GetItem(fetchItem.m_shared.m_name); if (item == null) { continue; } else { ___m_aiStatus = UpdateAiStatus(___m_nview, $"Trying to Pickup {item} from Chest "); var pickedUpInstance = humanoid.PickupPrefab(item.m_dropPrefab); humanoid.GetInventory().Print(); humanoid.EquipItem(pickedUpInstance); m_containers[instanceId].Peek().GetInventory().RemoveItem(item, 1); typeof(Container).GetMethod("Save", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(m_containers[instanceId].Peek(), new object[] { }); typeof(Inventory).GetMethod("Changed", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(m_containers[instanceId].Peek().GetInventory(), new object[] { }); m_carrying[instanceId] = pickedUpInstance; m_spottedItem[instanceId] = null; m_fetchitems[instanceId].Clear(); m_searchcontainer[instanceId] = false; m_stateChangeTimer[instanceId] = 0; return(false); } } m_searchcontainer[instanceId] = false; m_stateChangeTimer[instanceId] = 0; return(false); } } if (hasSpottedAnItem) { bool isNotCloseToPickupItem = Vector3.Distance(greylingPosition, m_spottedItem[instanceId].transform.position) > 1; if (isNotCloseToPickupItem) { ___m_aiStatus = UpdateAiStatus(___m_nview, "Heading to pickup item"); Invoke(__instance, "MoveAndAvoid", new object[] { dt, m_spottedItem[instanceId].transform.position, 0.5f, false }); return(false); } else // Pickup item from ground { humanoid.SetMoveDir(Vector3.zero); ___m_aiStatus = UpdateAiStatus(___m_nview, $"Trying to Pickup {m_spottedItem[instanceId].gameObject.name}"); var pickedUpInstance = humanoid.PickupPrefab(m_spottedItem[instanceId].m_itemData.m_dropPrefab); humanoid.GetInventory().Print(); humanoid.EquipItem(pickedUpInstance); if (m_spottedItem[instanceId].m_itemData.m_stack == 1) { if (___m_nview.GetZDO() == null) { Destroy(m_spottedItem[instanceId].gameObject); } else { ZNetScene.instance.Destroy(m_spottedItem[instanceId].gameObject); } } else { m_spottedItem[instanceId].m_itemData.m_stack--; Traverse.Create(m_spottedItem[instanceId]).Method("Save").GetValue(); } m_carrying[instanceId] = pickedUpInstance; m_spottedItem[instanceId] = null; m_fetchitems[instanceId].Clear(); m_stateChangeTimer[instanceId] = 0; return(false); } } ___m_aiStatus = UpdateAiStatus(___m_nview, $"Done with assignment"); if (m_carrying[instanceId] != null) { humanoid.UnequipItem(m_carrying[instanceId], false); m_carrying[instanceId] = null; ___m_aiStatus = UpdateAiStatus(___m_nview, $"Dropping unused item"); } m_fetchitems[instanceId].Clear(); m_spottedItem[instanceId] = null; m_containers[instanceId].Clear(); m_searchcontainer[instanceId] = false; m_assigned[instanceId] = false; m_stateChangeTimer[instanceId] = 0; return(false); } ___m_aiStatus = UpdateAiStatus(___m_nview, "Random movement (No new assignments found)"); typeof(MonsterAI).GetMethod("IdleMovement", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(__instance, new object[] { dt }); return(false); }