871 lines
27 KiB
Plaintext
871 lines
27 KiB
Plaintext
根据向量相似度分析,与 'PsychicRitualDef' 最相关的代码定义如下:
|
|
|
|
---
|
|
**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\PsychicRitualDef.txt`
|
|
|
|
```csharp
|
|
public class PsychicRitualDef : Def
|
|
{
|
|
public ResearchProjectDef researchPrerequisite;
|
|
|
|
public bool allowsDrafting;
|
|
|
|
public bool allowsFloatMenu;
|
|
|
|
public int cooldownHours;
|
|
|
|
public bool nonRequiredPawnsMayLeave;
|
|
|
|
public float rolePowerFactor = 0.2f;
|
|
|
|
public bool aiCastable;
|
|
|
|
public bool playerCastable = true;
|
|
|
|
public float minThreatPoints;
|
|
|
|
public bool castableOnPocketMaps = true;
|
|
|
|
public List<PlanetLayerDef> layerWhitelist = new List<PlanetLayerDef>();
|
|
|
|
[MustTranslate]
|
|
public string letterAICompleteLabel;
|
|
|
|
[MustTranslate]
|
|
public string letterAICompleteText;
|
|
|
|
[MustTranslate]
|
|
public string letterAIArrivedText;
|
|
|
|
[NoTranslate]
|
|
public string iconPath;
|
|
|
|
public Texture2D uiIcon = BaseContent.BadTex;
|
|
|
|
private List<PsychicRitualRoleDef> rolesBackingList = new List<PsychicRitualRoleDef>(8);
|
|
|
|
private static readonly List<Pawn> tmpPawnsIterationList = new List<Pawn>(16);
|
|
|
|
public virtual List<PsychicRitualRoleDef> Roles
|
|
{
|
|
get
|
|
{
|
|
rolesBackingList.Clear();
|
|
return rolesBackingList;
|
|
}
|
|
}
|
|
|
|
public bool Visible
|
|
{
|
|
get
|
|
{
|
|
if (!playerCastable)
|
|
{
|
|
return false;
|
|
}
|
|
if (DebugSettings.godMode)
|
|
{
|
|
return true;
|
|
}
|
|
if (researchPrerequisite == null)
|
|
{
|
|
return true;
|
|
}
|
|
if (!researchPrerequisite.IsFinished)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public override void PostLoad()
|
|
{
|
|
if (!string.IsNullOrEmpty(iconPath))
|
|
{
|
|
LongEventHandler.ExecuteWhenFinished(delegate
|
|
{
|
|
uiIcon = ContentFinder<Texture2D>.Get(iconPath);
|
|
});
|
|
}
|
|
}
|
|
|
|
public virtual AcceptanceReport AllowsDrafting(Pawn pawn)
|
|
{
|
|
if (allowsDrafting)
|
|
{
|
|
return true;
|
|
}
|
|
return new AcceptanceReport("ParticipatingInPsychicRitual".Translate(pawn, label));
|
|
}
|
|
|
|
public virtual AcceptanceReport AllowsFloatMenu(Pawn pawn)
|
|
{
|
|
if (allowsFloatMenu)
|
|
{
|
|
return true;
|
|
}
|
|
return new AcceptanceReport("ParticipatingInPsychicRitual".Translate(pawn, label));
|
|
}
|
|
|
|
public virtual bool BlocksSocialInteraction(Pawn pawn)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public virtual AcceptanceReport AbilityAllowed(Ability ability)
|
|
{
|
|
return new AcceptanceReport("AbilityDisabledInPsychicRitual".Translate(ability.pawn, label));
|
|
}
|
|
|
|
public virtual PsychicRitualGraph CreateGraph()
|
|
{
|
|
return new PsychicRitualGraph();
|
|
}
|
|
|
|
public virtual List<PsychicRitualToil> CreateToils(PsychicRitual psychicRitual, PsychicRitualGraph parent)
|
|
{
|
|
throw new NotImplementedException("You must subclass PsychicRitualDef and override CreateToils() to return a list of toils.");
|
|
}
|
|
|
|
public virtual PsychicRitualCandidatePool FindCandidatePool()
|
|
{
|
|
return new PsychicRitualCandidatePool(new List<Pawn>(Find.CurrentMap.mapPawns.FreeColonistsAndPrisonersSpawned.Where((Pawn p) => !p.IsSubhuman)), new List<Pawn>());
|
|
}
|
|
|
|
public virtual PsychicRitualRoleAssignments BuildRoleAssignments(TargetInfo target)
|
|
{
|
|
return new PsychicRitualRoleAssignments(Roles, target);
|
|
}
|
|
|
|
public static bool OfferingReachable(Map map, List<Pawn> pawns, IngredientCount offering, out int reachableCount)
|
|
{
|
|
using (new ProfilerBlock("Offering reachable"))
|
|
{
|
|
reachableCount = 0;
|
|
float num = offering.GetBaseCount();
|
|
if (num <= 0f)
|
|
{
|
|
return true;
|
|
}
|
|
List<Thing> list;
|
|
using (new ProfilerBlock("ThingsMatchingFilter"))
|
|
{
|
|
list = map.listerThings.ThingsMatchingFilter(offering.filter);
|
|
}
|
|
foreach (Thing item in list)
|
|
{
|
|
if (num <= 0f)
|
|
{
|
|
break;
|
|
}
|
|
foreach (Pawn pawn in pawns)
|
|
{
|
|
if (pawn.CanReserveAndReach(item, PathEndMode.Touch, pawn.NormalMaxDanger()) && !item.IsForbidden(pawn) && !item.Fogged())
|
|
{
|
|
num -= (float)item.stackCount;
|
|
reachableCount += item.stackCount;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return num <= 0f;
|
|
}
|
|
}
|
|
|
|
public virtual IEnumerable<string> BlockingIssues(PsychicRitualRoleAssignments assignments, Map map)
|
|
{
|
|
return Enumerable.Empty<string>();
|
|
}
|
|
|
|
public virtual TaggedString PsychicRitualBegunMessage(PsychicRitualRoleAssignments assignments)
|
|
{
|
|
return "PsychicRitualBegun".Translate(label);
|
|
}
|
|
|
|
public virtual TaggedString PsychicRitualCompletedMessage()
|
|
{
|
|
return "PsychicRitualCompleted".Translate(label);
|
|
}
|
|
|
|
public virtual TaggedString PsychicRitualCanceledMessage(TaggedString reason)
|
|
{
|
|
if (reason.NullOrEmpty())
|
|
{
|
|
return "PsychicRitualCanceled".Translate(label);
|
|
}
|
|
return "PsychicRitualCanceledBecause".Translate(label, reason);
|
|
}
|
|
|
|
public virtual TaggedString LeftPsychicRitualMessage(Pawn pawn, TaggedString reason)
|
|
{
|
|
if (reason.NullOrEmpty())
|
|
{
|
|
return "PsychicRitualLeft".Translate(pawn, label);
|
|
}
|
|
return "PsychicRitualLeftBecause".Translate(pawn, label, reason);
|
|
}
|
|
|
|
public virtual string GetPawnReport(PsychicRitual psychicRitual, Pawn pawn)
|
|
{
|
|
return "PsychicRitualAttending".Translate(label.Named("RITUALNAME"));
|
|
}
|
|
|
|
public virtual Lord MakeNewLord(PsychicRitualRoleAssignments assignments)
|
|
{
|
|
Lord lord = LordMaker.MakeNewLord(Faction.OfPlayer, new LordJob_PsychicRitual(this, assignments), Find.CurrentMap, assignments.AllAssignedPawns);
|
|
if (assignments.Target.Thing is Building b)
|
|
{
|
|
lord.AddBuilding(b);
|
|
}
|
|
return lord;
|
|
}
|
|
|
|
public virtual bool IsValidTarget(TargetInfo target, out AnyEnum reason)
|
|
{
|
|
reason = AnyEnum.None;
|
|
return true;
|
|
}
|
|
|
|
public virtual TaggedString InvalidTargetReason(AnyEnum reason)
|
|
{
|
|
if (reason == AnyEnum.None)
|
|
{
|
|
return TaggedString.Empty;
|
|
}
|
|
throw new InvalidOperationException("Unknown enum type " + reason.enumType.ToStringSafe() + "; did you forget to override `InvalidTargetReason` in a child class?");
|
|
}
|
|
|
|
public virtual void CalculateMaxPower(PsychicRitualRoleAssignments assignments, List<QualityFactor> powerFactorsOut, out float power)
|
|
{
|
|
power = 0f;
|
|
int num = 0;
|
|
IReadOnlyDictionary<PsychicRitualRoleDef, List<Pawn>> roleAssignments = assignments.RoleAssignments;
|
|
PsychicRitualRoleDef key;
|
|
List<Pawn> value;
|
|
foreach (KeyValuePair<PsychicRitualRoleDef, List<Pawn>> item in roleAssignments)
|
|
{
|
|
item.Deconstruct(out key, out value);
|
|
PsychicRitualRoleDef psychicRitualRoleDef = key;
|
|
List<Pawn> list = value;
|
|
if (psychicRitualRoleDef.applyPowerOffset)
|
|
{
|
|
num += list.Count;
|
|
}
|
|
if (psychicRitualRoleDef.MaxCount != psychicRitualRoleDef.MinCount)
|
|
{
|
|
float num2 = (float)(list.Count - psychicRitualRoleDef.MinCount) / (float)(psychicRitualRoleDef.MaxCount - psychicRitualRoleDef.MinCount);
|
|
power += rolePowerFactor * num2;
|
|
powerFactorsOut?.Add(new QualityFactor
|
|
{
|
|
count = $"{list.Count} / {psychicRitualRoleDef.MaxCount}",
|
|
label = Find.ActiveLanguageWorker.Pluralize(psychicRitualRoleDef.LabelCap),
|
|
positive = (list.Count >= psychicRitualRoleDef.MinCount),
|
|
quality = rolePowerFactor * num2,
|
|
toolTip = psychicRitualRoleDef.description.CapitalizeFirst().EndWithPeriod()
|
|
});
|
|
}
|
|
}
|
|
if (num > 0)
|
|
{
|
|
float num3 = 0f;
|
|
foreach (KeyValuePair<PsychicRitualRoleDef, List<Pawn>> item2 in roleAssignments)
|
|
{
|
|
item2.Deconstruct(out key, out value);
|
|
PsychicRitualRoleDef psychicRitualRoleDef2 = key;
|
|
List<Pawn> list2 = value;
|
|
if (!psychicRitualRoleDef2.applyPowerOffset)
|
|
{
|
|
continue;
|
|
}
|
|
foreach (Pawn item3 in list2)
|
|
{
|
|
num3 += item3.GetStatValue(StatDefOf.PsychicRitualQualityOffset) / (float)num;
|
|
}
|
|
}
|
|
if (!Mathf.Approximately(num3, 0f))
|
|
{
|
|
power += num3;
|
|
powerFactorsOut?.Add(new QualityFactor
|
|
{
|
|
label = "PsychicRitualDef_InvocationCircle_QualityFactor_Ideoligion".Translate(),
|
|
positive = (num3 > 0f),
|
|
count = num3.ToStringPercent(),
|
|
quality = num3,
|
|
toolTip = "PsychicRitualDef_InvocationCircle_QualityFactor_Ideoligion_Tooltip".Translate()
|
|
});
|
|
}
|
|
}
|
|
power = Mathf.Clamp01(power);
|
|
}
|
|
|
|
public virtual void RemoveIncapablePawns(PsychicRitual psychicRitual)
|
|
{
|
|
foreach (var (psychicRitualRoleDef2, collection) in psychicRitual.assignments.RoleAssignments)
|
|
{
|
|
tmpPawnsIterationList.Clear();
|
|
tmpPawnsIterationList.AddRange(collection);
|
|
foreach (Pawn tmpPawnsIteration in tmpPawnsIterationList)
|
|
{
|
|
if (!psychicRitualRoleDef2.PawnCanDo(PsychicRitualRoleDef.Context.Runtime, tmpPawnsIteration, psychicRitual.assignments.Target, out var reason) && psychicRitual.LeaveOrCancelPsychicRitual(psychicRitualRoleDef2, tmpPawnsIteration, reason.ToPlayerReadable()) == PsychicRitual.LeftOrCanceled.Canceled)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public virtual void CheckPsychicRitualCancelConditions(PsychicRitual psychicRitual)
|
|
{
|
|
TargetInfo target = psychicRitual.assignments.Target;
|
|
if (target.ThingDestroyed)
|
|
{
|
|
psychicRitual.CancelPsychicRitual("PsychicRitualDef_TargetDestroyed".Translate(target.Thing.Named("TARGET")));
|
|
}
|
|
}
|
|
|
|
public virtual TaggedString OutcomeDescription(FloatRange qualityRange, string qualityNumber, PsychicRitualRoleAssignments assignments)
|
|
{
|
|
return TaggedString.Empty;
|
|
}
|
|
|
|
public virtual IEnumerable<TaggedString> OutcomeWarnings(PsychicRitualRoleAssignments assignments)
|
|
{
|
|
return Enumerable.Empty<TaggedString>();
|
|
}
|
|
|
|
public virtual TaggedString TimeAndOfferingLabel()
|
|
{
|
|
return TaggedString.Empty;
|
|
}
|
|
|
|
public virtual void InitializeCast(Map map)
|
|
{
|
|
}
|
|
|
|
public virtual IntVec3 GetBestStandableRolePosition(bool playerRitual, IntVec3 origin, IntVec3 ritualPosition, Map map, float radius = 8f)
|
|
{
|
|
if (playerRitual)
|
|
{
|
|
return origin;
|
|
}
|
|
IntVec3 result = CellFinder.StandableCellNear(origin, map, radius, (IntVec3 c) => map.reachability.CanReach(ritualPosition, c, PathEndMode.OnCell, TraverseMode.NoPassClosedDoorsOrWater));
|
|
if (result.IsValid)
|
|
{
|
|
return result;
|
|
}
|
|
return origin;
|
|
}
|
|
|
|
public virtual IEnumerable<string> GetPawnTooltipExtras(Pawn pawn)
|
|
{
|
|
yield break;
|
|
}
|
|
}
|
|
```
|
|
---
|
|
**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\PsychicRitualDef_NeurosisPulse.txt`
|
|
**相似度:** 0.7397
|
|
|
|
```csharp
|
|
public class PsychicRitualDef_NeurosisPulse : PsychicRitualDef_InvocationCircle
|
|
{
|
|
public SimpleCurve durationDaysFromQualityCurve;
|
|
|
|
public override List<PsychicRitualToil> CreateToils(PsychicRitual psychicRitual, PsychicRitualGraph graph)
|
|
{
|
|
List<PsychicRitualToil> list = base.CreateToils(psychicRitual, graph);
|
|
list.Add(new PsychicRitualToil_NeurosisPulse(InvokerRole));
|
|
return list;
|
|
}
|
|
|
|
public override TaggedString OutcomeDescription(FloatRange qualityRange, string qualityNumber, PsychicRitualRoleAssignments assignments)
|
|
{
|
|
return outcomeDescription.Formatted(Mathf.FloorToInt(durationDaysFromQualityCurve.Evaluate(qualityRange.min) * 60000f).ToStringTicksToDays());
|
|
}
|
|
}
|
|
```
|
|
---
|
|
**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\PsychicRitualDef_Psychophagy.txt`
|
|
**相似度:** 0.7324
|
|
|
|
```csharp
|
|
public class PsychicRitualDef_Psychophagy : PsychicRitualDef_InvocationCircle
|
|
{
|
|
public FloatRange brainDamageRange;
|
|
|
|
public SimpleCurve effectDurationDaysFromQualityCurve;
|
|
|
|
public override List<PsychicRitualToil> CreateToils(PsychicRitual psychicRitual, PsychicRitualGraph parent)
|
|
{
|
|
List<PsychicRitualToil> list = base.CreateToils(psychicRitual, parent);
|
|
list.Add(new PsychicRitualToil_Psychophagy(InvokerRole, TargetRole, brainDamageRange));
|
|
list.Add(new PsychicRitualToil_TargetCleanup(InvokerRole, TargetRole));
|
|
return list;
|
|
}
|
|
|
|
public override TaggedString OutcomeDescription(FloatRange qualityRange, string qualityNumber, PsychicRitualRoleAssignments assignments)
|
|
{
|
|
string text = Mathf.FloorToInt(effectDurationDaysFromQualityCurve.Evaluate(qualityRange.min) * 60000f).ToStringTicksToDays();
|
|
IntRange disappearsAfterTicks = HediffDefOf.DarkPsychicShock.CompProps<HediffCompProperties_Disappears>().disappearsAfterTicks;
|
|
FloatRange floatRange = new FloatRange(Mathf.FloorToInt(disappearsAfterTicks.min.TicksToDays()), Mathf.FloorToInt(disappearsAfterTicks.max.TicksToDays()));
|
|
return outcomeDescription.Formatted(text, floatRange.ToString(), brainDamageRange.ToString());
|
|
}
|
|
}
|
|
```
|
|
---
|
|
**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse.AI.Group\PsychicRitualToil_PleasurePulse.txt`
|
|
**相似度:** 0.7237
|
|
|
|
```csharp
|
|
public class PsychicRitualToil_PleasurePulse : PsychicRitualToil
|
|
{
|
|
private PsychicRitualRoleDef invokerRole;
|
|
|
|
protected PsychicRitualToil_PleasurePulse()
|
|
{
|
|
}
|
|
|
|
public PsychicRitualToil_PleasurePulse(PsychicRitualRoleDef invokerRole)
|
|
{
|
|
this.invokerRole = invokerRole;
|
|
}
|
|
|
|
public override void Start(PsychicRitual psychicRitual, PsychicRitualGraph parent)
|
|
{
|
|
base.Start(psychicRitual, parent);
|
|
Pawn pawn = psychicRitual.assignments.FirstAssignedPawn(invokerRole);
|
|
float duration = ((PsychicRitualDef_PleasurePulse)psychicRitual.def).durationDaysFromQualityCurve.Evaluate(psychicRitual.PowerPercent);
|
|
psychicRitual.ReleaseAllPawnsAndBuildings();
|
|
if (pawn != null)
|
|
{
|
|
ApplyOutcome(psychicRitual, pawn, duration);
|
|
}
|
|
}
|
|
|
|
private void ApplyOutcome(PsychicRitual psychicRitual, Pawn invoker, float duration)
|
|
{
|
|
foreach (Pawn item in invoker.Map.mapPawns.AllHumanlikeSpawned)
|
|
{
|
|
if (!(item.GetStatValue(StatDefOf.PsychicSensitivity) <= 0f))
|
|
{
|
|
Hediff firstHediffOfDef = item.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.NeurosisPulse);
|
|
if (firstHediffOfDef != null)
|
|
{
|
|
item.health.RemoveHediff(firstHediffOfDef);
|
|
}
|
|
Hediff hediff = HediffMaker.MakeHediff(HediffDefOf.PleasurePulse, item);
|
|
HediffComp_Disappears hediffComp_Disappears = hediff.TryGetComp<HediffComp_Disappears>();
|
|
if (hediffComp_Disappears != null)
|
|
{
|
|
hediffComp_Disappears.ticksToDisappear = Mathf.RoundToInt(duration * 60000f);
|
|
}
|
|
item.health.AddHediff(hediff);
|
|
}
|
|
}
|
|
Find.LetterStack.ReceiveLetter("PsychicRitualCompleteLabel".Translate(psychicRitual.def.label), "PleasurePulseCompleteText".Translate(invoker, Mathf.FloorToInt(duration * 60000f).ToStringTicksToDays(), psychicRitual.def.Named("RITUAL")), LetterDefOf.NeutralEvent);
|
|
}
|
|
|
|
public override void ExposeData()
|
|
{
|
|
base.ExposeData();
|
|
Scribe_Defs.Look(ref invokerRole, "invokerRole");
|
|
}
|
|
}
|
|
```
|
|
---
|
|
**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\PsychicRitualDef_InvocationCircle.txt`
|
|
**相似度:** 0.7220
|
|
|
|
```csharp
|
|
public class PsychicRitualDef_InvocationCircle : PsychicRitualDef
|
|
{
|
|
public enum InvalidTargetReasonEnum
|
|
{
|
|
None,
|
|
AreaNotClear
|
|
}
|
|
|
|
private class RitualQualityOffsetCount
|
|
{
|
|
public float offset;
|
|
|
|
public int count;
|
|
|
|
public RitualQualityOffsetCount(int count, float offset)
|
|
{
|
|
this.count = count;
|
|
this.offset = offset;
|
|
}
|
|
}
|
|
|
|
public FloatRange hoursUntilHoraxEffect;
|
|
|
|
public FloatRange hoursUntilOutcome;
|
|
|
|
public float invocationCircleRadius = 3.9f;
|
|
|
|
[MustTranslate]
|
|
public string outcomeDescription;
|
|
|
|
public float psychicSensitivityPowerFactor = 0.25f;
|
|
|
|
protected PsychicRitualRoleDef invokerRole;
|
|
|
|
protected PsychicRitualRoleDef chanterRole;
|
|
|
|
protected PsychicRitualRoleDef targetRole;
|
|
|
|
protected PsychicRitualRoleDef defenderRole;
|
|
|
|
protected IngredientCount requiredOffering;
|
|
|
|
protected string timeAndOfferingLabelCached;
|
|
|
|
public static readonly SimpleCurve PsychicSensitivityToPowerFactor = new SimpleCurve
|
|
{
|
|
new CurvePoint(0f, 0f),
|
|
new CurvePoint(1f, 0.5f),
|
|
new CurvePoint(2f, 0.9f),
|
|
new CurvePoint(3f, 1f)
|
|
};
|
|
|
|
protected const int DurationTicksWaitPostEffect = 120;
|
|
|
|
private static Dictionary<PsychicRitualRoleDef, List<IntVec3>> tmpParticipants = new Dictionary<PsychicRitualRoleDef, List<IntVec3>>(8);
|
|
|
|
private List<Pawn> tmpGatheringPawns = new List<Pawn>(8);
|
|
|
|
public virtual PsychicRitualRoleDef InvokerRole => invokerRole;
|
|
|
|
public virtual PsychicRitualRoleDef ChanterRole => chanterRole;
|
|
|
|
public virtual PsychicRitualRoleDef TargetRole => targetRole;
|
|
|
|
public virtual PsychicRitualRoleDef DefenderRole => defenderRole;
|
|
|
|
public virtual IngredientCount RequiredOffering => requiredOffering;
|
|
|
|
public TaggedString CooldownLabel => "PsychicRitualCooldownLabel".Translate() + ": " + (cooldownHours * 2500).ToStringTicksToPeriod();
|
|
|
|
public override List<PsychicRitualRoleDef> Roles
|
|
{
|
|
get
|
|
{
|
|
List<PsychicRitualRoleDef> roles = base.Roles;
|
|
if (InvokerRole != null)
|
|
{
|
|
roles.Add(InvokerRole);
|
|
}
|
|
if (TargetRole != null)
|
|
{
|
|
roles.Add(TargetRole);
|
|
}
|
|
if (ChanterRole != null)
|
|
{
|
|
roles.Add(ChanterRole);
|
|
}
|
|
if (DefenderRole != null)
|
|
{
|
|
roles.Add(DefenderRole);
|
|
}
|
|
return roles;
|
|
}
|
|
}
|
|
|
|
public override void ResolveReferences()
|
|
{
|
|
base.ResolveReferences();
|
|
requiredOffering?.ResolveReferences();
|
|
invokerRole = invokerRole ?? PsychicRitualRoleDefOf.Invoker;
|
|
chanterRole = chanterRole ?? PsychicRitualRoleDefOf.Chanter;
|
|
}
|
|
|
|
public override List<PsychicRitualToil> CreateToils(PsychicRitual psychicRitual, PsychicRitualGraph parent)
|
|
{
|
|
float randomInRange = hoursUntilOutcome.RandomInRange;
|
|
IReadOnlyDictionary<PsychicRitualRoleDef, List<IntVec3>> readOnlyDictionary = GenerateRolePositions(psychicRitual.assignments);
|
|
return new List<PsychicRitualToil>
|
|
{
|
|
new PsychicRitualToil_GatherForInvocation(psychicRitual, this, readOnlyDictionary),
|
|
new PsychicRitualToil_InvokeHorax(InvokerRole, readOnlyDictionary.TryGetValue(InvokerRole), TargetRole, readOnlyDictionary.TryGetValue(TargetRole), ChanterRole, readOnlyDictionary.TryGetValue(ChanterRole), DefenderRole, readOnlyDictionary.TryGetValue(DefenderRole), RequiredOffering)
|
|
{
|
|
hoursUntilHoraxEffect = hoursUntilHoraxEffect.RandomInRange,
|
|
hoursUntilOutcome = randomInRange
|
|
},
|
|
new PsychicRitualToil_Wait(120)
|
|
};
|
|
}
|
|
|
|
public override bool IsValidTarget(TargetInfo target, out AnyEnum reason)
|
|
{
|
|
foreach (IntVec3 item in GenRadial.RadialCellsAround(target.Cell, invocationCircleRadius, useCenter: true))
|
|
{
|
|
if (!item.Standable(target.Map))
|
|
{
|
|
reason = AnyEnum.FromEnum(InvalidTargetReasonEnum.AreaNotClear);
|
|
return false;
|
|
}
|
|
}
|
|
reason = AnyEnum.None;
|
|
return true;
|
|
}
|
|
|
|
public override TaggedString InvalidTargetReason(AnyEnum reason)
|
|
{
|
|
InvalidTargetReasonEnum? invalidTargetReasonEnum = reason.As<InvalidTargetReasonEnum>();
|
|
if (invalidTargetReasonEnum.HasValue)
|
|
{
|
|
InvalidTargetReasonEnum valueOrDefault = invalidTargetReasonEnum.GetValueOrDefault();
|
|
return valueOrDefault switch
|
|
{
|
|
InvalidTargetReasonEnum.None => TaggedString.Empty,
|
|
InvalidTargetReasonEnum.AreaNotClear => "PsychicRitualDef_InvocationCircle_AreaMustBeClear".Translate(),
|
|
_ => throw new InvalidOperationException($"Unknown reason {valueOrDefault}"),
|
|
};
|
|
}
|
|
return base.InvalidTargetReason(reason);
|
|
}
|
|
|
|
public override TaggedString OutcomeDescription(FloatRange qualityRange, string qualityNumber, PsychicRitualRoleAssignments assignments)
|
|
{
|
|
return outcomeDescription.Formatted();
|
|
}
|
|
|
|
public override IEnumerable<TaggedString> OutcomeWarnings(PsychicRitualRoleAssignments assignments)
|
|
{
|
|
foreach (Pawn item in assignments.AssignedPawns(TargetRole))
|
|
{
|
|
if (item.HomeFaction != null && item.HomeFaction != Faction.OfPlayer && item.HomeFaction.def.humanlikeFaction && !item.HomeFaction.def.PermanentlyHostileTo(FactionDefOf.PlayerColony) && !item.HomeFaction.temporary && !item.HomeFaction.Hidden)
|
|
{
|
|
yield return "PsychicRitualFactionWarning".Translate(item.Named("PAWN"), item.HomeFaction.Named("FACTION")).Colorize(ColoredText.WarningColor);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override TaggedString TimeAndOfferingLabel()
|
|
{
|
|
if (timeAndOfferingLabelCached != null)
|
|
{
|
|
return timeAndOfferingLabelCached;
|
|
}
|
|
StringBuilder stringBuilder = new StringBuilder();
|
|
stringBuilder.AppendLine(DurationLabel());
|
|
stringBuilder.Append(CooldownLabel);
|
|
if (!OfferingLabel().NullOrEmpty())
|
|
{
|
|
stringBuilder.AppendLine();
|
|
stringBuilder.Append(OfferingLabel());
|
|
}
|
|
timeAndOfferingLabelCached = stringBuilder.ToString();
|
|
return timeAndOfferingLabelCached;
|
|
}
|
|
|
|
private TaggedString OfferingLabel()
|
|
{
|
|
StringBuilder stringBuilder = new StringBuilder();
|
|
if (RequiredOffering != null)
|
|
{
|
|
stringBuilder.Append("PsychicRitualRequiredOffering".Translate().CapitalizeFirst());
|
|
stringBuilder.Append(": ");
|
|
stringBuilder.Append(RequiredOffering.SummaryFilterFirst);
|
|
}
|
|
return stringBuilder.ToString();
|
|
}
|
|
|
|
public TaggedString DurationLabel()
|
|
{
|
|
string value = ((int)(hoursUntilOutcome.Average * 2500f)).ToStringTicksToPeriod();
|
|
TaggedString taggedString = ((hoursUntilOutcome.min != hoursUntilOutcome.max) ? "ExpectedLordJobDuration".Translate().CapitalizeFirst() : "PsychicRitualExpectedDurationLabel".Translate().CapitalizeFirst());
|
|
StringBuilder stringBuilder = new StringBuilder();
|
|
stringBuilder.Append(taggedString);
|
|
stringBuilder.Append(": ");
|
|
stringBuilder.Append(value);
|
|
return stringBuilder.ToString();
|
|
}
|
|
|
|
private IReadOnlyDictionary<PsychicRitualRoleDef, List<IntVec3>> GenerateRolePositions(PsychicRitualRoleAssignments assignments)
|
|
{
|
|
tmpParticipants.ClearAndPoolValueLists();
|
|
foreach (PsychicRitualRoleDef role in Roles)
|
|
{
|
|
tmpParticipants[role] = SimplePool<List<IntVec3>>.Get();
|
|
}
|
|
int num = assignments.RoleAssignedCount(ChanterRole) + assignments.RoleAssignedCount(InvokerRole);
|
|
int num2 = 0;
|
|
foreach (Pawn item in assignments.AssignedPawns(InvokerRole))
|
|
{
|
|
_ = item;
|
|
int num3 = 0;
|
|
IntVec3 cell;
|
|
do
|
|
{
|
|
cell = assignments.Target.Cell;
|
|
cell += IntVec3.FromPolar(360f * (float)num2++ / (float)num, invocationCircleRadius);
|
|
}
|
|
while (!cell.Walkable(assignments.Target.Map) && num3++ <= 10);
|
|
if (num3 >= 10)
|
|
{
|
|
cell = assignments.Target.Cell;
|
|
}
|
|
tmpParticipants[InvokerRole].Add(cell);
|
|
}
|
|
foreach (Pawn item2 in assignments.AssignedPawns(ChanterRole))
|
|
{
|
|
_ = item2;
|
|
IntVec3 cell2 = assignments.Target.Cell;
|
|
cell2 += IntVec3.FromPolar(360f * (float)num2++ / (float)num, invocationCircleRadius);
|
|
tmpParticipants[ChanterRole].Add(cell2);
|
|
}
|
|
foreach (Pawn item3 in assignments.AssignedPawns(TargetRole))
|
|
{
|
|
_ = item3;
|
|
tmpParticipants[TargetRole].Add(assignments.Target.Cell);
|
|
}
|
|
if (DefenderRole != null)
|
|
{
|
|
num2 = 0;
|
|
int num4 = assignments.RoleAssignedCount(DefenderRole);
|
|
bool playerRitual = assignments.AllAssignedPawns.Any((Pawn x) => x.Faction == Faction.OfPlayer);
|
|
foreach (Pawn item4 in assignments.AssignedPawns(DefenderRole))
|
|
{
|
|
_ = item4;
|
|
IntVec3 cell3 = assignments.Target.Cell;
|
|
cell3 += IntVec3.FromPolar(360f * (float)num2++ / (float)num4, invocationCircleRadius + 5f);
|
|
cell3 = GetBestStandableRolePosition(playerRitual, cell3, assignments.Target.Cell, assignments.Target.Map);
|
|
tmpParticipants[DefenderRole].Add(cell3);
|
|
}
|
|
}
|
|
return tmpParticipants;
|
|
}
|
|
|
|
public override IEnumerable<string> BlockingIssues(PsychicRitualRoleAssignments assignments, Map map)
|
|
{
|
|
using (new ProfilerBlock("PsychicRitualDef.BlockingIssues"))
|
|
{
|
|
tmpGatheringPawns.Clear();
|
|
foreach (var (psychicRitualRoleDef2, collection) in assignments.RoleAssignments)
|
|
{
|
|
if (psychicRitualRoleDef2.CanHandleOfferings)
|
|
{
|
|
tmpGatheringPawns.AddRange(collection);
|
|
}
|
|
}
|
|
tmpGatheringPawns.RemoveAll(map, (Map _map, Pawn _pawn) => _pawn.MapHeld != _map);
|
|
if (TargetRole != null && InvokerRole != null)
|
|
{
|
|
Pawn pawn = assignments.FirstAssignedPawn(TargetRole);
|
|
if (pawn != null)
|
|
{
|
|
Pawn pawn2 = assignments.FirstAssignedPawn(InvokerRole);
|
|
if (pawn2 != null && pawn.IsPrisoner && !map.reachability.CanReach(assignments.Target.Cell, pawn.PositionHeld, PathEndMode.Touch, TraverseParms.For(pawn2)))
|
|
{
|
|
yield return "PsychicRitualTargetUnreachableByInvoker".Translate(pawn.Named("TARGET"), pawn2.Named("INVOKER"));
|
|
}
|
|
}
|
|
}
|
|
if (RequiredOffering != null && !PsychicRitualDef.OfferingReachable(map, tmpGatheringPawns, RequiredOffering, out var reachableCount))
|
|
{
|
|
yield return "PsychicRitualOfferingsInsufficient".Translate(RequiredOffering.SummaryFilterFirst, reachableCount);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void CalculateMaxPower(PsychicRitualRoleAssignments assignments, List<QualityFactor> powerFactorsOut, out float power)
|
|
{
|
|
power = 0f;
|
|
foreach (Pawn item in assignments.AssignedPawns(InvokerRole))
|
|
{
|
|
float statValue = item.GetStatValue(StatDefOf.PsychicSensitivity);
|
|
float num = PsychicSensitivityToPowerFactor.Evaluate(statValue);
|
|
num *= psychicSensitivityPowerFactor;
|
|
powerFactorsOut?.Add(new QualityFactor
|
|
{
|
|
label = "PsychicRitualDef_InvocationCircle_QualityFactor_PsychicSensitivity".Translate(item.Named("PAWN")),
|
|
positive = (statValue >= 1f),
|
|
count = statValue.ToStringPercent(),
|
|
quality = num,
|
|
toolTip = "PsychicRitualDef_InvocationCircle_QualityFactor_PsychicSensitivity_Tooltip".Translate(item.Named("PAWN"))
|
|
});
|
|
power += num;
|
|
}
|
|
base.CalculateMaxPower(assignments, powerFactorsOut, out var power2);
|
|
power += power2;
|
|
if (assignments.Target.Thing is Building building)
|
|
{
|
|
CalculateFacilityQualityOffset(powerFactorsOut, ref power, building);
|
|
}
|
|
power = Mathf.Clamp01(power);
|
|
}
|
|
|
|
private static void CalculateFacilityQualityOffset(List<QualityFactor> powerFactorsOut, ref float power, Building building)
|
|
{
|
|
Dictionary<ThingDef, RitualQualityOffsetCount> dictionary = new Dictionary<ThingDef, RitualQualityOffsetCount>();
|
|
List<Thing> linkedFacilitiesListForReading = building.GetComp<CompAffectedByFacilities>().LinkedFacilitiesListForReading;
|
|
for (int i = 0; i < linkedFacilitiesListForReading.Count; i++)
|
|
{
|
|
Thing thing = linkedFacilitiesListForReading[i];
|
|
CompFacility compFacility = thing.TryGetComp<CompFacility>();
|
|
if (compFacility?.StatOffsets == null)
|
|
{
|
|
continue;
|
|
}
|
|
for (int j = 0; j < compFacility.StatOffsets.Count; j++)
|
|
{
|
|
StatModifier statModifier = compFacility.StatOffsets[j];
|
|
if (statModifier.stat == StatDefOf.PsychicRitualQuality)
|
|
{
|
|
if (dictionary.TryGetValue(thing.def, out var value))
|
|
{
|
|
value.count++;
|
|
value.offset += statModifier.value;
|
|
}
|
|
else
|
|
{
|
|
dictionary.Add(thing.def, new RitualQualityOffsetCount(1, statModifier.value));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
foreach (KeyValuePair<ThingDef, RitualQualityOffsetCount> item in dictionary)
|
|
{
|
|
powerFactorsOut?.Add(new QualityFactor
|
|
{
|
|
label = Find.ActiveLanguageWorker.Pluralize(item.Key.label).CapitalizeFirst(),
|
|
positive = true,
|
|
count = item.Value.count + " / " + item.Key.GetCompProperties<CompProperties_Facility>().maxSimultaneous,
|
|
quality = item.Value.offset,
|
|
toolTip = "PsychicRitualDef_InvocationCircle_QualityFactor_Increase_Tooltip".Translate().CapitalizeFirst().EndWithPeriod()
|
|
});
|
|
power += item.Value.offset;
|
|
}
|
|
}
|
|
|
|
public override IEnumerable<StatDrawEntry> SpecialDisplayStats(StatRequest req)
|
|
{
|
|
foreach (StatDrawEntry item in base.SpecialDisplayStats(req))
|
|
{
|
|
yield return item;
|
|
}
|
|
if (requiredOffering != null)
|
|
{
|
|
yield return new StatDrawEntry(StatCategoryDefOf.PsychicRituals, "StatsReport_Offering".Translate(), requiredOffering.SummaryFilterFirst, "StatsReport_Offering_Desc".Translate(), 1000);
|
|
}
|
|
yield return new StatDrawEntry(StatCategoryDefOf.PsychicRituals, "StatsReport_RitualDuration".Translate(), Mathf.FloorToInt(hoursUntilOutcome.min * 2500f).ToStringTicksToPeriod(), "StatsReport_RitualDuration_Desc".Translate(), 500);
|
|
yield return new StatDrawEntry(StatCategoryDefOf.PsychicRituals, "StatsReport_RitualCooldown".Translate(), (cooldownHours * 2500).ToStringTicksToPeriod(), "StatsReport_RitualCooldown_Desc".Translate(), 100);
|
|
}
|
|
|
|
public override void CheckPsychicRitualCancelConditions(PsychicRitual psychicRitual)
|
|
{
|
|
base.CheckPsychicRitualCancelConditions(psychicRitual);
|
|
if (!psychicRitual.canceled && invokerRole != null)
|
|
{
|
|
Pawn pawn = psychicRitual.assignments.FirstAssignedPawn(InvokerRole);
|
|
if (pawn != null && pawn.DeadOrDowned)
|
|
{
|
|
psychicRitual.CancelPsychicRitual("PsychicRitualDef_InvocationCircle_InvokerLost".Translate(pawn.Named("PAWN")));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
``` |