public static bool DropThing(Thing toDrop, IntVec3 from, Map map, bool makeForbidden = true)
        {
            try
            {
                if (!toDrop.Spawned)
                {
                    GenThing.TryDropAndSetForbidden(toDrop, from, map, ThingPlaceMode.Near, out Thing t, makeForbidden);
                    if (!toDrop.Spawned)
                    {
                        GenPlace.TryPlaceThing(toDrop, from, map, ThingPlaceMode.Near);
                    }
                }

                toDrop.Position = from;

                return(toDrop.Spawned);
            }
            catch (Exception e)
            {
                Log.Warning(
                    "ChangeDresser:BuildingUtil.DropApparel\n" +
                    e.GetType().Name + " " + e.Message + "\n" +
                    e.StackTrace);
            }
            return(false);
        }
Example #2
0
        internal static bool TryDrop(this Pawn_ApparelTracker _this, Apparel ap, out Apparel resultingAp, IntVec3 pos, bool forbid = true)
        {
            // drop all toolbelt & backpack stuff so that it won't disappear
            Apparel_Backpack backpack = ap as Apparel_Backpack;

            Thing dropThing = null;

            if (backpack?.slotsComp?.slots?.Count >= 1)
            {
                foreach (Thing slot in backpack.slotsComp.slots)
                {
                    GenThing.TryDropAndSetForbidden(slot, pos, ThingPlaceMode.Near, out dropThing, forbid);
                }
            }

            if (!_this.WornApparel.Contains(ap))
            {
                Log.Warning(_this.pawn.LabelCap + " tried to drop apparel he didn't have: " + ap.LabelCap);
                resultingAp = null;
                return(false);
            }
            _this.WornApparel.Remove(ap);
            ap.wearer = null;
            Thing thing = null;
            bool  flag  = GenThing.TryDropAndSetForbidden(ap, pos, ThingPlaceMode.Near, out thing, forbid);

            resultingAp = (thing as Apparel);
            _this.ApparelChanged();
            if (flag && _this.pawn.outfits != null)
            {
                _this.pawn.outfits.forcedHandler.SetForced(ap, false);
            }
            Combat_Realism.CR_Utility.TryUpdateInventory(_this.pawn);     // Apparel was dropped, update inventory
            return(flag);
        }
        public static bool DropSingleThing(Thing toDrop, IntVec3 from, Map map, bool makeForbidden = false)
        {
            if (toDrop.stackCount == 0)
            {
                Log.Warning("To Drop Thing " + toDrop.Label + " had stack count of 0");
                return(false);
            }

            try
            {
                if (!toDrop.Spawned)
                {
                    GenThing.TryDropAndSetForbidden(toDrop, from, map, ThingPlaceMode.Near, out Thing result, makeForbidden);
                    if (!toDrop.Spawned &&
                        !GenPlace.TryPlaceThing(toDrop, from, map, ThingPlaceMode.Near))
                    {
                        Log.Error("Failed to spawn " + toDrop.Label + " x" + toDrop.stackCount);
                        return(false);
                    }
                }

                toDrop.Position = from;
            }
            catch (Exception e)
            {
                Log.Error(
                    typeof(BuildingUtil).Name + ".DropApparel\n" +
                    e.GetType().Name + " " + e.Message + "\n" +
                    e.StackTrace);
            }
            return(toDrop != null && toDrop.Spawned);
        }
        internal static bool TryDrop(this Pawn_ApparelTracker _this, Apparel ap, out Apparel resultingAp, IntVec3 pos, bool forbid = true)
        {
            // drop all toolbelt & backpack stuff so that it won't disappear
            Apparel_Backpack backpack  = ap as Apparel_Backpack;
            Apparel_Toolbelt toolbelt  = ap as Apparel_Toolbelt;
            Thing            dropThing = null;

            if (backpack?.SlotsComp?.slots?.Count >= 1)
            {
                foreach (Thing slot in backpack.SlotsComp.slots)
                {
                    GenThing.TryDropAndSetForbidden(slot, pos, ap.Map, ThingPlaceMode.Near, out dropThing, forbid);
                }
            }

            if (toolbelt?.slotsComp?.slots?.Count >= 1)
            {
                foreach (Thing slot in toolbelt.slotsComp.slots)
                {
                    GenThing.TryDropAndSetForbidden(slot, pos, ap.Map, ThingPlaceMode.Near, out dropThing, forbid);
                }

                for (int i = MapComponent_ToolsForHaul.CachedToolEntries.Count - 1;
                     i >= 0;
                     i--)
                {
                    var entry = MapComponent_ToolsForHaul.CachedToolEntries[i];
                    if (entry.pawn == _this.pawn)
                    {
                        MapComponent_ToolsForHaul.CachedToolEntries.RemoveAt(i);
                    }
                }
            }


            if (!_this.WornApparel.Contains(ap))
            {
                Log.Warning(_this.pawn.LabelCap + " tried to drop apparel he didn't have: " + ap.LabelCap);
                resultingAp = null;
                return(false);
            }
            if (_this.pawn.MapHeld == null)
            {
                Log.Warning(_this.pawn.LabelCap + " tried to drop apparel but his MapHeld is null.");
                resultingAp = null;
                return(false);
            }
            ap.Notify_Stripped(_this.pawn);
            _this.Remove(ap);
            Thing thing  = null;
            bool  result = GenThing.TryDropAndSetForbidden(ap, pos, _this.pawn.MapHeld, ThingPlaceMode.Near, out thing, forbid);

            resultingAp = (thing as Apparel);

#if CR
            Combat_Realism.CR_Utility.TryUpdateInventory(_this.pawn);     // Apparel was dropped, update inventory
#endif
            return(result);
        }
Example #5
0
        public override void DoEffect(Pawn p)
        {
            base.DoEffect(p);
            var key_stamp = parent.GetComp <CompHoloCryptoStamped>();

            if ((key_stamp == null) || (p.MapHeld == null) || (p.apparel == null))
            {
                return;
            }

            Apparel locked_app = null;
            var     any_locked = false;

            {
                foreach (var app in p.apparel.WornApparel)
                {
                    var app_stamp = app.GetComp <CompHoloCryptoStamped>();
                    if (app_stamp != null)
                    {
                        any_locked = true;
                        if (app_stamp.matches(key_stamp))
                        {
                            locked_app = app;
                            break;
                        }
                    }
                }
            }

            if (locked_app != null)
            {
                //locked_app.Notify_Stripped (p); // TODO This was removed. Necessary?

                p.apparel.Remove(locked_app);
                Thing dropped = null;
                GenThing.TryDropAndSetForbidden(locked_app, p.Position, p.MapHeld, ThingPlaceMode.Near, out dropped, false);                 //this will create a new key somehow.
                if (dropped != null)
                {
                    Messages.Message("Unlocked " + locked_app.def.label, p, MessageTypeDefOf.SilentInput);
                    //parent.DeSpawn();
                    IntVec3 keyPostition = parent.Position;
                    parent.Destroy();
                    keyPostition.GetFirstThing(p.MapHeld, xxx.holokey).Destroy();                      // so I need this line to despawn the new generated key.
                }
                else if (PawnUtility.ShouldSendNotificationAbout(p))
                {
                    Messages.Message("Couldn't drop " + locked_app.def.label, p, MessageTypeDefOf.NegativeEvent);
                }
            }
            else if (any_locked)
            {
                Messages.Message("The key doesn't fit!", p, MessageTypeDefOf.NegativeEvent);
            }
        }
Example #6
0
        public Job ReloadJob()
        {
            if (!hasMagazine)
            {
                return(null);
            }
            IntVec3 position = wielder.Position;

            if (useAmmo)
            {
                // Add remaining ammo back to inventory
                if (curMagCountInt > 0)
                {
                    Thing ammoThing = ThingMaker.MakeThing(currentAmmoInt);
                    ammoThing.stackCount = curMagCountInt;
                    curMagCountInt       = 0;

                    if (compInventory != null)
                    {
                        compInventory.container.TryAdd(ammoThing, ammoThing.stackCount);
                    }
                    else
                    {
                        Thing outThing;
                        GenThing.TryDropAndSetForbidden(ammoThing, position, Find.VisibleMap, ThingPlaceMode.Near, out outThing, turret.Faction != Faction.OfPlayer);
                    }
                }
                // Check for ammo
                if (wielder != null && !hasAmmo)
                {
                    DoOutOfAmmoAction();
                    return(null);
                }
            }

            // Throw mote
            if (Props.throwMote)
            {
                MoteMaker.ThrowText(position.ToVector3Shifted(), Find.VisibleMap, "CE_ReloadingMote".Translate());
            }

            // Issue reload job
            if (wielder != null)
            {
                Job reloadJob = new Job(CE_JobDefOf.ReloadWeapon, wielder, parent)
                {
                    playerForced = true
                };

                return(reloadJob);
            }
            return(null);
        }
Example #7
0
        public bool TryUnload(out Thing droppedAmmo, bool forceUnload = false)
        {
            droppedAmmo = null;
            if (!HasMagazine || (Holder == null && turret == null))
            {
                return(false); // nothing to do as we are in a bad state;
            }
            if (!UseAmmo || curMagCountInt == 0)
            {
                return(true); // nothing to do but we aren't in a bad state either.  Claim success.
            }
            if (Props.reloadOneAtATime && !forceUnload && selectedAmmo == CurrentAmmo && turret == null)
            {
                //For reloadOneAtATime weapons that haven't been explicitly told to unload, and aren't switching their ammo type, skip unloading.
                //The big advantage of a shotguns' reload mechanism is that you can add more shells without unloading the already loaded ones.
                return(true);
            }

            // Add remaining ammo back to inventory
            Thing ammoThing = ThingMaker.MakeThing(currentAmmoInt);

            ammoThing.stackCount = curMagCountInt;
            bool doDrop = false;

            if (CompInventory != null)
            {
                doDrop = (curMagCountInt != CompInventory.container.TryAdd(ammoThing, ammoThing.stackCount)); // TryAdd should report how many ammoThing.stackCount it stored.
            }
            else
            {
                doDrop = true; // Inventory was null so no place to shift the ammo besides the ground.
            }
            if (doDrop)
            {
                // NOTE: If we get here from ThingContainer.TryAdd() it will have modified the ammoThing.stackCount to what it couldn't take.
                //Thing outThing;
                if (!GenThing.TryDropAndSetForbidden(ammoThing, Position, Map, ThingPlaceMode.Near, out droppedAmmo, turret.Faction != Faction.OfPlayer))
                {
                    Log.Warning(String.Concat(this.GetType().Assembly.GetName().Name + " :: " + this.GetType().Name + " :: ",
                                              "Unable to drop ", ammoThing.LabelCap, " on the ground, thing was destroyed."));
                }
            }

            // don't forget to set the clip to empty...
            CurMagCount = 0;

            return(true);
        }
        internal static bool TryDropEquipment(this Pawn_EquipmentTracker _this, ThingWithComps eq, out ThingWithComps resultingEq, IntVec3 pos, bool forbid = true)
        {
            // Fetch private fields
            Pawn           pawn       = (Pawn)pawnFieldInfo.GetValue(_this);
            ThingWithComps primaryInt = (ThingWithComps)primaryIntFieldInfo.GetValue(_this);

            if (!_this.AllEquipment.Contains(eq))
            {
                Log.Warning(pawn.LabelCap + " tried to drop equipment they didn't have: " + eq);
                resultingEq = null;
                return(false);
            }
            if (!pos.IsValid)
            {
                Log.Error(string.Concat(new object[]
                {
                    pawn,
                    " tried to drop ",
                    eq,
                    " at invalid cell."
                }));
                resultingEq = null;
                return(false);
            }
            if (primaryInt == eq)
            {
                primaryIntFieldInfo.SetValue(_this, null);  // Changed assignment to SetValue() since we're fetching a private variable through reflection
            }
            Thing thing = null;
            bool  flag  = GenThing.TryDropAndSetForbidden(eq, pos, ThingPlaceMode.Near, out thing, forbid);

            resultingEq = (thing as ThingWithComps);
            if (flag && resultingEq != null)
            {
                resultingEq.GetComp <CompEquippable>().Notify_Dropped();
            }
            pawn.meleeVerbs.Notify_EquipmentLost();

            Utility.TryUpdateInventory(pawn);       // Dropped equipment, update inventory

            // Cancel current job (use verb, etc.)
            if (pawn.Spawned)
            {
                pawn.stances.CancelBusyStanceSoft();
            }

            return(flag);
        }
        public override void Execute(int amount, string boughtBy)
        {
            var currentMap = Find.CurrentMap;
            var animals    = currentMap.listerThings.ThingsInGroup(ThingRequestGroup.Pawn).Where(nonBondedAnimalPredicate).ToList();

            animals.ForEach(animal =>
            {
                var position = animal.Position;
                animal.Kill();

                var componentToDrop        = ThingMaker.MakeThing(ThingDefOf.ComponentIndustrial);
                componentToDrop.stackCount = Rand.Range(1, 3);
                Thing outThing             = new Thing();
                GenThing.TryDropAndSetForbidden(componentToDrop, position, currentMap, ThingPlaceMode.Direct, out outThing, true);
            });

            AlertManager.NormalEventNotification("Every animal on the map has suddenly died to a bionic plague. You'll find they left behind some surprises!");
        }
 private void DropApparel(Thing a, bool makeForbidden = true)
 {
     try
     {
         Thing t;
         if (!a.Spawned)
         {
             GenThing.TryDropAndSetForbidden(a, base.Position, this.CurrentMap, ThingPlaceMode.Near, out t, makeForbidden);
             if (!a.Spawned)
             {
                 GenPlace.TryPlaceThing(a, base.Position, this.CurrentMap, ThingPlaceMode.Near);
             }
         }
         if (a.Position.Equals(base.Position))
         {
             IntVec3 pos = a.Position;
             if (this.random == null)
             {
                 this.random = new Random();
             }
             int dir    = this.random.Next(2);
             int amount = this.random.Next(2);
             if (amount == 0)
             {
                 amount = -1;
             }
             if (dir == 0)
             {
                 pos.x = pos.x + amount;
             }
             else
             {
                 pos.z = pos.z + amount;
             }
             a.Position = pos;
         }
     }
     catch (Exception e)
     {
         Log.Error("ChangeDresser:Building_Dresser.DropApparel error while dropping apparel. " + e.GetType() + " " + e.Message);
     }
 }
Example #11
0
        public bool TryUnload(out Thing droppedAmmo)
        {
            droppedAmmo = null;
            if (!HasMagazine || (Holder == null && turret == null))
            {
                return(false);        // nothing to do as we are in a bad state;
            }
            if (!UseAmmo || curMagCountInt == 0)
            {
                return(true);        // nothing to do but we aren't in a bad state either.  Claim success.
            }
            // Add remaining ammo back to inventory
            Thing ammoThing = ThingMaker.MakeThing(currentAmmoInt);

            ammoThing.stackCount = curMagCountInt;
            bool doDrop = false;

            if (CompInventory != null)
            {
                doDrop = (curMagCountInt != CompInventory.container.TryAdd(ammoThing, ammoThing.stackCount)); // TryAdd should report how many ammoThing.stackCount it stored.
            }
            else
            {
                doDrop = true; // Inventory was null so no place to shift the ammo besides the ground.
            }
            if (doDrop)
            {
                // NOTE: If we get here from ThingContainer.TryAdd() it will have modified the ammoThing.stackCount to what it couldn't take.
                //Thing outThing;
                if (!GenThing.TryDropAndSetForbidden(ammoThing, Position, Map, ThingPlaceMode.Near, out droppedAmmo, turret.Faction != Faction.OfPlayer))
                {
                    Log.Warning(String.Concat(this.GetType().Assembly.GetName().Name + " :: " + this.GetType().Name + " :: ",
                                              "Unable to drop ", ammoThing.LabelCap, " on the ground, thing was destroyed."));
                }
            }

            // don't forget to set the clip to empty...
            curMagCountInt = 0;

            return(true);
        }
Example #12
0
        internal static bool TryDrop(this Pawn_ApparelTracker _this, Apparel ap, out Apparel resultingAp, IntVec3 pos, bool forbid = true)
        {
            if (!_this.WornApparel.Contains(ap))
            {
                Log.Warning(_this.pawn.LabelCap + " tried to drop apparel he didn't have: " + ap.LabelCap);
                resultingAp = null;
                return(false);
            }
            _this.WornApparel.Remove(ap);
            ap.wearer = null;
            Thing thing = null;
            bool  flag  = GenThing.TryDropAndSetForbidden(ap, pos, ThingPlaceMode.Near, out thing, forbid);

            resultingAp = (thing as Apparel);
            _this.ApparelChanged();
            if (flag && _this.pawn.outfits != null)
            {
                _this.pawn.outfits.forcedHandler.SetForced(ap, false);
            }
            Utility.TryUpdateInventory(_this.pawn);     // Apparel was dropped, update inventory
            return(flag);
        }
        internal static bool TryDropEquipment(this Pawn_EquipmentTracker _this, ThingWithComps eq, out ThingWithComps resultingEq, IntVec3 pos, bool forbid = true)
        {
            // Fetch private fields
            Pawn pawn = (Pawn)pawnFieldInfo.GetValue(_this);

            if (!_this.AllEquipment.Contains(eq))
            {
                Log.Warning(pawn.LabelCap + " tried to drop equipment they didn't have: " + eq);
                resultingEq = null;
                return(false);
            }
            if (!pos.IsValid)
            {
                Log.Error(string.Concat(new object[]
                {
                    pawn,
                    " tried to drop ",
                    eq,
                    " at invalid cell."
                }));
                resultingEq = null;
                return(false);
            }
            _this.Remove(eq);
            Thing thing  = null;
            bool  result = GenThing.TryDropAndSetForbidden(eq, pos, pawn.MapHeld, ThingPlaceMode.Near, out thing, forbid);

            resultingEq = (thing as ThingWithComps);
            CE_Utility.TryUpdateInventory(pawn);       // Dropped equipment, update inventory

            // Cancel current job (use verb, etc.)
            if (pawn.Spawned)
            {
                pawn.stances.CancelBusyStanceSoft();
            }

            return(result);
        }
Example #14
0
        internal static bool _TryDrop(this Pawn_ApparelTracker obj, Apparel ap, out Apparel resultingAp, IntVec3 pos, bool forbid = true)
        {
            var wornApparel = obj.wornApparel();

            if (!wornApparel.Contains(ap))
            {
                Verse.Log.Warning(obj.pawn.LabelCap + " tried to drop apparel he didn't have: " + ap.LabelCap);
                resultingAp = (Apparel)null;
                return(false);
            }
            if (
                (ap is Apparel_SlaveCollar) &&
                (!ap.wearer.health.Dead)
                )
            {
                // Can only take off slave collars of the dead
                Verse.Log.Message(obj.pawn.LabelCap + " tried to remove slave collar but they aren't dead.");
                resultingAp = (Apparel)null;
                return(false);
            }
            wornApparel.Remove(ap);
            ap.wearer = (Pawn)null;
            Thing resultingThing = (Thing)null;
            bool  flag           = GenThing.TryDropAndSetForbidden((Thing)ap, pos, ThingPlaceMode.Near, out resultingThing, forbid);

            resultingAp = resultingThing as Apparel;
            obj.pawn.Drawer.renderer.graphics.ResolveApparelGraphics();
            if (
                (flag) &&
                (obj.pawn.outfits != null)
                )
            {
                obj.pawn.outfits.forcedHandler.SetForced(ap, false);
            }
            return(flag);
        }
Example #15
0
        internal static bool TryDrop(this Pawn_ApparelTracker _this, Apparel ap, out Apparel resultingAp, IntVec3 pos, bool forbid = true)
        {
            if (!_this.WornApparel.Contains(ap))
            {
                Log.Warning(_this.pawn.LabelCap + " tried to drop apparel he didn't have: " + ap.LabelCap);
                resultingAp = null;
                return(false);
            }
            if (_this.pawn.MapHeld == null)
            {
                Log.Warning(_this.pawn.LabelCap + " tried to drop apparel but his MapHeld is null.");
                resultingAp = null;
                return(false);
            }
            ap.Notify_Stripped(_this.pawn);
            _this.Remove(ap);
            Thing thing = null;

            bool result = GenThing.TryDropAndSetForbidden(ap, pos, _this.pawn.MapHeld, ThingPlaceMode.Near, out thing, forbid);

            resultingAp = (thing as Apparel);
            CR_Utility.TryUpdateInventory(_this.pawn);     // Apparel was dropped, update inventory
            return(result);
        }
Example #16
0
        public void TryStartReload()
        {
            if (!hasMagazine)
            {
                return;
            }
            IntVec3 position;

            if (wielder == null)
            {
                if (turret == null)
                {
                    return;
                }
                turret.isReloading = true;
                position           = turret.Position;
            }
            else
            {
                position = wielder.Position;
            }

            if (useAmmo)
            {
                // Add remaining ammo back to inventory
                if (curMagCountInt > 0)
                {
                    Thing ammoThing = ThingMaker.MakeThing(currentAmmoInt);
                    ammoThing.stackCount = curMagCountInt;
                    curMagCountInt       = 0;

                    if (compInventory != null)
                    {
                        compInventory.container.TryAdd(ammoThing, ammoThing.stackCount);
                    }
                    else
                    {
                        Thing outThing;
                        GenThing.TryDropAndSetForbidden(ammoThing, position, Find.VisibleMap, ThingPlaceMode.Near, out outThing, turret.Faction != Faction.OfPlayer);
                    }
                }
                // Check for ammo
                if (wielder != null && !hasAmmo)
                {
                    DoOutOfAmmoAction();
                    return;
                }
            }

            // Throw mote
            if (Props.throwMote)
            {
                MoteMaker.ThrowText(position.ToVector3Shifted(), Find.VisibleMap, "CE_ReloadingMote".Translate());
            }

            // Issue reload job
            if (wielder != null)
            {
                Job reloadJob = new Job(CE_JobDefOf.ReloadWeapon, wielder, parent)
                {
                    playerForced = true
                };

                // Store the current job so we can reassign it later
                if (wielder.Faction == Faction.OfPlayer &&
                    wielder.CurJob != null &&
                    (wielder.CurJob.def == JobDefOf.AttackStatic || wielder.CurJob.def == JobDefOf.Goto || wielder.CurJob.def == JobDefOf.Hunt))
                {
                    if (wielder.CurJob.targetA.HasThing)
                    {
                        storedTarget = new LocalTargetInfo(wielder.CurJob.targetA.Thing);
                    }
                    else
                    {
                        storedTarget = new LocalTargetInfo(wielder.CurJob.targetA.Cell);
                    }
                    storedJobDef = wielder.CurJob.def;
                }
                else
                {
                    storedTarget = null;
                    storedJobDef = null;
                }
                AssignJobToWielder(reloadJob);
            }
        }
Example #17
0
        public static Toil FreeSlave(TargetIndex PrisonerInd, TargetIndex CollarInd)
        {
            var toil = new Toil();

            toil.defaultCompleteMode = ToilCompleteMode.Delay;
            toil.defaultDuration     = 100;
            toil.AddFinishAction(new Action(() =>
            {
                try
                {
                    var slave     = toil.actor.CurJob.GetTarget(PrisonerInd).Thing as Pawn;
                    var collar    = toil.actor.CurJob.GetTarget(CollarInd).Thing as Apparel;
                    var compSlave = slave.TryGetComp <CompSlave>();
                    if (
                        (slave == null) ||
                        (collar == null) ||
                        (compSlave == null)
                        )
                    {
                        throw new Exception(
                            string.Format(
                                "slave = {0}\n\tcollar = {1}\n\tcompSlaver = {2}",
                                slave == null ? "null" : slave.ThingID,
                                collar == null ? "null" : collar.ThingID,
                                compSlave == null ? "null" : "valid"));
                    }
                    if (slave.outfits != null)
                    {
                        slave.outfits.forcedHandler.SetForced(collar, false);
                    }
                    slave.apparel.wornApparel().Remove(collar);
                    collar.wearer        = (Pawn)null;
                    Thing resultingThing = (Thing)null;
                    bool flag            = GenThing.TryDropAndSetForbidden((Thing)collar, slave.Position, ThingPlaceMode.Near, out resultingThing, false);
                    slave.Drawer.renderer.graphics.ResolveApparelGraphics();
                    if (slave.ownership != null)
                    {
                        slave.ownership.UnclaimAll();
                    }
                    var faction = compSlave.originalFaction;
                    if (
                        (faction == null) ||
                        (faction == Faction.OfColony)
                        )
                    {                       // Unknown faction or originally from the colony
                        // Pick outlander faction
                        faction = Find.FactionManager.FirstFactionOfDef(FactionDefOf.Outlander);
                        if (faction == null)
                        {                           // No outlander faction, pick a random non-colony faction
                            Find.FactionManager.TryGetRandomNonColonyHumanlikeFaction(out faction, false);
                        }
                    }
                    // Update control flags
                    compSlave.wasSlave          = true;
                    compSlave.freeSlave         = false;
                    slave.guest.released        = true;
                    slave.guest.interactionMode = PrisonerInteractionMode.NoInteraction;
                    // Remove enslaved trait
                    slave.RemoveTrait(Data.EnslavedTraitDef);
                    // Adjust thoughts
                    if (
                        (slave.needs != null) &&
                        (slave.needs.mood != null) &&
                        (slave.needs.mood.thoughts != null)
                        )
                    {
                        slave.needs.mood.thoughts.RemoveThoughtsOfDef(Data.EnslavedThoughtDef);
                        slave.needs.mood.thoughts.TryGainThought(Data.FreedThoughtDef);
                    }
                    // Restore faction
                    slave.SetFaction(faction, null);
                    // Restore PawnKindDef
                    slave.kindDef = compSlave.originalPawnKind;
                    // Find an exit spot
                    IntVec3 spot;
                    if (!ExitUtility.TryFindClosestExitSpot(slave, out spot, TraverseMode.ByPawn))
                    {
                        Log.Warning("Tried to make slave " + slave.Name + " leave but couldn't find an exit spot");
                        return;
                    }
                    // Stop any other jobs
                    slave.jobs.StopAll(true);
                    Job newJob = new Job(JobDefOf.Goto, spot);
                    newJob.exitMapOnArrival = true;
                    // Assign new exit job
                    slave.jobs.StartJob(newJob, JobCondition.None, (ThinkNode)null, false, true, (ThinkTreeDef)null);
                }
                catch (Exception e)
                {
                    Log.Error("ESM - Prison Improvements :: Could not free slave!\n\t" + e.Message);
                }
            }));
            return(toil);
        }