diff --git a/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll similarity index 100% rename from 1.6/Assemblies/WulaFallenEmpire.dll rename to 1.6/1.6/Assemblies/WulaFallenEmpire.dll diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/Constant/Constant.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/Constant/Constant.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/Constant/Constant.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/Constant/Constant.xml diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/Constant/Thoughts.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/Constant/Thoughts.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/Constant/Thoughts.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/Constant/Thoughts.xml diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/AttackMelee.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/AttackMelee.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/AttackMelee.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/AttackMelee.xml diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/AttackStatic.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/AttackStatic.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/AttackStatic.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/AttackStatic.xml diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/DoBill.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/DoBill.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/DoBill.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/DoBill.xml diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Goto.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Goto.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Goto.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Goto.xml diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Ingest.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Ingest.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Ingest.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Ingest.xml diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/LayDown.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/LayDown.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/LayDown.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/LayDown.xml diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Lovin.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Lovin.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Lovin.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Lovin.xml diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Mine.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Mine.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Mine.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Mine.xml diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/RemoveApparel.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/RemoveApparel.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/RemoveApparel.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/RemoveApparel.xml diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Research.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Research.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Research.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Research.xml diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/SocialRelax.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/SocialRelax.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/SocialRelax.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/SocialRelax.xml diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/StandAndBeSociallyActive.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/StandAndBeSociallyActive.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/StandAndBeSociallyActive.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/StandAndBeSociallyActive.xml diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Strip.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Strip.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Strip.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Strip.xml diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/WaitCombat.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/WaitCombat.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/WaitCombat.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/WaitCombat.xml diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Wait_Downed.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Wait_Downed.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Wait_Downed.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Wait_Downed.xml diff --git a/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Wear.xml b/1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Wear.xml similarity index 100% rename from 1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Wear.xml rename to 1.6/1.6/Defs/AnimationDefs/WulaSpecies/ForJobs/Wear.xml diff --git a/1.6/Defs/BackstoryDefs/Solid/Solid_Adult_WULA.xml b/1.6/1.6/Defs/BackstoryDefs/Solid/Solid_Adult_WULA.xml similarity index 100% rename from 1.6/Defs/BackstoryDefs/Solid/Solid_Adult_WULA.xml rename to 1.6/1.6/Defs/BackstoryDefs/Solid/Solid_Adult_WULA.xml diff --git a/1.6/Defs/BackstoryDefs/Solid/Solid_Child_WULA.xml b/1.6/1.6/Defs/BackstoryDefs/Solid/Solid_Child_WULA.xml similarity index 100% rename from 1.6/Defs/BackstoryDefs/Solid/Solid_Child_WULA.xml rename to 1.6/1.6/Defs/BackstoryDefs/Solid/Solid_Child_WULA.xml diff --git a/1.6/Defs/BodyAndPartDefs/Bodyparts_WULA.xml b/1.6/1.6/Defs/BodyAndPartDefs/Bodyparts_WULA.xml similarity index 100% rename from 1.6/Defs/BodyAndPartDefs/Bodyparts_WULA.xml rename to 1.6/1.6/Defs/BodyAndPartDefs/Bodyparts_WULA.xml diff --git a/1.6/Defs/DamageDefs/Damages_Wula.xml b/1.6/1.6/Defs/DamageDefs/Damages_Wula.xml similarity index 100% rename from 1.6/Defs/DamageDefs/Damages_Wula.xml rename to 1.6/1.6/Defs/DamageDefs/Damages_Wula.xml diff --git a/1.6/Defs/DesignationCategoryDefs/WULA_DesignationCategoryDefs.xml b/1.6/1.6/Defs/DesignationCategoryDefs/WULA_DesignationCategoryDefs.xml similarity index 100% rename from 1.6/Defs/DesignationCategoryDefs/WULA_DesignationCategoryDefs.xml rename to 1.6/1.6/Defs/DesignationCategoryDefs/WULA_DesignationCategoryDefs.xml diff --git a/1.6/Defs/Effects/Mote_Wula.xml b/1.6/1.6/Defs/Effects/Mote_Wula.xml similarity index 100% rename from 1.6/Defs/Effects/Mote_Wula.xml rename to 1.6/1.6/Defs/Effects/Mote_Wula.xml diff --git a/1.6/Defs/EventDefs/EventDef_Examples.xml b/1.6/1.6/Defs/EventDefs/EventDef_Examples.xml similarity index 100% rename from 1.6/Defs/EventDefs/EventDef_Examples.xml rename to 1.6/1.6/Defs/EventDefs/EventDef_Examples.xml diff --git a/1.6/Defs/EventDefs/EventDef_VariableTest.xml b/1.6/1.6/Defs/EventDefs/EventDef_VariableTest.xml similarity index 100% rename from 1.6/Defs/EventDefs/EventDef_VariableTest.xml rename to 1.6/1.6/Defs/EventDefs/EventDef_VariableTest.xml diff --git a/1.6/Defs/EventDefs/EventDef_WULA_FE_Spiritualist.xml b/1.6/1.6/Defs/EventDefs/EventDef_WULA_FE_Spiritualist.xml similarity index 100% rename from 1.6/Defs/EventDefs/EventDef_WULA_FE_Spiritualist.xml rename to 1.6/1.6/Defs/EventDefs/EventDef_WULA_FE_Spiritualist.xml diff --git a/1.6/Defs/EventDefs/EventDef_Wula.xml b/1.6/1.6/Defs/EventDefs/EventDef_Wula.xml similarity index 100% rename from 1.6/Defs/EventDefs/EventDef_Wula.xml rename to 1.6/1.6/Defs/EventDefs/EventDef_Wula.xml diff --git a/1.6/Defs/FaceShapeDefs/BrowShape.xml b/1.6/1.6/Defs/FaceShapeDefs/BrowShape.xml similarity index 100% rename from 1.6/Defs/FaceShapeDefs/BrowShape.xml rename to 1.6/1.6/Defs/FaceShapeDefs/BrowShape.xml diff --git a/1.6/Defs/FaceShapeDefs/EmotionShape.xml b/1.6/1.6/Defs/FaceShapeDefs/EmotionShape.xml similarity index 100% rename from 1.6/Defs/FaceShapeDefs/EmotionShape.xml rename to 1.6/1.6/Defs/FaceShapeDefs/EmotionShape.xml diff --git a/1.6/Defs/FaceShapeDefs/EyeShape.xml b/1.6/1.6/Defs/FaceShapeDefs/EyeShape.xml similarity index 100% rename from 1.6/Defs/FaceShapeDefs/EyeShape.xml rename to 1.6/1.6/Defs/FaceShapeDefs/EyeShape.xml diff --git a/1.6/Defs/FaceShapeDefs/HeadShape.xml b/1.6/1.6/Defs/FaceShapeDefs/HeadShape.xml similarity index 100% rename from 1.6/Defs/FaceShapeDefs/HeadShape.xml rename to 1.6/1.6/Defs/FaceShapeDefs/HeadShape.xml diff --git a/1.6/Defs/FaceShapeDefs/LidOptionShape.xml b/1.6/1.6/Defs/FaceShapeDefs/LidOptionShape.xml similarity index 100% rename from 1.6/Defs/FaceShapeDefs/LidOptionShape.xml rename to 1.6/1.6/Defs/FaceShapeDefs/LidOptionShape.xml diff --git a/1.6/Defs/FaceShapeDefs/LidShape.xml b/1.6/1.6/Defs/FaceShapeDefs/LidShape.xml similarity index 100% rename from 1.6/Defs/FaceShapeDefs/LidShape.xml rename to 1.6/1.6/Defs/FaceShapeDefs/LidShape.xml diff --git a/1.6/Defs/FaceShapeDefs/MouthShape.xml b/1.6/1.6/Defs/FaceShapeDefs/MouthShape.xml similarity index 100% rename from 1.6/Defs/FaceShapeDefs/MouthShape.xml rename to 1.6/1.6/Defs/FaceShapeDefs/MouthShape.xml diff --git a/1.6/Defs/FaceShapeDefs/SkinShape.xml b/1.6/1.6/Defs/FaceShapeDefs/SkinShape.xml similarity index 100% rename from 1.6/Defs/FaceShapeDefs/SkinShape.xml rename to 1.6/1.6/Defs/FaceShapeDefs/SkinShape.xml diff --git a/1.6/Defs/FaceTypeDefs/WulaSpecies/BrowType.xml b/1.6/1.6/Defs/FaceTypeDefs/WulaSpecies/BrowType.xml similarity index 100% rename from 1.6/Defs/FaceTypeDefs/WulaSpecies/BrowType.xml rename to 1.6/1.6/Defs/FaceTypeDefs/WulaSpecies/BrowType.xml diff --git a/1.6/Defs/FaceTypeDefs/WulaSpecies/EmotionType.xml b/1.6/1.6/Defs/FaceTypeDefs/WulaSpecies/EmotionType.xml similarity index 100% rename from 1.6/Defs/FaceTypeDefs/WulaSpecies/EmotionType.xml rename to 1.6/1.6/Defs/FaceTypeDefs/WulaSpecies/EmotionType.xml diff --git a/1.6/Defs/FaceTypeDefs/WulaSpecies/EyeType.xml b/1.6/1.6/Defs/FaceTypeDefs/WulaSpecies/EyeType.xml similarity index 100% rename from 1.6/Defs/FaceTypeDefs/WulaSpecies/EyeType.xml rename to 1.6/1.6/Defs/FaceTypeDefs/WulaSpecies/EyeType.xml diff --git a/1.6/Defs/FaceTypeDefs/WulaSpecies/HeadType.xml b/1.6/1.6/Defs/FaceTypeDefs/WulaSpecies/HeadType.xml similarity index 100% rename from 1.6/Defs/FaceTypeDefs/WulaSpecies/HeadType.xml rename to 1.6/1.6/Defs/FaceTypeDefs/WulaSpecies/HeadType.xml diff --git a/1.6/Defs/FaceTypeDefs/WulaSpecies/LidType.xml b/1.6/1.6/Defs/FaceTypeDefs/WulaSpecies/LidType.xml similarity index 100% rename from 1.6/Defs/FaceTypeDefs/WulaSpecies/LidType.xml rename to 1.6/1.6/Defs/FaceTypeDefs/WulaSpecies/LidType.xml diff --git a/1.6/Defs/FaceTypeDefs/WulaSpecies/MouthType.xml b/1.6/1.6/Defs/FaceTypeDefs/WulaSpecies/MouthType.xml similarity index 100% rename from 1.6/Defs/FaceTypeDefs/WulaSpecies/MouthType.xml rename to 1.6/1.6/Defs/FaceTypeDefs/WulaSpecies/MouthType.xml diff --git a/1.6/Defs/FaceTypeDefs/WulaSpecies/SkinType.xml b/1.6/1.6/Defs/FaceTypeDefs/WulaSpecies/SkinType.xml similarity index 100% rename from 1.6/Defs/FaceTypeDefs/WulaSpecies/SkinType.xml rename to 1.6/1.6/Defs/FaceTypeDefs/WulaSpecies/SkinType.xml diff --git a/1.6/Defs/FactionDefs/Factions_Player_WULA.xml b/1.6/1.6/Defs/FactionDefs/Factions_Player_WULA.xml similarity index 100% rename from 1.6/Defs/FactionDefs/Factions_Player_WULA.xml rename to 1.6/1.6/Defs/FactionDefs/Factions_Player_WULA.xml diff --git a/1.6/Defs/FleshTypeDefs/FleshType_WULA.xml b/1.6/1.6/Defs/FleshTypeDefs/FleshType_WULA.xml similarity index 100% rename from 1.6/Defs/FleshTypeDefs/FleshType_WULA.xml rename to 1.6/1.6/Defs/FleshTypeDefs/FleshType_WULA.xml diff --git a/1.6/Defs/HairDefs/WULA_Hairs.xml b/1.6/1.6/Defs/HairDefs/WULA_Hairs.xml similarity index 100% rename from 1.6/Defs/HairDefs/WULA_Hairs.xml rename to 1.6/1.6/Defs/HairDefs/WULA_Hairs.xml diff --git a/1.6/Defs/HediffDefs/Hediffs_BodyParts_WULA.xml b/1.6/1.6/Defs/HediffDefs/Hediffs_BodyParts_WULA.xml similarity index 100% rename from 1.6/Defs/HediffDefs/Hediffs_BodyParts_WULA.xml rename to 1.6/1.6/Defs/HediffDefs/Hediffs_BodyParts_WULA.xml diff --git a/1.6/Defs/HediffDefs/Hediffs_WULA.xml b/1.6/1.6/Defs/HediffDefs/Hediffs_WULA.xml similarity index 100% rename from 1.6/Defs/HediffDefs/Hediffs_WULA.xml rename to 1.6/1.6/Defs/HediffDefs/Hediffs_WULA.xml diff --git a/1.6/Defs/HediffDefs/Hediffs_WULA_Damage_Effect.xml b/1.6/1.6/Defs/HediffDefs/Hediffs_WULA_Damage_Effect.xml similarity index 100% rename from 1.6/Defs/HediffDefs/Hediffs_WULA_Damage_Effect.xml rename to 1.6/1.6/Defs/HediffDefs/Hediffs_WULA_Damage_Effect.xml diff --git a/1.6/Defs/HediffDefs/Hediffs_WULA_Maintenance.xml b/1.6/1.6/Defs/HediffDefs/Hediffs_WULA_Maintenance.xml similarity index 100% rename from 1.6/Defs/HediffDefs/Hediffs_WULA_Maintenance.xml rename to 1.6/1.6/Defs/HediffDefs/Hediffs_WULA_Maintenance.xml diff --git a/1.6/Defs/IncidentDefs/Wula_ScheduledIncidents.xml b/1.6/1.6/Defs/IncidentDefs/Wula_ScheduledIncidents.xml similarity index 100% rename from 1.6/Defs/IncidentDefs/Wula_ScheduledIncidents.xml rename to 1.6/1.6/Defs/IncidentDefs/Wula_ScheduledIncidents.xml diff --git a/1.6/Defs/JobDefs/WULA_JobDefs.xml b/1.6/1.6/Defs/JobDefs/WULA_JobDefs.xml similarity index 100% rename from 1.6/Defs/JobDefs/WULA_JobDefs.xml rename to 1.6/1.6/Defs/JobDefs/WULA_JobDefs.xml diff --git a/1.6/Defs/MentalBreakDefs/MentalBreaks_WULA.xml b/1.6/1.6/Defs/MentalBreakDefs/MentalBreaks_WULA.xml similarity index 100% rename from 1.6/Defs/MentalBreakDefs/MentalBreaks_WULA.xml rename to 1.6/1.6/Defs/MentalBreakDefs/MentalBreaks_WULA.xml diff --git a/1.6/Defs/MentalStateDefs/MentalStates_WULA_Broken.xml b/1.6/1.6/Defs/MentalStateDefs/MentalStates_WULA_Broken.xml similarity index 100% rename from 1.6/Defs/MentalStateDefs/MentalStates_WULA_Broken.xml rename to 1.6/1.6/Defs/MentalStateDefs/MentalStates_WULA_Broken.xml diff --git a/1.6/Defs/NeedDefs/WULA_Needs.xml b/1.6/1.6/Defs/NeedDefs/WULA_Needs.xml similarity index 100% rename from 1.6/Defs/NeedDefs/WULA_Needs.xml rename to 1.6/1.6/Defs/NeedDefs/WULA_Needs.xml diff --git a/1.6/Defs/PawnKinds/PawnKinds_Wula.xml b/1.6/1.6/Defs/PawnKinds/PawnKinds_Wula.xml similarity index 100% rename from 1.6/Defs/PawnKinds/PawnKinds_Wula.xml rename to 1.6/1.6/Defs/PawnKinds/PawnKinds_Wula.xml diff --git a/1.6/Defs/QuestScriptDefs/Wula_ScheduledEvents.xml b/1.6/1.6/Defs/QuestScriptDefs/Wula_ScheduledEvents.xml similarity index 100% rename from 1.6/Defs/QuestScriptDefs/Wula_ScheduledEvents.xml rename to 1.6/1.6/Defs/QuestScriptDefs/Wula_ScheduledEvents.xml diff --git a/1.6/Defs/RecipeDefs/Recipes_WULA.xml b/1.6/1.6/Defs/RecipeDefs/Recipes_WULA.xml similarity index 100% rename from 1.6/Defs/RecipeDefs/Recipes_WULA.xml rename to 1.6/1.6/Defs/RecipeDefs/Recipes_WULA.xml diff --git a/1.6/Defs/ResearchProjectDefs/ResearchProjects_WULA.xml b/1.6/1.6/Defs/ResearchProjectDefs/ResearchProjects_WULA.xml similarity index 100% rename from 1.6/Defs/ResearchProjectDefs/ResearchProjects_WULA.xml rename to 1.6/1.6/Defs/ResearchProjectDefs/ResearchProjects_WULA.xml diff --git a/1.6/Defs/ResearchTabDef/ResearchTabs_WULA.xml b/1.6/1.6/Defs/ResearchTabDef/ResearchTabs_WULA.xml similarity index 100% rename from 1.6/Defs/ResearchTabDef/ResearchTabs_WULA.xml rename to 1.6/1.6/Defs/ResearchTabDef/ResearchTabs_WULA.xml diff --git a/1.6/Defs/RulePackDefs/RulePacks_Namers_Factions_Wula.xml b/1.6/1.6/Defs/RulePackDefs/RulePacks_Namers_Factions_Wula.xml similarity index 100% rename from 1.6/Defs/RulePackDefs/RulePacks_Namers_Factions_Wula.xml rename to 1.6/1.6/Defs/RulePackDefs/RulePacks_Namers_Factions_Wula.xml diff --git a/1.6/Defs/Scenarios/Scenarios_WULA.xml b/1.6/1.6/Defs/Scenarios/Scenarios_WULA.xml similarity index 100% rename from 1.6/Defs/Scenarios/Scenarios_WULA.xml rename to 1.6/1.6/Defs/Scenarios/Scenarios_WULA.xml diff --git a/1.6/Defs/StatDefs/WULA_Stats.xml b/1.6/1.6/Defs/StatDefs/WULA_Stats.xml similarity index 100% rename from 1.6/Defs/StatDefs/WULA_Stats.xml rename to 1.6/1.6/Defs/StatDefs/WULA_Stats.xml diff --git a/1.6/Defs/StoryTellers/WULA_Storytellers.xml b/1.6/1.6/Defs/StoryTellers/WULA_Storytellers.xml similarity index 100% rename from 1.6/Defs/StoryTellers/WULA_Storytellers.xml rename to 1.6/1.6/Defs/StoryTellers/WULA_Storytellers.xml diff --git a/1.6/Defs/StyleItemCategoryDefs/WULA_StyleItemCategoryDefs.xml b/1.6/1.6/Defs/StyleItemCategoryDefs/WULA_StyleItemCategoryDefs.xml similarity index 100% rename from 1.6/Defs/StyleItemCategoryDefs/WULA_StyleItemCategoryDefs.xml rename to 1.6/1.6/Defs/StyleItemCategoryDefs/WULA_StyleItemCategoryDefs.xml diff --git a/1.6/Defs/ThingDefs/WULA_Item.xml b/1.6/1.6/Defs/ThingDefs/WULA_Item.xml similarity index 100% rename from 1.6/Defs/ThingDefs/WULA_Item.xml rename to 1.6/1.6/Defs/ThingDefs/WULA_Item.xml diff --git a/1.6/Defs/ThingDefs_Buildings/Buildings_Structure.xml b/1.6/1.6/Defs/ThingDefs_Buildings/Buildings_Structure.xml similarity index 100% rename from 1.6/Defs/ThingDefs_Buildings/Buildings_Structure.xml rename to 1.6/1.6/Defs/ThingDefs_Buildings/Buildings_Structure.xml diff --git a/1.6/Defs/ThingDefs_Buildings/Buildings_WULA.xml b/1.6/1.6/Defs/ThingDefs_Buildings/Buildings_WULA.xml similarity index 100% rename from 1.6/Defs/ThingDefs_Buildings/Buildings_WULA.xml rename to 1.6/1.6/Defs/ThingDefs_Buildings/Buildings_WULA.xml diff --git a/1.6/Defs/ThingDefs_Buildings/WULA_FallenEmpire_Buildings_Ritual.xml b/1.6/1.6/Defs/ThingDefs_Buildings/WULA_FallenEmpire_Buildings_Ritual.xml similarity index 100% rename from 1.6/Defs/ThingDefs_Buildings/WULA_FallenEmpire_Buildings_Ritual.xml rename to 1.6/1.6/Defs/ThingDefs_Buildings/WULA_FallenEmpire_Buildings_Ritual.xml diff --git a/1.6/Defs/ThingDefs_Misc/Apperals/WULA_Apparel.xml b/1.6/1.6/Defs/ThingDefs_Misc/Apperals/WULA_Apparel.xml similarity index 100% rename from 1.6/Defs/ThingDefs_Misc/Apperals/WULA_Apparel.xml rename to 1.6/1.6/Defs/ThingDefs_Misc/Apperals/WULA_Apparel.xml diff --git a/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon.xml b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon.xml similarity index 100% rename from 1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon.xml rename to 1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon.xml diff --git a/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml b/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml similarity index 100% rename from 1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml rename to 1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml diff --git a/1.6/Defs/ThinkTreeDefs/WULA_ThinkTrees.xml b/1.6/1.6/Defs/ThinkTreeDefs/WULA_ThinkTrees.xml similarity index 100% rename from 1.6/Defs/ThinkTreeDefs/WULA_ThinkTrees.xml rename to 1.6/1.6/Defs/ThinkTreeDefs/WULA_ThinkTrees.xml diff --git a/1.6/Defs/ThoughtDefs/Thoughts_WULA.xml b/1.6/1.6/Defs/ThoughtDefs/Thoughts_WULA.xml similarity index 100% rename from 1.6/Defs/ThoughtDefs/Thoughts_WULA.xml rename to 1.6/1.6/Defs/ThoughtDefs/Thoughts_WULA.xml diff --git a/1.6/Defs/TraitDefs/Traits_WULA.xml b/1.6/1.6/Defs/TraitDefs/Traits_WULA.xml similarity index 100% rename from 1.6/Defs/TraitDefs/Traits_WULA.xml rename to 1.6/1.6/Defs/TraitDefs/Traits_WULA.xml diff --git a/1.6/Defs/WeaponTraitDefs/WULA_WeaponCategoryDefs.xml b/1.6/1.6/Defs/WeaponTraitDefs/WULA_WeaponCategoryDefs.xml similarity index 100% rename from 1.6/Defs/WeaponTraitDefs/WULA_WeaponCategoryDefs.xml rename to 1.6/1.6/Defs/WeaponTraitDefs/WULA_WeaponCategoryDefs.xml diff --git a/1.6/Defs/WeaponTraitDefs/WULA_WeaponTraitDefs.xml b/1.6/1.6/Defs/WeaponTraitDefs/WULA_WeaponTraitDefs.xml similarity index 100% rename from 1.6/Defs/WeaponTraitDefs/WULA_WeaponTraitDefs.xml rename to 1.6/1.6/Defs/WeaponTraitDefs/WULA_WeaponTraitDefs.xml diff --git a/1.6/Defs/WorkGivers/Wula_WorkGivers.xml b/1.6/1.6/Defs/WorkGivers/Wula_WorkGivers.xml similarity index 100% rename from 1.6/Defs/WorkGivers/Wula_WorkGivers.xml rename to 1.6/1.6/Defs/WorkGivers/Wula_WorkGivers.xml diff --git a/1.6/Defs/WulaMiscSettingDefs/EventUIConfig.xml b/1.6/1.6/Defs/WulaMiscSettingDefs/EventUIConfig.xml similarity index 100% rename from 1.6/Defs/WulaMiscSettingDefs/EventUIConfig.xml rename to 1.6/1.6/Defs/WulaMiscSettingDefs/EventUIConfig.xml diff --git a/1.6/Defs/WulaMiscSettingDefs/LetterDefs/EventLetter.xml b/1.6/1.6/Defs/WulaMiscSettingDefs/LetterDefs/EventLetter.xml similarity index 100% rename from 1.6/Defs/WulaMiscSettingDefs/LetterDefs/EventLetter.xml rename to 1.6/1.6/Defs/WulaMiscSettingDefs/LetterDefs/EventLetter.xml diff --git a/1.6/Defs/WulaMiscSettingDefs/LifeStageDefs/LifeStages_WULA.xml b/1.6/1.6/Defs/WulaMiscSettingDefs/LifeStageDefs/LifeStages_WULA.xml similarity index 100% rename from 1.6/Defs/WulaMiscSettingDefs/LifeStageDefs/LifeStages_WULA.xml rename to 1.6/1.6/Defs/WulaMiscSettingDefs/LifeStageDefs/LifeStages_WULA.xml diff --git a/1.6/Defs/WulaMiscSettingDefs/WulaCaravanEnergyDefs.xml b/1.6/1.6/Defs/WulaMiscSettingDefs/WulaCaravanEnergyDefs.xml similarity index 100% rename from 1.6/Defs/WulaMiscSettingDefs/WulaCaravanEnergyDefs.xml rename to 1.6/1.6/Defs/WulaMiscSettingDefs/WulaCaravanEnergyDefs.xml diff --git a/1.6/Defs/WulaMiscSettingDefs/WulaHullDef.xml b/1.6/1.6/Defs/WulaMiscSettingDefs/WulaHullDef.xml similarity index 100% rename from 1.6/Defs/WulaMiscSettingDefs/WulaHullDef.xml rename to 1.6/1.6/Defs/WulaMiscSettingDefs/WulaHullDef.xml diff --git a/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml similarity index 100% rename from Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml rename to 1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml diff --git a/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Ritual_Keys.xml b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Ritual_Keys.xml similarity index 100% rename from Languages/ChineseSimplified (简体中文)/Keyed/WULA_Ritual_Keys.xml rename to 1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Ritual_Keys.xml diff --git a/Languages/ChineseSimplified (简体中文)/Keyed/WULA_SkillTrainer.xml b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_SkillTrainer.xml similarity index 100% rename from Languages/ChineseSimplified (简体中文)/Keyed/WULA_SkillTrainer.xml rename to 1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_SkillTrainer.xml diff --git a/Patches/Patch.xml b/1.6/1.6/Patches/Patch.xml similarity index 100% rename from Patches/Patch.xml rename to 1.6/1.6/Patches/Patch.xml diff --git a/1.6/Mods/Anomaly/BodyAndPartDefs/Bodyparts_WULA_FE_Spiritualist.xml b/1.6/Anomaly/BodyAndPartDefs/Bodyparts_WULA_FE_Spiritualist.xml similarity index 100% rename from 1.6/Mods/Anomaly/BodyAndPartDefs/Bodyparts_WULA_FE_Spiritualist.xml rename to 1.6/Anomaly/BodyAndPartDefs/Bodyparts_WULA_FE_Spiritualist.xml diff --git a/1.6/Mods/Anomaly/FactionDefs/Factions_WULA_FE_Spiritualist.xml b/1.6/Anomaly/FactionDefs/Factions_WULA_FE_Spiritualist.xml similarity index 100% rename from 1.6/Mods/Anomaly/FactionDefs/Factions_WULA_FE_Spiritualist.xml rename to 1.6/Anomaly/FactionDefs/Factions_WULA_FE_Spiritualist.xml diff --git a/1.6/Mods/Anomaly/HediffDefs/Hediffs_WULA_FE_Spiritualist.xml b/1.6/Anomaly/HediffDefs/Hediffs_WULA_FE_Spiritualist.xml similarity index 100% rename from 1.6/Mods/Anomaly/HediffDefs/Hediffs_WULA_FE_Spiritualist.xml rename to 1.6/Anomaly/HediffDefs/Hediffs_WULA_FE_Spiritualist.xml diff --git a/1.6/Mods/Anomaly/PawnKinds/PawnKinds_Wula_FE_Spiritualist.xml b/1.6/Anomaly/PawnKinds/PawnKinds_Wula_FE_Spiritualist.xml similarity index 100% rename from 1.6/Mods/Anomaly/PawnKinds/PawnKinds_Wula_FE_Spiritualist.xml rename to 1.6/Anomaly/PawnKinds/PawnKinds_Wula_FE_Spiritualist.xml diff --git a/1.6/Mods/Anomaly/PsychicRitualDefs/WULA_FE_Spiritualist_Rituals.xml b/1.6/Anomaly/PsychicRitualDefs/WULA_FE_Spiritualist_Rituals.xml similarity index 100% rename from 1.6/Mods/Anomaly/PsychicRitualDefs/WULA_FE_Spiritualist_Rituals.xml rename to 1.6/Anomaly/PsychicRitualDefs/WULA_FE_Spiritualist_Rituals.xml diff --git a/1.6/Mods/Anomaly/ResearchProjectDefs/ResearchProjects_WULA_FE_Spiritualist.xml b/1.6/Anomaly/ResearchProjectDefs/ResearchProjects_WULA_FE_Spiritualist.xml similarity index 100% rename from 1.6/Mods/Anomaly/ResearchProjectDefs/ResearchProjects_WULA_FE_Spiritualist.xml rename to 1.6/Anomaly/ResearchProjectDefs/ResearchProjects_WULA_FE_Spiritualist.xml diff --git a/1.6/Mods/Anomaly/ResearchTabDef/ResearchTabs_WULA_FE_Spiritualist.xml b/1.6/Anomaly/ResearchTabDef/ResearchTabs_WULA_FE_Spiritualist.xml similarity index 100% rename from 1.6/Mods/Anomaly/ResearchTabDef/ResearchTabs_WULA_FE_Spiritualist.xml rename to 1.6/Anomaly/ResearchTabDef/ResearchTabs_WULA_FE_Spiritualist.xml diff --git a/1.6/Mods/Anomaly/ThingDefs/WULA_FE_Spiritualist_Item.xml b/1.6/Anomaly/ThingDefs/WULA_FE_Spiritualist_Item.xml similarity index 100% rename from 1.6/Mods/Anomaly/ThingDefs/WULA_FE_Spiritualist_Item.xml rename to 1.6/Anomaly/ThingDefs/WULA_FE_Spiritualist_Item.xml diff --git a/1.6/Mods/Anomaly/ThingDefs_Misc/Apperals/WULA_FE_Spiritualist_Apparel.xml b/1.6/Anomaly/ThingDefs_Misc/Apperals/WULA_FE_Spiritualist_Apparel.xml similarity index 100% rename from 1.6/Mods/Anomaly/ThingDefs_Misc/Apperals/WULA_FE_Spiritualist_Apparel.xml rename to 1.6/Anomaly/ThingDefs_Misc/Apperals/WULA_FE_Spiritualist_Apparel.xml diff --git a/1.6/Mods/Anomaly/ThingDefs_Misc/Weapons/WULA_FE_Spiritualist_Weapon.xml b/1.6/Anomaly/ThingDefs_Misc/Weapons/WULA_FE_Spiritualist_Weapon.xml similarity index 100% rename from 1.6/Mods/Anomaly/ThingDefs_Misc/Weapons/WULA_FE_Spiritualist_Weapon.xml rename to 1.6/Anomaly/ThingDefs_Misc/Weapons/WULA_FE_Spiritualist_Weapon.xml diff --git a/1.6/Mods/Anomaly/ThingDefs_Races/Races_Wulaspecies_FE_Spiritualist.xml b/1.6/Anomaly/ThingDefs_Races/Races_Wulaspecies_FE_Spiritualist.xml similarity index 100% rename from 1.6/Mods/Anomaly/ThingDefs_Races/Races_Wulaspecies_FE_Spiritualist.xml rename to 1.6/Anomaly/ThingDefs_Races/Races_Wulaspecies_FE_Spiritualist.xml diff --git a/1.6/Mods/Anomaly/TraderKindDefs/TraderKinds_WULA_FE_Spiritualist.xml b/1.6/Anomaly/TraderKindDefs/TraderKinds_WULA_FE_Spiritualist.xml similarity index 100% rename from 1.6/Mods/Anomaly/TraderKindDefs/TraderKinds_WULA_FE_Spiritualist.xml rename to 1.6/Anomaly/TraderKindDefs/TraderKinds_WULA_FE_Spiritualist.xml diff --git a/Textures/Wula/Apparel/WULA_Apperal_Empty.png b/Content/Textures/Wula/Apparel/WULA_Apperal_Empty.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Apperal_Empty.png rename to Content/Textures/Wula/Apparel/WULA_Apperal_Empty.png diff --git a/Textures/Wula/Apparel/WULA_Assault_Troop_Helmet.png b/Content/Textures/Wula/Apparel/WULA_Assault_Troop_Helmet.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Assault_Troop_Helmet.png rename to Content/Textures/Wula/Apparel/WULA_Assault_Troop_Helmet.png diff --git a/Textures/Wula/Apparel/WULA_Assault_Troop_Helmet_east.png b/Content/Textures/Wula/Apparel/WULA_Assault_Troop_Helmet_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Assault_Troop_Helmet_east.png rename to Content/Textures/Wula/Apparel/WULA_Assault_Troop_Helmet_east.png diff --git a/Textures/Wula/Apparel/WULA_Assault_Troop_Helmet_north.png b/Content/Textures/Wula/Apparel/WULA_Assault_Troop_Helmet_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Assault_Troop_Helmet_north.png rename to Content/Textures/Wula/Apparel/WULA_Assault_Troop_Helmet_north.png diff --git a/Textures/Wula/Apparel/WULA_Assault_Troop_Helmet_south.png b/Content/Textures/Wula/Apparel/WULA_Assault_Troop_Helmet_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Assault_Troop_Helmet_south.png rename to Content/Textures/Wula/Apparel/WULA_Assault_Troop_Helmet_south.png diff --git a/Textures/Wula/Apparel/WULA_Assault_Troop_PowerArmor.png b/Content/Textures/Wula/Apparel/WULA_Assault_Troop_PowerArmor.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Assault_Troop_PowerArmor.png rename to Content/Textures/Wula/Apparel/WULA_Assault_Troop_PowerArmor.png diff --git a/Textures/Wula/Apparel/WULA_Assault_Troop_PowerArmor_Thin_east.png b/Content/Textures/Wula/Apparel/WULA_Assault_Troop_PowerArmor_Thin_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Assault_Troop_PowerArmor_Thin_east.png rename to Content/Textures/Wula/Apparel/WULA_Assault_Troop_PowerArmor_Thin_east.png diff --git a/Textures/Wula/Apparel/WULA_Assault_Troop_PowerArmor_Thin_north.png b/Content/Textures/Wula/Apparel/WULA_Assault_Troop_PowerArmor_Thin_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Assault_Troop_PowerArmor_Thin_north.png rename to Content/Textures/Wula/Apparel/WULA_Assault_Troop_PowerArmor_Thin_north.png diff --git a/Textures/Wula/Apparel/WULA_Assault_Troop_PowerArmor_Thin_south.png b/Content/Textures/Wula/Apparel/WULA_Assault_Troop_PowerArmor_Thin_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Assault_Troop_PowerArmor_Thin_south.png rename to Content/Textures/Wula/Apparel/WULA_Assault_Troop_PowerArmor_Thin_south.png diff --git a/Textures/Wula/Apparel/WULA_Body_Suit.png b/Content/Textures/Wula/Apparel/WULA_Body_Suit.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Body_Suit.png rename to Content/Textures/Wula/Apparel/WULA_Body_Suit.png diff --git a/Textures/Wula/Apparel/WULA_Body_Suit_Thin_east.png b/Content/Textures/Wula/Apparel/WULA_Body_Suit_Thin_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Body_Suit_Thin_east.png rename to Content/Textures/Wula/Apparel/WULA_Body_Suit_Thin_east.png diff --git a/Textures/Wula/Apparel/WULA_Body_Suit_Thin_north.png b/Content/Textures/Wula/Apparel/WULA_Body_Suit_Thin_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Body_Suit_Thin_north.png rename to Content/Textures/Wula/Apparel/WULA_Body_Suit_Thin_north.png diff --git a/Textures/Wula/Apparel/WULA_Body_Suit_Thin_south.png b/Content/Textures/Wula/Apparel/WULA_Body_Suit_Thin_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Body_Suit_Thin_south.png rename to Content/Textures/Wula/Apparel/WULA_Body_Suit_Thin_south.png diff --git a/Textures/Wula/Apparel/WULA_Bodystocking.png b/Content/Textures/Wula/Apparel/WULA_Bodystocking.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Bodystocking.png rename to Content/Textures/Wula/Apparel/WULA_Bodystocking.png diff --git a/Textures/Wula/Apparel/WULA_Bodystocking_Thin_east.png b/Content/Textures/Wula/Apparel/WULA_Bodystocking_Thin_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Bodystocking_Thin_east.png rename to Content/Textures/Wula/Apparel/WULA_Bodystocking_Thin_east.png diff --git a/Textures/Wula/Apparel/WULA_Bodystocking_Thin_north.png b/Content/Textures/Wula/Apparel/WULA_Bodystocking_Thin_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Bodystocking_Thin_north.png rename to Content/Textures/Wula/Apparel/WULA_Bodystocking_Thin_north.png diff --git a/Textures/Wula/Apparel/WULA_Bodystocking_Thin_south.png b/Content/Textures/Wula/Apparel/WULA_Bodystocking_Thin_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Bodystocking_Thin_south.png rename to Content/Textures/Wula/Apparel/WULA_Bodystocking_Thin_south.png diff --git a/Textures/Wula/Apparel/WULA_Bodystocking_White.png b/Content/Textures/Wula/Apparel/WULA_Bodystocking_White.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Bodystocking_White.png rename to Content/Textures/Wula/Apparel/WULA_Bodystocking_White.png diff --git a/Textures/Wula/Apparel/WULA_Bodystocking_White_Thin_east.png b/Content/Textures/Wula/Apparel/WULA_Bodystocking_White_Thin_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Bodystocking_White_Thin_east.png rename to Content/Textures/Wula/Apparel/WULA_Bodystocking_White_Thin_east.png diff --git a/Textures/Wula/Apparel/WULA_Bodystocking_White_Thin_north.png b/Content/Textures/Wula/Apparel/WULA_Bodystocking_White_Thin_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Bodystocking_White_Thin_north.png rename to Content/Textures/Wula/Apparel/WULA_Bodystocking_White_Thin_north.png diff --git a/Textures/Wula/Apparel/WULA_Bodystocking_White_Thin_south.png b/Content/Textures/Wula/Apparel/WULA_Bodystocking_White_Thin_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Bodystocking_White_Thin_south.png rename to Content/Textures/Wula/Apparel/WULA_Bodystocking_White_Thin_south.png diff --git a/Textures/Wula/Apparel/WULA_Heavy_Infantry_Helmet.png b/Content/Textures/Wula/Apparel/WULA_Heavy_Infantry_Helmet.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Heavy_Infantry_Helmet.png rename to Content/Textures/Wula/Apparel/WULA_Heavy_Infantry_Helmet.png diff --git a/Textures/Wula/Apparel/WULA_Heavy_Infantry_Helmet_east.png b/Content/Textures/Wula/Apparel/WULA_Heavy_Infantry_Helmet_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Heavy_Infantry_Helmet_east.png rename to Content/Textures/Wula/Apparel/WULA_Heavy_Infantry_Helmet_east.png diff --git a/Textures/Wula/Apparel/WULA_Heavy_Infantry_Helmet_north.png b/Content/Textures/Wula/Apparel/WULA_Heavy_Infantry_Helmet_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Heavy_Infantry_Helmet_north.png rename to Content/Textures/Wula/Apparel/WULA_Heavy_Infantry_Helmet_north.png diff --git a/Textures/Wula/Apparel/WULA_Heavy_Infantry_Helmet_south.png b/Content/Textures/Wula/Apparel/WULA_Heavy_Infantry_Helmet_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Heavy_Infantry_Helmet_south.png rename to Content/Textures/Wula/Apparel/WULA_Heavy_Infantry_Helmet_south.png diff --git a/Textures/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor.png b/Content/Textures/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor.png rename to Content/Textures/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor.png diff --git a/Textures/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor_Thin_east.png b/Content/Textures/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor_Thin_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor_Thin_east.png rename to Content/Textures/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor_Thin_east.png diff --git a/Textures/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor_Thin_north.png b/Content/Textures/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor_Thin_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor_Thin_north.png rename to Content/Textures/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor_Thin_north.png diff --git a/Textures/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor_Thin_south.png b/Content/Textures/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor_Thin_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor_Thin_south.png rename to Content/Textures/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor_Thin_south.png diff --git a/Textures/Wula/Apparel/WULA_Knight_Helmet.png b/Content/Textures/Wula/Apparel/WULA_Knight_Helmet.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Knight_Helmet.png rename to Content/Textures/Wula/Apparel/WULA_Knight_Helmet.png diff --git a/Textures/Wula/Apparel/WULA_Knight_Helmet_east.png b/Content/Textures/Wula/Apparel/WULA_Knight_Helmet_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Knight_Helmet_east.png rename to Content/Textures/Wula/Apparel/WULA_Knight_Helmet_east.png diff --git a/Textures/Wula/Apparel/WULA_Knight_Helmet_north.png b/Content/Textures/Wula/Apparel/WULA_Knight_Helmet_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Knight_Helmet_north.png rename to Content/Textures/Wula/Apparel/WULA_Knight_Helmet_north.png diff --git a/Textures/Wula/Apparel/WULA_Knight_Helmet_south.png b/Content/Textures/Wula/Apparel/WULA_Knight_Helmet_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Knight_Helmet_south.png rename to Content/Textures/Wula/Apparel/WULA_Knight_Helmet_south.png diff --git a/Textures/Wula/Apparel/WULA_Knight_PowerArmor.png b/Content/Textures/Wula/Apparel/WULA_Knight_PowerArmor.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Knight_PowerArmor.png rename to Content/Textures/Wula/Apparel/WULA_Knight_PowerArmor.png diff --git a/Textures/Wula/Apparel/WULA_Knight_PowerArmor_Thin_east.png b/Content/Textures/Wula/Apparel/WULA_Knight_PowerArmor_Thin_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Knight_PowerArmor_Thin_east.png rename to Content/Textures/Wula/Apparel/WULA_Knight_PowerArmor_Thin_east.png diff --git a/Textures/Wula/Apparel/WULA_Knight_PowerArmor_Thin_north.png b/Content/Textures/Wula/Apparel/WULA_Knight_PowerArmor_Thin_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Knight_PowerArmor_Thin_north.png rename to Content/Textures/Wula/Apparel/WULA_Knight_PowerArmor_Thin_north.png diff --git a/Textures/Wula/Apparel/WULA_Knight_PowerArmor_Thin_south.png b/Content/Textures/Wula/Apparel/WULA_Knight_PowerArmor_Thin_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Knight_PowerArmor_Thin_south.png rename to Content/Textures/Wula/Apparel/WULA_Knight_PowerArmor_Thin_south.png diff --git a/Textures/Wula/Apparel/WULA_Knight_PowerArmor_Thin_west.png b/Content/Textures/Wula/Apparel/WULA_Knight_PowerArmor_Thin_west.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Knight_PowerArmor_Thin_west.png rename to Content/Textures/Wula/Apparel/WULA_Knight_PowerArmor_Thin_west.png diff --git a/Textures/Wula/Apparel/WULA_Maid_Uniform.png b/Content/Textures/Wula/Apparel/WULA_Maid_Uniform.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Maid_Uniform.png rename to Content/Textures/Wula/Apparel/WULA_Maid_Uniform.png diff --git a/Textures/Wula/Apparel/WULA_Maid_Uniform_Headband.png b/Content/Textures/Wula/Apparel/WULA_Maid_Uniform_Headband.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Maid_Uniform_Headband.png rename to Content/Textures/Wula/Apparel/WULA_Maid_Uniform_Headband.png diff --git a/Textures/Wula/Apparel/WULA_Maid_Uniform_Headband_east.png b/Content/Textures/Wula/Apparel/WULA_Maid_Uniform_Headband_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Maid_Uniform_Headband_east.png rename to Content/Textures/Wula/Apparel/WULA_Maid_Uniform_Headband_east.png diff --git a/Textures/Wula/Apparel/WULA_Maid_Uniform_Headband_south.png b/Content/Textures/Wula/Apparel/WULA_Maid_Uniform_Headband_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Maid_Uniform_Headband_south.png rename to Content/Textures/Wula/Apparel/WULA_Maid_Uniform_Headband_south.png diff --git a/Textures/Wula/Apparel/WULA_Maid_Uniform_Thin_east.png b/Content/Textures/Wula/Apparel/WULA_Maid_Uniform_Thin_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Maid_Uniform_Thin_east.png rename to Content/Textures/Wula/Apparel/WULA_Maid_Uniform_Thin_east.png diff --git a/Textures/Wula/Apparel/WULA_Maid_Uniform_Thin_north.png b/Content/Textures/Wula/Apparel/WULA_Maid_Uniform_Thin_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Maid_Uniform_Thin_north.png rename to Content/Textures/Wula/Apparel/WULA_Maid_Uniform_Thin_north.png diff --git a/Textures/Wula/Apparel/WULA_Maid_Uniform_Thin_south.png b/Content/Textures/Wula/Apparel/WULA_Maid_Uniform_Thin_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Maid_Uniform_Thin_south.png rename to Content/Textures/Wula/Apparel/WULA_Maid_Uniform_Thin_south.png diff --git a/Textures/Wula/Apparel/WULA_Nun_Uniform.png b/Content/Textures/Wula/Apparel/WULA_Nun_Uniform.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nun_Uniform.png rename to Content/Textures/Wula/Apparel/WULA_Nun_Uniform.png diff --git a/Textures/Wula/Apparel/WULA_Nun_Uniform_Thin_east.png b/Content/Textures/Wula/Apparel/WULA_Nun_Uniform_Thin_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nun_Uniform_Thin_east.png rename to Content/Textures/Wula/Apparel/WULA_Nun_Uniform_Thin_east.png diff --git a/Textures/Wula/Apparel/WULA_Nun_Uniform_Thin_north.png b/Content/Textures/Wula/Apparel/WULA_Nun_Uniform_Thin_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nun_Uniform_Thin_north.png rename to Content/Textures/Wula/Apparel/WULA_Nun_Uniform_Thin_north.png diff --git a/Textures/Wula/Apparel/WULA_Nun_Uniform_Thin_south.png b/Content/Textures/Wula/Apparel/WULA_Nun_Uniform_Thin_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nun_Uniform_Thin_south.png rename to Content/Textures/Wula/Apparel/WULA_Nun_Uniform_Thin_south.png diff --git a/Textures/Wula/Apparel/WULA_Nun_Uniform_Thin_west.png b/Content/Textures/Wula/Apparel/WULA_Nun_Uniform_Thin_west.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nun_Uniform_Thin_west.png rename to Content/Textures/Wula/Apparel/WULA_Nun_Uniform_Thin_west.png diff --git a/Textures/Wula/Apparel/WULA_Nun_veil.png b/Content/Textures/Wula/Apparel/WULA_Nun_veil.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nun_veil.png rename to Content/Textures/Wula/Apparel/WULA_Nun_veil.png diff --git a/Textures/Wula/Apparel/WULA_Nun_veil_east.png b/Content/Textures/Wula/Apparel/WULA_Nun_veil_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nun_veil_east.png rename to Content/Textures/Wula/Apparel/WULA_Nun_veil_east.png diff --git a/Textures/Wula/Apparel/WULA_Nun_veil_north.png b/Content/Textures/Wula/Apparel/WULA_Nun_veil_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nun_veil_north.png rename to Content/Textures/Wula/Apparel/WULA_Nun_veil_north.png diff --git a/Textures/Wula/Apparel/WULA_Nun_veil_south.png b/Content/Textures/Wula/Apparel/WULA_Nun_veil_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nun_veil_south.png rename to Content/Textures/Wula/Apparel/WULA_Nun_veil_south.png diff --git a/Textures/Wula/Apparel/WULA_Nurse_Uniform.png b/Content/Textures/Wula/Apparel/WULA_Nurse_Uniform.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nurse_Uniform.png rename to Content/Textures/Wula/Apparel/WULA_Nurse_Uniform.png diff --git a/Textures/Wula/Apparel/WULA_Nurse_Uniform_Headband.png b/Content/Textures/Wula/Apparel/WULA_Nurse_Uniform_Headband.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nurse_Uniform_Headband.png rename to Content/Textures/Wula/Apparel/WULA_Nurse_Uniform_Headband.png diff --git a/Textures/Wula/Apparel/WULA_Nurse_Uniform_Headband_east.png b/Content/Textures/Wula/Apparel/WULA_Nurse_Uniform_Headband_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nurse_Uniform_Headband_east.png rename to Content/Textures/Wula/Apparel/WULA_Nurse_Uniform_Headband_east.png diff --git a/Textures/Wula/Apparel/WULA_Nurse_Uniform_Headband_north.png b/Content/Textures/Wula/Apparel/WULA_Nurse_Uniform_Headband_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nurse_Uniform_Headband_north.png rename to Content/Textures/Wula/Apparel/WULA_Nurse_Uniform_Headband_north.png diff --git a/Textures/Wula/Apparel/WULA_Nurse_Uniform_Headband_south.png b/Content/Textures/Wula/Apparel/WULA_Nurse_Uniform_Headband_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nurse_Uniform_Headband_south.png rename to Content/Textures/Wula/Apparel/WULA_Nurse_Uniform_Headband_south.png diff --git a/Textures/Wula/Apparel/WULA_Nurse_Uniform_Thin_east.png b/Content/Textures/Wula/Apparel/WULA_Nurse_Uniform_Thin_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nurse_Uniform_Thin_east.png rename to Content/Textures/Wula/Apparel/WULA_Nurse_Uniform_Thin_east.png diff --git a/Textures/Wula/Apparel/WULA_Nurse_Uniform_Thin_north.png b/Content/Textures/Wula/Apparel/WULA_Nurse_Uniform_Thin_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nurse_Uniform_Thin_north.png rename to Content/Textures/Wula/Apparel/WULA_Nurse_Uniform_Thin_north.png diff --git a/Textures/Wula/Apparel/WULA_Nurse_Uniform_Thin_south.png b/Content/Textures/Wula/Apparel/WULA_Nurse_Uniform_Thin_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nurse_Uniform_Thin_south.png rename to Content/Textures/Wula/Apparel/WULA_Nurse_Uniform_Thin_south.png diff --git a/Textures/Wula/Apparel/WULA_Nurse_Uniform_Thin_west.png b/Content/Textures/Wula/Apparel/WULA_Nurse_Uniform_Thin_west.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Nurse_Uniform_Thin_west.png rename to Content/Textures/Wula/Apparel/WULA_Nurse_Uniform_Thin_west.png diff --git a/Textures/Wula/Apparel/WULA_Priest_Hat.png b/Content/Textures/Wula/Apparel/WULA_Priest_Hat.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Priest_Hat.png rename to Content/Textures/Wula/Apparel/WULA_Priest_Hat.png diff --git a/Textures/Wula/Apparel/WULA_Priest_Hat_east.png b/Content/Textures/Wula/Apparel/WULA_Priest_Hat_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Priest_Hat_east.png rename to Content/Textures/Wula/Apparel/WULA_Priest_Hat_east.png diff --git a/Textures/Wula/Apparel/WULA_Priest_Hat_north.png b/Content/Textures/Wula/Apparel/WULA_Priest_Hat_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Priest_Hat_north.png rename to Content/Textures/Wula/Apparel/WULA_Priest_Hat_north.png diff --git a/Textures/Wula/Apparel/WULA_Priest_Hat_south.png b/Content/Textures/Wula/Apparel/WULA_Priest_Hat_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Priest_Hat_south.png rename to Content/Textures/Wula/Apparel/WULA_Priest_Hat_south.png diff --git a/Textures/Wula/Apparel/WULA_Priest_Uniform.png b/Content/Textures/Wula/Apparel/WULA_Priest_Uniform.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Priest_Uniform.png rename to Content/Textures/Wula/Apparel/WULA_Priest_Uniform.png diff --git a/Textures/Wula/Apparel/WULA_Priest_Uniform_Thin_east.png b/Content/Textures/Wula/Apparel/WULA_Priest_Uniform_Thin_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Priest_Uniform_Thin_east.png rename to Content/Textures/Wula/Apparel/WULA_Priest_Uniform_Thin_east.png diff --git a/Textures/Wula/Apparel/WULA_Priest_Uniform_Thin_north.png b/Content/Textures/Wula/Apparel/WULA_Priest_Uniform_Thin_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Priest_Uniform_Thin_north.png rename to Content/Textures/Wula/Apparel/WULA_Priest_Uniform_Thin_north.png diff --git a/Textures/Wula/Apparel/WULA_Priest_Uniform_Thin_south.png b/Content/Textures/Wula/Apparel/WULA_Priest_Uniform_Thin_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Priest_Uniform_Thin_south.png rename to Content/Textures/Wula/Apparel/WULA_Priest_Uniform_Thin_south.png diff --git a/Textures/Wula/Apparel/WULA_Qipao.png b/Content/Textures/Wula/Apparel/WULA_Qipao.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Qipao.png rename to Content/Textures/Wula/Apparel/WULA_Qipao.png diff --git a/Textures/Wula/Apparel/WULA_Qipao_Thin_east.png b/Content/Textures/Wula/Apparel/WULA_Qipao_Thin_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Qipao_Thin_east.png rename to Content/Textures/Wula/Apparel/WULA_Qipao_Thin_east.png diff --git a/Textures/Wula/Apparel/WULA_Qipao_Thin_north.png b/Content/Textures/Wula/Apparel/WULA_Qipao_Thin_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Qipao_Thin_north.png rename to Content/Textures/Wula/Apparel/WULA_Qipao_Thin_north.png diff --git a/Textures/Wula/Apparel/WULA_Qipao_Thin_south.png b/Content/Textures/Wula/Apparel/WULA_Qipao_Thin_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Qipao_Thin_south.png rename to Content/Textures/Wula/Apparel/WULA_Qipao_Thin_south.png diff --git a/Textures/Wula/Apparel/WULA_Sailor_Dress.png b/Content/Textures/Wula/Apparel/WULA_Sailor_Dress.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Sailor_Dress.png rename to Content/Textures/Wula/Apparel/WULA_Sailor_Dress.png diff --git a/Textures/Wula/Apparel/WULA_Sailor_Dress_Thin_east.png b/Content/Textures/Wula/Apparel/WULA_Sailor_Dress_Thin_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Sailor_Dress_Thin_east.png rename to Content/Textures/Wula/Apparel/WULA_Sailor_Dress_Thin_east.png diff --git a/Textures/Wula/Apparel/WULA_Sailor_Dress_Thin_north.png b/Content/Textures/Wula/Apparel/WULA_Sailor_Dress_Thin_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Sailor_Dress_Thin_north.png rename to Content/Textures/Wula/Apparel/WULA_Sailor_Dress_Thin_north.png diff --git a/Textures/Wula/Apparel/WULA_Sailor_Dress_Thin_south.png b/Content/Textures/Wula/Apparel/WULA_Sailor_Dress_Thin_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Sailor_Dress_Thin_south.png rename to Content/Textures/Wula/Apparel/WULA_Sailor_Dress_Thin_south.png diff --git a/Textures/Wula/Apparel/WULA_Shield_Base.png b/Content/Textures/Wula/Apparel/WULA_Shield_Base.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Shield_Base.png rename to Content/Textures/Wula/Apparel/WULA_Shield_Base.png diff --git a/Textures/Wula/Apparel/WULA_Shield_Base_Thin_east.png b/Content/Textures/Wula/Apparel/WULA_Shield_Base_Thin_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Shield_Base_Thin_east.png rename to Content/Textures/Wula/Apparel/WULA_Shield_Base_Thin_east.png diff --git a/Textures/Wula/Apparel/WULA_Shield_Base_Thin_north.png b/Content/Textures/Wula/Apparel/WULA_Shield_Base_Thin_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Shield_Base_Thin_north.png rename to Content/Textures/Wula/Apparel/WULA_Shield_Base_Thin_north.png diff --git a/Textures/Wula/Apparel/WULA_Shield_Base_Thin_south.png b/Content/Textures/Wula/Apparel/WULA_Shield_Base_Thin_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Shield_Base_Thin_south.png rename to Content/Textures/Wula/Apparel/WULA_Shield_Base_Thin_south.png diff --git a/Textures/Wula/Apparel/WULA_Shield_Prismatic.png b/Content/Textures/Wula/Apparel/WULA_Shield_Prismatic.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Shield_Prismatic.png rename to Content/Textures/Wula/Apparel/WULA_Shield_Prismatic.png diff --git a/Textures/Wula/Apparel/WULA_Shield_Prismatic_Thin_east.png b/Content/Textures/Wula/Apparel/WULA_Shield_Prismatic_Thin_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Shield_Prismatic_Thin_east.png rename to Content/Textures/Wula/Apparel/WULA_Shield_Prismatic_Thin_east.png diff --git a/Textures/Wula/Apparel/WULA_Shield_Prismatic_Thin_north.png b/Content/Textures/Wula/Apparel/WULA_Shield_Prismatic_Thin_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Shield_Prismatic_Thin_north.png rename to Content/Textures/Wula/Apparel/WULA_Shield_Prismatic_Thin_north.png diff --git a/Textures/Wula/Apparel/WULA_Shield_Prismatic_Thin_south.png b/Content/Textures/Wula/Apparel/WULA_Shield_Prismatic_Thin_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Shield_Prismatic_Thin_south.png rename to Content/Textures/Wula/Apparel/WULA_Shield_Prismatic_Thin_south.png diff --git a/Textures/Wula/Apparel/WULA_Skitarii_Uniform.png b/Content/Textures/Wula/Apparel/WULA_Skitarii_Uniform.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Skitarii_Uniform.png rename to Content/Textures/Wula/Apparel/WULA_Skitarii_Uniform.png diff --git a/Textures/Wula/Apparel/WULA_Skitarii_Uniform_Thin_east.png b/Content/Textures/Wula/Apparel/WULA_Skitarii_Uniform_Thin_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Skitarii_Uniform_Thin_east.png rename to Content/Textures/Wula/Apparel/WULA_Skitarii_Uniform_Thin_east.png diff --git a/Textures/Wula/Apparel/WULA_Skitarii_Uniform_Thin_north.png b/Content/Textures/Wula/Apparel/WULA_Skitarii_Uniform_Thin_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Skitarii_Uniform_Thin_north.png rename to Content/Textures/Wula/Apparel/WULA_Skitarii_Uniform_Thin_north.png diff --git a/Textures/Wula/Apparel/WULA_Skitarii_Uniform_Thin_south.png b/Content/Textures/Wula/Apparel/WULA_Skitarii_Uniform_Thin_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Skitarii_Uniform_Thin_south.png rename to Content/Textures/Wula/Apparel/WULA_Skitarii_Uniform_Thin_south.png diff --git a/Textures/Wula/Apparel/WULA_Skitarii_veil.png b/Content/Textures/Wula/Apparel/WULA_Skitarii_veil.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Skitarii_veil.png rename to Content/Textures/Wula/Apparel/WULA_Skitarii_veil.png diff --git a/Textures/Wula/Apparel/WULA_Skitarii_veil_east.png b/Content/Textures/Wula/Apparel/WULA_Skitarii_veil_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Skitarii_veil_east.png rename to Content/Textures/Wula/Apparel/WULA_Skitarii_veil_east.png diff --git a/Textures/Wula/Apparel/WULA_Skitarii_veil_north.png b/Content/Textures/Wula/Apparel/WULA_Skitarii_veil_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Skitarii_veil_north.png rename to Content/Textures/Wula/Apparel/WULA_Skitarii_veil_north.png diff --git a/Textures/Wula/Apparel/WULA_Skitarii_veil_south.png b/Content/Textures/Wula/Apparel/WULA_Skitarii_veil_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_Skitarii_veil_south.png rename to Content/Textures/Wula/Apparel/WULA_Skitarii_veil_south.png diff --git a/Textures/Wula/Apparel/WULA_official_uniform.png b/Content/Textures/Wula/Apparel/WULA_official_uniform.png similarity index 100% rename from Textures/Wula/Apparel/WULA_official_uniform.png rename to Content/Textures/Wula/Apparel/WULA_official_uniform.png diff --git a/Textures/Wula/Apparel/WULA_official_uniform_Thin_east.png b/Content/Textures/Wula/Apparel/WULA_official_uniform_Thin_east.png similarity index 100% rename from Textures/Wula/Apparel/WULA_official_uniform_Thin_east.png rename to Content/Textures/Wula/Apparel/WULA_official_uniform_Thin_east.png diff --git a/Textures/Wula/Apparel/WULA_official_uniform_Thin_north.png b/Content/Textures/Wula/Apparel/WULA_official_uniform_Thin_north.png similarity index 100% rename from Textures/Wula/Apparel/WULA_official_uniform_Thin_north.png rename to Content/Textures/Wula/Apparel/WULA_official_uniform_Thin_north.png diff --git a/Textures/Wula/Apparel/WULA_official_uniform_Thin_south.png b/Content/Textures/Wula/Apparel/WULA_official_uniform_Thin_south.png similarity index 100% rename from Textures/Wula/Apparel/WULA_official_uniform_Thin_south.png rename to Content/Textures/Wula/Apparel/WULA_official_uniform_Thin_south.png diff --git a/Textures/Wula/Apparel/WULA_official_uniform_Thin_west.png b/Content/Textures/Wula/Apparel/WULA_official_uniform_Thin_west.png similarity index 100% rename from Textures/Wula/Apparel/WULA_official_uniform_Thin_west.png rename to Content/Textures/Wula/Apparel/WULA_official_uniform_Thin_west.png diff --git a/Textures/Wula/Building/Door/WulaAutodoor.png b/Content/Textures/Wula/Building/Door/WulaAutodoor.png similarity index 100% rename from Textures/Wula/Building/Door/WulaAutodoor.png rename to Content/Textures/Wula/Building/Door/WulaAutodoor.png diff --git a/Textures/Wula/Building/Door/WulaAutodoor_BluePrint.png b/Content/Textures/Wula/Building/Door/WulaAutodoor_BluePrint.png similarity index 100% rename from Textures/Wula/Building/Door/WulaAutodoor_BluePrint.png rename to Content/Textures/Wula/Building/Door/WulaAutodoor_BluePrint.png diff --git a/Textures/Wula/Building/Door/WulaAutodoor_Mover.png b/Content/Textures/Wula/Building/Door/WulaAutodoor_Mover.png similarity index 100% rename from Textures/Wula/Building/Door/WulaAutodoor_Mover.png rename to Content/Textures/Wula/Building/Door/WulaAutodoor_Mover.png diff --git a/Textures/Wula/Building/Door/WulaAutodoor_Mover_east.png b/Content/Textures/Wula/Building/Door/WulaAutodoor_Mover_east.png similarity index 100% rename from Textures/Wula/Building/Door/WulaAutodoor_Mover_east.png rename to Content/Textures/Wula/Building/Door/WulaAutodoor_Mover_east.png diff --git a/Textures/Wula/Building/Door/WulaAutodoor_Mover_south.png b/Content/Textures/Wula/Building/Door/WulaAutodoor_Mover_south.png similarity index 100% rename from Textures/Wula/Building/Door/WulaAutodoor_Mover_south.png rename to Content/Textures/Wula/Building/Door/WulaAutodoor_Mover_south.png diff --git a/Textures/Wula/Building/Door/WulaAutodoor_east.png b/Content/Textures/Wula/Building/Door/WulaAutodoor_east.png similarity index 100% rename from Textures/Wula/Building/Door/WulaAutodoor_east.png rename to Content/Textures/Wula/Building/Door/WulaAutodoor_east.png diff --git a/Textures/Wula/Building/Door/WulaAutodoor_south.png b/Content/Textures/Wula/Building/Door/WulaAutodoor_south.png similarity index 100% rename from Textures/Wula/Building/Door/WulaAutodoor_south.png rename to Content/Textures/Wula/Building/Door/WulaAutodoor_south.png diff --git a/Textures/Wula/Building/Linked/WULA_Fortress_Wall_Blueprint.png b/Content/Textures/Wula/Building/Linked/WULA_Fortress_Wall_Blueprint.png similarity index 100% rename from Textures/Wula/Building/Linked/WULA_Fortress_Wall_Blueprint.png rename to Content/Textures/Wula/Building/Linked/WULA_Fortress_Wall_Blueprint.png diff --git a/Textures/Wula/Building/Linked/WULA_Fortress_Wall_MenuIcon.png b/Content/Textures/Wula/Building/Linked/WULA_Fortress_Wall_MenuIcon.png similarity index 100% rename from Textures/Wula/Building/Linked/WULA_Fortress_Wall_MenuIcon.png rename to Content/Textures/Wula/Building/Linked/WULA_Fortress_Wall_MenuIcon.png diff --git a/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_northeast.png b/Content/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_northeast.png similarity index 100% rename from Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_northeast.png rename to Content/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_northeast.png diff --git a/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_northwest.png b/Content/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_northwest.png similarity index 100% rename from Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_northwest.png rename to Content/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_northwest.png diff --git a/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_southeast.png b/Content/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_southeast.png similarity index 100% rename from Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_southeast.png rename to Content/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_southeast.png diff --git a/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_southwest.png b/Content/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_southwest.png similarity index 100% rename from Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_southwest.png rename to Content/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_southwest.png diff --git a/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_northeast.png b/Content/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_northeast.png similarity index 100% rename from Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_northeast.png rename to Content/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_northeast.png diff --git a/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_northwest.png b/Content/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_northwest.png similarity index 100% rename from Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_northwest.png rename to Content/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_northwest.png diff --git a/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_southeast.png b/Content/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_southeast.png similarity index 100% rename from Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_southeast.png rename to Content/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_southeast.png diff --git a/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_southwest.png b/Content/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_southwest.png similarity index 100% rename from Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_southwest.png rename to Content/Textures/Wula/Building/Linked/WulaWall/AngledWulaWall_southwest.png diff --git a/Textures/Wula/Building/Linked/WulaWall/SubstructureCorner_Full_east.psd b/Content/Textures/Wula/Building/Linked/WulaWall/SubstructureCorner_Full_east.psd similarity index 100% rename from Textures/Wula/Building/Linked/WulaWall/SubstructureCorner_Full_east.psd rename to Content/Textures/Wula/Building/Linked/WulaWall/SubstructureCorner_Full_east.psd diff --git a/Textures/Wula/Building/Linked/WulaWall/SubstructureCorner_Full_west.psd b/Content/Textures/Wula/Building/Linked/WulaWall/SubstructureCorner_Full_west.psd similarity index 100% rename from Textures/Wula/Building/Linked/WulaWall/SubstructureCorner_Full_west.psd rename to Content/Textures/Wula/Building/Linked/WulaWall/SubstructureCorner_Full_west.psd diff --git a/Textures/Wula/Building/Linked/WulaWall/SubstructureCorner_Tip_east.psd b/Content/Textures/Wula/Building/Linked/WulaWall/SubstructureCorner_Tip_east.psd similarity index 100% rename from Textures/Wula/Building/Linked/WulaWall/SubstructureCorner_Tip_east.psd rename to Content/Textures/Wula/Building/Linked/WulaWall/SubstructureCorner_Tip_east.psd diff --git a/Textures/Wula/Building/Linked/WulaWall/SubstructureCorner_Tip_west.psd b/Content/Textures/Wula/Building/Linked/WulaWall/SubstructureCorner_Tip_west.psd similarity index 100% rename from Textures/Wula/Building/Linked/WulaWall/SubstructureCorner_Tip_west.psd rename to Content/Textures/Wula/Building/Linked/WulaWall/SubstructureCorner_Tip_west.psd diff --git a/Textures/Wula/Building/Linked/WulaWall/WulaWall_Atlas.png b/Content/Textures/Wula/Building/Linked/WulaWall/WulaWall_Atlas.png similarity index 100% rename from Textures/Wula/Building/Linked/WulaWall/WulaWall_Atlas.png rename to Content/Textures/Wula/Building/Linked/WulaWall/WulaWall_Atlas.png diff --git a/Textures/Wula/Building/WULA_Charging_Station_Synth_east.png b/Content/Textures/Wula/Building/WULA_Charging_Station_Synth_east.png similarity index 100% rename from Textures/Wula/Building/WULA_Charging_Station_Synth_east.png rename to Content/Textures/Wula/Building/WULA_Charging_Station_Synth_east.png diff --git a/Textures/Wula/Building/WULA_Charging_Station_Synth_north.png b/Content/Textures/Wula/Building/WULA_Charging_Station_Synth_north.png similarity index 100% rename from Textures/Wula/Building/WULA_Charging_Station_Synth_north.png rename to Content/Textures/Wula/Building/WULA_Charging_Station_Synth_north.png diff --git a/Textures/Wula/Building/WULA_Charging_Station_Synth_south.png b/Content/Textures/Wula/Building/WULA_Charging_Station_Synth_south.png similarity index 100% rename from Textures/Wula/Building/WULA_Charging_Station_Synth_south.png rename to Content/Textures/Wula/Building/WULA_Charging_Station_Synth_south.png diff --git a/Textures/Wula/Building/WULA_Communicator_Station.png b/Content/Textures/Wula/Building/WULA_Communicator_Station.png similarity index 100% rename from Textures/Wula/Building/WULA_Communicator_Station.png rename to Content/Textures/Wula/Building/WULA_Communicator_Station.png diff --git a/Textures/Wula/Building/WULA_Cube_Productor_BIO_east.png b/Content/Textures/Wula/Building/WULA_Cube_Productor_BIO_east.png similarity index 100% rename from Textures/Wula/Building/WULA_Cube_Productor_BIO_east.png rename to Content/Textures/Wula/Building/WULA_Cube_Productor_BIO_east.png diff --git a/Textures/Wula/Building/WULA_Cube_Productor_BIO_north.png b/Content/Textures/Wula/Building/WULA_Cube_Productor_BIO_north.png similarity index 100% rename from Textures/Wula/Building/WULA_Cube_Productor_BIO_north.png rename to Content/Textures/Wula/Building/WULA_Cube_Productor_BIO_north.png diff --git a/Textures/Wula/Building/WULA_Cube_Productor_BIO_south.png b/Content/Textures/Wula/Building/WULA_Cube_Productor_BIO_south.png similarity index 100% rename from Textures/Wula/Building/WULA_Cube_Productor_BIO_south.png rename to Content/Textures/Wula/Building/WULA_Cube_Productor_BIO_south.png diff --git a/Textures/Wula/Building/WULA_Cube_Productor_Component_east.png b/Content/Textures/Wula/Building/WULA_Cube_Productor_Component_east.png similarity index 100% rename from Textures/Wula/Building/WULA_Cube_Productor_Component_east.png rename to Content/Textures/Wula/Building/WULA_Cube_Productor_Component_east.png diff --git a/Textures/Wula/Building/WULA_Cube_Productor_Component_north.png b/Content/Textures/Wula/Building/WULA_Cube_Productor_Component_north.png similarity index 100% rename from Textures/Wula/Building/WULA_Cube_Productor_Component_north.png rename to Content/Textures/Wula/Building/WULA_Cube_Productor_Component_north.png diff --git a/Textures/Wula/Building/WULA_Cube_Productor_Component_south.png b/Content/Textures/Wula/Building/WULA_Cube_Productor_Component_south.png similarity index 100% rename from Textures/Wula/Building/WULA_Cube_Productor_Component_south.png rename to Content/Textures/Wula/Building/WULA_Cube_Productor_Component_south.png diff --git a/Textures/Wula/Building/WULA_Cube_Productor_Energy_east.png b/Content/Textures/Wula/Building/WULA_Cube_Productor_Energy_east.png similarity index 100% rename from Textures/Wula/Building/WULA_Cube_Productor_Energy_east.png rename to Content/Textures/Wula/Building/WULA_Cube_Productor_Energy_east.png diff --git a/Textures/Wula/Building/WULA_Cube_Productor_Energy_north.png b/Content/Textures/Wula/Building/WULA_Cube_Productor_Energy_north.png similarity index 100% rename from Textures/Wula/Building/WULA_Cube_Productor_Energy_north.png rename to Content/Textures/Wula/Building/WULA_Cube_Productor_Energy_north.png diff --git a/Textures/Wula/Building/WULA_Cube_Productor_Energy_south.png b/Content/Textures/Wula/Building/WULA_Cube_Productor_Energy_south.png similarity index 100% rename from Textures/Wula/Building/WULA_Cube_Productor_Energy_south.png rename to Content/Textures/Wula/Building/WULA_Cube_Productor_Energy_south.png diff --git a/Textures/Wula/Building/WULA_Floor.png b/Content/Textures/Wula/Building/WULA_Floor.png similarity index 100% rename from Textures/Wula/Building/WULA_Floor.png rename to Content/Textures/Wula/Building/WULA_Floor.png diff --git a/Textures/Wula/Building/WULA_Floor_Icon.png b/Content/Textures/Wula/Building/WULA_Floor_Icon.png similarity index 100% rename from Textures/Wula/Building/WULA_Floor_Icon.png rename to Content/Textures/Wula/Building/WULA_Floor_Icon.png diff --git a/Textures/Wula/Building/WULA_Heavy_War_Machine_Productor_east.png b/Content/Textures/Wula/Building/WULA_Heavy_War_Machine_Productor_east.png similarity index 100% rename from Textures/Wula/Building/WULA_Heavy_War_Machine_Productor_east.png rename to Content/Textures/Wula/Building/WULA_Heavy_War_Machine_Productor_east.png diff --git a/Textures/Wula/Building/WULA_Heavy_War_Machine_Productor_north.png b/Content/Textures/Wula/Building/WULA_Heavy_War_Machine_Productor_north.png similarity index 100% rename from Textures/Wula/Building/WULA_Heavy_War_Machine_Productor_north.png rename to Content/Textures/Wula/Building/WULA_Heavy_War_Machine_Productor_north.png diff --git a/Textures/Wula/Building/WULA_Heavy_War_Machine_Productor_south.png b/Content/Textures/Wula/Building/WULA_Heavy_War_Machine_Productor_south.png similarity index 100% rename from Textures/Wula/Building/WULA_Heavy_War_Machine_Productor_south.png rename to Content/Textures/Wula/Building/WULA_Heavy_War_Machine_Productor_south.png diff --git a/Textures/Wula/Building/WULA_Nourishment_Center_Unit.png b/Content/Textures/Wula/Building/WULA_Nourishment_Center_Unit.png similarity index 100% rename from Textures/Wula/Building/WULA_Nourishment_Center_Unit.png rename to Content/Textures/Wula/Building/WULA_Nourishment_Center_Unit.png diff --git a/Textures/Wula/Building/WULA_Synth_Maintainer_south.png b/Content/Textures/Wula/Building/WULA_Synth_Maintainer_south.png similarity index 100% rename from Textures/Wula/Building/WULA_Synth_Maintainer_south.png rename to Content/Textures/Wula/Building/WULA_Synth_Maintainer_south.png diff --git a/Textures/Wula/Building/WULA_Synth_Server_east.png b/Content/Textures/Wula/Building/WULA_Synth_Server_east.png similarity index 100% rename from Textures/Wula/Building/WULA_Synth_Server_east.png rename to Content/Textures/Wula/Building/WULA_Synth_Server_east.png diff --git a/Textures/Wula/Building/WULA_Synth_Server_north.png b/Content/Textures/Wula/Building/WULA_Synth_Server_north.png similarity index 100% rename from Textures/Wula/Building/WULA_Synth_Server_north.png rename to Content/Textures/Wula/Building/WULA_Synth_Server_north.png diff --git a/Textures/Wula/Building/WULA_Synth_Server_south.png b/Content/Textures/Wula/Building/WULA_Synth_Server_south.png similarity index 100% rename from Textures/Wula/Building/WULA_Synth_Server_south.png rename to Content/Textures/Wula/Building/WULA_Synth_Server_south.png diff --git a/Textures/Wula/Building/WULA_Turret_Component.png b/Content/Textures/Wula/Building/WULA_Turret_Component.png similarity index 100% rename from Textures/Wula/Building/WULA_Turret_Component.png rename to Content/Textures/Wula/Building/WULA_Turret_Component.png diff --git a/Textures/Wula/Building/WULA_WM_Panzer_Autocannon.png b/Content/Textures/Wula/Building/WULA_WM_Panzer_Autocannon.png similarity index 100% rename from Textures/Wula/Building/WULA_WM_Panzer_Autocannon.png rename to Content/Textures/Wula/Building/WULA_WM_Panzer_Autocannon.png diff --git a/Textures/Wula/Building/Wula_AI_Heavy_Panzer_Gunnery_Turret.png b/Content/Textures/Wula/Building/Wula_AI_Heavy_Panzer_Gunnery_Turret.png similarity index 100% rename from Textures/Wula/Building/Wula_AI_Heavy_Panzer_Gunnery_Turret.png rename to Content/Textures/Wula/Building/Wula_AI_Heavy_Panzer_Gunnery_Turret.png diff --git a/Textures/Wula/Building/Wula_DarkEnergy_FuelTank.png b/Content/Textures/Wula/Building/Wula_DarkEnergy_FuelTank.png similarity index 100% rename from Textures/Wula/Building/Wula_DarkEnergy_FuelTank.png rename to Content/Textures/Wula/Building/Wula_DarkEnergy_FuelTank.png diff --git a/Textures/Wula/Building/Wula_DarkEnergy_FuelTank_east.png b/Content/Textures/Wula/Building/Wula_DarkEnergy_FuelTank_east.png similarity index 100% rename from Textures/Wula/Building/Wula_DarkEnergy_FuelTank_east.png rename to Content/Textures/Wula/Building/Wula_DarkEnergy_FuelTank_east.png diff --git a/Textures/Wula/Building/Wula_DarkEnergy_FuelTank_north.png b/Content/Textures/Wula/Building/Wula_DarkEnergy_FuelTank_north.png similarity index 100% rename from Textures/Wula/Building/Wula_DarkEnergy_FuelTank_north.png rename to Content/Textures/Wula/Building/Wula_DarkEnergy_FuelTank_north.png diff --git a/Textures/Wula/Building/Wula_DarkEnergy_FuelTank_south.png b/Content/Textures/Wula/Building/Wula_DarkEnergy_FuelTank_south.png similarity index 100% rename from Textures/Wula/Building/Wula_DarkEnergy_FuelTank_south.png rename to Content/Textures/Wula/Building/Wula_DarkEnergy_FuelTank_south.png diff --git a/Textures/Wula/Events/Portraits/WULA_Anisia_1.png b/Content/Textures/Wula/Events/Portraits/WULA_Anisia_1.png similarity index 100% rename from Textures/Wula/Events/Portraits/WULA_Anisia_1.png rename to Content/Textures/Wula/Events/Portraits/WULA_Anisia_1.png diff --git a/Textures/Wula/Events/Portraits/WULA_Anisia_2.png b/Content/Textures/Wula/Events/Portraits/WULA_Anisia_2.png similarity index 100% rename from Textures/Wula/Events/Portraits/WULA_Anisia_2.png rename to Content/Textures/Wula/Events/Portraits/WULA_Anisia_2.png diff --git a/Textures/Wula/Events/Portraits/WULA_Anisia_3.png b/Content/Textures/Wula/Events/Portraits/WULA_Anisia_3.png similarity index 100% rename from Textures/Wula/Events/Portraits/WULA_Anisia_3.png rename to Content/Textures/Wula/Events/Portraits/WULA_Anisia_3.png diff --git a/Textures/Wula/Events/Portraits/WULA_Anisia_4.png b/Content/Textures/Wula/Events/Portraits/WULA_Anisia_4.png similarity index 100% rename from Textures/Wula/Events/Portraits/WULA_Anisia_4.png rename to Content/Textures/Wula/Events/Portraits/WULA_Anisia_4.png diff --git a/Textures/Wula/Events/Portraits/WULA_Anisia_5.png b/Content/Textures/Wula/Events/Portraits/WULA_Anisia_5.png similarity index 100% rename from Textures/Wula/Events/Portraits/WULA_Anisia_5.png rename to Content/Textures/Wula/Events/Portraits/WULA_Anisia_5.png diff --git a/Textures/Wula/Events/Portraits/WULA_Anisia_6.png b/Content/Textures/Wula/Events/Portraits/WULA_Anisia_6.png similarity index 100% rename from Textures/Wula/Events/Portraits/WULA_Anisia_6.png rename to Content/Textures/Wula/Events/Portraits/WULA_Anisia_6.png diff --git a/Textures/Wula/Events/Portraits/WULA_FE_Spiritualist_1.png b/Content/Textures/Wula/Events/Portraits/WULA_FE_Spiritualist_1.png similarity index 100% rename from Textures/Wula/Events/Portraits/WULA_FE_Spiritualist_1.png rename to Content/Textures/Wula/Events/Portraits/WULA_FE_Spiritualist_1.png diff --git a/Textures/Wula/Events/Portraits/WULA_FE_Spiritualist_2.png b/Content/Textures/Wula/Events/Portraits/WULA_FE_Spiritualist_2.png similarity index 100% rename from Textures/Wula/Events/Portraits/WULA_FE_Spiritualist_2.png rename to Content/Textures/Wula/Events/Portraits/WULA_FE_Spiritualist_2.png diff --git a/Textures/Wula/Events/Portraits/WULA_FE_Spiritualist_3.png b/Content/Textures/Wula/Events/Portraits/WULA_FE_Spiritualist_3.png similarity index 100% rename from Textures/Wula/Events/Portraits/WULA_FE_Spiritualist_3.png rename to Content/Textures/Wula/Events/Portraits/WULA_FE_Spiritualist_3.png diff --git a/Textures/Wula/Events/Portraits/WULA_FE_Spiritualist_4.png b/Content/Textures/Wula/Events/Portraits/WULA_FE_Spiritualist_4.png similarity index 100% rename from Textures/Wula/Events/Portraits/WULA_FE_Spiritualist_4.png rename to Content/Textures/Wula/Events/Portraits/WULA_FE_Spiritualist_4.png diff --git a/Textures/Wula/Events/Portraits/Wula_insignal.png b/Content/Textures/Wula/Events/Portraits/Wula_insignal.png similarity index 100% rename from Textures/Wula/Events/Portraits/Wula_insignal.png rename to Content/Textures/Wula/Events/Portraits/Wula_insignal.png diff --git a/Textures/Wula/Hair/WULA_Double_Ponytail_Long_east.png b/Content/Textures/Wula/Hair/WULA_Double_Ponytail_Long_east.png similarity index 100% rename from Textures/Wula/Hair/WULA_Double_Ponytail_Long_east.png rename to Content/Textures/Wula/Hair/WULA_Double_Ponytail_Long_east.png diff --git a/Textures/Wula/Hair/WULA_Double_Ponytail_Long_north.png b/Content/Textures/Wula/Hair/WULA_Double_Ponytail_Long_north.png similarity index 100% rename from Textures/Wula/Hair/WULA_Double_Ponytail_Long_north.png rename to Content/Textures/Wula/Hair/WULA_Double_Ponytail_Long_north.png diff --git a/Textures/Wula/Hair/WULA_Double_Ponytail_Long_south.png b/Content/Textures/Wula/Hair/WULA_Double_Ponytail_Long_south.png similarity index 100% rename from Textures/Wula/Hair/WULA_Double_Ponytail_Long_south.png rename to Content/Textures/Wula/Hair/WULA_Double_Ponytail_Long_south.png diff --git a/Textures/Wula/Hair/WULA_High_Ponytail_east.png b/Content/Textures/Wula/Hair/WULA_High_Ponytail_east.png similarity index 100% rename from Textures/Wula/Hair/WULA_High_Ponytail_east.png rename to Content/Textures/Wula/Hair/WULA_High_Ponytail_east.png diff --git a/Textures/Wula/Hair/WULA_High_Ponytail_north.png b/Content/Textures/Wula/Hair/WULA_High_Ponytail_north.png similarity index 100% rename from Textures/Wula/Hair/WULA_High_Ponytail_north.png rename to Content/Textures/Wula/Hair/WULA_High_Ponytail_north.png diff --git a/Textures/Wula/Hair/WULA_High_Ponytail_south.png b/Content/Textures/Wula/Hair/WULA_High_Ponytail_south.png similarity index 100% rename from Textures/Wula/Hair/WULA_High_Ponytail_south.png rename to Content/Textures/Wula/Hair/WULA_High_Ponytail_south.png diff --git a/Textures/Wula/Hair/WULA_One_Side_Ponytail_east.png b/Content/Textures/Wula/Hair/WULA_One_Side_Ponytail_east.png similarity index 100% rename from Textures/Wula/Hair/WULA_One_Side_Ponytail_east.png rename to Content/Textures/Wula/Hair/WULA_One_Side_Ponytail_east.png diff --git a/Textures/Wula/Hair/WULA_One_Side_Ponytail_north.png b/Content/Textures/Wula/Hair/WULA_One_Side_Ponytail_north.png similarity index 100% rename from Textures/Wula/Hair/WULA_One_Side_Ponytail_north.png rename to Content/Textures/Wula/Hair/WULA_One_Side_Ponytail_north.png diff --git a/Textures/Wula/Hair/WULA_One_Side_Ponytail_south.png b/Content/Textures/Wula/Hair/WULA_One_Side_Ponytail_south.png similarity index 100% rename from Textures/Wula/Hair/WULA_One_Side_Ponytail_south.png rename to Content/Textures/Wula/Hair/WULA_One_Side_Ponytail_south.png diff --git a/Textures/Wula/Hair/WULA_One_Side_Ponytail_west.png b/Content/Textures/Wula/Hair/WULA_One_Side_Ponytail_west.png similarity index 100% rename from Textures/Wula/Hair/WULA_One_Side_Ponytail_west.png rename to Content/Textures/Wula/Hair/WULA_One_Side_Ponytail_west.png diff --git a/Textures/Wula/Hair/WULA_Rotational_Ponytail_east.png b/Content/Textures/Wula/Hair/WULA_Rotational_Ponytail_east.png similarity index 100% rename from Textures/Wula/Hair/WULA_Rotational_Ponytail_east.png rename to Content/Textures/Wula/Hair/WULA_Rotational_Ponytail_east.png diff --git a/Textures/Wula/Hair/WULA_Rotational_Ponytail_north.png b/Content/Textures/Wula/Hair/WULA_Rotational_Ponytail_north.png similarity index 100% rename from Textures/Wula/Hair/WULA_Rotational_Ponytail_north.png rename to Content/Textures/Wula/Hair/WULA_Rotational_Ponytail_north.png diff --git a/Textures/Wula/Hair/WULA_Rotational_Ponytail_south.png b/Content/Textures/Wula/Hair/WULA_Rotational_Ponytail_south.png similarity index 100% rename from Textures/Wula/Hair/WULA_Rotational_Ponytail_south.png rename to Content/Textures/Wula/Hair/WULA_Rotational_Ponytail_south.png diff --git a/Textures/Wula/Hair/WULA_Scattered_Hair_Long_east.png b/Content/Textures/Wula/Hair/WULA_Scattered_Hair_Long_east.png similarity index 100% rename from Textures/Wula/Hair/WULA_Scattered_Hair_Long_east.png rename to Content/Textures/Wula/Hair/WULA_Scattered_Hair_Long_east.png diff --git a/Textures/Wula/Hair/WULA_Scattered_Hair_Long_north.png b/Content/Textures/Wula/Hair/WULA_Scattered_Hair_Long_north.png similarity index 100% rename from Textures/Wula/Hair/WULA_Scattered_Hair_Long_north.png rename to Content/Textures/Wula/Hair/WULA_Scattered_Hair_Long_north.png diff --git a/Textures/Wula/Hair/WULA_Scattered_Hair_Long_south.png b/Content/Textures/Wula/Hair/WULA_Scattered_Hair_Long_south.png similarity index 100% rename from Textures/Wula/Hair/WULA_Scattered_Hair_Long_south.png rename to Content/Textures/Wula/Hair/WULA_Scattered_Hair_Long_south.png diff --git a/Textures/Wula/Item/WULA_Charge_Cube.png b/Content/Textures/Wula/Item/WULA_Charge_Cube.png similarity index 100% rename from Textures/Wula/Item/WULA_Charge_Cube.png rename to Content/Textures/Wula/Item/WULA_Charge_Cube.png diff --git a/Textures/Wula/Item/WULA_Dark_Matter_Item.png b/Content/Textures/Wula/Item/WULA_Dark_Matter_Item.png similarity index 100% rename from Textures/Wula/Item/WULA_Dark_Matter_Item.png rename to Content/Textures/Wula/Item/WULA_Dark_Matter_Item.png diff --git a/Textures/Wula/Item/WULA_Default_Item.png b/Content/Textures/Wula/Item/WULA_Default_Item.png similarity index 100% rename from Textures/Wula/Item/WULA_Default_Item.png rename to Content/Textures/Wula/Item/WULA_Default_Item.png diff --git a/Textures/Wula/Item/WULA_MechRepairKit.png b/Content/Textures/Wula/Item/WULA_MechRepairKit.png similarity index 100% rename from Textures/Wula/Item/WULA_MechRepairKit.png rename to Content/Textures/Wula/Item/WULA_MechRepairKit.png diff --git a/Textures/Wula/Item/WULA_Neutronium.png b/Content/Textures/Wula/Item/WULA_Neutronium.png similarity index 100% rename from Textures/Wula/Item/WULA_Neutronium.png rename to Content/Textures/Wula/Item/WULA_Neutronium.png diff --git a/Textures/Wula/Item/WULA_Soul_Wedge.png b/Content/Textures/Wula/Item/WULA_Soul_Wedge.png similarity index 100% rename from Textures/Wula/Item/WULA_Soul_Wedge.png rename to Content/Textures/Wula/Item/WULA_Soul_Wedge.png diff --git a/Textures/Wula/Item/WULA_Syhth_Passion_Trainer.png b/Content/Textures/Wula/Item/WULA_Syhth_Passion_Trainer.png similarity index 100% rename from Textures/Wula/Item/WULA_Syhth_Passion_Trainer.png rename to Content/Textures/Wula/Item/WULA_Syhth_Passion_Trainer.png diff --git a/Textures/Wula/Item/WULA_Syhth_Trainer.png b/Content/Textures/Wula/Item/WULA_Syhth_Trainer.png similarity index 100% rename from Textures/Wula/Item/WULA_Syhth_Trainer.png rename to Content/Textures/Wula/Item/WULA_Syhth_Trainer.png diff --git a/Textures/Wula/Item/WULA_charge_cube_No_Power.png b/Content/Textures/Wula/Item/WULA_charge_cube_No_Power.png similarity index 100% rename from Textures/Wula/Item/WULA_charge_cube_No_Power.png rename to Content/Textures/Wula/Item/WULA_charge_cube_No_Power.png diff --git a/Textures/Wula/Item/Wula_Zro.png b/Content/Textures/Wula/Item/Wula_Zro.png similarity index 100% rename from Textures/Wula/Item/Wula_Zro.png rename to Content/Textures/Wula/Item/Wula_Zro.png diff --git a/Textures/Wula/Mote/WULA_Bullet_Dark_Matter_Beam.png b/Content/Textures/Wula/Mote/WULA_Bullet_Dark_Matter_Beam.png similarity index 100% rename from Textures/Wula/Mote/WULA_Bullet_Dark_Matter_Beam.png rename to Content/Textures/Wula/Mote/WULA_Bullet_Dark_Matter_Beam.png diff --git a/Textures/Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red.png b/Content/Textures/Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red.png similarity index 100% rename from Textures/Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red.png rename to Content/Textures/Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red.png diff --git a/Textures/Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red_Double.png b/Content/Textures/Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red_Double.png similarity index 100% rename from Textures/Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red_Double.png rename to Content/Textures/Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red_Double.png diff --git a/Textures/Wula/Projectile/WULA_Bullet_StarDrift_Shotgun_Spear.png b/Content/Textures/Wula/Projectile/WULA_Bullet_StarDrift_Shotgun_Spear.png similarity index 100% rename from Textures/Wula/Projectile/WULA_Bullet_StarDrift_Shotgun_Spear.png rename to Content/Textures/Wula/Projectile/WULA_Bullet_StarDrift_Shotgun_Spear.png diff --git a/Textures/Wula/Projectile/WULA_Mortar_Shell.png b/Content/Textures/Wula/Projectile/WULA_Mortar_Shell.png similarity index 100% rename from Textures/Wula/Projectile/WULA_Mortar_Shell.png rename to Content/Textures/Wula/Projectile/WULA_Mortar_Shell.png diff --git a/Textures/Wula/Projectile/WULA_Photon_Missile.png b/Content/Textures/Wula/Projectile/WULA_Photon_Missile.png similarity index 100% rename from Textures/Wula/Projectile/WULA_Photon_Missile.png rename to Content/Textures/Wula/Projectile/WULA_Photon_Missile.png diff --git a/Textures/Wula/Projectile/WULA_Shrapnel.png b/Content/Textures/Wula/Projectile/WULA_Shrapnel.png similarity index 100% rename from Textures/Wula/Projectile/WULA_Shrapnel.png rename to Content/Textures/Wula/Projectile/WULA_Shrapnel.png diff --git a/Textures/Wula/Storyteller/WULA_Anisia.png b/Content/Textures/Wula/Storyteller/WULA_Anisia.png similarity index 100% rename from Textures/Wula/Storyteller/WULA_Anisia.png rename to Content/Textures/Wula/Storyteller/WULA_Anisia.png diff --git a/Textures/Wula/Storyteller/WULA_Anisia_TINY.png b/Content/Textures/Wula/Storyteller/WULA_Anisia_TINY.png similarity index 100% rename from Textures/Wula/Storyteller/WULA_Anisia_TINY.png rename to Content/Textures/Wula/Storyteller/WULA_Anisia_TINY.png diff --git a/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_east.dds b/Content/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_east.dds similarity index 100% rename from Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_east.dds rename to Content/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_east.dds diff --git a/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_east.png b/Content/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_east.png similarity index 100% rename from Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_east.png rename to Content/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_east.png diff --git a/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_north.dds b/Content/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_north.dds similarity index 100% rename from Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_north.dds rename to Content/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_north.dds diff --git a/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_north.png b/Content/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_north.png similarity index 100% rename from Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_north.png rename to Content/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_north.png diff --git a/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_south.dds b/Content/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_south.dds similarity index 100% rename from Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_south.dds rename to Content/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_south.dds diff --git a/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_south.png b/Content/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_south.png similarity index 100% rename from Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_south.png rename to Content/Textures/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_south.png diff --git a/Textures/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_east.png b/Content/Textures/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_east.png similarity index 100% rename from Textures/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_east.png rename to Content/Textures/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_east.png diff --git a/Textures/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_north.png b/Content/Textures/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_north.png similarity index 100% rename from Textures/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_north.png rename to Content/Textures/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_north.png diff --git a/Textures/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_south.png b/Content/Textures/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_south.png similarity index 100% rename from Textures/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_south.png rename to Content/Textures/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_south.png diff --git a/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_east.dds b/Content/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_east.dds similarity index 100% rename from Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_east.dds rename to Content/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_east.dds diff --git a/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_east.png b/Content/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_east.png similarity index 100% rename from Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_east.png rename to Content/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_east.png diff --git a/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_north.dds b/Content/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_north.dds similarity index 100% rename from Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_north.dds rename to Content/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_north.dds diff --git a/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_north.png b/Content/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_north.png similarity index 100% rename from Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_north.png rename to Content/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_north.png diff --git a/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_south.dds b/Content/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_south.dds similarity index 100% rename from Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_south.dds rename to Content/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_south.dds diff --git a/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_south.png b/Content/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_south.png similarity index 100% rename from Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_south.png rename to Content/Textures/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_south.png diff --git a/Textures/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_east.png b/Content/Textures/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_east.png similarity index 100% rename from Textures/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_east.png rename to Content/Textures/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_east.png diff --git a/Textures/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_north.png b/Content/Textures/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_north.png similarity index 100% rename from Textures/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_north.png rename to Content/Textures/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_north.png diff --git a/Textures/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_south.png b/Content/Textures/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_south.png similarity index 100% rename from Textures/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_south.png rename to Content/Textures/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_south.png diff --git a/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_east.dds b/Content/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_east.dds similarity index 100% rename from Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_east.dds rename to Content/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_east.dds diff --git a/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_east.png b/Content/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_east.png similarity index 100% rename from Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_east.png rename to Content/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_east.png diff --git a/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_north.dds b/Content/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_north.dds similarity index 100% rename from Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_north.dds rename to Content/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_north.dds diff --git a/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_north.png b/Content/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_north.png similarity index 100% rename from Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_north.png rename to Content/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_north.png diff --git a/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_south.dds b/Content/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_south.dds similarity index 100% rename from Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_south.dds rename to Content/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_south.dds diff --git a/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_south.png b/Content/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_south.png similarity index 100% rename from Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_south.png rename to Content/Textures/Wula/Things/WULA_Cat/AllegianceOverlays/None_south.png diff --git a/Textures/Wula/Things/WULA_Cat/WULA_Cat_Thin_east.png b/Content/Textures/Wula/Things/WULA_Cat/WULA_Cat_Thin_east.png similarity index 100% rename from Textures/Wula/Things/WULA_Cat/WULA_Cat_Thin_east.png rename to Content/Textures/Wula/Things/WULA_Cat/WULA_Cat_Thin_east.png diff --git a/Textures/Wula/Things/WULA_Cat/WULA_Cat_Thin_north.png b/Content/Textures/Wula/Things/WULA_Cat/WULA_Cat_Thin_north.png similarity index 100% rename from Textures/Wula/Things/WULA_Cat/WULA_Cat_Thin_north.png rename to Content/Textures/Wula/Things/WULA_Cat/WULA_Cat_Thin_north.png diff --git a/Textures/Wula/Things/WULA_Cat/WULA_Cat_Thin_south.png b/Content/Textures/Wula/Things/WULA_Cat/WULA_Cat_Thin_south.png similarity index 100% rename from Textures/Wula/Things/WULA_Cat/WULA_Cat_Thin_south.png rename to Content/Textures/Wula/Things/WULA_Cat/WULA_Cat_Thin_south.png diff --git a/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_east.dds b/Content/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_east.dds similarity index 100% rename from Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_east.dds rename to Content/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_east.dds diff --git a/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_east.png b/Content/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_east.png similarity index 100% rename from Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_east.png rename to Content/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_east.png diff --git a/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_north.dds b/Content/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_north.dds similarity index 100% rename from Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_north.dds rename to Content/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_north.dds diff --git a/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_north.png b/Content/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_north.png similarity index 100% rename from Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_north.png rename to Content/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_north.png diff --git a/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_south.dds b/Content/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_south.dds similarity index 100% rename from Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_south.dds rename to Content/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_south.dds diff --git a/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_south.png b/Content/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_south.png similarity index 100% rename from Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_south.png rename to Content/Textures/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_south.png diff --git a/Textures/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_east.png b/Content/Textures/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_east.png similarity index 100% rename from Textures/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_east.png rename to Content/Textures/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_east.png diff --git a/Textures/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_north.png b/Content/Textures/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_north.png similarity index 100% rename from Textures/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_north.png rename to Content/Textures/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_north.png diff --git a/Textures/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_south.png b/Content/Textures/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_south.png similarity index 100% rename from Textures/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_south.png rename to Content/Textures/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_south.png diff --git a/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_east.dds b/Content/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_east.dds similarity index 100% rename from Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_east.dds rename to Content/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_east.dds diff --git a/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_east.png b/Content/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_east.png similarity index 100% rename from Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_east.png rename to Content/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_east.png diff --git a/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_north.dds b/Content/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_north.dds similarity index 100% rename from Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_north.dds rename to Content/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_north.dds diff --git a/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_north.png b/Content/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_north.png similarity index 100% rename from Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_north.png rename to Content/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_north.png diff --git a/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_south.dds b/Content/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_south.dds similarity index 100% rename from Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_south.dds rename to Content/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_south.dds diff --git a/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_south.png b/Content/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_south.png similarity index 100% rename from Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_south.png rename to Content/Textures/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_south.png diff --git a/Textures/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_east.png b/Content/Textures/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_east.png similarity index 100% rename from Textures/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_east.png rename to Content/Textures/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_east.png diff --git a/Textures/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_north.png b/Content/Textures/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_north.png similarity index 100% rename from Textures/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_north.png rename to Content/Textures/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_north.png diff --git a/Textures/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_south.png b/Content/Textures/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_south.png similarity index 100% rename from Textures/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_south.png rename to Content/Textures/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_south.png diff --git a/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_east.dds b/Content/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_east.dds similarity index 100% rename from Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_east.dds rename to Content/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_east.dds diff --git a/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_east.png b/Content/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_east.png similarity index 100% rename from Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_east.png rename to Content/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_east.png diff --git a/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_north.dds b/Content/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_north.dds similarity index 100% rename from Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_north.dds rename to Content/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_north.dds diff --git a/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_north.png b/Content/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_north.png similarity index 100% rename from Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_north.png rename to Content/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_north.png diff --git a/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_south.dds b/Content/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_south.dds similarity index 100% rename from Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_south.dds rename to Content/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_south.dds diff --git a/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_south.png b/Content/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_south.png similarity index 100% rename from Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_south.png rename to Content/Textures/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_south.png diff --git a/Textures/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_east.png b/Content/Textures/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_east.png similarity index 100% rename from Textures/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_east.png rename to Content/Textures/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_east.png diff --git a/Textures/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_north.png b/Content/Textures/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_north.png similarity index 100% rename from Textures/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_north.png rename to Content/Textures/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_north.png diff --git a/Textures/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_south.png b/Content/Textures/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_south.png similarity index 100% rename from Textures/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_south.png rename to Content/Textures/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_south.png diff --git a/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_east.dds b/Content/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_east.dds similarity index 100% rename from Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_east.dds rename to Content/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_east.dds diff --git a/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_east.png b/Content/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_east.png similarity index 100% rename from Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_east.png rename to Content/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_east.png diff --git a/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_north.dds b/Content/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_north.dds similarity index 100% rename from Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_north.dds rename to Content/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_north.dds diff --git a/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_north.png b/Content/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_north.png similarity index 100% rename from Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_north.png rename to Content/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_north.png diff --git a/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_south.dds b/Content/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_south.dds similarity index 100% rename from Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_south.dds rename to Content/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_south.dds diff --git a/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_south.png b/Content/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_south.png similarity index 100% rename from Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_south.png rename to Content/Textures/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_south.png diff --git a/Textures/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_east.png b/Content/Textures/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_east.png similarity index 100% rename from Textures/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_east.png rename to Content/Textures/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_east.png diff --git a/Textures/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_north.png b/Content/Textures/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_north.png similarity index 100% rename from Textures/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_north.png rename to Content/Textures/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_north.png diff --git a/Textures/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_south.png b/Content/Textures/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_south.png similarity index 100% rename from Textures/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_south.png rename to Content/Textures/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_east.png b/Content/Textures/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_north.png b/Content/Textures/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_north.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_north.png rename to Content/Textures/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_north.png diff --git a/Textures/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_south.png b/Content/Textures/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Bodies/Naked_Thin_east.png b/Content/Textures/Wula/Things/WulaSpecies/Bodies/Naked_Thin_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Bodies/Naked_Thin_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Bodies/Naked_Thin_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Bodies/Naked_Thin_north.png b/Content/Textures/Wula/Things/WulaSpecies/Bodies/Naked_Thin_north.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Bodies/Naked_Thin_north.png rename to Content/Textures/Wula/Things/WulaSpecies/Bodies/Naked_Thin_north.png diff --git a/Textures/Wula/Things/WulaSpecies/Bodies/Naked_Thin_south.png b/Content/Textures/Wula/Things/WulaSpecies/Bodies/Naked_Thin_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Bodies/Naked_Thin_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Bodies/Naked_Thin_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/angled_east.png b/Content/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/angled_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/angled_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/angled_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/angled_south.png b/Content/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/angled_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/angled_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/angled_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/flat_east.png b/Content/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/flat_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/flat_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/flat_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/flat_south.png b/Content/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/flat_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/flat_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/flat_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/normal_east.png b/Content/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/normal_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/normal_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/normal_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/normal_south.png b/Content/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/normal_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/normal_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/normal_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/s-shaped_east.png b/Content/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/s-shaped_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/s-shaped_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/s-shaped_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/s-shaped_south.png b/Content/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/s-shaped_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/s-shaped_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Brows/Normal/Unisex/s-shaped_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_L_east.png b/Content/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_L_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_L_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_L_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_L_south.png b/Content/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_L_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_L_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_L_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_L_west.png b/Content/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_L_west.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_L_west.png rename to Content/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_L_west.png diff --git a/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_R_east.png b/Content/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_R_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_R_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_R_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_R_south.png b/Content/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_R_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_R_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_R_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_R_west.png b/Content/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_R_west.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_R_west.png rename to Content/Textures/Wula/Things/WulaSpecies/Eyes/Common/Unisex/normal_R_west.png diff --git a/Textures/Wula/Things/WulaSpecies/Eyes/Normal/Unisex/normal_east.png b/Content/Textures/Wula/Things/WulaSpecies/Eyes/Normal/Unisex/normal_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Eyes/Normal/Unisex/normal_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Eyes/Normal/Unisex/normal_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Eyes/Normal/Unisex/normal_highlight_east.png b/Content/Textures/Wula/Things/WulaSpecies/Eyes/Normal/Unisex/normal_highlight_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Eyes/Normal/Unisex/normal_highlight_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Eyes/Normal/Unisex/normal_highlight_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Eyes/Normal/Unisex/normal_highlight_south.png b/Content/Textures/Wula/Things/WulaSpecies/Eyes/Normal/Unisex/normal_highlight_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Eyes/Normal/Unisex/normal_highlight_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Eyes/Normal/Unisex/normal_highlight_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Eyes/Normal/Unisex/normal_south.png b/Content/Textures/Wula/Things/WulaSpecies/Eyes/Normal/Unisex/normal_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Eyes/Normal/Unisex/normal_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Eyes/Normal/Unisex/normal_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Heads/Average_Normal_east.png b/Content/Textures/Wula/Things/WulaSpecies/Heads/Average_Normal_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Heads/Average_Normal_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Heads/Average_Normal_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Heads/Average_Normal_north.png b/Content/Textures/Wula/Things/WulaSpecies/Heads/Average_Normal_north.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Heads/Average_Normal_north.png rename to Content/Textures/Wula/Things/WulaSpecies/Heads/Average_Normal_north.png diff --git a/Textures/Wula/Things/WulaSpecies/Heads/Average_Normal_south.png b/Content/Textures/Wula/Things/WulaSpecies/Heads/Average_Normal_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Heads/Average_Normal_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Heads/Average_Normal_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Heads/Average_Normal_west.png b/Content/Textures/Wula/Things/WulaSpecies/Heads/Average_Normal_west.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Heads/Average_Normal_west.png rename to Content/Textures/Wula/Things/WulaSpecies/Heads/Average_Normal_west.png diff --git a/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/blush_east.png b/Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/blush_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/blush_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/blush_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/blush_north.png b/Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/blush_north.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/blush_north.png rename to Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/blush_north.png diff --git a/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/blush_south.png b/Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/blush_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/blush_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/blush_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/blush_west.png b/Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/blush_west.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/blush_west.png rename to Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/blush_west.png diff --git a/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/normal_east.png b/Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/normal_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/normal_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/normal_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/normal_north.png b/Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/normal_north.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/normal_north.png rename to Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/normal_north.png diff --git a/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/normal_south.png b/Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/normal_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/normal_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/normal_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/normal_west.png b/Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/normal_west.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/normal_west.png rename to Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/normal_west.png diff --git a/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/part_blush_east.png b/Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/part_blush_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/part_blush_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/part_blush_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/part_blush_south.png b/Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/part_blush_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/part_blush_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/part_blush_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/part_normal_east.png b/Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/part_normal_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/part_normal_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/part_normal_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/part_normal_south.png b/Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/part_normal_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/part_normal_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Heads_Blank/Normal/Unisex/part_normal_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Lids/Normal/Unisex/close_east.png b/Content/Textures/Wula/Things/WulaSpecies/Lids/Normal/Unisex/close_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Lids/Normal/Unisex/close_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Lids/Normal/Unisex/close_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Lids/Normal/Unisex/close_south.png b/Content/Textures/Wula/Things/WulaSpecies/Lids/Normal/Unisex/close_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Lids/Normal/Unisex/close_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Lids/Normal/Unisex/close_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Lids/Normal/Unisex/normal_east.png b/Content/Textures/Wula/Things/WulaSpecies/Lids/Normal/Unisex/normal_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Lids/Normal/Unisex/normal_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Lids/Normal/Unisex/normal_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Lids/Normal/Unisex/normal_south.png b/Content/Textures/Wula/Things/WulaSpecies/Lids/Normal/Unisex/normal_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Lids/Normal/Unisex/normal_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Lids/Normal/Unisex/normal_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Mouth/Normal/Unisex/normal_east.png b/Content/Textures/Wula/Things/WulaSpecies/Mouth/Normal/Unisex/normal_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Mouth/Normal/Unisex/normal_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Mouth/Normal/Unisex/normal_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Mouth/Normal/Unisex/normal_south.png b/Content/Textures/Wula/Things/WulaSpecies/Mouth/Normal/Unisex/normal_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Mouth/Normal/Unisex/normal_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Mouth/Normal/Unisex/normal_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Mouth/Normal/Unisex/open_east.png b/Content/Textures/Wula/Things/WulaSpecies/Mouth/Normal/Unisex/open_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Mouth/Normal/Unisex/open_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Mouth/Normal/Unisex/open_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Mouth/Normal/Unisex/open_south.png b/Content/Textures/Wula/Things/WulaSpecies/Mouth/Normal/Unisex/open_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Mouth/Normal/Unisex/open_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Mouth/Normal/Unisex/open_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Skins/LeftChin/Unisex/normal_east.png b/Content/Textures/Wula/Things/WulaSpecies/Skins/LeftChin/Unisex/normal_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Skins/LeftChin/Unisex/normal_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Skins/LeftChin/Unisex/normal_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Skins/LeftChin/Unisex/normal_north.png b/Content/Textures/Wula/Things/WulaSpecies/Skins/LeftChin/Unisex/normal_north.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Skins/LeftChin/Unisex/normal_north.png rename to Content/Textures/Wula/Things/WulaSpecies/Skins/LeftChin/Unisex/normal_north.png diff --git a/Textures/Wula/Things/WulaSpecies/Skins/LeftChin/Unisex/normal_south.png b/Content/Textures/Wula/Things/WulaSpecies/Skins/LeftChin/Unisex/normal_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Skins/LeftChin/Unisex/normal_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Skins/LeftChin/Unisex/normal_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Skins/LeftChin/Unisex/normal_west.png b/Content/Textures/Wula/Things/WulaSpecies/Skins/LeftChin/Unisex/normal_west.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Skins/LeftChin/Unisex/normal_west.png rename to Content/Textures/Wula/Things/WulaSpecies/Skins/LeftChin/Unisex/normal_west.png diff --git a/Textures/Wula/Things/WulaSpecies/Skins/RightEye/Unisex/normal_east.png b/Content/Textures/Wula/Things/WulaSpecies/Skins/RightEye/Unisex/normal_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Skins/RightEye/Unisex/normal_east.png rename to Content/Textures/Wula/Things/WulaSpecies/Skins/RightEye/Unisex/normal_east.png diff --git a/Textures/Wula/Things/WulaSpecies/Skins/RightEye/Unisex/normal_north.png b/Content/Textures/Wula/Things/WulaSpecies/Skins/RightEye/Unisex/normal_north.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Skins/RightEye/Unisex/normal_north.png rename to Content/Textures/Wula/Things/WulaSpecies/Skins/RightEye/Unisex/normal_north.png diff --git a/Textures/Wula/Things/WulaSpecies/Skins/RightEye/Unisex/normal_south.png b/Content/Textures/Wula/Things/WulaSpecies/Skins/RightEye/Unisex/normal_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Skins/RightEye/Unisex/normal_south.png rename to Content/Textures/Wula/Things/WulaSpecies/Skins/RightEye/Unisex/normal_south.png diff --git a/Textures/Wula/Things/WulaSpecies/Skins/RightEye/Unisex/normal_west.png b/Content/Textures/Wula/Things/WulaSpecies/Skins/RightEye/Unisex/normal_west.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Skins/RightEye/Unisex/normal_west.png rename to Content/Textures/Wula/Things/WulaSpecies/Skins/RightEye/Unisex/normal_west.png diff --git a/Textures/Wula/Things/WulaSpecies/WULA_Species_Icon.png b/Content/Textures/Wula/Things/WulaSpecies/WULA_Species_Icon.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/WULA_Species_Icon.png rename to Content/Textures/Wula/Things/WulaSpecies/WULA_Species_Icon.png diff --git a/Textures/Wula/Things/WulaSpecies/Wounds/WULA_Species_Wound_None.png b/Content/Textures/Wula/Things/WulaSpecies/Wounds/WULA_Species_Wound_None.png similarity index 100% rename from Textures/Wula/Things/WulaSpecies/Wounds/WULA_Species_Wound_None.png rename to Content/Textures/Wula/Things/WulaSpecies/Wounds/WULA_Species_Wound_None.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Addons/WULA_Bow_Tie_east.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Addons/WULA_Bow_Tie_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Addons/WULA_Bow_Tie_east.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Addons/WULA_Bow_Tie_east.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Addons/WULA_Bow_Tie_north.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Addons/WULA_Bow_Tie_north.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Addons/WULA_Bow_Tie_north.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Addons/WULA_Bow_Tie_north.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Addons/WULA_Bow_Tie_south.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Addons/WULA_Bow_Tie_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Addons/WULA_Bow_Tie_south.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Addons/WULA_Bow_Tie_south.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Bodies/Naked_Thin_east.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Bodies/Naked_Thin_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Bodies/Naked_Thin_east.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Bodies/Naked_Thin_east.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Bodies/Naked_Thin_north.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Bodies/Naked_Thin_north.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Bodies/Naked_Thin_north.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Bodies/Naked_Thin_north.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Bodies/Naked_Thin_south.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Bodies/Naked_Thin_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Bodies/Naked_Thin_south.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Bodies/Naked_Thin_south.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Heads/Average_Normal_north.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Heads/Average_Normal_north.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Heads/Average_Normal_north.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Heads/Average_Normal_north.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Heads/Average_Normal_south.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Heads/Average_Normal_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Heads/Average_Normal_south.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Heads/Average_Normal_south.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Heads/Average_Normal_west.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Heads/Average_Normal_west.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Heads/Average_Normal_west.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Heads/Average_Normal_west.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/blush_east.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/blush_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/blush_east.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/blush_east.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/blush_north.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/blush_north.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/blush_north.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/blush_north.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/blush_south.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/blush_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/blush_south.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/blush_south.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/normal_east.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/normal_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/normal_east.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/normal_east.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/normal_north.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/normal_north.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/normal_north.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/normal_north.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/normal_south.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/normal_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/normal_south.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/normal_south.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/part_blush_east.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/part_blush_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/part_blush_east.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/part_blush_east.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/part_blush_south.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/part_blush_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/part_blush_south.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/part_blush_south.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/part_normal_east.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/part_normal_east.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/part_normal_east.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/part_normal_east.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/part_normal_south.png b/Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/part_normal_south.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/part_normal_south.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/Heads_Blank/Normal/Unisex/part_normal_south.png diff --git a/Textures/Wula/Things/WulaSpeciesReal/WULA_Species_Icon.png b/Content/Textures/Wula/Things/WulaSpeciesReal/WULA_Species_Icon.png similarity index 100% rename from Textures/Wula/Things/WulaSpeciesReal/WULA_Species_Icon.png rename to Content/Textures/Wula/Things/WulaSpeciesReal/WULA_Species_Icon.png diff --git a/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_east.dds b/Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_east.dds similarity index 100% rename from Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_east.dds rename to Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_east.dds diff --git a/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_east.png b/Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_east.png similarity index 100% rename from Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_east.png rename to Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_east.png diff --git a/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_north.dds b/Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_north.dds similarity index 100% rename from Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_north.dds rename to Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_north.dds diff --git a/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_north.png b/Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_north.png similarity index 100% rename from Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_north.png rename to Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_north.png diff --git a/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_south.dds b/Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_south.dds similarity index 100% rename from Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_south.dds rename to Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_south.dds diff --git a/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_south.png b/Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_south.png similarity index 100% rename from Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_south.png rename to Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_south.png diff --git a/Textures/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_east.png b/Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_east.png similarity index 100% rename from Textures/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_east.png rename to Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_east.png diff --git a/Textures/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_north.png b/Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_north.png similarity index 100% rename from Textures/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_north.png rename to Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_north.png diff --git a/Textures/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_south.png b/Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_south.png similarity index 100% rename from Textures/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_south.png rename to Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_south.png diff --git a/Textures/Wula/Things/Wula_AI_Bomb_Mother/Wula_AI_Bomb_Mother_Icon.png b/Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/Wula_AI_Bomb_Mother_Icon.png similarity index 100% rename from Textures/Wula/Things/Wula_AI_Bomb_Mother/Wula_AI_Bomb_Mother_Icon.png rename to Content/Textures/Wula/Things/Wula_AI_Bomb_Mother/Wula_AI_Bomb_Mother_Icon.png diff --git a/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_east.dds b/Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_east.dds similarity index 100% rename from Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_east.dds rename to Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_east.dds diff --git a/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_east.png b/Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_east.png similarity index 100% rename from Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_east.png rename to Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_east.png diff --git a/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_north.dds b/Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_north.dds similarity index 100% rename from Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_north.dds rename to Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_north.dds diff --git a/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_north.png b/Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_north.png similarity index 100% rename from Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_north.png rename to Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_north.png diff --git a/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_south.dds b/Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_south.dds similarity index 100% rename from Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_south.dds rename to Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_south.dds diff --git a/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_south.png b/Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_south.png similarity index 100% rename from Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_south.png rename to Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_south.png diff --git a/Textures/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_east.png b/Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_east.png similarity index 100% rename from Textures/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_east.png rename to Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_east.png diff --git a/Textures/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_north.png b/Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_north.png similarity index 100% rename from Textures/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_north.png rename to Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_north.png diff --git a/Textures/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_south.png b/Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_south.png similarity index 100% rename from Textures/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_south.png rename to Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_south.png diff --git a/Textures/Wula/Things/Wula_AI_Heavy_Panzer/Wula_AI_Heavy_Panzer_Icon.png b/Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/Wula_AI_Heavy_Panzer_Icon.png similarity index 100% rename from Textures/Wula/Things/Wula_AI_Heavy_Panzer/Wula_AI_Heavy_Panzer_Icon.png rename to Content/Textures/Wula/Things/Wula_AI_Heavy_Panzer/Wula_AI_Heavy_Panzer_Icon.png diff --git a/Textures/Wula/Things/Wula_Armour/Bodies/Naked_Thin_east.png b/Content/Textures/Wula/Things/Wula_Armour/Bodies/Naked_Thin_east.png similarity index 100% rename from Textures/Wula/Things/Wula_Armour/Bodies/Naked_Thin_east.png rename to Content/Textures/Wula/Things/Wula_Armour/Bodies/Naked_Thin_east.png diff --git a/Textures/Wula/Things/Wula_Armour/Bodies/Naked_Thin_north.png b/Content/Textures/Wula/Things/Wula_Armour/Bodies/Naked_Thin_north.png similarity index 100% rename from Textures/Wula/Things/Wula_Armour/Bodies/Naked_Thin_north.png rename to Content/Textures/Wula/Things/Wula_Armour/Bodies/Naked_Thin_north.png diff --git a/Textures/Wula/Things/Wula_Armour/Bodies/Naked_Thin_south.png b/Content/Textures/Wula/Things/Wula_Armour/Bodies/Naked_Thin_south.png similarity index 100% rename from Textures/Wula/Things/Wula_Armour/Bodies/Naked_Thin_south.png rename to Content/Textures/Wula/Things/Wula_Armour/Bodies/Naked_Thin_south.png diff --git a/Textures/Wula/Things/Wula_Armour/Heads/Average_Normal_east.png b/Content/Textures/Wula/Things/Wula_Armour/Heads/Average_Normal_east.png similarity index 100% rename from Textures/Wula/Things/Wula_Armour/Heads/Average_Normal_east.png rename to Content/Textures/Wula/Things/Wula_Armour/Heads/Average_Normal_east.png diff --git a/Textures/Wula/Things/Wula_Armour/Heads/Average_Normal_north.png b/Content/Textures/Wula/Things/Wula_Armour/Heads/Average_Normal_north.png similarity index 100% rename from Textures/Wula/Things/Wula_Armour/Heads/Average_Normal_north.png rename to Content/Textures/Wula/Things/Wula_Armour/Heads/Average_Normal_north.png diff --git a/Textures/Wula/Things/Wula_Armour/Heads/Average_Normal_south.png b/Content/Textures/Wula/Things/Wula_Armour/Heads/Average_Normal_south.png similarity index 100% rename from Textures/Wula/Things/Wula_Armour/Heads/Average_Normal_south.png rename to Content/Textures/Wula/Things/Wula_Armour/Heads/Average_Normal_south.png diff --git a/Textures/Wula/Things/Wula_Armour/Wula_Armour_Icon.png b/Content/Textures/Wula/Things/Wula_Armour/Wula_Armour_Icon.png similarity index 100% rename from Textures/Wula/Things/Wula_Armour/Wula_Armour_Icon.png rename to Content/Textures/Wula/Things/Wula_Armour/Wula_Armour_Icon.png diff --git a/Textures/Wula/Things/Wula_Armour/abandon/Naked_Thin_east.png b/Content/Textures/Wula/Things/Wula_Armour/abandon/Naked_Thin_east.png similarity index 100% rename from Textures/Wula/Things/Wula_Armour/abandon/Naked_Thin_east.png rename to Content/Textures/Wula/Things/Wula_Armour/abandon/Naked_Thin_east.png diff --git a/Textures/Wula/Things/Wula_Armour/abandon/Naked_Thin_north.png b/Content/Textures/Wula/Things/Wula_Armour/abandon/Naked_Thin_north.png similarity index 100% rename from Textures/Wula/Things/Wula_Armour/abandon/Naked_Thin_north.png rename to Content/Textures/Wula/Things/Wula_Armour/abandon/Naked_Thin_north.png diff --git a/Textures/Wula/Things/Wula_Armour/abandon/Naked_Thin_south.png b/Content/Textures/Wula/Things/Wula_Armour/abandon/Naked_Thin_south.png similarity index 100% rename from Textures/Wula/Things/Wula_Armour/abandon/Naked_Thin_south.png rename to Content/Textures/Wula/Things/Wula_Armour/abandon/Naked_Thin_south.png diff --git a/Textures/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_east.png b/Content/Textures/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_east.png similarity index 100% rename from Textures/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_east.png rename to Content/Textures/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_east.png diff --git a/Textures/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_north.png b/Content/Textures/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_north.png similarity index 100% rename from Textures/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_north.png rename to Content/Textures/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_north.png diff --git a/Textures/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_south.png b/Content/Textures/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_south.png similarity index 100% rename from Textures/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_south.png rename to Content/Textures/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_south.png diff --git a/Textures/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_east.png b/Content/Textures/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_east.png similarity index 100% rename from Textures/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_east.png rename to Content/Textures/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_east.png diff --git a/Textures/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_north.png b/Content/Textures/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_north.png similarity index 100% rename from Textures/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_north.png rename to Content/Textures/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_north.png diff --git a/Textures/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_south.png b/Content/Textures/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_south.png similarity index 100% rename from Textures/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_south.png rename to Content/Textures/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_south.png diff --git a/Textures/Wula/Things/Wula_Psi_Titan/Wula_Psi_Titan_Icon.png b/Content/Textures/Wula/Things/Wula_Psi_Titan/Wula_Psi_Titan_Icon.png similarity index 100% rename from Textures/Wula/Things/Wula_Psi_Titan/Wula_Psi_Titan_Icon.png rename to Content/Textures/Wula/Things/Wula_Psi_Titan/Wula_Psi_Titan_Icon.png diff --git a/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_CLoak_Ability.png b/Content/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_CLoak_Ability.png similarity index 100% rename from Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_CLoak_Ability.png rename to Content/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_CLoak_Ability.png diff --git a/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Explosive_Ability.png b/Content/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Explosive_Ability.png similarity index 100% rename from Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Explosive_Ability.png rename to Content/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Explosive_Ability.png diff --git a/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Feather_Ability.png b/Content/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Feather_Ability.png similarity index 100% rename from Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Feather_Ability.png rename to Content/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Feather_Ability.png diff --git a/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Flash_Ability.png b/Content/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Flash_Ability.png similarity index 100% rename from Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Flash_Ability.png rename to Content/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Flash_Ability.png diff --git a/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Lost_Ability.png b/Content/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Lost_Ability.png similarity index 100% rename from Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Lost_Ability.png rename to Content/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Lost_Ability.png diff --git a/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Perception_Ability.png b/Content/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Perception_Ability.png similarity index 100% rename from Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Perception_Ability.png rename to Content/Textures/Wula/UI/Abilities/WULA_MW_Scepter_Of_Perception_Ability.png diff --git a/Textures/Wula/UI/Abilities/WULA_Scepter_Of_Heaven_Ability.png b/Content/Textures/Wula/UI/Abilities/WULA_Scepter_Of_Heaven_Ability.png similarity index 100% rename from Textures/Wula/UI/Abilities/WULA_Scepter_Of_Heaven_Ability.png rename to Content/Textures/Wula/UI/Abilities/WULA_Scepter_Of_Heaven_Ability.png diff --git a/Textures/Wula/Weapon/WULA_MW_Armour_Lance.png b/Content/Textures/Wula/Weapon/WULA_MW_Armour_Lance.png similarity index 100% rename from Textures/Wula/Weapon/WULA_MW_Armour_Lance.png rename to Content/Textures/Wula/Weapon/WULA_MW_Armour_Lance.png diff --git a/Textures/Wula/Weapon/WULA_MW_Breaker_Bar.png b/Content/Textures/Wula/Weapon/WULA_MW_Breaker_Bar.png similarity index 100% rename from Textures/Wula/Weapon/WULA_MW_Breaker_Bar.png rename to Content/Textures/Wula/Weapon/WULA_MW_Breaker_Bar.png diff --git a/Textures/Wula/Weapon/WULA_MW_ChainSword.png b/Content/Textures/Wula/Weapon/WULA_MW_ChainSword.png similarity index 100% rename from Textures/Wula/Weapon/WULA_MW_ChainSword.png rename to Content/Textures/Wula/Weapon/WULA_MW_ChainSword.png diff --git a/Textures/Wula/Weapon/WULA_MW_Charge_Mace.png b/Content/Textures/Wula/Weapon/WULA_MW_Charge_Mace.png similarity index 100% rename from Textures/Wula/Weapon/WULA_MW_Charge_Mace.png rename to Content/Textures/Wula/Weapon/WULA_MW_Charge_Mace.png diff --git a/Textures/Wula/Weapon/WULA_MW_Constructor_Hammer.png b/Content/Textures/Wula/Weapon/WULA_MW_Constructor_Hammer.png similarity index 100% rename from Textures/Wula/Weapon/WULA_MW_Constructor_Hammer.png rename to Content/Textures/Wula/Weapon/WULA_MW_Constructor_Hammer.png diff --git a/Textures/Wula/Weapon/WULA_MW_Glaive.png b/Content/Textures/Wula/Weapon/WULA_MW_Glaive.png similarity index 100% rename from Textures/Wula/Weapon/WULA_MW_Glaive.png rename to Content/Textures/Wula/Weapon/WULA_MW_Glaive.png diff --git a/Textures/Wula/Weapon/WULA_MW_Lance.png b/Content/Textures/Wula/Weapon/WULA_MW_Lance.png similarity index 100% rename from Textures/Wula/Weapon/WULA_MW_Lance.png rename to Content/Textures/Wula/Weapon/WULA_MW_Lance.png diff --git a/Textures/Wula/Weapon/WULA_MW_Mace.png b/Content/Textures/Wula/Weapon/WULA_MW_Mace.png similarity index 100% rename from Textures/Wula/Weapon/WULA_MW_Mace.png rename to Content/Textures/Wula/Weapon/WULA_MW_Mace.png diff --git a/Textures/Wula/Weapon/WULA_MW_Scepter_Of_CLoak.png b/Content/Textures/Wula/Weapon/WULA_MW_Scepter_Of_CLoak.png similarity index 100% rename from Textures/Wula/Weapon/WULA_MW_Scepter_Of_CLoak.png rename to Content/Textures/Wula/Weapon/WULA_MW_Scepter_Of_CLoak.png diff --git a/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Explosive.png b/Content/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Explosive.png similarity index 100% rename from Textures/Wula/Weapon/WULA_MW_Scepter_Of_Explosive.png rename to Content/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Explosive.png diff --git a/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Feather.png b/Content/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Feather.png similarity index 100% rename from Textures/Wula/Weapon/WULA_MW_Scepter_Of_Feather.png rename to Content/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Feather.png diff --git a/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Flash.png b/Content/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Flash.png similarity index 100% rename from Textures/Wula/Weapon/WULA_MW_Scepter_Of_Flash.png rename to Content/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Flash.png diff --git a/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Heaven.png b/Content/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Heaven.png similarity index 100% rename from Textures/Wula/Weapon/WULA_MW_Scepter_Of_Heaven.png rename to Content/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Heaven.png diff --git a/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Lost.png b/Content/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Lost.png similarity index 100% rename from Textures/Wula/Weapon/WULA_MW_Scepter_Of_Lost.png rename to Content/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Lost.png diff --git a/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Perception.png b/Content/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Perception.png similarity index 100% rename from Textures/Wula/Weapon/WULA_MW_Scepter_Of_Perception.png rename to Content/Textures/Wula/Weapon/WULA_MW_Scepter_Of_Perception.png diff --git a/Textures/Wula/Weapon/WULA_RW_AutoCannon.png b/Content/Textures/Wula/Weapon/WULA_RW_AutoCannon.png similarity index 100% rename from Textures/Wula/Weapon/WULA_RW_AutoCannon.png rename to Content/Textures/Wula/Weapon/WULA_RW_AutoCannon.png diff --git a/Textures/Wula/Weapon/WULA_RW_Auto_GL.png b/Content/Textures/Wula/Weapon/WULA_RW_Auto_GL.png similarity index 100% rename from Textures/Wula/Weapon/WULA_RW_Auto_GL.png rename to Content/Textures/Wula/Weapon/WULA_RW_Auto_GL.png diff --git a/Textures/Wula/Weapon/WULA_RW_Base_AR.png b/Content/Textures/Wula/Weapon/WULA_RW_Base_AR.png similarity index 100% rename from Textures/Wula/Weapon/WULA_RW_Base_AR.png rename to Content/Textures/Wula/Weapon/WULA_RW_Base_AR.png diff --git a/Textures/Wula/Weapon/WULA_RW_Base_AR_Cat.png b/Content/Textures/Wula/Weapon/WULA_RW_Base_AR_Cat.png similarity index 100% rename from Textures/Wula/Weapon/WULA_RW_Base_AR_Cat.png rename to Content/Textures/Wula/Weapon/WULA_RW_Base_AR_Cat.png diff --git a/Textures/Wula/Weapon/WULA_RW_DM_AR.png b/Content/Textures/Wula/Weapon/WULA_RW_DM_AR.png similarity index 100% rename from Textures/Wula/Weapon/WULA_RW_DM_AR.png rename to Content/Textures/Wula/Weapon/WULA_RW_DM_AR.png diff --git a/Textures/Wula/Weapon/WULA_RW_DM_Cannon.png b/Content/Textures/Wula/Weapon/WULA_RW_DM_Cannon.png similarity index 100% rename from Textures/Wula/Weapon/WULA_RW_DM_Cannon.png rename to Content/Textures/Wula/Weapon/WULA_RW_DM_Cannon.png diff --git a/Textures/Wula/Weapon/WULA_RW_Fractal_RF.png b/Content/Textures/Wula/Weapon/WULA_RW_Fractal_RF.png similarity index 100% rename from Textures/Wula/Weapon/WULA_RW_Fractal_RF.png rename to Content/Textures/Wula/Weapon/WULA_RW_Fractal_RF.png diff --git a/Textures/Wula/Weapon/WULA_RW_Handle_Cannon.png b/Content/Textures/Wula/Weapon/WULA_RW_Handle_Cannon.png similarity index 100% rename from Textures/Wula/Weapon/WULA_RW_Handle_Cannon.png rename to Content/Textures/Wula/Weapon/WULA_RW_Handle_Cannon.png diff --git a/Textures/Wula/Weapon/WULA_RW_Photon_Missile.png b/Content/Textures/Wula/Weapon/WULA_RW_Photon_Missile.png similarity index 100% rename from Textures/Wula/Weapon/WULA_RW_Photon_Missile.png rename to Content/Textures/Wula/Weapon/WULA_RW_Photon_Missile.png diff --git a/Textures/Wula/Weapon/WULA_RW_Sphene_MG.png b/Content/Textures/Wula/Weapon/WULA_RW_Sphene_MG.png similarity index 100% rename from Textures/Wula/Weapon/WULA_RW_Sphene_MG.png rename to Content/Textures/Wula/Weapon/WULA_RW_Sphene_MG.png diff --git a/Textures/Wula/Weapon/WULA_RW_StarDrift_SG.png b/Content/Textures/Wula/Weapon/WULA_RW_StarDrift_SG.png similarity index 100% rename from Textures/Wula/Weapon/WULA_RW_StarDrift_SG.png rename to Content/Textures/Wula/Weapon/WULA_RW_StarDrift_SG.png diff --git a/Textures/Wula/Weapon/WULA_SP_Cotton_Counter.png b/Content/Textures/Wula/Weapon/WULA_SP_Cotton_Counter.png similarity index 100% rename from Textures/Wula/Weapon/WULA_SP_Cotton_Counter.png rename to Content/Textures/Wula/Weapon/WULA_SP_Cotton_Counter.png diff --git a/Textures/Wula/Weapon/WULA_SP_Live_Shelter.png b/Content/Textures/Wula/Weapon/WULA_SP_Live_Shelter.png similarity index 100% rename from Textures/Wula/Weapon/WULA_SP_Live_Shelter.png rename to Content/Textures/Wula/Weapon/WULA_SP_Live_Shelter.png diff --git a/Textures/Wula/Weapon/WULA_SP_Mist_Incinerator.png b/Content/Textures/Wula/Weapon/WULA_SP_Mist_Incinerator.png similarity index 100% rename from Textures/Wula/Weapon/WULA_SP_Mist_Incinerator.png rename to Content/Textures/Wula/Weapon/WULA_SP_Mist_Incinerator.png diff --git a/Textures/Wula/Weapon/WULA_SP_Spear_Impale.png b/Content/Textures/Wula/Weapon/WULA_SP_Spear_Impale.png similarity index 100% rename from Textures/Wula/Weapon/WULA_SP_Spear_Impale.png rename to Content/Textures/Wula/Weapon/WULA_SP_Spear_Impale.png diff --git a/Textures/Wula/Weapon/WULA_SP_Spell_Medium.png b/Content/Textures/Wula/Weapon/WULA_SP_Spell_Medium.png similarity index 100% rename from Textures/Wula/Weapon/WULA_SP_Spell_Medium.png rename to Content/Textures/Wula/Weapon/WULA_SP_Spell_Medium.png diff --git a/Textures/Wula/Weapon/WULA_WM_Panzer_Autocannon.png b/Content/Textures/Wula/Weapon/WULA_WM_Panzer_Autocannon.png similarity index 100% rename from Textures/Wula/Weapon/WULA_WM_Panzer_Autocannon.png rename to Content/Textures/Wula/Weapon/WULA_WM_Panzer_Autocannon.png diff --git a/Textures/Wula/Weapon/WULA_WM_Panzer_Turret.png b/Content/Textures/Wula/Weapon/WULA_WM_Panzer_Turret.png similarity index 100% rename from Textures/Wula/Weapon/WULA_WM_Panzer_Turret.png rename to Content/Textures/Wula/Weapon/WULA_WM_Panzer_Turret.png diff --git a/Textures/Wula/Weapon/WULA_Weapon_Empty.png b/Content/Textures/Wula/Weapon/WULA_Weapon_Empty.png similarity index 100% rename from Textures/Wula/Weapon/WULA_Weapon_Empty.png rename to Content/Textures/Wula/Weapon/WULA_Weapon_Empty.png diff --git a/Textures/Wula/World/WorldObjects/Expanding/Wula_Broken_Personality_Faction.png b/Content/Textures/Wula/World/WorldObjects/Expanding/Wula_Broken_Personality_Faction.png similarity index 100% rename from Textures/Wula/World/WorldObjects/Expanding/Wula_Broken_Personality_Faction.png rename to Content/Textures/Wula/World/WorldObjects/Expanding/Wula_Broken_Personality_Faction.png diff --git a/Textures/Wula/World/WorldObjects/Expanding/Wula_FE_Faction.png b/Content/Textures/Wula/World/WorldObjects/Expanding/Wula_FE_Faction.png similarity index 100% rename from Textures/Wula/World/WorldObjects/Expanding/Wula_FE_Faction.png rename to Content/Textures/Wula/World/WorldObjects/Expanding/Wula_FE_Faction.png diff --git a/LoadFolders.xml b/LoadFolders.xml index 477da22a..f71ccb6a 100644 --- a/LoadFolders.xml +++ b/LoadFolders.xml @@ -1,7 +1,7 @@ -
  • /
  • -
  • 1.6
  • -
  • 1.6/Mods/Anomaly
  • +
  • 1.6/1.6
  • +
  • Content
  • +
  • 1.6/Anomaly
  • \ No newline at end of file diff --git a/MCP/mcpserver.log b/MCP/mcpserver.log new file mode 100644 index 00000000..e5c7d339 --- /dev/null +++ b/MCP/mcpserver.log @@ -0,0 +1,687 @@ +2025-08-03 15:44:02,402 - INFO - 成功加载 DASHSCOPE_API_KEY。 +2025-08-03 15:44:02,412 - INFO - RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动... +2025-08-03 15:44:02,419 - INFO - Processing request of type ListToolsRequest +2025-08-03 15:44:02,421 - INFO - Processing request of type ListResourcesRequest +2025-08-03 15:44:02,422 - INFO - Processing request of type ListResourceTemplatesRequest +2025-08-03 15:44:27,828 - INFO - Processing request of type CallToolRequest +2025-08-03 15:44:27,828 - INFO - 收到问题: 查找 CompProperties_Explosive 的定义和用法 +2025-08-03 15:44:27,828 - INFO - 找到的潜在关键词: [('CompProperties_Explosive', 3)] +2025-08-03 15:44:27,828 - INFO - 提取到关键词: CompProperties_Explosive +2025-08-03 15:44:27,828 - INFO - 缓存未命中,开始实时搜索: CompProperties_Explosive +2025-08-03 15:44:29,235 - INFO - 找到 31 个候选文件,开始向量化处理... +2025-08-03 15:44:42,863 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-03 15:50:03,065 - INFO - Processing request of type CallToolRequest +2025-08-03 15:50:03,065 - INFO - 收到问题: 查找 CompProperties_Explosive 的定义和用法 +2025-08-03 15:50:03,065 - INFO - 找到的潜在关键词: [('CompProperties_Explosive', 3)] +2025-08-03 15:50:03,065 - INFO - 提取到关键词: CompProperties_Explosive +2025-08-03 15:50:03,065 - INFO - 缓存命中: 关键词 'CompProperties_Explosive' +2025-08-03 15:53:04,845 - INFO - 成功加载 DASHSCOPE_API_KEY。 +2025-08-03 15:53:04,853 - INFO - RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动... +2025-08-03 15:53:51,828 - INFO - 成功加载 DASHSCOPE_API_KEY。 +2025-08-03 15:53:51,838 - INFO - RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动... +2025-08-03 15:53:51,846 - INFO - Processing request of type ListToolsRequest +2025-08-03 15:53:51,848 - INFO - Processing request of type ListResourcesRequest +2025-08-03 15:53:51,848 - INFO - Processing request of type ListResourceTemplatesRequest +2025-08-03 15:54:10,754 - INFO - Processing request of type CallToolRequest +2025-08-03 15:54:10,755 - INFO - 收到问题: 查找 CompProperties_Explosive 的定义 +2025-08-03 15:54:10,755 - INFO - 找到的潜在关键词: [('CompProperties_Explosive', 3)] +2025-08-03 15:54:10,755 - INFO - 提取到关键词: CompProperties_Explosive +2025-08-03 15:54:10,755 - INFO - 缓存未命中,开始实时搜索: CompProperties_Explosive +2025-08-03 15:54:12,401 - INFO - 找到 31 个候选文件,开始向量化处理... +2025-08-03 15:54:28,384 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-03 15:54:52,951 - INFO - Processing request of type CallToolRequest +2025-08-03 15:54:52,951 - INFO - 收到问题: 查找 CompProperties_Explosive 的定义 +2025-08-03 15:54:52,951 - INFO - 找到的潜在关键词: [('CompProperties_Explosive', 3)] +2025-08-03 15:54:52,951 - INFO - 提取到关键词: CompProperties_Explosive +2025-08-03 15:54:52,963 - INFO - 缓存命中: 关键词 'CompProperties_Explosive' +2025-08-03 18:58:03,910 - INFO - 成功加载 DASHSCOPE_API_KEY。 +2025-08-03 18:58:03,919 - INFO - RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动... +2025-08-03 18:58:03,927 - INFO - Processing request of type ListToolsRequest +2025-08-03 18:58:03,929 - INFO - Processing request of type ListResourcesRequest +2025-08-03 18:58:03,930 - INFO - Processing request of type ListResourceTemplatesRequest +2025-08-03 18:58:21,536 - INFO - Processing request of type CallToolRequest +2025-08-03 18:58:21,536 - INFO - 收到问题: AspirationWorker IsCompleted +2025-08-03 18:58:21,536 - INFO - 找到的潜在关键词: [('AspirationWorker', 2), ('IsCompleted', 2)] +2025-08-03 18:58:21,536 - INFO - 提取到关键词: AspirationWorker +2025-08-03 18:58:21,536 - INFO - 缓存未命中,开始实时搜索: AspirationWorker +2025-08-03 18:58:23,022 - INFO - 未找到与 'AspirationWorker' 相关的文件。 +2025-08-03 21:00:57,503 - INFO - 成功加载 DASHSCOPE_API_KEY。 +2025-08-03 21:00:57,518 - INFO - RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动... +2025-08-03 21:00:57,531 - INFO - Processing request of type ListToolsRequest +2025-08-03 21:00:57,533 - INFO - Processing request of type ListResourcesRequest +2025-08-03 21:00:57,535 - INFO - Processing request of type ListResourceTemplatesRequest +2025-08-03 21:12:32,710 - INFO - Processing request of type CallToolRequest +2025-08-03 21:12:32,713 - INFO - 收到问题: DamageDef additionalHediffsThisPart +2025-08-03 21:12:32,713 - INFO - 找到的潜在关键词: [('DamageDef', 2), ('additionalHediffsThisPart', 2)] +2025-08-03 21:12:32,713 - INFO - 提取到关键词: DamageDef +2025-08-03 21:12:32,713 - INFO - 缓存未命中,开始实时搜索: DamageDef +2025-08-03 21:12:34,071 - INFO - 找到 226 个候选文件,开始向量化处理... +2025-08-03 21:13:37,263 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-03 21:14:01,551 - INFO - Processing request of type CallToolRequest +2025-08-03 21:14:01,551 - INFO - 收到问题: DamageDef additionalHediffsThisPart +2025-08-03 21:14:01,551 - INFO - 找到的潜在关键词: [('DamageDef', 2), ('additionalHediffsThisPart', 2)] +2025-08-03 21:14:01,551 - INFO - 提取到关键词: DamageDef +2025-08-03 21:14:01,561 - INFO - 缓存命中: 关键词 'DamageDef' +2025-08-03 21:15:20,068 - INFO - Processing request of type CallToolRequest +2025-08-03 21:15:20,068 - INFO - 收到问题: DamageWorker Apply additionalHediffsThisPart +2025-08-03 21:15:20,068 - INFO - 找到的潜在关键词: [('DamageWorker', 2), ('Apply', 2), ('additionalHediffsThisPart', 2)] +2025-08-03 21:15:20,068 - INFO - 提取到关键词: DamageWorker +2025-08-03 21:15:20,068 - INFO - 缓存未命中,开始实时搜索: DamageWorker +2025-08-03 21:15:21,443 - INFO - 找到 37 个候选文件,开始向量化处理... +2025-08-03 21:15:30,428 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-03 21:16:16,210 - INFO - Processing request of type CallToolRequest +2025-08-03 21:16:16,210 - INFO - 收到问题: HediffDef +2025-08-03 21:16:16,210 - INFO - 找到的潜在关键词: [('HediffDef', 2)] +2025-08-03 21:16:16,210 - INFO - 提取到关键词: HediffDef +2025-08-03 21:16:16,211 - INFO - 缓存未命中,开始实时搜索: HediffDef +2025-08-03 21:16:17,587 - INFO - 找到 428 个候选文件,开始向量化处理... +2025-08-03 21:18:43,382 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-03 21:18:43,387 - INFO - Processing request of type CallToolRequest +2025-08-03 21:18:43,387 - INFO - 收到问题: HediffDef class +2025-08-03 21:18:43,387 - INFO - 找到的潜在关键词: [('HediffDef', 2)] +2025-08-03 21:18:43,387 - INFO - 提取到关键词: HediffDef +2025-08-03 21:18:43,392 - INFO - 缓存命中: 关键词 'HediffDef' +2025-08-03 21:18:55,913 - INFO - Processing request of type CallToolRequest +2025-08-03 21:18:55,913 - INFO - 收到问题: HediffMaker.MakeHediff +2025-08-03 21:18:55,913 - INFO - 找到的潜在关键词: [('HediffMaker.MakeHediff', 2)] +2025-08-03 21:18:55,913 - INFO - 提取到关键词: HediffMaker.MakeHediff +2025-08-03 21:18:55,913 - INFO - 缓存未命中,开始实时搜索: HediffMaker.MakeHediff +2025-08-03 21:18:57,267 - INFO - 找到 54 个候选文件,开始向量化处理... +2025-08-03 21:19:12,272 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-03 21:20:38,686 - INFO - Processing request of type CallToolRequest +2025-08-03 21:20:38,686 - INFO - 收到问题: DamageWorker Apply additionalHediffs +2025-08-03 21:20:38,686 - INFO - 找到的潜在关键词: [('DamageWorker', 2), ('Apply', 2), ('additionalHediffs', 2)] +2025-08-03 21:20:38,686 - INFO - 提取到关键词: DamageWorker +2025-08-03 21:20:38,687 - INFO - 缓存命中: 关键词 'DamageWorker' +2025-08-03 21:23:10,383 - INFO - Processing request of type CallToolRequest +2025-08-03 21:23:10,383 - INFO - 收到问题: DamageDefAdditionalHediff +2025-08-03 21:23:10,383 - INFO - 找到的潜在关键词: [('DamageDefAdditionalHediff', 2)] +2025-08-03 21:23:10,383 - INFO - 提取到关键词: DamageDefAdditionalHediff +2025-08-03 21:23:10,383 - INFO - 缓存未命中,开始实时搜索: DamageDefAdditionalHediff +2025-08-03 21:23:11,759 - INFO - 找到 5 个候选文件,开始向量化处理... +2025-08-03 21:23:13,303 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-03 21:40:06,239 - INFO - Processing request of type CallToolRequest +2025-08-03 21:40:06,239 - INFO - 收到问题: PsychicRitualDef +2025-08-03 21:40:06,239 - INFO - 找到的潜在关键词: [('PsychicRitualDef', 2)] +2025-08-03 21:40:06,239 - INFO - 提取到关键词: PsychicRitualDef +2025-08-03 21:40:06,239 - INFO - 缓存未命中,开始实时搜索: PsychicRitualDef +2025-08-03 21:40:07,588 - INFO - 找到 57 个候选文件,开始向量化处理... +2025-08-03 21:40:23,047 - WARNING - 未能从 C:\Steam\steamapps\common\RimWorld\Data\Anomaly\Languages\ChineseSimplified (简体中文)\Keyed\Misc_PsychicRituals.xml 提取到完整的代码块。 +2025-08-03 21:40:23,048 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-03 21:40:38,955 - INFO - Processing request of type CallToolRequest +2025-08-03 21:40:38,955 - INFO - 收到问题: CompProperties_PsychicRitualSpot +2025-08-03 21:40:38,955 - INFO - 找到的潜在关键词: [('CompProperties_PsychicRitualSpot', 3)] +2025-08-03 21:40:38,955 - INFO - 提取到关键词: CompProperties_PsychicRitualSpot +2025-08-03 21:40:38,955 - INFO - 缓存未命中,开始实时搜索: CompProperties_PsychicRitualSpot +2025-08-03 21:40:40,281 - INFO - 找到 2 个候选文件,开始向量化处理... +2025-08-03 21:40:41,046 - INFO - 向量搜索完成。找到了 2 个匹配项并成功提取了代码。 +2025-08-03 21:41:38,879 - INFO - Processing request of type CallToolRequest +2025-08-03 21:41:38,879 - INFO - 收到问题: PsychicRitualGizmo +2025-08-03 21:41:38,879 - INFO - 找到的潜在关键词: [('PsychicRitualGizmo', 2)] +2025-08-03 21:41:38,879 - INFO - 提取到关键词: PsychicRitualGizmo +2025-08-03 21:41:38,879 - INFO - 缓存未命中,开始实时搜索: PsychicRitualGizmo +2025-08-03 21:41:40,315 - INFO - 找到 3 个候选文件,开始向量化处理... +2025-08-03 21:41:41,300 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-03 21:43:48,740 - INFO - Processing request of type CallToolRequest +2025-08-03 21:43:48,740 - INFO - 收到问题: PsychicRitualDef_InvocationCircle +2025-08-03 21:43:48,740 - INFO - 找到的潜在关键词: [('PsychicRitualDef_InvocationCircle', 3)] +2025-08-03 21:43:48,740 - INFO - 提取到关键词: PsychicRitualDef_InvocationCircle +2025-08-03 21:43:48,740 - INFO - 缓存未命中,开始实时搜索: PsychicRitualDef_InvocationCircle +2025-08-03 21:43:50,020 - INFO - 找到 26 个候选文件,开始向量化处理... +2025-08-03 21:43:55,992 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-03 22:01:51,554 - INFO - Processing request of type CallToolRequest +2025-08-03 22:01:51,554 - INFO - 收到问题: Show the C# source code for the CompPsychicRitualSpot class, specifically the CompGetGizmosExtra method. I need to see how it creates the ritual selection gizmo and what it passes to the dialog window. +2025-08-03 22:01:51,554 - INFO - 找到的潜在关键词: [('Show', 2), ('CompPsychicRitualSpot', 2), ('CompGetGizmosExtra', 2)] +2025-08-03 22:01:51,554 - INFO - 提取到关键词: Show +2025-08-03 22:01:51,555 - INFO - 缓存未命中,开始实时搜索: Show +2025-08-03 22:01:52,936 - INFO - 找到 840 个候选文件,开始向量化处理... +2025-08-03 22:06:16,237 - WARNING - 未能从 C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\RitualTargetUseReport.txt 提取到完整的代码块。 +2025-08-03 22:06:16,237 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-03 22:13:55,178 - INFO - Processing request of type CallToolRequest +2025-08-03 22:13:55,178 - INFO - 收到问题: Show the C# source code for the PsychicRitualDef class and the Dialog_BeginPsychicRitual class. I need to see the correct properties for Icon, cooldowns, roles, and the exact constructor signature for the dialog. +2025-08-03 22:13:55,178 - INFO - 找到的潜在关键词: [('Dialog_BeginPsychicRitual', 3), ('Show', 2), ('PsychicRitualDef', 2), ('Icon', 2)] +2025-08-03 22:13:55,178 - INFO - 提取到关键词: Dialog_BeginPsychicRitual +2025-08-03 22:13:55,178 - INFO - 缓存未命中,开始实时搜索: Dialog_BeginPsychicRitual +2025-08-03 22:13:56,380 - INFO - 找到 8 个候选文件,开始向量化处理... +2025-08-03 22:13:58,927 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-03 22:30:34,550 - INFO - Processing request of type CallToolRequest +2025-08-03 22:30:34,550 - INFO - 收到问题: PsychicRitualDef_InvocationCircle class definition +2025-08-03 22:30:34,550 - INFO - 找到的潜在关键词: [('PsychicRitualDef_InvocationCircle', 3)] +2025-08-03 22:30:34,550 - INFO - 提取到关键词: PsychicRitualDef_InvocationCircle +2025-08-03 22:30:34,558 - INFO - 缓存命中: 关键词 'PsychicRitualDef_InvocationCircle' +2025-08-03 22:59:18,371 - INFO - Processing request of type CallToolRequest +2025-08-03 22:59:18,371 - INFO - 收到问题: CompPsychicRitualSpot CompGetGizmosExtra +2025-08-03 22:59:18,371 - INFO - 找到的潜在关键词: [('CompPsychicRitualSpot', 2), ('CompGetGizmosExtra', 2)] +2025-08-03 22:59:18,371 - INFO - 提取到关键词: CompPsychicRitualSpot +2025-08-03 22:59:18,371 - INFO - 缓存未命中,开始实时搜索: CompPsychicRitualSpot +2025-08-03 22:59:31,774 - INFO - 找到 4 个候选文件,开始向量化处理... +2025-08-03 22:59:33,291 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-03 22:59:51,745 - INFO - Processing request of type CallToolRequest +2025-08-03 22:59:51,745 - INFO - 收到问题: PsychicRitualGizmo GetGizmos +2025-08-03 22:59:51,745 - INFO - 找到的潜在关键词: [('PsychicRitualGizmo', 2), ('GetGizmos', 2)] +2025-08-03 22:59:51,745 - INFO - 提取到关键词: PsychicRitualGizmo +2025-08-03 22:59:51,758 - INFO - 缓存命中: 关键词 'PsychicRitualGizmo' +2025-08-03 23:28:19,476 - INFO - Processing request of type CallToolRequest +2025-08-03 23:28:19,476 - INFO - 收到问题: PsychicRitualDef LabelCap usage +2025-08-03 23:28:19,476 - INFO - 找到的潜在关键词: [('PsychicRitualDef', 2), ('LabelCap', 2)] +2025-08-03 23:28:19,476 - INFO - 提取到关键词: PsychicRitualDef +2025-08-03 23:28:19,486 - INFO - 缓存命中: 关键词 'PsychicRitualDef' +2025-08-03 23:36:54,188 - INFO - Processing request of type CallToolRequest +2025-08-03 23:36:54,189 - INFO - 收到问题: PsychicRitualDef reward +2025-08-03 23:36:54,189 - INFO - 找到的潜在关键词: [('PsychicRitualDef', 2)] +2025-08-03 23:36:54,189 - INFO - 提取到关键词: PsychicRitualDef +2025-08-03 23:36:54,189 - INFO - 缓存命中: 关键词 'PsychicRitualDef' +2025-08-03 23:43:11,852 - INFO - Processing request of type CallToolRequest +2025-08-03 23:43:11,852 - INFO - 收到问题: PsychicRitualDef create item +2025-08-03 23:43:11,852 - INFO - 找到的潜在关键词: [('PsychicRitualDef', 2)] +2025-08-03 23:43:11,852 - INFO - 提取到关键词: PsychicRitualDef +2025-08-03 23:43:11,852 - INFO - 缓存命中: 关键词 'PsychicRitualDef' +2025-08-03 23:54:25,993 - INFO - Processing request of type CallToolRequest +2025-08-03 23:54:25,993 - INFO - 收到问题: CompProperties_PsychicRitualSpot PsychicRitualGizmo +2025-08-03 23:54:25,994 - INFO - 找到的潜在关键词: [('CompProperties_PsychicRitualSpot', 3), ('PsychicRitualGizmo', 2)] +2025-08-03 23:54:25,994 - INFO - 提取到关键词: CompProperties_PsychicRitualSpot +2025-08-03 23:54:26,001 - INFO - 缓存命中: 关键词 'CompProperties_PsychicRitualSpot' +2025-08-03 23:54:38,820 - INFO - Processing request of type CallToolRequest +2025-08-03 23:54:38,820 - INFO - 收到问题: CompPsychicRitualSpot CompGetGizmosExtra +2025-08-03 23:54:38,820 - INFO - 找到的潜在关键词: [('CompPsychicRitualSpot', 2), ('CompGetGizmosExtra', 2)] +2025-08-03 23:54:38,820 - INFO - 提取到关键词: CompPsychicRitualSpot +2025-08-03 23:54:38,831 - INFO - 缓存命中: 关键词 'CompPsychicRitualSpot' +2025-08-03 23:55:28,827 - INFO - Processing request of type CallToolRequest +2025-08-03 23:55:28,828 - INFO - 收到问题: PsychicRitualGizmo GetGizmos +2025-08-03 23:55:28,828 - INFO - 找到的潜在关键词: [('PsychicRitualGizmo', 2), ('GetGizmos', 2)] +2025-08-03 23:55:28,828 - INFO - 提取到关键词: PsychicRitualGizmo +2025-08-03 23:55:28,840 - INFO - 缓存命中: 关键词 'PsychicRitualGizmo' +2025-08-03 23:57:23,467 - INFO - 成功加载 DASHSCOPE_API_KEY。 +2025-08-03 23:57:23,479 - INFO - RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动... +2025-08-03 23:57:23,492 - INFO - Processing request of type ListToolsRequest +2025-08-03 23:57:23,494 - INFO - Processing request of type ListResourcesRequest +2025-08-03 23:57:23,495 - INFO - Processing request of type ListResourceTemplatesRequest +2025-08-04 00:00:37,307 - INFO - Processing request of type CallToolRequest +2025-08-04 00:00:37,307 - INFO - 收到问题: PsychicRitualDef +2025-08-04 00:00:37,307 - INFO - 找到的潜在关键词: [('PsychicRitualDef', 2)] +2025-08-04 00:00:37,307 - INFO - 提取到关键词: PsychicRitualDef +2025-08-04 00:00:37,317 - INFO - 缓存命中: 关键词 'PsychicRitualDef' +2025-08-04 00:00:55,095 - INFO - Processing request of type CallToolRequest +2025-08-04 00:00:55,095 - INFO - 收到问题: class PsychicRitualDef +2025-08-04 00:00:55,095 - INFO - 找到的潜在关键词: [('PsychicRitualDef', 2)] +2025-08-04 00:00:55,095 - INFO - 提取到关键词: PsychicRitualDef +2025-08-04 00:00:55,095 - INFO - 缓存命中: 关键词 'PsychicRitualDef' +2025-08-04 00:09:55,831 - INFO - Processing request of type CallToolRequest +2025-08-04 00:09:55,831 - INFO - 收到问题: public class PsychicRitualDef : Def +2025-08-04 00:09:55,832 - INFO - 找到的潜在关键词: [('PsychicRitualDef', 2)] +2025-08-04 00:09:55,832 - INFO - 提取到关键词: PsychicRitualDef +2025-08-04 00:09:55,832 - INFO - 缓存命中: 关键词 'PsychicRitualDef' +2025-08-04 07:20:33,529 - INFO - 成功加载 DASHSCOPE_API_KEY。 +2025-08-04 07:20:33,539 - INFO - RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动... +2025-08-04 07:20:33,547 - INFO - Processing request of type ListToolsRequest +2025-08-04 07:20:33,549 - INFO - Processing request of type ListResourcesRequest +2025-08-04 07:20:33,551 - INFO - Processing request of type ListResourceTemplatesRequest +2025-08-04 07:20:33,559 - INFO - Processing request of type ListToolsRequest +2025-08-04 07:20:33,560 - INFO - Processing request of type ListToolsRequest +2025-08-04 07:20:35,996 - INFO - 成功加载 DASHSCOPE_API_KEY。 +2025-08-04 07:20:36,004 - INFO - RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动... +2025-08-04 07:20:36,011 - INFO - Processing request of type ListToolsRequest +2025-08-04 07:20:36,013 - INFO - Processing request of type ListResourcesRequest +2025-08-04 07:20:36,013 - INFO - Processing request of type ListResourceTemplatesRequest +2025-08-04 07:24:35,273 - INFO - Processing request of type CallToolRequest +2025-08-04 07:24:35,273 - INFO - 收到问题: public class PsychicRitualDef : Def +2025-08-04 07:24:35,273 - INFO - 找到的潜在关键词: [('PsychicRitualDef', 2)] +2025-08-04 07:24:35,273 - INFO - 提取到关键词: PsychicRitualDef +2025-08-04 07:24:35,282 - INFO - 缓存命中: 关键词 'PsychicRitualDef' +2025-08-04 07:26:21,038 - INFO - Processing request of type CallToolRequest +2025-08-04 07:26:21,038 - INFO - 收到问题: public class PsychicRitualDef : Def +2025-08-04 07:26:21,038 - INFO - 找到的潜在关键词: [('PsychicRitualDef', 2)] +2025-08-04 07:26:21,038 - INFO - 提取到关键词: PsychicRitualDef +2025-08-04 07:26:21,038 - INFO - 缓存未命中,开始实时搜索: PsychicRitualDef +2025-08-04 07:27:10,095 - INFO - 找到 57 个候选文件,开始向量化处理... +2025-08-04 07:27:28,833 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-04 07:28:17,494 - INFO - Processing request of type CallToolRequest +2025-08-04 07:28:17,494 - INFO - 收到问题: public class PsychicRitualDef : Def +2025-08-04 07:28:17,494 - INFO - 找到的潜在关键词: [('PsychicRitualDef', 2)] +2025-08-04 07:28:17,494 - INFO - 提取到关键词: PsychicRitualDef +2025-08-04 07:28:17,501 - INFO - 缓存命中: 关键词 'PsychicRitualDef' +2025-08-04 07:30:47,851 - INFO - 成功加载 DASHSCOPE_API_KEY。 +2025-08-04 07:30:47,860 - INFO - RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动... +2025-08-04 07:30:47,868 - INFO - Processing request of type ListToolsRequest +2025-08-04 07:30:47,869 - INFO - Processing request of type ListResourcesRequest +2025-08-04 07:30:47,870 - INFO - Processing request of type ListResourceTemplatesRequest +2025-08-04 07:31:58,371 - INFO - Processing request of type CallToolRequest +2025-08-04 07:31:58,372 - INFO - 收到问题: PsychicRitualDef +2025-08-04 07:31:58,372 - INFO - 找到的潜在关键词: ['PsychicRitualDef'] +2025-08-04 07:31:58,372 - INFO - 提取到关键词: ['PsychicRitualDef'] +2025-08-04 07:31:58,372 - INFO - 缓存未命中,开始实时搜索: PsychicRitualDef +2025-08-04 07:31:59,657 - INFO - 找到 57 个候选文件,开始向量化处理... +2025-08-04 07:31:59,658 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\PsychicRitualDef.txt +2025-08-04 07:31:59,658 - WARNING - 候选文件过多 (56),仅处理前 25 个。 +2025-08-04 07:32:06,642 - INFO - 向量搜索完成。找到了 5 个匹配项并成功提取了代码。 +2025-08-04 07:32:54,871 - INFO - Processing request of type CallToolRequest +2025-08-04 07:32:54,871 - INFO - 收到问题: public class PsychicRitualDef +2025-08-04 07:32:54,872 - INFO - 找到的潜在关键词: ['PsychicRitualDef'] +2025-08-04 07:32:54,872 - INFO - 提取到关键词: ['PsychicRitualDef'] +2025-08-04 07:32:54,878 - INFO - 缓存命中: 关键词 'PsychicRitualDef' +2025-08-04 07:35:55,326 - INFO - Processing request of type CallToolRequest +2025-08-04 07:35:55,326 - INFO - 收到问题: PsychicRitualToil_GatherForInvocation +2025-08-04 07:35:55,326 - INFO - 找到的潜在关键词: ['PsychicRitualToil_GatherForInvocation'] +2025-08-04 07:35:55,326 - INFO - 提取到关键词: ['PsychicRitualToil_GatherForInvocation'] +2025-08-04 07:35:55,327 - INFO - 缓存未命中,开始实时搜索: PsychicRitualToil_GatherForInvocation +2025-08-04 07:35:56,578 - INFO - 找到 4 个候选文件,开始向量化处理... +2025-08-04 07:35:56,578 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse.AI.Group\PsychicRitualToil_GatherForInvocation.txt +2025-08-04 07:35:58,159 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-04 07:42:57,428 - INFO - Processing request of type CallToolRequest +2025-08-04 07:42:57,428 - INFO - 收到问题: PsychicRitualDef_InvocationCircle class +2025-08-04 07:42:57,428 - INFO - 找到的潜在关键词: ['PsychicRitualDef_InvocationCircle'] +2025-08-04 07:42:57,428 - INFO - 提取到关键词: ['PsychicRitualDef_InvocationCircle'] +2025-08-04 07:42:57,429 - INFO - 缓存未命中,开始实时搜索: PsychicRitualDef_InvocationCircle +2025-08-04 07:42:58,898 - INFO - 找到 26 个候选文件,开始向量化处理... +2025-08-04 07:42:58,898 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\PsychicRitualDef_InvocationCircle.txt +2025-08-04 07:43:06,851 - INFO - 向量搜索完成。找到了 5 个匹配项并成功提取了代码。 +2025-08-04 07:43:37,198 - INFO - Processing request of type CallToolRequest +2025-08-04 07:43:37,198 - INFO - 收到问题: PsychicRitualDef class source +2025-08-04 07:43:37,198 - INFO - 找到的潜在关键词: ['PsychicRitualDef'] +2025-08-04 07:43:37,198 - INFO - 提取到关键词: ['PsychicRitualDef'] +2025-08-04 07:43:37,199 - INFO - 缓存命中: 关键词 'PsychicRitualDef' +2025-08-04 07:44:18,730 - INFO - Processing request of type CallToolRequest +2025-08-04 07:44:18,730 - INFO - 收到问题: PsychicRitualToil_GatherOfferings class source +2025-08-04 07:44:18,730 - INFO - 找到的潜在关键词: ['PsychicRitualToil_GatherOfferings'] +2025-08-04 07:44:18,730 - INFO - 提取到关键词: ['PsychicRitualToil_GatherOfferings'] +2025-08-04 07:44:18,730 - INFO - 缓存未命中,开始实时搜索: PsychicRitualToil_GatherOfferings +2025-08-04 07:44:20,107 - INFO - 找到 5 个候选文件,开始向量化处理... +2025-08-04 07:44:20,107 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse.AI.Group\PsychicRitualToil_GatherOfferings.txt +2025-08-04 07:44:22,143 - INFO - 向量搜索完成。找到了 4 个匹配项并成功提取了代码。 +2025-08-04 07:53:02,419 - INFO - Processing request of type CallToolRequest +2025-08-04 07:53:02,419 - INFO - 收到问题: StatDef for melee attack speed +2025-08-04 07:53:02,419 - INFO - 找到的潜在关键词: ['StatDef'] +2025-08-04 07:53:02,419 - INFO - 提取到关键词: ['StatDef'] +2025-08-04 07:53:02,419 - INFO - 缓存未命中,开始实时搜索: StatDef +2025-08-04 07:53:03,865 - INFO - 找到 516 个候选文件,开始向量化处理... +2025-08-04 07:53:03,867 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\StatDef.txt +2025-08-04 07:53:03,868 - WARNING - 候选文件过多 (515),仅处理前 25 个。 +2025-08-04 07:53:12,872 - INFO - 向量搜索完成。找到了 2 个匹配项并成功提取了代码。 +2025-08-04 07:55:01,722 - INFO - Processing request of type CallToolRequest +2025-08-04 07:55:01,723 - INFO - 收到问题: AbilityDef for berserk pulse +2025-08-04 07:55:01,723 - INFO - 找到的潜在关键词: ['AbilityDef'] +2025-08-04 07:55:01,723 - INFO - 提取到关键词: ['AbilityDef'] +2025-08-04 07:55:01,723 - INFO - 缓存未命中,开始实时搜索: AbilityDef +2025-08-04 07:55:03,037 - INFO - 找到 104 个候选文件,开始向量化处理... +2025-08-04 07:55:03,037 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\AbilityDef.txt +2025-08-04 07:55:03,037 - WARNING - 候选文件过多 (103),仅处理前 25 个。 +2025-08-04 07:55:10,617 - INFO - 向量搜索完成。找到了 5 个匹配项并成功提取了代码。 +2025-08-04 07:58:42,495 - INFO - Processing request of type CallToolRequest +2025-08-04 07:58:42,495 - INFO - 收到问题: 现在我需要找到原版“群体狂暴”灵能的 defName。 +2025-08-04 07:58:42,495 - INFO - 找到的潜在关键词: ['defName。'] +2025-08-04 07:58:42,495 - INFO - 提取到关键词: ['defName。'] +2025-08-04 07:58:42,495 - INFO - 缓存未命中,开始实时搜索: defName。 +2025-08-04 07:58:43,777 - INFO - 未找到与 '['defName。']' 相关的文件。 +2025-08-04 07:59:36,124 - INFO - Processing request of type CallToolRequest +2025-08-04 07:59:36,124 - INFO - 收到问题: 现在我需要找到原版“群体狂暴”灵能的 defName。 +2025-08-04 07:59:36,124 - INFO - 找到的潜在关键词: ['defName。'] +2025-08-04 07:59:36,124 - INFO - 提取到关键词: ['defName。'] +2025-08-04 07:59:36,124 - INFO - 缓存未命中,开始实时搜索: defName。 +2025-08-04 07:59:37,427 - INFO - 未找到与 '['defName。']' 相关的文件。 +2025-08-04 08:00:44,966 - INFO - Processing request of type CallToolRequest +2025-08-04 08:00:44,966 - INFO - 收到问题: 现在我需要找到原版“群体狂暴”灵能的 defName。 +2025-08-04 08:00:44,966 - INFO - 找到的潜在关键词: ['defName。'] +2025-08-04 08:00:44,967 - INFO - 提取到关键词: ['defName。'] +2025-08-04 08:00:44,967 - INFO - 缓存未命中,开始实时搜索: defName。 +2025-08-04 08:00:46,237 - INFO - 未找到与 '['defName。']' 相关的文件。 +2025-08-04 08:01:42,734 - INFO - Processing request of type CallToolRequest +2025-08-04 08:01:42,734 - INFO - 收到问题: 现在我需要找到原版“群体狂暴”灵能的 defName。 +2025-08-04 08:01:42,734 - INFO - 找到的潜在关键词: ['defName。'] +2025-08-04 08:01:42,734 - INFO - 提取到关键词: ['defName。'] +2025-08-04 08:01:42,734 - INFO - 缓存未命中,开始实时搜索: defName。 +2025-08-04 08:01:43,967 - INFO - 未找到与 '['defName。']' 相关的文件。 +2025-08-04 08:54:04,338 - INFO - 成功加载 DASHSCOPE_API_KEY。 +2025-08-04 08:54:04,354 - INFO - RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动... +2025-08-04 08:54:04,367 - INFO - Processing request of type ListToolsRequest +2025-08-04 08:54:04,369 - INFO - Processing request of type ListResourcesRequest +2025-08-04 08:54:04,370 - INFO - Processing request of type ListResourceTemplatesRequest +2025-08-04 21:57:57,767 - INFO - 成功加载 DASHSCOPE_API_KEY。 +2025-08-04 21:57:57,782 - INFO - RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动... +2025-08-04 21:57:57,795 - INFO - Processing request of type ListToolsRequest +2025-08-04 21:57:57,797 - INFO - Processing request of type ListResourcesRequest +2025-08-04 21:57:57,798 - INFO - Processing request of type ListResourceTemplatesRequest +2025-08-05 18:39:23,841 - INFO - 成功加载 DASHSCOPE_API_KEY。 +2025-08-05 18:39:23,858 - INFO - RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动... +2025-08-05 18:39:23,871 - INFO - Processing request of type ListToolsRequest +2025-08-05 18:39:23,873 - INFO - Processing request of type ListResourcesRequest +2025-08-05 18:39:23,874 - INFO - Processing request of type ListResourceTemplatesRequest +2025-08-05 18:47:28,304 - INFO - Processing request of type CallToolRequest +2025-08-05 18:47:28,306 - INFO - 收到问题: Pawn_InventoryTracker.get_FirstUnloadableThing +2025-08-05 18:47:28,306 - INFO - 找到的潜在关键词: ['get_FirstUnloadableThing', 'Pawn_InventoryTracker'] +2025-08-05 18:47:28,306 - INFO - 提取到关键词: ['get_FirstUnloadableThing', 'Pawn_InventoryTracker'] +2025-08-05 18:47:28,306 - INFO - 缓存未命中,开始实时搜索: Pawn_InventoryTracker-get_FirstUnloadableThing +2025-08-05 18:48:42,219 - INFO - 使用最具体的关键词 'get_FirstUnloadableThing' 未找到文件,尝试所有关键词... +2025-08-05 18:48:44,293 - INFO - 找到 20 个候选文件,开始向量化处理... +2025-08-05 18:48:44,293 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\Pawn_InventoryTracker.txt +2025-08-05 18:48:50,652 - INFO - 向量搜索完成。找到了 5 个匹配项并成功提取了代码。 +2025-08-05 18:49:27,121 - INFO - Processing request of type CallToolRequest +2025-08-05 18:49:27,121 - INFO - 收到问题: Pawn_InventoryTracker.get_FirstUnloadableThing +2025-08-05 18:49:27,122 - INFO - 找到的潜在关键词: ['get_FirstUnloadableThing', 'Pawn_InventoryTracker'] +2025-08-05 18:49:27,122 - INFO - 提取到关键词: ['get_FirstUnloadableThing', 'Pawn_InventoryTracker'] +2025-08-05 18:49:27,131 - INFO - 缓存命中: 关键词 'Pawn_InventoryTracker-get_FirstUnloadableThing' +2025-08-05 19:04:16,910 - INFO - Processing request of type CallToolRequest +2025-08-05 19:04:16,910 - INFO - 收到问题: Verse.Projectile.TickInterval +2025-08-05 19:04:16,910 - INFO - 找到的潜在关键词: ['TickInterval', 'Projectile', 'Verse'] +2025-08-05 19:04:16,910 - INFO - 提取到关键词: ['TickInterval', 'Projectile', 'Verse'] +2025-08-05 19:04:16,910 - INFO - 缓存未命中,开始实时搜索: Projectile-TickInterval-Verse +2025-08-05 19:04:18,552 - INFO - 找到 289 个候选文件,开始向量化处理... +2025-08-05 19:04:18,553 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\Projectile.txt +2025-08-05 19:04:18,554 - WARNING - 候选文件过多 (288),仅处理前 25 个。 +2025-08-05 19:04:28,272 - ERROR - HTTPSConnectionPool(host='dashscope.aliyuncs.com', port=443): Max retries exceeded with url: /api/v1/services/embeddings/text-embedding/text-embedding (Caused by SSLError(SSLEOFError(8, '[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol (_ssl.c:1000)'))) +2025-08-05 19:04:28,272 - ERROR - 调用向量API时出错: HTTPSConnectionPool(host='dashscope.aliyuncs.com', port=443): Max retries exceeded with url: /api/v1/services/embeddings/text-embedding/text-embedding (Caused by SSLError(SSLEOFError(8, '[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol (_ssl.c:1000)'))) +urllib3.exceptions.SSLError: [SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol (_ssl.c:1000) + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "C:\Users\Kalo\AppData\Local\Programs\Python\Python312\Lib\site-packages\requests\adapters.py", line 667, in send + resp = conn.urlopen( + ^^^^^^^^^^^^^ + File "C:\Users\Kalo\AppData\Local\Programs\Python\Python312\Lib\site-packages\urllib3\connectionpool.py", line 841, in urlopen + retries = retries.increment( + ^^^^^^^^^^^^^^^^^^ + File "C:\Users\Kalo\AppData\Local\Programs\Python\Python312\Lib\site-packages\urllib3\util\retry.py", line 519, in increment + raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='dashscope.aliyuncs.com', port=443): Max retries exceeded with url: /api/v1/services/embeddings/text-embedding/text-embedding (Caused by SSLError(SSLEOFError(8, '[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol (_ssl.c:1000)'))) + +During handling of the above exception, another exception occurred: + +Traceback (most recent call last): + File "c:\Steam\steamapps\common\RimWorld\Mods\3516260226\Source\MCP\mcpserver_stdio.py", line 82, in get_embedding + response = dashscope.TextEmbedding.call( + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\Kalo\AppData\Local\Programs\Python\Python312\Lib\site-packages\dashscope\embeddings\text_embedding.py", line 49, in call + return super().call(model=model, + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\Kalo\AppData\Local\Programs\Python\Python312\Lib\site-packages\dashscope\client\base_api.py", line 148, in call + return request.call() + ^^^^^^^^^^^^^^ + File "C:\Users\Kalo\AppData\Local\Programs\Python\Python312\Lib\site-packages\dashscope\api_entities\http_request.py", line 101, in call + output = next(response) + ^^^^^^^^^^^^^^ + File "C:\Users\Kalo\AppData\Local\Programs\Python\Python312\Lib\site-packages\dashscope\api_entities\http_request.py", line 330, in _handle_request + raise e + File "C:\Users\Kalo\AppData\Local\Programs\Python\Python312\Lib\site-packages\dashscope\api_entities\http_request.py", line 313, in _handle_request + response = session.post(url=self.url, + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\Kalo\AppData\Local\Programs\Python\Python312\Lib\site-packages\requests\sessions.py", line 637, in post + return self.request("POST", url, data=data, json=json, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\Kalo\AppData\Local\Programs\Python\Python312\Lib\site-packages\requests\sessions.py", line 589, in request + resp = self.send(prep, **send_kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\Kalo\AppData\Local\Programs\Python\Python312\Lib\site-packages\requests\sessions.py", line 703, in send + r = adapter.send(request, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\Kalo\AppData\Local\Programs\Python\Python312\Lib\site-packages\requests\adapters.py", line 698, in send + raise SSLError(e, request=request) +requests.exceptions.SSLError: HTTPSConnectionPool(host='dashscope.aliyuncs.com', port=443): Max retries exceeded with url: /api/v1/services/embeddings/text-embedding/text-embedding (Caused by SSLError(SSLEOFError(8, '[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol (_ssl.c:1000)'))) +2025-08-05 19:04:32,638 - INFO - 向量搜索完成。找到了 2 个匹配项并成功提取了代码。 +2025-08-06 19:25:05,631 - INFO - 成功加载 DASHSCOPE_API_KEY。 +2025-08-06 19:25:05,642 - INFO - RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动... +2025-08-06 19:25:05,651 - INFO - Processing request of type ListToolsRequest +2025-08-06 19:25:05,653 - INFO - Processing request of type ListResourcesRequest +2025-08-06 19:25:05,653 - INFO - Processing request of type ListResourceTemplatesRequest +2025-08-06 20:19:21,633 - INFO - Processing request of type CallToolRequest +2025-08-06 20:19:21,638 - INFO - 收到问题: How does RimWorld handle delayed actions or events over a specific number of ticks? I'm looking for schedulers or managers. +2025-08-06 20:19:21,640 - INFO - 找到的潜在关键词: ['RimWorld'] +2025-08-06 20:19:21,640 - INFO - 提取到关键词: ['RimWorld'] +2025-08-06 20:19:21,640 - INFO - 缓存未命中,开始实时搜索: RimWorld +2025-08-06 20:19:23,841 - INFO - 找到 8024 个候选文件,开始向量化处理... +2025-08-06 20:19:23,869 - WARNING - 候选文件过多 (8024),仅处理前 25 个。 +2025-08-08 17:22:58,354 - INFO - 成功加载 DASHSCOPE_API_KEY。 +2025-08-08 17:22:58,366 - INFO - RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动... +2025-08-08 17:22:58,377 - INFO - Processing request of type ListToolsRequest +2025-08-08 17:22:58,378 - INFO - Processing request of type ListResourcesRequest +2025-08-08 17:22:58,379 - INFO - Processing request of type ListResourceTemplatesRequest +2025-08-08 17:41:24,024 - INFO - Processing request of type CallToolRequest +2025-08-08 17:41:24,025 - INFO - 收到问题: Building_Bed +2025-08-08 17:41:24,026 - INFO - 找到的潜在关键词: ['Building_Bed'] +2025-08-08 17:41:24,026 - INFO - 提取到关键词: ['Building_Bed'] +2025-08-08 17:41:24,026 - INFO - 缓存未命中,开始实时搜索: Building_Bed +2025-08-08 17:42:44,193 - INFO - 找到 103 个候选文件,开始向量化处理... +2025-08-08 17:42:44,193 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\Building_Bed.txt +2025-08-08 17:42:44,197 - WARNING - 候选文件过多 (102),仅处理前 25 个。 +2025-08-08 17:42:51,398 - INFO - 向量搜索完成。找到了 5 个匹配项并成功提取了代码。 +2025-08-08 17:42:51,404 - INFO - Processing request of type CallToolRequest +2025-08-08 17:42:51,404 - INFO - 收到问题: CryptosleepCasket +2025-08-08 17:42:51,404 - INFO - 找到的潜在关键词: ['CryptosleepCasket'] +2025-08-08 17:42:51,404 - INFO - 提取到关键词: ['CryptosleepCasket'] +2025-08-08 17:42:51,404 - INFO - 缓存未命中,开始实时搜索: CryptosleepCasket +2025-08-08 17:42:53,357 - INFO - 找到 56 个候选文件,开始向量化处理... +2025-08-08 17:42:53,359 - WARNING - 候选文件过多 (56),仅处理前 25 个。 +2025-08-08 17:43:01,261 - INFO - 向量搜索完成。找到了 5 个匹配项并成功提取了代码。 +2025-08-08 17:46:37,047 - INFO - Processing request of type CallToolRequest +2025-08-08 17:46:37,047 - INFO - 收到问题: BiosculpterPod +2025-08-08 17:46:37,047 - INFO - 找到的潜在关键词: ['BiosculpterPod'] +2025-08-08 17:46:37,048 - INFO - 提取到关键词: ['BiosculpterPod'] +2025-08-08 17:46:37,048 - INFO - 缓存未命中,开始实时搜索: BiosculpterPod +2025-08-08 17:46:39,286 - INFO - 找到 42 个候选文件,开始向量化处理... +2025-08-08 17:46:39,286 - WARNING - 候选文件过多 (42),仅处理前 25 个。 +2025-08-08 17:46:46,223 - INFO - 向量搜索完成。找到了 5 个匹配项并成功提取了代码。 +2025-08-08 17:47:06,637 - INFO - Processing request of type CallToolRequest +2025-08-08 17:47:06,637 - INFO - 收到问题: Building_BiosculpterPod class +2025-08-08 17:47:06,637 - INFO - 找到的潜在关键词: ['Building_BiosculpterPod'] +2025-08-08 17:47:06,637 - INFO - 提取到关键词: ['Building_BiosculpterPod'] +2025-08-08 17:47:06,638 - INFO - 缓存未命中,开始实时搜索: Building_BiosculpterPod +2025-08-08 17:47:08,918 - INFO - 未找到与 '['Building_BiosculpterPod']' 相关的文件。 +2025-08-08 17:56:16,922 - INFO - Processing request of type CallToolRequest +2025-08-08 17:56:16,922 - INFO - 收到问题: ThingDef of BiosculpterPod +2025-08-08 17:56:16,922 - INFO - 找到的潜在关键词: ['BiosculpterPod', 'ThingDef'] +2025-08-08 17:56:16,922 - INFO - 提取到关键词: ['BiosculpterPod', 'ThingDef'] +2025-08-08 17:56:16,922 - INFO - 缓存未命中,开始实时搜索: BiosculpterPod-ThingDef +2025-08-08 17:56:18,882 - INFO - 找到 50 个候选文件,开始向量化处理... +2025-08-08 17:56:18,882 - WARNING - 候选文件过多 (50),仅处理前 25 个。 +2025-08-08 17:56:25,938 - INFO - 向量搜索完成。找到了 5 个匹配项并成功提取了代码。 +2025-08-08 18:50:39,345 - INFO - Processing request of type CallToolRequest +2025-08-08 18:50:39,347 - INFO - 收到问题: Building_BiosculpterPod class definition +2025-08-08 18:50:39,348 - INFO - 找到的潜在关键词: ['Building_BiosculpterPod'] +2025-08-08 18:50:39,348 - INFO - 提取到关键词: ['Building_BiosculpterPod'] +2025-08-08 18:50:39,348 - INFO - 缓存未命中,开始实时搜索: Building_BiosculpterPod +2025-08-08 18:52:17,079 - INFO - 未找到与 '['Building_BiosculpterPod']' 相关的文件。 +2025-08-08 18:53:58,078 - INFO - Processing request of type CallToolRequest +2025-08-08 18:53:58,078 - INFO - 收到问题: Building_BiosculpterPod class definition +2025-08-08 18:53:58,078 - INFO - 找到的潜在关键词: ['Building_BiosculpterPod'] +2025-08-08 18:53:58,078 - INFO - 提取到关键词: ['Building_BiosculpterPod'] +2025-08-08 18:53:58,078 - INFO - 缓存未命中,开始实时搜索: Building_BiosculpterPod +2025-08-08 18:54:00,558 - INFO - 未找到与 '['Building_BiosculpterPod']' 相关的文件。 +2025-08-08 19:07:28,003 - INFO - Processing request of type CallToolRequest +2025-08-08 19:07:28,003 - INFO - 收到问题: CompBiosculpterPod and CompProperties_BiosculpterPod +2025-08-08 19:07:28,003 - INFO - 找到的潜在关键词: ['CompProperties_BiosculpterPod', 'CompBiosculpterPod'] +2025-08-08 19:07:28,003 - INFO - 提取到关键词: ['CompProperties_BiosculpterPod', 'CompBiosculpterPod'] +2025-08-08 19:07:28,004 - INFO - 缓存未命中,开始实时搜索: CompBiosculpterPod-CompProperties_BiosculpterPod +2025-08-08 19:07:29,829 - INFO - 找到 11 个候选文件,开始向量化处理... +2025-08-08 19:07:29,829 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_BiosculpterPod.txt +2025-08-08 19:07:29,829 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompBiosculpterPod.txt +2025-08-08 19:07:31,777 - INFO - 向量搜索完成。找到了 5 个匹配项并成功提取了代码。 +2025-08-08 19:35:05,891 - INFO - Processing request of type CallToolRequest +2025-08-08 19:35:05,891 - INFO - 收到问题: C# class JobDef fields +2025-08-08 19:35:05,891 - INFO - 找到的潜在关键词: ['JobDef'] +2025-08-08 19:35:05,891 - INFO - 提取到关键词: ['JobDef'] +2025-08-08 19:35:05,891 - INFO - 缓存未命中,开始实时搜索: JobDef +2025-08-08 19:35:08,071 - INFO - 找到 571 个候选文件,开始向量化处理... +2025-08-08 19:35:08,072 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\JobDef.txt +2025-08-08 19:35:08,073 - WARNING - 候选文件过多 (570),仅处理前 25 个。 +2025-08-08 19:35:13,917 - INFO - 向量搜索完成。找到了 2 个匹配项并成功提取了代码。 +2025-08-08 23:59:20,246 - INFO - Processing request of type CallToolRequest +2025-08-08 23:59:20,269 - INFO - 收到问题: ThingDef for BiosculpterPod +2025-08-08 23:59:20,270 - INFO - 找到的潜在关键词: ['BiosculpterPod', 'ThingDef'] +2025-08-08 23:59:20,270 - INFO - 提取到关键词: ['BiosculpterPod', 'ThingDef'] +2025-08-08 23:59:20,302 - INFO - 缓存命中: 关键词 'BiosculpterPod-ThingDef' +2025-08-09 00:32:44,309 - INFO - Processing request of type CallToolRequest +2025-08-09 00:32:44,309 - INFO - 收到问题: JobDriver_EnterCryptosleepCasket +2025-08-09 00:32:44,310 - INFO - 找到的潜在关键词: ['JobDriver_EnterCryptosleepCasket'] +2025-08-09 00:32:44,310 - INFO - 提取到关键词: ['JobDriver_EnterCryptosleepCasket'] +2025-08-09 00:32:44,310 - INFO - 缓存未命中,开始实时搜索: JobDriver_EnterCryptosleepCasket +2025-08-09 00:33:57,816 - INFO - 找到 2 个候选文件,开始向量化处理... +2025-08-09 00:33:57,816 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\JobDriver_EnterCryptosleepCasket.txt +2025-08-09 00:33:58,572 - INFO - 向量搜索完成。找到了 1 个匹配项并成功提取了代码。 +2025-08-09 00:42:26,054 - INFO - Processing request of type CallToolRequest +2025-08-09 00:42:26,054 - INFO - 收到问题: ThingDef for BiosculpterPod +2025-08-09 00:42:26,054 - INFO - 找到的潜在关键词: ['BiosculpterPod', 'ThingDef'] +2025-08-09 00:42:26,054 - INFO - 提取到关键词: ['BiosculpterPod', 'ThingDef'] +2025-08-09 00:42:26,069 - INFO - 缓存命中: 关键词 'BiosculpterPod-ThingDef' +2025-08-09 10:18:42,504 - INFO - 成功加载 DASHSCOPE_API_KEY。 +2025-08-09 10:18:42,520 - INFO - RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动... +2025-08-09 10:18:42,533 - INFO - Processing request of type ListToolsRequest +2025-08-09 10:18:42,536 - INFO - Processing request of type ListResourcesRequest +2025-08-09 10:18:42,537 - INFO - Processing request of type ListResourceTemplatesRequest +2025-08-09 11:08:17,356 - INFO - 成功加载 DASHSCOPE_API_KEY。 +2025-08-09 11:08:17,366 - INFO - RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动... +2025-08-09 11:08:17,375 - INFO - Processing request of type ListToolsRequest +2025-08-09 11:08:17,377 - INFO - Processing request of type ListResourcesRequest +2025-08-09 11:08:17,378 - INFO - Processing request of type ListResourceTemplatesRequest +2025-08-09 13:01:19,595 - INFO - Processing request of type CallToolRequest +2025-08-09 13:01:19,600 - INFO - 收到问题: HediffDef named Malnutrition +2025-08-09 13:01:19,603 - INFO - 找到的潜在关键词: ['HediffDef', 'Malnutrition'] +2025-08-09 13:01:19,603 - INFO - 提取到关键词: ['HediffDef', 'Malnutrition'] +2025-08-09 13:01:19,604 - INFO - 缓存未命中,开始实时搜索: HediffDef-Malnutrition +2025-08-09 13:01:21,133 - INFO - 找到 20 个候选文件,开始向量化处理... +2025-08-09 13:01:28,002 - INFO - 向量搜索完成。找到了 5 个匹配项并成功提取了代码。 +2025-08-09 13:02:58,802 - INFO - Processing request of type CallToolRequest +2025-08-09 13:02:58,803 - INFO - 收到问题: HediffDef named Luciferium +2025-08-09 13:02:58,803 - INFO - 找到的潜在关键词: ['HediffDef', 'Luciferium'] +2025-08-09 13:02:58,803 - INFO - 提取到关键词: ['HediffDef', 'Luciferium'] +2025-08-09 13:02:58,803 - INFO - 缓存未命中,开始实时搜索: HediffDef-Luciferium +2025-08-09 13:03:00,318 - INFO - 找到 29 个候选文件,开始向量化处理... +2025-08-09 13:03:00,318 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\Core\Languages\ChineseSimplified (简体中文)\DefInjected\NeedDef\Luciferium.xml +2025-08-09 13:03:00,318 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\Core\Defs\Drugs\Luciferium.xml +2025-08-09 13:03:00,318 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\Core\Languages\ChineseSimplified (简体中文)\DefInjected\ChemicalDef\Luciferium.xml +2025-08-09 13:03:00,318 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\Core\Languages\ChineseSimplified (简体中文)\DefInjected\ThingDef\Luciferium.xml +2025-08-09 13:03:00,318 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\Core\Languages\ChineseSimplified (简体中文)\DefInjected\HediffDef\Luciferium.xml +2025-08-09 13:03:12,903 - INFO - 向量搜索完成。找到了 1 个匹配项并成功提取了代码。 +2025-08-09 13:33:10,729 - INFO - Processing request of type CallToolRequest +2025-08-09 13:33:10,729 - INFO - 收到问题: ThingDef for Wula race +2025-08-09 13:33:10,729 - INFO - 找到的潜在关键词: ['Wula', 'ThingDef'] +2025-08-09 13:33:10,729 - INFO - 提取到关键词: ['Wula', 'ThingDef'] +2025-08-09 13:33:10,729 - INFO - 缓存未命中,开始实时搜索: ThingDef-Wula +2025-08-09 13:33:12,622 - INFO - 找到 2044 个候选文件,开始向量化处理... +2025-08-09 13:33:12,628 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\ThingDef.txt +2025-08-09 13:33:12,629 - WARNING - 候选文件过多 (2043),仅处理前 25 个。 +2025-08-09 13:34:54,603 - INFO - Processing request of type CallToolRequest +2025-08-09 13:34:54,603 - INFO - 收到问题: LifeStageDef for HumanlikeAdult +2025-08-09 13:34:54,603 - INFO - 找到的潜在关键词: ['LifeStageDef', 'HumanlikeAdult'] +2025-08-09 13:34:54,603 - INFO - 提取到关键词: ['LifeStageDef', 'HumanlikeAdult'] +2025-08-09 13:34:54,603 - INFO - 缓存未命中,开始实时搜索: HumanlikeAdult-LifeStageDef +2025-08-09 13:34:56,048 - INFO - 找到 6 个候选文件,开始向量化处理... +2025-08-09 13:34:58,422 - INFO - 向量搜索完成。找到了 5 个匹配项并成功提取了代码。 +2025-08-09 13:35:56,165 - INFO - Processing request of type CallToolRequest +2025-08-09 13:35:56,165 - INFO - 收到问题: source code for ColonistBarColonistDrawer.DrawIcons +2025-08-09 13:35:56,165 - INFO - 找到的潜在关键词: ['DrawIcons', 'ColonistBarColonistDrawer'] +2025-08-09 13:35:56,165 - INFO - 提取到关键词: ['DrawIcons', 'ColonistBarColonistDrawer'] +2025-08-09 13:35:56,165 - INFO - 缓存未命中,开始实时搜索: ColonistBarColonistDrawer-DrawIcons +2025-08-09 13:35:57,819 - INFO - 找到 2 个候选文件,开始向量化处理... +2025-08-09 13:35:57,820 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\ColonistBarColonistDrawer.txt +2025-08-09 13:35:58,503 - INFO - 向量搜索完成。找到了 1 个匹配项并成功提取了代码。 +2025-08-09 19:13:46,499 - INFO - Processing request of type CallToolRequest +2025-08-09 19:13:46,501 - INFO - 收到问题: PawnKindDef lifeStages +2025-08-09 19:13:46,502 - INFO - 找到的潜在关键词: ['PawnKindDef', 'lifeStages'] +2025-08-09 19:13:46,502 - INFO - 提取到关键词: ['PawnKindDef', 'lifeStages'] +2025-08-09 19:13:46,502 - INFO - 缓存未命中,开始实时搜索: PawnKindDef-lifeStages +2025-08-09 19:14:57,492 - INFO - 找到 314 个候选文件,开始向量化处理... +2025-08-09 19:14:57,492 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\PawnKindDef.txt +2025-08-09 19:14:57,493 - WARNING - 候选文件过多 (313),仅处理前 25 个。 +2025-08-09 19:15:07,385 - INFO - 向量搜索完成。找到了 1 个匹配项并成功提取了代码。 +2025-08-09 19:15:07,406 - INFO - Processing request of type CallToolRequest +2025-08-09 19:15:07,407 - INFO - 收到问题: PawnKindDef lifeStages +2025-08-09 19:15:07,407 - INFO - 找到的潜在关键词: ['PawnKindDef', 'lifeStages'] +2025-08-09 19:15:07,407 - INFO - 提取到关键词: ['PawnKindDef', 'lifeStages'] +2025-08-09 19:15:07,415 - INFO - 缓存命中: 关键词 'PawnKindDef-lifeStages' +2025-08-09 19:22:06,405 - INFO - Processing request of type CallToolRequest +2025-08-09 19:22:06,405 - INFO - 收到问题: CompProperties_Refuelable +2025-08-09 19:22:06,405 - INFO - 找到的潜在关键词: ['CompProperties_Refuelable'] +2025-08-09 19:22:06,405 - INFO - 提取到关键词: ['CompProperties_Refuelable'] +2025-08-09 19:22:06,405 - INFO - 缓存未命中,开始实时搜索: CompProperties_Refuelable +2025-08-09 19:22:08,376 - INFO - 找到 18 个候选文件,开始向量化处理... +2025-08-09 19:22:08,376 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_Refuelable.txt +2025-08-09 19:22:17,721 - INFO - 向量搜索完成。找到了 5 个匹配项并成功提取了代码。 +2025-08-09 19:24:09,129 - INFO - Processing request of type CallToolRequest +2025-08-09 19:24:09,129 - INFO - 收到问题: CompProperties_Refuelable +2025-08-09 19:24:09,129 - INFO - 找到的潜在关键词: ['CompProperties_Refuelable'] +2025-08-09 19:24:09,129 - INFO - 提取到关键词: ['CompProperties_Refuelable'] +2025-08-09 19:24:09,148 - INFO - 缓存命中: 关键词 'CompProperties_Refuelable' +2025-08-09 20:37:05,246 - INFO - Processing request of type CallToolRequest +2025-08-09 20:37:05,247 - INFO - 收到问题: WorkGiver_Scanner class definition, especially methods for float menu options +2025-08-09 20:37:05,248 - INFO - 找到的潜在关键词: ['WorkGiver_Scanner'] +2025-08-09 20:37:05,248 - INFO - 提取到关键词: ['WorkGiver_Scanner'] +2025-08-09 20:37:05,248 - INFO - 缓存未命中,开始实时搜索: WorkGiver_Scanner +2025-08-09 20:37:15,713 - INFO - 找到 83 个候选文件,开始向量化处理... +2025-08-09 20:37:15,714 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_Scanner.txt +2025-08-09 20:37:15,714 - WARNING - 候选文件过多 (82),仅处理前 25 个。 +2025-08-09 20:37:21,549 - INFO - 向量搜索完成。找到了 5 个匹配项并成功提取了代码。 +2025-08-09 21:04:45,693 - INFO - Processing request of type CallToolRequest +2025-08-09 21:04:45,712 - INFO - 收到问题: TargetingParameters.ForRescue +2025-08-09 21:04:45,712 - INFO - 找到的潜在关键词: ['TargetingParameters', 'ForRescue'] +2025-08-09 21:04:45,712 - INFO - 提取到关键词: ['TargetingParameters', 'ForRescue'] +2025-08-09 21:04:45,746 - INFO - 缓存未命中,开始实时搜索: ForRescue-TargetingParameters +2025-08-09 21:05:06,716 - INFO - 找到 55 个候选文件,开始向量化处理... +2025-08-09 21:05:06,717 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\TargetingParameters.txt +2025-08-09 21:05:06,732 - WARNING - 候选文件过多 (54),仅处理前 25 个。 +2025-08-09 21:05:34,758 - INFO - Processing request of type CallToolRequest +2025-08-09 21:05:34,758 - INFO - 收到问题: FloatMenuMakerMap AddHumanlikeOrders +2025-08-09 21:05:34,758 - INFO - 找到的潜在关键词: ['AddHumanlikeOrders', 'FloatMenuMakerMap'] +2025-08-09 21:05:34,758 - INFO - 提取到关键词: ['AddHumanlikeOrders', 'FloatMenuMakerMap'] +2025-08-09 21:05:34,758 - INFO - 缓存未命中,开始实时搜索: AddHumanlikeOrders-FloatMenuMakerMap +2025-08-09 21:05:36,675 - INFO - 使用最具体的关键词 'AddHumanlikeOrders' 未找到文件,尝试所有关键词... +2025-08-09 21:05:38,735 - INFO - 找到 9 个候选文件,开始向量化处理... +2025-08-09 21:05:38,735 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\FloatMenuMakerMap.txt +2025-08-09 21:05:41,806 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-09 22:01:45,270 - INFO - 成功加载 DASHSCOPE_API_KEY。 +2025-08-09 22:01:45,281 - INFO - RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动... +2025-08-09 22:01:45,293 - INFO - Processing request of type ListToolsRequest +2025-08-09 22:01:45,294 - INFO - Processing request of type ListResourcesRequest +2025-08-09 22:01:45,295 - INFO - Processing request of type ListResourceTemplatesRequest +2025-08-09 22:36:40,663 - INFO - Processing request of type CallToolRequest +2025-08-09 22:36:40,664 - INFO - 收到问题: Source code for the Toil Toils_Haul.StartCarryThing +2025-08-09 22:36:40,664 - INFO - 找到的潜在关键词: ['Source', 'Toils_Haul', 'StartCarryThing', 'Toil'] +2025-08-09 22:36:40,664 - INFO - 提取到关键词: ['Source', 'Toils_Haul', 'StartCarryThing', 'Toil'] +2025-08-09 22:36:40,664 - INFO - 缓存未命中,开始实时搜索: Source-StartCarryThing-Toil-Toils_Haul +2025-08-09 22:36:42,122 - INFO - 找到 58 个候选文件,开始向量化处理... +2025-08-09 22:36:42,122 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse.AI\Toils_Haul.txt +2025-08-09 22:36:42,123 - WARNING - 候选文件过多 (57),仅处理前 25 个。 +2025-08-09 22:36:49,931 - INFO - 向量搜索完成。找到了 5 个匹配项并成功提取了代码。 +2025-08-09 22:37:26,949 - INFO - Processing request of type CallToolRequest +2025-08-09 22:37:26,950 - INFO - 收到问题: ThingDef for the Human race +2025-08-09 22:37:26,950 - INFO - 找到的潜在关键词: ['Human', 'ThingDef'] +2025-08-09 22:37:26,950 - INFO - 提取到关键词: ['Human', 'ThingDef'] +2025-08-09 22:37:26,950 - INFO - 缓存未命中,开始实时搜索: Human-ThingDef +2025-08-09 22:37:28,442 - INFO - 找到 2044 个候选文件,开始向量化处理... +2025-08-09 22:37:28,444 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\ThingDef.txt +2025-08-09 22:37:28,449 - WARNING - 候选文件过多 (2043),仅处理前 25 个。 +2025-08-09 22:37:37,558 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-09 22:51:16,961 - INFO - Processing request of type CallToolRequest +2025-08-09 22:51:16,961 - INFO - 收到问题: WorkGiver_HaulToMaintenancePod +2025-08-09 22:51:16,961 - INFO - 找到的潜在关键词: ['WorkGiver_HaulToMaintenancePod'] +2025-08-09 22:51:16,961 - INFO - 提取到关键词: ['WorkGiver_HaulToMaintenancePod'] +2025-08-09 22:51:16,961 - INFO - 缓存未命中,开始实时搜索: WorkGiver_HaulToMaintenancePod +2025-08-09 22:51:18,339 - INFO - 未找到与 '['WorkGiver_HaulToMaintenancePod']' 相关的文件。 +2025-08-09 23:24:17,104 - INFO - Processing request of type CallToolRequest +2025-08-09 23:24:17,104 - INFO - 收到问题: WorkGiver_HaulToBiosculpterPod, CompBiosculpterPod +2025-08-09 23:24:17,104 - INFO - 找到的潜在关键词: ['WorkGiver_HaulToBiosculpterPod', 'CompBiosculpterPod'] +2025-08-09 23:24:17,104 - INFO - 提取到关键词: ['WorkGiver_HaulToBiosculpterPod', 'CompBiosculpterPod'] +2025-08-09 23:24:17,104 - INFO - 缓存未命中,开始实时搜索: CompBiosculpterPod-WorkGiver_HaulToBiosculpterPod +2025-08-09 23:24:18,974 - INFO - 找到 2 个候选文件,开始向量化处理... +2025-08-09 23:24:18,974 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_HaulToBiosculpterPod.txt +2025-08-09 23:24:19,422 - INFO - 向量搜索完成。找到了 1 个匹配项并成功提取了代码。 +2025-08-09 23:30:21,294 - INFO - Processing request of type CallToolRequest +2025-08-09 23:30:21,294 - INFO - 收到问题: JobDefOf.Rescue, JobDriver_TakeToBed +2025-08-09 23:30:21,294 - INFO - 找到的潜在关键词: ['JobDriver_TakeToBed', 'Rescue', 'JobDefOf'] +2025-08-09 23:30:21,294 - INFO - 提取到关键词: ['JobDriver_TakeToBed', 'Rescue', 'JobDefOf'] +2025-08-09 23:30:21,294 - INFO - 缓存未命中,开始实时搜索: JobDefOf-JobDriver_TakeToBed-Rescue +2025-08-09 23:30:22,675 - INFO - 找到 4 个候选文件,开始向量化处理... +2025-08-09 23:30:22,675 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\JobDriver_TakeToBed.txt +2025-08-09 23:30:24,295 - INFO - 向量搜索完成。找到了 3 个匹配项并成功提取了代码。 +2025-08-09 23:31:46,828 - INFO - Processing request of type CallToolRequest +2025-08-09 23:31:46,828 - INFO - 收到问题: ThingDef of BiosculpterPod +2025-08-09 23:31:46,828 - INFO - 找到的潜在关键词: ['BiosculpterPod', 'ThingDef'] +2025-08-09 23:31:46,829 - INFO - 提取到关键词: ['BiosculpterPod', 'ThingDef'] +2025-08-09 23:31:46,845 - INFO - 缓存命中: 关键词 'BiosculpterPod-ThingDef' +2025-08-09 23:32:57,437 - INFO - Processing request of type CallToolRequest +2025-08-09 23:32:57,437 - INFO - 收到问题: JobDefOf.CarryToBiosculpterPod, JobDriver_CarryToBiosculpterPod +2025-08-09 23:32:57,437 - INFO - 找到的潜在关键词: ['JobDriver_CarryToBiosculpterPod', 'JobDefOf', 'CarryToBiosculpterPod'] +2025-08-09 23:32:57,437 - INFO - 提取到关键词: ['JobDriver_CarryToBiosculpterPod', 'JobDefOf', 'CarryToBiosculpterPod'] +2025-08-09 23:32:57,437 - INFO - 缓存未命中,开始实时搜索: CarryToBiosculpterPod-JobDefOf-JobDriver_CarryToBiosculpterPod +2025-08-09 23:32:58,909 - INFO - 找到 3 个候选文件,开始向量化处理... +2025-08-09 23:32:58,910 - INFO - 文件名精确匹配: C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\JobDriver_CarryToBiosculpterPod.txt +2025-08-09 23:32:59,792 - INFO - 向量搜索完成。找到了 1 个匹配项并成功提取了代码。 diff --git a/Source/MCP/mcpserver_stdio.py b/MCP/mcpserver_stdio.py similarity index 100% rename from Source/MCP/mcpserver_stdio.py rename to MCP/mcpserver_stdio.py diff --git a/MCP/pid.txt b/MCP/pid.txt new file mode 100644 index 00000000..32b2ab6a --- /dev/null +++ b/MCP/pid.txt @@ -0,0 +1 @@ +86696 \ No newline at end of file diff --git a/MCP/vector_cache/AbilityDef.txt b/MCP/vector_cache/AbilityDef.txt new file mode 100644 index 00000000..08b7ce71 --- /dev/null +++ b/MCP/vector_cache/AbilityDef.txt @@ -0,0 +1,621 @@ +根据向量相似度分析,与 'AbilityDef' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\AbilityDef.txt` + +```csharp +public class AbilityDef : Def +{ + public Type abilityClass = typeof(Ability); + + public Type gizmoClass = typeof(Command_Ability); + + public List comps = new List(); + + public AbilityCategoryDef category; + + public int displayOrder; + + public List statBases; + + public VerbProperties verbProperties; + + public KeyBindingDef hotKey; + + public JobDef jobDef; + + public ThingDef warmupMote; + + public EffecterDef warmupEffecter; + + public FleckDef emittedFleck; + + public int emissionInterval; + + public string warmupMoteSocialSymbol; + + public SoundDef warmupStartSound; + + public SoundDef warmupSound; + + public SoundDef warmupPreEndSound; + + public float warmupPreEndSoundSeconds; + + public Vector3 moteDrawOffset; + + public float moteOffsetAmountTowardsTarget; + + public bool canUseAoeToGetTargets = true; + + public bool useAverageTargetPositionForWarmupEffecter; + + public bool targetRequired = true; + + public bool targetWorldCell; + + public bool showGizmoOnWorldView; + + public bool aiCanUse; + + public bool ai_SearchAOEForTargets; + + public bool ai_IsOffensive = true; + + public bool ai_IsIncendiary = true; + + public bool groupAbility; + + public int level; + + public IntRange cooldownTicksRange; + + public bool cooldownPerCharge; + + public bool hasExternallyHandledCooldown; + + public int charges = -1; + + public AbilityGroupDef groupDef; + + public bool overrideGroupCooldown; + + public List requiredMemes; + + public bool sendLetterOnCooldownComplete; + + public bool sendMessageOnCooldownComplete; + + public bool displayGizmoWhileUndrafted; + + public bool disableGizmoWhileUndrafted = true; + + public bool writeCombatLog; + + public bool stunTargetWhileCasting; + + public bool showPsycastEffects = true; + + public bool showCastingProgressBar; + + public float detectionChanceOverride = -1f; + + public float uiOrder; + + public bool waitForJobEnd; + + public bool showWhenDrafted = true; + + public bool showOnCharacterCard = true; + + public bool hostile = true; + + public bool casterMustBeCapableOfViolence = true; + + [MustTranslate] + public string confirmationDialogText; + + [NoTranslate] + public string iconPath; + + public Texture2D uiIcon = BaseContent.BadTex; + + private string cachedTooltip; + + private Pawn cachedTooltipPawn; + + private List cachedTargets; + + private int requiredPsyfocusBandCached = -1; + + private bool? anyCompOverridesPsyfocusCost; + + private FloatRange psyfocusCostRange = new FloatRange(-1f, -1f); + + private string psyfocusCostPercent; + + private string psyfocusCostPercentMax; + + private Texture2D warmupMoteSocialSymbolCached; + + public float EntropyGain => statBases.GetStatValueFromList(StatDefOf.Ability_EntropyGain, 0f); + + public float PsyfocusCost => statBases.GetStatValueFromList(StatDefOf.Ability_PsyfocusCost, 0f); + + public float EffectRadius => statBases.GetStatValueFromList(StatDefOf.Ability_EffectRadius, 0f); + + public bool HasAreaOfEffect => EffectRadius > float.Epsilon; + + public float DetectionChance + { + get + { + if (!(detectionChanceOverride >= 0f)) + { + return this.GetStatValueAbstract(StatDefOf.Ability_DetectChancePerEntropy); + } + return detectionChanceOverride; + } + } + + public bool IsPsycast => typeof(Psycast).IsAssignableFrom(abilityClass); + + public string PsyfocusCostPercent + { + get + { + if (psyfocusCostPercent.NullOrEmpty()) + { + psyfocusCostPercent = PsyfocusCost.ToStringPercent(); + } + return psyfocusCostPercent; + } + } + + public string PsyfocusCostPercentMax + { + get + { + if (psyfocusCostPercentMax.NullOrEmpty()) + { + psyfocusCostPercentMax = PsyfocusCostRange.max.ToStringPercent(); + } + return psyfocusCostPercentMax; + } + } + + public int RequiredPsyfocusBand + { + get + { + if (requiredPsyfocusBandCached == -1) + { + requiredPsyfocusBandCached = Pawn_PsychicEntropyTracker.MaxAbilityLevelPerPsyfocusBand.Count - 1; + for (int i = 0; i < Pawn_PsychicEntropyTracker.MaxAbilityLevelPerPsyfocusBand.Count; i++) + { + int num = Pawn_PsychicEntropyTracker.MaxAbilityLevelPerPsyfocusBand[i]; + if (level <= num) + { + requiredPsyfocusBandCached = i; + break; + } + } + } + return requiredPsyfocusBandCached; + } + } + + public bool AnyCompOverridesPsyfocusCost + { + get + { + if (!anyCompOverridesPsyfocusCost.HasValue) + { + anyCompOverridesPsyfocusCost = false; + if (comps != null) + { + foreach (AbilityCompProperties comp in comps) + { + if (comp.OverridesPsyfocusCost) + { + anyCompOverridesPsyfocusCost = true; + break; + } + } + } + } + return anyCompOverridesPsyfocusCost.Value; + } + } + + public FloatRange PsyfocusCostRange + { + get + { + if (psyfocusCostRange.min < 0f) + { + if (!AnyCompOverridesPsyfocusCost) + { + psyfocusCostRange = new FloatRange(PsyfocusCost, PsyfocusCost); + } + else + { + foreach (AbilityCompProperties comp in comps) + { + if (comp.OverridesPsyfocusCost) + { + psyfocusCostRange = comp.PsyfocusCostRange; + break; + } + } + } + } + return psyfocusCostRange; + } + } + + public Texture2D WarmupMoteSocialSymbol + { + get + { + if (!warmupMoteSocialSymbol.NullOrEmpty() && warmupMoteSocialSymbolCached == null) + { + warmupMoteSocialSymbolCached = ContentFinder.Get(warmupMoteSocialSymbol); + } + return warmupMoteSocialSymbolCached; + } + } + + public IEnumerable StatSummary(Pawn forPawn = null) + { + string text = null; + foreach (AbilityCompProperties comp in comps) + { + if (comp.OverridesPsyfocusCost) + { + text = comp.PsyfocusCostExplanation; + break; + } + } + if (text == null) + { + if (PsyfocusCost > float.Epsilon) + { + yield return "AbilityPsyfocusCost".Translate() + ": " + PsyfocusCost.ToStringPercent(); + } + } + else + { + yield return text; + } + if (EntropyGain > float.Epsilon) + { + yield return string.Concat("AbilityEntropyGain".Translate() + ": ", EntropyGain.ToString()); + } + if (verbProperties.warmupTime > float.Epsilon) + { + yield return string.Concat("AbilityCastingTime".Translate() + ": ", verbProperties.warmupTime.ToString()) + "LetterSecond".Translate(); + } + if (cooldownTicksRange.min == cooldownTicksRange.max && cooldownTicksRange.min > 0) + { + yield return "StatsReport_Cooldown".Translate() + ": " + cooldownTicksRange.min.ToStringTicksToPeriod(allowSeconds: true, shortForm: false, canUseDecimals: true, allowYears: false); + } + float num = EffectDuration(forPawn); + if (num > float.Epsilon) + { + int num2 = num.SecondsToTicks(); + yield return "AbilityDuration".Translate() + ": " + ((num2 >= 2500) ? num2.ToStringTicksToPeriod() : (num.ToString() + "LetterSecond".Translate())); + } + if (HasAreaOfEffect) + { + yield return string.Concat("AbilityEffectRadius".Translate() + ": ", Mathf.Ceil(EffectRadius).ToString()); + } + if (comps == null) + { + yield break; + } + for (int i = 0; i < comps.Count; i++) + { + foreach (string item in comps[i].ExtraStatSummary()) + { + yield return item; + } + } + } + + public float EffectDuration(Pawn forPawn = null) + { + return this.GetStatValueAbstract(StatDefOf.Ability_Duration, forPawn); + } + + public override void PostLoad() + { + if (!string.IsNullOrEmpty(iconPath)) + { + LongEventHandler.ExecuteWhenFinished(delegate + { + uiIcon = ContentFinder.Get(iconPath); + }); + } + } + + public string GetTooltip(Pawn pawn = null) + { + if (cachedTooltip == null || cachedTooltipPawn != pawn) + { + cachedTooltip = LabelCap.Colorize(ColoredText.TipSectionTitleColor) + ((level > 0) ? string.Concat("\n" + "Level".Translate().CapitalizeFirst() + " ", level.ToString()) : "") + "\n\n" + description; + cachedTooltipPawn = pawn; + string text = StatSummary(pawn).ToLineList(); + if (!text.NullOrEmpty()) + { + cachedTooltip = cachedTooltip + "\n\n" + text; + } + } + if (pawn != null && ModsConfig.RoyaltyActive && IsPsycast && level > 0) + { + Faction first = Faction.GetMinTitleForImplantAllFactions(HediffDefOf.PsychicAmplifier).First; + if (first != null) + { + RoyalTitleDef minTitleForImplant = first.GetMinTitleForImplant(HediffDefOf.PsychicAmplifier, level); + RoyalTitleDef currentTitle = pawn.royalty.GetCurrentTitle(first); + if (minTitleForImplant != null && (currentTitle == null || currentTitle.seniority < minTitleForImplant.seniority) && DetectionChance > 0f) + { + return cachedTooltip + "\n\n" + ((string)"PsycastIsIllegal".Translate(pawn.Named("PAWN"), minTitleForImplant.GetLabelCapFor(pawn).Named("TITLE"))).Colorize(ColoredText.WarningColor); + } + } + } + return cachedTooltip; + } + + public override IEnumerable SpecialDisplayStats(StatRequest req) + { + if (cachedTargets == null) + { + cachedTargets = new List(); + if (verbProperties.targetParams.canTargetPawns && verbProperties.targetParams.canTargetSelf) + { + cachedTargets.Add("TargetSelf".Translate()); + } + if (verbProperties.targetParams.canTargetLocations) + { + cachedTargets.Add("TargetGround".Translate()); + } + if (verbProperties.targetParams.canTargetPawns && verbProperties.targetParams.canTargetHumans) + { + cachedTargets.Add("TargetHuman".Translate()); + } + if (verbProperties.targetParams.canTargetPawns && verbProperties.targetParams.canTargetAnimals) + { + cachedTargets.Add("TargetAnimal".Translate()); + } + } + int num = comps.OfType().Sum((CompProperties_AbilityEffect e) => e.goodwillImpact); + if (num != 0) + { + yield return new StatDrawEntry(StatCategoryDefOf.Ability, StatDefOf.Ability_GoodwillImpact, num, req); + } + if (IsPsycast && level != 0) + { + yield return new StatDrawEntry(StatCategoryDefOf.Ability, StatDefOf.Ability_RequiredPsylink, level, req); + } + yield return new StatDrawEntry(StatCategoryDefOf.Ability, StatDefOf.Ability_CastingTime, verbProperties.warmupTime, req); + if (verbProperties.range > 0f) + { + yield return new StatDrawEntry(StatCategoryDefOf.Ability, StatDefOf.Ability_Range, verbProperties.range, req); + } + yield return new StatDrawEntry(StatCategoryDefOf.Ability, "Target".Translate(), cachedTargets.ToCommaList().CapitalizeFirst(), "AbilityTargetDesc".Translate(), 1001); + yield return new StatDrawEntry(StatCategoryDefOf.Ability, "AbilityRequiresLOS".Translate(), verbProperties.requireLineOfSight ? "Yes".Translate() : "No".Translate(), "", 1000); + } + + public override IEnumerable ConfigErrors() + { + foreach (string item in base.ConfigErrors()) + { + yield return item; + } + if (abilityClass == null) + { + yield return "abilityClass is null"; + } + if (verbProperties == null) + { + yield return "verbProperties are null"; + } + if (label.NullOrEmpty()) + { + yield return "no label"; + } + if (statBases != null) + { + foreach (StatModifier statBase in statBases) + { + if (statBases.Count((StatModifier st) => st.stat == statBase.stat) > 1) + { + yield return "defines the stat base " + statBase.stat?.ToString() + " more than once."; + } + } + } + for (int i = 0; i < comps.Count; i++) + { + foreach (string item2 in comps[i].ConfigErrors(this)) + { + yield return item2; + } + } + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Royalty\Defs\AbilityDefs\Abilities.xml` +**相似度:** 0.5815 + +```xml + + Skip + +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\AbilityStatModifiers.txt` +**相似度:** 0.5807 + +```csharp +public class AbilityStatModifiers +{ + public AbilityDef ability; + + public List modifiers; +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\AbilityDefOf.txt` +**相似度:** 0.5779 + +```csharp +public static class AbilityDefOf +{ + [MayRequireRoyalty] + public static AbilityDef Speech; + + [MayRequireBiotech] + public static AbilityDef ReimplantXenogerm; + + [MayRequireBiotech] + public static AbilityDef ResurrectionMech; + + [MayRequireAnomaly] + public static AbilityDef EntitySkip; + + [MayRequireAnomaly] + public static AbilityDef UnnaturalCorpseSkip; + + [MayRequireAnomaly] + public static AbilityDef ConsumeLeap_Devourer; + + [MayRequireOdyssey] + public static AbilityDef SludgeSpew; + + [MayRequireOdyssey] + public static AbilityDef EggSpew; + + static AbilityDefOf() + { + DefOfHelper.EnsureInitializedInCtor(typeof(AbilityDefOf)); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompAbilityEffect_GiveMentalState.txt` +**相似度:** 0.5541 + +```csharp +public class CompAbilityEffect_GiveMentalState : CompAbilityEffect +{ + public new CompProperties_AbilityGiveMentalState Props => (CompProperties_AbilityGiveMentalState)props; + + public override void Apply(LocalTargetInfo target, LocalTargetInfo dest) + { + base.Apply(target, dest); + Pawn pawn = (Props.applyToSelf ? parent.pawn : (target.Thing as Pawn)); + if (pawn != null && !pawn.InMentalState) + { + TryGiveMentalState(pawn.RaceProps.IsMechanoid ? (Props.stateDefForMechs ?? Props.stateDef) : Props.stateDef, pawn, parent.def, Props.durationMultiplier, parent.pawn, Props.forced); + RestUtility.WakeUp(pawn); + if (Props.casterEffect != null) + { + Effecter effecter = Props.casterEffect.SpawnAttached(parent.pawn, parent.pawn.MapHeld); + effecter.Trigger(parent.pawn, null); + effecter.Cleanup(); + } + if (Props.targetEffect != null) + { + Effecter effecter2 = Props.targetEffect.SpawnAttached(parent.pawn, parent.pawn.MapHeld); + effecter2.Trigger(pawn, null); + effecter2.Cleanup(); + } + } + } + + public override bool Valid(LocalTargetInfo target, bool throwMessages = false) + { + if (!base.Valid(target, throwMessages)) + { + return false; + } + Pawn pawn = target.Pawn; + if (pawn != null) + { + if (!AbilityUtility.ValidateNoMentalState(pawn, throwMessages, parent)) + { + return false; + } + if (Props.excludeNPCFactions && pawn.Faction != null && !pawn.Faction.IsPlayer) + { + if (throwMessages) + { + Messages.Message("CannotUseAbility".Translate(parent.def.label) + ": " + "TargetBelongsToNPCFaction".Translate(), pawn, MessageTypeDefOf.RejectInput, historical: false); + } + return false; + } + } + return true; + } + + public static void TryGiveMentalState(MentalStateDef def, Pawn p, AbilityDef ability, StatDef multiplierStat, Pawn caster, bool forced = false) + { + if (p.mindState.mentalStateHandler.TryStartMentalState(def, null, forced, forceWake: true, causedByMood: false, caster, transitionSilently: false, causedByDamage: false, ability.IsPsycast)) + { + float num = ability.GetStatValueAbstract(StatDefOf.Ability_Duration, caster); + if (multiplierStat != null) + { + num *= p.GetStatValue(multiplierStat); + } + if (num > 0f) + { + p.mindState.mentalStateHandler.CurState.forceRecoverAfterTicks = num.SecondsToTicks(); + } + p.mindState.mentalStateHandler.CurState.sourceFaction = caster.Faction; + } + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_ResurrectMech.txt` +**相似度:** 0.5473 + +```csharp +public class CompProperties_ResurrectMech : CompProperties_AbilityEffect +{ + public int maxCorpseAgeTicks = int.MaxValue; + + public List costs = new List(); + + public EffecterDef appliedEffecterDef; + + public EffecterDef centerEffecterDef; + + public CompProperties_ResurrectMech() + { + compClass = typeof(CompAbilityEffect_ResurrectMech); + } + + public override IEnumerable ConfigErrors(AbilityDef parentDef) + { + foreach (string item in base.ConfigErrors(parentDef)) + { + yield return item; + } + if (costs.NullOrEmpty()) + { + yield return "costs list is null"; + yield break; + } + foreach (MechChargeCosts cost in costs) + { + if (cost.weightClass == null) + { + yield return $"costs list contains null weight class with cost {cost.cost}"; + } + } + } +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/AddHumanlikeOrders-FloatMenuMakerMap.txt b/MCP/vector_cache/AddHumanlikeOrders-FloatMenuMakerMap.txt new file mode 100644 index 00000000..96addb59 --- /dev/null +++ b/MCP/vector_cache/AddHumanlikeOrders-FloatMenuMakerMap.txt @@ -0,0 +1,519 @@ +根据向量相似度分析,与 'AddHumanlikeOrders, FloatMenuMakerMap' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\FloatMenuMakerMap.txt` + +```csharp +public static class FloatMenuMakerMap +{ + private static List providers; + + public static FloatMenuOptionProvider currentProvider; + + public static Pawn makingFor; + + public static void Init() + { + providers = new List(); + foreach (Type item in typeof(FloatMenuOptionProvider).AllSubclassesNonAbstract()) + { + providers.Add((FloatMenuOptionProvider)Activator.CreateInstance(item)); + } + } + + public static List GetOptions(List selectedPawns, Vector3 clickPos, out FloatMenuContext context) + { + List list = new List(); + context = null; + if (!clickPos.InBounds(Find.CurrentMap)) + { + return list; + } + context = new FloatMenuContext(selectedPawns, clickPos, Find.CurrentMap); + if (!context.allSelectedPawns.Any()) + { + return list; + } + if (!context.ClickedCell.IsValid || !context.ClickedCell.InBounds(Find.CurrentMap)) + { + return list; + } + if (!context.IsMultiselect) + { + AcceptanceReport acceptanceReport = ShouldGenerateFloatMenuForPawn(context.FirstSelectedPawn); + if (!acceptanceReport.Accepted) + { + if (!acceptanceReport.Reason.NullOrEmpty()) + { + Messages.Message(acceptanceReport.Reason, context.FirstSelectedPawn, MessageTypeDefOf.RejectInput, historical: false); + } + return list; + } + } + else + { + context.allSelectedPawns.RemoveAll((Pawn selectedPawn) => !ShouldGenerateFloatMenuForPawn(selectedPawn)); + if (!context.allSelectedPawns.Any()) + { + return list; + } + } + if (!context.IsMultiselect) + { + makingFor = context.FirstSelectedPawn; + } + GetProviderOptions(context, list); + makingFor = null; + return list; + } + + private static void GetProviderOptions(FloatMenuContext context, List options) + { + foreach (FloatMenuOptionProvider provider in providers) + { + try + { + currentProvider = provider; + if (!context.ValidSelectedPawns.Any() || !provider.Applies(context)) + { + continue; + } + options.AddRange(provider.GetOptions(context)); + foreach (Thing clickedThing in context.ClickedThings) + { + if (!provider.TargetThingValid(clickedThing, context)) + { + continue; + } + Thing thing = clickedThing; + if (thing.TryGetComp(out CompSelectProxy comp) && comp.thingToSelect != null) + { + thing = comp.thingToSelect; + } + foreach (FloatMenuOption item in provider.GetOptionsFor(thing, context)) + { + FloatMenuOption floatMenuOption = item; + if (floatMenuOption.iconThing == null) + { + floatMenuOption.iconThing = thing; + } + item.targetsDespawned = !thing.Spawned; + options.Add(item); + } + } + foreach (Pawn clickedPawn in context.ClickedPawns) + { + if (!provider.TargetPawnValid(clickedPawn, context)) + { + continue; + } + foreach (FloatMenuOption item2 in provider.GetOptionsFor(clickedPawn, context)) + { + FloatMenuOption floatMenuOption = item2; + if (floatMenuOption.iconThing == null) + { + floatMenuOption.iconThing = clickedPawn; + } + item2.targetsDespawned = !clickedPawn.Spawned; + options.Add(item2); + } + } + } + catch (Exception arg) + { + Log.Error($"Error in FloatMenuWorker {provider.GetType().Name}: {arg}"); + } + } + currentProvider = null; + } + + public static AcceptanceReport ShouldGenerateFloatMenuForPawn(Pawn pawn) + { + if (pawn.Map != Find.CurrentMap) + { + return false; + } + if (pawn.Downed) + { + return "IsIncapped".Translate(pawn.LabelCap, pawn); + } + if (ModsConfig.BiotechActive && pawn.Deathresting) + { + return "IsDeathresting".Translate(pawn.Named("PAWN")); + } + Lord lord = pawn.GetLord(); + if (lord != null) + { + AcceptanceReport result = lord.AllowsFloatMenu(pawn); + if (!result.Accepted) + { + return result; + } + } + return true; + } + + public static FloatMenuOption GetAutoTakeOption(List options) + { + bool flag = true; + FloatMenuOption floatMenuOption = null; + foreach (FloatMenuOption option in options) + { + if (option.Disabled || !option.autoTakeable) + { + flag = false; + break; + } + if (floatMenuOption == null || option.autoTakeablePriority > floatMenuOption.autoTakeablePriority) + { + floatMenuOption = option; + } + } + if (!flag || floatMenuOption == null) + { + return null; + } + return floatMenuOption; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\FloatMenuContext.txt` +**相似度:** 0.5788 + +```csharp +public class FloatMenuContext +{ + public List allSelectedPawns; + + public Vector3 clickPosition; + + public Map map; + + private IntVec3 cachedClickedCell; + + private List cachedClickedThings; + + private List cachedClickedPawns; + + private Room cachedClickedRoom; + + private Zone cachedClickedZone; + + public IntVec3 ClickedCell => cachedClickedCell; + + public Room ClickedRoom => cachedClickedRoom; + + public Zone ClickedZone => cachedClickedZone; + + public List ClickedThings => cachedClickedThings; + + public List ClickedPawns => cachedClickedPawns; + + public bool IsMultiselect => allSelectedPawns.Count > 1; + + public Pawn FirstSelectedPawn + { + get + { + foreach (Pawn allSelectedPawn in allSelectedPawns) + { + if (FloatMenuMakerMap.currentProvider == null || FloatMenuMakerMap.currentProvider.SelectedPawnValid(allSelectedPawn, this)) + { + return allSelectedPawn; + } + } + return null; + } + } + + public IEnumerable ValidSelectedPawns + { + get + { + foreach (Pawn allSelectedPawn in allSelectedPawns) + { + if (FloatMenuMakerMap.currentProvider == null || FloatMenuMakerMap.currentProvider.SelectedPawnValid(allSelectedPawn, this)) + { + yield return allSelectedPawn; + } + } + } + } + + public FloatMenuContext(List selectedPawns, Vector3 clickPosition, Map map) + { + allSelectedPawns = selectedPawns; + this.clickPosition = clickPosition; + this.map = map; + cachedClickedCell = IntVec3.FromVector3(clickPosition); + cachedClickedRoom = cachedClickedCell.GetRoom(map); + cachedClickedZone = cachedClickedCell.GetZone(map); + cachedClickedThings = GenUI.ThingsUnderMouse(clickPosition, 0.8f, TargetingParameters.ForThing()); + cachedClickedPawns = GenUI.ThingsUnderMouse(clickPosition, 0.8f, TargetingParameters.ForPawns()).OfType().ToList(); + selectedPawns.RemoveAll((Pawn pawn) => !pawn.CanTakeOrder); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\FloatMenuMap.txt` +**相似度:** 0.5739 + +```csharp +public class FloatMenuMap : FloatMenu +{ + private Vector3 clickPos; + + private static Dictionary> cachedChoices = new Dictionary>(); + + private List lastOptionsForRevalidation; + + private int nextOptionToRevalidate; + + public const int RevalidateEveryFrame = 4; + + public FloatMenuMap(List options, string title, Vector3 clickPos) + : base(options, title) + { + this.clickPos = clickPos; + } + + public override void DoWindowContents(Rect inRect) + { + if (!Find.Selector.AnyPawnSelected) + { + Find.WindowStack.TryRemove(this); + return; + } + bool flag = options.Count >= 3; + if (Time.frameCount % 4 == 0 || lastOptionsForRevalidation == null) + { + lastOptionsForRevalidation = FloatMenuMakerMap.GetOptions(Find.Selector.SelectedPawns, clickPos, out var _); + cachedChoices.Clear(); + cachedChoices.Add(clickPos, lastOptionsForRevalidation); + if (!flag) + { + for (int i = 0; i < options.Count; i++) + { + RevalidateOption(options[i]); + } + } + } + else if (flag) + { + if (nextOptionToRevalidate >= options.Count) + { + nextOptionToRevalidate = 0; + } + int num = Mathf.CeilToInt((float)options.Count / 3f); + int num2 = nextOptionToRevalidate; + int num3 = 0; + while (num2 < options.Count && num3 < num) + { + RevalidateOption(options[num2]); + nextOptionToRevalidate++; + num2++; + num3++; + } + } + base.DoWindowContents(inRect); + void RevalidateOption(FloatMenuOption option) + { + if (!option.Disabled && !StillValid(option, lastOptionsForRevalidation)) + { + option.Disabled = true; + } + } + } + + private static bool StillValid(FloatMenuOption opt, List curOpts) + { + if (opt.revalidateClickTarget == null) + { + for (int i = 0; i < curOpts.Count; i++) + { + if (OptionsMatch(opt, curOpts[i])) + { + return true; + } + } + } + else + { + if (!opt.targetsDespawned && !opt.revalidateClickTarget.Spawned) + { + return false; + } + Vector3 key = opt.revalidateClickTarget.PositionHeld.ToVector3Shifted(); + if (!cachedChoices.TryGetValue(key, out var value)) + { + FloatMenuContext context; + List list = FloatMenuMakerMap.GetOptions(Find.Selector.SelectedPawns, key, out context); + cachedChoices.Add(key, list); + value = list; + } + for (int j = 0; j < value.Count; j++) + { + if (OptionsMatch(opt, value[j])) + { + return !value[j].Disabled; + } + } + } + return false; + } + + public override void PreOptionChosen(FloatMenuOption opt) + { + base.PreOptionChosen(opt); + if (!opt.Disabled && !StillValid(opt, FloatMenuMakerMap.GetOptions(Find.Selector.SelectedPawns, clickPos, out var _))) + { + opt.Disabled = true; + } + } + + private static bool OptionsMatch(FloatMenuOption a, FloatMenuOption b) + { + if (a.Label == b.Label) + { + return true; + } + return false; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\FloatMenuOptionProvider.txt` +**相似度:** 0.5483 + +```csharp +public abstract class FloatMenuOptionProvider +{ + protected abstract bool Drafted { get; } + + protected abstract bool Undrafted { get; } + + protected abstract bool Multiselect { get; } + + protected virtual bool RequiresManipulation => false; + + protected virtual bool MechanoidCanDo => false; + + protected virtual bool CanSelfTarget => false; + + public virtual bool CanTargetDespawned => false; + + protected virtual bool IgnoreFogged => true; + + public virtual bool SelectedPawnValid(Pawn pawn, FloatMenuContext context) + { + if (pawn.IsMutant && pawn.mutant.Def.whitelistedFloatMenuProviders != null && !pawn.mutant.Def.whitelistedFloatMenuProviders.Contains(FloatMenuMakerMap.currentProvider.GetType())) + { + return false; + } + if (!Drafted && pawn.Drafted) + { + return false; + } + if (!Undrafted && !pawn.Drafted) + { + return false; + } + if (!MechanoidCanDo && pawn.RaceProps.IsMechanoid) + { + return false; + } + if (RequiresManipulation && !pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) + { + return false; + } + return true; + } + + public virtual bool TargetThingValid(Thing thing, FloatMenuContext context) + { + if (!CanTargetDespawned && !thing.Spawned) + { + return false; + } + if (thing is Pawn pawn && !TargetPawnValid(pawn, context)) + { + return false; + } + return true; + } + + public virtual bool TargetPawnValid(Pawn pawn, FloatMenuContext context) + { + if (!CanSelfTarget && pawn == context.FirstSelectedPawn) + { + return false; + } + return true; + } + + public virtual bool Applies(FloatMenuContext context) + { + if (!Multiselect && context.IsMultiselect) + { + return false; + } + if (IgnoreFogged && context.ClickedCell.Fogged(context.map)) + { + return false; + } + if (!AppliesInt(context)) + { + return false; + } + return true; + } + + protected virtual bool AppliesInt(FloatMenuContext context) + { + return true; + } + + public virtual IEnumerable GetOptions(FloatMenuContext context) + { + FloatMenuOption singleOption = GetSingleOption(context); + if (singleOption != null) + { + yield return singleOption; + } + } + + public virtual IEnumerable GetOptionsFor(Thing clickedThing, FloatMenuContext context) + { + FloatMenuOption singleOptionFor = GetSingleOptionFor(clickedThing, context); + if (singleOptionFor != null) + { + yield return singleOptionFor; + } + } + + public virtual IEnumerable GetOptionsFor(Pawn clickedPawn, FloatMenuContext context) + { + FloatMenuOption singleOptionFor = GetSingleOptionFor(clickedPawn, context); + if (singleOptionFor != null) + { + yield return singleOptionFor; + } + } + + protected virtual FloatMenuOption GetSingleOption(FloatMenuContext context) + { + return null; + } + + protected virtual FloatMenuOption GetSingleOptionFor(Thing clickedThing, FloatMenuContext context) + { + return null; + } + + protected virtual FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context) + { + return null; + } +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/BiosculpterPod-ThingDef.txt b/MCP/vector_cache/BiosculpterPod-ThingDef.txt new file mode 100644 index 00000000..a55a7d7b --- /dev/null +++ b/MCP/vector_cache/BiosculpterPod-ThingDef.txt @@ -0,0 +1,1502 @@ +根据向量相似度分析,与 'BiosculpterPod, ThingDef' 最相关的代码定义如下: + +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_BiosculpterPod_BaseCycle.txt` +**相似度:** 0.7659 + +```csharp +public abstract class CompProperties_BiosculpterPod_BaseCycle : CompProperties +{ + [NoTranslate] + public string key; + + [MustTranslate] + public string label; + + [MustTranslate] + public string description; + + [NoTranslate] + public string iconPath; + + public float durationDays; + + public Color operatingColor = new Color(0.5f, 0.7f, 0.5f); + + public ThoughtDef gainThoughtOnCompletion; + + public List requiredResearch; + + public List extraRequiredIngredients; + + private Texture2D icon; + + public Texture2D Icon + { + get + { + if (icon == null) + { + icon = ContentFinder.Get(iconPath); + } + return icon; + } + } + + public string LabelCap => label.CapitalizeFirst(); +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompBiosculpterPod.txt` +**相似度:** 0.7294 + +```csharp +public class CompBiosculpterPod : ThingComp, ISuspendableThingHolder, IThingHolder, IThingHolderWithDrawnPawn, IStoreSettingsParent, INotifyHauledTo, ISearchableContents +{ + private const int NoPowerEjectCumulativeTicks = 60000; + + private const int BiotunedDuration = 4800000; + + private const float NutritionRequired = 5f; + + private const float CacheForSecs = 2f; + + private static readonly Texture2D InterruptCycleIcon = ContentFinder.Get("UI/Designators/Cancel"); + + private static readonly Material BackgroundMat = SolidColorMaterials.NewSolidColorMaterial(new Color(0.082f, 0.078f, 0.063f), ShaderDatabase.SolidColorBehind); + + private const float BackgroundRect_YOff = 0.07317074f; + + private const float Pawn_YOff = 0.03658537f; + + private string currentCycleKey; + + private float currentCycleTicksRemaining; + + private int currentCyclePowerCutTicks; + + private ThingOwner innerContainer; + + private Pawn biotunedTo; + + private int biotunedCountdownTicks; + + private StorageSettings allowedNutritionSettings; + + private float liquifiedNutrition; + + public bool autoLoadNutrition = true; + + public bool devFillPodLatch; + + private bool autoAgeReversal; + + private int tickEntered = -99999; + + public Job queuedEnterJob; + + public Pawn queuedPawn; + + private List chosenExtraItems = new List(); + + private List cycleEligiblePawnOptions = new List(); + + private Pawn pawnEnteringBiosculpter; + + private Dictionary> cachedExtraIngredients = new Dictionary>(); + + private Dictionary cachedAnyPawnEligible = new Dictionary(); + + private static Dictionary> cachedBiotunedPods = new Dictionary>(); + + private Pawn cacheReachIngredientsPawn; + + private CompBiosculpterPod_Cycle cacheReachIngredientsCycle; + + private float cacheReachIngredientsTime = float.MinValue; + + private bool cacheReachIngredientsResult; + + private Effecter progressBarEffecter; + + private Effecter operatingEffecter; + + private Effecter readyEffecter; + + private Texture2D cachedAutoAgeReverseIcon; + + private List cachedAvailableCycles; + + private Dictionary cycleLookup; + + private static string cachedAgeReversalCycleKey = null; + + private List tmpIngredientsStrings = new List(); + + private static readonly List tmpItems = new List(); + + private CompPowerTrader powerTraderComp; + + private CompPower powerComp; + + private static List cachedPodDefs; + + public CompProperties_BiosculpterPod Props => props as CompProperties_BiosculpterPod; + + public ThingOwner SearchableContents => innerContainer; + + public bool IsContentsSuspended => true; + + public float RequiredNutritionRemaining => Mathf.Max(5f - liquifiedNutrition, 0f); + + public bool NutritionLoaded => RequiredNutritionRemaining <= 0f; + + public bool AutoAgeReversal => autoAgeReversal; + + private Texture2D AutoAgeReversalIcon + { + get + { + if (cachedAutoAgeReverseIcon == null) + { + cachedAutoAgeReverseIcon = ContentFinder.Get("UI/Gizmos/BiosculpterAutoAgeReversal"); + } + return cachedAutoAgeReverseIcon; + } + } + + public BiosculpterPodState State + { + get + { + if (Occupant != null) + { + return BiosculpterPodState.Occupied; + } + if (NutritionLoaded) + { + return BiosculpterPodState.SelectingCycle; + } + return BiosculpterPodState.LoadingNutrition; + } + } + + public Pawn Occupant + { + get + { + if (pawnEnteringBiosculpter != null) + { + return pawnEnteringBiosculpter; + } + if (currentCycleKey == null) + { + return null; + } + if (innerContainer.Count != 1) + { + return null; + } + return innerContainer[0] as Pawn; + } + } + + public CompBiosculpterPod_Cycle CurrentCycle + { + get + { + if (currentCycleKey == null) + { + return null; + } + foreach (CompBiosculpterPod_Cycle availableCycle in AvailableCycles) + { + if (availableCycle.Props.key == currentCycleKey) + { + return availableCycle; + } + } + return null; + } + } + + public List AvailableCycles + { + get + { + if (cachedAvailableCycles == null) + { + SetupCycleCaches(); + } + return cachedAvailableCycles; + } + } + + public string AgeReversalCycleKey + { + get + { + if (cachedAgeReversalCycleKey == null) + { + SetupCycleCaches(); + } + return cachedAgeReversalCycleKey; + } + } + + private float CycleSpeedFactorNoPawn => CleanlinessSpeedFactor * BiotunedSpeedFactor; + + public float CycleSpeedFactor + { + get + { + if (Occupant == null) + { + return Mathf.Max(0.1f, CycleSpeedFactorNoPawn); + } + return GetCycleSpeedFactorForPawn(Occupant); + } + } + + private float CleanlinessSpeedFactor => parent.GetStatValue(StatDefOf.BiosculpterPodSpeedFactor); + + private float BiotunedSpeedFactor + { + get + { + if (biotunedTo == null) + { + return 1f; + } + return Props.biotunedCycleSpeedFactor; + } + } + + public bool PowerOn => parent.TryGetComp().PowerOn; + + public float HeldPawnDrawPos_Y => parent.DrawPos.y - 0.03658537f; + + public float HeldPawnBodyAngle => parent.Rotation.Opposite.AsAngle; + + public PawnPosture HeldPawnPosture => PawnPosture.LayingOnGroundFaceUp; + + public bool StorageTabVisible => true; + + public CompBiosculpterPod() + { + innerContainer = new ThingOwner(this); + } + + public override void Initialize(CompProperties props) + { + base.Initialize(props); + allowedNutritionSettings = new StorageSettings(this); + if (parent.def.building.defaultStorageSettings != null) + { + allowedNutritionSettings.CopyFrom(parent.def.building.defaultStorageSettings); + } + } + + public override void PostSpawnSetup(bool respawningAfterLoad) + { + if (ModLister.CheckIdeology("Biosculpter pod comp")) + { + base.PostSpawnSetup(respawningAfterLoad); + } + } + + public override void PostExposeData() + { + base.PostExposeData(); + Scribe_Deep.Look(ref innerContainer, "innerContainer", this); + Scribe_Values.Look(ref currentCycleKey, "currentCycleKey"); + Scribe_Values.Look(ref currentCycleTicksRemaining, "currentCycleTicksRemaining", 0f); + Scribe_Values.Look(ref currentCyclePowerCutTicks, "currentCyclePowerCutTicks", 0); + Scribe_References.Look(ref biotunedTo, "biotunedTo"); + Scribe_Values.Look(ref biotunedCountdownTicks, "biotunedCountdownTicks", 0); + Scribe_Deep.Look(ref allowedNutritionSettings, "allowedNutritionSettings"); + Scribe_Values.Look(ref liquifiedNutrition, "liquifiedNutrition", 0f); + Scribe_Values.Look(ref autoLoadNutrition, "autoLoadNutrition", defaultValue: false); + Scribe_Values.Look(ref devFillPodLatch, "devFillPodLatch", defaultValue: false); + Scribe_Values.Look(ref autoAgeReversal, "autoAgeReversal", defaultValue: false); + Scribe_Values.Look(ref tickEntered, "tickEntered", 0); + Scribe_References.Look(ref queuedEnterJob, "queuedEnterJob"); + Scribe_References.Look(ref queuedPawn, "queuedPawn"); + if (allowedNutritionSettings == null) + { + allowedNutritionSettings = new StorageSettings(this); + if (parent.def.building.defaultStorageSettings != null) + { + allowedNutritionSettings.CopyFrom(parent.def.building.defaultStorageSettings); + } + } + if (Scribe.mode == LoadSaveMode.PostLoadInit) + { + if (currentCycleKey == "healing") + { + currentCycleKey = "medic"; + } + if (biotunedTo != null) + { + SetBiotuned(biotunedTo); + } + LiquifyNutrition(); + } + } + + public CompBiosculpterPod_Cycle GetCycle(string key) + { + if (cycleLookup == null) + { + SetupCycleCaches(); + } + return cycleLookup[key]; + } + + public float GetCycleSpeedFactorForPawn(Pawn p) + { + return Mathf.Max(0.1f, CycleSpeedFactorNoPawn * p.GetStatValue(StatDefOf.BiosculpterOccupantSpeed)); + } + + private void SetupCycleCaches() + { + cachedAvailableCycles = new List(); + cachedAvailableCycles.AddRange(parent.AllComps.OfType()); + cycleLookup = new Dictionary(); + foreach (CompBiosculpterPod_Cycle cachedAvailableCycle in cachedAvailableCycles) + { + if (cachedAvailableCycle is CompBiosculpterPod_AgeReversalCycle compBiosculpterPod_AgeReversalCycle) + { + cachedAgeReversalCycleKey = compBiosculpterPod_AgeReversalCycle.Props.key; + } + cycleLookup[cachedAvailableCycle.Props.key] = cachedAvailableCycle; + } + } + + public void SetBiotuned(Pawn newBiotunedTo) + { + if (newBiotunedTo != biotunedTo) + { + autoAgeReversal = false; + } + if (biotunedTo != null && cachedBiotunedPods.ContainsKey(biotunedTo)) + { + cachedBiotunedPods[biotunedTo].Remove(this); + } + if (newBiotunedTo != null && !cachedBiotunedPods.ContainsKey(newBiotunedTo)) + { + cachedBiotunedPods[newBiotunedTo] = new List(); + } + if (newBiotunedTo != null && !cachedBiotunedPods[newBiotunedTo].Contains(this)) + { + cachedBiotunedPods[newBiotunedTo].Add(this); + } + if (newBiotunedTo != null && newBiotunedTo != biotunedTo) + { + biotunedCountdownTicks = 4800000; + } + biotunedTo = newBiotunedTo; + } + + public override void PostDestroy(DestroyMode mode, Map previousMap) + { + SetBiotuned(null); + if (mode == DestroyMode.Deconstruct || mode == DestroyMode.KillFinalize) + { + EjectContents(interrupted: true, playSounds: false, previousMap); + } + innerContainer.ClearAndDestroyContents(); + base.PostDestroy(mode, previousMap); + } + + public override void PostDeSpawn(Map map, DestroyMode mode = DestroyMode.Vanish) + { + if (mode != DestroyMode.WillReplace) + { + EjectContents(interrupted: true, playSounds: false, map); + currentCycleKey = null; + } + progressBarEffecter?.Cleanup(); + progressBarEffecter = null; + operatingEffecter?.Cleanup(); + operatingEffecter = null; + readyEffecter?.Cleanup(); + readyEffecter = null; + } + + public override void DrawGUIOverlay() + { + base.DrawGUIOverlay(); + if (!Find.ScreenshotModeHandler.Active && (biotunedTo != null || Occupant != null)) + { + GenMapUI.DrawThingLabel(parent, biotunedTo?.LabelShort ?? Occupant.LabelShort, GenMapUI.DefaultThingLabelColor); + } + } + + public override string CompInspectStringExtra() + { + StringBuilder stringBuilder = new StringBuilder(); + BiosculpterPodState state = State; + if (parent.Spawned) + { + CompBiosculpterPod_Cycle currentCycle = CurrentCycle; + if (currentCycle != null) + { + stringBuilder.AppendLineIfNotEmpty().Append("BiosculpterPodCycleLabel".Translate()).Append(": ") + .Append(currentCycle.Props.LabelCap); + if (biotunedTo == null) + { + stringBuilder.Append(" " + "BiosculpterPodCycleWillBiotune".Translate()); + } + } + else if (state == BiosculpterPodState.SelectingCycle) + { + if (PowerOn) + { + if (queuedEnterJob != null && !queuedEnterJob.biosculpterCycleKey.NullOrEmpty()) + { + stringBuilder.Append("BiosculpterPodCycleStandby".Translate(GetCycle(queuedEnterJob.biosculpterCycleKey).Props.label.Named("CYCLE"), queuedPawn.Named("PAWN"))); + } + else + { + stringBuilder.Append("BiosculpterPodCycleSelection".Translate().CapitalizeFirst()); + } + } + else + { + stringBuilder.Append("BiosculpterPodCycleSelectionNoPower".Translate().CapitalizeFirst()); + } + } + if (state == BiosculpterPodState.LoadingNutrition) + { + stringBuilder.Append("BiosculpterPodCycleLabelLoading".Translate().CapitalizeFirst()); + stringBuilder.AppendLineIfNotEmpty().Append("Nutrition".Translate()).Append(": ") + .Append(liquifiedNutrition.ToStringByStyle(ToStringStyle.FloatMaxOne)) + .Append(" / ") + .Append(5f); + } + if (state == BiosculpterPodState.Occupied) + { + float num = currentCycleTicksRemaining / CycleSpeedFactor; + stringBuilder.AppendLineIfNotEmpty().Append("Contains".Translate()).Append(": ") + .Append(Occupant.NameShortColored.Resolve()); + if (!PowerOn) + { + stringBuilder.AppendLine().Append("BiosculpterCycleNoPowerInterrupt".Translate((60000 - currentCyclePowerCutTicks).ToStringTicksToPeriod().Named("TIME")).Colorize(ColorLibrary.RedReadable)); + } + stringBuilder.AppendLine().Append("BiosculpterCycleTimeRemaining".Translate()).Append(": ") + .Append(((int)num).ToStringTicksToPeriod().Colorize(ColoredText.DateTimeColor)); + Ideo ideo = Occupant.Ideo; + if (ideo != null && ideo.HasPrecept(PreceptDefOf.Biosculpting_Accelerated)) + { + stringBuilder.Append(" (" + "BiosculpterCycleAccelerated".Translate() + ")"); + } + if (biotunedTo != null) + { + stringBuilder.AppendLine().Append("BiosculpterBiotunedSpeedFactor".Translate()).Append(": ") + .Append(BiotunedSpeedFactor.ToStringPercent()); + } + stringBuilder.AppendLine().Append("BiosculpterCleanlinessSpeedFactor".Translate()).Append(": ") + .Append(CleanlinessSpeedFactor.ToStringPercent()); + } + } + if (biotunedTo != null && state != BiosculpterPodState.Occupied) + { + stringBuilder.AppendLineIfNotEmpty().Append("BiosculpterBiotunedTo".Translate()).Append(": ") + .Append(biotunedTo.LabelShort) + .Append(" (") + .Append(biotunedCountdownTicks.ToStringTicksToPeriod()) + .Append(")"); + } + if (stringBuilder.Length <= 0) + { + return null; + } + return stringBuilder.ToString(); + } + + public override IEnumerable CompGetGizmosExtra() + { + BiosculpterPodState state = State; + string cycleIndependentCannotUseReason = CannotUseNowReason(); + foreach (CompBiosculpterPod_Cycle cycle in AvailableCycles) + { + string text = cycleIndependentCannotUseReason ?? CannotUseNowCycleReason(cycle); + Command_Action command_Action = new Command_Action(); + command_Action.defaultLabel = "BiosculpterPodCycleCommand".Translate(cycle.Props.label) + ((biotunedTo != null) ? (" (" + biotunedTo.LabelShort + ")") : ""); + command_Action.defaultDesc = CycleDescription(cycle); + command_Action.icon = cycle.Props.Icon; + command_Action.action = delegate + { + SelectPawnsForCycleOptions(cycle, out var options2); + if (biotunedTo != null && options2.Count > 0) + { + options2[0].action(); + if (!(cycle is CompBiosculpterPod_HealingCycle)) + { + Messages.Message("BiosculpterEnteringMessage".Translate(biotunedTo.Named("PAWN"), cycle.Props.label.Named("CYCLE")).CapitalizeFirst(), parent, MessageTypeDefOf.SilentInput, historical: false); + } + } + else + { + Find.WindowStack.Add(new FloatMenu(options2)); + } + }; + command_Action.activateSound = SoundDefOf.Tick_Tiny; + command_Action.Disabled = text != null; + List options; + if (text != null) + { + command_Action.Disable(text); + } + else if (!SelectPawnsForCycleOptions(cycle, out options, shortCircuit: true)) + { + command_Action.Disable((biotunedTo != null) ? "BiosculpterNoEligiblePawnsBiotuned".Translate(biotunedTo.Named("PAWN")) : "BiosculpterNoEligiblePawns".Translate()); + } + yield return command_Action; + } + if (state == BiosculpterPodState.Occupied) + { + Command_Action command_Action2 = new Command_Action(); + command_Action2.defaultLabel = "BiosculpterInteruptCycle".Translate(); + command_Action2.defaultDesc = "BiosculpterInteruptCycleDesc".Translate(); + command_Action2.icon = InterruptCycleIcon; + command_Action2.action = delegate + { + EjectContents(interrupted: true, playSounds: true); + }; + command_Action2.activateSound = SoundDefOf.Designate_Cancel; + yield return command_Action2; + } + Command_Toggle command_Toggle = new Command_Toggle(); + command_Toggle.defaultLabel = "BiosculpterAutoLoadNutritionLabel".Translate(); + command_Toggle.defaultDesc = "BiosculpterAutoLoadNutritionDescription".Translate(); + command_Toggle.icon = (autoLoadNutrition ? TexCommand.ForbidOff : TexCommand.ForbidOn); + command_Toggle.isActive = () => autoLoadNutrition; + command_Toggle.toggleAction = delegate + { + autoLoadNutrition = !autoLoadNutrition; + }; + yield return command_Toggle; + if ((biotunedTo?.Ideo?.HasPrecept(PreceptDefOf.AgeReversal_Demanded)).GetValueOrDefault()) + { + Command_Toggle command_Toggle2 = new Command_Toggle(); + command_Toggle2.defaultLabel = "BiosculpterAutoAgeReversalLabel".Translate(biotunedTo.Named("PAWN")); + TaggedString taggedString = ((biotunedTo.ageTracker.AgeReversalDemandedDeadlineTicks > 0) ? "BiosculpterAutoAgeReversalDescriptionFuture".Translate(biotunedTo.Named("PAWN"), ((int)biotunedTo.ageTracker.AgeReversalDemandedDeadlineTicks).ToStringTicksToPeriodVague().Named("TIME")) : "BiosculpterAutoAgeReversalDescriptionNow".Translate(biotunedTo.Named("PAWN"))); + command_Toggle2.defaultDesc = "BiosculpterAutoAgeReversalDescription".Translate(biotunedTo.Named("PAWN"), taggedString.Named("NEXTTREATMENT")); + command_Toggle2.icon = AutoAgeReversalIcon; + command_Toggle2.isActive = () => AutoAgeReversal; + command_Toggle2.toggleAction = delegate + { + autoAgeReversal = !autoAgeReversal; + }; + if (!CanAgeReverse(biotunedTo)) + { + command_Toggle2.Disable("UnderMinBiosculpterAgeReversalAge".Translate(biotunedTo.ageTracker.AdultMinAge.Named("ADULTAGE")).CapitalizeFirst()); + autoAgeReversal = false; + } + yield return command_Toggle2; + } + foreach (Gizmo item in StorageSettingsClipboard.CopyPasteGizmosFor(allowedNutritionSettings)) + { + yield return item; + } + Gizmo gizmo = Building.SelectContainedItemGizmo(parent, Occupant); + if (gizmo != null) + { + yield return gizmo; + } + if (DebugSettings.ShowDevGizmos) + { + yield return new Command_Action + { + defaultLabel = "DEV: complete cycle", + action = delegate + { + currentCycleTicksRemaining = 10f; + }, + Disabled = (State != BiosculpterPodState.Occupied) + }; + yield return new Command_Action + { + defaultLabel = "DEV: advance cycle +1 day", + action = delegate + { + currentCycleTicksRemaining -= 60000f; + }, + Disabled = (State != BiosculpterPodState.Occupied) + }; + yield return new Command_Action + { + defaultLabel = "DEV: complete biotune timer", + action = delegate + { + biotunedCountdownTicks = 10; + }, + Disabled = (biotunedCountdownTicks <= 0) + }; + yield return new Command_Action + { + defaultLabel = "DEV: fill nutrition and cycle ingredients", + action = delegate + { + liquifiedNutrition = 5f; + devFillPodLatch = true; + }, + Disabled = (State == BiosculpterPodState.Occupied || (devFillPodLatch && liquifiedNutrition == 5f)) + }; + } + } + + private string IngredientsDescription(CompBiosculpterPod_Cycle cycle) + { + tmpIngredientsStrings.Clear(); + if (!cycle.Props.extraRequiredIngredients.NullOrEmpty() && !devFillPodLatch) + { + for (int i = 0; i < cycle.Props.extraRequiredIngredients.Count; i++) + { + tmpIngredientsStrings.Add(cycle.Props.extraRequiredIngredients[i].Summary); + } + } + return tmpIngredientsStrings.ToCommaList(useAnd: true); + } + + private string CycleDescription(CompBiosculpterPod_Cycle cycle) + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.Append(cycle.Description(biotunedTo)); + float num = cycle.Props.durationDays / CycleSpeedFactor; + float num2 = num / PreceptDefOf.Biosculpting_Accelerated.biosculpterPodCycleSpeedFactor; + stringBuilder.AppendLine("\n\n" + "BiosculpterPodCycleDuration".Translate() + ": " + ((int)(num * 60000f)).ToStringTicksToDays()); + if (!Find.IdeoManager.classicMode) + { + stringBuilder.Append("BiosculpterPodCycleDurationTranshumanists".Translate() + ": " + ((int)(num2 * 60000f)).ToStringTicksToDays()); + } + return stringBuilder.ToString(); + } + + public bool PawnCanUseNow(Pawn pawn, CompBiosculpterPod_Cycle cycle) + { + return (CannotUseNowReason() ?? CannotUseNowPawnReason(pawn) ?? CannotUseNowCycleReason(cycle) ?? CannotUseNowPawnCycleReason(pawn, cycle)) == null; + } + + public override IEnumerable CompFloatMenuOptions(Pawn selPawn) + { + if (selPawn.IsQuestLodger()) + { + yield return new FloatMenuOption("CannotEnter".Translate() + ": " + "CryptosleepCasketGuestsNotAllowed".Translate().CapitalizeFirst(), null); + yield break; + } + string cycleIndependentfailureReason = CannotUseNowReason() ?? CannotUseNowPawnReason(selPawn); + foreach (CompBiosculpterPod_Cycle cycle in AvailableCycles) + { + string text = cycleIndependentfailureReason ?? CannotUseNowCycleReason(cycle) ?? CannotUseNowPawnCycleReason(selPawn, cycle); + if (text != null) + { + yield return new FloatMenuOption(CannotStartText(cycle, text), null); + continue; + } + string label = "EnterBiosculpterPod".Translate(cycle.Props.label, ((int)(cycle.Props.durationDays / GetCycleSpeedFactorForPawn(selPawn) * 60000f)).ToStringTicksToDays()); + yield return FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(label, delegate + { + PrepareCycleJob(selPawn, selPawn, cycle, EnterBiosculpterJob()); + }), selPawn, parent); + } + } + + public static bool CanAgeReverse(Pawn biosculptee) + { + return biosculptee.ageTracker.Adult; + } + + public static List BiotunedPods(Pawn pawn) + { + return cachedBiotunedPods.TryGetValue(pawn); + } + + public static bool HasBiotunedAutoAgeReversePod(Pawn pawn) + { + List list = cachedBiotunedPods.TryGetValue(pawn); + if (list == null) + { + return false; + } + foreach (CompBiosculpterPod item in list) + { + if (item.AutoAgeReversal) + { + return true; + } + } + return false; + } + + public static string CannotStartText(CompBiosculpterPod_Cycle cycle, string translatedReason) + { + return "BiosculpterCannotStartCycle".Translate(cycle.Props.label) + ": " + translatedReason.CapitalizeFirst(); + } + + public string CannotUseNowCycleReason(CompBiosculpterPod_Cycle cycle) + { + List list = cycle.MissingResearchLabels(); + if (list.Any()) + { + return "MissingRequiredResearch".Translate() + " " + list.ToCommaList(); + } + return null; + } + + public string CannotUseNowPawnCycleReason(Pawn p, CompBiosculpterPod_Cycle cycle, bool checkIngredients = true) + { + return CannotUseNowPawnCycleReason(p, p, cycle, checkIngredients); + } + + private bool CanReachOrHasIngredients(Pawn hauler, Pawn biosculptee, CompBiosculpterPod_Cycle cycle, bool useCache = false) + { + if (!PawnCarryingExtraCycleIngredients(biosculptee, cycle) && (biosculptee == hauler || !PawnCarryingExtraCycleIngredients(hauler, cycle))) + { + return CanReachRequiredIngredients(hauler, cycle, useCache); + } + return true; + } + + public string CannotUseNowPawnCycleReason(Pawn hauler, Pawn biosculptee, CompBiosculpterPod_Cycle cycle, bool checkIngredients = true) + { + if (AgeReversalCycleKey != null && cycle.Props.key == AgeReversalCycleKey && !CanAgeReverse(biosculptee)) + { + return "UnderMinBiosculpterAgeReversalAge".Translate(biosculptee.ageTracker.AdultMinAge.Named("ADULTAGE")).CapitalizeFirst(); + } + if (checkIngredients && !CanReachOrHasIngredients(hauler, biosculptee, cycle, useCache: true)) + { + return "BiosculpterMissingIngredients".Translate(IngredientsDescription(cycle).Named("INGREDIENTS")).CapitalizeFirst(); + } + return null; + } + + public string CannotUseNowPawnReason(Pawn p) + { + if (biotunedTo != null && biotunedTo != p) + { + return "BiosculpterBiotunedToAnother".Translate().CapitalizeFirst(); + } + if (!p.CanReach(parent, PathEndMode.InteractionCell, Danger.Deadly)) + { + return "NoPath".Translate().CapitalizeFirst(); + } + return null; + } + + public string CannotUseNowReason() + { + if (!PowerOn) + { + return "NoPower".Translate().CapitalizeFirst(); + } + if (State == BiosculpterPodState.LoadingNutrition) + { + return "BiosculpterNutritionNotLoaded".Translate().CapitalizeFirst(); + } + if (State == BiosculpterPodState.Occupied) + { + return "BiosculpterOccupied".Translate().CapitalizeFirst(); + } + return null; + } + + private List RequiredIngredients(CompBiosculpterPod_Cycle cycle) + { + List extraRequiredIngredients = cycle.Props.extraRequiredIngredients; + if (extraRequiredIngredients == null || devFillPodLatch) + { + return null; + } + if (!cachedExtraIngredients.ContainsKey(cycle)) + { + cachedExtraIngredients[cycle] = extraRequiredIngredients.Select((ThingDefCountClass tc) => tc.ToIngredientCount()).ToList(); + } + return cachedExtraIngredients[cycle]; + } + + private bool CanReachRequiredIngredients(Pawn pawn, CompBiosculpterPod_Cycle cycle, bool useCache = false) + { + chosenExtraItems.Clear(); + if (cycle.Props.extraRequiredIngredients == null || devFillPodLatch) + { + return true; + } + float realtimeSinceStartup = Time.realtimeSinceStartup; + if (useCache && cacheReachIngredientsPawn == pawn && cacheReachIngredientsCycle == cycle && realtimeSinceStartup < cacheReachIngredientsTime + 2f) + { + return cacheReachIngredientsResult; + } + cacheReachIngredientsPawn = pawn; + cacheReachIngredientsCycle = cycle; + cacheReachIngredientsTime = realtimeSinceStartup; + cacheReachIngredientsResult = WorkGiver_DoBill.TryFindBestFixedIngredients(RequiredIngredients(cycle), pawn, parent, chosenExtraItems); + return cacheReachIngredientsResult; + } + + private bool SelectPawnCycleOption(Pawn pawn, CompBiosculpterPod_Cycle cycle, out FloatMenuOption option) + { + string text = CannotUseNowPawnReason(pawn) ?? CannotUseNowPawnCycleReason(pawn, cycle, checkIngredients: false); + string label = pawn.Label + ((text == null) ? "" : (": " + text)); + Action action = null; + if (text == null) + { + action = delegate + { + PrepareCycleJob(pawn, pawn, cycle, EnterBiosculpterJob()); + }; + } + option = new FloatMenuOption(label, action); + return text == null; + } + + private bool SelectPawnsForCycleOptions(CompBiosculpterPod_Cycle cycle, out List options, bool shortCircuit = false) + { + cycleEligiblePawnOptions.Clear(); + options = cycleEligiblePawnOptions; + if (!cachedAnyPawnEligible.ContainsKey(cycle)) + { + cachedAnyPawnEligible[cycle] = new CacheAnyPawnEligibleCycle + { + gameTime = float.MinValue + }; + } + int ticksGame = Find.TickManager.TicksGame; + if (shortCircuit && (float)ticksGame < cachedAnyPawnEligible[cycle].gameTime + 2f) + { + return cachedAnyPawnEligible[cycle].anyEligible; + } + cachedAnyPawnEligible[cycle].gameTime = ticksGame; + if (biotunedTo != null) + { + if (biotunedTo.Dead || !biotunedTo.Spawned || biotunedTo.Map != parent.Map) + { + cachedAnyPawnEligible[cycle].anyEligible = false; + return cachedAnyPawnEligible[cycle].anyEligible; + } + if (SelectPawnCycleOption(biotunedTo, cycle, out var option) && shortCircuit) + { + cachedAnyPawnEligible[cycle].anyEligible = true; + return cachedAnyPawnEligible[cycle].anyEligible; + } + cycleEligiblePawnOptions.Add(option); + } + else + { + foreach (Pawn item in parent.Map.mapPawns.FreeColonistsSpawned) + { + if (SelectPawnCycleOption(item, cycle, out var option2) && shortCircuit) + { + cachedAnyPawnEligible[cycle].anyEligible = true; + return cachedAnyPawnEligible[cycle].anyEligible; + } + cycleEligiblePawnOptions.Add(option2); + } + } + cachedAnyPawnEligible[cycle].anyEligible = cycleEligiblePawnOptions.Count > 0; + return cachedAnyPawnEligible[cycle].anyEligible; + } + + public Job EnterBiosculpterJob() + { + return JobMaker.MakeJob(JobDefOf.EnterBiosculpterPod, parent); + } + + public Job MakeCarryToBiosculpterJob(Pawn willBeCarried) + { + return JobMaker.MakeJob(JobDefOf.CarryToBiosculpterPod, willBeCarried, LocalTargetInfo.Invalid, parent); + } + + public void ConfigureJobForCycle(Job job, CompBiosculpterPod_Cycle cycle, List extraIngredients) + { + if (!extraIngredients.NullOrEmpty()) + { + job.targetQueueB = new List(extraIngredients.Count); + job.countQueue = new List(extraIngredients.Count); + foreach (ThingCount extraIngredient in extraIngredients) + { + job.targetQueueB.Add(extraIngredient.Thing); + job.countQueue.Add(extraIngredient.Count); + } + } + job.haulMode = HaulMode.ToCellNonStorage; + job.biosculpterCycleKey = cycle.Props.key; + } + + public void PrepareCycleJob(Pawn hauler, Pawn biosculptee, CompBiosculpterPod_Cycle cycle, Job job) + { + OrderToPod(cycle, biosculptee, delegate + { + chosenExtraItems.Clear(); + if (!CanReachOrHasIngredients(hauler, biosculptee, cycle)) + { + Messages.Message("BiosculpterMissingIngredients".Translate(IngredientsDescription(cycle).Named("INGREDIENTS")).CapitalizeFirst(), parent, MessageTypeDefOf.NegativeEvent, historical: false); + } + else + { + ConfigureJobForCycle(job, cycle, chosenExtraItems); + if (cycle.Props.extraRequiredIngredients != null && !devFillPodLatch) + { + if (job.def == JobDefOf.CarryToBiosculpterPod) + { + Messages.Message("BiosculpterCarryStartedMessage".Translate(hauler.Named("PAWN"), IngredientsDescription(cycle).Named("INGREDIENTS"), biosculptee.Named("DOWNED"), cycle.Props.label.Named("CYCLE")), parent, MessageTypeDefOf.SilentInput, historical: false); + } + else + { + Messages.Message("BiosculpterLoadingStartedMessage".Translate(hauler.Named("PAWN"), IngredientsDescription(cycle).Named("INGREDIENTS"), cycle.Props.label.Named("CYCLE")), parent, MessageTypeDefOf.SilentInput, historical: false); + } + } + if (hauler.jobs.TryTakeOrderedJob(job, JobTag.Misc)) + { + SetQueuedInformation(job, biosculptee); + } + } + }); + } + + public void ClearQueuedInformation() + { + SetQueuedInformation(null, null); + } + + public void SetQueuedInformation(Job job, Pawn biosculptee) + { + queuedEnterJob = job; + queuedPawn = biosculptee; + } + + public bool CanAcceptNutrition(Thing thing) + { + return allowedNutritionSettings.AllowedToAccept(thing); + } + + public bool CanAcceptOnceCycleChosen(Pawn pawn) + { + if (State != BiosculpterPodState.SelectingCycle || !PowerOn) + { + return false; + } + if (biotunedTo != null && biotunedTo != pawn) + { + return false; + } + return true; + } + + public bool PawnCarryingExtraCycleIngredients(Pawn pawn, string cycleKey, bool remove = false) + { + return PawnCarryingExtraCycleIngredients(pawn, GetCycle(cycleKey), remove); + } + + public bool PawnCarryingExtraCycleIngredients(Pawn pawn, CompBiosculpterPod_Cycle cycle, bool remove = false) + { + if (cycle.Props.extraRequiredIngredients.NullOrEmpty() || devFillPodLatch) + { + return true; + } + foreach (ThingDefCountClass extraRequiredIngredient in cycle.Props.extraRequiredIngredients) + { + if (pawn.inventory.Count(extraRequiredIngredient.thingDef) < extraRequiredIngredient.count) + { + return false; + } + } + if (remove) + { + foreach (ThingDefCountClass extraRequiredIngredient2 in cycle.Props.extraRequiredIngredients) + { + pawn.inventory.RemoveCount(extraRequiredIngredient2.thingDef, extraRequiredIngredient2.count); + } + } + return true; + } + + public bool TryAcceptPawn(Pawn pawn, string cycleKey) + { + return TryAcceptPawn(pawn, GetCycle(cycleKey)); + } + + public bool TryAcceptPawn(Pawn pawn, CompBiosculpterPod_Cycle cycle) + { + if (!CanAcceptOnceCycleChosen(pawn)) + { + return false; + } + if (!PawnCarryingExtraCycleIngredients(pawn, cycle, remove: true)) + { + return false; + } + currentCycleKey = cycle.Props.key; + innerContainer.ClearAndDestroyContents(); + pawnEnteringBiosculpter = pawn; + bool num = pawn.DeSpawnOrDeselect(); + if (pawn.holdingOwner != null) + { + pawn.holdingOwner.TryTransferToContainer(pawn, innerContainer); + } + else + { + innerContainer.TryAdd(pawn); + } + if (num) + { + Find.Selector.Select(pawn, playSound: false, forceDesignatorDeselect: false); + } + pawnEnteringBiosculpter = null; + currentCycleTicksRemaining = cycle.Props.durationDays * 60000f; + liquifiedNutrition = 0f; + devFillPodLatch = false; + ClearQueuedInformation(); + tickEntered = Find.TickManager.TicksGame; + return true; + } + + public void EjectContents(bool interrupted, bool playSounds, Map destMap = null) + { + if (destMap == null) + { + destMap = parent.Map; + } + Pawn occupant = Occupant; + currentCycleKey = null; + currentCycleTicksRemaining = 0f; + currentCyclePowerCutTicks = 0; + liquifiedNutrition = 0f; + devFillPodLatch = false; + innerContainer.TryDropAll(parent.InteractionCell, destMap, ThingPlaceMode.Near); + if (occupant != null) + { + FilthMaker.TryMakeFilth(parent.InteractionCell, destMap, ThingDefOf.Filth_PodSlime, new IntRange(3, 6).RandomInRange); + if (interrupted) + { + occupant.needs?.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.SoakingWet); + occupant.health?.AddHediff(HediffDefOf.BiosculptingSickness); + } + } + if (playSounds) + { + Props.exitSound?.PlayOneShot(SoundInfo.InMap(new TargetInfo(parent.Position, parent.Map))); + } + } + + private void CycleCompleted() + { + Pawn occupant = Occupant; + CompBiosculpterPod_Cycle currentCycle = CurrentCycle; + SetBiotuned(occupant); + currentCycle.CycleCompleted(occupant); + EjectContents(interrupted: false, playSounds: true); + if (occupant != null) + { + Need_Food need_Food = occupant.needs?.food; + if (need_Food != null) + { + need_Food.CurLevelPercentage = 1f; + } + Need_Rest need_Rest = occupant.needs?.rest; + if (need_Rest != null) + { + need_Rest.CurLevelPercentage = 1f; + } + if (currentCycle.Props.gainThoughtOnCompletion != null) + { + occupant.needs?.mood?.thoughts.memories.TryGainMemory(ThoughtDefOf.AgeReversalReceived); + } + Find.HistoryEventsManager.RecordEvent(new HistoryEvent(HistoryEventDefOf.UsedBiosculpterPod, occupant.Named(HistoryEventArgsNames.Doer))); + } + if (tickEntered > 0) + { + occupant.drugs.Notify_LeftSuspension(Find.TickManager.TicksGame - tickEntered); + } + } + + private void LiquifyNutrition() + { + tmpItems.AddRange(innerContainer); + foreach (Thing tmpItem in tmpItems) + { + float num = tmpItem.GetStatValue(StatDefOf.Nutrition) * (float)tmpItem.stackCount; + if (!(num <= 0f) && !(tmpItem is Pawn)) + { + liquifiedNutrition = Mathf.Min(5f, liquifiedNutrition + num); + tmpItem.Destroy(); + } + } + tmpItems.Clear(); + } + + public override void CompTick() + { + if (!ModLister.CheckIdeology("Biosculpting")) + { + return; + } + base.CompTick(); + if (State != BiosculpterPodState.SelectingCycle || !PowerOn) + { + readyEffecter?.Cleanup(); + readyEffecter = null; + } + else if (Props.readyEffecter != null) + { + if (readyEffecter == null) + { + readyEffecter = Props.readyEffecter.Spawn(); + ColorizeEffecter(readyEffecter, Props.selectCycleColor); + readyEffecter.Trigger(parent, new TargetInfo(parent.InteractionCell, parent.Map)); + } + readyEffecter.EffectTick(parent, new TargetInfo(parent.InteractionCell, parent.Map)); + } + if (State != BiosculpterPodState.Occupied) + { + progressBarEffecter?.Cleanup(); + progressBarEffecter = null; + operatingEffecter?.Cleanup(); + operatingEffecter = null; + } + else + { + Pawn occupant = Occupant; + biotunedCountdownTicks = 4800000; + if (PowerOn) + { + int num = 1; + currentCycleTicksRemaining -= (float)num * CycleSpeedFactor; + if (currentCycleTicksRemaining <= 0f) + { + CycleCompleted(); + } + } + else + { + currentCyclePowerCutTicks++; + if (currentCyclePowerCutTicks >= 60000) + { + EjectContents(interrupted: true, playSounds: true); + Messages.Message("BiosculpterNoPowerEjectedMessage".Translate(occupant.Named("PAWN")), occupant, MessageTypeDefOf.NegativeEvent, historical: false); + } + } + if (currentCycleTicksRemaining > 0f) + { + if (progressBarEffecter == null) + { + progressBarEffecter = EffecterDefOf.ProgressBar.Spawn(); + } + progressBarEffecter.EffectTick(parent, TargetInfo.Invalid); + MoteProgressBar moteProgressBar = (progressBarEffecter.children[0] as SubEffecter_ProgressBar)?.mote; + if (moteProgressBar != null) + { + float num2 = CurrentCycle.Props.durationDays * 60000f; + moteProgressBar.progress = 1f - Mathf.Clamp01(currentCycleTicksRemaining / num2); + int num3 = (parent.RotatedSize.z - 1) / 2; + moteProgressBar.offsetZ = 0f - ((float)num3 + 0.5f); + } + if (Props.operatingEffecter != null) + { + if (!PowerOn) + { + operatingEffecter?.Cleanup(); + operatingEffecter = null; + } + else + { + if (operatingEffecter == null) + { + operatingEffecter = Props.operatingEffecter.Spawn(); + ColorizeEffecter(operatingEffecter, CurrentCycle.Props.operatingColor); + operatingEffecter.Trigger(parent, new TargetInfo(parent.InteractionCell, parent.Map)); + } + operatingEffecter.EffectTick(parent, new TargetInfo(parent.InteractionCell, parent.Map)); + } + } + } + } + if (PowerOn && biotunedCountdownTicks > 0) + { + biotunedCountdownTicks--; + } + if (biotunedCountdownTicks <= 0) + { + SetBiotuned(null); + } + SetPower(); + if (biotunedTo?.Ideo != null && !biotunedTo.Ideo.HasPrecept(PreceptDefOf.AgeReversal_Demanded)) + { + autoAgeReversal = false; + } + } + + private void SetPower() + { + if (powerTraderComp == null) + { + powerTraderComp = parent.TryGetComp(); + } + if (powerComp == null) + { + powerComp = parent.TryGetComp(); + } + if (State == BiosculpterPodState.Occupied) + { + powerTraderComp.PowerOutput = 0f - powerComp.Props.PowerConsumption; + } + else + { + powerTraderComp.PowerOutput = 0f - powerComp.Props.idlePowerDraw; + } + } + + private void ColorizeEffecter(Effecter effecter, Color color) + { + foreach (SubEffecter child in effecter.children) + { + if (child is SubEffecter_Sprayer subEffecter_Sprayer) + { + subEffecter_Sprayer.colorOverride = color * child.def.color; + } + } + } + + public override void PostDraw() + { + base.PostDraw(); + Rot4 rotation = parent.Rotation; + Vector3 s = new Vector3(parent.def.graphicData.drawSize.x * 0.8f, 1f, parent.def.graphicData.drawSize.y * 0.8f); + Vector3 drawPos = parent.DrawPos; + drawPos.y -= 0.07317074f; + Graphics.DrawMesh(MeshPool.plane10, Matrix4x4.TRS(drawPos, rotation.AsQuat, s), BackgroundMat, 0); + if (State == BiosculpterPodState.Occupied) + { + Pawn occupant = Occupant; + Vector3 drawLoc = parent.DrawPos + FloatingOffset(currentCycleTicksRemaining + (float)currentCyclePowerCutTicks); + Rot4 rotation2 = parent.Rotation; + if (rotation2 == Rot4.East || rotation2 == Rot4.West) + { + drawLoc.z += 0.2f; + } + occupant.Drawer.renderer.RenderPawnAt(drawLoc, null, neverAimWeapon: true); + } + } + + public static Vector3 FloatingOffset(float tickOffset) + { + float num = tickOffset % 500f / 500f; + float num2 = Mathf.Sin(MathF.PI * num); + float z = num2 * num2 * 0.04f; + return new Vector3(0f, 0f, z); + } + + public void GetChildHolders(List outChildren) + { + ThingOwnerUtility.AppendThingHoldersFromThings(outChildren, GetDirectlyHeldThings()); + } + + public ThingOwner GetDirectlyHeldThings() + { + return innerContainer; + } + + public StorageSettings GetStoreSettings() + { + return allowedNutritionSettings; + } + + public StorageSettings GetParentStoreSettings() + { + return parent.def.building.fixedStorageSettings; + } + + public void Notify_SettingsChanged() + { + } + + private static void OrderToPod(CompBiosculpterPod_Cycle cycle, Pawn pawn, Action giveJobAct) + { + if (cycle is CompBiosculpterPod_HealingCycle compBiosculpterPod_HealingCycle) + { + string healingDescriptionForPawn = compBiosculpterPod_HealingCycle.GetHealingDescriptionForPawn(pawn); + string text = (healingDescriptionForPawn.NullOrEmpty() ? "BiosculpterNoCoditionsToHeal".Translate(pawn.Named("PAWN"), compBiosculpterPod_HealingCycle.Props.label.Named("CYCLE")).Resolve() : ("OnCompletionOfCycle".Translate(compBiosculpterPod_HealingCycle.Props.label.Named("CYCLE")).Resolve() + ":\n\n" + healingDescriptionForPawn)); + Find.WindowStack.Add(Dialog_MessageBox.CreateConfirmation(text, giveJobAct, healingDescriptionForPawn.NullOrEmpty())); + } + else + { + giveJobAct(); + } + } + + public static Thing FindPodFor(Pawn pawn, Pawn traveller, bool biotuned) + { + if (cachedPodDefs.NullOrEmpty()) + { + cachedPodDefs = DefDatabase.AllDefs.Where((ThingDef def) => def.GetCompProperties() != null).ToList(); + } + foreach (ThingDef cachedPodDef in cachedPodDefs) + { + Thing thing = GenClosest.ClosestThingReachable(traveller.Position, pawn.Map, ThingRequest.ForDef(cachedPodDef), PathEndMode.InteractionCell, TraverseParms.For(pawn), 9999f, Validator); + if (thing != null) + { + return thing; + } + } + return null; + bool Validator(Thing t) + { + CompBiosculpterPod compBiosculpterPod = t.TryGetComp(); + if (biotuned && compBiosculpterPod.biotunedTo != traveller) + { + return false; + } + return compBiosculpterPod.CanAcceptOnceCycleChosen(traveller); + } + } + + public static bool WasLoadingCanceled(Thing thing) + { + CompBiosculpterPod compBiosculpterPod = thing.TryGetComp(); + if (compBiosculpterPod != null && compBiosculpterPod.State != 0) + { + return true; + } + return false; + } + + public void ClearCycle() + { + currentCycleKey = null; + } + + public void Notify_HauledTo(Pawn hauler, Thing thing, int count) + { + LiquifyNutrition(); + SoundDefOf.Standard_Drop.PlayOneShot(parent); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompBiosculpterPod_Cycle.txt` +**相似度:** 0.7210 + +```csharp +public abstract class CompBiosculpterPod_Cycle : ThingComp +{ + private List tmpMissingResearchLabels = new List(); + + public CompProperties_BiosculpterPod_BaseCycle Props => (CompProperties_BiosculpterPod_BaseCycle)props; + + public abstract void CycleCompleted(Pawn occupant); + + public virtual string Description(Pawn tunedFor) + { + return Props.description; + } + + public List MissingResearchLabels() + { + tmpMissingResearchLabels.Clear(); + if (Props.requiredResearch.NullOrEmpty()) + { + return tmpMissingResearchLabels; + } + foreach (ResearchProjectDef item in Props.requiredResearch) + { + if (!item.IsFinished) + { + tmpMissingResearchLabels.Add(item.LabelCap); + } + } + return tmpMissingResearchLabels; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_HaulToBiosculpterPod.txt` +**相似度:** 0.7198 + +```csharp +public class WorkGiver_HaulToBiosculpterPod : WorkGiver_Scanner +{ + public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForDef(ThingDefOf.BiosculpterPod); + + public override PathEndMode PathEndMode => PathEndMode.Touch; + + public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) + { + if (!ModLister.CheckIdeology("Biosculpting")) + { + return false; + } + if (!pawn.CanReserve(t, 1, -1, null, forced)) + { + return false; + } + if (pawn.Map.designationManager.DesignationOn(t, DesignationDefOf.Deconstruct) != null) + { + return false; + } + CompBiosculpterPod compBiosculpterPod = t.TryGetComp(); + if (compBiosculpterPod == null || !compBiosculpterPod.PowerOn || compBiosculpterPod.State != 0 || (!forced && !compBiosculpterPod.autoLoadNutrition)) + { + return false; + } + if (t.IsBurning()) + { + return false; + } + if (compBiosculpterPod.RequiredNutritionRemaining > 0f) + { + if (FindNutrition(pawn, compBiosculpterPod).Thing == null) + { + JobFailReason.Is("NoFood".Translate()); + return false; + } + return true; + } + return false; + } + + public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) + { + CompBiosculpterPod compBiosculpterPod = t.TryGetComp(); + if (compBiosculpterPod == null) + { + return null; + } + if (compBiosculpterPod.RequiredNutritionRemaining > 0f) + { + ThingCount thingCount = FindNutrition(pawn, compBiosculpterPod); + if (thingCount.Thing != null) + { + Job job = HaulAIUtility.HaulToContainerJob(pawn, thingCount.Thing, t); + job.count = Mathf.Min(job.count, thingCount.Count); + return job; + } + } + return null; + } + + private ThingCount FindNutrition(Pawn pawn, CompBiosculpterPod pod) + { + Thing thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree), PathEndMode.ClosestTouch, TraverseParms.For(pawn), 9999f, Validator); + if (thing == null) + { + return default(ThingCount); + } + int b = Mathf.CeilToInt(pod.RequiredNutritionRemaining / thing.GetStatValue(StatDefOf.Nutrition)); + return new ThingCount(thing, Mathf.Min(thing.stackCount, b)); + bool Validator(Thing x) + { + if (x.IsForbidden(pawn) || !pawn.CanReserve(x)) + { + return false; + } + if (!pod.CanAcceptNutrition(x)) + { + return false; + } + return true; + } + } +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/BiosculpterPod.txt b/MCP/vector_cache/BiosculpterPod.txt new file mode 100644 index 00000000..db82d121 --- /dev/null +++ b/MCP/vector_cache/BiosculpterPod.txt @@ -0,0 +1,74 @@ +根据向量相似度分析,与 'BiosculpterPod' 最相关的代码定义如下: + +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_BiosculpterPod_BaseCycle.txt` +**相似度:** 0.6754 + +```csharp +public abstract class CompProperties_BiosculpterPod_BaseCycle : CompProperties +{ + [NoTranslate] + public string key; + + [MustTranslate] + public string label; + + [MustTranslate] + public string description; + + [NoTranslate] + public string iconPath; + + public float durationDays; + + public Color operatingColor = new Color(0.5f, 0.7f, 0.5f); + + public ThoughtDef gainThoughtOnCompletion; + + public List requiredResearch; + + public List extraRequiredIngredients; + + private Texture2D icon; + + public Texture2D Icon + { + get + { + if (icon == null) + { + icon = ContentFinder.Get(iconPath); + } + return icon; + } + } + + public string LabelCap => label.CapitalizeFirst(); +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_BiosculpterPod_PleasureCycle.txt` +**相似度:** 0.6624 + +```csharp +public class CompProperties_BiosculpterPod_PleasureCycle : CompProperties_BiosculpterPod_BaseCycle +{ + public CompProperties_BiosculpterPod_PleasureCycle() + { + compClass = typeof(CompBiosculpterPod_PleasureCycle); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_BiosculpterPod_AgeReversalCycle.txt` +**相似度:** 0.6461 + +```csharp +public class CompProperties_BiosculpterPod_AgeReversalCycle : CompProperties_BiosculpterPod_BaseCycle +{ + public CompProperties_BiosculpterPod_AgeReversalCycle() + { + compClass = typeof(CompBiosculpterPod_AgeReversalCycle); + } +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/Building_Bed.txt b/MCP/vector_cache/Building_Bed.txt new file mode 100644 index 00000000..10294a2c --- /dev/null +++ b/MCP/vector_cache/Building_Bed.txt @@ -0,0 +1,1122 @@ +根据向量相似度分析,与 'Building_Bed' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\Building_Bed.txt` + +```csharp +public class Building_Bed : Building +{ + private BedOwnerType forOwnerType; + + private bool medicalInt; + + private bool alreadySetDefaultMed; + + private static int lastBedOwnerSetChangeFrame = -1; + + private static List tmpOrderedInteractionCells = new List(8); + + private static readonly Color SheetColorNormal = new Color(0.6313726f, 71f / 85f, 0.7058824f); + + private static readonly Color SheetColorRoyal = new Color(57f / 85f, 0.9137255f, 38f / 51f); + + public static readonly Color SheetColorForPrisoner = new Color(1f, 61f / 85f, 11f / 85f); + + private static readonly Color SheetColorMedical = new Color(33f / 85f, 53f / 85f, 0.8862745f); + + private static readonly Color SheetColorMedicalForPrisoner = new Color(0.654902f, 32f / 85f, 13f / 85f); + + private static readonly Color SheetColorForSlave = new Color32(252, 244, 3, byte.MaxValue); + + private static readonly Color SheetColorMedicalForSlave = new Color32(153, 148, 0, byte.MaxValue); + + private static readonly BedInteractionCellSearchPattern defaultBedInteractionCellsOrder = new BedInteractionCellSearchPattern(); + + public List OwnersForReading => CompAssignableToPawn.AssignedPawnsForReading; + + public CompAssignableToPawn CompAssignableToPawn => GetComp(); + + public bool ForPrisoners + { + get + { + return forOwnerType == BedOwnerType.Prisoner; + } + set + { + if (value == ForPrisoners || !def.building.bed_humanlike || ForHumanBabies) + { + return; + } + if (Current.ProgramState != ProgramState.Playing && Scribe.mode != 0) + { + Log.Error("Tried to set ForPrisoners while game mode was " + Current.ProgramState); + return; + } + RemoveAllOwners(); + if (value) + { + forOwnerType = BedOwnerType.Prisoner; + } + else + { + forOwnerType = BedOwnerType.Colonist; + Log.Error("Bed ForPrisoners=false, but should it be for for colonists or slaves? Set ForOwnerType instead."); + } + Notify_ColorChanged(); + NotifyRoomBedTypeChanged(); + } + } + + public bool ForSlaves => ForOwnerType == BedOwnerType.Slave; + + public bool ForColonists => ForOwnerType == BedOwnerType.Colonist; + + public bool ForHumanBabies + { + get + { + if (def.building.bed_humanlike) + { + return def.building.bed_maxBodySize < LifeStageDefOf.HumanlikeChild.bodySizeFactor; + } + return false; + } + } + + public BedOwnerType ForOwnerType + { + get + { + return forOwnerType; + } + set + { + if (value != forOwnerType && def.building.bed_humanlike && !ForHumanBabies && (value != BedOwnerType.Slave || ModLister.CheckIdeology("Slavery"))) + { + RemoveAllOwners(); + forOwnerType = value; + Notify_ColorChanged(); + NotifyRoomBedTypeChanged(); + } + } + } + + public bool Medical + { + get + { + return medicalInt; + } + set + { + if (value != medicalInt && (!value || def.building.bed_canBeMedical)) + { + RemoveAllOwners(); + medicalInt = value; + Notify_ColorChanged(); + if (base.Spawned) + { + base.Map.mapDrawer.MapMeshDirty(base.Position, MapMeshFlagDefOf.Things); + NotifyRoomBedTypeChanged(); + } + FacilityChanged(); + } + } + } + + public bool AnyUnownedSleepingSlot + { + get + { + if (Medical) + { + Log.Warning("Tried to check for unowned sleeping slot on medical bed " + this); + return false; + } + return CompAssignableToPawn.HasFreeSlot; + } + } + + public int TotalSleepingSlots + { + get + { + if (Medical) + { + Log.Warning("Tried to check for total sleeping slots on medical bed " + this); + return 0; + } + return CompAssignableToPawn.TotalSlots; + } + } + + public bool AnyUnoccupiedSleepingSlot + { + get + { + for (int i = 0; i < SleepingSlotsCount; i++) + { + if (GetCurOccupant(i) == null) + { + return true; + } + } + return false; + } + } + + public IEnumerable CurOccupants + { + get + { + for (int i = 0; i < SleepingSlotsCount; i++) + { + Pawn curOccupant = GetCurOccupant(i); + if (curOccupant != null) + { + yield return curOccupant; + } + } + } + } + + public bool AnyOccupants + { + get + { + for (int i = 0; i < SleepingSlotsCount; i++) + { + if (GetCurOccupant(i) != null) + { + return true; + } + } + return false; + } + } + + public override Color DrawColor + { + get + { + if (def.MadeFromStuff) + { + return base.DrawColor; + } + return DrawColorTwo; + } + } + + public override Color DrawColorTwo + { + get + { + if (def.building != null && !def.building.bed_UseSheetColor) + { + return base.DrawColorTwo; + } + bool medical = Medical; + switch (forOwnerType) + { + case BedOwnerType.Prisoner: + if (!medical) + { + return SheetColorForPrisoner; + } + return SheetColorMedicalForPrisoner; + case BedOwnerType.Slave: + if (!medical) + { + return SheetColorForSlave; + } + return SheetColorMedicalForSlave; + default: + if (medical) + { + return SheetColorMedical; + } + if (def == ThingDefOf.RoyalBed) + { + return SheetColorRoyal; + } + return SheetColorNormal; + } + } + } + + public int SleepingSlotsCount => BedUtility.GetSleepingSlotsCount(def.size); + + private bool PlayerCanSeeOwners => CompAssignableToPawn.PlayerCanSeeAssignments; + + public override IntVec3 InteractionCell => FindPreferredInteractionCell(base.Position) ?? base.InteractionCell; + + public override void SpawnSetup(Map map, bool respawningAfterLoad) + { + base.SpawnSetup(map, respawningAfterLoad); + Region validRegionAt_NoRebuild = map.regionGrid.GetValidRegionAt_NoRebuild(base.Position); + if (validRegionAt_NoRebuild != null && validRegionAt_NoRebuild.Room.IsPrisonCell) + { + ForPrisoners = true; + } + if (!alreadySetDefaultMed) + { + alreadySetDefaultMed = true; + if (def.building.bed_defaultMedical) + { + Medical = true; + } + } + if (!respawningAfterLoad) + { + District district = this.GetDistrict(); + if (district != null) + { + district.Notify_RoomShapeOrContainedBedsChanged(); + district.Room.Notify_RoomShapeChanged(); + } + } + } + + public override void DeSpawn(DestroyMode mode = DestroyMode.Vanish) + { + if (mode != DestroyMode.WillReplace) + { + if (mode != 0) + { + RemoveAllOwners(mode == DestroyMode.KillFinalize); + } + else if (InstallBlueprintUtility.ExistingBlueprintFor(this) == null) + { + foreach (Pawn item in OwnersForReading) + { + Messages.Message("MessageBedLostAssignment".Translate(def, item), new LookTargets(this, item), MessageTypeDefOf.CautionInput, historical: false); + } + } + ForOwnerType = BedOwnerType.Colonist; + Medical = false; + alreadySetDefaultMed = false; + } + District district = this.GetDistrict(); + base.DeSpawn(mode); + if (district != null) + { + district.Notify_RoomShapeOrContainedBedsChanged(); + district.Room.Notify_RoomShapeChanged(); + } + } + + public override void ExposeData() + { + base.ExposeData(); + Scribe_Values.Look(ref medicalInt, "medical", defaultValue: false); + Scribe_Values.Look(ref alreadySetDefaultMed, "alreadySetDefaultMed", defaultValue: false); + Scribe_Values.Look(ref forOwnerType, "forOwnerType", BedOwnerType.Colonist); + BackCompatibility.PostExposeData(this); + } + + public override void DrawExtraSelectionOverlays() + { + base.DrawExtraSelectionOverlays(); + Room room = this.GetRoom(); + if (room != null && RoomCanBePrisonCell(room)) + { + room.DrawFieldEdges(); + } + } + + public static bool RoomCanBePrisonCell(Room r) + { + if (r.ProperRoom) + { + return !r.IsHuge; + } + return false; + } + + public override IEnumerable GetGizmos() + { + foreach (Gizmo gizmo in base.GetGizmos()) + { + yield return gizmo; + } + if (base.Faction != Faction.OfPlayer) + { + yield break; + } + if (def.building.bed_humanlike && !ForHumanBabies) + { + if (ModsConfig.IdeologyActive) + { + yield return new Command_SetBedOwnerType(this); + } + else + { + Command_Toggle command_Toggle = new Command_Toggle(); + command_Toggle.defaultLabel = "CommandBedSetForPrisonersLabel".Translate(); + command_Toggle.defaultDesc = "CommandBedSetForPrisonersDesc".Translate(); + command_Toggle.icon = ContentFinder.Get("UI/Commands/ForPrisoners"); + command_Toggle.isActive = () => ForPrisoners; + command_Toggle.toggleAction = delegate + { + SetBedOwnerTypeByInterface((!ForPrisoners) ? BedOwnerType.Prisoner : BedOwnerType.Colonist); + }; + if (!RoomCanBePrisonCell(this.GetRoom()) && !ForPrisoners) + { + command_Toggle.Disable("CommandBedSetForPrisonersFailOutdoors".Translate()); + } + command_Toggle.hotKey = KeyBindingDefOf.Misc3; + command_Toggle.turnOffSound = null; + command_Toggle.turnOnSound = null; + yield return command_Toggle; + } + } + if (def.building.bed_canBeMedical) + { + Command_Toggle command_Toggle2 = new Command_Toggle(); + command_Toggle2.defaultLabel = "CommandBedSetAsMedicalLabel".Translate(); + command_Toggle2.defaultDesc = "CommandBedSetAsMedicalDesc".Translate(); + command_Toggle2.icon = ContentFinder.Get("UI/Commands/AsMedical"); + command_Toggle2.isActive = () => Medical; + command_Toggle2.toggleAction = delegate + { + Medical = !Medical; + }; + command_Toggle2.hotKey = KeyBindingDefOf.Misc2; + yield return command_Toggle2; + } + } + + public void SetBedOwnerTypeByInterface(BedOwnerType ownerType) + { + if (lastBedOwnerSetChangeFrame == Time.frameCount) + { + return; + } + lastBedOwnerSetChangeFrame = Time.frameCount; + ((ForOwnerType != ownerType) ? SoundDefOf.Checkbox_TurnedOn : SoundDefOf.Checkbox_TurnedOff).PlayOneShotOnCamera(); + List bedsToAffect = new List(); + foreach (Building_Bed item in Find.Selector.SelectedObjects.OfType()) + { + if (item.ForOwnerType == ownerType) + { + continue; + } + Room room = item.GetRoom(); + if (room == null && ownerType != BedOwnerType.Prisoner) + { + if (!bedsToAffect.Contains(item)) + { + bedsToAffect.Add(item); + } + continue; + } + foreach (Building_Bed containedBed in room.ContainedBeds) + { + if (containedBed.ForOwnerType != ownerType) + { + if (containedBed.ForOwnerType == BedOwnerType.Prisoner && !bedsToAffect.Contains(containedBed)) + { + bedsToAffect.Add(containedBed); + } + else if (ownerType == BedOwnerType.Prisoner && RoomCanBePrisonCell(room) && !bedsToAffect.Contains(containedBed)) + { + bedsToAffect.Add(containedBed); + } + else if (containedBed == item && !bedsToAffect.Contains(containedBed)) + { + bedsToAffect.Add(containedBed); + } + } + } + } + Action action = delegate + { + List list = new List(); + List list2 = new List(); + foreach (Building_Bed item2 in bedsToAffect) + { + District district = item2.GetDistrict(); + Room room2 = district.Room; + if (ownerType == BedOwnerType.Prisoner && room2.TouchesMapEdge) + { + item2.ForOwnerType = BedOwnerType.Colonist; + } + else + { + item2.ForOwnerType = ownerType; + } + if (!room2.TouchesMapEdge) + { + if (!list2.Contains(room2)) + { + list2.Add(room2); + } + if (!list.Contains(district)) + { + list.Add(district); + } + } + } + foreach (District item3 in list) + { + item3.Notify_RoomShapeOrContainedBedsChanged(); + } + foreach (Room item4 in list2) + { + item4.Notify_RoomShapeChanged(); + } + }; + if (bedsToAffect.Where((Building_Bed b) => b.OwnersForReading.Any((Pawn owner) => owner.RaceProps.Humanlike) && b != this).Count() == 0) + { + action(); + return; + } + StringBuilder stringBuilder = new StringBuilder(); + if (!ModsConfig.IdeologyActive) + { + if (ownerType == BedOwnerType.Prisoner) + { + stringBuilder.Append("TurningOnPrisonerBedWarning".Translate()); + } + else + { + stringBuilder.Append("TurningOffPrisonerBedWarning".Translate()); + } + } + else + { + stringBuilder.Append("ChangingOwnerTypeBedWarning".Translate()); + } + stringBuilder.AppendLine(); + foreach (Building_Bed item5 in bedsToAffect) + { + if (ownerType != item5.ForOwnerType) + { + for (int i = 0; i < item5.OwnersForReading.Count; i++) + { + stringBuilder.AppendLine(); + stringBuilder.Append(item5.OwnersForReading[i].LabelShort); + } + } + } + stringBuilder.AppendLine(); + stringBuilder.AppendLine(); + stringBuilder.Append("AreYouSure".Translate()); + Find.WindowStack.Add(Dialog_MessageBox.CreateConfirmation(stringBuilder.ToString(), action)); + } + + public override string GetInspectString() + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.Append(base.GetInspectString()); + if (def.building.bed_humanlike && def.building.bed_DisplayOwnerType && base.Faction == Faction.OfPlayer) + { + switch (ForOwnerType) + { + case BedOwnerType.Prisoner: + stringBuilder.AppendInNewLine("ForPrisonerUse".Translate()); + break; + case BedOwnerType.Slave: + stringBuilder.AppendInNewLine("ForSlaveUse".Translate()); + break; + case BedOwnerType.Colonist: + stringBuilder.AppendInNewLine("ForColonistUse".Translate()); + break; + default: + Log.Error($"Unknown bed owner type: {ForOwnerType}"); + break; + } + } + if (Medical) + { + stringBuilder.AppendInNewLine("MedicalBed".Translate()); + if (base.Spawned) + { + stringBuilder.AppendInNewLine("RoomInfectionChanceFactor".Translate() + ": " + this.GetRoom().GetStat(RoomStatDefOf.InfectionChanceFactor).ToStringPercent()); + } + } + else if (PlayerCanSeeOwners && def.building.bed_DisplayOwnersInInspectString) + { + if (OwnersForReading.Count == 0) + { + stringBuilder.AppendInNewLine("Owner".Translate() + ": " + "Nobody".Translate()); + } + else if (OwnersForReading.Count == 1) + { + stringBuilder.AppendInNewLine("Owner".Translate() + ": " + OwnersForReading[0].Label); + } + else + { + stringBuilder.AppendInNewLine("Owners".Translate() + ": "); + bool flag = false; + for (int i = 0; i < OwnersForReading.Count; i++) + { + if (flag) + { + stringBuilder.Append(", "); + } + flag = true; + stringBuilder.Append(OwnersForReading[i].LabelShort); + } + } + if (OwnersForReading.Count == 1 && ChildcareUtility.CanSuckle(OwnersForReading[0], out var _)) + { + Pawn p = OwnersForReading[0]; + float ambientTemperature = base.AmbientTemperature; + if (!p.SafeTemperatureRange().IncludesEpsilon(ambientTemperature)) + { + stringBuilder.AppendInNewLine("BedUnsafeTemperature".Translate().Colorize(ColoredText.WarningColor)); + } + else if (!p.ComfortableTemperatureRange().IncludesEpsilon(ambientTemperature)) + { + stringBuilder.AppendInNewLine("BedUncomfortableTemperature".Translate()); + } + } + } + return stringBuilder.ToString(); + } + + public override IEnumerable GetFloatMenuOptions(Pawn myPawn) + { + FloatMenuOption bedRestFloatMenuOption = GetBedRestFloatMenuOption(myPawn); + if (bedRestFloatMenuOption != null) + { + yield return bedRestFloatMenuOption; + } + } + + public FloatMenuOption GetBedRestFloatMenuOption(Pawn myPawn) + { + if (myPawn.RaceProps.Humanlike && !ForPrisoners && Medical && !myPawn.Drafted && base.Faction == Faction.OfPlayer && RestUtility.CanUseBedEver(myPawn, def)) + { + if (!HealthAIUtility.ShouldSeekMedicalRest(myPawn)) + { + if (myPawn.health.surgeryBills.AnyShouldDoNow && !WorkGiver_PatientGoToBedTreatment.AnyAvailableDoctorFor(myPawn)) + { + return new FloatMenuOption("UseMedicalBed".Translate() + " (" + "NoDoctor".Translate() + ")", null); + } + return new FloatMenuOption("UseMedicalBed".Translate() + " (" + "NotInjured".Translate() + ")", null); + } + if (myPawn.IsSlaveOfColony && !ForSlaves) + { + return new FloatMenuOption("UseMedicalBed".Translate() + " (" + "NotForSlaves".Translate() + ")", null); + } + Action action = delegate + { + if (!ForPrisoners && Medical && myPawn.CanReserveAndReach(this, PathEndMode.ClosestTouch, Danger.Deadly, SleepingSlotsCount, -1, null, ignoreOtherReservations: true)) + { + if (myPawn.CurJobDef == JobDefOf.LayDown && myPawn.CurJob.GetTarget(TargetIndex.A).Thing == this) + { + myPawn.CurJob.restUntilHealed = true; + } + else + { + Job job = JobMaker.MakeJob(JobDefOf.LayDown, this); + job.restUntilHealed = true; + myPawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); + } + myPawn.mindState.ResetLastDisturbanceTick(); + } + }; + return FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("UseMedicalBed".Translate(), action), myPawn, this, (AnyUnoccupiedSleepingSlot ? "ReservedBy" : "SomeoneElseSleeping").CapitalizeFirst()); + } + return null; + } + + public override void DrawGUIOverlay() + { + if (Medical || Find.CameraDriver.CurrentZoom != 0 || !PlayerCanSeeOwners) + { + return; + } + Color defaultThingLabelColor = GenMapUI.DefaultThingLabelColor; + if (!OwnersForReading.Any()) + { + GenMapUI.DrawThingLabel(this, "Unowned".Translate(), defaultThingLabelColor); + return; + } + if (OwnersForReading.Count == 1) + { + Pawn pawn = OwnersForReading[0]; + if ((!pawn.InBed() || pawn.CurrentBed() != this) && (!pawn.RaceProps.Animal || Prefs.AnimalNameMode.ShouldDisplayAnimalName(pawn))) + { + GenMapUI.DrawThingLabel(this, pawn.LabelShort, defaultThingLabelColor); + } + return; + } + for (int i = 0; i < OwnersForReading.Count; i++) + { + Pawn pawn2 = OwnersForReading[i]; + if (!pawn2.InBed() || OwnersForReading[i].CurrentBed() != this || !(pawn2.Position == GetSleepingSlotPos(i))) + { + if (pawn2.RaceProps.Animal && !Prefs.AnimalNameMode.ShouldDisplayAnimalName(pawn2)) + { + break; + } + GenMapUI.DrawThingLabel(GetMultiOwnersLabelScreenPosFor(i), pawn2.LabelShort, defaultThingLabelColor); + } + } + } + + public Pawn GetCurOccupant(int slotIndex) + { + if (!base.Spawned) + { + return null; + } + IntVec3 sleepingSlotPos = GetSleepingSlotPos(slotIndex); + List list = base.Map.thingGrid.ThingsListAt(sleepingSlotPos); + for (int i = 0; i < list.Count; i++) + { + if (list[i] is Pawn { CurJob: not null } pawn && pawn.GetPosture().InBed()) + { + return pawn; + } + } + return null; + } + + public int GetCurOccupantSlotIndex(Pawn curOccupant) + { + for (int i = 0; i < SleepingSlotsCount; i++) + { + if (GetCurOccupant(i) == curOccupant) + { + return i; + } + } + Log.Error("Could not find pawn " + curOccupant?.ToString() + " on any of sleeping slots."); + return 0; + } + + public Pawn GetCurOccupantAt(IntVec3 pos) + { + for (int i = 0; i < SleepingSlotsCount; i++) + { + if (GetSleepingSlotPos(i) == pos) + { + return GetCurOccupant(i); + } + } + return null; + } + + public IntVec3 GetSleepingSlotPos(int index) + { + return BedUtility.GetSleepingSlotPos(index, base.Position, base.Rotation, def.size); + } + + public IntVec3 GetFootSlotPos(int index) + { + return BedUtility.GetFeetSlotPos(index, base.Position, base.Rotation, def.size); + } + + public bool IsOwner(Pawn p) + { + int? assignedSleepingSlot; + return IsOwner(p, out assignedSleepingSlot); + } + + public bool IsOwner(Pawn p, out int? assignedSleepingSlot) + { + int num = GetComp().AssignedPawnsForReading.IndexOf(p); + if (num >= 0) + { + assignedSleepingSlot = num; + return true; + } + assignedSleepingSlot = null; + return false; + } + + private void RemoveAllOwners(bool destroyed = false) + { + for (int num = OwnersForReading.Count - 1; num >= 0; num--) + { + Pawn pawn = OwnersForReading[num]; + pawn.ownership.UnclaimBed(); + string key = "MessageBedLostAssignment"; + if (destroyed) + { + key = "MessageBedDestroyed"; + } + Messages.Message(key.Translate(def, pawn), new LookTargets(this, pawn), MessageTypeDefOf.CautionInput, historical: false); + } + } + + private void NotifyRoomBedTypeChanged() + { + this.GetRoom()?.Notify_BedTypeChanged(); + } + + public void NotifyRoomAssignedPawnsChanged() + { + this.GetRoom()?.Notify_BedTypeChanged(); + } + + private void FacilityChanged() + { + CompFacility compFacility = this.TryGetComp(); + CompAffectedByFacilities compAffectedByFacilities = this.TryGetComp(); + compFacility?.Notify_ThingChanged(); + compAffectedByFacilities?.Notify_ThingChanged(); + } + + private Vector3 GetMultiOwnersLabelScreenPosFor(int slotIndex) + { + IntVec3 sleepingSlotPos = GetSleepingSlotPos(slotIndex); + Vector3 drawPos = DrawPos; + if (base.Rotation.IsHorizontal) + { + drawPos.z = (float)sleepingSlotPos.z + 0.6f; + } + else + { + drawPos.x = (float)sleepingSlotPos.x + 0.5f; + drawPos.z += -0.4f; + } + Vector2 vector = drawPos.MapToUIPosition(); + if (!base.Rotation.IsHorizontal && SleepingSlotsCount == 2) + { + vector = AdjustOwnerLabelPosToAvoidOverlapping(vector, slotIndex); + } + return vector; + } + + private Vector3 AdjustOwnerLabelPosToAvoidOverlapping(Vector3 screenPos, int slotIndex) + { + Text.Font = GameFont.Tiny; + float num = Text.CalcSize(OwnersForReading[slotIndex].LabelShort).x + 1f; + Vector2 vector = DrawPos.MapToUIPosition(); + float num2 = Mathf.Abs(screenPos.x - vector.x); + IntVec3 sleepingSlotPos = GetSleepingSlotPos(slotIndex); + if (num > num2 * 2f) + { + float num3 = 0f; + num3 = ((slotIndex != 0) ? ((float)GetSleepingSlotPos(0).x) : ((float)GetSleepingSlotPos(1).x)); + if ((float)sleepingSlotPos.x < num3) + { + screenPos.x -= (num - num2 * 2f) / 2f; + } + else + { + screenPos.x += (num - num2 * 2f) / 2f; + } + } + return screenPos; + } + + private bool RemoveLeastDesirableInteractionCells(List cells, Map map) + { + cells.RemoveAll(map, (Map innerMap, IntVec3 cell) => !cell.Standable(innerMap) || !TouchPathEndModeUtility.IsAdjacentOrInsideAndAllowedToTouch(cell, new LocalTargetInfo(this), map.pathing.Normal)); + if (cells.RemoveAll_IfNotAll(map, delegate(Map innerMap, IntVec3 cell) + { + Building building = map.edificeGrid[cell]; + return building == null || building.def?.IsBed != true; + })) + { + return cells.RemoveAll_IfNotAll(map, (Map innerMap, IntVec3 cell) => cell.GetDoor(map) == null); + } + return false; + } + + public IntVec3? FindPreferredInteractionCell(IntVec3 occupantLocation, CellSearchPattern customSearchPattern = null) + { + CellRect cellRect = this.OccupiedRect(); + if (!cellRect.Contains(occupantLocation)) + { + Log.Error($"interiorLocation {occupantLocation} is not within the bounds of this bed {cellRect}."); + return null; + } + tmpOrderedInteractionCells.Clear(); + (customSearchPattern ?? defaultBedInteractionCellsOrder).AddCellsToList(tmpOrderedInteractionCells, this, cellRect, occupantLocation, base.Rotation); + RemoveLeastDesirableInteractionCells(tmpOrderedInteractionCells, base.Map); + if (tmpOrderedInteractionCells.Count == 0) + { + return null; + } + return tmpOrderedInteractionCells[0]; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\RoomRoleWorker_Bedroom.txt` +**相似度:** 0.5705 + +```csharp +public class RoomRoleWorker_Bedroom : RoomRoleWorker +{ + private static List tmpBeds = new List(); + + private static List children = new List(); + + private static List adults = new List(); + + public override float GetScore(Room room) + { + tmpBeds.Clear(); + List containedAndAdjacentThings = room.ContainedAndAdjacentThings; + int num = 0; + for (int i = 0; i < containedAndAdjacentThings.Count; i++) + { + if (containedAndAdjacentThings[i] is Building_Bed building_Bed && building_Bed.def.building.bed_humanlike && building_Bed.def.building.bed_countsForBedroomOrBarracks) + { + if (building_Bed.Medical || building_Bed.ForPrisoners) + { + tmpBeds.Clear(); + return 0f; + } + num++; + tmpBeds.Add(building_Bed); + } + } + if (num == 0) + { + tmpBeds.Clear(); + return 0f; + } + bool num2 = IsBedroom(tmpBeds); + tmpBeds.Clear(); + if (!num2) + { + return 0f; + } + return 100000f; + } + + public static bool IsBedroom(List beds) + { + children.Clear(); + adults.Clear(); + bool result = IsBedroomHelper(beds); + children.Clear(); + adults.Clear(); + return result; + } + + private static bool IsBedroomHelper(List beds) + { + List list = null; + int num = 0; + int num2 = 0; + int num3 = 0; + foreach (Building_Bed bed in beds) + { + List ownersForReading = bed.OwnersForReading; + if (ownersForReading.NullOrEmpty() && bed.def.building.bed_emptyCountsForBarracks) + { + num++; + continue; + } + if (ownersForReading.Count > 0) + { + num2++; + } + bool flag = false; + foreach (Pawn item in ownersForReading) + { + if (item.DevelopmentalStage.Juvenile()) + { + children.Add(item); + continue; + } + adults.Add(item); + if (list == null) + { + list = item.GetLoveCluster(); + } + if (!list.Contains(item)) + { + flag = true; + } + } + if (flag) + { + num3++; + } + } + if (num == 1 && num2 == 0) + { + return true; + } + if (num == 0 && num2 == 1) + { + return true; + } + if (num > 0) + { + return false; + } + if (adults.NullOrEmpty()) + { + return true; + } + if (num3 > 0) + { + return false; + } + foreach (Pawn child in children) + { + Pawn mother = child.GetMother(); + Pawn father = child.GetFather(); + if (!adults.Any((Pawn adult) => adult == mother || adult == father)) + { + return false; + } + } + return true; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\RoomRoleWorker_Barracks.txt` +**相似度:** 0.5548 + +```csharp +public class RoomRoleWorker_Barracks : RoomRoleWorker +{ + private static List tmpBeds = new List(); + + public override float GetScore(Room room) + { + tmpBeds.Clear(); + int num = 0; + List containedAndAdjacentThings = room.ContainedAndAdjacentThings; + for (int i = 0; i < containedAndAdjacentThings.Count; i++) + { + if (containedAndAdjacentThings[i] is Building_Bed building_Bed && building_Bed.def.building.bed_humanlike && building_Bed.def.building.bed_countsForBedroomOrBarracks) + { + if (building_Bed.ForPrisoners) + { + tmpBeds.Clear(); + return 0f; + } + tmpBeds.Add(building_Bed); + if (!building_Bed.Medical) + { + num++; + } + } + } + bool num2 = RoomRoleWorker_Bedroom.IsBedroom(tmpBeds); + tmpBeds.Clear(); + if (num2) + { + return 0f; + } + return (float)num * 100100f; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld.BaseGen\SymbolResolver_PrisonerBed.txt` +**相似度:** 0.5535 + +```csharp +public class SymbolResolver_PrisonerBed : SymbolResolver +{ + public override void Resolve(ResolveParams rp) + { + ResolveParams resolveParams = rp; + Action prevPostThingSpawn = resolveParams.postThingSpawn; + resolveParams.postThingSpawn = delegate(Thing x) + { + if (prevPostThingSpawn != null) + { + prevPostThingSpawn(x); + } + if (x is Building_Bed building_Bed) + { + building_Bed.ForPrisoners = true; + } + }; + BaseGen.symbolStack.Push("bed", resolveParams); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_TakeToBed.txt` +**相似度:** 0.5270 + +```csharp +public abstract class WorkGiver_TakeToBed : WorkGiver_Scanner +{ + protected Building_Bed FindBed(Pawn pawn, Pawn patient) + { + return RestUtility.FindBedFor(patient, pawn, checkSocialProperness: false, ignoreOtherReservations: false, patient.GuestStatus); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompAssignableToPawn_DeathrestCasket.txt` +**相似度:** 0.5238 + +```csharp +public class CompAssignableToPawn_DeathrestCasket : CompAssignableToPawn_Bed +{ + public override string CompInspectStringExtra() + { + return null; + } + + public override bool AssignedAnything(Pawn pawn) + { + return pawn.ownership.AssignedDeathrestCasket != null; + } + + public override void TryAssignPawn(Pawn pawn) + { + Building_Bed building_Bed = (Building_Bed)parent; + pawn.ownership.ClaimDeathrestCasket(building_Bed); + building_Bed.NotifyRoomAssignedPawnsChanged(); + } + + public override void TryUnassignPawn(Pawn pawn, bool sort = true, bool uninstall = false) + { + Building_Bed ownedBed = pawn.ownership.OwnedBed; + pawn.ownership.UnclaimDeathrestCasket(); + ownedBed?.NotifyRoomAssignedPawnsChanged(); + } + + public override AcceptanceReport CanAssignTo(Pawn pawn) + { + Building_Bed building_Bed = (Building_Bed)parent; + if (pawn.BodySize > building_Bed.def.building.bed_maxBodySize) + { + return "TooLargeForBed".Translate(); + } + if (building_Bed.ForSlaves && !pawn.IsSlave) + { + return "CannotAssignBedToColonist".Translate(); + } + if (building_Bed.ForColonists && pawn.IsSlave) + { + return "CannotAssignBedToSlave".Translate(); + } + CompDeathrestBindable compDeathrestBindable = parent.TryGetComp(); + if (compDeathrestBindable != null && compDeathrestBindable.BoundPawn != null && compDeathrestBindable.BoundPawn != pawn) + { + return "CannotAssignAlreadyBound".Translate(compDeathrestBindable.BoundPawn); + } + Gene_Deathrest gene_Deathrest = pawn.genes?.GetFirstGeneOfType(); + if (gene_Deathrest == null) + { + return "CannotAssignBedCannotDeathrest".Translate(); + } + if (compDeathrestBindable != null && gene_Deathrest.BindingWillExceedStackLimit(compDeathrestBindable)) + { + return "CannotAssignBedCannotBindToMoreBuildings".Translate(NamedArgumentUtility.Named(parent.def, "BUILDING")); + } + return AcceptanceReport.WasAccepted; + } + + protected override void PostPostExposeData() + { + if (Scribe.mode == LoadSaveMode.PostLoadInit && ModsConfig.BiotechActive && assignedPawns.RemoveAll((Pawn x) => x.ownership.AssignedDeathrestCasket != parent) > 0) + { + Log.Warning(parent.ToStringSafe() + " had pawns assigned that don't have it as an assigned bed. Removing."); + } + } +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/CarryToBiosculpterPod-JobDefOf-JobDriver_CarryToBiosculpterPod.txt b/MCP/vector_cache/CarryToBiosculpterPod-JobDefOf-JobDriver_CarryToBiosculpterPod.txt new file mode 100644 index 00000000..cbec2925 --- /dev/null +++ b/MCP/vector_cache/CarryToBiosculpterPod-JobDefOf-JobDriver_CarryToBiosculpterPod.txt @@ -0,0 +1,198 @@ +根据向量相似度分析,与 'JobDriver_CarryToBiosculpterPod, JobDefOf, CarryToBiosculpterPod' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\JobDriver_CarryToBiosculpterPod.txt` + +```csharp +public class JobDriver_CarryToBiosculpterPod : JobDriver +{ + private const TargetIndex TakeeInd = TargetIndex.A; + + private const TargetIndex IngredientInd = TargetIndex.B; + + private const TargetIndex PodInd = TargetIndex.C; + + private List pickedUpIngredients = new List(); + + private List thingsToTransfer = new List(); + + private Pawn Takee => (Pawn)job.GetTarget(TargetIndex.A).Thing; + + private CompBiosculpterPod Pod => job.GetTarget(TargetIndex.C).Thing.TryGetComp(); + + public override bool TryMakePreToilReservations(bool errorOnFailed) + { + if (!pawn.Reserve(Takee, job, 1, -1, null, errorOnFailed) || !pawn.Reserve(Pod.parent, job, 1, -1, null, errorOnFailed)) + { + return false; + } + List targetQueue = job.GetTargetQueue(TargetIndex.B); + for (int i = 0; i < targetQueue.Count; i++) + { + if (!pawn.Reserve(targetQueue[i], job, 1, -1, null, errorOnFailed)) + { + return false; + } + } + return true; + } + + protected override IEnumerable MakeNewToils() + { + if (!ModLister.CheckIdeology("Biosculpting")) + { + yield break; + } + AddFinishAction(delegate + { + if (Pod != null) + { + if (Pod.queuedEnterJob == job) + { + Pod.ClearQueuedInformation(); + } + if (Pod.Occupant != Takee) + { + foreach (Thing pickedUpIngredient in pickedUpIngredients) + { + Thing lastResultingThing; + if (pawn.inventory.Contains(pickedUpIngredient)) + { + pawn.inventory.innerContainer.TryDrop(pickedUpIngredient, ThingPlaceMode.Near, out lastResultingThing); + } + else if (Takee.inventory.Contains(pickedUpIngredient)) + { + Takee.inventory.innerContainer.TryDrop(pickedUpIngredient, ThingPlaceMode.Near, out lastResultingThing); + } + } + } + } + }); + this.FailOnDestroyedOrNull(TargetIndex.A); + this.FailOnDestroyedOrNull(TargetIndex.C); + this.FailOnAggroMentalState(TargetIndex.A); + this.FailOn(() => job.biosculpterCycleKey == null || !Pod.CanAcceptOnceCycleChosen(Takee)); + Toil goToTakee = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.OnCell).FailOnDestroyedNullOrForbidden(TargetIndex.A).FailOnDespawnedNullOrForbidden(TargetIndex.C) + .FailOn(() => Takee.IsFreeColonist && !Takee.Downed) + .FailOnSomeonePhysicallyInteracting(TargetIndex.A); + Toil startCarryingTakee = Toils_Haul.StartCarryThing(TargetIndex.A); + Toil goToThing = Toils_Goto.GotoThing(TargetIndex.C, PathEndMode.InteractionCell); + Toil toil = Toils_Jump.JumpIf(goToThing, () => pawn.IsCarryingPawn(Takee) && job.GetTargetQueue(TargetIndex.B).NullOrEmpty()); + Toil jumpIfGoToTakee = Toils_Jump.JumpIf(goToTakee, () => job.GetTargetQueue(TargetIndex.B).NullOrEmpty()); + yield return toil; + yield return jumpIfGoToTakee; + yield return DropCarryToGrabIngredients(); + foreach (Toil item in JobDriver_EnterBiosculpterPod.CollectIngredientsToilsHelper(TargetIndex.B, pawn, pickedUpIngredients)) + { + yield return item; + } + yield return goToTakee; + yield return TransferIngredientsAndPrepareCarryDownedPawn(); + yield return startCarryingTakee; + yield return goToThing.FailOn(() => !Pod.PawnCarryingExtraCycleIngredients(Takee, job.biosculpterCycleKey)); + yield return JobDriver_EnterBiosculpterPod.PrepareToEnterToil(TargetIndex.C); + Toil toil2 = ToilMaker.MakeToil("MakeNewToils"); + toil2.initAction = delegate + { + Pod.TryAcceptPawn(Takee, job.biosculpterCycleKey); + }; + toil2.defaultCompleteMode = ToilCompleteMode.Instant; + yield return toil2; + } + + private Toil TransferIngredientsAndPrepareCarryDownedPawn() + { + Toil toil = ToilMaker.MakeToil("TransferIngredientsAndPrepareCarryDownedPawn"); + toil.initAction = delegate + { + List extraRequiredIngredients = Pod.GetCycle(job.biosculpterCycleKey).Props.extraRequiredIngredients; + if (extraRequiredIngredients != null && !Pod.devFillPodLatch) + { + ThingOwner innerContainer = pawn.inventory.innerContainer; + foreach (ThingDefCountClass item in extraRequiredIngredients) + { + if (Takee.inventory.Count(item.thingDef) < item.count) + { + if (pawn.inventory.Count(item.thingDef) < item.count) + { + EndJobWith(JobCondition.Incompletable); + return; + } + thingsToTransfer.Clear(); + int num = 0; + foreach (Thing item2 in innerContainer) + { + if (num >= item.count) + { + break; + } + if (item2.def == item.thingDef) + { + int num2 = Mathf.Min(item.count - num, item2.stackCount); + thingsToTransfer.Add(new ThingCount(item2, Mathf.Min(item.count - num, item2.stackCount))); + num += num2; + } + } + foreach (ThingCount item3 in thingsToTransfer) + { + int num3 = Takee.inventory.innerContainer.TryAddOrTransfer(item3.Thing, item3.Count); + if (num3 != item3.Count) + { + Log.Warning($"Only able to transfer x{num3} of the expected x{item3.Count} of {item3.Thing.Label} while CarryToBiosculpter"); + EndJobWith(JobCondition.Incompletable); + return; + } + } + } + } + } + job.count = 1; + }; + toil.defaultCompleteMode = ToilCompleteMode.Instant; + return toil; + } + + private Toil DropCarryToGrabIngredients() + { + Toil toil = ToilMaker.MakeToil("DropCarryToGrabIngredients"); + toil.initAction = delegate + { + if (pawn.carryTracker.CarriedThing != null) + { + pawn.carryTracker.TryDropCarriedThing(pawn.Position, ThingPlaceMode.Near, out var _); + } + }; + toil.defaultCompleteMode = ToilCompleteMode.Instant; + return toil; + } + + public override string GetReport() + { + if (!Pod.PawnCarryingExtraCycleIngredients(Takee, job.biosculpterCycleKey) && !Pod.PawnCarryingExtraCycleIngredients(pawn, job.biosculpterCycleKey)) + { + return "BiosculpterJobReportCollectIngredients".Translate(); + } + return base.GetReport(); + } + + public override void ExposeData() + { + base.ExposeData(); + Scribe_Collections.Look(ref pickedUpIngredients, "pickedUpIngredients", LookMode.Reference); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Ideology\Defs\JobDefs\Jobs_Misc.xml` +**相似度:** 0.5483 + +```xml + CarryToBiosculpterPod + JobDriver_CarryToBiosculpterPod + carrying TargetA to biosculpter pod. + false + + + + RecolorApparel +``` \ No newline at end of file diff --git a/MCP/vector_cache/ColonistBarColonistDrawer-DrawIcons.txt b/MCP/vector_cache/ColonistBarColonistDrawer-DrawIcons.txt new file mode 100644 index 00000000..54867b4b --- /dev/null +++ b/MCP/vector_cache/ColonistBarColonistDrawer-DrawIcons.txt @@ -0,0 +1,985 @@ +根据向量相似度分析,与 'DrawIcons, ColonistBarColonistDrawer' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\ColonistBarColonistDrawer.txt` + +```csharp +public class ColonistBarColonistDrawer +{ + private struct IconDrawCall + { + public Texture2D texture; + + public string tooltip; + + public Color? color; + + public IconDrawCall(Texture2D texture, string tooltip = null, Color? color = null) + { + this.texture = texture; + this.tooltip = tooltip; + this.color = color; + } + } + + private Dictionary pawnLabelsCache = new Dictionary(); + + private static readonly Texture2D MoodBGTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.4f, 0.47f, 0.53f, 0.44f)); + + private static readonly Texture2D MoodAtlas = ContentFinder.Get("UI/Widgets/SubtleGradient"); + + private static readonly Texture2D DeadColonistTex = ContentFinder.Get("UI/Misc/DeadColonist"); + + private static readonly Texture2D Icon_FormingCaravan = ContentFinder.Get("UI/Icons/ColonistBar/FormingCaravan"); + + private static readonly Texture2D Icon_MentalStateNonAggro = ContentFinder.Get("UI/Icons/ColonistBar/MentalStateNonAggro"); + + private static readonly Texture2D Icon_MentalStateAggro = ContentFinder.Get("UI/Icons/ColonistBar/MentalStateAggro"); + + private static readonly Texture2D Icon_MedicalRest = ContentFinder.Get("UI/Icons/ColonistBar/MedicalRest"); + + private static readonly Texture2D Icon_Sleeping = ContentFinder.Get("UI/Icons/ColonistBar/Sleeping"); + + private static readonly Texture2D Icon_Fleeing = ContentFinder.Get("UI/Icons/ColonistBar/Fleeing"); + + private static readonly Texture2D Icon_Attacking = ContentFinder.Get("UI/Icons/ColonistBar/Attacking"); + + private static readonly Texture2D Icon_Idle = ContentFinder.Get("UI/Icons/ColonistBar/Idle"); + + private static readonly Texture2D Icon_Burning = ContentFinder.Get("UI/Icons/ColonistBar/Burning"); + + private static readonly Texture2D Icon_Inspired = ContentFinder.Get("UI/Icons/ColonistBar/Inspired"); + + private static readonly Texture2D MoodGradient = ContentFinder.Get("UI/Widgets/MoodGradient"); + + public static readonly Vector2 PawnTextureSize = new Vector2(ColonistBar.BaseSize.x - 2f, 75f); + + public static readonly Vector3 PawnTextureCameraOffset = new Vector3(0f, 0f, 0.3f); + + public const float PawnTextureCameraZoom = 1.28205f; + + private const float PawnTextureHorizontalPadding = 1f; + + private static readonly float BaseIconAreaWidth = PawnTextureSize.x; + + private static readonly float BaseIconMaxSize = 20f; + + private const float BaseGroupFrameMargin = 12f; + + public const float DoubleClickTime = 0.5f; + + public const float FactionIconSpacing = 2f; + + public const float IdeoRoleIconSpacing = 2f; + + public const float SlaveIconSpacing = 2f; + + private const float MoodGradientHeight = 35f; + + private static List tmpIconsToDraw = new List(); + + private ColonistBar ColonistBar => Find.ColonistBar; + + public void DrawColonist(Rect rect, Pawn colonist, Map pawnMap, bool highlight, bool reordering) + { + float alpha = ColonistBar.GetEntryRectAlpha(rect); + bool num = Prefs.VisibleMood && colonist.needs?.mood != null && colonist.mindState.mentalBreaker.CanDoRandomMentalBreaks && !colonist.Dead && !colonist.Downed; + MoodThreshold moodThreshold = MoodThresholdExtensions.CurrentMoodThresholdFor(colonist); + Color color = moodThreshold.GetColor(); + color.a *= alpha; + ApplyEntryInAnotherMapAlphaFactor(pawnMap, ref alpha); + if (reordering) + { + alpha *= 0.5f; + } + Color color3 = (GUI.color = new Color(1f, 1f, 1f, alpha)); + if (num && alpha >= 1f) + { + float num2 = moodThreshold.EdgeExpansion(); + if (num2 > 0f) + { + GUI.color = color; + Widgets.DrawAtlas(rect.ExpandedBy(num2), MoodAtlas); + GUI.color = color3; + } + } + GUI.DrawTexture(rect, ColonistBar.BGTex); + if (colonist.needs != null && colonist.needs.mood != null) + { + Rect position = rect.ContractedBy(2f); + float num3 = position.height * colonist.needs.mood.CurLevelPercentage; + position.yMin = position.yMax - num3; + position.height = num3; + GUI.DrawTexture(position, MoodBGTex); + } + if (num && alpha >= 1f) + { + float transparency = ((moodThreshold < MoodThreshold.Major) ? 0.1f : 0.15f); + Widgets.DrawBoxSolid(rect, moodThreshold.GetColor().ToTransparent(transparency)); + } + if (highlight) + { + int thickness = ((rect.width <= 22f) ? 2 : 3); + GUI.color = Color.white; + Widgets.DrawBox(rect, thickness); + GUI.color = color3; + } + Rect rect2 = rect.ContractedBy(-2f * ColonistBar.Scale); + if ((colonist.Dead ? Find.Selector.SelectedObjects.Contains(colonist.Corpse) : Find.Selector.SelectedObjects.Contains(colonist)) && !WorldRendererUtility.WorldSelected) + { + DrawSelectionOverlayOnGUI(colonist, rect2); + } + else if (WorldRendererUtility.WorldSelected && colonist.IsCaravanMember() && Find.WorldSelector.IsSelected(colonist.GetCaravan())) + { + DrawCaravanSelectionOverlayOnGUI(colonist.GetCaravan(), rect2); + } + GUI.DrawTexture(GetPawnTextureRect(rect.position), PortraitsCache.Get(colonist, PawnTextureSize, Rot4.South, PawnTextureCameraOffset, 1.28205f)); + if (num) + { + Rect rect3 = rect.ContractedBy(1f); + Widgets.BeginGroup(rect3); + Rect position2 = rect3.AtZero(); + position2.yMin = position2.yMax - 35f; + GUI.color = color; + GUI.DrawTexture(position2, MoodGradient); + GUI.color = color3; + Widgets.EndGroup(); + } + GUI.color = new Color(1f, 1f, 1f, alpha * 0.8f); + DrawIcons(rect, colonist); + GUI.color = color3; + if (colonist.Dead) + { + GUI.DrawTexture(rect, DeadColonistTex); + } + float num4 = 4f * ColonistBar.Scale; + Vector2 pos = new Vector2(rect.center.x, rect.yMax - num4); + GenMapUI.DrawPawnLabel(colonist, pos, alpha, rect.width + ColonistBar.SpaceBetweenColonistsHorizontal - 2f, pawnLabelsCache); + Text.Font = GameFont.Small; + GUI.color = Color.white; + } + + private Rect GroupFrameRect(int group) + { + float num = 99999f; + float num2 = 0f; + float num3 = 0f; + List entries = ColonistBar.Entries; + List drawLocs = ColonistBar.DrawLocs; + for (int i = 0; i < entries.Count; i++) + { + if (entries[i].group == group) + { + num = Mathf.Min(num, drawLocs[i].x); + num2 = Mathf.Max(num2, drawLocs[i].x + ColonistBar.Size.x); + num3 = Mathf.Max(num3, drawLocs[i].y + ColonistBar.Size.y); + } + } + return new Rect(num, 0f, num2 - num, num3 - 0f).ContractedBy(-12f * ColonistBar.Scale); + } + + public void DrawGroupFrame(int group) + { + Rect position = GroupFrameRect(group); + Map map = ColonistBar.Entries.Find((ColonistBar.Entry x) => x.group == group).map; + float num = ((map == null) ? ((!WorldRendererUtility.WorldSelected) ? 0.75f : 1f) : ((map == Find.CurrentMap && !WorldRendererUtility.WorldSelected) ? 1f : 0.75f)); + Widgets.DrawRectFast(position, new Color(0.5f, 0.5f, 0.5f, 0.4f * num)); + } + + private void ApplyEntryInAnotherMapAlphaFactor(Map map, ref float alpha) + { + if (map == null) + { + if (!WorldRendererUtility.WorldSelected) + { + alpha = Mathf.Min(alpha, 0.4f); + } + } + else if (map != Find.CurrentMap || WorldRendererUtility.WorldSelected) + { + alpha = Mathf.Min(alpha, 0.4f); + } + } + + public void HandleClicks(Rect rect, Pawn colonist, int reorderableGroup, out bool reordering) + { + if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && Event.current.clickCount == 2 && Mouse.IsOver(rect)) + { + Event.current.Use(); + CameraJumper.TryJump(colonist); + } + reordering = ReorderableWidget.Reorderable(reorderableGroup, rect, useRightButton: true); + if (Event.current.type == EventType.MouseDown && Event.current.button == 1 && Mouse.IsOver(rect)) + { + Event.current.Use(); + } + } + + public void HandleGroupFrameClicks(int group) + { + Rect rect = GroupFrameRect(group); + if (Event.current.type == EventType.MouseUp && Event.current.button == 0 && Mouse.IsOver(rect) && !ColonistBar.AnyColonistOrCorpseAt(UI.MousePositionOnUIInverted)) + { + bool worldSelected = WorldRendererUtility.WorldSelected; + if ((!worldSelected && !Find.Selector.dragBox.IsValidAndActive) || (worldSelected && !Find.WorldSelector.dragBox.IsValidAndActive)) + { + Find.Selector.dragBox.active = false; + Find.WorldSelector.dragBox.active = false; + ColonistBar.Entry entry = ColonistBar.Entries.Find((ColonistBar.Entry x) => x.group == group); + Map map = entry.map; + if (map == null) + { + if (WorldRendererUtility.WorldSelected) + { + CameraJumper.TrySelect(entry.pawn); + } + else + { + CameraJumper.TryJumpAndSelect(entry.pawn); + } + } + else + { + if (!CameraJumper.TryHideWorld() && Find.CurrentMap != map) + { + SoundDefOf.MapSelected.PlayOneShotOnCamera(); + } + Current.Game.CurrentMap = map; + } + } + } + if (Event.current.type == EventType.MouseDown && Event.current.button == 1 && Mouse.IsOver(rect)) + { + Event.current.Use(); + } + } + + public void Notify_RecachedEntries() + { + pawnLabelsCache.Clear(); + } + + public void ClearLabelCache() + { + pawnLabelsCache.Clear(); + } + + public Rect GetPawnTextureRect(Vector2 pos) + { + float x = pos.x; + float y = pos.y; + Vector2 vector = PawnTextureSize * ColonistBar.Scale; + return new Rect(x + 1f, y - (vector.y - ColonistBar.Size.y) - 1f, vector.x, vector.y).ContractedBy(1f); + } + + private void DrawIcons(Rect rect, Pawn colonist) + { + if (colonist.Dead) + { + return; + } + tmpIconsToDraw.Clear(); + bool flag = false; + if (colonist.CurJob != null) + { + JobDef def = colonist.CurJob.def; + if (def == JobDefOf.AttackMelee || def == JobDefOf.AttackStatic) + { + flag = true; + } + else if (def == JobDefOf.Wait_Combat && colonist.stances.curStance is Stance_Busy stance_Busy && stance_Busy.focusTarg.IsValid) + { + flag = true; + } + } + if (colonist.IsFormingCaravan()) + { + tmpIconsToDraw.Add(new IconDrawCall(Icon_FormingCaravan, "ActivityIconFormingCaravan".Translate())); + } + if (colonist.InAggroMentalState) + { + tmpIconsToDraw.Add(new IconDrawCall(Icon_MentalStateAggro, colonist.MentalStateDef.LabelCap)); + } + else if (colonist.InMentalState) + { + tmpIconsToDraw.Add(new IconDrawCall(Icon_MentalStateNonAggro, colonist.MentalStateDef.LabelCap)); + } + else if (colonist.InBed() && colonist.CurrentBed().Medical) + { + tmpIconsToDraw.Add(new IconDrawCall(Icon_MedicalRest, "ActivityIconMedicalRest".Translate())); + } + else + { + if (colonist.CurJob != null && colonist.jobs.curDriver.asleep) + { + goto IL_01c5; + } + if (colonist.GetCaravan() != null) + { + Pawn_NeedsTracker needs = colonist.needs; + if (needs != null && needs.rest?.Resting == true) + { + goto IL_01c5; + } + } + if (colonist.CurJob != null && colonist.CurJob.def == JobDefOf.FleeAndCower) + { + tmpIconsToDraw.Add(new IconDrawCall(Icon_Fleeing, "ActivityIconFleeing".Translate())); + } + else if (flag) + { + tmpIconsToDraw.Add(new IconDrawCall(Icon_Attacking, "ActivityIconAttacking".Translate())); + } + else if (colonist.mindState.IsIdle && GenDate.DaysPassed >= 1) + { + tmpIconsToDraw.Add(new IconDrawCall(Icon_Idle, "ActivityIconIdle".Translate())); + } + } + goto IL_02b4; + IL_01c5: + tmpIconsToDraw.Add(new IconDrawCall(Icon_Sleeping, "ActivityIconSleeping".Translate())); + goto IL_02b4; + IL_02b4: + if (colonist.IsBurning()) + { + tmpIconsToDraw.Add(new IconDrawCall(Icon_Burning, "ActivityIconBurning".Translate())); + } + if (colonist.Inspired) + { + tmpIconsToDraw.Add(new IconDrawCall(Icon_Inspired, colonist.InspirationDef.LabelCap)); + } + if (colonist.IsSlaveOfColony) + { + tmpIconsToDraw.Add(new IconDrawCall(colonist.guest.GetIcon())); + } + else + { + bool flag2 = false; + if (colonist.Ideo != null) + { + Ideo ideo = colonist.Ideo; + Precept_Role role = ideo.GetRole(colonist); + if (role != null) + { + tmpIconsToDraw.Add(new IconDrawCall(role.Icon, null, ideo.Color)); + flag2 = true; + } + } + if (!flag2) + { + Faction faction = null; + if (colonist.HasExtraMiniFaction()) + { + faction = colonist.GetExtraMiniFaction(); + } + else if (colonist.HasExtraHomeFaction()) + { + faction = colonist.GetExtraHomeFaction(); + } + if (faction != null) + { + tmpIconsToDraw.Add(new IconDrawCall(faction.def.FactionIcon, null, faction.Color)); + } + } + } + float num = Mathf.Min(BaseIconAreaWidth / (float)tmpIconsToDraw.Count, BaseIconMaxSize) * ColonistBar.Scale; + Vector2 pos = new Vector2(rect.x + 1f, rect.yMax - num - 1f); + foreach (IconDrawCall item in tmpIconsToDraw) + { + GUI.color = item.color ?? Color.white; + DrawIcon(item.texture, ref pos, num, item.tooltip); + GUI.color = Color.white; + } + } + + private void DrawIcon(Texture2D icon, ref Vector2 pos, float iconSize, string tooltip = null) + { + Rect rect = new Rect(pos.x, pos.y, iconSize, iconSize); + GUI.DrawTexture(rect, icon); + if (tooltip != null) + { + TooltipHandler.TipRegion(rect, tooltip); + } + pos.x += iconSize; + } + + private void DrawSelectionOverlayOnGUI(Pawn colonist, Rect rect) + { + Thing target = colonist; + if (colonist.Dead) + { + target = colonist.Corpse; + } + SelectionDrawerUtility.DrawSelectionOverlayOnGUI(target, rect, 0.4f * ColonistBar.Scale, 20f * ColonistBar.Scale); + } + + private void DrawCaravanSelectionOverlayOnGUI(Caravan caravan, Rect rect) + { + SelectionDrawerUtility.DrawSelectionOverlayOnGUI(caravan, rect, 0.4f * ColonistBar.Scale, 20f * ColonistBar.Scale); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\ColonistBar.txt` +**相似度:** 0.7704 + +```csharp +public class ColonistBar +{ + public struct Entry + { + public Pawn pawn; + + public Map map; + + public int group; + + public Action reorderAction; + + public Action extraDraggedItemOnGUI; + + public Entry(Pawn pawn, Map map, int group) + { + this.pawn = pawn; + this.map = map; + this.group = group; + reorderAction = delegate(int from, int to) + { + Find.ColonistBar.Reorder(from, to, group); + }; + extraDraggedItemOnGUI = delegate(int index, Vector2 dragStartPos) + { + Find.ColonistBar.DrawColonistMouseAttachment(index, dragStartPos, group); + }; + } + } + + public ColonistBarColonistDrawer drawer = new ColonistBarColonistDrawer(); + + private ColonistBarDrawLocsFinder drawLocsFinder = new ColonistBarDrawLocsFinder(); + + private List cachedEntries = new List(); + + private List cachedDrawLocs = new List(); + + private List cachedReorderableGroups = new List(); + + private float cachedScale = 1f; + + private bool entriesDirty = true; + + private List colonistsToHighlight = new List(); + + public static readonly Texture2D BGTex = Command.BGTex; + + public static readonly Vector2 BaseSize = new Vector2(48f, 48f); + + public const float BaseSelectedTexJump = 20f; + + public const float BaseSelectedTexScale = 0.4f; + + public const float EntryInAnotherMapAlpha = 0.4f; + + public const float BaseSpaceBetweenGroups = 25f; + + public const float BaseSpaceBetweenColonistsHorizontal = 24f; + + public const float BaseSpaceBetweenColonistsVertical = 32f; + + private const float WeaponIconOffsetScaleFactor = 1.05f; + + private const float WeaponIconScaleFactor = 0.75f; + + private static List tmpPawns = new List(); + + private static List tmpMaps = new List(); + + private static List tmpCaravans = new List(); + + private static List tmpColonistsInOrder = new List(); + + private static List> tmpColonistsWithMap = new List>(); + + private static List tmpColonists = new List(); + + private static List tmpMapColonistsOrCorpsesInScreenRect = new List(); + + private static List tmpCaravanPawns = new List(); + + public List Entries + { + get + { + CheckRecacheEntries(); + return cachedEntries; + } + } + + private bool ShowGroupFrames + { + get + { + List entries = Entries; + int num = -1; + for (int i = 0; i < entries.Count; i++) + { + num = Mathf.Max(num, entries[i].group); + } + return num >= 1; + } + } + + public float Scale => cachedScale; + + public List DrawLocs => cachedDrawLocs; + + public Vector2 Size => BaseSize * Scale; + + public float SpaceBetweenColonistsHorizontal => 24f * Scale; + + private bool Visible + { + get + { + if (UI.screenWidth < 800 || UI.screenHeight < 500) + { + return false; + } + if (Find.TilePicker.Active) + { + return false; + } + return true; + } + } + + public void MarkColonistsDirty() + { + entriesDirty = true; + } + + public void ColonistBarOnGUI() + { + if (!Visible) + { + return; + } + if (Event.current.type != EventType.Layout) + { + List entries = Entries; + int num = -1; + bool showGroupFrames = ShowGroupFrames; + int value = -1; + for (int i = 0; i < cachedDrawLocs.Count; i++) + { + Rect rect = new Rect(cachedDrawLocs[i].x, cachedDrawLocs[i].y, Size.x, Size.y); + Entry entry = entries[i]; + bool flag = num != entry.group; + num = entry.group; + if (Event.current.type == EventType.Repaint) + { + if (flag) + { + value = ReorderableWidget.NewGroup(entry.reorderAction, ReorderableDirection.Horizontal, new Rect(0f, 0f, UI.screenWidth, UI.screenHeight), SpaceBetweenColonistsHorizontal, entry.extraDraggedItemOnGUI); + } + cachedReorderableGroups[i] = value; + } + bool reordering; + if (entry.pawn != null) + { + drawer.HandleClicks(rect, entry.pawn, cachedReorderableGroups[i], out reordering); + } + else + { + reordering = false; + } + if (Event.current.type != EventType.Repaint) + { + continue; + } + if (flag && showGroupFrames) + { + drawer.DrawGroupFrame(entry.group); + } + if (entry.pawn != null) + { + drawer.DrawColonist(rect, entry.pawn, entry.map, colonistsToHighlight.Contains(entry.pawn), reordering); + ThingWithComps thingWithComps = entry.pawn.equipment?.Primary; + if ((Prefs.ShowWeaponsUnderPortraitMode == ShowWeaponsUnderPortraitMode.Always || (Prefs.ShowWeaponsUnderPortraitMode == ShowWeaponsUnderPortraitMode.WhileDrafted && entry.pawn.Drafted)) && thingWithComps != null && thingWithComps.def.IsWeapon) + { + Widgets.ThingIcon(new Rect(rect.x, rect.y + rect.height * 1.05f, rect.width, rect.height).ScaledBy(0.75f), thingWithComps, 1f, null, stackOfOne: true); + } + } + } + num = -1; + if (showGroupFrames) + { + for (int j = 0; j < cachedDrawLocs.Count; j++) + { + Entry entry2 = entries[j]; + bool num2 = num != entry2.group; + num = entry2.group; + if (num2) + { + drawer.HandleGroupFrameClicks(entry2.group); + } + } + } + } + if (Event.current.type == EventType.Repaint) + { + colonistsToHighlight.Clear(); + } + } + + private void CheckRecacheEntries() + { + if (!entriesDirty) + { + return; + } + entriesDirty = false; + cachedEntries.Clear(); + int num = 0; + if (Find.PlaySettings.showColonistBar) + { + tmpMaps.Clear(); + tmpMaps.AddRange(Find.Maps); + tmpMaps.SortBy((Map x) => !x.IsPlayerHome, (Map x) => x.uniqueID); + for (int i = 0; i < tmpMaps.Count; i++) + { + tmpPawns.Clear(); + tmpPawns.AddRange(tmpMaps[i].mapPawns.FreeColonists); + tmpPawns.AddRange(tmpMaps[i].mapPawns.ColonySubhumansControllable); + List list = tmpMaps[i].listerThings.ThingsInGroup(ThingRequestGroup.Corpse); + for (int j = 0; j < list.Count; j++) + { + if (!list[j].IsDessicated()) + { + Pawn innerPawn = ((Corpse)list[j]).InnerPawn; + if (innerPawn != null && innerPawn.IsColonist) + { + tmpPawns.Add(innerPawn); + } + } + } + IReadOnlyList allPawnsSpawned = tmpMaps[i].mapPawns.AllPawnsSpawned; + for (int k = 0; k < allPawnsSpawned.Count; k++) + { + if (allPawnsSpawned[k].carryTracker.CarriedThing is Corpse corpse && !corpse.IsDessicated() && corpse.InnerPawn.IsColonist) + { + tmpPawns.Add(corpse.InnerPawn); + } + } + foreach (Pawn tmpPawn in tmpPawns) + { + if (tmpPawn.playerSettings.displayOrder == -9999999) + { + tmpPawn.playerSettings.displayOrder = Mathf.Max(tmpPawns.MaxBy((Pawn p) => p.playerSettings.displayOrder).playerSettings.displayOrder, 0) + 1; + } + } + PlayerPawnsDisplayOrderUtility.Sort(tmpPawns); + foreach (Pawn tmpPawn2 in tmpPawns) + { + cachedEntries.Add(new Entry(tmpPawn2, tmpMaps[i], num)); + } + if (!tmpPawns.Any()) + { + cachedEntries.Add(new Entry(null, tmpMaps[i], num)); + } + num++; + } + tmpCaravans.Clear(); + tmpCaravans.AddRange(Find.WorldObjects.Caravans); + tmpCaravans.SortBy((Caravan x) => x.ID); + for (int l = 0; l < tmpCaravans.Count; l++) + { + if (!tmpCaravans[l].IsPlayerControlled) + { + continue; + } + tmpPawns.Clear(); + tmpPawns.AddRange(tmpCaravans[l].PawnsListForReading); + PlayerPawnsDisplayOrderUtility.Sort(tmpPawns); + for (int m = 0; m < tmpPawns.Count; m++) + { + if (tmpPawns[m].IsColonist || tmpPawns[m].IsColonySubhumanPlayerControlled) + { + cachedEntries.Add(new Entry(tmpPawns[m], null, num)); + } + } + num++; + } + } + cachedReorderableGroups.Clear(); + foreach (Entry cachedEntry in cachedEntries) + { + _ = cachedEntry; + cachedReorderableGroups.Add(-1); + } + drawer.Notify_RecachedEntries(); + tmpPawns.Clear(); + tmpMaps.Clear(); + tmpCaravans.Clear(); + drawLocsFinder.CalculateDrawLocs(cachedDrawLocs, out cachedScale, num); + } + + public float GetEntryRectAlpha(Rect rect) + { + if (Messages.CollidesWithAnyMessage(rect, out var messageAlpha)) + { + return Mathf.Lerp(1f, 0.2f, messageAlpha); + } + return 1f; + } + + public void Highlight(Pawn pawn) + { + if (Visible && !colonistsToHighlight.Contains(pawn)) + { + colonistsToHighlight.Add(pawn); + } + } + + public void Reorder(int from, int to, int entryGroup) + { + int num = 0; + Pawn pawn = null; + Pawn pawn2 = null; + Pawn pawn3 = null; + for (int i = 0; i < cachedEntries.Count; i++) + { + if (cachedEntries[i].group == entryGroup && cachedEntries[i].pawn != null) + { + if (num == from) + { + pawn = cachedEntries[i].pawn; + } + if (num == to) + { + pawn2 = cachedEntries[i].pawn; + } + pawn3 = cachedEntries[i].pawn; + num++; + } + } + if (pawn == null) + { + return; + } + int num2 = pawn2?.playerSettings.displayOrder ?? (pawn3.playerSettings.displayOrder + 1); + for (int j = 0; j < cachedEntries.Count; j++) + { + Pawn pawn4 = cachedEntries[j].pawn; + if (pawn4 == null) + { + continue; + } + if (pawn4.playerSettings.displayOrder == num2) + { + if (pawn2 != null && cachedEntries[j].group == entryGroup) + { + pawn4.playerSettings.displayOrder++; + } + } + else if (pawn4.playerSettings.displayOrder > num2) + { + pawn4.playerSettings.displayOrder++; + } + else + { + pawn4.playerSettings.displayOrder--; + } + } + pawn.playerSettings.displayOrder = num2; + MarkColonistsDirty(); + MainTabWindowUtility.NotifyAllPawnTables_PawnsChanged(); + } + + public void DrawColonistMouseAttachment(int index, Vector2 dragStartPos, int entryGroup) + { + Pawn pawn = null; + Vector2 vector = default(Vector2); + int num = 0; + for (int i = 0; i < cachedEntries.Count; i++) + { + if (cachedEntries[i].group == entryGroup && cachedEntries[i].pawn != null) + { + if (num == index) + { + pawn = cachedEntries[i].pawn; + vector = cachedDrawLocs[i]; + break; + } + num++; + } + } + if (pawn != null) + { + RenderTexture iconTex = PortraitsCache.Get(pawn, ColonistBarColonistDrawer.PawnTextureSize, Rot4.South, ColonistBarColonistDrawer.PawnTextureCameraOffset, 1.28205f); + Rect rect = new Rect(vector.x, vector.y, Size.x, Size.y); + Rect pawnTextureRect = drawer.GetPawnTextureRect(rect.position); + pawnTextureRect.position += Event.current.mousePosition - dragStartPos; + Rect? customRect = pawnTextureRect; + GenUI.DrawMouseAttachment(iconTex, "", 0f, default(Vector2), customRect); + } + } + + public bool AnyColonistOrCorpseAt(Vector2 pos) + { + if (!TryGetEntryAt(pos, out var entry)) + { + return false; + } + return entry.pawn != null; + } + + public bool TryGetEntryAt(Vector2 pos, out Entry entry) + { + List drawLocs = DrawLocs; + List entries = Entries; + Vector2 size = Size; + for (int i = 0; i < drawLocs.Count; i++) + { + if (new Rect(drawLocs[i].x, drawLocs[i].y, size.x, size.y).Contains(pos)) + { + entry = entries[i]; + return true; + } + } + entry = default(Entry); + return false; + } + + public List GetColonistsInOrder() + { + List entries = Entries; + tmpColonistsInOrder.Clear(); + for (int i = 0; i < entries.Count; i++) + { + if (entries[i].pawn != null) + { + tmpColonistsInOrder.Add(entries[i].pawn); + } + } + return tmpColonistsInOrder; + } + + public List ColonistsOrCorpsesInScreenRect(Rect rect) + { + List drawLocs = DrawLocs; + List entries = Entries; + Vector2 size = Size; + tmpColonistsWithMap.Clear(); + for (int i = 0; i < drawLocs.Count; i++) + { + if (rect.Overlaps(new Rect(drawLocs[i].x, drawLocs[i].y, size.x, size.y))) + { + Pawn pawn = entries[i].pawn; + if (pawn != null) + { + Thing first = ((!pawn.Dead || pawn.Corpse == null || !pawn.Corpse.SpawnedOrAnyParentSpawned) ? ((Thing)pawn) : ((Thing)pawn.Corpse)); + tmpColonistsWithMap.Add(new Pair(first, entries[i].map)); + } + } + } + if (WorldRendererUtility.WorldSelected && tmpColonistsWithMap.Any((Pair x) => x.Second == null)) + { + tmpColonistsWithMap.RemoveAll((Pair x) => x.Second != null); + } + else if (tmpColonistsWithMap.Any((Pair x) => x.Second == Find.CurrentMap)) + { + tmpColonistsWithMap.RemoveAll((Pair x) => x.Second != Find.CurrentMap); + } + tmpColonists.Clear(); + for (int j = 0; j < tmpColonistsWithMap.Count; j++) + { + tmpColonists.Add(tmpColonistsWithMap[j].First); + } + tmpColonistsWithMap.Clear(); + return tmpColonists; + } + + public List MapColonistsOrCorpsesInScreenRect(Rect rect) + { + tmpMapColonistsOrCorpsesInScreenRect.Clear(); + if (!Visible) + { + return tmpMapColonistsOrCorpsesInScreenRect; + } + List list = ColonistsOrCorpsesInScreenRect(rect); + for (int i = 0; i < list.Count; i++) + { + if (list[i].Spawned) + { + tmpMapColonistsOrCorpsesInScreenRect.Add(list[i]); + } + } + return tmpMapColonistsOrCorpsesInScreenRect; + } + + public List CaravanMembersInScreenRect(Rect rect) + { + tmpCaravanPawns.Clear(); + if (!Visible) + { + return tmpCaravanPawns; + } + List list = ColonistsOrCorpsesInScreenRect(rect); + for (int i = 0; i < list.Count; i++) + { + if (list[i] is Pawn pawn && pawn.IsCaravanMember()) + { + tmpCaravanPawns.Add(pawn); + } + } + return tmpCaravanPawns; + } + + public List CaravanMembersCaravansInScreenRect(Rect rect) + { + tmpCaravans.Clear(); + if (!Visible) + { + return tmpCaravans; + } + List list = CaravanMembersInScreenRect(rect); + for (int i = 0; i < list.Count; i++) + { + tmpCaravans.Add(list[i].GetCaravan()); + } + return tmpCaravans; + } + + public Caravan CaravanMemberCaravanAt(Vector2 at) + { + if (!Visible) + { + return null; + } + if (ColonistOrCorpseAt(at) is Pawn pawn && pawn.IsCaravanMember()) + { + return pawn.GetCaravan(); + } + return null; + } + + public Thing ColonistOrCorpseAt(Vector2 pos) + { + if (!Visible) + { + return null; + } + if (!TryGetEntryAt(pos, out var entry)) + { + return null; + } + Pawn pawn = entry.pawn; + if (pawn != null && pawn.Dead && pawn.Corpse != null && pawn.Corpse.SpawnedOrAnyParentSpawned) + { + return pawn.Corpse; + } + return pawn; + } +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/CompBiosculpterPod-CompProperties_BiosculpterPod.txt b/MCP/vector_cache/CompBiosculpterPod-CompProperties_BiosculpterPod.txt new file mode 100644 index 00000000..d14fb0bc --- /dev/null +++ b/MCP/vector_cache/CompBiosculpterPod-CompProperties_BiosculpterPod.txt @@ -0,0 +1,1485 @@ +根据向量相似度分析,与 'CompProperties_BiosculpterPod, CompBiosculpterPod' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_BiosculpterPod.txt` + +```csharp +public class CompProperties_BiosculpterPod : CompProperties +{ + public SoundDef enterSound; + + public SoundDef exitSound; + + public EffecterDef operatingEffecter; + + public EffecterDef readyEffecter; + + public Color selectCycleColor; + + public float biotunedCycleSpeedFactor; + + public CompProperties_BiosculpterPod() + { + compClass = typeof(CompBiosculpterPod); + } + + public override IEnumerable ConfigErrors(ThingDef parentDef) + { + foreach (string item in base.ConfigErrors(parentDef)) + { + yield return item; + } + if (parentDef.tickerType != TickerType.Normal) + { + yield return GetType().Name + " requires parent ticker type Normal"; + } + } +} +``` +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompBiosculpterPod.txt` + +```csharp +public class CompBiosculpterPod : ThingComp, ISuspendableThingHolder, IThingHolder, IThingHolderWithDrawnPawn, IStoreSettingsParent, INotifyHauledTo, ISearchableContents +{ + private const int NoPowerEjectCumulativeTicks = 60000; + + private const int BiotunedDuration = 4800000; + + private const float NutritionRequired = 5f; + + private const float CacheForSecs = 2f; + + private static readonly Texture2D InterruptCycleIcon = ContentFinder.Get("UI/Designators/Cancel"); + + private static readonly Material BackgroundMat = SolidColorMaterials.NewSolidColorMaterial(new Color(0.082f, 0.078f, 0.063f), ShaderDatabase.SolidColorBehind); + + private const float BackgroundRect_YOff = 0.07317074f; + + private const float Pawn_YOff = 0.03658537f; + + private string currentCycleKey; + + private float currentCycleTicksRemaining; + + private int currentCyclePowerCutTicks; + + private ThingOwner innerContainer; + + private Pawn biotunedTo; + + private int biotunedCountdownTicks; + + private StorageSettings allowedNutritionSettings; + + private float liquifiedNutrition; + + public bool autoLoadNutrition = true; + + public bool devFillPodLatch; + + private bool autoAgeReversal; + + private int tickEntered = -99999; + + public Job queuedEnterJob; + + public Pawn queuedPawn; + + private List chosenExtraItems = new List(); + + private List cycleEligiblePawnOptions = new List(); + + private Pawn pawnEnteringBiosculpter; + + private Dictionary> cachedExtraIngredients = new Dictionary>(); + + private Dictionary cachedAnyPawnEligible = new Dictionary(); + + private static Dictionary> cachedBiotunedPods = new Dictionary>(); + + private Pawn cacheReachIngredientsPawn; + + private CompBiosculpterPod_Cycle cacheReachIngredientsCycle; + + private float cacheReachIngredientsTime = float.MinValue; + + private bool cacheReachIngredientsResult; + + private Effecter progressBarEffecter; + + private Effecter operatingEffecter; + + private Effecter readyEffecter; + + private Texture2D cachedAutoAgeReverseIcon; + + private List cachedAvailableCycles; + + private Dictionary cycleLookup; + + private static string cachedAgeReversalCycleKey = null; + + private List tmpIngredientsStrings = new List(); + + private static readonly List tmpItems = new List(); + + private CompPowerTrader powerTraderComp; + + private CompPower powerComp; + + private static List cachedPodDefs; + + public CompProperties_BiosculpterPod Props => props as CompProperties_BiosculpterPod; + + public ThingOwner SearchableContents => innerContainer; + + public bool IsContentsSuspended => true; + + public float RequiredNutritionRemaining => Mathf.Max(5f - liquifiedNutrition, 0f); + + public bool NutritionLoaded => RequiredNutritionRemaining <= 0f; + + public bool AutoAgeReversal => autoAgeReversal; + + private Texture2D AutoAgeReversalIcon + { + get + { + if (cachedAutoAgeReverseIcon == null) + { + cachedAutoAgeReverseIcon = ContentFinder.Get("UI/Gizmos/BiosculpterAutoAgeReversal"); + } + return cachedAutoAgeReverseIcon; + } + } + + public BiosculpterPodState State + { + get + { + if (Occupant != null) + { + return BiosculpterPodState.Occupied; + } + if (NutritionLoaded) + { + return BiosculpterPodState.SelectingCycle; + } + return BiosculpterPodState.LoadingNutrition; + } + } + + public Pawn Occupant + { + get + { + if (pawnEnteringBiosculpter != null) + { + return pawnEnteringBiosculpter; + } + if (currentCycleKey == null) + { + return null; + } + if (innerContainer.Count != 1) + { + return null; + } + return innerContainer[0] as Pawn; + } + } + + public CompBiosculpterPod_Cycle CurrentCycle + { + get + { + if (currentCycleKey == null) + { + return null; + } + foreach (CompBiosculpterPod_Cycle availableCycle in AvailableCycles) + { + if (availableCycle.Props.key == currentCycleKey) + { + return availableCycle; + } + } + return null; + } + } + + public List AvailableCycles + { + get + { + if (cachedAvailableCycles == null) + { + SetupCycleCaches(); + } + return cachedAvailableCycles; + } + } + + public string AgeReversalCycleKey + { + get + { + if (cachedAgeReversalCycleKey == null) + { + SetupCycleCaches(); + } + return cachedAgeReversalCycleKey; + } + } + + private float CycleSpeedFactorNoPawn => CleanlinessSpeedFactor * BiotunedSpeedFactor; + + public float CycleSpeedFactor + { + get + { + if (Occupant == null) + { + return Mathf.Max(0.1f, CycleSpeedFactorNoPawn); + } + return GetCycleSpeedFactorForPawn(Occupant); + } + } + + private float CleanlinessSpeedFactor => parent.GetStatValue(StatDefOf.BiosculpterPodSpeedFactor); + + private float BiotunedSpeedFactor + { + get + { + if (biotunedTo == null) + { + return 1f; + } + return Props.biotunedCycleSpeedFactor; + } + } + + public bool PowerOn => parent.TryGetComp().PowerOn; + + public float HeldPawnDrawPos_Y => parent.DrawPos.y - 0.03658537f; + + public float HeldPawnBodyAngle => parent.Rotation.Opposite.AsAngle; + + public PawnPosture HeldPawnPosture => PawnPosture.LayingOnGroundFaceUp; + + public bool StorageTabVisible => true; + + public CompBiosculpterPod() + { + innerContainer = new ThingOwner(this); + } + + public override void Initialize(CompProperties props) + { + base.Initialize(props); + allowedNutritionSettings = new StorageSettings(this); + if (parent.def.building.defaultStorageSettings != null) + { + allowedNutritionSettings.CopyFrom(parent.def.building.defaultStorageSettings); + } + } + + public override void PostSpawnSetup(bool respawningAfterLoad) + { + if (ModLister.CheckIdeology("Biosculpter pod comp")) + { + base.PostSpawnSetup(respawningAfterLoad); + } + } + + public override void PostExposeData() + { + base.PostExposeData(); + Scribe_Deep.Look(ref innerContainer, "innerContainer", this); + Scribe_Values.Look(ref currentCycleKey, "currentCycleKey"); + Scribe_Values.Look(ref currentCycleTicksRemaining, "currentCycleTicksRemaining", 0f); + Scribe_Values.Look(ref currentCyclePowerCutTicks, "currentCyclePowerCutTicks", 0); + Scribe_References.Look(ref biotunedTo, "biotunedTo"); + Scribe_Values.Look(ref biotunedCountdownTicks, "biotunedCountdownTicks", 0); + Scribe_Deep.Look(ref allowedNutritionSettings, "allowedNutritionSettings"); + Scribe_Values.Look(ref liquifiedNutrition, "liquifiedNutrition", 0f); + Scribe_Values.Look(ref autoLoadNutrition, "autoLoadNutrition", defaultValue: false); + Scribe_Values.Look(ref devFillPodLatch, "devFillPodLatch", defaultValue: false); + Scribe_Values.Look(ref autoAgeReversal, "autoAgeReversal", defaultValue: false); + Scribe_Values.Look(ref tickEntered, "tickEntered", 0); + Scribe_References.Look(ref queuedEnterJob, "queuedEnterJob"); + Scribe_References.Look(ref queuedPawn, "queuedPawn"); + if (allowedNutritionSettings == null) + { + allowedNutritionSettings = new StorageSettings(this); + if (parent.def.building.defaultStorageSettings != null) + { + allowedNutritionSettings.CopyFrom(parent.def.building.defaultStorageSettings); + } + } + if (Scribe.mode == LoadSaveMode.PostLoadInit) + { + if (currentCycleKey == "healing") + { + currentCycleKey = "medic"; + } + if (biotunedTo != null) + { + SetBiotuned(biotunedTo); + } + LiquifyNutrition(); + } + } + + public CompBiosculpterPod_Cycle GetCycle(string key) + { + if (cycleLookup == null) + { + SetupCycleCaches(); + } + return cycleLookup[key]; + } + + public float GetCycleSpeedFactorForPawn(Pawn p) + { + return Mathf.Max(0.1f, CycleSpeedFactorNoPawn * p.GetStatValue(StatDefOf.BiosculpterOccupantSpeed)); + } + + private void SetupCycleCaches() + { + cachedAvailableCycles = new List(); + cachedAvailableCycles.AddRange(parent.AllComps.OfType()); + cycleLookup = new Dictionary(); + foreach (CompBiosculpterPod_Cycle cachedAvailableCycle in cachedAvailableCycles) + { + if (cachedAvailableCycle is CompBiosculpterPod_AgeReversalCycle compBiosculpterPod_AgeReversalCycle) + { + cachedAgeReversalCycleKey = compBiosculpterPod_AgeReversalCycle.Props.key; + } + cycleLookup[cachedAvailableCycle.Props.key] = cachedAvailableCycle; + } + } + + public void SetBiotuned(Pawn newBiotunedTo) + { + if (newBiotunedTo != biotunedTo) + { + autoAgeReversal = false; + } + if (biotunedTo != null && cachedBiotunedPods.ContainsKey(biotunedTo)) + { + cachedBiotunedPods[biotunedTo].Remove(this); + } + if (newBiotunedTo != null && !cachedBiotunedPods.ContainsKey(newBiotunedTo)) + { + cachedBiotunedPods[newBiotunedTo] = new List(); + } + if (newBiotunedTo != null && !cachedBiotunedPods[newBiotunedTo].Contains(this)) + { + cachedBiotunedPods[newBiotunedTo].Add(this); + } + if (newBiotunedTo != null && newBiotunedTo != biotunedTo) + { + biotunedCountdownTicks = 4800000; + } + biotunedTo = newBiotunedTo; + } + + public override void PostDestroy(DestroyMode mode, Map previousMap) + { + SetBiotuned(null); + if (mode == DestroyMode.Deconstruct || mode == DestroyMode.KillFinalize) + { + EjectContents(interrupted: true, playSounds: false, previousMap); + } + innerContainer.ClearAndDestroyContents(); + base.PostDestroy(mode, previousMap); + } + + public override void PostDeSpawn(Map map, DestroyMode mode = DestroyMode.Vanish) + { + if (mode != DestroyMode.WillReplace) + { + EjectContents(interrupted: true, playSounds: false, map); + currentCycleKey = null; + } + progressBarEffecter?.Cleanup(); + progressBarEffecter = null; + operatingEffecter?.Cleanup(); + operatingEffecter = null; + readyEffecter?.Cleanup(); + readyEffecter = null; + } + + public override void DrawGUIOverlay() + { + base.DrawGUIOverlay(); + if (!Find.ScreenshotModeHandler.Active && (biotunedTo != null || Occupant != null)) + { + GenMapUI.DrawThingLabel(parent, biotunedTo?.LabelShort ?? Occupant.LabelShort, GenMapUI.DefaultThingLabelColor); + } + } + + public override string CompInspectStringExtra() + { + StringBuilder stringBuilder = new StringBuilder(); + BiosculpterPodState state = State; + if (parent.Spawned) + { + CompBiosculpterPod_Cycle currentCycle = CurrentCycle; + if (currentCycle != null) + { + stringBuilder.AppendLineIfNotEmpty().Append("BiosculpterPodCycleLabel".Translate()).Append(": ") + .Append(currentCycle.Props.LabelCap); + if (biotunedTo == null) + { + stringBuilder.Append(" " + "BiosculpterPodCycleWillBiotune".Translate()); + } + } + else if (state == BiosculpterPodState.SelectingCycle) + { + if (PowerOn) + { + if (queuedEnterJob != null && !queuedEnterJob.biosculpterCycleKey.NullOrEmpty()) + { + stringBuilder.Append("BiosculpterPodCycleStandby".Translate(GetCycle(queuedEnterJob.biosculpterCycleKey).Props.label.Named("CYCLE"), queuedPawn.Named("PAWN"))); + } + else + { + stringBuilder.Append("BiosculpterPodCycleSelection".Translate().CapitalizeFirst()); + } + } + else + { + stringBuilder.Append("BiosculpterPodCycleSelectionNoPower".Translate().CapitalizeFirst()); + } + } + if (state == BiosculpterPodState.LoadingNutrition) + { + stringBuilder.Append("BiosculpterPodCycleLabelLoading".Translate().CapitalizeFirst()); + stringBuilder.AppendLineIfNotEmpty().Append("Nutrition".Translate()).Append(": ") + .Append(liquifiedNutrition.ToStringByStyle(ToStringStyle.FloatMaxOne)) + .Append(" / ") + .Append(5f); + } + if (state == BiosculpterPodState.Occupied) + { + float num = currentCycleTicksRemaining / CycleSpeedFactor; + stringBuilder.AppendLineIfNotEmpty().Append("Contains".Translate()).Append(": ") + .Append(Occupant.NameShortColored.Resolve()); + if (!PowerOn) + { + stringBuilder.AppendLine().Append("BiosculpterCycleNoPowerInterrupt".Translate((60000 - currentCyclePowerCutTicks).ToStringTicksToPeriod().Named("TIME")).Colorize(ColorLibrary.RedReadable)); + } + stringBuilder.AppendLine().Append("BiosculpterCycleTimeRemaining".Translate()).Append(": ") + .Append(((int)num).ToStringTicksToPeriod().Colorize(ColoredText.DateTimeColor)); + Ideo ideo = Occupant.Ideo; + if (ideo != null && ideo.HasPrecept(PreceptDefOf.Biosculpting_Accelerated)) + { + stringBuilder.Append(" (" + "BiosculpterCycleAccelerated".Translate() + ")"); + } + if (biotunedTo != null) + { + stringBuilder.AppendLine().Append("BiosculpterBiotunedSpeedFactor".Translate()).Append(": ") + .Append(BiotunedSpeedFactor.ToStringPercent()); + } + stringBuilder.AppendLine().Append("BiosculpterCleanlinessSpeedFactor".Translate()).Append(": ") + .Append(CleanlinessSpeedFactor.ToStringPercent()); + } + } + if (biotunedTo != null && state != BiosculpterPodState.Occupied) + { + stringBuilder.AppendLineIfNotEmpty().Append("BiosculpterBiotunedTo".Translate()).Append(": ") + .Append(biotunedTo.LabelShort) + .Append(" (") + .Append(biotunedCountdownTicks.ToStringTicksToPeriod()) + .Append(")"); + } + if (stringBuilder.Length <= 0) + { + return null; + } + return stringBuilder.ToString(); + } + + public override IEnumerable CompGetGizmosExtra() + { + BiosculpterPodState state = State; + string cycleIndependentCannotUseReason = CannotUseNowReason(); + foreach (CompBiosculpterPod_Cycle cycle in AvailableCycles) + { + string text = cycleIndependentCannotUseReason ?? CannotUseNowCycleReason(cycle); + Command_Action command_Action = new Command_Action(); + command_Action.defaultLabel = "BiosculpterPodCycleCommand".Translate(cycle.Props.label) + ((biotunedTo != null) ? (" (" + biotunedTo.LabelShort + ")") : ""); + command_Action.defaultDesc = CycleDescription(cycle); + command_Action.icon = cycle.Props.Icon; + command_Action.action = delegate + { + SelectPawnsForCycleOptions(cycle, out var options2); + if (biotunedTo != null && options2.Count > 0) + { + options2[0].action(); + if (!(cycle is CompBiosculpterPod_HealingCycle)) + { + Messages.Message("BiosculpterEnteringMessage".Translate(biotunedTo.Named("PAWN"), cycle.Props.label.Named("CYCLE")).CapitalizeFirst(), parent, MessageTypeDefOf.SilentInput, historical: false); + } + } + else + { + Find.WindowStack.Add(new FloatMenu(options2)); + } + }; + command_Action.activateSound = SoundDefOf.Tick_Tiny; + command_Action.Disabled = text != null; + List options; + if (text != null) + { + command_Action.Disable(text); + } + else if (!SelectPawnsForCycleOptions(cycle, out options, shortCircuit: true)) + { + command_Action.Disable((biotunedTo != null) ? "BiosculpterNoEligiblePawnsBiotuned".Translate(biotunedTo.Named("PAWN")) : "BiosculpterNoEligiblePawns".Translate()); + } + yield return command_Action; + } + if (state == BiosculpterPodState.Occupied) + { + Command_Action command_Action2 = new Command_Action(); + command_Action2.defaultLabel = "BiosculpterInteruptCycle".Translate(); + command_Action2.defaultDesc = "BiosculpterInteruptCycleDesc".Translate(); + command_Action2.icon = InterruptCycleIcon; + command_Action2.action = delegate + { + EjectContents(interrupted: true, playSounds: true); + }; + command_Action2.activateSound = SoundDefOf.Designate_Cancel; + yield return command_Action2; + } + Command_Toggle command_Toggle = new Command_Toggle(); + command_Toggle.defaultLabel = "BiosculpterAutoLoadNutritionLabel".Translate(); + command_Toggle.defaultDesc = "BiosculpterAutoLoadNutritionDescription".Translate(); + command_Toggle.icon = (autoLoadNutrition ? TexCommand.ForbidOff : TexCommand.ForbidOn); + command_Toggle.isActive = () => autoLoadNutrition; + command_Toggle.toggleAction = delegate + { + autoLoadNutrition = !autoLoadNutrition; + }; + yield return command_Toggle; + if ((biotunedTo?.Ideo?.HasPrecept(PreceptDefOf.AgeReversal_Demanded)).GetValueOrDefault()) + { + Command_Toggle command_Toggle2 = new Command_Toggle(); + command_Toggle2.defaultLabel = "BiosculpterAutoAgeReversalLabel".Translate(biotunedTo.Named("PAWN")); + TaggedString taggedString = ((biotunedTo.ageTracker.AgeReversalDemandedDeadlineTicks > 0) ? "BiosculpterAutoAgeReversalDescriptionFuture".Translate(biotunedTo.Named("PAWN"), ((int)biotunedTo.ageTracker.AgeReversalDemandedDeadlineTicks).ToStringTicksToPeriodVague().Named("TIME")) : "BiosculpterAutoAgeReversalDescriptionNow".Translate(biotunedTo.Named("PAWN"))); + command_Toggle2.defaultDesc = "BiosculpterAutoAgeReversalDescription".Translate(biotunedTo.Named("PAWN"), taggedString.Named("NEXTTREATMENT")); + command_Toggle2.icon = AutoAgeReversalIcon; + command_Toggle2.isActive = () => AutoAgeReversal; + command_Toggle2.toggleAction = delegate + { + autoAgeReversal = !autoAgeReversal; + }; + if (!CanAgeReverse(biotunedTo)) + { + command_Toggle2.Disable("UnderMinBiosculpterAgeReversalAge".Translate(biotunedTo.ageTracker.AdultMinAge.Named("ADULTAGE")).CapitalizeFirst()); + autoAgeReversal = false; + } + yield return command_Toggle2; + } + foreach (Gizmo item in StorageSettingsClipboard.CopyPasteGizmosFor(allowedNutritionSettings)) + { + yield return item; + } + Gizmo gizmo = Building.SelectContainedItemGizmo(parent, Occupant); + if (gizmo != null) + { + yield return gizmo; + } + if (DebugSettings.ShowDevGizmos) + { + yield return new Command_Action + { + defaultLabel = "DEV: complete cycle", + action = delegate + { + currentCycleTicksRemaining = 10f; + }, + Disabled = (State != BiosculpterPodState.Occupied) + }; + yield return new Command_Action + { + defaultLabel = "DEV: advance cycle +1 day", + action = delegate + { + currentCycleTicksRemaining -= 60000f; + }, + Disabled = (State != BiosculpterPodState.Occupied) + }; + yield return new Command_Action + { + defaultLabel = "DEV: complete biotune timer", + action = delegate + { + biotunedCountdownTicks = 10; + }, + Disabled = (biotunedCountdownTicks <= 0) + }; + yield return new Command_Action + { + defaultLabel = "DEV: fill nutrition and cycle ingredients", + action = delegate + { + liquifiedNutrition = 5f; + devFillPodLatch = true; + }, + Disabled = (State == BiosculpterPodState.Occupied || (devFillPodLatch && liquifiedNutrition == 5f)) + }; + } + } + + private string IngredientsDescription(CompBiosculpterPod_Cycle cycle) + { + tmpIngredientsStrings.Clear(); + if (!cycle.Props.extraRequiredIngredients.NullOrEmpty() && !devFillPodLatch) + { + for (int i = 0; i < cycle.Props.extraRequiredIngredients.Count; i++) + { + tmpIngredientsStrings.Add(cycle.Props.extraRequiredIngredients[i].Summary); + } + } + return tmpIngredientsStrings.ToCommaList(useAnd: true); + } + + private string CycleDescription(CompBiosculpterPod_Cycle cycle) + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.Append(cycle.Description(biotunedTo)); + float num = cycle.Props.durationDays / CycleSpeedFactor; + float num2 = num / PreceptDefOf.Biosculpting_Accelerated.biosculpterPodCycleSpeedFactor; + stringBuilder.AppendLine("\n\n" + "BiosculpterPodCycleDuration".Translate() + ": " + ((int)(num * 60000f)).ToStringTicksToDays()); + if (!Find.IdeoManager.classicMode) + { + stringBuilder.Append("BiosculpterPodCycleDurationTranshumanists".Translate() + ": " + ((int)(num2 * 60000f)).ToStringTicksToDays()); + } + return stringBuilder.ToString(); + } + + public bool PawnCanUseNow(Pawn pawn, CompBiosculpterPod_Cycle cycle) + { + return (CannotUseNowReason() ?? CannotUseNowPawnReason(pawn) ?? CannotUseNowCycleReason(cycle) ?? CannotUseNowPawnCycleReason(pawn, cycle)) == null; + } + + public override IEnumerable CompFloatMenuOptions(Pawn selPawn) + { + if (selPawn.IsQuestLodger()) + { + yield return new FloatMenuOption("CannotEnter".Translate() + ": " + "CryptosleepCasketGuestsNotAllowed".Translate().CapitalizeFirst(), null); + yield break; + } + string cycleIndependentfailureReason = CannotUseNowReason() ?? CannotUseNowPawnReason(selPawn); + foreach (CompBiosculpterPod_Cycle cycle in AvailableCycles) + { + string text = cycleIndependentfailureReason ?? CannotUseNowCycleReason(cycle) ?? CannotUseNowPawnCycleReason(selPawn, cycle); + if (text != null) + { + yield return new FloatMenuOption(CannotStartText(cycle, text), null); + continue; + } + string label = "EnterBiosculpterPod".Translate(cycle.Props.label, ((int)(cycle.Props.durationDays / GetCycleSpeedFactorForPawn(selPawn) * 60000f)).ToStringTicksToDays()); + yield return FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(label, delegate + { + PrepareCycleJob(selPawn, selPawn, cycle, EnterBiosculpterJob()); + }), selPawn, parent); + } + } + + public static bool CanAgeReverse(Pawn biosculptee) + { + return biosculptee.ageTracker.Adult; + } + + public static List BiotunedPods(Pawn pawn) + { + return cachedBiotunedPods.TryGetValue(pawn); + } + + public static bool HasBiotunedAutoAgeReversePod(Pawn pawn) + { + List list = cachedBiotunedPods.TryGetValue(pawn); + if (list == null) + { + return false; + } + foreach (CompBiosculpterPod item in list) + { + if (item.AutoAgeReversal) + { + return true; + } + } + return false; + } + + public static string CannotStartText(CompBiosculpterPod_Cycle cycle, string translatedReason) + { + return "BiosculpterCannotStartCycle".Translate(cycle.Props.label) + ": " + translatedReason.CapitalizeFirst(); + } + + public string CannotUseNowCycleReason(CompBiosculpterPod_Cycle cycle) + { + List list = cycle.MissingResearchLabels(); + if (list.Any()) + { + return "MissingRequiredResearch".Translate() + " " + list.ToCommaList(); + } + return null; + } + + public string CannotUseNowPawnCycleReason(Pawn p, CompBiosculpterPod_Cycle cycle, bool checkIngredients = true) + { + return CannotUseNowPawnCycleReason(p, p, cycle, checkIngredients); + } + + private bool CanReachOrHasIngredients(Pawn hauler, Pawn biosculptee, CompBiosculpterPod_Cycle cycle, bool useCache = false) + { + if (!PawnCarryingExtraCycleIngredients(biosculptee, cycle) && (biosculptee == hauler || !PawnCarryingExtraCycleIngredients(hauler, cycle))) + { + return CanReachRequiredIngredients(hauler, cycle, useCache); + } + return true; + } + + public string CannotUseNowPawnCycleReason(Pawn hauler, Pawn biosculptee, CompBiosculpterPod_Cycle cycle, bool checkIngredients = true) + { + if (AgeReversalCycleKey != null && cycle.Props.key == AgeReversalCycleKey && !CanAgeReverse(biosculptee)) + { + return "UnderMinBiosculpterAgeReversalAge".Translate(biosculptee.ageTracker.AdultMinAge.Named("ADULTAGE")).CapitalizeFirst(); + } + if (checkIngredients && !CanReachOrHasIngredients(hauler, biosculptee, cycle, useCache: true)) + { + return "BiosculpterMissingIngredients".Translate(IngredientsDescription(cycle).Named("INGREDIENTS")).CapitalizeFirst(); + } + return null; + } + + public string CannotUseNowPawnReason(Pawn p) + { + if (biotunedTo != null && biotunedTo != p) + { + return "BiosculpterBiotunedToAnother".Translate().CapitalizeFirst(); + } + if (!p.CanReach(parent, PathEndMode.InteractionCell, Danger.Deadly)) + { + return "NoPath".Translate().CapitalizeFirst(); + } + return null; + } + + public string CannotUseNowReason() + { + if (!PowerOn) + { + return "NoPower".Translate().CapitalizeFirst(); + } + if (State == BiosculpterPodState.LoadingNutrition) + { + return "BiosculpterNutritionNotLoaded".Translate().CapitalizeFirst(); + } + if (State == BiosculpterPodState.Occupied) + { + return "BiosculpterOccupied".Translate().CapitalizeFirst(); + } + return null; + } + + private List RequiredIngredients(CompBiosculpterPod_Cycle cycle) + { + List extraRequiredIngredients = cycle.Props.extraRequiredIngredients; + if (extraRequiredIngredients == null || devFillPodLatch) + { + return null; + } + if (!cachedExtraIngredients.ContainsKey(cycle)) + { + cachedExtraIngredients[cycle] = extraRequiredIngredients.Select((ThingDefCountClass tc) => tc.ToIngredientCount()).ToList(); + } + return cachedExtraIngredients[cycle]; + } + + private bool CanReachRequiredIngredients(Pawn pawn, CompBiosculpterPod_Cycle cycle, bool useCache = false) + { + chosenExtraItems.Clear(); + if (cycle.Props.extraRequiredIngredients == null || devFillPodLatch) + { + return true; + } + float realtimeSinceStartup = Time.realtimeSinceStartup; + if (useCache && cacheReachIngredientsPawn == pawn && cacheReachIngredientsCycle == cycle && realtimeSinceStartup < cacheReachIngredientsTime + 2f) + { + return cacheReachIngredientsResult; + } + cacheReachIngredientsPawn = pawn; + cacheReachIngredientsCycle = cycle; + cacheReachIngredientsTime = realtimeSinceStartup; + cacheReachIngredientsResult = WorkGiver_DoBill.TryFindBestFixedIngredients(RequiredIngredients(cycle), pawn, parent, chosenExtraItems); + return cacheReachIngredientsResult; + } + + private bool SelectPawnCycleOption(Pawn pawn, CompBiosculpterPod_Cycle cycle, out FloatMenuOption option) + { + string text = CannotUseNowPawnReason(pawn) ?? CannotUseNowPawnCycleReason(pawn, cycle, checkIngredients: false); + string label = pawn.Label + ((text == null) ? "" : (": " + text)); + Action action = null; + if (text == null) + { + action = delegate + { + PrepareCycleJob(pawn, pawn, cycle, EnterBiosculpterJob()); + }; + } + option = new FloatMenuOption(label, action); + return text == null; + } + + private bool SelectPawnsForCycleOptions(CompBiosculpterPod_Cycle cycle, out List options, bool shortCircuit = false) + { + cycleEligiblePawnOptions.Clear(); + options = cycleEligiblePawnOptions; + if (!cachedAnyPawnEligible.ContainsKey(cycle)) + { + cachedAnyPawnEligible[cycle] = new CacheAnyPawnEligibleCycle + { + gameTime = float.MinValue + }; + } + int ticksGame = Find.TickManager.TicksGame; + if (shortCircuit && (float)ticksGame < cachedAnyPawnEligible[cycle].gameTime + 2f) + { + return cachedAnyPawnEligible[cycle].anyEligible; + } + cachedAnyPawnEligible[cycle].gameTime = ticksGame; + if (biotunedTo != null) + { + if (biotunedTo.Dead || !biotunedTo.Spawned || biotunedTo.Map != parent.Map) + { + cachedAnyPawnEligible[cycle].anyEligible = false; + return cachedAnyPawnEligible[cycle].anyEligible; + } + if (SelectPawnCycleOption(biotunedTo, cycle, out var option) && shortCircuit) + { + cachedAnyPawnEligible[cycle].anyEligible = true; + return cachedAnyPawnEligible[cycle].anyEligible; + } + cycleEligiblePawnOptions.Add(option); + } + else + { + foreach (Pawn item in parent.Map.mapPawns.FreeColonistsSpawned) + { + if (SelectPawnCycleOption(item, cycle, out var option2) && shortCircuit) + { + cachedAnyPawnEligible[cycle].anyEligible = true; + return cachedAnyPawnEligible[cycle].anyEligible; + } + cycleEligiblePawnOptions.Add(option2); + } + } + cachedAnyPawnEligible[cycle].anyEligible = cycleEligiblePawnOptions.Count > 0; + return cachedAnyPawnEligible[cycle].anyEligible; + } + + public Job EnterBiosculpterJob() + { + return JobMaker.MakeJob(JobDefOf.EnterBiosculpterPod, parent); + } + + public Job MakeCarryToBiosculpterJob(Pawn willBeCarried) + { + return JobMaker.MakeJob(JobDefOf.CarryToBiosculpterPod, willBeCarried, LocalTargetInfo.Invalid, parent); + } + + public void ConfigureJobForCycle(Job job, CompBiosculpterPod_Cycle cycle, List extraIngredients) + { + if (!extraIngredients.NullOrEmpty()) + { + job.targetQueueB = new List(extraIngredients.Count); + job.countQueue = new List(extraIngredients.Count); + foreach (ThingCount extraIngredient in extraIngredients) + { + job.targetQueueB.Add(extraIngredient.Thing); + job.countQueue.Add(extraIngredient.Count); + } + } + job.haulMode = HaulMode.ToCellNonStorage; + job.biosculpterCycleKey = cycle.Props.key; + } + + public void PrepareCycleJob(Pawn hauler, Pawn biosculptee, CompBiosculpterPod_Cycle cycle, Job job) + { + OrderToPod(cycle, biosculptee, delegate + { + chosenExtraItems.Clear(); + if (!CanReachOrHasIngredients(hauler, biosculptee, cycle)) + { + Messages.Message("BiosculpterMissingIngredients".Translate(IngredientsDescription(cycle).Named("INGREDIENTS")).CapitalizeFirst(), parent, MessageTypeDefOf.NegativeEvent, historical: false); + } + else + { + ConfigureJobForCycle(job, cycle, chosenExtraItems); + if (cycle.Props.extraRequiredIngredients != null && !devFillPodLatch) + { + if (job.def == JobDefOf.CarryToBiosculpterPod) + { + Messages.Message("BiosculpterCarryStartedMessage".Translate(hauler.Named("PAWN"), IngredientsDescription(cycle).Named("INGREDIENTS"), biosculptee.Named("DOWNED"), cycle.Props.label.Named("CYCLE")), parent, MessageTypeDefOf.SilentInput, historical: false); + } + else + { + Messages.Message("BiosculpterLoadingStartedMessage".Translate(hauler.Named("PAWN"), IngredientsDescription(cycle).Named("INGREDIENTS"), cycle.Props.label.Named("CYCLE")), parent, MessageTypeDefOf.SilentInput, historical: false); + } + } + if (hauler.jobs.TryTakeOrderedJob(job, JobTag.Misc)) + { + SetQueuedInformation(job, biosculptee); + } + } + }); + } + + public void ClearQueuedInformation() + { + SetQueuedInformation(null, null); + } + + public void SetQueuedInformation(Job job, Pawn biosculptee) + { + queuedEnterJob = job; + queuedPawn = biosculptee; + } + + public bool CanAcceptNutrition(Thing thing) + { + return allowedNutritionSettings.AllowedToAccept(thing); + } + + public bool CanAcceptOnceCycleChosen(Pawn pawn) + { + if (State != BiosculpterPodState.SelectingCycle || !PowerOn) + { + return false; + } + if (biotunedTo != null && biotunedTo != pawn) + { + return false; + } + return true; + } + + public bool PawnCarryingExtraCycleIngredients(Pawn pawn, string cycleKey, bool remove = false) + { + return PawnCarryingExtraCycleIngredients(pawn, GetCycle(cycleKey), remove); + } + + public bool PawnCarryingExtraCycleIngredients(Pawn pawn, CompBiosculpterPod_Cycle cycle, bool remove = false) + { + if (cycle.Props.extraRequiredIngredients.NullOrEmpty() || devFillPodLatch) + { + return true; + } + foreach (ThingDefCountClass extraRequiredIngredient in cycle.Props.extraRequiredIngredients) + { + if (pawn.inventory.Count(extraRequiredIngredient.thingDef) < extraRequiredIngredient.count) + { + return false; + } + } + if (remove) + { + foreach (ThingDefCountClass extraRequiredIngredient2 in cycle.Props.extraRequiredIngredients) + { + pawn.inventory.RemoveCount(extraRequiredIngredient2.thingDef, extraRequiredIngredient2.count); + } + } + return true; + } + + public bool TryAcceptPawn(Pawn pawn, string cycleKey) + { + return TryAcceptPawn(pawn, GetCycle(cycleKey)); + } + + public bool TryAcceptPawn(Pawn pawn, CompBiosculpterPod_Cycle cycle) + { + if (!CanAcceptOnceCycleChosen(pawn)) + { + return false; + } + if (!PawnCarryingExtraCycleIngredients(pawn, cycle, remove: true)) + { + return false; + } + currentCycleKey = cycle.Props.key; + innerContainer.ClearAndDestroyContents(); + pawnEnteringBiosculpter = pawn; + bool num = pawn.DeSpawnOrDeselect(); + if (pawn.holdingOwner != null) + { + pawn.holdingOwner.TryTransferToContainer(pawn, innerContainer); + } + else + { + innerContainer.TryAdd(pawn); + } + if (num) + { + Find.Selector.Select(pawn, playSound: false, forceDesignatorDeselect: false); + } + pawnEnteringBiosculpter = null; + currentCycleTicksRemaining = cycle.Props.durationDays * 60000f; + liquifiedNutrition = 0f; + devFillPodLatch = false; + ClearQueuedInformation(); + tickEntered = Find.TickManager.TicksGame; + return true; + } + + public void EjectContents(bool interrupted, bool playSounds, Map destMap = null) + { + if (destMap == null) + { + destMap = parent.Map; + } + Pawn occupant = Occupant; + currentCycleKey = null; + currentCycleTicksRemaining = 0f; + currentCyclePowerCutTicks = 0; + liquifiedNutrition = 0f; + devFillPodLatch = false; + innerContainer.TryDropAll(parent.InteractionCell, destMap, ThingPlaceMode.Near); + if (occupant != null) + { + FilthMaker.TryMakeFilth(parent.InteractionCell, destMap, ThingDefOf.Filth_PodSlime, new IntRange(3, 6).RandomInRange); + if (interrupted) + { + occupant.needs?.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.SoakingWet); + occupant.health?.AddHediff(HediffDefOf.BiosculptingSickness); + } + } + if (playSounds) + { + Props.exitSound?.PlayOneShot(SoundInfo.InMap(new TargetInfo(parent.Position, parent.Map))); + } + } + + private void CycleCompleted() + { + Pawn occupant = Occupant; + CompBiosculpterPod_Cycle currentCycle = CurrentCycle; + SetBiotuned(occupant); + currentCycle.CycleCompleted(occupant); + EjectContents(interrupted: false, playSounds: true); + if (occupant != null) + { + Need_Food need_Food = occupant.needs?.food; + if (need_Food != null) + { + need_Food.CurLevelPercentage = 1f; + } + Need_Rest need_Rest = occupant.needs?.rest; + if (need_Rest != null) + { + need_Rest.CurLevelPercentage = 1f; + } + if (currentCycle.Props.gainThoughtOnCompletion != null) + { + occupant.needs?.mood?.thoughts.memories.TryGainMemory(ThoughtDefOf.AgeReversalReceived); + } + Find.HistoryEventsManager.RecordEvent(new HistoryEvent(HistoryEventDefOf.UsedBiosculpterPod, occupant.Named(HistoryEventArgsNames.Doer))); + } + if (tickEntered > 0) + { + occupant.drugs.Notify_LeftSuspension(Find.TickManager.TicksGame - tickEntered); + } + } + + private void LiquifyNutrition() + { + tmpItems.AddRange(innerContainer); + foreach (Thing tmpItem in tmpItems) + { + float num = tmpItem.GetStatValue(StatDefOf.Nutrition) * (float)tmpItem.stackCount; + if (!(num <= 0f) && !(tmpItem is Pawn)) + { + liquifiedNutrition = Mathf.Min(5f, liquifiedNutrition + num); + tmpItem.Destroy(); + } + } + tmpItems.Clear(); + } + + public override void CompTick() + { + if (!ModLister.CheckIdeology("Biosculpting")) + { + return; + } + base.CompTick(); + if (State != BiosculpterPodState.SelectingCycle || !PowerOn) + { + readyEffecter?.Cleanup(); + readyEffecter = null; + } + else if (Props.readyEffecter != null) + { + if (readyEffecter == null) + { + readyEffecter = Props.readyEffecter.Spawn(); + ColorizeEffecter(readyEffecter, Props.selectCycleColor); + readyEffecter.Trigger(parent, new TargetInfo(parent.InteractionCell, parent.Map)); + } + readyEffecter.EffectTick(parent, new TargetInfo(parent.InteractionCell, parent.Map)); + } + if (State != BiosculpterPodState.Occupied) + { + progressBarEffecter?.Cleanup(); + progressBarEffecter = null; + operatingEffecter?.Cleanup(); + operatingEffecter = null; + } + else + { + Pawn occupant = Occupant; + biotunedCountdownTicks = 4800000; + if (PowerOn) + { + int num = 1; + currentCycleTicksRemaining -= (float)num * CycleSpeedFactor; + if (currentCycleTicksRemaining <= 0f) + { + CycleCompleted(); + } + } + else + { + currentCyclePowerCutTicks++; + if (currentCyclePowerCutTicks >= 60000) + { + EjectContents(interrupted: true, playSounds: true); + Messages.Message("BiosculpterNoPowerEjectedMessage".Translate(occupant.Named("PAWN")), occupant, MessageTypeDefOf.NegativeEvent, historical: false); + } + } + if (currentCycleTicksRemaining > 0f) + { + if (progressBarEffecter == null) + { + progressBarEffecter = EffecterDefOf.ProgressBar.Spawn(); + } + progressBarEffecter.EffectTick(parent, TargetInfo.Invalid); + MoteProgressBar moteProgressBar = (progressBarEffecter.children[0] as SubEffecter_ProgressBar)?.mote; + if (moteProgressBar != null) + { + float num2 = CurrentCycle.Props.durationDays * 60000f; + moteProgressBar.progress = 1f - Mathf.Clamp01(currentCycleTicksRemaining / num2); + int num3 = (parent.RotatedSize.z - 1) / 2; + moteProgressBar.offsetZ = 0f - ((float)num3 + 0.5f); + } + if (Props.operatingEffecter != null) + { + if (!PowerOn) + { + operatingEffecter?.Cleanup(); + operatingEffecter = null; + } + else + { + if (operatingEffecter == null) + { + operatingEffecter = Props.operatingEffecter.Spawn(); + ColorizeEffecter(operatingEffecter, CurrentCycle.Props.operatingColor); + operatingEffecter.Trigger(parent, new TargetInfo(parent.InteractionCell, parent.Map)); + } + operatingEffecter.EffectTick(parent, new TargetInfo(parent.InteractionCell, parent.Map)); + } + } + } + } + if (PowerOn && biotunedCountdownTicks > 0) + { + biotunedCountdownTicks--; + } + if (biotunedCountdownTicks <= 0) + { + SetBiotuned(null); + } + SetPower(); + if (biotunedTo?.Ideo != null && !biotunedTo.Ideo.HasPrecept(PreceptDefOf.AgeReversal_Demanded)) + { + autoAgeReversal = false; + } + } + + private void SetPower() + { + if (powerTraderComp == null) + { + powerTraderComp = parent.TryGetComp(); + } + if (powerComp == null) + { + powerComp = parent.TryGetComp(); + } + if (State == BiosculpterPodState.Occupied) + { + powerTraderComp.PowerOutput = 0f - powerComp.Props.PowerConsumption; + } + else + { + powerTraderComp.PowerOutput = 0f - powerComp.Props.idlePowerDraw; + } + } + + private void ColorizeEffecter(Effecter effecter, Color color) + { + foreach (SubEffecter child in effecter.children) + { + if (child is SubEffecter_Sprayer subEffecter_Sprayer) + { + subEffecter_Sprayer.colorOverride = color * child.def.color; + } + } + } + + public override void PostDraw() + { + base.PostDraw(); + Rot4 rotation = parent.Rotation; + Vector3 s = new Vector3(parent.def.graphicData.drawSize.x * 0.8f, 1f, parent.def.graphicData.drawSize.y * 0.8f); + Vector3 drawPos = parent.DrawPos; + drawPos.y -= 0.07317074f; + Graphics.DrawMesh(MeshPool.plane10, Matrix4x4.TRS(drawPos, rotation.AsQuat, s), BackgroundMat, 0); + if (State == BiosculpterPodState.Occupied) + { + Pawn occupant = Occupant; + Vector3 drawLoc = parent.DrawPos + FloatingOffset(currentCycleTicksRemaining + (float)currentCyclePowerCutTicks); + Rot4 rotation2 = parent.Rotation; + if (rotation2 == Rot4.East || rotation2 == Rot4.West) + { + drawLoc.z += 0.2f; + } + occupant.Drawer.renderer.RenderPawnAt(drawLoc, null, neverAimWeapon: true); + } + } + + public static Vector3 FloatingOffset(float tickOffset) + { + float num = tickOffset % 500f / 500f; + float num2 = Mathf.Sin(MathF.PI * num); + float z = num2 * num2 * 0.04f; + return new Vector3(0f, 0f, z); + } + + public void GetChildHolders(List outChildren) + { + ThingOwnerUtility.AppendThingHoldersFromThings(outChildren, GetDirectlyHeldThings()); + } + + public ThingOwner GetDirectlyHeldThings() + { + return innerContainer; + } + + public StorageSettings GetStoreSettings() + { + return allowedNutritionSettings; + } + + public StorageSettings GetParentStoreSettings() + { + return parent.def.building.fixedStorageSettings; + } + + public void Notify_SettingsChanged() + { + } + + private static void OrderToPod(CompBiosculpterPod_Cycle cycle, Pawn pawn, Action giveJobAct) + { + if (cycle is CompBiosculpterPod_HealingCycle compBiosculpterPod_HealingCycle) + { + string healingDescriptionForPawn = compBiosculpterPod_HealingCycle.GetHealingDescriptionForPawn(pawn); + string text = (healingDescriptionForPawn.NullOrEmpty() ? "BiosculpterNoCoditionsToHeal".Translate(pawn.Named("PAWN"), compBiosculpterPod_HealingCycle.Props.label.Named("CYCLE")).Resolve() : ("OnCompletionOfCycle".Translate(compBiosculpterPod_HealingCycle.Props.label.Named("CYCLE")).Resolve() + ":\n\n" + healingDescriptionForPawn)); + Find.WindowStack.Add(Dialog_MessageBox.CreateConfirmation(text, giveJobAct, healingDescriptionForPawn.NullOrEmpty())); + } + else + { + giveJobAct(); + } + } + + public static Thing FindPodFor(Pawn pawn, Pawn traveller, bool biotuned) + { + if (cachedPodDefs.NullOrEmpty()) + { + cachedPodDefs = DefDatabase.AllDefs.Where((ThingDef def) => def.GetCompProperties() != null).ToList(); + } + foreach (ThingDef cachedPodDef in cachedPodDefs) + { + Thing thing = GenClosest.ClosestThingReachable(traveller.Position, pawn.Map, ThingRequest.ForDef(cachedPodDef), PathEndMode.InteractionCell, TraverseParms.For(pawn), 9999f, Validator); + if (thing != null) + { + return thing; + } + } + return null; + bool Validator(Thing t) + { + CompBiosculpterPod compBiosculpterPod = t.TryGetComp(); + if (biotuned && compBiosculpterPod.biotunedTo != traveller) + { + return false; + } + return compBiosculpterPod.CanAcceptOnceCycleChosen(traveller); + } + } + + public static bool WasLoadingCanceled(Thing thing) + { + CompBiosculpterPod compBiosculpterPod = thing.TryGetComp(); + if (compBiosculpterPod != null && compBiosculpterPod.State != 0) + { + return true; + } + return false; + } + + public void ClearCycle() + { + currentCycleKey = null; + } + + public void Notify_HauledTo(Pawn hauler, Thing thing, int count) + { + LiquifyNutrition(); + SoundDefOf.Standard_Drop.PlayOneShot(parent); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_BiosculpterPod_BaseCycle.txt` +**相似度:** 0.7539 + +```csharp +public abstract class CompProperties_BiosculpterPod_BaseCycle : CompProperties +{ + [NoTranslate] + public string key; + + [MustTranslate] + public string label; + + [MustTranslate] + public string description; + + [NoTranslate] + public string iconPath; + + public float durationDays; + + public Color operatingColor = new Color(0.5f, 0.7f, 0.5f); + + public ThoughtDef gainThoughtOnCompletion; + + public List requiredResearch; + + public List extraRequiredIngredients; + + private Texture2D icon; + + public Texture2D Icon + { + get + { + if (icon == null) + { + icon = ContentFinder.Get(iconPath); + } + return icon; + } + } + + public string LabelCap => label.CapitalizeFirst(); +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_BiosculpterPod_PleasureCycle.txt` +**相似度:** 0.7363 + +```csharp +public class CompProperties_BiosculpterPod_PleasureCycle : CompProperties_BiosculpterPod_BaseCycle +{ + public CompProperties_BiosculpterPod_PleasureCycle() + { + compClass = typeof(CompBiosculpterPod_PleasureCycle); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_BiosculpterPod_AgeReversalCycle.txt` +**相似度:** 0.7237 + +```csharp +public class CompProperties_BiosculpterPod_AgeReversalCycle : CompProperties_BiosculpterPod_BaseCycle +{ + public CompProperties_BiosculpterPod_AgeReversalCycle() + { + compClass = typeof(CompBiosculpterPod_AgeReversalCycle); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompBiosculpterPod_Cycle.txt` +**相似度:** 0.7087 + +```csharp +public abstract class CompBiosculpterPod_Cycle : ThingComp +{ + private List tmpMissingResearchLabels = new List(); + + public CompProperties_BiosculpterPod_BaseCycle Props => (CompProperties_BiosculpterPod_BaseCycle)props; + + public abstract void CycleCompleted(Pawn occupant); + + public virtual string Description(Pawn tunedFor) + { + return Props.description; + } + + public List MissingResearchLabels() + { + tmpMissingResearchLabels.Clear(); + if (Props.requiredResearch.NullOrEmpty()) + { + return tmpMissingResearchLabels; + } + foreach (ResearchProjectDef item in Props.requiredResearch) + { + if (!item.IsFinished) + { + tmpMissingResearchLabels.Add(item.LabelCap); + } + } + return tmpMissingResearchLabels; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_BiosculpterPod_HealingCycle.txt` +**相似度:** 0.6966 + +```csharp +public class CompProperties_BiosculpterPod_HealingCycle : CompProperties_BiosculpterPod_BaseCycle +{ + public List bodyPartsToRestore; + + public List conditionsToPossiblyCure; +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/CompBiosculpterPod-WorkGiver_HaulToBiosculpterPod.txt b/MCP/vector_cache/CompBiosculpterPod-WorkGiver_HaulToBiosculpterPod.txt new file mode 100644 index 00000000..6bbbe9dc --- /dev/null +++ b/MCP/vector_cache/CompBiosculpterPod-WorkGiver_HaulToBiosculpterPod.txt @@ -0,0 +1,91 @@ +根据向量相似度分析,与 'WorkGiver_HaulToBiosculpterPod, CompBiosculpterPod' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_HaulToBiosculpterPod.txt` + +```csharp +public class WorkGiver_HaulToBiosculpterPod : WorkGiver_Scanner +{ + public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForDef(ThingDefOf.BiosculpterPod); + + public override PathEndMode PathEndMode => PathEndMode.Touch; + + public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) + { + if (!ModLister.CheckIdeology("Biosculpting")) + { + return false; + } + if (!pawn.CanReserve(t, 1, -1, null, forced)) + { + return false; + } + if (pawn.Map.designationManager.DesignationOn(t, DesignationDefOf.Deconstruct) != null) + { + return false; + } + CompBiosculpterPod compBiosculpterPod = t.TryGetComp(); + if (compBiosculpterPod == null || !compBiosculpterPod.PowerOn || compBiosculpterPod.State != 0 || (!forced && !compBiosculpterPod.autoLoadNutrition)) + { + return false; + } + if (t.IsBurning()) + { + return false; + } + if (compBiosculpterPod.RequiredNutritionRemaining > 0f) + { + if (FindNutrition(pawn, compBiosculpterPod).Thing == null) + { + JobFailReason.Is("NoFood".Translate()); + return false; + } + return true; + } + return false; + } + + public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) + { + CompBiosculpterPod compBiosculpterPod = t.TryGetComp(); + if (compBiosculpterPod == null) + { + return null; + } + if (compBiosculpterPod.RequiredNutritionRemaining > 0f) + { + ThingCount thingCount = FindNutrition(pawn, compBiosculpterPod); + if (thingCount.Thing != null) + { + Job job = HaulAIUtility.HaulToContainerJob(pawn, thingCount.Thing, t); + job.count = Mathf.Min(job.count, thingCount.Count); + return job; + } + } + return null; + } + + private ThingCount FindNutrition(Pawn pawn, CompBiosculpterPod pod) + { + Thing thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree), PathEndMode.ClosestTouch, TraverseParms.For(pawn), 9999f, Validator); + if (thing == null) + { + return default(ThingCount); + } + int b = Mathf.CeilToInt(pod.RequiredNutritionRemaining / thing.GetStatValue(StatDefOf.Nutrition)); + return new ThingCount(thing, Mathf.Min(thing.stackCount, b)); + bool Validator(Thing x) + { + if (x.IsForbidden(pawn) || !pawn.CanReserve(x)) + { + return false; + } + if (!pod.CanAcceptNutrition(x)) + { + return false; + } + return true; + } + } +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/CompProperties_Refuelable.txt b/MCP/vector_cache/CompProperties_Refuelable.txt new file mode 100644 index 00000000..89d178ca --- /dev/null +++ b/MCP/vector_cache/CompProperties_Refuelable.txt @@ -0,0 +1,881 @@ +根据向量相似度分析,与 'CompProperties_Refuelable' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_Refuelable.txt` + +```csharp +public class CompProperties_Refuelable : CompProperties +{ + public float fuelConsumptionRate = 1f; + + public float fuelCapacity = 2f; + + public float initialFuelPercent; + + public float autoRefuelPercent = 0.3f; + + public float fuelConsumptionPerTickInRain; + + public ThingFilter fuelFilter; + + public bool destroyOnNoFuel; + + public bool consumeFuelOnlyWhenUsed; + + public bool consumeFuelOnlyWhenPowered; + + public bool showFuelGizmo; + + public bool initialAllowAutoRefuel = true; + + public bool showAllowAutoRefuelToggle; + + public bool allowRefuelIfNotEmpty = true; + + public bool fuelIsMortarBarrel; + + public bool targetFuelLevelConfigurable; + + public float initialConfigurableTargetFuelLevel; + + public bool drawOutOfFuelOverlay = true; + + public float minimumFueledThreshold; + + public bool drawFuelGaugeInMap; + + public bool atomicFueling; + + private float fuelMultiplier = 1f; + + public bool factorByDifficulty; + + [MustTranslate] + public string fuelLabel; + + [MustTranslate] + public string fuelGizmoLabel; + + [MustTranslate] + public string outOfFuelMessage; + + [NoTranslate] + public string fuelIconPath; + + public bool externalTicking; + + public bool hideGizmosIfNotPlayerFaction; + + public bool functionsInVacuum = true; + + private Texture2D fuelIcon; + + public string FuelLabel + { + get + { + if (fuelLabel.NullOrEmpty()) + { + return "Fuel".TranslateSimple(); + } + return fuelLabel; + } + } + + public string FuelGizmoLabel + { + get + { + if (fuelGizmoLabel.NullOrEmpty()) + { + return "Fuel".TranslateSimple(); + } + return fuelGizmoLabel; + } + } + + public Texture2D FuelIcon + { + get + { + if (fuelIcon == null) + { + if (!fuelIconPath.NullOrEmpty()) + { + fuelIcon = ContentFinder.Get(fuelIconPath); + } + else + { + ThingDef thingDef = ((fuelFilter.AnyAllowedDef == null) ? ThingDefOf.Chemfuel : fuelFilter.AnyAllowedDef); + fuelIcon = thingDef.uiIcon; + } + } + return fuelIcon; + } + } + + public float FuelMultiplierCurrentDifficulty + { + get + { + if (factorByDifficulty && Find.Storyteller?.difficulty != null) + { + return fuelMultiplier / Find.Storyteller.difficulty.maintenanceCostFactor; + } + return fuelMultiplier; + } + } + + public CompProperties_Refuelable() + { + compClass = typeof(CompRefuelable); + } + + public override void ResolveReferences(ThingDef parentDef) + { + base.ResolveReferences(parentDef); + fuelFilter.ResolveReferences(); + } + + public override IEnumerable ConfigErrors(ThingDef parentDef) + { + foreach (string item in base.ConfigErrors(parentDef)) + { + yield return item; + } + if (destroyOnNoFuel && initialFuelPercent <= 0f) + { + yield return "Refuelable component has destroyOnNoFuel, but initialFuelPercent <= 0"; + } + if ((!consumeFuelOnlyWhenUsed || fuelConsumptionPerTickInRain > 0f) && parentDef.tickerType != TickerType.Normal) + { + yield return $"Refuelable component set to consume fuel per tick, but parent tickertype is {parentDef.tickerType} instead of {TickerType.Normal}"; + } + } + + public override IEnumerable SpecialDisplayStats(StatRequest req) + { + foreach (StatDrawEntry item in base.SpecialDisplayStats(req)) + { + yield return item; + } + if (((ThingDef)req.Def).building.IsTurret) + { + yield return new StatDrawEntry(StatCategoryDefOf.Building, "ShotsBeforeRearm".Translate(), ((int)fuelCapacity).ToString(), "ShotsBeforeRearmExplanation".Translate(), 3171); + } + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompRefuelable.txt` +**相似度:** 0.7548 + +```csharp +public class CompRefuelable : ThingComp_VacuumAware, IThingGlower +{ + private float fuel; + + private float configuredTargetFuelLevel = -1f; + + public bool allowAutoRefuel = true; + + private CompFlickable flickComp; + + private CompExplosive explosiveComp; + + public const string RefueledSignal = "Refueled"; + + public const string RanOutOfFuelSignal = "RanOutOfFuel"; + + private static readonly Texture2D SetTargetFuelLevelCommand = ContentFinder.Get("UI/Commands/SetTargetFuelLevel"); + + private static readonly Vector2 FuelBarSize = new Vector2(1f, 0.2f); + + private static readonly Material FuelBarFilledMat = SolidColorMaterials.SimpleSolidColorMaterial(new Color(0.6f, 0.56f, 0.13f)); + + private static readonly Material FuelBarUnfilledMat = SolidColorMaterials.SimpleSolidColorMaterial(new Color(0.3f, 0.3f, 0.3f)); + + protected override bool FunctionsInVacuum => Props.functionsInVacuum; + + public float TargetFuelLevel + { + get + { + if (configuredTargetFuelLevel >= 0f) + { + return configuredTargetFuelLevel; + } + if (Props.targetFuelLevelConfigurable) + { + return Props.initialConfigurableTargetFuelLevel; + } + return Props.fuelCapacity; + } + set + { + configuredTargetFuelLevel = Mathf.Clamp(value, 0f, Props.fuelCapacity); + } + } + + public CompProperties_Refuelable Props => (CompProperties_Refuelable)props; + + public float Fuel => fuel; + + public float FuelPercentOfTarget => fuel / TargetFuelLevel; + + public float FuelPercentOfMax => fuel / Props.fuelCapacity; + + public bool IsFull => TargetFuelLevel - fuel < 1f; + + public bool HasFuel + { + get + { + if (fuel > 0f && fuel >= Props.minimumFueledThreshold) + { + if (!FunctionsInVacuum) + { + return !base.InVacuum; + } + return true; + } + return false; + } + } + + private float ConsumptionRatePerTick => Props.fuelConsumptionRate / 60000f; + + public bool ShouldAutoRefuelNow + { + get + { + if (FuelPercentOfTarget <= Props.autoRefuelPercent && !IsFull && TargetFuelLevel > 0f) + { + return ShouldAutoRefuelNowIgnoringFuelPct; + } + return false; + } + } + + public bool ShouldAutoRefuelNowIgnoringFuelPct + { + get + { + if (!parent.IsBurning() && (flickComp == null || flickComp.SwitchIsOn) && parent.Map.designationManager.DesignationOn(parent, DesignationDefOf.Flick) == null) + { + return parent.Map.designationManager.DesignationOn(parent, DesignationDefOf.Deconstruct) == null; + } + return false; + } + } + + public bool ShouldBeLitNow() + { + return HasFuel; + } + + public override void Initialize(CompProperties props) + { + base.Initialize(props); + allowAutoRefuel = Props.initialAllowAutoRefuel; + fuel = Props.fuelCapacity * Props.initialFuelPercent; + } + + public override void PostSpawnSetup(bool respawningAfterLoad) + { + flickComp = parent.GetComp(); + explosiveComp = parent.GetComp(); + } + + public override void PostExposeData() + { + base.PostExposeData(); + Scribe_Values.Look(ref fuel, "fuel", 0f); + Scribe_Values.Look(ref configuredTargetFuelLevel, "configuredTargetFuelLevel", -1f); + Scribe_Values.Look(ref allowAutoRefuel, "allowAutoRefuel", defaultValue: false); + if (Scribe.mode == LoadSaveMode.PostLoadInit && !Props.showAllowAutoRefuelToggle) + { + allowAutoRefuel = Props.initialAllowAutoRefuel; + } + } + + public override void PostDraw() + { + base.PostDraw(); + if (!allowAutoRefuel) + { + parent.Map.overlayDrawer.DrawOverlay(parent, OverlayTypes.ForbiddenRefuel); + } + else if (!HasFuel && Props.drawOutOfFuelOverlay) + { + parent.Map.overlayDrawer.DrawOverlay(parent, OverlayTypes.OutOfFuel); + } + if (Props.drawFuelGaugeInMap) + { + GenDraw.FillableBarRequest r = default(GenDraw.FillableBarRequest); + r.center = parent.DrawPos + Vector3.up * 0.1f; + r.size = FuelBarSize; + r.fillPercent = FuelPercentOfMax; + r.filledMat = FuelBarFilledMat; + r.unfilledMat = FuelBarUnfilledMat; + r.margin = 0.15f; + Rot4 rotation = parent.Rotation; + rotation.Rotate(RotationDirection.Clockwise); + r.rotation = rotation; + GenDraw.DrawFillableBar(r); + } + } + + public override void PostDestroy(DestroyMode mode, Map previousMap) + { + base.PostDestroy(mode, previousMap); + if ((!Props.fuelIsMortarBarrel || !Find.Storyteller.difficulty.classicMortars) && mode != 0 && previousMap != null && Props.fuelFilter.AllowedDefCount == 1 && Props.initialFuelPercent == 0f) + { + ThingDef thingDef = Props.fuelFilter.AllowedThingDefs.First(); + int num = Mathf.FloorToInt(1f * fuel); + while (num > 0) + { + Thing thing = ThingMaker.MakeThing(thingDef); + thing.stackCount = Mathf.Min(num, thingDef.stackLimit); + num -= thing.stackCount; + GenPlace.TryPlaceThing(thing, parent.Position, previousMap, ThingPlaceMode.Near); + } + } + } + + public override string CompInspectStringExtra() + { + if (Props.fuelIsMortarBarrel && Find.Storyteller.difficulty.classicMortars) + { + return string.Empty; + } + string text = base.CompInspectStringExtra(); + text = ((text != null) ? (text + "\n") : string.Empty); + text = text + Props.FuelLabel + ": " + fuel.ToStringDecimalIfSmall() + " / " + Props.fuelCapacity.ToStringDecimalIfSmall(); + if (!Props.consumeFuelOnlyWhenUsed && HasFuel) + { + int numTicks = (int)(fuel / Props.fuelConsumptionRate * 60000f); + text = text + " (" + numTicks.ToStringTicksToPeriod() + ")"; + } + if (!HasFuel && !Props.outOfFuelMessage.NullOrEmpty()) + { + string arg = ((parent.def.building != null && parent.def.building.IsTurret) ? ("CannotShoot".Translate() + ": " + Props.outOfFuelMessage).Resolve() : Props.outOfFuelMessage); + text += $"\n{arg} ({GetFuelCountToFullyRefuel()}x {Props.fuelFilter.AnyAllowedDef.label})"; + } + if (Props.targetFuelLevelConfigurable) + { + text += "\n" + "ConfiguredTargetFuelLevel".Translate(TargetFuelLevel.ToStringDecimalIfSmall()); + } + return text; + } + + public override IEnumerable SpecialDisplayStats() + { + if (parent.def.building != null && parent.def.building.IsTurret) + { + TaggedString taggedString = "RearmCostExplanation".Translate(); + if (Props.factorByDifficulty) + { + taggedString += " (" + "RearmCostExplanationDifficulty".Translate() + ")"; + } + taggedString += "."; + yield return new StatDrawEntry(StatCategoryDefOf.Building, "RearmCost".Translate(), GenLabel.ThingLabel(Props.fuelFilter.AnyAllowedDef, null, GetFuelCountToFullyRefuel()).CapitalizeFirst(), taggedString, 3171); + } + } + + public override void CompTick() + { + base.CompTick(); + CompPowerTrader comp = parent.GetComp(); + if (!Props.consumeFuelOnlyWhenUsed && (flickComp == null || flickComp.SwitchIsOn) && (!Props.consumeFuelOnlyWhenPowered || (comp != null && comp.PowerOn)) && !Props.externalTicking) + { + ConsumeFuel(ConsumptionRatePerTick); + } + if (Props.fuelConsumptionPerTickInRain > 0f && parent.Spawned && parent.Map.weatherManager.RainRate > 0.4f && !parent.Map.roofGrid.Roofed(parent.Position) && !Props.externalTicking) + { + ConsumeFuel(Props.fuelConsumptionPerTickInRain); + } + } + + public void ConsumeFuel(float amount) + { + if ((!Props.fuelIsMortarBarrel || !Find.Storyteller.difficulty.classicMortars) && !(fuel <= 0f)) + { + fuel -= amount; + if (fuel <= 0f) + { + fuel = 0f; + Notify_RanOutOfFuel(); + } + } + } + + private void Notify_RanOutOfFuel() + { + if (Props.destroyOnNoFuel) + { + parent.Destroy(); + } + parent.BroadcastCompSignal("RanOutOfFuel"); + } + + public void Refuel(List fuelThings) + { + if (Props.atomicFueling && fuelThings.Sum((Thing t) => t.stackCount) < GetFuelCountToFullyRefuel()) + { + Log.ErrorOnce("Error refueling; not enough fuel available for proper atomic refuel", 19586442); + return; + } + int num = GetFuelCountToFullyRefuel(); + while (num > 0 && fuelThings.Count > 0) + { + Thing thing = fuelThings.Pop(); + int num2 = Mathf.Min(num, thing.stackCount); + Refuel(num2); + thing.SplitOff(num2).Destroy(); + num -= num2; + } + } + + public void Refuel(float amount) + { + fuel += amount * Props.FuelMultiplierCurrentDifficulty; + if (fuel > Props.fuelCapacity) + { + fuel = Props.fuelCapacity; + } + parent.BroadcastCompSignal("Refueled"); + } + + public AcceptanceReport CanEjectFuel() + { + CompExplosive compExplosive = explosiveComp; + if (compExplosive != null && compExplosive.wickStarted) + { + return "AboutToExplode".Translate(); + } + if (Fuel == 0f) + { + return "RefuelableNoFuelToEject".Translate(); + } + return true; + } + + public void EjectFuel() + { + ThingDef thingDef = Props.fuelFilter.AllowedThingDefs.First(); + int num = Mathf.FloorToInt(fuel); + while (num > 0) + { + Thing thing = ThingMaker.MakeThing(thingDef); + thing.stackCount = Mathf.Min(num, thingDef.stackLimit); + num -= thing.stackCount; + GenPlace.TryPlaceThing(thing, parent.Position, parent.Map, ThingPlaceMode.Near); + thing.SetForbidden(value: true); + } + fuel = 0f; + Notify_RanOutOfFuel(); + } + + public void Notify_UsedThisTick() + { + ConsumeFuel(ConsumptionRatePerTick); + } + + public int GetFuelCountToFullyRefuel() + { + if (Props.atomicFueling) + { + return Mathf.CeilToInt(Props.fuelCapacity / Props.FuelMultiplierCurrentDifficulty); + } + return Mathf.Max(Mathf.CeilToInt((TargetFuelLevel - fuel) / Props.FuelMultiplierCurrentDifficulty), 1); + } + + public override IEnumerable CompGetGizmosExtra() + { + if (Props.fuelIsMortarBarrel && Find.Storyteller.difficulty.classicMortars) + { + yield break; + } + if (!Props.hideGizmosIfNotPlayerFaction || parent.Faction == Faction.OfPlayer) + { + if (Find.Selector.SelectedObjects.Count == 1) + { + yield return new Gizmo_SetFuelLevel(this); + } + else + { + if (Props.targetFuelLevelConfigurable) + { + Command_SetTargetFuelLevel command_SetTargetFuelLevel = new Command_SetTargetFuelLevel(); + command_SetTargetFuelLevel.refuelable = this; + command_SetTargetFuelLevel.defaultLabel = "CommandSetTargetFuelLevel".Translate(); + command_SetTargetFuelLevel.defaultDesc = "CommandSetTargetFuelLevelDesc".Translate(); + command_SetTargetFuelLevel.icon = SetTargetFuelLevelCommand; + yield return command_SetTargetFuelLevel; + } + if (Props.showAllowAutoRefuelToggle) + { + string str = (allowAutoRefuel ? "On".Translate() : "Off".Translate()); + Command_Toggle command_Toggle = new Command_Toggle(); + command_Toggle.isActive = () => allowAutoRefuel; + command_Toggle.toggleAction = delegate + { + allowAutoRefuel = !allowAutoRefuel; + }; + command_Toggle.defaultLabel = "CommandToggleAllowAutoRefuel".Translate(); + command_Toggle.defaultDesc = "CommandToggleAllowAutoRefuelDescMult".Translate(str.UncapitalizeFirst().Named("ONOFF")); + command_Toggle.icon = (allowAutoRefuel ? TexCommand.ForbidOn : TexCommand.ForbidOff); + command_Toggle.Order = 20f; + command_Toggle.hotKey = KeyBindingDefOf.Command_ItemForbid; + yield return command_Toggle; + } + } + } + if (DebugSettings.ShowDevGizmos) + { + Command_Action command_Action = new Command_Action(); + command_Action.defaultLabel = "DEV: Set fuel to 0"; + command_Action.action = delegate + { + fuel = 0f; + parent.BroadcastCompSignal("Refueled"); + }; + yield return command_Action; + Command_Action command_Action2 = new Command_Action(); + command_Action2.defaultLabel = "DEV: Set fuel to 0.1"; + command_Action2.action = delegate + { + fuel = 0.1f; + parent.BroadcastCompSignal("Refueled"); + }; + yield return command_Action2; + Command_Action command_Action3 = new Command_Action(); + command_Action3.defaultLabel = "DEV: Fuel -20%"; + command_Action3.action = delegate + { + ConsumeFuel(Props.fuelCapacity * 0.2f); + }; + yield return command_Action3; + Command_Action command_Action4 = new Command_Action(); + command_Action4.defaultLabel = "DEV: Set fuel to max"; + command_Action4.action = delegate + { + fuel = Props.fuelCapacity; + parent.BroadcastCompSignal("Refueled"); + }; + yield return command_Action4; + } + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Odyssey\Defs\ThingDefs_Buildings\Buildings_Gravship.xml` +**相似度:** 0.5864 + +```xml + ChemfuelTank + + A chemfuel storage tank that supplies fuel for thrusters on a gravship. + + Graphic_Multi + Things/Building/ChemfuelTank/ChemfuelTank + (2, 2) + + + 200 + 30 + 1 + -10 + 2000 + + (2, 2) + + 120 + + +
  • BasicGravtech
  • +
    + +
  • + 250 + true + 250 + + +
  • Chemfuel
  • + + + Chemfuel + Chemfuel + true + 1 + true + false + true + true + false + +
    +
    + + + LargeChemfuelTank +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Core\Defs\ThingDefs_Buildings\Buildings_Power.xml` +**相似度:** 0.5793 + +```xml + WoodFiredGenerator + + Produces power by consuming wood. Must be periodically loaded with wood fuel by hand. + Building + MapMeshAndRealTime + + Things/Building/Power/WoodFiredGenerator + Graphic_Single + (2,2) + + (1.93,1,1.69) + (-0.03,0,-0.1) + + + Building + PassThroughOnly + 0.9 + 50 + false + true + false + + 300 + 2500 + 1.0 + -20 + + Normal + false + (2,2) + + BuildingDestroyed_Metal_Medium + + + 100 + 2 + + +
  • + CompPowerPlant + -1000 + true + WoodFiredGenerator_Ambience +
  • +
  • +
  • + 22.0 + 75.0 + + +
  • WoodLog
  • + + + true + true + +
  • + 6 + (217,112,33,0) +
  • +
  • + CompHeatPusherPowered + 6 +
  • +
  • +
  • + true + +
  • EMP
  • + + +
    + Medium + Power + 2100 + Misc3 + ConstructMetal + +
  • Electricity
  • +
    + 4 +
    + + + ChemfuelPoweredGenerator +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Biotech\Defs\ThingDefs_Buildings\Buildings_Deathrest.xml` +**相似度:** 0.5764 + +```xml + + +
  • + CompPowerTrader + 100 + 0 + true +
  • +
  • +
  • + 0.5 + 5 + Hemogen + + +
  • HemogenPack
  • + + + 1 + true + true + 0.05 + true + +
    +
    +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Core\Defs\ThingDefs_Buildings\Buildings_Temperature.xml` +**相似度:** 0.5668 + +```xml + BulletImpact_Ground + false + 0 + +
  • PlaceWorker_PreventInteractionSpotOverlap
  • +
  • PlaceWorker_Heater
  • +
  • PlaceWorker_GlowRadius
  • +
    + true + +
  • + 10.0 + 20.0 + 0.0006 + + +
  • WoodLog
  • + + + 1 + true + false + +
  • + 10 + (252,187,113,0) +
  • +
  • + CompHeatPusherPowered + 21 + 28 +
  • +
  • + 1 +
  • +
  • + CompGatherSpot +
  • +
  • + MeditationFocusStrength +
  • Flame
  • + +
  • + 0.12 +
  • +
  • + +
  • Campfire
  • +
  • TorchLamp
  • +
  • Brazier
  • +
  • DarklightBrazier
  • +
  • Darktorch
  • +
  • DarktorchFungus
  • + + 0.02 + 9.9 + 8 + MeditationFocusPerFlame + MeditationFocusPerFlameAbstract + +
    + +
    + Temperature + Misc1 + True + (0,0,-1) + +
  • CookMealSimple
  • +
  • CookMealSimpleBulk
  • +
  • Make_Pemmican
  • +
  • Make_PemmicanBulk
  • +
  • BurnApparel
  • +
  • BurnWeapon
  • +
  • BurnDrugs
  • +
  • Make_BabyFood
  • +
  • Make_BabyFoodBulk
  • +
    + +
  • ITab_Bills
  • +
    + + true + BillsTab + false + BuildingDestroyed_Wood_Small + +
    + + + PassiveCooler + + A traditional unpowered cooler that works by water evaporation. Must be regularly replenished with wood. Not efficient enough to refrigerate food. + Building + + Things/Building/Misc/PassiveCooler + Graphic_Single + false + false + true + + (0.9,0.3,0.9) + + + (0.2,0,0.6,0.1) + + + false + Building + PassThroughOnly + 30 + ConstructDirt + Normal + RealtimeOnly + 0.40 + + 80 + 200 + 1 + + true + + 50 + + + BuildingDestroyed_Metal_Small + + BulletImpact_Ground +``` \ No newline at end of file diff --git a/MCP/vector_cache/CryptosleepCasket.txt b/MCP/vector_cache/CryptosleepCasket.txt new file mode 100644 index 00000000..5502f0c1 --- /dev/null +++ b/MCP/vector_cache/CryptosleepCasket.txt @@ -0,0 +1,267 @@ +根据向量相似度分析,与 'CryptosleepCasket' 最相关的代码定义如下: + +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\RoomContents_CryptosleepCasket.txt` +**相似度:** 0.7176 + +```csharp +public class RoomContents_CryptosleepCasket : RoomContentsWorker +{ + private const string OpenedSignal = "OpenedSignal"; + + public override void FillRoom(Map map, LayoutRoom room, Faction faction, float? threatPoints = null) + { + if (!room.TryGetRandomCellInRoom(map, out var cell, 3)) + { + cell = room.rects[0].CenterCell; + } + int nextAncientCryptosleepCasketGroupID = Find.UniqueIDsManager.GetNextAncientCryptosleepCasketGroupID(); + PodContentsType type = Gen.RandomEnumValue(disallowFirstValue: true); + Building_AncientCryptosleepCasket pod = RoomGenUtility.SpawnCryptoCasket(cell, map, Rot4.Random, nextAncientCryptosleepCasketGroupID, type, ThingSetMakerDefOf.MapGen_ScarlandsAncientPodContents); + ThreatSignal = "OpenedSignal" + Find.UniqueIDsManager.GetNextSignalTagID(); + RoomGenUtility.SpawnOpenCryptoCasketSignal(pod, map, ThreatSignal); + base.FillRoom(map, room, faction, threatPoints); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\Building_AncientCryptosleepPod.txt` +**相似度:** 0.7115 + +```csharp +public class Building_AncientCryptosleepPod : Building_AncientCryptosleepCasket +{ + public override IEnumerable GetFloatMenuOptions(Pawn myPawn) + { + return Enumerable.Empty(); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\Building_AncientCryptosleepCasket.txt` +**相似度:** 0.7023 + +```csharp +public class Building_AncientCryptosleepCasket : Building_CryptosleepCasket +{ + public int groupID = -1; + + public override void ExposeData() + { + base.ExposeData(); + Scribe_Values.Look(ref groupID, "groupID", 0); + } + + public override void PreApplyDamage(ref DamageInfo dinfo, out bool absorbed) + { + base.PreApplyDamage(ref dinfo, out absorbed); + if (absorbed) + { + return; + } + if (!contentsKnown && innerContainer.Count > 0 && dinfo.Def.harmsHealth && dinfo.Instigator != null && dinfo.Instigator.Faction != null) + { + bool flag = false; + foreach (Thing item in (IEnumerable)innerContainer) + { + if (item is Pawn) + { + flag = true; + break; + } + } + if (flag) + { + EjectContents(); + } + } + absorbed = false; + } + + public override void EjectContents() + { + bool num = contentsKnown; + List list = null; + if (!num) + { + list = new List(); + list.AddRange(innerContainer); + list.AddRange(UnopenedCasketsInGroup().SelectMany((Building_AncientCryptosleepCasket c) => c.innerContainer)); + list.RemoveDuplicates(); + } + base.EjectContents(); + if ((bool)ClaimableBy(Faction.OfPlayer)) + { + SetFaction(null); + } + if (num) + { + return; + } + ThingDef filth_Slime = ThingDefOf.Filth_Slime; + FilthMaker.TryMakeFilth(base.Position, base.Map, filth_Slime, Rand.Range(8, 12)); + foreach (Building_AncientCryptosleepCasket item in UnopenedCasketsInGroup()) + { + item.contentsKnown = true; + item.EjectContents(); + } + IEnumerable enumerable = from p in list.OfType().ToList() + where p.RaceProps.Humanlike && p.GetLord() == null && p.Faction == Faction.OfAncientsHostile + select p; + if (enumerable.Any()) + { + LordMaker.MakeNewLord(Faction.OfAncientsHostile, new LordJob_AssaultColony(Faction.OfAncientsHostile, canKidnap: false, canTimeoutOrFlee: true, sappers: false, useAvoidGridSmart: false, canSteal: false), base.Map, enumerable); + } + } + + private IEnumerable UnopenedCasketsInGroup() + { + yield return this; + if (groupID == -1) + { + yield break; + } + foreach (Thing item in base.Map.listerThings.ThingsOfDef(ThingDefOf.AncientCryptosleepCasket)) + { + Building_AncientCryptosleepCasket building_AncientCryptosleepCasket = item as Building_AncientCryptosleepCasket; + if (building_AncientCryptosleepCasket.groupID == groupID && !building_AncientCryptosleepCasket.contentsKnown) + { + yield return building_AncientCryptosleepCasket; + } + } + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\ComplexThreatWorker_CryptosleepPods.txt` +**相似度:** 0.6424 + +```csharp +public class ComplexThreatWorker_CryptosleepPods : ComplexThreatWorker +{ + private const string TriggerOpenAction = "TriggerOpenAction"; + + private const string CompletedOpenAction = "CompletedOpenAction"; + + private const float RoomEntryTriggerChance = 0.25f; + + protected override bool CanResolveInt(ComplexResolveParams parms) + { + if (base.CanResolveInt(parms) && ComplexUtility.TryFindRandomSpawnCell(ThingDefOf.AncientCryptosleepPod, parms.room, parms.map, out var _) && parms.points >= PawnKindDefOf.AncientSoldier.combatPower) + { + if (parms.hostileFaction != null) + { + return parms.hostileFaction == Faction.OfAncientsHostile; + } + return true; + } + return false; + } + + protected override void ResolveInt(ComplexResolveParams parms, ref float threatPointsUsed, List outSpawnedThings) + { + List list = SpawnCasketsWithHostiles(parms.room, parms.points, parms.triggerSignal, parms.map); + SignalAction_OpenCasket signalAction_OpenCasket = (SignalAction_OpenCasket)ThingMaker.MakeThing(ThingDefOf.SignalAction_OpenCasket); + signalAction_OpenCasket.signalTag = parms.triggerSignal; + signalAction_OpenCasket.caskets.AddRange(list); + signalAction_OpenCasket.completedSignalTag = "CompletedOpenAction" + Find.UniqueIDsManager.GetNextSignalTagID(); + if (parms.delayTicks.HasValue) + { + signalAction_OpenCasket.delayTicks = parms.delayTicks.Value; + SignalAction_Message obj = (SignalAction_Message)ThingMaker.MakeThing(ThingDefOf.SignalAction_Message); + obj.signalTag = parms.triggerSignal; + obj.lookTargets = list; + obj.messageType = MessageTypeDefOf.ThreatBig; + obj.message = "MessageSleepingThreatDelayActivated".Translate(Faction.OfAncientsHostile, signalAction_OpenCasket.delayTicks.ToStringTicksToPeriod()); + GenSpawn.Spawn(obj, parms.room.rects[0].CenterCell, parms.map); + } + GenSpawn.Spawn(signalAction_OpenCasket, parms.map.Center, parms.map); + for (int i = 0; i < list.Count; i++) + { + if (!(list[i] is Building_Casket building_Casket)) + { + continue; + } + foreach (Thing item in (IEnumerable)building_Casket.GetDirectlyHeldThings()) + { + if (item is Pawn pawn) + { + threatPointsUsed += pawn.kindDef.combatPower; + } + } + } + SignalAction_Message obj2 = (SignalAction_Message)ThingMaker.MakeThing(ThingDefOf.SignalAction_Message); + obj2.signalTag = signalAction_OpenCasket.completedSignalTag; + obj2.lookTargets = list; + obj2.messageType = MessageTypeDefOf.ThreatBig; + obj2.message = "MessageSleepingPawnsWokenUp".Translate(Faction.OfAncientsHostile.def.pawnsPlural.CapitalizeFirst()); + GenSpawn.Spawn(obj2, parms.room.rects[0].CenterCell, parms.map); + } + + private List SpawnCasketsWithHostiles(LayoutRoom room, float threatPoints, string openSignal, Map map) + { + int num = Mathf.FloorToInt(threatPoints / PawnKindDefOf.AncientSoldier.combatPower); + List list = new List(); + for (int i = 0; i < num; i++) + { + if (!ComplexUtility.TryFindRandomSpawnCell(ThingDefOf.AncientCryptosleepPod, room, map, out var spawnPosition)) + { + break; + } + Building_AncientCryptosleepPod building_AncientCryptosleepPod = (Building_AncientCryptosleepPod)GenSpawn.Spawn(ThingDefOf.AncientCryptosleepPod, spawnPosition, map); + building_AncientCryptosleepPod.groupID = Find.UniqueIDsManager.GetNextAncientCryptosleepCasketGroupID(); + building_AncientCryptosleepPod.openedSignal = openSignal; + ThingSetMakerParams parms = default(ThingSetMakerParams); + parms.podContentsType = PodContentsType.AncientHostile; + List list2 = ThingSetMakerDefOf.MapGen_AncientPodContents.root.Generate(parms); + for (int j = 0; j < list2.Count; j++) + { + Pawn pawn = list2[j] as Pawn; + if (!building_AncientCryptosleepPod.TryAcceptThing(list2[j], allowSpecialEffects: false)) + { + if (pawn != null) + { + Find.WorldPawns.PassToWorld(pawn, PawnDiscardDecideMode.Discard); + } + else + { + list2[i].Destroy(); + } + } + } + list.Add(building_AncientCryptosleepPod); + } + return list; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Core\Defs\ThingDefs_Buildings\Buildings_Ancient_Active.xml` +**相似度:** 0.6040 + +```xml + + AncientCryptosleepPod + + Building_AncientCryptosleepPod + true + A single-use pod for preserving one person in a state of suspended animation. Unlike cryptosleep caskets, cryptosleep pods can only be used once. + + Things/Building/Ruins/AncientCryptosleepPod + Graphic_Multi + + + false + false + + + false + + 2000 + 200 + + + + + +``` \ No newline at end of file diff --git a/MCP/vector_cache/HediffDef-Luciferium.txt b/MCP/vector_cache/HediffDef-Luciferium.txt new file mode 100644 index 00000000..b421e522 --- /dev/null +++ b/MCP/vector_cache/HediffDef-Luciferium.txt @@ -0,0 +1,118 @@ +根据向量相似度分析,与 'HediffDef, Luciferium' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\Core\Defs\Drugs\Luciferium.xml` + +```xml + Luciferium + + A concoction of mechanites that dramatically improve the body's functioning in all respects. Over time, it can even heal old scarred-over wounds or brain damage, though it cannot regenerate lost limbs. Unfortunately, without the moderating effects of regular doses every five or six days, the mechanites lose cohesion, causing continuous berserk rages and, eventually, death.\n\nAfter the first dose, there is no way to get the mechanites out, ever.\n\nOn the urbworlds, they call Luciferium the 'Devil's Bargain'. Many have been forced to kill friends when no more of the seductive red pills could be found. + + LuciferiumHigh + LuciferiumAddiction + + + Things/Item/Drug/Luciferium + Graphic_StackCount + + false + + 70 + 0.01 + + Ultra + 10 + + Medical + +
  • + LuciferiumHigh + 1.00 + true +
  • +
    +
    + +
  • + Luciferium + 1.00 + 0.9 + 1010 +
  • +
    + +
  • ExoticMisc
  • +
    +
  • RewardStandardCore
  • + 50 +
    + + + LuciferiumHigh +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Anomaly\Defs\Misc\Mutants.xml` +**相似度:** 0.5154 + +```xml + + +
  • AllWork
  • +
  • Shooting
  • +
    + true + false + false + + true + true + true + true + true + true + true + true + true + true + true + true + false + true + true + true + true + true + true + false + false + +
  • CryptosleepSickness
  • +
  • LuciferiumHigh
  • +
  • LuciferiumAddiction
  • +
  • Scaria
  • +
  • CorpseTorment
  • +
  • CubeInterest
  • +
  • CubeWithdrawal
  • +
  • CubeComa
  • +
  • CubeRage
  • +
  • HeartAttack
  • +
  • Scaria
  • +
  • PsychicAmplifier
  • +
  • MechlinkImplant
  • +
  • PregnantHuman
  • +
  • PregnancyLabor
  • +
  • HemogenAmplified
  • +
  • DeathrestExhaustion
  • +
  • InterruptedDeathrest
  • +
  • HemogenCraving
  • +
  • Deathrest
  • +
  • RegenerationComa
  • +
  • PostpartumExhaustion
  • +
  • Inhumanized
  • +
    + +
  • Hemogenic
  • +
  • Deathrest
  • +
    +
    +``` \ No newline at end of file diff --git a/MCP/vector_cache/HediffDef-Malnutrition.txt b/MCP/vector_cache/HediffDef-Malnutrition.txt new file mode 100644 index 00000000..b318bf38 --- /dev/null +++ b/MCP/vector_cache/HediffDef-Malnutrition.txt @@ -0,0 +1,750 @@ +根据向量相似度分析,与 'HediffDef, Malnutrition' 最相关的代码定义如下: + +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Core\Defs\HediffDefs\Hediffs_Global_Needs.xml` +**相似度:** 0.8237 + +```xml + + Malnutrition + + Abnormally low body fat and weight, typically caused by lack of food. Malnutrition is always very unpleasant, but its initial effects are mild. Without food, though, a malnourished creature will waste away, losing muscle mass and capacities. Malnutrition ends with death. Upon re-feeding malnutrition naturally recovers over time. Malnourished creatures have larger appetites than normal. + 1 + true + +
  • + + 1.5 + 0.5 + +
  • + Consciousness + -0.05 +
  • + + +
  • + 0.2 + + 2 + 0.6 + +
  • + Consciousness + -0.10 +
  • + + +
  • + 0.4 + + 2.5 + 0.6 + +
  • + Consciousness + -0.20 +
  • + + +
  • + 0.6 + + 3 + 0.6 + +
  • + Consciousness + -0.30 +
  • + + +
  • + 0.8 + + true + 0.6 + +
  • + Consciousness + 0.1 +
  • + + +
    +
    +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\StatPart_Malnutrition.txt` +**相似度:** 0.7310 + +```csharp +public class StatPart_Malnutrition : StatPart +{ + private SimpleCurve curve; + + public override void TransformValue(StatRequest req, ref float val) + { + if (TryGetMalnutritionFactor(req, out var _, out var factor)) + { + val *= factor; + } + } + + public override string ExplanationPart(StatRequest req) + { + if (TryGetMalnutritionFactor(req, out var malnutritionSeverity, out var factor)) + { + return "StatsReport_Malnutrition".Translate(malnutritionSeverity.ToStringPercent()) + ": x" + factor.ToStringPercent(); + } + return null; + } + + private bool TryGetMalnutritionFactor(StatRequest req, out float malnutritionSeverity, out float factor) + { + factor = 0f; + malnutritionSeverity = 0f; + if (!req.HasThing || !(req.Thing is Pawn pawn)) + { + return false; + } + Hediff firstHediffOfDef = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.Malnutrition); + if (firstHediffOfDef == null) + { + return false; + } + malnutritionSeverity = firstHediffOfDef.Severity; + factor = curve.Evaluate(malnutritionSeverity); + return true; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\Need_Food.txt` +**相似度:** 0.6580 + +```csharp +public class Need_Food : Need +{ + public int lastNonStarvingTick = -99999; + + public const float BaseFoodFallPerTick = 2.6666667E-05f; + + private const float BaseMalnutritionSeverityPerDay = 0.453f; + + private const float BaseMalnutritionSeverityPerInterval = 0.0011325f; + + private CompHoldingPlatformTarget platformComp; + + public bool Starving => CurCategory == HungerCategory.Starving; + + public float PercentageThreshUrgentlyHungry => pawn.RaceProps.FoodLevelPercentageWantEat * 0.4f; + + public float PercentageThreshHungry => pawn.RaceProps.FoodLevelPercentageWantEat * 0.8f; + + public float NutritionBetweenHungryAndFed => (1f - PercentageThreshHungry) * MaxLevel; + + private CompHoldingPlatformTarget PlatformTarget => platformComp ?? (platformComp = pawn.TryGetComp()); + + public HungerCategory CurCategory + { + get + { + if (base.CurLevelPercentage <= 0f) + { + return HungerCategory.Starving; + } + if (base.CurLevelPercentage < PercentageThreshUrgentlyHungry) + { + return HungerCategory.UrgentlyHungry; + } + if (base.CurLevelPercentage < PercentageThreshHungry) + { + return HungerCategory.Hungry; + } + return HungerCategory.Fed; + } + } + + public float FoodFallPerTick => FoodFallPerTickAssumingCategory(CurCategory); + + public int TicksUntilHungryWhenFed => Mathf.CeilToInt(NutritionBetweenHungryAndFed / FoodFallPerTickAssumingCategory(HungerCategory.Fed)); + + public int TicksUntilHungryWhenFedIgnoringMalnutrition => Mathf.CeilToInt(NutritionBetweenHungryAndFed / FoodFallPerTickAssumingCategory(HungerCategory.Fed, ignoreMalnutrition: true)); + + public override int GUIChangeArrow + { + get + { + if (GainingFood()) + { + return 1; + } + if (!(FoodFallPerTickAssumingCategory(HungerCategory.Hungry) > 0f)) + { + return 0; + } + return -1; + } + } + + public override float MaxLevel + { + get + { + if (Current.ProgramState != ProgramState.Playing) + { + return pawn.BodySize * pawn.ageTracker.CurLifeStage.foodMaxFactor; + } + return pawn.GetStatValue(StatDefOf.MaxNutrition, applyPostProcess: true, 15); + } + } + + public float NutritionWanted => MaxLevel - CurLevel; + + public int TicksStarving => Mathf.Max(0, Find.TickManager.TicksGame - lastNonStarvingTick); + + private float MalnutritionSeverityPerInterval => 0.0011325f * Mathf.Lerp(0.8f, 1.2f, Rand.ValueSeeded(pawn.thingIDNumber ^ 0x26EF7A)); + + protected override bool IsFrozen + { + get + { + if (!base.IsFrozen && !pawn.Deathresting) + { + return PlatformTarget?.CurrentlyHeldOnPlatform ?? false; + } + return true; + } + } + + public Need_Food(Pawn pawn) + : base(pawn) + { + } + + public bool GainingFood() + { + if (pawn.jobs?.curDriver is IEatingDriver { GainingNutritionNow: not false }) + { + return true; + } + if (ModsConfig.BiotechActive && ChildcareUtility.CanSuckle(pawn, out var _) && pawn.CarriedBy?.jobs.curDriver is JobDriver_FeedBaby { Feeding: not false }) + { + return true; + } + return false; + } + + public float FoodFallPerTickAssumingCategory(HungerCategory hunger, bool ignoreMalnutrition = false) + { + Building_Bed building_Bed = pawn.CurrentBed(); + float num = BaseHungerRate(pawn.ageTracker.CurLifeStage, pawn.def) * hunger.HungerMultiplier() * pawn.health.hediffSet.GetHungerRateFactor(ignoreMalnutrition ? HediffDefOf.Malnutrition : null) * (pawn.story?.traits?.HungerRateFactor ?? 1f) * (building_Bed?.GetStatValue(StatDefOf.BedHungerRateFactor) ?? 1f); + if (ModsConfig.BiotechActive) + { + Hediff firstHediffOfDef = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.Lactating); + if (firstHediffOfDef != null) + { + HediffComp_Lactating hediffComp_Lactating = firstHediffOfDef.TryGetComp(); + if (hediffComp_Lactating != null) + { + num += hediffComp_Lactating.AddedNutritionPerDay() / 60000f; + } + } + } + if (ModsConfig.BiotechActive && pawn.genes != null) + { + int num2 = 0; + foreach (Gene item in pawn.genes.GenesListForReading) + { + if (!item.Overridden) + { + num2 += item.def.biostatMet; + } + } + num *= GeneTuning.MetabolismToFoodConsumptionFactorCurve.Evaluate(num2); + } + if (ModsConfig.AnomalyActive) + { + CompHoldingPlatformTarget platformTarget = PlatformTarget; + if (platformTarget != null && platformTarget.CurrentlyHeldOnPlatform) + { + num = 0f; + } + } + return num; + } + + public override void NeedInterval() + { + if (!IsFrozen) + { + CurLevel -= FoodFallPerTick * 150f; + } + if (!Starving) + { + lastNonStarvingTick = Find.TickManager.TicksGame; + } + if (!IsFrozen || pawn.Deathresting) + { + if (Starving) + { + HealthUtility.AdjustSeverity(pawn, HediffDefOf.Malnutrition, MalnutritionSeverityPerInterval); + } + else + { + HealthUtility.AdjustSeverity(pawn, HediffDefOf.Malnutrition, 0f - MalnutritionSeverityPerInterval); + } + } + } + + public override void SetInitialLevel() + { + StatDefOf.MaxNutrition.Worker.ClearCacheForThing(pawn); + base.CurLevelPercentage = (pawn.RaceProps.Humanlike ? 0.8f : Rand.Range(0.5f, 0.9f)); + if (Current.ProgramState == ProgramState.Playing) + { + lastNonStarvingTick = Find.TickManager.TicksGame; + } + } + + public override void OnNeedRemoved() + { + if (pawn.health.hediffSet.TryGetHediff(HediffDefOf.Malnutrition, out var hediff)) + { + pawn.health.RemoveHediff(hediff); + } + } + + public override string GetTipString() + { + return (base.LabelCap + ": " + base.CurLevelPercentage.ToStringPercent()).Colorize(ColoredText.TipSectionTitleColor) + " (" + CurLevel.ToString("0.##") + " / " + MaxLevel.ToString("0.##") + ")\n" + def.description; + } + + public override void DrawOnGUI(Rect rect, int maxThresholdMarkers = int.MaxValue, float customMargin = -1f, bool drawArrows = true, bool doTooltip = true, Rect? rectForTooltip = null, bool drawLabel = true) + { + if (threshPercents == null) + { + threshPercents = new List(); + } + threshPercents.Clear(); + threshPercents.Add(PercentageThreshHungry); + threshPercents.Add(PercentageThreshUrgentlyHungry); + base.DrawOnGUI(rect, maxThresholdMarkers, customMargin, drawArrows, doTooltip, rectForTooltip, drawLabel); + } + + public static float BaseHungerRate(LifeStageDef lifeStage, ThingDef pawnDef) + { + return lifeStage.hungerRateFactor * pawnDef.race.baseHungerRate * 2.6666667E-05f; + } + + public override void ExposeData() + { + base.ExposeData(); + Scribe_Values.Look(ref lastNonStarvingTick, "lastNonStarvingTick", -99999); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\HediffDefOf.txt` +**相似度:** 0.6514 + +```csharp +public static class HediffDefOf +{ + public static HediffDef Cut; + + public static HediffDef SurgicalCut; + + public static HediffDef ExecutionCut; + + public static HediffDef Bite; + + public static HediffDef MissingBodyPart; + + public static HediffDef Misc; + + [MayRequireBiotech] + public static HediffDef BloodfeederMark; + + [MayRequireAnomaly] + public static HediffDef Decayed; + + [MayRequireAnomaly] + public static HediffDef Digested; + + [MayRequireOdyssey] + public static HediffDef PorcupineQuill; + + public static HediffDef BloodLoss; + + public static HediffDef Hypothermia; + + public static HediffDef Heatstroke; + + public static HediffDef Malnutrition; + + public static HediffDef ToxicBuildup; + + public static HediffDef PsychicShock; + + public static HediffDef ResurrectionSickness; + + public static HediffDef ResurrectionPsychosis; + + [MayRequireBiotech] + public static HediffDef PollutionStimulus; + + [MayRequireBiotech] + public static HediffDef ToxGasExposure; + + [MayRequireAnomaly] + public static HediffDef Shambler; + + [MayRequireAnomaly] + public static HediffDef ShamblerCorpse; + + [MayRequireAnomaly] + public static HediffDef Rising; + + [MayRequireAnomaly] + public static HediffDef DeathRefusal; + + [MayRequireAnomaly] + public static HediffDef DeathRefusalSickness; + + [MayRequireAnomaly] + public static HediffDef MetalhorrorImplant; + + [MayRequireAnomaly] + public static HediffDef MetalhorrorSpeedBoost; + + [MayRequireAnomaly] + public static HediffDef PsychicTrance; + + [MayRequireAnomaly] + public static HediffDef DuplicateSickness; + + [MayRequireAnomaly] + public static HediffDef VoidTouched; + + [MayRequireAnomaly] + public static HediffDef MeatHunger; + + [MayRequireAnomaly] + public static HediffDef ShardHolder; + + [MayRequireAnomaly] + public static HediffDef Inhumanized; + + [MayRequireAnomaly] + public static HediffDef DarknessExposure; + + [MayRequireAnomaly] + public static HediffDef LightExposure; + + [MayRequireAnomaly] + public static HediffDef DisruptorFlash; + + [MayRequireOdyssey] + public static HediffDef VacuumExposure; + + [MayRequireOdyssey] + public static HediffDef PsilocapHigh; + + [MayRequireOdyssey] + public static HediffDef GravNausea; + + [MayRequireOdyssey] + public static HediffDef VolcanicAsh; + + public static HediffDef Anesthetic; + + public static HediffDef CryptosleepSickness; + + public static HediffDef FoodPoisoning; + + public static HediffDef Pregnant; + + [MayRequireBiotech] + public static HediffDef PregnantHuman; + + [MayRequireBiotech] + public static HediffDef MorningSickness; + + [MayRequireBiotech] + public static HediffDef PregnancyMood; + + [MayRequireBiotech] + public static HediffDef PregnancyLabor; + + [MayRequireBiotech] + public static HediffDef PregnancyLaborPushing; + + [MayRequireBiotech] + public static HediffDef OvumExtracted; + + [MayRequireBiotech] + public static HediffDef VatLearning; + + [MayRequireBiotech] + public static HediffDef VatGrowing; + + public static HediffDef CatatonicBreakdown; + + public static HediffDef Scaria; + + [MayRequireIdeology] + public static HediffDef Scarification; + + [MayRequireIdeology] + public static HediffDef NeuralSupercharge; + + [MayRequireIdeology] + public static HediffDef BiosculptingSickness; + + [MayRequireRoyalty] + public static HediffDef PsychicEntropy; + + [MayRequireRoyalty] + public static HediffDef PsychicHangover; + + [MayRequireRoyalty] + public static HediffDef PsychicSuppression; + + [MayRequireRoyalty] + public static HediffDef Abasia; + + [MayRequireRoyalty] + public static HediffDef PsychicLove; + + public static HediffDef Sterilized; + + [MayRequireBiotech] + public static HediffDef Vasectomy; + + [MayRequireBiotech] + public static HediffDef ImplantedIUD; + + [MayRequireIdeology] + public static HediffDef WorkFocus; + + [MayRequireBiotech] + public static HediffDef ScanningSickness; + + [MayRequireBiotech] + public static HediffDef PsychicBond; + + [MayRequireBiotech] + public static HediffDef PsychicBondTorn; + + public static HediffDef LungRot; + + public static HediffDef LungRotExposure; + + public static HediffDef CoveredInFirefoam; + + [MayRequireAnomaly] + public static HediffDef BioferriteExtracted; + + public static HediffDef Plague; + + public static HediffDef WoundInfection; + + public static HediffDef ScariaInfection; + + public static HediffDef AlcoholHigh; + + public static HediffDef Hangover; + + public static HediffDef DrugOverdose; + + public static HediffDef WakeUpTolerance; + + public static HediffDef GoJuiceTolerance; + + public static HediffDef Blindness; + + public static HediffDef Carcinoma; + + public static HediffDef Dementia; + + public static HediffDef OrganDecay; + + [MayRequireBiotech] + public static HediffDef DetoxifierLung; + + [MayRequireRoyalty] + public static HediffDef LoveEnhancer; + + [MayRequireRoyalty] + public static HediffDef PsychicAmplifier; + + [MayRequireRoyalty] + public static HediffDef PsychicHarmonizer; + + [MayRequireBiotech] + public static HediffDef MechlinkImplant; + + [MayRequireBiotech] + public static HediffDef SelfShutdown; + + [MayRequireBiotech] + public static HediffDef InterruptedDeathrest; + + [MayRequireBiotech] + public static HediffDef InfantIllness; + + [MayRequireBiotech] + public static HediffDef Stillborn; + + [MayRequireBiotech] + public static HediffDef PostpartumExhaustion; + + [MayRequireBiotech] + public static HediffDef Lactating; + + [MayRequireBiotech] + public static HediffDef RegenerationComa; + + [MayRequireBiotech] + public static HediffDef XenogermLossShock; + + [MayRequireBiotech] + public static HediffDef XenogermReplicating; + + [MayRequireBiotech] + public static HediffDef GeneticDrugNeed; + + [MayRequireBiotech] + public static HediffDef BioStarvation; + + [MayRequireBiotech] + public static HediffDef XenogerminationComa; + + [MayRequireBiotech] + public static HediffDef Deathrest; + + [MayRequireBiotech] + public static HediffDef DeathrestExhaustion; + + [MayRequireBiotech] + public static HediffDef BandNode; + + [MayRequireBiotech] + public static HediffDef HemogenCraving; + + [MayRequireAnomaly] + public static HediffDef HoraxianInvisibility; + + [MayRequireAnomaly] + public static HediffDef RevenantHypnosis; + + [MayRequireAnomaly] + public static HediffDef AwokenHypnosis; + + [MayRequireAnomaly] + public static HediffDef DarkPsychicShock; + + [MayRequireAnomaly] + public static HediffDef Tentacle; + + [MayRequireAnomaly] + public static HediffDef FleshWhip; + + [MayRequireAnomaly] + public static HediffDef OrganDecayUndiagnosedDuplicaton; + + [MayRequireAnomaly] + public static HediffDef CrumblingMindUndiagnosedDuplication; + + [MayRequireAnomaly] + public static HediffDef OrganDecayCreepjoiner; + + [MayRequireAnomaly] + public static HediffDef CrumblingMind; + + [MayRequireAnomaly] + public static HediffDef CrumbledMind; + + [MayRequireAnomaly] + public static HediffDef BlissLobotomy; + + [MayRequireAnomaly] + public static HediffDef PleasurePulse; + + [MayRequireAnomaly] + public static HediffDef NeurosisPulse; + + [MayRequireAnomaly] + public static HediffDef BloodRage; + + [MayRequireAnomaly] + public static HediffDef FrenzyField; + + [MayRequireAnomaly] + public static HediffDef AgonyPulse; + + [MayRequireAnomaly] + public static HediffDef CubeInterest; + + [MayRequireAnomaly] + public static HediffDef CubeWithdrawal; + + [MayRequireAnomaly] + public static HediffDef CubeRage; + + [MayRequireAnomaly] + public static HediffDef CubeComa; + + [MayRequireAnomaly] + public static HediffDef BrainwipeComa; + + [MayRequireAnomaly] + public static HediffDef CorpseTorment; + + [MayRequireAnomaly] + public static HediffDef PsychicallyDead; + + [MayRequireAnomaly] + public static HediffDef Psychophage; + + [MayRequireAnomaly] + public static HediffDef SleepSuppression; + + [MayRequireAnomaly] + public static HediffDef RageSpeed; + + [MayRequireAnomaly] + public static HediffDef AwokenCorpse; + + [MayRequireAnomaly] + public static HediffDef RapidRegeneration; + + [MayRequireAnomaly] + public static HediffDef GhoulBarbs; + + [MayRequireAnomaly] + public static HediffDef GhoulPlating; + + [MayRequireAnomaly] + public static HediffDef AdrenalHeart; + + [MayRequireAnomaly] + public static HediffDef FleshmassStomach; + + [MayRequireAnomaly] + public static HediffDef FleshmassLung; + + [MayRequireAnomaly] + public static HediffDef Metalblood; + + [MayRequireOdyssey] + public static HediffDef SentienceCatalyst; + + static HediffDefOf() + { + DefOfHelper.EnsureInitializedInCtor(typeof(HediffDefOf)); + } +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/Human-ThingDef.txt b/MCP/vector_cache/Human-ThingDef.txt new file mode 100644 index 00000000..ac72ecd3 --- /dev/null +++ b/MCP/vector_cache/Human-ThingDef.txt @@ -0,0 +1,2691 @@ +根据向量相似度分析,与 'Human, ThingDef' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\ThingDef.txt` + +```csharp +public class ThingDef : BuildableDef +{ + public Type thingClass; + + public ThingCategory category; + + public TickerType tickerType; + + public int stackLimit = 1; + + public IntVec2 size = IntVec2.One; + + public bool destroyable = true; + + public bool rotatable = true; + + public bool smallVolume; + + public bool useHitPoints = true; + + public bool receivesSignals; + + public List comps = new List(); + + public List virtualDefs = new List(); + + public ThingDef virtualDefParent; + + [NoTranslate] + public string devNote; + + public List killedLeavingsRanges; + + public List killedLeavings; + + public List killedLeavingsPlayerHostile; + + public float killedLeavingsChance = 1f; + + public bool forceLeavingsAllowed; + + public List butcherProducts; + + public List smeltProducts; + + public bool smeltable; + + public bool burnableByRecipe; + + public bool randomizeRotationOnSpawn; + + public List damageMultipliers; + + public bool isTechHediff; + + public RecipeMakerProperties recipeMaker; + + public ThingDef minifiedDef; + + public bool isUnfinishedThing; + + public bool leaveResourcesWhenKilled; + + public ThingDef slagDef; + + public bool isFrameInt; + + public List multipleInteractionCellOffsets; + + public IntVec3 interactionCellOffset = IntVec3.Zero; + + public bool hasInteractionCell; + + public ThingDef interactionCellIcon; + + public bool interactionCellIconReverse; + + public ThingDef filthLeaving; + + public bool forceDebugSpawnable; + + public bool intricate; + + public bool scatterableOnMapGen = true; + + public float deepCommonality; + + public int deepCountPerCell = 300; + + public int deepCountPerPortion = -1; + + public IntRange deepLumpSizeRange = IntRange.Zero; + + public float generateCommonality = 1f; + + public float generateAllowChance = 1f; + + private bool canOverlapZones = true; + + public FloatRange startingHpRange = FloatRange.One; + + [NoTranslate] + public List thingSetMakerTags; + + public bool alwaysFlee; + + public List recipes; + + public bool messageOnDeteriorateInStorage = true; + + public bool deteriorateFromEnvironmentalEffects = true; + + public bool canDeteriorateUnspawned; + + public bool canLoadIntoCaravan = true; + + public bool isMechClusterThreat; + + public FloatRange displayNumbersBetweenSameDefDistRange = FloatRange.Zero; + + public int minRewardCount = 1; + + public bool preventSkyfallersLandingOn; + + public FactionDef requiresFactionToAcquire; + + public float relicChance; + + public OrderedTakeGroupDef orderedTakeGroup; + + public int allowedArchonexusCount; + + public int possessionCount; + + public bool notifyMapRemoved; + + public bool canScatterOver = true; + + public bool genericMarketSellable = true; + + public bool drawHighlight; + + public Color? highlightColor; + + public bool drawHighlightOnlyForHostile; + + public bool autoTargetNearbyIdenticalThings; + + public bool preventDroppingThingsOn; + + public bool hiddenWhileUndiscovered; + + public bool disableImpassableShotOverConfigError; + + public bool showInSearch = true; + + public bool bringAlongOnGravship = true; + + public ThingDef dropPodFaller; + + public bool preventSpawningInResourcePod; + + public bool pathfinderDangerous; + + public bool noRightClickDraftAttack; + + public int gravshipSpawnPriority = 1; + + public List replaceTags; + + public GraphicData graphicData; + + public DrawerType drawerType = DrawerType.RealtimeOnly; + + public bool drawOffscreen; + + public ColorGenerator colorGenerator; + + public float hideAtSnowOrSandDepth = 99999f; + + public bool drawDamagedOverlay = true; + + public bool castEdgeShadows; + + public float staticSunShadowHeight; + + public bool useSameGraphicForGhost; + + public bool useBlueprintGraphicAsGhost; + + public List randomStyle; + + public float randomStyleChance; + + public bool canEditAnyStyle; + + public bool dontPrint; + + public ThingDef defaultStuff; + + public int killedLeavingsExpandRect; + + public bool minifiedManualDraw; + + public float minifiedDrawScale = 1f; + + public Rot4 overrideMinifiedRot = Rot4.Invalid; + + public Vector3 minifiedDrawOffset = Vector3.zero; + + public float deselectedSelectionBracketFactor = 1f; + + public bool selectable; + + public bool containedPawnsSelectable; + + public bool containedItemsSelectable; + + public bool neverMultiSelect; + + public bool isAutoAttackableMapObject; + + public bool hasTooltip; + + public List inspectorTabs; + + [Unsaved(false)] + public List inspectorTabsResolved; + + public bool seeThroughFog; + + public bool drawGUIOverlay; + + public bool drawGUIOverlayQuality = true; + + public ResourceCountPriority resourceReadoutPriority; + + public bool resourceReadoutAlwaysShow; + + public bool drawPlaceWorkersWhileSelected; + + public bool drawPlaceWorkersWhileInstallBlueprintSelected; + + public ConceptDef storedConceptLearnOpportunity; + + public float uiIconScale = 1f; + + public bool hasCustomRectForSelector; + + public bool hideStats; + + public bool hideInspect; + + public bool onlyShowInspectString; + + public bool hideMainDesc; + + public bool alwaysHaulable; + + public bool designateHaulable; + + public List thingCategories; + + public bool mineable; + + public bool socialPropernessMatters; + + public bool stealable = true; + + public SoundDef soundSpawned; + + public SoundDef soundDrop; + + public SoundDef soundPickup; + + public SoundDef soundInteract; + + public SoundDef soundImpactDefault; + + public SoundDef soundPlayInstrument; + + public SoundDef soundOpen; + + public bool saveCompressible; + + public bool isSaveable = true; + + public bool holdsRoof; + + public float fillPercent; + + public bool coversFloor; + + public bool neverOverlapFloors; + + public SurfaceType surfaceType; + + public bool wipesPlants; + + public bool blockPlants; + + public bool blockLight; + + public bool blockWind; + + public bool blockWeather; + + public Tradeability tradeability = Tradeability.All; + + [NoTranslate] + public List tradeTags; + + public bool tradeNeverStack; + + public bool tradeNeverGenerateStacked; + + public bool healthAffectsPrice = true; + + public ColorGenerator colorGeneratorInTraderStock; + + private List verbs; + + public List tools; + + public float equippedAngleOffset; + + public float equippedDistanceOffset; + + public EquipmentType equipmentType; + + public TechLevel techLevel; + + public List weaponClasses; + + [NoTranslate] + public List weaponTags; + + [NoTranslate] + public List techHediffsTags; + + public bool violentTechHediff; + + public bool destroyOnDrop; + + public List equippedStatOffsets; + + public SoundDef meleeHitSound; + + public float recoilPower = 1f; + + public float recoilRelaxation = 10f; + + public bool rotateInShelves = true; + + public bool mergeVerbGizmos = true; + + public BuildableDef entityDefToBuild; + + public ThingDef projectileWhenLoaded; + + public RulePackDef ideoBuildingNamerBase; + + public EntityCodexEntryDef entityCodexEntry; + + public IngestibleProperties ingestible; + + public FilthProperties filth; + + public GasProperties gas; + + public BuildingProperties building; + + public RaceProperties race; + + public ApparelProperties apparel; + + public MoteProperties mote; + + public PlantProperties plant; + + public ProjectileProperties projectile; + + public StuffProperties stuffProps; + + public SkyfallerProperties skyfaller; + + public PawnFlyerProperties pawnFlyer; + + public RitualFocusProperties ritualFocus; + + public IngredientProperties ingredient; + + public MapPortalProperties portal; + + public bool canBeUsedUnderRoof = true; + + [Unsaved(false)] + private string descriptionDetailedCached; + + [Unsaved(false)] + public Graphic interactionCellGraphic; + + [Unsaved(false)] + private bool? isNaturalOrganCached; + + [Unsaved(false)] + private bool? hasSunShadowsCached; + + [Unsaved(false)] + private List cachedRelevantStyleCategories; + + public const int SmallUnitPerVolume = 10; + + public const float SmallVolumePerUnit = 0.1f; + + public const float ArchonexusMaxItemStackMass = 5f; + + public const int ArchonexusMaxItemStackCount = 25; + + public const float ArchonexusMaxItemStackValue = 2000f; + + public const int ArchonexusAutoCalculateValue = -1; + + private List allRecipesCached; + + private static List EmptyVerbPropertiesList = new List(); + + private Dictionary concreteExamplesInt; + + public bool EverHaulable + { + get + { + if (!alwaysHaulable) + { + return designateHaulable; + } + return true; + } + } + + public bool EverPollutable => !building.isNaturalRock; + + public float VolumePerUnit + { + get + { + if (smallVolume) + { + return 0.1f; + } + return 1f; + } + } + + public override IntVec2 Size => size; + + public bool DiscardOnDestroyed => race == null; + + public int BaseMaxHitPoints => Mathf.RoundToInt(this.GetStatValueAbstract(StatDefOf.MaxHitPoints)); + + public float BaseFlammability => this.GetStatValueAbstract(StatDefOf.Flammability); + + public float BaseMarketValue + { + get + { + return this.GetStatValueAbstract(StatDefOf.MarketValue); + } + set + { + this.SetStatBaseValue(StatDefOf.MarketValue, value); + } + } + + public float BaseMass => this.GetStatValueAbstract(StatDefOf.Mass); + + public int ArchonexusMaxAllowedCount + { + get + { + if (allowedArchonexusCount == -1) + { + return Mathf.Min(stackLimit, 25, (BaseMass > 0f) ? ((int)(5f / BaseMass)) : 0, (BaseMarketValue > 0f) ? ((int)(2000f / BaseMarketValue)) : 0); + } + return allowedArchonexusCount; + } + } + + public bool PlayerAcquirable + { + get + { + if (destroyOnDrop) + { + return false; + } + if (this == ThingDefOf.ReinforcedBarrel && Find.Storyteller != null && Find.Storyteller.difficulty.classicMortars) + { + return false; + } + if (requiresFactionToAcquire != null && Find.World != null && Find.World.factionManager != null) + { + return Find.FactionManager.FirstFactionOfDef(requiresFactionToAcquire) != null; + } + return true; + } + } + + public bool EverTransmitsPower + { + get + { + for (int i = 0; i < comps.Count; i++) + { + if (comps[i] is CompProperties_Power { transmitsPower: not false }) + { + return true; + } + } + return false; + } + } + + public bool Minifiable => minifiedDef != null; + + public bool HasThingIDNumber => category != ThingCategory.Mote; + + public List AllRecipes + { + get + { + if (allRecipesCached == null) + { + allRecipesCached = new List(); + if (recipes != null) + { + for (int i = 0; i < recipes.Count; i++) + { + allRecipesCached.Add(recipes[i]); + } + } + List allDefsListForReading = DefDatabase.AllDefsListForReading; + for (int j = 0; j < allDefsListForReading.Count; j++) + { + if (allDefsListForReading[j].recipeUsers != null && allDefsListForReading[j].recipeUsers.Contains(this)) + { + allRecipesCached.Add(allDefsListForReading[j]); + } + } + } + return allRecipesCached; + } + } + + public bool ConnectToPower + { + get + { + if (EverTransmitsPower) + { + return false; + } + for (int i = 0; i < comps.Count; i++) + { + if (comps[i].compClass == typeof(CompPowerBattery)) + { + return true; + } + if (comps[i].compClass == typeof(CompPowerTrader)) + { + return true; + } + } + return false; + } + } + + public bool CoexistsWithFloors + { + get + { + if (!neverOverlapFloors) + { + return !coversFloor; + } + return false; + } + } + + public FillCategory Fillage + { + get + { + if (fillPercent < 0.01f) + { + return FillCategory.None; + } + if (fillPercent > 0.99f) + { + return FillCategory.Full; + } + return FillCategory.Partial; + } + } + + public bool MakeFog => Fillage == FillCategory.Full; + + public bool CanOverlapZones + { + get + { + if (building != null && building.SupportsPlants) + { + return false; + } + if (passability == Traversability.Impassable && category != ThingCategory.Plant && !HasComp(typeof(CompTransporter))) + { + return false; + } + if ((int)surfaceType >= 1) + { + return false; + } + if (typeof(ISlotGroupParent).IsAssignableFrom(thingClass)) + { + return false; + } + if (!canOverlapZones) + { + return false; + } + if ((IsBlueprint || IsFrame) && entityDefToBuild is ThingDef thingDef) + { + return thingDef.CanOverlapZones; + } + return true; + } + } + + public bool CountAsResource => resourceReadoutPriority != ResourceCountPriority.Uncounted; + + public List Verbs + { + get + { + if (verbs != null) + { + return verbs; + } + return EmptyVerbPropertiesList; + } + } + + public bool CanHaveFaction + { + get + { + if (IsBlueprint || IsFrame) + { + return true; + } + return category switch + { + ThingCategory.Pawn => true, + ThingCategory.Building => true, + _ => false, + }; + } + } + + public bool Claimable + { + get + { + if (building != null && building.claimable) + { + return !building.isNaturalRock; + } + return false; + } + } + + public ThingCategoryDef FirstThingCategory + { + get + { + if (thingCategories.NullOrEmpty()) + { + return null; + } + return thingCategories[0]; + } + } + + public float MedicineTendXpGainFactor => Mathf.Clamp(this.GetStatValueAbstract(StatDefOf.MedicalPotency) * 0.7f, 0.5f, 1f); + + public bool CanEverDeteriorate + { + get + { + if (!useHitPoints) + { + return false; + } + if (category != ThingCategory.Item) + { + if (plant != null) + { + return plant.canDeteriorate; + } + return false; + } + return true; + } + } + + public bool CanInteractThroughCorners + { + get + { + if (category != ThingCategory.Building) + { + return false; + } + if (!holdsRoof) + { + return false; + } + if (building != null && building.isNaturalRock && !IsSmoothed) + { + return false; + } + return true; + } + } + + public bool AffectsRegions + { + get + { + if (passability != Traversability.Impassable && !IsDoor) + { + return IsFence; + } + return true; + } + } + + public bool AffectsReachability + { + get + { + if (AffectsRegions) + { + return true; + } + if (passability == Traversability.Impassable || IsDoor) + { + return true; + } + if (TouchPathEndModeUtility.MakesOccupiedCellsAlwaysReachableDiagonally(this)) + { + return true; + } + return false; + } + } + + public string DescriptionDetailed + { + get + { + if (descriptionDetailedCached == null) + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.Append(description); + if (IsApparel) + { + stringBuilder.AppendLine(); + stringBuilder.AppendLine(); + stringBuilder.AppendLine(string.Format("{0}: {1}", "Layer".Translate(), apparel.GetLayersString())); + stringBuilder.Append(string.Format("{0}: {1}", "Covers".Translate(), apparel.GetCoveredOuterPartsString(BodyDefOf.Human))); + if (equippedStatOffsets != null && equippedStatOffsets.Count > 0) + { + stringBuilder.AppendLine(); + stringBuilder.AppendLine(); + for (int i = 0; i < equippedStatOffsets.Count; i++) + { + if (i > 0) + { + stringBuilder.AppendLine(); + } + StatModifier statModifier = equippedStatOffsets[i]; + stringBuilder.Append($"{statModifier.stat.LabelCap}: {statModifier.ValueToStringAsOffset}"); + } + } + } + descriptionDetailedCached = stringBuilder.ToString(); + } + return descriptionDetailedCached; + } + } + + public bool CanBenefitFromCover + { + get + { + if (category == ThingCategory.Pawn) + { + return true; + } + if (building != null && building.IsTurret) + { + return true; + } + return false; + } + } + + public bool PotentiallySmeltable + { + get + { + if (!smeltable) + { + return false; + } + if (base.MadeFromStuff) + { + foreach (ThingDef item in GenStuff.AllowedStuffsFor(this)) + { + if (item.smeltable) + { + return true; + } + } + return false; + } + return true; + } + } + + public bool HasSingleOrMultipleInteractionCells + { + get + { + if (!hasInteractionCell) + { + return !multipleInteractionCellOffsets.NullOrEmpty(); + } + return true; + } + } + + public bool IsApparel => apparel != null; + + public bool IsBed => typeof(Building_Bed).IsAssignableFrom(thingClass); + + public bool IsWall + { + get + { + if (building != null) + { + return building.isWall; + } + return false; + } + } + + public bool IsCorpse => typeof(Corpse).IsAssignableFrom(thingClass); + + public bool IsFrame => isFrameInt; + + public bool IsBlueprint + { + get + { + if (entityDefToBuild != null) + { + return category == ThingCategory.Ethereal; + } + return false; + } + } + + public bool IsStuff => stuffProps != null; + + public bool IsMedicine => statBases.StatListContains(StatDefOf.MedicalPotency); + + public bool IsDoor => typeof(Building_Door).IsAssignableFrom(thingClass); + + public bool IsFence + { + get + { + if (building != null) + { + return building.isFence; + } + return false; + } + } + + public bool IsFilth => filth != null; + + public bool IsIngestible => ingestible != null; + + public bool IsNutritionGivingIngestible + { + get + { + if (IsIngestible) + { + return ingestible.CachedNutrition > 0f; + } + return false; + } + } + + public bool IsNutritionGivingIngestibleForHumanlikeBabies + { + get + { + if (IsNutritionGivingIngestible && ingestible.HumanEdible) + { + return ingestible.babiesCanIngest; + } + return false; + } + } + + public bool IsWeapon + { + get + { + if (category == ThingCategory.Item && (!verbs.NullOrEmpty() || !tools.NullOrEmpty())) + { + return !IsApparel; + } + return false; + } + } + + public bool IsCommsConsole => typeof(Building_CommsConsole).IsAssignableFrom(thingClass); + + public bool IsOrbitalTradeBeacon => typeof(Building_OrbitalTradeBeacon).IsAssignableFrom(thingClass); + + public bool IsFoodDispenser => typeof(Building_NutrientPasteDispenser).IsAssignableFrom(thingClass); + + public bool IsDrug + { + get + { + if (ingestible != null) + { + return ingestible.drugCategory != DrugCategory.None; + } + return false; + } + } + + public bool IsPleasureDrug + { + get + { + if (IsDrug) + { + return ingestible.joy > 0f; + } + return false; + } + } + + public bool IsNonMedicalDrug + { + get + { + if (IsDrug) + { + return ingestible.drugCategory != DrugCategory.Medical; + } + return false; + } + } + + public bool IsTable + { + get + { + if (surfaceType == SurfaceType.Eat) + { + return HasComp(typeof(CompGatherSpot)); + } + return false; + } + } + + public bool IsWorkTable => typeof(Building_WorkTable).IsAssignableFrom(thingClass); + + public bool IsShell => projectileWhenLoaded != null; + + public bool IsArt => IsWithinCategory(ThingCategoryDefOf.BuildingsArt); + + public bool IsSmoothable => building?.smoothedThing != null; + + public bool IsSmoothed => building?.unsmoothedThing != null; + + public bool IsMetal + { + get + { + if (stuffProps != null) + { + return stuffProps.categories.Contains(StuffCategoryDefOf.Metallic); + } + return false; + } + } + + public bool IsCryptosleepCasket => typeof(Building_CryptosleepCasket).IsAssignableFrom(thingClass); + + public bool IsGibbetCage => typeof(Building_GibbetCage).IsAssignableFrom(thingClass); + + public bool IsMechGestator => typeof(Building_MechGestator).IsAssignableFrom(thingClass); + + public bool IsMechRecharger => typeof(Building_MechCharger).IsAssignableFrom(thingClass); + + public bool IsAddictiveDrug + { + get + { + CompProperties_Drug compProperties = GetCompProperties(); + if (compProperties != null) + { + return compProperties.addictiveness > 0f; + } + return false; + } + } + + public bool IsMeat + { + get + { + if (category == ThingCategory.Item && thingCategories != null) + { + return thingCategories.Contains(ThingCategoryDefOf.MeatRaw); + } + return false; + } + } + + public bool IsEgg + { + get + { + if (category == ThingCategory.Item && thingCategories != null) + { + if (!thingCategories.Contains(ThingCategoryDefOf.EggsFertilized)) + { + return thingCategories.Contains(ThingCategoryDefOf.EggsUnfertilized); + } + return true; + } + return false; + } + } + + public bool IsLeather + { + get + { + if (category == ThingCategory.Item && thingCategories != null) + { + return thingCategories.Contains(ThingCategoryDefOf.Leathers); + } + return false; + } + } + + public bool IsWool + { + get + { + if (category == ThingCategory.Item && thingCategories != null) + { + return thingCategories.Contains(ThingCategoryDefOf.Wools); + } + return false; + } + } + + public bool IsRangedWeapon + { + get + { + if (!IsWeapon) + { + return false; + } + if (!verbs.NullOrEmpty()) + { + for (int i = 0; i < verbs.Count; i++) + { + if (!verbs[i].IsMeleeAttack) + { + return true; + } + } + } + return false; + } + } + + public bool IsMeleeWeapon + { + get + { + if (IsWeapon) + { + return !IsRangedWeapon; + } + return false; + } + } + + public bool IsWeaponUsingProjectiles + { + get + { + if (!IsWeapon) + { + return false; + } + if (!verbs.NullOrEmpty()) + { + for (int i = 0; i < verbs.Count; i++) + { + if (verbs[i].LaunchesProjectile) + { + return true; + } + } + } + return false; + } + } + + public bool IsShieldThatBlocksRanged + { + get + { + if (HasComp(typeof(CompShield))) + { + return GetCompProperties().blocksRangedWeapons; + } + return false; + } + } + + public bool IsBuildingArtificial + { + get + { + if (category == ThingCategory.Building || IsFrame) + { + if (building != null) + { + if (!building.isNaturalRock) + { + return !building.isResourceRock; + } + return false; + } + return true; + } + return false; + } + } + + public bool IsNonResourceNaturalRock + { + get + { + if (category == ThingCategory.Building && building.isNaturalRock && !building.isResourceRock && !building.mineablePreventNaturalRockOnSurface) + { + return !IsSmoothed; + } + return false; + } + } + + public bool HasSunShadows + { + get + { + if (!hasSunShadowsCached.HasValue) + { + hasSunShadowsCached = typeof(Pawn).IsAssignableFrom(thingClass); + } + return hasSunShadowsCached.Value; + } + } + + public bool IsNaturalOrgan + { + get + { + if (!isNaturalOrganCached.HasValue) + { + if (category != ThingCategory.Item) + { + isNaturalOrganCached = false; + } + else + { + List allDefsListForReading = DefDatabase.AllDefsListForReading; + isNaturalOrganCached = false; + for (int i = 0; i < allDefsListForReading.Count; i++) + { + if (allDefsListForReading[i].spawnThingOnRemoved == this) + { + isNaturalOrganCached = true; + break; + } + } + } + } + return isNaturalOrganCached.Value; + } + } + + public bool IsFungus + { + get + { + if (ingestible != null) + { + return ingestible.foodType.HasFlag(FoodTypeFlags.Fungus); + } + return false; + } + } + + public bool IsAnimalProduct + { + get + { + if (ingestible != null) + { + return ingestible.foodType.HasFlag(FoodTypeFlags.AnimalProduct); + } + return false; + } + } + + public bool IsProcessedFood + { + get + { + if (ingestible != null) + { + return ingestible.foodType.HasFlag(FoodTypeFlags.Processed); + } + return false; + } + } + + public bool CanAffectLinker + { + get + { + if (graphicData == null || !graphicData.Linked) + { + return IsDoor; + } + return true; + } + } + + public bool IsNonDeconstructibleAttackableBuilding + { + get + { + if (IsBuildingArtificial && !building.IsDeconstructible && destroyable && !mineable && building.isTargetable) + { + return building.draftAttackNonDeconstructable; + } + return false; + } + } + + public bool IsPlant => typeof(Plant).IsAssignableFrom(thingClass); + + public bool IsDeadPlant => typeof(DeadPlant).IsAssignableFrom(thingClass); + + public bool IsStudiable => HasAssignableCompFrom(typeof(CompStudiable)); + + public List RelevantStyleCategories + { + get + { + if (cachedRelevantStyleCategories == null) + { + cachedRelevantStyleCategories = new List(); + foreach (StyleCategoryDef allDef in DefDatabase.AllDefs) + { + if (allDef.thingDefStyles.NullOrEmpty()) + { + continue; + } + foreach (ThingDefStyle thingDefStyle in allDef.thingDefStyles) + { + if (thingDefStyle.ThingDef == this) + { + cachedRelevantStyleCategories.Add(allDef); + break; + } + } + } + } + return cachedRelevantStyleCategories; + } + } + + public string LabelAsStuff + { + get + { + if (!stuffProps.stuffAdjective.NullOrEmpty()) + { + return stuffProps.stuffAdjective; + } + return label; + } + } + + public bool BlocksPlanting(bool canWipePlants = false) + { + if (building != null && building.SupportsPlants) + { + return false; + } + if (building != null && building.isAttachment) + { + return false; + } + if (blockPlants) + { + return true; + } + if (!canWipePlants && category == ThingCategory.Plant) + { + return true; + } + if ((int)Fillage > 0) + { + return true; + } + if (this.IsEdifice()) + { + return true; + } + return false; + } + + public virtual bool CanSpawnAt(IntVec3 pos, Rot4 rot, Map map) + { + return true; + } + + public bool EverStorable(bool willMinifyIfPossible) + { + if (typeof(MinifiedThing).IsAssignableFrom(thingClass)) + { + return true; + } + if (!thingCategories.NullOrEmpty()) + { + if (category == ThingCategory.Item) + { + return true; + } + if (willMinifyIfPossible && Minifiable) + { + return true; + } + } + return false; + } + + public Thing GetConcreteExample(ThingDef stuff = null) + { + if (concreteExamplesInt == null) + { + concreteExamplesInt = new Dictionary(); + } + if (stuff == null) + { + stuff = ThingDefOf.Steel; + } + if (!concreteExamplesInt.ContainsKey(stuff)) + { + if (race == null) + { + concreteExamplesInt[stuff] = ThingMaker.MakeThing(this, base.MadeFromStuff ? stuff : null); + } + else + { + concreteExamplesInt[stuff] = PawnGenerator.GeneratePawn(DefDatabase.AllDefsListForReading.FirstOrDefault((PawnKindDef pkd) => pkd.race == this)); + } + } + return concreteExamplesInt[stuff]; + } + + public CompProperties CompDefFor() where T : ThingComp + { + for (int i = 0; i < comps.Count; i++) + { + if (comps[i].compClass == typeof(T)) + { + return comps[i]; + } + } + return null; + } + + public CompProperties CompDefForAssignableFrom() where T : ThingComp + { + for (int i = 0; i < comps.Count; i++) + { + if (typeof(T).IsAssignableFrom(comps[i].compClass)) + { + return comps[i]; + } + } + return null; + } + + public bool HasComp(Type compType) + { + for (int i = 0; i < comps.Count; i++) + { + if (comps[i].compClass == compType) + { + return true; + } + } + return false; + } + + public bool HasComp() where T : ThingComp + { + for (int i = 0; i < comps.Count; i++) + { + if (comps[i].compClass == typeof(T) || typeof(T).IsAssignableFrom(comps[i].compClass)) + { + return true; + } + } + return false; + } + + public bool HasAssignableCompFrom(Type compType) + { + for (int i = 0; i < comps.Count; i++) + { + if (compType.IsAssignableFrom(comps[i].compClass)) + { + return true; + } + } + return false; + } + + public T GetCompProperties() where T : CompProperties + { + for (int i = 0; i < comps.Count; i++) + { + if (comps[i] is T result) + { + return result; + } + } + return null; + } + + public override void PostLoad() + { + if (graphicData != null) + { + LongEventHandler.ExecuteWhenFinished(delegate + { + GraphicData graphicData = this.graphicData; + if (graphicData.shaderType == null) + { + graphicData.shaderType = ShaderTypeDefOf.Cutout; + } + ContentFinderRequester.requester = this; + try + { + graphic = this.graphicData.Graphic; + if (drawerType != DrawerType.RealtimeOnly) + { + TextureAtlasGroup textureAtlasGroup = category.ToAtlasGroup(); + graphic.TryInsertIntoAtlas(textureAtlasGroup); + if (textureAtlasGroup == TextureAtlasGroup.Building && Minifiable) + { + graphic.TryInsertIntoAtlas(TextureAtlasGroup.Item); + } + } + } + finally + { + ContentFinderRequester.requester = null; + } + }); + } + if (tools != null) + { + for (int i = 0; i < tools.Count; i++) + { + tools[i].id = i.ToString(); + } + } + if (verbs != null && verbs.Count == 1 && verbs[0].label.NullOrEmpty()) + { + verbs[0].label = label; + } + base.PostLoad(); + if (category == ThingCategory.Building && building == null) + { + building = new BuildingProperties(); + } + building?.PostLoadSpecial(this); + apparel?.PostLoadSpecial(this); + plant?.PostLoadSpecial(this); + if (comps == null) + { + return; + } + foreach (CompProperties comp in comps) + { + comp.PostLoadSpecial(this); + } + } + + protected override void ResolveIcon() + { + base.ResolveIcon(); + if (category == ThingCategory.Pawn) + { + if (!uiIconPath.NullOrEmpty()) + { + uiIcon = ContentFinder.Get(uiIconPath); + } + else + { + if (race.Humanlike) + { + return; + } + PawnKindDef anyPawnKind = race.AnyPawnKind; + if (anyPawnKind != null) + { + Material material = ((ModsConfig.BiotechActive && anyPawnKind.RaceProps.IsMechanoid) ? anyPawnKind.lifeStages.First() : anyPawnKind.lifeStages.Last()).bodyGraphicData.Graphic.MatAt(Rot4.East); + uiIcon = (Texture2D)material.mainTexture; + uiIconColor = material.color; + if (ShaderDatabase.TryGetUIShader(material.shader, out var uiShader) && MaterialPool.TryGetRequestForMat(material, out var request)) + { + request.shader = uiShader; + uiIconMaterial = MaterialPool.MatFrom(request); + } + } + } + } + else + { + ThingDef thingDef = GenStuff.DefaultStuffFor(this); + if (colorGenerator != null && (thingDef == null || thingDef.stuffProps.allowColorGenerators)) + { + uiIconColor = colorGenerator.ExemplaryColor; + } + else if (thingDef != null) + { + uiIconColor = GetColorForStuff(thingDef); + } + else if (graphicData != null) + { + uiIconColor = graphicData.color; + } + if (rotatable && graphic != null && graphic != BaseContent.BadGraphic && graphic.ShouldDrawRotated && defaultPlacingRot == Rot4.South) + { + uiIconAngle = 180f + graphic.DrawRotatedExtraAngleOffset; + } + } + } + + public override void ResolveReferences() + { + base.ResolveReferences(); + if (ingestible != null) + { + ingestible.parent = this; + } + if (stuffProps != null) + { + stuffProps.parent = this; + } + building?.ResolveReferencesSpecial(); + graphicData?.ResolveReferencesSpecial(); + race?.ResolveReferencesSpecial(); + stuffProps?.ResolveReferencesSpecial(); + apparel?.ResolveReferencesSpecial(); + if (soundImpactDefault == null) + { + soundImpactDefault = SoundDefOf.BulletImpact_Ground; + } + if (soundDrop == null) + { + soundDrop = SoundDefOf.Standard_Drop; + } + if (soundPickup == null) + { + soundPickup = SoundDefOf.Standard_Pickup; + } + if (soundInteract == null) + { + soundInteract = SoundDefOf.Standard_Pickup; + } + if (inspectorTabs != null && inspectorTabs.Any()) + { + inspectorTabsResolved = new List(); + for (int i = 0; i < inspectorTabs.Count; i++) + { + try + { + inspectorTabsResolved.Add(InspectTabManager.GetSharedInstance(inspectorTabs[i])); + } + catch (Exception ex) + { + Log.Error("Could not instantiate inspector tab of type " + inspectorTabs[i]?.ToString() + ": " + ex); + } + } + } + if (comps != null) + { + for (int j = 0; j < comps.Count; j++) + { + comps[j].ResolveReferences(this); + } + } + } + + public override IEnumerable ConfigErrors() + { + foreach (string item in base.ConfigErrors()) + { + yield return item; + } + if (category != ThingCategory.Ethereal && label.NullOrEmpty()) + { + yield return "no label"; + } + if (category == ThingCategory.Building && !IsFrame && building.IsDeconstructible && thingClass != null && typeof(Building).IsSubclassOf(thingClass)) + { + yield return "has building category and is marked as deconstructible, but thing class is not a subclass of building (" + thingClass.Name + ")"; + } + if (graphicData != null) + { + foreach (string item2 in graphicData.ConfigErrors(this)) + { + yield return item2; + } + } + if (projectile != null) + { + foreach (string item3 in projectile.ConfigErrors(this)) + { + yield return item3; + } + } + if (statBases != null) + { + foreach (StatModifier statBase in statBases) + { + if (statBases.Count((StatModifier st) => st.stat == statBase.stat) > 1) + { + yield return "defines the stat base " + statBase.stat?.ToString() + " more than once."; + } + } + } + if (!BeautyUtility.BeautyRelevant(category) && this.StatBaseDefined(StatDefOf.Beauty)) + { + yield return "Beauty stat base is defined, but Things of category " + category.ToString() + " cannot have beauty."; + } + if (!BeautyUtility.BeautyRelevant(category) && this.StatBaseDefined(StatDefOf.BeautyOutdoors)) + { + yield return "BeautyOutdoors stat base is defined, but Things of category " + category.ToString() + " cannot have beauty."; + } + if (char.IsNumber(defName[defName.Length - 1])) + { + yield return "ends with a numerical digit, which is not allowed on ThingDefs."; + } + if (thingClass == null) + { + yield return "has null thingClass."; + } + if (comps.Count > 0 && !typeof(ThingWithComps).IsAssignableFrom(thingClass)) + { + yield return "has components but it's thingClass is not a ThingWithComps"; + } + if (ConnectToPower && drawerType == DrawerType.RealtimeOnly && IsFrame) + { + yield return "connects to power but does not add to map mesh. Will not create wire meshes."; + } + if (costList != null) + { + foreach (ThingDefCountClass cost in costList) + { + if (cost.count == 0) + { + yield return "cost in " + cost.thingDef?.ToString() + " is zero."; + } + } + } + ThingCategoryDef thingCategoryDef = thingCategories?.FirstOrDefault((ThingCategoryDef cat) => thingCategories.Count((ThingCategoryDef c) => c == cat) > 1); + if (thingCategoryDef != null) + { + yield return "has duplicate thingCategory " + thingCategoryDef?.ToString() + "."; + } + if (Fillage == FillCategory.Full && category != ThingCategory.Building) + { + yield return "gives full cover but is not a building."; + } + if (equipmentType != 0) + { + if (techLevel == TechLevel.Undefined && !destroyOnDrop) + { + yield return "is equipment but has no tech level."; + } + if (!comps.Any((CompProperties c) => typeof(CompEquippable).IsAssignableFrom(c.compClass))) + { + yield return "is equipment but has no CompEquippable"; + } + } + if (thingClass == typeof(Bullet) && projectile.damageDef == null) + { + yield return " is a bullet but has no damageDef."; + } + if (destroyOnDrop && tradeability != 0) + { + yield return "destroyOnDrop but tradeability is " + tradeability; + } + if (stackLimit > 1 && !drawGUIOverlay) + { + yield return "has stackLimit > 1 but also has drawGUIOverlay = false."; + } + if (damageMultipliers != null) + { + foreach (DamageMultiplier mult in damageMultipliers) + { + if (damageMultipliers.Count((DamageMultiplier m) => m.damageDef == mult.damageDef) > 1) + { + yield return "has multiple damage multipliers for damageDef " + mult.damageDef; + break; + } + } + } + if (Fillage == FillCategory.Full && !this.IsEdifice()) + { + yield return "fillPercent is 1.00 but is not edifice"; + } + if (base.MadeFromStuff && constructEffect != null) + { + yield return "madeFromStuff but has a defined constructEffect (which will always be overridden by stuff's construct animation)."; + } + if (base.MadeFromStuff && stuffCategories.NullOrEmpty()) + { + yield return "madeFromStuff but has no stuffCategories."; + } + if (costList.NullOrEmpty() && costStuffCount <= 0 && recipeMaker != null) + { + yield return "has a recipeMaker but no costList or costStuffCount."; + } + if (costStuffCount > 0 && stuffCategories.NullOrEmpty()) + { + yield return "has costStuffCount but no stuffCategories."; + } + if (this.GetStatValueAbstract(StatDefOf.DeteriorationRate) > 1E-05f && !CanEverDeteriorate && !destroyOnDrop) + { + yield return "has >0 DeteriorationRate but can't deteriorate."; + } + if (smeltProducts != null && !smeltable) + { + yield return "has smeltProducts but has smeltable=false"; + } + if (smeltable && smeltProducts.NullOrEmpty() && base.CostList.NullOrEmpty() && !IsStuff && !base.MadeFromStuff && !destroyOnDrop) + { + yield return "is smeltable but does not give anything for smelting."; + } + if (equipmentType != 0 && verbs.NullOrEmpty() && tools.NullOrEmpty()) + { + yield return "is equipment but has no verbs or tools"; + } + if (Minifiable && thingCategories.NullOrEmpty()) + { + yield return "is minifiable but not in any thing category"; + } + if (category == ThingCategory.Building && !Minifiable && !thingCategories.NullOrEmpty()) + { + yield return "is not minifiable yet has thing categories (could be confusing in thing filters because it can't be moved/stored anyway)"; + } + if (!destroyOnDrop && !typeof(MinifiedThing).IsAssignableFrom(thingClass) && (EverHaulable || Minifiable) && (statBases.NullOrEmpty() || !statBases.Any((StatModifier s) => s.stat == StatDefOf.Mass))) + { + yield return "is haulable, but does not have an authored mass value"; + } + if (ingestible == null && this.GetStatValueAbstract(StatDefOf.Nutrition) != 0f) + { + yield return "has nutrition but ingestible properties are null"; + } + if (BaseFlammability != 0f && !useHitPoints && category != ThingCategory.Pawn && !destroyOnDrop) + { + yield return "flammable but has no hitpoints (will burn indefinitely)"; + } + if (graphicData?.shadowData != null && staticSunShadowHeight > 0f) + { + yield return "graphicData defines a shadowInfo but staticSunShadowHeight > 0"; + } + if (saveCompressible && Claimable) + { + yield return "claimable item is compressible; faction will be unset after load"; + } + if (deepCommonality > 0f != deepLumpSizeRange.TrueMax > 0) + { + yield return "if deepCommonality or deepLumpSizeRange is set, the other also must be set"; + } + if (deepCommonality > 0f && deepCountPerPortion <= 0) + { + yield return "deepCommonality > 0 but deepCountPerPortion is not set"; + } + if (verbs != null) + { + for (int i = 0; i < verbs.Count; i++) + { + foreach (string item4 in verbs[i].ConfigErrors(this)) + { + yield return $"verb {i}: {item4}"; + } + } + } + if (building != null) + { + foreach (string item5 in building.ConfigErrors(this)) + { + yield return item5; + } + if ((building.isAirtight || building.isStuffableAirtight) && Fillage != FillCategory.Full) + { + yield return "is airtight but Fillage is not Full"; + } + } + if (apparel != null) + { + foreach (string item6 in apparel.ConfigErrors(this)) + { + yield return item6; + } + } + if (comps != null) + { + for (int i = 0; i < comps.Count; i++) + { + foreach (string item7 in comps[i].ConfigErrors(this)) + { + yield return item7; + } + } + } + if (race != null) + { + foreach (string item8 in race.ConfigErrors(this)) + { + yield return item8; + } + if (race.body != null && race != null && tools != null) + { + int i; + for (i = 0; i < tools.Count; i++) + { + if (tools[i].linkedBodyPartsGroup != null && !race.body.AllParts.Any((BodyPartRecord part) => part.groups.Contains(tools[i].linkedBodyPartsGroup))) + { + yield return "has tool with linkedBodyPartsGroup " + tools[i].linkedBodyPartsGroup?.ToString() + " but body " + race.body?.ToString() + " has no parts with that group."; + } + } + } + if (race.Animal && this.GetStatValueAbstract(StatDefOf.Wildness) < 0f) + { + yield return "is animal but wildness is not defined"; + } + } + if (ingestible != null) + { + foreach (string item9 in ingestible.ConfigErrors()) + { + yield return item9; + } + } + if (plant != null) + { + foreach (string item10 in plant.ConfigErrors()) + { + yield return item10; + } + } + if (tools != null) + { + Tool tool = tools.SelectMany((Tool lhs) => tools.Where((Tool rhs) => lhs != rhs && lhs.id == rhs.id)).FirstOrDefault(); + if (tool != null) + { + yield return "duplicate thingdef tool id " + tool.id; + } + foreach (Tool tool2 in tools) + { + foreach (string item11 in tool2.ConfigErrors()) + { + yield return item11; + } + } + } + if (!randomStyle.NullOrEmpty()) + { + foreach (ThingStyleChance item12 in randomStyle) + { + if (item12.Chance <= 0f) + { + yield return "style chance <= 0."; + } + } + if (!comps.Any((CompProperties c) => c.compClass == typeof(CompStyleable))) + { + yield return "random style assigned, but missing CompStyleable!"; + } + } + if (relicChance > 0f && category != ThingCategory.Item) + { + yield return "relic chance > 0 but category != item"; + } + if (hasInteractionCell && !multipleInteractionCellOffsets.NullOrEmpty()) + { + yield return "both single and multiple interaction cells are defined, it should be one or the other"; + } + if (Fillage != FillCategory.Full && passability == Traversability.Impassable && !IsDoor && base.BuildableByPlayer && !disableImpassableShotOverConfigError) + { + yield return "impassable, player-buildable building that can be shot/seen over."; + } + } + + public static ThingDef Named(string defName) + { + return DefDatabase.GetNamed(defName); + } + + public bool IsWithinCategory(ThingCategoryDef category) + { + if (thingCategories == null) + { + return false; + } + for (int i = 0; i < thingCategories.Count; i++) + { + for (ThingCategoryDef thingCategoryDef = thingCategories[i]; thingCategoryDef != null; thingCategoryDef = thingCategoryDef.parent) + { + if (thingCategoryDef == category) + { + return true; + } + } + } + return false; + } + + public void Notify_UnlockedByResearch() + { + if (comps != null) + { + for (int i = 0; i < comps.Count; i++) + { + comps[i].Notify_PostUnlockedByResearch(this); + } + } + } + + public override IEnumerable SpecialDisplayStats(StatRequest req) + { + foreach (StatDrawEntry item in base.SpecialDisplayStats(req)) + { + yield return item; + } + if (apparel != null) + { + string coveredOuterPartsString = apparel.GetCoveredOuterPartsString(BodyDefOf.Human); + yield return new StatDrawEntry(StatCategoryDefOf.Apparel, "Covers".Translate(), coveredOuterPartsString, "Stat_Thing_Apparel_Covers_Desc".Translate(), 2750); + yield return new StatDrawEntry(StatCategoryDefOf.Apparel, "Layer".Translate(), apparel.GetLayersString(), "Stat_Thing_Apparel_Layer_Desc".Translate(), 2751); + yield return new StatDrawEntry(StatCategoryDefOf.Apparel, "Stat_Thing_Apparel_CountsAsClothingNudity_Name".Translate(), apparel.countsAsClothingForNudity ? "Yes".Translate() : "No".Translate(), "Stat_Thing_Apparel_CountsAsClothingNudity_Desc".Translate(), 2753); + if (ModsConfig.BiotechActive) + { + yield return new StatDrawEntry(StatCategoryDefOf.Apparel, "Stat_Thing_Apparel_ValidLifestage".Translate(), apparel.developmentalStageFilter.ToCommaList().CapitalizeFirst(), "Stat_Thing_Apparel_ValidLifestage_Desc".Translate(), 2748); + } + if (apparel.gender != 0) + { + yield return new StatDrawEntry(StatCategoryDefOf.Apparel, "Stat_Thing_Apparel_Gender".Translate(), apparel.gender.GetLabel().CapitalizeFirst(), "Stat_Thing_Apparel_Gender_Desc".Translate(), 2749); + } + } + if (IsMedicine && MedicineTendXpGainFactor != 1f) + { + yield return new StatDrawEntry(StatCategoryDefOf.Basics, "MedicineXpGainFactor".Translate(), MedicineTendXpGainFactor.ToStringPercent(), "Stat_Thing_Drug_MedicineXpGainFactor_Desc".Translate(), 1000); + } + if (fillPercent > 0f && (category == ThingCategory.Item || category == ThingCategory.Building || category == ThingCategory.Plant)) + { + yield return new StatDrawEntry(StatCategoryDefOf.Basics, "CoverEffectiveness".Translate(), this.BaseBlockChance().ToStringPercent(), "CoverEffectivenessExplanation".Translate(), 2000); + } + if (constructionSkillPrerequisite > 0) + { + yield return new StatDrawEntry(StatCategoryDefOf.Basics, "SkillRequiredToBuild".Translate(SkillDefOf.Construction.LabelCap), constructionSkillPrerequisite.ToString(), "SkillRequiredToBuildExplanation".Translate(SkillDefOf.Construction.LabelCap), 1100); + } + if (artisticSkillPrerequisite > 0) + { + yield return new StatDrawEntry(StatCategoryDefOf.Basics, "SkillRequiredToBuild".Translate(SkillDefOf.Artistic.LabelCap), artisticSkillPrerequisite.ToString(), "SkillRequiredToBuildExplanation".Translate(SkillDefOf.Artistic.LabelCap), 1100); + } + IEnumerable recipes = DefDatabase.AllDefsListForReading.Where((RecipeDef r) => r.products.Count == 1 && r.products.Any((ThingDefCountClass p) => p.thingDef == this) && !r.IsSurgery); + if (recipes.Any()) + { + IEnumerable enumerable = (from u in recipes.Where((RecipeDef x) => x.recipeUsers != null).SelectMany((RecipeDef r) => r.recipeUsers) + select u.label).Concat(from x in DefDatabase.AllDefsListForReading + where x.recipes != null && x.recipes.Any((RecipeDef y) => y.products.Any((ThingDefCountClass z) => z.thingDef == this)) + select x.label).Distinct(); + if (enumerable.Any()) + { + yield return new StatDrawEntry(StatCategoryDefOf.Basics, "CreatedAt".Translate(), enumerable.ToCommaList().CapitalizeFirst(), "Stat_Thing_CreatedAt_Desc".Translate(), 1103); + } + RecipeDef recipeDef = recipes.FirstOrDefault(); + if (recipeDef != null && !recipeDef.ingredients.NullOrEmpty()) + { + BuildableDef.tmpCostList.Clear(); + BuildableDef.tmpHyperlinks.Clear(); + for (int j = 0; j < recipeDef.ingredients.Count; j++) + { + IngredientCount ingredientCount = recipeDef.ingredients[j]; + if (ingredientCount.filter.Summary.NullOrEmpty()) + { + continue; + } + IEnumerable allowedThingDefs = ingredientCount.filter.AllowedThingDefs; + if (allowedThingDefs.Any()) + { + foreach (ThingDef p in allowedThingDefs) + { + if (!BuildableDef.tmpHyperlinks.Any((Dialog_InfoCard.Hyperlink x) => x.def == p)) + { + BuildableDef.tmpHyperlinks.Add(new Dialog_InfoCard.Hyperlink(p)); + } + } + } + BuildableDef.tmpCostList.Add(recipeDef.IngredientValueGetter.BillRequirementsDescription(recipeDef, ingredientCount)); + } + } + if (BuildableDef.tmpCostList.Any()) + { + yield return new StatDrawEntry(StatCategoryDefOf.Basics, "Ingredients".Translate(), BuildableDef.tmpCostList.ToCommaList(), "Stat_Thing_Ingredients".Translate(), 1102, null, BuildableDef.tmpHyperlinks); + } + } + if (thingClass != null && typeof(Building_Bed).IsAssignableFrom(thingClass) && !statBases.StatListContains(StatDefOf.BedRestEffectiveness)) + { + yield return new StatDrawEntry(StatCategoryDefOf.Building, StatDefOf.BedRestEffectiveness, StatDefOf.BedRestEffectiveness.valueIfMissing, StatRequest.ForEmpty()); + } + if (!verbs.NullOrEmpty()) + { + VerbProperties verb = verbs.First((VerbProperties x) => x.isPrimary); + StatCategoryDef verbStatCategory = ((category == ThingCategory.Pawn) ? StatCategoryDefOf.PawnCombat : null); + float num = verb.warmupTime; + StringBuilder stringBuilder = new StringBuilder("Stat_Thing_Weapon_RangedWarmupTime_Desc".Translate()); + stringBuilder.AppendLine(); + stringBuilder.AppendLine(); + stringBuilder.AppendLine("StatsReport_BaseValue".Translate() + ": " + num.ToString("0.##") + " " + "LetterSecond".Translate()); + if (num > 0f) + { + if (req.HasThing) + { + float statValue = req.Thing.GetStatValue(StatDefOf.RangedWeapon_WarmupMultiplier); + num *= statValue; + if (!Mathf.Approximately(statValue, 1f)) + { + stringBuilder.AppendLine(); + stringBuilder.AppendLine("Stat_Thing_Weapon_WarmupTime_Multiplier".Translate() + ": x" + statValue.ToStringPercent()); + stringBuilder.Append(StatUtility.GetOffsetsAndFactorsFor(StatDefOf.RangedWeapon_WarmupMultiplier, req.Thing)); + } + } + stringBuilder.AppendLine(); + stringBuilder.AppendLine("StatsReport_FinalValue".Translate() + ": " + num.ToString("0.##") + " " + "LetterSecond".Translate()); + yield return new StatDrawEntry(verbStatCategory ?? StatCategoryDefOf.Weapon_Ranged, "RangedWarmupTime".Translate(), num.ToString("0.##") + " " + "LetterSecond".Translate(), stringBuilder.ToString(), 3555); + } + if (verb.defaultProjectile?.projectile.damageDef != null && verb.defaultProjectile.projectile.damageDef.harmsHealth) + { + StatCategoryDef statCat = verbStatCategory ?? StatCategoryDefOf.Weapon_Ranged; + StringBuilder stringBuilder2 = new StringBuilder(); + stringBuilder2.AppendLine("Stat_Thing_Damage_Desc".Translate()); + stringBuilder2.AppendLine(); + float num2 = verb.defaultProjectile.projectile.GetDamageAmount(req.Thing, stringBuilder2); + yield return new StatDrawEntry(statCat, "Damage".Translate(), num2.ToString(), stringBuilder2.ToString(), 5500); + if (verb.defaultProjectile.projectile.damageDef.armorCategory != null) + { + StringBuilder stringBuilder3 = new StringBuilder(); + float armorPenetration = verb.defaultProjectile.projectile.GetArmorPenetration(req.Thing, stringBuilder3); + TaggedString taggedString = "ArmorPenetrationExplanation".Translate(); + if (stringBuilder3.Length != 0) + { + taggedString += "\n\n" + stringBuilder3; + } + yield return new StatDrawEntry(statCat, "ArmorPenetration".Translate(), armorPenetration.ToStringPercent(), taggedString, 5400); + } + float buildingDamageFactor = verb.defaultProjectile.projectile.damageDef.buildingDamageFactor; + float dmgBuildingsImpassable = verb.defaultProjectile.projectile.damageDef.buildingDamageFactorImpassable; + float dmgBuildingsPassable = verb.defaultProjectile.projectile.damageDef.buildingDamageFactorPassable; + if (buildingDamageFactor != 1f) + { + yield return new StatDrawEntry(statCat, "BuildingDamageFactor".Translate(), buildingDamageFactor.ToStringPercent(), "BuildingDamageFactorExplanation".Translate(), 5410); + } + if (dmgBuildingsImpassable != 1f) + { + yield return new StatDrawEntry(statCat, "BuildingDamageFactorImpassable".Translate(), dmgBuildingsImpassable.ToStringPercent(), "BuildingDamageFactorImpassableExplanation".Translate(), 5420); + } + if (dmgBuildingsPassable != 1f) + { + yield return new StatDrawEntry(statCat, "BuildingDamageFactorPassable".Translate(), dmgBuildingsPassable.ToStringPercent(), "BuildingDamageFactorPassableExplanation".Translate(), 5430); + } + } + if (verb.defaultProjectile == null && verb.beamDamageDef != null) + { + yield return new StatDrawEntry(verbStatCategory ?? StatCategoryDefOf.Weapon_Ranged, "ArmorPenetration".Translate(), verb.beamDamageDef.defaultArmorPenetration.ToStringPercent(), "ArmorPenetrationExplanation".Translate(), 5400); + } + if (verb.Ranged) + { + float num3 = verb.burstShotCount; + float num4 = verb.ticksBetweenBurstShots; + float dmgBuildingsPassable = (verb?.defaultProjectile?.projectile?.stoppingPower).GetValueOrDefault(); + StringBuilder stringBuilder4 = new StringBuilder("Stat_Thing_Weapon_BurstShotFireRate_Desc".Translate()); + stringBuilder4.AppendLine(); + stringBuilder4.AppendLine(); + stringBuilder4.AppendLine("StatsReport_BaseValue".Translate() + ": " + verb.burstShotCount.ToString()); + stringBuilder4.AppendLine(); + StringBuilder ticksBetweenBurstShotsExplanation = new StringBuilder("Stat_Thing_Weapon_BurstShotFireRate_Desc".Translate()); + ticksBetweenBurstShotsExplanation.AppendLine(); + ticksBetweenBurstShotsExplanation.AppendLine(); + ticksBetweenBurstShotsExplanation.AppendLine("StatsReport_BaseValue".Translate() + ": " + (60f / verb.ticksBetweenBurstShots.TicksToSeconds()).ToString("0.##") + " rpm"); + ticksBetweenBurstShotsExplanation.AppendLine(); + StringBuilder stoppingPowerExplanation = new StringBuilder("StoppingPowerExplanation".Translate()); + stoppingPowerExplanation.AppendLine(); + stoppingPowerExplanation.AppendLine(); + stoppingPowerExplanation.AppendLine("StatsReport_BaseValue".Translate() + ": " + dmgBuildingsPassable.ToString("F1")); + stoppingPowerExplanation.AppendLine(); + if (req.HasThing && req.Thing.TryGetComp(out CompUniqueWeapon comp)) + { + bool flag = false; + bool flag2 = false; + bool flag3 = false; + foreach (WeaponTraitDef item2 in comp.TraitsListForReading) + { + if (!Mathf.Approximately(item2.burstShotCountMultiplier, 1f)) + { + if (!flag) + { + stringBuilder4.AppendLine("StatsReport_WeaponTraits".Translate() + ":"); + flag = true; + } + num3 *= item2.burstShotCountMultiplier; + stringBuilder4.AppendLine(" " + item2.LabelCap + ": " + item2.burstShotCountMultiplier.ToStringByStyle(ToStringStyle.PercentOne, ToStringNumberSense.Factor)); + } + if (!Mathf.Approximately(item2.burstShotSpeedMultiplier, 1f)) + { + if (!flag2) + { + ticksBetweenBurstShotsExplanation.AppendLine("StatsReport_WeaponTraits".Translate() + ":"); + flag2 = true; + } + num4 /= item2.burstShotSpeedMultiplier; + ticksBetweenBurstShotsExplanation.AppendLine(" " + item2.LabelCap + ": " + item2.burstShotSpeedMultiplier.ToStringByStyle(ToStringStyle.PercentOne, ToStringNumberSense.Factor)); + } + if (!Mathf.Approximately(item2.additionalStoppingPower, 0f)) + { + if (!flag3) + { + stoppingPowerExplanation.AppendLine("StatsReport_WeaponTraits".Translate() + ":"); + flag3 = true; + } + dmgBuildingsPassable += item2.additionalStoppingPower; + stoppingPowerExplanation.AppendLine(" " + item2.LabelCap + ": " + item2.additionalStoppingPower.ToStringByStyle(ToStringStyle.FloatOne, ToStringNumberSense.Offset)); + } + } + } + stringBuilder4.AppendLine(); + stringBuilder4.AppendLine("StatsReport_FinalValue".Translate() + ": " + Mathf.CeilToInt(num3).ToString()); + float dmgBuildingsImpassable = 60f / ((int)num4).TicksToSeconds(); + ticksBetweenBurstShotsExplanation.AppendLine(); + ticksBetweenBurstShotsExplanation.AppendLine("StatsReport_FinalValue".Translate() + ": " + dmgBuildingsImpassable.ToString("0.##") + " rpm"); + stoppingPowerExplanation.AppendLine(); + stoppingPowerExplanation.AppendLine("StatsReport_FinalValue".Translate() + ": " + dmgBuildingsPassable.ToString("F1")); + StatCategoryDef statCat = verbStatCategory ?? StatCategoryDefOf.Weapon_Ranged; + if (verb.showBurstShotStats && verb.burstShotCount > 1) + { + yield return new StatDrawEntry(statCat, "BurstShotCount".Translate(), Mathf.CeilToInt(num3).ToString(), stringBuilder4.ToString(), 5391); + yield return new StatDrawEntry(statCat, "BurstShotFireRate".Translate(), dmgBuildingsImpassable.ToString("0.##") + " rpm", ticksBetweenBurstShotsExplanation.ToString(), 5395); + } + if (dmgBuildingsPassable > 0f) + { + yield return new StatDrawEntry(statCat, "StoppingPower".Translate(), dmgBuildingsPassable.ToString("F1"), stoppingPowerExplanation.ToString(), 5402); + } + float num5 = verb.range; + StringBuilder stringBuilder5 = new StringBuilder("Stat_Thing_Weapon_Range_Desc".Translate()); + stringBuilder5.AppendLine(); + stringBuilder5.AppendLine(); + stringBuilder5.AppendLine("StatsReport_BaseValue".Translate() + ": " + num5.ToString("F0")); + if (req.HasThing) + { + float statValue2 = req.Thing.GetStatValue(StatDefOf.RangedWeapon_RangeMultiplier); + num5 *= statValue2; + if (!Mathf.Approximately(statValue2, 1f)) + { + stringBuilder5.AppendLine(); + stringBuilder5.AppendLine("Stat_Thing_Weapon_Range_Multiplier".Translate() + ": x" + statValue2.ToStringPercent()); + stringBuilder5.Append(StatUtility.GetOffsetsAndFactorsFor(StatDefOf.RangedWeapon_RangeMultiplier, req.Thing)); + } + Map obj = req.Thing.Map ?? req.Thing.MapHeld; + if (obj != null && obj.weatherManager.CurWeatherMaxRangeCap >= 0f) + { + WeatherManager weatherManager = (req.Thing.Map ?? req.Thing.MapHeld).weatherManager; + bool num6 = num5 > weatherManager.CurWeatherMaxRangeCap; + float num7 = num5; + num5 = Mathf.Min(num5, weatherManager.CurWeatherMaxRangeCap); + if (num6) + { + stringBuilder5.AppendLine(); + stringBuilder5.AppendLine(" " + "Stat_Thing_Weapon_Range_Clamped".Translate(num5.ToString("F0").Named("CAP"), num7.ToString("F0").Named("ORIGINAL"))); + } + } + } + stringBuilder5.AppendLine(); + stringBuilder5.AppendLine("StatsReport_FinalValue".Translate() + ": " + num5.ToString("F0")); + yield return new StatDrawEntry(statCat, "Range".Translate(), num5.ToString("F0"), stringBuilder5.ToString(), 5390); + } + if (verb.ForcedMissRadius > 0f) + { + StatCategoryDef statCat = verbStatCategory ?? StatCategoryDefOf.Weapon_Ranged; + yield return new StatDrawEntry(statCat, "MissRadius".Translate(), verb.ForcedMissRadius.ToString("0.#"), "Stat_Thing_Weapon_MissRadius_Desc".Translate(), 3557); + yield return new StatDrawEntry(statCat, "DirectHitChance".Translate(), (1f / (float)GenRadial.NumCellsInRadius(verb.ForcedMissRadius)).ToStringPercent(), "Stat_Thing_Weapon_DirectHitChance_Desc".Translate(), 3560); + } + } + if (plant != null) + { + foreach (StatDrawEntry item3 in plant.SpecialDisplayStats()) + { + yield return item3; + } + } + if (ingestible != null) + { + foreach (StatDrawEntry item4 in ingestible.SpecialDisplayStats()) + { + yield return item4; + } + } + if (race != null) + { + foreach (StatDrawEntry item5 in race.SpecialDisplayStats(this, req)) + { + yield return item5; + } + } + if (building != null) + { + foreach (StatDrawEntry item6 in building.SpecialDisplayStats(this, req)) + { + yield return item6; + } + } + if (isTechHediff) + { + IEnumerable enumerable2 = DefDatabase.AllDefs.Where((RecipeDef x) => x.addsHediff != null && x.IsIngredient(this)); + foreach (StatDrawEntry medicalStatsFromRecipeDef in MedicalRecipesUtility.GetMedicalStatsFromRecipeDefs(enumerable2)) + { + yield return medicalStatsFromRecipeDef; + } + } + for (int i = 0; i < comps.Count; i++) + { + foreach (StatDrawEntry item7 in comps[i].SpecialDisplayStats(req)) + { + yield return item7; + } + } + if (building != null) + { + if (building.mineableThing != null) + { + Dialog_InfoCard.Hyperlink[] hyperlinks = new Dialog_InfoCard.Hyperlink[1] + { + new Dialog_InfoCard.Hyperlink(building.mineableThing) + }; + yield return new StatDrawEntry(StatCategoryDefOf.BasicsImportant, "Stat_MineableThing_Name".Translate(), building.mineableThing.LabelCap, "Stat_MineableThing_Desc".Translate(), 2200, null, hyperlinks); + StringBuilder stringBuilder6 = new StringBuilder(); + stringBuilder6.AppendLine("Stat_MiningYield_Desc".Translate()); + stringBuilder6.AppendLine(); + stringBuilder6.AppendLine("StatsReport_DifficultyMultiplier".Translate(Find.Storyteller.difficultyDef.label) + ": " + Find.Storyteller.difficulty.mineYieldFactor.ToStringByStyle(ToStringStyle.PercentZero, ToStringNumberSense.Factor)); + yield return new StatDrawEntry(StatCategoryDefOf.Basics, "Stat_MiningYield_Name".Translate(), Mathf.CeilToInt(building.EffectiveMineableYield).ToString("F0"), stringBuilder6.ToString(), 2200, null, hyperlinks); + } + if (building.IsTurret) + { + ThingDef turret = building.turretGunDef; + yield return new StatDrawEntry(StatCategoryDefOf.BasicsImportant, "Stat_Weapon_Name".Translate(), turret.LabelCap, "Stat_Weapon_Desc".Translate(), 5389, null, new Dialog_InfoCard.Hyperlink[1] + { + new Dialog_InfoCard.Hyperlink(turret) + }); + StatRequest request = StatRequest.For(turret, null); + foreach (StatDrawEntry item8 in turret.SpecialDisplayStats(request)) + { + if (item8.category == StatCategoryDefOf.Weapon_Ranged) + { + yield return item8; + } + } + for (int i = 0; i < turret.statBases.Count; i++) + { + StatModifier statModifier = turret.statBases[i]; + if (statModifier.stat.category == StatCategoryDefOf.Weapon_Ranged) + { + yield return new StatDrawEntry(StatCategoryDefOf.Weapon_Ranged, statModifier.stat, statModifier.value, request); + } + } + } + if (ModsConfig.OdysseyActive && Fillage == FillCategory.Full) + { + bool b = building.isAirtight || (building.isStuffableAirtight && req.StuffDef.stuffProps.isAirtight); + yield return new StatDrawEntry(StatCategoryDefOf.Building, "Stat_Airtight".Translate(), b.ToStringYesNo(), "Stat_Airtight_Desc".Translate(), 6100); + } + } + if (IsMeat) + { + List list = new List(); + bool flag4 = false; + foreach (ThingDef allDef in DefDatabase.AllDefs) + { + if (allDef.race != null && allDef.race.meatDef == this && !allDef.IsCorpse) + { + if (!Find.HiddenItemsManager.Hidden(allDef)) + { + flag4 = true; + } + list.Add(allDef); + } + } + yield return new StatDrawEntry(valueString: (!flag4) ? string.Format("({0})", "NotYetDiscovered".Translate()) : string.Join(", ", (from x in list + where !Find.HiddenItemsManager.Hidden(x) + select x into p + select p.label).ToArray()).CapitalizeFirst(), category: StatCategoryDefOf.BasicsPawn, label: "Stat_SourceSpecies_Name".Translate(), reportText: "Stat_SourceSpecies_Desc".Translate(), displayPriorityWithinCategory: 1200, overrideReportTitle: null, hyperlinks: Dialog_InfoCard.DefsToHyperlinks(list)); + } + if (IsLeather) + { + List list2 = new List(); + bool flag5 = false; + foreach (ThingDef allDef2 in DefDatabase.AllDefs) + { + if (allDef2.race != null && allDef2.race.leatherDef == this && !allDef2.IsCorpse) + { + if (!Find.HiddenItemsManager.Hidden(allDef2)) + { + flag5 = true; + } + list2.Add(allDef2); + } + } + yield return new StatDrawEntry(valueString: (!flag5) ? string.Format("({0})", "NotYetDiscovered".Translate()) : string.Join(", ", (from x in list2 + where !Find.HiddenItemsManager.Hidden(x) + select x into p + select p.label).ToArray()).CapitalizeFirst(), category: StatCategoryDefOf.BasicsPawn, label: "Stat_SourceSpecies_Name".Translate(), reportText: "Stat_SourceSpecies_Desc".Translate(), displayPriorityWithinCategory: 1200, overrideReportTitle: null, hyperlinks: Dialog_InfoCard.DefsToHyperlinks(list2)); + } + if (!equippedStatOffsets.NullOrEmpty()) + { + for (int i = 0; i < equippedStatOffsets.Count; i++) + { + StatDef stat = equippedStatOffsets[i].stat; + float num8 = equippedStatOffsets[i].value; + StringBuilder stringBuilder7 = new StringBuilder(stat.description); + if (req.HasThing && stat.Worker != null) + { + stringBuilder7.AppendLine(); + stringBuilder7.AppendLine(); + stringBuilder7.AppendLine("StatsReport_BaseValue".Translate() + ": " + stat.ValueToString(num8, ToStringNumberSense.Offset, stat.finalizeEquippedStatOffset)); + num8 = StatWorker.StatOffsetFromGear(req.Thing, stat); + if (!stat.parts.NullOrEmpty()) + { + stringBuilder7.AppendLine(); + for (int k = 0; k < stat.parts.Count; k++) + { + string text = stat.parts[k].ExplanationPart(req); + if (!text.NullOrEmpty()) + { + stringBuilder7.AppendLine(text); + } + } + } + stringBuilder7.AppendLine(); + stringBuilder7.AppendLine("StatsReport_FinalValue".Translate() + ": " + stat.ValueToString(num8, ToStringNumberSense.Offset, !stat.formatString.NullOrEmpty())); + } + yield return new StatDrawEntry(StatCategoryDefOf.EquippedStatOffsets, equippedStatOffsets[i].stat, num8, StatRequest.ForEmpty(), ToStringNumberSense.Offset, null, forceUnfinalizedMode: true).SetReportText(stringBuilder7.ToString()); + } + } + if (!IsDrug) + { + yield break; + } + foreach (StatDrawEntry item9 in DrugStatsUtility.SpecialDisplayStats(this)) + { + yield return item9; + } + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Core\Defs\ThingDefs_Races\Races_Animal_Insect.xml` +**相似度:** 0.5880 + +```xml + + insect + + 1 + 1 + 60 + 0.8 + + + Insect + InsectConstant + Insectoid + Filth_BloodInsect + (160,168,139) + 0.5 + OmnivoreAnimal, AnimalProduct + 0.50 + Insectoid_Eat + false + + + +
  • InsectMeat
  • +
    +
    + true + +
  • + +
  • Food
  • + + +
  • + true + false +
  • +
    +
    +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Core\Defs\ThingDefs_Items\Items_Luxury.xml` +**相似度:** 0.5741 + +```xml + + Chocolate + + A delicious preparation of cocoa seeds ground together with sugar and vanilla. It fulfills the need for recreation, but it is not very nutritious. + + Things/Item/Resource/Chocolate + Graphic_StackCount + 0.88 + + Standard_Drop + Standard_Drop + true + + 60 + 3 + 0.075 + 1.0 + 8 + 0.1 + + +
  • Foods
  • +
    + + DesperateOnly + Processed + 0.10 + Gluttonous + 4 + 4 + Meal_Eat + + 80 + 10 +
    +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompMechGestatorTank.txt` +**相似度:** 0.5175 + +```csharp +public class CompMechGestatorTank : ThingComp, IThingGlower +{ + public enum TankState + { + Empty, + Dormant, + Proximity + } + + private TankState state; + + private float triggerRadius; + + private const int StunTicks = 180; + + private static readonly IntRange GestationFluidFilthRange = new IntRange(2, 4); + + private CompProperties_MechGestatorTank Props => (CompProperties_MechGestatorTank)props; + + public TankState State + { + get + { + return state; + } + set + { + state = value; + if (parent.Spawned) + { + parent.DirtyMapMesh(parent.Map); + parent.TryGetComp()?.UpdateLit(parent.Map); + } + } + } + + public override string CompInspectStringExtra() + { + return string.Format("{0}: {1}", "Contains".Translate(), ((state == TankState.Empty) ? "Nothing" : "Unknown").Translate().CapitalizeFirst()); + } + + public bool ShouldBeLitNow() + { + return state != TankState.Empty; + } + + public override bool DontDrawParent() + { + return true; + } + + public override void PostPostMake() + { + triggerRadius = Props.triggerRadiusRange.RandomInRange; + } + + public override void CompTick() + { + if (state == TankState.Proximity && parent.IsHashIntervalTick(250)) + { + CheckTrigger(); + } + } + + private void CheckTrigger() + { + if (!parent.Spawned) + { + return; + } + foreach (IntVec3 item in GenRadial.RadialCellsAround(parent.Position, triggerRadius, useCenter: false)) + { + if (!item.InBounds(parent.Map) || !GenSight.LineOfSight(parent.Position, item, parent.Map)) + { + continue; + } + foreach (Thing thing in item.GetThingList(parent.Map)) + { + if (thing is Pawn { IsColonist: not false }) + { + Trigger(parent.Map); + return; + } + } + } + } + + public override void PostDestroy(DestroyMode mode, Map previousMap) + { + if (mode != DestroyMode.WillReplace && state != 0) + { + Trigger(previousMap); + } + } + + private void Trigger(Map map) + { + if (state == TankState.Empty) + { + return; + } + State = TankState.Empty; + IntVec3 loc = parent.OccupiedRect().ExpandedBy(1).EdgeCells.Where(Standable).RandomElementWithFallback(IntVec3.Invalid); + ScatterDebrisUtility.ScatterFilthAroundThing(parent, map, ThingDefOf.Filth_GestationFluid, GestationFluidFilthRange); + if (loc.IsValid) + { + Pawn pawn = PawnGenerator.GeneratePawn(Props.mechKindOptions.RandomElementByWeight((PawnKindDefWeight x) => x.weight).kindDef, Faction.OfMechanoids); + GenSpawn.Spawn(pawn, loc, map); + pawn.stances?.stunner?.StunFor(180, null, addBattleLog: false); + if (!map.lordManager.TryGetLordByJob(Faction.OfMechanoids, out var lord)) + { + LordMaker.MakeNewLord(Faction.OfMechanoids, new LordJob_AssaultColony(Faction.OfMechanoids, canKidnap: false, canTimeoutOrFlee: false, sappers: false, useAvoidGridSmart: false, canSteal: false), map, new List { pawn }); + } + else + { + lord.lord.AddPawn(pawn); + } + Messages.Message(Props.triggeredMessage.Formatted(pawn), pawn, MessageTypeDefOf.NegativeEvent); + Props.triggerSound.PlayOneShot(parent); + } + bool Standable(IntVec3 c) + { + return c.Standable(map); + } + } + + public override IEnumerable CompGetGizmosExtra() + { + if (!DebugSettings.ShowDevGizmos) + { + yield break; + } + if (State == TankState.Empty) + { + Command_Action command_Action = new Command_Action(); + command_Action.defaultLabel = "DEV: Add mech"; + command_Action.action = delegate + { + State = TankState.Proximity; + }; + yield return command_Action; + } + else + { + Command_Action command_Action2 = new Command_Action(); + command_Action2.defaultLabel = "DEV: Remove mech"; + command_Action2.action = delegate + { + State = TankState.Empty; + }; + yield return command_Action2; + } + } + + public override void PostPrintOnto(SectionLayer layer) + { + ((state == TankState.Empty) ? Props.emptyGraphic.Graphic : Props.dormantGraphic.Graphic).Print(layer, parent, 0f); + } + + public override void PostExposeData() + { + Scribe_Values.Look(ref state, "state", TankState.Empty); + Scribe_Values.Look(ref triggerRadius, "triggerRadius", 0f); + } +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/HumanlikeAdult-LifeStageDef.txt b/MCP/vector_cache/HumanlikeAdult-LifeStageDef.txt new file mode 100644 index 00000000..34ab74a1 --- /dev/null +++ b/MCP/vector_cache/HumanlikeAdult-LifeStageDef.txt @@ -0,0 +1,134 @@ +根据向量相似度分析,与 'LifeStageDef, HumanlikeAdult' 最相关的代码定义如下: + +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\LifeStageDefOf.txt` +**相似度:** 0.7850 + +```csharp +public static class LifeStageDefOf +{ + public static LifeStageDef HumanlikeBaby; + + public static LifeStageDef HumanlikeChild; + + public static LifeStageDef HumanlikeAdult; +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Core\Defs\Misc\LifeStageDefs\LifeStages.xml` +**相似度:** 0.7399 + +```xml + + MechanoidFullyFormed + + false + +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Core\Defs\Misc\LifeStageDefs\LifeStages.xml` +**相似度:** 0.7399 + +```xml + HumanlikeTeenager + + LifeStageWorker_HumanlikeAdult + teenage + true + 0.8 + 0.90 + 1.25 + 0.75 + 0.65 + 0.23 + + Things/Pawn/Humanlike/Silhouettes/Silhouette_HumanChild + Graphic_Single + 1 + + + 0.95 + + + + + HumanlikeAdult +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\LifeStageWorker_HumanlikeAdult.txt` +**相似度:** 0.7169 + +```csharp +public class LifeStageWorker_HumanlikeAdult : LifeStageWorker +{ + public const int VatGrowBackstoryTicks = 1200000; + + private static readonly List VatgrowBackstoryFilter = new List + { + new BackstoryCategoryFilter + { + categories = new List { "VatGrown" } + } + }; + + private static readonly List BackstoryFiltersTribal = new List + { + new BackstoryCategoryFilter + { + categories = new List { "AdultTribal" } + } + }; + + private static readonly List BackstoryFiltersColonist = new List + { + new BackstoryCategoryFilter + { + categories = new List { "AdultColonist" } + } + }; + + public override void Notify_LifeStageStarted(Pawn pawn, LifeStageDef previousLifeStage) + { + base.Notify_LifeStageStarted(pawn, previousLifeStage); + if (Current.ProgramState != ProgramState.Playing) + { + return; + } + if (pawn.Spawned && previousLifeStage != null && previousLifeStage.developmentalStage.Juvenile()) + { + EffecterDefOf.Birthday.SpawnAttached(pawn, pawn.Map); + } + if (pawn.story.bodyType == BodyTypeDefOf.Child || pawn.story.bodyType == BodyTypeDefOf.Baby) + { + pawn.apparel?.DropAllOrMoveAllToInventory((Apparel apparel) => !apparel.def.apparel.developmentalStageFilter.Has(DevelopmentalStage.Adult)); + BodyTypeDef bodyTypeFor = PawnGenerator.GetBodyTypeFor(pawn); + pawn.story.bodyType = bodyTypeFor; + pawn.Drawer.renderer.SetAllGraphicsDirty(); + } + if (!pawn.IsColonist) + { + return; + } + List backstoryCategories = ((Faction.OfPlayer.def == FactionDefOf.PlayerTribe) ? BackstoryFiltersTribal : BackstoryFiltersColonist); + if (previousLifeStage.developmentalStage.Juvenile()) + { + if (pawn.ageTracker.vatGrowTicks >= 1200000) + { + PawnBioAndNameGenerator.FillBackstorySlotShuffled(pawn, BackstorySlot.Childhood, VatgrowBackstoryFilter, pawn.Faction?.def); + } + else + { + BackstoryDef backstory = pawn.story.GetBackstory(BackstorySlot.Childhood); + if (backstory != null && backstory.IsPlayerColonyChildBackstory) + { + PawnBioAndNameGenerator.FillBackstorySlotShuffled(pawn, BackstorySlot.Childhood, backstoryCategories, pawn.Faction?.def); + } + } + } + if (pawn.story.GetBackstory(BackstorySlot.Adulthood) == null) + { + PawnBioAndNameGenerator.FillBackstorySlotShuffled(pawn, BackstorySlot.Adulthood, backstoryCategories, pawn.Faction?.def); + } + } +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/JobDef.txt b/MCP/vector_cache/JobDef.txt new file mode 100644 index 00000000..d78f8d6d --- /dev/null +++ b/MCP/vector_cache/JobDef.txt @@ -0,0 +1,115 @@ +根据向量相似度分析,与 'JobDef' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\JobDef.txt` + +```csharp +public class JobDef : Def +{ + public Type driverClass; + + [MustTranslate] + public string reportString = "Doing something."; + + public bool playerInterruptible = true; + + public bool forceCompleteBeforeNextJob; + + public CheckJobOverrideOnDamageMode checkOverrideOnDamage = CheckJobOverrideOnDamageMode.Always; + + public bool alwaysShowWeapon; + + public bool neverShowWeapon; + + public bool suspendable = true; + + public bool casualInterruptible = true; + + public bool allowOpportunisticPrefix; + + public bool collideWithPawns; + + public bool isIdle; + + public TaleDef taleOnCompletion; + + public bool neverFleeFromEnemies; + + public bool sleepCanInterrupt = true; + + public bool makeTargetPrisoner; + + public int waitAfterArriving; + + public bool carryThingAfterJob; + + public bool dropThingBeforeJob = true; + + public bool isCrawlingIfDowned = true; + + public bool alwaysShowReport; + + public bool abilityCasting; + + public bool tryStartFlying; + + public bool ifFlyingKeepFlying; + + public float overrideFlyChance = -1f; + + public bool displayAsAreaInFloatMenu = true; + + public int joyDuration = 4000; + + public int joyMaxParticipants = 1; + + public float joyGainRate = 1f; + + public SkillDef joySkill; + + public float joyXpPerTick; + + public JoyKindDef joyKind; + + public Rot4 faceDir = Rot4.Invalid; + + public int learningDuration = 20000; + + public ReservationLayerDef containerReservationLayer; + + public override IEnumerable ConfigErrors() + { + foreach (string item in base.ConfigErrors()) + { + yield return item; + } + if (joySkill != null && joyXpPerTick == 0f) + { + yield return "funSkill is not null but funXpPerTick is zero"; + } + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Core\Defs\JobDefs\Jobs_Animal.xml` +**相似度:** 0.5912 + +```xml + + Nuzzle + JobDriver_Nuzzle + nuzzling TargetA. + true + +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Ideology\Defs\JobDefs\Jobs_Gatherings.xml` +**相似度:** 0.5788 + +```xml + + Dance + JobDriver_Dance + dancing. + +``` \ No newline at end of file diff --git a/MCP/vector_cache/JobDefOf-JobDriver_TakeToBed-Rescue.txt b/MCP/vector_cache/JobDefOf-JobDriver_TakeToBed-Rescue.txt new file mode 100644 index 00000000..c09c600b --- /dev/null +++ b/MCP/vector_cache/JobDefOf-JobDriver_TakeToBed-Rescue.txt @@ -0,0 +1,827 @@ +根据向量相似度分析,与 'JobDriver_TakeToBed, Rescue, JobDefOf' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\JobDriver_TakeToBed.txt` + +```csharp +public class JobDriver_TakeToBed : JobDriver +{ + private const TargetIndex TakeeIndex = TargetIndex.A; + + private const TargetIndex BedIndex = TargetIndex.B; + + protected Pawn Takee => (Pawn)job.GetTarget(TargetIndex.A).Thing; + + protected Building_Bed DropBed => (Building_Bed)job.GetTarget(TargetIndex.B).Thing; + + private bool TakeeRescued + { + get + { + if (Takee.RaceProps.Humanlike && job.def != JobDefOf.Arrest && !Takee.IsPrisonerOfColony) + { + if (Takee.ageTracker.CurLifeStage.alwaysDowned) + { + return HealthAIUtility.ShouldSeekMedicalRest(Takee); + } + return true; + } + return false; + } + } + + public override string GetReport() + { + if (job.def == JobDefOf.Rescue && !TakeeRescued) + { + return "TakingToBed".Translate(Takee); + } + return base.GetReport(); + } + + public override bool TryMakePreToilReservations(bool errorOnFailed) + { + Takee.ClearAllReservations(); + if (pawn.Reserve(Takee, job, 1, -1, null, errorOnFailed)) + { + return pawn.Reserve(DropBed, job, DropBed.SleepingSlotsCount, 0, null, errorOnFailed); + } + return false; + } + + protected override IEnumerable MakeNewToils() + { + this.FailOnDestroyedOrNull(TargetIndex.A); + this.FailOnDestroyedOrNull(TargetIndex.B); + this.FailOnAggroMentalStateAndHostile(TargetIndex.A); + this.FailOn(delegate + { + if (job.def.makeTargetPrisoner) + { + if (!DropBed.ForPrisoners) + { + return true; + } + } + else if (DropBed.ForPrisoners != Takee.IsPrisoner) + { + return true; + } + return false; + }); + yield return Toils_Bed.ClaimBedIfNonMedical(TargetIndex.B, TargetIndex.A); + AddFinishAction(delegate + { + if (job.def.makeTargetPrisoner && Takee.ownership.OwnedBed == DropBed && Takee.Position != RestUtility.GetBedSleepingSlotPosFor(Takee, DropBed)) + { + Takee.ownership.UnclaimBed(); + } + if (pawn.carryTracker.CarriedThing != null) + { + pawn.carryTracker.TryDropCarriedThing(pawn.Position, ThingPlaceMode.Direct, out var _); + } + }); + Toil goToTakee = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.A).FailOnDespawnedNullOrForbidden(TargetIndex.B) + .FailOn(() => job.def == JobDefOf.Arrest && !Takee.CanBeArrestedBy(pawn)) + .FailOn(() => !pawn.CanReach(DropBed, PathEndMode.OnCell, Danger.Deadly)) + .FailOn(() => (job.def == JobDefOf.Rescue || job.def == JobDefOf.Capture) && !Takee.Downed) + .FailOnSomeonePhysicallyInteracting(TargetIndex.A); + Toil checkArrestResistance = ToilMaker.MakeToil("MakeNewToils"); + checkArrestResistance.initAction = delegate + { + if (job.def.makeTargetPrisoner) + { + Pawn pawn = (Pawn)job.targetA.Thing; + pawn.GetLord()?.Notify_PawnAttemptArrested(pawn); + GenClamor.DoClamor(pawn, 10f, ClamorDefOf.Harm); + if (!pawn.IsPrisoner && !pawn.IsSlave) + { + QuestUtility.SendQuestTargetSignals(pawn.questTags, "Arrested", pawn.Named("SUBJECT")); + if (pawn.Faction != null) + { + QuestUtility.SendQuestTargetSignals(pawn.Faction.questTags, "FactionMemberArrested", pawn.Faction.Named("FACTION")); + } + } + if (job.def == JobDefOf.Arrest && !pawn.CheckAcceptArrest(base.pawn)) + { + base.pawn.jobs.EndCurrentJob(JobCondition.Incompletable); + } + } + }; + yield return Toils_Jump.JumpIf(checkArrestResistance, () => pawn.IsCarryingPawn(Takee)); + yield return goToTakee; + yield return checkArrestResistance; + Toil startCarrying = Toils_Haul.StartCarryThing(TargetIndex.A); + startCarrying.FailOnBedNoLongerUsable(TargetIndex.B, TargetIndex.A); + startCarrying.AddPreInitAction(CheckMakeTakeeGuest); + startCarrying.AddFinishAction(delegate + { + if (pawn.Faction == Takee.Faction) + { + CheckMakeTakeePrisoner(); + } + }); + Toil goToBed = Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.Touch).FailOn(() => !pawn.IsCarryingPawn(Takee)); + goToBed.FailOnBedNoLongerUsable(TargetIndex.B, TargetIndex.A); + yield return Toils_Jump.JumpIf(goToBed, () => pawn.IsCarryingPawn(Takee)); + yield return startCarrying; + yield return goToBed; + Toil toil = ToilMaker.MakeToil("MakeNewToils"); + toil.initAction = delegate + { + CheckMakeTakeePrisoner(); + if (Takee.playerSettings == null) + { + Takee.playerSettings = new Pawn_PlayerSettings(Takee); + } + }; + yield return toil; + yield return Toils_Reserve.Release(TargetIndex.B); + yield return Toils_Bed.TuckIntoBed(DropBed, pawn, Takee, TakeeRescued); + yield return Toils_General.Do(delegate + { + if (!job.ritualTag.NullOrEmpty()) + { + if (Takee.GetLord()?.LordJob is LordJob_Ritual lordJob_Ritual) + { + lordJob_Ritual.AddTagForPawn(Takee, job.ritualTag); + } + if (pawn.GetLord()?.LordJob is LordJob_Ritual lordJob_Ritual2) + { + lordJob_Ritual2.AddTagForPawn(pawn, job.ritualTag); + } + } + }); + } + + private void CheckMakeTakeePrisoner() + { + if (job.def.makeTargetPrisoner) + { + if (Takee.guest.Released) + { + Takee.guest.Released = false; + Takee.guest.SetExclusiveInteraction(PrisonerInteractionModeDefOf.MaintainOnly); + GenGuest.RemoveHealthyPrisonerReleasedThoughts(Takee); + } + if (!Takee.IsPrisonerOfColony) + { + Takee.guest.CapturedBy(Faction.OfPlayer, pawn); + } + } + } + + private void CheckMakeTakeeGuest() + { + if (!job.def.makeTargetPrisoner && Takee.Faction != Faction.OfPlayer && Takee.HostFaction != Faction.OfPlayer && Takee.guest != null && !Takee.IsWildMan() && Takee.DevelopmentalStage != DevelopmentalStage.Baby) + { + Takee.guest.SetGuestStatus(Faction.OfPlayer); + QuestUtility.SendQuestTargetSignals(Takee.questTags, "Rescued", Takee.Named("SUBJECT")); + } + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Core\Defs\JobDefs\Jobs_Work.xml` +**相似度:** 0.6607 + +```xml + Rescue + JobDriver_TakeToBed + rescuing TargetA. + false + true + false +
    + + + CarryToCryptosleepCasket +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Core\Defs\JobDefs\Jobs_Misc.xml` +**相似度:** 0.6320 + +```xml + DeliverToBed + JobDriver_TakeToBed + delivering TargetA. + false + + + + TakeCountToInventory +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\RestUtility.txt` +**相似度:** 0.5085 + +```csharp +public static class RestUtility +{ + public const int NoSleepingDurationAfterBeingDisturbed = 400; + + private static List bedDefsBestToWorst_RestEffectiveness; + + private static List bedDefsBestToWorst_Medical; + + private static List bedDefsBestToWorst_SlabBed_RestEffectiveness; + + private static List bedDefsBestToWorst_SlabBed_Medical; + + public static List AllBedDefBestToWorst => bedDefsBestToWorst_RestEffectiveness; + + public static void Reset() + { + bedDefsBestToWorst_RestEffectiveness = (from d in DefDatabase.AllDefs + where d.IsBed + orderby d.building.bed_maxBodySize, d.GetStatValueAbstract(StatDefOf.BedRestEffectiveness) descending + select d).ToList(); + bedDefsBestToWorst_SlabBed_RestEffectiveness = (from d in DefDatabase.AllDefs + where d.IsBed + orderby (!d.building.bed_slabBed) ? 1 : 0, d.building.bed_maxBodySize, d.GetStatValueAbstract(StatDefOf.BedRestEffectiveness) descending + select d).ToList(); + bedDefsBestToWorst_Medical = (from d in DefDatabase.AllDefs + where d.IsBed + orderby d.building.bed_maxBodySize, d.GetStatValueAbstract(StatDefOf.MedicalTendQualityOffset) descending, d.GetStatValueAbstract(StatDefOf.BedRestEffectiveness) descending + select d).ToList(); + bedDefsBestToWorst_SlabBed_Medical = (from d in DefDatabase.AllDefs + where d.IsBed + orderby (!d.building.bed_slabBed) ? 1 : 0, d.building.bed_maxBodySize, d.GetStatValueAbstract(StatDefOf.MedicalTendQualityOffset) descending, d.GetStatValueAbstract(StatDefOf.BedRestEffectiveness) descending + select d).ToList(); + } + + public static bool BedOwnerWillShare(Building_Bed bed, Pawn sleeper, GuestStatus? guestStatus) + { + if (!bed.OwnersForReading.Any()) + { + return true; + } + if (sleeper.IsPrisoner || guestStatus == GuestStatus.Prisoner || sleeper.IsSlave || guestStatus == GuestStatus.Slave) + { + if (!bed.AnyUnownedSleepingSlot) + { + return false; + } + } + else + { + if (!bed.AnyUnownedSleepingSlot) + { + return false; + } + if (!IsAnyOwnerLovePartnerOf(bed, sleeper)) + { + return false; + } + } + return true; + } + + public static bool CanUseBedNow(Thing bedThing, Pawn sleeper, bool checkSocialProperness, bool allowMedBedEvenIfSetToNoCare = false, GuestStatus? guestStatusOverride = null) + { + if (!(bedThing is Building_Bed building_Bed)) + { + return false; + } + if (!building_Bed.Spawned) + { + return false; + } + if (building_Bed.Map != sleeper.MapHeld) + { + return false; + } + if (building_Bed.IsBurning()) + { + return false; + } + if (sleeper.HarmedByVacuum && building_Bed.Position.GetVacuum(bedThing.Map) >= 0.5f) + { + return false; + } + if (!CanUseBedEver(sleeper, building_Bed.def)) + { + return false; + } + if (building_Bed.CompAssignableToPawn.IdeoligionForbids(sleeper)) + { + return false; + } + int? assignedSleepingSlot; + bool flag = building_Bed.IsOwner(sleeper, out assignedSleepingSlot); + int? sleepingSlot; + bool flag2 = sleeper.CurrentBed(out sleepingSlot) == building_Bed; + if (!building_Bed.AnyUnoccupiedSleepingSlot && !flag && !flag2) + { + return false; + } + GuestStatus? obj = guestStatusOverride ?? sleeper.GuestStatus; + bool flag3 = obj == GuestStatus.Prisoner; + bool flag4 = obj == GuestStatus.Slave; + if (checkSocialProperness && !building_Bed.IsSociallyProper(sleeper, flag3)) + { + return false; + } + if (building_Bed.ForPrisoners != flag3) + { + return false; + } + if (building_Bed.ForSlaves != flag4) + { + return false; + } + if (building_Bed.ForPrisoners && !building_Bed.Position.IsInPrisonCell(building_Bed.Map)) + { + return false; + } + if (building_Bed.Medical) + { + if (!allowMedBedEvenIfSetToNoCare && !HealthAIUtility.ShouldEverReceiveMedicalCareFromPlayer(sleeper)) + { + return false; + } + if (!HealthAIUtility.ShouldSeekMedicalRest(sleeper)) + { + return false; + } + } + else + { + if (!flag && !BedOwnerWillShare(building_Bed, sleeper, guestStatusOverride)) + { + return false; + } + if (flag2 && sleepingSlot != assignedSleepingSlot) + { + return false; + } + } + if (sleeper.IsColonist && !flag3) + { + Job curJob = sleeper.CurJob; + if ((curJob == null || !curJob.ignoreForbidden) && !sleeper.Downed && building_Bed.IsForbidden(sleeper)) + { + return false; + } + } + return true; + } + + public static bool IsValidBedFor(Thing bedThing, Pawn sleeper, Pawn traveler, bool checkSocialProperness, bool allowMedBedEvenIfSetToNoCare = false, bool ignoreOtherReservations = false, GuestStatus? guestStatus = null) + { + if (!CanUseBedNow(bedThing, sleeper, checkSocialProperness, allowMedBedEvenIfSetToNoCare, guestStatus)) + { + return false; + } + Building_Bed building_Bed = (Building_Bed)bedThing; + if (!traveler.CanReach(building_Bed, PathEndMode.OnCell, Danger.Some)) + { + return false; + } + if (!sleeper.HasReserved(building_Bed) && !traveler.CanReserve(building_Bed, building_Bed.SleepingSlotsCount, 0, null, ignoreOtherReservations)) + { + return false; + } + if (traveler.HasReserved(building_Bed, sleeper)) + { + return false; + } + if (building_Bed.IsForbidden(traveler)) + { + return false; + } + bool num = guestStatus == GuestStatus.Prisoner; + bool flag = guestStatus == GuestStatus.Slave; + if (!num && !flag && building_Bed.Faction != traveler.Faction && (traveler.HostFaction == null || building_Bed.Faction != traveler.HostFaction)) + { + return false; + } + if (ModsConfig.AnomalyActive && sleeper.IsMutant && sleeper.needs.rest == null && sleeper.mutant.Def.entitledToMedicalCare && !building_Bed.Medical) + { + return false; + } + return true; + } + + public static void TuckIntoBed(Building_Bed bed, Pawn taker, Pawn takee, bool rescued) + { + IntVec3 position = bed.Position; + if (taker != takee) + { + taker.carryTracker.TryDropCarriedThing(position, ThingPlaceMode.Direct, out var _); + } + if (CanUseBedNow(bed, takee, checkSocialProperness: false)) + { + takee.jobs.Notify_TuckedIntoBed(bed); + if (taker != takee && rescued) + { + takee.relations.Notify_RescuedBy(taker); + } + takee.mindState.Notify_TuckedIntoBed(); + } + if (takee.IsPrisonerOfColony) + { + LessonAutoActivator.TeachOpportunity(ConceptDefOf.PrisonerTab, takee, OpportunityType.GoodToKnow); + } + } + + private static bool IsAnyOwnerLovePartnerOf(Building_Bed bed, Pawn sleeper) + { + for (int i = 0; i < bed.OwnersForReading.Count; i++) + { + if (LovePartnerRelationUtility.LovePartnerRelationExists(sleeper, bed.OwnersForReading[i])) + { + return true; + } + } + return false; + } + + public static Building_Bed FindBedFor(Pawn p) + { + return FindBedFor(p, p, checkSocialProperness: true, ignoreOtherReservations: false, p.GuestStatus); + } + + public static Building_Bed FindBedFor(Pawn sleeper, Pawn traveler, bool checkSocialProperness, bool ignoreOtherReservations = false, GuestStatus? guestStatus = null) + { + if (sleeper.RaceProps.IsMechanoid) + { + return null; + } + if (ModsConfig.BiotechActive && sleeper.Deathresting) + { + Building_Bed assignedDeathrestCasket = sleeper.ownership.AssignedDeathrestCasket; + if (assignedDeathrestCasket != null && IsValidBedFor(assignedDeathrestCasket, sleeper, traveler, checkSocialProperness: true)) + { + CompDeathrestBindable compDeathrestBindable = assignedDeathrestCasket.TryGetComp(); + if (compDeathrestBindable != null && (compDeathrestBindable.BoundPawn == sleeper || compDeathrestBindable.BoundPawn == null)) + { + return assignedDeathrestCasket; + } + } + } + bool flag = false; + if (sleeper.Ideo != null) + { + foreach (Precept item in sleeper.Ideo.PreceptsListForReading) + { + if (item.def.prefersSlabBed) + { + flag = true; + break; + } + } + } + List list = (flag ? bedDefsBestToWorst_SlabBed_Medical : bedDefsBestToWorst_Medical); + List list2 = (flag ? bedDefsBestToWorst_SlabBed_RestEffectiveness : bedDefsBestToWorst_RestEffectiveness); + if (HealthAIUtility.ShouldSeekMedicalRest(sleeper)) + { + if (sleeper.InBed() && sleeper.CurrentBed().Medical && IsValidBedFor(sleeper.CurrentBed(), sleeper, traveler, checkSocialProperness, allowMedBedEvenIfSetToNoCare: false, ignoreOtherReservations, guestStatus)) + { + return sleeper.CurrentBed(); + } + for (int i = 0; i < list.Count; i++) + { + ThingDef thingDef = list[i]; + if (!CanUseBedEver(sleeper, thingDef)) + { + continue; + } + for (int j = 0; j < 2; j++) + { + Danger maxDanger = ((j == 0) ? Danger.None : Danger.Deadly); + Building_Bed building_Bed = (Building_Bed)GenClosest.ClosestThingReachable(sleeper.Position, sleeper.MapHeld, ThingRequest.ForDef(thingDef), PathEndMode.OnCell, TraverseParms.For(traveler), 9999f, (Thing b) => ((Building_Bed)b).Medical && (int)b.Position.GetDangerFor(sleeper, sleeper.Map) <= (int)maxDanger && IsValidBedFor(b, sleeper, traveler, checkSocialProperness, allowMedBedEvenIfSetToNoCare: false, ignoreOtherReservations, guestStatus)); + if (building_Bed != null) + { + return building_Bed; + } + } + } + } + if (sleeper.RaceProps.Dryad) + { + return null; + } + if (sleeper.ownership != null && sleeper.ownership.OwnedBed != null && IsValidBedFor(sleeper.ownership.OwnedBed, sleeper, traveler, checkSocialProperness, allowMedBedEvenIfSetToNoCare: false, ignoreOtherReservations, guestStatus)) + { + return sleeper.ownership.OwnedBed; + } + DirectPawnRelation directPawnRelation = LovePartnerRelationUtility.ExistingMostLikedLovePartnerRel(sleeper, allowDead: false); + if (directPawnRelation != null) + { + Building_Bed ownedBed = directPawnRelation.otherPawn.ownership.OwnedBed; + if (ownedBed != null && IsValidBedFor(ownedBed, sleeper, traveler, checkSocialProperness, allowMedBedEvenIfSetToNoCare: false, ignoreOtherReservations, guestStatus)) + { + return ownedBed; + } + } + for (int dg = 0; dg < 3; dg++) + { + Danger maxDanger = ((dg <= 1) ? Danger.None : Danger.Deadly); + for (int k = 0; k < list2.Count; k++) + { + ThingDef thingDef2 = list2[k]; + if (!CanUseBedEver(sleeper, thingDef2)) + { + continue; + } + Building_Bed building_Bed2 = (Building_Bed)GenClosest.ClosestThingReachable(sleeper.PositionHeld, sleeper.MapHeld, ThingRequest.ForDef(thingDef2), PathEndMode.OnCell, TraverseParms.For(traveler), 9999f, (Thing b) => !((Building_Bed)b).Medical && (int)b.Position.GetDangerFor(sleeper, sleeper.MapHeld) <= (int)maxDanger && IsValidBedFor(b, sleeper, traveler, checkSocialProperness, allowMedBedEvenIfSetToNoCare: false, ignoreOtherReservations, guestStatus) && (dg > 0 || !b.Position.GetItems(b.Map).Any((Thing thing) => thing.def.IsCorpse))); + if (building_Bed2 != null) + { + return building_Bed2; + } + } + } + return null; + } + + public static Building_Bed FindPatientBedFor(Pawn pawn) + { + Predicate medBedValidator = delegate(Thing t) + { + if (!(t is Building_Bed building_Bed2)) + { + return false; + } + if (!building_Bed2.Medical) + { + return false; + } + return IsValidBedFor(building_Bed2, pawn, pawn, checkSocialProperness: false, allowMedBedEvenIfSetToNoCare: true, ignoreOtherReservations: false, pawn.GuestStatus) ? true : false; + }; + if (pawn.InBed() && medBedValidator(pawn.CurrentBed())) + { + return pawn.CurrentBed(); + } + for (int i = 0; i < 2; i++) + { + Danger maxDanger = ((i == 0) ? Danger.None : Danger.Deadly); + Building_Bed building_Bed = (Building_Bed)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Bed), PathEndMode.OnCell, TraverseParms.For(pawn), 9999f, (Thing b) => (int)b.Position.GetDangerFor(pawn, pawn.Map) <= (int)maxDanger && medBedValidator(b)); + if (building_Bed != null) + { + return building_Bed; + } + } + return FindBedFor(pawn); + } + + public static IntVec3 GetBedSleepingSlotPosFor(Pawn pawn, Building_Bed bed) + { + if (bed.IsOwner(pawn, out var assignedSleepingSlot)) + { + return bed.GetSleepingSlotPos(assignedSleepingSlot.Value); + } + for (int i = 0; i < bed.SleepingSlotsCount; i++) + { + Pawn curOccupant = bed.GetCurOccupant(i); + if ((i >= bed.OwnersForReading.Count || bed.OwnersForReading[i] == null) && curOccupant == pawn) + { + return bed.GetSleepingSlotPos(i); + } + } + for (int j = 0; j < bed.SleepingSlotsCount; j++) + { + Pawn curOccupant2 = bed.GetCurOccupant(j); + if ((j >= bed.OwnersForReading.Count || bed.OwnersForReading[j] == null) && curOccupant2 == null) + { + return bed.GetSleepingSlotPos(j); + } + } + Log.Error("Could not find good sleeping slot position for " + pawn?.ToString() + ". Perhaps AnyUnoccupiedSleepingSlot check is missing somewhere."); + return bed.GetSleepingSlotPos(0); + } + + public static void KickOutOfBed(Pawn pawn, Building_Bed bed) + { + if (pawn == null) + { + return; + } + if (!pawn.Spawned) + { + Log.Error("Tried to kick unspawned pawn " + pawn.ToStringSafe() + " out of bed."); + } + if (!pawn.Dead && !pawn.GetPosture().InBed()) + { + Log.Error("Tried to kick pawn " + pawn.ToStringSafe() + " out of bed when they weren't in bed."); + } + int? sleepingSlot; + Building_Bed building_Bed = pawn.CurrentBed(out sleepingSlot); + if (building_Bed != bed) + { + if (building_Bed == null) + { + bed = null; + } + else + { + Log.Error("Tried to kick pawn " + pawn.ToStringSafe() + " out of a bed they're not currently in."); + } + } + pawn.jobs.posture &= ~PawnPosture.InBedMask; + if (bed != null && (pawn.Downed || pawn.Deathresting)) + { + pawn.Position = bed.GetFootSlotPos(sleepingSlot.Value); + } + } + + public static bool CanUseBedEver(Pawn p, ThingDef bedDef) + { + if (p.RaceProps.IsMechanoid) + { + return false; + } + if (p.BodySize > bedDef.building.bed_maxBodySize) + { + return false; + } + if (p.RaceProps.Humanlike != bedDef.building.bed_humanlike) + { + return false; + } + if (ModsConfig.BiotechActive && bedDef == ThingDefOf.DeathrestCasket && !p.CanDeathrest()) + { + return false; + } + return true; + } + + public static bool TimetablePreventsLayDown(Pawn pawn) + { + if (pawn.timetable?.CurrentAssignment != null && !pawn.timetable.CurrentAssignment.allowRest && pawn.needs?.rest != null && pawn.needs.rest.CurLevel >= 0.2f) + { + return true; + } + return false; + } + + public static bool DisturbancePreventsLyingDown(Pawn pawn) + { + if (pawn.Downed) + { + return false; + } + return Find.TickManager.TicksGame - pawn.mindState.lastDisturbanceTick < 400; + } + + public static bool Awake(this Pawn p) + { + if (!p.health.capacities.CanBeAwake) + { + return false; + } + if (p.CurJob != null && p.jobs.curDriver != null) + { + return !p.jobs.curDriver.asleep; + } + return true; + } + + public static bool IsSelfShutdown(this Pawn p) + { + if (p.needs?.energy == null) + { + return false; + } + return p.needs.energy.IsSelfShutdown; + } + + public static bool IsDeactivated(this Pawn p) + { + return p.TryGetComp()?.Deactivated ?? false; + } + + public static bool IsActivityDormant(this Pawn p) + { + if (p.GetComp() == null) + { + return false; + } + return p.GetComp().IsActive; + } + + public static bool IsCharging(this Pawn p) + { + return p.needs?.energy?.currentCharger != null; + } + + public static Building_Bed CurrentBed(this Pawn p) + { + int? sleepingSlot; + return p.CurrentBed(out sleepingSlot); + } + + public static Building_Bed CurrentBed(this Pawn p, out int? sleepingSlot) + { + sleepingSlot = null; + if (!p.Spawned || p.CurJob == null || !p.GetPosture().InBed()) + { + return null; + } + Building_Bed building_Bed = null; + List thingList = p.Position.GetThingList(p.Map); + for (int i = 0; i < thingList.Count; i++) + { + building_Bed = thingList[i] as Building_Bed; + if (building_Bed != null) + { + break; + } + } + if (building_Bed == null) + { + return null; + } + for (int j = 0; j < building_Bed.SleepingSlotsCount; j++) + { + if (building_Bed.GetCurOccupant(j) == p) + { + sleepingSlot = j; + return building_Bed; + } + } + return null; + } + + public static bool InBed(this Pawn p) + { + return p.CurrentBed() != null; + } + + public static bool IsLayingForJobCleanup(Pawn p) + { + if (!p.InBed()) + { + if (p.CurJob != null && p.CurJob.def == JobDefOf.LayDown) + { + return p.GetPosture().Laying(); + } + return false; + } + return true; + } + + public static void WakeUp(Pawn p, bool startNewJob = true) + { + if (p.CurJob != null && (p.GetPosture().Laying() || p.CurJobDef == JobDefOf.LayDown) && !p.Downed) + { + p.jobs.EndCurrentJob(JobCondition.InterruptForced, startNewJob); + } + p.GetComp()?.WakeUp(); + if (p.mindState != null) + { + p.mindState.hibernationEndedTick = GenTicks.TicksGame; + } + } + + public static bool ShouldWakeUp(Pawn pawn) + { + if (pawn.Deathresting) + { + return false; + } + if (pawn.needs?.rest != null && !(pawn.needs.rest.CurLevel >= WakeThreshold(pawn))) + { + return pawn.health.hediffSet.HasHediffBlocksSleeping(); + } + return true; + } + + public static bool CanFallAsleep(Pawn pawn) + { + if (pawn.Deathresting) + { + return true; + } + Pawn_NeedsTracker needs = pawn.needs; + if (needs != null && needs.food?.Starving == true && !pawn.ageTracker.CurLifeStage.canSleepWhenStarving) + { + return false; + } + if (pawn.mindState != null && Find.TickManager.TicksGame - pawn.mindState.lastDisturbanceTick < 400) + { + return false; + } + if (pawn.needs?.rest?.CurLevel < FallAsleepMaxLevel(pawn) && !pawn.health.hediffSet.HasHediffBlocksSleeping()) + { + return pawn.CurJobDef?.sleepCanInterrupt ?? true; + } + return false; + } + + private static float WakeThreshold(Pawn p) + { + Lord lord = p.GetLord(); + if (lord != null && lord.CurLordToil != null && lord.CurLordToil.CustomWakeThreshold.HasValue) + { + return lord.CurLordToil.CustomWakeThreshold.Value; + } + return p.ageTracker.CurLifeStage?.naturalWakeThresholdOverride ?? 1f; + } + + private static float FallAsleepMaxLevel(Pawn p) + { + return Mathf.Min(p.ageTracker.CurLifeStage?.fallAsleepMaxThresholdOverride ?? 0.75f, WakeThreshold(p) - 0.01f); + } +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/JobDriver_EnterCryptosleepCasket.txt b/MCP/vector_cache/JobDriver_EnterCryptosleepCasket.txt new file mode 100644 index 00000000..5166933a --- /dev/null +++ b/MCP/vector_cache/JobDriver_EnterCryptosleepCasket.txt @@ -0,0 +1,70 @@ +根据向量相似度分析,与 'JobDriver_EnterCryptosleepCasket' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\JobDriver_EnterCryptosleepCasket.txt` + +```csharp +public class JobDriver_EnterCryptosleepCasket : JobDriver +{ + public override bool TryMakePreToilReservations(bool errorOnFailed) + { + return pawn.Reserve(job.targetA, job, 1, -1, null, errorOnFailed); + } + + protected override IEnumerable MakeNewToils() + { + this.FailOnDespawnedOrNull(TargetIndex.A); + yield return Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell); + Toil toil = Toils_General.Wait(500); + toil.FailOnCannotTouch(TargetIndex.A, PathEndMode.InteractionCell); + toil.WithProgressBarToilDelay(TargetIndex.A); + yield return toil; + Toil enter = ToilMaker.MakeToil("MakeNewToils"); + _003C_003Ec__DisplayClass1_0 CS_0024_003C_003E8__locals0; + enter.initAction = delegate + { + Building_CryptosleepCasket pod = (Building_CryptosleepCasket)((Pawn)(object)CS_0024_003C_003E8__locals0).CurJob.targetA.Thing; + Action action = delegate + { + bool flag = ((Thing)(object)CS_0024_003C_003E8__locals0).DeSpawnOrDeselect(DestroyMode.Vanish); + if (pod.TryAcceptThing((Thing)(object)CS_0024_003C_003E8__locals0) && flag) + { + Find.Selector.Select(CS_0024_003C_003E8__locals0, playSound: false, forceDesignatorDeselect: false); + } + }; + if (!pod.def.building.isPlayerEjectable) + { + if (base.Map.mapPawns.FreeColonistsSpawnedOrInPlayerEjectablePodsCount <= 1) + { + Find.WindowStack.Add(Dialog_MessageBox.CreateConfirmation("CasketWarning".Translate(CS_0024_003C_003E8__locals0.Named("PAWN")).AdjustedFor((Pawn)(object)CS_0024_003C_003E8__locals0), action)); + } + else + { + action(); + } + } + else + { + action(); + } + }; + enter.defaultCompleteMode = ToilCompleteMode.Instant; + yield return enter; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Core\Defs\JobDefs\Jobs_Misc.xml` +**相似度:** 0.5540 + +```xml + EnterCryptosleepCasket + JobDriver_EnterCryptosleepCasket + entering cryptosleep casket. + EnteredCryptosleep + true + + + + UseNeurotrainer +``` \ No newline at end of file diff --git a/MCP/vector_cache/PawnKindDef-lifeStages.txt b/MCP/vector_cache/PawnKindDef-lifeStages.txt new file mode 100644 index 00000000..20e16166 --- /dev/null +++ b/MCP/vector_cache/PawnKindDef-lifeStages.txt @@ -0,0 +1,535 @@ +根据向量相似度分析,与 'PawnKindDef, lifeStages' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\PawnKindDef.txt` + +```csharp +public class PawnKindDef : Def +{ + public ThingDef race; + + [LoadAlias("defaultFactionType")] + public FactionDef defaultFactionDef; + + [NoTranslate] + public List backstoryFilters; + + [NoTranslate] + public List backstoryFiltersOverride; + + [NoTranslate] + public List backstoryCategories; + + [MustTranslate] + public string labelPlural; + + public List lifeStages = new List(); + + public List alternateGraphics; + + [XmlInheritanceAllowDuplicateNodes] + public List forcedTraits; + + [XmlInheritanceAllowDuplicateNodes] + public List disallowedTraitsWithDegree; + + public List disallowedTraits; + + public float alternateGraphicChance; + + public MutantDef mutant; + + public XenotypeSet xenotypeSet; + + public bool useFactionXenotypes = true; + + [LoadAlias("hairTags")] + public List styleItemTags; + + public HairDef forcedHair; + + public Color? forcedHairColor; + + public List missingParts; + + public RulePackDef nameMaker; + + public RulePackDef nameMakerFemale; + + public List abilities; + + public bool preventIdeo; + + public bool studiableAsPrisoner; + + public bool isBoss; + + public Dictionary moveSpeedFactorByTerrainTag = new Dictionary(); + + public List fixedChildBackstories = new List(); + + public List fixedAdultBackstories = new List(); + + public float backstoryCryptosleepCommonality; + + public FloatRange? chronologicalAgeRange; + + public int minGenerationAge; + + public int maxGenerationAge = 999999; + + public bool factionLeader; + + public Gender? fixedGender; + + public bool allowOldAgeInjuries = true; + + public bool generateInitialNonFamilyRelations = true; + + public DevelopmentalStage? pawnGroupDevelopmentStage; + + public bool destroyGearOnDrop; + + public bool canStrip = true; + + public float defendPointRadius = -1f; + + public bool factionHostileOnKill; + + public bool factionHostileOnDeath; + + public bool hostileToAll; + + public FloatRange? initialResistanceRange; + + public FloatRange? initialWillRange; + + public bool forceNoDeathNotification; + + public bool skipResistant; + + public float controlGroupPortraitZoom = 1f; + + public float? overrideDeathOnDownedChance; + + public bool forceDeathOnDowned; + + public bool immuneToGameConditionEffects; + + public bool immuneToTraps; + + public bool collidesWithPawns = true; + + public bool ignoresPainShock; + + public bool canMeleeAttack = true; + + public float basePrisonBreakMtbDays = 60f; + + public bool useFixedRotation; + + public Rot4 fixedRotation; + + public bool showInDebugSpawner = true; + + public bool canOpenAnyDoor; + + public bool canOpenDoors = true; + + [NoTranslate] + public string overrideDebugActionCategory; + + public float royalTitleChance; + + public RoyalTitleDef titleRequired; + + public RoyalTitleDef minTitleRequired; + + public List titleSelectOne; + + public bool allowRoyalRoomRequirements = true; + + public bool allowRoyalApparelRequirements = true; + + public List meleeAttackInfectionPathways; + + public List rangedAttackInfectionPathways; + + public bool isFighter = true; + + public float combatPower = -1f; + + public bool canArriveManhunter = true; + + public bool canBeSapper; + + public bool isGoodBreacher; + + public bool allowInMechClusters = true; + + public int maxPerGroup = int.MaxValue; + + public bool isGoodPsychicRitualInvoker; + + public bool canBeScattered = true; + + public bool appearsRandomlyInCombatGroups = true; + + public bool aiAvoidCover; + + public FloatRange fleeHealthThresholdRange = new FloatRange(-0.4f, 0.4f); + + public float acceptArrestChanceFactor = 1f; + + public bool canUseAvoidGrid; + + public QualityCategory itemQuality = QualityCategory.Normal; + + public QualityCategory? forceWeaponQuality; + + public bool forceNormalGearQuality; + + public FloatRange gearHealthRange = FloatRange.One; + + public FloatRange weaponMoney = FloatRange.Zero; + + [NoTranslate] + public List weaponTags; + + public ThingDef weaponStuffOverride; + + public ThingStyleDef weaponStyleDef; + + public FloatRange apparelMoney = FloatRange.Zero; + + public List apparelRequired; + + [NoTranslate] + public List apparelTags; + + [NoTranslate] + public List apparelDisallowTags; + + public float apparelAllowHeadgearChance = 1f; + + public bool apparelIgnoreSeasons; + + public bool apparelIgnorePollution; + + public bool ignoreFactionApparelStuffRequirements; + + public Color apparelColor = Color.white; + + public Color? skinColorOverride; + + public ColorDef favoriteColor; + + public bool ignoreIdeoApparelColors; + + public List specificApparelRequirements; + + public List techHediffsRequired; + + public FloatRange techHediffsMoney = FloatRange.Zero; + + [NoTranslate] + public List techHediffsTags; + + [NoTranslate] + public List techHediffsDisallowTags; + + public float techHediffsChance; + + public int techHediffsMaxAmount = 1; + + public float biocodeWeaponChance; + + public float humanPregnancyChance = 0.03f; + + public List startingHediffs; + + public float nakedChance; + + public List existingDamage = new List(); + + public QualityCategory minApparelQuality; + + public QualityCategory maxApparelQuality = QualityCategory.Excellent; + + public List fixedInventory = new List(); + + public PawnInventoryOption inventoryOptions; + + public float invNutrition; + + public ThingDef invFoodDef; + + public float chemicalAddictionChance; + + public float combatEnhancingDrugsChance; + + public IntRange combatEnhancingDrugsCount = IntRange.Zero; + + public List forcedAddictions = new List(); + + public bool trader; + + public List skills; + + public WorkTags requiredWorkTags; + + public WorkTags disabledWorkTags; + + public int extraSkillLevels; + + public int minTotalSkillLevels; + + public int minBestSkillLevel; + + [MustTranslate] + public string labelMale; + + [MustTranslate] + public string labelMalePlural; + + [MustTranslate] + public string labelFemale; + + [MustTranslate] + public string labelFemalePlural; + + public IntRange wildGroupSize = IntRange.One; + + public float ecoSystemWeight = 1f; + + [NoTranslate] + public string flyingAnimationFramePathPrefix; + + [NoTranslate] + public string flyingAnimationFramePathPrefixFemale; + + public int flyingAnimationFrameCount; + + public int flyingAnimationTicksPerFrame = -1; + + public float flyingAnimationDrawSize = 1f; + + public bool flyingAnimationDrawSizeIsMultiplier; + + public bool flyingAnimationInheritColors; + + private const int MaxWeaponMoney = 999999; + + public RaceProperties RaceProps => race.race; + + public override void ResolveReferences() + { + base.ResolveReferences(); + for (int i = 0; i < lifeStages.Count; i++) + { + lifeStages[i].ResolveReferences(); + } + } + + public string GetLabelPlural(int count = -1) + { + if (!labelPlural.NullOrEmpty()) + { + return labelPlural; + } + return Find.ActiveLanguageWorker.Pluralize(label, count); + } + + public string GetLabelGendered(Gender gender) + { + if (gender == Gender.Female && !labelFemale.NullOrEmpty()) + { + return labelFemale; + } + if (gender == Gender.Male && !labelMale.NullOrEmpty()) + { + return labelMale; + } + return label; + } + + public RulePackDef GetNameMaker(Gender gender) + { + if (gender == Gender.Female && nameMakerFemale != null) + { + return nameMakerFemale; + } + if (nameMaker != null) + { + return nameMaker; + } + return null; + } + + public override void PostLoad() + { + if (backstoryCategories != null && backstoryCategories.Count > 0) + { + if (backstoryFilters == null) + { + backstoryFilters = new List(); + } + backstoryFilters.Add(new BackstoryCategoryFilter + { + categories = backstoryCategories + }); + } + LongEventHandler.ExecuteWhenFinished(delegate + { + foreach (PawnKindLifeStage lifeStage in lifeStages) + { + if (lifeStage.swimmingGraphicData != null && lifeStage.swimmingGraphicData.shaderType == null) + { + lifeStage.swimmingGraphicData.shaderType = ShaderTypeDefOf.Transparent; + } + if (lifeStage.femaleSwimmingGraphicData != null && lifeStage.femaleSwimmingGraphicData.shaderType == null) + { + lifeStage.femaleSwimmingGraphicData.shaderType = ShaderTypeDefOf.Transparent; + } + } + }); + } + + public float GetAnimalPointsToHuntOrSlaughter() + { + return combatPower * 5f * (1f + RaceProps.manhunterOnDamageChance * 0.5f) * (1f + RaceProps.manhunterOnTameFailChance * 0.2f) * (1f + race.GetStatValueAbstract(StatDefOf.Wildness)) + race.BaseMarketValue; + } + + public override IEnumerable ConfigErrors() + { + foreach (string item in base.ConfigErrors()) + { + yield return item; + } + if (backstoryFilters != null && backstoryFiltersOverride != null) + { + yield return "both backstoryCategories and backstoryCategoriesOverride are defined"; + } + if (race == null) + { + yield return "no race"; + } + if (combatPower < 0f) + { + yield return defName + " has no combatPower."; + } + if (weaponMoney != FloatRange.Zero) + { + if (weaponTags == null) + { + yield return "weaponMoney is set but weaponTags is not."; + } + else + { + float num = 999999f; + int i; + for (i = 0; i < weaponTags.Count; i++) + { + IEnumerable source = DefDatabase.AllDefs.Where((ThingDef d) => d.weaponTags != null && d.weaponTags.Contains(weaponTags[i])); + if (source.Any()) + { + num = Mathf.Min(num, source.Min((Func)PawnWeaponGenerator.CheapestNonDerpPriceFor)); + } + } + if (num < 999999f && num > weaponMoney.min) + { + yield return "Cheapest weapon with one of my weaponTags costs " + num + " but weaponMoney min is " + weaponMoney.min + ", so could end up weaponless."; + } + } + } + if (!RaceProps.Humanlike && lifeStages.Count != RaceProps.lifeStageAges.Count) + { + yield return "PawnKindDef defines " + lifeStages.Count + " lifeStages while race def defines " + RaceProps.lifeStageAges.Count; + } + if (apparelRequired != null) + { + for (int i = 0; i < apparelRequired.Count; i++) + { + for (int j = i + 1; j < apparelRequired.Count; j++) + { + if (!ApparelUtility.CanWearTogether(apparelRequired[i], apparelRequired[j], race.race.body)) + { + yield return "required apparel can't be worn together (" + apparelRequired[i]?.ToString() + ", " + apparelRequired[j]?.ToString() + ")"; + } + } + } + } + if (alternateGraphics != null) + { + foreach (AlternateGraphic alternateGraphic in alternateGraphics) + { + if (alternateGraphic.Weight < 0f) + { + yield return "alternate graphic has negative weight."; + } + } + } + if (RaceProps.Humanlike && !initialResistanceRange.HasValue) + { + yield return "initial resistance range is undefined for humanlike pawn kind."; + } + if (RaceProps.Humanlike && !initialWillRange.HasValue) + { + yield return "initial will range is undefined for humanlike pawn kind."; + } + if (startingHediffs == null) + { + yield break; + } + foreach (StartingHediff startingHediff in startingHediffs) + { + if (startingHediff.durationTicksRange.HasValue && startingHediff.def.CompProps() == null) + { + yield return "starting hediff " + startingHediff.def.defName + " has duration ticks set but doesn't have Disappears comp."; + } + } + } + + public static PawnKindDef Named(string defName) + { + return DefDatabase.GetNamed(defName); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Anomaly\Defs\PawnKinds\PawnKinds_Fleshbeasts.xml` +**相似度:** 0.5160 + +```xml + + Entities + Entity + +
  • EntityAttacked
  • +
    +
    +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Anomaly\Defs\PawnKinds\PawnKinds_Fleshbeasts.xml` +**相似度:** 0.5160 + +```xml + Bulbfreak + + 0.9 + Bulbfreak + 360 + +
  • + + Things/Pawn/Fleshbeast/Bulbfreak/Bulbfreak + Graphic_Multi + 3 + +
  • +
    +
    + + + Fingerspike +``` \ No newline at end of file diff --git a/MCP/vector_cache/Pawn_InventoryTracker-get_FirstUnloadableThing.txt b/MCP/vector_cache/Pawn_InventoryTracker-get_FirstUnloadableThing.txt new file mode 100644 index 00000000..5fd164b6 --- /dev/null +++ b/MCP/vector_cache/Pawn_InventoryTracker-get_FirstUnloadableThing.txt @@ -0,0 +1,4149 @@ +根据向量相似度分析,与 'get_FirstUnloadableThing, Pawn_InventoryTracker' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\Pawn_InventoryTracker.txt` + +```csharp +public class Pawn_InventoryTracker : IThingHolder, IExposable +{ + public Pawn pawn; + + public ThingOwner innerContainer; + + private bool unloadEverything; + + private List itemsNotForSale = new List(); + + private List unpackedCaravanItems = new List(); + + public static readonly Texture2D DrugTex = ContentFinder.Get("UI/Commands/TakeDrug"); + + private static List tmpItemsToKeep = new List(); + + private static readonly List tmpThingList = new List(); + + private List usableDrugsTmp = new List(); + + public bool UnloadEverything + { + get + { + if (unloadEverything) + { + return HasAnyUnloadableThing; + } + return false; + } + set + { + if (value && HasAnyUnloadableThing) + { + unloadEverything = true; + } + else + { + unloadEverything = false; + } + } + } + + public bool HasAnyUnpackedCaravanItems => unpackedCaravanItems.Count > 0; + + private bool HasAnyUnloadableThing => FirstUnloadableThing != default(ThingCount); + + public ThingCount FirstUnloadableThing + { + get + { + if (innerContainer.Count == 0) + { + return default(ThingCount); + } + if (pawn.drugs?.CurrentPolicy != null) + { + DrugPolicy currentPolicy = pawn.drugs.CurrentPolicy; + tmpItemsToKeep.Clear(); + for (int i = 0; i < currentPolicy.Count; i++) + { + if (currentPolicy[i].takeToInventory > 0) + { + tmpItemsToKeep.Add(new ThingDefCount(currentPolicy[i].drug, currentPolicy[i].takeToInventory)); + } + } + } + Pawn_InventoryStockTracker inventoryStock = pawn.inventoryStock; + if (inventoryStock != null && inventoryStock.stockEntries?.Count > 0) + { + foreach (InventoryStockEntry value in pawn.inventoryStock.stockEntries.Values) + { + tmpItemsToKeep.Add(new ThingDefCount(value.thingDef, value.count)); + } + } + foreach (Thing item in innerContainer) + { + int num = -1; + for (int j = 0; j < tmpItemsToKeep.Count; j++) + { + if (item.def == tmpItemsToKeep[j].ThingDef) + { + num = j; + break; + } + } + if (pawn.IsColonist && item.def.IsNutritionGivingIngestible && !item.def.IsDrug && JobGiver_PackFood.IsGoodPackableFoodFor(item, pawn, checkMass: false)) + { + float inventoryPackableFoodNutrition = JobGiver_PackFood.GetInventoryPackableFoodNutrition(pawn); + float maxLevel = pawn.needs.food.MaxLevel; + if (inventoryPackableFoodNutrition - item.GetStatValue(StatDefOf.Nutrition) * (float)item.stackCount <= maxLevel) + { + int k; + for (k = 0; inventoryPackableFoodNutrition - item.GetStatValue(StatDefOf.Nutrition) * (float)k > maxLevel; k++) + { + } + if (item.stackCount - k > 0) + { + tmpItemsToKeep.Add(new ThingDefCount(item.def, item.stackCount - k)); + num = tmpItemsToKeep.Count - 1; + } + } + } + if (num < 0) + { + return new ThingCount(item, item.stackCount); + } + if (item.stackCount > tmpItemsToKeep[num].Count) + { + return new ThingCount(item, item.stackCount - tmpItemsToKeep[num].Count); + } + tmpItemsToKeep[num] = new ThingDefCount(tmpItemsToKeep[num].ThingDef, tmpItemsToKeep[num].Count - item.stackCount); + } + return default(ThingCount); + } + } + + public IThingHolder ParentHolder => pawn; + + public Pawn_InventoryTracker(Pawn pawn) + { + this.pawn = pawn; + innerContainer = new ThingOwner(this, oneStackOnly: false); + } + + public void ExposeData() + { + Scribe_Collections.Look(ref itemsNotForSale, "itemsNotForSale", LookMode.Reference); + Scribe_Collections.Look(ref unpackedCaravanItems, "unpackedCaravanItems", LookMode.Reference); + Scribe_Deep.Look(ref innerContainer, "innerContainer", this); + Scribe_Values.Look(ref unloadEverything, "unloadEverything", defaultValue: false); + } + + public void InventoryTrackerTick() + { + if (unloadEverything && !HasAnyUnloadableThing) + { + unloadEverything = false; + } + } + + public void DropAllNearPawn(IntVec3 pos, bool forbid = false, bool unforbid = false) + { + DropAllNearPawnHelper(pos, forbid, unforbid); + } + + private void DropAllNearPawnHelper(IntVec3 pos, bool forbid = false, bool unforbid = false, bool caravanHaulOnly = false) + { + if (pawn.MapHeld == null) + { + Log.Error("Tried to drop all inventory near pawn but the pawn is unspawned. pawn=" + pawn); + return; + } + tmpThingList.Clear(); + if (caravanHaulOnly) + { + tmpThingList.AddRange(unpackedCaravanItems); + } + else + { + tmpThingList.AddRange(innerContainer); + } + int i; + for (i = 0; i < tmpThingList.Count; i++) + { + if (caravanHaulOnly && !innerContainer.Contains(tmpThingList[i])) + { + unpackedCaravanItems.Remove(tmpThingList[i]); + Log.Warning("Could not drop unpacked caravan item " + tmpThingList[i].Label + ", inventory no longer contains it"); + continue; + } + innerContainer.TryDrop(tmpThingList[i], pos, pawn.MapHeld, ThingPlaceMode.Near, out var _, delegate(Thing t, int unused) + { + if (forbid) + { + t.SetForbiddenIfOutsideHomeArea(); + } + if (unforbid) + { + t.SetForbidden(value: false, warnOnFail: false); + } + if (t.def.IsPleasureDrug) + { + LessonAutoActivator.TeachOpportunity(ConceptDefOf.DrugBurning, OpportunityType.Important); + } + LordJob_FormAndSendCaravan lordJob_FormAndSendCaravan = CaravanFormingUtility.GetFormAndSendCaravanLord(pawn)?.LordJob as LordJob_FormAndSendCaravan; + if (caravanHaulOnly && lordJob_FormAndSendCaravan != null && lordJob_FormAndSendCaravan.GatheringItemsNow) + { + CaravanFormingUtility.TryAddItemBackToTransferables(t, lordJob_FormAndSendCaravan.transferables, tmpThingList[i].stackCount); + } + unpackedCaravanItems.Remove(tmpThingList[i]); + }); + } + } + + public void DropCount(ThingDef def, int count, bool forbid = false, bool unforbid = false) + { + if (pawn.MapHeld == null) + { + Log.Error("Tried to drop a thing near pawn but the pawn is unspawned. pawn=" + pawn); + return; + } + tmpThingList.Clear(); + tmpThingList.AddRange(innerContainer); + int num = 0; + for (int i = 0; i < tmpThingList.Count; i++) + { + Thing thing = tmpThingList[i]; + if (thing.def != def) + { + continue; + } + int num2 = Math.Min(thing.stackCount, count); + innerContainer.TryDrop(tmpThingList[i], pawn.Position, pawn.MapHeld, ThingPlaceMode.Near, num2, out var _, delegate(Thing t, int unused) + { + if (forbid) + { + t.SetForbiddenIfOutsideHomeArea(); + } + if (unforbid) + { + t.SetForbidden(value: false, warnOnFail: false); + } + if (t.def.IsPleasureDrug) + { + LessonAutoActivator.TeachOpportunity(ConceptDefOf.DrugBurning, OpportunityType.Important); + } + }); + num += num2; + if (num >= count) + { + break; + } + } + } + + public void RemoveCount(ThingDef def, int count, bool destroy = true) + { + tmpThingList.Clear(); + tmpThingList.AddRange(innerContainer); + foreach (Thing tmpThing in tmpThingList) + { + if (tmpThing.def != def) + { + continue; + } + if (tmpThing.stackCount > count) + { + tmpThing.stackCount -= count; + break; + } + innerContainer.Remove(tmpThing); + if (destroy) + { + tmpThing.Destroy(); + } + break; + } + } + + public void DestroyAll(DestroyMode mode = DestroyMode.Vanish) + { + innerContainer.ClearAndDestroyContents(mode); + } + + public bool Contains(Thing item) + { + return innerContainer.Contains(item); + } + + public int Count(ThingDef def) + { + int num = 0; + foreach (Thing item in innerContainer) + { + if (item.def == def) + { + num += item.stackCount; + } + } + return num; + } + + public int Count(Func validator) + { + int num = 0; + foreach (Thing item in innerContainer) + { + if (validator(item)) + { + num += item.stackCount; + } + } + return num; + } + + public void AddHauledCaravanItem(Thing item) + { + if (pawn.carryTracker.innerContainer.TryTransferToContainer(item, innerContainer, item.stackCount, out var resultingTransferredItem, canMergeWithExistingStacks: false) > 0) + { + unpackedCaravanItems.Add(resultingTransferredItem); + } + CompForbiddable compForbiddable = resultingTransferredItem?.TryGetComp(); + if (compForbiddable != null) + { + compForbiddable.Forbidden = false; + } + } + + public void TryAddAndUnforbid(Thing item) + { + CompForbiddable compForbiddable = item.TryGetComp(); + if (innerContainer.TryAdd(item) && compForbiddable != null) + { + compForbiddable.Forbidden = false; + } + } + + public void TransferCaravanItemsToCarrier(Pawn_InventoryTracker carrierInventory) + { + List list = new List(); + list.AddRange(pawn.inventory.unpackedCaravanItems); + foreach (Thing item in list) + { + if (MassUtility.IsOverEncumbered(carrierInventory.pawn)) + { + break; + } + if (innerContainer.Contains(item)) + { + pawn.inventory.innerContainer.TryTransferToContainer(item, carrierInventory.innerContainer, item.stackCount); + } + unpackedCaravanItems.Remove(item); + } + } + + public void DropAllPackingCaravanThings() + { + if (pawn.Spawned) + { + DropAllNearPawnHelper(pawn.Position, forbid: false, unforbid: false, caravanHaulOnly: true); + ClearHaulingCaravanCache(); + } + } + + public void ClearHaulingCaravanCache() + { + unpackedCaravanItems.Clear(); + } + + public bool NotForSale(Thing item) + { + return itemsNotForSale.Contains(item); + } + + public void TryAddItemNotForSale(Thing item) + { + if (innerContainer.TryAdd(item, canMergeWithExistingStacks: false)) + { + itemsNotForSale.Add(item); + } + } + + public void Notify_ItemRemoved(Thing item) + { + itemsNotForSale.Remove(item); + unpackedCaravanItems.Remove(item); + if (unloadEverything && !HasAnyUnloadableThing) + { + unloadEverything = false; + } + } + + public ThingOwner GetDirectlyHeldThings() + { + return innerContainer; + } + + public void GetChildHolders(List outChildren) + { + ThingOwnerUtility.AppendThingHoldersFromThings(outChildren, GetDirectlyHeldThings()); + } + + public IEnumerable GetDrugs() + { + foreach (Thing item in innerContainer) + { + if (item.TryGetComp() != null) + { + yield return item; + } + } + } + + public IEnumerable GetCombatEnhancingDrugs() + { + foreach (Thing item in innerContainer) + { + CompDrug compDrug = item.TryGetComp(); + if (compDrug != null && compDrug.Props.isCombatEnhancingDrug) + { + yield return item; + } + } + } + + public Thing FindCombatEnhancingDrug() + { + return GetCombatEnhancingDrugs().FirstOrDefault(); + } + + public IEnumerable GetGizmos() + { + if (!pawn.IsColonistPlayerControlled || !pawn.Drafted || Find.Selector.SingleSelectedThing != pawn) + { + yield break; + } + usableDrugsTmp.Clear(); + foreach (Thing drug2 in GetDrugs()) + { + if (FoodUtility.WillIngestFromInventoryNow(pawn, drug2)) + { + usableDrugsTmp.Add(drug2); + } + } + if (usableDrugsTmp.Count == 0) + { + yield break; + } + if (usableDrugsTmp.Count == 1) + { + Thing drug = usableDrugsTmp[0]; + string defaultLabel = (drug.def.ingestible.ingestCommandString.NullOrEmpty() ? "ConsumeThing".Translate(drug.LabelNoCount, drug) : drug.def.ingestible.ingestCommandString.Formatted(drug.LabelShort)); + Command_Action command_Action = new Command_Action(); + command_Action.defaultLabel = defaultLabel; + command_Action.defaultDesc = drug.LabelCapNoCount + ": " + drug.def.description.CapitalizeFirst(); + command_Action.icon = drug.def.uiIcon; + command_Action.iconAngle = drug.def.uiIconAngle; + command_Action.iconOffset = drug.def.uiIconOffset; + command_Action.action = delegate + { + FoodUtility.IngestFromInventoryNow(pawn, drug); + }; + yield return command_Action; + yield break; + } + Command_Action command_Action2 = new Command_Action(); + command_Action2.defaultLabel = "TakeDrug".Translate(); + command_Action2.defaultDesc = "TakeDrugDesc".Translate(); + command_Action2.icon = DrugTex; + command_Action2.action = delegate + { + List list = new List(); + foreach (Thing drug in usableDrugsTmp) + { + string label = (drug.def.ingestible.ingestCommandString.NullOrEmpty() ? "ConsumeThing".Translate(drug.LabelNoCount, drug) : drug.def.ingestible.ingestCommandString.Formatted(drug.LabelShort)); + list.Add(new FloatMenuOption(label, delegate + { + FoodUtility.IngestFromInventoryNow(pawn, drug); + })); + } + Find.WindowStack.Add(new FloatMenu(list)); + }; + yield return command_Action2; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\ThingOwnerUtility.txt` +**相似度:** 0.6304 + +```csharp +public static class ThingOwnerUtility +{ + private static readonly Stack tmpStack = new Stack(); + + private static readonly List tmpHolders = new List(); + + private static readonly List tmpThings = new List(); + + private static readonly List tmpMapChildHolders = new List(); + + public static bool ThisOrAnyCompIsThingHolder(this ThingDef thingDef) + { + if (typeof(IThingHolder).IsAssignableFrom(thingDef.thingClass)) + { + return true; + } + for (int i = 0; i < thingDef.comps.Count; i++) + { + if (typeof(IThingHolder).IsAssignableFrom(thingDef.comps[i].compClass)) + { + return true; + } + } + return false; + } + + public static ThingOwner TryGetInnerInteractableThingOwner(this Thing thing) + { + IThingHolder thingHolder = thing as IThingHolder; + ThingWithComps thingWithComps = thing as ThingWithComps; + if (thingHolder != null) + { + ThingOwner directlyHeldThings = thingHolder.GetDirectlyHeldThings(); + if (directlyHeldThings != null) + { + return directlyHeldThings; + } + } + if (thingWithComps != null) + { + List allComps = thingWithComps.AllComps; + for (int i = 0; i < allComps.Count; i++) + { + if (allComps[i] is IThingHolder thingHolder2) + { + ThingOwner directlyHeldThings2 = thingHolder2.GetDirectlyHeldThings(); + if (directlyHeldThings2 != null) + { + return directlyHeldThings2; + } + } + } + } + tmpHolders.Clear(); + if (thingHolder != null) + { + thingHolder.GetChildHolders(tmpHolders); + if (tmpHolders.Any()) + { + ThingOwner directlyHeldThings3 = tmpHolders[0].GetDirectlyHeldThings(); + if (directlyHeldThings3 != null) + { + tmpHolders.Clear(); + return directlyHeldThings3; + } + } + } + if (thingWithComps != null) + { + List allComps2 = thingWithComps.AllComps; + for (int j = 0; j < allComps2.Count; j++) + { + if (!(allComps2[j] is IThingHolder thingHolder3)) + { + continue; + } + thingHolder3.GetChildHolders(tmpHolders); + if (tmpHolders.Any()) + { + ThingOwner directlyHeldThings4 = tmpHolders[0].GetDirectlyHeldThings(); + if (directlyHeldThings4 != null) + { + tmpHolders.Clear(); + return directlyHeldThings4; + } + } + } + } + tmpHolders.Clear(); + return null; + } + + public static bool SpawnedOrAnyParentSpawned(IThingHolder holder) + { + return SpawnedParentOrMe(holder) != null; + } + + public static Thing SpawnedParentOrMe(IThingHolder holder) + { + while (holder != null) + { + if (holder is Thing { Spawned: not false } thing) + { + return thing; + } + if (holder is ThingComp thingComp && thingComp.parent.Spawned) + { + return thingComp.parent; + } + holder = holder.ParentHolder; + } + return null; + } + + public static IntVec3 GetRootPosition(IThingHolder holder) + { + IntVec3 result = IntVec3.Invalid; + while (holder != null) + { + if (holder is Thing { Position: { IsValid: not false } } thing) + { + result = thing.Position; + } + else if (holder is ThingComp thingComp && thingComp.parent.Position.IsValid) + { + result = thingComp.parent.Position; + } + holder = holder.ParentHolder; + } + return result; + } + + public static Map GetRootMap(IThingHolder holder) + { + while (holder != null) + { + if (holder is Map result) + { + return result; + } + holder = holder.ParentHolder; + } + return null; + } + + public static PlanetTile GetRootTile(IThingHolder holder) + { + while (holder != null) + { + if (holder is WorldObject { Tile: { Valid: not false } } worldObject) + { + return worldObject.Tile; + } + holder = holder.ParentHolder; + } + return PlanetTile.Invalid; + } + + public static bool ContentsSuspended(IThingHolder holder) + { + while (holder != null) + { + if (holder is Building_CryptosleepCasket || holder is ISuspendableThingHolder { IsContentsSuspended: not false }) + { + return true; + } + holder = holder.ParentHolder; + } + return false; + } + + public static bool ContentsInCryptosleep(IThingHolder holder) + { + while (holder != null) + { + if (holder is Building_CryptosleepCasket) + { + return true; + } + holder = holder.ParentHolder; + } + return false; + } + + public static bool IsEnclosingContainer(this IThingHolder holder) + { + if (holder != null && !(holder is Pawn_CarryTracker) && !(holder is Corpse) && !(holder is Map) && !(holder is Caravan) && !(holder is Settlement_TraderTracker)) + { + return !(holder is TradeShip); + } + return false; + } + + public static bool ShouldAutoRemoveDestroyedThings(IThingHolder holder) + { + if (!(holder is Corpse)) + { + return !(holder is Caravan); + } + return false; + } + + public static bool ShouldAutoExtinguishInnerThings(IThingHolder holder) + { + return !(holder is Map); + } + + public static bool ShouldRemoveDesignationsOnAddedThings(IThingHolder holder) + { + return holder.IsEnclosingContainer(); + } + + public static void AppendThingHoldersFromThings(List outThingsHolders, IList container) + { + if (container == null) + { + return; + } + int i = 0; + for (int count = container.Count; i < count; i++) + { + if (container[i] is IThingHolder item) + { + outThingsHolders.Add(item); + } + if (!(container[i] is ThingWithComps { AllComps: var allComps })) + { + continue; + } + for (int j = 0; j < allComps.Count; j++) + { + if (allComps[j] is IThingHolder item2) + { + outThingsHolders.Add(item2); + } + } + } + } + + public static bool AnyParentIs(Thing thing) where T : class, IThingHolder + { + return GetAnyParent(thing) != null; + } + + public static T GetAnyParent(Thing thing) where T : class, IThingHolder + { + if (thing is T result) + { + return result; + } + for (IThingHolder parentHolder = thing.ParentHolder; parentHolder != null; parentHolder = parentHolder.ParentHolder) + { + if (parentHolder is T result2) + { + return result2; + } + } + return null; + } + + public static Thing GetFirstParentThing(Thing thing) + { + for (IThingHolder parentHolder = thing.ParentHolder; parentHolder != null; parentHolder = parentHolder.ParentHolder) + { + if (parentHolder is Thing result) + { + return result; + } + if (parentHolder is ThingComp thingComp) + { + return thingComp.parent; + } + } + return null; + } + + public static Thing GetFirstSpawnedParentThing(Thing thing) + { + if (thing.Spawned) + { + return thing; + } + for (IThingHolder parentHolder = thing.ParentHolder; parentHolder != null; parentHolder = parentHolder.ParentHolder) + { + if (parentHolder is Thing { Spawned: not false } thing2) + { + return thing2; + } + if (parentHolder is ThingComp thingComp && thingComp.parent.Spawned) + { + return thingComp.parent; + } + } + return null; + } + + public static void GetAllThingsRecursively(IThingHolder holder, List outThings, bool allowUnreal = true, Predicate passCheck = null) + { + outThings.Clear(); + if (passCheck != null && !passCheck(holder)) + { + return; + } + tmpStack.Clear(); + tmpStack.Push(holder); + while (tmpStack.Count != 0) + { + IThingHolder thingHolder = tmpStack.Pop(); + if (allowUnreal || AreImmediateContentsReal(thingHolder)) + { + ThingOwner directlyHeldThings = thingHolder.GetDirectlyHeldThings(); + if (directlyHeldThings != null) + { + outThings.AddRange(directlyHeldThings); + } + } + tmpHolders.Clear(); + thingHolder.GetChildHolders(tmpHolders); + for (int i = 0; i < tmpHolders.Count; i++) + { + if (passCheck == null || passCheck(tmpHolders[i])) + { + tmpStack.Push(tmpHolders[i]); + } + } + } + tmpStack.Clear(); + tmpHolders.Clear(); + } + + public static void GetAllThingsRecursively(Map map, ThingRequest request, List outThings, bool allowUnreal = true, Predicate passCheck = null, bool alsoGetSpawnedThings = true) where T : Thing + { + outThings.Clear(); + if (alsoGetSpawnedThings) + { + List list = map.listerThings.ThingsMatching(request); + for (int i = 0; i < list.Count; i++) + { + if (list[i] is T item) + { + outThings.Add(item); + } + } + } + tmpMapChildHolders.Clear(); + map.GetChildHolders(tmpMapChildHolders); + for (int j = 0; j < tmpMapChildHolders.Count; j++) + { + tmpThings.Clear(); + GetAllThingsRecursively(tmpMapChildHolders[j], tmpThings, allowUnreal, passCheck); + for (int k = 0; k < tmpThings.Count; k++) + { + if (tmpThings[k] is T val && request.Accepts(val)) + { + outThings.Add(val); + } + } + } + tmpThings.Clear(); + tmpMapChildHolders.Clear(); + } + + public static List GetAllThingsRecursively(IThingHolder holder, bool allowUnreal = true) + { + List list = new List(); + GetAllThingsRecursively(holder, list, allowUnreal); + return list; + } + + public static bool AreImmediateContentsReal(IThingHolder holder) + { + if (!(holder is Corpse)) + { + return !(holder is MinifiedThing); + } + return false; + } + + public static bool TryGetFixedTemperature(IThingHolder holder, Thing forThing, out float temperature) + { + if (holder is Pawn_InventoryTracker && forThing.TryGetComp() != null) + { + temperature = 14f; + return true; + } + if (holder is CompLaunchable || holder is ActiveTransporterInfo || holder is TravellingTransporters) + { + temperature = 14f; + return true; + } + if (holder is Settlement_TraderTracker || holder is TradeShip) + { + temperature = 14f; + return true; + } + if (holder is CompTransporter) + { + temperature = 14f; + return true; + } + temperature = 21f; + return false; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld.Planet\CaravanInventoryUtility.txt` +**相似度:** 0.6279 + +```csharp +public static class CaravanInventoryUtility +{ + private static List inventoryItems = new List(); + + private static List inventoryToMove = new List(); + + private static List tmpApparel = new List(); + + private static List tmpEquipment = new List(); + + public static List AllInventoryItems(Caravan caravan) + { + inventoryItems.Clear(); + List pawnsListForReading = caravan.PawnsListForReading; + for (int i = 0; i < pawnsListForReading.Count; i++) + { + Pawn pawn = pawnsListForReading[i]; + for (int num = pawn.inventory.innerContainer.Count - 1; num >= 0; num--) + { + Thing item = pawn.inventory.innerContainer[num]; + inventoryItems.Add(item); + } + } + return inventoryItems; + } + + public static Building_PassengerShuttle FindShuttle(Caravan caravan) + { + List list = AllInventoryItems(caravan); + for (int i = 0; i < list.Count; i++) + { + if (list[i] is Building_PassengerShuttle result) + { + return result; + } + } + return null; + } + + public static void CaravanInventoryUtilityStaticUpdate() + { + inventoryItems.Clear(); + } + + public static Pawn GetOwnerOf(Caravan caravan, Thing item) + { + IThingHolder parentHolder = item.ParentHolder; + if (parentHolder is Pawn_InventoryTracker) + { + Pawn pawn = (Pawn)parentHolder.ParentHolder; + if (caravan.ContainsPawn(pawn)) + { + return pawn; + } + } + return null; + } + + public static bool TryGetBestFood(Caravan caravan, Pawn forPawn, out Thing food, out Pawn owner) + { + List list = AllInventoryItems(caravan); + Thing thing = null; + float num = 0f; + for (int i = 0; i < list.Count; i++) + { + Thing thing2 = list[i]; + if (CaravanPawnsNeedsUtility.CanEatForNutritionNow(thing2, forPawn)) + { + float foodScore = CaravanPawnsNeedsUtility.GetFoodScore(thing2, forPawn); + if (thing == null || foodScore > num) + { + thing = thing2; + num = foodScore; + } + } + } + if (thing != null) + { + food = thing; + owner = GetOwnerOf(caravan, thing); + return true; + } + food = null; + owner = null; + return false; + } + + public static bool TryGetDrugToSatisfyChemicalNeed(Caravan caravan, Pawn forPawn, Hediff hediff, out Thing drug, out Pawn owner) + { + if (hediff == null) + { + drug = null; + owner = null; + return false; + } + List list = AllInventoryItems(caravan); + Thing thing = null; + for (int i = 0; i < list.Count; i++) + { + Thing thing2 = list[i]; + if (!thing2.IngestibleNow || !thing2.def.IsDrug) + { + continue; + } + CompDrug compDrug = thing2.TryGetComp(); + if (compDrug != null && compDrug.Props.chemical != null && (!(hediff is Hediff_ChemicalDependency hediff_ChemicalDependency) || compDrug.Props.chemical == hediff_ChemicalDependency.chemical) && (!(hediff is Hediff_Addiction hediff_Addiction) || compDrug.Props.chemical.addictionHediff == hediff_Addiction.def)) + { + DrugPolicy drugPolicy = forPawn.drugs?.CurrentPolicy; + if (drugPolicy == null || drugPolicy[thing2.def].allowedForAddiction || forPawn.story == null || forPawn.story.traits.DegreeOfTrait(TraitDefOf.DrugDesire) > 0) + { + thing = thing2; + break; + } + } + } + if (thing != null) + { + drug = thing; + owner = GetOwnerOf(caravan, thing); + return true; + } + drug = null; + owner = null; + return false; + } + + public static bool TryGetBestMedicine(Caravan caravan, Pawn patient, out Medicine medicine, out Pawn owner) + { + if (patient.playerSettings == null || (int)patient.playerSettings.medCare <= 1) + { + medicine = null; + owner = null; + return false; + } + List list = AllInventoryItems(caravan); + Medicine medicine2 = null; + float num = 0f; + for (int i = 0; i < list.Count; i++) + { + Thing thing = list[i]; + if (thing.def.IsMedicine && patient.playerSettings.medCare.AllowsMedicine(thing.def)) + { + float statValue = thing.GetStatValue(StatDefOf.MedicalPotency); + if (statValue > num || medicine2 == null) + { + num = statValue; + medicine2 = (Medicine)thing; + } + } + } + if (medicine2 != null) + { + medicine = medicine2; + owner = GetOwnerOf(caravan, medicine2); + return true; + } + medicine = null; + owner = null; + return false; + } + + public static bool TryGetThingOfDef(Caravan caravan, ThingDef thingDef, out Thing thing, out Pawn owner) + { + List list = AllInventoryItems(caravan); + for (int i = 0; i < list.Count; i++) + { + Thing thing2 = list[i]; + if (thing2.def == thingDef) + { + thing = thing2; + owner = GetOwnerOf(caravan, thing2); + return true; + } + } + thing = null; + owner = null; + return false; + } + + public static void MoveAllInventoryToSomeoneElse(Pawn from, List candidates, List ignoreCandidates = null) + { + inventoryToMove.Clear(); + inventoryToMove.AddRange(from.inventory.innerContainer); + for (int i = 0; i < inventoryToMove.Count; i++) + { + MoveInventoryToSomeoneElse(from, inventoryToMove[i], candidates, ignoreCandidates, inventoryToMove[i].stackCount); + } + inventoryToMove.Clear(); + } + + public static void MoveInventoryToSomeoneElse(Pawn itemOwner, Thing item, List candidates, List ignoreCandidates, int numToMove) + { + if (numToMove < 0 || numToMove > item.stackCount) + { + Log.Warning("Tried to move item " + item?.ToString() + " with numToMove=" + numToMove + " (item stack count = " + item.stackCount + ")"); + } + else + { + Pawn pawn = FindPawnToMoveInventoryTo(item, candidates, ignoreCandidates, itemOwner); + if (pawn != null) + { + itemOwner.inventory.innerContainer.TryTransferToContainer(item, pawn.inventory.innerContainer, numToMove); + } + } + } + + public static Pawn FindPawnToMoveInventoryTo(Thing item, List candidates, List ignoreCandidates, Pawn currentItemOwner = null) + { + if (item is Pawn) + { + Log.Error("Called FindPawnToMoveInventoryTo but the item is a pawn."); + return null; + } + if (candidates.Where((Pawn x) => CanMoveInventoryTo(x) && (ignoreCandidates == null || !ignoreCandidates.Contains(x)) && x != currentItemOwner && !MassUtility.IsOverEncumbered(x)).TryRandomElement(out var result)) + { + return result; + } + if (candidates.Where((Pawn x) => CanMoveInventoryTo(x) && (ignoreCandidates == null || !ignoreCandidates.Contains(x)) && x != currentItemOwner).TryRandomElement(out result)) + { + return result; + } + if (candidates.Where((Pawn x) => (ignoreCandidates == null || !ignoreCandidates.Contains(x)) && x != currentItemOwner).TryRandomElement(out result)) + { + return result; + } + return null; + } + + public static void MoveAllApparelToSomeonesInventory(Pawn moveFrom, List candidates, bool moveLocked = true) + { + if (moveFrom.apparel == null) + { + return; + } + tmpApparel.Clear(); + if (moveLocked) + { + tmpApparel.AddRange(moveFrom.apparel.WornApparel); + } + else + { + for (int i = 0; i < moveFrom.apparel.WornApparel.Count; i++) + { + Apparel apparel = moveFrom.apparel.WornApparel[i]; + if (!moveFrom.apparel.IsLocked(apparel)) + { + tmpApparel.Add(apparel); + } + } + } + for (int j = 0; j < tmpApparel.Count; j++) + { + moveFrom.apparel.Remove(tmpApparel[j]); + FindPawnToMoveInventoryTo(tmpApparel[j], candidates, null, moveFrom)?.inventory.innerContainer.TryAdd(tmpApparel[j]); + } + tmpApparel.Clear(); + } + + public static void MoveAllEquipmentToSomeonesInventory(Pawn moveFrom, List candidates) + { + if (moveFrom.equipment != null) + { + tmpEquipment.Clear(); + tmpEquipment.AddRange(moveFrom.equipment.AllEquipmentListForReading); + for (int i = 0; i < tmpEquipment.Count; i++) + { + moveFrom.equipment.Remove(tmpEquipment[i]); + FindPawnToMoveInventoryTo(tmpEquipment[i], candidates, null, moveFrom)?.inventory.innerContainer.TryAdd(tmpEquipment[i]); + } + tmpEquipment.Clear(); + } + } + + private static bool CanMoveInventoryTo(Pawn pawn) + { + return MassUtility.CanEverCarryAnything(pawn); + } + + public static List TakeThings(Caravan caravan, Func takeQuantity) + { + List list = new List(); + foreach (Thing item in AllInventoryItems(caravan).ToList()) + { + int num = takeQuantity(item); + if (num > 0) + { + list.Add(item.holdingOwner.Take(item, num)); + } + } + return list; + } + + public static void GiveThing(Caravan caravan, Thing thing) + { + if (AllInventoryItems(caravan).Contains(thing)) + { + Log.Error("Tried to give the same item twice (" + thing?.ToString() + ") to a caravan (" + caravan?.ToString() + ")."); + return; + } + Pawn pawn = FindPawnToMoveInventoryTo(thing, caravan.PawnsListForReading, null); + if (pawn == null) + { + Log.Error($"Failed to give item {thing} to caravan {caravan}; item was lost"); + thing.Destroy(); + } + else if (!pawn.inventory.innerContainer.TryAdd(thing)) + { + Log.Error($"Failed to give item {thing} to caravan {caravan}; item was lost"); + thing.Destroy(); + } + } + + public static bool HasThings(Caravan caravan, ThingDef thingDef, int count, Func validator = null) + { + int num = 0; + List list = AllInventoryItems(caravan); + for (int i = 0; i < list.Count; i++) + { + Thing thing = list[i]; + if (thing.def == thingDef && (validator == null || validator(thing))) + { + num += thing.stackCount; + } + } + return num >= count; + } + + public static IEnumerable GetAllDissolvingThings(Caravan caravan) + { + ThingRequest group = ThingRequest.ForGroup(ThingRequestGroup.Dissolving); + List items = AllInventoryItems(caravan); + for (int i = 0; i < items.Count; i++) + { + if (group.Accepts(items[i])) + { + yield return items[i]; + } + } + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\ThingOwner.txt` +**相似度:** 0.6188 + +```csharp +public abstract class ThingOwner : IExposable, IList, ICollection, IEnumerable, IEnumerable +{ + protected IThingHolder owner; + + protected int maxStacks = 999999; + + public LookMode contentsLookMode = LookMode.Deep; + + public bool removeContentsIfDestroyed = true; + + private const int InfMaxStacks = 999999; + + public IThingHolder Owner => owner; + + public abstract int Count { get; } + + public Thing this[int index] => GetAt(index); + + public bool Any => Count > 0; + + public int TotalStackCount + { + get + { + int num = 0; + int count = Count; + for (int i = 0; i < count; i++) + { + num += GetAt(i).stackCount; + } + return num; + } + } + + public string ContentsString + { + get + { + if (Any) + { + return GenThing.ThingsToCommaList(this); + } + return "NothingLower".Translate(); + } + } + + Thing IList.this[int index] + { + get + { + return GetAt(index); + } + set + { + throw new InvalidOperationException("ThingOwner doesn't allow setting individual elements."); + } + } + + bool ICollection.IsReadOnly => true; + + public event Action OnContentsChanged; + + public ThingOwner() + { + } + + public ThingOwner(IThingHolder owner) + { + this.owner = owner; + } + + public ThingOwner(IThingHolder owner, LookMode contentsLookMode = LookMode.Deep, bool removeContentsIfDestroyed = true) + { + this.owner = owner; + this.contentsLookMode = contentsLookMode; + this.removeContentsIfDestroyed = removeContentsIfDestroyed; + } + + public ThingOwner(IThingHolder owner, bool oneStackOnly, LookMode contentsLookMode = LookMode.Deep, bool removeContentsIfDestroyed = true) + : this(owner) + { + maxStacks = (oneStackOnly ? 1 : 999999); + this.contentsLookMode = contentsLookMode; + this.removeContentsIfDestroyed = removeContentsIfDestroyed; + } + + public virtual void ExposeData() + { + Scribe_Values.Look(ref maxStacks, "maxStacks", 999999); + Scribe_Values.Look(ref contentsLookMode, "contentsLookMode", LookMode.Deep); + Scribe_Values.Look(ref removeContentsIfDestroyed, "removeContentsIfDestroyed", defaultValue: true); + } + + public void DoTick() + { + for (int num = Count - 1; num >= 0; num--) + { + Thing at = GetAt(num); + int offset = ((owner is Thing t) ? t.HashOffset() : 0); + at.DoTick(); + if (at.def.tickerType == TickerType.Rare && GenTicks.IsTickInterval(offset, 250)) + { + at.TickRare(); + } + else if (at.def.tickerType == TickerType.Long && GenTicks.IsTickInterval(offset, 2000)) + { + at.TickLong(); + } + if (at.Destroyed && removeContentsIfDestroyed) + { + Remove(at); + } + } + } + + public void Clear() + { + for (int num = Count - 1; num >= 0; num--) + { + Remove(GetAt(num)); + } + } + + public void ClearAndDestroyContents(DestroyMode mode = DestroyMode.Vanish) + { + while (Any) + { + for (int num = Count - 1; num >= 0; num--) + { + Thing at = GetAt(num); + at.Destroy(mode); + Remove(at); + } + } + } + + public void ClearAndDestroyContentsOrPassToWorld(DestroyMode mode = DestroyMode.Vanish) + { + while (Any) + { + for (int num = Count - 1; num >= 0; num--) + { + Thing at = GetAt(num); + at.DestroyOrPassToWorld(mode); + Remove(at); + } + } + } + + public bool CanAcceptAnyOf(Thing item, bool canMergeWithExistingStacks = true) + { + return GetCountCanAccept(item, canMergeWithExistingStacks) > 0; + } + + public virtual int GetCountCanAccept(Thing item, bool canMergeWithExistingStacks = true) + { + if (item == null || item.stackCount <= 0) + { + return 0; + } + if (maxStacks == 999999) + { + return item.stackCount; + } + int num = 0; + if (Count < maxStacks) + { + num += (maxStacks - Count) * item.def.stackLimit; + } + if (num >= item.stackCount) + { + return Mathf.Min(num, item.stackCount); + } + if (canMergeWithExistingStacks) + { + int i = 0; + for (int count = Count; i < count; i++) + { + Thing at = GetAt(i); + if (at.stackCount < at.def.stackLimit && at.CanStackWith(item)) + { + num += at.def.stackLimit - at.stackCount; + if (num >= item.stackCount) + { + return Mathf.Min(num, item.stackCount); + } + } + } + } + return Mathf.Min(num, item.stackCount); + } + + public abstract int TryAdd(Thing item, int count, bool canMergeWithExistingStacks = true); + + public abstract bool TryAdd(Thing item, bool canMergeWithExistingStacks = true); + + public abstract int IndexOf(Thing item); + + public abstract bool Remove(Thing item); + + protected abstract Thing GetAt(int index); + + public bool Contains(Thing item) + { + if (item == null) + { + return false; + } + return item.holdingOwner == this; + } + + public void RemoveAt(int index) + { + if (index < 0 || index >= Count) + { + throw new ArgumentOutOfRangeException("index"); + } + Remove(GetAt(index)); + } + + public int TryAddOrTransfer(Thing item, int count, bool canMergeWithExistingStacks = true) + { + if (item == null) + { + Log.Warning("Tried to add or transfer null item to ThingOwner."); + return 0; + } + if (item.holdingOwner != null) + { + return item.holdingOwner.TryTransferToContainer(item, this, count, canMergeWithExistingStacks); + } + return TryAdd(item, count, canMergeWithExistingStacks); + } + + public bool TryAddOrTransfer(Thing item, bool canMergeWithExistingStacks = true) + { + if (item == null) + { + Log.Warning("Tried to add or transfer null item to ThingOwner."); + return false; + } + if (item.holdingOwner != null) + { + return item.holdingOwner.TryTransferToContainer(item, this, canMergeWithExistingStacks); + } + return TryAdd(item, canMergeWithExistingStacks); + } + + public void TryAddRangeOrTransfer(IEnumerable things, bool canMergeWithExistingStacks = true, bool destroyLeftover = false) + { + if (things == this) + { + return; + } + if (things is ThingOwner thingOwner) + { + thingOwner.TryTransferAllToContainer(this, canMergeWithExistingStacks); + if (destroyLeftover) + { + thingOwner.ClearAndDestroyContents(); + } + return; + } + if (things is IList list) + { + for (int i = 0; i < list.Count; i++) + { + if (!TryAddOrTransfer(list[i], canMergeWithExistingStacks) && destroyLeftover) + { + list[i].Destroy(); + } + } + return; + } + foreach (Thing thing in things) + { + if (!TryAddOrTransfer(thing, canMergeWithExistingStacks) && destroyLeftover) + { + thing.Destroy(); + } + } + } + + public int RemoveAll(Predicate predicate) + { + int num = 0; + for (int num2 = Count - 1; num2 >= 0; num2--) + { + if (predicate(GetAt(num2))) + { + Remove(GetAt(num2)); + num++; + } + } + return num; + } + + public bool TryTransferToContainer(Thing item, ThingOwner otherContainer, bool canMergeWithExistingStacks = true) + { + return TryTransferToContainer(item, otherContainer, item.stackCount, canMergeWithExistingStacks) == item.stackCount; + } + + public int TryTransferToContainer(Thing item, ThingOwner otherContainer, int count, bool canMergeWithExistingStacks = true) + { + Thing resultingTransferredItem; + return TryTransferToContainer(item, otherContainer, count, out resultingTransferredItem, canMergeWithExistingStacks); + } + + public int TryTransferToContainer(Thing item, ThingOwner otherContainer, int count, out Thing resultingTransferredItem, bool canMergeWithExistingStacks = true) + { + if (!Contains(item)) + { + Log.Error("Can't transfer item " + item?.ToString() + " because it's not here. owner=" + owner.ToStringSafe()); + resultingTransferredItem = null; + return 0; + } + if (otherContainer == this && count > 0) + { + resultingTransferredItem = item; + return item.stackCount; + } + if (!otherContainer.CanAcceptAnyOf(item, canMergeWithExistingStacks)) + { + resultingTransferredItem = null; + return 0; + } + if (count <= 0) + { + resultingTransferredItem = null; + return 0; + } + if (owner is Map || otherContainer.owner is Map) + { + Log.Warning("Can't transfer items to or from Maps directly. They must be spawned or despawned manually. Use TryAdd(item.SplitOff(count))"); + resultingTransferredItem = null; + return 0; + } + int num = Mathf.Min(item.stackCount, count); + Thing thing = item.SplitOff(num); + if (Contains(thing)) + { + Remove(thing); + } + if (otherContainer.TryAdd(thing, canMergeWithExistingStacks)) + { + resultingTransferredItem = thing; + item.MapHeld?.resourceCounter?.CheckUpdateResource(thing); + return thing.stackCount; + } + resultingTransferredItem = null; + if (!otherContainer.Contains(thing) && thing.stackCount > 0 && !thing.Destroyed) + { + int result = num - thing.stackCount; + if (item != thing) + { + item.TryAbsorbStack(thing, respectStackLimit: false); + } + else + { + TryAdd(thing, canMergeWithExistingStacks: false); + } + Map mapHeld = item.MapHeld; + if (mapHeld != null) + { + ResourceCounter resourceCounter = mapHeld.resourceCounter; + if (resourceCounter != null) + { + resourceCounter.CheckUpdateResource(thing); + return result; + } + return result; + } + return result; + } + return thing.stackCount; + } + + public void TryTransferAllToContainer(ThingOwner other, bool canMergeWithExistingStacks = true) + { + for (int num = Count - 1; num >= 0; num--) + { + TryTransferToContainer(GetAt(num), other, canMergeWithExistingStacks); + } + } + + public Thing Take(Thing thing, int count) + { + if (!Contains(thing)) + { + Log.Error("Tried to take " + thing.ToStringSafe() + " but it's not here."); + return null; + } + if (count > thing.stackCount) + { + Log.Error("Tried to get " + count + " of " + thing.ToStringSafe() + " while only having " + thing.stackCount); + count = thing.stackCount; + } + if (count == thing.stackCount) + { + Remove(thing); + return thing; + } + Thing thing2 = thing.SplitOff(count); + thing2.holdingOwner = null; + return thing2; + } + + public Thing Take(Thing thing) + { + return Take(thing, thing.stackCount); + } + + public bool TryDrop(Thing thing, ThingPlaceMode mode, int count, out Thing lastResultingThing, Action placedAction = null, Predicate nearPlaceValidator = null) + { + Map rootMap = ThingOwnerUtility.GetRootMap(owner); + IntVec3 rootPosition = ThingOwnerUtility.GetRootPosition(owner); + if (rootMap == null || !rootPosition.IsValid) + { + Log.Error("Cannot drop " + thing?.ToString() + " without a dropLoc and with an owner whose map is null."); + lastResultingThing = null; + return false; + } + return TryDrop(thing, rootPosition, rootMap, mode, count, out lastResultingThing, placedAction, nearPlaceValidator); + } + + public bool TryDrop(Thing thing, IntVec3 dropLoc, Map map, ThingPlaceMode mode, int count, out Thing resultingThing, Action placedAction = null, Predicate nearPlaceValidator = null) + { + if (!Contains(thing)) + { + Log.Error("Tried to drop " + thing.ToStringSafe() + " but it's not here."); + resultingThing = null; + return false; + } + if (thing.stackCount < count) + { + Log.Error("Tried to drop " + count + " of " + thing?.ToString() + " while only having " + thing.stackCount); + count = thing.stackCount; + } + if (count == thing.stackCount) + { + if (GenDrop.TryDropSpawn(thing, dropLoc, map, mode, out resultingThing, placedAction, nearPlaceValidator)) + { + Remove(thing); + return true; + } + return false; + } + Thing thing2 = thing.SplitOff(count); + if (GenDrop.TryDropSpawn(thing2, dropLoc, map, mode, out resultingThing, placedAction, nearPlaceValidator)) + { + return true; + } + thing.TryAbsorbStack(thing2, respectStackLimit: false); + return false; + } + + public bool TryDrop(Thing thing, ThingPlaceMode mode, out Thing lastResultingThing, Action placedAction = null, Predicate nearPlaceValidator = null) + { + Map rootMap = ThingOwnerUtility.GetRootMap(owner); + IntVec3 rootPosition = ThingOwnerUtility.GetRootPosition(owner); + if (rootMap == null || !rootPosition.IsValid) + { + Log.Error("Cannot drop " + thing?.ToString() + " without a dropLoc and with an owner whose map is null."); + lastResultingThing = null; + return false; + } + return TryDrop(thing, rootPosition, rootMap, mode, out lastResultingThing, placedAction, nearPlaceValidator); + } + + public bool TryDrop(Thing thing, IntVec3 dropLoc, Map map, ThingPlaceMode mode, out Thing lastResultingThing, Action placedAction = null, Predicate nearPlaceValidator = null, bool playDropSound = true) + { + if (!Contains(thing)) + { + Log.Error(owner.ToStringSafe() + " container tried to drop " + thing.ToStringSafe() + " which it didn't contain."); + lastResultingThing = null; + return false; + } + if (GenDrop.TryDropSpawn(thing, dropLoc, map, mode, out lastResultingThing, placedAction, nearPlaceValidator, playDropSound)) + { + Remove(thing); + return true; + } + return false; + } + + public bool TryDropAll(IntVec3 dropLoc, Map map, ThingPlaceMode mode, Action placeAction = null, Predicate nearPlaceValidator = null, bool playDropSound = true) + { + bool result = true; + for (int num = Count - 1; num >= 0; num--) + { + if (!TryDrop(GetAt(num), dropLoc, map, mode, out var _, placeAction, nearPlaceValidator, playDropSound)) + { + result = false; + } + } + return result; + } + + public bool Contains(ThingDef def) + { + return Contains(def, 1); + } + + public bool Contains(ThingDef def, int minCount) + { + if (minCount <= 0) + { + return true; + } + int num = 0; + int count = Count; + for (int i = 0; i < count; i++) + { + if (GetAt(i).def == def) + { + num += GetAt(i).stackCount; + } + if (num >= minCount) + { + return true; + } + } + return false; + } + + public int TotalStackCountOfDef(ThingDef def) + { + int num = 0; + int count = Count; + for (int i = 0; i < count; i++) + { + if (GetAt(i).def == def) + { + num += GetAt(i).stackCount; + } + } + return num; + } + + public void Notify_ContainedItemDestroyed(Thing t) + { + if (ThingOwnerUtility.ShouldAutoRemoveDestroyedThings(owner)) + { + Remove(t); + } + } + + protected virtual void NotifyAdded(Thing item) + { + if (ThingOwnerUtility.ShouldAutoExtinguishInnerThings(owner) && item.HasAttachment(ThingDefOf.Fire)) + { + item.GetAttachment(ThingDefOf.Fire).Destroy(); + } + if (ThingOwnerUtility.ShouldRemoveDesignationsOnAddedThings(owner)) + { + List maps = Find.Maps; + for (int i = 0; i < maps.Count; i++) + { + maps[i].designationManager.RemoveAllDesignationsOn(item); + } + } + if ((owner is Thing thing && thing.Faction.IsPlayerSafe()) || (owner is WorldObject worldObject && worldObject.Faction.IsPlayerSafe()) || (owner is Pawn_InventoryTracker pawn_InventoryTracker && pawn_InventoryTracker.pawn.Faction.IsPlayerSafe())) + { + item.EverSeenByPlayer = true; + } + if (owner is CompTransporter compTransporter) + { + compTransporter.Notify_ThingAdded(item); + } + if (owner is Caravan caravan) + { + caravan.Notify_PawnAdded((Pawn)item); + } + if (owner is Pawn_ApparelTracker pawn_ApparelTracker) + { + pawn_ApparelTracker.Notify_ApparelAdded((Apparel)item); + if (pawn_ApparelTracker.pawn.Faction.IsPlayerSafe()) + { + item.EverSeenByPlayer = true; + } + } + if (owner is Pawn_EquipmentTracker pawn_EquipmentTracker) + { + pawn_EquipmentTracker.Notify_EquipmentAdded((ThingWithComps)item); + if (pawn_EquipmentTracker.pawn.Faction.IsPlayerSafe()) + { + item.EverSeenByPlayer = true; + } + } + NotifyColonistBarIfColonistCorpse(item); + this.OnContentsChanged?.Invoke(); + } + + protected void NotifyAddedAndMergedWith(Thing item, int mergedCount) + { + if (owner is CompTransporter compTransporter) + { + compTransporter.Notify_ThingAddedAndMergedWith(item, mergedCount); + } + } + + protected virtual void NotifyRemoved(Thing item) + { + if (owner is Pawn_InventoryTracker pawn_InventoryTracker) + { + pawn_InventoryTracker.Notify_ItemRemoved(item); + } + if (owner is Pawn_ApparelTracker pawn_ApparelTracker) + { + pawn_ApparelTracker.Notify_ApparelRemoved((Apparel)item); + } + if (owner is Pawn_EquipmentTracker pawn_EquipmentTracker) + { + pawn_EquipmentTracker.Notify_EquipmentRemoved((ThingWithComps)item); + } + if (owner is Caravan caravan) + { + caravan.Notify_PawnRemoved((Pawn)item); + } + NotifyColonistBarIfColonistCorpse(item); + this.OnContentsChanged?.Invoke(); + } + + private void NotifyColonistBarIfColonistCorpse(Thing thing) + { + if (thing is Corpse { Bugged: false } corpse && corpse.InnerPawn.Faction != null && corpse.InnerPawn.Faction.IsPlayer && Current.ProgramState == ProgramState.Playing) + { + Find.ColonistBar.MarkColonistsDirty(); + } + } + + void IList.Insert(int index, Thing item) + { + throw new InvalidOperationException("ThingOwner doesn't allow inserting individual elements at any position."); + } + + void ICollection.Add(Thing item) + { + TryAdd(item); + } + + void ICollection.CopyTo(Thing[] array, int arrayIndex) + { + for (int i = 0; i < Count; i++) + { + array[i + arrayIndex] = GetAt(i); + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + for (int i = 0; i < Count; i++) + { + yield return GetAt(i); + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + for (int i = 0; i < Count; i++) + { + yield return GetAt(i); + } + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse.AI\Toils_Haul.txt` +**相似度:** 0.6124 + +```csharp +public class Toils_Haul +{ + public static bool ErrorCheckForCarry(Pawn pawn, Thing haulThing, bool canTakeFromInventory = false) + { + if (!haulThing.SpawnedOrAnyParentSpawned || (!canTakeFromInventory && !haulThing.Spawned)) + { + Log.Message(pawn?.ToString() + " tried to start carry " + haulThing?.ToString() + " which isn't spawned."); + pawn.jobs.EndCurrentJob(JobCondition.Incompletable); + return true; + } + if (haulThing.stackCount == 0) + { + Log.Message(pawn?.ToString() + " tried to start carry " + haulThing?.ToString() + " which had stackcount 0."); + pawn.jobs.EndCurrentJob(JobCondition.Incompletable); + return true; + } + if (pawn.jobs.curJob.count <= 0) + { + Log.Error("Invalid count: " + pawn.jobs.curJob.count + ", setting to 1. Job was " + pawn.jobs.curJob); + pawn.jobs.curJob.count = 1; + } + return false; + } + + public static Toil StartCarryThing(TargetIndex haulableInd, bool putRemainderInQueue = false, bool subtractNumTakenFromJobCount = false, bool failIfStackCountLessThanJobCount = false, bool reserve = true, bool canTakeFromInventory = false) + { + Toil toil = ToilMaker.MakeToil("StartCarryThing"); + toil.initAction = delegate + { + Pawn actor = toil.actor; + Job curJob = actor.jobs.curJob; + Thing thing = curJob.GetTarget(haulableInd).Thing; + if (!ErrorCheckForCarry(actor, thing, canTakeFromInventory)) + { + if (curJob.count == 0) + { + throw new Exception($"StartCarryThing job had count = {curJob.count}. Job: {curJob}"); + } + int num = actor.carryTracker.AvailableStackSpace(thing.def); + if (num <= 0) + { + int num2 = actor.carryTracker.MaxStackSpaceEver(thing.def); + int num3 = 0; + if (actor.carryTracker.CarriedThing != null) + { + num3 = actor.carryTracker.CarriedThing.stackCount; + } + throw new Exception($"StartCarryThing got availableStackSpace {num} (haulTarg {thing}, Job: {curJob}, maximum: {num2}, carrying: {num3})"); + } + if (failIfStackCountLessThanJobCount && thing.stackCount < curJob.count) + { + actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable); + } + else + { + int num4 = Mathf.Min(curJob.count, num, thing.stackCount); + if (num4 <= 0) + { + int num5 = actor.carryTracker.MaxStackSpaceEver(thing.def); + int num6 = 0; + if (actor.carryTracker.CarriedThing != null) + { + num6 = actor.carryTracker.CarriedThing.stackCount; + } + throw new Exception($"StartCarryThing zero or negative desiredNumToTake ({num4}), curJob.count: {curJob.count}, availableStackSpace: {num} (maximum: {num5}, carrying: {num6}), haulTarg.stackCount: {thing.stackCount}"); + } + int stackCount = thing.stackCount; + int num7 = actor.carryTracker.TryStartCarry(thing, num4, reserve); + if (num7 == 0) + { + actor.jobs.EndCurrentJob(JobCondition.Incompletable); + } + if (num7 < stackCount) + { + int num8 = curJob.count - num7; + if (putRemainderInQueue && num8 > 0) + { + curJob.GetTargetQueue(haulableInd).Insert(0, thing); + Job job = curJob; + if (job.countQueue == null) + { + job.countQueue = new List(); + } + curJob.countQueue.Insert(0, num8); + } + else if (actor.Map.reservationManager.ReservedBy(thing, actor, curJob)) + { + actor.Map.reservationManager.Release(thing, actor, curJob); + } + } + if (subtractNumTakenFromJobCount) + { + curJob.count -= num7; + } + curJob.SetTarget(haulableInd, actor.carryTracker.CarriedThing); + actor.records.Increment(RecordDefOf.ThingsHauled); + } + } + }; + return toil; + } + + public static Toil StoreThingJob(TargetIndex thingIndex) + { + Toil toil = ToilMaker.MakeToil("StoreThingJob"); + toil.initAction = delegate + { + Pawn actor = toil.actor; + Job curJob = actor.CurJob; + Thing thing = curJob.GetTarget(thingIndex).Thing; + Job job = HaulAIUtility.HaulToStorageJob(actor, thing, curJob.playerForced); + if (job != null) + { + actor.jobs.TryTakeOrderedJob(job, JobTag.Misc); + } + }; + return toil; + } + + public static Toil DropCarriedThing() + { + Toil toil = ToilMaker.MakeToil("DropCarriedThing"); + toil.initAction = delegate + { + Pawn actor = toil.actor; + Thing resultingThing; + if (actor.carryTracker.CarriedThing == null) + { + Log.Error(actor?.ToString() + " tried to drop carried thing but is not carrying anything."); + } + else if (!actor.carryTracker.TryDropCarriedThing(actor.Position, ThingPlaceMode.Direct, out resultingThing)) + { + actor.jobs.EndCurrentJob(JobCondition.Incompletable); + } + }; + return toil; + } + + public static Toil JumpIfAlsoCollectingNextTargetInQueue(Toil gotoGetTargetToil, TargetIndex ind) + { + Toil toil = ToilMaker.MakeToil("JumpIfAlsoCollectingNextTargetInQueue"); + toil.initAction = delegate + { + Pawn actor = toil.actor; + Job curJob = actor.jobs.curJob; + List targetQueue = curJob.GetTargetQueue(ind); + if (!targetQueue.NullOrEmpty() && curJob.count > 0) + { + if (actor.carryTracker.CarriedThing == null) + { + Log.Error("JumpToAlsoCollectTargetInQueue run on " + actor?.ToString() + " who is not carrying something."); + } + else if (actor.carryTracker.AvailableStackSpace(actor.carryTracker.CarriedThing.def) > 0) + { + for (int i = 0; i < targetQueue.Count; i++) + { + if (!GenAI.CanUseItemForWork(actor, targetQueue[i].Thing)) + { + actor.jobs.EndCurrentJob(JobCondition.Incompletable); + break; + } + if (targetQueue[i].Thing.def == actor.carryTracker.CarriedThing.def) + { + curJob.SetTarget(ind, targetQueue[i].Thing); + targetQueue.RemoveAt(i); + actor.jobs.curDriver.JumpToToil(gotoGetTargetToil); + break; + } + } + } + } + }; + return toil; + } + + public static Toil CheckForGetOpportunityDuplicate(Toil getHaulTargetToil, TargetIndex haulableInd, TargetIndex storeCellInd, bool takeFromValidStorage = false, Predicate extraValidator = null) + { + Toil toil = ToilMaker.MakeToil("CheckForGetOpportunityDuplicate"); + toil.initAction = delegate + { + Pawn actor = toil.actor; + Job curJob = actor.jobs.curJob; + if (actor.carryTracker.CarriedThing.def.stackLimit != 1 && !actor.carryTracker.Full && curJob.count > 0) + { + Thing thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableAlways), PathEndMode.ClosestTouch, TraverseParms.For(actor), 8f, DupeValidator); + if (thing != null) + { + curJob.SetTarget(haulableInd, thing); + actor.jobs.curDriver.JumpToToil(getHaulTargetToil); + } + } + bool DupeValidator(Thing t) + { + if (!t.Spawned) + { + return false; + } + if (t.def != actor.carryTracker.CarriedThing.def) + { + return false; + } + if (!t.CanStackWith(actor.carryTracker.CarriedThing)) + { + return false; + } + if (t.IsForbidden(actor)) + { + return false; + } + if (!t.IsSociallyProper(actor, forPrisoner: false, animalsCare: true)) + { + return false; + } + if (takeFromValidStorage && storeCellInd != 0 && curJob.GetTarget(storeCellInd).Cell.TryGetSlotGroup(actor.Map, out var group) && t.TryGetValidStoragePriority(out var priority) && (int)priority >= (int)group.Settings.Priority) + { + return false; + } + if (storeCellInd != 0 && !curJob.GetTarget(storeCellInd).Cell.IsValidStorageFor(actor.Map, t)) + { + return false; + } + if (!actor.CanReserve(t)) + { + return false; + } + if (extraValidator != null && !extraValidator(t)) + { + return false; + } + return true; + } + }; + return toil; + } + + public static Toil CarryHauledThingToCell(TargetIndex squareIndex, PathEndMode pathEndMode = PathEndMode.ClosestTouch) + { + Toil toil = ToilMaker.MakeToil("CarryHauledThingToCell"); + toil.initAction = delegate + { + IntVec3 cell3 = toil.actor.jobs.curJob.GetTarget(squareIndex).Cell; + toil.actor.pather.StartPath(cell3, pathEndMode); + }; + toil.defaultCompleteMode = ToilCompleteMode.PatherArrival; + toil.AddEndCondition(delegate + { + Pawn actor2 = toil.actor; + IntVec3 cell2 = actor2.jobs.curJob.GetTarget(squareIndex).Cell; + CompPushable compPushable2 = actor2.carryTracker.CarriedThing.TryGetComp(); + if (compPushable2 != null) + { + Vector3 v = actor2.Position.ToVector3() + compPushable2.drawPos; + if (new IntVec3(v) == cell2) + { + return JobCondition.Succeeded; + } + } + return JobCondition.Ongoing; + }); + toil.AddFailCondition(delegate + { + Pawn actor = toil.actor; + IntVec3 cell = actor.jobs.curJob.GetTarget(squareIndex).Cell; + if (actor.carryTracker.CarriedThing == null) + { + return true; + } + if (actor.jobs.curJob.haulMode == HaulMode.ToCellStorage && !cell.IsValidStorageFor(actor.Map, actor.carryTracker.CarriedThing)) + { + return true; + } + CompPushable compPushable = actor.carryTracker.CarriedThing.TryGetComp(); + return (compPushable != null && !compPushable.canBePushed) ? true : false; + }); + return toil; + } + + public static Toil PlaceCarriedThingInCellFacing(TargetIndex facingTargetInd) + { + Toil toil = ToilMaker.MakeToil("PlaceCarriedThingInCellFacing"); + toil.initAction = delegate + { + Pawn actor = toil.actor; + if (actor.carryTracker.CarriedThing == null) + { + Log.Error(actor?.ToString() + " tried to place hauled thing in facing cell but is not hauling anything."); + } + else + { + LocalTargetInfo target = actor.CurJob.GetTarget(facingTargetInd); + IntVec3 intVec = ((!target.HasThing) ? target.Cell : target.Thing.OccupiedRect().ClosestCellTo(actor.Position)); + IntVec3 dropLoc = actor.Position + Pawn_RotationTracker.RotFromAngleBiased((actor.Position - intVec).AngleFlat).FacingCell; + if (!actor.carryTracker.TryDropCarriedThing(dropLoc, ThingPlaceMode.Direct, out var _)) + { + actor.jobs.EndCurrentJob(JobCondition.Incompletable); + } + } + }; + return toil; + } + + public static Toil PlaceHauledThingInCell(TargetIndex cellInd, Toil nextToilOnPlaceFailOrIncomplete, bool storageMode, bool tryStoreInSameStorageIfSpotCantHoldWholeStack = false) + { + Toil toil = ToilMaker.MakeToil("PlaceHauledThingInCell"); + toil.initAction = delegate + { + Pawn actor = toil.actor; + Job curJob = actor.jobs.curJob; + IntVec3 cell = curJob.GetTarget(cellInd).Cell; + if (actor.carryTracker.CarriedThing == null) + { + Log.Error(actor?.ToString() + " tried to place hauled thing in cell but is not hauling anything."); + } + else + { + SlotGroup slotGroup = actor.Map.haulDestinationManager.SlotGroupAt(cell); + if (slotGroup != null && slotGroup.Settings.AllowedToAccept(actor.carryTracker.CarriedThing)) + { + actor.Map.designationManager.TryRemoveDesignationOn(actor.carryTracker.CarriedThing, DesignationDefOf.Haul); + } + Action placedAction = null; + if (curJob.def == JobDefOf.DoBill || curJob.def == JobDefOf.RecolorApparel || curJob.def == JobDefOf.RefuelAtomic || curJob.def == JobDefOf.RearmTurretAtomic) + { + placedAction = delegate(Thing th, int added) + { + HaulAIUtility.UpdateJobWithPlacedThings(curJob, th, added); + }; + } + if (!actor.carryTracker.TryDropCarriedThing(cell, ThingPlaceMode.Direct, out var _, placedAction)) + { + if (storageMode) + { + IntVec3 storeCell; + if (nextToilOnPlaceFailOrIncomplete != null && ((tryStoreInSameStorageIfSpotCantHoldWholeStack && StoreUtility.TryFindBestBetterStoreCellForIn(actor.carryTracker.CarriedThing, actor, actor.Map, StoragePriority.Unstored, actor.Faction, curJob.bill.GetSlotGroup(), out var foundCell)) || StoreUtility.TryFindBestBetterStoreCellFor(actor.carryTracker.CarriedThing, actor, actor.Map, StoragePriority.Unstored, actor.Faction, out foundCell))) + { + if (actor.CanReserve(foundCell)) + { + actor.Reserve(foundCell, actor.CurJob); + } + actor.CurJob.SetTarget(cellInd, foundCell); + actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete); + } + else if (HaulAIUtility.CanHaulAside(actor, actor.carryTracker.CarriedThing, out storeCell)) + { + curJob.SetTarget(cellInd, storeCell); + curJob.count = int.MaxValue; + curJob.haulOpportunisticDuplicates = false; + curJob.haulMode = HaulMode.ToCellNonStorage; + if (nextToilOnPlaceFailOrIncomplete != null) + { + actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete); + } + } + else + { + Log.Warning($"Incomplete haul for {actor}: Could not find anywhere to put {actor.carryTracker.CarriedThing} near {actor.Position}. Destroying. This should be very uncommon!"); + actor.carryTracker.CarriedThing.Destroy(); + } + } + else if (nextToilOnPlaceFailOrIncomplete != null) + { + actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete); + } + } + } + }; + return toil; + } + + public static Toil CarryHauledThingToContainer() + { + Toil gotoDest = ToilMaker.MakeToil("CarryHauledThingToContainer"); + gotoDest.initAction = delegate + { + gotoDest.actor.pather.StartPath(gotoDest.actor.jobs.curJob.targetB.Thing, PathEndMode.Touch); + }; + gotoDest.AddFailCondition(delegate + { + Thing thing = gotoDest.actor.jobs.curJob.targetB.Thing; + if (thing.Destroyed || (!gotoDest.actor.jobs.curJob.ignoreForbidden && thing.IsForbidden(gotoDest.actor))) + { + return true; + } + ThingOwner thingOwner = thing.TryGetInnerInteractableThingOwner(); + return (thingOwner != null && !thingOwner.CanAcceptAnyOf(gotoDest.actor.carryTracker.CarriedThing)) ? true : false; + }); + gotoDest.defaultCompleteMode = ToilCompleteMode.PatherArrival; + return gotoDest; + } + + public static Toil DepositHauledThingInContainer(TargetIndex containerInd, TargetIndex reserveForContainerInd, Action onDeposited = null) + { + Toil toil = ToilMaker.MakeToil("DepositHauledThingInContainer"); + toil.initAction = delegate + { + Pawn actor = toil.actor; + Job curJob = actor.jobs.curJob; + if (actor.carryTracker.CarriedThing == null) + { + Log.Error(actor?.ToString() + " tried to place hauled thing in container but is not hauling anything."); + } + else + { + Thing thing = curJob.GetTarget(containerInd).Thing; + ThingOwner thingOwner = thing.TryGetInnerInteractableThingOwner(); + if (thingOwner != null) + { + int num = actor.carryTracker.CarriedThing.stackCount; + if (thing is IHaulEnroute haulEnroute) + { + ThingDef def = actor.carryTracker.CarriedThing.def; + num = Mathf.Min(haulEnroute.GetSpaceRemainingWithEnroute(def, actor), num); + if (reserveForContainerInd != 0) + { + Thing thing2 = curJob.GetTarget(reserveForContainerInd).Thing; + if (!thing2.DestroyedOrNull() && thing2 != haulEnroute && thing2 is IHaulEnroute enroute) + { + int spaceRemainingWithEnroute = enroute.GetSpaceRemainingWithEnroute(def, actor); + num = Mathf.Min(num, actor.carryTracker.CarriedThing.stackCount - spaceRemainingWithEnroute); + } + } + } + Thing carriedThing = actor.carryTracker.CarriedThing; + int num2 = actor.carryTracker.innerContainer.TryTransferToContainer(carriedThing, thingOwner, num); + if (num2 != 0) + { + if (thing is IHaulEnroute container) + { + thing.Map.enrouteManager.ReleaseFor(container, actor); + } + if (thing is INotifyHauledTo notifyHauledTo) + { + notifyHauledTo.Notify_HauledTo(actor, carriedThing, num2); + } + if (thing is ThingWithComps thingWithComps) + { + foreach (ThingComp allComp in thingWithComps.AllComps) + { + if (allComp is INotifyHauledTo notifyHauledTo2) + { + notifyHauledTo2.Notify_HauledTo(actor, carriedThing, num2); + } + } + } + if (curJob.def == JobDefOf.DoBill) + { + HaulAIUtility.UpdateJobWithPlacedThings(curJob, carriedThing, num2); + } + onDeposited?.Invoke(); + } + } + else if (curJob.GetTarget(containerInd).Thing.def.Minifiable) + { + actor.carryTracker.innerContainer.ClearAndDestroyContents(); + } + else + { + Log.Error("Could not deposit hauled thing in container: " + curJob.GetTarget(containerInd).Thing); + } + } + }; + return toil; + } + + public static Toil JumpToCarryToNextContainerIfPossible(Toil carryToContainerToil, TargetIndex primaryTargetInd) + { + Toil toil = ToilMaker.MakeToil("JumpToCarryToNextContainerIfPossible"); + toil.debugName = "Jump carry if possible"; + toil.initAction = delegate + { + Pawn actor = toil.actor; + Job curJob = actor.jobs.curJob; + if (actor.carryTracker.CarriedThing != null && curJob.targetQueueB != null && curJob.targetQueueB.Count > 0) + { + if (TryGetNextDestinationFromQueue(primaryTargetInd, TargetIndex.B, actor.carryTracker.CarriedThing.def, curJob, actor, out var nextTarget)) + { + curJob.targetQueueB.RemoveAll((LocalTargetInfo target) => target.Thing == nextTarget); + curJob.targetB = nextTarget; + curJob.targetC = nextTarget; + actor.jobs.curDriver.JumpToToil(carryToContainerToil); + } + } + }; + return toil; + } + + public static bool TryGetNextDestinationFromQueue(TargetIndex primaryIndex, TargetIndex destIndex, ThingDef stuff, Job job, Pawn actor, out Thing target) + { + Thing primaryTarget = job.GetTarget(primaryIndex).Thing; + target = null; + if (actor.carryTracker?.CarriedThing == null) + { + return false; + } + bool hasSpareItems = actor.carryTracker.CarriedThing.stackCount > 0; + if (primaryTarget != null && primaryTarget.Spawned && primaryTarget is IHaulEnroute enroute) + { + int spaceRemainingWithEnroute = enroute.GetSpaceRemainingWithEnroute(stuff, actor); + hasSpareItems = actor.carryTracker.CarriedThing.stackCount > spaceRemainingWithEnroute; + } + target = GenClosest.ClosestThing_Global_Reachable(actor.Position, actor.Map, from x in job.GetTargetQueue(destIndex) + select x.Thing, PathEndMode.Touch, TraverseParms.For(actor), 99999f, Validator); + return target != null; + bool Validator(Thing th) + { + if (!(th is IHaulEnroute enroute2)) + { + return false; + } + if (enroute2.GetSpaceRemainingWithEnroute(stuff, actor) <= 0) + { + return false; + } + if (th != primaryTarget && !hasSpareItems) + { + return false; + } + return true; + } + } + + public static Toil TakeToInventory(TargetIndex ind, int count) + { + return TakeToInventory(ind, count, null, null); + } + + private static Toil TakeToInventory(TargetIndex ind, int? count, Func countGetter, Func countGetterPassingThing) + { + Toil takeThing = ToilMaker.MakeToil("TakeToInventory"); + takeThing.initAction = delegate + { + Pawn actor = takeThing.actor; + Thing thing = actor.CurJob.GetTarget(ind).Thing; + if (!ErrorCheckForCarry(actor, thing)) + { + int num = Mathf.Min(count ?? countGetterPassingThing?.Invoke(thing) ?? countGetter(), thing.stackCount); + if (actor.CurJob.checkEncumbrance) + { + num = Math.Min(num, MassUtility.CountToPickUpUntilOverEncumbered(actor, thing)); + } + if (num <= 0) + { + actor.jobs.curDriver.ReadyForNextToil(); + } + else + { + actor.inventory.GetDirectlyHeldThings().TryAdd(thing.SplitOff(num)); + if (thing.def.ingestible != null && (int)thing.def.ingestible.preferability <= 5) + { + actor.mindState.lastInventoryRawFoodUseTick = Find.TickManager.TicksGame; + } + thing.def.soundPickup.PlayOneShot(new TargetInfo(actor.Position, actor.Map)); + } + } + }; + return takeThing; + } + + public static Toil TakeToInventory(TargetIndex ind, Func countGetter) + { + return TakeToInventory(ind, null, countGetter, null); + } + + public static Toil TakeToInventory(TargetIndex ind, Func countGetter) + { + return TakeToInventory(ind, null, null, countGetter); + } + + public static Toil TakeFromOtherInventory(Thing item, ThingOwner taker, ThingOwner holder, int count = -1, TargetIndex indexToSet = TargetIndex.None) + { + Toil toil = ToilMaker.MakeToil("TakeFromOtherInventory"); + toil.initAction = delegate + { + if (!holder.Contains(item)) + { + toil.actor.jobs.EndCurrentJob(JobCondition.Incompletable); + } + else + { + count = ((count < 0) ? toil.actor.jobs.curJob.count : count); + holder.TryTransferToContainer(item, taker, Mathf.Min(item.stackCount, count), out var resultingTransferredItem); + if (resultingTransferredItem == null) + { + Log.Warning($"Taker {toil.actor.Label} unable to take count {count} of thing {item.Label} from holder's inventory"); + toil.actor.jobs.EndCurrentJob(JobCondition.Incompletable); + } + else if (indexToSet != 0) + { + toil.actor.jobs.curJob.SetTarget(indexToSet, resultingTransferredItem); + } + } + }; + return toil; + } + + public static Toil CheckItemCarriedByOtherPawn(Thing item, TargetIndex targetPawnIfCarried = TargetIndex.None, Toil jumpIfCarriedByOther = null) + { + Toil toil = ToilMaker.MakeToil("CheckItemCarriedByOtherPawn"); + toil.initAction = delegate + { + Pawn pawn = (item?.ParentHolder as Pawn_InventoryTracker)?.pawn; + if (pawn != null && pawn != toil.actor) + { + if (targetPawnIfCarried != 0) + { + toil.actor.jobs.curJob.SetTarget(targetPawnIfCarried, pawn); + } + if (jumpIfCarriedByOther != null) + { + toil.actor.jobs.curDriver.JumpToToil(jumpIfCarriedByOther); + } + } + }; + toil.defaultCompleteMode = ToilCompleteMode.Instant; + toil.atomicWithPrevious = true; + return toil; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\PawnUtility.txt` +**相似度:** 0.5783 + +```csharp +public static class PawnUtility +{ + private static List tmpPawns = new List(); + + private static List tmpPawnKindsStr = new List(); + + private static HashSet tmpAddedPawnKinds = new HashSet(); + + private static List tmpPawnKinds = new List(); + + private static List tmpThings = new List(); + + public static Faction GetFactionLeaderFaction(Pawn pawn) + { + List allFactionsListForReading = Find.FactionManager.AllFactionsListForReading; + for (int i = 0; i < allFactionsListForReading.Count; i++) + { + if (allFactionsListForReading[i].leader == pawn) + { + return allFactionsListForReading[i]; + } + } + return null; + } + + public static bool IsFactionLeader(Pawn pawn) + { + return GetFactionLeaderFaction(pawn) != null; + } + + public static bool IsInteractionBlocked(this Pawn pawn, InteractionDef interaction, bool isInitiator, bool isRandom) + { + MentalStateDef mentalStateDef = pawn.MentalStateDef; + if (mentalStateDef != null) + { + if (isRandom) + { + return mentalStateDef.blockRandomInteraction; + } + if (interaction == null) + { + return false; + } + List list = (isInitiator ? mentalStateDef.blockInteractionInitiationExcept : mentalStateDef.blockInteractionRecipientExcept); + if (list != null) + { + return !list.Contains(interaction); + } + return false; + } + List hediffs = pawn.health.hediffSet.hediffs; + for (int i = 0; i < hediffs.Count; i++) + { + if (hediffs[i].def.blocksSocialInteraction) + { + return true; + } + } + Lord lord = pawn.GetLord(); + if (lord != null && lord.BlocksSocialInteraction(pawn)) + { + return true; + } + return false; + } + + public static bool IsKidnappedPawn(Pawn pawn) + { + List allFactionsListForReading = Find.FactionManager.AllFactionsListForReading; + for (int i = 0; i < allFactionsListForReading.Count; i++) + { + if (allFactionsListForReading[i].kidnapped.KidnappedPawnsListForReading.Contains(pawn)) + { + return true; + } + } + return false; + } + + public static bool IsTravelingInTransportPodWorldObject(Pawn pawn) + { + if (!pawn.IsWorldPawn() || !ThingOwnerUtility.AnyParentIs(pawn)) + { + return ThingOwnerUtility.AnyParentIs(pawn); + } + return true; + } + + public static bool ForSaleBySettlement(Pawn pawn) + { + return pawn.ParentHolder is Settlement_TraderTracker; + } + + public static bool IsCarrying(this Pawn pawn) + { + if (!pawn.Destroyed && pawn.carryTracker != null) + { + return pawn.carryTracker.CarriedThing != null; + } + return false; + } + + public static bool IsCarryingPawn(this Pawn pawn, Pawn carryPawn = null) + { + if (pawn.carryTracker != null && pawn.carryTracker.CarriedThing is Pawn) + { + if (carryPawn != null) + { + return pawn.carryTracker.CarriedThing == carryPawn; + } + return true; + } + return false; + } + + public static bool IsCarryingThing(this Pawn pawn, Thing carriedThing) + { + if (pawn.carryTracker != null && pawn.carryTracker.CarriedThing != null) + { + return pawn.carryTracker.CarriedThing == carriedThing; + } + return false; + } + + public static void TryDestroyStartingColonistFamily(Pawn pawn) + { + if (!pawn.relations.RelatedPawns.Any((Pawn x) => Find.GameInitData.startingAndOptionalPawns.Contains(x))) + { + DestroyStartingColonistFamily(pawn); + } + } + + public static void DestroyStartingColonistFamily(Pawn pawn) + { + foreach (Pawn item in pawn.relations.RelatedPawns.ToList()) + { + if (!Find.GameInitData.startingAndOptionalPawns.Contains(item)) + { + WorldPawnSituation situation = Find.WorldPawns.GetSituation(item); + if (situation == WorldPawnSituation.Free || situation == WorldPawnSituation.Dead) + { + Find.WorldPawns.RemovePawn(item); + Find.WorldPawns.PassToWorld(item, PawnDiscardDecideMode.Discard); + } + } + } + } + + public static bool EnemiesAreNearby(Pawn pawn, int regionsToScan = 9, bool passDoors = false, float maxDistance = -1f, int maxCount = 1, bool invisible = false) + { + TraverseParms tp = (passDoors ? TraverseParms.For(TraverseMode.PassDoors) : TraverseParms.For(pawn)); + int count = 0; + RegionTraverser.BreadthFirstTraverse(pawn.Position, pawn.Map, (Region from, Region to) => to.Allows(tp, isDestination: false), delegate(Region r) + { + List list = r.ListerThings.ThingsInGroup(ThingRequestGroup.AttackTarget); + for (int i = 0; i < list.Count; i++) + { + Thing thing = list[i]; + if ((maxDistance <= 0f || thing.Position.InHorDistOf(pawn.Position, maxDistance)) && thing.HostileTo(pawn) && (invisible || !(thing is Pawn pawn2) || !pawn2.IsPsychologicallyInvisible())) + { + count++; + } + } + return count >= maxCount; + }, regionsToScan); + return count >= maxCount; + } + + public static bool WillSoonHaveBasicNeed(Pawn p, float thresholdOffset = 0.05f) + { + if (p.needs == null) + { + return false; + } + if (p.needs.rest != null && p.needs.rest.CurLevel < 0.28f + thresholdOffset) + { + return true; + } + if (p.needs.food != null && p.needs.food.CurLevelPercentage < p.needs.food.PercentageThreshHungry + thresholdOffset) + { + return true; + } + return false; + } + + public static bool CanCasuallyInteractNow(this Pawn p, bool twoWayInteraction = false, bool canInteractWhileSleeping = false, bool canInteractWhileRoaming = false, bool canInteractWhileDrafted = false) + { + if (p.Drafted && !canInteractWhileDrafted) + { + return false; + } + if (p.IsPsychologicallyInvisible()) + { + return false; + } + if (ThinkNode_ConditionalShouldFollowMaster.ShouldFollowMaster(p)) + { + return false; + } + if (p.InAggroMentalState) + { + return false; + } + if (p.InMentalState && p.MentalStateDef == MentalStateDefOf.Roaming && !canInteractWhileRoaming) + { + return false; + } + if (!p.Awake() && !canInteractWhileSleeping) + { + return false; + } + if (p.IsFormingCaravan()) + { + return false; + } + Job curJob = p.CurJob; + if (curJob != null && twoWayInteraction && (!curJob.def.casualInterruptible || !curJob.playerForced)) + { + return false; + } + return true; + } + + public static IEnumerable SpawnedMasteredPawns(Pawn master) + { + if (Current.ProgramState != ProgramState.Playing || master.Faction == null || !master.RaceProps.Humanlike || !master.Spawned) + { + yield break; + } + List pawns = master.Map.mapPawns.SpawnedPawnsInFaction(master.Faction); + for (int i = 0; i < pawns.Count; i++) + { + if (pawns[i].playerSettings != null && pawns[i].playerSettings.Master == master) + { + yield return pawns[i]; + } + } + } + + public static bool InValidState(Pawn p) + { + if (p.health == null) + { + return false; + } + if (!p.Dead && (p.stances == null || p.mindState == null || p.needs == null || p.ageTracker == null)) + { + return false; + } + return true; + } + + public static PawnPosture GetPosture(this Pawn p) + { + PawnPosture pawnPosture = (p.Dead ? PawnPosture.LayingOnGroundNormal : ((!ModsConfig.BiotechActive || !p.IsCharging()) ? ((!(p.ParentHolder is IThingHolderWithDrawnPawn thingHolderWithDrawnPawn)) ? (p.Downed ? ((p.jobs == null || !p.jobs.posture.Laying()) ? PawnPosture.LayingOnGroundNormal : p.jobs.posture) : ((p.jobs != null) ? p.jobs.posture : PawnPosture.Standing)) : thingHolderWithDrawnPawn.HeldPawnPosture) : PawnPosture.Standing)); + Pawn_MindState mindState = p.mindState; + if (mindState != null && mindState.duty?.def?.forceFaceUpPosture == true && pawnPosture != 0) + { + pawnPosture |= PawnPosture.FaceUpMask; + } + return pawnPosture; + } + + public static void ForceWait(Pawn pawn, int ticks, Thing faceTarget = null, bool maintainPosture = false, bool maintainSleep = false) + { + if (ticks <= 0) + { + Log.ErrorOnce("Forcing a wait for zero ticks", 47045639); + } + JobDef def = (maintainPosture ? JobDefOf.Wait_MaintainPosture : JobDefOf.Wait); + if (pawn.IsDeactivated()) + { + def = JobDefOf.Deactivated; + } + if (pawn.IsSelfShutdown()) + { + def = JobDefOf.SelfShutdown; + } + else if (pawn.InBed()) + { + def = (pawn.Awake() ? JobDefOf.LayDownAwake : JobDefOf.LayDown); + } + else if (!pawn.health.capacities.CanBeAwake) + { + def = JobDefOf.Wait_Downed; + } + else if (maintainSleep && !pawn.Awake()) + { + def = JobDefOf.Wait_Asleep; + } + Job job = JobMaker.MakeJob(def, faceTarget); + if (maintainSleep && !pawn.Awake()) + { + job.forceSleep = true; + job.targetA = pawn.Position; + } + if (pawn.InBed()) + { + job.targetA = pawn.CurrentBed(); + } + job.expiryInterval = ticks; + pawn.jobs.StartJob(job, JobCondition.InterruptForced, null, resumeCurJobAfterwards: true); + } + + public static void GainComfortFromCellIfPossible(this Pawn p, int delta, bool chairsOnly = false) + { + if (p.Spawned && p.IsHashIntervalTick(15, delta)) + { + Building edifice = p.Position.GetEdifice(p.Map); + if (edifice != null && (!chairsOnly || (edifice.def.category == ThingCategory.Building && edifice.def.building.isSittable))) + { + GainComfortFromThingIfPossible(p, edifice, delta); + } + } + } + + public static void GainComfortFromThingIfPossible(Pawn p, Thing from, int delta) + { + if (p.IsHashIntervalTick(15, delta)) + { + float statValue = from.GetStatValue(StatDefOf.Comfort, applyPostProcess: true, 100); + if (statValue >= 0f && p.needs != null && p.needs.comfort != null) + { + p.needs.comfort.ComfortUsed(statValue); + } + } + } + + public static float BodyResourceGrowthSpeed(Pawn pawn) + { + return pawn.needs?.food?.CurCategory.HungerMultiplier() ?? 1f; + } + + public static bool FertileMateTarget(Pawn male, Pawn female) + { + if (female.gender != Gender.Female || female.Sterile()) + { + return false; + } + CompEggLayer compEggLayer = female.TryGetComp(); + if (compEggLayer != null) + { + return !compEggLayer.FullyFertilized; + } + return true; + } + + public static void Mated(Pawn male, Pawn female) + { + if (!female.Sterile() && !male.Sterile()) + { + CompEggLayer compEggLayer = female.TryGetComp(); + if (compEggLayer != null) + { + compEggLayer.Fertilize(male); + } + else if (Rand.Value < 0.5f) + { + Hediff_Pregnant hediff_Pregnant = (Hediff_Pregnant)HediffMaker.MakeHediff(HediffDefOf.Pregnant, female); + hediff_Pregnant.SetParents(null, male, null); + female.health.AddHediff(hediff_Pregnant); + } + } + } + + public static bool PlayerForcedJobNowOrSoon(Pawn pawn) + { + if (pawn.jobs == null) + { + return false; + } + Job curJob = pawn.CurJob; + if (curJob != null) + { + return curJob.playerForced; + } + if (pawn.jobs.jobQueue.Count > 0) + { + return pawn.jobs.jobQueue.Peek().job.playerForced; + } + return false; + } + + public static bool TrySpawnHatchedOrBornPawn(Pawn pawn, Thing motherOrEgg, IntVec3? positionOverride = null) + { + if (motherOrEgg.SpawnedOrAnyParentSpawned) + { + return GenSpawn.Spawn(pawn, positionOverride ?? motherOrEgg.PositionHeld, motherOrEgg.MapHeld) != null; + } + if (motherOrEgg is Pawn pawn2) + { + if (pawn2.IsCaravanMember()) + { + pawn2.GetCaravan().AddPawn(pawn, addCarriedPawnToWorldPawnsIfAny: true); + Find.WorldPawns.PassToWorld(pawn); + return true; + } + if (pawn2.IsWorldPawn()) + { + Find.WorldPawns.PassToWorld(pawn); + return true; + } + } + else if (motherOrEgg.ParentHolder != null && motherOrEgg.ParentHolder is Pawn_InventoryTracker pawn_InventoryTracker) + { + if (pawn_InventoryTracker.pawn.IsCaravanMember()) + { + pawn_InventoryTracker.pawn.GetCaravan().AddPawn(pawn, addCarriedPawnToWorldPawnsIfAny: true); + Find.WorldPawns.PassToWorld(pawn); + return true; + } + if (pawn_InventoryTracker.pawn.IsWorldPawn()) + { + Find.WorldPawns.PassToWorld(pawn); + return true; + } + } + return false; + } + + public static bool TryGetAvoidGrid(this Pawn p, out AvoidGrid grid, bool onlyIfLordAllows = true) + { + grid = null; + if (!p.Spawned) + { + return false; + } + if (p.Faction == null) + { + return false; + } + if (!p.Faction.def.canUseAvoidGrid) + { + return false; + } + if (p.Faction == Faction.OfPlayer || !p.Faction.HostileTo(Faction.OfPlayer)) + { + return false; + } + if (p.kindDef.canUseAvoidGrid) + { + grid = p.Map.avoidGrid; + return true; + } + if (onlyIfLordAllows) + { + Lord lord = p.GetLord(); + LordToil lordToil = lord?.CurLordToil; + if (lordToil != null && lordToil.useAvoidGrid) + { + grid = lord.Map.avoidGrid; + return true; + } + return false; + } + grid = p.Map.avoidGrid; + return true; + } + + public static bool ShouldCollideWithPawns(Pawn p) + { + if (p == null || p.Downed || p.Dead) + { + return false; + } + if (p.IsShambler) + { + return true; + } + if (!p.mindState.anyCloseHostilesRecently) + { + return false; + } + if (p.IsPsychologicallyInvisible()) + { + return false; + } + if (!p.kindDef.collidesWithPawns) + { + return false; + } + return true; + } + + public static bool AnyPawnBlockingPathAt(IntVec3 c, Pawn forPawn, bool actAsIfHadCollideWithPawnsJob = false, bool collideOnlyWithStandingPawns = false, bool forPathFinder = false, bool useId = false) + { + return PawnBlockingPathAt(c, forPawn, actAsIfHadCollideWithPawnsJob, collideOnlyWithStandingPawns, forPathFinder, useId) != null; + } + + public static Pawn PawnBlockingPathAt(IntVec3 c, Pawn forPawn, bool actAsIfHadCollideWithPawnsJob = false, bool collideOnlyWithStandingPawns = false, bool forPathFinder = false, bool useId = false) + { + List thingList = c.GetThingList(forPawn.Map); + if (thingList.Count == 0) + { + return null; + } + bool collideWithNonHostile = false; + if (actAsIfHadCollideWithPawnsJob) + { + collideWithNonHostile = true; + } + else + { + Job curJob = forPawn.CurJob; + if (curJob != null && (curJob.collideWithPawns || curJob.def.collideWithPawns || forPawn.jobs.curDriver.collideWithPawns)) + { + collideWithNonHostile = true; + } + } + for (int i = 0; i < thingList.Count; i++) + { + Pawn pawn = thingList[i] as Pawn; + if (PawnBlockedBy(forPawn, pawn, collideOnlyWithStandingPawns, collideWithNonHostile, forPathFinder, useId)) + { + return pawn; + } + } + return null; + } + + public static bool PawnBlockedBy(Pawn forPawn, Pawn other, bool collideOnlyWithStandingPawns = false, bool collideWithNonHostile = false, bool forPathFinder = false, bool useId = false) + { + if (!ShouldCollideWithPawns(other)) + { + return false; + } + if (useId && forPawn.thingIDNumber < other.thingIDNumber && !other.stances.FullBodyBusyRecently) + { + return false; + } + if (other == forPawn) + { + return false; + } + if (collideOnlyWithStandingPawns) + { + if (other.pather.MovingNow) + { + return false; + } + if (other.pather.Moving && other.pather.MovedRecently(60)) + { + return false; + } + } + if (PawnsCanShareCellBecauseOfBodySize(other, forPawn)) + { + return false; + } + if (other.IsPsychologicallyInvisible()) + { + return false; + } + if (!other.kindDef.collidesWithPawns) + { + return false; + } + if (other.HostileTo(forPawn)) + { + return true; + } + if (forPawn.IsShambler && !MutantUtility.ShamblerShouldCollideWith(forPawn, other)) + { + return false; + } + if (collideWithNonHostile) + { + if (!forPathFinder && forPawn.Drafted && other.RaceProps.Animal) + { + return false; + } + Job curJob = other.CurJob; + if (curJob != null && (curJob.collideWithPawns || curJob.def.collideWithPawns || other.jobs.curDriver.collideWithPawns)) + { + return true; + } + } + return false; + } + + private static bool PawnsCanShareCellBecauseOfBodySize(Pawn p1, Pawn p2) + { + float bodySize = p1.BodySize; + float bodySize2 = p2.BodySize; + if (bodySize >= 1.5f || bodySize2 >= 1.5f) + { + return false; + } + float num = bodySize / bodySize2; + if (num < 1f) + { + num = 1f / num; + } + return num > 3.57f; + } + + public static bool KnownDangerAt(IntVec3 c, Map map, Pawn forPawn) + { + return c.GetEdifice(map)?.IsDangerousFor(forPawn) ?? false; + } + + [Obsolete("Lord and job report display validation is now checked separately.")] + public static bool ShouldDisplayActionInInspectString(Pawn p) + { + if (p.Faction != Faction.OfPlayer && p.HostFaction != Faction.OfPlayer) + { + return false; + } + if (p.InMentalState) + { + return false; + } + if (p.IsMutant && p.mutant.Def.overrideInspectString) + { + return false; + } + return true; + } + + public static bool ShouldDisplayLordReport(Pawn pawn) + { + if (ShouldShowCultistLordReport(pawn)) + { + return true; + } + return ShouldShowActionReportToPlayer(pawn); + } + + public static bool ShouldDisplayJobReport(Pawn pawn) + { + if (pawn.IsMutant && pawn.mutant.Def.overrideInspectString) + { + return false; + } + if (pawn.CurJobDef != null && pawn.CurJobDef.alwaysShowReport) + { + return true; + } + if (ModsConfig.AnomalyActive && pawn.Faction == Faction.OfHoraxCult && pawn.CurJobDef == JobDefOf.HateChanting) + { + return true; + } + if (ShouldShowCultistLordReport(pawn)) + { + return true; + } + return ShouldShowActionReportToPlayer(pawn); + } + + private static bool ShouldShowActionReportToPlayer(Pawn p) + { + if (p.Faction != Faction.OfPlayer && p.HostFaction != Faction.OfPlayer) + { + return false; + } + if (p.InMentalState) + { + return false; + } + if (p.IsMutant && p.mutant.Def.overrideInspectString) + { + return false; + } + return true; + } + + public static bool ShouldDisplayFactionInInspectString(Pawn p) + { + if (p.IsMutant && p.mutant.Def.overrideInspectString) + { + return false; + } + return true; + } + + private static bool ShouldShowCultistLordReport(Pawn pawn) + { + if (ModsConfig.AnomalyActive && pawn.Faction == Faction.OfHoraxCult && pawn.mindState.duty?.def == DutyDefOf.Invoke) + { + return true; + } + return false; + } + + public static bool ShouldSendNotificationAbout(Pawn p) + { + if (Current.ProgramState != ProgramState.Playing) + { + return false; + } + if (p == null) + { + return false; + } + if (PawnGenerator.IsBeingGenerated(p)) + { + return false; + } + if (p.IsWorldPawn() && (!p.IsCaravanMember() || !p.GetCaravan().IsPlayerControlled) && !IsTravelingInTransportPodWorldObject(p) && !p.IsBorrowedByAnyFaction() && p.Corpse.DestroyedOrNull()) + { + return false; + } + if (p.IsSubhuman) + { + return false; + } + if (ModsConfig.AnomalyActive && p.Corpse is UnnaturalCorpse) + { + return false; + } + if (p.Faction != Faction.OfPlayer) + { + if (p.HostFaction != Faction.OfPlayer) + { + return false; + } + if (p.RaceProps.Humanlike && p.guest.Released && !p.Downed && !p.InBed()) + { + return false; + } + if (p.CurJob != null && p.CurJob.exitMapOnArrival && !PrisonBreakUtility.IsPrisonBreaking(p)) + { + return false; + } + if (IsExitingMap(p)) + { + return false; + } + } + return true; + } + + public static bool ShouldGetThoughtAbout(Pawn pawn, Pawn subject) + { + if (pawn.IsSubhuman || subject.IsSubhuman) + { + return false; + } + if (pawn.Faction != subject.Faction) + { + if (!subject.IsWorldPawn()) + { + return !pawn.IsWorldPawn(); + } + return false; + } + return true; + } + + public static bool IsTeetotaler(this Pawn pawn) + { + if (!new HistoryEvent(HistoryEventDefOf.IngestedDrug, pawn.Named(HistoryEventArgsNames.Doer)).DoerWillingToDo()) + { + return true; + } + if (!new HistoryEvent(HistoryEventDefOf.IngestedRecreationalDrug, pawn.Named(HistoryEventArgsNames.Doer)).DoerWillingToDo()) + { + return true; + } + if (pawn.story != null) + { + return pawn.story.traits.DegreeOfTrait(TraitDefOf.DrugDesire) < 0; + } + return false; + } + + public static bool CanTakeDrug(this Pawn pawn, ThingDef drug) + { + CompProperties_Drug compProperties = drug.GetCompProperties(); + if (compProperties == null) + { + return true; + } + if (CanTakeDrugForDependency(pawn, drug)) + { + return true; + } + if (!compProperties.teetotalerCanConsume && pawn.IsTeetotaler()) + { + return false; + } + if (ModsConfig.IdeologyActive) + { + if (!IdeoUtility.DoerWillingToDo(HistoryEventDefOf.IngestedDrug, pawn)) + { + return false; + } + if (drug.IsNonMedicalDrug && !IdeoUtility.DoerWillingToDo(HistoryEventDefOf.IngestedRecreationalDrug, pawn)) + { + return false; + } + if (drug.ingestible != null && drug.ingestible.drugCategory == DrugCategory.Hard && !IdeoUtility.DoerWillingToDo(HistoryEventDefOf.IngestedHardDrug, pawn)) + { + return false; + } + } + return true; + } + + public static bool CanTakeDrugForDependency(Pawn pawn, ThingDef drug) + { + if (!ModsConfig.BiotechActive || pawn.genes == null) + { + return false; + } + CompProperties_Drug compProperties = drug.GetCompProperties(); + if (compProperties == null) + { + return true; + } + foreach (Gene item in pawn.genes.GenesListForReading) + { + if (item is Gene_ChemicalDependency gene_ChemicalDependency && item.Active && gene_ChemicalDependency.def.chemical == compProperties.chemical) + { + return true; + } + } + return false; + } + + public static bool TryGetChemicalDependencyGene(Pawn pawn, out Gene_ChemicalDependency gene) + { + gene = null; + if (!ModsConfig.BiotechActive || pawn.genes == null) + { + return false; + } + foreach (Gene item in pawn.genes.GenesListForReading) + { + if (item is Gene_ChemicalDependency gene_ChemicalDependency) + { + gene = gene_ChemicalDependency; + return true; + } + } + return false; + } + + public static bool PawnWouldBeUnhappyTakingDrug(this Pawn pawn, ThingDef drug) + { + if (pawn.IsTeetotaler()) + { + return drug.GetCompProperties() != null; + } + return false; + } + + public static bool IsProsthophobe(this Pawn pawn) + { + if (pawn.story != null) + { + return pawn.story.traits.HasTrait(TraitDefOf.BodyPurist); + } + return false; + } + + public static bool IsPrisonerInPrisonCell(this Pawn pawn) + { + if (pawn.IsPrisoner && pawn.Spawned) + { + return pawn.Position.IsInPrisonCell(pawn.Map); + } + return false; + } + + public static bool IsBeingArrested(Pawn pawn) + { + if (pawn.Map == null) + { + return false; + } + foreach (Pawn item in pawn.Map.mapPawns.AllPawnsSpawned) + { + if (item != pawn && item.CurJobDef == JobDefOf.Arrest && item.CurJob.AnyTargetIs(pawn)) + { + return true; + } + } + return false; + } + + public static string PawnKindsToCommaList(IEnumerable pawns, bool useAnd = false) + { + tmpPawns.Clear(); + tmpPawns.AddRange(pawns); + if (tmpPawns.Count >= 2) + { + tmpPawns.SortBy((Pawn x) => !x.RaceProps.Humanlike, (Pawn x) => x.GetKindLabelPlural()); + } + tmpAddedPawnKinds.Clear(); + tmpPawnKindsStr.Clear(); + for (int i = 0; i < tmpPawns.Count; i++) + { + if (tmpAddedPawnKinds.Contains(tmpPawns[i].kindDef)) + { + continue; + } + tmpAddedPawnKinds.Add(tmpPawns[i].kindDef); + int num = 0; + for (int j = 0; j < tmpPawns.Count; j++) + { + if (tmpPawns[j].kindDef == tmpPawns[i].kindDef) + { + num++; + } + } + if (num == 1) + { + tmpPawnKindsStr.Add("1 " + tmpPawns[i].KindLabel); + } + else + { + tmpPawnKindsStr.Add(num + " " + tmpPawns[i].GetKindLabelPlural(num)); + } + } + tmpPawns.Clear(); + return tmpPawnKindsStr.ToCommaList(useAnd); + } + + public static List PawnKindsToList(IEnumerable pawnKinds) + { + tmpPawnKinds.Clear(); + tmpPawnKinds.AddRange(pawnKinds); + if (tmpPawnKinds.Count >= 2) + { + tmpPawnKinds.SortBy((PawnKindDef x) => !x.RaceProps.Humanlike, (PawnKindDef x) => GenLabel.BestKindLabel(x, Gender.None, plural: true)); + } + tmpAddedPawnKinds.Clear(); + tmpPawnKindsStr.Clear(); + for (int i = 0; i < tmpPawnKinds.Count; i++) + { + if (tmpAddedPawnKinds.Contains(tmpPawnKinds[i])) + { + continue; + } + tmpAddedPawnKinds.Add(tmpPawnKinds[i]); + int num = 0; + for (int j = 0; j < tmpPawnKinds.Count; j++) + { + if (tmpPawnKinds[j] == tmpPawnKinds[i]) + { + num++; + } + } + if (num == 1) + { + tmpPawnKindsStr.Add("1 " + GenLabel.BestKindLabel(tmpPawnKinds[i], Gender.None)); + } + else + { + tmpPawnKindsStr.Add(num + " " + GenLabel.BestKindLabel(tmpPawnKinds[i], Gender.None, plural: true, num)); + } + } + return tmpPawnKindsStr; + } + + public static string PawnKindsToLineList(IEnumerable pawnKinds, string prefix) + { + PawnKindsToList(pawnKinds); + return tmpPawnKindsStr.ToLineList(prefix); + } + + public static string PawnKindsToLineList(IEnumerable pawnKinds, string prefix, Color color) + { + PawnKindsToList(pawnKinds); + for (int i = 0; i < tmpPawnKindsStr.Count; i++) + { + tmpPawnKindsStr[i] = tmpPawnKindsStr[i].Colorize(color); + } + return tmpPawnKindsStr.ToLineList(prefix); + } + + public static string PawnKindsToCommaList(IEnumerable pawnKinds, bool useAnd = false) + { + PawnKindsToList(pawnKinds); + return tmpPawnKindsStr.ToCommaList(useAnd); + } + + public static LocomotionUrgency ResolveLocomotion(Pawn pawn, LocomotionUrgency secondPriority) + { + if (!pawn.Dead && pawn.mindState.duty != null && pawn.mindState.duty.locomotion != 0) + { + return pawn.mindState.duty.locomotion; + } + return secondPriority; + } + + public static LocomotionUrgency ResolveLocomotion(Pawn pawn, LocomotionUrgency secondPriority, LocomotionUrgency thirdPriority) + { + LocomotionUrgency locomotionUrgency = ResolveLocomotion(pawn, secondPriority); + if (locomotionUrgency != 0) + { + return locomotionUrgency; + } + return thirdPriority; + } + + public static Danger ResolveMaxDanger(Pawn pawn, Danger secondPriority) + { + if (!pawn.Dead && pawn.mindState.duty != null && pawn.mindState.duty.maxDanger != 0) + { + return pawn.mindState.duty.maxDanger; + } + return secondPriority; + } + + public static Danger ResolveMaxDanger(Pawn pawn, Danger secondPriority, Danger thirdPriority) + { + Danger danger = ResolveMaxDanger(pawn, secondPriority); + if (danger != 0) + { + return danger; + } + return thirdPriority; + } + + public static bool IsPermanentCombatant(this Pawn pawn) + { + if (pawn?.mindState == null) + { + return true; + } + if (pawn.IsAnimal && pawn.Faction != null) + { + return false; + } + if (pawn.DevelopmentalStage.Juvenile()) + { + return false; + } + return true; + } + + public static bool IsCombatant(this Pawn pawn) + { + if (pawn.IsPermanentCombatant()) + { + return true; + } + return pawn.mindState.CombatantRecently; + } + + public static bool IsFighting(this Pawn pawn) + { + if (pawn.CurJob != null) + { + if (pawn.CurJob.def != JobDefOf.AttackMelee && pawn.CurJob.def != JobDefOf.AttackStatic && pawn.CurJob.def != JobDefOf.Wait_Combat && pawn.CurJob.def != JobDefOf.PredatorHunt) + { + return pawn.CurJob.def == JobDefOf.ManTurret; + } + return true; + } + return false; + } + + public static bool IsAttacking(this Pawn pawn) + { + if (pawn.CurJobDef == JobDefOf.AttackMelee || pawn.CurJobDef == JobDefOf.AttackStatic) + { + return true; + } + if (pawn.CurJobDef == JobDefOf.Wait_Combat && pawn.stances.curStance is Stance_Busy stance_Busy && stance_Busy.focusTarg.IsValid) + { + return true; + } + return false; + } + + public static Hediff_Psylink GetMainPsylinkSource(this Pawn pawn) + { + return (Hediff_Psylink)pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.PsychicAmplifier); + } + + public static int GetPsylinkLevel(this Pawn pawn) + { + int num = 0; + foreach (Hediff hediff in pawn.health.hediffSet.hediffs) + { + if (hediff is Hediff_Psylink hediff_Psylink) + { + num += hediff_Psylink.level; + } + } + return num; + } + + public static int GetMaxPsylinkLevel(this Pawn pawn) + { + return (int)HediffDefOf.PsychicAmplifier.maxSeverity; + } + + public static RoyalTitle GetMaxPsylinkLevelTitle(this Pawn pawn) + { + if (pawn.royalty == null) + { + return null; + } + int num = 0; + RoyalTitle result = null; + foreach (RoyalTitle item in pawn.royalty.AllTitlesInEffectForReading) + { + if (num < item.def.maxPsylinkLevel) + { + num = item.def.maxPsylinkLevel; + result = item; + } + } + return result; + } + + public static int GetMaxPsylinkLevelByTitle(this Pawn pawn) + { + return pawn.GetMaxPsylinkLevelTitle()?.def.maxPsylinkLevel ?? 0; + } + + public static void ChangePsylinkLevel(this Pawn pawn, int levelOffset, bool sendLetter = true) + { + Hediff_Psylink mainPsylinkSource = pawn.GetMainPsylinkSource(); + if (mainPsylinkSource == null) + { + mainPsylinkSource = (Hediff_Psylink)HediffMaker.MakeHediff(HediffDefOf.PsychicAmplifier, pawn); + try + { + mainPsylinkSource.suppressPostAddLetter = !sendLetter; + pawn.health.AddHediff(mainPsylinkSource, pawn.health.hediffSet.GetBrain()); + return; + } + finally + { + mainPsylinkSource.suppressPostAddLetter = false; + } + } + mainPsylinkSource.ChangeLevel(levelOffset, sendLetter); + } + + public static void GiveAllStartingPlayerPawnsThought(ThoughtDef thought) + { + foreach (Pawn startingAndOptionalPawn in Find.GameInitData.startingAndOptionalPawns) + { + if (startingAndOptionalPawn.needs.mood == null) + { + continue; + } + if (thought.IsSocial) + { + foreach (Pawn startingAndOptionalPawn2 in Find.GameInitData.startingAndOptionalPawns) + { + if (startingAndOptionalPawn2 != startingAndOptionalPawn) + { + startingAndOptionalPawn.needs.mood.thoughts.memories.TryGainMemory(thought, startingAndOptionalPawn2); + } + } + } + else + { + startingAndOptionalPawn.needs.mood.thoughts.memories.TryGainMemory(thought); + } + } + } + + public static IntVec3 DutyLocation(this Pawn pawn) + { + Pawn_RopeTracker roping = pawn.roping; + if (roping != null && roping.IsRopedToSpot) + { + return pawn.roping.RopedToSpot; + } + if (pawn.mindState.duty != null && pawn.mindState.duty.focus.IsValid) + { + return pawn.mindState.duty.focus.Cell; + } + return pawn.Position; + } + + public static bool EverBeenColonistOrTameAnimal(Pawn pawn) + { + return pawn.records.GetAsInt(RecordDefOf.TimeAsColonistOrColonyAnimal) > 0; + } + + public static bool EverBeenPrisoner(Pawn pawn) + { + return pawn.records.GetAsInt(RecordDefOf.TimeAsPrisoner) > 0; + } + + public static bool EverBeenQuestLodger(Pawn pawn) + { + return pawn.records.GetAsInt(RecordDefOf.TimeAsQuestLodger) > 0; + } + + public static void RecoverFromUnwalkablePositionOrKill(IntVec3 c, Map map) + { + if (!c.InBounds(map) || c.Walkable(map)) + { + return; + } + tmpThings.Clear(); + tmpThings.AddRange(c.GetThingList(map)); + for (int i = 0; i < tmpThings.Count; i++) + { + if (!(tmpThings[i] is Pawn pawn)) + { + continue; + } + if (CellFinder.TryFindBestPawnStandCell(pawn, out var cell)) + { + pawn.Position = cell; + pawn.Notify_Teleported(endCurrentJob: true, resetTweenedPos: false); + continue; + } + DamageInfo damageInfo = new DamageInfo(DamageDefOf.Crush, 99999f, 999f, -1f, null, pawn.health.hediffSet.GetBrain(), null, DamageInfo.SourceCategory.Collapse); + damageInfo.SetIgnoreInstantKillProtection(ignore: true); + pawn.TakeDamage(damageInfo); + if (!pawn.Dead) + { + pawn.Kill(damageInfo); + } + } + } + + public static float GetManhunterOnDamageChance(Pawn pawn, Thing instigator = null, float distance = -1f) + { + float num = GetManhunterOnDamageChance(pawn.def); + if (pawn.health.hediffSet.HasHediff(HediffDefOf.Scaria)) + { + num += 0.5f; + } + if (instigator != null) + { + num *= GenMath.LerpDoubleClamped(1f, 30f, 3f, 1f, distance); + num *= 1f - instigator.GetStatValue(StatDefOf.HuntingStealth); + if (instigator is Pawn instigator2) + { + num *= GetManhunterChanceFactorForInstigator(instigator2); + } + } + return Mathf.Clamp01(num); + } + + public static float GetManhunterOnDamageChance(ThingDef def) + { + return def.race.manhunterOnDamageChance * Find.Storyteller.difficulty.manhunterChanceOnDamageFactor; + } + + public static string GetManhunterOnDamageChanceExplanation(ThingDef def, Pawn pawn) + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.AppendLine("HarmedRevengeChanceExplanation".Translate()); + stringBuilder.AppendLine(); + stringBuilder.AppendLine(def.LabelCap + ": " + def.race.manhunterOnDamageChance.ToStringPercent()); + stringBuilder.AppendLine("StatsReport_DifficultyMultiplier".Translate(Find.Storyteller.difficultyDef.label) + ": " + Find.Storyteller.difficulty.manhunterChanceOnDamageFactor.ToStringPercent()); + if (pawn != null && pawn.health.hediffSet.HasHediff(HediffDefOf.Scaria)) + { + stringBuilder.AppendLine(HediffDefOf.Scaria.LabelCap + ": " + 0.5f.ToStringPercentSigned()); + } + stringBuilder.AppendLine(); + float f = ((pawn == null) ? GetManhunterOnDamageChance(def) : GetManhunterOnDamageChance(pawn)); + stringBuilder.AppendLine("StatsReport_FinalValue".Translate() + ": " + f.ToStringPercent()); + return stringBuilder.ToString(); + } + + public static float GetManhunterChanceFactorForInstigator(Pawn instigator) + { + if (ModsConfig.AnomalyActive && instigator?.Faction == Faction.OfEntities) + { + return 0f; + } + float num = 1f; + if (ModsConfig.IdeologyActive && instigator?.Ideo != null) + { + RoleEffect roleEffect = instigator.Ideo.GetRole(instigator)?.def.roleEffects?.FirstOrDefault((RoleEffect eff) => eff is RoleEffect_HuntingRevengeChanceFactor); + if (roleEffect != null) + { + num *= ((RoleEffect_HuntingRevengeChanceFactor)roleEffect).factor; + } + } + return num; + } + + public static float GetManhunterOnTameFailChance(Pawn pawn) + { + return Mathf.Clamp01(GetManhunterOnTameFailChance(pawn.def)); + } + + public static float GetManhunterOnTameFailChance(ThingDef def) + { + return def.race.manhunterOnTameFailChance; + } + + public static string GetManhunterOnTameFailChanceExplanation(ThingDef def, Pawn pawn) + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.AppendLine("Stat_Race_Animal_TameFailedRevengeChance_Desc".Translate()); + stringBuilder.AppendLine(); + stringBuilder.AppendLine(def.LabelCap + ": " + def.race.manhunterOnTameFailChance.ToStringPercent()); + stringBuilder.AppendLine(); + float f = ((pawn == null) ? GetManhunterOnTameFailChance(def) : GetManhunterOnTameFailChance(pawn)); + stringBuilder.AppendLine("StatsReport_FinalValue".Translate() + ": " + f.ToStringPercent()); + return stringBuilder.ToString(); + } + + public static MentalStateDef ManhunterStateFor(Pawn pawn) + { + if (pawn.health.hediffSet.HasHediff(HediffDefOf.Scaria)) + { + return MentalStateDefOf.ManhunterPermanent; + } + return MentalStateDefOf.Manhunter; + } + + public static bool PlayerHasReproductivePair(PawnKindDef pawnKindDef) + { + if (!pawnKindDef.RaceProps.Animal) + { + return false; + } + List allMapsCaravansAndTravellingTransporters_Alive_OfPlayerFaction = PawnsFinder.AllMapsCaravansAndTravellingTransporters_Alive_OfPlayerFaction; + bool flag = false; + bool flag2 = false; + for (int i = 0; i < allMapsCaravansAndTravellingTransporters_Alive_OfPlayerFaction.Count; i++) + { + Pawn pawn = allMapsCaravansAndTravellingTransporters_Alive_OfPlayerFaction[i]; + if (pawn.kindDef == pawnKindDef && pawn.ageTracker.CurLifeStage.reproductive) + { + if (pawn.gender == Gender.Male) + { + flag = true; + } + else if (pawn.gender == Gender.Female) + { + flag2 = true; + } + if (flag && flag2) + { + return true; + } + } + } + return false; + } + + public static float PlayerAnimalBodySizePerCapita() + { + float num = 0f; + int num2 = 0; + List allMapsCaravansAndTravellingTransporters_Alive_OfPlayerFaction = PawnsFinder.AllMapsCaravansAndTravellingTransporters_Alive_OfPlayerFaction; + for (int i = 0; i < allMapsCaravansAndTravellingTransporters_Alive_OfPlayerFaction.Count; i++) + { + Pawn pawn = allMapsCaravansAndTravellingTransporters_Alive_OfPlayerFaction[i]; + if (pawn.IsFreeColonist && !pawn.IsQuestLodger()) + { + num2++; + } + if (pawn.IsAnimal) + { + num += pawn.BodySize; + } + } + if (num2 <= 0) + { + return 0f; + } + return num / (float)num2; + } + + private static List PawnsOfFactionOnMapOrInCaravan(Pawn pawn) + { + if (pawn.Spawned) + { + return pawn.Map.mapPawns.SpawnedPawnsInFaction(pawn.Faction); + } + return pawn.GetCaravan()?.PawnsListForReading; + } + + public static float PlayerVeneratedAnimalBodySizePerCapitaOnMapOrCaravan(Pawn pawn) + { + if (pawn.Ideo == null || pawn.Faction == null) + { + return 0f; + } + float num = 0f; + int num2 = 0; + List list = PawnsOfFactionOnMapOrInCaravan(pawn); + for (int i = 0; i < list.Count; i++) + { + if (list[i].Faction == pawn.Faction && !pawn.IsQuestLodger()) + { + if (list[i].IsAnimal && pawn.Ideo.IsVeneratedAnimal(list[i])) + { + num += list[i].BodySize; + } + else if (list[i].RaceProps.Humanlike) + { + num2++; + } + } + } + return Mathf.Round(((num2 > 0) ? (num / (float)num2) : 0f) * 100f) / 100f; + } + + public static Pawn FirstVeneratedAnimalOnMapOrCaravan(Pawn pawn) + { + if (pawn.Ideo == null || pawn.Faction == null) + { + return null; + } + List list = PawnsOfFactionOnMapOrInCaravan(pawn); + for (int i = 0; i < list.Count; i++) + { + if (pawn.Faction == list[i].Faction && pawn.Ideo.IsVeneratedAnimal(list[i])) + { + return list[i]; + } + } + return null; + } + + public static bool HasClothingNotRequiredByKind(Pawn p) + { + if (p.apparel == null) + { + return false; + } + List wornApparel = p.apparel.WornApparel; + if (wornApparel.Count > 0 && p.kindDef.apparelRequired.NullOrEmpty()) + { + return true; + } + for (int i = 0; i < wornApparel.Count; i++) + { + Apparel apparel = wornApparel[i]; + if (apparel.def.apparel.countsAsClothingForNudity && !p.kindDef.apparelRequired.Contains(apparel.def)) + { + return true; + } + } + return false; + } + + public static IEnumerable GetCombatPawnKindsForPoints(Func selector, float points, Func selectionWeight = null) + { + IEnumerable allKinds = DefDatabase.AllDefsListForReading.Where(selector); + if (selectionWeight == null) + { + selectionWeight = (PawnKindDef _) => 1f; + } + PawnKindDef result; + while (points > 0f && allKinds.Where((PawnKindDef def) => def.combatPower > 0f && def.combatPower <= points && def.appearsRandomlyInCombatGroups).TryRandomElementByWeight(selectionWeight, out result)) + { + points -= result.combatPower; + yield return result; + } + } + + public static int GetMaxAllowedToPickUp(Pawn pawn, ThingDef thingDef) + { + int maxAllowedToPickUp = GetMaxAllowedToPickUp(thingDef, pawn.Map); + if (maxAllowedToPickUp <= 0) + { + return 0; + } + int num = pawn.inventory.Count((Thing t) => t.def.orderedTakeGroup == thingDef.orderedTakeGroup); + return Math.Max(maxAllowedToPickUp - num, 0); + } + + public static int GetMaxAllowedToPickUp(ThingDef thingDef, Map map = null) + { + if (map != null && !map.IsPlayerHome) + { + return int.MaxValue; + } + if (thingDef.orderedTakeGroup == null) + { + return 0; + } + return thingDef.orderedTakeGroup.max; + } + + public static bool CanPickUp(Pawn pawn, ThingDef thingDef) + { + if (!pawn.Map.IsPlayerHome) + { + return true; + } + if (pawn.inventory != null && thingDef.orderedTakeGroup != null) + { + return thingDef.orderedTakeGroup.max > 0; + } + return false; + } + + public static bool ShouldBeSlaughtered(this Pawn pawn) + { + if (!pawn.Spawned || !pawn.IsAnimal) + { + return false; + } + if (pawn.Map.designationManager.DesignationOn(pawn, DesignationDefOf.Slaughter) != null || pawn.Map.autoSlaughterManager.AnimalsToSlaughter.Contains(pawn)) + { + return pawn.Map.designationManager.DesignationOn(pawn, DesignationDefOf.ReleaseAnimalToWild) == null; + } + return false; + } + + public static bool CanBeBuried(this Thing t) + { + if (t is Corpse { MapHeld: not null } corpse) + { + return corpse.MapHeld.designationManager.DesignationOn(corpse, DesignationDefOf.ExtractSkull) == null; + } + return true; + } + + public static bool PawnHadFuneral(Pawn pawn) + { + Precept_Ritual precept_Ritual = (Precept_Ritual)(pawn.ideo?.Ideo?.GetPrecept(PreceptDefOf.Funeral)); + if (precept_Ritual != null && !precept_Ritual.completedObligations.NullOrEmpty()) + { + return precept_Ritual.completedObligations.Any((RitualObligation o) => o.FirstValidTarget.Thing == pawn); + } + return false; + } + + public static bool IsBiologicallyOrArtificiallyBlind(Pawn pawn) + { + if (!IsBiologicallyBlind(pawn)) + { + return IsArtificiallyBlind(pawn); + } + return true; + } + + public static bool IsBiologicallyBlind(Pawn pawn) + { + return !pawn.health.capacities.CapableOf(PawnCapacityDefOf.Sight); + } + + public static bool IsArtificiallyBlind(Pawn p) + { + if (IsBiologicallyBlind(p)) + { + return false; + } + if (p.apparel != null) + { + foreach (Apparel item in p.apparel.WornApparel) + { + if (item.def.apparel.blocksVision) + { + return true; + } + } + } + return false; + } + + public static bool IsWorkTypeDisabledByAge(this Pawn pawn, WorkTypeDef workType, out int minAgeRequired) + { + for (int i = 0; i < pawn.RaceProps.lifeStageWorkSettings.Count; i++) + { + LifeStageWorkSettings lifeStageWorkSettings = pawn.RaceProps.lifeStageWorkSettings[i]; + if (lifeStageWorkSettings.workType == workType && lifeStageWorkSettings.IsDisabled(pawn)) + { + minAgeRequired = lifeStageWorkSettings.minAge; + return true; + } + } + minAgeRequired = 0; + return false; + } + + public static bool DutyActiveWhenDown(this Pawn pawn, bool onlyInBed = false) + { + if (onlyInBed && !pawn.InBed()) + { + return false; + } + return (pawn.GetLord()?.LordJob?.DutyActiveWhenDown(pawn)).GetValueOrDefault(); + } + + public static bool IsExitingMap(Pawn pawn) + { + Lord lord = pawn.GetLord(); + if (lord == null) + { + return false; + } + if (!(lord.LordJob is LordJob_ExitMapBest) && !(lord.LordJob is LordJob_ExitMapNear) && !(lord.LordJob is LordJob_ExitOnShuttle)) + { + return lord.LordJob is LordJob_TravelAndExit; + } + return true; + } + + public static void ForceEjectFromContainer(Pawn pawn) + { + Thing resultingThing; + if (pawn.ParentHolder is Pawn_CarryTracker pawn_CarryTracker) + { + pawn_CarryTracker.TryDropCarriedThing(pawn_CarryTracker.pawn.Position, ThingPlaceMode.Near, out resultingThing); + pawn_CarryTracker.pawn.jobs.EndCurrentJob(JobCondition.InterruptForced); + } + if (pawn.ParentHolder is Building_Enterable building_Enterable) + { + building_Enterable.innerContainer.TryDrop(pawn, building_Enterable.InteractionCell, building_Enterable.Map, ThingPlaceMode.Near, out resultingThing); + } + if (pawn.ParentHolder is Building_Casket building_Casket) + { + building_Casket.EjectContents(); + } + if (pawn.ParentHolder is Building_HoldingPlatform building_HoldingPlatform) + { + building_HoldingPlatform.EjectContents(); + } + if (pawn.ParentHolder is CompBiosculpterPod compBiosculpterPod) + { + compBiosculpterPod.EjectContents(interrupted: true, playSounds: true); + } + } +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/Projectile-TickInterval-Verse.txt b/MCP/vector_cache/Projectile-TickInterval-Verse.txt new file mode 100644 index 00000000..d02770d8 --- /dev/null +++ b/MCP/vector_cache/Projectile-TickInterval-Verse.txt @@ -0,0 +1,655 @@ +根据向量相似度分析,与 'TickInterval, Projectile, Verse' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\Projectile.txt` + +```csharp +public abstract class Projectile : ThingWithComps +{ + private static readonly Material shadowMaterial = MaterialPool.MatFrom("Things/Skyfaller/SkyfallerShadowCircle", ShaderDatabase.Transparent); + + protected Vector3 origin; + + protected Vector3 destination; + + public LocalTargetInfo usedTarget; + + public LocalTargetInfo intendedTarget; + + protected Thing equipment; + + protected ThingDef equipmentDef; + + protected Thing launcher; + + protected ThingDef targetCoverDef; + + private ProjectileHitFlags desiredHitFlags = ProjectileHitFlags.All; + + protected bool preventFriendlyFire; + + protected int lifetime; + + protected QualityCategory equipmentQuality = QualityCategory.Normal; + + public float stoppingPower; + + public DamageDef damageDefOverride; + + public List extraDamages = new List(); + + protected bool landed; + + protected int ticksToImpact; + + private Sustainer ambientSustainer; + + private static List checkedCells = new List(); + + public DamageDef DamageDef => damageDefOverride ?? def.projectile.damageDef; + + public IEnumerable ExtraDamages + { + get + { + List first = extraDamages; + IEnumerable enumerable = def.projectile.extraDamages; + return first.Concat(enumerable ?? Enumerable.Empty()); + } + } + + public ProjectileHitFlags HitFlags + { + get + { + if (def.projectile.alwaysFreeIntercept) + { + return ProjectileHitFlags.All; + } + if (def.projectile.flyOverhead) + { + return ProjectileHitFlags.None; + } + return desiredHitFlags; + } + set + { + desiredHitFlags = value; + } + } + + protected float StartingTicksToImpact + { + get + { + float num = (origin - destination).magnitude / def.projectile.SpeedTilesPerTick; + if (num <= 0f) + { + num = 0.001f; + } + return num; + } + } + + protected IntVec3 DestinationCell => new IntVec3(destination); + + public virtual Vector3 ExactPosition + { + get + { + Vector3 vector = (destination - origin).Yto0() * DistanceCoveredFraction; + return origin.Yto0() + vector + Vector3.up * def.Altitude; + } + } + + protected float DistanceCoveredFraction => Mathf.Clamp01(1f - (float)ticksToImpact / StartingTicksToImpact); + + protected float DistanceCoveredFractionArc => Mathf.Clamp01(1f - (float)(landed ? lifetime : ticksToImpact) / StartingTicksToImpact); + + public virtual Quaternion ExactRotation => Quaternion.LookRotation((destination - origin).Yto0()); + + public virtual bool AnimalsFleeImpact => false; + + public override Vector3 DrawPos => ExactPosition; + + public virtual Material DrawMat => def.graphic.MatSingleFor(this); + + public virtual int DamageAmount => def.projectile.GetDamageAmount(equipment); + + public virtual float ArmorPenetration => def.projectile.GetArmorPenetration(equipment); + + public ThingDef EquipmentDef => equipmentDef; + + public Thing Launcher => launcher; + + public override int UpdateRateTicks + { + get + { + if (base.Spawned && Find.CurrentMap == base.Map && Find.CameraDriver.InViewOf(this)) + { + return 1; + } + return 15; + } + } + + private float ArcHeightFactor + { + get + { + float num = def.projectile.arcHeightFactor; + float num2 = (destination - origin).MagnitudeHorizontalSquared(); + if (num * num > num2 * 0.2f * 0.2f) + { + num = Mathf.Sqrt(num2) * 0.2f; + } + return num; + } + } + + public override void ExposeData() + { + base.ExposeData(); + Scribe_Values.Look(ref origin, "origin"); + Scribe_Values.Look(ref destination, "destination"); + Scribe_Values.Look(ref ticksToImpact, "ticksToImpact", 0); + Scribe_TargetInfo.Look(ref usedTarget, "usedTarget"); + Scribe_TargetInfo.Look(ref intendedTarget, "intendedTarget"); + Scribe_References.Look(ref launcher, "launcher"); + Scribe_References.Look(ref equipment, "equipment"); + Scribe_Defs.Look(ref equipmentDef, "equipmentDef"); + Scribe_Defs.Look(ref targetCoverDef, "targetCoverDef"); + Scribe_Values.Look(ref desiredHitFlags, "desiredHitFlags", ProjectileHitFlags.All); + Scribe_Values.Look(ref preventFriendlyFire, "preventFriendlyFire", defaultValue: false); + Scribe_Values.Look(ref landed, "landed", defaultValue: false); + Scribe_Values.Look(ref lifetime, "lifetime", 0); + Scribe_Values.Look(ref equipmentQuality, "equipmentQuality", QualityCategory.Normal); + } + + public void Launch(Thing launcher, LocalTargetInfo usedTarget, LocalTargetInfo intendedTarget, ProjectileHitFlags hitFlags, bool preventFriendlyFire = false, Thing equipment = null) + { + Launch(launcher, base.Position.ToVector3Shifted(), usedTarget, intendedTarget, hitFlags, preventFriendlyFire, equipment); + } + + public virtual void Launch(Thing launcher, Vector3 origin, LocalTargetInfo usedTarget, LocalTargetInfo intendedTarget, ProjectileHitFlags hitFlags, bool preventFriendlyFire = false, Thing equipment = null, ThingDef targetCoverDef = null) + { + this.launcher = launcher; + this.origin = origin; + this.usedTarget = usedTarget; + this.intendedTarget = intendedTarget; + this.targetCoverDef = targetCoverDef; + this.preventFriendlyFire = preventFriendlyFire; + HitFlags = hitFlags; + stoppingPower = def.projectile.stoppingPower; + if (stoppingPower == 0f && def.projectile.damageDef != null) + { + stoppingPower = def.projectile.damageDef.defaultStoppingPower; + } + if (equipment != null) + { + this.equipment = equipment; + equipmentDef = equipment.def; + equipment.TryGetQuality(out equipmentQuality); + if (equipment.TryGetComp(out CompUniqueWeapon comp)) + { + foreach (WeaponTraitDef item in comp.TraitsListForReading) + { + if (!Mathf.Approximately(item.additionalStoppingPower, 0f)) + { + stoppingPower += item.additionalStoppingPower; + } + } + } + } + else + { + equipmentDef = null; + } + destination = usedTarget.Cell.ToVector3Shifted() + Gen.RandomHorizontalVector(0.3f); + ticksToImpact = Mathf.CeilToInt(StartingTicksToImpact); + if (ticksToImpact < 1) + { + ticksToImpact = 1; + } + lifetime = ticksToImpact; + if (!def.projectile.soundAmbient.NullOrUndefined()) + { + ambientSustainer = def.projectile.soundAmbient.TrySpawnSustainer(SoundInfo.InMap(this, MaintenanceType.PerTick)); + } + } + + protected override void Tick() + { + base.Tick(); + if (ticksToImpact == 60 && Find.TickManager.CurTimeSpeed == TimeSpeed.Normal && def.projectile.soundImpactAnticipate != null) + { + def.projectile.soundImpactAnticipate.PlayOneShot(this); + } + if (ambientSustainer != null) + { + ambientSustainer.Maintain(); + } + } + + protected override void TickInterval(int delta) + { + base.TickInterval(delta); + lifetime -= delta; + if (landed) + { + return; + } + Vector3 exactPosition = ExactPosition; + ticksToImpact -= delta; + if (!ExactPosition.InBounds(base.Map)) + { + ticksToImpact += delta; + base.Position = ExactPosition.ToIntVec3(); + Destroy(); + return; + } + Vector3 exactPosition2 = ExactPosition; + if (CheckForFreeInterceptBetween(exactPosition, exactPosition2)) + { + return; + } + base.Position = ExactPosition.ToIntVec3(); + if (ticksToImpact <= 0) + { + if (DestinationCell.InBounds(base.Map)) + { + base.Position = DestinationCell; + } + ImpactSomething(); + } + } + + private bool CheckForFreeInterceptBetween(Vector3 lastExactPos, Vector3 newExactPos) + { + if (lastExactPos == newExactPos) + { + return false; + } + List list = base.Map.listerThings.ThingsInGroup(ThingRequestGroup.ProjectileInterceptor); + for (int i = 0; i < list.Count; i++) + { + if (list[i].TryGetComp().CheckIntercept(this, lastExactPos, newExactPos)) + { + Impact(null, blockedByShield: true); + return true; + } + } + IntVec3 intVec = lastExactPos.ToIntVec3(); + IntVec3 intVec2 = newExactPos.ToIntVec3(); + if (intVec2 == intVec) + { + return false; + } + if (!intVec.InBounds(base.Map) || !intVec2.InBounds(base.Map)) + { + return false; + } + if (intVec2.AdjacentToCardinal(intVec)) + { + return CheckForFreeIntercept(intVec2); + } + if (VerbUtility.InterceptChanceFactorFromDistance(origin, intVec2) <= 0f) + { + return false; + } + Vector3 vect = lastExactPos; + Vector3 v = newExactPos - lastExactPos; + Vector3 vector = v.normalized * 0.2f; + int num = (int)(v.MagnitudeHorizontal() / 0.2f); + checkedCells.Clear(); + int num2 = 0; + IntVec3 intVec3; + do + { + vect += vector; + intVec3 = vect.ToIntVec3(); + if (!checkedCells.Contains(intVec3)) + { + if (CheckForFreeIntercept(intVec3)) + { + return true; + } + checkedCells.Add(intVec3); + } + num2++; + if (num2 > num) + { + return false; + } + } + while (!(intVec3 == intVec2)); + return false; + } + + private bool CheckForFreeIntercept(IntVec3 c) + { + if (destination.ToIntVec3() == c) + { + return false; + } + float num = VerbUtility.InterceptChanceFactorFromDistance(origin, c); + if (num <= 0f) + { + return false; + } + bool flag = false; + List thingList = c.GetThingList(base.Map); + for (int i = 0; i < thingList.Count; i++) + { + Thing thing = thingList[i]; + if (!CanHit(thing)) + { + continue; + } + bool flag2 = false; + if (thing.def.Fillage == FillCategory.Full) + { + if (!(thing is Building_Door { Open: not false })) + { + ThrowDebugText("int-wall", c); + Impact(thing); + return true; + } + flag2 = true; + } + float num2 = 0f; + if (thing is Pawn pawn) + { + num2 = 0.4f * Mathf.Clamp(pawn.BodySize, 0.1f, 2f); + if (pawn.GetPosture() != 0) + { + num2 *= 0.1f; + } + if (launcher != null && pawn.Faction != null && launcher.Faction != null && !pawn.Faction.HostileTo(launcher.Faction)) + { + if (preventFriendlyFire) + { + num2 = 0f; + ThrowDebugText("ff-miss", c); + } + else + { + num2 *= Find.Storyteller.difficulty.friendlyFireChanceFactor; + } + } + } + else if (thing.def.fillPercent > 0.2f) + { + num2 = (flag2 ? 0.05f : ((!DestinationCell.AdjacentTo8Way(c)) ? (thing.def.fillPercent * 0.15f) : (thing.def.fillPercent * 1f))); + } + num2 *= num; + if (num2 > 1E-05f) + { + if (Rand.Chance(num2)) + { + ThrowDebugText("int-" + num2.ToStringPercent(), c); + Impact(thing); + return true; + } + flag = true; + ThrowDebugText(num2.ToStringPercent(), c); + } + } + if (!flag) + { + ThrowDebugText("o", c); + } + return false; + } + + private void ThrowDebugText(string text, IntVec3 c) + { + if (DebugViewSettings.drawShooting) + { + MoteMaker.ThrowText(c.ToVector3Shifted(), base.Map, text); + } + } + + protected override void DrawAt(Vector3 drawLoc, bool flip = false) + { + float num = ArcHeightFactor * GenMath.InverseParabola(DistanceCoveredFractionArc); + Vector3 vector = drawLoc + new Vector3(0f, 0f, 1f) * num; + if (def.projectile.shadowSize > 0f) + { + DrawShadow(drawLoc, num); + } + Quaternion rotation = ExactRotation; + if (def.projectile.spinRate != 0f) + { + float num2 = 60f / def.projectile.spinRate; + rotation = Quaternion.AngleAxis((float)Find.TickManager.TicksGame % num2 / num2 * 360f, Vector3.up); + } + if (def.projectile.useGraphicClass) + { + Graphic.Draw(vector, base.Rotation, this, rotation.eulerAngles.y); + } + else + { + Graphics.DrawMesh(MeshPool.GridPlane(def.graphicData.drawSize), vector, rotation, DrawMat, 0); + } + Comps_PostDraw(); + } + + protected bool CanHit(Thing thing) + { + if (!thing.Spawned) + { + return false; + } + if (thing == launcher) + { + return false; + } + ProjectileHitFlags hitFlags = HitFlags; + if (hitFlags == ProjectileHitFlags.None) + { + return false; + } + if (thing.Map != base.Map) + { + return false; + } + if (CoverUtility.ThingCovered(thing, base.Map)) + { + return false; + } + if (thing == intendedTarget && (hitFlags & ProjectileHitFlags.IntendedTarget) != 0) + { + return true; + } + if (thing != intendedTarget) + { + if (thing is Pawn) + { + if ((hitFlags & ProjectileHitFlags.NonTargetPawns) != 0) + { + return true; + } + } + else if ((hitFlags & ProjectileHitFlags.NonTargetWorld) != 0) + { + return true; + } + } + if (thing == intendedTarget && thing.def.Fillage == FillCategory.Full) + { + return true; + } + return false; + } + + protected virtual void ImpactSomething() + { + if (def.projectile.flyOverhead) + { + RoofDef roofDef = base.Map.roofGrid.RoofAt(base.Position); + if (roofDef != null) + { + if (roofDef.isThickRoof) + { + ThrowDebugText("hit-thick-roof", base.Position); + if (!def.projectile.soundHitThickRoof.NullOrUndefined()) + { + def.projectile.soundHitThickRoof.PlayOneShot(new TargetInfo(base.Position, base.Map)); + } + Destroy(); + return; + } + if (base.Position.GetEdifice(base.Map) == null || base.Position.GetEdifice(base.Map).def.Fillage != FillCategory.Full) + { + RoofCollapserImmediate.DropRoofInCells(base.Position, base.Map); + } + } + } + if (usedTarget.HasThing && CanHit(usedTarget.Thing)) + { + if (usedTarget.Thing is Pawn p && p.GetPosture() != 0 && (origin - destination).MagnitudeHorizontalSquared() >= 20.25f && !Rand.Chance(0.5f)) + { + ThrowDebugText("miss-laying", base.Position); + Impact(null); + } + else + { + Impact(usedTarget.Thing); + } + return; + } + List list = VerbUtility.ThingsToHit(base.Position, base.Map, CanHit); + list.Shuffle(); + for (int i = 0; i < list.Count; i++) + { + Thing thing = list[i]; + float num; + if (thing is Pawn pawn) + { + num = 0.5f * Mathf.Clamp(pawn.BodySize, 0.1f, 2f); + if (pawn.GetPosture() != 0 && (origin - destination).MagnitudeHorizontalSquared() >= 20.25f) + { + num *= 0.5f; + } + if (launcher != null && pawn.Faction != null && launcher.Faction != null && !pawn.Faction.HostileTo(launcher.Faction)) + { + num *= VerbUtility.InterceptChanceFactorFromDistance(origin, base.Position); + } + } + else + { + num = 1.5f * thing.def.fillPercent; + } + if (Rand.Chance(num)) + { + ThrowDebugText("hit-" + num.ToStringPercent(), base.Position); + Impact(list.RandomElement()); + return; + } + ThrowDebugText("miss-" + num.ToStringPercent(), base.Position); + } + Impact(null); + } + + protected virtual void Impact(Thing hitThing, bool blockedByShield = false) + { + GenClamor.DoClamor(this, 12f, ClamorDefOf.Impact); + if (!blockedByShield && def.projectile.landedEffecter != null) + { + def.projectile.landedEffecter.Spawn(base.Position, base.Map).Cleanup(); + } + Destroy(); + } + + private void DrawShadow(Vector3 drawLoc, float height) + { + if (!(shadowMaterial == null)) + { + float num = def.projectile.shadowSize * Mathf.Lerp(1f, 0.6f, height); + Vector3 s = new Vector3(num, 1f, num); + Vector3 vector = new Vector3(0f, -0.01f, 0f); + Matrix4x4 matrix = default(Matrix4x4); + matrix.SetTRS(drawLoc + vector, Quaternion.identity, s); + Graphics.DrawMesh(MeshPool.plane10, matrix, shadowMaterial, 0); + } + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompRitualEffect_IntervalSpawn.txt` +**相似度:** 0.5662 + +```csharp +public abstract class CompRitualEffect_IntervalSpawn : RitualVisualEffectComp +{ + public int lastSpawnTick = -1; + + public int ticksPassed; + + protected int burstsDone; + + protected CompProperties_RitualEffectIntervalSpawn Props => (CompProperties_RitualEffectIntervalSpawn)props; + + public override bool ShouldSpawnNow(LordJob_Ritual ritual) + { + if (Props.delay > 0 && ticksPassed < Props.delay) + { + return false; + } + if (Props.maxBursts > 0 && burstsDone >= Props.maxBursts) + { + return false; + } + if (lastSpawnTick != -1) + { + return GenTicks.TicksGame - lastSpawnTick >= Props.spawnIntervalTicks; + } + return true; + } + + public override void TickInterval(int delta) + { + base.TickInterval(delta); + ticksPassed += delta; + } + + public override void ExposeData() + { + base.ExposeData(); + Scribe_Values.Look(ref lastSpawnTick, "lastSpawnTick", -1); + Scribe_Values.Look(ref burstsDone, "burstsDone", 0); + Scribe_Values.Look(ref ticksPassed, "ticksPassed", 0); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\Gene_Clotting.txt` +**相似度:** 0.5078 + +```csharp +public class Gene_Clotting : Gene +{ + private const int ClotCheckInterval = 360; + + private static readonly FloatRange TendingQualityRange = new FloatRange(0.2f, 0.7f); + + public override void TickInterval(int delta) + { + base.TickInterval(delta); + if (!pawn.IsHashIntervalTick(360, delta)) + { + return; + } + List hediffs = pawn.health.hediffSet.hediffs; + for (int num = hediffs.Count - 1; num >= 0; num--) + { + if (hediffs[num].Bleeding) + { + hediffs[num].Tended(TendingQualityRange.RandomInRange, TendingQualityRange.TrueMax, 1); + } + } + } +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/PsychicRitualDef.txt b/MCP/vector_cache/PsychicRitualDef.txt new file mode 100644 index 00000000..1cb31bc6 --- /dev/null +++ b/MCP/vector_cache/PsychicRitualDef.txt @@ -0,0 +1,871 @@ +根据向量相似度分析,与 '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 layerWhitelist = new List(); + + [MustTranslate] + public string letterAICompleteLabel; + + [MustTranslate] + public string letterAICompleteText; + + [MustTranslate] + public string letterAIArrivedText; + + [NoTranslate] + public string iconPath; + + public Texture2D uiIcon = BaseContent.BadTex; + + private List rolesBackingList = new List(8); + + private static readonly List tmpPawnsIterationList = new List(16); + + public virtual List 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.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 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(Find.CurrentMap.mapPawns.FreeColonistsAndPrisonersSpawned.Where((Pawn p) => !p.IsSubhuman)), new List()); + } + + public virtual PsychicRitualRoleAssignments BuildRoleAssignments(TargetInfo target) + { + return new PsychicRitualRoleAssignments(Roles, target); + } + + public static bool OfferingReachable(Map map, List pawns, IngredientCount offering, out int reachableCount) + { + using (new ProfilerBlock("Offering reachable")) + { + reachableCount = 0; + float num = offering.GetBaseCount(); + if (num <= 0f) + { + return true; + } + List 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 BlockingIssues(PsychicRitualRoleAssignments assignments, Map map) + { + return Enumerable.Empty(); + } + + 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 powerFactorsOut, out float power) + { + power = 0f; + int num = 0; + IReadOnlyDictionary> roleAssignments = assignments.RoleAssignments; + PsychicRitualRoleDef key; + List value; + foreach (KeyValuePair> item in roleAssignments) + { + item.Deconstruct(out key, out value); + PsychicRitualRoleDef psychicRitualRoleDef = key; + List 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> item2 in roleAssignments) + { + item2.Deconstruct(out key, out value); + PsychicRitualRoleDef psychicRitualRoleDef2 = key; + List 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 OutcomeWarnings(PsychicRitualRoleAssignments assignments) + { + return Enumerable.Empty(); + } + + 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 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 CreateToils(PsychicRitual psychicRitual, PsychicRitualGraph graph) + { + List 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 CreateToils(PsychicRitual psychicRitual, PsychicRitualGraph parent) + { + List 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().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(); + 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> tmpParticipants = new Dictionary>(8); + + private List tmpGatheringPawns = new List(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 Roles + { + get + { + List 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 CreateToils(PsychicRitual psychicRitual, PsychicRitualGraph parent) + { + float randomInRange = hoursUntilOutcome.RandomInRange; + IReadOnlyDictionary> readOnlyDictionary = GenerateRolePositions(psychicRitual.assignments); + return new List + { + 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(); + 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 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> GenerateRolePositions(PsychicRitualRoleAssignments assignments) + { + tmpParticipants.ClearAndPoolValueLists(); + foreach (PsychicRitualRoleDef role in Roles) + { + tmpParticipants[role] = SimplePool>.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 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 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 powerFactorsOut, ref float power, Building building) + { + Dictionary dictionary = new Dictionary(); + List linkedFacilitiesListForReading = building.GetComp().LinkedFacilitiesListForReading; + for (int i = 0; i < linkedFacilitiesListForReading.Count; i++) + { + Thing thing = linkedFacilitiesListForReading[i]; + CompFacility compFacility = thing.TryGetComp(); + 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 item in dictionary) + { + powerFactorsOut?.Add(new QualityFactor + { + label = Find.ActiveLanguageWorker.Pluralize(item.Key.label).CapitalizeFirst(), + positive = true, + count = item.Value.count + " / " + item.Key.GetCompProperties().maxSimultaneous, + quality = item.Value.offset, + toolTip = "PsychicRitualDef_InvocationCircle_QualityFactor_Increase_Tooltip".Translate().CapitalizeFirst().EndWithPeriod() + }); + power += item.Value.offset; + } + } + + public override IEnumerable 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"))); + } + } + } +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/PsychicRitualDef_InvocationCircle.txt b/MCP/vector_cache/PsychicRitualDef_InvocationCircle.txt new file mode 100644 index 00000000..8b20176c --- /dev/null +++ b/MCP/vector_cache/PsychicRitualDef_InvocationCircle.txt @@ -0,0 +1,573 @@ +根据向量相似度分析,与 'PsychicRitualDef_InvocationCircle' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\PsychicRitualDef_InvocationCircle.txt` + +```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> tmpParticipants = new Dictionary>(8); + + private List tmpGatheringPawns = new List(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 Roles + { + get + { + List 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 CreateToils(PsychicRitual psychicRitual, PsychicRitualGraph parent) + { + float randomInRange = hoursUntilOutcome.RandomInRange; + IReadOnlyDictionary> readOnlyDictionary = GenerateRolePositions(psychicRitual.assignments); + return new List + { + 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(); + 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 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> GenerateRolePositions(PsychicRitualRoleAssignments assignments) + { + tmpParticipants.ClearAndPoolValueLists(); + foreach (PsychicRitualRoleDef role in Roles) + { + tmpParticipants[role] = SimplePool>.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 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 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 powerFactorsOut, ref float power, Building building) + { + Dictionary dictionary = new Dictionary(); + List linkedFacilitiesListForReading = building.GetComp().LinkedFacilitiesListForReading; + for (int i = 0; i < linkedFacilitiesListForReading.Count; i++) + { + Thing thing = linkedFacilitiesListForReading[i]; + CompFacility compFacility = thing.TryGetComp(); + 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 item in dictionary) + { + powerFactorsOut?.Add(new QualityFactor + { + label = Find.ActiveLanguageWorker.Pluralize(item.Key.label).CapitalizeFirst(), + positive = true, + count = item.Value.count + " / " + item.Key.GetCompProperties().maxSimultaneous, + quality = item.Value.offset, + toolTip = "PsychicRitualDef_InvocationCircle_QualityFactor_Increase_Tooltip".Translate().CapitalizeFirst().EndWithPeriod() + }); + power += item.Value.offset; + } + } + + public override IEnumerable 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"))); + } + } + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse.AI.Group\PsychicRitualToil_GatherForInvocation.txt` +**相似度:** 0.7802 + +```csharp +public class PsychicRitualToil_GatherForInvocation : PsychicRitualToil_Multiplex +{ + protected PsychicRitualToil_Goto fallbackToil; + + protected PsychicRitualGraph invokerToil; + + protected PsychicRitualToil_Goto invokerFinalToil; + + private static List blockingPawns = new List(16); + + protected PsychicRitualToil_GatherForInvocation() + { + } + + protected PsychicRitualToil_GatherForInvocation(PsychicRitualDef_InvocationCircle def, PsychicRitualToil_Goto fallbackToil, PsychicRitualGraph invokerToil) + : base(new Dictionary { { def.InvokerRole, invokerToil } }, fallbackToil) + { + this.fallbackToil = fallbackToil; + this.invokerToil = invokerToil; + invokerFinalToil = (PsychicRitualToil_Goto)invokerToil.GetToil(invokerToil.ToilCount - 1); + } + + public PsychicRitualToil_GatherForInvocation(PsychicRitual psychicRitual, PsychicRitualDef_InvocationCircle def, IReadOnlyDictionary> rolePositions) + : this(def, FallbackToil(psychicRitual, def, rolePositions), InvokerToil(def, rolePositions)) + { + } + + public override void ExposeData() + { + base.ExposeData(); + Scribe_References.Look(ref fallbackToil, "fallbackToil"); + Scribe_References.Look(ref invokerToil, "invokerToil"); + Scribe_References.Look(ref invokerFinalToil, "invokerFinalToil"); + } + + public override string GetReport(PsychicRitual psychicRitual, PsychicRitualGraph parent) + { + blockingPawns.Clear(); + blockingPawns.AddRange(fallbackToil.BlockingPawns); + if (invokerToil.CurrentToil == invokerFinalToil) + { + blockingPawns.AddRange(invokerFinalToil.BlockingPawns); + } + else + { + blockingPawns.AddRange(invokerFinalToil.ControlledPawns(psychicRitual)); + } + string text = "PsychicRitualToil_GatherForInvocation_Report".Translate(); + string text2 = blockingPawns.Select((Pawn pawn) => pawn.LabelShortCap).ToCommaList(); + return text + ": " + text2; + } + + public static PsychicRitualToil_Goto FallbackToil(PsychicRitual psychicRitual, PsychicRitualDef_InvocationCircle def, IReadOnlyDictionary> rolePositions) + { + return new PsychicRitualToil_Goto(rolePositions.Slice(rolePositions.Keys.Except(def.InvokerRole))); + } + + public static PsychicRitualGraph InvokerToil(PsychicRitualDef_InvocationCircle def, IReadOnlyDictionary> rolePositions) + { + return new PsychicRitualGraph(InvokerGatherPhaseToils(def, rolePositions)) + { + willAdvancePastLastToil = false + }; + } + + public static IEnumerable InvokerGatherPhaseToils(PsychicRitualDef_InvocationCircle def, IReadOnlyDictionary> rolePositions) + { + if (def.RequiredOffering != null) + { + yield return new PsychicRitualToil_GatherOfferings(def.InvokerRole, def.RequiredOffering); + } + if (def.TargetRole != null) + { + yield return new PsychicRitualToil_CarryAndGoto(def.InvokerRole, def.TargetRole, rolePositions); + } + yield return new PsychicRitualToil_Goto(rolePositions.Slice(def.InvokerRole)); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\PsychicRitualDef_SkipAbduction.txt` +**相似度:** 0.7696 + +```csharp +public class PsychicRitualDef_SkipAbduction : PsychicRitualDef_InvocationCircle +{ + public override List CreateToils(PsychicRitual psychicRitual, PsychicRitualGraph graph) + { + List list = base.CreateToils(psychicRitual, graph); + list.Add(new PsychicRitualToil_SkipAbduction(InvokerRole)); + return list; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\PsychicRitualDef_BloodRain.txt` +**相似度:** 0.7621 + +```csharp +public class PsychicRitualDef_BloodRain : PsychicRitualDef_InvocationCircle +{ + private FloatRange durationHoursFromQualityRange; + + public override List CreateToils(PsychicRitual psychicRitual, PsychicRitualGraph graph) + { + List list = base.CreateToils(psychicRitual, graph); + list.Add(new PsychicRitualToil_BloodRain(InvokerRole, durationHoursFromQualityRange)); + return list; + } + + public override TaggedString OutcomeDescription(FloatRange qualityRange, string qualityNumber, PsychicRitualRoleAssignments assignments) + { + return outcomeDescription.Formatted(Mathf.FloorToInt(durationHoursFromQualityRange.LerpThroughRange(qualityRange.min) * 2500f).ToStringTicksToPeriod()); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\PsychicRitualDef_SummonFleshbeasts.txt` +**相似度:** 0.7620 + +```csharp +public class PsychicRitualDef_SummonFleshbeasts : PsychicRitualDef_InvocationCircle +{ + public SimpleCurve fleshbeastPointsFromThreatPointsCurve; + + public override List CreateToils(PsychicRitual psychicRitual, PsychicRitualGraph graph) + { + List list = base.CreateToils(psychicRitual, graph); + list.Add(new PsychicRitualToil_SummonFleshbeastsCultist(InvokerRole)); + return list; + } + + public override void CalculateMaxPower(PsychicRitualRoleAssignments assignments, List powerFactorsOut, out float power) + { + power = 0f; + if (assignments.FirstAssignedPawn(InvokerRole)?.GetLord()?.LordJob is LordJob_PsychicRitual lordJob_PsychicRitual) + { + power = Mathf.Max(power, lordJob_PsychicRitual.points); + } + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\PsychicRitualDef_SummonPitGate.txt` +**相似度:** 0.7581 + +```csharp +public class PsychicRitualDef_SummonPitGate : PsychicRitualDef_InvocationCircle +{ + private FloatRange combatPointMultiplierFromQualityRange; + + public override List CreateToils(PsychicRitual psychicRitual, PsychicRitualGraph graph) + { + List list = base.CreateToils(psychicRitual, graph); + list.Add(new PsychicRitualToil_SummonPitGate(InvokerRole, combatPointMultiplierFromQualityRange)); + return list; + } + + public override IEnumerable BlockingIssues(PsychicRitualRoleAssignments assignments, Map map) + { + foreach (string item in base.BlockingIssues(assignments, map)) + { + yield return item; + } + if (map.listerThings.ThingsOfDef(ThingDefOf.PitGate).Count > 0 || map.listerThings.ThingsOfDef(ThingDefOf.PitGateSpawner).Count > 0) + { + yield return "PitGateAlreadyExists".Translate(); + } + } +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/PsychicRitualToil_GatherForInvocation.txt b/MCP/vector_cache/PsychicRitualToil_GatherForInvocation.txt new file mode 100644 index 00000000..a0c2836b --- /dev/null +++ b/MCP/vector_cache/PsychicRitualToil_GatherForInvocation.txt @@ -0,0 +1,103 @@ +根据向量相似度分析,与 'PsychicRitualToil_GatherForInvocation' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse.AI.Group\PsychicRitualToil_GatherForInvocation.txt` + +```csharp +public class PsychicRitualToil_GatherForInvocation : PsychicRitualToil_Multiplex +{ + protected PsychicRitualToil_Goto fallbackToil; + + protected PsychicRitualGraph invokerToil; + + protected PsychicRitualToil_Goto invokerFinalToil; + + private static List blockingPawns = new List(16); + + protected PsychicRitualToil_GatherForInvocation() + { + } + + protected PsychicRitualToil_GatherForInvocation(PsychicRitualDef_InvocationCircle def, PsychicRitualToil_Goto fallbackToil, PsychicRitualGraph invokerToil) + : base(new Dictionary { { def.InvokerRole, invokerToil } }, fallbackToil) + { + this.fallbackToil = fallbackToil; + this.invokerToil = invokerToil; + invokerFinalToil = (PsychicRitualToil_Goto)invokerToil.GetToil(invokerToil.ToilCount - 1); + } + + public PsychicRitualToil_GatherForInvocation(PsychicRitual psychicRitual, PsychicRitualDef_InvocationCircle def, IReadOnlyDictionary> rolePositions) + : this(def, FallbackToil(psychicRitual, def, rolePositions), InvokerToil(def, rolePositions)) + { + } + + public override void ExposeData() + { + base.ExposeData(); + Scribe_References.Look(ref fallbackToil, "fallbackToil"); + Scribe_References.Look(ref invokerToil, "invokerToil"); + Scribe_References.Look(ref invokerFinalToil, "invokerFinalToil"); + } + + public override string GetReport(PsychicRitual psychicRitual, PsychicRitualGraph parent) + { + blockingPawns.Clear(); + blockingPawns.AddRange(fallbackToil.BlockingPawns); + if (invokerToil.CurrentToil == invokerFinalToil) + { + blockingPawns.AddRange(invokerFinalToil.BlockingPawns); + } + else + { + blockingPawns.AddRange(invokerFinalToil.ControlledPawns(psychicRitual)); + } + string text = "PsychicRitualToil_GatherForInvocation_Report".Translate(); + string text2 = blockingPawns.Select((Pawn pawn) => pawn.LabelShortCap).ToCommaList(); + return text + ": " + text2; + } + + public static PsychicRitualToil_Goto FallbackToil(PsychicRitual psychicRitual, PsychicRitualDef_InvocationCircle def, IReadOnlyDictionary> rolePositions) + { + return new PsychicRitualToil_Goto(rolePositions.Slice(rolePositions.Keys.Except(def.InvokerRole))); + } + + public static PsychicRitualGraph InvokerToil(PsychicRitualDef_InvocationCircle def, IReadOnlyDictionary> rolePositions) + { + return new PsychicRitualGraph(InvokerGatherPhaseToils(def, rolePositions)) + { + willAdvancePastLastToil = false + }; + } + + public static IEnumerable InvokerGatherPhaseToils(PsychicRitualDef_InvocationCircle def, IReadOnlyDictionary> rolePositions) + { + if (def.RequiredOffering != null) + { + yield return new PsychicRitualToil_GatherOfferings(def.InvokerRole, def.RequiredOffering); + } + if (def.TargetRole != null) + { + yield return new PsychicRitualToil_CarryAndGoto(def.InvokerRole, def.TargetRole, rolePositions); + } + yield return new PsychicRitualToil_Goto(rolePositions.Slice(def.InvokerRole)); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\PsychicRitualDef_InvocationCircle.txt` +**相似度:** 0.7275 + +```csharp + private class RitualQualityOffsetCount + { + public float offset; + + public int count; + + public RitualQualityOffsetCount(int count, float offset) + { + this.count = count; + this.offset = offset; + } + } +``` \ No newline at end of file diff --git a/MCP/vector_cache/PsychicRitualToil_GatherOfferings.txt b/MCP/vector_cache/PsychicRitualToil_GatherOfferings.txt new file mode 100644 index 00000000..f834d65e --- /dev/null +++ b/MCP/vector_cache/PsychicRitualToil_GatherOfferings.txt @@ -0,0 +1,270 @@ +根据向量相似度分析,与 'PsychicRitualToil_GatherOfferings' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse.AI.Group\PsychicRitualToil_GatherOfferings.txt` + +```csharp +public class PsychicRitualToil_GatherOfferings : PsychicRitualToil +{ + protected PsychicRitualRoleDef gathererRole; + + protected bool offeringsGathered; + + protected IngredientCount requiredOffering; + + protected PsychicRitualToil_GatherOfferings() + { + } + + public PsychicRitualToil_GatherOfferings(PsychicRitualRoleDef offeringGatherer, IngredientCount requiredOffering) + { + gathererRole = offeringGatherer; + this.requiredOffering = requiredOffering; + } + + public override void UpdateAllDuties(PsychicRitual psychicRitual, PsychicRitualGraph parent) + { + DutyDef def; + if (offeringsGathered || PawnsHaveOfferings(psychicRitual)) + { + offeringsGathered = true; + def = DutyDefOf.Idle; + } + else + { + def = DutyDefOf.GatherOfferingsForPsychicRitual; + } + foreach (Pawn item in psychicRitual.assignments.AssignedPawns(gathererRole)) + { + SetPawnDuty(item, psychicRitual, parent, def); + } + } + + public override bool Tick(PsychicRitual psychicRitual, PsychicRitualGraph parent) + { + return offeringsGathered; + } + + public override void ExposeData() + { + base.ExposeData(); + Scribe_Defs.Look(ref gathererRole, "gathererRole"); + Scribe_Values.Look(ref offeringsGathered, "offeringsGathered", defaultValue: false); + Scribe_Deep.Look(ref requiredOffering, "requiredOffering"); + } + + public static float PawnsOfferingCount(IEnumerable pawns, IngredientCount offering) + { + float num = 0f; + foreach (Pawn pawn in pawns) + { + foreach (Thing item in (IEnumerable)pawn.inventory.GetDirectlyHeldThings()) + { + if (offering.filter.Allows(item)) + { + num += (float)item.stackCount; + if (num >= offering.GetBaseCount()) + { + return offering.GetBaseCount(); + } + } + } + } + return num; + } + + private bool PawnsHaveOfferings(PsychicRitual psychicRitual) + { + float baseCount = requiredOffering.GetBaseCount(); + return PawnsOfferingCount(psychicRitual.assignments.AssignedPawns(gathererRole), requiredOffering) >= baseCount; + } + + public override void Notify_PawnJobDone(PsychicRitual psychicRitual, PsychicRitualGraph parent, Pawn pawn, Job job, JobCondition condition) + { + base.Notify_PawnJobDone(psychicRitual, parent, pawn, job, condition); + if (psychicRitual.assignments.RoleForPawn(pawn) == gathererRole && (offeringsGathered || PawnsHaveOfferings(psychicRitual))) + { + offeringsGathered = true; + SetPawnDuty(pawn, psychicRitual, parent, DutyDefOf.Idle); + } + } + + public override ThinkResult Notify_DutyResult(PsychicRitual psychicRitual, PsychicRitualGraph parent, ThinkResult result, Pawn pawn, JobIssueParams issueParams) + { + result = base.Notify_DutyResult(psychicRitual, parent, result, pawn, issueParams); + if (result.Job != null) + { + return result; + } + if (psychicRitual.assignments.RoleForPawn(pawn) != gathererRole) + { + return result; + } + if (offeringsGathered || PawnsHaveOfferings(psychicRitual)) + { + offeringsGathered = true; + SetPawnDuty(pawn, psychicRitual, parent, DutyDefOf.Idle); + return new ThinkResult(JobMaker.MakeJob(JobDefOf.Wait, 1), null); + } + TaggedString reason = "PsychicRitualToil_GatherOfferings_OfferingUnavailable".Translate(pawn.Named("PAWN"), requiredOffering.filter.Summary); + psychicRitual.LeaveOrCancelPsychicRitual(gathererRole, pawn, reason); + return result; + } + + public override string GetJobReport(PsychicRitual psychicRitual, PsychicRitualGraph parent, Pawn pawn) + { + if (psychicRitual.assignments.RoleForPawn(pawn) == gathererRole) + { + return "PsychicRitualToil_GatherOfferings_JobReport".Translate(); + } + return base.GetJobReport(psychicRitual, parent, pawn); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\JobGiver_GatherOfferingsForPsychicRitual.txt` +**相似度:** 0.8171 + +```csharp +public class JobGiver_GatherOfferingsForPsychicRitual : ThinkNode_JobGiver +{ + protected override Job TryGiveJob(Pawn pawn) + { + Lord lord = pawn.GetLord(); + if (lord == null) + { + return null; + } + if (!(lord.CurLordToil is LordToil_PsychicRitual lordToil_PsychicRitual)) + { + return null; + } + PsychicRitualDef def = lordToil_PsychicRitual.RitualData.psychicRitual.def; + PsychicRitualDef_InvocationCircle ritualDef = def as PsychicRitualDef_InvocationCircle; + if (ritualDef == null) + { + return null; + } + if (ritualDef.RequiredOffering == null) + { + return null; + } + PsychicRitual psychicRitual = lordToil_PsychicRitual.RitualData.psychicRitual; + PsychicRitualRoleDef psychicRitualRoleDef = psychicRitual.assignments.RoleForPawn(pawn); + if (psychicRitualRoleDef == null) + { + return null; + } + float num = PsychicRitualToil_GatherOfferings.PawnsOfferingCount(psychicRitual.assignments.AssignedPawns(psychicRitualRoleDef), ritualDef.RequiredOffering); + int needed = Mathf.CeilToInt(ritualDef.RequiredOffering.GetBaseCount() - num); + if (needed == 0) + { + return null; + } + Thing thing2 = GenClosest.ClosestThingReachable(pawn.PositionHeld, pawn.MapHeld, ThingRequest.ForGroup(ThingRequestGroup.HaulableAlways), PathEndMode.Touch, TraverseParms.For(pawn), 9999f, delegate(Thing thing) + { + if (!ritualDef.RequiredOffering.filter.Allows(thing)) + { + return false; + } + if (thing.IsForbidden(pawn)) + { + return false; + } + int stackCount = Mathf.Min(needed, thing.stackCount); + return pawn.CanReserve(thing, 10, stackCount) ? true : false; + }); + if (thing2 == null) + { + return null; + } + Job job = JobMaker.MakeJob(JobDefOf.TakeCountToInventory, thing2); + job.count = Mathf.Min(needed, thing2.stackCount); + return job; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse.AI.Group\PsychicRitualToil_GatherForInvocation.txt` +**相似度:** 0.7774 + +```csharp +public class PsychicRitualToil_GatherForInvocation : PsychicRitualToil_Multiplex +{ + protected PsychicRitualToil_Goto fallbackToil; + + protected PsychicRitualGraph invokerToil; + + protected PsychicRitualToil_Goto invokerFinalToil; + + private static List blockingPawns = new List(16); + + protected PsychicRitualToil_GatherForInvocation() + { + } + + protected PsychicRitualToil_GatherForInvocation(PsychicRitualDef_InvocationCircle def, PsychicRitualToil_Goto fallbackToil, PsychicRitualGraph invokerToil) + : base(new Dictionary { { def.InvokerRole, invokerToil } }, fallbackToil) + { + this.fallbackToil = fallbackToil; + this.invokerToil = invokerToil; + invokerFinalToil = (PsychicRitualToil_Goto)invokerToil.GetToil(invokerToil.ToilCount - 1); + } + + public PsychicRitualToil_GatherForInvocation(PsychicRitual psychicRitual, PsychicRitualDef_InvocationCircle def, IReadOnlyDictionary> rolePositions) + : this(def, FallbackToil(psychicRitual, def, rolePositions), InvokerToil(def, rolePositions)) + { + } + + public override void ExposeData() + { + base.ExposeData(); + Scribe_References.Look(ref fallbackToil, "fallbackToil"); + Scribe_References.Look(ref invokerToil, "invokerToil"); + Scribe_References.Look(ref invokerFinalToil, "invokerFinalToil"); + } + + public override string GetReport(PsychicRitual psychicRitual, PsychicRitualGraph parent) + { + blockingPawns.Clear(); + blockingPawns.AddRange(fallbackToil.BlockingPawns); + if (invokerToil.CurrentToil == invokerFinalToil) + { + blockingPawns.AddRange(invokerFinalToil.BlockingPawns); + } + else + { + blockingPawns.AddRange(invokerFinalToil.ControlledPawns(psychicRitual)); + } + string text = "PsychicRitualToil_GatherForInvocation_Report".Translate(); + string text2 = blockingPawns.Select((Pawn pawn) => pawn.LabelShortCap).ToCommaList(); + return text + ": " + text2; + } + + public static PsychicRitualToil_Goto FallbackToil(PsychicRitual psychicRitual, PsychicRitualDef_InvocationCircle def, IReadOnlyDictionary> rolePositions) + { + return new PsychicRitualToil_Goto(rolePositions.Slice(rolePositions.Keys.Except(def.InvokerRole))); + } + + public static PsychicRitualGraph InvokerToil(PsychicRitualDef_InvocationCircle def, IReadOnlyDictionary> rolePositions) + { + return new PsychicRitualGraph(InvokerGatherPhaseToils(def, rolePositions)) + { + willAdvancePastLastToil = false + }; + } + + public static IEnumerable InvokerGatherPhaseToils(PsychicRitualDef_InvocationCircle def, IReadOnlyDictionary> rolePositions) + { + if (def.RequiredOffering != null) + { + yield return new PsychicRitualToil_GatherOfferings(def.InvokerRole, def.RequiredOffering); + } + if (def.TargetRole != null) + { + yield return new PsychicRitualToil_CarryAndGoto(def.InvokerRole, def.TargetRole, rolePositions); + } + yield return new PsychicRitualToil_Goto(rolePositions.Slice(def.InvokerRole)); + } +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/Source-StartCarryThing-Toil-Toils_Haul.txt b/MCP/vector_cache/Source-StartCarryThing-Toil-Toils_Haul.txt new file mode 100644 index 00000000..cca8869f --- /dev/null +++ b/MCP/vector_cache/Source-StartCarryThing-Toil-Toils_Haul.txt @@ -0,0 +1,1333 @@ +根据向量相似度分析,与 'Source, Toils_Haul, StartCarryThing, Toil' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse.AI\Toils_Haul.txt` + +```csharp +public class Toils_Haul +{ + public static bool ErrorCheckForCarry(Pawn pawn, Thing haulThing, bool canTakeFromInventory = false) + { + if (!haulThing.SpawnedOrAnyParentSpawned || (!canTakeFromInventory && !haulThing.Spawned)) + { + Log.Message(pawn?.ToString() + " tried to start carry " + haulThing?.ToString() + " which isn't spawned."); + pawn.jobs.EndCurrentJob(JobCondition.Incompletable); + return true; + } + if (haulThing.stackCount == 0) + { + Log.Message(pawn?.ToString() + " tried to start carry " + haulThing?.ToString() + " which had stackcount 0."); + pawn.jobs.EndCurrentJob(JobCondition.Incompletable); + return true; + } + if (pawn.jobs.curJob.count <= 0) + { + Log.Error("Invalid count: " + pawn.jobs.curJob.count + ", setting to 1. Job was " + pawn.jobs.curJob); + pawn.jobs.curJob.count = 1; + } + return false; + } + + public static Toil StartCarryThing(TargetIndex haulableInd, bool putRemainderInQueue = false, bool subtractNumTakenFromJobCount = false, bool failIfStackCountLessThanJobCount = false, bool reserve = true, bool canTakeFromInventory = false) + { + Toil toil = ToilMaker.MakeToil("StartCarryThing"); + toil.initAction = delegate + { + Pawn actor = toil.actor; + Job curJob = actor.jobs.curJob; + Thing thing = curJob.GetTarget(haulableInd).Thing; + if (!ErrorCheckForCarry(actor, thing, canTakeFromInventory)) + { + if (curJob.count == 0) + { + throw new Exception($"StartCarryThing job had count = {curJob.count}. Job: {curJob}"); + } + int num = actor.carryTracker.AvailableStackSpace(thing.def); + if (num <= 0) + { + int num2 = actor.carryTracker.MaxStackSpaceEver(thing.def); + int num3 = 0; + if (actor.carryTracker.CarriedThing != null) + { + num3 = actor.carryTracker.CarriedThing.stackCount; + } + throw new Exception($"StartCarryThing got availableStackSpace {num} (haulTarg {thing}, Job: {curJob}, maximum: {num2}, carrying: {num3})"); + } + if (failIfStackCountLessThanJobCount && thing.stackCount < curJob.count) + { + actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable); + } + else + { + int num4 = Mathf.Min(curJob.count, num, thing.stackCount); + if (num4 <= 0) + { + int num5 = actor.carryTracker.MaxStackSpaceEver(thing.def); + int num6 = 0; + if (actor.carryTracker.CarriedThing != null) + { + num6 = actor.carryTracker.CarriedThing.stackCount; + } + throw new Exception($"StartCarryThing zero or negative desiredNumToTake ({num4}), curJob.count: {curJob.count}, availableStackSpace: {num} (maximum: {num5}, carrying: {num6}), haulTarg.stackCount: {thing.stackCount}"); + } + int stackCount = thing.stackCount; + int num7 = actor.carryTracker.TryStartCarry(thing, num4, reserve); + if (num7 == 0) + { + actor.jobs.EndCurrentJob(JobCondition.Incompletable); + } + if (num7 < stackCount) + { + int num8 = curJob.count - num7; + if (putRemainderInQueue && num8 > 0) + { + curJob.GetTargetQueue(haulableInd).Insert(0, thing); + Job job = curJob; + if (job.countQueue == null) + { + job.countQueue = new List(); + } + curJob.countQueue.Insert(0, num8); + } + else if (actor.Map.reservationManager.ReservedBy(thing, actor, curJob)) + { + actor.Map.reservationManager.Release(thing, actor, curJob); + } + } + if (subtractNumTakenFromJobCount) + { + curJob.count -= num7; + } + curJob.SetTarget(haulableInd, actor.carryTracker.CarriedThing); + actor.records.Increment(RecordDefOf.ThingsHauled); + } + } + }; + return toil; + } + + public static Toil StoreThingJob(TargetIndex thingIndex) + { + Toil toil = ToilMaker.MakeToil("StoreThingJob"); + toil.initAction = delegate + { + Pawn actor = toil.actor; + Job curJob = actor.CurJob; + Thing thing = curJob.GetTarget(thingIndex).Thing; + Job job = HaulAIUtility.HaulToStorageJob(actor, thing, curJob.playerForced); + if (job != null) + { + actor.jobs.TryTakeOrderedJob(job, JobTag.Misc); + } + }; + return toil; + } + + public static Toil DropCarriedThing() + { + Toil toil = ToilMaker.MakeToil("DropCarriedThing"); + toil.initAction = delegate + { + Pawn actor = toil.actor; + Thing resultingThing; + if (actor.carryTracker.CarriedThing == null) + { + Log.Error(actor?.ToString() + " tried to drop carried thing but is not carrying anything."); + } + else if (!actor.carryTracker.TryDropCarriedThing(actor.Position, ThingPlaceMode.Direct, out resultingThing)) + { + actor.jobs.EndCurrentJob(JobCondition.Incompletable); + } + }; + return toil; + } + + public static Toil JumpIfAlsoCollectingNextTargetInQueue(Toil gotoGetTargetToil, TargetIndex ind) + { + Toil toil = ToilMaker.MakeToil("JumpIfAlsoCollectingNextTargetInQueue"); + toil.initAction = delegate + { + Pawn actor = toil.actor; + Job curJob = actor.jobs.curJob; + List targetQueue = curJob.GetTargetQueue(ind); + if (!targetQueue.NullOrEmpty() && curJob.count > 0) + { + if (actor.carryTracker.CarriedThing == null) + { + Log.Error("JumpToAlsoCollectTargetInQueue run on " + actor?.ToString() + " who is not carrying something."); + } + else if (actor.carryTracker.AvailableStackSpace(actor.carryTracker.CarriedThing.def) > 0) + { + for (int i = 0; i < targetQueue.Count; i++) + { + if (!GenAI.CanUseItemForWork(actor, targetQueue[i].Thing)) + { + actor.jobs.EndCurrentJob(JobCondition.Incompletable); + break; + } + if (targetQueue[i].Thing.def == actor.carryTracker.CarriedThing.def) + { + curJob.SetTarget(ind, targetQueue[i].Thing); + targetQueue.RemoveAt(i); + actor.jobs.curDriver.JumpToToil(gotoGetTargetToil); + break; + } + } + } + } + }; + return toil; + } + + public static Toil CheckForGetOpportunityDuplicate(Toil getHaulTargetToil, TargetIndex haulableInd, TargetIndex storeCellInd, bool takeFromValidStorage = false, Predicate extraValidator = null) + { + Toil toil = ToilMaker.MakeToil("CheckForGetOpportunityDuplicate"); + toil.initAction = delegate + { + Pawn actor = toil.actor; + Job curJob = actor.jobs.curJob; + if (actor.carryTracker.CarriedThing.def.stackLimit != 1 && !actor.carryTracker.Full && curJob.count > 0) + { + Thing thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableAlways), PathEndMode.ClosestTouch, TraverseParms.For(actor), 8f, DupeValidator); + if (thing != null) + { + curJob.SetTarget(haulableInd, thing); + actor.jobs.curDriver.JumpToToil(getHaulTargetToil); + } + } + bool DupeValidator(Thing t) + { + if (!t.Spawned) + { + return false; + } + if (t.def != actor.carryTracker.CarriedThing.def) + { + return false; + } + if (!t.CanStackWith(actor.carryTracker.CarriedThing)) + { + return false; + } + if (t.IsForbidden(actor)) + { + return false; + } + if (!t.IsSociallyProper(actor, forPrisoner: false, animalsCare: true)) + { + return false; + } + if (takeFromValidStorage && storeCellInd != 0 && curJob.GetTarget(storeCellInd).Cell.TryGetSlotGroup(actor.Map, out var group) && t.TryGetValidStoragePriority(out var priority) && (int)priority >= (int)group.Settings.Priority) + { + return false; + } + if (storeCellInd != 0 && !curJob.GetTarget(storeCellInd).Cell.IsValidStorageFor(actor.Map, t)) + { + return false; + } + if (!actor.CanReserve(t)) + { + return false; + } + if (extraValidator != null && !extraValidator(t)) + { + return false; + } + return true; + } + }; + return toil; + } + + public static Toil CarryHauledThingToCell(TargetIndex squareIndex, PathEndMode pathEndMode = PathEndMode.ClosestTouch) + { + Toil toil = ToilMaker.MakeToil("CarryHauledThingToCell"); + toil.initAction = delegate + { + IntVec3 cell3 = toil.actor.jobs.curJob.GetTarget(squareIndex).Cell; + toil.actor.pather.StartPath(cell3, pathEndMode); + }; + toil.defaultCompleteMode = ToilCompleteMode.PatherArrival; + toil.AddEndCondition(delegate + { + Pawn actor2 = toil.actor; + IntVec3 cell2 = actor2.jobs.curJob.GetTarget(squareIndex).Cell; + CompPushable compPushable2 = actor2.carryTracker.CarriedThing.TryGetComp(); + if (compPushable2 != null) + { + Vector3 v = actor2.Position.ToVector3() + compPushable2.drawPos; + if (new IntVec3(v) == cell2) + { + return JobCondition.Succeeded; + } + } + return JobCondition.Ongoing; + }); + toil.AddFailCondition(delegate + { + Pawn actor = toil.actor; + IntVec3 cell = actor.jobs.curJob.GetTarget(squareIndex).Cell; + if (actor.carryTracker.CarriedThing == null) + { + return true; + } + if (actor.jobs.curJob.haulMode == HaulMode.ToCellStorage && !cell.IsValidStorageFor(actor.Map, actor.carryTracker.CarriedThing)) + { + return true; + } + CompPushable compPushable = actor.carryTracker.CarriedThing.TryGetComp(); + return (compPushable != null && !compPushable.canBePushed) ? true : false; + }); + return toil; + } + + public static Toil PlaceCarriedThingInCellFacing(TargetIndex facingTargetInd) + { + Toil toil = ToilMaker.MakeToil("PlaceCarriedThingInCellFacing"); + toil.initAction = delegate + { + Pawn actor = toil.actor; + if (actor.carryTracker.CarriedThing == null) + { + Log.Error(actor?.ToString() + " tried to place hauled thing in facing cell but is not hauling anything."); + } + else + { + LocalTargetInfo target = actor.CurJob.GetTarget(facingTargetInd); + IntVec3 intVec = ((!target.HasThing) ? target.Cell : target.Thing.OccupiedRect().ClosestCellTo(actor.Position)); + IntVec3 dropLoc = actor.Position + Pawn_RotationTracker.RotFromAngleBiased((actor.Position - intVec).AngleFlat).FacingCell; + if (!actor.carryTracker.TryDropCarriedThing(dropLoc, ThingPlaceMode.Direct, out var _)) + { + actor.jobs.EndCurrentJob(JobCondition.Incompletable); + } + } + }; + return toil; + } + + public static Toil PlaceHauledThingInCell(TargetIndex cellInd, Toil nextToilOnPlaceFailOrIncomplete, bool storageMode, bool tryStoreInSameStorageIfSpotCantHoldWholeStack = false) + { + Toil toil = ToilMaker.MakeToil("PlaceHauledThingInCell"); + toil.initAction = delegate + { + Pawn actor = toil.actor; + Job curJob = actor.jobs.curJob; + IntVec3 cell = curJob.GetTarget(cellInd).Cell; + if (actor.carryTracker.CarriedThing == null) + { + Log.Error(actor?.ToString() + " tried to place hauled thing in cell but is not hauling anything."); + } + else + { + SlotGroup slotGroup = actor.Map.haulDestinationManager.SlotGroupAt(cell); + if (slotGroup != null && slotGroup.Settings.AllowedToAccept(actor.carryTracker.CarriedThing)) + { + actor.Map.designationManager.TryRemoveDesignationOn(actor.carryTracker.CarriedThing, DesignationDefOf.Haul); + } + Action placedAction = null; + if (curJob.def == JobDefOf.DoBill || curJob.def == JobDefOf.RecolorApparel || curJob.def == JobDefOf.RefuelAtomic || curJob.def == JobDefOf.RearmTurretAtomic) + { + placedAction = delegate(Thing th, int added) + { + HaulAIUtility.UpdateJobWithPlacedThings(curJob, th, added); + }; + } + if (!actor.carryTracker.TryDropCarriedThing(cell, ThingPlaceMode.Direct, out var _, placedAction)) + { + if (storageMode) + { + IntVec3 storeCell; + if (nextToilOnPlaceFailOrIncomplete != null && ((tryStoreInSameStorageIfSpotCantHoldWholeStack && StoreUtility.TryFindBestBetterStoreCellForIn(actor.carryTracker.CarriedThing, actor, actor.Map, StoragePriority.Unstored, actor.Faction, curJob.bill.GetSlotGroup(), out var foundCell)) || StoreUtility.TryFindBestBetterStoreCellFor(actor.carryTracker.CarriedThing, actor, actor.Map, StoragePriority.Unstored, actor.Faction, out foundCell))) + { + if (actor.CanReserve(foundCell)) + { + actor.Reserve(foundCell, actor.CurJob); + } + actor.CurJob.SetTarget(cellInd, foundCell); + actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete); + } + else if (HaulAIUtility.CanHaulAside(actor, actor.carryTracker.CarriedThing, out storeCell)) + { + curJob.SetTarget(cellInd, storeCell); + curJob.count = int.MaxValue; + curJob.haulOpportunisticDuplicates = false; + curJob.haulMode = HaulMode.ToCellNonStorage; + if (nextToilOnPlaceFailOrIncomplete != null) + { + actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete); + } + } + else + { + Log.Warning($"Incomplete haul for {actor}: Could not find anywhere to put {actor.carryTracker.CarriedThing} near {actor.Position}. Destroying. This should be very uncommon!"); + actor.carryTracker.CarriedThing.Destroy(); + } + } + else if (nextToilOnPlaceFailOrIncomplete != null) + { + actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete); + } + } + } + }; + return toil; + } + + public static Toil CarryHauledThingToContainer() + { + Toil gotoDest = ToilMaker.MakeToil("CarryHauledThingToContainer"); + gotoDest.initAction = delegate + { + gotoDest.actor.pather.StartPath(gotoDest.actor.jobs.curJob.targetB.Thing, PathEndMode.Touch); + }; + gotoDest.AddFailCondition(delegate + { + Thing thing = gotoDest.actor.jobs.curJob.targetB.Thing; + if (thing.Destroyed || (!gotoDest.actor.jobs.curJob.ignoreForbidden && thing.IsForbidden(gotoDest.actor))) + { + return true; + } + ThingOwner thingOwner = thing.TryGetInnerInteractableThingOwner(); + return (thingOwner != null && !thingOwner.CanAcceptAnyOf(gotoDest.actor.carryTracker.CarriedThing)) ? true : false; + }); + gotoDest.defaultCompleteMode = ToilCompleteMode.PatherArrival; + return gotoDest; + } + + public static Toil DepositHauledThingInContainer(TargetIndex containerInd, TargetIndex reserveForContainerInd, Action onDeposited = null) + { + Toil toil = ToilMaker.MakeToil("DepositHauledThingInContainer"); + toil.initAction = delegate + { + Pawn actor = toil.actor; + Job curJob = actor.jobs.curJob; + if (actor.carryTracker.CarriedThing == null) + { + Log.Error(actor?.ToString() + " tried to place hauled thing in container but is not hauling anything."); + } + else + { + Thing thing = curJob.GetTarget(containerInd).Thing; + ThingOwner thingOwner = thing.TryGetInnerInteractableThingOwner(); + if (thingOwner != null) + { + int num = actor.carryTracker.CarriedThing.stackCount; + if (thing is IHaulEnroute haulEnroute) + { + ThingDef def = actor.carryTracker.CarriedThing.def; + num = Mathf.Min(haulEnroute.GetSpaceRemainingWithEnroute(def, actor), num); + if (reserveForContainerInd != 0) + { + Thing thing2 = curJob.GetTarget(reserveForContainerInd).Thing; + if (!thing2.DestroyedOrNull() && thing2 != haulEnroute && thing2 is IHaulEnroute enroute) + { + int spaceRemainingWithEnroute = enroute.GetSpaceRemainingWithEnroute(def, actor); + num = Mathf.Min(num, actor.carryTracker.CarriedThing.stackCount - spaceRemainingWithEnroute); + } + } + } + Thing carriedThing = actor.carryTracker.CarriedThing; + int num2 = actor.carryTracker.innerContainer.TryTransferToContainer(carriedThing, thingOwner, num); + if (num2 != 0) + { + if (thing is IHaulEnroute container) + { + thing.Map.enrouteManager.ReleaseFor(container, actor); + } + if (thing is INotifyHauledTo notifyHauledTo) + { + notifyHauledTo.Notify_HauledTo(actor, carriedThing, num2); + } + if (thing is ThingWithComps thingWithComps) + { + foreach (ThingComp allComp in thingWithComps.AllComps) + { + if (allComp is INotifyHauledTo notifyHauledTo2) + { + notifyHauledTo2.Notify_HauledTo(actor, carriedThing, num2); + } + } + } + if (curJob.def == JobDefOf.DoBill) + { + HaulAIUtility.UpdateJobWithPlacedThings(curJob, carriedThing, num2); + } + onDeposited?.Invoke(); + } + } + else if (curJob.GetTarget(containerInd).Thing.def.Minifiable) + { + actor.carryTracker.innerContainer.ClearAndDestroyContents(); + } + else + { + Log.Error("Could not deposit hauled thing in container: " + curJob.GetTarget(containerInd).Thing); + } + } + }; + return toil; + } + + public static Toil JumpToCarryToNextContainerIfPossible(Toil carryToContainerToil, TargetIndex primaryTargetInd) + { + Toil toil = ToilMaker.MakeToil("JumpToCarryToNextContainerIfPossible"); + toil.debugName = "Jump carry if possible"; + toil.initAction = delegate + { + Pawn actor = toil.actor; + Job curJob = actor.jobs.curJob; + if (actor.carryTracker.CarriedThing != null && curJob.targetQueueB != null && curJob.targetQueueB.Count > 0) + { + if (TryGetNextDestinationFromQueue(primaryTargetInd, TargetIndex.B, actor.carryTracker.CarriedThing.def, curJob, actor, out var nextTarget)) + { + curJob.targetQueueB.RemoveAll((LocalTargetInfo target) => target.Thing == nextTarget); + curJob.targetB = nextTarget; + curJob.targetC = nextTarget; + actor.jobs.curDriver.JumpToToil(carryToContainerToil); + } + } + }; + return toil; + } + + public static bool TryGetNextDestinationFromQueue(TargetIndex primaryIndex, TargetIndex destIndex, ThingDef stuff, Job job, Pawn actor, out Thing target) + { + Thing primaryTarget = job.GetTarget(primaryIndex).Thing; + target = null; + if (actor.carryTracker?.CarriedThing == null) + { + return false; + } + bool hasSpareItems = actor.carryTracker.CarriedThing.stackCount > 0; + if (primaryTarget != null && primaryTarget.Spawned && primaryTarget is IHaulEnroute enroute) + { + int spaceRemainingWithEnroute = enroute.GetSpaceRemainingWithEnroute(stuff, actor); + hasSpareItems = actor.carryTracker.CarriedThing.stackCount > spaceRemainingWithEnroute; + } + target = GenClosest.ClosestThing_Global_Reachable(actor.Position, actor.Map, from x in job.GetTargetQueue(destIndex) + select x.Thing, PathEndMode.Touch, TraverseParms.For(actor), 99999f, Validator); + return target != null; + bool Validator(Thing th) + { + if (!(th is IHaulEnroute enroute2)) + { + return false; + } + if (enroute2.GetSpaceRemainingWithEnroute(stuff, actor) <= 0) + { + return false; + } + if (th != primaryTarget && !hasSpareItems) + { + return false; + } + return true; + } + } + + public static Toil TakeToInventory(TargetIndex ind, int count) + { + return TakeToInventory(ind, count, null, null); + } + + private static Toil TakeToInventory(TargetIndex ind, int? count, Func countGetter, Func countGetterPassingThing) + { + Toil takeThing = ToilMaker.MakeToil("TakeToInventory"); + takeThing.initAction = delegate + { + Pawn actor = takeThing.actor; + Thing thing = actor.CurJob.GetTarget(ind).Thing; + if (!ErrorCheckForCarry(actor, thing)) + { + int num = Mathf.Min(count ?? countGetterPassingThing?.Invoke(thing) ?? countGetter(), thing.stackCount); + if (actor.CurJob.checkEncumbrance) + { + num = Math.Min(num, MassUtility.CountToPickUpUntilOverEncumbered(actor, thing)); + } + if (num <= 0) + { + actor.jobs.curDriver.ReadyForNextToil(); + } + else + { + actor.inventory.GetDirectlyHeldThings().TryAdd(thing.SplitOff(num)); + if (thing.def.ingestible != null && (int)thing.def.ingestible.preferability <= 5) + { + actor.mindState.lastInventoryRawFoodUseTick = Find.TickManager.TicksGame; + } + thing.def.soundPickup.PlayOneShot(new TargetInfo(actor.Position, actor.Map)); + } + } + }; + return takeThing; + } + + public static Toil TakeToInventory(TargetIndex ind, Func countGetter) + { + return TakeToInventory(ind, null, countGetter, null); + } + + public static Toil TakeToInventory(TargetIndex ind, Func countGetter) + { + return TakeToInventory(ind, null, null, countGetter); + } + + public static Toil TakeFromOtherInventory(Thing item, ThingOwner taker, ThingOwner holder, int count = -1, TargetIndex indexToSet = TargetIndex.None) + { + Toil toil = ToilMaker.MakeToil("TakeFromOtherInventory"); + toil.initAction = delegate + { + if (!holder.Contains(item)) + { + toil.actor.jobs.EndCurrentJob(JobCondition.Incompletable); + } + else + { + count = ((count < 0) ? toil.actor.jobs.curJob.count : count); + holder.TryTransferToContainer(item, taker, Mathf.Min(item.stackCount, count), out var resultingTransferredItem); + if (resultingTransferredItem == null) + { + Log.Warning($"Taker {toil.actor.Label} unable to take count {count} of thing {item.Label} from holder's inventory"); + toil.actor.jobs.EndCurrentJob(JobCondition.Incompletable); + } + else if (indexToSet != 0) + { + toil.actor.jobs.curJob.SetTarget(indexToSet, resultingTransferredItem); + } + } + }; + return toil; + } + + public static Toil CheckItemCarriedByOtherPawn(Thing item, TargetIndex targetPawnIfCarried = TargetIndex.None, Toil jumpIfCarriedByOther = null) + { + Toil toil = ToilMaker.MakeToil("CheckItemCarriedByOtherPawn"); + toil.initAction = delegate + { + Pawn pawn = (item?.ParentHolder as Pawn_InventoryTracker)?.pawn; + if (pawn != null && pawn != toil.actor) + { + if (targetPawnIfCarried != 0) + { + toil.actor.jobs.curJob.SetTarget(targetPawnIfCarried, pawn); + } + if (jumpIfCarriedByOther != null) + { + toil.actor.jobs.curDriver.JumpToToil(jumpIfCarriedByOther); + } + } + }; + toil.defaultCompleteMode = ToilCompleteMode.Instant; + toil.atomicWithPrevious = true; + return toil; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse.AI\JobDriver_HaulToContainer.txt` +**相似度:** 0.6036 + +```csharp +public class JobDriver_HaulToContainer : JobDriver, IBuildableDriver +{ + private Effecter graveDigEffect; + + protected const TargetIndex CarryThingIndex = TargetIndex.A; + + public const TargetIndex DestIndex = TargetIndex.B; + + protected const TargetIndex PrimaryDestIndex = TargetIndex.C; + + protected const int DiggingEffectInterval = 80; + + public Thing ThingToCarry => (Thing)job.GetTarget(TargetIndex.A); + + public Thing Container => (Thing)job.GetTarget(TargetIndex.B); + + public ThingDef ThingDef => ThingToCarry.def; + + protected virtual int Duration + { + get + { + if (Container == null || !(Container is Building building)) + { + return 0; + } + return building.HaulToContainerDuration(ThingToCarry); + } + } + + protected virtual EffecterDef WorkEffecter => null; + + protected virtual SoundDef WorkSustainer => null; + + public bool TryGetBuildableRect(out CellRect rect) + { + if (Container is Blueprint) + { + rect = Container.OccupiedRect(); + return true; + } + rect = default(CellRect); + return false; + } + + public override string GetReport() + { + Thing thing = ((pawn.CurJob != job || pawn.carryTracker.CarriedThing == null) ? base.TargetThingA : pawn.carryTracker.CarriedThing); + if (thing == null || !job.targetB.HasThing) + { + return "ReportHaulingUnknown".Translate(); + } + return ((job.GetTarget(TargetIndex.B).Thing is Building_Grave) ? "ReportHaulingToGrave" : "ReportHaulingTo").Translate(thing.Label, job.targetB.Thing.LabelShort.Named("DESTINATION"), thing.Named("THING")); + } + + public override bool TryMakePreToilReservations(bool errorOnFailed) + { + if (!pawn.Reserve(job.GetTarget(TargetIndex.A), job, 1, -1, null, errorOnFailed)) + { + return false; + } + if (Container.Isnt()) + { + if (!pawn.Reserve(job.GetTarget(TargetIndex.B), job, 1, 1, null, errorOnFailed)) + { + return false; + } + pawn.ReserveAsManyAsPossible(job.GetTargetQueue(TargetIndex.B), job); + } + UpdateEnrouteTrackers(); + pawn.ReserveAsManyAsPossible(job.GetTargetQueue(TargetIndex.A), job); + return true; + } + + protected virtual void ModifyPrepareToil(Toil toil) + { + } + + private bool TryReplaceWithFrame(TargetIndex index) + { + Thing thing = GetActor().jobs.curJob.GetTarget(index).Thing; + Building edifice = thing.Position.GetEdifice(pawn.Map); + if (edifice != null && thing is Blueprint_Build blueprint_Build && edifice is Frame frame && frame.BuildDef == blueprint_Build.BuildDef) + { + job.SetTarget(TargetIndex.B, frame); + return true; + } + return false; + } + + protected override IEnumerable MakeNewToils() + { + this.FailOnDestroyedOrNull(TargetIndex.A); + this.FailOn(delegate + { + Thing thing = GetActor().jobs.curJob.GetTarget(TargetIndex.B).Thing; + Thing thing2 = GetActor().jobs.curJob.GetTarget(TargetIndex.C).Thing; + if (thing == null) + { + return true; + } + if (thing2 != null && thing2.Destroyed && !TryReplaceWithFrame(TargetIndex.C)) + { + job.SetTarget(TargetIndex.C, null); + } + if (!thing.Spawned || (thing.Destroyed && !TryReplaceWithFrame(TargetIndex.B))) + { + if (job.targetQueueB.NullOrEmpty()) + { + return true; + } + if (!Toils_Haul.TryGetNextDestinationFromQueue(TargetIndex.C, TargetIndex.B, ThingDef, job, pawn, out var nextTarget)) + { + return true; + } + job.targetQueueB.RemoveAll((LocalTargetInfo target) => target.Thing == nextTarget); + job.targetB = nextTarget; + } + ThingOwner thingOwner = Container.TryGetInnerInteractableThingOwner(); + if (thingOwner != null && !thingOwner.CanAcceptAnyOf(ThingToCarry)) + { + return true; + } + return (Container is IHaulDestination haulDestination && !haulDestination.Accepts(ThingToCarry)) ? true : false; + }); + this.FailOnForbidden(TargetIndex.B); + this.FailOn(() => EnterPortalUtility.WasLoadingCanceled(Container)); + this.FailOn(() => TransporterUtility.WasLoadingCanceled(Container)); + this.FailOn(() => CompBiosculpterPod.WasLoadingCanceled(Container)); + this.FailOn(() => Building_SubcoreScanner.WasLoadingCancelled(Container)); + Toil getToHaulTarget = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch, canGotoSpawnedParent: true).FailOn(() => ThingToCarry.ParentHolder is MinifiedThing).FailOnSelfAndParentsDespawnedOrNull(TargetIndex.A); + Toil uninstallIfMinifiable = Toils_Construct.UninstallIfMinifiable(TargetIndex.A).FailOnSomeonePhysicallyInteracting(TargetIndex.A).FailOn(() => ThingToCarry.ParentHolder is MinifiedThing) + .FailOnSelfAndParentsDespawnedOrNull(TargetIndex.A) + .FailOnDestroyedOrNull(TargetIndex.A); + Toil startCarryingThing = Toils_Haul.StartCarryThing(TargetIndex.A, putRemainderInQueue: false, subtractNumTakenFromJobCount: true, failIfStackCountLessThanJobCount: false, reserve: true, canTakeFromInventory: true); + Toil jumpIfAlsoCollectingNextTarget = Toils_Haul.JumpIfAlsoCollectingNextTargetInQueue(getToHaulTarget, TargetIndex.A); + Toil carryToContainer = Toils_Haul.CarryHauledThingToContainer(); + yield return Toils_Jump.JumpIf(jumpIfAlsoCollectingNextTarget, () => pawn.IsCarryingThing(ThingToCarry)); + yield return getToHaulTarget; + yield return uninstallIfMinifiable; + yield return startCarryingThing; + yield return jumpIfAlsoCollectingNextTarget; + yield return carryToContainer; + yield return Toils_Goto.MoveOffTargetBlueprint(TargetIndex.B); + Toil toil = Toils_General.Wait(Duration, TargetIndex.B); + toil.WithProgressBarToilDelay(TargetIndex.B); + EffecterDef workEffecter = WorkEffecter; + if (workEffecter != null) + { + toil.WithEffect(workEffecter, TargetIndex.B); + } + SoundDef workSustainer = WorkSustainer; + if (workSustainer != null) + { + toil.PlaySustainerOrSound(workSustainer); + } + Thing destThing = job.GetTarget(TargetIndex.B).Thing; + toil.tickIntervalAction = delegate(int delta) + { + if (pawn.IsHashIntervalTick(80, delta) && destThing is Building_Grave && graveDigEffect == null) + { + graveDigEffect = EffecterDefOf.BuryPawn.Spawn(); + graveDigEffect.Trigger(destThing, destThing); + } + }; + toil.tickAction = delegate + { + graveDigEffect?.EffectTick(destThing, destThing); + }; + ModifyPrepareToil(toil); + yield return toil; + yield return Toils_Construct.MakeSolidThingFromBlueprintIfNecessary(TargetIndex.B, TargetIndex.C); + yield return Toils_Haul.DepositHauledThingInContainer(TargetIndex.B, TargetIndex.C); + yield return Toils_Haul.JumpToCarryToNextContainerIfPossible(carryToContainer, TargetIndex.C); + } + + private void UpdateEnrouteTrackers() + { + int count = job.count; + TryReserveEnroute(base.TargetThingC, ref count); + if (base.TargetB != base.TargetC) + { + TryReserveEnroute(base.TargetThingB, ref count); + } + if (job.targetQueueB == null) + { + return; + } + foreach (LocalTargetInfo item in job.targetQueueB) + { + if (!base.TargetC.HasThing || !(item == base.TargetThingC)) + { + TryReserveEnroute(item.Thing, ref count); + } + } + } + + private void TryReserveEnroute(Thing thing, ref int count) + { + if (thing is IHaulEnroute container && !thing.DestroyedOrNull()) + { + UpdateTracker(container, ref count); + } + } + + private void UpdateTracker(IHaulEnroute container, ref int count) + { + if (!ThingToCarry.DestroyedOrNull()) + { + if (job.playerForced && container.GetSpaceRemainingWithEnroute(ThingDef) == 0) + { + container.Map.enrouteManager.InterruptEnroutePawns(container, pawn); + } + int num = Mathf.Min(count, container.GetSpaceRemainingWithEnroute(ThingDef)); + if (num > 0) + { + container.Map.enrouteManager.AddEnroute(container, pawn, base.TargetThingA.def, num); + } + count -= num; + } + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\JobDriver_PrepareCaravan_GatherItems.txt` +**相似度:** 0.5905 + +```csharp +public class JobDriver_PrepareCaravan_GatherItems : JobDriver +{ + private int pickedUpFirstItemTicks = -1; + + private int toilLoops; + + private PrepareCaravanGatherState gatherState; + + private const TargetIndex ToHaulInd = TargetIndex.A; + + private const TargetIndex CarrierInd = TargetIndex.B; + + private const int MaxTicksGatherItems = 7500; + + private const int LoopBackstop = 500; + + public Thing ToHaul => job.GetTarget(TargetIndex.A).Thing; + + public Pawn Carrier => (Pawn)job.GetTarget(TargetIndex.B).Thing; + + private List Transferables => ((LordJob_FormAndSendCaravan)job.lord.LordJob).transferables; + + private TransferableOneWay Transferable + { + get + { + TransferableOneWay transferableOneWay = TransferableUtility.TransferableMatchingDesperate(ToHaul, Transferables, TransferAsOneMode.PodsOrCaravanPacking); + if (transferableOneWay != null) + { + return transferableOneWay; + } + throw new InvalidOperationException("Could not find any matching transferable."); + } + } + + public override bool TryMakePreToilReservations(bool errorOnFailed) + { + return pawn.Reserve(ToHaul, job, 1, -1, null, errorOnFailed); + } + + protected override IEnumerable MakeNewToils() + { + if (gatherState == PrepareCaravanGatherState.Unset) + { + gatherState = ((pawn.IsFormingCaravan() && (!MassUtility.IsOverEncumbered(pawn) || pawn.inventory.HasAnyUnpackedCaravanItems)) ? PrepareCaravanGatherState.Haul : PrepareCaravanGatherState.Carry); + } + if (gatherState == PrepareCaravanGatherState.Carry) + { + return MakeNewToilsCarry(); + } + return MakeNewToilsHaulInInventory(); + } + + private IEnumerable MakeNewToilsCarry() + { + this.FailOn(() => !base.Map.lordManager.lords.Contains(job.lord)); + Toil reserve = Toils_Reserve.Reserve(TargetIndex.A).FailOnDestroyedOrNull(TargetIndex.A); + yield return reserve; + bool inInventory = HaulAIUtility.IsInHaulableInventory(ToHaul); + yield return Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch, inInventory); + yield return DetermineNumToHaul(); + yield return Toils_Haul.StartCarryThing(TargetIndex.A, putRemainderInQueue: false, subtractNumTakenFromJobCount: true, failIfStackCountLessThanJobCount: false, reserve: true, inInventory); + yield return AddCarriedThingToTransferables(); + yield return Toils_Haul.CheckForGetOpportunityDuplicate(reserve, TargetIndex.A, TargetIndex.None, takeFromValidStorage: true, (Thing x) => Transferable.things.Contains(x)); + Toil findCarrier = FindCarrier(); + yield return findCarrier; + yield return Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.Touch).JumpIf(() => !IsUsableCarrier(Carrier, pawn, allowColonists: true), findCarrier); + yield return Toils_General.Wait(25).JumpIf(() => !IsUsableCarrier(Carrier, pawn, allowColonists: true), findCarrier).WithProgressBarToilDelay(TargetIndex.B); + yield return PlaceTargetInCarrierInventory(); + } + + private IEnumerable MakeNewToilsHaulInInventory() + { + this.FailOn(() => !base.Map.lordManager.lords.Contains(job.lord)); + bool inInventory = HaulAIUtility.IsInHaulableInventory(ToHaul); + Toil reserve = Toils_Reserve.Reserve(TargetIndex.A).FailOnDestroyedOrNull(TargetIndex.A); + Toil findCarrier = FindCarrier(); + yield return reserve; + yield return Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch, inInventory).JumpIf(IsFinishedCollectingItems, findCarrier); + yield return DetermineNumToHaul(findCarrier); + yield return Toils_Haul.StartCarryThing(TargetIndex.A, putRemainderInQueue: false, subtractNumTakenFromJobCount: true, failIfStackCountLessThanJobCount: false, reserve: true, inInventory); + yield return AddCarriedThingToTransferables(); + yield return Toils_General.Wait(25).WithProgressBarToilDelay(TargetIndex.B); + yield return HaulCaravanItemInInventory(reserve); + yield return findCarrier; + yield return Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.Touch).JumpIf(() => !IsUsableCarrier(Carrier, pawn, allowColonists: true), findCarrier); + yield return Toils_General.Wait(25).JumpIf(() => !IsUsableCarrier(Carrier, pawn, allowColonists: true), findCarrier).WithProgressBarToilDelay(TargetIndex.B); + yield return AddHauledItemsToCarrier(findCarrier); + } + + private Toil DetermineNumToHaul(Toil findCarrier = null) + { + Toil toil = ToilMaker.MakeToil("DetermineNumToHaul"); + toil.initAction = delegate + { + int num = GatherItemsForCaravanUtility.CountLeftToTransfer(pawn, Transferable, job.lord); + if (pawn.carryTracker.CarriedThing != null) + { + num -= pawn.carryTracker.CarriedThing.stackCount; + } + if (num <= 0) + { + if (findCarrier == null || !pawn.inventory.HasAnyUnpackedCaravanItems) + { + pawn.jobs.EndCurrentJob(JobCondition.Succeeded); + } + else + { + pawn.jobs.curDriver.JumpToToil(findCarrier); + } + } + else + { + job.count = num; + } + }; + toil.defaultCompleteMode = ToilCompleteMode.Instant; + toil.atomicWithPrevious = true; + return toil; + } + + private Toil AddCarriedThingToTransferables() + { + Toil toil = ToilMaker.MakeToil("AddCarriedThingToTransferables"); + toil.initAction = delegate + { + TransferableOneWay transferable = Transferable; + if (!transferable.things.Contains(pawn.carryTracker.CarriedThing)) + { + transferable.things.Add(pawn.carryTracker.CarriedThing); + } + }; + toil.defaultCompleteMode = ToilCompleteMode.Instant; + toil.atomicWithPrevious = true; + return toil; + } + + private Toil FindCarrier() + { + Toil toil = ToilMaker.MakeToil("FindCarrier"); + toil.initAction = delegate + { + Pawn pawn = FindBestCarrier(onlyAnimals: true); + if (pawn == null) + { + bool flag = base.pawn.GetLord() == job.lord; + if (flag && !MassUtility.IsOverEncumbered(base.pawn)) + { + pawn = base.pawn; + } + else + { + pawn = FindBestCarrier(onlyAnimals: false); + if (pawn == null) + { + if (flag) + { + pawn = base.pawn; + } + else + { + IEnumerable source = job.lord.ownedPawns.Where((Pawn x) => IsUsableCarrier(x, base.pawn, allowColonists: true)); + if (!source.Any()) + { + EndJobWith(JobCondition.Incompletable); + return; + } + pawn = source.RandomElement(); + } + } + } + } + job.SetTarget(TargetIndex.B, pawn); + }; + return toil; + } + + private bool IsFinishedCollectingItems() + { + if (!MassUtility.IsOverEncumbered(pawn)) + { + if (pickedUpFirstItemTicks > -1) + { + return Find.TickManager.TicksGame > pickedUpFirstItemTicks + 7500; + } + return false; + } + return true; + } + + private Toil HaulCaravanItemInInventory(Toil reserve) + { + Toil toil = ToilMaker.MakeToil("HaulCaravanItemInInventory"); + toil.initAction = delegate + { + if (pickedUpFirstItemTicks == -1) + { + pickedUpFirstItemTicks = Find.TickManager.TicksGame; + } + Transferable.AdjustTo(Mathf.Max(Transferable.CountToTransfer - pawn.carryTracker.CarriedThing.stackCount, 0)); + pawn.inventory.AddHauledCaravanItem(pawn.carryTracker.CarriedThing); + if (!IsFinishedCollectingItems()) + { + SetNewHaulTargetAndJumpToReserve(reserve); + } + }; + return toil; + } + + private void SetNewHaulTargetAndJumpToReserve(Toil reserve) + { + if (CheckToilLoopBackstop()) + { + Thing thing = GatherItemsForCaravanUtility.FindThingToHaul(pawn, pawn.GetLord()); + if (thing != null) + { + job.SetTarget(TargetIndex.A, thing); + pawn.jobs.curDriver.JumpToToil(reserve); + } + } + } + + private Toil AddHauledItemsToCarrier(Toil findCarrier) + { + Toil toil = ToilMaker.MakeToil("AddHauledItemsToCarrier"); + toil.initAction = delegate + { + if (Carrier == pawn) + { + pawn.inventory.ClearHaulingCaravanCache(); + } + else + { + pawn.inventory.TransferCaravanItemsToCarrier(Carrier.inventory); + if (pawn.inventory.HasAnyUnpackedCaravanItems && CheckToilLoopBackstop()) + { + pawn.jobs.curDriver.JumpToToil(findCarrier); + } + } + }; + return toil; + } + + private bool CheckToilLoopBackstop() + { + if (++toilLoops > 500) + { + Log.Error("Prepare caravan gather items job for pawn " + pawn.Label + " looped through toils too many times"); + EndJobWith(JobCondition.Errored); + return false; + } + return true; + } + + private Toil PlaceTargetInCarrierInventory() + { + Toil toil = ToilMaker.MakeToil("PlaceTargetInCarrierInventory"); + toil.initAction = delegate + { + Pawn_CarryTracker carryTracker = pawn.carryTracker; + Thing carriedThing = carryTracker.CarriedThing; + if (carryTracker.innerContainer.Count == 0) + { + carryTracker.pawn.Drawer.renderer.SetAllGraphicsDirty(); + } + Transferable.AdjustTo(Mathf.Max(Transferable.CountToTransfer - carriedThing.stackCount, 0)); + carryTracker.innerContainer.TryTransferToContainer(carriedThing, Carrier.inventory.innerContainer, carriedThing.stackCount, out var resultingTransferredItem); + CompForbiddable compForbiddable = resultingTransferredItem?.TryGetComp(); + if (compForbiddable != null) + { + compForbiddable.Forbidden = false; + } + }; + return toil; + } + + public static bool IsUsableCarrier(Pawn p, Pawn forPawn, bool allowColonists) + { + if (!p.IsFormingCaravan()) + { + return false; + } + if (p == forPawn) + { + return true; + } + if (p.DestroyedOrNull() || !p.Spawned || p.inventory.UnloadEverything || !forPawn.CanReach(p, PathEndMode.Touch, Danger.Deadly)) + { + return false; + } + if (allowColonists && p.IsColonist) + { + return true; + } + if ((p.RaceProps.packAnimal || p.HostFaction == Faction.OfPlayer) && !p.IsBurning() && !p.Downed) + { + return !MassUtility.IsOverEncumbered(p); + } + return false; + } + + private float GetCarrierScore(Pawn p) + { + float lengthHorizontal = (p.Position - pawn.Position).LengthHorizontal; + float num = MassUtility.EncumbrancePercent(p); + return 1f - num - lengthHorizontal / 10f * 0.2f; + } + + private Pawn FindBestCarrier(bool onlyAnimals) + { + Lord lord = job.lord; + Pawn pawn = null; + float num = 0f; + if (lord != null) + { + for (int i = 0; i < lord.ownedPawns.Count; i++) + { + Pawn pawn2 = lord.ownedPawns[i]; + if (pawn2 != base.pawn && (!onlyAnimals || pawn2.RaceProps.Animal) && IsUsableCarrier(pawn2, base.pawn, allowColonists: false)) + { + float carrierScore = GetCarrierScore(pawn2); + if (pawn == null || carrierScore > num) + { + pawn = pawn2; + num = carrierScore; + } + } + } + } + return pawn; + } + + public override void ExposeData() + { + base.ExposeData(); + Scribe_Values.Look(ref pickedUpFirstItemTicks, "pickedUpFirstItemTicks", 0); + Scribe_Values.Look(ref toilLoops, "toilLoops", 0); + Scribe_Values.Look(ref gatherState, "gatherState", PrepareCaravanGatherState.Unset); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\JobDriver_CarryToCryptosleepCasket.txt` +**相似度:** 0.5506 + +```csharp +public class JobDriver_CarryToCryptosleepCasket : JobDriver +{ + private const TargetIndex TakeeInd = TargetIndex.A; + + private const TargetIndex DropPodInd = TargetIndex.B; + + protected Pawn Takee => (Pawn)job.GetTarget(TargetIndex.A).Thing; + + protected Building_CryptosleepCasket DropPod => (Building_CryptosleepCasket)job.GetTarget(TargetIndex.B).Thing; + + public override bool TryMakePreToilReservations(bool errorOnFailed) + { + if (pawn.Reserve(Takee, job, 1, -1, null, errorOnFailed)) + { + return pawn.Reserve(DropPod, job, 1, -1, null, errorOnFailed); + } + return false; + } + + protected override IEnumerable MakeNewToils() + { + this.FailOnDestroyedOrNull(TargetIndex.A); + this.FailOnDestroyedOrNull(TargetIndex.B); + this.FailOnAggroMentalState(TargetIndex.A); + this.FailOn(() => !DropPod.Accepts(Takee)); + Toil goToTakee = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.OnCell).FailOnDestroyedNullOrForbidden(TargetIndex.A).FailOnDespawnedNullOrForbidden(TargetIndex.B) + .FailOn(() => DropPod.GetDirectlyHeldThings().Count > 0) + .FailOn(() => !pawn.CanReach(Takee, PathEndMode.OnCell, Danger.Deadly)) + .FailOnSomeonePhysicallyInteracting(TargetIndex.A); + Toil startCarryingTakee = Toils_Haul.StartCarryThing(TargetIndex.A); + Toil goToThing = Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.InteractionCell); + yield return Toils_Jump.JumpIf(goToThing, () => pawn.IsCarryingPawn(Takee)); + yield return goToTakee; + yield return startCarryingTakee; + yield return goToThing; + Toil toil = Toils_General.Wait(500, TargetIndex.B); + toil.FailOnCannotTouch(TargetIndex.B, PathEndMode.InteractionCell); + toil.WithProgressBarToilDelay(TargetIndex.B); + yield return toil; + Toil toil2 = ToilMaker.MakeToil("MakeNewToils"); + toil2.initAction = delegate + { + DropPod.TryAcceptThing(Takee); + }; + toil2.defaultCompleteMode = ToilCompleteMode.Instant; + yield return toil2; + } + + public override object[] TaleParameters() + { + return new object[2] { pawn, Takee }; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse.AI\JobDriver_HaulToAtomizer.txt` +**相似度:** 0.5312 + +```csharp +public class JobDriver_HaulToAtomizer : JobDriver +{ + private const TargetIndex AtomizerInd = TargetIndex.A; + + private const TargetIndex WastepackInd = TargetIndex.B; + + private const TargetIndex ChargerCellInd = TargetIndex.C; + + public override bool TryMakePreToilReservations(bool errorOnFailed) + { + pawn.ReserveAsManyAsPossible(job.GetTargetQueue(TargetIndex.B), job); + return pawn.Reserve(job.GetTarget(TargetIndex.A), job, 1, -1, null, errorOnFailed); + } + + protected override IEnumerable MakeNewToils() + { + this.FailOnDespawnedNullOrForbidden(TargetIndex.A); + AddEndCondition(() => (base.TargetThingA.TryGetComp().SpaceLeft > 0) ? JobCondition.Ongoing : JobCondition.Succeeded); + Toil clearQueue = Toils_JobTransforms.ClearDespawnedNullOrForbiddenQueuedTargets(TargetIndex.B); + yield return clearQueue; + yield return Toils_JobTransforms.SucceedOnNoTargetInQueue(TargetIndex.B); + yield return Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.B); + yield return Toils_Reserve.Reserve(TargetIndex.B); + yield return Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch).FailOnSomeonePhysicallyInteracting(TargetIndex.B); + yield return Toils_Haul.StartCarryThing(TargetIndex.B, putRemainderInQueue: false, subtractNumTakenFromJobCount: true); + yield return Toils_Haul.CheckForGetOpportunityDuplicate(clearQueue, TargetIndex.B, TargetIndex.None, takeFromValidStorage: true); + yield return Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell); + yield return Toils_Haul.DepositHauledThingInContainer(TargetIndex.A, TargetIndex.B); + yield return Toils_Jump.Jump(clearQueue); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse.AI\JobDriver_PickupToHold.txt` +**相似度:** 0.5219 + +```csharp +public class JobDriver_PickupToHold : JobDriver +{ + private const TargetIndex HeldItemInd = TargetIndex.A; + + public static bool TryMakePreToilReservations(JobDriver driver, bool errorOnFailed) + { + driver.pawn.Map.pawnDestinationReservationManager.Reserve(driver.pawn, driver.job, driver.job.GetTarget(TargetIndex.A).Cell); + return driver.pawn.Reserve(driver.job.GetTarget(TargetIndex.A), driver.job, 1, -1, null, errorOnFailed); + } + + public static IEnumerable Toils(JobDriver driver, TargetIndex HeldItem = TargetIndex.A, bool subtractNumTakenFromJobCount = true) + { + driver.FailOn(() => !driver.GetActor().health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)); + driver.FailOnDestroyedOrNull(HeldItem); + driver.FailOnForbidden(HeldItem); + Toil end = Toils_General.Label(); + yield return Toils_Jump.JumpIf(end, () => driver.GetActor().IsCarryingThing(driver.GetActor().CurJob.GetTarget(HeldItem).Thing)); + yield return Toils_Goto.GotoThing(HeldItem, PathEndMode.ClosestTouch).FailOnSomeonePhysicallyInteracting(HeldItem); + yield return Toils_Haul.StartCarryThing(HeldItem, putRemainderInQueue: false, subtractNumTakenFromJobCount); + yield return end; + } + + public override bool TryMakePreToilReservations(bool errorOnFailed) + { + return TryMakePreToilReservations(this, errorOnFailed); + } + + protected override IEnumerable MakeNewToils() + { + return Toils(this); + } +} +``` \ No newline at end of file diff --git a/MCP/vector_cache/StatDef.txt b/MCP/vector_cache/StatDef.txt new file mode 100644 index 00000000..b26afb92 --- /dev/null +++ b/MCP/vector_cache/StatDef.txt @@ -0,0 +1,502 @@ +根据向量相似度分析,与 'StatDef' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\StatDef.txt` + +```csharp +public class StatDef : Def +{ + private static HashSet mutableStats; + + public StatCategoryDef category; + + public Type workerClass = typeof(StatWorker); + + public string labelForFullStatList; + + public bool forInformationOnly; + + [MustTranslate] + private string offsetLabel; + + public float hideAtValue = -2.1474836E+09f; + + public bool alwaysHide; + + public bool showNonAbstract = true; + + public bool showIfUndefined = true; + + public bool showOnPawns = true; + + public bool showOnHumanlikes = true; + + public bool showOnNonWildManHumanlikes = true; + + public bool showOnAnimals = true; + + public bool showOnMechanoids = true; + + public bool showOnNonWorkTables = true; + + public bool showOnEntities = true; + + public bool showOnDrones = true; + + public bool showOnNonPowerPlants = true; + + public bool showOnDefaultValue = true; + + public bool showOnUnhaulables = true; + + public bool showOnUntradeables = true; + + public List showIfModsLoaded; + + public List showIfModsLoadedAny; + + public List showIfHediffsPresent; + + public bool neverDisabled; + + public bool showZeroBaseValue; + + public bool showOnSlavesOnly; + + public bool showOnPlayerMechanoids; + + public DevelopmentalStage showDevelopmentalStageFilter = DevelopmentalStage.Baby | DevelopmentalStage.Child | DevelopmentalStage.Adult; + + public bool hideInClassicMode; + + public List showOnPawnKind; + + public bool overridesHideStats; + + public int displayPriorityInCategory; + + public ToStringNumberSense toStringNumberSense = ToStringNumberSense.Absolute; + + public ToStringStyle toStringStyle; + + private ToStringStyle? toStringStyleUnfinalized; + + [MustTranslate] + public string formatString; + + [MustTranslate] + public string formatStringUnfinalized; + + public bool finalizeEquippedStatOffset = true; + + [MustTranslate] + public string statFactorsExplanationHeader; + + public float defaultBaseValue = 1f; + + public List skillNeedOffsets; + + public float noSkillOffset; + + public List capacityOffsets; + + public List statFactors; + + public bool applyFactorsIfNegative = true; + + public List skillNeedFactors; + + public float noSkillFactor = 1f; + + public List capacityFactors; + + public SimpleCurve postProcessCurve; + + public List postProcessStatFactors; + + public float minValue = -9999999f; + + public float maxValue = 9999999f; + + public float valueIfMissing; + + public bool roundValue; + + public float roundToFiveOver = float.MaxValue; + + public bool minifiedThingInherits; + + public bool supressDisabledError; + + public bool cacheable; + + public bool displayMaxWhenAboveOrEqual; + + public bool scenarioRandomizable; + + public SkillDef disableIfSkillDisabled; + + public List parts; + + [Unsaved(false)] + private StatWorker workerInt; + + [Unsaved(false)] + public bool immutable; + + public StatWorker Worker + { + get + { + if (workerInt == null) + { + if (parts != null) + { + for (int i = 0; i < parts.Count; i++) + { + parts[i].parentStat = this; + } + } + workerInt = (StatWorker)Activator.CreateInstance(workerClass); + workerInt.InitSetStat(this); + } + return workerInt; + } + } + + public ToStringStyle ToStringStyleUnfinalized + { + get + { + if (!toStringStyleUnfinalized.HasValue) + { + return toStringStyle; + } + return toStringStyleUnfinalized.Value; + } + } + + public string LabelForFullStatList + { + get + { + if (!labelForFullStatList.NullOrEmpty()) + { + return labelForFullStatList; + } + return label; + } + } + + public string LabelForFullStatListCap => LabelForFullStatList.CapitalizeFirst(this); + + public string OffsetLabel => offsetLabel ?? label; + + public string OffsetLabelCap => OffsetLabel.CapitalizeFirst(); + + public override IEnumerable ConfigErrors() + { + foreach (string item in base.ConfigErrors()) + { + yield return item; + } + if (capacityFactors != null) + { + foreach (PawnCapacityFactor capacityFactor in capacityFactors) + { + if (capacityFactor.weight > 1f) + { + yield return defName + " has activity factor with weight > 1"; + } + } + } + if (parts == null) + { + yield break; + } + for (int i = 0; i < parts.Count; i++) + { + foreach (string item2 in parts[i].ConfigErrors()) + { + yield return defName + " has error in StatPart " + parts[i].ToString() + ": " + item2; + } + } + } + + public string ValueToString(float val, ToStringNumberSense numberSense = ToStringNumberSense.Absolute, bool finalized = true) + { + return Worker.ValueToString(val, finalized, numberSense); + } + + public static StatDef Named(string defName) + { + return DefDatabase.GetNamed(defName); + } + + public override void PostLoad() + { + base.PostLoad(); + if (parts != null) + { + List partsCopy = parts.ToList(); + parts.SortBy((StatPart x) => 0f - x.priority, (StatPart x) => partsCopy.IndexOf(x)); + } + } + + public T GetStatPart() where T : StatPart + { + return parts.OfType().FirstOrDefault(); + } + + public bool CanShowWithLoadedMods() + { + if (!showIfModsLoaded.NullOrEmpty()) + { + for (int i = 0; i < showIfModsLoaded.Count; i++) + { + if (!ModsConfig.IsActive(showIfModsLoaded[i])) + { + return false; + } + } + } + if (!showIfModsLoadedAny.NullOrEmpty()) + { + bool result = false; + for (int j = 0; j < showIfModsLoadedAny.Count; j++) + { + if (ModsConfig.IsActive(showIfModsLoadedAny[j])) + { + result = true; + break; + } + } + return result; + } + return true; + } + + private static void PopulateMutableStats() + { + mutableStats = new HashSet(); + foreach (TraitDef item in DefDatabase.AllDefsListForReading) + { + foreach (TraitDegreeData degreeData in item.degreeDatas) + { + AddStatsFromModifiers(degreeData.statOffsets); + AddStatsFromModifiers(degreeData.statFactors); + } + } + foreach (HediffDef item2 in DefDatabase.AllDefsListForReading) + { + if (item2.stages == null) + { + continue; + } + foreach (HediffStage stage in item2.stages) + { + AddStatsFromModifiers(stage.statOffsets); + AddStatsFromModifiers(stage.statFactors); + if (stage.statOffsetEffectMultiplier != null) + { + mutableStats.Add(stage.statOffsetEffectMultiplier); + } + if (stage.statFactorEffectMultiplier != null) + { + mutableStats.Add(stage.statFactorEffectMultiplier); + } + if (stage.capacityFactorEffectMultiplier != null) + { + mutableStats.Add(stage.capacityFactorEffectMultiplier); + } + } + } + foreach (PreceptDef item3 in DefDatabase.AllDefsListForReading) + { + AddStatsFromModifiers(item3.statOffsets); + AddStatsFromModifiers(item3.statFactors); + if (item3.roleEffects != null) + { + foreach (RoleEffect roleEffect in item3.roleEffects) + { + if (roleEffect is RoleEffect_PawnStatOffset roleEffect_PawnStatOffset) + { + mutableStats.Add(roleEffect_PawnStatOffset.statDef); + } + if (roleEffect is RoleEffect_PawnStatFactor roleEffect_PawnStatFactor) + { + mutableStats.Add(roleEffect_PawnStatFactor.statDef); + } + } + } + if (item3.abilityStatFactors == null) + { + continue; + } + foreach (AbilityStatModifiers abilityStatFactor in item3.abilityStatFactors) + { + AddStatsFromModifiers(abilityStatFactor.modifiers); + } + } + foreach (GeneDef item4 in DefDatabase.AllDefsListForReading) + { + AddStatsFromModifiers(item4.statOffsets); + AddStatsFromModifiers(item4.statFactors); + if (item4.conditionalStatAffecters == null) + { + continue; + } + foreach (ConditionalStatAffecter conditionalStatAffecter in item4.conditionalStatAffecters) + { + AddStatsFromModifiers(conditionalStatAffecter.statOffsets); + AddStatsFromModifiers(conditionalStatAffecter.statFactors); + } + } + foreach (ThingDef item5 in DefDatabase.AllDefsListForReading) + { + AddStatsFromModifiers(item5.equippedStatOffsets); + if (!item5.HasAssignableCompFrom(typeof(CompFacility))) + { + continue; + } + CompProperties_Facility compProperties = item5.GetCompProperties(); + if (compProperties?.statOffsets != null) + { + AddStatsFromModifiers(compProperties.statOffsets); + } + if (!(compProperties is CompProperties_FacilityQualityBased compProperties_FacilityQualityBased)) + { + continue; + } + foreach (StatDef key in compProperties_FacilityQualityBased.statOffsetsPerQuality.Keys) + { + mutableStats.Add(key); + } + } + foreach (WeaponTraitDef item6 in DefDatabase.AllDefsListForReading) + { + AddStatsFromModifiers(item6.equippedStatOffsets); + } + foreach (LifeStageDef item7 in DefDatabase.AllDefsListForReading) + { + AddStatsFromModifiers(item7.statFactors); + AddStatsFromModifiers(item7.statOffsets); + } + foreach (InspirationDef item8 in DefDatabase.AllDefsListForReading) + { + AddStatsFromModifiers(item8.statOffsets); + AddStatsFromModifiers(item8.statFactors); + } + static void AddStatsFromModifiers(List mods) + { + if (mods != null) + { + mutableStats.AddRange(mods.Select((StatModifier mod) => mod.stat)); + } + } + } + + public bool IsImmutable() + { + if (workerClass != typeof(StatWorker)) + { + return false; + } + if (!skillNeedOffsets.NullOrEmpty() || !skillNeedFactors.NullOrEmpty()) + { + return false; + } + if (!capacityOffsets.NullOrEmpty() || !capacityFactors.NullOrEmpty()) + { + return false; + } + if (!statFactors.NullOrEmpty()) + { + return false; + } + if (!parts.NullOrEmpty()) + { + return false; + } + if (!postProcessStatFactors.NullOrEmpty()) + { + return false; + } + if (mutableStats.Contains(this)) + { + return false; + } + return true; + } + + public static void SetImmutability() + { + PopulateMutableStats(); + foreach (StatDef item in DefDatabase.AllDefsListForReading) + { + item.immutable = item.IsImmutable(); + item.Worker.SetCacheability(item.immutable); + } + } + + public static void ResetStaticData() + { + mutableStats = null; + foreach (StatDef item in DefDatabase.AllDefsListForReading) + { + item.immutable = false; + item.Worker.DeleteStatCache(); + } + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Core\Defs\Stats\Stats_Building_Special.xml` +**相似度:** 0.5742 + +```xml + + WorkToBuild + + The base amount of work it takes to build a structure, once all materials are gathered.\n\nThe work required to deconstruct the structure is also based on this. + Building + 1 + 0 + WorkAmount + 300 + false + true + 3101 + +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Royalty\Defs\Stats\Stats_Basics_Special.xml` +**相似度:** 0.5197 + +```xml + + MeditationPlantGrowthOffset + + An offset applied to the growth rate of plants, like anima grass, from meditation. This value can change based on the number of artificial buildings nearby. + Meditation + 0 + false + false + false + 4000 + PercentZero + +
  • + 27.9 + + +
  • (0, 0.0)
  • +
  • (5, -0.08)
  • +
  • (10, -0.15)
  • +
  • (50, -0.3)
  • + + + +
    +
    +``` \ No newline at end of file diff --git a/MCP/vector_cache/WorkGiver_Scanner.txt b/MCP/vector_cache/WorkGiver_Scanner.txt new file mode 100644 index 00000000..01ee366c --- /dev/null +++ b/MCP/vector_cache/WorkGiver_Scanner.txt @@ -0,0 +1,507 @@ +根据向量相似度分析,与 'WorkGiver_Scanner' 最相关的代码定义如下: + +--- +**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_Scanner.txt` + +```csharp +public abstract class WorkGiver_Scanner : WorkGiver +{ + public virtual ThingRequest PotentialWorkThingRequest => ThingRequest.ForGroup(ThingRequestGroup.Undefined); + + public virtual int MaxRegionsToScanBeforeGlobalSearch => -1; + + public virtual bool Prioritized => false; + + public virtual bool AllowUnreachable => false; + + public virtual PathEndMode PathEndMode => PathEndMode.Touch; + + public virtual IEnumerable PotentialWorkCellsGlobal(Pawn pawn) + { + return Enumerable.Empty(); + } + + public virtual IEnumerable PotentialWorkThingsGlobal(Pawn pawn) + { + return null; + } + + public virtual Danger MaxPathDanger(Pawn pawn) + { + return pawn.NormalMaxDanger(); + } + + public virtual bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) + { + return JobOnThing(pawn, t, forced) != null; + } + + public virtual string JobInfo(Pawn pawn, Job job) + { + return string.Empty; + } + + public virtual Job JobOnThing(Pawn pawn, Thing t, bool forced = false) + { + return null; + } + + public virtual bool HasJobOnCell(Pawn pawn, IntVec3 c, bool forced = false) + { + return JobOnCell(pawn, c, forced) != null; + } + + public virtual Job JobOnCell(Pawn pawn, IntVec3 cell, bool forced = false) + { + return null; + } + + public virtual float GetPriority(Pawn pawn, TargetInfo t) + { + return 0f; + } + + public virtual string PostProcessedGerund(Job job) + { + return def.gerund; + } + + public float GetPriority(Pawn pawn, IntVec3 cell) + { + return GetPriority(pawn, new TargetInfo(cell, pawn.Map)); + } + + public virtual ReservationLayerDef GetReservationLayer(Pawn pawn, LocalTargetInfo target) + { + return null; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_HaulToSubcoreScanner.txt` +**相似度:** 0.5742 + +```csharp +public class WorkGiver_HaulToSubcoreScanner : WorkGiver_Scanner +{ + public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForGroup(ThingRequestGroup.SubcoreScanner); + + public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) + { + if (!ModLister.CheckBiotech("Haul to subcore scanner")) + { + return false; + } + if (!(t is Building_SubcoreScanner { State: SubcoreScannerState.WaitingForIngredients } building_SubcoreScanner)) + { + return false; + } + if (!pawn.CanReserve(t, 1, -1, null, forced)) + { + return false; + } + return FindIngredients(pawn, building_SubcoreScanner).Thing != null; + } + + public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) + { + if (!(t is Building_SubcoreScanner { State: SubcoreScannerState.WaitingForIngredients } building_SubcoreScanner)) + { + return null; + } + ThingCount thingCount = FindIngredients(pawn, building_SubcoreScanner); + if (thingCount.Thing != null) + { + Job job = HaulAIUtility.HaulToContainerJob(pawn, thingCount.Thing, t); + job.count = Mathf.Min(job.count, thingCount.Count); + return job; + } + return null; + } + + private ThingCount FindIngredients(Pawn pawn, Building_SubcoreScanner scanner) + { + Thing thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableEver), PathEndMode.ClosestTouch, TraverseParms.For(pawn), 9999f, Validator); + if (thing == null) + { + return default(ThingCount); + } + int requiredCountOf = scanner.GetRequiredCountOf(thing.def); + return new ThingCount(thing, Mathf.Min(thing.stackCount, requiredCountOf)); + bool Validator(Thing x) + { + if (!pawn.CanReserve(x)) + { + return false; + } + if (x.IsForbidden(pawn)) + { + return false; + } + return scanner.CanAcceptIngredient(x); + } + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_HaulToBiosculpterPod.txt` +**相似度:** 0.5453 + +```csharp +public class WorkGiver_HaulToBiosculpterPod : WorkGiver_Scanner +{ + public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForDef(ThingDefOf.BiosculpterPod); + + public override PathEndMode PathEndMode => PathEndMode.Touch; + + public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) + { + if (!ModLister.CheckIdeology("Biosculpting")) + { + return false; + } + if (!pawn.CanReserve(t, 1, -1, null, forced)) + { + return false; + } + if (pawn.Map.designationManager.DesignationOn(t, DesignationDefOf.Deconstruct) != null) + { + return false; + } + CompBiosculpterPod compBiosculpterPod = t.TryGetComp(); + if (compBiosculpterPod == null || !compBiosculpterPod.PowerOn || compBiosculpterPod.State != 0 || (!forced && !compBiosculpterPod.autoLoadNutrition)) + { + return false; + } + if (t.IsBurning()) + { + return false; + } + if (compBiosculpterPod.RequiredNutritionRemaining > 0f) + { + if (FindNutrition(pawn, compBiosculpterPod).Thing == null) + { + JobFailReason.Is("NoFood".Translate()); + return false; + } + return true; + } + return false; + } + + public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) + { + CompBiosculpterPod compBiosculpterPod = t.TryGetComp(); + if (compBiosculpterPod == null) + { + return null; + } + if (compBiosculpterPod.RequiredNutritionRemaining > 0f) + { + ThingCount thingCount = FindNutrition(pawn, compBiosculpterPod); + if (thingCount.Thing != null) + { + Job job = HaulAIUtility.HaulToContainerJob(pawn, thingCount.Thing, t); + job.count = Mathf.Min(job.count, thingCount.Count); + return job; + } + } + return null; + } + + private ThingCount FindNutrition(Pawn pawn, CompBiosculpterPod pod) + { + Thing thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree), PathEndMode.ClosestTouch, TraverseParms.For(pawn), 9999f, Validator); + if (thing == null) + { + return default(ThingCount); + } + int b = Mathf.CeilToInt(pod.RequiredNutritionRemaining / thing.GetStatValue(StatDefOf.Nutrition)); + return new ThingCount(thing, Mathf.Min(thing.stackCount, b)); + bool Validator(Thing x) + { + if (x.IsForbidden(pawn) || !pawn.CanReserve(x)) + { + return false; + } + if (!pod.CanAcceptNutrition(x)) + { + return false; + } + return true; + } + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_ConstructFinishFrames.txt` +**相似度:** 0.5184 + +```csharp +public class WorkGiver_ConstructFinishFrames : WorkGiver_Scanner +{ + public override PathEndMode PathEndMode => PathEndMode.Touch; + + public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForGroup(ThingRequestGroup.BuildingFrame); + + public override Danger MaxPathDanger(Pawn pawn) + { + return Danger.Deadly; + } + + public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) + { + if (t.Faction != pawn.Faction) + { + return null; + } + if (!(t is Frame frame)) + { + return null; + } + if (!frame.IsCompleted()) + { + return null; + } + if (!GenConstruct.CanTouchTargetFromValidCell(frame, pawn)) + { + return null; + } + if (GenConstruct.FirstBlockingThing(frame, pawn) != null) + { + return GenConstruct.HandleBlockingThingJob(frame, pawn, forced); + } + if (!GenConstruct.CanConstruct(frame, pawn, checkSkills: true, forced)) + { + return null; + } + return JobMaker.MakeJob(JobDefOf.FinishFrame, frame); + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_CookFillHopper.txt` +**相似度:** 0.5093 + +```csharp +public class WorkGiver_CookFillHopper : WorkGiver_Scanner +{ + private static string TheOnlyAvailableFoodIsInStorageOfHigherPriorityTrans; + + private static string NoFoodToFillHopperTrans; + + public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForDef(ThingDefOf.Hopper); + + public override PathEndMode PathEndMode => PathEndMode.ClosestTouch; + + public WorkGiver_CookFillHopper() + { + if (TheOnlyAvailableFoodIsInStorageOfHigherPriorityTrans == null) + { + TheOnlyAvailableFoodIsInStorageOfHigherPriorityTrans = "TheOnlyAvailableFoodIsInStorageOfHigherPriority".Translate(); + } + if (NoFoodToFillHopperTrans == null) + { + NoFoodToFillHopperTrans = "NoFoodToFillHopper".Translate(); + } + } + + public override Job JobOnThing(Pawn pawn, Thing thing, bool forced = false) + { + if (!(thing is ISlotGroupParent hopperSgp)) + { + return null; + } + if (!pawn.CanReserve(thing.Position)) + { + return null; + } + float num = 0f; + List list = pawn.Map.thingGrid.ThingsListAt(thing.Position); + for (int i = 0; i < list.Count; i++) + { + Thing thing2 = list[i]; + if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(thing2.def)) + { + num = (float)thing2.stackCount / (float)thing2.def.stackLimit; + } + } + if (num > 0.35f) + { + JobFailReason.Is("AlreadyFilledLower".Translate()); + return null; + } + return HopperFillFoodJob(pawn, hopperSgp, forced); + } + + public static Job HopperFillFoodJob(Pawn pawn, ISlotGroupParent hopperSgp, bool forced) + { + Building building = (Building)hopperSgp; + if (!pawn.CanReserveAndReach(building.Position, PathEndMode.Touch, pawn.NormalMaxDanger())) + { + return null; + } + ThingDef thingDef = null; + Thing firstItem = building.Position.GetFirstItem(building.Map); + if (firstItem != null) + { + if (!Building_NutrientPasteDispenser.IsAcceptableFeedstock(firstItem.def)) + { + if (firstItem.IsForbidden(pawn)) + { + return null; + } + return HaulAIUtility.HaulAsideJobFor(pawn, firstItem); + } + thingDef = firstItem.def; + } + List list = ((thingDef != null) ? pawn.Map.listerThings.ThingsOfDef(thingDef) : pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.FoodSourceNotPlantOrTree)); + bool flag = false; + for (int i = 0; i < list.Count; i++) + { + Thing thing = list[i]; + if (!thing.def.IsNutritionGivingIngestible || (thing.def.ingestible.preferability != FoodPreferability.RawBad && thing.def.ingestible.preferability != FoodPreferability.RawTasty) || !HaulAIUtility.PawnCanAutomaticallyHaul(pawn, thing, forced) || !pawn.Map.haulDestinationManager.SlotGroupAt(building.Position).Settings.AllowedToAccept(thing)) + { + continue; + } + if ((int)StoreUtility.CurrentStoragePriorityOf(thing, forced) >= (int)hopperSgp.GetSlotGroup().Settings.Priority) + { + flag = true; + JobFailReason.Is(TheOnlyAvailableFoodIsInStorageOfHigherPriorityTrans); + continue; + } + Job job = HaulAIUtility.HaulToCellStorageJob(pawn, thing, building.Position, fitInStoreCell: true); + if (job != null) + { + return job; + } + } + if (!flag) + { + JobFailReason.Is(NoFoodToFillHopperTrans); + } + return null; + } +} +``` +--- +**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_InteractAnimal.txt` +**相似度:** 0.5082 + +```csharp +public abstract class WorkGiver_InteractAnimal : WorkGiver_Scanner +{ + protected static string NoUsableFoodTrans; + + protected static string AnimalInteractedTooRecentlyTrans; + + private static string CantInteractAnimalDownedTrans; + + private static string CantInteractAnimalAsleepTrans; + + private static string CantInteractAnimalBusyTrans; + + protected bool canInteractWhileSleeping; + + public override PathEndMode PathEndMode => PathEndMode.OnCell; + + public static void ResetStaticData() + { + NoUsableFoodTrans = "NoUsableFood".Translate(); + AnimalInteractedTooRecentlyTrans = "AnimalInteractedTooRecently".Translate(); + CantInteractAnimalDownedTrans = "CantInteractAnimalDowned".Translate(); + CantInteractAnimalAsleepTrans = "CantInteractAnimalAsleep".Translate(); + CantInteractAnimalBusyTrans = "CantInteractAnimalBusy".Translate(); + } + + protected virtual bool CanInteractWithAnimal(Pawn pawn, Pawn animal, bool forced) + { + if (CanInteractWithAnimal(pawn, animal, out var jobFailReason, forced, canInteractWhileSleeping)) + { + return true; + } + if (jobFailReason != null) + { + JobFailReason.Is(jobFailReason); + } + return false; + } + + public static bool CanInteractWithAnimal(Pawn pawn, Pawn animal, out string jobFailReason, bool forced, bool canInteractWhileSleeping = false, bool ignoreSkillRequirements = false, bool canInteractWhileRoaming = false) + { + jobFailReason = null; + if (!pawn.CanReserve(animal, 1, -1, null, forced)) + { + return false; + } + if (animal.Downed) + { + jobFailReason = CantInteractAnimalDownedTrans; + return false; + } + if (!animal.Awake() && !canInteractWhileSleeping) + { + jobFailReason = CantInteractAnimalAsleepTrans; + return false; + } + if (!animal.CanCasuallyInteractNow(twoWayInteraction: false, canInteractWhileSleeping, canInteractWhileRoaming)) + { + jobFailReason = CantInteractAnimalBusyTrans; + return false; + } + int num = TrainableUtility.MinimumHandlingSkill(animal); + if (!ignoreSkillRequirements && num > pawn.skills.GetSkill(SkillDefOf.Animals).Level) + { + jobFailReason = "AnimalsSkillTooLow".Translate(num); + return false; + } + return true; + } + + protected bool HasFoodToInteractAnimal(Pawn pawn, Pawn tamee) + { + ThingOwner innerContainer = pawn.inventory.innerContainer; + int num = 0; + float num2 = JobDriver_InteractAnimal.RequiredNutritionPerFeed(tamee); + float num3 = 0f; + for (int i = 0; i < innerContainer.Count; i++) + { + Thing thing = innerContainer[i]; + if (!tamee.WillEat(thing, pawn) || (int)thing.def.ingestible.preferability > 5 || thing.def.IsDrug) + { + continue; + } + for (int j = 0; j < thing.stackCount; j++) + { + num3 += thing.GetStatValue(StatDefOf.Nutrition); + if (num3 >= num2) + { + num++; + num3 = 0f; + } + if (num >= 2) + { + return true; + } + } + } + return false; + } + + protected Job TakeFoodForAnimalInteractJob(Pawn pawn, Pawn tamee) + { + ThingDef foodDef; + Thing thing = FoodUtility.BestFoodSourceOnMap(pawn, tamee, desperate: false, out foodDef, FoodPreferability.RawTasty, allowPlant: false, allowDrug: false, allowCorpse: false, allowDispenserFull: false, allowDispenserEmpty: false, allowForbidden: false, allowSociallyImproper: false, allowHarvest: false, forceScanWholeMap: false, ignoreReservations: false, calculateWantedStackCount: false, FoodPreferability.Undefined, JobDriver_InteractAnimal.RequiredNutritionPerFeed(tamee) * 2f * 4f); + if (thing == null) + { + return null; + } + float wantedNutrition = JobDriver_InteractAnimal.RequiredNutritionPerFeed(tamee) * 2f * 4f; + float nutrition = FoodUtility.GetNutrition(tamee, thing, foodDef); + int count = FoodUtility.StackCountForNutrition(wantedNutrition, nutrition); + Job job = JobMaker.MakeJob(JobDefOf.TakeInventory, thing); + job.count = count; + return job; + } +} +``` \ No newline at end of file diff --git a/Documentation/EventSystem_Documentation.md b/Source/Documentation/EventSystem_Documentation.md similarity index 100% rename from Documentation/EventSystem_Documentation.md rename to Source/Documentation/EventSystem_Documentation.md diff --git a/Documentation/layout_preview.html b/Source/Documentation/layout_preview.html similarity index 100% rename from Documentation/layout_preview.html rename to Source/Documentation/layout_preview.html diff --git a/Source/MCP/python-sdk b/Source/MCP/python-sdk deleted file mode 160000 index 959d4e39..00000000 --- a/Source/MCP/python-sdk +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 959d4e39ae13e45d3059ec6d6ca82fb231039a91 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Assault_Troop_Helmet_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Assault_Troop_Helmet_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Assault_Troop_Helmet_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Assault_Troop_Helmet_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Assault_Troop_PowerArmor_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Assault_Troop_PowerArmor_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Assault_Troop_PowerArmor_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Assault_Troop_PowerArmor_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Body_Suit_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Body_Suit_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Body_Suit_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Body_Suit_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Bodystocking_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Bodystocking_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Bodystocking_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Bodystocking_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Bodystocking_White_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Bodystocking_White_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Bodystocking_White_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Bodystocking_White_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Heavy_Infantry_Helmet_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Heavy_Infantry_Helmet_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Heavy_Infantry_Helmet_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Heavy_Infantry_Helmet_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Heavy_Infantry_PowerArmor_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Knight_Helmet_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Knight_Helmet_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Knight_Helmet_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Knight_Helmet_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Knight_PowerArmor_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Knight_PowerArmor_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Knight_PowerArmor_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Knight_PowerArmor_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Maid_Uniform_Headband.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Maid_Uniform_Headband.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Maid_Uniform_Headband.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Maid_Uniform_Headband.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Maid_Uniform_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Maid_Uniform_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Maid_Uniform_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Maid_Uniform_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Nun_Uniform_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Nun_Uniform_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Nun_Uniform_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Nun_Uniform_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Nun_veil_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Nun_veil_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Nun_veil_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Nun_veil_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Nurse_Uniform_Headband_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Nurse_Uniform_Headband_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Nurse_Uniform_Headband_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Nurse_Uniform_Headband_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Nurse_Uniform_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Nurse_Uniform_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Nurse_Uniform_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Nurse_Uniform_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Priest_Hat_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Priest_Hat_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Priest_Hat_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Priest_Hat_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Priest_Uniform_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Priest_Uniform_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Priest_Uniform_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Priest_Uniform_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Qipao_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Qipao_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Qipao_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Qipao_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Sailor_Dress_Thin_east.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Sailor_Dress_Thin_east.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Sailor_Dress_Thin_east.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Sailor_Dress_Thin_east.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Sailor_Dress_Thin_north.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Sailor_Dress_Thin_north.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Sailor_Dress_Thin_north.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Sailor_Dress_Thin_north.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Sailor_Dress_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Sailor_Dress_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Sailor_Dress_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Sailor_Dress_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Shield_Base_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Shield_Base_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Shield_Base_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Shield_Base_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Shield_Prismatic_Thin_north.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Shield_Prismatic_Thin_north.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Shield_Prismatic_Thin_north.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Shield_Prismatic_Thin_north.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Skitarii_Uniform_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Skitarii_Uniform_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Skitarii_Uniform_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Skitarii_Uniform_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_Skitarii_veil_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_Skitarii_veil_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_Skitarii_veil_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_Skitarii_veil_south.sai2 diff --git a/美术与文本源文件/Wula/Apparel/WULA_official_uniform_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Apparel/WULA_official_uniform_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Apparel/WULA_official_uniform_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Apparel/WULA_official_uniform_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Building/Door/WulaAutodoor.png b/Source/美术与文本源文件/Wula/Building/Door/WulaAutodoor.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Door/WulaAutodoor.png rename to Source/美术与文本源文件/Wula/Building/Door/WulaAutodoor.png diff --git a/美术与文本源文件/Wula/Building/Door/WulaAutodoor_BluePrint.png b/Source/美术与文本源文件/Wula/Building/Door/WulaAutodoor_BluePrint.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Door/WulaAutodoor_BluePrint.png rename to Source/美术与文本源文件/Wula/Building/Door/WulaAutodoor_BluePrint.png diff --git a/美术与文本源文件/Wula/Building/Door/WulaAutodoor_Mover.png b/Source/美术与文本源文件/Wula/Building/Door/WulaAutodoor_Mover.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Door/WulaAutodoor_Mover.png rename to Source/美术与文本源文件/Wula/Building/Door/WulaAutodoor_Mover.png diff --git a/美术与文本源文件/Wula/Building/Door/WulaAutodoor_Mover.sai2 b/Source/美术与文本源文件/Wula/Building/Door/WulaAutodoor_Mover.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Building/Door/WulaAutodoor_Mover.sai2 rename to Source/美术与文本源文件/Wula/Building/Door/WulaAutodoor_Mover.sai2 diff --git a/美术与文本源文件/Wula/Building/Door/WulaAutodoor_Mover_east.png b/Source/美术与文本源文件/Wula/Building/Door/WulaAutodoor_Mover_east.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Door/WulaAutodoor_Mover_east.png rename to Source/美术与文本源文件/Wula/Building/Door/WulaAutodoor_Mover_east.png diff --git a/美术与文本源文件/Wula/Building/Door/WulaAutodoor_Mover_south.png b/Source/美术与文本源文件/Wula/Building/Door/WulaAutodoor_Mover_south.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Door/WulaAutodoor_Mover_south.png rename to Source/美术与文本源文件/Wula/Building/Door/WulaAutodoor_Mover_south.png diff --git a/美术与文本源文件/Wula/Building/Door/WulaAutodoor_east.png b/Source/美术与文本源文件/Wula/Building/Door/WulaAutodoor_east.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Door/WulaAutodoor_east.png rename to Source/美术与文本源文件/Wula/Building/Door/WulaAutodoor_east.png diff --git a/美术与文本源文件/Wula/Building/Door/WulaAutodoor_south.png b/Source/美术与文本源文件/Wula/Building/Door/WulaAutodoor_south.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Door/WulaAutodoor_south.png rename to Source/美术与文本源文件/Wula/Building/Door/WulaAutodoor_south.png diff --git a/美术与文本源文件/Wula/Building/Linked/WULA_Fortress_Wall_Blueprint.png b/Source/美术与文本源文件/Wula/Building/Linked/WULA_Fortress_Wall_Blueprint.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Linked/WULA_Fortress_Wall_Blueprint.png rename to Source/美术与文本源文件/Wula/Building/Linked/WULA_Fortress_Wall_Blueprint.png diff --git a/美术与文本源文件/Wula/Building/Linked/WULA_Fortress_Wall_MenuIcon.png b/Source/美术与文本源文件/Wula/Building/Linked/WULA_Fortress_Wall_MenuIcon.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Linked/WULA_Fortress_Wall_MenuIcon.png rename to Source/美术与文本源文件/Wula/Building/Linked/WULA_Fortress_Wall_MenuIcon.png diff --git a/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_northeast.png b/Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_northeast.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_northeast.png rename to Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_northeast.png diff --git a/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_northwest.png b/Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_northwest.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_northwest.png rename to Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_northwest.png diff --git a/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_southeast.png b/Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_southeast.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_southeast.png rename to Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_southeast.png diff --git a/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_southwest.png b/Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_southwest.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_southwest.png rename to Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_Partial_southwest.png diff --git a/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_northeast.png b/Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_northeast.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_northeast.png rename to Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_northeast.png diff --git a/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_northwest.png b/Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_northwest.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_northwest.png rename to Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_northwest.png diff --git a/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_northwest.sai2 b/Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_northwest.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_northwest.sai2 rename to Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_northwest.sai2 diff --git a/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_southeast.png b/Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_southeast.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_southeast.png rename to Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_southeast.png diff --git a/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_southwest.png b/Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_southwest.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_southwest.png rename to Source/美术与文本源文件/Wula/Building/Linked/WulaWall/AngledWulaWall_southwest.png diff --git a/美术与文本源文件/Wula/Building/Linked/WulaWall/SubstructureCorner_Full_east.psd b/Source/美术与文本源文件/Wula/Building/Linked/WulaWall/SubstructureCorner_Full_east.psd similarity index 100% rename from 美术与文本源文件/Wula/Building/Linked/WulaWall/SubstructureCorner_Full_east.psd rename to Source/美术与文本源文件/Wula/Building/Linked/WulaWall/SubstructureCorner_Full_east.psd diff --git a/美术与文本源文件/Wula/Building/Linked/WulaWall/SubstructureCorner_Full_west.psd b/Source/美术与文本源文件/Wula/Building/Linked/WulaWall/SubstructureCorner_Full_west.psd similarity index 100% rename from 美术与文本源文件/Wula/Building/Linked/WulaWall/SubstructureCorner_Full_west.psd rename to Source/美术与文本源文件/Wula/Building/Linked/WulaWall/SubstructureCorner_Full_west.psd diff --git a/美术与文本源文件/Wula/Building/Linked/WulaWall/SubstructureCorner_Tip_east.psd b/Source/美术与文本源文件/Wula/Building/Linked/WulaWall/SubstructureCorner_Tip_east.psd similarity index 100% rename from 美术与文本源文件/Wula/Building/Linked/WulaWall/SubstructureCorner_Tip_east.psd rename to Source/美术与文本源文件/Wula/Building/Linked/WulaWall/SubstructureCorner_Tip_east.psd diff --git a/美术与文本源文件/Wula/Building/Linked/WulaWall/SubstructureCorner_Tip_west.psd b/Source/美术与文本源文件/Wula/Building/Linked/WulaWall/SubstructureCorner_Tip_west.psd similarity index 100% rename from 美术与文本源文件/Wula/Building/Linked/WulaWall/SubstructureCorner_Tip_west.psd rename to Source/美术与文本源文件/Wula/Building/Linked/WulaWall/SubstructureCorner_Tip_west.psd diff --git a/美术与文本源文件/Wula/Building/Linked/WulaWall/WULA_Fortress_Wall_Smooth.sai2 b/Source/美术与文本源文件/Wula/Building/Linked/WulaWall/WULA_Fortress_Wall_Smooth.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Building/Linked/WulaWall/WULA_Fortress_Wall_Smooth.sai2 rename to Source/美术与文本源文件/Wula/Building/Linked/WulaWall/WULA_Fortress_Wall_Smooth.sai2 diff --git a/美术与文本源文件/Wula/Building/Linked/WulaWall/WulaWall_Atlas.png b/Source/美术与文本源文件/Wula/Building/Linked/WulaWall/WulaWall_Atlas.png similarity index 100% rename from 美术与文本源文件/Wula/Building/Linked/WulaWall/WulaWall_Atlas.png rename to Source/美术与文本源文件/Wula/Building/Linked/WulaWall/WulaWall_Atlas.png diff --git a/美术与文本源文件/Wula/Building/WULA_Chair.sai2 b/Source/美术与文本源文件/Wula/Building/WULA_Chair.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Building/WULA_Chair.sai2 rename to Source/美术与文本源文件/Wula/Building/WULA_Chair.sai2 diff --git a/美术与文本源文件/Wula/Building/WULA_Charging_Station_Synth_south.sai2 b/Source/美术与文本源文件/Wula/Building/WULA_Charging_Station_Synth_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Building/WULA_Charging_Station_Synth_south.sai2 rename to Source/美术与文本源文件/Wula/Building/WULA_Charging_Station_Synth_south.sai2 diff --git a/美术与文本源文件/Wula/Building/WULA_Communicator_Station.sai2 b/Source/美术与文本源文件/Wula/Building/WULA_Communicator_Station.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Building/WULA_Communicator_Station.sai2 rename to Source/美术与文本源文件/Wula/Building/WULA_Communicator_Station.sai2 diff --git a/美术与文本源文件/Wula/Building/WULA_Cube_Productor_BIO.sai2 b/Source/美术与文本源文件/Wula/Building/WULA_Cube_Productor_BIO.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Building/WULA_Cube_Productor_BIO.sai2 rename to Source/美术与文本源文件/Wula/Building/WULA_Cube_Productor_BIO.sai2 diff --git a/美术与文本源文件/Wula/Building/WULA_Cube_Productor_Component.sai2 b/Source/美术与文本源文件/Wula/Building/WULA_Cube_Productor_Component.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Building/WULA_Cube_Productor_Component.sai2 rename to Source/美术与文本源文件/Wula/Building/WULA_Cube_Productor_Component.sai2 diff --git a/美术与文本源文件/Wula/Building/WULA_Heavy_War_Machine_Productor_south.sai2 b/Source/美术与文本源文件/Wula/Building/WULA_Heavy_War_Machine_Productor_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Building/WULA_Heavy_War_Machine_Productor_south.sai2 rename to Source/美术与文本源文件/Wula/Building/WULA_Heavy_War_Machine_Productor_south.sai2 diff --git a/美术与文本源文件/Wula/Building/WULA_Nourishment_Center_Unit.sai2 b/Source/美术与文本源文件/Wula/Building/WULA_Nourishment_Center_Unit.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Building/WULA_Nourishment_Center_Unit.sai2 rename to Source/美术与文本源文件/Wula/Building/WULA_Nourishment_Center_Unit.sai2 diff --git a/美术与文本源文件/Wula/Building/WULA_Synth_Maintainer_south.sai2 b/Source/美术与文本源文件/Wula/Building/WULA_Synth_Maintainer_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Building/WULA_Synth_Maintainer_south.sai2 rename to Source/美术与文本源文件/Wula/Building/WULA_Synth_Maintainer_south.sai2 diff --git a/美术与文本源文件/Wula/Building/WULA_Synth_Server_south.sai2 b/Source/美术与文本源文件/Wula/Building/WULA_Synth_Server_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Building/WULA_Synth_Server_south.sai2 rename to Source/美术与文本源文件/Wula/Building/WULA_Synth_Server_south.sai2 diff --git a/美术与文本源文件/Wula/Building/WULA_Turret_Component.sai2 b/Source/美术与文本源文件/Wula/Building/WULA_Turret_Component.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Building/WULA_Turret_Component.sai2 rename to Source/美术与文本源文件/Wula/Building/WULA_Turret_Component.sai2 diff --git a/美术与文本源文件/Wula/Building/Wula_DarkEnergy_FuelTank.sai2 b/Source/美术与文本源文件/Wula/Building/Wula_DarkEnergy_FuelTank.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Building/Wula_DarkEnergy_FuelTank.sai2 rename to Source/美术与文本源文件/Wula/Building/Wula_DarkEnergy_FuelTank.sai2 diff --git a/美术与文本源文件/Wula/Hair/WULA_Double_Ponytail_Long_east.png b/Source/美术与文本源文件/Wula/Hair/WULA_Double_Ponytail_Long_east.png similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_Double_Ponytail_Long_east.png rename to Source/美术与文本源文件/Wula/Hair/WULA_Double_Ponytail_Long_east.png diff --git a/美术与文本源文件/Wula/Hair/WULA_Double_Ponytail_Long_north.png b/Source/美术与文本源文件/Wula/Hair/WULA_Double_Ponytail_Long_north.png similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_Double_Ponytail_Long_north.png rename to Source/美术与文本源文件/Wula/Hair/WULA_Double_Ponytail_Long_north.png diff --git a/美术与文本源文件/Wula/Hair/WULA_Double_Ponytail_Long_south.png b/Source/美术与文本源文件/Wula/Hair/WULA_Double_Ponytail_Long_south.png similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_Double_Ponytail_Long_south.png rename to Source/美术与文本源文件/Wula/Hair/WULA_Double_Ponytail_Long_south.png diff --git a/美术与文本源文件/Wula/Hair/WULA_Double_Ponytail_Long_south.sai2 b/Source/美术与文本源文件/Wula/Hair/WULA_Double_Ponytail_Long_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_Double_Ponytail_Long_south.sai2 rename to Source/美术与文本源文件/Wula/Hair/WULA_Double_Ponytail_Long_south.sai2 diff --git a/美术与文本源文件/Wula/Hair/WULA_High_Ponytail_east.png b/Source/美术与文本源文件/Wula/Hair/WULA_High_Ponytail_east.png similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_High_Ponytail_east.png rename to Source/美术与文本源文件/Wula/Hair/WULA_High_Ponytail_east.png diff --git a/美术与文本源文件/Wula/Hair/WULA_High_Ponytail_north.png b/Source/美术与文本源文件/Wula/Hair/WULA_High_Ponytail_north.png similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_High_Ponytail_north.png rename to Source/美术与文本源文件/Wula/Hair/WULA_High_Ponytail_north.png diff --git a/美术与文本源文件/Wula/Hair/WULA_High_Ponytail_south.png b/Source/美术与文本源文件/Wula/Hair/WULA_High_Ponytail_south.png similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_High_Ponytail_south.png rename to Source/美术与文本源文件/Wula/Hair/WULA_High_Ponytail_south.png diff --git a/美术与文本源文件/Wula/Hair/WULA_High_Ponytail_south.sai2 b/Source/美术与文本源文件/Wula/Hair/WULA_High_Ponytail_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_High_Ponytail_south.sai2 rename to Source/美术与文本源文件/Wula/Hair/WULA_High_Ponytail_south.sai2 diff --git a/美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_east.png b/Source/美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_east.png similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_east.png rename to Source/美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_east.png diff --git a/美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_north.png b/Source/美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_north.png similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_north.png rename to Source/美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_north.png diff --git a/美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_south.png b/Source/美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_south.png similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_south.png rename to Source/美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_south.png diff --git a/美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_south.sai2 b/Source/美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_south.sai2 rename to Source/美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_south.sai2 diff --git a/美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_west.png b/Source/美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_west.png similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_west.png rename to Source/美术与文本源文件/Wula/Hair/WULA_One_Side_Ponytail_west.png diff --git a/美术与文本源文件/Wula/Hair/WULA_Rotational_Ponytail_east.png b/Source/美术与文本源文件/Wula/Hair/WULA_Rotational_Ponytail_east.png similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_Rotational_Ponytail_east.png rename to Source/美术与文本源文件/Wula/Hair/WULA_Rotational_Ponytail_east.png diff --git a/美术与文本源文件/Wula/Hair/WULA_Rotational_Ponytail_north.png b/Source/美术与文本源文件/Wula/Hair/WULA_Rotational_Ponytail_north.png similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_Rotational_Ponytail_north.png rename to Source/美术与文本源文件/Wula/Hair/WULA_Rotational_Ponytail_north.png diff --git a/美术与文本源文件/Wula/Hair/WULA_Rotational_Ponytail_south.png b/Source/美术与文本源文件/Wula/Hair/WULA_Rotational_Ponytail_south.png similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_Rotational_Ponytail_south.png rename to Source/美术与文本源文件/Wula/Hair/WULA_Rotational_Ponytail_south.png diff --git a/美术与文本源文件/Wula/Hair/WULA_Rotational_Ponytail_south.sai2 b/Source/美术与文本源文件/Wula/Hair/WULA_Rotational_Ponytail_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_Rotational_Ponytail_south.sai2 rename to Source/美术与文本源文件/Wula/Hair/WULA_Rotational_Ponytail_south.sai2 diff --git a/美术与文本源文件/Wula/Hair/WULA_Scattered_Hair_Long_east.png b/Source/美术与文本源文件/Wula/Hair/WULA_Scattered_Hair_Long_east.png similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_Scattered_Hair_Long_east.png rename to Source/美术与文本源文件/Wula/Hair/WULA_Scattered_Hair_Long_east.png diff --git a/美术与文本源文件/Wula/Hair/WULA_Scattered_Hair_Long_north.png b/Source/美术与文本源文件/Wula/Hair/WULA_Scattered_Hair_Long_north.png similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_Scattered_Hair_Long_north.png rename to Source/美术与文本源文件/Wula/Hair/WULA_Scattered_Hair_Long_north.png diff --git a/美术与文本源文件/Wula/Hair/WULA_Scattered_Hair_Long_south.png b/Source/美术与文本源文件/Wula/Hair/WULA_Scattered_Hair_Long_south.png similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_Scattered_Hair_Long_south.png rename to Source/美术与文本源文件/Wula/Hair/WULA_Scattered_Hair_Long_south.png diff --git a/美术与文本源文件/Wula/Hair/WULA_Scattered_Hair_Long_south.sai2 b/Source/美术与文本源文件/Wula/Hair/WULA_Scattered_Hair_Long_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_Scattered_Hair_Long_south.sai2 rename to Source/美术与文本源文件/Wula/Hair/WULA_Scattered_Hair_Long_south.sai2 diff --git a/美术与文本源文件/Wula/Hair/WULA_Sidelocks_south.sai2 b/Source/美术与文本源文件/Wula/Hair/WULA_Sidelocks_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Hair/WULA_Sidelocks_south.sai2 rename to Source/美术与文本源文件/Wula/Hair/WULA_Sidelocks_south.sai2 diff --git a/美术与文本源文件/Wula/Item/WULA_Charge_Cube_No_Power.sai2 b/Source/美术与文本源文件/Wula/Item/WULA_Charge_Cube_No_Power.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Item/WULA_Charge_Cube_No_Power.sai2 rename to Source/美术与文本源文件/Wula/Item/WULA_Charge_Cube_No_Power.sai2 diff --git a/美术与文本源文件/Wula/Item/WULA_Dark_Matter_Item.sai2 b/Source/美术与文本源文件/Wula/Item/WULA_Dark_Matter_Item.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Item/WULA_Dark_Matter_Item.sai2 rename to Source/美术与文本源文件/Wula/Item/WULA_Dark_Matter_Item.sai2 diff --git a/美术与文本源文件/Wula/Item/WULA_Default_Item.sai2 b/Source/美术与文本源文件/Wula/Item/WULA_Default_Item.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Item/WULA_Default_Item.sai2 rename to Source/美术与文本源文件/Wula/Item/WULA_Default_Item.sai2 diff --git a/美术与文本源文件/Wula/Item/WULA_MechRepairKit.sai2 b/Source/美术与文本源文件/Wula/Item/WULA_MechRepairKit.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Item/WULA_MechRepairKit.sai2 rename to Source/美术与文本源文件/Wula/Item/WULA_MechRepairKit.sai2 diff --git a/美术与文本源文件/Wula/Item/WULA_Neutronium.sai2 b/Source/美术与文本源文件/Wula/Item/WULA_Neutronium.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Item/WULA_Neutronium.sai2 rename to Source/美术与文本源文件/Wula/Item/WULA_Neutronium.sai2 diff --git a/美术与文本源文件/Wula/Item/WULA_Soul_Wedge.sai2 b/Source/美术与文本源文件/Wula/Item/WULA_Soul_Wedge.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Item/WULA_Soul_Wedge.sai2 rename to Source/美术与文本源文件/Wula/Item/WULA_Soul_Wedge.sai2 diff --git a/美术与文本源文件/Wula/Item/WULA_Syhth_Passion_Trainer.sai2 b/Source/美术与文本源文件/Wula/Item/WULA_Syhth_Passion_Trainer.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Item/WULA_Syhth_Passion_Trainer.sai2 rename to Source/美术与文本源文件/Wula/Item/WULA_Syhth_Passion_Trainer.sai2 diff --git a/美术与文本源文件/Wula/Item/WULA_Syhth_Trainer.sai2 b/Source/美术与文本源文件/Wula/Item/WULA_Syhth_Trainer.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Item/WULA_Syhth_Trainer.sai2 rename to Source/美术与文本源文件/Wula/Item/WULA_Syhth_Trainer.sai2 diff --git a/美术与文本源文件/Wula/Item/WULA_charge_cube.sai2 b/Source/美术与文本源文件/Wula/Item/WULA_charge_cube.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Item/WULA_charge_cube.sai2 rename to Source/美术与文本源文件/Wula/Item/WULA_charge_cube.sai2 diff --git a/美术与文本源文件/Wula/Item/Wula_Zro.sai2 b/Source/美术与文本源文件/Wula/Item/Wula_Zro.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Item/Wula_Zro.sai2 rename to Source/美术与文本源文件/Wula/Item/Wula_Zro.sai2 diff --git a/美术与文本源文件/Wula/Mote/BeamSecondaryNoise_A.psd b/Source/美术与文本源文件/Wula/Mote/BeamSecondaryNoise_A.psd similarity index 100% rename from 美术与文本源文件/Wula/Mote/BeamSecondaryNoise_A.psd rename to Source/美术与文本源文件/Wula/Mote/BeamSecondaryNoise_A.psd diff --git a/美术与文本源文件/Wula/Mote/BeamSecondaryNoise_B.psd b/Source/美术与文本源文件/Wula/Mote/BeamSecondaryNoise_B.psd similarity index 100% rename from 美术与文本源文件/Wula/Mote/BeamSecondaryNoise_B.psd rename to Source/美术与文本源文件/Wula/Mote/BeamSecondaryNoise_B.psd diff --git a/美术与文本源文件/Wula/Mote/GraserBeam.psd b/Source/美术与文本源文件/Wula/Mote/GraserBeam.psd similarity index 100% rename from 美术与文本源文件/Wula/Mote/GraserBeam.psd rename to Source/美术与文本源文件/Wula/Mote/GraserBeam.psd diff --git a/美术与文本源文件/Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red.png b/Source/美术与文本源文件/Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red.png similarity index 100% rename from 美术与文本源文件/Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red.png rename to Source/美术与文本源文件/Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red.png diff --git a/美术与文本源文件/Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red_Double.png b/Source/美术与文本源文件/Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red_Double.png similarity index 100% rename from 美术与文本源文件/Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red_Double.png rename to Source/美术与文本源文件/Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red_Double.png diff --git a/美术与文本源文件/Wula/Projectile/WULA_Bullet_Dark_Matter_Beam.png b/Source/美术与文本源文件/Wula/Projectile/WULA_Bullet_Dark_Matter_Beam.png similarity index 100% rename from 美术与文本源文件/Wula/Projectile/WULA_Bullet_Dark_Matter_Beam.png rename to Source/美术与文本源文件/Wula/Projectile/WULA_Bullet_Dark_Matter_Beam.png diff --git a/美术与文本源文件/Wula/Projectile/WULA_Bullet_StarDrift_Shotgun_Spear.png b/Source/美术与文本源文件/Wula/Projectile/WULA_Bullet_StarDrift_Shotgun_Spear.png similarity index 100% rename from 美术与文本源文件/Wula/Projectile/WULA_Bullet_StarDrift_Shotgun_Spear.png rename to Source/美术与文本源文件/Wula/Projectile/WULA_Bullet_StarDrift_Shotgun_Spear.png diff --git a/美术与文本源文件/Wula/Projectile/WULA_Bullet_StarDrift_Shotgun_Spear.sai2 b/Source/美术与文本源文件/Wula/Projectile/WULA_Bullet_StarDrift_Shotgun_Spear.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Projectile/WULA_Bullet_StarDrift_Shotgun_Spear.sai2 rename to Source/美术与文本源文件/Wula/Projectile/WULA_Bullet_StarDrift_Shotgun_Spear.sai2 diff --git a/美术与文本源文件/Wula/Projectile/WULA_Mortar_Shell.png b/Source/美术与文本源文件/Wula/Projectile/WULA_Mortar_Shell.png similarity index 100% rename from 美术与文本源文件/Wula/Projectile/WULA_Mortar_Shell.png rename to Source/美术与文本源文件/Wula/Projectile/WULA_Mortar_Shell.png diff --git a/美术与文本源文件/Wula/Projectile/WULA_Photon_Missile.png b/Source/美术与文本源文件/Wula/Projectile/WULA_Photon_Missile.png similarity index 100% rename from 美术与文本源文件/Wula/Projectile/WULA_Photon_Missile.png rename to Source/美术与文本源文件/Wula/Projectile/WULA_Photon_Missile.png diff --git a/美术与文本源文件/Wula/Projectile/WULA_Shrapnel.png b/Source/美术与文本源文件/Wula/Projectile/WULA_Shrapnel.png similarity index 100% rename from 美术与文本源文件/Wula/Projectile/WULA_Shrapnel.png rename to Source/美术与文本源文件/Wula/Projectile/WULA_Shrapnel.png diff --git a/美术与文本源文件/Wula/Storyteller/WULA_Anisia.png b/Source/美术与文本源文件/Wula/Storyteller/WULA_Anisia.png similarity index 100% rename from 美术与文本源文件/Wula/Storyteller/WULA_Anisia.png rename to Source/美术与文本源文件/Wula/Storyteller/WULA_Anisia.png diff --git a/美术与文本源文件/Wula/Storyteller/WULA_Anisia_TINY.png b/Source/美术与文本源文件/Wula/Storyteller/WULA_Anisia_TINY.png similarity index 100% rename from 美术与文本源文件/Wula/Storyteller/WULA_Anisia_TINY.png rename to Source/美术与文本源文件/Wula/Storyteller/WULA_Anisia_TINY.png diff --git a/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-修女.sai2 b/Source/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-修女.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-修女.sai2 rename to Source/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-修女.sai2 diff --git a/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-修女特殊.sai2 b/Source/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-修女特殊.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-修女特殊.sai2 rename to Source/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-修女特殊.sai2 diff --git a/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-女仆.sai2 b/Source/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-女仆.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-女仆.sai2 rename to Source/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-女仆.sai2 diff --git a/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-皇家制服.png b/Source/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-皇家制服.png similarity index 100% rename from 美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-皇家制服.png rename to Source/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-皇家制服.png diff --git a/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-皇家制服.sai2 b/Source/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-皇家制服.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-皇家制服.sai2 rename to Source/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-皇家制服.sai2 diff --git a/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-默认.sai2 b/Source/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-默认.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-默认.sai2 rename to Source/美术与文本源文件/Wula/Storyteller/艾妮西娅/艾妮西娅-默认.sai2 diff --git a/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_east.dds b/Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_east.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_east.dds rename to Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_east.dds diff --git a/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_east.png b/Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_east.png rename to Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_east.png diff --git a/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_north.dds b/Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_north.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_north.dds rename to Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_north.dds diff --git a/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_north.png b/Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_north.png rename to Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_north.png diff --git a/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_south.dds b/Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_south.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_south.dds rename to Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_south.dds diff --git a/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_south.png b/Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_south.png rename to Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None_south.png diff --git a/美术与文本源文件/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_east.png b/Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_east.png rename to Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_east.png diff --git a/美术与文本源文件/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_north.png b/Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_north.png rename to Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_north.png diff --git a/美术与文本源文件/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_south.png b/Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_south.png rename to Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_south.png diff --git a/美术与文本源文件/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_east.dds b/Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_east.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_east.dds rename to Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_east.dds diff --git a/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_east.png b/Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_east.png rename to Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_east.png diff --git a/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_north.dds b/Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_north.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_north.dds rename to Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_north.dds diff --git a/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_north.png b/Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_north.png rename to Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_north.png diff --git a/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_south.dds b/Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_south.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_south.dds rename to Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_south.dds diff --git a/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_south.png b/Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_south.png rename to Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None_south.png diff --git a/美术与文本源文件/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_east.png b/Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_east.png rename to Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_east.png diff --git a/美术与文本源文件/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_north.png b/Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_north.png rename to Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_north.png diff --git a/美术与文本源文件/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_south.png b/Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_south.png rename to Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_south.png diff --git a/美术与文本源文件/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_east.dds b/Source/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_east.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_east.dds rename to Source/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_east.dds diff --git a/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_east.png b/Source/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_east.png rename to Source/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_east.png diff --git a/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_north.dds b/Source/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_north.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_north.dds rename to Source/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_north.dds diff --git a/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_north.png b/Source/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_north.png rename to Source/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_north.png diff --git a/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_south.dds b/Source/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_south.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_south.dds rename to Source/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_south.dds diff --git a/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_south.png b/Source/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_south.png rename to Source/美术与文本源文件/Wula/Things/WULA_Cat/AllegianceOverlays/None_south.png diff --git a/美术与文本源文件/Wula/Things/WULA_Cat/WULA_Cat_Thin_east.png b/Source/美术与文本源文件/Wula/Things/WULA_Cat/WULA_Cat_Thin_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Cat/WULA_Cat_Thin_east.png rename to Source/美术与文本源文件/Wula/Things/WULA_Cat/WULA_Cat_Thin_east.png diff --git a/美术与文本源文件/Wula/Things/WULA_Cat/WULA_Cat_Thin_north.png b/Source/美术与文本源文件/Wula/Things/WULA_Cat/WULA_Cat_Thin_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Cat/WULA_Cat_Thin_north.png rename to Source/美术与文本源文件/Wula/Things/WULA_Cat/WULA_Cat_Thin_north.png diff --git a/美术与文本源文件/Wula/Things/WULA_Cat/WULA_Cat_Thin_south.png b/Source/美术与文本源文件/Wula/Things/WULA_Cat/WULA_Cat_Thin_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Cat/WULA_Cat_Thin_south.png rename to Source/美术与文本源文件/Wula/Things/WULA_Cat/WULA_Cat_Thin_south.png diff --git a/美术与文本源文件/Wula/Things/WULA_Cat/WULA_Cat_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Things/WULA_Cat/WULA_Cat_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Cat/WULA_Cat_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Things/WULA_Cat/WULA_Cat_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_east.dds b/Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_east.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_east.dds rename to Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_east.dds diff --git a/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_east.png b/Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_east.png rename to Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_east.png diff --git a/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_north.dds b/Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_north.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_north.dds rename to Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_north.dds diff --git a/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_north.png b/Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_north.png rename to Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_north.png diff --git a/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_south.dds b/Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_south.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_south.dds rename to Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_south.dds diff --git a/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_south.png b/Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_south.png rename to Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/AllegianceOverlays/None_south.png diff --git a/美术与文本源文件/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_east.png b/Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_east.png rename to Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_east.png diff --git a/美术与文本源文件/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_north.png b/Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_north.png rename to Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_north.png diff --git a/美术与文本源文件/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_south.png b/Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_south.png rename to Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_south.png diff --git a/美术与文本源文件/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Things/WULA_Commander_Cat/WULA_Cat_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_east.dds b/Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_east.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_east.dds rename to Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_east.dds diff --git a/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_east.png b/Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_east.png rename to Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_east.png diff --git a/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_north.dds b/Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_north.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_north.dds rename to Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_north.dds diff --git a/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_north.png b/Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_north.png rename to Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_north.png diff --git a/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_south.dds b/Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_south.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_south.dds rename to Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_south.dds diff --git a/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_south.png b/Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_south.png rename to Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None_south.png diff --git a/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_east.png b/Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_east.png rename to Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_east.png diff --git a/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_north.png b/Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_north.png rename to Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_north.png diff --git a/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_south.png b/Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_south.png rename to Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_south.png diff --git a/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_east.dds b/Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_east.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_east.dds rename to Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_east.dds diff --git a/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_east.png b/Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_east.png rename to Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_east.png diff --git a/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_north.dds b/Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_north.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_north.dds rename to Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_north.dds diff --git a/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_north.png b/Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_north.png rename to Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_north.png diff --git a/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_south.dds b/Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_south.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_south.dds rename to Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_south.dds diff --git a/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_south.png b/Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_south.png rename to Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/AllegianceOverlays/None_south.png diff --git a/美术与文本源文件/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_east.png b/Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_east.png rename to Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_east.png diff --git a/美术与文本源文件/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_north.png b/Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_north.png rename to Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_north.png diff --git a/美术与文本源文件/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_south.png b/Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_south.png rename to Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_south.png diff --git a/美术与文本源文件/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_east.dds b/Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_east.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_east.dds rename to Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_east.dds diff --git a/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_east.png b/Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_east.png rename to Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_east.png diff --git a/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_north.dds b/Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_north.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_north.dds rename to Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_north.dds diff --git a/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_north.png b/Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_north.png rename to Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_north.png diff --git a/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_south.dds b/Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_south.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_south.dds rename to Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_south.dds diff --git a/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_south.png b/Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_south.png rename to Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/AllegianceOverlays/None_south.png diff --git a/美术与文本源文件/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_east.png b/Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_east.png rename to Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_east.png diff --git a/美术与文本源文件/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_north.png b/Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_north.png rename to Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_north.png diff --git a/美术与文本源文件/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_south.png b/Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_south.png rename to Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_south.png diff --git a/美术与文本源文件/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_south.sai2 b/Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_south.sai2 rename to Source/美术与文本源文件/Wula/Things/WULA_bomb_Cat/WULA_Cat_Thin_south.sai2 diff --git a/美术与文本源文件/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_east.png b/Source/美术与文本源文件/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_east.png rename to Source/美术与文本源文件/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_east.png diff --git a/美术与文本源文件/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_north.png b/Source/美术与文本源文件/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_north.png rename to Source/美术与文本源文件/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_north.png diff --git a/美术与文本源文件/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_south.png b/Source/美术与文本源文件/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_south.png rename to Source/美术与文本源文件/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_south.png diff --git a/美术与文本源文件/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_south.sai2 b/Source/美术与文本源文件/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_south.sai2 rename to Source/美术与文本源文件/Wula/Things/WulaSpecies/Addons/WULA_Addons_Antenna_south.sai2 diff --git a/美术与文本源文件/Wula/Things/WulaSpecies/Bodies/Naked_Thin_east.png b/Source/美术与文本源文件/Wula/Things/WulaSpecies/Bodies/Naked_Thin_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WulaSpecies/Bodies/Naked_Thin_east.png rename to Source/美术与文本源文件/Wula/Things/WulaSpecies/Bodies/Naked_Thin_east.png diff --git a/美术与文本源文件/Wula/Things/WulaSpecies/Bodies/Naked_Thin_east.sai2 b/Source/美术与文本源文件/Wula/Things/WulaSpecies/Bodies/Naked_Thin_east.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Things/WulaSpecies/Bodies/Naked_Thin_east.sai2 rename to Source/美术与文本源文件/Wula/Things/WulaSpecies/Bodies/Naked_Thin_east.sai2 diff --git a/美术与文本源文件/Wula/Things/WulaSpecies/Bodies/Naked_Thin_north.png b/Source/美术与文本源文件/Wula/Things/WulaSpecies/Bodies/Naked_Thin_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WulaSpecies/Bodies/Naked_Thin_north.png rename to Source/美术与文本源文件/Wula/Things/WulaSpecies/Bodies/Naked_Thin_north.png diff --git a/美术与文本源文件/Wula/Things/WulaSpecies/Bodies/Naked_Thin_south.png b/Source/美术与文本源文件/Wula/Things/WulaSpecies/Bodies/Naked_Thin_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WulaSpecies/Bodies/Naked_Thin_south.png rename to Source/美术与文本源文件/Wula/Things/WulaSpecies/Bodies/Naked_Thin_south.png diff --git a/美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_east.png b/Source/美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_east.png rename to Source/美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_east.png diff --git a/美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_north.png b/Source/美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_north.png rename to Source/美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_north.png diff --git a/美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_south.png b/Source/美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_south.png rename to Source/美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_south.png diff --git a/美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_south.sai2 b/Source/美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_south.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_south.sai2 rename to Source/美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_south.sai2 diff --git a/美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_west.png b/Source/美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_west.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_west.png rename to Source/美术与文本源文件/Wula/Things/WulaSpecies/Heads/Average_Normal_west.png diff --git a/美术与文本源文件/Wula/Things/WulaSpecies/WULA_Species_Icon.png b/Source/美术与文本源文件/Wula/Things/WulaSpecies/WULA_Species_Icon.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WulaSpecies/WULA_Species_Icon.png rename to Source/美术与文本源文件/Wula/Things/WulaSpecies/WULA_Species_Icon.png diff --git a/美术与文本源文件/Wula/Things/WulaSpecies/Wounds/WULA_Species_Wound_None.png b/Source/美术与文本源文件/Wula/Things/WulaSpecies/Wounds/WULA_Species_Wound_None.png similarity index 100% rename from 美术与文本源文件/Wula/Things/WulaSpecies/Wounds/WULA_Species_Wound_None.png rename to Source/美术与文本源文件/Wula/Things/WulaSpecies/Wounds/WULA_Species_Wound_None.png diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_east.dds b/Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_east.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_east.dds rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_east.dds diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_east.png b/Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_east.png rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_east.png diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_north.dds b/Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_north.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_north.dds rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_north.dds diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_north.png b/Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_north.png rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_north.png diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_south.dds b/Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_south.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_south.dds rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_south.dds diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_south.png b/Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_south.png rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/AllegianceOverlays/None_south.png diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_east.png b/Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_east.png rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_east.png diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_east.sai2 b/Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_east.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_east.sai2 rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_east.sai2 diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_north.png b/Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_north.png rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_north.png diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_south.png b/Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_south.png rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Bodies/Naked_Thin_south.png diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Wula_AI_Bomb_Mother_Icon.png b/Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Wula_AI_Bomb_Mother_Icon.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Wula_AI_Bomb_Mother_Icon.png rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Bomb_Mother/Wula_AI_Bomb_Mother_Icon.png diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_east.dds b/Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_east.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_east.dds rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_east.dds diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_east.png b/Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_east.png rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_east.png diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_north.dds b/Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_north.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_north.dds rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_north.dds diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_north.png b/Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_north.png rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_north.png diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_south.dds b/Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_south.dds similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_south.dds rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_south.dds diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_south.png b/Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_south.png rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/AllegianceOverlays/None_south.png diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_east.png b/Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_east.png rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_east.png diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_east.sai2 b/Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_east.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_east.sai2 rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_east.sai2 diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_north.png b/Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_north.png rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_north.png diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_south.png b/Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_south.png rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Bodies/Naked_Thin_south.png diff --git a/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Wula_AI_Heavy_Panzer_Icon.png b/Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Wula_AI_Heavy_Panzer_Icon.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Wula_AI_Heavy_Panzer_Icon.png rename to Source/美术与文本源文件/Wula/Things/Wula_AI_Heavy_Panzer/Wula_AI_Heavy_Panzer_Icon.png diff --git a/美术与文本源文件/Wula/Things/Wula_Armour/Bodies/Naked_Thin_east.png b/Source/美术与文本源文件/Wula/Things/Wula_Armour/Bodies/Naked_Thin_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Armour/Bodies/Naked_Thin_east.png rename to Source/美术与文本源文件/Wula/Things/Wula_Armour/Bodies/Naked_Thin_east.png diff --git a/美术与文本源文件/Wula/Things/Wula_Armour/Bodies/Naked_Thin_east.sai2 b/Source/美术与文本源文件/Wula/Things/Wula_Armour/Bodies/Naked_Thin_east.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Armour/Bodies/Naked_Thin_east.sai2 rename to Source/美术与文本源文件/Wula/Things/Wula_Armour/Bodies/Naked_Thin_east.sai2 diff --git a/美术与文本源文件/Wula/Things/Wula_Armour/Bodies/Naked_Thin_north.png b/Source/美术与文本源文件/Wula/Things/Wula_Armour/Bodies/Naked_Thin_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Armour/Bodies/Naked_Thin_north.png rename to Source/美术与文本源文件/Wula/Things/Wula_Armour/Bodies/Naked_Thin_north.png diff --git a/美术与文本源文件/Wula/Things/Wula_Armour/Bodies/Naked_Thin_south.png b/Source/美术与文本源文件/Wula/Things/Wula_Armour/Bodies/Naked_Thin_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Armour/Bodies/Naked_Thin_south.png rename to Source/美术与文本源文件/Wula/Things/Wula_Armour/Bodies/Naked_Thin_south.png diff --git a/美术与文本源文件/Wula/Things/Wula_Armour/Heads/Average_Normal_east.png b/Source/美术与文本源文件/Wula/Things/Wula_Armour/Heads/Average_Normal_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Armour/Heads/Average_Normal_east.png rename to Source/美术与文本源文件/Wula/Things/Wula_Armour/Heads/Average_Normal_east.png diff --git a/美术与文本源文件/Wula/Things/Wula_Armour/Heads/Average_Normal_north.png b/Source/美术与文本源文件/Wula/Things/Wula_Armour/Heads/Average_Normal_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Armour/Heads/Average_Normal_north.png rename to Source/美术与文本源文件/Wula/Things/Wula_Armour/Heads/Average_Normal_north.png diff --git a/美术与文本源文件/Wula/Things/Wula_Armour/Heads/Average_Normal_south.png b/Source/美术与文本源文件/Wula/Things/Wula_Armour/Heads/Average_Normal_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Armour/Heads/Average_Normal_south.png rename to Source/美术与文本源文件/Wula/Things/Wula_Armour/Heads/Average_Normal_south.png diff --git a/美术与文本源文件/Wula/Things/Wula_Armour/Wula_Armour_Icon.png b/Source/美术与文本源文件/Wula/Things/Wula_Armour/Wula_Armour_Icon.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Armour/Wula_Armour_Icon.png rename to Source/美术与文本源文件/Wula/Things/Wula_Armour/Wula_Armour_Icon.png diff --git a/美术与文本源文件/Wula/Things/Wula_Armour/abandon/Naked_Thin_east.png b/Source/美术与文本源文件/Wula/Things/Wula_Armour/abandon/Naked_Thin_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Armour/abandon/Naked_Thin_east.png rename to Source/美术与文本源文件/Wula/Things/Wula_Armour/abandon/Naked_Thin_east.png diff --git a/美术与文本源文件/Wula/Things/Wula_Armour/abandon/Naked_Thin_east.sai2 b/Source/美术与文本源文件/Wula/Things/Wula_Armour/abandon/Naked_Thin_east.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Armour/abandon/Naked_Thin_east.sai2 rename to Source/美术与文本源文件/Wula/Things/Wula_Armour/abandon/Naked_Thin_east.sai2 diff --git a/美术与文本源文件/Wula/Things/Wula_Armour/abandon/Naked_Thin_north.png b/Source/美术与文本源文件/Wula/Things/Wula_Armour/abandon/Naked_Thin_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Armour/abandon/Naked_Thin_north.png rename to Source/美术与文本源文件/Wula/Things/Wula_Armour/abandon/Naked_Thin_north.png diff --git a/美术与文本源文件/Wula/Things/Wula_Armour/abandon/Naked_Thin_south.png b/Source/美术与文本源文件/Wula/Things/Wula_Armour/abandon/Naked_Thin_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Armour/abandon/Naked_Thin_south.png rename to Source/美术与文本源文件/Wula/Things/Wula_Armour/abandon/Naked_Thin_south.png diff --git a/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_east.png b/Source/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_east.png rename to Source/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_east.png diff --git a/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_east.sai2 b/Source/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_east.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_east.sai2 rename to Source/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_east.sai2 diff --git a/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_north.png b/Source/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_north.png rename to Source/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_north.png diff --git a/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_south.png b/Source/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_south.png rename to Source/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Bodies/Naked_Thin_south.png diff --git a/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_east.png b/Source/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_east.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_east.png rename to Source/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_east.png diff --git a/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_north.png b/Source/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_north.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_north.png rename to Source/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_north.png diff --git a/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_south.png b/Source/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_south.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_south.png rename to Source/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Heads/Average_Normal_south.png diff --git a/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Wula_Psi_Titan_Icon.png b/Source/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Wula_Psi_Titan_Icon.png similarity index 100% rename from 美术与文本源文件/Wula/Things/Wula_Psi_Titan/Wula_Psi_Titan_Icon.png rename to Source/美术与文本源文件/Wula/Things/Wula_Psi_Titan/Wula_Psi_Titan_Icon.png diff --git a/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_CLoak_Ability.png b/Source/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_CLoak_Ability.png similarity index 100% rename from 美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_CLoak_Ability.png rename to Source/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_CLoak_Ability.png diff --git a/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Explosive_Ability.png b/Source/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Explosive_Ability.png similarity index 100% rename from 美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Explosive_Ability.png rename to Source/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Explosive_Ability.png diff --git a/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Feather_Ability.png b/Source/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Feather_Ability.png similarity index 100% rename from 美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Feather_Ability.png rename to Source/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Feather_Ability.png diff --git a/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Flash_Ability.png b/Source/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Flash_Ability.png similarity index 100% rename from 美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Flash_Ability.png rename to Source/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Flash_Ability.png diff --git a/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Lost_Ability.png b/Source/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Lost_Ability.png similarity index 100% rename from 美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Lost_Ability.png rename to Source/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Lost_Ability.png diff --git a/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Perception_Ability.png b/Source/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Perception_Ability.png similarity index 100% rename from 美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Perception_Ability.png rename to Source/美术与文本源文件/Wula/UI/Abilities/WULA_MW_Scepter_Of_Perception_Ability.png diff --git a/美术与文本源文件/Wula/UI/Abilities/WULA_Scepter_Of_Heaven_Ability.png b/Source/美术与文本源文件/Wula/UI/Abilities/WULA_Scepter_Of_Heaven_Ability.png similarity index 100% rename from 美术与文本源文件/Wula/UI/Abilities/WULA_Scepter_Of_Heaven_Ability.png rename to Source/美术与文本源文件/Wula/UI/Abilities/WULA_Scepter_Of_Heaven_Ability.png diff --git a/美术与文本源文件/Wula/UI/EventUI/新建画布1.sai2 b/Source/美术与文本源文件/Wula/UI/EventUI/新建画布1.sai2 similarity index 100% rename from 美术与文本源文件/Wula/UI/EventUI/新建画布1.sai2 rename to Source/美术与文本源文件/Wula/UI/EventUI/新建画布1.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Armour_Lance.png b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Armour_Lance.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Armour_Lance.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Armour_Lance.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Armour_Lance.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Armour_Lance.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Armour_Lance.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Armour_Lance.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Breaker_Bar.png b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Breaker_Bar.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Breaker_Bar.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Breaker_Bar.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Breaker_Bar.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Breaker_Bar.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Breaker_Bar.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Breaker_Bar.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_ChainSword.png b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_ChainSword.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_ChainSword.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_ChainSword.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_ChainSword.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_ChainSword.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_ChainSword.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_ChainSword.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Charge_Mace.png b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Charge_Mace.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Charge_Mace.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Charge_Mace.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Charge_Mace.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Charge_Mace.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Charge_Mace.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Charge_Mace.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Constructor_Hammer.png b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Constructor_Hammer.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Constructor_Hammer.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Constructor_Hammer.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Constructor_Hammer.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Constructor_Hammer.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Constructor_Hammer.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Constructor_Hammer.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Glaive.png b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Glaive.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Glaive.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Glaive.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Lance.png b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Lance.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Lance.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Lance.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Lance.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Lance.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Lance.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Lance.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Mace.png b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Mace.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Mace.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Mace.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_CLoak.png b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_CLoak.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_CLoak.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_CLoak.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_CLoak.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_CLoak.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_CLoak.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_CLoak.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Explosive.png b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Explosive.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Explosive.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Explosive.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Explosive.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Explosive.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Explosive.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Explosive.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Feather.png b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Feather.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Feather.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Feather.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Feather.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Feather.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Feather.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Feather.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Flash.png b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Flash.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Flash.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Flash.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Flash.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Flash.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Flash.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Flash.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Heaven.png b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Heaven.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Heaven.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Heaven.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Heaven.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Heaven.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Heaven.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Heaven.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Lost.png b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Lost.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Lost.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Lost.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Lost.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Lost.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Lost.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Lost.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Perception.png b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Perception.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Perception.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Perception.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Perception.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Perception.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Perception.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_MW_Scepter_Of_Perception.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_RW_AutoCannon.png b/Source/美术与文本源文件/Wula/Weapon/WULA_RW_AutoCannon.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_RW_AutoCannon.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_RW_AutoCannon.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_RW_AutoCannon.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_RW_AutoCannon.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_RW_AutoCannon.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_RW_AutoCannon.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_RW_Auto_GL.png b/Source/美术与文本源文件/Wula/Weapon/WULA_RW_Auto_GL.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_RW_Auto_GL.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_RW_Auto_GL.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_RW_Auto_GL.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_RW_Auto_GL.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_RW_Auto_GL.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_RW_Auto_GL.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_RW_Base_AR.png b/Source/美术与文本源文件/Wula/Weapon/WULA_RW_Base_AR.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_RW_Base_AR.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_RW_Base_AR.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_RW_Base_AR_Cat.png b/Source/美术与文本源文件/Wula/Weapon/WULA_RW_Base_AR_Cat.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_RW_Base_AR_Cat.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_RW_Base_AR_Cat.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_RW_DM_AR.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_RW_DM_AR.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_RW_DM_AR.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_RW_DM_AR.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_RW_DM_Cannon.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_RW_DM_Cannon.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_RW_DM_Cannon.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_RW_DM_Cannon.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_RW_Fractal_RF.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_RW_Fractal_RF.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_RW_Fractal_RF.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_RW_Fractal_RF.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_RW_Handle_Cannon.png b/Source/美术与文本源文件/Wula/Weapon/WULA_RW_Handle_Cannon.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_RW_Handle_Cannon.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_RW_Handle_Cannon.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_RW_Handle_Cannon.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_RW_Handle_Cannon.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_RW_Handle_Cannon.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_RW_Handle_Cannon.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_RW_Sphene_MG.png b/Source/美术与文本源文件/Wula/Weapon/WULA_RW_Sphene_MG.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_RW_Sphene_MG.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_RW_Sphene_MG.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_RW_Sphene_MG.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_RW_Sphene_MG.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_RW_Sphene_MG.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_RW_Sphene_MG.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_RW_StarDrift_SG.png b/Source/美术与文本源文件/Wula/Weapon/WULA_RW_StarDrift_SG.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_RW_StarDrift_SG.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_RW_StarDrift_SG.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_RW_StarDrift_Shotgun.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_RW_StarDrift_Shotgun.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_RW_StarDrift_Shotgun.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_RW_StarDrift_Shotgun.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_SP_Spell_Medium.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_SP_Spell_Medium.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_SP_Spell_Medium.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_SP_Spell_Medium.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_WM_Panzer_Autocannon.png b/Source/美术与文本源文件/Wula/Weapon/WULA_WM_Panzer_Autocannon.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_WM_Panzer_Autocannon.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_WM_Panzer_Autocannon.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_WM_Panzer_Autocannon.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_WM_Panzer_Autocannon.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_WM_Panzer_Autocannon.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_WM_Panzer_Autocannon.sai2 diff --git a/美术与文本源文件/Wula/Weapon/WULA_WM_Panzer_Turret.png b/Source/美术与文本源文件/Wula/Weapon/WULA_WM_Panzer_Turret.png similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_WM_Panzer_Turret.png rename to Source/美术与文本源文件/Wula/Weapon/WULA_WM_Panzer_Turret.png diff --git a/美术与文本源文件/Wula/Weapon/WULA_WM_Panzer_Turret.sai2 b/Source/美术与文本源文件/Wula/Weapon/WULA_WM_Panzer_Turret.sai2 similarity index 100% rename from 美术与文本源文件/Wula/Weapon/WULA_WM_Panzer_Turret.sai2 rename to Source/美术与文本源文件/Wula/Weapon/WULA_WM_Panzer_Turret.sai2 diff --git a/美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_Broken_Personality_Faction.png b/Source/美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_Broken_Personality_Faction.png similarity index 100% rename from 美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_Broken_Personality_Faction.png rename to Source/美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_Broken_Personality_Faction.png diff --git a/美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_Broken_Personality_Faction.sai2 b/Source/美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_Broken_Personality_Faction.sai2 similarity index 100% rename from 美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_Broken_Personality_Faction.sai2 rename to Source/美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_Broken_Personality_Faction.sai2 diff --git a/美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_FE_Faction.png b/Source/美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_FE_Faction.png similarity index 100% rename from 美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_FE_Faction.png rename to Source/美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_FE_Faction.png diff --git a/美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_FE_Faction.sai2 b/Source/美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_FE_Faction.sai2 similarity index 100% rename from 美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_FE_Faction.sai2 rename to Source/美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_FE_Faction.sai2 diff --git a/美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_FE_Spiritualist_Faction.sai2 b/Source/美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_FE_Spiritualist_Faction.sai2 similarity index 100% rename from 美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_FE_Spiritualist_Faction.sai2 rename to Source/美术与文本源文件/Wula/World/WorldObjects/Expanding/Wula_FE_Spiritualist_Faction.sai2 diff --git a/美术与文本源文件/thumbnail.png b/Source/美术与文本源文件/thumbnail.png similarity index 100% rename from 美术与文本源文件/thumbnail.png rename to Source/美术与文本源文件/thumbnail.png diff --git a/美术与文本源文件/thumbnail.sai2 b/Source/美术与文本源文件/thumbnail.sai2 similarity index 100% rename from 美术与文本源文件/thumbnail.sai2 rename to Source/美术与文本源文件/thumbnail.sai2 diff --git a/美术与文本源文件/《堕落乌拉帝国》.txt b/Source/美术与文本源文件/《堕落乌拉帝国》.txt similarity index 100% rename from 美术与文本源文件/《堕落乌拉帝国》.txt rename to Source/美术与文本源文件/《堕落乌拉帝国》.txt diff --git a/美术与文本源文件/修女乌拉.sai2 b/Source/美术与文本源文件/修女乌拉.sai2 similarity index 100% rename from 美术与文本源文件/修女乌拉.sai2 rename to Source/美术与文本源文件/修女乌拉.sai2 diff --git a/美术与文本源文件/宣传图2.png b/Source/美术与文本源文件/宣传图2.png similarity index 100% rename from 美术与文本源文件/宣传图2.png rename to Source/美术与文本源文件/宣传图2.png diff --git a/美术与文本源文件/宣传图2.sai2 b/Source/美术与文本源文件/宣传图2.sai2 similarity index 100% rename from 美术与文本源文件/宣传图2.sai2 rename to Source/美术与文本源文件/宣传图2.sai2 diff --git a/美术与文本源文件/宣传图3.png b/Source/美术与文本源文件/宣传图3.png similarity index 100% rename from 美术与文本源文件/宣传图3.png rename to Source/美术与文本源文件/宣传图3.png diff --git a/美术与文本源文件/宣传图3.sai2 b/Source/美术与文本源文件/宣传图3.sai2 similarity index 100% rename from 美术与文本源文件/宣传图3.sai2 rename to Source/美术与文本源文件/宣传图3.sai2 diff --git a/美术与文本源文件/宣传图4.sai2 b/Source/美术与文本源文件/宣传图4.sai2 similarity index 100% rename from 美术与文本源文件/宣传图4.sai2 rename to Source/美术与文本源文件/宣传图4.sai2 diff --git a/美术与文本源文件/宣传图5.png b/Source/美术与文本源文件/宣传图5.png similarity index 100% rename from 美术与文本源文件/宣传图5.png rename to Source/美术与文本源文件/宣传图5.png diff --git a/美术与文本源文件/故障的arc代码之扇形攻击.txt b/Source/美术与文本源文件/故障的arc代码之扇形攻击.txt similarity index 100% rename from 美术与文本源文件/故障的arc代码之扇形攻击.txt rename to Source/美术与文本源文件/故障的arc代码之扇形攻击.txt diff --git a/美术与文本源文件/新建文本文档.txt b/Source/美术与文本源文件/新建文本文档.txt similarity index 100% rename from 美术与文本源文件/新建文本文档.txt rename to Source/美术与文本源文件/新建文本文档.txt diff --git a/美术与文本源文件/眉栏.sai2 b/Source/美术与文本源文件/眉栏.sai2 similarity index 100% rename from 美术与文本源文件/眉栏.sai2 rename to Source/美术与文本源文件/眉栏.sai2 diff --git a/美术与文本源文件/群星文本/dip_messages_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/dip_messages_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/dip_messages_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/dip_messages_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/fallen_empire_awake_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/fallen_empire_awake_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/fallen_empire_awake_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/fallen_empire_awake_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/fallen_empire_buildings_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/fallen_empire_buildings_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/fallen_empire_buildings_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/fallen_empire_buildings_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/fallen_empire_dip_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/fallen_empire_dip_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/fallen_empire_dip_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/fallen_empire_dip_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/fallen_empire_events_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/fallen_empire_events_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/fallen_empire_events_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/fallen_empire_events_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/fallen_empire_jobs_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/fallen_empire_jobs_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/fallen_empire_jobs_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/fallen_empire_jobs_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/fallen_empire_main_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/fallen_empire_main_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/fallen_empire_main_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/fallen_empire_main_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/fallen_empire_planet_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/fallen_empire_planet_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/fallen_empire_planet_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/fallen_empire_planet_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/fallen_empire_test_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/fallen_empire_test_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/fallen_empire_test_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/fallen_empire_test_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/name_lists/name_list_WULA_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/name_lists/name_list_WULA_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/name_lists/name_list_WULA_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/name_lists/name_list_WULA_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_ascension_perks_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_ascension_perks_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_ascension_perks_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_ascension_perks_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_civics_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_civics_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_civics_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_civics_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_concept_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_concept_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_concept_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_concept_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_courier_events_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_courier_events_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_courier_events_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_courier_events_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_fallen_empire_machine_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_fallen_empire_machine_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_fallen_empire_machine_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_fallen_empire_machine_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_fallen_empire_materialist_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_fallen_empire_materialist_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_fallen_empire_materialist_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_fallen_empire_materialist_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_fallen_empire_preftl_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_fallen_empire_preftl_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_fallen_empire_preftl_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_fallen_empire_preftl_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_fallen_empire_rogue_trader_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_fallen_empire_rogue_trader_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_fallen_empire_rogue_trader_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_fallen_empire_rogue_trader_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_fallen_empire_spiritualist_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_fallen_empire_spiritualist_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_fallen_empire_spiritualist_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_fallen_empire_spiritualist_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_fallen_empire_xenophile_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_fallen_empire_xenophile_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_fallen_empire_xenophile_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_fallen_empire_xenophile_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_fallen_empire_xenophobe_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_fallen_empire_xenophobe_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_fallen_empire_xenophobe_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_fallen_empire_xenophobe_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_fallen_empires_mid_events_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_fallen_empires_mid_events_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_fallen_empires_mid_events_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_fallen_empires_mid_events_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_fleet_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_fleet_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_fleet_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_fleet_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_megastructure_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_megastructure_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_megastructure_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_megastructure_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_modifiers_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_modifiers_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_modifiers_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_modifiers_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_narrative_events_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_narrative_events_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_narrative_events_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_narrative_events_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_observation_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_observation_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_observation_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_observation_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_operation_event_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_operation_event_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_operation_event_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_operation_event_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_policy_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_policy_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_policy_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_policy_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_species_rights_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_species_rights_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_species_rights_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_species_rights_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_tech_componment_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_tech_componment_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_tech_componment_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_tech_componment_l_simp_chinese.yml diff --git a/美术与文本源文件/群星文本/wula_traits_l_simp_chinese.yml b/Source/美术与文本源文件/群星文本/wula_traits_l_simp_chinese.yml similarity index 100% rename from 美术与文本源文件/群星文本/wula_traits_l_simp_chinese.yml rename to Source/美术与文本源文件/群星文本/wula_traits_l_simp_chinese.yml diff --git a/WulaFallenEmpireTest.rar b/WulaFallenEmpireTest.rar deleted file mode 100644 index 46163272..00000000 Binary files a/WulaFallenEmpireTest.rar and /dev/null differ