namespace Harmony.ProjectileMoveScriptPatches { [HarmonyPatch(typeof(ProjectileMoveScript))] [HarmonyPatch("checkCollision")] public class checkCollisionPatch { public static bool Prefix(ProjectileMoveScript __instance) { if (__instance.state != ProjectileMoveScript.State.Active || (UnityEngine.Object)ProjectileMoveScript.gameManager == (UnityEngine.Object)null) return false; World world = ProjectileMoveScript.gameManager.World; if (world == null) return false; Vector3 vector3_1 = !__instance.bOnIdealPos ? __instance.idealPosition : __instance.transform.position + Origin.position; Vector3 vector3_2 = vector3_1 - __instance.previousPosition; float magnitude = vector3_2.magnitude; if ((double)magnitude < 0.039999999105930328) return false; EntityAlive firingEntity = (EntityAlive)__instance.firingEntity; Ray ray = new Ray(__instance.previousPosition, vector3_2.normalized); __instance.waterCollisionParticles.CheckCollision(ray.origin, ray.direction, magnitude, (UnityEngine.Object)firingEntity != (UnityEngine.Object)null ? firingEntity.entityId : -1); int _layerId = -1; if ((UnityEngine.Object)firingEntity != (UnityEngine.Object)null && (UnityEngine.Object)firingEntity.emodel != (UnityEngine.Object)null) { _layerId = firingEntity.GetModelLayer(); firingEntity.SetModelLayer(2); } int _hitMask = __instance.hmOverride == 0 ? 80 : __instance.hmOverride; int num1 = Voxel.Raycast(world, ray, magnitude, -538750997, _hitMask, __instance.radius) ? 1 : 0; if (_layerId >= 0) firingEntity.SetModelLayer(_layerId); if (num1 != 0 && (GameUtils.IsBlockOrTerrain(Voxel.voxelRayHitInfo.tag) || Voxel.voxelRayHitInfo.tag.StartsWith("E_"))) { if ((UnityEngine.Object)__instance.firingEntity != (UnityEngine.Object)null && !__instance.firingEntity.isEntityRemote) { firingEntity.MinEventContext.Other = ItemActionAttack.FindHitEntity(Voxel.voxelRayHitInfo) as EntityAlive; ItemActionAttack.AttackHitInfo _attackDetails = new ItemActionAttack.AttackHitInfo() { WeaponTypeTag = ItemActionAttack.RangedTag }; ItemActionAttack.Hit(Voxel.voxelRayHitInfo, __instance.ProjectileOwnerID, EnumDamageTypes.Piercing, Mathf.Lerp(1f, __instance.itemActionProjectile.GetDamageBlock(__instance.itemValueLauncher, ItemActionAttack.GetBlockHit(world, Voxel.voxelRayHitInfo), firingEntity), __instance.actionData.strainPercent), Mathf.Lerp(1f, __instance.itemActionProjectile.GetDamageEntity(__instance.itemValueLauncher, firingEntity), __instance.actionData.strainPercent), 1f, 1f, EffectManager.GetValue(PassiveEffects.CriticalChance, __instance.itemValueLauncher, __instance.itemProjectile.CritChance.Value, firingEntity, tags: __instance.itemProjectile.ItemTags), ItemAction.GetDismemberChance((ItemActionData)__instance.actionData, Voxel.voxelRayHitInfo), __instance.itemProjectile.MadeOfMaterial.SurfaceCategory, __instance.itemActionProjectile.GetDamageMultiplier(), __instance.getBuffActions(), _attackDetails, _actionExp: __instance.itemActionProjectile.ActionExp, _actionExpBonus: __instance.itemActionProjectile.ActionExpBonusMultiplier, damagingItemValue: __instance.itemValueLauncher); if ((UnityEngine.Object)firingEntity.MinEventContext.Other == (UnityEngine.Object)null) firingEntity.FireEvent(MinEventTypes.onSelfPrimaryActionMissEntity); firingEntity.FireEvent(MinEventTypes.onProjectileImpact, false); MinEventParams.CachedEventParam.Self = firingEntity; MinEventParams.CachedEventParam.Position = Voxel.voxelRayHitInfo.hit.pos; MinEventParams.CachedEventParam.ItemValue = __instance.itemValueProjectile; MinEventParams.CachedEventParam.Other = firingEntity.MinEventContext.Other; __instance.itemProjectile.FireEvent(MinEventTypes.onProjectileImpact, MinEventParams.CachedEventParam); if (__instance.itemActionProjectile.Explosion.ParticleIndex > 0) { Vector3 hitPos = Voxel.voxelRayHitInfo.hit.pos - vector3_2.normalized * 0.1f; Vector3i vector3i = World.worldToBlockPos(hitPos); if (!world.GetBlock(vector3i).isair) vector3i = Voxel.OneVoxelStep(vector3i, hitPos, -vector3_2.normalized, out hitPos, out BlockFace _); ProjectileMoveScript.gameManager.ExplosionServer(Voxel.voxelRayHitInfo.hit.clrIdx, hitPos, vector3i, Quaternion.identity, __instance.itemActionProjectile.Explosion, __instance.ProjectileOwnerID, 0.0f, false, __instance.itemValueLauncher); __instance.SetState(ProjectileMoveScript.State.Dead); return false; } if (__instance.itemProjectile.IsSticky) { GameRandom gameRandom = world.GetGameRandom(); ProgressionValue progressionValue = firingEntity.Progression.GetProgressionValue("FuriousRamsayPerkBows"); int progressionLevel = 1; if (!RebirthUtilities.ScenarioSkip() && progressionValue != null) { progressionLevel = progressionValue.Level; } float baseStickChance = 0f; float addedChance = 0f; float stickChance; bool isArrow = __instance.itemProjectile.Name.ToLower().Contains("ammoarrow") || __instance.itemProjectile.Name.ToLower().Contains("ammocrossbowbolt"); if (!isArrow) { stickChance = EffectManager.GetValue(PassiveEffects.ProjectileStickChance, __instance.itemValueLauncher, 0.5f, firingEntity, tags: __instance.itemProjectile.ItemTags); } else { if (__instance.itemProjectile.Name.ToLower().Contains("stone")) { baseStickChance = 0.3f; addedChance = progressionLevel / 25f; //Log.Out("ProjectileMoveScriptPatches-checkCollision STONE, addedChance: " + addedChance); stickChance = baseStickChance + addedChance; } else if (__instance.itemProjectile.Name.ToLower().Contains("iron")) { baseStickChance = 0.4f; addedChance = progressionLevel / 25f; //Log.Out("ProjectileMoveScriptPatches-checkCollision IRON, addedChance: " + addedChance); stickChance = baseStickChance + addedChance; } else if (__instance.itemProjectile.Name.ToLower().Contains("steelap")) { baseStickChance = 0.5f; addedChance = progressionLevel / 25f; //Log.Out("ProjectileMoveScriptPatches-checkCollision STEEL, addedChance: " + addedChance); stickChance = baseStickChance + addedChance; } else { //Log.Out("ProjectileMoveScriptPatches-checkCollision OTHER"); stickChance = 0f; } } float random = gameRandom.RandomFloat; //Log.Out("ProjectileMoveScriptPatches-checkCollision baseStickChance: " + baseStickChance); //Log.Out("ProjectileMoveScriptPatches-checkCollision addedChance: " + addedChance); //Log.Out("ProjectileMoveScriptPatches-checkCollision progressionLevel: " + progressionLevel); //Log.Out("ProjectileMoveScriptPatches-checkCollision stickChance: " + stickChance); //Log.Out("ProjectileMoveScriptPatches-checkCollision ItemClass.Name: " + __instance.itemValueLauncher.ItemClass.Name); //Log.Out("ProjectileMoveScriptPatches-checkCollision itemProjectile.Name: " + __instance.itemProjectile.Name); //Log.Out("ProjectileMoveScriptPatches-checkCollision random: " + random); if (GameUtils.IsBlockOrTerrain(Voxel.voxelRayHitInfo.tag)) { double randomFloat = (double)gameRandom.RandomFloat; ItemValue itemValueLauncher = __instance.itemValueLauncher; EntityAlive _entity = firingEntity; FastTags itemTags = __instance.itemProjectile.ItemTags; BlockValue blockValue = Voxel.voxelRayHitInfo.fmcHit.blockValue; FastTags fastTags = FastTags.Parse(blockValue.Block.blockMaterial.SurfaceCategory); FastTags tags = itemTags | fastTags; double num2 = (double)EffectManager.GetValue(PassiveEffects.ProjectileStickChance, itemValueLauncher, 0.5f, _entity, tags: tags); if (randomFloat < num2) { __instance.ProjectileID = ProjectileManager.AddProjectileItem(__instance.transform, _position: Voxel.voxelRayHitInfo.hit.pos, _movementLastFrame: vector3_2.normalized, _itemValueType: __instance.itemValueProjectile.type); __instance.SetState(ProjectileMoveScript.State.Sticky); } else { GameManager gameManager = ProjectileMoveScript.gameManager; Vector3 pos = Voxel.voxelRayHitInfo.hit.pos; Quaternion rotation = Utils.BlockFaceToRotation(Voxel.voxelRayHitInfo.fmcHit.blockFace); Color white = Color.white; blockValue = Voxel.voxelRayHitInfo.fmcHit.blockValue; string _soundName = string.Format("{0}hit{1}", (object)blockValue.Block.blockMaterial.SurfaceCategory, (object)__instance.itemProjectile.MadeOfMaterial.SurfaceCategory); ParticleEffect _pe = new ParticleEffect("impact_metal_on_wood", pos, rotation, 1f, white, _soundName, (Transform)null); int entityId = __instance.firingEntity.entityId; gameManager.SpawnParticleEffectServer(_pe, entityId, false, false); __instance.SetState(ProjectileMoveScript.State.Dead); } } else if (random < stickChance) { __instance.ProjectileID = ProjectileManager.AddProjectileItem(__instance.transform, _position: Voxel.voxelRayHitInfo.hit.pos, _movementLastFrame: vector3_2.normalized, _itemValueType: __instance.itemValueProjectile.type); Utils.SetLayerRecursively(ProjectileManager.GetProjectile(__instance.ProjectileID).gameObject, 14); __instance.SetState(ProjectileMoveScript.State.Sticky); } else { ProjectileMoveScript.gameManager.SpawnParticleEffectServer(new ParticleEffect("impact_metal_on_wood", Voxel.voxelRayHitInfo.hit.pos, Utils.BlockFaceToRotation(Voxel.voxelRayHitInfo.fmcHit.blockFace), 1f, Color.white, "bullethitwood", (Transform)null), __instance.firingEntity.entityId, false, false); __instance.SetState(ProjectileMoveScript.State.Dead); } } else __instance.SetState(ProjectileMoveScript.State.Dead); } else __instance.SetState(ProjectileMoveScript.State.Dead); } __instance.previousPosition = vector3_1; return false; } } }