separated single file.converted to sdk style, initial CE compat on going.
This commit is contained in:
parent
28345a1b5f
commit
b34353deae
Binary file not shown.
Binary file not shown.
@ -4,7 +4,29 @@
|
|||||||
<name>Implants</name>
|
<name>Implants</name>
|
||||||
</assembly>
|
</assembly>
|
||||||
<members>
|
<members>
|
||||||
<member name="T:LTS_Implants.HarmonyPatches">
|
<member name="M:Implants.Biotech.BiotechMechanitorPatches.Pawn_MechanitorTracker_CanCommandTo_Patch.CanCommandToPostfix(Verse.LocalTargetInfo,RimWorld.Pawn_MechanitorTracker,System.Boolean@)">
|
||||||
|
<summary>
|
||||||
|
pushed always commandable check to front to reduct compute.
|
||||||
|
TODO perhaps need a custom patch order to make sure this logic always works.
|
||||||
|
</summary>
|
||||||
|
<param name="target">target mech to command</param>
|
||||||
|
<param name="__instance">should be mechanitor, but not always the mechanitor for example like Dead man switch ctrl mechs </param>
|
||||||
|
<param name="__result">Commandable result from original code.</param>
|
||||||
|
</member>
|
||||||
|
<member name="M:Implants.Biotech.BiotechMechanitorPatches.Pawn_MechanitorTracker_DrawCommandRadius_Patch.DrawCommandRadiusPrefix">
|
||||||
|
<summary>
|
||||||
|
Skip original draw radius using a prefix.
|
||||||
|
TODO may need specify fixed patch order to make sure this works.
|
||||||
|
</summary>
|
||||||
|
<returns>return false to skip original draw.</returns>
|
||||||
|
</member>
|
||||||
|
<member name="M:Implants.Biotech.BiotechMechanitorPatches.Pawn_MechanitorTracker_DrawCommandRadius_Patch.DrawCommandRadiusPostfix(RimWorld.Pawn_MechanitorTracker)">
|
||||||
|
<summary>
|
||||||
|
Postfix the draw radius by apply our extended radius on top.
|
||||||
|
</summary>
|
||||||
|
<param name="__instance"></param>
|
||||||
|
</member>
|
||||||
|
<member name="T:LTS_Implants.StatPart_FertilityByGenderAge_AgeFactor_Patch">
|
||||||
<summary>
|
<summary>
|
||||||
Bootstrap class to do the harmony patches.
|
Bootstrap class to do the harmony patches.
|
||||||
</summary>
|
</summary>
|
||||||
@ -22,27 +44,5 @@
|
|||||||
Why don`t let them render their own instead?
|
Why don`t let them render their own instead?
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:LTS_Implants.Pawn_MechanitorTracker_CanCommandTo_Patch.CanCommandToPostfix(Verse.LocalTargetInfo,RimWorld.Pawn_MechanitorTracker,System.Boolean@)">
|
|
||||||
<summary>
|
|
||||||
pushed always commandable check to front to reduct compute.
|
|
||||||
TODO perhaps need a custom patch order to make sure this logic always works.
|
|
||||||
</summary>
|
|
||||||
<param name="target">target mech to command</param>
|
|
||||||
<param name="__instance">should be mechanitor, but not always the mechanitor for example like Deadmanswitch </param>
|
|
||||||
<param name="__result">Commandable result from original code.</param>
|
|
||||||
</member>
|
|
||||||
<member name="M:LTS_Implants.Pawn_MechanitorTracker_DrawCommandRadius_Patch.DrawCommandRadiusPrefix">
|
|
||||||
<summary>
|
|
||||||
Skip original draw radius using a prefix.
|
|
||||||
TODO may need specify fixed patch order to make sure this works.
|
|
||||||
</summary>
|
|
||||||
<returns>return false to skip original draw.</returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:LTS_Implants.Pawn_MechanitorTracker_DrawCommandRadius_Patch.DrawCommandRadiusPostfix(RimWorld.Pawn_MechanitorTracker)">
|
|
||||||
<summary>
|
|
||||||
Postfix the draw radius by apply our extended radius on top.
|
|
||||||
</summary>
|
|
||||||
<param name="__instance"></param>
|
|
||||||
</member>
|
|
||||||
</members>
|
</members>
|
||||||
</doc>
|
</doc>
|
||||||
|
308
1.5/Assemblies/Implants/Anomaly/AnomalyGeneral.cs
Normal file
308
1.5/Assemblies/Implants/Anomaly/AnomalyGeneral.cs
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using LTS_Implants;
|
||||||
|
using RimWorld;
|
||||||
|
using UnityEngine;
|
||||||
|
using Verse;
|
||||||
|
|
||||||
|
namespace Implants.Anomaly
|
||||||
|
{
|
||||||
|
|
||||||
|
public class LTS_Hediff_PsychicReaper : Hediff
|
||||||
|
{
|
||||||
|
private int previousHumanKills = -1;
|
||||||
|
|
||||||
|
public override void PostAdd(DamageInfo? dinfo)
|
||||||
|
{
|
||||||
|
base.PostAdd(dinfo);
|
||||||
|
previousHumanKills = (int)pawn.records.GetValue(RecordDefOf.KillsHumanlikes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Notify_Spawned()
|
||||||
|
{
|
||||||
|
base.Notify_Spawned();
|
||||||
|
PostAdd(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Tick()
|
||||||
|
{
|
||||||
|
base.Tick();
|
||||||
|
//Log.Message("Psychic Reaper Tick");
|
||||||
|
if (Find.TickManager.TicksGame % 10 == 0)
|
||||||
|
{
|
||||||
|
if ((int)pawn.records.GetValue(RecordDefOf.KillsHumanlikes) > previousHumanKills)
|
||||||
|
{
|
||||||
|
//Log.Message("Previous kills: " + previousHumanKills);
|
||||||
|
//Log.Message("Current kills: "+ (int)pawn.records.GetValue(RecordDefOf.KillsHumanlikes));
|
||||||
|
pawn.psychicEntropy.OffsetPsyfocusDirectly(0.05f*((int)pawn.records.GetValue(RecordDefOf.KillsHumanlikes) - previousHumanKills));//add 5 psyfocus per humanlike kill
|
||||||
|
}
|
||||||
|
previousHumanKills = (int)pawn.records.GetValue(RecordDefOf.KillsHumanlikes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LTS_Hediff_Voidlink : Hediff
|
||||||
|
{
|
||||||
|
public override bool ShouldRemove => false;
|
||||||
|
public override void Tick()
|
||||||
|
{
|
||||||
|
base.Tick();
|
||||||
|
if (Find.TickManager.TicksGame % 30 == 0)
|
||||||
|
{
|
||||||
|
Severity = Find.Anomaly.LevelDef.level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LTS_HediffCompProperties_MetalhorrorEmerge : HediffCompProperties
|
||||||
|
{
|
||||||
|
public string letterLabel;
|
||||||
|
|
||||||
|
public string letterText;
|
||||||
|
|
||||||
|
public LTS_HediffCompProperties_MetalhorrorEmerge()
|
||||||
|
{
|
||||||
|
compClass = typeof(LTS_HediffComp_MetalhorrorEmerge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LTS_HediffComp_MetalhorrorEmerge : HediffComp
|
||||||
|
{
|
||||||
|
private static readonly IntRange StunDuration = new IntRange(120, 240);
|
||||||
|
|
||||||
|
public LTS_HediffCompProperties_MetalhorrorEmerge Props => (LTS_HediffCompProperties_MetalhorrorEmerge)props;
|
||||||
|
|
||||||
|
public override void Notify_SurgicallyRemoved(Pawn surgeon)
|
||||||
|
{
|
||||||
|
TentacleAttack(surgeon);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Notify_SurgicallyReplaced(Pawn surgeon)
|
||||||
|
{
|
||||||
|
TentacleAttack(surgeon);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TentacleAttack(Pawn surgeon)
|
||||||
|
{
|
||||||
|
if (ModsConfig.AnomalyActive)
|
||||||
|
{
|
||||||
|
Pawn pawn = parent.pawn;
|
||||||
|
Pawn pawn2 = PawnGenerator.GeneratePawn(new PawnGenerationRequest(PawnKindDefOf.Metalhorror, Faction.OfEntities, PawnGenerationContext.NonPlayer, -1, forceGenerateNewPawn: false, allowDead: false, allowDowned: false, canGeneratePawnRelations: true, mustBeCapableOfViolence: false, 1f, forceAddFreeWarmLayerIfNeeded: false, allowGay: true, allowPregnant: false, allowFood: true, allowAddictions: true, inhabitant: false, certainlyBeenInCryptosleep: false, forceRedressWorldPawnIfFormerColonist: false, worldPawnFactionDoesntMatter: false, 0f, 0f, null, 1f, null, null, null, null, null, 0f, 0f));
|
||||||
|
GenSpawn.Spawn(pawn2, CellFinder.StandableCellNear(pawn.Position, pawn.Map, 2f), pawn.Map);
|
||||||
|
pawn2.stances.stunner.StunFor(StunDuration.RandomInRange, surgeon);
|
||||||
|
CompInspectStringEmergence compInspectStringEmergence = pawn2.TryGetComp<CompInspectStringEmergence>();
|
||||||
|
if (compInspectStringEmergence != null)
|
||||||
|
{
|
||||||
|
compInspectStringEmergence.sourcePawn = pawn;
|
||||||
|
}
|
||||||
|
TaggedString label = Props.letterLabel.Formatted(pawn.Named("PAWN"));
|
||||||
|
TaggedString text = Props.letterText.Formatted(pawn.Named("PAWN"));
|
||||||
|
Find.LetterStack.ReceiveLetter(label, text, LetterDefOf.ThreatBig, pawn2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class LTS_Hediff_HyperAdrenalineGland : Hediff
|
||||||
|
{
|
||||||
|
private float totalDamageTaken;
|
||||||
|
|
||||||
|
public override void Notify_PawnPostApplyDamage(DamageInfo dinfo, float totalDamageDealt)
|
||||||
|
{
|
||||||
|
base.Notify_PawnPostApplyDamage(dinfo, totalDamageDealt);
|
||||||
|
if (pawn.Dead)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//if (pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("PsychokeneticShield")) != null && ((pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("PsychokeneticShield"))) as LTS_ShieldHediff).PsychicShieldCurrentHealth > 0)
|
||||||
|
//{
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
totalDamageTaken += totalDamageDealt;
|
||||||
|
if (!pawn.Dead && totalDamageTaken > 0f && !pawn.health.hediffSet.HasHediff(HediffDefOf.RageSpeed) && !pawn.health.Downed)
|
||||||
|
{
|
||||||
|
pawn.health.AddHediff(HediffMaker.MakeHediff(HediffDefOf.RageSpeed, pawn));
|
||||||
|
if (pawn.Spawned)
|
||||||
|
{
|
||||||
|
EffecterDefOf.ChimeraRage.Spawn(pawn.Position, pawn.Map).Cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Notify_Downed()
|
||||||
|
{
|
||||||
|
Hediff firstHediffOfDef = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.RageSpeed);
|
||||||
|
if (firstHediffOfDef != null)
|
||||||
|
{
|
||||||
|
pawn.health.RemoveHediff(firstHediffOfDef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Tick()
|
||||||
|
{
|
||||||
|
base.Tick();
|
||||||
|
if (!pawn.Dead && pawn.health.summaryHealth.SummaryHealthPercent >= 0.98f)
|
||||||
|
{
|
||||||
|
Hediff firstHediffOfDef = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.RageSpeed);
|
||||||
|
if (firstHediffOfDef != null)
|
||||||
|
{
|
||||||
|
pawn.health.RemoveHediff(firstHediffOfDef);
|
||||||
|
totalDamageTaken = 0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ExposeData()
|
||||||
|
{
|
||||||
|
base.ExposeData();
|
||||||
|
Scribe_Values.Look(ref totalDamageTaken, "totalDamageTaken", 0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LTS_Hediff_DefensiveImpaler : Hediff
|
||||||
|
{
|
||||||
|
public override void Notify_PawnPostApplyDamage(DamageInfo dinfo, float totalDamageDealt)
|
||||||
|
{
|
||||||
|
base.Notify_PawnPostApplyDamage(dinfo, totalDamageDealt);
|
||||||
|
if (pawn.Dead)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dinfo.Instigator != null && pawn.Position.InHorDistOf(dinfo.Instigator.Position, 1.5f))//attacker next to user //apply 6 stab damage, 20% penetration
|
||||||
|
{
|
||||||
|
//SoundDefOf..PlayOneShot(pawn);
|
||||||
|
//BattleLogEntry_DamageTaken battleLogEntry_DamageTaken = new BattleLogEntry_DamageTaken(pawn, RulePackDefOf.DamageEvent_UnnaturalDarkness);
|
||||||
|
//Find.BattleLog.Add(battleLogEntry_DamageTaken);
|
||||||
|
//dinfo.Instigator.TakeDamage(new DamageInfo(DamageDefOf.Stab, 6)).AssociateWithLog(battleLogEntry_DamageTaken);
|
||||||
|
dinfo.Instigator.TakeDamage(new DamageInfo(DamageDefOf.Stab, 6));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region The Cube
|
||||||
|
|
||||||
|
|
||||||
|
public class CompProperties_PsychicBeguile : CompProperties_AbilityEffect
|
||||||
|
{
|
||||||
|
public CompProperties_PsychicBeguile()
|
||||||
|
{
|
||||||
|
this.compClass = typeof(CompAbilityEffect_PsychicBeguile);
|
||||||
|
}
|
||||||
|
public PawnRelationDef pawnRelationDef;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CompAbilityEffect_PsychicBeguile : CompAbilityEffect
|
||||||
|
{
|
||||||
|
public new CompProperties_PsychicBeguile Props
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (CompProperties_PsychicBeguile)this.props;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
||||||
|
{
|
||||||
|
base.Apply(target, dest);
|
||||||
|
if (target.Pawn.Faction != parent.pawn.Faction)
|
||||||
|
{
|
||||||
|
target.Pawn.SetFaction(parent.pawn.Faction);
|
||||||
|
IncidentWorker.SendIncidentLetter(target.Pawn.Name + " beguiled!", parent.pawn.Name + " has used " + parent.pawn.Possessive() + " psychic beguiler to psychically manipulate " + target.Pawn.Name + ". " + target.Pawn.Name + " has become obsessed with " + parent.pawn.Name + " and is joining " + parent.pawn.Possessive() + " faction.", LetterDefOf.PositiveEvent, new IncidentParms(), target.Pawn, IncidentDefOf.WandererJoin);
|
||||||
|
}
|
||||||
|
target.Pawn.relations.AddDirectRelation(Props.pawnRelationDef, parent.pawn);
|
||||||
|
if(target.Pawn.health.hediffSet.TryGetHediff(HediffDefOf.CubeComa, out Hediff cubeComa))
|
||||||
|
{
|
||||||
|
target.Pawn.health.RemoveHediff(cubeComa);
|
||||||
|
}
|
||||||
|
if (target.Pawn.health.hediffSet.TryGetHediff(HediffDefOf.CubeInterest, out Hediff cubeInterest))
|
||||||
|
{
|
||||||
|
target.Pawn.health.RemoveHediff(cubeInterest);
|
||||||
|
}
|
||||||
|
if (target.Pawn.health.hediffSet.TryGetHediff(HediffDefOf.CubeWithdrawal, out Hediff cubeWithdrawal))
|
||||||
|
{
|
||||||
|
target.Pawn.health.RemoveHediff(cubeWithdrawal);
|
||||||
|
}
|
||||||
|
if (target.Pawn.health.hediffSet.TryGetHediff(HediffDefOf.CubeRage, out Hediff cubeRage))
|
||||||
|
{
|
||||||
|
target.Pawn.health.RemoveHediff(cubeRage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LTS_Hediff_ObsessionBerserkOnDeath : HediffWithComps
|
||||||
|
{
|
||||||
|
|
||||||
|
public override void Notify_PawnCorpseSpawned()
|
||||||
|
{
|
||||||
|
base.Notify_PawnCorpseSpawned();
|
||||||
|
List<Pawn> allHumanlikeSpawned = pawn.Corpse.Map.mapPawns.AllHumanlikeSpawned;
|
||||||
|
for (int i = 0; i < allHumanlikeSpawned.Count; i++)
|
||||||
|
{
|
||||||
|
Pawn otherPawn = allHumanlikeSpawned[i];
|
||||||
|
if (otherPawn.RaceProps.Humanlike && otherPawn.relations.GetDirectRelation(I_DefOf.PsychicBeguileObsessed, pawn) != null)
|
||||||
|
{
|
||||||
|
MentalBreakDefOf.BerserkShort.Worker.TryStart(otherPawn, "Target of obsession died", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override void PostAdd(DamageInfo? dinfo)
|
||||||
|
{
|
||||||
|
base.PostAdd(dinfo);
|
||||||
|
RemoveCubeHediffs(pawn);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveCubeHediffs(Pawn pawn)
|
||||||
|
{
|
||||||
|
if (pawn.health.hediffSet.TryGetHediff(HediffDefOf.CubeComa, out Hediff cubeComa))
|
||||||
|
{
|
||||||
|
pawn.health.RemoveHediff(cubeComa);
|
||||||
|
}
|
||||||
|
if (pawn.health.hediffSet.TryGetHediff(HediffDefOf.CubeInterest, out Hediff cubeInterest))
|
||||||
|
{
|
||||||
|
pawn.health.RemoveHediff(cubeInterest);
|
||||||
|
}
|
||||||
|
if (pawn.health.hediffSet.TryGetHediff(HediffDefOf.CubeWithdrawal, out Hediff cubeWithdrawal))
|
||||||
|
{
|
||||||
|
pawn.health.RemoveHediff(cubeWithdrawal);
|
||||||
|
}
|
||||||
|
if (pawn.health.hediffSet.TryGetHediff(HediffDefOf.CubeRage, out Hediff cubeRage))
|
||||||
|
{
|
||||||
|
pawn.health.RemoveHediff(cubeRage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
public class LTS_Hediff_DeathRaiseAsShambler : HediffWithComps
|
||||||
|
{
|
||||||
|
//PawnKindDef spawnedPawn = PawnKindDefOf.Metalhorror;
|
||||||
|
|
||||||
|
public override void Notify_PawnDied(DamageInfo? dinfo, Hediff culprit = null)
|
||||||
|
{
|
||||||
|
base.Notify_PawnDied(dinfo, culprit);
|
||||||
|
if (pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.ShamblerCorpse) == null)
|
||||||
|
{
|
||||||
|
//Faction faction;
|
||||||
|
//if (pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.ShamblerCorpse) != null)
|
||||||
|
//{
|
||||||
|
// faction = pawn?.health?.hediffSet?.GetFirstHediffOfDef(HediffDef.Named("ScratchDeadlife"))
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// faction = pawn.Faction;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
Faction faction = dinfo.GetValueOrDefault().Instigator?.Faction ?? pawn.Faction;
|
||||||
|
if (pawn?.health?.hediffSet?.GetFirstHediffOfDef(HediffDef.Named("DeadlifeCollar")) != null) { faction = pawn.Faction; }
|
||||||
|
GasUtility.AddDeadifeGas(pawn.Position, pawn.MapHeld, faction, Mathf.CeilToInt(255));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
129
1.5/Assemblies/Implants/Biotech/Gene_Deathrest.cs
Normal file
129
1.5/Assemblies/Implants/Biotech/Gene_Deathrest.cs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using HarmonyLib;
|
||||||
|
using RimWorld;
|
||||||
|
using UnityEngine;
|
||||||
|
using Verse;
|
||||||
|
|
||||||
|
namespace Implants.Biotech
|
||||||
|
{
|
||||||
|
[HarmonyPatch(typeof(Gene_Deathrest))]
|
||||||
|
[HarmonyPatch(nameof(Gene_Deathrest.RemoveOldDeathrestBonuses))]
|
||||||
|
class Gene_Deathrest_RemoveOldDeathrestBonuses_Patch //offsets the pawn's hemogen capacity by their BaseHemogenOffset stat after reset
|
||||||
|
{
|
||||||
|
[HarmonyPostfix]
|
||||||
|
public static void RemoveOldDeathrestBonusesPostfix(Gene_Deathrest __instance)
|
||||||
|
{
|
||||||
|
if (__instance?.pawn?.genes?.GetFirstGeneOfType<Gene_Hemogen>() != null)
|
||||||
|
{
|
||||||
|
__instance.pawn.genes.GetFirstGeneOfType<Gene_Hemogen>().SetMax(__instance.pawn.genes.GetFirstGeneOfType<Gene_Hemogen>().Max + __instance.pawn.GetStatValue(StatDef.Named("BaseHemogenOffset")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(Need_Deathrest))]
|
||||||
|
[HarmonyPatch(nameof(Need_Deathrest.NeedInterval))]
|
||||||
|
class Need_Deathrest_NeedInterval_Patch//reduces and increases the time left for and between death rests for the DeathrestApparatus and DeathrestCapacitor respectively
|
||||||
|
{
|
||||||
|
[HarmonyPostfix]
|
||||||
|
public static void NeedIntervalPostfix(Need_Deathrest __instance, Pawn ___pawn)
|
||||||
|
{
|
||||||
|
bool IsFrozen = ___pawn.Suspended || (__instance.def.freezeWhileSleeping && !___pawn.Awake()) || (__instance.def.freezeInMentalState && ___pawn.InMentalState);
|
||||||
|
|
||||||
|
if (!IsFrozen)
|
||||||
|
{
|
||||||
|
float deathrestingOffset = (((___pawn?.GetStatValue(StatDef.Named("DeathrestEffectivenessFactor")) ?? 1f)) - 1f) * 0.2f; // + 1.2 0r 1 -1 *0.2 //also total factor = implant factor * gene factor * (___pawn.genes.GetFirstGeneOfType<Gene_Deathrest>()?.DeathrestEfficiency ?? 1f)
|
||||||
|
float notDeathrestingOffset = (1f / 30f); // cancels out base function
|
||||||
|
|
||||||
|
deathrestingOffset += (float)(___pawn.genes.GetFirstGeneOfType<Gene_Deathrest>()?.DeathrestEfficiency-0.5) * 0.2f; //-0.5 is an arbritrary, place holder number until I find the correct maths
|
||||||
|
//Log.Message(___pawn.genes.GetFirstGeneOfType<Gene_Deathrest>()?.DeathrestEfficiency);
|
||||||
|
notDeathrestingOffset += (1 / (___pawn?.GetStatValue(StatDef.Named("DeathrestIntervalFactor")) ?? 1f)) * (-1f / 30f); // 1/stat*base, so 200% = decrease at half the rate and 50% = decrease at double
|
||||||
|
|
||||||
|
|
||||||
|
__instance.CurLevel += (__instance.Deathresting ? deathrestingOffset : notDeathrestingOffset) / 400f;
|
||||||
|
//__instance.CurLevel += (__instance.Deathresting ? (0.2f * ((___pawn?.GetStatValue(StatDef.Named("DeathrestEffectivenessFactor")) ?? 1f) - 1f)) : (((___pawn?.GetStatValue(StatDef.Named("DeathrestIntervalFactor")) ?? 1f) - 1f) / 30f)) / 400f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(Gene_Deathrest))]
|
||||||
|
[HarmonyPatch(nameof(Gene_Deathrest.TickDeathresting))]
|
||||||
|
class Gene_Deathrest_TickDeathresting_patch//makes deathrest hediff go up. and death res need.
|
||||||
|
{
|
||||||
|
[HarmonyPostfix]
|
||||||
|
public static void TickDeathrestingPostfix(bool paused, Gene_Deathrest __instance, Pawn ___pawn, Need_Deathrest ___cachedDeathrestNeed)
|
||||||
|
{
|
||||||
|
int everyXTicks = (int)(1 / ((___pawn?.GetStatValue(StatDef.Named("DeathrestEffectivenessFactor")) ?? 1f) - 1f));
|
||||||
|
if (Find.TickManager.TicksGame % everyXTicks == 0)
|
||||||
|
{
|
||||||
|
__instance.deathrestTicks++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[HarmonyPatch(typeof(Need_Deathrest))]
|
||||||
|
[HarmonyPatch(nameof(Need_Deathrest.GetTipString))]
|
||||||
|
class Need_Deathrest_GetTipString_Patch //increases the displayed time left between deathresting if the pawn has a DeathrestCapacitor
|
||||||
|
{
|
||||||
|
[HarmonyPostfix]
|
||||||
|
public static void GetTipStringPostfix(Need_Deathrest __instance, Pawn ___pawn, ref string __result)
|
||||||
|
{
|
||||||
|
string text = (__instance.LabelCap + ": " + __instance.CurLevelPercentage.ToStringPercent()).Colorize(ColoredText.TipSectionTitleColor) + "\n";
|
||||||
|
if (!__instance.Deathresting)
|
||||||
|
{
|
||||||
|
if (__instance.CurLevelPercentage > 0.1f)
|
||||||
|
{
|
||||||
|
float num = (__instance.CurLevelPercentage - 0.1f) / (0.033333335f * (1f / ___pawn?.GetStatValue(StatDef.Named("DeathrestIntervalFactor")) ?? 1f));//multiplies listed time until next deathrest by DeathrestIntervalFactor
|
||||||
|
text += "NextDeathrestNeed".Translate(___pawn.Named("PAWN"), "PeriodDays".Translate(num.ToString("F1")).Named("DURATION")).Resolve().CapitalizeFirst();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
text += "PawnShouldDeathrestNow".Translate(___pawn.Named("PAWN")).CapitalizeFirst().Colorize(ColorLibrary.RedReadable);
|
||||||
|
}
|
||||||
|
text += "\n\n";
|
||||||
|
}
|
||||||
|
__result = text + __instance.def.description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(SanguophageUtility))]
|
||||||
|
[HarmonyPatch(nameof(SanguophageUtility.DeathrestJobReport))]
|
||||||
|
class SanguophageUtility_DeathrestJobReport_Patch //reduces the displayed time left while deathresting if the pawn has a DeathrestApparatus
|
||||||
|
{
|
||||||
|
[HarmonyPostfix]
|
||||||
|
public static void DeathrestJobReportPostfix(Pawn pawn, ref string __result)
|
||||||
|
{
|
||||||
|
Hediff_Deathrest hediff_Deathrest = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.Deathrest, false) as Hediff_Deathrest;
|
||||||
|
if (hediff_Deathrest != null && hediff_Deathrest.Paused)
|
||||||
|
{
|
||||||
|
__result = "DeathrestPaused".Translate() + ": " + "LethalInjuries".Translate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Gene_Deathrest firstGeneOfType = pawn.genes.GetFirstGeneOfType<Gene_Deathrest>();
|
||||||
|
TaggedString taggedString = "Deathresting".Translate().CapitalizeFirst() + ": ";
|
||||||
|
float deathrestPercent = firstGeneOfType.DeathrestPercent;
|
||||||
|
if (deathrestPercent < 1f)
|
||||||
|
{
|
||||||
|
taggedString += Mathf.Min(deathrestPercent, 0.99f).ToStringPercent("F0");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
taggedString += string.Format("{0} - {1}", "Complete".Translate().CapitalizeFirst(), "CanWakeSafely".Translate());
|
||||||
|
}
|
||||||
|
if (deathrestPercent < 1f)
|
||||||
|
{
|
||||||
|
//taggedString += ", " + "DurationLeft".Translate((Mathf.RoundToInt(firstGeneOfType.MinDeathrestTicks * (1f / pawn?.GetStatValue(StatDef.Named("DeathrestEffectivenessFactor")) ?? 1f) - firstGeneOfType.deathrestTicks)).ToStringTicksToPeriod(true, false, true, true, false));
|
||||||
|
//taggedString += ", " + "DurationLeft".Translate((Mathf.RoundToInt(firstGeneOfType.MinDeathrestTicks * (1f / pawn?.GetStatValue(StatDef.Named("DeathrestEffectivenessFactor")) ?? 1f) - firstGeneOfType.deathrestTicks)).ToStringTicksToPeriod(true, false, true, true, false));
|
||||||
|
|
||||||
|
taggedString += ", " + "DurationLeft".Translate((firstGeneOfType.MinDeathrestTicks - (Mathf.RoundToInt(firstGeneOfType.deathrestTicks * (1f / pawn?.GetStatValue(StatDef.Named("DeathrestEffectivenessFactor")) ?? 1f)))).ToStringTicksToPeriod(true, false, true, true, false));
|
||||||
|
|
||||||
|
|
||||||
|
//Log.Message(pawn?.GetStatValue(StatDef.Named("DeathrestEffectivenessFactor")));
|
||||||
|
//Log.Message(firstGeneOfType.deathrestTicks);
|
||||||
|
}
|
||||||
|
__result = taggedString.Resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
557
1.5/Assemblies/Implants/Biotech/Mechanitor.cs
Normal file
557
1.5/Assemblies/Implants/Biotech/Mechanitor.cs
Normal file
@ -0,0 +1,557 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using HarmonyLib;
|
||||||
|
using RimWorld;
|
||||||
|
using UnityEngine;
|
||||||
|
using Verse;
|
||||||
|
using Verse.AI.Group;
|
||||||
|
|
||||||
|
namespace Implants.Biotech
|
||||||
|
{
|
||||||
|
#region Command Range
|
||||||
|
|
||||||
|
[HarmonyPatchCategory("Biotech")]
|
||||||
|
class BiotechMechanitorPatches
|
||||||
|
{
|
||||||
|
[HarmonyPatch(typeof(Pawn_MechanitorTracker))]
|
||||||
|
[HarmonyPatch(nameof(Pawn_MechanitorTracker.CanCommandTo))]
|
||||||
|
class
|
||||||
|
Pawn_MechanitorTracker_CanCommandTo_Patch //increases the mechanitor's range by MechRemoteControlDistanceOffset
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// pushed always commandable check to front to reduct compute.
|
||||||
|
/// TODO perhaps need a custom patch order to make sure this logic always works.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">target mech to command</param>
|
||||||
|
/// <param name="__instance">should be mechanitor, but not always the mechanitor for example like Dead man switch ctrl mechs </param>
|
||||||
|
/// <param name="__result">Commandable result from original code.</param>
|
||||||
|
[HarmonyPostfix]
|
||||||
|
public static void CanCommandToPostfix(LocalTargetInfo target, Pawn_MechanitorTracker __instance,
|
||||||
|
ref bool __result)
|
||||||
|
{
|
||||||
|
if (__result)
|
||||||
|
return;
|
||||||
|
float SignalBoosterRange =
|
||||||
|
__instance.Pawn?.GetStatValue(StatDef.Named("MechRemoteControlDistanceOffset")) ?? 0f;
|
||||||
|
__result = target.Cell.InBounds(__instance.Pawn.MapHeld) &&
|
||||||
|
(float)__instance.Pawn.Position.DistanceToSquared(target.Cell) <
|
||||||
|
(24.9f + SignalBoosterRange) *
|
||||||
|
(24.9f +
|
||||||
|
SignalBoosterRange); //last line should mean that if something else makes it true, then it is(?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(Pawn_MechanitorTracker))]
|
||||||
|
[HarmonyPatch(nameof(Pawn_MechanitorTracker.DrawCommandRadius))]
|
||||||
|
class
|
||||||
|
Pawn_MechanitorTracker_DrawCommandRadius_Patch //increases the displayed mechanitor range by MechRemoteControlDistanceOffset
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Skip original draw radius using a prefix.
|
||||||
|
/// TODO may need specify fixed patch order to make sure this works.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>return false to skip original draw.</returns>
|
||||||
|
[HarmonyPrefix]
|
||||||
|
static bool DrawCommandRadiusPrefix()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Postfix the draw radius by apply our extended radius on top.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="__instance"></param>
|
||||||
|
[HarmonyPostfix]
|
||||||
|
public static void DrawCommandRadiusPostfix(Pawn_MechanitorTracker __instance)
|
||||||
|
{
|
||||||
|
if (__instance.Pawn.Spawned && __instance.AnySelectedDraftedMechs)
|
||||||
|
{
|
||||||
|
//GenDraw.DrawRadiusRing(___pawn.Position, 24.9f + (3f*___pawn.health?.hediffSet?.GetFirstHediffOfDef(HediffDef.Named("SignalBoosterImplant"))?.Severity ?? 0f), Color.white, (IntVec3 c) => __instance.CanCommandTo(c));
|
||||||
|
if (!ModsConfig.IsActive("swwu.MechanitorCommandRange") &&
|
||||||
|
!ModsConfig.IsActive(
|
||||||
|
"Neronix17.TweaksGalore")) //for tweaks galore, it'd be better to try to find the setting specifically, with an inverted result and a null check true
|
||||||
|
{
|
||||||
|
IntVec3 position = __instance.Pawn.Position;
|
||||||
|
float radius = 24.9f +
|
||||||
|
(__instance.Pawn?.GetStatValue(
|
||||||
|
StatDef.Named("MechRemoteControlDistanceOffset")) ?? 0f);
|
||||||
|
//Make our command circle yellow. And make sure this postfix implemented draw follows vanilla impl.
|
||||||
|
GenDraw.DrawRadiusRing(position, radius, Color.yellow,
|
||||||
|
(IntVec3 c) => __instance.CanCommandTo((LocalTargetInfo)c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Resurrect
|
||||||
|
|
||||||
|
public class CompProperties_MechanitorResurrectMech : CompProperties_AbilityEffect
|
||||||
|
{
|
||||||
|
public CompProperties_MechanitorResurrectMech()
|
||||||
|
{
|
||||||
|
this.compClass = typeof(CompAbilityEffect_MechanitorResurrectMech);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int maxCorpseAgeTicks = int.MaxValue;
|
||||||
|
|
||||||
|
public EffecterDef appliedEffecterDef;
|
||||||
|
|
||||||
|
public EffecterDef resolveEffecterDef;
|
||||||
|
|
||||||
|
//public EffecterDef centerEffecterDef;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CompAbilityEffect_MechanitorResurrectMech : CompAbilityEffect
|
||||||
|
{
|
||||||
|
public new CompProperties_MechanitorResurrectMech Props
|
||||||
|
{
|
||||||
|
get { return (CompProperties_MechanitorResurrectMech)this.props; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanApplyOn(LocalTargetInfo target, LocalTargetInfo dest)
|
||||||
|
{
|
||||||
|
Corpse corpse;
|
||||||
|
bool bandwidthCheck = (target.Thing as Corpse).InnerPawn.GetStatValue(StatDef.Named("BandwidthCost")) <=
|
||||||
|
this.parent.pawn.mechanitor.TotalBandwidth -
|
||||||
|
this.parent.pawn.mechanitor.UsedBandwidth;
|
||||||
|
bool canApplyOnCheck = (base.CanApplyOn(target, dest) && target.HasThing &&
|
||||||
|
(corpse = target.Thing as Corpse) != null && this.CanResurrect(corpse) &&
|
||||||
|
bandwidthCheck);
|
||||||
|
//Log.Message("CanApplyOn check: " + canApplyOnCheck);
|
||||||
|
|
||||||
|
|
||||||
|
if ((target.Thing as Corpse).InnerPawn.Faction != this.parent.pawn.Faction)
|
||||||
|
{
|
||||||
|
Messages.Message("Can only resurrect allied mechs", (target.Thing as Pawn),
|
||||||
|
MessageTypeDefOf.NegativeEvent);
|
||||||
|
}
|
||||||
|
else if ((target.Thing as Corpse).timeOfDeath <=
|
||||||
|
Find.TickManager.TicksGame - this.Props.maxCorpseAgeTicks)
|
||||||
|
{
|
||||||
|
Messages.Message("Target has been dead too long", (target.Thing as Pawn),
|
||||||
|
MessageTypeDefOf.NegativeEvent);
|
||||||
|
}
|
||||||
|
else if (!bandwidthCheck)
|
||||||
|
{
|
||||||
|
Messages.Message("Insufficient bandwidth", (target.Thing as Pawn), MessageTypeDefOf.NegativeEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return canApplyOnCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool CanResurrect(Corpse corpse)
|
||||||
|
{
|
||||||
|
//return corpse.InnerPawn.RaceProps.IsMechanoid && corpse.InnerPawn.RaceProps.mechWeightClass < MechWeightClass.UltraHeavy && corpse.InnerPawn.Faction == this.parent.pawn.Faction && (corpse.InnerPawn.kindDef.abilities == null || !corpse.InnerPawn.kindDef.abilities.Contains(AbilityDefOf.ResurrectionMech)) && corpse.timeOfDeath >= Find.TickManager.TicksGame - this.Props.maxCorpseAgeTicks;
|
||||||
|
return corpse.InnerPawn.RaceProps.IsMechanoid && corpse.InnerPawn.Faction == this.parent.pawn.Faction &&
|
||||||
|
(corpse.InnerPawn.kindDef.abilities == null ||
|
||||||
|
!corpse.InnerPawn.kindDef.abilities.Contains(AbilityDefOf.ResurrectionMech)) &&
|
||||||
|
corpse.timeOfDeath >= Find.TickManager.TicksGame - this.Props.maxCorpseAgeTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
||||||
|
{
|
||||||
|
//Log.Message("Apply called");
|
||||||
|
base.Apply(target, dest);
|
||||||
|
Corpse corpse = (Corpse)target.Thing;
|
||||||
|
if (!this.CanResurrect(corpse))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pawn innerPawn = corpse.InnerPawn;
|
||||||
|
ResurrectionUtility.TryResurrect(innerPawn, null);
|
||||||
|
if (this.Props.appliedEffecterDef != null)
|
||||||
|
{
|
||||||
|
Effecter effecter = this.Props.appliedEffecterDef.SpawnAttached(innerPawn, innerPawn.MapHeld, 1f);
|
||||||
|
effecter.Trigger(innerPawn, innerPawn, -1);
|
||||||
|
effecter.Cleanup();
|
||||||
|
this.parent.pawn.relations.AddDirectRelation(PawnRelationDefOf.Overseer,
|
||||||
|
innerPawn); //if resurrection successful, immediately takes control of resurrected mech.
|
||||||
|
}
|
||||||
|
|
||||||
|
innerPawn.stances.stagger.StaggerFor(60, 0.17f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool GizmoDisabled(out string reason)
|
||||||
|
{
|
||||||
|
reason = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<Mote> CustomWarmupMotes(LocalTargetInfo target)
|
||||||
|
{
|
||||||
|
foreach (LocalTargetInfo localTargetInfo in this.parent.GetAffectedTargets(target))
|
||||||
|
{
|
||||||
|
Thing thing = localTargetInfo.Thing;
|
||||||
|
yield return MoteMaker.MakeAttachedOverlay(thing, ThingDefOf.Mote_MechResurrectWarmupOnTarget,
|
||||||
|
Vector3.zero, 1f, -1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void PostApplied(List<LocalTargetInfo> targets, Map map)
|
||||||
|
{
|
||||||
|
//Log.Message("PostApplied called");
|
||||||
|
Vector3 vector = Vector3.zero;
|
||||||
|
foreach (LocalTargetInfo localTargetInfo in targets)
|
||||||
|
{
|
||||||
|
vector += localTargetInfo.Cell.ToVector3Shifted();
|
||||||
|
}
|
||||||
|
|
||||||
|
vector /= (float)targets.Count<LocalTargetInfo>();
|
||||||
|
IntVec3 intVec = vector.ToIntVec3();
|
||||||
|
this.Props.resolveEffecterDef.Spawn(intVec, map, 1f).EffectTick(new TargetInfo(intVec, map, false),
|
||||||
|
new TargetInfo(intVec, map, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Remote Dominate
|
||||||
|
|
||||||
|
public class CompProperties_MechanitorDominateMech : CompProperties_AbilityEffect
|
||||||
|
{
|
||||||
|
public CompProperties_MechanitorDominateMech()
|
||||||
|
{
|
||||||
|
this.compClass = typeof(CompAbilityEffect_MechanitorDominateMech);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CompAbilityEffect_MechanitorDominateMech : CompAbilityEffect
|
||||||
|
{
|
||||||
|
public new CompProperties_MechanitorDominateMech Props
|
||||||
|
{
|
||||||
|
get { return (CompProperties_MechanitorDominateMech)this.props; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanApplyOn(LocalTargetInfo target, LocalTargetInfo dest)
|
||||||
|
{
|
||||||
|
Pawn pawn;
|
||||||
|
|
||||||
|
bool bandwidthCheck = (target.Thing as Pawn).GetStatValue(StatDef.Named("BandwidthCost")) <=
|
||||||
|
this.parent.pawn.mechanitor.TotalBandwidth -
|
||||||
|
this.parent.pawn.mechanitor.UsedBandwidth;
|
||||||
|
bool notTempMech = target.Thing.TryGetComp<CompMechPowerCell>() == null;
|
||||||
|
bool canApplyOnCheck = (base.CanApplyOn(target, dest) && target.HasThing &&
|
||||||
|
(pawn = target.Thing as Pawn) != null && bandwidthCheck &&
|
||||||
|
this.CanDominate(pawn) && notTempMech);
|
||||||
|
|
||||||
|
|
||||||
|
if (!notTempMech)
|
||||||
|
{
|
||||||
|
Messages.Message("Cannot target temporary mech", (target.Thing as Pawn),
|
||||||
|
MessageTypeDefOf.NegativeEvent);
|
||||||
|
}
|
||||||
|
else if ((target.Thing as Pawn).RaceProps.mechWeightClass >= MechWeightClass.UltraHeavy)
|
||||||
|
{
|
||||||
|
Messages.Message("Cannot target superheavy mech", (target.Thing as Pawn),
|
||||||
|
MessageTypeDefOf.NegativeEvent);
|
||||||
|
}
|
||||||
|
else if (!bandwidthCheck)
|
||||||
|
{
|
||||||
|
Messages.Message("Insufficient bandwidth", (target.Thing as Pawn), MessageTypeDefOf.NegativeEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return canApplyOnCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool CanDominate(Pawn pawn)
|
||||||
|
{
|
||||||
|
return pawn.RaceProps.IsMechanoid && pawn.RaceProps.mechWeightClass < MechWeightClass.UltraHeavy &&
|
||||||
|
(pawn.kindDef.abilities == null ||
|
||||||
|
!pawn.kindDef.abilities.Contains(AbilityDefOf.ResurrectionMech));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
||||||
|
{
|
||||||
|
//Log.Message("Apply called");
|
||||||
|
base.Apply(target, dest);
|
||||||
|
Pawn pawn = (Pawn)target;
|
||||||
|
if (!this.CanDominate(pawn))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pawn.SetFaction(this.parent.pawn.Faction); //convert pawn
|
||||||
|
|
||||||
|
this.parent.pawn.relations.AddDirectRelation(PawnRelationDefOf.Overseer, pawn);
|
||||||
|
pawn.stances.stagger.StaggerFor(60, 0.17f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool GizmoDisabled(out string reason)
|
||||||
|
{
|
||||||
|
reason = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//public override IEnumerable<Mote> CustomWarmupMotes(LocalTargetInfo target)
|
||||||
|
//{
|
||||||
|
// foreach (LocalTargetInfo localTargetInfo in this.parent.GetAffectedTargets(target))
|
||||||
|
// {
|
||||||
|
// Thing thing = localTargetInfo.Thing;
|
||||||
|
// yield return MoteMaker.MakeAttachedOverlay(thing, ThingDefOf.Mote_MechResurrectWarmupOnTarget, Vector3.zero, 1f, -1f);
|
||||||
|
// }
|
||||||
|
// IEnumerator<LocalTargetInfo> enumerator = null;
|
||||||
|
// yield break;
|
||||||
|
// yield break;
|
||||||
|
//}
|
||||||
|
|
||||||
|
public override void PostApplied(List<LocalTargetInfo> targets, Map map)
|
||||||
|
{
|
||||||
|
//Log.Message("PostApplied called");
|
||||||
|
//Vector3 vector = Vector3.zero;
|
||||||
|
//foreach (LocalTargetInfo localTargetInfo in targets)
|
||||||
|
//{
|
||||||
|
// vector += localTargetInfo.Cell.ToVector3Shifted();
|
||||||
|
//}
|
||||||
|
//vector /= (float)targets.Count<LocalTargetInfo>();
|
||||||
|
//IntVec3 intVec = vector.ToIntVec3();
|
||||||
|
//this.Props.resolveEffecterDef.Spawn(intVec, map, 1f).EffectTick(new TargetInfo(intVec, map, false), new TargetInfo(intVec, map, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Mech carrier
|
||||||
|
|
||||||
|
public class CompProperties_MechanitorMechCarrier : CompProperties_AbilityEffect
|
||||||
|
{
|
||||||
|
public CompProperties_MechanitorMechCarrier()
|
||||||
|
{
|
||||||
|
this.compClass = typeof(CompAbilityEffect_MechanitorMechCarrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PawnKindDef spawnPawnKind;
|
||||||
|
public int cooldownTicks = 900;
|
||||||
|
public int maxPawnsToSpawn = 2;
|
||||||
|
public EffecterDef spawnEffecter;
|
||||||
|
public EffecterDef spawnedMechEffecter;
|
||||||
|
public bool attachSpawnedEffecter;
|
||||||
|
public bool attachSpawnedMechEffecter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CompAbilityEffect_MechanitorMechCarrier : CompAbilityEffect
|
||||||
|
{
|
||||||
|
public new CompProperties_MechanitorMechCarrier Props
|
||||||
|
{
|
||||||
|
get { return (CompProperties_MechanitorMechCarrier)this.props; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CompTick()
|
||||||
|
{
|
||||||
|
base.CompTick();
|
||||||
|
//if (Find.Selector.IsSelected(parent.pawn) && (int)Find.TickManager.CurTimeSpeed != 0 && Find.TickManager.TicksGame % (int)Find.TickManager.CurTimeSpeed == 0)//if the mechanitor is selected, and once erry 60/1 irl seconds
|
||||||
|
//{
|
||||||
|
// for (int i = 0; i < spawnedPawns.Count; i++)
|
||||||
|
// {
|
||||||
|
// if (!spawnedPawns[i].Dead)
|
||||||
|
// {
|
||||||
|
// GenDraw.DrawLineBetween(this.parent.pawn.TrueCenter(), spawnedPawns[i].TrueCenter());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
||||||
|
{
|
||||||
|
base.Apply(target, dest);
|
||||||
|
TrySpawnPawns();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int maxspawn()
|
||||||
|
{
|
||||||
|
//Log.Message("RemainingCharges: " + parent.RemainingCharges+1);
|
||||||
|
int max = parent.RemainingCharges +
|
||||||
|
1; //requires +1 to account for the charge that's automatically used upon ability activation, prior to this.
|
||||||
|
if (max > 2)
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TrySpawnPawns()
|
||||||
|
{
|
||||||
|
int maxCanSpawn = maxspawn();
|
||||||
|
//Log.Message("max spawns: "+ maxCanSpawn);
|
||||||
|
if (maxCanSpawn <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PawnGenerationRequest pawnGenerationRequest = new PawnGenerationRequest(this.Props.spawnPawnKind,
|
||||||
|
this.parent.pawn.Faction, PawnGenerationContext.NonPlayer, -1, true, false, false, true, false, 1f,
|
||||||
|
false, true, false, true, true, false, false, false, false, 0f, 0f, null, 1f, null, null, null,
|
||||||
|
null, null, null, null, null, null, null, null, null, false, false, false, false, null, null, null,
|
||||||
|
null, null, 0f, DevelopmentalStage.Newborn, null, null, null, false, false, false, -1, 0, false);
|
||||||
|
Pawn pawn;
|
||||||
|
Lord lord = (((pawn = this.parent.pawn as Pawn) != null) ? pawn.GetLord() : null);
|
||||||
|
for (int i = 0; i < maxCanSpawn; i++)
|
||||||
|
{
|
||||||
|
Pawn pawn2 = PawnGenerator.GeneratePawn(pawnGenerationRequest);
|
||||||
|
GenSpawn.Spawn(pawn2, this.parent.pawn.Position, this.parent.pawn.Map, WipeMode.Vanish);
|
||||||
|
this.spawnedPawns.Add(pawn2);
|
||||||
|
if (lord != null)
|
||||||
|
{
|
||||||
|
lord.AddPawn(pawn2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.Props.spawnedMechEffecter != null)
|
||||||
|
{
|
||||||
|
Effecter effecter = new Effecter(this.Props.spawnedMechEffecter);
|
||||||
|
effecter.Trigger(
|
||||||
|
this.Props.attachSpawnedMechEffecter
|
||||||
|
? pawn2
|
||||||
|
: new TargetInfo(pawn2.Position, pawn2.Map, false), TargetInfo.Invalid, -1);
|
||||||
|
effecter.Cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cooldownTicksRemaining = this.Props.cooldownTicks;
|
||||||
|
if (this.Props.spawnEffecter != null)
|
||||||
|
{
|
||||||
|
Effecter effecter2 = new Effecter(this.Props.spawnEffecter);
|
||||||
|
effecter2.Trigger(
|
||||||
|
this.Props.attachSpawnedEffecter
|
||||||
|
? this.parent.pawn
|
||||||
|
: new TargetInfo(this.parent.pawn.Position, this.parent.pawn.Map, false),
|
||||||
|
TargetInfo.Invalid, -1);
|
||||||
|
effecter2.Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxCanSpawn == 2) //subtract an extra charge, as we're summoning 2
|
||||||
|
{
|
||||||
|
parent.RemainingCharges--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Pawn> GetSpawnedPawns()
|
||||||
|
{
|
||||||
|
return spawnedPawns;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int cooldownTicksRemaining;
|
||||||
|
private List<Pawn> spawnedPawns = new List<Pawn>();
|
||||||
|
public SoundDef soundReload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HediffCompProperties_KillSpawnedPawns : HediffCompProperties
|
||||||
|
{
|
||||||
|
public AbilityDef abilityDef;
|
||||||
|
|
||||||
|
public HediffCompProperties_KillSpawnedPawns()
|
||||||
|
{
|
||||||
|
compClass = typeof(HediffComp_KillSpawnedPawns);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HediffComp_KillSpawnedPawns : HediffComp
|
||||||
|
{
|
||||||
|
public HediffCompProperties_KillSpawnedPawns Props => (HediffCompProperties_KillSpawnedPawns)props;
|
||||||
|
|
||||||
|
public override void Notify_PawnKilled()
|
||||||
|
{
|
||||||
|
foreach (Pawn i in base.Pawn.abilities.GetAbility(Props.abilityDef)
|
||||||
|
.CompOfType<CompAbilityEffect_MechanitorMechCarrier>().GetSpawnedPawns())
|
||||||
|
{
|
||||||
|
if (!i.Dead)
|
||||||
|
{
|
||||||
|
i.Kill(null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Call a cluster
|
||||||
|
|
||||||
|
public class CompProperties_AbilityMechCluster : CompProperties_AbilityEffect
|
||||||
|
{
|
||||||
|
public CompProperties_AbilityMechCluster()
|
||||||
|
{
|
||||||
|
this.compClass = typeof(CompAbilityEffect_MechCluster);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float displayRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CompAbilityEffect_MechCluster : CompAbilityEffect
|
||||||
|
{
|
||||||
|
public new CompProperties_AbilityMechCluster Props
|
||||||
|
{
|
||||||
|
get { return (CompProperties_AbilityMechCluster)this.props; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ShouldHaveInspectString
|
||||||
|
{
|
||||||
|
get { return ModsConfig.BiotechActive && this.parent.pawn.RaceProps.IsMechanoid; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
||||||
|
{
|
||||||
|
base.Apply(target, dest);
|
||||||
|
if (Faction.OfMechanoids == null)
|
||||||
|
{
|
||||||
|
Messages.Message("MessageNoFactionForVerbMechCluster".Translate(), this.parent.pawn,
|
||||||
|
MessageTypeDefOf.RejectInput, null, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MechClusterUtility.SpawnCluster(target.Cell, this.parent.pawn.MapHeld,
|
||||||
|
MechClusterGenerator.GenerateClusterSketch(2500f, this.parent.pawn.MapHeld, true, true), true,
|
||||||
|
false, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void PostApplied(List<LocalTargetInfo> targets, Map map)
|
||||||
|
{
|
||||||
|
base.PostApplied(targets, map);
|
||||||
|
if (this.parent.def.defName ==
|
||||||
|
"MechhiveSatelliteUplink") //add field for cooldownFactorStat. Change this if statement to if it's not null. change the contents of getstatvalue on the next line to that field.
|
||||||
|
{
|
||||||
|
this.parent.StartCooldown(Mathf.RoundToInt(this.parent.def.cooldownTicksRange.RandomInRange *
|
||||||
|
this.parent.pawn?.GetStatValue(StatDef.Named("MechhiveSatelliteUplinkCooldownFactor")) ?? 1f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DrawEffectPreview(LocalTargetInfo target)
|
||||||
|
{
|
||||||
|
GenDraw.DrawRadiusRing(target.Cell, this.Props.displayRadius);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string CompInspectStringExtra()
|
||||||
|
{
|
||||||
|
if (!this.ShouldHaveInspectString)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.parent.CanCast)
|
||||||
|
{
|
||||||
|
return "AbilityMechSmokepopCharged".Translate();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "AbilityMechSmokepopRecharging".Translate(
|
||||||
|
this.parent.CooldownTicksRemaining.ToStringTicksToPeriod(true, false, true, true, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
88
1.5/Assemblies/Implants/CaptiveControl.cs
Normal file
88
1.5/Assemblies/Implants/CaptiveControl.cs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using RimWorld;
|
||||||
|
using Verse;
|
||||||
|
using Verse.Sound;
|
||||||
|
|
||||||
|
namespace Implants
|
||||||
|
{
|
||||||
|
|
||||||
|
public class LTS_CompProperties_CaptiveControl : CompProperties_AbilityEffect
|
||||||
|
{
|
||||||
|
public LTS_CompProperties_CaptiveControl()
|
||||||
|
{
|
||||||
|
this.compClass = typeof(LTS_CompAbilityEffect_CaptiveControl);
|
||||||
|
}
|
||||||
|
public HediffDef hediffDef;
|
||||||
|
public float StartSeverity;
|
||||||
|
public string location = null;
|
||||||
|
public int duration = 3600; // 1 hour
|
||||||
|
public bool headExploder = false;
|
||||||
|
public bool hediffToggle = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LTS_CompAbilityEffect_CaptiveControl : CompAbilityEffect
|
||||||
|
{
|
||||||
|
public new LTS_CompProperties_CaptiveControl Props
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (LTS_CompProperties_CaptiveControl)this.props;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
||||||
|
{
|
||||||
|
base.Apply(target, dest);
|
||||||
|
|
||||||
|
if (target.Pawn != null)
|
||||||
|
{
|
||||||
|
if (Props.headExploder)
|
||||||
|
{
|
||||||
|
if (EffecterDefOf.MeatExplosion != null)
|
||||||
|
{
|
||||||
|
EffecterDefOf.MeatExplosion.Spawn(parent.pawn.PositionHeld, parent.pawn.MapHeld).Cleanup();
|
||||||
|
}
|
||||||
|
SoundDefOf.CocoonDestroyed.PlayOneShot(new TargetInfo(target.Pawn.Position, target.Pawn.Map));
|
||||||
|
target.Pawn.TakeDamage(new DamageInfo(DamageDefOf.Crush, 100, 0, -1, null, target.Pawn.health.hediffSet.GetBodyPartRecord(BodyPartDefOf.Head)));
|
||||||
|
//target.Pawn.TakeDamage(new DamageInfo(DamageDefOf.Bomb, 100, 0, -1, null, target.Pawn.health.hediffSet.GetBodyPartRecord(BodyPartDefOf.Head)));
|
||||||
|
}
|
||||||
|
else if (Props.hediffToggle)
|
||||||
|
{
|
||||||
|
if (target.Pawn.health?.hediffSet?.GetFirstHediffOfDef(this.Props.hediffDef) != null)
|
||||||
|
{
|
||||||
|
target.Pawn.health.RemoveHediff(target.Pawn.health.hediffSet.GetFirstHediffOfDef(this.Props.hediffDef));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
target.Pawn.health.AddHediff(this.Props.hediffDef, location(target));
|
||||||
|
if (target.Pawn.health.hediffSet.GetFirstHediffOfDef(this.Props.hediffDef).TryGetComp<HediffComp_Lactating>() != null)
|
||||||
|
{
|
||||||
|
target.Pawn.health.hediffSet.GetFirstHediffOfDef(this.Props.hediffDef).TryGetComp<HediffComp_Lactating>().TryCharge(-0.124f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
target.Pawn.health.AddHediff(this.Props.hediffDef, location(target));
|
||||||
|
if (target.Pawn.health.hediffSet.GetFirstHediffOfDef(this.Props.hediffDef).TryGetComp<HediffComp_Disappears>() != null)
|
||||||
|
{
|
||||||
|
target.Pawn.health.hediffSet.GetFirstHediffOfDef(this.Props.hediffDef).TryGetComp<HediffComp_Disappears>().ticksToDisappear = Props.duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BodyPartRecord location(LocalTargetInfo target)
|
||||||
|
{
|
||||||
|
if (Props.location == null) { return null; }
|
||||||
|
|
||||||
|
//return target.Pawn.health.hediffSet.GetNotMissingParts(BodyPartHeight.Undefined, BodyPartDepth.Undefined).Where(part => part.def.tags.Contains(BodyPartTagDefOf.ManipulationLimbSegment)).ToList()[0];
|
||||||
|
return target.Pawn.health.hediffSet.GetNotMissingParts(BodyPartHeight.Undefined, BodyPartDepth.Undefined).Where(part => part.def.defName == Props.location).ToList()[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,68 +1,42 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<TargetFramework>net472</TargetFramework>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
|
||||||
<ProjectGuid>{A5BB73F5-2B73-4464-9585-5553F3695021}</ProjectGuid>
|
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
<RootNamespace>Implants</RootNamespace>
|
<AssemblyTitle>Implants</AssemblyTitle>
|
||||||
<AssemblyName>Implants</AssemblyName>
|
<Product>Implants</Product>
|
||||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
<Copyright>Copyright © 2024</Copyright>
|
||||||
<FileAlignment>512</FileAlignment>
|
<AssemblyVersion>1.0.0.0</AssemblyVersion>
|
||||||
<Deterministic>true</Deterministic>
|
<FileVersion>1.0.0.0</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<Optimize>false</Optimize>
|
|
||||||
<OutputPath>..\</OutputPath>
|
<OutputPath>..\</OutputPath>
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||||
<WarningLevel>4</WarningLevel>
|
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
||||||
<DocumentationFile>..\Implants.xml</DocumentationFile>
|
<DocumentationFile>..\Implants.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="0Harmony, Version=2.3.3.0, Culture=neutral, processorArchitecture=MSIL">
|
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||||
<HintPath>packages\Lib.Harmony.2.3.3\lib\net472\0Harmony.dll</HintPath>
|
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Lib.Harmony" Version="2.3.3">
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
<Reference Include="Assembly-CSharp">
|
<Reference Include="Assembly-CSharp">
|
||||||
<HintPath>..\..\..\..\..\RimWorldWin64_Data\Managed\Assembly-CSharp.dll</HintPath>
|
<HintPath>..\..\..\..\..\..\..\SteamLibrary\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\Assembly-CSharp.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
<Reference Include="System.Xml.Linq" />
|
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
|
||||||
<Reference Include="Microsoft.CSharp" />
|
|
||||||
<Reference Include="System.Data" />
|
|
||||||
<Reference Include="System.Net.Http" />
|
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
<Reference Include="UnityEngine">
|
<Reference Include="UnityEngine">
|
||||||
<HintPath>..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.dll</HintPath>
|
<HintPath>..\..\..\..\..\..\..\SteamLibrary\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\UnityEngine.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="UnityEngine.CoreModule">
|
<Reference Include="UnityEngine.CoreModule">
|
||||||
<HintPath>..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
|
<HintPath>..\..\..\..\..\..\..\SteamLibrary\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="LTS_Implants.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="packages.config" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
||||||
</Project>
|
</Project>
|
@ -334,226 +334,6 @@ namespace LTS_Implants
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CompProperties_MechanitorResurrectMech : CompProperties_AbilityEffect
|
|
||||||
{
|
|
||||||
public CompProperties_MechanitorResurrectMech()
|
|
||||||
{
|
|
||||||
this.compClass = typeof(CompAbilityEffect_MechanitorResurrectMech);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int maxCorpseAgeTicks = int.MaxValue;
|
|
||||||
|
|
||||||
public EffecterDef appliedEffecterDef;
|
|
||||||
|
|
||||||
public EffecterDef resolveEffecterDef;
|
|
||||||
|
|
||||||
//public EffecterDef centerEffecterDef;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CompAbilityEffect_MechanitorResurrectMech : CompAbilityEffect
|
|
||||||
{
|
|
||||||
public new CompProperties_MechanitorResurrectMech Props
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (CompProperties_MechanitorResurrectMech)this.props;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanApplyOn(LocalTargetInfo target, LocalTargetInfo dest)
|
|
||||||
{
|
|
||||||
Corpse corpse;
|
|
||||||
bool bandwidthCheck = (target.Thing as Corpse).InnerPawn.GetStatValue(StatDef.Named("BandwidthCost")) <= this.parent.pawn.mechanitor.TotalBandwidth - this.parent.pawn.mechanitor.UsedBandwidth;
|
|
||||||
bool canApplyOnCheck = (base.CanApplyOn(target, dest) && target.HasThing && (corpse = target.Thing as Corpse) != null && this.CanResurrect(corpse) && bandwidthCheck);
|
|
||||||
//Log.Message("CanApplyOn check: " + canApplyOnCheck);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ((target.Thing as Corpse).InnerPawn.Faction != this.parent.pawn.Faction)
|
|
||||||
{
|
|
||||||
Messages.Message("Can only resurrect allied mechs", (target.Thing as Pawn), MessageTypeDefOf.NegativeEvent);
|
|
||||||
}
|
|
||||||
else if ((target.Thing as Corpse).timeOfDeath <= Find.TickManager.TicksGame - this.Props.maxCorpseAgeTicks)
|
|
||||||
{
|
|
||||||
Messages.Message("Target has been dead too long", (target.Thing as Pawn), MessageTypeDefOf.NegativeEvent);
|
|
||||||
}
|
|
||||||
else if (!bandwidthCheck)
|
|
||||||
{
|
|
||||||
Messages.Message("Insufficient bandwidth", (target.Thing as Pawn), MessageTypeDefOf.NegativeEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return canApplyOnCheck;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private bool CanResurrect(Corpse corpse)
|
|
||||||
{
|
|
||||||
//return corpse.InnerPawn.RaceProps.IsMechanoid && corpse.InnerPawn.RaceProps.mechWeightClass < MechWeightClass.UltraHeavy && corpse.InnerPawn.Faction == this.parent.pawn.Faction && (corpse.InnerPawn.kindDef.abilities == null || !corpse.InnerPawn.kindDef.abilities.Contains(AbilityDefOf.ResurrectionMech)) && corpse.timeOfDeath >= Find.TickManager.TicksGame - this.Props.maxCorpseAgeTicks;
|
|
||||||
return corpse.InnerPawn.RaceProps.IsMechanoid && corpse.InnerPawn.Faction == this.parent.pawn.Faction && (corpse.InnerPawn.kindDef.abilities == null || !corpse.InnerPawn.kindDef.abilities.Contains(AbilityDefOf.ResurrectionMech)) && corpse.timeOfDeath >= Find.TickManager.TicksGame - this.Props.maxCorpseAgeTicks;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
|
||||||
{
|
|
||||||
//Log.Message("Apply called");
|
|
||||||
base.Apply(target, dest);
|
|
||||||
Corpse corpse = (Corpse)target.Thing;
|
|
||||||
if (!this.CanResurrect(corpse))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Pawn innerPawn = corpse.InnerPawn;
|
|
||||||
ResurrectionUtility.TryResurrect(innerPawn, null);
|
|
||||||
if (this.Props.appliedEffecterDef != null)
|
|
||||||
{
|
|
||||||
Effecter effecter = this.Props.appliedEffecterDef.SpawnAttached(innerPawn, innerPawn.MapHeld, 1f);
|
|
||||||
effecter.Trigger(innerPawn, innerPawn, -1);
|
|
||||||
effecter.Cleanup();
|
|
||||||
this.parent.pawn.relations.AddDirectRelation(PawnRelationDefOf.Overseer, innerPawn);//if resurrection successful, immediately takes control of resurrected mech.
|
|
||||||
|
|
||||||
}
|
|
||||||
innerPawn.stances.stagger.StaggerFor(60, 0.17f);
|
|
||||||
}
|
|
||||||
public override bool GizmoDisabled(out string reason)
|
|
||||||
{
|
|
||||||
reason = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<Mote> CustomWarmupMotes(LocalTargetInfo target)
|
|
||||||
{
|
|
||||||
foreach (LocalTargetInfo localTargetInfo in this.parent.GetAffectedTargets(target))
|
|
||||||
{
|
|
||||||
Thing thing = localTargetInfo.Thing;
|
|
||||||
yield return MoteMaker.MakeAttachedOverlay(thing, ThingDefOf.Mote_MechResurrectWarmupOnTarget, Vector3.zero, 1f, -1f);
|
|
||||||
}
|
|
||||||
yield break;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void PostApplied(List<LocalTargetInfo> targets, Map map)
|
|
||||||
{
|
|
||||||
//Log.Message("PostApplied called");
|
|
||||||
Vector3 vector = Vector3.zero;
|
|
||||||
foreach (LocalTargetInfo localTargetInfo in targets)
|
|
||||||
{
|
|
||||||
vector += localTargetInfo.Cell.ToVector3Shifted();
|
|
||||||
}
|
|
||||||
vector /= (float)targets.Count<LocalTargetInfo>();
|
|
||||||
IntVec3 intVec = vector.ToIntVec3();
|
|
||||||
this.Props.resolveEffecterDef.Spawn(intVec, map, 1f).EffectTick(new TargetInfo(intVec, map, false), new TargetInfo(intVec, map, false));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CompProperties_MechanitorDominateMech : CompProperties_AbilityEffect
|
|
||||||
{
|
|
||||||
public CompProperties_MechanitorDominateMech()
|
|
||||||
{
|
|
||||||
this.compClass = typeof(CompAbilityEffect_MechanitorDominateMech);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CompAbilityEffect_MechanitorDominateMech : CompAbilityEffect
|
|
||||||
{
|
|
||||||
public new CompProperties_MechanitorDominateMech Props
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (CompProperties_MechanitorDominateMech)this.props;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanApplyOn(LocalTargetInfo target, LocalTargetInfo dest)
|
|
||||||
{
|
|
||||||
Pawn pawn;
|
|
||||||
|
|
||||||
bool bandwidthCheck = (target.Thing as Pawn).GetStatValue(StatDef.Named("BandwidthCost")) <= this.parent.pawn.mechanitor.TotalBandwidth - this.parent.pawn.mechanitor.UsedBandwidth;
|
|
||||||
bool notTempMech = target.Thing.TryGetComp<CompMechPowerCell>() == null;
|
|
||||||
bool canApplyOnCheck = (base.CanApplyOn(target, dest) && target.HasThing && (pawn = target.Thing as Pawn) != null && bandwidthCheck && this.CanDominate(pawn) && notTempMech);
|
|
||||||
|
|
||||||
|
|
||||||
if (!notTempMech)
|
|
||||||
{
|
|
||||||
Messages.Message("Cannot target temporary mech", (target.Thing as Pawn), MessageTypeDefOf.NegativeEvent);
|
|
||||||
}
|
|
||||||
else if ((target.Thing as Pawn).RaceProps.mechWeightClass >= MechWeightClass.UltraHeavy)
|
|
||||||
{
|
|
||||||
Messages.Message("Cannot target superheavy mech", (target.Thing as Pawn), MessageTypeDefOf.NegativeEvent);
|
|
||||||
}
|
|
||||||
else if(!bandwidthCheck)
|
|
||||||
{
|
|
||||||
Messages.Message("Insufficient bandwidth", (target.Thing as Pawn), MessageTypeDefOf.NegativeEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
return canApplyOnCheck;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private bool CanDominate(Pawn pawn)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return pawn.RaceProps.IsMechanoid && pawn.RaceProps.mechWeightClass < MechWeightClass.UltraHeavy && (pawn.kindDef.abilities == null || !pawn.kindDef.abilities.Contains(AbilityDefOf.ResurrectionMech));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
|
||||||
{
|
|
||||||
//Log.Message("Apply called");
|
|
||||||
base.Apply(target, dest);
|
|
||||||
Pawn pawn = (Pawn)target;
|
|
||||||
if (!this.CanDominate(pawn))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pawn.SetFaction(this.parent.pawn.Faction);//convert pawn
|
|
||||||
|
|
||||||
this.parent.pawn.relations.AddDirectRelation(PawnRelationDefOf.Overseer, pawn);
|
|
||||||
pawn.stances.stagger.StaggerFor(60, 0.17f);
|
|
||||||
}
|
|
||||||
public override bool GizmoDisabled(out string reason)
|
|
||||||
{
|
|
||||||
reason = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//public override IEnumerable<Mote> CustomWarmupMotes(LocalTargetInfo target)
|
|
||||||
//{
|
|
||||||
// foreach (LocalTargetInfo localTargetInfo in this.parent.GetAffectedTargets(target))
|
|
||||||
// {
|
|
||||||
// Thing thing = localTargetInfo.Thing;
|
|
||||||
// yield return MoteMaker.MakeAttachedOverlay(thing, ThingDefOf.Mote_MechResurrectWarmupOnTarget, Vector3.zero, 1f, -1f);
|
|
||||||
// }
|
|
||||||
// IEnumerator<LocalTargetInfo> enumerator = null;
|
|
||||||
// yield break;
|
|
||||||
// yield break;
|
|
||||||
//}
|
|
||||||
|
|
||||||
public override void PostApplied(List<LocalTargetInfo> targets, Map map)
|
|
||||||
{
|
|
||||||
//Log.Message("PostApplied called");
|
|
||||||
//Vector3 vector = Vector3.zero;
|
|
||||||
//foreach (LocalTargetInfo localTargetInfo in targets)
|
|
||||||
//{
|
|
||||||
// vector += localTargetInfo.Cell.ToVector3Shifted();
|
|
||||||
//}
|
|
||||||
//vector /= (float)targets.Count<LocalTargetInfo>();
|
|
||||||
//IntVec3 intVec = vector.ToIntVec3();
|
|
||||||
//this.Props.resolveEffecterDef.Spawn(intVec, map, 1f).EffectTick(new TargetInfo(intVec, map, false), new TargetInfo(intVec, map, false));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//public class CompProperties_MechanitorMechCarrier : CompProperties_AbilityEffect
|
//public class CompProperties_MechanitorMechCarrier : CompProperties_AbilityEffect
|
||||||
//{
|
//{
|
||||||
// public CompProperties_MechanitorMechCarrier()
|
// public CompProperties_MechanitorMechCarrier()
|
||||||
@ -816,129 +596,6 @@ namespace LTS_Implants
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
public class CompProperties_MechanitorMechCarrier : CompProperties_AbilityEffect
|
|
||||||
{
|
|
||||||
public CompProperties_MechanitorMechCarrier()
|
|
||||||
{
|
|
||||||
this.compClass = typeof(CompAbilityEffect_MechanitorMechCarrier);
|
|
||||||
}
|
|
||||||
public PawnKindDef spawnPawnKind;
|
|
||||||
public int cooldownTicks = 900;
|
|
||||||
public int maxPawnsToSpawn = 2;
|
|
||||||
public EffecterDef spawnEffecter;
|
|
||||||
public EffecterDef spawnedMechEffecter;
|
|
||||||
public bool attachSpawnedEffecter;
|
|
||||||
public bool attachSpawnedMechEffecter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CompAbilityEffect_MechanitorMechCarrier : CompAbilityEffect
|
|
||||||
{
|
|
||||||
public new CompProperties_MechanitorMechCarrier Props
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (CompProperties_MechanitorMechCarrier)this.props;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override void CompTick()
|
|
||||||
{
|
|
||||||
base.CompTick();
|
|
||||||
//if (Find.Selector.IsSelected(parent.pawn) && (int)Find.TickManager.CurTimeSpeed != 0 && Find.TickManager.TicksGame % (int)Find.TickManager.CurTimeSpeed == 0)//if the mechanitor is selected, and once erry 60/1 irl seconds
|
|
||||||
//{
|
|
||||||
// for (int i = 0; i < spawnedPawns.Count; i++)
|
|
||||||
// {
|
|
||||||
// if (!spawnedPawns[i].Dead)
|
|
||||||
// {
|
|
||||||
// GenDraw.DrawLineBetween(this.parent.pawn.TrueCenter(), spawnedPawns[i].TrueCenter());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
|
||||||
{
|
|
||||||
base.Apply(target, dest);
|
|
||||||
TrySpawnPawns();
|
|
||||||
}
|
|
||||||
public int maxspawn()
|
|
||||||
{
|
|
||||||
//Log.Message("RemainingCharges: " + parent.RemainingCharges+1);
|
|
||||||
int max = parent.RemainingCharges+1;//requires +1 to account for the charge that's automatically used upon ability activation, prior to this.
|
|
||||||
if (max > 2) { return 2; }
|
|
||||||
else { return max; }
|
|
||||||
}
|
|
||||||
public void TrySpawnPawns()
|
|
||||||
{
|
|
||||||
int maxCanSpawn = maxspawn();
|
|
||||||
//Log.Message("max spawns: "+ maxCanSpawn);
|
|
||||||
if (maxCanSpawn <= 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PawnGenerationRequest pawnGenerationRequest = new PawnGenerationRequest(this.Props.spawnPawnKind, this.parent.pawn.Faction, PawnGenerationContext.NonPlayer, -1, true, false, false, true, false, 1f, false, true, false, true, true, false, false, false, false, 0f, 0f, null, 1f, null, null, null, null, null, null, null, null, null, null, null, null, false, false, false, false, null, null, null, null, null, 0f, DevelopmentalStage.Newborn, null, null, null, false, false, false, -1, 0, false);
|
|
||||||
Pawn pawn;
|
|
||||||
Lord lord = (((pawn = this.parent.pawn as Pawn) != null) ? pawn.GetLord() : null);
|
|
||||||
for (int i = 0; i < maxCanSpawn; i++)
|
|
||||||
{
|
|
||||||
Pawn pawn2 = PawnGenerator.GeneratePawn(pawnGenerationRequest);
|
|
||||||
GenSpawn.Spawn(pawn2, this.parent.pawn.Position, this.parent.pawn.Map, WipeMode.Vanish);
|
|
||||||
this.spawnedPawns.Add(pawn2);
|
|
||||||
if (lord != null)
|
|
||||||
{
|
|
||||||
lord.AddPawn(pawn2);
|
|
||||||
}
|
|
||||||
if (this.Props.spawnedMechEffecter != null)
|
|
||||||
{
|
|
||||||
Effecter effecter = new Effecter(this.Props.spawnedMechEffecter);
|
|
||||||
effecter.Trigger(this.Props.attachSpawnedMechEffecter ? pawn2 : new TargetInfo(pawn2.Position, pawn2.Map, false), TargetInfo.Invalid, -1);
|
|
||||||
effecter.Cleanup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.cooldownTicksRemaining = this.Props.cooldownTicks;
|
|
||||||
if (this.Props.spawnEffecter != null)
|
|
||||||
{
|
|
||||||
Effecter effecter2 = new Effecter(this.Props.spawnEffecter);
|
|
||||||
effecter2.Trigger(this.Props.attachSpawnedEffecter ? this.parent.pawn : new TargetInfo(this.parent.pawn.Position, this.parent.pawn.Map, false), TargetInfo.Invalid, -1);
|
|
||||||
effecter2.Cleanup();
|
|
||||||
}
|
|
||||||
if (maxCanSpawn == 2)//subtract an extra charge, as we're summoning 2
|
|
||||||
{
|
|
||||||
parent.RemainingCharges--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public List<Pawn> GetSpawnedPawns()
|
|
||||||
{
|
|
||||||
return spawnedPawns;
|
|
||||||
}
|
|
||||||
private int cooldownTicksRemaining;
|
|
||||||
private List<Pawn> spawnedPawns = new List<Pawn>();
|
|
||||||
public SoundDef soundReload;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class HediffCompProperties_KillSpawnedPawns : HediffCompProperties
|
|
||||||
{
|
|
||||||
public AbilityDef abilityDef;
|
|
||||||
public HediffCompProperties_KillSpawnedPawns()
|
|
||||||
{
|
|
||||||
compClass = typeof(HediffComp_KillSpawnedPawns);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class HediffComp_KillSpawnedPawns : HediffComp
|
|
||||||
{
|
|
||||||
public HediffCompProperties_KillSpawnedPawns Props => (HediffCompProperties_KillSpawnedPawns)props;
|
|
||||||
|
|
||||||
public override void Notify_PawnKilled()
|
|
||||||
{
|
|
||||||
foreach (Pawn i in base.Pawn.abilities.GetAbility(Props.abilityDef).CompOfType<CompAbilityEffect_MechanitorMechCarrier>().GetSpawnedPawns())
|
|
||||||
{
|
|
||||||
if (!i.Dead)
|
|
||||||
{
|
|
||||||
i.Kill(null, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//public class Command_AbilityReloadable : Command_Ability
|
//public class Command_AbilityReloadable : Command_Ability
|
||||||
//{
|
//{
|
||||||
// public Command_AbilityReloadable(Ability ability, Pawn pawn) : base(ability, pawn)
|
// public Command_AbilityReloadable(Ability ability, Pawn pawn) : base(ability, pawn)
|
||||||
@ -1632,33 +1289,6 @@ namespace LTS_Implants
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LTS_Hediff_DeathRaiseAsShambler : HediffWithComps
|
|
||||||
{
|
|
||||||
//PawnKindDef spawnedPawn = PawnKindDefOf.Metalhorror;
|
|
||||||
|
|
||||||
public override void Notify_PawnDied(DamageInfo? dinfo, Hediff culprit = null)
|
|
||||||
{
|
|
||||||
base.Notify_PawnDied(dinfo, culprit);
|
|
||||||
if (pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.ShamblerCorpse) == null)
|
|
||||||
{
|
|
||||||
//Faction faction;
|
|
||||||
//if (pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.ShamblerCorpse) != null)
|
|
||||||
//{
|
|
||||||
// faction = pawn?.health?.hediffSet?.GetFirstHediffOfDef(HediffDef.Named("ScratchDeadlife"))
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// faction = pawn.Faction;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
Faction faction = dinfo.GetValueOrDefault().Instigator?.Faction ?? pawn.Faction;
|
|
||||||
if (pawn?.health?.hediffSet?.GetFirstHediffOfDef(HediffDef.Named("DeadlifeCollar")) != null) { faction = pawn.Faction; }
|
|
||||||
GasUtility.AddDeadifeGas(pawn.Position, pawn.MapHeld, faction, Mathf.CeilToInt(255));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LTS_Hediff_HeadFitter : HediffWithComps //on creation: get hair and head type, then set them to bald and narrow. on removal, set hair type to orignal (null check, check this works for newly spawning ghouls). Deep save. don't forget to null check due to xenobionic patcher
|
public class LTS_Hediff_HeadFitter : HediffWithComps //on creation: get hair and head type, then set them to bald and narrow. on removal, set hair type to orignal (null check, check this works for newly spawning ghouls). Deep save. don't forget to null check due to xenobionic patcher
|
||||||
{
|
{
|
||||||
HairDef originalHair;
|
HairDef originalHair;
|
||||||
@ -1873,172 +1503,6 @@ namespace LTS_Implants
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CompProperties_PsychicBeguile : CompProperties_AbilityEffect
|
|
||||||
{
|
|
||||||
public CompProperties_PsychicBeguile()
|
|
||||||
{
|
|
||||||
this.compClass = typeof(CompAbilityEffect_PsychicBeguile);
|
|
||||||
}
|
|
||||||
public PawnRelationDef pawnRelationDef;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CompAbilityEffect_PsychicBeguile : CompAbilityEffect
|
|
||||||
{
|
|
||||||
public new CompProperties_PsychicBeguile Props
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (CompProperties_PsychicBeguile)this.props;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
|
||||||
{
|
|
||||||
base.Apply(target, dest);
|
|
||||||
if (target.Pawn.Faction != parent.pawn.Faction)
|
|
||||||
{
|
|
||||||
target.Pawn.SetFaction(parent.pawn.Faction);
|
|
||||||
IncidentWorker.SendIncidentLetter(target.Pawn.Name + " beguiled!", parent.pawn.Name + " has used " + parent.pawn.Possessive() + " psychic beguiler to psychically manipulate " + target.Pawn.Name + ". " + target.Pawn.Name + " has become obsessed with " + parent.pawn.Name + " and is joining " + parent.pawn.Possessive() + " faction.", LetterDefOf.PositiveEvent, new IncidentParms(), target.Pawn, IncidentDefOf.WandererJoin);
|
|
||||||
}
|
|
||||||
target.Pawn.relations.AddDirectRelation(Props.pawnRelationDef, parent.pawn);
|
|
||||||
if(target.Pawn.health.hediffSet.TryGetHediff(HediffDefOf.CubeComa, out Hediff cubeComa))
|
|
||||||
{
|
|
||||||
target.Pawn.health.RemoveHediff(cubeComa);
|
|
||||||
}
|
|
||||||
if (target.Pawn.health.hediffSet.TryGetHediff(HediffDefOf.CubeInterest, out Hediff cubeInterest))
|
|
||||||
{
|
|
||||||
target.Pawn.health.RemoveHediff(cubeInterest);
|
|
||||||
}
|
|
||||||
if (target.Pawn.health.hediffSet.TryGetHediff(HediffDefOf.CubeWithdrawal, out Hediff cubeWithdrawal))
|
|
||||||
{
|
|
||||||
target.Pawn.health.RemoveHediff(cubeWithdrawal);
|
|
||||||
}
|
|
||||||
if (target.Pawn.health.hediffSet.TryGetHediff(HediffDefOf.CubeRage, out Hediff cubeRage))
|
|
||||||
{
|
|
||||||
target.Pawn.health.RemoveHediff(cubeRage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LTS_Hediff_ObsessionBerserkOnDeath : HediffWithComps
|
|
||||||
{
|
|
||||||
|
|
||||||
public override void Notify_PawnCorpseSpawned()
|
|
||||||
{
|
|
||||||
base.Notify_PawnCorpseSpawned();
|
|
||||||
List<Pawn> allHumanlikeSpawned = pawn.Corpse.Map.mapPawns.AllHumanlikeSpawned;
|
|
||||||
for (int i = 0; i < allHumanlikeSpawned.Count; i++)
|
|
||||||
{
|
|
||||||
Pawn otherPawn = allHumanlikeSpawned[i];
|
|
||||||
if (otherPawn.RaceProps.Humanlike && otherPawn.relations.GetDirectRelation(I_DefOf.PsychicBeguileObsessed, pawn) != null)
|
|
||||||
{
|
|
||||||
MentalBreakDefOf.BerserkShort.Worker.TryStart(otherPawn, "Target of obsession died", false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override void PostAdd(DamageInfo? dinfo)
|
|
||||||
{
|
|
||||||
base.PostAdd(dinfo);
|
|
||||||
RemoveCubeHediffs(pawn);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveCubeHediffs(Pawn pawn)
|
|
||||||
{
|
|
||||||
if (pawn.health.hediffSet.TryGetHediff(HediffDefOf.CubeComa, out Hediff cubeComa))
|
|
||||||
{
|
|
||||||
pawn.health.RemoveHediff(cubeComa);
|
|
||||||
}
|
|
||||||
if (pawn.health.hediffSet.TryGetHediff(HediffDefOf.CubeInterest, out Hediff cubeInterest))
|
|
||||||
{
|
|
||||||
pawn.health.RemoveHediff(cubeInterest);
|
|
||||||
}
|
|
||||||
if (pawn.health.hediffSet.TryGetHediff(HediffDefOf.CubeWithdrawal, out Hediff cubeWithdrawal))
|
|
||||||
{
|
|
||||||
pawn.health.RemoveHediff(cubeWithdrawal);
|
|
||||||
}
|
|
||||||
if (pawn.health.hediffSet.TryGetHediff(HediffDefOf.CubeRage, out Hediff cubeRage))
|
|
||||||
{
|
|
||||||
pawn.health.RemoveHediff(cubeRage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LTS_Hediff_HyperAdrenalineGland : Hediff
|
|
||||||
{
|
|
||||||
private float totalDamageTaken;
|
|
||||||
|
|
||||||
public override void Notify_PawnPostApplyDamage(DamageInfo dinfo, float totalDamageDealt)
|
|
||||||
{
|
|
||||||
base.Notify_PawnPostApplyDamage(dinfo, totalDamageDealt);
|
|
||||||
if (pawn.Dead)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//if (pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("PsychokeneticShield")) != null && ((pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("PsychokeneticShield"))) as LTS_ShieldHediff).PsychicShieldCurrentHealth > 0)
|
|
||||||
//{
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
totalDamageTaken += totalDamageDealt;
|
|
||||||
if (!pawn.Dead && totalDamageTaken > 0f && !pawn.health.hediffSet.HasHediff(HediffDefOf.RageSpeed) && !pawn.health.Downed)
|
|
||||||
{
|
|
||||||
pawn.health.AddHediff(HediffMaker.MakeHediff(HediffDefOf.RageSpeed, pawn));
|
|
||||||
if (pawn.Spawned)
|
|
||||||
{
|
|
||||||
EffecterDefOf.ChimeraRage.Spawn(pawn.Position, pawn.Map).Cleanup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Notify_Downed()
|
|
||||||
{
|
|
||||||
Hediff firstHediffOfDef = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.RageSpeed);
|
|
||||||
if (firstHediffOfDef != null)
|
|
||||||
{
|
|
||||||
pawn.health.RemoveHediff(firstHediffOfDef);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Tick()
|
|
||||||
{
|
|
||||||
base.Tick();
|
|
||||||
if (!pawn.Dead && pawn.health.summaryHealth.SummaryHealthPercent >= 0.98f)
|
|
||||||
{
|
|
||||||
Hediff firstHediffOfDef = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.RageSpeed);
|
|
||||||
if (firstHediffOfDef != null)
|
|
||||||
{
|
|
||||||
pawn.health.RemoveHediff(firstHediffOfDef);
|
|
||||||
totalDamageTaken = 0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ExposeData()
|
|
||||||
{
|
|
||||||
base.ExposeData();
|
|
||||||
Scribe_Values.Look(ref totalDamageTaken, "totalDamageTaken", 0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LTS_Hediff_DefensiveImpaler : Hediff
|
|
||||||
{
|
|
||||||
public override void Notify_PawnPostApplyDamage(DamageInfo dinfo, float totalDamageDealt)
|
|
||||||
{
|
|
||||||
base.Notify_PawnPostApplyDamage(dinfo, totalDamageDealt);
|
|
||||||
if (pawn.Dead)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (dinfo.Instigator != null && pawn.Position.InHorDistOf(dinfo.Instigator.Position, 1.5f))//attacker next to user //apply 6 stab damage, 20% penetration
|
|
||||||
{
|
|
||||||
//SoundDefOf..PlayOneShot(pawn);
|
|
||||||
//BattleLogEntry_DamageTaken battleLogEntry_DamageTaken = new BattleLogEntry_DamageTaken(pawn, RulePackDefOf.DamageEvent_UnnaturalDarkness);
|
|
||||||
//Find.BattleLog.Add(battleLogEntry_DamageTaken);
|
|
||||||
//dinfo.Instigator.TakeDamage(new DamageInfo(DamageDefOf.Stab, 6)).AssociateWithLog(battleLogEntry_DamageTaken);
|
|
||||||
dinfo.Instigator.TakeDamage(new DamageInfo(DamageDefOf.Stab, 6));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LTS_HediffCompProperties_HediffApparel : HediffCompProperties
|
public class LTS_HediffCompProperties_HediffApparel : HediffCompProperties
|
||||||
{
|
{
|
||||||
public HediffDef maleHediffDef;
|
public HediffDef maleHediffDef;
|
||||||
@ -2417,82 +1881,6 @@ namespace LTS_Implants
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LTS_CompProperties_CaptiveControl : CompProperties_AbilityEffect
|
|
||||||
{
|
|
||||||
public LTS_CompProperties_CaptiveControl()
|
|
||||||
{
|
|
||||||
this.compClass = typeof(LTS_CompAbilityEffect_CaptiveControl);
|
|
||||||
}
|
|
||||||
public HediffDef hediffDef;
|
|
||||||
public float StartSeverity;
|
|
||||||
public string location = null;
|
|
||||||
public int duration = 3600; // 1 hour
|
|
||||||
public bool headExploder = false;
|
|
||||||
public bool hediffToggle = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LTS_CompAbilityEffect_CaptiveControl : CompAbilityEffect
|
|
||||||
{
|
|
||||||
public new LTS_CompProperties_CaptiveControl Props
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (LTS_CompProperties_CaptiveControl)this.props;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
|
||||||
{
|
|
||||||
base.Apply(target, dest);
|
|
||||||
|
|
||||||
if (target.Pawn != null)
|
|
||||||
{
|
|
||||||
if (Props.headExploder)
|
|
||||||
{
|
|
||||||
if (EffecterDefOf.MeatExplosion != null)
|
|
||||||
{
|
|
||||||
EffecterDefOf.MeatExplosion.Spawn(parent.pawn.PositionHeld, parent.pawn.MapHeld).Cleanup();
|
|
||||||
}
|
|
||||||
SoundDefOf.CocoonDestroyed.PlayOneShot(new TargetInfo(target.Pawn.Position, target.Pawn.Map));
|
|
||||||
target.Pawn.TakeDamage(new DamageInfo(DamageDefOf.Crush, 100, 0, -1, null, target.Pawn.health.hediffSet.GetBodyPartRecord(BodyPartDefOf.Head)));
|
|
||||||
//target.Pawn.TakeDamage(new DamageInfo(DamageDefOf.Bomb, 100, 0, -1, null, target.Pawn.health.hediffSet.GetBodyPartRecord(BodyPartDefOf.Head)));
|
|
||||||
}
|
|
||||||
else if (Props.hediffToggle)
|
|
||||||
{
|
|
||||||
if (target.Pawn.health?.hediffSet?.GetFirstHediffOfDef(this.Props.hediffDef) != null)
|
|
||||||
{
|
|
||||||
target.Pawn.health.RemoveHediff(target.Pawn.health.hediffSet.GetFirstHediffOfDef(this.Props.hediffDef));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
target.Pawn.health.AddHediff(this.Props.hediffDef, location(target));
|
|
||||||
if (target.Pawn.health.hediffSet.GetFirstHediffOfDef(this.Props.hediffDef).TryGetComp<HediffComp_Lactating>() != null)
|
|
||||||
{
|
|
||||||
target.Pawn.health.hediffSet.GetFirstHediffOfDef(this.Props.hediffDef).TryGetComp<HediffComp_Lactating>().TryCharge(-0.124f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
target.Pawn.health.AddHediff(this.Props.hediffDef, location(target));
|
|
||||||
if (target.Pawn.health.hediffSet.GetFirstHediffOfDef(this.Props.hediffDef).TryGetComp<HediffComp_Disappears>() != null)
|
|
||||||
{
|
|
||||||
target.Pawn.health.hediffSet.GetFirstHediffOfDef(this.Props.hediffDef).TryGetComp<HediffComp_Disappears>().ticksToDisappear = Props.duration;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public BodyPartRecord location(LocalTargetInfo target)
|
|
||||||
{
|
|
||||||
if (Props.location == null) { return null; }
|
|
||||||
|
|
||||||
//return target.Pawn.health.hediffSet.GetNotMissingParts(BodyPartHeight.Undefined, BodyPartDepth.Undefined).Where(part => part.def.tags.Contains(BodyPartTagDefOf.ManipulationLimbSegment)).ToList()[0];
|
|
||||||
return target.Pawn.health.hediffSet.GetNotMissingParts(BodyPartHeight.Undefined, BodyPartDepth.Undefined).Where(part => part.def.defName == Props.location).ToList()[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LTS_Hediff_PsychicSustainer : Hediff
|
public class LTS_Hediff_PsychicSustainer : Hediff
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -2749,10 +2137,6 @@ namespace LTS_Implants
|
|||||||
{
|
{
|
||||||
return RefuelWorkGiverUtility.FindEnoughReservableThings(parent.pawn, parent.pawn.Position, new IntRange(Props.ammoCountPerCharge, ammoCountToRefill), (Thing ammo) => ammo.def == Props.ammoDef);
|
return RefuelWorkGiverUtility.FindEnoughReservableThings(parent.pawn, parent.pawn.Position, new IntRange(Props.ammoCountPerCharge, ammoCountToRefill), (Thing ammo) => ammo.def == Props.ammoDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//public class LTS_JobDriver_ReloadAbility : JobDriver
|
//public class LTS_JobDriver_ReloadAbility : JobDriver
|
||||||
@ -3322,108 +2706,6 @@ namespace LTS_Implants
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LTS_Hediff_PsychicReaper : Hediff
|
|
||||||
{
|
|
||||||
private int previousHumanKills = -1;
|
|
||||||
|
|
||||||
public override void PostAdd(DamageInfo? dinfo)
|
|
||||||
{
|
|
||||||
base.PostAdd(dinfo);
|
|
||||||
previousHumanKills = (int)pawn.records.GetValue(RecordDefOf.KillsHumanlikes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Notify_Spawned()
|
|
||||||
{
|
|
||||||
base.Notify_Spawned();
|
|
||||||
PostAdd(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Tick()
|
|
||||||
{
|
|
||||||
base.Tick();
|
|
||||||
//Log.Message("Psychic Reaper Tick");
|
|
||||||
if (Find.TickManager.TicksGame % 10 == 0)
|
|
||||||
{
|
|
||||||
if ((int)pawn.records.GetValue(RecordDefOf.KillsHumanlikes) > previousHumanKills)
|
|
||||||
{
|
|
||||||
//Log.Message("Previous kills: " + previousHumanKills);
|
|
||||||
//Log.Message("Current kills: "+ (int)pawn.records.GetValue(RecordDefOf.KillsHumanlikes));
|
|
||||||
pawn.psychicEntropy.OffsetPsyfocusDirectly(0.05f*((int)pawn.records.GetValue(RecordDefOf.KillsHumanlikes) - previousHumanKills));//add 5 psyfocus per humanlike kill
|
|
||||||
}
|
|
||||||
previousHumanKills = (int)pawn.records.GetValue(RecordDefOf.KillsHumanlikes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LTS_Hediff_Voidlink : Hediff
|
|
||||||
{
|
|
||||||
public override bool ShouldRemove => false;
|
|
||||||
public override void Tick()
|
|
||||||
{
|
|
||||||
base.Tick();
|
|
||||||
if (Find.TickManager.TicksGame % 30 == 0)
|
|
||||||
{
|
|
||||||
Severity = Find.Anomaly.LevelDef.level;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LTS_HediffCompProperties_MetalhorrorEmerge : HediffCompProperties
|
|
||||||
{
|
|
||||||
public string letterLabel;
|
|
||||||
|
|
||||||
public string letterText;
|
|
||||||
|
|
||||||
public LTS_HediffCompProperties_MetalhorrorEmerge()
|
|
||||||
{
|
|
||||||
compClass = typeof(LTS_HediffComp_MetalhorrorEmerge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LTS_HediffComp_MetalhorrorEmerge : HediffComp
|
|
||||||
{
|
|
||||||
private static readonly IntRange StunDuration = new IntRange(120, 240);
|
|
||||||
|
|
||||||
public LTS_HediffCompProperties_MetalhorrorEmerge Props => (LTS_HediffCompProperties_MetalhorrorEmerge)props;
|
|
||||||
|
|
||||||
public override void Notify_SurgicallyRemoved(Pawn surgeon)
|
|
||||||
{
|
|
||||||
TentacleAttack(surgeon);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Notify_SurgicallyReplaced(Pawn surgeon)
|
|
||||||
{
|
|
||||||
TentacleAttack(surgeon);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TentacleAttack(Pawn surgeon)
|
|
||||||
{
|
|
||||||
if (ModsConfig.AnomalyActive)
|
|
||||||
{
|
|
||||||
Pawn pawn = parent.pawn;
|
|
||||||
Pawn pawn2 = PawnGenerator.GeneratePawn(new PawnGenerationRequest(PawnKindDefOf.Metalhorror, Faction.OfEntities, PawnGenerationContext.NonPlayer, -1, forceGenerateNewPawn: false, allowDead: false, allowDowned: false, canGeneratePawnRelations: true, mustBeCapableOfViolence: false, 1f, forceAddFreeWarmLayerIfNeeded: false, allowGay: true, allowPregnant: false, allowFood: true, allowAddictions: true, inhabitant: false, certainlyBeenInCryptosleep: false, forceRedressWorldPawnIfFormerColonist: false, worldPawnFactionDoesntMatter: false, 0f, 0f, null, 1f, null, null, null, null, null, 0f, 0f));
|
|
||||||
GenSpawn.Spawn(pawn2, CellFinder.StandableCellNear(pawn.Position, pawn.Map, 2f), pawn.Map);
|
|
||||||
pawn2.stances.stunner.StunFor(StunDuration.RandomInRange, surgeon);
|
|
||||||
CompInspectStringEmergence compInspectStringEmergence = pawn2.TryGetComp<CompInspectStringEmergence>();
|
|
||||||
if (compInspectStringEmergence != null)
|
|
||||||
{
|
|
||||||
compInspectStringEmergence.sourcePawn = pawn;
|
|
||||||
}
|
|
||||||
TaggedString label = Props.letterLabel.Formatted(pawn.Named("PAWN"));
|
|
||||||
TaggedString text = Props.letterText.Formatted(pawn.Named("PAWN"));
|
|
||||||
Find.LetterStack.ReceiveLetter(label, text, LetterDefOf.ThreatBig, pawn2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class LTS_IModExtension : DefModExtension
|
public class LTS_IModExtension : DefModExtension
|
||||||
{
|
{
|
||||||
public int LTS_TicksBetweenPulse;
|
public int LTS_TicksBetweenPulse;
|
||||||
@ -3465,40 +2747,6 @@ namespace LTS_Implants
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Bootstrap class to do the harmony patches.
|
/// Bootstrap class to do the harmony patches.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[StaticConstructorOnStartup]
|
|
||||||
public static class HarmonyPatches
|
|
||||||
{
|
|
||||||
static HarmonyPatches()
|
|
||||||
{
|
|
||||||
Harmony harmony = new Harmony("rimworld.LTS.implants");
|
|
||||||
Harmony.DEBUG = false;
|
|
||||||
harmony.PatchAll();
|
|
||||||
#if DEBUG
|
|
||||||
foreach (var method in harmony.GetPatchedMethods())
|
|
||||||
{
|
|
||||||
Verse.Log.Message($"[LTS Implants]Patched Method {method.Name}");
|
|
||||||
var patchinfo = Harmony.GetPatchInfo(method);
|
|
||||||
foreach (var VARIABLE in patchinfo.Owners)
|
|
||||||
{
|
|
||||||
Verse.Log.Message("The Method has been patched by:"+VARIABLE);
|
|
||||||
}
|
|
||||||
foreach (var VARIABLE in patchinfo.Prefixes)
|
|
||||||
{
|
|
||||||
Verse.Log.Message("has Prefix:"+VARIABLE.PatchMethod);
|
|
||||||
}
|
|
||||||
foreach (var VARIABLE in patchinfo.Postfixes)
|
|
||||||
{
|
|
||||||
Verse.Log.Message("has Postfix:"+VARIABLE.PatchMethod);
|
|
||||||
}
|
|
||||||
foreach (var VARIABLE in patchinfo.Transpilers)
|
|
||||||
{
|
|
||||||
Verse.Log.Message("has Transpiler:"+VARIABLE.PatchMethod);
|
|
||||||
}
|
|
||||||
Verse.Log.Message("Displaying next method");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[HarmonyPatch(typeof(StatPart_FertilityByGenderAge), "AgeFactor")]
|
[HarmonyPatch(typeof(StatPart_FertilityByGenderAge), "AgeFactor")]
|
||||||
class StatPart_FertilityByGenderAge_AgeFactor_Patch
|
class StatPart_FertilityByGenderAge_AgeFactor_Patch
|
||||||
{
|
{
|
||||||
@ -4391,188 +3639,6 @@ namespace LTS_Implants
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
[HarmonyPatch(typeof(Pawn_MechanitorTracker))]
|
|
||||||
[HarmonyPatch(nameof(Pawn_MechanitorTracker.CanCommandTo))]
|
|
||||||
class Pawn_MechanitorTracker_CanCommandTo_Patch //increases the mechanitor's range by MechRemoteControlDistanceOffset
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// pushed always commandable check to front to reduct compute.
|
|
||||||
/// TODO perhaps need a custom patch order to make sure this logic always works.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="target">target mech to command</param>
|
|
||||||
/// <param name="__instance">should be mechanitor, but not always the mechanitor for example like Dead man switch ctrl mechs </param>
|
|
||||||
/// <param name="__result">Commandable result from original code.</param>
|
|
||||||
[HarmonyPostfix]
|
|
||||||
public static void CanCommandToPostfix(LocalTargetInfo target, Pawn_MechanitorTracker __instance, ref bool __result)
|
|
||||||
{
|
|
||||||
if (__result)
|
|
||||||
return;
|
|
||||||
float SignalBoosterRange = __instance.Pawn?.GetStatValue(StatDef.Named("MechRemoteControlDistanceOffset")) ?? 0f;
|
|
||||||
__result = target.Cell.InBounds(__instance.Pawn.MapHeld) && (float)__instance.Pawn.Position.DistanceToSquared(target.Cell) < (24.9f + SignalBoosterRange) * (24.9f + SignalBoosterRange);//last line should mean that if something else makes it true, then it is(?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(Pawn_MechanitorTracker))]
|
|
||||||
[HarmonyPatch(nameof(Pawn_MechanitorTracker.DrawCommandRadius))]
|
|
||||||
class Pawn_MechanitorTracker_DrawCommandRadius_Patch //increases the displayed mechanitor range by MechRemoteControlDistanceOffset
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Skip original draw radius using a prefix.
|
|
||||||
/// TODO may need specify fixed patch order to make sure this works.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>return false to skip original draw.</returns>
|
|
||||||
[HarmonyPrefix]
|
|
||||||
static bool DrawCommandRadiusPrefix()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Postfix the draw radius by apply our extended radius on top.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="__instance"></param>
|
|
||||||
[HarmonyPostfix]
|
|
||||||
public static void DrawCommandRadiusPostfix(Pawn_MechanitorTracker __instance)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (__instance.Pawn.Spawned && __instance.AnySelectedDraftedMechs)
|
|
||||||
{
|
|
||||||
//GenDraw.DrawRadiusRing(___pawn.Position, 24.9f + (3f*___pawn.health?.hediffSet?.GetFirstHediffOfDef(HediffDef.Named("SignalBoosterImplant"))?.Severity ?? 0f), Color.white, (IntVec3 c) => __instance.CanCommandTo(c));
|
|
||||||
if (!ModsConfig.IsActive("swwu.MechanitorCommandRange") && !ModsConfig.IsActive("Neronix17.TweaksGalore")) //for tweaks galore, it'd be better to try to find the setting specifically, with an inverted result and a null check true
|
|
||||||
{
|
|
||||||
IntVec3 position = __instance.Pawn.Position;
|
|
||||||
float radius = 24.9f + (__instance.Pawn?.GetStatValue(StatDef.Named("MechRemoteControlDistanceOffset")) ?? 0f);
|
|
||||||
MoteMaker.ThrowText();
|
|
||||||
//Make our command circle yellow. And make sure this postfix implemented draw follows vanilla impl.
|
|
||||||
GenDraw.DrawRadiusRing(position, radius, Color.yellow,(IntVec3 c) => __instance.CanCommandTo((LocalTargetInfo)c));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(Gene_Deathrest))]
|
|
||||||
[HarmonyPatch(nameof(Gene_Deathrest.RemoveOldDeathrestBonuses))]
|
|
||||||
class Gene_Deathrest_RemoveOldDeathrestBonuses_Patch //offsets the pawn's hemogen capacity by their BaseHemogenOffset stat after reset
|
|
||||||
{
|
|
||||||
[HarmonyPostfix]
|
|
||||||
public static void RemoveOldDeathrestBonusesPostfix(Gene_Deathrest __instance)
|
|
||||||
{
|
|
||||||
if (__instance?.pawn?.genes?.GetFirstGeneOfType<Gene_Hemogen>() != null)
|
|
||||||
{
|
|
||||||
__instance.pawn.genes.GetFirstGeneOfType<Gene_Hemogen>().SetMax(__instance.pawn.genes.GetFirstGeneOfType<Gene_Hemogen>().Max + __instance.pawn.GetStatValue(StatDef.Named("BaseHemogenOffset")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(Need_Deathrest))]
|
|
||||||
[HarmonyPatch(nameof(Need_Deathrest.NeedInterval))]
|
|
||||||
class Need_Deathrest_NeedInterval_Patch//reduces and increases the time left for and between death rests for the DeathrestApparatus and DeathrestCapacitor respectively
|
|
||||||
{
|
|
||||||
[HarmonyPostfix]
|
|
||||||
public static void NeedIntervalPostfix(Need_Deathrest __instance, Pawn ___pawn)
|
|
||||||
{
|
|
||||||
bool IsFrozen = ___pawn.Suspended || (__instance.def.freezeWhileSleeping && !___pawn.Awake()) || (__instance.def.freezeInMentalState && ___pawn.InMentalState);
|
|
||||||
|
|
||||||
if (!IsFrozen)
|
|
||||||
{
|
|
||||||
float deathrestingOffset = (((___pawn?.GetStatValue(StatDef.Named("DeathrestEffectivenessFactor")) ?? 1f)) - 1f) * 0.2f; // + 1.2 0r 1 -1 *0.2 //also total factor = implant factor * gene factor * (___pawn.genes.GetFirstGeneOfType<Gene_Deathrest>()?.DeathrestEfficiency ?? 1f)
|
|
||||||
float notDeathrestingOffset = (1f / 30f); // cancels out base function
|
|
||||||
|
|
||||||
deathrestingOffset += (float)(___pawn.genes.GetFirstGeneOfType<Gene_Deathrest>()?.DeathrestEfficiency-0.5) * 0.2f; //-0.5 is an arbritrary, place holder number until I find the correct maths
|
|
||||||
//Log.Message(___pawn.genes.GetFirstGeneOfType<Gene_Deathrest>()?.DeathrestEfficiency);
|
|
||||||
notDeathrestingOffset += (1 / (___pawn?.GetStatValue(StatDef.Named("DeathrestIntervalFactor")) ?? 1f)) * (-1f / 30f); // 1/stat*base, so 200% = decrease at half the rate and 50% = decrease at double
|
|
||||||
|
|
||||||
|
|
||||||
__instance.CurLevel += (__instance.Deathresting ? deathrestingOffset : notDeathrestingOffset) / 400f;
|
|
||||||
//__instance.CurLevel += (__instance.Deathresting ? (0.2f * ((___pawn?.GetStatValue(StatDef.Named("DeathrestEffectivenessFactor")) ?? 1f) - 1f)) : (((___pawn?.GetStatValue(StatDef.Named("DeathrestIntervalFactor")) ?? 1f) - 1f) / 30f)) / 400f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(Gene_Deathrest))]
|
|
||||||
[HarmonyPatch(nameof(Gene_Deathrest.TickDeathresting))]
|
|
||||||
class Gene_Deathrest_TickDeathresting_patch//makes deathrest hediff go up. and death res need.
|
|
||||||
{
|
|
||||||
[HarmonyPostfix]
|
|
||||||
public static void TickDeathrestingPostfix(bool paused, Gene_Deathrest __instance, Pawn ___pawn, Need_Deathrest ___cachedDeathrestNeed)
|
|
||||||
{
|
|
||||||
int everyXTicks = (int)(1 / ((___pawn?.GetStatValue(StatDef.Named("DeathrestEffectivenessFactor")) ?? 1f) - 1f));
|
|
||||||
if (Find.TickManager.TicksGame % everyXTicks == 0)
|
|
||||||
{
|
|
||||||
__instance.deathrestTicks++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(Need_Deathrest))]
|
|
||||||
[HarmonyPatch(nameof(Need_Deathrest.GetTipString))]
|
|
||||||
class Need_Deathrest_GetTipString_Patch //increases the displayed time left between deathresting if the pawn has a DeathrestCapacitor
|
|
||||||
{
|
|
||||||
[HarmonyPostfix]
|
|
||||||
public static void GetTipStringPostfix(Need_Deathrest __instance, Pawn ___pawn, ref string __result)
|
|
||||||
{
|
|
||||||
string text = (__instance.LabelCap + ": " + __instance.CurLevelPercentage.ToStringPercent()).Colorize(ColoredText.TipSectionTitleColor) + "\n";
|
|
||||||
if (!__instance.Deathresting)
|
|
||||||
{
|
|
||||||
if (__instance.CurLevelPercentage > 0.1f)
|
|
||||||
{
|
|
||||||
float num = (__instance.CurLevelPercentage - 0.1f) / (0.033333335f * (1f / ___pawn?.GetStatValue(StatDef.Named("DeathrestIntervalFactor")) ?? 1f));//multiplies listed time until next deathrest by DeathrestIntervalFactor
|
|
||||||
text += "NextDeathrestNeed".Translate(___pawn.Named("PAWN"), "PeriodDays".Translate(num.ToString("F1")).Named("DURATION")).Resolve().CapitalizeFirst();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
text += "PawnShouldDeathrestNow".Translate(___pawn.Named("PAWN")).CapitalizeFirst().Colorize(ColorLibrary.RedReadable);
|
|
||||||
}
|
|
||||||
text += "\n\n";
|
|
||||||
}
|
|
||||||
__result = text + __instance.def.description;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(SanguophageUtility))]
|
|
||||||
[HarmonyPatch(nameof(SanguophageUtility.DeathrestJobReport))]
|
|
||||||
class SanguophageUtility_DeathrestJobReport_Patch //reduces the displayed time left while deathresting if the pawn has a DeathrestApparatus
|
|
||||||
{
|
|
||||||
[HarmonyPostfix]
|
|
||||||
public static void DeathrestJobReportPostfix(Pawn pawn, ref string __result)
|
|
||||||
{
|
|
||||||
Hediff_Deathrest hediff_Deathrest = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.Deathrest, false) as Hediff_Deathrest;
|
|
||||||
if (hediff_Deathrest != null && hediff_Deathrest.Paused)
|
|
||||||
{
|
|
||||||
__result = "DeathrestPaused".Translate() + ": " + "LethalInjuries".Translate();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Gene_Deathrest firstGeneOfType = pawn.genes.GetFirstGeneOfType<Gene_Deathrest>();
|
|
||||||
TaggedString taggedString = "Deathresting".Translate().CapitalizeFirst() + ": ";
|
|
||||||
float deathrestPercent = firstGeneOfType.DeathrestPercent;
|
|
||||||
if (deathrestPercent < 1f)
|
|
||||||
{
|
|
||||||
taggedString += Mathf.Min(deathrestPercent, 0.99f).ToStringPercent("F0");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
taggedString += string.Format("{0} - {1}", "Complete".Translate().CapitalizeFirst(), "CanWakeSafely".Translate());
|
|
||||||
}
|
|
||||||
if (deathrestPercent < 1f)
|
|
||||||
{
|
|
||||||
//taggedString += ", " + "DurationLeft".Translate((Mathf.RoundToInt(firstGeneOfType.MinDeathrestTicks * (1f / pawn?.GetStatValue(StatDef.Named("DeathrestEffectivenessFactor")) ?? 1f) - firstGeneOfType.deathrestTicks)).ToStringTicksToPeriod(true, false, true, true, false));
|
|
||||||
//taggedString += ", " + "DurationLeft".Translate((Mathf.RoundToInt(firstGeneOfType.MinDeathrestTicks * (1f / pawn?.GetStatValue(StatDef.Named("DeathrestEffectivenessFactor")) ?? 1f) - firstGeneOfType.deathrestTicks)).ToStringTicksToPeriod(true, false, true, true, false));
|
|
||||||
|
|
||||||
taggedString += ", " + "DurationLeft".Translate((firstGeneOfType.MinDeathrestTicks - (Mathf.RoundToInt(firstGeneOfType.deathrestTicks * (1f / pawn?.GetStatValue(StatDef.Named("DeathrestEffectivenessFactor")) ?? 1f)))).ToStringTicksToPeriod(true, false, true, true, false));
|
|
||||||
|
|
||||||
|
|
||||||
//Log.Message(pawn?.GetStatValue(StatDef.Named("DeathrestEffectivenessFactor")));
|
|
||||||
//Log.Message(firstGeneOfType.deathrestTicks);
|
|
||||||
}
|
|
||||||
__result = taggedString.Resolve();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(DamageWorker_AddInjury))] //change to bite?
|
[HarmonyPatch(typeof(DamageWorker_AddInjury))] //change to bite?
|
||||||
[HarmonyPatch(nameof(DamageWorker_AddInjury.Apply))]
|
[HarmonyPatch(nameof(DamageWorker_AddInjury.Apply))]
|
||||||
class DamageWorker_AddInjury_Apply_Patch
|
class DamageWorker_AddInjury_Apply_Patch
|
||||||
|
51
1.5/Assemblies/Implants/PatchBootStrap.cs
Normal file
51
1.5/Assemblies/Implants/PatchBootStrap.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using HarmonyLib;
|
||||||
|
using Verse;
|
||||||
|
|
||||||
|
namespace LTS_Implants
|
||||||
|
{
|
||||||
|
[StaticConstructorOnStartup]
|
||||||
|
public static class HarmonyPatches
|
||||||
|
{
|
||||||
|
public static bool IsCombatExtended = false;
|
||||||
|
static HarmonyPatches()
|
||||||
|
{
|
||||||
|
Harmony harmony = new Harmony("rimworld.LTS.implants");
|
||||||
|
Harmony.DEBUG = false;
|
||||||
|
//Check if we are in a CE enabled env
|
||||||
|
if(ModLister.GetModWithIdentifier("ceteam.combatextended")!=null)
|
||||||
|
IsCombatExtended = true;
|
||||||
|
if (ModLister.BiotechInstalled)
|
||||||
|
{
|
||||||
|
Verse.Log.Message("[LTS Intrgated Implants Forked]Biotech found, harmony patch running");
|
||||||
|
harmony.PatchCategory("Biotech");
|
||||||
|
}
|
||||||
|
|
||||||
|
harmony.PatchAllUncategorized(Assembly.GetExecutingAssembly());
|
||||||
|
#if DEBUG
|
||||||
|
foreach (var method in harmony.GetPatchedMethods())
|
||||||
|
{
|
||||||
|
Verse.Log.Message($"[LTS Implants]Patched Method {method.Name}");
|
||||||
|
var patchinfo = Harmony.GetPatchInfo(method);
|
||||||
|
foreach (var VARIABLE in patchinfo.Owners)
|
||||||
|
{
|
||||||
|
Verse.Log.Message("The Method has been patched by:" + VARIABLE);
|
||||||
|
}
|
||||||
|
foreach (var VARIABLE in patchinfo.Prefixes)
|
||||||
|
{
|
||||||
|
Verse.Log.Message("has Prefix:" + VARIABLE.PatchMethod);
|
||||||
|
}
|
||||||
|
foreach (var VARIABLE in patchinfo.Postfixes)
|
||||||
|
{
|
||||||
|
Verse.Log.Message("has Postfix:" + VARIABLE.PatchMethod);
|
||||||
|
}
|
||||||
|
foreach (var VARIABLE in patchinfo.Transpilers)
|
||||||
|
{
|
||||||
|
Verse.Log.Message("has Transpiler:" + VARIABLE.PatchMethod);
|
||||||
|
}
|
||||||
|
Verse.Log.Message("Displaying next method");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,6 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
|
||||||
// set of attributes. Change these attribute values to modify the information
|
|
||||||
// associated with an assembly.
|
|
||||||
[assembly: AssemblyTitle("Implants")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("Implants")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © 2024")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
@ -21,16 +11,3 @@ using System.Runtime.InteropServices;
|
|||||||
|
|
||||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
[assembly: Guid("a5bb73f5-2b73-4464-9585-5553f3695021")]
|
[assembly: Guid("a5bb73f5-2b73-4464-9585-5553f3695021")]
|
||||||
|
|
||||||
// Version information for an assembly consists of the following four values:
|
|
||||||
//
|
|
||||||
// Major Version
|
|
||||||
// Minor Version
|
|
||||||
// Build Number
|
|
||||||
// Revision
|
|
||||||
//
|
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
|
||||||
// by using the '*' as shown below:
|
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
|
||||||
[assembly: AssemblyVersion("1.0.0.0")]
|
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<packages>
|
|
||||||
<package id="Lib.Harmony" version="2.3.3" targetFramework="net472" />
|
|
||||||
</packages>
|
|
Loading…
Reference in New Issue
Block a user