public Skill(SkillCollection skills, PlayerFields field, SkillRecord record, SkillLine skillLine) { PlayerField = field; m_skills = skills; m_record = record; SkillLine = skillLine; m_skills.Owner.SetUInt16Low(field, (ushort)skillLine.Id); m_skills.Owner.SetUInt16High(field, skillLine.Abandonable); SetCurrentValueSilently(record.CurrentValue); MaxValue = record.MaxValue; }
public Skill(SkillCollection skills, PlayerFields field, SkillLine skill, uint value, uint max) { m_record = new SkillRecord { SkillId = skill.Id, OwnerId = skills.Owner.Record.Guid }; m_skills = skills; PlayerField = field; SkillLine = skill; m_skills.Owner.SetUInt16Low(field, (ushort)skill.Id); m_skills.Owner.SetUInt16High(field, skill.Abandonable); CurrentValue = (ushort)value; MaxValue = (ushort)max; m_record.CreateLater(); }
protected override IEnumerable <Toil> MakeNewToils() { yield return(Toils_Reserve.Reserve(TargetIndex.A)); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.A).FailOnSomeonePhysicallyInteracting(TargetIndex.A)); Toil fillUp = new Toil() { defaultCompleteMode = ToilCompleteMode.Never }; fillUp.tickAction = delegate { Pawn actor = fillUp.actor; if (Crack.Filled >= 100) { Crack.Destroy(); Find.LetterStack.ReceiveLetter("Building_TribalCrack_Title".Translate(), "Building_TribalCrack_Desc".Translate(actor.Name.ToStringFull), LetterDefOf.PositiveEvent); EndJobWith(JobCondition.Succeeded); return; } SkillRecord record = actor.skills.GetSkill(SkillDefOf.Construction); float statValue = 0f; if (!record.TotallyDisabled) { statValue = actor.GetStatValue(StatDefOf.MeleeDPS); statValue *= 0.003f; } Crack.Filled += 0.00013f + statValue; }; yield return(fillUp); }
public static void GivePawnTrait([NotNull] Pawn pawn, [NotNull] Trait trait) { ForciblyGivePawnTrait(pawn, trait); TraitDegreeData val = trait.CurrentData; if (val?.skillGains == null) { return; } foreach (KeyValuePair <SkillDef, int> skillGain in val.skillGains) { SkillRecord skill = pawn.skills.GetSkill(skillGain.Key); if (skill.TotallyDisabled) { continue; } skill.Level += skillGain.Value; } List <WorkTypeDef> disabledWorkTypes = trait.GetDisabledWorkTypes().ToList(); if (disabledWorkTypes.Count <= 0) { return; } pawn.Notify_DisabledWorkTypesChanged(); foreach (WorkTypeDef workType in disabledWorkTypes.Where(workType => !pawn.WorkTypeIsDisabled(workType))) { pawn.workSettings.Disable(workType); } }
public override float RandomSelectionWeight(Pawn initiator, Pawn recipient) { if (initiator == null || recipient == null) { return(0f); } var weightMult = 0; taggedInitiatorSkill = RandomSkillToDiscuss(initiator, recipient); //no passion, recipient is more educated in relevant skills than initiator, or passionate skills are disabled on initiator or recipient :( if (taggedInitiatorSkill == null) { return(0f); } SkillRecord recipientSkill = recipient.skills.GetSkill(taggedInitiatorSkill.def); //baseWeight.min = 0.20, baseWeight.max = 0.80 weightMult += (int)recipientSkill.passion + (int)taggedInitiatorSkill.passion; return(ModSettings.instance.baseInteractionWeight * weightMult * ModSettings.instance.interactionAdjustMultiplier); }
private static void Postfix(Object model, SkillDef def, object __instance) { var r = AccessTools.PropertyGetter(Patch_RimHUDBase.hudPawnModel, "Base"); Pawn b = (Pawn)r.Invoke(model, null); Pawn_SkillTracker st = b.skills; SkillRecord skillRecord = (st != null) ? st.GetSkill(def) : null; if (skillRecord == null) { return; } var label = AccessTools.Field(Patch_RimHUDBase.hudSkillModel, "<Label>k__BackingField"); if (label == null) { return; } InterestDef i = InterestBase.interestList[(int)skillRecord.passion]; string end = ""; float val = i.GetValue(); if (val < 0) { end = new string('-', -(int)Math.Floor(val / 75.0f)); } else if (val > 0) { end = new string('+', (int)Math.Floor(val / 75.0f)); } string l = def.LabelCap + end; label.SetValue(__instance, l); }
//战斗 public override void OnEnterCombat(ObjNPC npc) { //先停止移动 if (npc.IsMoving()) { npc.StopMove(); } //保存下进入战斗时的位置,距离这个位置太远了就要回家 mBackPosition = npc.GetPosition(); //获得目标 var enemy = npc.Scene.FindCharacter(npc.LastEnemyId); if (null != enemy) { npc.TurnFaceTo(enemy.GetPosition()); } npc.BroadcastDirection(); //保存普攻数据 if (-1 != npc.NormalSkillId) { mTableNormalSkill = Table.GetSkill(npc.NormalSkillId); //计算普攻技能距离 mSkillDistance = SkillManager.GetSkillDistance((SkillTargetType)mTableNormalSkill.TargetType, mTableNormalSkill.TargetParam); //上来先来个cd,要不攻击者一攻击怪一瞬间怪就反击 GenNextNormalAttackTime(); } mNoMoveTime = 0; }
public static SkillRecord GetHighestSkillOfpack(Pawn pawn) { AvaliPack pack = GetPack(pawn); int highestSkillLevel = 0; SkillRecord highestSkill = null; foreach (Pawn pawn2 in pack.pawns) { List <SkillRecord> list = new List <SkillRecord>(); foreach (SkillRecord skillRecord in pawn2.skills.skills) { list.Add(skillRecord); foreach (SkillRecord skill in list) { if (skill.Level > highestSkillLevel) { highestSkillLevel = skill.Level; highestSkill = skill; } } } } return(highestSkill); }
public static SkillRecord GetHighestPackSkill(this Pawn thisPawn, List <Pawn> pack) { pack.Add(thisPawn); SkillRecord highestSkill = null; int highestSkillLevel = 0; for (int i = 0; i < pack.Count; i++) { Pawn pawn = pack[i]; List <SkillRecord> pawnSkills = new List <SkillRecord>(); pawnSkills.Add(pawn.skills.GetSkill(SkillDefOf.Animals)); pawnSkills.Add(pawn.skills.GetSkill(SkillDefOf.Artistic)); pawnSkills.Add(pawn.skills.GetSkill(SkillDefOf.Construction)); pawnSkills.Add(pawn.skills.GetSkill(SkillDefOf.Cooking)); pawnSkills.Add(pawn.skills.GetSkill(SkillDefOf.Crafting)); pawnSkills.Add(pawn.skills.GetSkill(SkillDefOf.Plants)); pawnSkills.Add(pawn.skills.GetSkill(SkillDefOf.Intellectual)); pawnSkills.Add(pawn.skills.GetSkill(SkillDefOf.Medicine)); pawnSkills.Add(pawn.skills.GetSkill(SkillDefOf.Melee)); pawnSkills.Add(pawn.skills.GetSkill(SkillDefOf.Mining)); pawnSkills.Add(pawn.skills.GetSkill(SkillDefOf.Shooting)); pawnSkills.Add(pawn.skills.GetSkill(SkillDefOf.Social)); for (int j = 0; j < pawnSkills.Count; j++) { SkillRecord skill = pawnSkills[j]; if (!skill.TotallyDisabled && skill.Level > highestSkillLevel) { highestSkill = skill; highestSkillLevel = skill.Level; } } } return(highestSkill); }
public override void OnIntervalPassed(Pawn pawn, Hediff cause) { if (!pawn.IsColonist) { return; } var active = InterestBase.GetActiveSkill(pawn); if (active == null) { DecreaseAllergy(pawn); return; } SkillRecord skill = pawn.skills.GetSkill(active); if (skill == null) { return; } int passion = (int)skill.passion; int allergic = InterestBase.interestList["DAllergic"]; HediffSet hediffSet = pawn.health.hediffSet; Hediff firstHediffOfDef = hediffSet.GetFirstHediffOfDef(this.hediff, false); if (passion != allergic && firstHediffOfDef != null) // pawn's active skill isn't causing an allergy, but they have the allergic hediff { DecreaseAllergy(pawn); //firstHediffOfDef.Severity -= gainRate; } else if (passion == allergic) // pawn's active skill is allergy causing { IncreaseAllergy(pawn); } base.OnIntervalPassed(pawn, cause); }
public static void Postfix(SkillRecord __instance) { if (!Settings.addTrait) { return; } var traverse = Traverse.Create(__instance); var value = traverse.Field("pawn").GetValue <Pawn>(); if (API.hasTrait(value)) { return; } if (!__instance.def.Equals(SkillDefOf.Melee)) { return; } if (__instance.levelInt != 20) { return; } value.story.traits.GainTrait(new Trait(TraitDef.Named("ProjectileInversion_Trait"))); var isColonist = value.IsColonist; if (isColonist) { Messages.Message( "YourPawnGainProjectileInversionTraitMsg".Translate(value.Label, TraitDef.Named("ProjectileInversion_Trait").degreeDatas.RandomElement().label), value, MessageTypeDefOf.PositiveEvent); } }
public void OnLevelUp(SkillRecord skillRecord, Pawn pawn, int level) { OnLevelChange(LevelUpMessage, MessageLevelUpDef, skillRecord, pawn, level, MoteLevelUpDef, 1.0f, 100f); }
public void OnLevelDown(SkillRecord skillRecord, Pawn pawn, int level) { OnLevelChange(LevelDownMessage, MessageLevelDownDef, skillRecord, pawn, level, MoteLevelDownDef, 8.0f, -100f); }
public void OverwritePawn(Pawn pawn) { var extension = this.def.GetModExtension <StackSavingOptionsModExtension>(); if (pawn.Faction != this.faction) { pawn.SetFaction(this.faction); } if (this.isFactionLeader) { pawn.Faction.leader = pawn; } pawn.Name = this.name; if (pawn.needs?.mood?.thoughts?.memories?.Memories != null) { for (int num = pawn.needs.mood.thoughts.memories.Memories.Count - 1; num >= 0; num--) { pawn.needs.mood.thoughts.memories.RemoveMemory(pawn.needs.mood.thoughts.memories.Memories[num]); } } if (this.thoughts != null) { if (this.gender == pawn.gender) { this.thoughts.RemoveAll(x => x.def == AlteredCarbonDefOf.AC_WrongGender); this.thoughts.RemoveAll(x => x.def == AlteredCarbonDefOf.AC_WrongGenderDouble); } foreach (var thought in this.thoughts) { if (thought is Thought_MemorySocial && thought.otherPawn == null) { continue; } pawn.needs.mood.thoughts.memories.TryGainMemory(thought, thought.otherPawn); } } pawn.story.traits.allTraits.RemoveAll(x => !extension.ignoresTraits.Contains(x.def.defName)); if (this.traits != null) { foreach (var trait in this.traits) { if (extension.ignoresTraits != null && extension.ignoresTraits.Contains(trait.def.defName)) { continue; } pawn.story.traits.GainTrait(trait); } } pawn.relations.ClearAllRelations(); var origPawn = GetOriginalPawn(pawn); foreach (var otherPawn in this.relatedPawns) { if (otherPawn != null) { foreach (var rel in otherPawn.relations.DirectRelations) { if (this.name == rel.otherPawn?.Name) { //Log.Message("1 Changing Rel: " + pawn.Name + " - " + rel.def + " - " + otherPawn.Name + " - " + rel.otherPawn.Name, true); rel.otherPawn = pawn; } } } } foreach (var otherPawn in this.relatedPawns) { if (otherPawn != null) { foreach (var rel in this.relations) { foreach (var rel2 in otherPawn.relations.DirectRelations) { if (rel.def == rel2.def && rel2.otherPawn?.Name == pawn.Name) { //Log.Message("2 Changing Rel: " + pawn.Name + " - " + rel.def + " - " + otherPawn.Name + " - " + rel.otherPawn.Name, true); rel2.otherPawn = pawn; } } } } } foreach (var rel in this.relations) { //Log.Message("Adding Rel: " + pawn.Name + " - " + rel.def + " - " + rel.otherPawn.Name, true); if (rel.otherPawn != null) { var oldRelation = rel.otherPawn.relations.DirectRelations.Where(r => r.def == rel.def && r.otherPawn.Name == pawn.Name).FirstOrDefault(); if (oldRelation != null) { //Log.Message("3 Changing Rel: " + pawn.Name + " - " + rel.def + " - " + oldRelation.otherPawn.Name + " - " + rel.otherPawn.Name, true); oldRelation.otherPawn = pawn; } } //foreach (var child in rel.otherPawn.relations.Children) //{ // if (child != null) // { // if (child.Name == pawn.Name) // { // var oldRelation2 = child.relations.DirectRelations.Where(r => r.def == rel.def && r.otherPawn == rel.otherPawn).FirstOrDefault(); // if (oldRelation2 != null) // { // var otherRelation = oldRelation2.otherPawn.relations.GetDirectRelation(oldRelation2.def, child); // Log.Message("4 Changing Rel: " + pawn.Name + " - " + rel.def + " - " + otherRelation.otherPawn.Name + " - " + rel.otherPawn.Name, true); // otherRelation.otherPawn = pawn; // } // } // } //} //foreach (var rel2 in rel.otherPawn.relations.DirectRelations) //{ // if (rel2.def == rel.def) // { // Log.Message("Check rel: " + rel.otherPawn.Name + " - " + rel2.def + " - " + rel2.otherPawn.Name, true); // } //} pawn.relations.AddDirectRelation(rel.def, rel.otherPawn); //foreach (var children in rel.otherPawn.relations.Children) //{ // //Log.Message("1.5: " + rel.otherPawn.Name + " - child: " + children.Name, true); //} //Log.Message("-------------"); } //foreach (var otherPawn in pawn.relations.RelatedPawns) //{ // for (int num = otherPawn.relations.DirectRelations.Count - 1; num >= 0; num--) // { // if (pawn.Name == otherPawn.relations.DirectRelations[num].otherPawn.Name) // { // if (pawn != otherPawn.relations.DirectRelations[num].otherPawn) // { // Log.Message("5 Rel: " + pawn.Name + " - " + otherPawn.relations.DirectRelations[num].def + " - " + otherPawn.Name + " - " + otherPawn.relations.DirectRelations[num].otherPawn.Name, true); // Log.Message("6 pawn != otherPawn: " + pawn + " - " + otherPawn.relations.DirectRelations[num].otherPawn, true); // } // } // } //} // //foreach (var children in pawn.relations.Children) //{ // Log.Message("7: " + pawn.Name + " - child: " + children.Name, true); //} if (origPawn != null) { origPawn.relations = new Pawn_RelationsTracker(origPawn); } pawn.skills.skills.Clear(); if (this.skills != null) { foreach (var skill in this.skills) { var newSkill = new SkillRecord(pawn, skill.def); newSkill.passion = skill.passion; newSkill.levelInt = skill.levelInt; newSkill.xpSinceLastLevel = skill.xpSinceLastLevel; newSkill.xpSinceMidnight = skill.xpSinceMidnight; pawn.skills.skills.Add(newSkill); } } if (pawn.playerSettings == null) { pawn.playerSettings = new Pawn_PlayerSettings(pawn); } pawn.playerSettings.hostilityResponse = (HostilityResponseMode)this.hostilityMode; Backstory newChildhood = null; BackstoryDatabase.TryGetWithIdentifier(this.childhood, out newChildhood, true); pawn.story.childhood = newChildhood; if (this.adulthood?.Length > 0) { Backstory newAdulthood = null; BackstoryDatabase.TryGetWithIdentifier(this.adulthood, out newAdulthood, true); pawn.story.adulthood = newAdulthood; } else { pawn.story.adulthood = null; } if (pawn.workSettings == null) { pawn.workSettings = new Pawn_WorkSettings(); } pawn.Notify_DisabledWorkTypesChanged(); if (priorities != null) { foreach (var priority in priorities) { pawn.workSettings.SetPriority(priority.Key, priority.Value); } } pawn.playerSettings.AreaRestriction = this.areaRestriction; pawn.playerSettings.medCare = this.medicalCareCategory; pawn.playerSettings.selfTend = this.selfTend; if (pawn.foodRestriction == null) { pawn.foodRestriction = new Pawn_FoodRestrictionTracker(); } pawn.foodRestriction.CurrentFoodRestriction = this.foodRestriction; if (pawn.outfits == null) { pawn.outfits = new Pawn_OutfitTracker(); } pawn.outfits.CurrentOutfit = this.outfit; if (pawn.drugs == null) { pawn.drugs = new Pawn_DrugPolicyTracker(); } pawn.drugs.CurrentPolicy = this.drugPolicy; pawn.ageTracker.AgeChronologicalTicks = this.ageChronologicalTicks; if (pawn.timetable == null) { pawn.timetable = new Pawn_TimetableTracker(pawn); } if (this.times != null) { pawn.timetable.times = this.times; } if (pawn.gender != this.gender) { if (pawn.story.traits.HasTrait(TraitDefOf.BodyPurist)) { pawn.needs.mood.thoughts.memories.TryGainMemory(AlteredCarbonDefOf.AC_WrongGenderDouble); } else { pawn.needs.mood.thoughts.memories.TryGainMemory(AlteredCarbonDefOf.AC_WrongGender); } } if (ModLister.RoyaltyInstalled) { if (pawn.royalty == null) { pawn.royalty = new Pawn_RoyaltyTracker(pawn); } if (this.royalTitles != null) { foreach (var title in this.royalTitles) { pawn.royalty.SetTitle(title.faction, title.def, false, false, false); } } if (this.heirs != null) { foreach (var heir in this.heirs) { pawn.royalty.SetHeir(heir.Value, heir.Key); } } if (this.favor != null) { foreach (var fav in this.favor) { pawn.royalty.SetFavor(fav.Key, fav.Value); } } if (this.bondedThings != null) { foreach (var bonded in this.bondedThings) { var comp = bonded.TryGetComp <CompBladelinkWeapon>(); if (comp != null) { comp.bondedPawn = pawn; } } } } }
protected override Toil DoBill() { Pawn actor = GetActor(); Job curJob = actor.jobs.curJob; Thing objectThing = curJob.GetTarget(objectTI).Thing; Building_WorkTable tableThing = curJob.GetTarget(tableTI).Thing as Building_WorkTable; Toil toil = new Toil(); toil.initAction = delegate { curJob.bill.Notify_DoBillStarted(actor); this.workCycleProgress = this.workCycle = Math.Max(curJob.bill.recipe.workAmount, 10f); }; toil.tickAction = delegate { if (objectThing == null || objectThing.Destroyed) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); } workCycleProgress -= StatExtension.GetStatValue(actor, StatDefOf.WorkToMake, true); tableThing.UsedThisTick(); //if (!tableThing.UsableNow) //{ // actor.jobs.EndCurrentJob(JobCondition.Incompletable); //} if (workCycleProgress <= 0) { float skillPerc = 0.5f; SkillDef skillDef = curJob.RecipeDef.workSkill; if (skillDef != null) { SkillRecord skill = actor.skills.GetSkill(skillDef); if (skill != null) { skillPerc = (float)skill.Level / 20f; skill.Learn(0.11f * curJob.RecipeDef.workSkillLearnFactor); } } actor.GainComfortFromCellIfPossible(); Apparel mendApparel = objectThing as Apparel; if (mendApparel != null) { ApparelWornByCorpseInt.SetValue(mendApparel, false); } List <Thing> list = new List <Thing>(); list.Add(objectThing); curJob.bill.Notify_IterationCompleted(actor, list); workCycleProgress = workCycle; ReadyForNextToil(); } }; toil.defaultCompleteMode = ToilCompleteMode.Never; toil.WithEffect(() => curJob.bill.recipe.effectWorking, tableTI); toil.PlaySustainerOrSound(() => toil.actor.CurJob.bill.recipe.soundWorking); toil.WithProgressBar(tableTI, delegate { return((float)objectThing.HitPoints / (float)objectThing.MaxHitPoints); }, false, 0.5f); toil.FailOn(() => { IBillGiver billGiver = curJob.GetTarget(tableTI).Thing as IBillGiver; return(curJob.bill.suspended || curJob.bill.DeletedOrDereferenced || (billGiver != null && !billGiver.CurrentlyUsableForBills())); }); return(toil); }
public static Pawn MakePawnFromGenomeSequence(GenomeSequence genomeSequence, Thing creator) { //int adultAge = (int)genome.pawnKindDef.RaceProps.lifeStageAges.Last().minAge; QEEMod.TryLog("Generating pawn..."); PawnGenerationRequest request = new PawnGenerationRequest( genomeSequence.pawnKindDef, faction: creator.Faction, forceGenerateNewPawn: true, canGeneratePawnRelations: false, fixedGender: genomeSequence.gender, fixedBiologicalAge: 0, fixedChronologicalAge: 0, allowFood: false); Pawn pawn = PawnGenerator.GeneratePawn(request); //No pregenerated equipment. pawn?.equipment?.DestroyAllEquipment(); pawn?.apparel?.DestroyAll(); pawn?.inventory?.DestroyAll(); //No pregenerated hediffs. pawn.health.hediffSet.Clear(); //Add Hediff marking them as a clone. QEEMod.TryLog("Adding hediffs to generated pawn"); pawn.health.AddHediff(QEHediffDefOf.QE_CloneStatus); if (genomeSequence.hediffInfos != null && genomeSequence.hediffInfos.Count > 0) { //add hediffs to pawn from defs in HediffInfo class foreach (HediffInfo h in genomeSequence.hediffInfos) { pawn.health.AddHediff(h.def, h.part); } } //Set everything else. if (pawn.story is Pawn_StoryTracker storyTracker) { QEEMod.TryLog("Setting Pawn_StoryTracker attributes for generated pawn..."); storyTracker.bodyType = genomeSequence.bodyType; //sanity check to remove possibility of an Undefined crownType if (genomeSequence.crownType == CrownType.Undefined) { storyTracker.crownType = CrownType.Average; } else { storyTracker.crownType = genomeSequence.crownType; } storyTracker.hairColor = genomeSequence.hairColor; storyTracker.hairDef = genomeSequence.hair ?? PawnHairChooser.RandomHairDefFor(pawn, pawn.Faction.def); storyTracker.melanin = genomeSequence.skinMelanin; //headGraphicPath is private, so we need Harmony to set its value if (genomeSequence.headGraphicPath != null) { QEEMod.TryLog("Setting headGraphicPath for generated pawn"); AccessTools.Field(typeof(Pawn_StoryTracker), "headGraphicPath").SetValue(storyTracker, genomeSequence.headGraphicPath); } else { //could use this code to make a random head, instead of the static graphic paths. //AccessTools.Field(typeof(Pawn_StoryTracker), "headGraphicPath").SetValue(storyTracker, //GraphicDatabaseHeadRecords.GetHeadRandom(genomeSequence.gender, PawnSkinColors.GetSkinColor(genomeSequence.skinMelanin), genomeSequence.crownType).GraphicPath); QEEMod.TryLog("No headGraphicPath in genome template, setting to default head"); string path = genomeSequence.gender == Gender.Male ? "Things/Pawn/Humanlike/Heads/Male/Male_Average_Normal" : "Things/Pawn/Humanlike/Heads/Female/Female_Narrow_Normal"; AccessTools.Field(typeof(Pawn_StoryTracker), "headGraphicPath").SetValue(storyTracker, path); } storyTracker.traits.allTraits.Clear(); QEEMod.TryLog("Setting traits for generated pawn"); foreach (ExposedTraitEntry trait in genomeSequence.traits) { //storyTracker.traits.GainTrait(new Trait(trait.def, trait.degree)); storyTracker.traits.allTraits.Add(new Trait(trait.def, trait.degree)); if (pawn.workSettings != null) { pawn.workSettings.Notify_DisabledWorkTypesChanged(); } if (pawn.skills != null) { pawn.skills.Notify_SkillDisablesChanged(); } if (!pawn.Dead && pawn.RaceProps.Humanlike) { pawn.needs.mood.thoughts.situational.Notify_SituationalThoughtsDirty(); } } QEEMod.TryLog("Setting backstory for generated pawn"); //Give random vatgrown backstory. storyTracker.childhood = DefDatabase <BackstoryDef> .GetNamed("Backstory_ColonyVatgrown").GetFromDatabase(); storyTracker.adulthood = null; } if (pawn.skills is Pawn_SkillTracker skillsTracker) { foreach (SkillRecord skill in skillsTracker.skills) { skill.Level = 0; skill.passion = Passion.None; skill.Notify_SkillDisablesChanged(); } List <SkillRecord> skillPassions = new List <SkillRecord>(); int skillsPicked = 0; int iterations = 0; //Pick 4 random skills to give minor passions to. while (skillsPicked < 4 && iterations < 1000) { SkillRecord randomSkill = skillsTracker.skills.RandomElement(); if (!skillPassions.Contains(randomSkill)) { skillPassions.Add(randomSkill); randomSkill.passion = Passion.Minor; skillsPicked++; } iterations++; } skillsPicked = 0; iterations = 0; //Pick 2 random skills to give major passions to. while (skillsPicked < 2 && iterations < 1000) { SkillRecord randomSkill = skillsTracker.skills.RandomElement(); if (!skillPassions.Contains(randomSkill)) { skillPassions.Add(randomSkill); randomSkill.passion = Passion.Major; skillsPicked++; } iterations++; } } if (pawn.workSettings is Pawn_WorkSettings workSettings) { workSettings.EnableAndInitialize(); } //Alien Races compatibility. if (CompatibilityTracker.AlienRacesActive) { AlienRaceCompat.SetFieldsToAlienComp(pawn, genomeSequence); } PortraitsCache.SetDirty(pawn); PortraitsCache.PortraitsCacheUpdate(); return(pawn); }
public override bool TryExecuteWorker(IncidentParms parms) { if (Settings.disableSkyMindSecurityStuff) { return(false); } List <Pawn> victims; List <string> cryptolockedThings = new List <string>(); string title = ""; string msg = ""; int nbConnectedClients = Utils.GCATPP.getNbThingsConnected(); int nbSurrogates = Utils.GCATPP.getNbSurrogateAndroids(); int nbUnsecurisedClients = nbConnectedClients - Utils.GCATPP.getNbSlotSecurisedAvailable(); LetterDef letter; //Selection type virus int attackType = 1; int fee = 0; //Check si sur lensemble des clients connecté il y a quand meme des surrogates if (nbSurrogates <= 0) { return(false); } //Attaque virale faible if (nbUnsecurisedClients <= 0) { if (!Rand.Chance(Settings.riskSecurisedSecuritySystemGetVirus)) { return(false); } int nb = 0; nb = nbSurrogates / 2; if (nb != 0) { nb = Rand.Range(1, nb + 1); } else { nb = 1; } letter = LetterDefOf.ThreatSmall; //Obtention des victimes victims = Utils.GCATPP.getRandomSurrogateAndroids(nb); if (victims.Count == 0) { return(false); } foreach (var v in victims) { CompSkyMind csm = v.TryGetComp <CompSkyMind>(); CompAndroidState cas = v.ATCompState; if (csm == null || cas == null) { continue; } csm.Infected = 4; //Deconnection du contorlleur le cas echeant if (cas.surrogateController != null) { CompSurrogateOwner cso = cas.surrogateController.ATCompSurrogateOwner; if (cso != null) { cso.disconnectControlledSurrogate(null); } } Hediff he = v.health.hediffSet.GetFirstHediffOfDef(Utils.hediffNoHost); if (he != null) { v.health.RemoveHediff(he); } Utils.ignoredPawnNotifications = v; Utils.VirusedRandomMentalBreak.RandomElement().Worker.TryStart(v, null, false); Utils.ignoredPawnNotifications = null; //v.mindState.mentalStateHandler.TryStartMentalState( , null, false, false, null, false); } title = "ATPP_IncidentSurrogateHackingVirus".Translate(); msg = "ATPP_IncidentSurrogateHackingLiteDesc".Translate(nb); } else { letter = LetterDefOf.ThreatBig; attackType = Rand.Range(1, 4); int nb = 0; LordJob_AssaultColony lordJob; Lord lord = null; if (attackType != 3) { //Attaque virale douce //Obtention des victimes (qui peut allez de 1 victime a N/2 victimes nb = nbSurrogates / 2; if (nb != 0) { nb = Rand.Range(1, nb + 1); } else { nb = 1; } lordJob = new LordJob_AssaultColony(Faction.OfAncientsHostile, false, false, false, false, false); if (lordJob != null) { lord = LordMaker.MakeNewLord(Faction.OfAncientsHostile, lordJob, Current.Game.CurrentMap, null); } } else { nb = nbSurrogates; } msg = "ATPP_IncidentSurrogateHackingHardDesc".Translate(nb) + "\n"; switch (attackType) { case 1: title = "ATPP_IncidentSurrogateHackingVirus".Translate(); msg += "ATPP_IncidentVirusedDesc".Translate(); break; case 2: title = "ATPP_IncidentSurrogateHackingExplosiveVirus".Translate(); msg += "ATPP_IncidentVirusedExplosiveDesc".Translate(); break; case 3: title = "ATPP_IncidentSurrogateHackingCryptolocker".Translate(); msg += "ATPP_IncidentCryptolockerDesc".Translate(); break; } victims = Utils.GCATPP.getRandomSurrogateAndroids(nb); if (victims.Count != nb) { return(false); } foreach (var v in victims) { CompSkyMind csm = v.TryGetComp <CompSkyMind>(); v.mindState.canFleeIndividual = false; csm.Infected = attackType; if (v.jobs != null) { v.jobs.StopAll(); v.jobs.ClearQueuedJobs(); } if (v.mindState != null) { v.mindState.Reset(true); } switch (attackType) { //Virus case 1: //Devient hostile if (lord != null) { lord.AddPawn(v); } break; //Virus explosif case 2: //Devient hostile if (lord != null) { lord.AddPawn(v); } break; //Virus cryptolocker case 3: cryptolockedThings.Add(v.GetUniqueLoadID()); switch (v.def.defName) { case Utils.T2: fee += Settings.ransomCostT2; break; case Utils.T3: fee += Settings.ransomCostT3; break; case Utils.T4: fee += Settings.ransomCostT4; break; case Utils.T5: fee += Settings.ransomCostT5; break; case Utils.T1: default: fee += Settings.ransomCostT1; break; } break; } if (attackType == 1 || attackType == 2) { //On va attribuer aleatoirement des poids d'attaque aux surrogate SkillRecord shooting = v.skills.GetSkill(SkillDefOf.Shooting); if (shooting != null && !shooting.TotallyDisabled) { shooting.levelInt = Rand.Range(3, 19); } SkillRecord melee = v.skills.GetSkill(SkillDefOf.Melee); if (melee != null && !melee.TotallyDisabled) { melee.levelInt = Rand.Range(3, 19); } } } } Find.LetterStack.ReceiveLetter(title, msg, letter, (LookTargets)victims, null, null); if (attackType == 3) { //Déduction faction ennemis au hasard Faction faction = Find.FactionManager.RandomEnemyFaction(); ChoiceLetter_RansomDemand ransom = (ChoiceLetter_RansomDemand)LetterMaker.MakeLetter(DefDatabase <LetterDef> .GetNamed("ATPP_CLPayCryptoRansom")); ransom.label = "ATPP_CryptolockerNeedPayRansomTitle".Translate(); ransom.text = "ATPP_CryptolockerNeedPayRansom".Translate(faction.Name, fee); ransom.faction = faction; ransom.radioMode = true; ransom.fee = fee; ransom.cryptolockedThings = cryptolockedThings; ransom.StartTimeout(60000); Find.LetterStack.ReceiveLetter(ransom, null); } return(true); }
private static string GetSkillValue(SkillRecord record) => record.TotallyDisabled ? "-" : record.levelInt.ToString();
public static void BeforeSkillLearned(SkillRecord __instance, ref int __state) { __state = __instance.levelInt; }
public static void OnSkillLearned(SkillRecord __instance, ref int __state) { Pawn pawn = Traverse.Create(__instance).Field("pawn").GetValue <Pawn>(); ChallengeManager.instance.currentChallenge.OnSkillLearned(__instance, pawn, __state); }
private Priority considerInterest(Pawn pawn, SkillDef skillDef, int skillCount, WorkTypeDef workTypeDef) { if (!YouDoYou_WorldComponent.HasInterestsFramework()) { return(this); } SkillRecord skillRecord = pawn.skills.GetSkill(skillDef); float x; string interest; try { interest = YouDoYou_WorldComponent.InterestsStrings[(int)skillRecord.passion]; } catch (System.Exception) { Logger.Message("could not find interest for index " + ((int)skillRecord.passion).ToString()); return(this); } switch (interest) { case "DMinorAversion": x = (1.0f - pawn.needs.mood.CurLevel) * -0.25f / skillCount; return(add(x, "YouDoYouPriorityMinorAversionTo".Translate() + " " + skillDef.skillLabel)); case "DMajorAversion": x = (1.0f - pawn.needs.mood.CurLevel) * -0.5f / skillCount; return(add(x, "YouDoYouPriorityMajorAversionTo".Translate() + " " + skillDef.skillLabel)); case "DCompulsion": List <Thought> allThoughts = new List <Thought>(); pawn.needs.mood.thoughts.GetAllMoodThoughts(allThoughts); foreach (var thought in allThoughts) { if (thought.def.defName == "CompulsionUnmet") { switch (thought.CurStage.label) { case "compulsive itch": x = 0.2f / skillCount; return(add(x, "YouDoYouPriorityCompulsiveItch".Translate() + " " + skillDef.skillLabel)); case "compulsive need": x = 0.4f / skillCount; return(add(x, "YouDoYouPriorityCompulsiveNeed".Translate() + " " + skillDef.skillLabel)); case "compulsive obsession": x = 0.6f / skillCount; return(add(x, "YouDoYouPriorityCompulsiveObsession".Translate() + " " + skillDef.skillLabel)); default: Logger.Debug("could not read compulsion label"); return(this); } } if (thought.def.defName == "NeuroticCompulsionUnmet") { switch (thought.CurStage.label) { case "compulsive itch": x = 0.3f / skillCount; return(add(x, "YouDoYouPriorityCompulsiveItch".Translate() + " " + skillDef.skillLabel)); case "compulsive demand": x = 0.6f / skillCount; return(add(x, "YouDoYouPriorityCompulsiveDemand".Translate() + " " + skillDef.skillLabel)); case "compulsive withdrawal": x = 0.9f / skillCount; return(add(x, "YouDoYouPriorityCompulsiveWithdrawl".Translate() + " " + skillDef.skillLabel)); default: Logger.Debug("could not read compulsion label"); return(this); } } if (thought.def.defName == "VeryNeuroticCompulsionUnmet") { switch (thought.CurStage.label) { case "compulsive yearning": x = 0.4f / skillCount; return(add(x, "YouDoYouPriorityCompulsiveYearning".Translate() + " " + skillDef.skillLabel)); case "compulsive tantrum": x = 0.8f / skillCount; return(add(x, "YouDoYouPriorityCompulsiveTantrum".Translate() + " " + skillDef.skillLabel)); case "compulsive hysteria": x = 1.2f / skillCount; return(add(x, "YouDoYouPriorityCompulsiveHysteria".Translate() + " " + skillDef.skillLabel)); default: Logger.Debug("could not read compulsion label"); return(this); } } } return(this); case "DInvigorating": x = 0.1f / skillCount; return(add(x, "YouDoYouPriorityInvigorating".Translate() + " " + skillDef.skillLabel)); case "DInspiring": return(this); case "DStagnant": return(this); case "DForgetful": return(this); case "DVocalHatred": return(this); case "DNaturalGenius": return(this); case "DBored": if (pawn.mindState.IsIdle) { return(this); } return(neverDo("YouDoYouPriorityBoredBy".Translate() + " " + skillDef.skillLabel)); case "DAllergic": foreach (var hediff in pawn.health.hediffSet.GetHediffs <Hediff>()) { if (hediff.def.defName == "DAllergicReaction") { switch (hediff.CurStage.label) { case "initial": x = -0.2f / skillCount; return(add(x, "YouDoYouPriorityReactionInitial".Translate() + " " + skillDef.skillLabel)); case "itching": x = -0.5f / skillCount; return(add(x, "YouDoYouPriorityReactionItching".Translate() + " " + skillDef.skillLabel)); case "sneezing": x = -0.8f / skillCount; return(add(x, "YouDoYouPriorityReactionSneezing".Translate() + " " + skillDef.skillLabel)); case "swelling": x = -1.1f / skillCount; return(add(x, "YouDoYouPriorityReactionSwelling".Translate() + " " + skillDef.skillLabel)); case "anaphylaxis": return(neverDo("YouDoYouPriorityReactionAnaphylaxis".Translate() + " " + skillDef.skillLabel)); default: break; } } x = 0.1f / skillCount; return(add(x, "YouDoYouPriorityNoReaction".Translate() + " " + skillDef.skillLabel)); } return(this); default: Logger.Debug("did not recognize interest: " + skillRecord.passion.ToString()); return(this); } }
protected override bool TryExecuteWorker(IncidentParms parms) { HarmonyPatches.DebugMessage("Chaos Theory attempted"); Map map = parms.target as Map; Pawn pawn = map.GetComponent <MapComponent_SacrificeTracker>().lastUsedAltar.SacrificeData.Executioner; HarmonyPatches.DebugMessage("Executioner selected"); if (HasIncapableWorkTags(pawn)) { HarmonyPatches.DebugMessage($"{pawn.Label} has incapable worktags and must be remade."); HarmonyPatches.DebugMessage("Childhood redo"); bool fixedChildhood = false; IEnumerable <WorkTypeDef> childWorkList = new List <WorkTypeDef>(pawn.story.childhood.DisabledWorkTypes); HarmonyPatches.DebugMessage($"childwork list defined"); while (fixedChildhood == false) { //200 tries to set to 0 disabled work types for (int i = 0; i < 200; i++) { childWorkList = pawn.story.childhood.DisabledWorkTypes; if (childWorkList.Count <WorkTypeDef>() == 0) { fixedChildhood = true; goto FirstLeap; } pawn.story.childhood = BackstoryDatabase.RandomBackstory(BackstorySlot.Childhood); } //200 tries to set to 1 disabled work type for (int i = 0; i < 200; i++) { childWorkList = pawn.story.childhood.DisabledWorkTypes; if (childWorkList.Count <WorkTypeDef>() <= 1) { fixedChildhood = true; goto FirstLeap; } pawn.story.childhood = BackstoryDatabase.RandomBackstory(BackstorySlot.Childhood); } //Give up fixedChildhood = true; } FirstLeap: HarmonyPatches.DebugMessage($"First leap"); //Your adulthood is out bool fixedAdulthood = false; IEnumerable <WorkTypeDef> adultWorkList = pawn.story.adulthood.DisabledWorkTypes; while (fixedAdulthood == false) { //Try 200 times to get to 0 disabled work types for (int i = 0; i < 200; i++) { adultWorkList = pawn.story.adulthood.DisabledWorkTypes; if (adultWorkList?.Count <WorkTypeDef>() == 0) { fixedAdulthood = true; goto SecondLeap; } pawn.story.adulthood = BackstoryDatabase.RandomBackstory(BackstorySlot.Adulthood); } //Try 200 times to get to 1 disabled work types for (int i = 0; i < 200; i++) { adultWorkList = pawn.story.adulthood.DisabledWorkTypes; if (adultWorkList?.Count <WorkTypeDef>() <= 1) { fixedAdulthood = true; goto SecondLeap; } pawn.story.adulthood = BackstoryDatabase.RandomBackstory(BackstorySlot.Adulthood); } //Give up fixedAdulthood = true; } SecondLeap: HarmonyPatches.DebugMessage($"Second leap"); } if (HasIncapableSkills(pawn)) { HarmonyPatches.DebugMessage($"{pawn.Label} has incapable skills"); //pawn.story.GenerateSkillsFromBackstory(); List <SkillDef> allDefsListForReading = DefDatabase <SkillDef> .AllDefsListForReading; for (int i = 0; i < allDefsListForReading.Count; i++) { SkillDef skillDef = allDefsListForReading[i]; SkillRecord skill = pawn.skills.GetSkill(skillDef); if (skill.Level <= 3) { skill.Level = 3; } if (skill.TotallyDisabled) { HarmonyPatches.DebugMessage($"{pawn.Label}'s {skill.def.LabelCap} is now 3"); skill.Level = 3; } skill.Notify_SkillDisablesChanged(); } HarmonyPatches.DebugMessage($"Skills assigned"); } HarmonyPatches.DebugMessage("Disabled Work Types Attempted"); Traverse.Create(pawn).Field("cachedDisabledWorkTypes").SetValue(null); HarmonyPatches.DebugMessage("Disabled Work Types Succeeded"); //typeof(Pawn).GetField("cachedDisabledWorkTypes", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(pawn, null); map.GetComponent <MapComponent_SacrificeTracker>().lastLocation = pawn.Position; Messages.Message(pawn.Label + " has lived their entire life over again.", MessageTypeDefOf.PositiveEvent); return(true); }
public ObjCharacter SelectTargetForSkill(ObjCharacter player, SkillRecord skillRecord) { var skillTargetType = (SkillTargetType)ObjMyPlayer.GetSkillData_Data(skillRecord, eModifySkillType.TargetType); if (GameControl.Instance.TargetObj != null && !GameControl.Instance.TargetObj.Dead && Instance.MyPlayer.IsMyEnemy(GameControl.Instance.TargetObj)) { // 这种技能,只能依靠自动瞄准,如果上一个目标可用,就继续打 if (skillTargetType != SkillTargetType.SECTOR && skillTargetType != SkillTargetType.RECT) { var dist = GameControl.GetSkillReleaseDistance(skillRecord); if (Vector3.Distance(player.Position, GameControl.Instance.TargetObj.Position) < dist) { return(GameControl.Instance.TargetObj); } } else { if (GameSetting.Instance.TargetSelectionAssistant && skillRecord.AutoEnemy == 1) { // 如果需要辅助瞄准,技能配置也需要辅助瞄准,而且上一个目标可用,就继续打它 var dist = GameControl.GetSkillReleaseDistance(skillRecord); if (Vector3.Distance(player.Position, GameControl.Instance.TargetObj.Position) < dist) { return(GameControl.Instance.TargetObj); } } else { // 如果不需要辅助瞄准,技能也配置了不需要辅助瞄准,那就不瞄准了 return(null); } } } ObjCharacter targetObj = null; if (skillTargetType == SkillTargetType.CIRCLE) { // nothing } else if (skillTargetType == SkillTargetType.SECTOR) { if (GameSetting.Instance.TargetSelectionAssistant && skillRecord.AutoEnemy == 1) { targetObj = SelectNearestCharacter(player.Position, character => !character.Dead && player.IsMyEnemy(character), skillRecord.TargetParam[0]); } } else if (skillTargetType == SkillTargetType.RECT) { if (GameSetting.Instance.TargetSelectionAssistant && skillRecord.AutoEnemy == 1) { targetObj = SelectNearestCharacter(player.Position, character => !character.Dead && player.IsMyEnemy(character), skillRecord.TargetParam[1]); } } else if (skillTargetType == SkillTargetType.TARGET_RECT) { targetObj = SelectNearestCharacter(player.Position, character => !character.Dead && player.IsMyEnemy(character)); } else if (skillTargetType == SkillTargetType.TARGET_SECTOR) { targetObj = SelectNearestCharacter(player.Position, character => !character.Dead && player.IsMyEnemy(character)); } else if (skillTargetType == SkillTargetType.SINGLE) { targetObj = SelectNearestCharacter(player.Position, character => !character.Dead && player.IsMyEnemy(character)); } else if (skillTargetType == SkillTargetType.TARGET_CIRCLE) { targetObj = SelectNearestCharacter(player.Position, character => !character.Dead && player.IsMyEnemy(character)); } return(targetObj); }
public static IEnumerable <ResearchProjectDef> GetExpertiseDefsFor(Pawn pawn, FactionDef faction) { //0. Info for debugging. if (Prefs.LogVerbose) { bool flag = false; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("[HumanResources] Including technologies from"); if (ModBaseHumanResources.TechPoolIncludesTechLevel) { stringBuilder.Append(" the faction tech level,"); flag = true; } if (ModBaseHumanResources.TechPoolIncludesScenario) { stringBuilder.Append(" the scenario,"); flag = true; } if (ModBaseHumanResources.TechPoolIncludesStarting) { stringBuilder.Append(" the starting techs"); flag = true; } if (flag) { Log.Message(stringBuilder.ToString().TrimEnd(new char[] { ',' }) + "."); } else { Log.Message("[HumanResources] Empty technology pool!"); } } //1. Gather info on that pawn //a. tech level startingTechLevel = faction?.techLevel ?? 0; if (startingTechLevel == 0) { startingTechLevel = InferTechLevelfromBG(pawn); } //b. higest skills SkillRecord highestSkillRecord = pawn.skills.skills.Aggregate(AccessHighestSkill); SkillDef highestSkill = highestSkillRecord.def; SkillDef secondSkill = pawn.skills.skills.Except(highestSkillRecord).Aggregate(AccessHighestSkill).def; //c. special cases isFighter = highestSkill == SkillDefOf.Melee; isShooter = highestSkill == SkillDefOf.Shooting; int fighterHandicap = (isFighter | isShooter) ? 1 : 0; int oldBonus = pawn.ageTracker.AgeBiologicalYears > pawn.RaceProps.lifeExpectancy / 2 ? 1 : 0; bool guru = startingTechLevel < TechLevel.Archotech && highestSkill == SkillDefOf.Intellectual && highestSkillRecord.Level >= Rand.Range(7, 10); //2. Calculate how many techs he should know int minSlots = startingTechLevel > TechLevel.Medieval ? 1 : oldBonus; int slots = Mathf.Max(minSlots, FactionExpertiseRange(startingTechLevel) - (4 - pawn.ageTracker.CurLifeStageIndex) + oldBonus - fighterHandicap); if (slots == 0) { if (Prefs.LogVerbose) { Log.Warning("Expertise generation for " + pawn + ": no slots, returning null. StartingTechLevel is " + startingTechLevel + ", CurLifeStageIndex is " + pawn.ageTracker.CurLifeStageIndex + ", fighterHandicap is " + fighterHandicap); } return(null); } //3. Distribute knowledge if (Prefs.LogVerbose) { string guruNote = guru ? " (with intellectual bounus)" : ""; Log.Message("Expertise generation for " + pawn + ": techLevel is " + startingTechLevel + guruNote + ", highest skills: " + highestSkill.label + " & " + secondSkill.label + ", " + slots + " calculated slots."); } bool isPlayer = pawn.Faction?.IsPlayer ?? false; var filtered = Extension_Research.SkillsByTech.Where(e => TechPool(isPlayer, e.Key, startingTechLevel, faction)); int pass = 0; List <ResearchProjectDef> result = new List <ResearchProjectDef>(); if (guru) { startingTechLevel++; } while (result.Count() < slots) { pass++; var remaining = filtered.Where(x => !result.Contains(x.Key)); if (remaining.EnumerableNullOrEmpty()) { break; } SkillDef skill = null; if (pass == 1 && remaining.Any(e => e.Value.Contains(highestSkill))) { skill = highestSkill; } else if (pass == 2 && remaining.Any(e => e.Value.Contains(secondSkill))) { skill = secondSkill; } ResearchProjectDef selected = remaining.RandomElementByWeightWithDefault(entry => TechLikelihoodForSkill(pawn, entry.Value, slots, pass, skill), 1f).Key ?? remaining.RandomElement().Key; result.Add(selected); if ((guru && pass == 1) | result.NullOrEmpty()) { startingTechLevel--; } if (startingTechLevel == 0) { break; } } if (!result.NullOrEmpty()) { return(result); } Log.Warning("Couldn't calculate any expertise for " + pawn); return(null); }
protected override Toil DoBill() { Pawn actor = GetActor(); Job curJob = actor.jobs.curJob; Thing objectThing = curJob.GetTarget(objectTI).Thing; Building_WorkTable tableThing = curJob.GetTarget(tableTI).Thing as Building_WorkTable; Toil toil = new Toil(); toil.initAction = delegate { curJob.bill.Notify_DoBillStarted(); this.failChance = ChanceDef.GetFor(objectThing); this.workCycleProgress = this.workCycle = Math.Max(curJob.bill.recipe.workAmount, 10f); }; toil.tickAction = delegate { if (objectThing == null || objectThing.Destroyed) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); } workCycleProgress -= StatExtension.GetStatValue(actor, StatDefOf.WorkToMake, true); if (!tableThing.UsableNow) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); } if (workCycleProgress <= 0) { int remainingHitPoints = objectThing.MaxHitPoints - objectThing.HitPoints; if (remainingHitPoints > 0) { objectThing.HitPoints += (int)Math.Min(remainingHitPoints, fixedHitPointsPerCycle); } SkillRecord skill = actor.skills.GetSkill(SkillDefOf.Crafting); if (skill == null) { Log.Error("Mending :: This should never happen! skill == null"); actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } float skillPerc = (float)skill.Level / 20f; skill.Learn(0.33f); CompQuality qualityComponent = objectThing.TryGetComp <CompQuality>(); if (qualityComponent != null && qualityComponent.Quality > QualityCategory.Awful) { QualityCategory qc = qualityComponent.Quality; float skillFactor = Mathf.Lerp(1.5f, 0f, skillPerc); if (failChance != null && Rand.Value < failChance.Chance(qc) * skillFactor) { objectThing.HitPoints -= fixedFailedDamage; MoteMaker.ThrowText(actor.DrawPos, actor.Map, "Failed"); } } actor.GainComfortFromCellIfPossible(); if (objectThing.HitPoints <= 0) { // recycling whats left... float skillFactor = Mathf.Lerp(0.5f, 1.5f, skillPerc); var list = JobDriverUtils.Reclaim(objectThing, skillFactor * 0.1f); pawn.Map.reservationManager.Release(curJob.targetB, pawn); objectThing.Destroy(DestroyMode.Vanish); if (list.Count > 1) { for (int j = 1; j < list.Count; j++) { if (!GenPlace.TryPlaceThing(list [j], actor.Position, actor.Map, ThingPlaceMode.Near, null)) { Log.Error("Mending :: " + actor + " could not drop recipe product " + list [j] + " near " + actor.Position); } } } list[0].SetPositionDirect(actor.Position); curJob.targetB = list[0]; curJob.bill.Notify_IterationCompleted(actor, list); pawn.Map.reservationManager.Reserve(pawn, curJob.targetB, 1); ReadyForNextToil(); } else if (objectThing.HitPoints == objectThing.MaxHitPoints) { // fixed! Apparel mendApparel = objectThing as Apparel; if (mendApparel != null) { ApparelWornByCorpseInt.SetValue(mendApparel, false); } List <Thing> list = new List <Thing> (); list.Add(objectThing); curJob.bill.Notify_IterationCompleted(actor, list); ReadyForNextToil(); } else if (objectThing.HitPoints > objectThing.MaxHitPoints) { Log.Error("Mending :: This should never happen! HitPoints > MaxHitPoints"); actor.jobs.EndCurrentJob(JobCondition.Incompletable); } workCycleProgress = workCycle; } }; toil.defaultCompleteMode = ToilCompleteMode.Never; toil.WithEffect(() => curJob.bill.recipe.effectWorking, tableTI); toil.PlaySustainerOrSound(() => toil.actor.CurJob.bill.recipe.soundWorking); toil.WithProgressBar(tableTI, delegate { return((float)objectThing.HitPoints / (float)objectThing.MaxHitPoints); }, false, 0.5f); toil.FailOn(() => { IBillGiver billGiver = curJob.GetTarget(tableTI).Thing as IBillGiver; return(curJob.bill.suspended || curJob.bill.DeletedOrDereferenced || (billGiver != null && !billGiver.CurrentlyUsable())); }); return(toil); }
public LearnedInfo(SkillRecord r, float x, int f) { record = r; xp = x; tickToKill = f; }
private static Color GetSkillColor(SkillRecord record) => record.TotallyDisabled ? SkillDisabledColor : SkillPassionColor[record.passion];
/// <summary> /// Transfers skills from pawn1 to pawn2 /// </summary> /// <param name="pawn1">The pawn1.</param> /// <param name="pawn2">The pawn2.</param> /// <param name="mode">The transfer mode.</param> /// <param name="passionTransferMode">The passion transfer mode.</param> public static void TransferSkills([NotNull] Pawn pawn1, [NotNull] Pawn pawn2, SkillTransferMode mode = SkillTransferMode.Set, SkillPassionTransferMode passionTransferMode = SkillPassionTransferMode.Ignore) { if (pawn2.skills == null) { Log.Warning($"sapient animal {pawn2.Name} does not have a skill tracker"); return; } if (pawn1.skills?.skills == null) { return; } foreach (SkillRecord skillRecord in pawn1.skills.skills) { SkillRecord p2Skill = TryGetSkill(pawn2.skills, skillRecord.def); if (p2Skill == null) { continue; } var oldLevel = p2Skill.Level; int newLevel; switch (mode) { case SkillTransferMode.Set: newLevel = skillRecord.Level; break; case SkillTransferMode.Min: newLevel = Mathf.Min(oldLevel, skillRecord.Level); break; case SkillTransferMode.Max: newLevel = Mathf.Max(oldLevel, skillRecord.Level); break; default: throw new ArgumentOutOfRangeException(nameof(mode), mode, null); } p2Skill.Level = newLevel; Passion passionLevel; switch (passionTransferMode) { case SkillPassionTransferMode.Min: passionLevel = (Passion)Mathf.Min((int)p2Skill.passion, (int)skillRecord.passion); break; case SkillPassionTransferMode.Max: passionLevel = (Passion)Mathf.Max((int)p2Skill.passion, (int)skillRecord.passion); break; case SkillPassionTransferMode.Set: passionLevel = skillRecord.passion; break; case SkillPassionTransferMode.Ignore: continue; default: throw new ArgumentOutOfRangeException(nameof(passionTransferMode), passionTransferMode, null); } p2Skill.passion = passionLevel; } }
public static Pawn MakePawnFromGenomeSequence(GenomeSequence genomeSequence, Thing creator) { //int adultAge = (int)genome.pawnKindDef.RaceProps.lifeStageAges.Last().minAge; PawnGenerationRequest request = new PawnGenerationRequest( genomeSequence.pawnKindDef, faction: creator.Faction, forceGenerateNewPawn: true, canGeneratePawnRelations: false, fixedGender: genomeSequence.gender, fixedBiologicalAge: 0, fixedChronologicalAge: 0, allowFood: false); Pawn pawn = PawnGenerator.GeneratePawn(request); //No pregenerated equipment. pawn?.equipment?.DestroyAllEquipment(); pawn?.apparel?.DestroyAll(); pawn?.inventory?.DestroyAll(); //No pregenerated hediffs. pawn.health.hediffSet.Clear(); //Set everything else. if (pawn.story is Pawn_StoryTracker storyTracker) { storyTracker.hairDef = DefDatabase <HairDef> .GetNamed("Shaved"); storyTracker.bodyType = genomeSequence.bodyType; storyTracker.crownType = genomeSequence.crownType; storyTracker.hairColor = genomeSequence.hairColor; storyTracker.melanin = genomeSequence.skinMelanin; storyTracker.traits.allTraits.Clear(); foreach (ExposedTraitEntry trait in genomeSequence.traits) { //storyTracker.traits.GainTrait(new Trait(trait.def, trait.degree)); storyTracker.traits.allTraits.Add(new Trait(trait.def, trait.degree)); if (pawn.workSettings != null) { pawn.workSettings.Notify_GainedTrait(); } if (pawn.skills != null) { pawn.skills.Notify_SkillDisablesChanged(); } if (!pawn.Dead && pawn.RaceProps.Humanlike) { pawn.needs.mood.thoughts.situational.Notify_SituationalThoughtsDirty(); } } //Give random vatgrown backstory. storyTracker.childhood = DefDatabase <BackstoryDef> .GetNamed("Backstory_ColonyVatgrown").GetFromDatabase(); storyTracker.adulthood = null; //Dirty hack ahoy! AccessTools.Field(typeof(Pawn_StoryTracker), "cachedDisabledWorkTypes").SetValue(storyTracker, null); //typeof(Pawn_StoryTracker).GetField("cachedDisabledWorkTypes", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(storyTracker, null); //typeof(PawnGenerator).GetMethod("GenerateSkills", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod).Invoke(null, new object[] { pawn }); } if (pawn.skills is Pawn_SkillTracker skillsTracker) { foreach (SkillRecord skill in skillsTracker.skills) { skill.Level = 0; skill.passion = Passion.None; skill.Notify_SkillDisablesChanged(); } List <SkillRecord> skillPassions = new List <SkillRecord>(); int skillsPicked = 0; int iterations = 0; //Pick 4 random skills to give minor passions to. while (skillsPicked < 4 && iterations < 1000) { SkillRecord randomSkill = skillsTracker.skills.RandomElement(); if (!skillPassions.Contains(randomSkill)) { skillPassions.Add(randomSkill); randomSkill.passion = Passion.Minor; skillsPicked++; } iterations++; } skillsPicked = 0; iterations = 0; //Pick 2 random skills to give major passions to. while (skillsPicked < 2 && iterations < 1000) { SkillRecord randomSkill = skillsTracker.skills.RandomElement(); if (!skillPassions.Contains(randomSkill)) { skillPassions.Add(randomSkill); randomSkill.passion = Passion.Major; skillsPicked++; } iterations++; } } if (pawn.workSettings is Pawn_WorkSettings workSettings) { workSettings.EnableAndInitialize(); } //Alien Races compatibility. if (CompatibilityTracker.AlienRacesActive) { AlienRaceCompat.SetFieldsToAlienComp(pawn, genomeSequence); } PortraitsCache.SetDirty(pawn); PortraitsCache.PortraitsCacheUpdate(); //Add Hediff marking them as a clone. pawn.health.AddHediff(QEHediffDefOf.QE_CloneStatus); return(pawn); }
public static void TrackPawnShootingSkill(Pawn pawn, SkillRecord skill) { int dayOfYear = GenLocalDate.DayOfYear(pawn); PawnShootingSkillValues[pawn.ThingID] = new SkillXpValues(dayOfYear, skill.xpSinceMidnight, skill.xpSinceLastLevel); }
public static void ApplyBrainScanTemplateOnPawn(Pawn thePawn, BrainScanTemplate brainScan, float efficency = 1f) { if (thePawn.IsValidBrainScanningTarget()) { //Backgrounds Pawn_StoryTracker storyTracker = thePawn.story; if (storyTracker != null) { //story.childhood = brainScan.backStoryChild; storyTracker.adulthood = brainScan.backStoryAdult; } //Skills Pawn_SkillTracker skillTracker = thePawn.skills; if (skillTracker != null) { foreach (ComparableSkillRecord skill in brainScan.skills) { SkillRecord pawnSkill = skillTracker.GetSkill(skill.def); pawnSkill.Level = (int)Math.Floor((float)skill.level * efficency); pawnSkill.passion = skill.passion; pawnSkill.Notify_SkillDisablesChanged(); } } //Dirty hack ahoy! if (storyTracker != null) { AccessTools.Field(typeof(Pawn_StoryTracker), "cachedDisabledWorkTypes").SetValue(storyTracker, null); } //Training Pawn_TrainingTracker trainingTracker = thePawn.training; if (trainingTracker != null) { DefMap <TrainableDef, bool> learned = (DefMap <TrainableDef, bool>)AccessTools.Field(typeof(Pawn_TrainingTracker), "learned").GetValue(trainingTracker); DefMap <TrainableDef, int> steps = (DefMap <TrainableDef, int>)AccessTools.Field(typeof(Pawn_TrainingTracker), "steps").GetValue(trainingTracker); //Copy foreach (var item in brainScan.trainingLearned) { learned[item.Key] = item.Value; } foreach (var item in brainScan.trainingSteps) { steps[item.Key] = (int)Math.Floor((float)item.Value * efficency); } } //Add Hediffs thePawn.health.AddHediff(QEHediffDefOf.QE_BrainTemplated); if (brainScan.hediffInfos != null && brainScan.hediffInfos.Count > 0) { //add hediffs to pawn from defs in HediffInfo class foreach (HediffInfo h in brainScan.hediffInfos) { thePawn.health.AddHediff(h.def, h.part); } } Messages.Message("QE_BrainTemplatingComplete".Translate(thePawn.Named("PAWN")), MessageTypeDefOf.PositiveEvent, false); } }