예제 #1
0
파일: Skill.cs 프로젝트: ebakkedahl/WCell
        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;
        }
예제 #2
0
파일: Skill.cs 프로젝트: ebakkedahl/WCell
        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();
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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);
        }
예제 #7
0
        //战斗
        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;
        }
예제 #8
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);
        }
예제 #9
0
        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);
        }
예제 #10
0
        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);
        }
예제 #11
0
    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);
        }
    }
예제 #12
0
 public void OnLevelUp(SkillRecord skillRecord, Pawn pawn, int level)
 {
     OnLevelChange(LevelUpMessage, MessageLevelUpDef, skillRecord, pawn, level, MoteLevelUpDef, 1.0f, 100f);
 }
예제 #13
0
 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;
                        }
                    }
                }
            }
        }
예제 #15
0
        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);
        }
예제 #16
0
        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);
        }
예제 #17
0
        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);
        }
예제 #18
0
 private static string GetSkillValue(SkillRecord record) => record.TotallyDisabled ? "-" : record.levelInt.ToString();
예제 #19
0
 public static void BeforeSkillLearned(SkillRecord __instance, ref int __state)
 {
     __state = __instance.levelInt;
 }
예제 #20
0
        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);
        }
예제 #21
0
        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);
            }
        }
예제 #22
0
        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);
        }
예제 #23
0
    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);
    }
예제 #24
0
        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;
 }
예제 #27
0
 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;
            }
        }
예제 #29
0

        
예제 #30
0
        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);
        }
예제 #32
0
        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);
            }
        }