public static void Postfix(Verb __instance, IntVec3 root, LocalTargetInfo targ, ref ShootLine resultingLine, ref bool __result) { if (teleportBack) { if (oldMap1 != null) { ZUtils.TeleportThing(targ.Thing, oldMap1, targ.Thing.Position); oldMap1 = null; } else if (oldMap2 != null) { ZUtils.TeleportThing(__instance.caster, oldMap2, __instance.caster.Position); oldMap2 = null; } if (__result) { if (ind1 > ind2 && !IsVoidsEverywhereInShootingLine(resultingLine, __instance.caster.Map, __instance.caster, targ.Thing)) { __result = false; } else if (ind1 < ind2 && !IsVoidsEverywhereInShootingLineInBackWard(resultingLine, targ.Thing.Map, __instance.caster, targ.Thing)) { __result = false; } } ind1 = 0; ind2 = 0; teleportBack = false; } }
internal static bool Prefix(Verb __instance, ref bool __result, IntVec3 root, LocalTargetInfo targ, ref ShootLine resultingLine) { if (__instance is Verb_LaunchProjectileCE launchVerbCE) { __result = launchVerbCE.TryFindCEShootLineFromTo(root, targ, out resultingLine); return(false); } return(true); }
public bool TryFindCEShootLineFromTo(IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine) { if (targ.HasThing && targ.Thing.Map != caster.Map) { resultingLine = default(ShootLine); return(false); } if (verbProps.range <= ShootTuning.MeleeRange) // If this verb has a MAX range up to melee range (NOT a MIN RANGE!) { resultingLine = new ShootLine(root, targ.Cell); return(ReachabilityImmediate.CanReachImmediate(root, targ, caster.Map, PathEndMode.Touch, null)); } CellRect cellRect = (!targ.HasThing) ? CellRect.SingleCell(targ.Cell) : targ.Thing.OccupiedRect(); float num = cellRect.ClosestDistSquaredTo(root); if (num > verbProps.range * verbProps.range || num < verbProps.minRange * verbProps.minRange) { resultingLine = new ShootLine(root, targ.Cell); return(false); } //if (!this.verbProps.NeedsLineOfSight) This method doesn't consider the currently loaded projectile if (Projectile.projectile.flyOverhead) { resultingLine = new ShootLine(root, targ.Cell); return(true); } // First check current cell for early opt-out IntVec3 dest; var shotSource = root.ToVector3Shifted(); shotSource.y = ShotHeight; // Adjust for multi-tile turrets if (caster.def.building?.IsTurret ?? false) { shotSource = ShotSource; } if (CanHitFromCellIgnoringRange(shotSource, targ, out dest)) { resultingLine = new ShootLine(root, dest); return(true); } // For pawns, calculate possible lean locations if (CasterIsPawn) { // Next check lean sources ShootLeanUtility.LeanShootingSourcesFromTo(root, cellRect.ClosestCellTo(root), caster.Map, tempLeanShootSources); foreach (var leanLoc in tempLeanShootSources) { var leanOffset = (leanLoc - root).ToVector3() * 0.5f; if (CanHitFromCellIgnoringRange(shotSource + leanOffset, targ, out dest)) { resultingLine = new ShootLine(leanLoc, dest); return(true); } } } resultingLine = new ShootLine(root, targ.Cell); return(false); }
public static void Prefix(Verb __instance, IntVec3 root, LocalTargetInfo targ, ref ShootLine resultingLine, ref bool __result) { if (__instance.caster?.Map != targ.Thing?.Map && __instance.caster?.Map?.Tile == targ.Thing?.Map?.Tile) { ind1 = ZUtils.ZTracker.GetZIndexFor(__instance.caster.Map); ind2 = ZUtils.ZTracker.GetZIndexFor(targ.Thing.Map); if (ind1 > ind2) { teleportBack = true; oldMap1 = targ.Thing.Map; ZUtils.TeleportThing(targ.Thing, __instance.caster.Map, targ.Thing.Position); } else if (ind1 < ind2) { teleportBack = true; oldMap2 = __instance.caster.Map; ZUtils.TeleportThing(__instance.caster, targ.Thing.Map, __instance.caster.Position); } } }
static bool AddShieldCheck(ref bool __result, Verb __instance, IntVec3 root, LocalTargetInfo targ, ref ShootLine resultingLine) { if (ShieldBlocks(__instance.caster, __instance, root, targ)) { __result = false; resultingLine = new ShootLine(); return(false); } return(true); }
private bool TryFindShootLineFromTo(IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine) { resultingLine = new ShootLine(root, targ.Cell); return(false); }
public void Notify_WarmingCastAlongLine(ShootLine newShootLine, IntVec3 ShootPosition) { shootSourceOffset = newShootLine.Source - actor.Position; }
public bool TryFindCEShootLineFromTo(IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine) { if (targ.HasThing && targ.Thing.Map != this.caster.Map) { resultingLine = default(ShootLine); return(false); } if (this.verbProps.MeleeRange) { resultingLine = new ShootLine(root, targ.Cell); return(ReachabilityImmediate.CanReachImmediate(root, targ, this.caster.Map, PathEndMode.Touch, null)); } CellRect cellRect = (!targ.HasThing) ? CellRect.SingleCell(targ.Cell) : targ.Thing.OccupiedRect(); float num = cellRect.ClosestDistSquaredTo(root); if (num > this.verbProps.range * this.verbProps.range || num < this.verbProps.minRange * this.verbProps.minRange) { resultingLine = new ShootLine(root, targ.Cell); return(false); } //if (!this.verbProps.NeedsLineOfSight) This method doesn't consider the currently loaded projectile if (ProjectileDef.projectile.flyOverhead) { resultingLine = new ShootLine(root, targ.Cell); return(true); } if (this.CasterIsPawn) { IntVec3 dest; if (this.CanHitFromCellIgnoringRange(root, targ, out dest)) { resultingLine = new ShootLine(root, dest); return(true); } ShootLeanUtility.LeanShootingSourcesFromTo(root, cellRect.ClosestCellTo(root), this.caster.Map, tempLeanShootSources); for (int i = 0; i < tempLeanShootSources.Count; i++) { IntVec3 intVec = tempLeanShootSources[i]; if (this.CanHitFromCellIgnoringRange(intVec, targ, out dest)) { resultingLine = new ShootLine(intVec, dest); return(true); } } } else { CellRect.CellRectIterator iterator = this.caster.OccupiedRect().GetIterator(); while (!iterator.Done()) { IntVec3 current = iterator.Current; IntVec3 dest; if (this.CanHitFromCellIgnoringRange(current, targ, out dest)) { resultingLine = new ShootLine(current, dest); return(true); } iterator.MoveNext(); } } resultingLine = new ShootLine(root, targ.Cell); return(false); }
//[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); }
// Token: 0x060041D3 RID: 16851 RVA: 0x001E066F File Offset: 0x001DEA6F public void Notify_WarmingCastAlongLine(ShootLine newShootLine, IntVec3 ShootPosition) { this.leaner.Notify_WarmingCastAlongLine(newShootLine, ShootPosition); }
public static bool Prefix(Verb __instance, IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine, ref bool __result) { if (__instance.verbProps.IsMeleeAttack) { resultingLine = new ShootLine(root, targ.Cell); __result = ReachabilityImmediate.CanReachImmediate(root, targ, __instance.caster.Map, PathEndMode.Touch, null); return(false); } if (__instance.verbProps.verbClass.ToString() == "Wizardry.Verb_BLOS") { //Ignores line of sight resultingLine = new ShootLine(root, targ.Cell); __result = true; return(false); } resultingLine = default(ShootLine); __result = true; return(true); }
public bool FireProjectile() { if (base.currentTarget.HasThing && base.currentTarget.Thing.Map != base.caster.Map) { return(false); } ThingDef projectile = this.Projectile; if (projectile == null) { return(false); } ShootLine shootLine = default(ShootLine); bool flag = base.TryFindShootLineFromTo(base.caster.Position, base.currentTarget, out shootLine); if (base.verbProps.stopBurstWithoutLos && !flag) { return(false); } if (base.EquipmentSource != null) { CompChangeableProjectile comp = base.EquipmentSource.GetComp <CompChangeableProjectile>(); if (comp != null) { comp.Notify_ProjectileLaunched(); } } Thing launcher = base.caster; Thing equipment = base.EquipmentSource; CompMannable compMannable = base.caster.TryGetComp <CompMannable>(); if (compMannable != null && compMannable.ManningPawn != null) { launcher = compMannable.ManningPawn; equipment = base.caster; // Earn skills if (compMannable.ManningPawn.skills != null) { int skillsAffectingAccuracy = 0; if (Settings.intellectualAffectsMortarAccuracy) { skillsAffectingAccuracy++; } if (Settings.shootingAffectsMortarAccuracy) { skillsAffectingAccuracy++; } float skillXP = verbProps.AdjustedFullCycleTime(this, CasterPawn) * 100; 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 = base.caster.DrawPos; Projectile projectile2 = (Projectile)GenSpawn.Spawn(projectile, shootLine.Source, base.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 - 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); } } if (base.verbProps.forcedMissRadius > 0.5f) { float adjustedForcedMissRadius = GetAdjustedForcedMissRadius(); ProjectileHitFlags projectileHitFlags = ProjectileHitFlags.All; IntVec3 targetPosition = currentTarget.Cell; if (adjustedForcedMissRadius > 0.5f) { int max = GenRadial.NumCellsInRadius(adjustedForcedMissRadius); 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, base.currentTarget, projectileHitFlags, equipment, null); return(true); } ShotReport shotReport = ShotReport.HitReportFor(base.caster, this, base.currentTarget); Thing randomCoverToMissInto = shotReport.GetRandomCoverToMissInto(); ThingDef targetCoverDef = (randomCoverToMissInto == null) ? null : randomCoverToMissInto.def; /*if (!Rand.Chance(shotReport.AimOnTargetChance_IgnoringPosture)) * { * shootLine.ChangeDestToMissWild(shotReport.AimOnTargetChance_StandardTarget); * this.ThrowDebugText("ToWild" + ((!base.canHitNonTargetPawnsNow) ? string.Empty : "\nchntp")); * this.ThrowDebugText("Wild\nDest", shootLine.Dest); * ProjectileHitFlags projectileHitFlags2 = ProjectileHitFlags.NonTargetWorld; * if (Rand.Chance(0.5f) && base.canHitNonTargetPawnsNow) * { * projectileHitFlags2 |= ProjectileHitFlags.NonTargetPawns; * } * projectile2.Launch(launcher, drawPos, shootLine.Dest, base.currentTarget, projectileHitFlags2, equipment, targetCoverDef); * return true; * }*/ /*if (base.currentTarget.Thing != null && base.currentTarget.Thing.def.category == ThingCategory.Pawn && !Rand.Chance(shotReport.PassCoverChance)) * { * this.ThrowDebugText("ToCover" + ((!base.canHitNonTargetPawnsNow) ? string.Empty : "\nchntp")); * this.ThrowDebugText("Cover\nDest", randomCoverToMissInto.Position); * ProjectileHitFlags projectileHitFlags3 = ProjectileHitFlags.NonTargetWorld; * if (base.canHitNonTargetPawnsNow) * { * projectileHitFlags3 |= ProjectileHitFlags.NonTargetPawns; * } * projectile2.Launch(launcher, drawPos, randomCoverToMissInto, base.currentTarget, projectileHitFlags3, equipment, targetCoverDef); * return true; * }*/ ProjectileHitFlags projectileHitFlags4 = ProjectileHitFlags.IntendedTarget; if (base.canHitNonTargetPawnsNow) { projectileHitFlags4 |= ProjectileHitFlags.NonTargetPawns; } if (!base.currentTarget.HasThing || base.currentTarget.Thing.def.Fillage == FillCategory.Full) { projectileHitFlags4 |= ProjectileHitFlags.NonTargetWorld; } this.ThrowDebugText("ToHit" + ((!base.canHitNonTargetPawnsNow) ? string.Empty : "\nchntp")); if (base.currentTarget.Thing != null) { projectile2.Launch(launcher, drawPos, base.currentTarget, base.currentTarget, projectileHitFlags4, equipment, targetCoverDef); this.ThrowDebugText("Hit\nDest", base.currentTarget.Cell); } else { projectile2.Launch(launcher, drawPos, shootLine.Dest, base.currentTarget, projectileHitFlags4, equipment, targetCoverDef); this.ThrowDebugText("Hit\nDest", shootLine.Dest); } return(true); }
// Token: 0x06003B77 RID: 15223 RVA: 0x001BFC0C File Offset: 0x001BE00C protected override IEnumerable <Toil> MakeNewToils() { yield return(Toils_General.DoAtomic(delegate { Pawn pawn = this.job.targetA.Thing as Pawn; if (pawn != null && pawn.Downed && this.pawn.mindState.duty != null && this.pawn.mindState.duty.attackDownedIfStarving && this.pawn.Starving()) { this.job.killIncappedTarget = true; } })); yield return(Toils_Misc.ThrowColonistAttackingMote(TargetIndex.A)); // yield return(new Toil() { initAction = () => { Pawn actor = this.GetActor(); Vector3 drawPos = actor.DrawPos; var shootLine = new ShootLine(actor.PositionHeld, pawn.PositionHeld); Projectile projectile2 = (Projectile)GenSpawn.Spawn(ThingDef.Named("LotRD_Dragonfireblast"), shootLine.Source, actor.Map, WipeMode.Vanish); if (Rand.Value > 0.9f) { //Log.Message("Miss"); int num = Rand.Range(2, 3); int max = GenRadial.NumCellsInRadius(num); int num2 = Rand.Range(0, max); if (num2 > 0) { IntVec3 c = pawn.PositionHeld + GenRadial.RadialPattern[num2]; ProjectileHitFlags projectileHitFlags = ProjectileHitFlags.NonTargetWorld; if (Rand.Chance(0.5f)) { projectileHitFlags = ProjectileHitFlags.All; } projectile2.Launch(actor, drawPos, c, pawn, projectileHitFlags, null, null); return; } } var covers = CoverUtility.CalculateCoverGiverSet(job.targetA, actor.Position, actor.Map); covers.TryRandomElementByWeight((CoverInfo c) => c.BlockChance, out CoverInfo coverInfo); ThingDef targetCoverDef = (coverInfo.Thing == null) ? null : coverInfo.Thing.def; if (pawn != null) { projectile2.Launch(actor, drawPos + new Vector3(0, 0, 3), pawn, pawn, ProjectileHitFlags.All, null, targetCoverDef); } else { projectile2.Launch(actor, drawPos + new Vector3(0, 0, 3), shootLine.Dest, pawn, ProjectileHitFlags.All, null, targetCoverDef); } // Sends a wave outwards of flames Vector2 behindVector = pawn.Rotation.AsVector2; var behind = new IntVec3((int)behindVector.x, 0, (int)behindVector.y); int rand = Rand.Range(6, 12); //Log.Message("Pawn position: " + pawn.PositionHeld.x.ToString() + " " + pawn.PositionHeld.z.ToString()); for (int i = 0; i < rand; i++) { IntVec3 adjustment = new IntVec3((int)pawn.PositionHeld.x + (int)behind.x + i, pawn.PositionHeld.y, (int)pawn.PositionHeld.z + (int)behind.z + i); //Log.Message("Fire position: " + adjustment.x.ToString() + " " + adjustment.z.ToString()); if (!adjustment.IsValid) { continue; } Projectile projectileNew = (Projectile)GenSpawn.Spawn(ThingDef.Named("LotRD_Dragonfireblast"), shootLine.Source, actor.Map, WipeMode.Vanish); var headoffset = (actor.Rotation == Rot4.West) ? -3.75f : 3.75f; projectileNew.Launch(actor, drawPos + new Vector3(0, 0, 1.5f) + new Vector3(actor.Rotation.AsVector2.x + headoffset, 0, actor.Rotation.AsVector2.y), adjustment, pawn, ProjectileHitFlags.All, null, targetCoverDef); } } });
public static void ExtraProjectiles(Projectile projectile2, Thing launcher, Vector3 origin, LocalTargetInfo usedTarget, LocalTargetInfo intendedTarget, ProjectileHitFlags hitFlags, 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, 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, equipment, targetCoverDef); } } }
// Verse.Verb // Token: 0x060022E2 RID: 8930 RVA: 0x000D4A4C File Offset: 0x000D2C4C public new bool TryFindShootLineFromTo(IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine) { if (targ.HasThing && targ.Thing.Map != this.Caster.Map) { resultingLine = default(ShootLine); return(false); } if (this.verbProps.IsMeleeAttack || this.EffectiveRange <= 1.42f) { resultingLine = new ShootLine(root, targ.Cell); return(ReachabilityImmediate.CanReachImmediate(root, targ, this.Caster.Map, PathEndMode.Touch, null)); } CellRect cellRect = targ.HasThing ? targ.Thing.OccupiedRect() : CellRect.SingleCell(targ.Cell); float num = this.verbProps.EffectiveMinRange(targ, this.Caster); float num2 = cellRect.ClosestDistSquaredTo(root); if (num2 > this.EffectiveRange * this.EffectiveRange || num2 < num * num) { resultingLine = new ShootLine(root, targ.Cell); return(false); } if (!this.verbProps.requireLineOfSight) { resultingLine = new ShootLine(root, targ.Cell); return(true); } if (this.CasterIsPawn) { IntVec3 dest; if (this.CanHitFromCellIgnoringRange(root, targ, out dest)) { resultingLine = new ShootLine(root, dest); return(true); } ShootLeanUtility.LeanShootingSourcesFromTo(root, cellRect.ClosestCellTo(root), this.Caster.Map, Verb_ShootCompMounted.tempLeanShootSources); for (int i = 0; i < Verb_ShootCompMounted.tempLeanShootSources.Count; i++) { IntVec3 intVec = Verb_ShootCompMounted.tempLeanShootSources[i]; if (this.CanHitFromCellIgnoringRange(intVec, targ, out dest)) { resultingLine = new ShootLine(intVec, dest); return(true); } } } else { IntVec2 size = new IntVec2(Caster.def.size.x + 1, Caster.def.size.z + 1); foreach (IntVec3 intVec2 in GenAdj.OccupiedRect(Caster.Position, Caster.Rotation, size)) { IntVec3 dest; if (this.CanHitFromCellIgnoringRange(intVec2, targ, out dest)) { resultingLine = new ShootLine(intVec2, dest); return(true); } } } resultingLine = new ShootLine(root, targ.Cell); return(false); }