/// <summary>
        /// enter the given sapience state
        /// </summary>
        /// <param name="stateDef">The state definition.</param>
        /// <param name="initialLevel">The initial level.</param>
        public void EnterState([NotNull] SapienceStateDef stateDef, float initialLevel)
        {
            _sapienceState?.Exit();
            _sapienceState = stateDef.CreateState();


            //need to refresh comps and needs for pawn here
            Pawn.needs?.AddOrRemoveNeedsAsAppropriate();
            _sapienceState.Init(this);
            SapienceLevel = FormerHumanUtilities.GetQuantizedSapienceLevel(initialLevel);
            PawnComponentsUtility.AddAndRemoveDynamicComponents(Pawn);
            var sNeed = SapienceNeed;

            sNeed?.SetSapience(initialLevel);
            _sapienceState.Enter();

            if (Pawn.Faction == Faction.OfPlayer)
            {
                Find.ColonistBar?.MarkColonistsDirty();
            }

            //initialize work settings if they have it
            Pawn.workSettings?.EnableAndInitializeIfNotAlreadyInitialized();

            //interrupts any jobs in case this changes their intelligence
            Pawn.jobs?.EndCurrentJob(JobCondition.InterruptForced);
        }
        /// <summary>
        ///     Makes the parent a former human.
        /// </summary>
        /// <returns></returns>
        public void MakeFormerHuman(float initialLevel) //TODO move most of FormerHumanUtilities.MakeAnimalSapient here
        {
            if (_isFormerHuman)
            {
                Log.Warning($"{nameof(MakeFormerHuman)} is being called on {parent.def}'s {nameof(FormerHumanTracker)} more then once!");
                return;
            }

            _isFormerHuman = true;
            SapienceLevel  = FormerHumanUtilities.GetQuantizedSapienceLevel(initialLevel);
        }
        /// <summary>
        ///     Sets the sapience.
        /// </summary>
        /// <param name="sapience">The sapience.</param>
        public void SetSapience(float sapience)
        {
            _seekerLevel = Mathf.Clamp(sapience, 0, Mathf.Min(MaxLevel, Limit));
            CurLevel     = _seekerLevel;

            SapienceLevel cLevel = FormerHumanUtilities.GetQuantizedSapienceLevel(CurLevel);

            if (_currentLevel != cLevel)
            {
                _currentLevel = cLevel;
                OnSapienceLevelChanges();
            }
        }
Beispiel #4
0
 /// <summary>
 ///     Exposes the data.
 /// </summary>
 public override void ExposeData()
 {
     base.ExposeData();
     Scribe_Values.Look(ref _seekerLevel, nameof(_seekerLevel), -1);
     if (Scribe.mode == LoadSaveMode.PostLoadInit)
     {
         if (_seekerLevel < 0)
         {
             _seekerLevel = CurLevel;
         }
         _currentLevel = FormerHumanUtilities.GetQuantizedSapienceLevel(_seekerLevel);
         CurLevel      = Mathf.Clamp(CurLevel, 0, MaxLevel);
     }
 }
 /// <summary>
 ///     called every so often by the need manager.
 /// </summary>
 /// <exception cref="System.NotImplementedException"></exception>
 public override void NeedInterval()
 {
     base.NeedInterval();
     if (pawn.IsHashIntervalTick(TimeMetrics.TICKS_PER_REAL_SECOND)) //just every second or so
     {
         TrySubscribe();
         CalculateCachesIfNeeded();
         _seekerLevel = Mathf.Min(_seekerLevel, Limit);
         float instinctChange = GetInstinctChangePerTick(pawn) * TimeMetrics.TICKS_PER_REAL_SECOND;
         if (Mathf.Abs(instinctChange) > EPSILON)
         {
             AddInstinctChange(instinctChange);
         }
         //_maxLevelCached = null;
         SapienceLevel sLevel = FormerHumanUtilities.GetQuantizedSapienceLevel(CurLevel);
         if (sLevel != _currentLevel)
         {
             _currentLevel = sLevel;
             OnSapienceLevelChanges();
         }
     }
 }
Beispiel #6
0
        /// <summary>
        ///     called every so often by the need manager.
        /// </summary>
        /// <exception cref="System.NotImplementedException"></exception>
        public override void NeedInterval()
        {
            base.NeedInterval();
            if (pawn.IsHashIntervalTick(TimeMetrics.TICKS_PER_REAL_SECOND)) //just every second or so
            {
                float instinctChange = GetInstinctChangePerTick(pawn) * TimeMetrics.TICKS_PER_REAL_SECOND;
                if (Mathf.Abs(instinctChange) > EPSILON)
                {
                    AddInstinctChange(Mathf.CeilToInt(instinctChange));
                }
                _maxLevelCached = null;
                SapienceLevel sLevel = FormerHumanUtilities.GetQuantizedSapienceLevel(CurLevel);
                if (sLevel != _currentLevel)
                {
                    _currentLevel = sLevel;
                    OnSapienceLevelChanges();
                }

                if (_currentLevel == SapienceLevel.Feral && Rand.MTBEventOccurs(4, 60000f, 30f))
                {
                    TriggerPermanentlyFeralChange();
                }
            }
        }
Beispiel #7
0
        /// <summary>
        ///     preform the requested transform
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns></returns>
        protected override TransformedPawnSingle TransformImpl(TransformationRequest request)
        {
            Pawn original = request.originals[0];

            if (request.addMutationToOriginal)
            {
                TryAddMutationsToPawn(original, request.cause, request.outputDef);
            }

            var     reactionStatus = original.GetFormerHumanReactionStatus();
            float   newAge         = TransformerUtility.ConvertAge(original, request.outputDef.race.race);
            Faction faction;

            faction = GetFaction(request, original);

            Gender newGender =
                TransformerUtility.GetTransformedGender(original, request.forcedGender, request.forcedGenderChance);


            var pRequest = FormerHumanUtilities.CreateSapientAnimalRequest(request.outputDef, original, faction, fixedGender: newGender);



            Pawn animalToSpawn = PawnGenerator.GeneratePawn(pRequest); //make the temp pawn



            animalToSpawn.needs.food.CurLevel =
                original.needs.food.CurLevel;   // Copies the original pawn's food need to the animal's.
            animalToSpawn.needs.rest.CurLevel =
                original.needs.rest.CurLevel;   // Copies the original pawn's rest need to the animal's.
            animalToSpawn.Name = original.Name; // Copies the original pawn's name to the animal's.
            float sapienceLevel = request.forcedSapienceLevel ?? GetSapienceLevel(original, animalToSpawn);

            if (request.forcedFaction == null && original.Faction != faction && original.Faction != animalToSpawn.Faction && FormerHumanUtilities.GetQuantizedSapienceLevel(sapienceLevel) <= SapienceLevel.MostlySapient)
            {
                //set the faction to the original's if mostly sapient or above
                animalToSpawn.SetFaction(original.Faction);
            }


            GiveTransformedPawnSapienceState(animalToSpawn, sapienceLevel);

            FormerHumanUtilities.InitializeTransformedPawn(original, animalToSpawn, sapienceLevel); //use a normal distribution?

            Pawn spawnedAnimal = SpawnAnimal(original, animalToSpawn);                              // Spawns the animal into the map.

            ReactionsHelper.OnPawnTransforms(original, animalToSpawn, reactionStatus);              //this needs to happen before MakeSapientAnimal because that removes relations

            var rFaction = request.factionResponsible ?? GetFactionResponsible(original);
            var inst     = new TransformedPawnSingle
            {
                original           = original,
                animal             = spawnedAnimal,
                factionResponsible = rFaction,
                reactionStatus     = reactionStatus
            };


            if (original.Spawned)
            {
                for (var i = 0; i < 10; i++) // Create a cloud of magic.
                {
                    IntermittentMagicSprayer.ThrowMagicPuffDown(spawnedAnimal.Position.ToVector3(), spawnedAnimal.MapHeld);
                    IntermittentMagicSprayer.ThrowMagicPuffUp(spawnedAnimal.Position.ToVector3(), spawnedAnimal.MapHeld);
                }
            }

            if (request.tale != null) // If a tale was provided, push it to the tale recorder.
            {
                TaleRecorder.RecordTale(request.tale, original, animalToSpawn);
            }

            Faction oFaction = original.FactionOrExtraHomeFaction;
            Map     oMap     = original.Map;


            //apply any other post tf effects
            ApplyPostTfEffects(original, animalToSpawn, request);

            TransformerUtility
            .CleanUpHumanPawnPostTf(original, request.cause);    //now clean up the original pawn (remove apparel, drop'em, ect)

            //notify the faction that their member has been transformed
            oFaction?.Notify_MemberTransformed(original, animalToSpawn, oMap == null, oMap);

            if (!request.noLetter && reactionStatus == FormerHumanReactionStatus.Colonist || reactionStatus == FormerHumanReactionStatus.Prisoner) //only send the letter for colonists and prisoners
            {
                SendLetter(request, original, spawnedAnimal);
            }

            if (original.Spawned)
            {
                original.DeSpawn(); // Remove the original pawn from the current map.
            }
            DebugLogUtils.Assert(!PrisonBreakUtility.CanParticipateInPrisonBreak(original),
                                 $"{original.Name} has been cleaned up and de-spawned but can still participate in prison breaks");


            return(inst);
        }