using Audio; using Platform; namespace Harmony.EntityVehiclePatches { internal class EntityVehiclePatches { [HarmonyPatch(typeof(EntityVehicle))] [HarmonyPatch("OnCollisionForward")] public class OnCollisionForwardPatch { private static bool Prefix(EntityVehicle __instance, Transform t, Collision collision, bool isStay) { if (__instance.isEntityRemote) return false; if (!__instance.RBActive) { if ((double)__instance.vehicleRB.velocity.magnitude > 0.0099999997764825821 && (double)__instance.vehicleRB.angularVelocity.magnitude > 0.05000000074505806) __instance.RBActive = true; if (__instance.vehicleRB.isKinematic && (!(bool)(UnityEngine.Object)collision.rigidbody || (double)collision.rigidbody.velocity.magnitude > 0.05000000074505806)) __instance.RBActive = true; } Entity entity = (Entity)null; int layer = collision.gameObject.layer; if (layer != 16) { ColliderHitCallForward component = collision.gameObject.GetComponent(); if ((bool)(UnityEngine.Object)component) entity = component.Entity; if (!(bool)(UnityEngine.Object)entity) entity = __instance.FindEntity(collision.transform.parent); if (!(bool)(UnityEngine.Object)entity) { Rigidbody rigidbody = collision.rigidbody; if ((bool)(UnityEngine.Object)rigidbody) entity = __instance.FindEntity(rigidbody.transform); } } if (entity is EntityPlayer || (entity is EntityNPCRebirth npc && npc.Buffs.GetCustomVar("$Leader") > 0)) { //Log.Out("EntityVehiclePatches-OnCollisionForward entity: " + entity.name); return false; } return true; } } [HarmonyPatch(typeof(EntityVehicle))] [HarmonyPatch("UseHorn")] public class UseHornPatch { private static void Postfix(EntityVehicle __instance) { //Log.Out("EntityVehiclePatches-UseHorn START"); if (__instance.AttachedMainEntity is EntityPlayer) { //Log.Out("EntityVehiclePatches-UseHorn IS PLAYER"); EntityPlayer player = __instance.AttachedMainEntity as EntityPlayer; if (player != null) { //Log.Out("EntityVehiclePatches-UseHorn player: " + player.EntityName); ProgressionValue progressionValue = player.Progression.GetProgressionValue("perkBetterBarter"); if (progressionValue != null && RebirthUtilities.GetCalculatedLevel(player, progressionValue) >= 1) { //Log.Out("EntityVehiclePatches-UseHorn progressionValue: " + progressionValue.level); RebirthUtilities.CheckForTraderDoor(__instance); } } } } } [HarmonyPatch(typeof(EntityVehicle))] [HarmonyPatch("MoveByAttachedEntity")] public class MoveByAttachedEntityPatch { private static void Postfix(EntityVehicle __instance, EntityPlayerLocal _player, ref MovementInput ___movementInput) { LocalPlayerUI uiForPlayer = LocalPlayerUI.GetUIForPlayer(_player); PlayerActionsVehicle vehicleActions = uiForPlayer.playerInput.VehicleActions; bool flag = _player.PlayerUI.windowManager.IsInputActive(); if (!flag && _player.AttachedToEntity != null) { bool isBicycle = _player.AttachedToEntity.EntityTags.Test_AllSet(FastTags.Parse("bicycle")); if (Input.GetKeyDown(KeyCode.Q)) { //Log.Out("EntityVehiclePatches-MoveByAttachedEntity PRESSED Q"); if (RebirthVariables.autoRun == 0) { RebirthVariables.autoRun = 1; } else if (RebirthVariables.autoRun == 1) { RebirthVariables.autoRun = 2; } else { RebirthVariables.autoRun = 0; } } else if ((double)vehicleActions.Move.Y > 0.0 || vehicleActions.MoveBack.IsPressed || vehicleActions.Brake.IsPressed && __instance as EntityVHelicopter == null && __instance as EntityVGyroCopter == null) { //Log.Out("EntityVehiclePatches-MoveByAttachedEntity CANCEL"); RebirthVariables.autoRun = 0; } else if (Input.GetKeyDown(KeyCode.Backspace) && !isBicycle) { if (RebirthVariables.musicMode == 0 || RebirthVariables.musicMode == -1) { RebirthVariables.musicMode = 1; RebirthVariables.walkman = false; } else { RebirthVariables.musicMode = 0; RebirthVariables.walkman = false; } } else if (Input.GetKeyDown(KeyCode.Return)) { if (RebirthVariables.musicMode == 1) { RebirthVariables.musicMode = 2; } } else if (Input.GetKeyDown(KeyCode.Equals)) { if (RebirthVariables.musicMode == 1) { RebirthVariables.musicMode = 4; } } else if (Input.GetKeyDown(KeyCode.Minus)) { if (RebirthVariables.musicMode == 1) { RebirthVariables.musicMode = 5; } } } if (RebirthVariables.autoRun == 1) { //Log.Out("RebirthVariables.autoRun: " + RebirthVariables.autoRun); ___movementInput.moveForward = 1; ___movementInput.running = false; } else if (RebirthVariables.autoRun == 2) { //Log.Out("RebirthVariables.autoRun: " + RebirthVariables.autoRun); ___movementInput.moveForward = 1; ___movementInput.running = true; } } } [HarmonyPatch(typeof(EntityVehicle))] [HarmonyPatch("StartInteraction")] public class StartInteractionPatch { private static void SendSyncData(ushort syncFlags, EntityVehicle __instance) { NetPackageVehicleDataSync package = NetPackageManager.GetPackage().Setup(__instance, GameManager.Instance.World.GetPrimaryPlayerId(), syncFlags); if (!SingletonMonoBehaviour.Instance.IsServer) { SingletonMonoBehaviour.Instance.SendToServer(package, false); return; } SingletonMonoBehaviour.Instance.SendPackage(package, false, -1, -1, -1, null, 192); } //public static MethodInfo StopInteraction = AccessTools.Method(typeof(EntityVehicle), "StopInteraction", new Type[] { typeof(ushort) }); private static void StopInteraction(ushort syncFlags, ref int ___interactingPlayerId, EntityVehicle __instance) { ___interactingPlayerId = -1; if (!SingletonMonoBehaviour.Instance.IsServer) { syncFlags |= 4096; } if (syncFlags != 0) { SendSyncData(syncFlags, __instance); } } private static bool Prefix(EntityVehicle __instance, int _playerId, int _requestId, ref int ___interactingPlayerId, int ___interactionRequestType, bool ___hasDriver) { EntityPlayerLocal localPlayerFromID = GameManager.Instance.World.GetLocalPlayerFromID(_playerId); if (!localPlayerFromID) { return false; } if (_requestId != _playerId) { GameManager.ShowTooltip(localPlayerFromID, Localization.Get("ttVehicleInUse"), string.Empty, "ui_denied", null); return false; } ___interactingPlayerId = _playerId; LocalPlayerUI uiforPlayer = LocalPlayerUI.GetUIForPlayer(localPlayerFromID); GUIWindowManager windowManager = uiforPlayer.windowManager; ushort num = 0; switch (___interactionRequestType) { case 1: string vehicleType = "V6CarRepair"; if (__instance.EntityClass.Properties.Values.ContainsKey("VehicleType")) { vehicleType = __instance.EntityClass.Properties.Values["VehicleType"]; } vehicleType = vehicleType + "Entity"; ((XUiC_VehicleWindowGroupRebirth)((XUiWindowGroup)windowManager.GetWindow(vehicleType)).Controller).CurrentVehicleEntity = __instance; windowManager.Open(vehicleType, true, false, true); Manager.BroadcastPlayByLocalPlayer(__instance.position, "UseActions/service_vehicle"); return false; case 2: if (XUiM_Vehicle.RepairVehicle(uiforPlayer.xui, __instance.vehicle)) { num |= 4; __instance.PlayOneShot("crafting/craft_repair_item", true); } StopInteraction(num, ref ___interactingPlayerId, __instance); //StopInteraction.Invoke(__instance, new object[] { num }); return false; case 3: case 4: case 5: case 8: break; case 6: //Log.Out("EntityVehiclePatches-StartInteractionPatch 6"); if (__instance.AddFuelFromInventory(localPlayerFromID)) { num |= 4; } StopInteraction(num, ref ___interactingPlayerId, __instance); //StopInteraction.Invoke(__instance, new object[] { num }); return false; case 7: if (!__instance.bag.IsEmpty()) { GameManager.ShowTooltip(localPlayerFromID, Localization.Get("ttEmptyVehicleBeforePickup"), string.Empty, "ui_denied", null); StopInteraction(0, ref ___interactingPlayerId, __instance); //StopInteraction.Invoke(__instance, new object[] { 0 }); return false; } if (!___hasDriver) { //Log.Out("EntityVehiclePatches-StartInteractionPatch __instance.Health: " + __instance.Health); //Log.Out("EntityVehiclePatches-StartInteractionPatch UseTimes: " + (float)((int)__instance.Stats.Health.BaseMax - __instance.Health)); //Log.Out("EntityVehiclePatches-StartInteractionPatch Meta: " + (int)(__instance.vehicle.GetFuelLevel() * 50f)); ItemValue itemValue = __instance.vehicle.GetUpdatedItemValue(); //Log.Out("EntityVehiclePatches-StartInteractionPatch itemValue.Meta: " + itemValue.Meta); //Log.Out("EntityVehiclePatches-StartInteractionPatch itemValue.UseTimes: " + itemValue.UseTimes); //Log.Out("EntityVehiclePatches-StartInteractionPatch itemValue.MaxUseTimes: " + itemValue.MaxUseTimes); ItemStack itemStack = new ItemStack(itemValue, 1); //Log.Out("EntityVehiclePatches-StartInteractionPatch Item: " + __instance.vehicle.GetUpdatedItemValue().ItemClass.GetItemName()); if (localPlayerFromID.inventory.CanTakeItem(itemStack) || localPlayerFromID.bag.CanTakeItem(itemStack)) { GameManager.Instance.CollectEntityServer(__instance.entityId, localPlayerFromID.entityId); } else { GameManager.ShowTooltip(localPlayerFromID, Localization.Get("xuiInventoryFullForPickup"), string.Empty, "ui_denied", null); } } StopInteraction(0, ref ___interactingPlayerId, __instance); //StopInteraction.Invoke(__instance, new object[] { 0 }); return false; case 9: ((XUiC_VehicleStorageWindowGroup)((XUiWindowGroup)windowManager.GetWindow("vehicleStorage")).Controller).CurrentVehicleEntity = __instance; windowManager.Open("vehicleStorage", true, false, true); break; default: return false; } return false; } } [HarmonyPatch(typeof(EntityVehicle))] [HarmonyPatch("ApplyCollisionDamageToAttached")] public class ApplyCollisionDamageToAttachedPatch { private static bool Prefix(EntityVehicle __instance, int damage) { if (!RebirthUtilities.IsHordeNight()) { return false; } return true; } } [HarmonyPatch(typeof(EntityVehicle))] [HarmonyPatch("ApplyDamage")] public class ApplyDamagePatch { private static bool Prefix(EntityVehicle __instance, int damage, ref float ___explodeHealth) { if (!RebirthUtilities.IsHordeNight()) { damage = damage / 10; } if (__instance is global::EntityVehicleRebirth) { int MinDamage = 1; /*Log.Out("EntityVehicleRebirth-ApplyDamage damage: " + damage); if (__instance.EntityClass.Properties.Values.ContainsKey("VehicleType")) { string vehicleType = __instance.EntityClass.Properties.Values["VehicleType"]; if (vehicleType == "BicycleRepair") { MinDamage = 5; } else if (vehicleType == "MinibikeRepair" || vehicleType == "GyroRepair" ) { MinDamage = 10; } else if (vehicleType == "MotorcycleRepair" || vehicleType == "QuadRepair" ) { MinDamage = 10; } else if (vehicleType == "V6CarRepair" || vehicleType == "V8CarRepair" ) { MinDamage = 15; } else if (vehicleType == "V6TruckRepair" || vehicleType == "V8TruckRepair" ) { MinDamage = 15; } else if (vehicleType == "RVRepair" || vehicleType == "6WheelerRepair" ) { MinDamage = 20; } else if (vehicleType == "8WheelerRepair") { MinDamage = 20; } }*/ if (damage >= MinDamage) { global::EntityVehicleRebirth entityVehicle = (global::EntityVehicleRebirth)__instance; int slotNumber = 0; GameRandom rng = new GameRandom(); foreach (ItemValue item in entityVehicle.itemValues) { int random = rng.RandomRange(1, 3); //Log.Out("EntityVehicleRebirth-ApplyDamage item.ItemClass.GetItemName(): " + item.ItemClass.GetItemName()); //Log.Out("EntityVehicleRebirth-ApplyDamage random: " + random); if (random == 2) { if (item.type == ItemValue.None.type) { } else { if ((item.UseTimes + 3) < item.MaxUseTimes) { item.UseTimes += 3; } else { item.UseTimes = item.MaxUseTimes; } if (!SingletonMonoBehaviour.Instance.IsServer) { //Log.Out("EntityVehicleRebirth-ApplyDamage slotNumber: " + slotNumber); //Log.Out("EntityVehicleRebirth-ApplyDamage Degradation: " + item.UseTimes + "/" + item.MaxUseTimes); //Log.Out("EntityVehicleRebirth-ApplyDamage Quality: " + item.Quality + "/" + item.Quality); NetPackageVehicleUpdatePartRebirth package = NetPackageManager.GetPackage().Setup(__instance.GetAttachedPlayerLocal().entityId, entityVehicle.entityId, slotNumber, item.UseTimes, item.Quality, item.ItemClass.GetItemName()); SingletonMonoBehaviour.Instance.SendToServer(package, false); } } } slotNumber++; } } } int num = __instance.Health; if (num <= 0) { return false; } bool flag = damage >= 99999; if (num == 1 || flag) { if (SingletonMonoBehaviour.Instance.IsServer) { ___explodeHealth -= (float)damage; if (___explodeHealth <= 0f && (flag || __instance.rand.RandomFloat < 0.2f)) { __instance.Kill(); GameManager.Instance.ExplosionServer(0, __instance.GetPosition(), World.worldToBlockPos(__instance.GetPosition()), __instance.transform.rotation, EntityClass.list[__instance.entityClass].explosionData, __instance.entityId, 0f, false, null); return false; } } } else { num -= damage; if (num <= 1) { num = 1; ___explodeHealth = (float)__instance.vehicle.GetMaxHealth() * 0.03f; } __instance.Health = num; if (!SingletonMonoBehaviour.Instance.IsServer) { NetPackageUpdateVehicleHealthRebirth package = NetPackageManager.GetPackage().Setup(__instance.entityId, num); SingletonMonoBehaviour.Instance.SendToServer(package, false); } } return false; } } [HarmonyPatch(typeof(EntityVehicle))] [HarmonyPatch("GetActivationCommands")] public class EntityVehicleGetActivationCommandsPatch { public static MethodInfo isDriveable = AccessTools.Method(typeof(EntityVehicle), "isDriveable", new Type[] { }); public static MethodInfo isAllowedUser = AccessTools.Method(typeof(EntityVehicle), "isAllowedUser", new Type[] { typeof(PlatformUserIdentifierAbs) }); private static bool Prefix(EntityVehicle __instance, ref EntityActivationCommand[] __result, Vector3i _tePos, EntityAlive _entityFocusing, Vehicle ___vehicle, bool ___hasDriver) { if (__instance.IsDead()) { __result = new EntityActivationCommand[0]; } bool isAdmin = _entityFocusing.Buffs.HasBuff("god"); bool optionVehicleSecurity = RebirthVariables.customVehicleSecurity; bool optionVehiclePickup = RebirthVariables.customVehiclePickUp; bool isOwner = __instance.LocalPlayerIsOwner(); bool isOwnerOrAdmin = isOwner || isAdmin; bool isAllowed = (bool)isAllowedUser.Invoke(__instance, new object[] { PlatformManager.InternalLocalUserIdentifier }); bool noSecurityUnlocked = !optionVehicleSecurity && !__instance.isLocked; bool canAccess = isOwnerOrAdmin || isAllowed || noSecurityUnlocked; bool isVehicle = __instance.CanAttach(_entityFocusing) && (bool)isDriveable.Invoke(__instance, new object[] { }); bool isDriven = __instance.IsDriven(); /*Log.Out("EntityVehiclePatches-GetActivationCommands isVehicle: " + isVehicle); Log.Out("EntityVehiclePatches-GetActivationCommands isDriven: " + isDriven); Log.Out("EntityVehiclePatches-GetActivationCommands isOwner: " + isOwner); Log.Out("EntityVehiclePatches-GetActivationCommands isOwnerOrAdmin: " + isOwnerOrAdmin); Log.Out("EntityVehiclePatches-GetActivationCommands isAllowed: " + isAllowed); Log.Out("EntityVehiclePatches-GetActivationCommands optionVehicleSecurity: " + optionVehicleSecurity); Log.Out("EntityVehiclePatches-GetActivationCommands isLocked: " + __instance.isLocked); Log.Out("EntityVehiclePatches-GetActivationCommands noSecurityUnlocked: " + noSecurityUnlocked); Log.Out("EntityVehiclePatches-GetActivationCommands canAccess: " + canAccess);*/ EntityActivationCommand entityActivationCommand; if (!isDriven) { entityActivationCommand = new EntityActivationCommand("drive", "drive", isVehicle && canAccess); } else { entityActivationCommand = new EntityActivationCommand("ride", "drive", isVehicle && canAccess); } bool optionPickUp = RebirthVariables.customVehiclePickUp; __result = new EntityActivationCommand[] { entityActivationCommand, new EntityActivationCommand("service", "service", canAccess), new EntityActivationCommand("repair", "wrench", false), //___vehicle.GetRepairAmountNeeded() > 0), new EntityActivationCommand("lock", "lock", isOwnerOrAdmin && !__instance.isLocked && !isDriven), new EntityActivationCommand("unlock", "unlock", __instance.isLocked && isOwnerOrAdmin), new EntityActivationCommand("keypad", "keypad", __instance.isLocked && (isOwnerOrAdmin || ___vehicle.PasswordHash != 0)), new EntityActivationCommand("refuel", "gas", false), //hasGasCan(_entityFocusing, ___vehicle) && needsFuel(___vehicle)), new EntityActivationCommand("take", "hand", !___hasDriver && isOwnerOrAdmin && (__instance.HasAnyTags(FastTags.Parse("canPickUp")) || optionPickUp)), new EntityActivationCommand("horn", "horn", false), //flag2 && ___vehicle.HasHorn()), new EntityActivationCommand("storage", "loot_sack", canAccess), new EntityActivationCommand("remove", "trash", !___hasDriver && !__instance.isLocked && isOwnerOrAdmin && !optionVehiclePickup) }; return false; } } [HarmonyPatch(typeof(EntityVehicle))] [HarmonyPatch("OnEntityActivated")] public class OnEntityActivatedPatch { private static bool Prefix(EntityVehicle __instance, int _indexInBlockActivationCommands, Vector3i _tePos, EntityAlive _entityFocusing, bool ___hasDriver) { //Log.Out("EntityVehiclePatches-OnEntityActivated _indexInBlockActivationCommands: " + _indexInBlockActivationCommands); EntityPlayerLocal entityPlayerLocal = _entityFocusing as EntityPlayerLocal; LocalPlayerUI uiforPlayer = LocalPlayerUI.GetUIForPlayer(entityPlayerLocal); if (entityPlayerLocal.inventory.IsHoldingItemActionRunning() || uiforPlayer.xui.isUsingItemActionEntryUse) { return false; } EntityActivationCommand[] myActivationCommands = __instance.GetActivationCommands(Vector3i.zero, _entityFocusing); bool optionPickUp = RebirthVariables.customVehiclePickUp; if (!__instance.HasAnyTags(FastTags.Parse("canPickUp")) && !optionPickUp) { if (myActivationCommands[_indexInBlockActivationCommands].text == "take") { GameManager.ShowTooltip(entityPlayerLocal, Localization.Get("ttCantPickupVehicle"), string.Empty, "ui_denied", null); return false; } } else { if (myActivationCommands[_indexInBlockActivationCommands].text == "take") { if (__instance is global::EntityVehicleRebirth) { if (!__instance.bag.IsEmpty()) { GameManager.ShowTooltip(entityPlayerLocal, Localization.Get("ttEmptyVehicleBeforePickup"), string.Empty, "ui_denied"); return false; } global::EntityVehicleRebirth entityVehicle = (global::EntityVehicleRebirth)__instance; if (!entityVehicle.EntityClass.entityClassName.ToLower().Contains("bicycle")) { int numParts = 0; foreach (ItemValue item in entityVehicle.itemValues) { if (item.type != ItemValue.None.type) { //numParts++; entityPlayerLocal.bag.AddItem(new ItemStack(item, 1)); } } } /*if (numParts > 0 && !entityVehicle.EntityClass.entityClassName.ToLower().Contains("bicycle")) { GameManager.ShowTooltip(entityPlayerLocal, Localization.Get("ttEmptyVehiclePartsBeforePickup"), string.Empty, "ui_denied", null); return false; }*/ } } } if (myActivationCommands[_indexInBlockActivationCommands].text == "remove") { if (uiforPlayer != null) { if (!__instance.bag.IsEmpty()) { GameManager.ShowTooltip(entityPlayerLocal, Localization.Get("ttEmptyVehicleBeforeRemove"), string.Empty, "ui_denied", null); return false; } if (__instance is global::EntityVehicleRebirth) { global::EntityVehicleRebirth entityVehicle = (global::EntityVehicleRebirth)__instance; int numParts = 0; foreach (ItemValue item in entityVehicle.itemValues) { if (item.type != ItemValue.None.type) { numParts++; } } if (numParts > 0) { GameManager.ShowTooltip(entityPlayerLocal, Localization.Get("ttEmptyVehiclePartsBeforeRemove"), string.Empty, "ui_denied", null); return false; } } if (!___hasDriver) { ((XUiC_ConfirmWindowGroupRebirth)((XUiWindowGroup)uiforPlayer.windowManager.GetWindow("Confirm")).Controller).currentVehicleEntity = __instance; uiforPlayer.windowManager.Open("Confirm", true, false, true); } return false; } } else if (myActivationCommands[_indexInBlockActivationCommands].text == "refuel") { if (!RebirthUtilities.hasItem(ItemClass.GetItem("ammoGasCan"), entityPlayerLocal)) { RebirthUtilities.notifyMissingItem(ItemClass.GetItem("ammoGasCan"), entityPlayerLocal); return false; } if ((__instance != null && !__instance.GetVehicle().HasEnginePart()) || !__instance.AddFuelFromInventory(entityPlayerLocal)) { return false; } } return true; } } [HarmonyPatch(typeof(EntityVehicle))] [HarmonyPatch("Awake")] public class AwakePatch { public static void Postfix(EntityVehicle __instance) { __instance.isLocked = false; } } [HarmonyPatch(typeof(EntityVehicle))] [HarmonyPatch("EnterVehicle")] public class EnterVehiclePatch { private static bool Prefix(EntityVehicle __instance, EntityAlive _entity) { float flActionInProgress = RebirthVariables.localConstants["$varFuriousRamsayActionInProgress"]; if (flActionInProgress == 1) { return false; } __instance.Buffs.SetCustomVar("$autoRunToggle", 0f); return true; } } } }