User talk:Hautarche

Jump to navigation Jump to search

About this board

I (Hauts) don't know where else to do this, so I've been using this section to write out the justifications for edits I make to the front-facing wiki pages.

Trait miscellanies that accompanied formatting changes

4
Hautarche (talkcontribs)

TODOs: go over creepjoiner section, copy the Pyromaniac info to the relevant documents if that hasn't been done by someone else already, note down the 'starting possessions', and satisfy the request for info on genes that affect traits.

Most of the recent round of changes pertained to more consistent formatting or templatization of moodlets. I could not find a template for opinion thoughts - is there one? Also, other question, what is the correct front-facing formatting for thoughts with dynamic labels e.g. "Jealous of otherPersonName's bedroom" or "Wearing human leather apparelLabel"?

"Xenogenes count as one artificial body part" had to be noted down because the traits page was formerly ambiguous about this. You can figure this out pretty quickly by testing, and the relevant C# function is GeneUtility.AddedAndImplantedPartsWithXenogenesCount. Generally, several other non-formatting changes were also made to reduce ambiguity; an example also pertinent to Body Modders and Purists is the opinion of others based on their artificial parts/xenogenes, which did not specify how the opinion scaled with number of parts/xenogenes.

Body Purist luciferium stuff was sourced by testing.

Ascetic mood lessens as bedroom quality increases - observed via testing. Greedy was also observed purely via testing.

The 'Room stats#Levels of impressiveness' simply redirected to the Rooms page, so I replaced it with a more correct link 'Rooms#Impressiveness'.

All the new stuff for Pyromaniac was verified via testing. "Has incendiary weapon" technically triggers for any equipped weapon that meets one of the following criteria:

  • Is melee and deals extra flame damage (plasmasword and persona version)
  • Fires a projectile with the <ai_IsIncendiary> field set to true in its <projectile> field (this is true for all launchers, despite several of them logically not being incendiary weapons)
  • Fires a beam whose verb has true <ai_BeamIsIncendiary> in its props (no examples usable by colonists)
  • Grants any ability which has true <ai_IsIncendiary> (hellcat, incinerator)

However, that last point is conspicuously absent in the method Pawn.UpdatePyroVerbThought, which is the sole source of the "used flame weapon" thought. Does it make any sense that an EMP launcher is for this purpose an incendiary weapon and the INCINERATOR - a weapon that shoots GLORIOUS FIRE over a WIDE SWATHE OF TERRAIN - is not? No. But this is the world we live in. EDIT: incinerator's normal attack triggers it due to being a "beam" weapon - it's only the ability that doesn't. Hellcat rifle is still exempted

Bloodlust was just severely outdated. I checked the values involved, they were almost all wrong. Also, Bloodlust doesn't just trigger off of strangers, easily verifiable via testing (I had my test Bloodluster punch a colonist she crashlanded with to death, and let her watch the other crashlander get gunned down). We were also missing an organ harvesting mood bonus.

Food poisoning chance for eating corpses was removed from the Cannibal section because it misleadingly implies an inviolable rule that can be circumvented with the Strong Stomach gene.

Perfect Memory was duplicated, in a normal-people traits section and a creepjoiner section, misleadingly implying availability to regular humanlikes.

Tortured Artist is a trait I know *very* well, since it was the inspiration the second trait I ever modded into the game back in late 2022. I just forgot to put in the "mood-induced" clause here for some reason? If you want to test it, tweak TA's <mentalBreakInspirationGainChance> field to >=1 so that it should ALWAYS proc. The relevant code path is MentalState.RecoverFromState -> Trait.Notify_MentalStateEndedOn -> another method with the same name which it calls if and only if the 'causedByMood' bool (passed down by the mental state) is true.

Abrasive "2.3x" was NOT derived from testing/observation, but from the RandomSelectionWeight for slight's and insult's InteractionWorker. Both multiply the base chance by a method called NegativeInteractionUtility.NegativeInteractionChanceFactor, which multiplies the result by 2.3f if the prospective initiator is Abrasive.

Kind Words weighting similarly obtained via looking at the RandomSelectionWeight for kind words: 0 if inhumanized or lacking the non-suppressed Kind trait, 0.01 otherwise.

The "Specific value not listed in flavor text." annotation in the Base Mood traits section was removed due to its redundancy and lack of importance. It's true for any and every moodlet in the game I can think of, so it did not need to appear for just these four traits.

Sickly's random diseases work via a field called <randomDiseaseMtbDays>, which is only referenced by Pawn_HealthTracker.HealthTick. When the MTB that this field gates triggers, it finds the biome the pawn is currently in (or gets a random biome if somehow the pawn isn't in a biome), gets all incident defs of the DiseaseHuman category, and picks one weighted on their evaluations by the biome's BiomeDef.CommonalityOfDisease method. It then applies this incident specifically to the Sickly pawn.

Hautarche (talkcontribs)

Saw the request to re-institute some of the things from the huge change that got reverted a while back, including the gene table. I tried my hand at adding it back. It makes sense for it to be described after the traits are described, but I don't know if it's currently in the best position. Maybe it should be before the obsolete traits?

GeneDefs have both a <forcedTraits> field and a <suppressedTraits> field. These do exactly what their names indicate. Six traits use forcedTraits, but Pyrophobia is the sole user of suppressedTraits. The former six were covered by the prior gene table; the latter was not, I think, but is just as important to note here.

The trait un/suppression shenanigans arise from both modding experience with the gene system, experience with heavily modded playthroughs, and verification just now in a modless testing environment. Take three test pawns:

  • A Baseliner with the psychically sensitive or psychically hypersensitive trait
  • A Yttakin with the same trait
  • Another Yttakin with the same trait

Set the xenotype of each to a Hussar via dev tools (which will populate their xenogenes with the Hussar genes) or otherwise find a way to add the psychically deaf gene to each of them. Then set the xenotype of each to a Baseliner via dev tools (which will remove all of their xenogenes, but leave their endogenes untouched, which is an important detail because Yttakin genes are endogenous) or otherwise find a way to remove the psychically deaf gene from each of them.

This "issue" occurs a lot more in playthroughs with mods that add more trait-forcing genes - the one I wrote into the Traits page is essentially the only way this issue occurs in an unmodded game, since only the Psychically Deaf and Psychically Dull genes suppress each other and the same set of traits.

Hautarche (talkcontribs)

Info for trait mechanics section sourced from PawnGenerator.GenerateTraits, which is as the name indicates how pawns get their traits (aside from growth moments and forced trait custom scenario parts). The "traits from quests" step is actually more flexible than indicated: this is where the "ForcedTraits" parameter of the pawn generation request is processed, it's just that this parameter is only ever used for quests' forced traits in unmodded games.

I could not provide examples for certain steps because no examples exist for those steps using only unmodded content. As an example, a randomly assigned trait can't be 'Any that would disable a work type required by the pawn's "pawn kind"', but Pyromaniac is the only trait that disables a work tag (Firefighting) and there are no pawn kinds that require Firefighting.

Some assertions are easily testable (e.g. if you use dev mode to spawn mechanitor babies, they will have the Recluse trait despite being too young to ordinarily have traits), but others are not (e.g. the 500 tries thing, although I've discovered you CAN test it on accident: simply give a trait an incapability for Violence and eventually you'll get error logs that attest to 500 tries per trait slot). Again, the source for this info is PawnGenerator.GenerateTraits.

Hautarche (talkcontribs)

Okay, that's all the info that needs to be in the traits page, I think.

Starting possessions order of operations is sourced from StartingPawnUtility.GeneratePossessions. Since it occurs in a linear fashion and traits are the second-to-last step, most of the order of operations are pertinent to the Traits page. Ideally, however, most of this information would go to a page actually describing the starting pawn selection process... which does not exist as far as I can tell. Once it is created, I think most of this info should go there, and at most the Traits page will only need an abbreviated summary and/or link alluding to it. Possibly, even the info on which starting possessions each trait has can be relegated to that page, rather than awkwardly crowding out the trait tables with something that's basically trivia.

Reply to "Trait miscellanies that accompanied formatting changes"
Hautarche (talkcontribs)

The stub I removed read "Production specialist order of operation with worked example iedeallwnith produl soec, GWS>1, and sight and manip change". In reverse order:

The listed sight and manipulation values are correct for the latest publicly available version of RimWorld. Assuming "GWS" means "Global Work Speed"... I still have no clue what this shorthand is supposed to mean. Construction Speed is straightforwardly multiplied by Global Work Speed, with no caps, curves, lerping, or any other shenanigans affecting it. I have no clue what "iedeallwnith produl soec" is, but similar "order of operation" requests in other stats make me think this is a request to clarify the order in which the offsets and factors resolve to determine the final stat value. There is apparently already a page that discusses this, so I dunno why there has to be discussion about order of operations, but here it is anyways as true for most^$ stats in the game:

0) start with the stat's defaultBaseValue, or if the requester (the pawn in this case) has a different default, use that instead

1) sum all offsets (except any from stuff-made-from, ThingComps, or the current inspiration). While there is technically an order in which this occurs (skills, health capacities, traits, hediffs, precepts, ideoligious role, genes, current life stage, apparel, wielded equipment), summing in any order obviously results in the same result.

2a) multiply by each of the following factors: traits, hediffs, precepts, ideoligious role, genes, current life stage, stuff made from & quality

2b) add offset from stuff-made-from & quality

2c) depends on if we're determining an ability's stat (in which case multiply by the any of the stat's statFactors that the AbilityDef has, then any that the caster pawn's precepts have) or a thing's, which is the case here as pawns are Things...

  • add each ThingComp's offsets for this stat
  • multiply by each ThingComp's factors
  • multiply by any of this stat's statFactors the Thing has
  • if a pawn, multiply by each of the stat's skillNeedFactors
  • if a pawn, multiply by each of the stat's capacityFactors
  • if a pawn, add any offset from the current inspiration
  • if a pawn, multiply by any factor from the current inspiration

3) perform the TransformValue operation of each of the stat's StatParts ("parts" field in XML), if any

4) evaluate by the stat's postProcessCurve, if any

5) multiply by each of the stat's postProcessStatFactors, if any, one at a time

6) multiply by the scenario settings' factor for that stat

7) round to the nearest 5 if the current absolute value is over the stat's roundToFiveOver field (default 3.40282347e+38; will therefore never trigger for any stat that doesn't specify this in its XML)

8) round to the nearest integer if the stat's roundValue is set to true (default false)

9) enforce the stat's minValue and maxValue, which are -/+ 9999999 by default

Under this process, Construction Speed is 1 (or 0.5 for Constructoids) at step 0. In step 1, production specialists gain +50%. Steps 2a and 2b have no effect, but in step 2c we multiply by the following: Global Work Speed, the level-appropriate speed modifier shown in the 100% Manipulation column of the table, manipulation, and (1 + ((sight-1)*0.2)). Construction Speed lacks anything for steps 3-5. Then multiply by scenario settings. Skip steps 7 and 8; bring up to 10% if it was lower.

^$ Exceptions to the outlined process exist; Construction Speed is not one of them.

  • The following calculate steps 1-2 differently: market value, max power output, melee armor penetration, melee average armor penetration, melee average DPS, melee damage amount, melee damage amount trap, melee DPS, minimum handling skill, Content added by the Royalty DLCmeditation psyfocus strength, Content added by the Anomaly DLCcold containment bonus, and containment strength.
  • Steps 4, 5, and 9 are skipped over ONLY for the purposes of UI display by stats that have a postProcessCurve: melee hit chance, melee dodge chance, shooting accuracy, meat amount, leather amount, hunting stealth, medical tend quality, and cooking speed.
Reply to "Construction speed stub"
Hautarche (talkcontribs)

This isn't a total overhaul of the Recreation page, despite how many edits I made to it. I have yet to check some things regarding gather spots, reigning from a throne, or anything regarding caravans or recreation fall rate. I just wanted to put the information that I found out about recreation gain rate while filling out the Anima Tree page in and then realized this one needed a lot of work, so let's do this point by point:

- "10 types of recreation": With the book system introduced in 1.5, there are now 9->10 distinct types of recreation. To be sure, I checked for all mentions of '</JoyKindDef>' using the Find in Files tool on the entire RimWorld folder, and then also checked to make sure there are no def classes that are derivatives of JoyKindDef.

- "Recreation gain rate": this is handled via the Need_Joy.GainJoy method. I found this referenced in JoyUtility.JoyTickCheckEnd (which itself is appended to every tick of every recreational activity's JobDriver), on every tick of JobDriver_VisitSickPawn (used to give the sick pawn joy as well), BabyPlayUtility.PlayTickCheckEnd (gives joy to pawns for playing with babies), and a couple other methods that I haven't had time to look at yet (pertaining to parties, caravans, ritual duels, and food/drug ingestion). In the three cases I looked at, the "base" joy gain is defined as 0.000144 (or 0.36/2500) per tick, which is why I call 36% the base gain rate per hour. In the case of JoyTickCheckEnd and PlayTickCheckEnd, this is then multiplied by the joy gain factor stat of the joy source building (if any); since VisitSickPawn never involves a joy source building, we can generalize this rather than noting the technical backend exception. In the case of JoyTickCheckEnd and VisitSickPawn, it is also multiplied by the recreation-seeker's job's joyGainRate, so I did another thorough Find in Files search for </joyGainRate> and noted down all the joy gain rates I could find (if a JobDef's XML does not specify, it defaults to 1x). Regardless of where it's used, GainJoy always multiplies the amount by the relevant recreation tolerance.

- "Activities table": was missing Reading, obviously, but was also missing Baby Play, which is easy to miss as it is not technically a JoyGiver - I only caught due to the searches I carried out in the previous point. Duration of meditation was wrong (source: XML). Gain Rate was misrepresented as a static value for some activities. There was no explanation for duration; while what it does is kind of obvious to anyone who has played the game, I both read the C# and tested in-game (along with altering the values in XML between tests) to verify that the explanation I have included as a footnote is correct. Cheering up a patient misleadingly claimed "Injured" as a required capacity, which wrongly implies that the pawn seeking recreation must themselves be injured - I felt it was better to leave that blank and just describe in detail in the dedicated text section for that activity below.

- "Activities": I went and read the JobDrivers and JoyGivers for every single one of them, and then implemented tests in a modless testing file to verify my understanding. I also wanted to ensure that each subsection actually details at least the following information: what conditions must be fulfilled for this activity to be available, where a pawn can perform this activity, and what pawns do when performing this activity.

(Cheering up a Patient and Watching Television were entirely missing, despite neither one being more intuitive than Going For a Walk; Praying and Meditating were falsely equivocated with each other, and along with various other activities were incredibly sparsely detailed which was starkly funny when compared to Relaxing Socially having an entire prescriptive (and somewhat incorrect) digression on the best way to handle gather spots.)

Hautarche (talkcontribs)

Building Snowmen: conditions were derived from the JoyGiver. The JobDriver did not provide mechanically relevant information, but did provide three interesting bits of trivia: snowman building speed = 1.7x the pawn's construction speed, and it can trigger 'Passion for my work' if the pawn is passionate about Construction, but it does not train Construction skill.

Cheering up a patient: was entirely missing. Derived from its bespoke JoyGiver and JobDriver. It was actually really interesting to learn about - and verify - the requisite conditions and strengths, because I've had sick pawns turn into a black hole that suck up my healthy colonists' time before and could never figure out how to get it to stop. If you have spare space in your hospitals, consider placing stools close to each bed for visitors' sake.

Meditating: pseudorandom capability based on ID is set by the pctPawnsEverDo field in its JoyGiverDef. Recreational meditating actually has the exact same JobDriver as meditation for Royalty-related reasons; it just flips some conditional switches if you have Royalty and/or Ideology.

Billiards: everything I wrote is obviously how billiards tables work, but I also verified it by looking at JG and JD as usual. Filled out the details I consider necessary per subsection, as detailed in the previous post, no matter how obvious they are to anyone who has used a billiards table before.

Chess: ditto. Is it obvious that the chairs have to be horizontally or vertically adjacent, rather than being usable on diagonals? Well, I've met someone who didn't even know the chess table NEEDS chairs. Don't chess tables give you an alert if they don't have chairs? I digress.

Hoopstone, horseshoes: ditto. Accuracy never hurt anyone, unless we're talking weapons.

Poker table: went with the precedent set forth by Billiards' description and noted its relative skill-training power.

Game of Ur: and conversely, noted this one's lack of instructive efficacy.

Praying: capability again set by pctPawnsEverDo. JG and JD for mechanisms as usual, though this was by far the easiest one to test all conditions of. Strangely, there are clauses for what rooms prisoners should pick to pray in, even though prisoners (of any faction, including the player's) do not have a recreation need.

Reading: JG, JD, extensive testing. Discrimination by book type is derived from BookUtility.TryGetRandomBookToRead, which evaluates each of the book's outcome doers based on their DoesProvidesOutcome function. The 'find a good reading spot' was very fun to test, and I actually needed to test it because I could not tell what was supposed to happen if no good spot was found just by reading the code. Decided to borrow the wikitable structure from the Anima Tree page to discuss Novel quality effect on joy gain.

Relaxing socially: JG, JD, testing. You can pretty trivially test the former claim that pawns prefer closer gather spots - no they don't, they'll go anywhere. I haven't conducted a robust search for all gather spot objects in the game, so we may still be missing some. This subsection needed to be more compact; it took like three sentences to say you could toggle gather spots, and did not provide a directly obvious causal link between gather spot toggling and adventures in dangerous mining pits.

Skygazing: it was already very correct and very thorough, just more long-winded than it needed to be. All I did was provide the specific maximum rain/snow level for skygazing and add DLC icons where appropriate. I thought its rain/snow level language was very good, so I borrowed it to describe the same phenomenon where relevant to other recreation activities.

Using telescope: cleaned up some potential confusion on wording (e.g. 'outdoors' and 'unroofed cell' are two very different things). Retained the "Oddly..." sentence.

Viewing art: JG, JD, testing (I mean this is true for all of them, we can stop saying this). Verified that all 'sculptures' in the game (including terror sculptures, cube sculptures of all kinds, and void sculptures) are usable for this activity: they have CompArt courtesy of CompProperties_Art, and all of them specify 'canBeEnjoyedAsArt' as true which makes them unconditionally usable for viewing art. The JoyGiverDef XML says that viewing art can be done while in bed, but the JobDriver is not configured to allow this to occur, even if an art piece is adjacent to the head of the bed.

Visiting grave: entirely correct, it was just missing what pawns actually DO when visiting graves.

Watching television: was entirely missing. Moved around a lot of beds, opened and closed a lot of doors, and built and tore down a lot of walls to make sure I had got the correct gist of how the viewing area is determined.

Musical instruments: was entirely missing. The ThoughtWorker code for the mood bonus seems to imply that the max range one can be from the instrument to still receive the thought is based on pathing distance rather than linear distance, since it incorporates a ClosestThingReachable argument, but increasing the path distance between a listener and instrument does not actually impact how far away they can be from it to still hear it, while moving the pawn two steps to the left into a different room suddenly cuts them off. I think Ludeon wanted to implement some sort of soundwave-travel effect into the radius, but then realized it was either player-unintuitive or nonperformant and just left what's basically an intronic sequence in the code. To test that drums aren't musical recreation options, I went Mr. Beast mode and locked four recreation-starved pawns in buildings each with a different instrument type; the one in the drums room never pursued recreation with them, no matter how many times I un/drafted him.

Playing with baby: does NOT have a JoyGiver. Does have a JobDriver. Before I had fully read the JobDriver (and the three associated sub-job JobDrivers) I erroneously assumed toyboxes had to be adjacent to the baby. This is not the case. In fact, the player does not even have to touch the toybox.

Speeds (half-speed, third-speed) were determined by the locomotionUrgency which pawns are set to by the JobDrivers. Amble (as in walking play with baby) multiplies pathing costs by 3, whereas walk (as in go for a walk) multiplies by 2.

Harakoni (talkcontribs)

What is the actual equation for snowman building time? Because 1.7 times the pawn's construction speed is ambiguous and could be interpreted as pawns with higher speeds take longer to construct a snow man

Hautarche (talkcontribs)

Good point. The amount of work to build a snowman is 2300, and each tick spent building the snowman performs 1.7x the pawn's construction speed worth of work, as phrased:

this.workLeft -= doWork.actor.GetStatValue(StatDefOf.ConstructionSpeed, true, -1) * 1.7f;

Reply to "Recreation details"

Anima tree linking ritual details

3
Hautarche (talkcontribs)

Attempted to verify the claim "This only works on pawns with the Natural meditation type and a non-zero psychic sensitivity.[Verify] Children cannot link to the anima tree."

  • Pawns without the Natural meditation focus type cannot even participate in the Anima Tree Linking ritual. By default, they are in the greyed-out "Not participating" row in the ritual UI. Attempting to drag them into the Participants row will not work, and the game tells you "Must have natural focus type". Attempting to put them in the Linker role will not work, and the game tells you "Must be a colonist with the natural meditation focus type who is below maximum psylink level."
  • Attempting to put a pawn with 0% psychic sensitivity in the Linker role does not work, and the game tells you "Must not be psychically deaf."
  • Children with the Natural meditation focus type can participate in the ritual. However, attempting to put them in the Linker role will not work, and the game tells you "Only adults can link with an anima tree".

Also missing in the Anima Tree page was information on how much grass is retained after a linking ritual. The amount of grass restored is dependent on the quality of the ritual, according to a SimpleCurve hardcoded into the RitualOutcomeEffectWorker_AnimaTreeLinking as follows (x = quality, y = grass restored):

  • (0.2, 0)
  • (0.4, 1)
  • (0.6, 3)
  • (0.8, 5)
  • (1, 8)

Quality is determined by participant count, which can be seen changing as you alter the number of participants in the ritual UI. The SimpleCurve is in the XML for the 'AnimaTreeLinking' RitualOutcomeEffectDef (x = participants, y = quality):

  • (1, 0.2)
  • (2, 0.4)
  • (4, 0.6)
  • (6, 0.8)
  • (8, 1)

Presumably this convoluted setup where you have to evaluate through two different SimpleCurves owes to technical limitations on the possible range of ritual qualities.

You can check all of this by making a testing scenario with at least eight tribals and an anima tree with 20 grass (to make grass on demand, select the anima tree, turn on dev mode, turn on god mode, and press the "DEV: Add 100% progress" button over and over again until you have >=20 grass). The ritual UI itself has a line at the bottom of the ritual description, which reads "With _ additional participants, _ anima grass will be restored at the end of the ceremony." The outcomes read as follows:

  • 7+ additional participants: 8 grass restored
  • 6: 6
  • 5: 5
  • 4: 4
  • 3: 3
  • 1-2: 1
  • 0: 0

EDIT: paragraph breaks

Hautarche (talkcontribs)

Also satisfied a stub request to fill out details about meditation at an anima tree works. I'll be putting citations for each of the claims below - if the citation does not end in '.xml', it can be found in RimWorld's C# assembly.

- Meditation is a form of solitary recreation (Jobs_Joy.xml). It has no specified joyGainRate, and so defaults to 1 (JobDef.joyGainRate).

- Every tick of meditation, joy is given to the pawn through the function JoyUtility.JoyTickCheckEnd, with the argument "extraJoyGainFactor" set to 1 (JobDriver_Meditate.MeditationTick).

- JoyTickCheckEnd provisionally grants a joy = extraJoyGainFactor * curJob.def.joyGainRate * 0.36 / 2500, which in this case is therefore 1*1*0.36/2500 = 0.000144 = 0.0144% (JoyUtility.JoyTickCheckEnd).

- This provisional amount is multiplied by the pawn's tolerance for solitary recreation, and then given to the pawn (Need_Joy.GainJoy).

Harakoni (talkcontribs)

Absolutely top tier work. Thank you so much!

Reply to "Anima tree linking ritual details"
Hautarche (talkcontribs)

Chaos Skip, Skip, and Mass Chaos Skip all achieve their effect through an ability comp shown in the XML as "CompProperties_AbilityTeleport". This has a field called "maxBodySize", which does basically what you expect - you can't target any pawn with such an ability if its body size > maxBodySize. The default value for maxBodySize is 3.5, and since none of these three abilities' XML has a specified maxBodySize, they all use the default value.

Items, lacking a body size value, are not subject to this limitation (even if the object would intuitively be larger 3.5x the typical adult humanlike body size).

Hautarche (talkcontribs)

CompProperties_AbilityTeleport abilities also cannot target any pawn with the "skipResistant" tag, but the only pawn kind with this tag is the Apocriton.

EDIT: since this is already about psycast targeting limitations, I'll also put the reasoning for Berserk, Berserk Pulse, and Neuroquake being unable to affect mech bosses and Dreadmelds here. That is, all of them have the "isBoss" tag, and those three abilities have "canTargetBosses" set to false; for single-target abilities like Berserk, this makes bosses ineligible for targeting, but for area-effect abilities like BPulse and Nquake, it simply renders them immune to the area effect.

Reply to "Skip ability body size limits"
Hautarche (talkcontribs)

I got around to playing a mechanitor in 1.5 and noticed that enemy diaboli behave oddly now; they seemed to prioritize using Fire Burst instead of using their Hellsphere Cannon or attempting to close the distance. At first, I thought this was an issue caused by mods.


So I started several Dev Quicktest runs without any mods. In each, I used Dev Mode to place down a diabolus, then I went through various scenarios of pawns attacking them with weapons of different ranges, running past them without attacking them, or outright ignoring them. I then also looked at the ThinkTrees that diaboli use, the AICanTargetNow function of the Fire Burst ability, and so on and so forth...


Anyways, sources for all the information I've edited into the Diabolus page:

- I ordered friendly diaboli to use Fire Burst, watched enemy diaboli use it, and used Dev Mode to force enemy diaboli to use it. In all three instances, their behavior is identical: a three-second warmup during which chemfuel puddles are deposited to random points in 5.9c radius, followed by the deposition of chemfuel puddles into the remaining cells in 5.9c radius and a flame explosion with 5.9c radius. The ability then goes on cooldown for what appears to be 1 hour according to the GUI, but is actually 2700 ticks (1.08 hours) per the XML.

- The code for CompAbilityEffect_FireBurst is just 'GenExplosion.DoExplosion(this.Pawn.Position, this.Pawn.MapHeld, this.Props.radius, DamageDefOf.Flame, this.Pawn, -1, -1f, null, null, null, null, ThingDefOf.Filth_Fuel, 1f, 1, null, false, null, 0f, 1, 1f, false, null, null, null, false, 0.6f, 0f, true, null, 1f, null, null)'. So yes, the damage type is Flame. The two fields after 'this.Pawn' are the damage amount and armor penetration fields, in that order; since the listed damage amount is <0, DoExplosion uses Flame damage's default damage amount, which is 10, and since the listed armor penetration is <0, DoExplosion uses its default armor penetration, which is 0.

- In testing, enemy diaboli start using Fire Burst as soon as someone starts aiming at them, unless they were already using the Hellsphere Cannon. Meanwhile, colonists, pets, and mechanoids can run in close proximity to a diabolus without provoking Fire Burst; instead, it tries using its Hellsphere Cannon or melee attacks. HOWEVER, in the run in which I first noticed odd diabolus behavior, it didn't seem to be this way; that may be due to the following reasons. 1) Some of my colonists have weapons that can attack from >=66c away; 2) Fire Burst's AI usage is governed by AICanTargetNow, which is ultimately called by the diabolus' ThinkTree under whatever ThinkNode gives it JobGiver_AIFightEnemy (or in this case its derivative JobGiver_AIFightEnemies); and 3) this node in the diabolus' ThinkTree has a targetAcquireRadius of 65c. Subsequent testing with mods that enabled me to give colonists weapons with >65c range showed that diaboli will start using Fire Burst if they are not currently using Hellsphere Cannon, and are being aimed at or attacked by a pawn within 65c.

- I actually tried to test the "friendly" claim and see how diaboli from an allied faction use Fire Burst. These diaboli, which I set to various allied or neutral factions, were instead confused about their existence and wandered around aimlessly, not responding to attacks from anything (though their mounted charge turret still shot at hostile pawns nearby). This may be due to how the "Set Faction" Dev Mode tool works, though - I suspect if a mod were to add an allied faction that can field diaboli, and bothers to give them a Lord AI that lets them attack, such friendly diaboli will use Fire Burst the same way enemy diaboli do.

Hautarche (talkcontribs)

After thinking about how AICanTargetNow gets called, and recalling discrepancies between diabolus behavior during testing and non-test gameplay, I ran another set of tests that were identical to the first, with one exception: instead of *spawning* diaboli from scratch, I had a mechanitor summon them, and then I either initiated the test while the diabolus was still preparing to attack or after it started making its way towards my base. This is important because diaboli spawned from the "Spawn Pawn" Dev Tool have a different AI Lord than those that drop in after being summoned by a mechanitor (or as part of the entourage of another mechanoid boss or raid); obviously the latter is the one actually pertinent to players reading the wiki.

This round of testing showed slightly different results. To make a long story short, non-player-controlled diaboli will only use Fire Burst if the ability's AICanTargetNow function says to do so, but that in turn only gets evaluated while the diabolus is fighting enemies. A diabolus that is NOT fighting enemies therefore cannot cast Fire Burst. Diaboli are NOT fighting enemies when wandering around in preparation for an assault, as well as when they are simply pathing towards your colony (or aiming a weapon at random buildings/furniture; this is also not 'fighting enemies'). Diaboli switch to fighting enemies when they are hit by a damaging attack, (sometimes) when anyone in their 'party' is hit by a damaging attack, or when they spend enough time proximate to pawns they COULD fight; you'll know they're in this mode because they path towards your pawns and then start trying to shoot them with the Hellsphere Cannon. Note that the charge blaster turret fires independently of the diabolus and so is not an identifier of the diabolus' current Toil.

All that said, when the diabolus IS fighting enemies, Fire Burst does in fact proc when attacked or even aimed at.

This is why I have submitted an edit-of-my-edit further clarifying how diaboli' fire burst work.

Reply to "Diabolus Fire Burst notes"

Proof for Psychopath nullified thought list

3
Hautarche (talkcontribs)

Went through all the xml files under RimWorld\Data\[Biotech, Core, Ideology, Royalty]\Defs\ThoughtDefs, searched for the term "Psychopath". Wrote down all thoughts for which Psychopath showed up in its "nullifyingTraits" list. Then went to test them in a Dev Quicktest run of RimWorld.

Harakoni (talkcontribs)

This is good work but I should let you know that annoyingly not all thoughts are in the ThoughtDef folders.

For example, precept related thoughts are often in the precept defs

Also, to make it even easier, coder oriented text editors like Sublime Text and Notepad++ have "Find in Files" searches that let you search the contents of all the files in a directory, so you can find every usage in all the .xmls. No need to manually look through each file.

Hautarche (talkcontribs)

Ooh, thanks for the tip. Will be using that File in Files search from now on.

Reply to "Proof for Psychopath nullified thought list"

Why Pyromania and Gourmand DO have 50 day MTBs for their random mental states (or: you can't plot a curve with just one point)

2
Hautarche (talkcontribs)

It is not easy to test how the mental states randomly induced by Pyromaniac or Gourmand (namely, fire-starting spree and food binge) work. They are, after all, random, and they seem to take a lot of time to proc. Of course, if you go find the XML of these traits, you'll find the randomMentalState and randomMentalStateMtbDaysMoodCurve fields which govern this behavior. The former governs which mental state is randomly induced by the trait. The latter governs the 'mean time between' (MTB) episodes. In both cases, the latter has a sub-field called "points" in which there is only one point, <0,50>. This has a clear relation to the MTB - for example, if you change it to <0,1>, you will very quickly find that this makes the random mental states extremely frequent. But how does it work, and why is it called a "curve"?

In the code, randomMentalStateMtbDaysMoodCurve's only use lies within an MTB calculation. These kinds of calculations use three fields, 'mtb', 'mtbUnit', and 'checkDuration'. In this case, 'checkDuration' is 150 ticks; mtbUnit is 60000 ticks (aka 1 in-game day); and mtb... is the SimpleCurve evaluation of the pawn's current mood, using the points described in randomMentalStateMtbDaysMoodCurve's "points" field. Well, uh, how does THAT work?

A SimpleCurve is created by plotting a list of <x,y> points onto a Cartesian grid. The curve is "simple" because instead of actually creating a curvy line to map the function, it just creates straight lines between each successive point. When "evaluating" a number, it treats that number as the x-value of a coordinate, and returns the y-value of that coordinate as it would be on the plotted 'curve' (again, not actually a curve). If the number would result in a coordinate point left of the 'curves leftmost point, the y-value is that of the leftmost point of the 'curve'; and if it would be right of the rightmost, the y-value is that of the rightmost.

That's fascinating and all, but you may have noticed a problem already. Our SimpleCurve is informed by randomMentalStateMtbDaysMoodCurve, and in both Pyromaniac's and Gourmand's cases, they each only list a SINGLE POINT (<0,50>). How do you make a curve - or a 'curve' - out of a single point?

You don't, actually. And this works just fine! Because, if a pawn's mood is lower than 0 (technically impossible, but let's allow it), it's left of the leftmost point... and so the returned y-value is the y-value of the leftmost point... which is 50. And if a pawn's mood is higher than 0, it's right of the rightmost... and so the returned y-value is the y-value of the rightmost... which is 50. And if a pawn's mood is 0, well! Then the y-value of the 'curve' at that point is 50.

It really is an MTB of 50 days for both traits.

Hautarche (talkcontribs)

Uh and obviously 'days' is the unit because the MTB calculation uses 60000 ticks (1day) for its 'mtbUnit'. This assertion is also somewhat testable - with Pyromaniac, change <0,50> in your copy of RimWorld's XML to <0,1> and you'll find a Pyromaniac's random fire starting sprees occur about once a day.

Reply to "Why Pyromania and Gourmand DO have 50 day MTBs for their random mental states (or: you can't plot a curve with just one point)"

Mechanics behind Pyromaniac fire moodlet

1
Hautarche (talkcontribs)

It didn't warrant putting in my proposed edit to the Pyromaniac section of the "Traits" page, but after testing each lit building and going through RimWorld's code via the dnSpy decompiler, it seems to work like this:

Whenever it needs to determine how many stacks it has, the thought checks all cells within 8cells of the Pyromaniac's position. If said cell is within map bounds, isn't in the fog-of-war, and is within the same room as the Pyromaniac, the thought then adds however many fires are in that cell to the amount of stacks it has (up to the max of 4 stacks). The method it uses to determine how many fires are in a given cell is weird. It grabs every 'Thing' in the cell, and checks if...

1) it has a component that is/derives from "CompFireOverlayBase" (meaning that, under some circumstance, the Thing will display a fire graphic overlaid atop it), that it has a "CompGlower" (under some circumstance the Thing will emanate light), and the CompGlower is currently glowing.

2) the Thing currently has a fire attached to it.

3) the Thing is Fire, and it is attached to an object.

For each such condition that is true, the cell is considered to have +1 fire.


Onto the weird exceptions in how the total mood impact of "Beautiful fire" is calculated:

- Lit burnbongs do not count as fires: burnbongs are the only building in unmodded RimWorld which DO have a derivative of CompFireOverlayBase, but DON'T have a CompGlower. They thus don't fulfill condition '1)'.

- Free-spreading fire counts as 2 fires: the Thing which caught fire fulfills condition '2)', and the fire itself is a Fire Thing, which fulfills condition '3)'. This feels unintentional.

- Free-spreading fire on a Pawn counts as 1 fire: ... I thought I had an answer for this, but on reading over the code again I have no clue why this is.

- Burning walls don't count: they're not part of the current room.

- If a building occupies at least one cell within 8c of the Pyromaniac, and it is on fire, BUT that fire is only in cell(s) further than 8c from the Pyromaniac... it will still be counted by condition '2)' since it is, technically, on fire. In fact, each cell of the building within 8c of the Pyromaniac will count as an individual passed check for '2)'.

- Due to similar per-cell logic, a building that fulfills '1)' can do so multiple times if it occupies multiple cells. This is why pyres, being 2x2, can provide up to 4 stacks of the buff.

- A doorway counts as its own room, so a Pyromaniac standing in a doorway won't get any stacks even if there's a fire directly on either/all side(s) of the doorway.

Reply to "Mechanics behind Pyromaniac fire moodlet"
There are no older topics