protected override Job TryGiveJob(Pawn pawn) { if (pawn != null && pawn.Map != null && pawn.health != null && pawn.health.hediffSet != null && pawn.health.hediffSet.HasHediff(TorannMagicDefOf.TM_ChiHD) && !pawn.Drafted) { if (pawn.InBed() || HealthAIUtility.ShouldSeekMedicalRest(pawn) || !(pawn.GetPosture() == PawnPosture.Standing)) { return(null); } Need_Joy curJoy = pawn.needs.joy; if (curJoy == null) { return(null); } if (curJoy.CurLevel >= .8f) { return(null); } CompAbilityUserMight comp = pawn.GetComp <CompAbilityUserMight>(); if (comp != null) { MightPower mightPower = comp.MightData.MightPowersM.FirstOrDefault <MightPower>((MightPower x) => x.abilityDef == TorannMagicDefOf.TM_Meditate); if (mightPower == null) { return(null); } if (!mightPower.AutoCast) { return(null); } Hediff hediff = pawn.health.hediffSet.GetFirstHediffOfDef(TorannMagicDefOf.TM_ChiHD); PawnAbility ability = pawn.GetComp <CompAbilityUserMight>().AbilityData.Powers.FirstOrDefault((PawnAbility x) => x.Def == TorannMagicDefOf.TM_Meditate); if (ability.CooldownTicksLeft > 0 || hediff.Severity >= 70) { return(null); } Building_Bed building_Bed = pawn.ownership.OwnedBed; if (building_Bed != null) { if (building_Bed.GetRoom() != null && !building_Bed.GetRoom().PsychologicallyOutdoors) { List <IntVec3> roomCells = building_Bed.GetRoom().Cells.ToList(); for (int i = 0; i < roomCells.Count; i++) { if (roomCells[i].IsValid && roomCells[i].Walkable(pawn.Map) && roomCells[i].GetFirstBuilding(pawn.Map) == null) { return(new Job(TorannMagicDefOf.JobDriver_TM_Meditate, roomCells[i])); } } } } return(new Job(TorannMagicDefOf.JobDriver_TM_Meditate, pawn.Position)); } } return(null); }
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) { bool result = false; Pawn pawn2 = t as Pawn; if (pawn.story.traits.HasTrait(WizardryDefOf.LotRW_Istari)) { CompWizardry comp = pawn.GetComp <CompWizardry>(); PawnAbility pawnAbility = comp.AbilityData.Powers.FirstOrDefault((PawnAbility x) => x.Def == WizardryDefOf.LotRW_Nienna_HealingTouch); if (pawn2 != null && (!this.def.tendToHumanlikesOnly || pawn2.RaceProps.Humanlike) && (!this.def.tendToAnimalsOnly || pawn2.RaceProps.Animal) && WorkGiver_Tend.GoodLayingStatusForTend(pawn2, pawn) && HasHediffInjuries(pawn2) && pawn != pawn2 && pawnAbility.CooldownTicksLeft <= 0) { LocalTargetInfo target = pawn2; if (pawn.CanReserve(target, 1, -1, null, forced)) { return(true); } } } return(result); }
public static int GetGizmoCount(Pawn p, PawnAbility pa) { if (iconPawn != p) { iconPawn = p; iconOffset.Clear(); iconAnchorY = 0; iconAnchorX = 0; } if (iconOffset.ContainsKey(pa)) { return(iconOffset[pa]); } else { int count = iconOffset.Count; iconOffset.Add(pa, count); return(count); } }
public static bool PawnAbility_GetJob_Prefix(PawnAbility __instance, AbilityContext context, LocalTargetInfo target, ref Job __result) { Job job; Log.Message("target is " + target.Thing.LabelShort); AbilityDef abilityDef = Traverse.Create(root: __instance).Field(name: "powerdef").GetValue <AbilityDef>(); Log.Message("ability def is " + abilityDef.defName); Verb_UseAbility verb = Traverse.Create(root: __instance).Field(name: "verb").GetValue <Verb_UseAbility>(); Log.Message("verb is " + verb); if (verb == null) { Verb_UseAbility verb_UseAbility = (Verb_UseAbility)Activator.CreateInstance(abilityDef.MainVerb.verbClass); verb_UseAbility.caster = __instance.Pawn; verb_UseAbility.Ability = __instance; verb_UseAbility.verbProps = abilityDef.MainVerb; verb = verb_UseAbility; } if (verb != null) { Log.Message("verb is no longer null"); } job = abilityDef.GetJob(verb.UseAbilityProps.AbilityTargetCategory, target); job.playerForced = true; job.verbToUse = verb; job.count = context == AbilityContext.Player ? 1 : 0; //Count 1 for Player : 0 for AI if (target != null) { if (target.Thing is Pawn pawn2) { job.killIncappedTarget = pawn2.Downed; } } __result = job; return(false); }
public static void Evaluate(CompAbilityUserMagic casterComp, TMAbilityDef abilitydef, PawnAbility ability, MagicPower power, HediffDef hediffDef, out bool success) { success = false; if (casterComp.Mana.CurLevel >= casterComp.ActualManaCost(abilitydef) && ability.CooldownTicksLeft <= 0) { Pawn caster = casterComp.Pawn; LocalTargetInfo jobTarget = TM_Calc.FindNearbyPawn(caster, (int)(abilitydef.MainVerb.range * .9f)); float distanceToTarget = (jobTarget.Cell - caster.Position).LengthHorizontal; if (distanceToTarget < (abilitydef.MainVerb.range * .9f) && jobTarget != null && jobTarget.Thing != null && jobTarget.Thing is Pawn) { Pawn targetPawn = jobTarget.Thing as Pawn; if (targetPawn.RaceProps.Humanlike && targetPawn.IsColonist) { bool tatteredApparel = false; //List<Thought_Memory> targetPawnThoughts = null; //targetPawn.needs.mood.thoughts.GetDistinctMoodThoughtGroups(targetPawnThoughts); //Log.Message("target pawn is " + targetPawn.LabelShort); //List<Thought_Memory> targetPawnThoughts = targetPawn.needs.mood.thoughts.memories.Memories; //for (int i = 0; i < targetPawnThoughts.Count; i++) //{ // if (targetPawnThoughts[i].def == ThoughtDefOf.ApparelDamaged) // { // tatteredApparel = true; // } //} List <Apparel> apparel = targetPawn.apparel.WornApparel; for (int i = 0; i < apparel.Count; i++) { //Log.Message("evaluating equipment " + apparel[i].def.defName + " with hitpoint % of " + (float)(apparel[i].HitPoints/ apparel[i].MaxHitPoints) + " or " + (float)(apparel[i].HitPoints) / (float)(apparel[i].MaxHitPoints)); if (((float)(apparel[i].HitPoints) / (float)(apparel[i].MaxHitPoints)) < .5f) { tatteredApparel = true; } } if (targetPawn.equipment.Primary != null) { if ((float)(targetPawn.equipment.Primary.HitPoints) / (float)(targetPawn.equipment.Primary.MaxHitPoints) < .5f) { tatteredApparel = true; } } if (!targetPawn.health.hediffSet.HasHediff(hediffDef, false) && tatteredApparel) { Job job = ability.GetJob(AbilityContext.AI, jobTarget); caster.jobs.TryTakeOrderedJob(job); success = true; } } } } }
public static void Evaluate(CompAbilityUserMight casterComp, TMAbilityDef abilitydef, PawnAbility ability, MightPower power, out bool success) { success = false; if (casterComp.Stamina.CurLevel >= abilitydef.staminaCost && ability.CooldownTicksLeft <= 0) { Pawn caster = casterComp.Pawn; LocalTargetInfo jobTarget = TM_Calc.FindNearbyFighter(caster, (int)(abilitydef.MainVerb.range * 1.5f), false); float distanceToTarget = (jobTarget.Cell - caster.Position).LengthHorizontal; if (distanceToTarget < (abilitydef.MainVerb.range * 1.5f) && jobTarget != null && jobTarget.Thing != null && jobTarget.Thing is Pawn) { Pawn targetPawn = jobTarget.Thing as Pawn; CompAbilityUserMight targetPawnComp = targetPawn.GetComp <CompAbilityUserMight>(); if (targetPawn.CurJobDef.joyKind != null || targetPawn.CurJobDef == JobDefOf.Wait_Wander || targetPawn.CurJobDef == JobDefOf.GotoWander) { if (targetPawn.IsColonist && targetPawnComp.MightUserLevel < casterComp.MightUserLevel && caster.relations.OpinionOf(targetPawn) >= 0) { Job job = ability.GetJob(AbilityContext.AI, jobTarget); caster.jobs.TryTakeOrderedJob(job); success = true; } } } } }
public static void Evaluate(CompAbilityUserMagic casterComp, TMAbilityDef abilitydef, PawnAbility ability, MagicPower power, out bool success) { success = false; Pawn caster = casterComp.Pawn; LocalTargetInfo jobTarget = caster; if (casterComp.Mana.CurLevel >= casterComp.ActualManaCost(abilitydef) && ability.CooldownTicksLeft <= 0 && jobTarget.Thing != null) { float injurySeverity = 0; using (IEnumerator <BodyPartRecord> enumerator = caster.health.hediffSet.GetInjuredParts().GetEnumerator()) { while (enumerator.MoveNext()) { BodyPartRecord rec = enumerator.Current; IEnumerable <Hediff_Injury> arg_BB_0 = caster.health.hediffSet.GetHediffs <Hediff_Injury>(); Func <Hediff_Injury, bool> arg_BB_1; arg_BB_1 = ((Hediff_Injury injury) => injury.Part == rec); foreach (Hediff_Injury current in arg_BB_0.Where(arg_BB_1)) { bool flag5 = current.CanHealNaturally() && !current.IsPermanent(); if (flag5) { injurySeverity += current.Severity; } } } } if (injurySeverity != 0 && !(caster.health.hediffSet.HasHediff(HediffDef.Named("TM_HediffShield")))) { Job job = ability.GetJob(AbilityContext.AI, jobTarget); caster.jobs.TryTakeOrderedJob(job); success = true; } } }
public static void Evaluate(CompAbilityUserMagic casterComp, TMAbilityDef abilitydef, PawnAbility ability, MagicPower power, out bool success) { success = false; Pawn caster = casterComp.Pawn; LocalTargetInfo jobTarget = caster.Position; if (casterComp.Mana.CurLevel >= casterComp.ActualManaCost(abilitydef) && ability.CooldownTicksLeft <= 0 && jobTarget != null) { Job job = ability.GetJob(AbilityContext.AI, jobTarget); caster.jobs.TryTakeOrderedJob(job); success = true; } }
public override AbilityAIDef TryPickAbility(Pawn caster) { //Get all eligible abilities. IEnumerable <AbilityAIDef> abilities = from validAbilityDef in //Initial filtering. (from abilityAIDef in profileDef.abilities //where tags.FindAll(tag => tags.Contains(tag))?.Count() >= tags.Count where tags.FindAll(tag => abilityAIDef.tags.Contains(tag))?.Count() >= tags.Count select abilityAIDef) //Blacklist filtering. where !validAbilityDef.tags.Any(tag => blacklistedTags.Contains(tag)) select validAbilityDef; //Debug //Log.Message("-=abilities list=-"); //GenDebug.LogList(abilities); if (abilities != null) { //Filter out abilities we do not have. ThingComp thingComp = caster.AllComps.First(comp => comp.GetType() == profileDef.compAbilityUserClass); CompAbilityUser compAbilityUser = thingComp as CompAbilityUser; IEnumerable <AbilityAIDef> knownAbilities = from abilityAIDef in abilities from abilityUserAbility in compAbilityUser.AbilityData.AllPowers where abilityAIDef.ability == abilityUserAbility.Def && profileDef.Worker.CanUseAbility(profileDef, caster, abilityAIDef) orderby abilityAIDef.Worker.PowerScoreFor(abilityAIDef, caster) descending select abilityAIDef; //Debug //Log.Message("-=knownAbilities list=-"); //GenDebug.LogList(knownAbilities); if (compAbilityUser != null) { if (knownAbilities != null && knownAbilities.Count() > 0) { //Return highest power ability which can be cast. foreach (AbilityAIDef ability in knownAbilities) { string reason = ""; //Log.Message("-=AbilityVerbs list=-"); //GenDebug.LogList(compAbilityUser.AbilityVerbs); //Can we cast the ability in the implementation of it? PawnAbility pawnAbility = compAbilityUser.AbilityData.AllPowers.First(pawnAbilityInt => pawnAbilityInt.Def == ability.ability); Verb_UseAbility abilityVerb = pawnAbility.Verb; //.First(abilityIntVerb => abilityIntVerb.Ability.Def == ability.ability); //Log.Message("abilityVerb=" + abilityVerb.ability.powerdef.defName); if (compAbilityUser.CanCastPowerCheck(abilityVerb, out reason) /*&& !pawnAbility.NeedsCooldown*/) //To-Do: Put back check after Ability Framework redesign. { //Debug //Log.Message("Can cast abilityVerb=" + abilityVerb.ability.powerdef.defName); if (ability.usedOnCaster) { //Target self. if (ability.CanPawnUseThisAbility(caster, caster)) { return(ability); } } else if (ability.needEnemyTarget) { //Enemy target specific. if (caster.mindState.enemyTarget != null && ability.CanPawnUseThisAbility(caster, caster.mindState.enemyTarget)) { return(ability); } } else { //Need no target. if (ability.CanPawnUseThisAbility(caster, LocalTargetInfo.Invalid)) { return(ability); } } } else { //Debug //Log.Message("Can't cast abilityVerb=" + abilityVerb.ability.powerdef.defName + ", with reason: " + reason.Translate(abilityVerb.caster.ToString())); } } } } } return(null); }
public static void TryExecute(CompAbilityUserMight casterComp, TMAbilityDef abilitydef, PawnAbility ability, MightPower power, LocalTargetInfo target, int minRange, out bool success) { success = false; if (casterComp.Stamina.CurLevel >= abilitydef.staminaCost && ability.CooldownTicksLeft <= 0) { Pawn caster = casterComp.Pawn; LocalTargetInfo jobTarget = target; float distanceToTarget = (jobTarget.Cell - caster.Position).LengthHorizontal; if (distanceToTarget > minRange && distanceToTarget < (abilitydef.MainVerb.range * .9f) && jobTarget != null && jobTarget.Thing != null && TM_Calc.HasLoSFromTo(caster.Position, jobTarget, caster, 0, abilitydef.MainVerb.range)) { Job job = ability.GetJob(AbilityContext.AI, jobTarget); job.endIfCantShootTargetFromCurPos = true; caster.jobs.TryTakeOrderedJob(job); success = true; } } }
public static void Evaluate(CompAbilityUserMagic casterComp, TMAbilityDef abilitydef, PawnAbility ability, MagicPower power, out bool success) { success = false; EvaluateMinRange(casterComp, abilitydef, ability, power, 6f, out success); }
public void ClearSpellRemnants(CompAbilityUserMagic comp) { if (comp != null) { if (comp.Pawn.equipment != null && comp.Pawn.equipment.Primary != null && comp.Pawn.equipment.Primary.def.defName.Contains("TM_TechnoWeapon_Base")) { comp.technoWeaponThing = null; comp.technoWeaponThingDef = null; comp.technoWeaponDefNum = -1; if (!comp.Pawn.equipment.Primary.DestroyedOrNull()) { comp.Pawn.equipment.Primary.Destroy(DestroyMode.Vanish); } } if (comp.MagicUserLevel >= 20) { PawnAbility pa = comp.AbilityData.Powers.FirstOrDefault((PawnAbility x) => x.Def == TorannMagicDefOf.TM_TeachMagic); if (pa != null) { pa.CooldownTicksLeft = Mathf.RoundToInt(pa.MaxCastingTicks * comp.coolDown); } } if (comp.earthSprites != IntVec3.Invalid || comp.earthSpriteType != 0) { comp.earthSpriteType = 0; comp.earthSpriteMap = null; comp.earthSprites = IntVec3.Invalid; comp.earthSpritesInArea = false; } if (comp.stoneskinPawns != null && comp.stoneskinPawns.Count > 0) { for (int i = 0; i < comp.stoneskinPawns.Count; i++) { if (comp.stoneskinPawns[i].health.hediffSet.HasHediff(TorannMagicDefOf.TM_StoneskinHD)) { Hediff hd = comp.stoneskinPawns[i].health?.hediffSet?.GetFirstHediffOfDef(TorannMagicDefOf.TM_StoneskinHD); if (hd != null) { comp.stoneskinPawns[i].health.RemoveHediff(hd); } } } } if (comp.weaponEnchants != null && comp.weaponEnchants.Count > 0) { for (int i = 0; i < comp.weaponEnchants.Count; i++) { Verb_DispelEnchantWeapon.RemoveExistingEnchantment(comp.weaponEnchants[i]); } comp.weaponEnchants.Clear(); comp.RemovePawnAbility(TorannMagicDefOf.TM_DispelEnchantWeapon); } if (comp.enchanterStones != null && comp.enchanterStones.Count > 0) { for (int i = 0; i < comp.enchanterStones.Count; i++) { if (comp.enchanterStones[i].Map != null) { TM_Action.TransmutateEffects(comp.enchanterStones[i].Position, comp.Pawn); } comp.enchanterStones[i].Destroy(DestroyMode.Vanish); } comp.enchanterStones.Clear(); comp.RemovePawnAbility(TorannMagicDefOf.TM_DismissEnchanterStones); } if (comp.summonedSentinels != null && comp.summonedSentinels.Count > 0) { for (int i = 0; i < comp.summonedSentinels.Count; i++) { if (comp.summonedSentinels[i].Map != null) { TM_Action.TransmutateEffects(comp.summonedSentinels[i].Position, comp.Pawn); } comp.summonedSentinels[i].Destroy(DestroyMode.Vanish); } comp.summonedSentinels.Clear(); comp.RemovePawnAbility(TorannMagicDefOf.TM_ShatterSentinel); } if (comp.soulBondPawn != null) { comp.soulBondPawn = null; } } }
public static void Evaluate(CompAbilityUserMagic casterComp, TMAbilityDef abilitydef, PawnAbility ability, MagicPower power, HediffDef hediffDef, out bool success) { success = false; EvaluateMinSeverity(casterComp, abilitydef, ability, power, hediffDef, 0, out success); }
public static void EvaluateMinSeverity(CompAbilityUserMagic casterComp, TMAbilityDef abilitydef, PawnAbility ability, MagicPower power, float minSeverity, out bool success) { success = false; if (casterComp.Mana.CurLevel >= casterComp.ActualManaCost(abilitydef) && ability.CooldownTicksLeft <= 0) { Pawn caster = casterComp.Pawn; LocalTargetInfo jobTarget = TM_Calc.FindNearbyPermanentlyInjuredPawn(caster, (int)(abilitydef.MainVerb.range * .9f), minSeverity); float distanceToTarget = (jobTarget.Cell - caster.Position).LengthHorizontal; if (distanceToTarget < (abilitydef.MainVerb.range * .9f) && jobTarget != null && jobTarget.Thing != null) { Job job = ability.GetJob(AbilityContext.AI, jobTarget); caster.jobs.TryTakeOrderedJob(job); success = true; TM_Action.TM_Toils.GotoAndWait(jobTarget.Thing as Pawn, caster, Mathf.RoundToInt(ability.Def.MainVerb.warmupTime * 60)); } } }
public static void EvaluateMinSeverity(CompAbilityUserMagic casterComp, TMAbilityDef abilitydef, PawnAbility ability, MagicPower power, float minSeverity, out bool success) { success = false; if (casterComp.Mana.CurLevel >= casterComp.ActualManaCost(abilitydef) && ability.CooldownTicksLeft <= 0) { Pawn caster = casterComp.Pawn; LocalTargetInfo jobTarget = TM_Calc.FindNearbyInjuredPawn(caster, (int)(abilitydef.MainVerb.range * .9f), minSeverity); float distanceToTarget = (jobTarget.Cell - caster.Position).LengthHorizontal; if (distanceToTarget < (abilitydef.MainVerb.range * .9f) && jobTarget != null && jobTarget.Thing != null) { if (abilitydef == TorannMagicDefOf.TM_CauterizeWound && jobTarget.Thing is Pawn) { Pawn targetPawn = jobTarget.Thing as Pawn; if (targetPawn.health.HasHediffsNeedingTend(false)) { Job job = ability.GetJob(AbilityContext.AI, jobTarget); job.endIfCantShootTargetFromCurPos = true; caster.jobs.TryTakeOrderedJob(job); success = true; } } else { Job job = ability.GetJob(AbilityContext.AI, jobTarget); caster.jobs.TryTakeOrderedJob(job); success = true; } } } }
public static void EvaluateMinRange(CompAbilityUserMight casterComp, TMAbilityDef abilitydef, PawnAbility ability, MightPower power, float minRange, out bool success) { success = false; if (casterComp.Stamina.CurLevel >= abilitydef.staminaCost && ability.CooldownTicksLeft <= 0) { Pawn caster = casterComp.Pawn; LocalTargetInfo jobTarget = TM_Calc.FindNearbyEnemy(caster, (int)(abilitydef.MainVerb.range * .9f)); if (jobTarget != null && jobTarget.Thing != null && abilitydef == TorannMagicDefOf.TM_AntiArmor) { Pawn targetPawn = jobTarget.Thing as Pawn; if (targetPawn.RaceProps.IsFlesh) { jobTarget = null; } } float distanceToTarget = (jobTarget.Cell - caster.Position).LengthHorizontal; if (jobTarget != null && jobTarget.Thing != null && (distanceToTarget > minRange && distanceToTarget < (abilitydef.MainVerb.range * .9f)) && TM_Calc.HasLoSFromTo(caster.Position, jobTarget, caster, 0, abilitydef.MainVerb.range)) { Job job = ability.GetJob(AbilityContext.AI, jobTarget); job.endIfCantShootTargetFromCurPos = true; caster.jobs.TryTakeOrderedJob(job); success = true; } } }
public static void Evaluate(CompAbilityUserMight mightComp, TMAbilityDef abilitydef, PawnAbility ability, MightPower power, int minTargetCount, int radiusAround, IntVec3 evaluatedCenter, bool hostile, out bool success) { success = false; if (mightComp.Stamina.CurLevel >= abilitydef.staminaCost && ability.CooldownTicksLeft <= 0) { Pawn caster = mightComp.Pawn; List <Pawn> targetList = TM_Calc.FindPawnsNearTarget(caster, radiusAround, evaluatedCenter, hostile); if (targetList != null) { LocalTargetInfo jobTarget = null; if (targetList.Count >= minTargetCount && (abilitydef == TorannMagicDefOf.TM_BladeSpin)) { jobTarget = caster; } if (jobTarget != null && jobTarget.Thing != caster) { float distanceToTarget = (jobTarget.Cell - caster.Position).LengthHorizontal; } if (jobTarget != null && jobTarget.Thing != null) { Job job = ability.GetJob(AbilityContext.AI, jobTarget); caster.jobs.TryTakeOrderedJob(job); success = true; } } } }
public static void Evaluate(CompAbilityUserMagic casterComp, TMAbilityDef abilitydef, PawnAbility ability, MagicPower power, float minDistance, out bool success) { success = false; Pawn caster = casterComp.Pawn; LocalTargetInfo jobTarget = caster.CurJob.targetA; Thing carriedThing = null; if (caster.CurJob.targetA.Thing != null) //&& caster.CurJob.def.defName != "Sow") { if (caster.CurJob.targetA.Thing.Map != caster.Map) //carrying thing { jobTarget = caster.CurJob.targetB; carriedThing = caster.CurJob.targetA.Thing; } else if (caster.CurJob.targetB != null && caster.CurJob.targetB.Thing != null && caster.CurJob.def != JobDefOf.Rescue) //targetA using targetB for job { if (caster.CurJob.targetB.Thing.Map != caster.Map) //carrying targetB to targetA { jobTarget = caster.CurJob.targetA; carriedThing = caster.CurJob.targetB.Thing; } else if (caster.CurJob.def == JobDefOf.TendPatient) { jobTarget = caster.CurJob.targetB; } else //Getting targetA to carry to TargetB { jobTarget = caster.CurJob.targetA; } } else { jobTarget = caster.CurJob.targetA; } } float distanceToTarget = (jobTarget.Cell - caster.Position).LengthHorizontal; Vector3 directionToTarget = TM_Calc.GetVector(caster.Position, jobTarget.Cell); //Log.Message("" + caster.LabelShort + " job def is " + caster.CurJob.def.defName + " targetA " + caster.CurJob.targetA + " targetB " + caster.CurJob.targetB + " jobTarget " + jobTarget + " at distance " + distanceToTarget + " min distance " + minDistance + " at vector " + directionToTarget); if (casterComp.Mana.CurLevel >= casterComp.ActualManaCost(abilitydef) && ability.CooldownTicksLeft <= 0 && distanceToTarget < 200) { if (distanceToTarget > minDistance && caster.CurJob.locomotionUrgency >= LocomotionUrgency.Jog && caster.CurJob.bill == null) { if (distanceToTarget <= abilitydef.MainVerb.range && jobTarget.Cell != default(IntVec3)) { //Log.Message("doing blink to thing"); DoBlink(caster, jobTarget.Cell, ability, carriedThing); success = true; } else { IntVec3 blinkToCell = caster.Position + (directionToTarget * abilitydef.MainVerb.range).ToIntVec3(); //Log.Message("doing partial blink to cell " + blinkToCell); //MoteMaker.ThrowHeatGlow(blinkToCell, caster.Map, 1f); if (blinkToCell.IsValid && blinkToCell.InBounds(caster.Map) && blinkToCell.Walkable(caster.Map) && !blinkToCell.Fogged(caster.Map) && ((blinkToCell - caster.Position).LengthHorizontal < distanceToTarget)) { DoBlink(caster, blinkToCell, ability, carriedThing); success = true; } } } } }
protected override Job TryGiveJob(Pawn pawn) { //Do we have at least one elegible profile? IEnumerable <AbilityUserAIProfileDef> profiles = pawn.EligibleAIProfiles(); /*StringBuilder builder = new StringBuilder("profiles = "); * * foreach(AbilityUserAIProfileDef profile in profiles) * { * builder.Append(profile.defName + ", "); * } * * Log.Message(builder.ToString());*/ if (profiles != null && profiles.Count() > 0) { //No Job to give. Yet. //Go through all available Profiles in order to find a Ability to use. foreach (AbilityUserAIProfileDef profile in profiles) { if (profile != null) { //Traverse the decision tree. //List<AbilityDecisionNode> currentNodes = new List<AbilityDecisionNode>(); //List<AbilityDecisionNode> nextNodes = new List<AbilityDecisionNode>(); //Seed root. //nextNodes.Add(profile.decisionTree); //Result AbilityAIDef to use. AbilityAIDef useThisAbility = null; if (profile.decisionTree != null) { useThisAbility = profile.decisionTree.RecursivelyGetAbility(pawn); } //Debug /*int nodesTraversed = 0; * AbilityDecisionNode lastNode = null; * * //Flat recursive iteration * do * { * //Add from next list to current list. * currentNodes.AddRange(nextNodes); * nextNodes.Clear(); * * //Check if we can continue traversing on the current level. * foreach (AbilityDecisionNode currentNode in currentNodes) * { * nodesTraversed++; * * if (currentNode.CanContinueTraversing(pawn)) * nextNodes.AddRange(currentNode.subNodes); * * //Try picking an ability. * useThisAbility = currentNode.TryPickAbility(pawn); * * //Found ability to use. * if (useThisAbility != null) * { * lastNode = currentNode; * break; * } * } * * //Found ability to use. * if (useThisAbility != null) * break; * * //Clear current set. * currentNodes.Clear(); * } while (nextNodes.Count > 0);*/ //Debug //if (useThisAbility != null) // Log.Message("JobGiver_AIAbilityUser.TryGiveJob for '" + pawn.ThingID + "' with ability: " + useThisAbility.defName + ", while traversing " + nodesTraversed + " nodes."); //else // Log.Message("JobGiver_AIAbilityUser.TryGiveJob for '" + pawn.ThingID + "' with ability: No ability, while traversing " + nodesTraversed + " nodes."); if (useThisAbility != null) { //Debug /*Log.Message("Ability '" + useThisAbility.defName + "' picked for AI.\n" + * "lastNode=" + lastNode.GetType().Name + "\n" + * "lastNode.parent=" + lastNode?.parent?.GetType()?.Name);*/ //Get CompAbilityUser ThingComp thingComp = pawn.AllComps.First(comp => comp.GetType() == profile.compAbilityUserClass); CompAbilityUser compAbilityUser = thingComp as CompAbilityUser; if (compAbilityUser != null) { //Get Ability from Pawn. PawnAbility useAbility = compAbilityUser.AbilityData.AllPowers.First(ability => ability.Def == useThisAbility.ability); string reason = ""; //Give job. if (useAbility.CanCastPowerCheck(AbilityContext.AI, out reason)) { LocalTargetInfo target = useThisAbility.Worker.TargetAbilityFor(useThisAbility, pawn); if (target.IsValid) { return(useAbility.UseAbility(AbilityContext.AI, target)); } } } } } } } //No Job to give. //Report. //Log.Message("JobGiver_AIAbilityUser.TryGiveJob for '" + pawn.ThingID + "' is Invalid."); return(null); }
private static void DoPhase(Pawn caster, IntVec3 targetCell, PawnAbility ability, Thing carriedThing) { JobDef retainJobDef = caster.CurJobDef; LocalTargetInfo retainTargetA = caster.CurJob.targetA; int retainCount = 1; if (retainTargetA.Thing != null && retainTargetA.Thing.stackCount != 1) { retainCount = retainTargetA.Thing.stackCount; } LocalTargetInfo retainTargetB = caster.CurJob.targetB; LocalTargetInfo retainTargetC = caster.CurJob.targetC; Pawn p = caster; Thing cT = carriedThing; if (cT != null && cT.stackCount != 1) { retainCount = cT.stackCount; } Map map = caster.Map; IntVec3 casterCell = caster.Position; bool selectCaster = false; if (Find.Selector.FirstSelectedObject == caster) { selectCaster = true; } try { for (int i = 0; i < 3; i++) { TM_MoteMaker.ThrowGenericMote(ThingDefOf.Mote_Smoke, caster.DrawPos, caster.Map, Rand.Range(.6f, 1f), .4f, .1f, Rand.Range(.8f, 1.2f), 0, Rand.Range(2, 3), Rand.Range(-30, 30), 0); TM_MoteMaker.ThrowGenericMote(TorannMagicDefOf.Mote_Enchanting, caster.DrawPos, caster.Map, Rand.Range(1.4f, 2f), .2f, .05f, Rand.Range(.4f, .6f), Rand.Range(-200, 200), 0, 0, 0); } caster.DeSpawn(); GenSpawn.Spawn(p, targetCell, map); if (carriedThing != null) { carriedThing.DeSpawn(); GenPlace.TryPlaceThing(cT, targetCell, map, ThingPlaceMode.Near); //GenSpawn.Spawn(cT, targetCell, map); } caster.GetComp <CompAbilityUserMight>().MightUserXP -= 50; ability.PostAbilityAttempt(); if (selectCaster) { Find.Selector.Select(caster, false, true); } for (int i = 0; i < 3; i++) { TM_MoteMaker.ThrowGenericMote(ThingDefOf.Mote_Smoke, caster.DrawPos, caster.Map, Rand.Range(.6f, 1f), .4f, .1f, Rand.Range(.8f, 1.2f), 0, Rand.Range(2, 3), Rand.Range(-30, 30), 0); TM_MoteMaker.ThrowGenericMote(TorannMagicDefOf.Mote_Enchanting, caster.DrawPos, caster.Map, Rand.Range(1.4f, 2f), .2f, .05f, Rand.Range(.4f, .6f), Rand.Range(-200, 200), 0, 0, 0); } Job job = new Job(retainJobDef, retainTargetA, retainTargetB, retainTargetC) { count = retainCount, playerForced = false }; //caster.jobs.TryTakeOrderedJob(); caster.jobs.StartJob(job); } catch { if (!caster.Spawned) { GenSpawn.Spawn(p, casterCell, map); } } }
public static void Evaluate(CompAbilityUserMagic casterComp, TMAbilityDef abilitydef, PawnAbility ability, MagicPower power, bool inCombat, bool reverse, out bool success) //reverse == true transfers mana to caster { success = false; if (casterComp.Mana.CurLevel >= casterComp.ActualManaCost(abilitydef) && ability.CooldownTicksLeft <= 0) { Pawn caster = casterComp.Pawn; LocalTargetInfo jobTarget = TM_Calc.FindNearbyMage(caster, (int)(abilitydef.MainVerb.range * .9f), inCombat); if (!inCombat && jobTarget != null && jobTarget.Thing != null) { Pawn transferPawn = jobTarget.Thing as Pawn; CompAbilityUserMagic tComp = transferPawn.GetComp <CompAbilityUserMagic>(); if (reverse) { if (casterComp.Mana.CurLevel >= .3f || tComp.Mana.CurLevel <= .9f) { jobTarget = null; } } else { if (casterComp.Mana.CurLevel <= .9f || tComp.Mana.CurLevel >= .9f) { jobTarget = null; } } } float distanceToTarget = (jobTarget.Cell - caster.Position).LengthHorizontal; if (distanceToTarget < (abilitydef.MainVerb.range * .9f) && jobTarget != null && jobTarget.Thing != null) { Job job = ability.GetJob(AbilityContext.AI, jobTarget); caster.jobs.TryTakeOrderedJob(job); success = true; } } }
public static void TryExecute(CompAbilityUser casterComp, AbilityDef abilitydef, PawnAbility ability, LocalTargetInfo target, int minRange, out bool success) { success = false; if (ability.CooldownTicksLeft <= 0) { Pawn caster = casterComp.Pawn; LocalTargetInfo jobTarget = target; float distanceToTarget = (jobTarget.Cell - caster.Position).LengthHorizontal; if (distanceToTarget > minRange && distanceToTarget < (abilitydef.MainVerb.range * .9f) && jobTarget != null && jobTarget.Thing != null && Functions.Eval.HasLoSFromTo(caster.Position, jobTarget, caster, 0, abilitydef.MainVerb.range)) { Log.Message("ability is " + ability.Def.defName + " target is " + jobTarget.Thing.LabelShort + " caster job is " + caster.CurJob); Job job = ability.GetJob(AbilityContext.AI, jobTarget); Log.Message("job is " + job); job.endIfCantShootTargetFromCurPos = true; caster.jobs.TryTakeOrderedJob(job); success = true; } //a small change to test a push } }
public static void Evaluate(CompAbilityUserMagic casterComp, TMAbilityDef abilitydef, PawnAbility ability, MagicPower power, float minDistance, out bool success) { success = false; Pawn caster = casterComp.Pawn; LocalTargetInfo jobTarget = caster.CurJob.targetA; float distanceToTarget = (jobTarget.Cell - caster.Position).LengthHorizontal; Vector3 directionToTarget = TM_Calc.GetVector(caster.Position, jobTarget.Cell); if (casterComp.Mana.CurLevel >= casterComp.ActualManaCost(abilitydef) && ability.CooldownTicksLeft <= 0 && jobTarget.Thing != null && jobTarget.Thing.def.EverHaulable) { //Log.Message("summon: " + caster.LabelShort + " job def is " + caster.CurJob.def.defName + " targetA " + caster.CurJob.targetA + " targetB " + caster.CurJob.targetB + " jobTarget " + jobTarget + " at distance " + distanceToTarget + " min distance " + minDistance + " at vector " + directionToTarget); if (distanceToTarget > minDistance && distanceToTarget < abilitydef.MainVerb.range && caster.CurJob.locomotionUrgency >= LocomotionUrgency.Jog && caster.CurJob.bill == null && distanceToTarget < 200) { Job job = ability.GetJob(AbilityContext.AI, jobTarget); caster.jobs.TryTakeOrderedJob(job); success = true; } } }
public static void EvaluateMinRange(CompAbilityUserMagic casterComp, TMAbilityDef abilitydef, PawnAbility ability, MagicPower power, float minRange, out bool success) { success = false; if (casterComp.Mana.CurLevel >= casterComp.ActualManaCost(abilitydef) && ability.CooldownTicksLeft <= 0) { Pawn caster = casterComp.Pawn; LocalTargetInfo jobTarget = TM_Calc.FindNearbyEnemy(caster, (int)(abilitydef.MainVerb.range * .9f)); float distanceToTarget = (jobTarget.Cell - caster.Position).LengthHorizontal; if (distanceToTarget > minRange && distanceToTarget < (abilitydef.MainVerb.range * .9f) && jobTarget != null && jobTarget.Thing != null && TM_Calc.HasLoSFromTo(caster.Position, jobTarget, caster, 0, abilitydef.MainVerb.range)) { Job job = ability.GetJob(AbilityContext.AI, jobTarget); job.endIfCantShootTargetFromCurPos = true; caster.jobs.TryTakeOrderedJob(job); success = true; } } }
protected override IEnumerable <Toil> MakeNewToils() { Pawn patient = TargetA.Thing as Pawn; Toil gotoPatient = new Toil() { initAction = () => { pawn.pather.StartPath(TargetA, PathEndMode.Touch); }, defaultCompleteMode = ToilCompleteMode.PatherArrival }; yield return(gotoPatient); Toil doHealing = new Toil(); doHealing.initAction = delegate { if (age > duration) { this.EndJobWith(JobCondition.Succeeded); } if (patient.DestroyedOrNull() || patient.Dead) { this.EndJobWith(JobCondition.Incompletable); } }; doHealing.tickAction = delegate { if (patient.DestroyedOrNull() || patient.Dead) { this.EndJobWith(JobCondition.Incompletable); } if (Find.TickManager.TicksGame % 1 == 0) { EffectMaker.MakeEffect(ThingDef.Named("Mote_HealingMote"), this.pawn.DrawPos, this.Map, Rand.Range(.3f, .5f), (Quaternion.AngleAxis(90, Vector3.up) * GetVector(this.pawn.Position, patient.Position)).ToAngleFlat() + Rand.Range(-10, 10), 5f, 0); } if (age > (lastHeal + ticksTillNextHeal)) { DoHealingEffect(patient); EffectMaker.MakeEffect(ThingDef.Named("Mote_HealingCircles"), patient.DrawPos, this.Map, Rand.Range(.3f, .4f), 0, 0, Rand.Range(400, 500), Rand.Range(0, 360), .08f, .01f, .24f, false); lastHeal = age; if (this.injuryCount == 0) { this.EndJobWith(JobCondition.Succeeded); } } if (!patient.Drafted && patient.CurJobDef != JobDefOf.Wait) { if (patient.jobs.posture == PawnPosture.Standing) { Job job = new Job(JobDefOf.Wait, patient); patient.jobs.TryTakeOrderedJob(job, JobTag.Misc); } } age++; ticksLeftThisToil = duration - age; if (age > duration) { this.EndJobWith(JobCondition.Succeeded); } }; doHealing.defaultCompleteMode = ToilCompleteMode.Delay; doHealing.defaultDuration = this.duration; doHealing.WithProgressBar(TargetIndex.B, delegate { if (this.pawn.DestroyedOrNull() || this.pawn.Dead) { return(1f); } return(1f - (float)doHealing.actor.jobs.curDriver.ticksLeftThisToil / this.duration); }, false, 0f); doHealing.AddFinishAction(delegate { CompWizardry comp = pawn.GetComp <CompWizardry>(); PawnAbility pawnAbility = comp.AbilityData.Powers.FirstOrDefault((PawnAbility x) => x.Def == WizardryDefOf.LotRW_Nienna_HealingTouch); pawnAbility.PostAbilityAttempt(); patient.jobs.EndCurrentJob(JobCondition.Succeeded, true); }); yield return(doHealing); }