public override bool Available() { // This part copied from vanilla Verb_LaunchProjectile if (!base.Available()) { return(false); } if (CasterIsPawn) { if (CasterPawn.Faction != Faction.OfPlayer && CasterPawn.mindState.MeleeThreatStillThreat && CasterPawn.mindState.meleeThreat.AdjacentTo8WayOrInside(CasterPawn)) { return(false); } } // Add check for reload if (Projectile == null || (IsAttacking && CompAmmo != null && !CompAmmo.CanBeFiredNow)) { CompAmmo?.TryStartReload(); return(false); } 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); }
protected override bool TryCastShot() { //Reduce ammunition if (CompAmmo != null) { if (!CompAmmo.TryReduceAmmoCount()) { if (CompAmmo.HasMagazine) { CompAmmo.TryStartReload(); } return(false); } } if (base.TryCastShot()) { //Required since Verb_Shoot does this but Verb_LaunchProjectileCE doesn't when calling base.TryCastShot() because Shoot isn't its base if (ShooterPawn != null) { ShooterPawn.records.Increment(RecordDefOf.ShotsFired); } //Drop casings if (VerbPropsCE.ejectsCasings && projectilePropsCE.dropsCasings) { CE_Utility.ThrowEmptyCasing(caster.DrawPos, caster.Map, ThingDef.Named(projectilePropsCE.casingMoteDefname)); } // This needs to here for weapons without magazine to ensure their last shot plays sounds if (CompAmmo != null && !CompAmmo.HasMagazine && CompAmmo.UseAmmo) { if (!CompAmmo.Notify_ShotFired()) { if (VerbPropsCE.muzzleFlashScale > 0.01f) { MoteMaker.MakeStaticMote(caster.Position, caster.Map, ThingDefOf.Mote_ShotFlash, VerbPropsCE.muzzleFlashScale); } if (VerbPropsCE.soundCast != null) { VerbPropsCE.soundCast.PlayOneShot(new TargetInfo(caster.Position, caster.Map)); } if (VerbPropsCE.soundCastTail != null) { VerbPropsCE.soundCastTail.PlayOneShotOnCamera(); } if (ShooterPawn != null) { if (ShooterPawn.thinker != null) { ShooterPawn.mindState.lastEngageTargetTick = Find.TickManager.TicksGame; } } } return(CompAmmo.Notify_PostShotFired()); } return(true); } return(false); }
/// <summary> /// Fires a projectile using the new aiming system /// </summary> /// <returns>True for successful shot, false otherwise</returns> protected 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); } 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); //New aiming algorithm projectile.canTargetSelf = false; var targDist = (sourceLoc - 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 sourceLoc, shotAngle, shotRotation, ShotHeight, ShotSpeed, EquipmentSource ); pelletMechanicsOnly = true; } pelletMechanicsOnly = false; numShotsFired++; if (CompAmmo != null && !CompAmmo.CanBeFiredNow) { CompAmmo?.TryStartReload(); } return(true); }
public override IEnumerable <Gizmo> GetGizmos() // Modified { foreach (Gizmo gizmo in base.GetGizmos()) { yield return(gizmo); } // Ammo gizmos if (CompAmmo != null && (PlayerControlled || Prefs.DevMode)) { foreach (Command com in CompAmmo.CompGetGizmosExtra()) { if (!PlayerControlled && Prefs.DevMode && com is GizmoAmmoStatus) { (com as GizmoAmmoStatus).prefix = "DEV: "; } yield return(com); } } // Don't show CONTROL gizmos on enemy turrets (even with dev mode enabled) if (PlayerControlled) { // Fire mode gizmos if (CompFireModes != null) { foreach (Command com in CompFireModes.GenerateGizmos()) { yield return(com); } } // Set forced target gizmo if (CanSetForcedTarget) { var vt = new Command_VerbTarget { defaultLabel = "CommandSetForceAttackTarget".Translate(), defaultDesc = "CommandSetForceAttackTargetDesc".Translate(), icon = ContentFinder <Texture2D> .Get("UI/Commands/Attack", true), verb = GunCompEq.PrimaryVerb, hotKey = KeyBindingDefOf.Misc4 }; if (Spawned && IsMortarOrProjectileFliesOverhead && Position.Roofed(Map)) { vt.Disable("CannotFire".Translate() + ": " + "Roofed".Translate().CapitalizeFirst()); } yield return(vt); } // Stop forced attack gizmo if (forcedTarget.IsValid) { Command_Action stop = new Command_Action(); stop.defaultLabel = "CommandStopForceAttack".Translate(); stop.defaultDesc = "CommandStopForceAttackDesc".Translate(); stop.icon = ContentFinder <Texture2D> .Get("UI/Commands/Halt", true); stop.action = delegate { ResetForcedTarget(); SoundDefOf.Tick_Low.PlayOneShotOnCamera(null); }; if (!this.forcedTarget.IsValid) { stop.Disable("CommandStopAttackFailNotForceAttacking".Translate()); } stop.hotKey = KeyBindingDefOf.Misc5; yield return(stop); } // Toggle fire gizmo if (CanToggleHoldFire) { yield return(new Command_Toggle { defaultLabel = "CommandHoldFire".Translate(), defaultDesc = "CommandHoldFireDesc".Translate(), icon = ContentFinder <Texture2D> .Get("UI/Commands/HoldFire", true), hotKey = KeyBindingDefOf.Misc6, toggleAction = delegate { holdFire = !holdFire; if (holdFire) { ResetForcedTarget(); } }, isActive = (() => holdFire) }); } } }
public override IEnumerable <Gizmo> GetGizmos() { foreach (Gizmo gizmo in base.GetGizmos()) { yield return(gizmo); } // Don't show gizmos on enemy turrets if (Faction == Faction.OfPlayer || MannedByColonist) { // Ammo gizmos if (CompAmmo != null) { foreach (Command com in CompAmmo.CompGetGizmosExtra()) { yield return(com); } } // Fire mode gizmos if (CompFireModes != null) { foreach (Command com in CompFireModes.GenerateGizmos()) { yield return(com); } } // Set forced target gizmo if (CanSetForcedTarget) { yield return(new Command_VerbTarget { defaultLabel = "CommandSetForceAttackTarget".Translate(), defaultDesc = "CommandSetForceAttackTargetDesc".Translate(), icon = ContentFinder <Texture2D> .Get("UI/Commands/Attack", true), verb = GunCompEq.PrimaryVerb, hotKey = KeyBindingDefOf.Misc4 }); } // Stop forced attack gizmo if (forcedTarget.IsValid) { Command_Action stop = new Command_Action(); stop.defaultLabel = "CommandStopForceAttack".Translate(); stop.defaultDesc = "CommandStopForceAttackDesc".Translate(); stop.icon = ContentFinder <Texture2D> .Get("UI/Commands/Halt", true); stop.action = delegate { ResetForcedTarget(); SoundDefOf.Tick_Low.PlayOneShotOnCamera(null); }; if (!this.forcedTarget.IsValid) { stop.Disable("CommandStopAttackFailNotForceAttacking".Translate()); } stop.hotKey = KeyBindingDefOf.Misc5; yield return(stop); } // Toggle fire gizmo if (CanToggleHoldFire) { yield return(new Command_Toggle { defaultLabel = "CommandHoldFire".Translate(), defaultDesc = "CommandHoldFireDesc".Translate(), icon = ContentFinder <Texture2D> .Get("UI/Commands/HoldFire", true), hotKey = KeyBindingDefOf.Misc6, toggleAction = delegate { holdFire = !holdFire; if (holdFire) { ResetForcedTarget(); } }, isActive = (() => holdFire) }); } } }
public override bool TryCastShot() { //Reduce ammunition if (CompAmmo != null) { if (!CompAmmo.TryReduceAmmoCount(VerbPropsCE.ammoConsumedPerShotCount)) { return(false); } } Vector3 muzzlePos = Caster.DrawPos; if (turretGun != null) { if (turretGun.UseAmmo) { bool playerpawn = this.CasterIsPawn && this.Caster.Faction == Faction.OfPlayer; if (turretGun.HasAmmo) { turretGun.UsedOnce(); } else { return(false); } if (turretGun.RemainingCharges == 0) { if (turretGun.Props.soundEmptyWarning != null && playerpawn) { turretGun.Props.soundEmptyWarning.PlayOneShot(new TargetInfo(this.Caster.Position, this.Caster.Map, false)); } if (!turretGun.Props.messageEmptyWarning.NullOrEmpty() && playerpawn) { MoteMaker.ThrowText(Caster.Position.ToVector3(), Caster.Map, turretGun.Props.messageEmptyWarning.Translate(EquipmentSource.LabelCap, Caster.LabelShortCap), 3f); } } float a = turretGun.RemainingCharges; float b = turretGun.MaxCharges; int remaining = (int)(a / b * 100f); if (remaining == 50 && warningticks == 0) { warningticks = this.verbProps.ticksBetweenBurstShots + 1; if (turretGun.Props.soundHalfRemaningWarning != null && playerpawn) { turretGun.Props.soundHalfRemaningWarning.PlayOneShot(new TargetInfo(this.Caster.Position, this.Caster.Map, false)); } if (!turretGun.Props.messageHalfRemaningWarning.NullOrEmpty() && playerpawn) { MoteMaker.ThrowText(Caster.Position.ToVector3(), Caster.Map, turretGun.Props.messageHalfRemaningWarning.Translate(EquipmentSource.LabelCap, Caster.LabelShortCap, remaining), 3f); } } if (remaining == 25 && warningticks == 0) { warningticks = this.verbProps.ticksBetweenBurstShots + 1; if (turretGun.Props.soundQuaterRemaningWarning != null && playerpawn) { turretGun.Props.soundQuaterRemaningWarning.PlayOneShot(new TargetInfo(this.Caster.Position, this.Caster.Map, false)); } if (!turretGun.Props.messageQuaterRemaningWarning.NullOrEmpty() && playerpawn) { MoteMaker.ThrowText(Caster.Position.ToVector3(), Caster.Map, turretGun.Props.messageQuaterRemaningWarning.Translate(EquipmentSource.LabelCap, Caster.LabelShortCap, remaining), 3f); } } muzzlePos = MuzzlePosition(this.Caster, this.currentTarget, Offset); } } // if (base.TryCastShot()) if (TryCastShotFrom(muzzlePos)) { //Required since Verb_Shoot does this but Verb_LaunchProjectileCE doesn't when calling base.TryCastShot() because Shoot isn't its base if (ShooterPawn != null) { ShooterPawn.records.Increment(RecordDefOf.ShotsFired); } //Drop casings if (VerbPropsCE.ejectsCasings && projectilePropsCE.dropsCasings) { ThrowEmptyCasing(caster.DrawPos, caster.Map, ThingDef.Named(projectilePropsCE.casingMoteDefname)); } // This needs to here for weapons without magazine to ensure their last shot plays sounds if (CompAmmo != null && !CompAmmo.HasMagazine && CompAmmo.UseAmmo) { if (!CompAmmo.Notify_ShotFired()) { if (VerbPropsCE.muzzleFlashScale > 0.01f) { MoteMaker.MakeStaticMote(caster.Position, caster.Map, ThingDefOf.Mote_ShotFlash, VerbPropsCE.muzzleFlashScale); } if (VerbPropsCE.soundCast != null) { VerbPropsCE.soundCast.PlayOneShot(new TargetInfo(caster.Position, caster.Map)); } if (VerbPropsCE.soundCastTail != null) { VerbPropsCE.soundCastTail.PlayOneShotOnCamera(); } if (ShooterPawn != null) { if (ShooterPawn.thinker != null) { ShooterPawn.mindState.lastEngageTargetTick = Find.TickManager.TicksGame; } } } return(CompAmmo.Notify_PostShotFired()); } return(true); } return(false); }
/// <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); }