protected override bool TryCastShot() { Pawn casterPawn = this.CasterPawn; if (casterPawn == null) { return(false); } foreach (CompUseEffect compUseEffect in base.EquipmentSource.GetComps <CompUseEffect>()) { if (compUseEffect.CanBeUsedBy(casterPawn, out string failReason)) { compUseEffect.DoEffect(casterPawn); } else { Messages.Message(failReason, casterPawn, MessageTypeDefOf.NegativeEvent, false); } } CompReloadable reloadableCompSource = base.ReloadableCompSource; if (reloadableCompSource != null) { reloadableCompSource.UsedOnce(); } return(true); }
// TryCastShotFrom(muzzlePos) public bool TryCastShotFrom(Vector3 muzzlePos) { if (!TryFindCEShootLineFromTo(caster.Position, currentTarget, out var shootLine)) { return(false); } if (projectilePropsCE.pelletCount < 1) { Log.Error(EquipmentSource.LabelCap + " tried firing with pelletCount less than 1."); return(false); } ShiftVecReport report = ShiftVecReportFor(currentTarget); bool pelletMechanicsOnly = false; numShotsFired = (int)AccessTools.Field(typeof(Verb_LaunchProjectileCE), "numShotsFired").GetValue(this); shotAngle = (float)AccessTools.Field(typeof(Verb_LaunchProjectileCE), "shotAngle").GetValue(this); shotRotation = (float)AccessTools.Field(typeof(Verb_LaunchProjectileCE), "shotRotation").GetValue(this); shotSpeed = (float)AccessTools.Field(typeof(Verb_LaunchProjectileCE), "shotSpeed").GetValue(this); for (int i = 0; i < projectilePropsCE.pelletCount; i++) { ProjectileCE projectile = (ProjectileCE)ThingMaker.MakeThing(Projectile, null); GenSpawn.Spawn(projectile, shootLine.Source, caster.Map); ShiftTarget(report, pelletMechanicsOnly); //New aiming algorithm projectile.canTargetSelf = false; var targDist = (muzzlePos.ToIntVec3().ToIntVec2.ToVector2Shifted() - currentTarget.Cell.ToIntVec2.ToVector2Shifted()).magnitude; if (targDist <= 2) { targDist *= 2; // Double to account for divide by 4 in ProjectileCE minimum collision distance calculations } // projectile.minCollisionSqr = Mathf.Pow(targDist, 2); projectile.intendedTarget = currentTarget.Thing; projectile.mount = caster.Position.GetThingList(caster.Map).FirstOrDefault(t => t is Pawn && t != caster); projectile.AccuracyFactor = report.accuracyFactor * report.swayDegrees * ((numShotsFired + 1) * 0.75f); projectile.Launch( Shooter, //Shooter instead of caster to give turret operators' records the damage/kills obtained new Vector2(muzzlePos.x, muzzlePos.z), shotAngle, shotRotation, ShotHeight, ShotSpeed, EquipmentSource ); pelletMechanicsOnly = true; } /// Log.Message("Fired from "+caster.ThingID+" at "+ShotHeight); /// pelletMechanicsOnly = false; numShotsFired++; if (CompAmmo != null && !CompAmmo.CanBeFiredNow) { CompAmmo?.TryStartReload(); } if (CompReloadable != null) { CompReloadable.UsedOnce(); } return(true); }
public static void EMP(CompReloadable comp) { if (comp == null || !comp.CanBeUsed) { return; } ThingWithComps parent = comp.parent; Pawn wearer = comp.Wearer; GenExplosion.DoExplosion(wearer.Position, wearer.Map, parent.GetStatValue(AvaliDefs.ExplodeEMPRadius, true), DamageDefOf.EMP, (Thing)null, -1, -1f, (SoundDef)null, (ThingDef)null, (ThingDef)null, (Thing)null, (ThingDef)null, 0.0f, 1, false, (ThingDef)null, 0.0f, 1, 0.0f, false, new float?(), (List <Thing>)null); comp.UsedOnce(); }
protected override bool TryCastShot() { if (!ModLister.RoyaltyInstalled) { Log.ErrorOnce("Items with jump capability are a Royalty-specific game system. If you want to use this code please check ModLister.RoyaltyInstalled before calling it. See rules on the Ludeon forum for more info.", 550187797); return(false); } #pragma warning disable CS0436 // Type conflicts with imported type CompReloadable reloadableCompSource = base.ReloadableCompSource; #pragma warning restore CS0436 // Type conflicts with imported type Pawn casterPawn = CasterPawn; if (casterPawn == null || reloadableCompSource == null || !reloadableCompSource.CanBeUsed) { return(false); } // Log.Message("reloadableCompSource " + reloadableCompSource.Props.chargeNoun); IntVec3 cell = currentTarget.Cell; Map map = casterPawn.Map; CompReloadableDual reloadableDual = reloadableCompSource as CompReloadableDual; if (reloadableDual != null) { if (this.verbProps.label == reloadableDual.Props.chargeNoun) { reloadableDual.UsedOnce(); // Log.Message("reloadableDual UsedOnce " + reloadableDual.RemainingCharges); } else if (this.verbProps.label == reloadableDual.Props.chargeNounSecondry) { reloadableDual.UsedOnceSecondry(); // Log.Message("reloadableDual UsedOnceSecondry " + reloadableDual.RemainingChargesSecondry); } } else { if (this.verbProps.label == reloadableCompSource.Props.chargeNoun) { reloadableCompSource.UsedOnce(); // Log.Message("reloadableCompSource UsedOnce " + reloadableCompSource.RemainingCharges); } } PawnFlyer pawnFlyer = PawnFlyer.MakeFlyer(verbProps.defaultProjectile ?? ThingDefOf.PawnJumper, casterPawn, cell); if (pawnFlyer != null) { GenSpawn.Spawn(pawnFlyer, cell, map); return(true); } return(false); }
protected override (bool success, Vector3 launchPos, float angle) TryCastShotInternal() { IntVec3 exitTarget = caster.Position.CellFromDistAngle(Building_Artillery.MaxMapDistance, heading); if (!target.HasWorldObject && !target.HasThing) { return(false, Vector3.zero, 0); } ThingDef projectile = Projectile; if (projectile is null) { return(false, Vector3.zero, 0); } bool flag = TryFindShootLineFromTo(caster.Position, exitTarget, out ShootLine shootLine); if (verbProps.stopBurstWithoutLos && !flag) { return(false, Vector3.zero, 0); } if (EquipmentSource != null) { CompChangeableProjectile comp = EquipmentSource.GetComp <CompChangeableProjectile>(); if (comp != null) { comp.Notify_ProjectileLaunched(); } CompReloadable comp2 = EquipmentSource.GetComp <CompReloadable>(); if (comp2 != null) { comp2.UsedOnce(); } } Thing launcher = caster; Thing equipment = EquipmentSource; CompMannable compMannable = caster.TryGetComp <CompMannable>(); if (compMannable != null && compMannable.ManningPawn != null) { launcher = compMannable.ManningPawn; equipment = caster; } Vector3 launchPos = caster.DrawPos; Projectile projectile2 = (Projectile)GenSpawn.Spawn(projectile, caster.Position, caster.Map, WipeMode.Vanish); if (projectile2.AllComps.NullOrEmpty()) { AccessTools.Field(typeof(ThingWithComps), "comps").SetValue(projectile2, new List <ThingComp>()); } projectile2.AllComps.Add(new CompProjectileExitMap(CasterTWC) { airDefenseDef = AntiAircraftDefOf.FlakProjectile, target = target.WorldObject as AerialVehicleInFlight, spawnPos = Building_Artillery.RandomWorldPosition(caster.Map.Tile, 1).FirstOrDefault() }); if (caster.def.GetModExtension <ProjectilePropertiesDefModExtension>() is ProjectilePropertiesDefModExtension projectileProps) { projectile2.AllComps.Add(new CompTurretProjectileProperties(CasterTWC) { speed = projectileProps.speed > 0 ? projectileProps.speed : projectile2.def.projectile.speed, hitflag = ProjectileHitFlags.IntendedTarget, hitflags = null }); } ThrowDebugText("ToHit" + (canHitNonTargetPawnsNow ? "\nchntp" : "")); launchPos += new Vector3(VerbProps.shootOffset.x, 0, VerbProps.shootOffset.y).RotatedBy(heading); projectile2.Launch(launcher, launchPos, exitTarget, exitTarget, ProjectileHitFlags.IntendedTarget, equipment); ThrowDebugText("Hit\nDest", shootLine.Dest); return(true, launchPos, heading); }
/// <summary> /// Fires a projectile using the new aiming system /// </summary> /// <returns>True for successful shot, false otherwise</returns> public override bool TryCastShot() { if (!TryFindCEShootLineFromTo(caster.Position, currentTarget, out var shootLine)) { return(false); } if (projectilePropsCE.pelletCount < 1) { Log.Error(EquipmentSource.LabelCap + " tried firing with pelletCount less than 1."); return(false); } bool instant = false; float spreadDegrees = 0; float aperatureSize = 0; if (Projectile.projectile is ProjectilePropertiesCE pprop) { instant = pprop.isInstant; spreadDegrees = (EquipmentSource?.GetStatValue(StatDef.Named("ShotSpread")) ?? 0) * pprop.spreadMult; aperatureSize = 0.03f; } ShiftVecReport report = ShiftVecReportFor(currentTarget); bool pelletMechanicsOnly = false; for (int i = 0; i < projectilePropsCE.pelletCount; i++) { ProjectileCE projectile = (ProjectileCE)ThingMaker.MakeThing(Projectile, null); GenSpawn.Spawn(projectile, shootLine.Source, caster.Map); ShiftTarget(report, pelletMechanicsOnly, instant); //New aiming algorithm projectile.canTargetSelf = false; var targetDistance = (sourceLoc - currentTarget.Cell.ToIntVec2.ToVector2Shifted()).magnitude; projectile.minCollisionDistance = GetMinCollisionDistance(targetDistance); projectile.intendedTarget = currentTarget; projectile.mount = caster.Position.GetThingList(caster.Map).FirstOrDefault(t => t is Pawn && t != caster); projectile.AccuracyFactor = report.accuracyFactor * report.swayDegrees * ((numShotsFired + 1) * 0.75f); if (instant) { var shotHeight = ShotHeight; float tsa = AdjustShotHeight(caster, currentTarget, ref shotHeight); projectile.RayCast( Shooter, verbProps, sourceLoc, shotAngle + tsa, shotRotation, shotHeight, ShotSpeed, spreadDegrees, aperatureSize, EquipmentSource); } else { projectile.Launch( Shooter, //Shooter instead of caster to give turret operators' records the damage/kills obtained sourceLoc, shotAngle, shotRotation, ShotHeight, ShotSpeed, EquipmentSource); } pelletMechanicsOnly = true; } /* * Notify the lighting tracker that shots fired with muzzle flash value of VerbPropsCE.muzzleFlashScale */ LightingTracker.Notify_ShotsFiredAt(caster.Position, intensity: VerbPropsCE.muzzleFlashScale); pelletMechanicsOnly = false; numShotsFired++; if (CompAmmo != null && !CompAmmo.CanBeFiredNow) { CompAmmo?.TryStartReload(); } if (CompReloadable != null) { CompReloadable.UsedOnce(); } return(true); }
//[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); }
protected virtual (bool success, Vector3 launchPos, float angle) TryCastShotInternal() { if (currentTarget.HasThing && currentTarget.Thing.Map != caster.Map) { return(false, Vector3.zero, 0); } ThingDef projectile = Projectile; if (projectile == null) { return(false, Vector3.zero, 0); } ShootLine shootLine; bool flag = TryFindShootLineFromTo(caster.Position, currentTarget, out shootLine); if (verbProps.stopBurstWithoutLos && !flag) { return(false, Vector3.zero, 0); } if (EquipmentSource != null) { CompChangeableProjectile comp = EquipmentSource.GetComp <CompChangeableProjectile>(); if (comp != null) { comp.Notify_ProjectileLaunched(); } CompReloadable comp2 = EquipmentSource.GetComp <CompReloadable>(); if (comp2 != null) { comp2.UsedOnce(); } } Thing launcher = caster; Thing equipment = EquipmentSource; CompMannable compMannable = caster.TryGetComp <CompMannable>(); if (compMannable != null && compMannable.ManningPawn != null) { launcher = compMannable.ManningPawn; equipment = caster; } Vector3 launchPos = caster.DrawPos; float angle = launchPos.AngleToPoint(currentTarget.CenterVector3); Projectile projectile2 = (Projectile)GenSpawn.Spawn(projectile, shootLine.Source, caster.Map, WipeMode.Vanish); if (caster.def.GetModExtension <ProjectilePropertiesDefModExtension>() is ProjectilePropertiesDefModExtension projectileProps) { projectile2.AllComps.Insert(0, new CompTurretProjectileProperties(CasterTWC) { speed = projectileProps.speed > 0 ? projectileProps.speed : projectile2.def.projectile.speed, hitflag = projectileProps.projectileHitFlag, hitflags = projectileProps.hitFlagDef }); } if (verbProps.forcedMissRadius > 0.5f) { float num = VerbUtility.CalculateAdjustedForcedMiss(verbProps.forcedMissRadius, currentTarget.Cell - caster.Position); if (num > 0.5f) { int max = GenRadial.NumCellsInRadius(num); int num2 = Rand.Range(0, max); if (num2 > 0) { IntVec3 c = currentTarget.Cell + GenRadial.RadialPattern[num2]; launchPos += new Vector3(VerbProps.shootOffset.x, 0, VerbProps.shootOffset.y).RotatedBy(angle); ThrowDebugText("ToRadius"); ThrowDebugText("Rad\nDest", c); ProjectileHitFlags projectileHitFlags = ProjectileHitFlags.NonTargetWorld; if (Rand.Chance(0.5f)) { projectileHitFlags = ProjectileHitFlags.All; } if (!canHitNonTargetPawnsNow) { projectileHitFlags &= ~ProjectileHitFlags.NonTargetPawns; } projectile2.Launch(launcher, launchPos, c, currentTarget, projectileHitFlags, equipment, null); return(true, launchPos, angle); } } } ShotReport shotReport = ShotReport.HitReportFor(caster, this, currentTarget); Thing randomCoverToMissInto = shotReport.GetRandomCoverToMissInto(); ThingDef targetCoverDef = (randomCoverToMissInto != null) ? randomCoverToMissInto.def : null; if (!Rand.Chance(shotReport.AimOnTargetChance_IgnoringPosture)) { shootLine.ChangeDestToMissWild(shotReport.AimOnTargetChance_StandardTarget); ThrowDebugText("ToWild" + (canHitNonTargetPawnsNow ? "\nchntp" : "")); ThrowDebugText("Wild\nDest", shootLine.Dest); ProjectileHitFlags projectileHitFlags2 = ProjectileHitFlags.NonTargetWorld; if (Rand.Chance(0.5f) && canHitNonTargetPawnsNow) { projectileHitFlags2 |= ProjectileHitFlags.NonTargetPawns; } launchPos += new Vector3(VerbProps.shootOffset.x, 0, VerbProps.shootOffset.y).RotatedBy(angle); projectile2.Launch(launcher, launchPos, shootLine.Dest, currentTarget, projectileHitFlags2, equipment, targetCoverDef); return(true, launchPos, angle); } if (currentTarget.Thing != null && currentTarget.Thing.def.category == ThingCategory.Pawn && !Rand.Chance(shotReport.PassCoverChance)) { ThrowDebugText("ToCover" + (canHitNonTargetPawnsNow ? "\nchntp" : "")); ThrowDebugText("Cover\nDest", randomCoverToMissInto.Position); ProjectileHitFlags projectileHitFlags3 = ProjectileHitFlags.NonTargetWorld; if (canHitNonTargetPawnsNow) { projectileHitFlags3 |= ProjectileHitFlags.NonTargetPawns; } launchPos += new Vector3(VerbProps.shootOffset.x, 0, VerbProps.shootOffset.y).RotatedBy(angle); projectile2.Launch(launcher, launchPos, randomCoverToMissInto, currentTarget, projectileHitFlags3, equipment, targetCoverDef); return(true, launchPos, angle); } ProjectileHitFlags projectileHitFlags4 = ProjectileHitFlags.IntendedTarget; if (canHitNonTargetPawnsNow) { projectileHitFlags4 |= ProjectileHitFlags.NonTargetPawns; } if (!currentTarget.HasThing || currentTarget.Thing.def.Fillage == FillCategory.Full) { projectileHitFlags4 |= ProjectileHitFlags.NonTargetWorld; } ThrowDebugText("ToHit" + (canHitNonTargetPawnsNow ? "\nchntp" : "")); if (currentTarget.Thing != null) { angle = launchPos.AngleToPoint(currentTarget.CenterVector3); launchPos += new Vector3(VerbProps.shootOffset.x, 0, VerbProps.shootOffset.y).RotatedBy(angle); projectile2.Launch(launcher, launchPos, currentTarget, currentTarget, projectileHitFlags4, equipment, targetCoverDef); ThrowDebugText("Hit\nDest", currentTarget.Cell); } else { angle = launchPos.AngleToPoint(shootLine.Dest.ToVector3Shifted()); launchPos += new Vector3(VerbProps.shootOffset.x, 0, VerbProps.shootOffset.y).RotatedBy(angle); projectile2.Launch(launcher, launchPos, shootLine.Dest, currentTarget, projectileHitFlags4, equipment, targetCoverDef); ThrowDebugText("Hit\nDest", shootLine.Dest); } return(true, launchPos, angle); }
protected override bool TryCastShot() { if (this.currentTarget.HasThing && this.currentTarget.Thing.Map != this.caster.Map) { return(false); } ThingDef projectile = this.Projectile; if (projectile == null) { return(false); } ShootLine shootLine; bool flag = base.TryFindShootLineFromTo(this.caster.Position, this.currentTarget, out shootLine); if (this.verbProps.stopBurstWithoutLos && !flag) { return(false); } if (base.EquipmentSource != null) { CompChangeableProjectile comp = base.EquipmentSource.GetComp <CompChangeableProjectile>(); if (comp != null) { comp.Notify_ProjectileLaunched(); } CompReloadable comp2 = base.EquipmentSource.GetComp <CompReloadable>(); if (comp2 != null) { comp2.UsedOnce(); } } Thing launcher = this.caster; Thing equipment = base.EquipmentSource; CompMannable compMannable = this.caster.TryGetComp <CompMannable>(); if (compMannable != null && compMannable.ManningPawn != null) { launcher = compMannable.ManningPawn; equipment = this.caster; } Vector3 drawPos = this.caster.DrawPos; var casterTurret = caster as Building_TurretGun; Thing gun = null; if (casterTurret != null) { gun = casterTurret.gun; } var newSource = ApplyOffset(shootLine.Source, shootLine.Dest); var newSourceVec = newSource.ToVector3(); Projectile projectile2 = (Projectile)GenSpawn.Spawn(projectile, this.caster.Position, this.caster.Map, WipeMode.Vanish); if (this.verbProps.ForcedMissRadius > 0.5f) { float num = VerbUtility.CalculateAdjustedForcedMiss(this.verbProps.ForcedMissRadius, this.currentTarget.Cell - this.caster.Position); if (num > 0.5f) { int max = GenRadial.NumCellsInRadius(num); int num2 = Rand.Range(0, max); if (num2 > 0) { IntVec3 c = this.currentTarget.Cell + GenRadial.RadialPattern[num2]; this.ThrowDebugText("ToRadius"); this.ThrowDebugText("Rad\nDest", c); ProjectileHitFlags projectileHitFlags = ProjectileHitFlags.NonTargetWorld; if (Rand.Chance(0.5f)) { projectileHitFlags = ProjectileHitFlags.All; } if (!this.canHitNonTargetPawnsNow) { projectileHitFlags &= ~ProjectileHitFlags.NonTargetPawns; } projectile2.Launch(launcher, newSourceVec, c, this.currentTarget, projectileHitFlags, false, equipment, null); return(true); } } } ShotReport shotReport = ShotReport.HitReportFor(this.caster, this, this.currentTarget); Thing randomCoverToMissInto = shotReport.GetRandomCoverToMissInto(); ThingDef targetCoverDef = (randomCoverToMissInto != null) ? randomCoverToMissInto.def : null; if (!Rand.Chance(shotReport.AimOnTargetChance_IgnoringPosture)) { shootLine.ChangeDestToMissWild(shotReport.AimOnTargetChance_StandardTarget); this.ThrowDebugText("ToWild" + (this.canHitNonTargetPawnsNow ? "\nchntp" : "")); this.ThrowDebugText("Wild\nDest", shootLine.Dest); ProjectileHitFlags projectileHitFlags2 = ProjectileHitFlags.NonTargetWorld; if (Rand.Chance(0.5f) && this.canHitNonTargetPawnsNow) { projectileHitFlags2 |= ProjectileHitFlags.NonTargetPawns; } projectile2.Launch(launcher, newSourceVec, shootLine.Dest, this.currentTarget, projectileHitFlags2, false, equipment, targetCoverDef); return(true); } if (this.currentTarget.Thing != null && this.currentTarget.Thing.def.category == ThingCategory.Pawn && !Rand.Chance(shotReport.PassCoverChance)) { this.ThrowDebugText("ToCover" + (this.canHitNonTargetPawnsNow ? "\nchntp" : "")); this.ThrowDebugText("Cover\nDest", randomCoverToMissInto.Position); ProjectileHitFlags projectileHitFlags3 = ProjectileHitFlags.NonTargetWorld; if (this.canHitNonTargetPawnsNow) { projectileHitFlags3 |= ProjectileHitFlags.NonTargetPawns; } projectile2.Launch(launcher, newSourceVec, randomCoverToMissInto, this.currentTarget, projectileHitFlags3, false, equipment, targetCoverDef); return(true); } ProjectileHitFlags projectileHitFlags4 = ProjectileHitFlags.IntendedTarget; if (this.canHitNonTargetPawnsNow) { projectileHitFlags4 |= ProjectileHitFlags.NonTargetPawns; } if (!this.currentTarget.HasThing || this.currentTarget.Thing.def.Fillage == FillCategory.Full) { projectileHitFlags4 |= ProjectileHitFlags.NonTargetWorld; } this.ThrowDebugText("ToHit" + (this.canHitNonTargetPawnsNow ? "\nchntp" : "")); if (this.currentTarget.Thing != null) { projectile2.Launch(launcher, newSourceVec, this.currentTarget, this.currentTarget, projectileHitFlags4, false, equipment, targetCoverDef); this.ThrowDebugText("Hit\nDest", this.currentTarget.Cell); } else { projectile2.Launch(launcher, newSourceVec, shootLine.Dest, this.currentTarget, projectileHitFlags4, false, equipment, targetCoverDef); this.ThrowDebugText("Hit\nDest", shootLine.Dest); } return(true); }