public void UpdateAction(SoLAction withAction = SoLAction.Pending) { SoLAction inAction = this.solAction; Vector3 destTarget = this.ExactPosition; this.curveVariance = 0; //Log.Message("action for " + solAction.ToString() + " queued action: " + queuedAction.ToString()); if (queuedAction != SoLAction.Null) { solAction = queuedAction; queuedAction = SoLAction.Null; } if (solAction == SoLAction.Pending || solAction == SoLAction.Goto) { if (this.pawn.GetPosture() == PawnPosture.LayingInBed || this.pawn.CurJobDef == JobDefOf.LayDown) { if (!pawn.Awake() && LightEnergy > 5f) { Action_Sleeping(out destTarget); } //pawn injured? } else if (this.pawn.Drafted) { this.delayCount++; if (LightEnergy > 20 && EnergyChance && this.delayCount > 2) { Pawn p = TM_Calc.FindNearbyEnemy(this.pawn, (int)AttackTarget_ShortRange); if (p != null && TM_Calc.HasLoSFromTo(pawn.Position, p, pawn, 0, AttackTarget_ShortRange)) { Action_AttackCharge(p, out destTarget); queuedAction = SoLAction.Limbo; } else { if (LightEnergy > 30 && this.delayCount > 6) { p = TM_Calc.FindNearbyEnemy(this.pawn.Position, this.pawn.Map, this.pawn.Faction, AttackTarget_MaxRange, AttackTarget_ShortRange); if (p != null && TM_Calc.HasLoSFromTo(pawn.Position, p, pawn, 0, AttackTarget_MaxRange)) { Action_Attack(p, out destTarget); queuedAction = SoLAction.Returning; } else { Action_Hover(out destTarget); } } else { Action_Hover(out destTarget); } } } else { Action_Hover(out destTarget); } } else if (this.pawn.Downed && this.pawn.health.hediffSet.GetInjuriesTendable().Count() > 0 && LightEnergy > 10) { Action_GotoTarget(this.pawn.DrawPos, speed_jog, out destTarget); this.assignedTarget = this.pawn; queuedAction = SoLAction.Guarding; } else if (this.shouldGlow) { this.shouldGlow = false; Action_GotoTarget(this.glowCenter.ToVector3Shifted(), this.speed_jog, out destTarget); queuedAction = SoLAction.Glow; } else if (LightEnergy > 20 && EnergyChance) { Pawn p = TM_Calc.FindNearbyInjuredPawnOther(this.pawn, 10, 10f); this.delayCount++; if (this.delayCount > 1 && p != null && p.Downed && TM_Calc.HasLoSFromTo(this.pawn.Position, p, this.pawn, 0, 10) && p.health.hediffSet.GetInjuriesTendable().Count() > 0) { Action_GotoTarget(p.DrawPos, speed_dash, out destTarget); queuedAction = SoLAction.Guarding; this.assignedTarget = p; } else if (LightEnergy > 60 && EnergyChance) { if (this.delayCount > 2) { p = TM_Calc.FindNearbyPawn(this.pawn, 10); if (p != null && p.needs != null && TM_Calc.HasLoSFromTo(this.pawn.Position, p, this.pawn, 0, 10)) { if ((this.pawn.CurJobDef.joyKind != null || this.pawn.CurJobDef == JobDefOf.Wait_Wander || this.pawn.CurJobDef == JobDefOf.GotoWander) && this.pawn.needs.joy.CurLevelPercentage < .5f) { this.delayCount = 0; Action_JoyBurst(this.pawn.DrawPos, out destTarget); } else if (p.needs.joy != null && (p.CurJobDef.joyKind != null || p.CurJobDef == JobDefOf.Wait_Wander || p.CurJobDef == JobDefOf.GotoWander) && p.needs.joy.CurLevelPercentage < .5f) { this.delayCount = 0; Action_JoyBurst(p.DrawPos, out destTarget); } else if (this.delayCount > 3 && p.needs.mood != null && p.needs.mood.thoughts != null && p.needs.mood.thoughts.memories != null && p.needs.mood.thoughts.memories.GetFirstMemoryOfDef(TorannMagicDefOf.TM_BrightDayTD) == null) { this.delayCount = 0; Action_GotoTarget(p.DrawPos, speed_jog, out destTarget); this.assignedTarget = p; queuedAction = SoLAction.BrightenDay; //action circle target } else { Action_Hover(out destTarget); } } else { Action_Hover(out destTarget); } } else { Action_Hover(out destTarget); } } else { Action_Hover(out destTarget); } } //else if(LightEnergy > 90 && (EnergyChance && EnergyChance && EnergyChance)) //{ // Action_Clean(out destTarget); //} else { this.delayCount = 0; Action_Hover(out destTarget); } } else if (solAction == SoLAction.BrightenDay) { if (this.assignedTarget != null && this.assignedTarget is Pawn) { Pawn p = this.assignedTarget as Pawn; ActualLightCost(6f); p.needs.mood.thoughts.memories.TryGainMemory(TorannMagicDefOf.TM_BrightDayTD); Action_CircleTarget(this.assignedTarget, out destTarget); queuedAction = SoLAction.Returning; } } else if (solAction == SoLAction.Glow) { if (this.glowing) { StopGlow(); } else { DoGlow(); } Action_Return(); } else if (solAction == SoLAction.Returning) { Action_Return(); } else if (solAction == SoLAction.Guarding) { if (LightEnergy > 10 && this.assignedTarget != null && this.assignedTarget is Pawn) { Pawn p = this.assignedTarget as Pawn; if (p.health.hediffSet.GetInjuriesTendable().Count() > 0) { this.ticksToImpact = 300; ActualLightCost(2f); CauterizeWounds(p); queuedAction = SoLAction.Guarding; } else { Action_Hover(out destTarget); } } else { Action_Hover(out destTarget); } } else if (solAction == SoLAction.Limbo) { Action_FromLimbo(out destTarget); } if (solAction != SoLAction.Attacking && solAction != SoLAction.Returning && solAction != SoLAction.Guarding && solAction != SoLAction.Circling) { this.destination = destTarget; this.ticksToImpact = this.StartingTicksToImpact; } //Log.Message("ending update action, new action: " + solAction.ToString() + " speed: " + this.speed + " delay action: " + this.delayCount + " light energy: "+ LightEnergy); if (this.solAction != inAction && this.solAction != SoLAction.Hovering && this.solAction != SoLAction.Sleeping) { this.delayCount = 0; } }
protected override void Impact(Thing hitThing) { Map map = base.Map; base.Impact(hitThing); ThingDef def = this.def; Pawn caster = this.launcher as Pawn; if (!this.initialized) { ModOptions.SettingsRef settingsRef = new ModOptions.SettingsRef(); CompAbilityUserMagic comp = caster.GetComp <CompAbilityUserMagic>(); pwrVal = comp.MagicData.MagicPowerSkill_Sabotage.FirstOrDefault((MagicPowerSkill x) => x.label == "TM_Sabotage_pwr").level; verVal = comp.MagicData.MagicPowerSkill_Sabotage.FirstOrDefault((MagicPowerSkill x) => x.label == "TM_Sabotage_ver").level; if (caster.story.traits.HasTrait(TorannMagicDefOf.Faceless)) { MightPowerSkill mpwr = caster.GetComp <CompAbilityUserMight>().MightData.MightPowerSkill_Mimic.FirstOrDefault((MightPowerSkill x) => x.label == "TM_Mimic_pwr"); MightPowerSkill mver = caster.GetComp <CompAbilityUserMight>().MightData.MightPowerSkill_Mimic.FirstOrDefault((MightPowerSkill x) => x.label == "TM_Mimic_ver"); pwrVal = mpwr.level; verVal = mver.level; } this.arcaneDmg = comp.arcaneDmg; if (settingsRef.AIHardMode && !caster.IsColonist) { pwrVal = 3; verVal = 3; } SoundInfo info = SoundInfo.InMap(new TargetInfo(base.Position, this.Map, false), MaintenanceType.None); info.pitchFactor = .5f; info.volumeFactor = .8f; SoundDefOf.PsychicPulseGlobal.PlayOneShot(info); Effecter SabotageEffect = TorannMagicDefOf.TM_SabotageExplosion.Spawn(); SabotageEffect.Trigger(new TargetInfo(base.Position, this.Map, false), new TargetInfo(base.Position, this.Map, false)); SabotageEffect.Cleanup(); targetCells = new List <IntVec3>(); targetCells.Clear(); targetCells = GenRadial.RadialCellsAround(base.Position, this.def.projectile.explosionRadius, true).ToList(); this.targetThings = new List <SabotageThing>(); this.targetThings.Clear(); this.initialized = true; Pawn targetPawn = null; Building targetBuilding = null; for (int i = 0; i < this.targetCells.Count; i++) { if (Rand.Chance(.5f + (.1f * verVal))) { float rnd = Rand.Range(0, 1f); targetPawn = this.targetCells[i].GetFirstPawn(this.Map); if (targetPawn != null) { if (TM_Calc.IsRobotPawn(targetPawn)) { if (Rand.Chance(TM_Calc.GetSpellSuccessChance(caster, targetPawn, true))) { if (rnd <= .33f) { TM_Action.DamageEntities(targetPawn, null, Rand.Range(8, 15) + pwrVal, TMDamageDefOf.DamageDefOf.TM_ElectricalBurn, this.launcher); } else if (rnd <= .66f) { if (targetPawn.mindState != null) { targetPawn.mindState.mentalStateHandler.TryStartMentalState(MentalStateDefOf.Berserk, "logic circuits sabotaged", true, false, null, true); } else { targetPawn.TryStartAttack(TM_Calc.FindNearbyPawn(targetPawn, 10)); } } else if (rnd <= 1f) { int rndCount = Rand.Range(2, 5); for (int j = 0; j < rndCount; j++) { TM_Action.DamageEntities(targetPawn, null, Rand.Range(3, 5) + pwrVal, TMDamageDefOf.DamageDefOf.TM_ElectricalBurn, this.launcher); } } } else { MoteMaker.ThrowText(targetPawn.DrawPos, targetPawn.Map, "TM_ResistedSpell".Translate(), -1); } this.age = this.duration; } else { targetPawn = null; //Log.Message("pawn not a robot, mechanoid, or android"); } } targetBuilding = this.targetCells[i].GetFirstBuilding(this.Map); if (targetPawn == null && targetBuilding != null) { CompPower compP = targetBuilding.GetComp <CompPower>(); CompPowerTrader cpt = targetBuilding.GetComp <CompPowerTrader>(); if (compP != null && compP.Props.basePowerConsumption != 0 && cpt != null && cpt.powerOutputInt != 0) { if (true) { //stun/electrical explosion GenExplosion.DoExplosion(targetBuilding.Position, base.Map, 2 + pwrVal + Mathf.RoundToInt(cpt.powerOutputInt / 400), DamageDefOf.Stun, null); GenExplosion.DoExplosion(targetBuilding.Position, base.Map, 1 + pwrVal + Mathf.RoundToInt(cpt.powerOutputInt / 600), TMDamageDefOf.DamageDefOf.TM_ElectricalBurn, null); } else if (rnd <= .66f) { //electrical burn short circuit } else { } } Building_Battery targetBattery = targetBuilding as Building_Battery; if (targetBattery != null && targetBattery.def.thingClass.ToString() == "RimWorld.Building_Battery") { CompPowerBattery compB = targetBattery.GetComp <CompPowerBattery>(); if (rnd <= .5f) { Traverse.Create(root: targetBattery).Field(name: "ticksToExplode").SetValue(Rand.Range(40, 130) - (5 * pwrVal)); compB.SetStoredEnergyPct(.81f); } else { GenExplosion.DoExplosion(targetBattery.Position, base.Map, 2 + pwrVal + Mathf.RoundToInt(compB.StoredEnergy / 200), DamageDefOf.EMP, null); compB.DrawPower(compB.StoredEnergy); } } Building_TurretGun targetTurret = targetBuilding as Building_TurretGun; if (targetTurret != null && targetTurret.gun != null) { if (rnd <= .5f) { targetTurret.SetFaction(Faction.OfAncientsHostile, null); } else { GenExplosion.DoExplosion(targetTurret.Position, base.Map, 2 + pwrVal, TMDamageDefOf.DamageDefOf.TM_ElectricalBurn, null); //20 default damage } } } else { //Log.Message("no thing to sabotage"); } targetPawn = null; targetBuilding = null; } } } else if (this.targetThings.Count > 0) { this.age = this.duration; } else { this.age = this.duration; } }