public static void Prefix(Verb_LaunchProjectile __instance, List <IntVec3> ___tempLeanShootSources, List <IntVec3> ___tempDestList, LocalTargetInfo ___currentTarget, ref bool __result) { //ZLogger.Message("__instance.caster: " + __instance.caster, true); //ZLogger.Message("__instance.caster.Map: " + __instance.caster.Map, true); //ZLogger.Message("__instance.caster.Map.Tile: " + __instance.caster.Map.Tile, true); // //ZLogger.Message("___currentTarget.Thing: " + ___currentTarget.Thing, true); //ZLogger.Message("___currentTarget.Thing?.Map: " + ___currentTarget.Thing?.Map, true); //ZLogger.Message("___currentTarget.Thing?.Map.Tile: " + ___currentTarget.Thing?.Map.Tile, true); if (__instance.caster.Map != ___currentTarget.Thing?.Map && __instance.caster.Map.Tile == ___currentTarget.Thing?.Map?.Tile) { var ind1 = ZUtils.ZTracker.GetZIndexFor(__instance.caster.Map); var ind2 = ZUtils.ZTracker.GetZIndexFor(___currentTarget.Thing.Map); if (ind1 > ind2) { teleportBack = true; targetOldMap = ___currentTarget.Thing.Map; ZUtils.TeleportThing(___currentTarget.Thing, __instance.caster.Map, ___currentTarget.Thing.Position); RoofAndFloorPatches.Patch_SpawnSetup.doTeleport = false; } else if (ind1 < ind2) { teleportBack = true; casterOldMap = __instance.caster.Map; ZUtils.TeleportThing(__instance.caster, ___currentTarget.Thing.Map, __instance.caster.Position); RoofAndFloorPatches.Patch_SpawnSetup.doTeleport = false; } } }
public static void Upgradeable_Projectile_Postfix(ref Verb_LaunchProjectile __instance, ref ThingDef __result) { if (__instance.EquipmentSource != null) { if (!__instance.EquipmentSource.AllComps.NullOrEmpty()) { if (__instance.EquipmentSource.GetComp <CompUpgradeableProjectile>() != null && __instance.verbProps.defaultProjectile == __result) { if (__instance.EquipmentSource.GetComp <CompUpgradeableProjectile>() is CompUpgradeableProjectile upgradeableProjectile) { if (__instance.CasterPawn.Faction != null) { bool flag = upgradeableProjectile.researchDef != null; if (flag) { if (__instance.CasterPawn.Faction == Faction.OfPlayer && upgradeableProjectile.researchDef.IsFinished) { __result = upgradeableProjectile.projectileDef; return; } } else { if (upgradeableProjectile.factionDefs.Contains(__instance.CasterPawn.Faction.def)) { __result = upgradeableProjectile.projectileDef; return; } } } } } /* * if (__instance.EquipmentSource.GetComp<CompSlotLoadable.CompSlotLoadable>() != null && __instance.verbProps.defaultProjectile == __result) * { * Log.Message(string.Format("{0} CompSlotLoadable != null", __instance.EquipmentSource)); * if (__instance.EquipmentSource.GetComp<CompSlotLoadable.CompSlotLoadable>() is CompSlotLoadable.CompSlotLoadable slotLoadable) * { * if (!slotLoadable.Slots.NullOrEmpty()) * { * Log.Message(string.Format("{0} Slots, Occupied: {1} Empty: {2}, Total: {3}", __instance.EquipmentSource, slotLoadable.Slots.FindAll(x => x.SlotOccupant != null).Count, slotLoadable.Slots.FindAll(x => x.SlotOccupant == null).Count, slotLoadable.Slots.Count)); * foreach (CompSlotLoadable.SlotLoadable slot in slotLoadable.Slots.FindAll(x => x.SlotOccupant != null)) * { * CompSlotLoadable.CompSlottedBonus slottedBonus = slot.SlotOccupant.TryGetComp<CompSlotLoadable.CompSlottedBonus>(); * Log.Message(string.Format("{0}'s Slot at {1} with: {2} slottedBonus: {3}", __instance.EquipmentSource, slotLoadable.Slots.IndexOf(slot), slot.SlotOccupant, slottedBonus!=null)); * if (slottedBonus != null) * { * Log.Message(string.Format("{0} slottedBonus: {1}", __instance.EquipmentSource, slottedBonus)); * __result = slottedBonus.Props.projectileReplacer; * break; * } * } * } * } * } */ } } }
/*[HarmonyPatch(typeof(Verb_LaunchProjectile), "HighlightFieldRadiusAroundTarget")] * static class Harmony_Verb_LaunchProjectile_HighlightFieldRadiusAroundTarget * { * static bool Prefix(ref float __result, Verb_LaunchProjectile __instance, LocalTargetInfo ___currentTarget, out bool needLOSToCenter) * { * if (__instance.verbProps.forcedMissRadius < 0.5f || __instance.verbProps.requireLineOfSight) * { * // Assuming this is not a mortar-like thing * // Perform vanilla logic * needLOSToCenter = true; * return true; * } * if (!Settings.showAccuracyRadius) * { * needLOSToCenter = true; * return true; * } * else * { * needLOSToCenter = false; * * float missRadius = GetAdjustedForcedMissRadius(__instance, ___currentTarget); * if (missRadius < 1) * { * missRadius = 1f; * } * __result = missRadius; * * // Skip normal execution, we will draw our own overlay * return false; * } * } * }*/ static float GetAdjustedForcedMissRadius(Verb_LaunchProjectile shootVerb, LocalTargetInfo ___currentTarget) { if (shootVerb.verbProps.forcedMissRadius < 0.5f || shootVerb.verbProps.requireLineOfSight) { return(0); } else { Pawn shooterPawn = null; CompMannable compMannable = shootVerb.caster.TryGetComp <CompMannable>(); if (compMannable != null && compMannable.ManningPawn != null) { shooterPawn = compMannable.ManningPawn; } else { shooterPawn = shootVerb.CasterPawn; } // Grab default forced miss radius for this particular weapon float missRadiusForShot = shootVerb.verbProps.forcedMissRadius; float skillMultiplier = 1f; // We want to multiply this forced miss radius by our pawn's skill modifier if (shooterPawn != null && shooterPawn.skills != null) { int totalSkill = 0; int skillsTotaled = 0; if (Settings.intellectualAffectsMortarAccuracy) { totalSkill += shooterPawn.skills.GetSkill(SkillDefOf.Intellectual).Level; skillsTotaled++; } if (Settings.shootingAffectsMortarAccuracy) { totalSkill += shooterPawn.skills.GetSkill(SkillDefOf.Shooting).Level; skillsTotaled++; } if (skillsTotaled > 0) { // get average skill int averageSkill = (int)(((float)totalSkill) / skillsTotaled); skillMultiplier = 1 - ((averageSkill - SkillRecord.MinLevel) * (Settings.maxSkillSpreadReduction - Settings.minSkillSpreadReduction) / (SkillRecord.MaxLevel - SkillRecord.MinLevel) + Settings.minSkillSpreadReduction); } } // Weather should affect shot no matter what the skill is if (Settings.weatherAffectsMortarAccuracy) { missRadiusForShot = (missRadiusForShot * skillMultiplier) + ((1 - shootVerb.caster.Map.weatherManager.CurWeatherAccuracyMultiplier) * missRadiusForShot); } else { missRadiusForShot = (missRadiusForShot * skillMultiplier); } // TODO: this is wrong. __curentTarget.Cell is origin when we are hovering over it, preview is incorrect return(VerbUtility.CalculateAdjustedForcedMiss(missRadiusForShot, ___currentTarget.Cell - shootVerb.caster.Position)); } }
public static void Prefix(Verb_LaunchProjectile __instance) { var projectileClass = __instance.GetProjectile()?.thingClass; if (projectileClass != null && typeof(TeslaProjectile).IsAssignableFrom(projectileClass)) { ShotReport_HitReportFor.accuracy = true; } }
public static bool get_Projectile_Prefix(Verb_LaunchProjectile __instance, ref ThingDef __result) { if (__instance is Verb_UseAbility) { __result = __instance.verbProps.defaultProjectile; return(false); } return(true); }
public static void Upgradeable_Projectile_Postfix(ref Verb_LaunchProjectile __instance, ref ThingDef __result) { if (__instance.EquipmentSource != null) { if (!__instance.EquipmentSource.AllComps.NullOrEmpty()) { if (__instance.EquipmentSource.GetComp <CompUpgradeableProjectile>() != null && __instance.verbProps.defaultProjectile == __result) { if (__instance.EquipmentSource.GetComp <CompUpgradeableProjectile>() is CompUpgradeableProjectile upgradeableProjectile) { if (__instance.CasterPawn.Faction != null) { bool flag = upgradeableProjectile.researchDef != null; if (flag) { if (__instance.CasterPawn.Faction == Faction.OfPlayer && upgradeableProjectile.researchDef.IsFinished) { __result = upgradeableProjectile.projectileDef; return; } } else { if (upgradeableProjectile.factionDefs.Contains(__instance.CasterPawn.Faction.def)) { __result = upgradeableProjectile.projectileDef; return; } } } } } if (__instance.EquipmentSource.GetComp <CompSlotLoadable.CompSlotLoadable>() != null && __instance.verbProps.defaultProjectile == __result) { if (__instance.EquipmentSource.GetComp <CompSlotLoadable.CompSlotLoadable>() is CompSlotLoadable.CompSlotLoadable slotLoadable) { if (!slotLoadable.Slots.NullOrEmpty()) { foreach (CompSlotLoadable.SlotLoadable slot in slotLoadable.Slots.FindAll(x => x.SlotOccupant != null)) { CompSlotLoadable.CompSlottedBonus slottedBonus = slot.SlotOccupant.TryGetComp <CompSlotLoadable.CompSlottedBonus>(); if (slottedBonus != null) { __result = slottedBonus.Props.projectileReplacer; break; } } } } } } } }
private static void Postfix(ref bool __result, Verb_LaunchProjectile __instance) { if (__instance is Verb_Shoot verb) { var comp = verb.EquipmentSource?.GetComp <CompGunWithMagazines>(); if (__result && comp?.Enabled is true) { __result = comp.CurrentAmmo > 0; } } }
internal static string ShotCalculationTipString(Thing target) { StringBuilder stringBuilder = new StringBuilder(); if (Find.Selector.SingleSelectedThing != null) { Pawn pawn = Find.Selector.SingleSelectedThing as Pawn; if (pawn != null && pawn != target && pawn.equipment != null && pawn.equipment.Primary != null) { Verb_LaunchProjectile verb_LaunchProjectile = pawn.equipment.PrimaryEq.PrimaryVerb as Verb_LaunchProjectile; if (verb_LaunchProjectile != null) { stringBuilder.AppendLine(); stringBuilder.Append("ShotBy".Translate(new object[] { pawn.LabelBaseShort }) + ":"); if (verb_LaunchProjectile.CanHitTarget(target)) { HitReport hitReport = verb_LaunchProjectile.HitReportFor(target); stringBuilder.Append(hitReport.GetTextReadout()); } else { stringBuilder.Append("CannotHit".Translate()); } } // Append CR tooltip else { Verb_LaunchProjectileCR verbCR = pawn.equipment.PrimaryEq.PrimaryVerb as Verb_LaunchProjectileCR; if (verbCR != null) { stringBuilder.AppendLine(); stringBuilder.Append("ShotBy".Translate(new object[] { pawn.LabelBaseShort }) + ":\n"); if (verbCR.CanHitTarget(target)) { ShiftVecReport report = verbCR.ShiftVecReportFor(target); stringBuilder.Append(report.GetTextReadout()); } else { stringBuilder.Append("CannotHit".Translate()); } } } } } return(stringBuilder.ToString()); }
public static bool WarmupComplete_Ranged_PreFix(Verb_LaunchProjectile __instance) { if (Utility.Eligable(__instance) && SettingsHelper.LatestVersion.NeedAmmo) { if (__instance.CasterPawn.IsColonistPlayerControlled) { return(!Utility.TryFire(__instance, out ThingDef thing)); } else if (SettingsHelper.LatestVersion.NPCNeedAmmo) { return(!Utility.TryFire(__instance, out ThingDef thing)); } } return(true); }
public static void Postfix(Verb_LaunchProjectile __instance, List <IntVec3> ___tempLeanShootSources, List <IntVec3> ___tempDestList, LocalTargetInfo ___currentTarget, ref bool __result) { if (teleportBack) { if (targetOldMap != null) { ZUtils.TeleportThing(___currentTarget.Thing, targetOldMap, ___currentTarget.Thing.Position); targetOldMap = null; RoofAndFloorPatches.Patch_SpawnSetup.doTeleport = true; } else if (casterOldMap != null) { ZUtils.TeleportThing(__instance.caster, casterOldMap, __instance.caster.Position); casterOldMap = null; RoofAndFloorPatches.Patch_SpawnSetup.doTeleport = true; } } }
public static Vector3 MuzzlePosition(Vector3 DrawPos, Verb_LaunchProjectile instance, Thing equipment, Thing launcher) { Vector3 result = DrawPos; if (equipment == null || !AMAMod.settings.AllowMuzzlePosition) { return(result); } Vector3 destination = instance.CurrentTarget.Cell.ToVector3Shifted(); float aimAngle = 0f; if ((destination - result).MagnitudeHorizontalSquared() > 0.001f) { aimAngle = (destination - result).AngleFlat(); } IDrawnWeaponWithRotation rotation = equipment as IDrawnWeaponWithRotation; if (rotation != null) { // Log.Message(gunOG + " is IDrawnWeaponWithRotation with RotationOffset: "+ gunOG.RotationOffset); aimAngle += rotation.RotationOffset; } if (equipment.def.HasComp(typeof(OgsCompOversizedWeapon.CompOversizedWeapon))) { OgsCompOversizedWeapon.CompOversizedWeapon compOversized = equipment.TryGetCompFast <OgsCompOversizedWeapon.CompOversizedWeapon>(); if (compOversized != null) { bool DualWeapon = compOversized.Props != null && compOversized.Props.isDualWeapon; Vector3 offsetMainHand = default(Vector3); Vector3 offsetOffHand = default(Vector3); float offHandAngle = aimAngle; float mainHandAngle = aimAngle; OversizedUtil.SetAnglesAndOffsets(equipment, equipment as ThingWithComps, aimAngle, launcher, ref offsetMainHand, ref offsetOffHand, ref offHandAngle, ref mainHandAngle, true, DualWeapon && !compOversized.FirstAttack); Vector3 vector = DualWeapon && !compOversized.FirstAttack ? offsetOffHand : offsetMainHand; // Vector3 vector = compOversized.AdjustRenderOffsetFromDir(equippable.PrimaryVerb.CasterPawn, !compOversized.FirstAttack); result += vector; } } result = equipment.MuzzlePositionFor(result, aimAngle); return(result); }
// RimWorld.Verb_MeleeAttack public static void get_Projectile_PostFix(Verb_LaunchProjectile __instance, ref ThingDef __result) { //__result = null; var EquipmentSource = __instance.EquipmentSource; if (EquipmentSource != null) { //Log.Message("1"); var comp = EquipmentSource.AllComps.FirstOrDefault(x => x is OgsCompSlotLoadable.CompSlotLoadable); if (comp != null) { //Log.Message("2"); var compSlotLoadable = comp as OgsCompSlotLoadable.CompSlotLoadable; if (compSlotLoadable.Slots != null && compSlotLoadable.Slots.Count > 0) { //Log.Message("3"); var statSlots = compSlotLoadable.Slots.FindAll(z => !z.IsEmpty() && ((OgsCompSlotLoadable.SlotLoadableDef)z.def).doesChangeStats); if (statSlots != null && statSlots.Count > 0) { foreach (var slot in statSlots) { //Log.Message("5"); var slotBonus = slot.SlotOccupant.def.GetModExtension <SlottedBonusExtension>(); if (slotBonus != null) { //Log.Message("6"); var superClass = __instance.GetType().BaseType; if (slotBonus.projectileReplacer != null) { __result = slotBonus.projectileReplacer; } } } } } } } }
static void Postfix(Verb_LaunchProjectile __instance) { __instance.EquipmentSource?.BroadcastCompSignal("FiredShot"); }
//[HarmonyPrefix] static bool Prefix(ref bool __result, Verb_LaunchProjectile __instance, LocalTargetInfo ___currentTarget) { if (__instance.verbProps.forcedMissRadius < 0.5f || __instance.verbProps.requireLineOfSight) { // Assuming this is not a mortar-like thing // Perform vanilla logic return(true); } else { // Perform the same vanilla checks if (___currentTarget.HasThing && ___currentTarget.Thing.Map != __instance.caster.Map) { __result = false; return(false); } ThingDef projectile = __instance.Projectile; if (projectile == null) { __result = false; return(false); } ShootLine shootLine = default(ShootLine); bool flag = __instance.TryFindShootLineFromTo(__instance.caster.Position, ___currentTarget, out shootLine); if (__instance.verbProps.stopBurstWithoutLos && !flag) { __result = false; return(false); } // Vanilla checks pass, we can shoot if (__instance.EquipmentSource != null) { CompChangeableProjectile comp = __instance.EquipmentSource.GetComp <CompChangeableProjectile>(); if (comp != null) { comp.Notify_ProjectileLaunched(); } CompReloadable comp2 = __instance.EquipmentSource.GetComp <CompReloadable>(); if (comp2 != null) { comp2.UsedOnce(); } } Thing launcher = __instance.caster; Thing equipment = __instance.EquipmentSource; CompMannable compMannable = __instance.caster.TryGetComp <CompMannable>(); if (compMannable != null && compMannable.ManningPawn != null) { launcher = compMannable.ManningPawn; equipment = __instance.caster; // Earn skills if (compMannable.ManningPawn.skills != null) { int skillsAffectingAccuracy = 0; if (Settings.intellectualAffectsMortarAccuracy) { skillsAffectingAccuracy++; } if (Settings.shootingAffectsMortarAccuracy) { skillsAffectingAccuracy++; } float skillXP = __instance.verbProps.AdjustedFullCycleTime(__instance, __instance.CasterPawn) * 100; skillXP = Mathf.Clamp(skillXP, 0, 200); skillXP /= skillsAffectingAccuracy; if (Settings.intellectualAffectsMortarAccuracy) { compMannable.ManningPawn.skills.Learn(SkillDefOf.Intellectual, skillXP, false); } if (Settings.shootingAffectsMortarAccuracy) { compMannable.ManningPawn.skills.Learn(SkillDefOf.Shooting, skillXP, false); } } } Vector3 drawPos = __instance.caster.DrawPos; Projectile projectile2 = (Projectile)GenSpawn.Spawn(projectile, shootLine.Source, __instance.caster.Map, WipeMode.Vanish); // If targetting a pawn if (Settings.targetLeading) { if (___currentTarget != null && ___currentTarget.Thing != null && ___currentTarget.Thing is Pawn targetPawn && targetPawn.pather.curPath != null) { List <IntVec3> nodes = new List <IntVec3>(targetPawn.pather.curPath.NodesReversed); nodes.Reverse(); // Purge outdated nodes from list for (int i = 0; i < nodes.Count; i++) { if (nodes[i] == targetPawn.Position) { // Remove all previous nodes nodes.RemoveRange(0, i); //Log.Message("Removed " + i + " entries. First node is now " + nodes[0].ToString()); break; } } // Path of target pawn from current to destination // Need travel speed of pawn, estimate Vec3 they will be in based on travel speed of our projectile float targetMoveSpeed = targetPawn.GetStatValue(StatDefOf.MoveSpeed); float projectileMoveSpeed = projectile.projectile.speed; // Estimate position target will be in after this amount of time IntVec3 bestTarget = targetPawn.Position; float bestTimeOffset = float.MaxValue; //Log.Message("Default time offset = " + Mathf.Abs(((targetPawn.Position - caster.Position).LengthHorizontal) / projectileMoveSpeed)); float accumulatedTargetTime = 0f; IntVec3 previousPosition = targetPawn.Position; foreach (IntVec3 pathPosition in nodes) { float projectileDistanceFromTarget = (pathPosition - __instance.caster.Position).LengthHorizontal; float timeForProjectileToReachPosition = projectileDistanceFromTarget / projectileMoveSpeed; //float pawnDistanceFromTarget = (pathPosition - targetPawn.Position).LengthHorizontal; //float timeForPawnToReachPosition = pawnDistanceFromTarget / targetMoveSpeed; float pawnDistanceFromLastPositionToHere = (pathPosition - previousPosition).LengthHorizontal; float timeForPawnToReachPositionFromLastPosition = pawnDistanceFromLastPositionToHere / targetMoveSpeed; accumulatedTargetTime += timeForPawnToReachPositionFromLastPosition; float timeOffset = Mathf.Abs(timeForProjectileToReachPosition - accumulatedTargetTime); if (timeOffset < bestTimeOffset) { bestTarget = pathPosition; bestTimeOffset = timeOffset; //Log.Message("Position " + pathPosition.ToString() + " is better. Time offset is " + timeOffset); } else { //Log.Message("Position " + pathPosition.ToString() + " is not better. Time offset is " + timeOffset); } previousPosition = pathPosition; } //Log.Message("Initial target cell = " + currentTarget.Cell.ToString() + " and new target is " + bestTarget.ToString()); ___currentTarget = new LocalTargetInfo(bestTarget); } } float adjustedForcedMissRadius = GetAdjustedForcedMissRadius(__instance, ___currentTarget); ProjectileHitFlags projectileHitFlags = ProjectileHitFlags.All; IntVec3 targetPosition = ___currentTarget.Cell; //if (adjustedForcedMissRadius > 0.5f) { if (MP.enabled) { Rand.PushState(); } // Calculate random target position using a uniform distribution float randomCircleArea = Rand.Range(0, Mathf.PI * adjustedForcedMissRadius * adjustedForcedMissRadius); float radiusOfRandomCircle = Mathf.Sqrt(randomCircleArea / Mathf.PI); float randomAngle = Rand.Range(0, 2 * Mathf.PI); targetPosition = new IntVec3( (int)(targetPosition.x + radiusOfRandomCircle * Mathf.Cos(randomAngle)), targetPosition.y, (int)(targetPosition.z + radiusOfRandomCircle * Mathf.Sin(randomAngle)) ); if (MP.enabled) { Rand.PopState(); } } //Log.Message("Final target is " + c.ToString()); projectile2.Launch(launcher, drawPos, targetPosition, ___currentTarget, projectileHitFlags, equipment, null); } __result = true; return(false); }
public static bool Patch_Verb_LaunchProjectile_GetProjectile(ref ThingDef __result, Verb_LaunchProjectile __instance) { if (__instance.EquipmentSource != null) { SocketComp comp = __instance.EquipmentSource.GetComp <SocketComp>(); if (comp != null && comp.SocketedRunes.FirstOrDefault(runeComp => runeComp.RuneProps.replacedProjectile != null) is RuneComp rune) { __result = rune.RuneProps.replacedProjectile; return(false); } } return(true); }
public static float CalculateAdjustedForcedMiss(float forcedMiss, IntVec3 vector, Verb_LaunchProjectile instance) { float num = (float)vector.LengthHorizontalSquared; if (num < instance.verbProps.range * 0.25f) { return(0f); } if (num < instance.verbProps.range * 0.5f) { return(forcedMiss * 0.5f); } if (num < instance.verbProps.range * 0.75f) { return(forcedMiss * 0.8f); } return(forcedMiss); }
static void Prefix(Verb_LaunchProjectile __instance) { __instance.EquipmentSource?.BroadcastCompSignal("AboutToFireShot"); }
public static void ExtraProjectiles(Projectile projectile2, Thing launcher, Vector3 origin, LocalTargetInfo usedTarget, LocalTargetInfo intendedTarget, ProjectileHitFlags hitFlags, bool preventFriendlyFire, Thing equipment, ThingDef targetCoverDef, ShootLine shootLine, Verb_LaunchProjectile instance) { IDrawnWeaponWithRotation weapon = null; Pawn pawn = launcher as Pawn; if (pawn != null && pawn.equipment != null) { weapon = pawn.equipment.Primary as IDrawnWeaponWithRotation; } if (weapon == null) { Building_LaserGun turret = launcher as Building_LaserGun; if (turret != null) { weapon = turret.gun as IDrawnWeaponWithRotation; } } if (weapon != null) { float angle = (usedTarget.CenterVector3 - origin).AngleFlat() - (intendedTarget.CenterVector3 - origin).AngleFlat(); weapon.RotationOffset = (angle + 180) % 360 - 180; } projectile2.Launch(launcher, origin, usedTarget, intendedTarget, hitFlags, preventFriendlyFire, equipment, targetCoverDef); int extras = 0; IAdvancedVerb Props = instance.verbProps as IAdvancedVerb; if (Props != null) { extras = Props.ScattershotCount; } else { ScattershotProjectileExtension ext = projectile2.def.GetModExtensionFast <ScattershotProjectileExtension>(); if (ext != null && ext.projectileCount.HasValue) { extras = ext.projectileCount.Value; } } if (extras > 0) { for (int i = 0; i < extras; i++) { Projectile projectile3 = (Projectile)GenSpawn.Spawn(projectile2.def, shootLine.Source, launcher.Map, WipeMode.Vanish); projectile3.Launch(launcher, origin, usedTarget, intendedTarget, hitFlags, preventFriendlyFire, equipment, targetCoverDef); } } }
public static void HighlightFieldRadiusAroundTarget_CustomExplosiveProjectile_Postfix(ref Verb_LaunchProjectile __instance, ref float __result) { if (__instance.Projectile != null) { if (__instance.Projectile.thingClass == typeof(Projectile_ExplosiveOG)) { ThingDef_BulletExplosiveOG bulletExplosiveOG = (ThingDef_BulletExplosiveOG)__instance.Projectile; if (bulletExplosiveOG.explosionradius != 0) { __result = bulletExplosiveOG.explosionradius; } } } }