Exemplo n.º 1
0
 private static string TendrilRestoreStr(BackData back, PlayerBase player)
 {
     return("You hear a faint pop, and see one of your tendrils falling to the ground out of the corner of your eye. " +
            SafelyFormattedString.FormattedText("That's strange", StringFormats.ITALIC) + " you think, though it's possible you whacked it on something earlier, and they are quite fragile." +
            " Several more pops follow, however, and now you're sure something's up. Each of your tentacles fall to the ground, and when you feel along your back, they show no signs of " +
            "regrowing. In fact, your back feels completely smooth. It seems " + SafelyFormattedString.FormattedText("you've lost your tendrils!", StringFormats.BOLD));
 }
Exemplo n.º 2
0
 protected static string BehemothRestoreStr(BackData back, PlayerBase player)
 {
     return("Your back and spine are suddenly overwhelmed with a sense of pins-and-needles. Unsure as to what exactly is causing this, you " +
            (player.wearingAnything ? "undress and " : "") + "find something reflective to check your back with. It seems that your back became completely normal " +
            "while you were searching for something reflective. That was fast! You wait for anything else to happen, and when nothing does, you are sure " +
            SafelyFormattedString.FormattedText("Your back is completely normal again!", StringFormats.BOLD));
 }
Exemplo n.º 3
0
        public BackData requestData(string[] data)
        {
            PBase _pBase = PFactory.instance.stringToClass(data);

            if (_pBase != null)
            {
                switch (_pBase.act)
                {
                case "1":
                    return(DBCtrl.instance.doSQLAdd(_pBase));

                case "2":
                    return(DBCtrl.instance.doSQLDel(_pBase));

                case "3":
                    return(DBCtrl.instance.doSQLEdit(_pBase));

                case "4":
                    return(DBCtrl.instance.doSQLFind(_pBase));
                }
            }
            BackData backData = new BackData();

            _pBase        = new PBase();
            _pBase.result = "0";
            //backData.data.Add(_pBase);

            return(backData);
        }
Exemplo n.º 4
0
        private static string DraconicSpikesTransformStr(BackData back, PlayerBase player)
        {
            string seeItHow;

            if (player.neck.type == NeckType.DRACONIC || player.neck.type == NeckType.COCKATRICE)
            {
                seeItHow = "you bend your neck around to look at it. ";
            }
            else if (player.tail.type == TailType.DRACONIC)
            {
                seeItHow = "you bend your tail around and look at it. ";
            }
            else
            {
                seeItHow = "strain your neck trying to see it, but eventually give up and find something reflective, "
                           + " and watch it that way. ";
            }

            string oldText  = back.type != BackType.NORMAL ? " your back shakes violently, forcibly reshaping until it's once again smooth, but the pain still remains. " : "";
            string tailText = player.tail.type != TailType.NONE ? "your tail, ending just before the tip. " : "until it reaches your butt. ";

            return(GlobalStrings.NewParagraph() + "You feel a sudden pain along your spine. Eager to see what's causing this, " + seeItHow + oldText +
                   "The pain seems to focus into smaller areas, which start to bulge outward against your skin. The bulges grow larger and more painful until, with one final " +
                   "burst of pain, spikes break through your skin. You nearly black out, but manage to retain your senses as they continue their growth, curving down and away from your neck. " +
                   GlobalStrings.NewParagraph() + "Once they stop growing, you notice the spikes form a line along your spine, starting at the base of your neck and continuing down " + tailText +
                   "The spikes are spaced evenly, each one steel-gray in color and maybe " + Measurement.ToNearestSmallUnit(2, false, true) +
                   " tall, their base roughly " + Measurement.ToNearestHalfSmallUnit(1, false, true) + " in diameter. "
                   + SafelyFormattedString.FormattedText("Your spine is now decorated with a row of curved spikes!", StringFormats.BOLD));
        }
Exemplo n.º 5
0
        protected static string BehemothTransformStr(BackData back, PlayerBase player)
        {
            StringBuilder sb = new StringBuilder(GlobalStrings.NewParagraph() + "Your back and spine are suddenly overwhelmed with a sense of pins-and-needles. Unsure as to what exactly is causing this, you " +
                                                 (player.wearingAnything ? "undress and " : "") + "find something reflective to check your back with.");

            if (back.type == BackType.DRACONIC_SPIKES)
            {
                sb.Append("Strangely, each one of your spikes has started to split, forming two smaller spikes to the left and right of their previous location. Hair starts to grow between each " +
                          "new pair, which continue to move away from the center of your back. Eventually, they stop moving and straighten out instead. Once this finishes, you notice ");
            }
            else if (back.type == BackType.DRACONIC_MANE)
            {
                sb.Append("Along both sides of the mane running down your spine, a set of small spikes poke through your skin, causing intense discomfort. Once the spikes have finished, " +
                          "you notice ");
            }

            else
            {
                if (back.type != BackType.NORMAL)
                {
                    sb.Append("It seems that your back became completely normal while you were searching for something reflective. That was fast! You shrug, assuming that was it, when you" +
                              "notice something else happening. ");
                }
                sb.Append("You begin to notice a unique tuft of hair forming along your spine, starting at the base of your neck and continuing down ");
                sb.Append(player.tail.type != TailType.NONE ? "your tail, all the way to the end, where it forms a small tuft. " : "until it reaches your butt. ");
                sb.Append("It is the same color as the hair on your head, but shorter and denser. Along either side of it, a set of small spikes poke through your skin, " +
                          "causing intense discomfort. Once the spikes have finished, you notice ");
            }



            sb.Append(SafelyFormattedString.FormattedText("you have a back much like your behemoth friend!", StringFormats.BOLD) + "The hair forms a thick vertical strip, maybe " +
                      Measurement.ToNearestSmallUnit(2, false, true) + " wide, and you'd estimate each spike is roughly half that width, but protrudes from your back at least that far.");
            return(sb.ToString());
        }
Exemplo n.º 6
0
        protected static string DraconicManeTransformStr(BackData previousBackData, PlayerBase player)
        {
            string seeItHow;

            if (player.neck.type == NeckType.DRACONIC || player.neck.type == NeckType.COCKATRICE)
            {
                seeItHow = "you bend your neck around to look at it. ";
            }
            else if (player.tail.type == TailType.DRACONIC)
            {
                seeItHow = "you bend your tail around and look at it. ";
            }
            else
            {
                seeItHow = "strain your neck trying to see it, but eventually give up and find something reflective, "
                           + " and watch it that way. ";
            }

            string tailText = player.tail.type != TailType.NONE ? "your tail, all the way to the end, where it forms a small tuft. " : "until it reaches your butt. ";
            string oldText  = previousBackData.type != BackType.NORMAL ? "Somehow, your back has become perfectly smooth, though the tingling remains. " : "";

            return(GlobalStrings.NewParagraph() + "You feel a sudden tingle just above your spine. Eager to see what's causing this, " + seeItHow + oldText +
                   "Tiny splotches of hair begin growing out of your " + player.body.mainEpidermis.ShortDescription() +
                   ". The hair grows longer and the splotches grow until they slowly merge to a vertical strip right above your spine." +
                   GlobalStrings.NewParagraph() + "The hair forms a mane along your spine, starting at the base of your neck and continuing down " + tailText +
                   "It is the same color as the hair on your head, but shorter and denser; it has grown in a thick vertical strip, maybe " + Measurement.ToNearestSmallUnit(2, false, true) +
                   " wide. It reminds you vaguely of a horse's mane. " + SafelyFormattedString.FormattedText("You now have a hairy mane along your spine!", StringFormats.BOLD));
        }
Exemplo n.º 7
0
 /// <summary>
 /// 打开串口的事件方法,也是启动所有功能的方法
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void ButtonClick_OpenSerial(object sender, RoutedEventArgs e)
 {
     _adam = new ADAM(
         comBoBox_SerialNames.Text,              //串口
         Convert.ToInt32(comBoBox_SerialPort));  //波特率
     _adam.Open();                               //启动
     _data = new BackData(_adam);                //后台注册
 }
Exemplo n.º 8
0
 public AnalogModelControl(BackData back, AnalogConfigModel model)
 {
     this._model    = model;
     this._backData = back;
     InitializeComponent();
     _backData.Timer.Add(GetValue);
     text_id.Text   = model.Name;
     text_port.Text = model.Port.ToString();
 }
Exemplo n.º 9
0
 private static string TendrilLongDesc(BackData back, bool alternateFormat)
 {
     if (alternateFormat)
     {
         return("a back covered in inky-black tendrils near the center, along the spine");
     }
     else
     {
         return("back, with inky-black tendrils sprouting from its center, near the spine");
     }
 }
Exemplo n.º 10
0
        private static string SharkFinTransformStr(BackData back, PlayerBase player)
        {
            string introText = "You groan as a sharp pain between your shoulders forces you to the ground. Your breathing becomes ragged and you start sweating profusely.";

            if (back.type == BackType.TENDRILS)
            {
                return(introText + " A sharp sensation seems to be pushing your tendrils off from the inside, and they fall to the ground as something else bursts from your spine. " +
                       "Replacing them is a strange fin-like structure, not nearly as wide but covering much more of your spine." +
                       SafelyFormattedString.FormattedText("You now have a shark-like fin!", StringFormats.BOLD));
            }
            else if (back.type == BackType.DRACONIC_SPIKES)
            {
                return(introText + " Your spikes seem to be moving up along your back, fusing together as they reach the area between your shoulders. They reshape, and skin forms around them." +
                       "Once the pain subsides, you notice your spikes " + SafelyFormattedString.FormattedText("are now a shark's fin!", StringFormats.BOLD));
            }
            else if (back.type == BackType.BEHEMOTH)
            {
                return(introText + "Your spikes start to move inward, toward the hair along your spine. As they do, the hair starts to fall away, briefly leaving clear skin before the spikes" +
                       "cover where it once was. the two rows become one, fusing together as they travel along your towards your shoulders. ");
            }
            else if (back.type == BackType.DRACONIC_MANE)
            {
                return(introText + " the hair forming the mane along your back starts falling off in great chunks, as if pushed off from the inside. Just as the final strand of hair falls away," +
                       "a large, fin like structure pushes out of your back and replaces it. " + SafelyFormattedString.FormattedText("You now have a shark fin!", StringFormats.BOLD));
            }
            else if (back.type != BackType.NORMAL)
            {
                string removeArmorText = player.wearingAnything ? " You hastily remove your " + player.armor.ItemName() + " and " : "You ";

                return(introText + removeArmorText + "notice your back isn't the same anymore - in fact, it appears normal. But it doesn't remain that way for long when a strange fin-like " +
                       "structure bursts from in-between your shoulders. You examine it carefully and make a few modifications to your " + player.armor.ItemName() + " to accommodate your new fin.");
            }
            else
            {
                string removeArmorText = player.wearingAnything ? " You hastily remove your " + player.armor.ItemName() + " barely getting it off before a " : "A ";

                return(introText + removeArmorText + "strange fin-like structure bursts from in-between your shoulders. You examine it carefully and make a few modifications to your " +
                       player.armor.ItemName() + " to accommodate your new fin.");
            }
        }
Exemplo n.º 11
0
        private static string TendrilTransformStr(BackData back, PlayerBase player)
        {
            StringBuilder sb = new StringBuilder("A stabbing pain erupts along your back. The pain is so intense, ");

            if (player.lowerBody.isBiped || player.lowerBody.type == LowerBodyType.GOO)
            {
                sb.Append("you're forced onto your " + player.hands.ShortDescription() + ", your back arched toward the sky. ");
            }
            else
            {
                sb.Append("you collapse to the ground, arching your back to try and alleviate it in some way. ");
            }

            //lazy man's way - just 'revert' it first, then go as if human.
            if (back.type != BackType.NORMAL)
            {
                sb.Append("Your back spasms violently, forcing you in and out of consciousness as your body handles a forced change. When it stops, you back is completely smooth, " +
                          "but another wave of pain suggests it's far from over. ");
            }

            sb.Append("A scream escapes your lips as the pain intensifies, culminating in a tearing sound as something bursts out around the middle of your back. " +
                      "It's quickly followed by several more, though you're in no condition to determine the exact amount. Finally, mercifully, it stops. Feeling along your back, " +
                      "You grab ahold of something soft, almost squishy, and you pull it around to the front to see exactly what it is. It suddenly squirms to life, and you panic, " +
                      "yanking it and throwing it away from you. Realizing what you just did, you brace for even more pain, but all you feel is minor discomfort. Cautiously, " +
                      "you investigate what exactly it was you just ripped off, which has since stopped squirming. It's a tendril - long, thing, and inky-black. " +
                      "You realize you have several of these along your back now, though one less than what your started with. Just as that thought crosses your mind, a tugging sensation " +
                      "occurs where the now severed tendril attached to your back, and you place your hand back there again. It seems a new tendril is growing in, right where the old one was. " +
                      "Seems like " + SafelyFormattedString.FormattedText("you now have tendrils growing along your back!", StringFormats.BOLD) + "You soon realize you can control them like a " +
                      "third arm (well, third and fourth and fifth, and so on). No doubt, these could be useful in combat");

            if (player.corruption >= 50)
            {
                sb.Append(", or in other, \"kinkier\" situations, you note with a smirk");
            }
            sb.Append(".");

            return(sb.ToString());
        }
Exemplo n.º 12
0
        protected internal override string DoTransformation(Creature target, out bool isBadEnd)
        {
            isBadEnd = false;

            int changeCount      = GenerateChangeCount(target, new int[] { 2, 2 });
            int remainingChanges = changeCount;

            StringBuilder sb = new StringBuilder();

            sb.Append(InitialTransformationText(target));

            //No cost stat changes.

            //Effect script 1: (higher intelligence)
            if (target.relativeIntelligence < 100 && Utils.Rand(3) == 0)
            {
                target.IncreaseIntelligence(1);
                if (target.relativeIntelligence < 50)
                {
                    target.IncreaseIntelligence(1);
                }
            }
            //Effect script 2: (lower sensitivity)
            if (target.relativeSensitivity >= 20 && Utils.Rand(3) == 0)
            {
                target.ChangeSensitivity(-2);
                if (target.relativeSensitivity >= 75)
                {
                    target.ChangeSensitivity(-2);
                }
            }
            //Effect script 3: (higher libido)
            if (target.relativeLibido < 100 && Utils.Rand(3) == 0)
            {
                target.ChangeLibido(1);
                if (target.relativeLibido < 50)
                {
                    target.ChangeLibido(1);
                }
            }

            //this will handle the edge case where the change count starts out as 0.
            if (remainingChanges <= 0)
            {
                return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
            }

            //Effect script a: (human wang)
            if (target.hasCock && target.cocks[0].type != CockType.defaultValue)
            {
                //sb.Append("\n\nA strange tingling begins behind your " + target.cockDescript(0) + ", slowly crawling up across its entire length. While neither particularly arousing nor uncomfortable, you do shift nervously as the feeling intensifies. You resist the urge to undo your " + target.armorName + " to check, but by the feel of it, your penis is shifting form. Eventually the transformative sensation fades, <b>leaving you with a completely human penis.</b>");
                target.genitals.RestoreCock(0);

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Neck restore
            if (!target.neck.isDefault && Utils.Rand(4) == 0)
            {
                NeckData oldData = target.neck.AsReadOnlyData();
                target.RestoreNeck();
                sb.Append(RestoredNeckText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Rear body restore
            if (!target.back.isDefault && Utils.Rand(5) == 0)
            {
                BackData oldData = target.back.AsReadOnlyData();
                target.RestoreBack();
                sb.Append(RestoredBackText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Ovi perk loss
            if (target.womb.canRemoveOviposition && Utils.Rand(5) == 0)
            {
                target.womb.ClearOviposition();
                sb.Append(ClearOvipositionText(target));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Appearnace Change
            //Hair
            if (Utils.Rand(4) == 0 && !target.hair.isSemiTransparent)
            {
                //this isn't a type anymore, so you can apply it to all types. it's now just a flag.

                //sb.Append("\n\nA sensation of weightlessness assaults your scalp. You reach up and grab a handful of hair, confused.
                //Your perplexion only heightens when you actually feel the follicles becoming lighter in your grasp, before you can hardly tell you're holding anything.
                //Plucking a strand, you hold it up before you, surprised to see... it's completely transparent! You have transparent hair!");
                target.hair.SetTransparency(true);

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Skin
            if (Utils.Rand(4) == 0 && target.body.type != BodyType.HUMANOID || (target.body.mainEpidermis.tone != Tones.SABLE && target.body.mainEpidermis.tone != Tones.WHITE &&
                                                                                target.body.mainEpidermis.tone != Tones.MILKY_WHITE))
            {
                Tones tone;
                Tones veins;

                if (Utils.RandBool())
                {
                    tone  = Tones.MILKY_WHITE;
                    veins = Tones.BLACK;
                }
                else
                {
                    tone  = Tones.SABLE;
                    veins = Tones.WHITE;
                }

                target.UpdateBody(BodyType.HUMANOID, tone);

                //sb.Append("\n\nA warmth begins in your belly, slowly spreading through your torso and appendages. The heat builds, becoming uncomfortable, then painful, then nearly unbearable. Your eyes unfocus from the pain, and by the time the burning sensation fades, you can already tell something's changed. You raise a hand, staring at the {tone} flesh. Your eyes are drawn to the veins in the back of your {hand}, {(tone == MILKY_WHITE ? "brightening to an ashen tone" : "darkening to a jet black")} as you watch. <b>You have {tone} skin, with {vein} veins!</b>");

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            if (!target.HasPerk <Incorporeal>() && target.hair.isSemiTransparent &&
                (target.body.mainEpidermis.tone == Tones.SABLE || target.body.mainEpidermis.tone == Tones.WHITE || target.body.mainEpidermis.tone == Tones.MILKY_WHITE))
            {
                //(ghost-legs! Absolutely no problem with regular encounters, though! [if you somehow got this with a centaur it'd probably do nothing cuz you're not supposed to be a centaur with ectoplasm ya dingus])
                //sb.Append("\n\nAn otherworldly sensation begins in your belly, working its way to your [hips]. Before you can react, your [legs]"
                //+ " begin to tingle, and you fall on your rump as a large shudder runs through them. As you watch, your lower body shimmers,"
                //+ " becoming ethereal, wisps rising from the newly ghost-like [legs]. You manage to rise, surprised to find your new,"
                //+ " ghostly form to be as sturdy as its former corporeal version. Suddenly, like a dam breaking,"
                //+ " fleeting visions and images flow into your head, never lasting long enough for you to concentrate on one."
                //+ " You don't even realize it, but your arms fly up to your head, grasping your temples as you groan in pain."
                //+ " As fast as the mental bombardment came, it disappears, leaving you with a surprising sense of spiritual superiority."
                //+ " <b>You have ghost legs!</b>\n\n");
                //sb.Append("<b>(Gained Perk: Incorporeality</b>)");
                target.perks.AddPerk <Incorporeal>();

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Effect Script 8: 100% chance of healing
            if (remainingChanges == changeCount && target is CombatCreature cc2)
            {
                //sb.Append("You feel strangely refreshed, as if you just gobbled down a bottle of sunshine. A smile graces your lips as vitality fills you. ");
                cc2.AddHP((uint)cc2.level * 5 + 10);
            }
            //Incorporeality Perk Text: You seem to have inherited some of the spiritual powers of the residents of the afterlife! While you wouldn't consider doing it for long due to its instability, you can temporarily become incorporeal for the sake of taking over enemies and giving them a taste of ghostly libido.

            //Sample possession text (>79 int, perhaps?): With a smile and a wink, your form becomes completely intangible, and you waste no time in throwing yourself into your opponent's frame. Before they can regain the initiative, you take control of one of their arms, vigorously masturbating for several seconds before you're finally thrown out. Recorporealizing, you notice your enemy's blush, and know your efforts were somewhat successful.
            //Failure: With a smile and a wink, your form becomes completely intangible, and you waste no time in throwing yourself into the opponent's frame. Unfortunately, it seems they were more mentally prepared than you hoped, and you're summarily thrown out of their body before you're even able to have fun with them. Darn, you muse. Gotta get smarter.

            //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes
            //occurred, then return the contents of the stringbuilder.
            return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
        }
        protected internal override string DoTransformation(Creature target, out bool isBadEnd)
        {
            isBadEnd = false;

            //for some unknown reason, demon tfs roll out their own chance system completely unique to them. ok.

            StringBuilder sb = new StringBuilder();

            //For all of these, any text regarding the transformation should be instead abstracted out as an abstract string function. append the result of this abstract function
            //to the string builder declared above (aka sb.Append(FunctionCall(variables));) string builder is just a fancy way of telling the compiler that you'll be creating a
            //long string, piece by piece, so don't do any crazy optimizations first.

            //the initial text for starting the transformation. feel free to add additional variables to this if needed.
            sb.Append(InitialTransformationText(target));

            //Add any free changes here - these can occur even if the change count is 0. these include things such as change in stats (intelligence, etc)
            //change in height, hips, and/or butt, or other similar stats.

            int rando = Utils.Rand(100);
            int delta = target.GetExtraData()?.deltaTransforms ?? 0;

            if (delta != 0)
            {
                rando += 5 * delta + Utils.Rand(5 * delta);
            }

            //First, check if this tf has the male flag set (for male or herm tfs). If it does, add or grow cocks.
            if (desiredGender.HasFlag(Gender.MALE))
            {
                byte addedCocks = 0;
                //if our initial roll was a crit, roll again. if we crit again, we may add several cocks, if possible.
                if (rando >= 85 && target.cocks.Count < Genitals.MAX_COCKS && Utils.Rand(10) < target.corruptionTrue / 25)
                {
                    addedCocks = GrowCockGeneric(target, (byte)(Utils.Rand(2) + 2));

                    target.DeltaCreatureStats(lib: 3 * addedCocks, sens: 5 * addedCocks, lus: 10 * addedCocks);
                    if (!isPurified)
                    {
                        target.IncreaseCorruption(8);
                    }
                }
                //otherwise, only add a c**k if we have none or we originally rolled a crit (but failed to crit again)
                else if (target.cocks.Count == 0 || (rando >= 85 && target.cocks.Count < Genitals.MAX_COCKS))
                {
                    addedCocks = GrowCockGeneric(target, 1);

                    target.DeltaCreatureStats(lib: 3, sens: 5, lus: 10);
                    if (!isPurified)
                    {
                        target.IncreaseCorruption(5);
                    }
                }
                //if that fails, it means we had a c**k already, or can't grow any more of them.
                else
                {
                    C**k   shortest = target.genitals.ShortestCock();
                    double lengthDelta;

                    if (rando >= 45)
                    {
                        lengthDelta = shortest.IncreaseLength(Utils.Rand(3) + 3);
                        shortest.IncreaseThickness(1);
                    }
                    else if (Utils.Rand(4) == 0)
                    {
                        lengthDelta = shortest.IncreaseLength(3);
                    }
                    else
                    {
                        lengthDelta = shortest.IncreaseLength(1);
                    }

                    target.DeltaCreatureStats(lib: 2, sens: 1, lus: 5 + lengthDelta * 3);
                    if (!isPurified)
                    {
                        target.IncreaseCorruption();
                    }
                    //no idea why this occurs, but ok.
                    target.IncreaseIntelligence(1);
                }
            }
            //Otherwise, we're targeting female demon tfs only. this means we need to shrink (and possibly remove) the largest c**k the target has, unless hyper happy is on.
            else if (!hyperHappy && target.hasCock)
            {
                C**k largest = target.genitals.LongestCock();                 //this loops through all the cocks and finds the longest. obviously, if the count is 1, this is simply the first element.

                //we'll need this if it gets removed. if not, this can still be used, this time to determine how much we shrunk.
                CockData oldData = largest.AsReadOnlyData();

                //try decreasing it by 1-3. if this causes it to be removed instead, that's fine, but we need to know.
                //Note that this remove is now IN PLACE, not LAST. so if we remove the 3rd one, the old 4th is now 3rd, and so on.
                bool removed = target.genitals.ShrinkCockAndRemoveIfTooSmall(largest, Utils.Rand(3) + 1);
            }

            //Then, check if the tf has the female flag set (for female or herm tfs). if it does, add a v****a (if needed), and increase breast size.
            if (desiredGender.HasFlag(Gender.FEMALE))
            {
                //don't currently have a v****a and herm tf or we're genderless, or it's a crit, or we rerolled a crit.
                if (!target.hasVagina && (desiredGender == Gender.HERM || target.gender == Gender.GENDERLESS || rando > 65 || Utils.Rand(3) == 0))
                {
                    target.genitals.AddVagina(VaginaType.HUMAN);
                }
                //do have one, and rolled a high crit.
                else if (target.hasVagina && rando >= 85)
                {
                    foreach (V****a vag in target.vaginas)
                    {
                        //grow each c**t anywhere from 0.25in to 1in, if they are below the largest normal size.
                        if (vag.c**t.length < vag.c**t.largestNormalSize)
                        {
                            vag.GrowClit((Utils.Rand(4) + 1) * 0.25);
                            //cap it at the largest normal size.
                            if (vag.c**t.length > vag.c**t.largestNormalSize)
                            {
                                vag.SetClitSize(vag.c**t.largestNormalSize);
                            }
                        }
                    }
                }
                //do have one, rolled a crit, but not a high crit.
                else if (target.hasVagina && rando > 65)
                {
                    target.HaveGenericVaginalOrgasm(0, true, true);
                    target.vaginas.ForEach(x => x.IncreaseWetness());
                }


                //now, breasts. these are the fallback, of sorts, so they grow larger when we don't crit. they also grow larger when we crit if we're targeting herms.

                if (rando < 85 || desiredGender == Gender.HERM)
                {
                    //only occurs via herm.
                    if (rando >= 85)
                    {
                        target.breasts.ForEach(x => x.GrowBreasts(3));
                    }
                    else
                    {
                        byte    temp        = (byte)(1 + Utils.Rand(3));
                        CupSize largestSize = target.genitals.BiggestCupSize();
                        if (largestSize < CupSize.B && Utils.Rand(3) == 0)
                        {
                            temp++;
                        }

                        if (largestSize < CupSize.DD && Utils.Rand(4) == 0)
                        {
                            temp++;
                        }

                        if (largestSize < CupSize.DD_BIG && Utils.Rand(5) == 0)
                        {
                            temp++;
                        }

                        target.breasts.ForEach(x => x.GrowBreasts(temp));
                    }
                }
            }
            //if not, we're targeting male demon tfs only. this means we may need to shrink any overlarge breasts. Additionally, higher rng rolls may now remove vaginas.
            else if (!hyperHappy)
            {
                //if high crit: decrease bonus capacity, and remove a v****a, flat-out.
                if (rando >= 85 && target.hasVagina)
                {
                    target.genitals.DecreaseBonusVaginalCapacity(5);
                    target.genitals.RemoveVagina();
                }
                //otherwise, if somewhat high, decrease bonus vaginal capacity (all vaginas), and wetness (last v****a). if this causes the bonus capacity to drop to 0
                //and would cause it to go negative if we allowed that, remove the last v****a.
                else if (rando >= 65)
                {
                    V****a lastVagina = target.vaginas[target.vaginas.Count - 1];
                    lastVagina.DecreaseWetness(1);

                    //this is being super pedantic, but i'd prefer it lower the stat, then remove the v****a. hence this bool here.
                    bool remove = target.genitals.standardBonusVaginalCapacity < 5;
                    //decrease first.
                    target.genitals.DecreaseBonusVaginalCapacity(5);

                    //then remove it.
                    if (remove)
                    {
                        target.genitals.RemoveVagina();
                    }
                }

                //
                if (target.genitals.BiggestCupSize() > target.genitals.smallestPossibleCupSize && (rando >= 85 || (rando > 65 && Utils.RandBool()) || (rando <= 65 && Utils.Rand(4) == 0)))
                {
                    foreach (Breasts breast in target.breasts)
                    {
                        if (breast.cupSize > target.genitals.smallestPossibleCupSize)
                        {
                            byte amount = 1;
                            if (rando >= 85)
                            {
                                amount++;
                            }

                            breast.ShrinkBreasts(amount);
                        }
                    }
                }
            }

            //never called in vanilla. if i read it correctly, it just initializes to 0 with a max of 1.
            int changeCount = base.GenerateChangeCount(target, new int[] { 3 }, 0, 0);

            if (changeCount == 0)
            {
                return(ApplyChangesAndReturn(target, sb, 0));
            }

            int remainingChanges = changeCount;


            //Neck restore
            if (!target.neck.isDefault && Utils.Rand(4) == 0)
            {
                NeckData oldData = target.neck.AsReadOnlyData();
                target.RestoreNeck();
                sb.Append(RestoredNeckText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Rear body restore
            if (!target.back.isDefault && Utils.Rand(5) == 0)
            {
                BackData oldData = target.back.AsReadOnlyData();
                target.RestoreBack();
                sb.Append(RestoredBackText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Ovi perk loss
            if (target.womb.canRemoveOviposition && Utils.Rand(5) == 0)
            {
                target.womb.ClearOviposition();
                sb.Append(ClearOvipositionText(target));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Demonic changes - higher chance with higher corruption.
            if (Utils.Rand(40) + target.corruption / 3 > 35 && !isPurified)
            {
                //Change tail if already horned.
                if (target.tail.type != TailType.DEMONIC && !target.horns.isDefault)
                {
                    target.IncreaseCorruption(4);
                    TailData oldData = target.tail.AsReadOnlyData();
                    target.UpdateTail(TailType.DEMONIC);
                    sb.Append(UpdateTailText(target, oldData));

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
                //grow horns!
                if (target.horns.numHorns == 0 || (Utils.Rand(target.horns.numHorns + 3) == 0))
                {
                    if (target.horns.numHorns < 12 && (target.horns.type == HornType.NONE || target.horns.type == HornType.DEMON))
                    {
                        if (target.horns.type == HornType.NONE)
                        {
                            target.UpdateHorns(HornType.DEMON);
                        }

                        target.IncreaseCorruption(3);
                    }
                    //Text for shifting horns
                    else if (target.horns.type != HornType.DEMON)
                    {
                        target.UpdateHorns(HornType.DEMON);
                        target.IncreaseCorruption(3);
                    }

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
                //Nipples Turn Back:
                if (target.genitals.hasBlackNipples && Utils.Rand(3) == 0)
                {
                    target.genitals.SetBlackNipples(false);

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }

                //remove fur
                if (target.face.type != FaceType.HUMAN || (target.body.type != BodyType.HUMANOID && Utils.Rand(3) == 0))
                {
                    //Remove face before fur!
                    if (target.face.type != FaceType.HUMAN)
                    {
                        target.RestoreFace();
                    }
                    //De-fur
                    else if (target.body.type != BodyType.HUMANOID)
                    {
                        target.RestoreBody();
                    }

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
                //Demon tongue
                if (target.tongue.type == TongueType.SNAKE && Utils.Rand(3) == 0)
                {
                    TongueData oldData = target.tongue.AsReadOnlyData();
                    target.UpdateTongue(TongueType.DEMONIC);
                    sb.Append(UpdateTongueText(target, oldData));

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
                //foot changes - requires furless
                if (target.body.type == BodyType.HUMANOID && Utils.Rand(4) == 0)
                {
                    bool changed;
                    //Males/genderless get clawed feet
                    if (!target.gender.HasFlag(Gender.FEMALE) || (target.gender == Gender.HERM && target.genitals.AppearsMoreMaleThanFemale()))
                    {
                        changed = target.UpdateLowerBody(LowerBodyType.DEMONIC_CLAWS);
                    }
                    //Females/futa get high heels
                    else
                    {
                        changed = target.UpdateLowerBody(LowerBodyType.DEMONIC_HIGH_HEELS);
                    }

                    if (changed && --remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
                //Grow demon wings
                if ((target.wings.type != WingType.BAT_LIKE || !target.wings.isLarge || target.back.type == BackType.SHARK_FIN) && Utils.Rand(8) == 0 && target.IsCorruptEnough(50))
                {
                    //grow smalls to large

                    if (target.wings.type == WingType.BAT_LIKE && target.IsCorruptEnough(75))
                    {
                        target.wings.GrowLarge();
                    }
                    else
                    {
                        target.UpdateWings(WingType.BAT_LIKE);
                    }

                    if (target.back.type == BackType.SHARK_FIN)
                    {
                        target.RestoreBack();
                    }

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
            }
            //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes
            //occurred, then return the contents of the stringbuilder.
            return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
        }
Exemplo n.º 14
0
        protected internal override string DoTransformation(Creature target, out bool isBadEnd)
        {
            isBadEnd = false;

            //by default, this is 2 rolls at 50%, so a 25% chance of 0 additional tfs, 50% chance of 1 additional tf, 25% chance of 2 additional tfs.
            //also takes into consideration any perks that increase or decrease tf effectiveness. if you need to roll out your own, feel free to do so.
            int changeCount      = GenerateChangeCount(target, new int[] { 2, 2 });
            int remainingChanges = changeCount;

            StringBuilder sb = new StringBuilder();

            //For all of these, any text regarding the transformation should be instead abstracted out as an abstract string function. append the result of this abstract function
            //to the string builder declared above (aka sb.Append(FunctionCall(variables));) string builder is just a fancy way of telling the compiler that you'll be creating a
            //long string, piece by piece, so don't do any crazy optimizations first.

            //the initial text for starting the transformation. feel free to add additional variables to this if needed.
            sb.Append(InitialTransformationText(target));

            //Add any free changes here - these can occur even if the change count is 0. these include things such as change in stats (intelligence, etc)
            //change in height, hips, and/or butt, or other similar stats.

            //this will handle the edge case where the change count starts out as 0.
            if (remainingChanges <= 0)
            {
                return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
            }

            //Any transformation related changes go here. these typically cost 1 change. these can be anything from body parts to gender (which technically also changes body parts,
            //but w/e). You are required to make sure you return as soon as you've applied changeCount changes, but a single line of code can be applied at the end of a change to do
            //this for you.

            //paste this line after any tf is applied, and it will: automatically decrement the remaining changes count. if it becomes 0 or less, apply the total number of changes
            //underwent to the target's change count (if applicable) and then return the StringBuilder content.
            //if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges);

            //Corruption reduction
            if (isPure)
            {             //Special honey will also reduce corruption, but uses different text and is handled separately
                target.ChangeCorruption(-(1 + (target.corruptionTrue / 20)));
                //Libido Reduction
                if (target.corruption > 0 && Utils.Rand(3) < 2 && target.relativeLibido > 40)
                {
                    target.DeltaCreatureStats(lib: -3, lus: -20);
                }
            }
            //Intelligence Boost
            if (Utils.Rand(2) == 0 && target.relativeIntelligence < 80)
            {
                target.IncreaseIntelligence(0.1 * (80 - target.relativeIntelligence));
            }
            //bee item corollary:
            if (target.hair.type == HairType.ANEMONE && Utils.Rand(2) == 0)
            {
                HairData oldData = target.hair.AsReadOnlyData();
                target.RestoreHair();
                sb.Append(RestoredHairText(target, oldData));
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //Sexual Stuff
            //No idears
            //Appearance Stuff
            //Hair Color
            if (target.hair.hairColor != HairFurColors.BLACK && target.hair.length > 10 && Utils.Rand(5) == 0)
            {
                if (Utils.Rand(9) == 0)
                {
                    target.hair.SetBothHairColors(HairFurColors.BLACK, HairFurColors.YELLOW);
                }
                else
                {
                    target.hair.SetHairColor(HairFurColors.BLACK);
                }

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Hair Length
            if (target.hair.length < 25 && target.hair.type.canLengthen && Utils.Rand(3) == 0)
            {
                target.hair.GrowHair(Utils.Rand(4) + 1);
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Remove extra breast rows
            if (target.breasts.Count > 2 && Utils.Rand(3) == 0 && !hyperHappy)
            {
                target.genitals.RemoveBreastRows();
            }
            //Antennae
            if (target.antennae.type == AntennaeType.NONE && target.horns.numHorns == 0 && Utils.Rand(3) == 0)
            {
                AntennaeData oldData = target.antennae.AsReadOnlyData();
                target.UpdateAntennae(AntennaeType.BEE);
                sb.Append(UpdateAntennaeText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Horns
            if (!target.horns.isDefault && Utils.Rand(3) == 0)
            {
                HornData oldData = target.horns.AsReadOnlyData();
                target.RestoreHorns();
                sb.Append(RestoredHornsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Bee Legs
            if (target.lowerBody.type != LowerBodyType.BEE && Utils.Rand(4) == 0)
            {
                LowerBodyData oldData = target.lowerBody.AsReadOnlyData();
                target.UpdateLowerBody(LowerBodyType.BEE);
                sb.Append(UpdateLowerBodyText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //(Arms to carapace-covered arms)
            if (target.arms.type != ArmType.BEE && Utils.Rand(4) == 0)
            {
                ArmData oldData = target.arms.AsReadOnlyData();
                target.UpdateArms(ArmType.BEE);
                sb.Append(UpdateArmsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Nipples reduction to 1 per tit.
            if (target.genitals.hasQuadNipples && Utils.Rand(4) == 0)
            {
                target.genitals.SetQuadNipples(false);

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Neck restore
            if (!target.neck.isDefault && Utils.Rand(4) == 0)
            {
                NeckData oldData = target.neck.AsReadOnlyData();
                target.RestoreNeck();
                sb.Append(RestoredNeckText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Rear body restore
            if (!target.back.isDefault && Utils.Rand(5) == 0)
            {
                BackData oldData = target.back.AsReadOnlyData();
                target.RestoreBack();
                sb.Append(RestoredBackText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Lose reptile oviposition!
            if (target.womb.canRemoveOviposition && Utils.Rand(5) == 0)
            {
                target.womb.ClearOviposition();
                sb.Append(ClearOvipositionText(target));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Gain bee ovipositor!
            if (target.tail.type == TailType.BEE_STINGER && !target.tail.hasOvipositor && Utils.Rand(2) == 0)
            {
                target.tail.GrantOvipositor();
            }

            //Bee butt - 66% lower chance if already has a tail
            if (target.tail.type != TailType.BEE_STINGER && (target.tail.type == TailType.NONE || Utils.Rand(3) < 2) && Utils.Rand(4) == 0)
            {
                target.UpdateTail(TailType.BEE_STINGER);
                target.tail.UpdateResources((short)(10 - target.tail.resources), (short)(2 - target.tail.regenRate));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Venom Increase
            if (target.tail.type == TailType.BEE_STINGER && target.tail.regenRate < 15 && Utils.Rand(2) == 0)
            {
                short additionalRegen = 1;
                if (target.tail.regenRate < 5)
                {
                    additionalRegen = 3;
                }
                else if (target.tail.regenRate < 10)
                {
                    additionalRegen = 2;
                }

                target.tail.UpdateResources(50, additionalRegen);

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Wings
            //Grow bigger bee wings!
            if (target.wings.type == WingType.BEE_LIKE && !target.wings.isLarge && Utils.Rand(4) == 0)
            {
                target.wings.GrowLarge();

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //Grow new bee wings if target has none.
            if (target.wings.type == WingType.NONE && Utils.Rand(4) == 0)
            {
                if (target.back.type == BackType.SHARK_FIN)
                {
                    target.RestoreBack();
                }
                WingData oldData = target.wings.AsReadOnlyData();
                target.UpdateWings(WingType.BEE_LIKE);
                sb.Append(UpdateWingsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Melt demon wings!
            if (target.wings.type == WingType.BAT_LIKE)
            {
                WingData oldData = target.wings.AsReadOnlyData();
                target.RestoreWings();
                sb.Append(RestoredWingsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Remove gills!
            if (Utils.Rand(4) == 0 && !target.gills.isDefault)
            {
                GillData oldData = target.gills.AsReadOnlyData();
                target.RestoreGills();
                sb.Append(RestoredGillsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //All the speical honey effects occur after any normal bee transformations (if the target wasn't a full bee morph)
            if (isSpecial)
            {
                //if no c**k: grow one.
                if (!target.hasCock)
                {
                    target.genitals.AddCock(CockType.defaultValue, Utils.Rand(3) + 8, 2);
                    target.HaveGenericCockOrgasm(0, false, true);
                    target.ChangeSensitivity(10);
                }
                //if multiple cocks, remove the largest c**k by area. combine its length/girth into the first c**k.
                else if (target.cocks.Count > 1)
                {
                    //find the biggest c**k that isn't the first one.
                    C**k   biggest = target.cocks.Skip(1).MaxItem(x => x.area);
                    double delta   = (double)(5 * Math.Sqrt(0.2 * biggest.area));

                    target.cocks[0].DeltaLengthAndGirth(delta, delta);
                    target.HaveGenericCockOrgasm(0, false, true);
                }
                //one c**k. grow it to 100 area total or larger
                else if (target.cocks[0].area < 100)
                {
                    target.cocks[0].DeltaLengthAndGirth(Utils.Rand(3) + 4, 0.1 * Utils.Rand(5) + 0.5);
                }
                //
                else
                {
                    double baseLengthChange;
                    double baseGirthChange;
                    if (target.cocks[0].type != CockType.BEE && Species.CurrentSpecies(target) == Species.BEE)
                    {
                        target.genitals.UpdateCock(0, CockType.BEE);
                        target.ChangeSensitivity(15);

                        baseLengthChange = 5;
                        baseGirthChange  = 1;
                    }
                    else
                    {
                        baseLengthChange = 0.1 * Utils.Rand(10) + 1;
                        baseGirthChange  = 0.1 * Utils.Rand(2) + 1;
                    }

                    double mult;
                    C**k   c**k = target.cocks[0];
                    if (c**k.area >= 400)
                    {
                        mult = 0;                         //C**k stops growing at that point.
                    }
                    else if (c**k.area >= 300)
                    {
                        mult = 0.1;
                    }
                    if (c**k.area > 100)
                    {
                        int offset = (((int)c**k.area) - 100) / 40;
                        mult = 1 - 0.2 * offset;
                    }
                    else
                    {
                        mult = 1;
                    }

                    double deltaLength = (double)(mult * baseLengthChange);
                    double deltaGirth  = (double)(mult * baseGirthChange);

                    target.cocks[0].DeltaLengthAndGirth(deltaLength, deltaGirth);
                }


                if (target.corruption >= 5)
                {
                    double corrLoss = Math.Min(0.1 * target.corruptionTrue + 5, target.corruptionTrue);
                    target.DeltaCreatureStats(corr: -corrLoss, lib: corrLoss);                     //Lose corruption and gains that much libido
                }
                else
                {
                    target.ChangeLibido(5);
                }

                if (target.femininity >= 60 || target.femininity <= 40)
                {
                    if (target.femininity >= 60)
                    {
                        target.femininity.IncreaseMasculinity(3);
                    }
                    else
                    {
                        target.femininity.IncreaseFemininity(3);
                    }
                }
                target.ChangeLust(0.2 * target.libidoTrue + 5);
            }


            //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes
            //occurred, then return the contents of the stringbuilder.
            return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
        }
Exemplo n.º 15
0
        protected internal override string DoTransformation(Creature target, out bool isBadEnd)
        {
            isBadEnd = false;

            int changeCount      = GenerateChangeCount(target, new int[] { 2, 2 });
            int remainingChanges = changeCount;

            StringBuilder sb = new StringBuilder();

            //the initial text for starting the transformation. feel free to add additional variables to this if needed.
            sb.Append(InitialTransformationText(target));

            //Add any free changes here - these can occur even if the change count is 0. these include things such as change in stats (intelligence, etc)
            //change in height, hips, and/or butt, or other similar stats.

            //this will handle the edge case where the change count starts out as 0.
            if (remainingChanges <= 0)
            {
                return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
            }

            //Any transformation related changes go here. these typically cost 1 change. these can be anything from body parts to gender (which technically also changes body parts,
            //but w/e). You are required to make sure you return as soon as you've applied changeCount changes, but a single line of code can be applied at the end of a change to do
            //this for you.

            //paste this line after any tf is applied, and it will: automatically decrement the remaining changes count. if it becomes 0 or less, apply the total number of changes
            //underwent to the target's change count (if applicable) and then return the StringBuilder content.
            //if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges);

            //-----------------------
            // MAJOR TRANSFORMATIONS
            //-----------------------
            //1st priority: Change lower body to bipedal.
            if (Utils.Rand(4) == 0)
            {
                LowerBodyData oldData = target.lowerBody.AsReadOnlyData();
                target.RestoreLowerBody();
                sb.Append(RestoredLowerBodyText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Remove Oviposition Perk
            if (target.womb.canRemoveOviposition && Utils.Rand(5) == 0)
            {
                target.womb.ClearOviposition();
                sb.Append(ClearOvipositionText(target));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Remove Incorporeality Perk, if not permanent
            if (target.HasPerk <Incorporeal>() && Utils.Rand(4) == 0)
            {
                target.RemovePerk <Incorporeal>();

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Restore neck
            if (target.neck.type != NeckType.HUMANOID && Utils.Rand(5) == 0)
            {
                NeckData oldData = target.neck.AsReadOnlyData();
                target.RestoreNeck();
                sb.Append(RestoredNeckText(target, oldData));
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Rear body restore
            if (!target.back.isDefault && Utils.Rand(5) == 0)
            {
                BackData oldData = target.back.AsReadOnlyData();
                target.RestoreBack();
                sb.Append(RestoredBackText(target, oldData));
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Skin color change – light, fair, olive, dark, ebony, mahogany, russet
            if (!Species.HUMAN.availableTones.Contains(target.body.primarySkin.tone) && Utils.Rand(5) == 0)
            {
                target.body.ChangeAllSkin(Utils.RandomChoice(Species.HUMAN.availableTones));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Change skin to normal
            if (target.body.type != BodyType.HUMANOID && (target.ears.type == EarType.HUMAN || target.ears.type == EarType.ELFIN) && Utils.Rand(4) == 0)
            {
                BodyData oldData = target.body.AsReadOnlyData();
                target.RestoreBody();
                sb.Append(RestoredBodyText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Restore arms to become human arms again
            if (Utils.Rand(4) == 0)
            {
                ArmData oldData = target.arms.AsReadOnlyData();
                target.RestoreArms();
                sb.Append(RestoredArmsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-----------------------
            // MINOR TRANSFORMATIONS
            //-----------------------
            //-Human face
            if (target.face.type != FaceType.HUMAN && Utils.Rand(4) == 0)
            {
                FaceData oldData = target.face.AsReadOnlyData();
                target.RestoreFace();
                sb.Append(RestoreFaceText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Human tongue
            if (target.tongue.type != TongueType.HUMAN && Utils.Rand(4) == 0)
            {
                TongueData oldData = target.tongue.AsReadOnlyData();
                target.RestoreTongue();
                sb.Append(RestoreTongueText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Remove odd eyes
            if (Utils.Rand(5) == 0 && target.eyes.type != EyeType.HUMAN)
            {
                EyeData oldData = target.eyes.AsReadOnlyData();
                target.RestoreEyes();
                sb.Append(RestoredEyesText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Gain human ears (If you have human face)
            if (target.ears.type != EarType.HUMAN && target.face.type == FaceType.HUMAN && Utils.Rand(4) == 0)
            {
                EarData oldData = target.ears.AsReadOnlyData();
                target.RestoreEar();
                sb.Append(RestoreEarsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Removes gills
            if (Utils.Rand(4) == 0 && !target.gills.isDefault)
            {
                GillData oldData = target.gills.AsReadOnlyData();
                target.RestoreGills();
                sb.Append(RestoredGillsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Nipples Turn Back:
            if (target.genitals.hasBlackNipples && Utils.Rand(3) == 0)
            {
                target.genitals.SetBlackNipples(false);
            }
            //Remove extra nipples
            if (target.genitals.hasQuadNipples && Utils.Rand(3) == 0)
            {
                target.genitals.SetQuadNipples(false);
            }
            //Hair turns normal
            //Restart hair growth, if hair's normal but growth isn't on. Or just over turning hair normal. The power of rng.
            if ((target.hair.type != HairType.NORMAL || target.hair.growthArtificallyDisabled) && Utils.Rand(3) == 0)
            {
                target.UpdateHair(HairType.NORMAL);
                if (target.hair.growthArtificallyDisabled)
                {
                    target.hair.SetHairGrowthStatus(true);
                }

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-----------------------
            // EXTRA PARTS REMOVAL
            //-----------------------
            //Removes antennae
            if (target.antennae.type != AntennaeType.NONE && Utils.Rand(3) == 0)
            {
                AntennaeData oldData = target.antennae.AsReadOnlyData();
                target.RestoreAntennae();
                sb.Append(RestoredAntennaeText(target, oldData));
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Removes horns
            if ((target.horns.type != HornType.NONE) && Utils.Rand(5) == 0)
            {
                HornData oldData = target.horns.AsReadOnlyData();
                target.RestoreHorns();
                sb.Append(RestoredHornsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Removes wings
            if (target.wings.type != WingType.NONE && Utils.Rand(5) == 0)
            {
                WingData oldData = target.wings.AsReadOnlyData();
                target.RestoreWings();
                sb.Append(RestoredWingsText(target, oldData));
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Removes tail
            if (target.tail.type != TailType.NONE && Utils.Rand(5) == 0)
            {
                TailData oldData = target.tail.AsReadOnlyData();
                target.RestoreTail();
                sb.Append(RestoredTailText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Increase height up to 4ft 10in.
            if (Utils.Rand(2) == 0 && target.build.heightInInches < 58)
            {
                int temp = Utils.Rand(5) + 3;
                //Flavor texts. Flavored like 1950's cigarettes. Yum.
                target.build.IncreaseHeight((byte)temp);
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Decrease height down to a maximum of 6ft 2in.
            if (Utils.Rand(2) == 0 && target.build.heightInInches > 74)
            {
                target.build.DecreaseHeight((byte)(3 + Utils.Rand(5)));
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-----------------------
            // SEXUAL TRANSFORMATIONS
            //-----------------------
            //Remove additional cocks
            if (target.cocks.Count > 1 && Utils.Rand(3) == 0)
            {
                target.RemoveCock();
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Remove additional balls/remove uniball
            if (target.balls.hasBalls && (target.balls.count != 2 || target.balls.uniBall) && Utils.Rand(3) == 0)
            {
                if (target.balls.size > 2)
                {
                    if (target.balls.size > 5)
                    {
                        target.balls.ShrinkBalls((byte)(1 + Utils.Rand(3)));
                    }

                    target.balls.ShrinkBalls(1);
                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
                else if (target.balls.count > 2)
                {
                    target.balls.RemoveExtraBalls();

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
                else                 //if (target.balls.count == 1 || target.balls.uniBall)
                {
                    target.balls.MakeStandard();

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
            }

            //remove second v****a.
            if (target.vaginas.Count > 1 && Utils.Rand(3) == 0)
            {
                target.genitals.RemoveExtraVaginas();
            }

            //Change c**k back to normal
            if (target.hasCock && !target.genitals.OnlyHasCocksOfType(CockType.HUMAN) && Utils.Rand(3) == 0)
            {
                //Select first non-human c**k
                C**k firstNonHuman = target.cocks.First(x => x.type != CockType.HUMAN);

                target.genitals.UpdateCock(firstNonHuman, CockType.HUMAN);
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            C**k   longest    = target.genitals.LongestCock();
            double targetSize = Math.Max(7, target.genitals.minimumCockLength);

            //Shrink oversized cocks
            if (target.hasCock && longest.length > targetSize && Utils.Rand(3) == 0)
            {
                longest.DecreaseLength((Utils.Rand(10) + 2) / 10.0);
                if (longest.girth > 1)
                {
                    longest.DecreaseThickness((Utils.Rand(4) + 1) / 10.0);
                }
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Remove additional breasts
            if (target.breasts.Count > 1 && Utils.Rand(3) == 0)
            {
                target.RemoveExtraBreastRows();

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            Breasts biggestCup = target.genitals.LargestBreast();
            CupSize targetCup  = EnumHelper.Max(CupSize.D, target.genitals.smallestPossibleFemaleCupSize);

            //Shrink t**s!
            if (Utils.Rand(3) == 0 && biggestCup.cupSize > targetCup)
            {
                foreach (Breasts t**s in target.breasts)
                {
                    t**s.ShrinkBreasts();
                }
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Change v****a back to normal
            if (Utils.Rand(3) == 0 && target.hasVagina && !target.genitals.OnlyHasVaginasOfType(VaginaType.defaultValue))
            {
                foreach (V****a vag in target.vaginas)
                {
                    target.genitals.RestoreVagina(vag);
                }

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            VaginalWetness targetWetness = EnumHelper.Max(VaginalWetness.WET, target.genitals.minVaginalWetness);

            //Reduce wetness down to a minimum of 2
            if (Utils.Rand(3) == 0 && target.hasVagina && target.genitals.LargestVaginalWetness() > targetWetness)
            {
                foreach (V****a vag in target.vaginas)
                {
                    if (vag.wetness > targetWetness)
                    {
                        vag.DecreaseWetness();
                    }
                }
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Fertility Decrease:
            if (target.hasVagina && target.fertility.baseFertility > 10 && Utils.Rand(3) == 0)
            {
                //High fertility:
                //Average fertility:

                target.fertility.DecreaseFertility((byte)(1 + Utils.Rand(3)));
                if (target.fertility.baseFertility < 10)
                {
                    target.fertility.SetFertility(10);
                }

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Cum Multiplier Decrease:
            if (target.hasCock && target.genitals.cumMultiplier > 5 && Utils.Rand(3) == 0)
            {
                target.genitals.DecreaseCumMultiplier(1 + (Utils.Rand(20) / 10.0));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Anal wetness decrease
            if (target.ass.wetness > 0 && Utils.Rand(3) == 0)
            {
                target.ass.DecreaseWetness();
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }


            //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes
            //occurred, then return the contents of the stringbuilder.
            return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
        }
Exemplo n.º 16
0
        protected internal override string DoTransformation(Creature target, out bool isBadEnd)
        {
            isBadEnd = false;

            //by default, this is 2 rolls at 50%, so a 25% chance of 0 additional tfs, 50% chance of 1 additional tf, 25% chance of 2 additional tfs.
            //also takes into consideration any perks that increase or decrease tf effectiveness. if you need to roll out your own, feel free to do so.
            int changeCount      = GenerateChangeCount(target, new int[] { 2, 2 });
            int remainingChanges = changeCount;

            StringBuilder sb = new StringBuilder();

            //For all of these, any text regarding the transformation should be instead abstracted out as an abstract string function. append the result of this abstract function
            //to the string builder declared above (aka sb.Append(FunctionCall(variables));) string builder is just a fancy way of telling the compiler that you'll be creating a
            //long string, piece by piece, so don't do any crazy optimizations first.

            //the initial text for starting the transformation. feel free to add additional variables to this if needed.

            //Add any free changes here - these can occur even if the change count is 0. these include things such as change in stats (intelligence, etc)
            //change in height, hips, and/or butt, or other similar stats.



            double crit = 0;

            if (Utils.Rand(100) < 15)
            {
                crit = Utils.Rand(20) / 10.0 + 2;
            }

            bool hasCrit() => crit > 1;

            sb.Append(InitialTransformationText(target, crit));


            //STAT CHANGES - TOU SPE INT RANDOM CHANCE, LIB LUST COR ALWAYS UPPED
            target.DeltaCreatureStats(lib: 1 + Utils.Rand(2), lus: 5 + Utils.Rand(10), corr: 1 + Utils.Rand(5));
            if (target.relativeToughness < 70 && Utils.Rand(3) == 0)
            {
                double delta = target.ChangeToughness(crit);
                sb.Append(IncreasedToughnessText(crit, delta));
            }
            if (target.relativeSpeed > 30 && Utils.Rand(7) == 0)
            {
                double loss = target.DecreaseSpeed(crit);
                sb.Append(DecreasedSpeedText(crit, loss));
            }
            if (target.relativeIntelligence < 60 && Utils.Rand(7) == 0)
            {
                double delta = target.ChangeIntelligence(crit);
                sb.Append(IncreasedIntelligenceText(crit, delta));
            }

            //handle edge case where we start at 0.
            if (remainingChanges <= 0)
            {
                return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
            }

            //Non-free changes.

            //if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges);


            //MUTATIONZZZZZ
            //PRE-CHANGES: become biped, remove horns, remove wings, give human tongue, remove claws, remove antennea
            //no claws
            if (Utils.Rand(4) == 0 && target.arms.hands.isClaws)
            {
                ArmData oldData = target.arms.AsReadOnlyData();

                if (target.RestoreArms())
                {
                    sb.Append(RestoredArmsText(target, oldData));
                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
            }
            //remove antennae
            if (target.antennae.type != AntennaeType.NONE && Utils.Rand(3) == 0)
            {
                AntennaeData oldData = target.antennae.AsReadOnlyData();
                target.RestoreAntennae();

                sb.Append(RestoredAntennaeText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //remove horns
            if (target.horns.type != HornType.NONE && Utils.Rand(3) == 0)
            {
                HornData oldData = target.horns.AsReadOnlyData();
                target.RestoreHorns();
                sb.Append(RestoredHornsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //remove wings
            if ((target.wings.type != WingType.NONE || target.back.type == BackType.SHARK_FIN) && Utils.Rand(3) == 0)
            {
                BackData oldBack = target.back.AsReadOnlyData();
                if (target.back.type == BackType.SHARK_FIN)
                {
                    target.RestoreBack();
                }

                WingData oldWings = target.wings.AsReadOnlyData();
                target.RestoreWings();
                sb.Append(RestoredBackAndWings(target, oldWings, oldBack));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //give human tongue
            if (target.tongue.type != TongueType.HUMAN && Utils.Rand(3) == 0)
            {
                //MOD NOTE: this was incorrect - this actually was === (equal with strict typechecking) instead of = (assign). so this was an implicit bool.
                //this is part of the reason why the rework forces all value updates as function calls. the more you know.
                TongueData oldData = target.tongue.AsReadOnlyData();
                target.RestoreTongue();
                sb.Append(RestoredTongueText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //remove non-wolf eyes
            if (Utils.Rand(3) == 0 && target.eyes.type != EyeType.HUMAN && target.eyes.type != EyeType.WOLF)
            {
                EyeData oldData = target.eyes.AsReadOnlyData();
                target.RestoreEyes();
                sb.Append(RestoredEyesText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //normal legs
            if (target.lowerBody.type != LowerBodyType.WOLF && Utils.Rand(4) == 0)
            {
                LowerBodyData oldData = target.lowerBody.AsReadOnlyData();
                target.RestoreLowerBody();
                sb.Append(RestoredLowerBodyText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //normal arms
            if (Utils.Rand(4) == 0)
            {
                ArmData oldData = target.arms.AsReadOnlyData();
                target.RestoreArms();
                sb.Append(RestoredArmsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            HairData oldHair = target.hair.AsReadOnlyData();

            //remove feather hair
            if (Utils.Rand(4) == 0 && RemoveFeatheryHair(target))
            {
                sb.Append(RemovedFeatheryHairText(target, oldHair));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //remove basilisk hair
            if (Utils.Rand(4) == 0 && target.hair.IsBasiliskHair())
            {
                HairData oldData = target.hair.AsReadOnlyData();
                target.RestoreHair();
                target.hair.SetHairLength(0);
                target.hair.ResumeNaturalGrowth();

                sb.Append(RemovedBasiliskHair(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //MUTATIONZ AT ANY TIME: wolf dick, add/decrease breasts, decrease breast size if above D
            //get a wolf dick
            //if ya genderless we give ya a dick cuz we nice like that
            //MOD: Now respects hyper happy.
            if (target.gender == Gender.GENDERLESS && !hyperHappy)
            {
                target.genitals.AddCock(CockType.WOLF, Utils.Rand(4) + 4, Utils.Rand(8) / 4.0 + 0.25, 1.5);

                sb.Append(BecameMaleByGrowingCock(target));

                target.DeltaCreatureStats(lib: 3, sens: 2, lus: 25);
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //if ya got a dick that's ok too we'll change it to wolf
            //MOD NOTE: but only if you don't only have wolf cocks, of course (because if they are all wolf cocks, we can't make anything wolf cocks, duh).
            if (target.hasCock && !target.genitals.OnlyHasCocksOfType(CockType.WOLF) && Utils.RandBool())
            {
                //MOD NOTE: no longer shamelessly copy/pasted from dog c**k, because we have better ways of looping in C#.

                C**k     firstNonWolf = target.cocks.First(x => x.type != CockType.WOLF);
                CockData oldData      = firstNonWolf.AsReadOnlyData();

                //Select first non-wolf c**k
                //MOD: now using type description because we can, so the fact this used generic is irrelevant now :)

                if (firstNonWolf.type == CockType.HORSE)
                {                 //horses get changes
                    if (firstNonWolf.length > 6)
                    {
                        firstNonWolf.DecreaseLength(2);
                    }
                    else
                    {
                        firstNonWolf.DecreaseLength(.5);
                    }

                    firstNonWolf.IncreaseThickness(.5);
                }

                target.DeltaCreatureStats(sens: 3, lus: 5 * crit);


                target.genitals.UpdateCockWithKnot(firstNonWolf, CockType.WOLF, 1.5);
                firstNonWolf.IncreaseThickness(2);

                sb.Append(ChangedCockToWolf(target, oldData, oldData.cockIndex));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //titties for those who got titties
            //wolfs have 8 nips so, 4 rows max. fen has no power here I'm making a wolf not a dog.
            //MOD: still stolen shamelessly from dog and updated, but now with the modern format. woo!

            //MOD: if breasts can be updated (not flat) and we flip a coin.
            if (target.genitals.BiggestCupSize() > CupSize.FLAT && Utils.RandBool())
            {
                if (target.breasts.Count < 4)
                {
                    byte breastCount = (byte)target.breasts.Count;
                    BreastCollectionData oldBreastData = target.genitals.allBreasts.AsReadOnlyData();

                    //in vanilla code, we had some strange checks here that required the first row (and only the first row) be a certain size.
                    //now, we check all the rows, but no longer require any of them to be a certain size. instead, if it's not the right size, we make it that size,
                    //then add the row. so, for two rows, your first row must be at least a B-Cup. for 3: first must be a C cup, second an A cup.
                    //if we supported 4 rows, it'd be D, B, A.

                    for (int x = 0; x < target.breasts.Count; x++)
                    {
                        CupSize requiredSize = (CupSize)(byte)(target.breasts.Count - x);
                        if (x == 0)
                        {
                            requiredSize++;
                        }
                        if (target.breasts[x].cupSize < requiredSize)
                        {
                            target.breasts[x].SetCupSize(requiredSize);
                        }
                    }

                    target.genitals.AddBreastRow(target.breasts[breastCount - 1].cupSize.ByteEnumSubtract(1));


                    bool doCrit = false, uberCrit = false;
                    if (target.breasts.Count == 2)
                    {
                        target.IncreaseCreatureStats(lus: 5, sens: 6);
                    }
                    else if (hasCrit())
                    {
                        doCrit = true;
                        if (crit > 2)
                        {
                            target.IncreaseCreatureStats(sens: 6, lus: 15);
                            uberCrit = true;
                        }
                        else
                        {
                            target.IncreaseCreatureStats(sens: 3, lus: 10);
                        }
                    }

                    sb.Append(UpdateAndGrowAdditionalRowText(target, oldBreastData, doCrit, uberCrit));


                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
                else
                {
                    BreastCollectionData oldBreastData = target.genitals.allBreasts.AsReadOnlyData();

                    //only call the normalize text if we actually did anything. related, anthro breasts now returns a bool. thanks, fox tfs.
                    if (target.genitals.AnthropomorphizeBreasts())
                    {
                        sb.Append(NormalizedBreastSizeText(target, oldBreastData));
                    }
                }
            }


            //Remove a breast row if over 4. afaik this should never happen.
            if (target.breasts.Count > 4 && Utils.Rand(3) == 0)
            {
                var oldData = target.breasts[target.breasts.Count - 1].AsReadOnlyData();
                target.genitals.RemoveBreastRows(1);

                sb.Append(RemovedExcessRow(target, oldData));
            }
            //Grow breasts if has v****a and has no breasts/nips
            //Shrink breasts if over D-cup
            CupSize targetSize = EnumHelper.Max(target.genitals.smallestPossibleCupSize, CupSize.D);

            if (!hyperHappy && target.genitals.BiggestCupSize() > targetSize && Utils.Rand(3) == 0)
            {
                BreastCollectionData oldCollection = target.genitals.allBreasts.AsReadOnlyData();

                bool changedAnything = false;
                foreach (Breasts row in target.breasts)
                {
                    //If this row is over threshhold
                    if (row.cupSize > targetSize)
                    {
                        //Big change
                        if (row.cupSize > CupSize.EE_BIG)
                        {
                            changedAnything |= row.ShrinkBreasts((byte)(2 + Utils.Rand(3))) > 0;
                        }
                        //Small change
                        else
                        {
                            changedAnything |= row.ShrinkBreasts() > 0;
                        }
                        //Increment changed rows
                    }
                }
                //Count shrinking
                if (changedAnything)
                {
                    sb.Append(ShrunkRowsText(target, oldCollection));

                    remainingChanges--;
                    if (remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
            }
            //MUTATIONZ LEVEL 1: fur, stop hair growth, ears, tail
            //Gain fur
            if (Utils.Rand(5) == 0 && !target.body.IsFurBodyType())
            {
                BodyData oldData = target.body.AsReadOnlyData();
                Species.WOLF.GetRandomFurColors(out FurColor primary, out FurColor underbody);
                if (FurColor.IsNullOrEmpty(underbody))
                {
                    target.UpdateBody(BodyType.UNDERBODY_FUR, primary);
                }
                else
                {
                    target.UpdateBody(BodyType.UNDERBODY_FUR, primary, underbody);
                }

                sb.Append(UpdateBodyText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Ears time
            if (Utils.Rand(3) == 0 && target.ears.type != EarType.WOLF)
            {
                EarData oldData = target.ears.AsReadOnlyData();
                target.UpdateEars(EarType.WOLF);
                sb.Append(UpdateEarsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Wolf tail
            if (Utils.Rand(3) == 0 && target.tail.type != TailType.WOLF)
            {
                TailData oldData = target.tail.AsReadOnlyData();
                target.UpdateTail(TailType.WOLF);
                sb.Append(UpdateTailText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Sets hair normal
            if (target.hair.type != HairType.NORMAL && Utils.Rand(3) == 0)
            {
                HairData oldData = target.hair.AsReadOnlyData();
                target.RestoreHair();
                sb.Append(RestoreHairText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //MUTATIONZ LEVEL 2: fur->arms fur+tail+ears->face stophair->nohair fur+tail->legs
            //gain wolf face
            if (target.face.type != FaceType.WOLF && target.ears.type == EarType.WOLF && target.tail.type == TailType.WOLF && target.body.IsFurBodyType() && Utils.Rand(5) == 0)
            {
                FaceData oldData = target.face.AsReadOnlyData();
                target.UpdateFace(FaceType.WOLF);
                sb.Append(UpdateFaceText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //legz
            if (target.lowerBody.legCount == 2 && target.lowerBody.type != LowerBodyType.WOLF && target.tail.type == TailType.WOLF && target.body.IsFurBodyType() && Utils.Rand(4) == 0)
            {
                //Hooman feets
                //Hooves -> Paws
                LowerBodyData oldData = target.lowerBody.AsReadOnlyData();
                target.UpdateLowerBody(LowerBodyType.WOLF);
                sb.Append(UpdateLowerBodyText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //MUTATIONZ LEVEL 3: face->eyes
            if (target.eyes.type != EyeType.WOLF && target.face.type == FaceType.WOLF && Utils.Rand(4) == 0)
            {
                EyeData oldData = target.eyes.AsReadOnlyData();
                target.UpdateEyes(EyeType.WOLF);
                sb.Append(UpdateEyesText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //MISC CRAP
            //Neck restore
            if (target.neck.type != NeckType.HUMANOID && Utils.Rand(4) == 0)
            {
                NeckData oldData = target.neck.AsReadOnlyData();
                target.RestoreNeck();
                sb.Append(RestoredNeckText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Rear body restore
            if (!target.back.isDefault && Utils.Rand(5) == 0)
            {
                BackData oldData = target.back.AsReadOnlyData();
                target.RestoreBack();
                sb.Append(RestoredBackText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Ovi perk loss
            if (target.womb.canRemoveOviposition && Utils.Rand(5) == 0)
            {
                target.womb.ClearOviposition();
                sb.Append(ClearOvipositionText(target));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            if (Utils.Rand(3) == 0)
            {
                var res = target.build.ChangeMuscleToneToward(100, 4);
                sb.Append(AdjustToneText(target, 4, res));
            }
            if (Utils.Rand(3) == 0)
            {
                var adjustedAmount = target.build.ChangeThicknessToward(75, 3);
                sb.Append(AdjustThicknessText(target, adjustedAmount));
            }



            //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes
            //occurred, then return the contents of the stringbuilder.
            return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
        }
Exemplo n.º 17
0
        protected internal override string DoTransformation(Creature target, out bool isBadEnd)
        {
            isBadEnd = false;

            //by default, this is 2 rolls at 50%, so a 25% chance of 0 additional tfs, 50% chance of 1 additional tf, 25% chance of 2 additional tfs.
            //also takes into consideration any perks that increase or decrease tf effectiveness. if you need to roll out your own, feel free to do so.
            int changeCount  = GenerateChangeCount(target, new int[] { 2, 2, 3 }, isEnhanced ? 3 : 1);
            int totalChanges = 0;

            StringBuilder sb = new StringBuilder();

            //For all of these, any text regarding the transformation should be instead abstracted out as an abstract string function. append the result of this abstract function
            //to the string builder declared above (aka sb.Append(FunctionCall(variables));) string builder is just a fancy way of telling the compiler that you'll be creating a
            //long string, piece by piece, so don't do any crazy optimizations first.

            //the initial text for starting the transformation. feel free to add additional variables to this if needed.
            sb.Append(InitialTransformationText(target));

            //Add any free changes here - these can occur even if the change count is 0. these include things such as change in stats (intelligence, etc)
            //change in height, hips, and/or butt, or other similar stats.

            //this will handle the edge case where the change count starts out as 0.

            //paste this line after any tf is applied, and it will: automatically decrement the remaining changes count. if it becomes 0 or less, apply the total number of changes
            //underwent to the target's change count (if applicable) and then return the StringBuilder content.
            //if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges);

            //STATS
            //Increase player str:
            if (target.strength < 60 && Utils.Rand(3) == 0)
            {
                double delta = target.IncreaseStrength((60 - target.strength) / 10.0);
                sb.Append(StrengthUpText(delta));
            }
            //Increase player tou:
            if (target.toughness < 60 && Utils.Rand(3) == 0)
            {
                double delta = target.IncreaseToughness((60 - target.toughness) / 10.0);
                sb.Append(ToughnessUpText(delta));
            }
            //Decrease player spd if it is over 30:
            if (target.relativeSpeed > 30 && target.speed > 30 && Utils.Rand(3) == 0)
            {
                double decrease = target.DecreaseSpeed((target.speed - 30) / 10.0);
                sb.Append(SpeedDownText(decrease));
            }
            //Increase Corr, up to a max of 50.
            //this is silent, apparently.
            if (!isPurified && target.corruption < 50)
            {
                target.IncreaseCorruptionBy((50 - target.corruption) / 10.0);
            }

            if (totalChanges >= changeCount)
            {
                return(FinalizeTransformation(target, sb, totalChanges));
            }

            //Sex bits - Duderiffic
            if (target.cocks.Count > 0 && Utils.Rand(2) == 0 && !hyperHappy)
            {
                //If the player has at least one dick, decrease the size of each slightly,

                C**k     biggest   = target.genitals.LongestCock();
                CockData preChange = biggest.AsReadOnlyData();

                if (biggest.DecreaseLengthAndCheckIfNeedsRemoval(Utils.Rand(3) + 1))
                {
                    target.genitals.RemoveCock(biggest);
                    if (target.cocks.Count == 0 && !target.hasVagina)
                    {
                        BallsData oldBalls = target.balls.AsReadOnlyData();
                        target.AddVagina(0.25);
                        target.genitals.RemoveAllBalls();

                        sb.Append(MadeFemale(target, preChange, oldBalls));
                    }
                    else
                    {
                        sb.Append(ShrunkOneCock(target, preChange, true));
                    }
                }
                else
                {
                    sb.Append(ShrunkOneCock(target, preChange, false));
                }

                if (++totalChanges >= changeCount)
                {
                    return(FinalizeTransformation(target, sb, totalChanges));
                }
            }
            //Sex bits - girly
            bool boobsGrew = false;
            //Increase player's breast size, if they are FF or bigger
            //do not increase size, but do the other actions:
            CupSize biggestCup = target.genitals.BiggestCupSize();

            if ((biggestCup < CupSize.DD || (!isPurified && biggestCup < CupSize.FF)) && (isEnhanced || Utils.Rand(3) == 0))
            {
                BreastData oldBreasts = target.breasts[0].AsReadOnlyData();
                if (target.breasts[0].GrowBreasts((byte)(1 + Utils.Rand(3))) > 0)
                {
                    boobsGrew = true;
                    sb.Append(GrewFirstBreastRow(target, oldBreasts));
                    if (++totalChanges >= changeCount)
                    {
                        return(FinalizeTransformation(target, sb, totalChanges));
                    }
                }
                target.DeltaCreatureStats(sens: .5);
            }

            //Remove feathery hair
            HairData oldHair = target.hair.AsReadOnlyData();

            if (base.RemoveFeatheryHair(target))
            {
                sb.Append(RemovedFeatheryHairText(target, oldHair));
                if (++totalChanges >= changeCount)
                {
                    return(FinalizeTransformation(target, sb, totalChanges));
                }
            }

            //refresh the biggest cup size because we may have grown some breasts earlier.
            biggestCup = target.genitals.BiggestCupSize();

            //If breasts are D or bigger and are not lactating, they also start lactating:
            if (biggestCup >= CupSize.D && !target.genitals.isLactating && (isEnhanced || boobsGrew || Utils.Rand(3) == 0))
            {
                BreastData preLactation = target.breasts[0].AsReadOnlyData();
                target.genitals.StartLactating();

                sb.Append(StartedLactatingText(target, preLactation));

                if (++totalChanges >= changeCount)
                {
                    return(FinalizeTransformation(target, sb, totalChanges));
                }

                target.DeltaCreatureStats(sens: .5);
            }
            //Quad nipples and other 'special isEnhanced things.
            if (isEnhanced)
            {
                //QUAD DAMAGE!
                if (!target.genitals.hasQuadNipples)
                {
                    BreastCollectionData oldBreasts = target.genitals.allBreasts.AsReadOnlyData();
                    target.genitals.SetQuadNipples(true);

                    sb.Append(GrantQuadNippleText(target, oldBreasts));

                    if (++totalChanges >= changeCount)
                    {
                        return(FinalizeTransformation(target, sb, totalChanges));
                    }
                }
                else if (target.genitals.isLactating)
                {
                    BreastCollectionData oldBreasts = target.genitals.allBreasts.AsReadOnlyData();

                    target.genitals.BoostLactation(2.5);
                    double delta = 0;

                    if (target.genitals.nippleLength < 1 || (target.genitals.nippleLength < 1.5 && !isPurified))
                    {
                        delta = target.genitals.GrowNipples(0.25);
                        target.DeltaCreatureStats(sens: .5);
                    }

                    sb.Append(BoostedLactationText(target, oldBreasts, delta));

                    if (++totalChanges >= changeCount)
                    {
                        return(FinalizeTransformation(target, sb, totalChanges));
                    }
                }
            }
            //If breasts are already lactating and the player is not lactating beyond a reasonable level, they start lactating more:
            else
            {
                if (target.genitals.isLactating && (target.genitals.lactationStatus < LactationStatus.MODERATE ||
                                                    (!isPurified && target.genitals.lactationStatus < LactationStatus.STRONG)) && (isEnhanced || Utils.Rand(3) == 0))
                {
                    BreastCollectionData oldBreasts = target.genitals.allBreasts.AsReadOnlyData();
                    double delta = 0;

                    target.genitals.BoostLactation(0.75);

                    if (target.genitals.nippleLength < 1 || (target.genitals.nippleLength < 1.5 && !isPurified))
                    {
                        delta = target.genitals.GrowNipples(0.25);
                        target.DeltaCreatureStats(sens: .5);
                    }

                    sb.Append(BoostedLactationText(target, oldBreasts, delta));

                    if (++totalChanges >= changeCount)
                    {
                        return(FinalizeTransformation(target, sb, totalChanges));
                    }
                }
                else if (isPurified && target.genitals.lactationStatus >= LactationStatus.STRONG)
                {
                    BreastCollectionData oldData = target.genitals.allBreasts.AsReadOnlyData();

                    target.DeltaCreatureStats(sens: .5);
                    target.genitals.BoostLactation(-1);

                    sb.Append(BoostedLactationText(target, oldData, 0));


                    if (++totalChanges >= changeCount)
                    {
                        return(FinalizeTransformation(target, sb, totalChanges));
                    }
                }
            }
            //If breasts are lactating at a fair level
            //and the player has not received this status,
            //apply an effect where the player really wants
            //to give their milk to other creatures
            //(capable of getting them addicted):
            biggestCup = target.genitals.BiggestCupSize();

            if (!target.HasPerk <Feeder>() && target.genitals.lactationStatus >= LactationStatus.MODERATE && Utils.Rand(2) == 0 && biggestCup >= CupSize.DD &&
                target.IsCorruptEnough(35))
            {
                target.perks.AddPerk <Feeder>();
                sb.Append(GainedFeederPerk(target));
                if (++totalChanges >= changeCount)
                {
                    return(FinalizeTransformation(target, sb, totalChanges));
                }
            }
            //UNFINISHED
            //If player has addictive quality and drinks pure version, removes addictive quality.
            //if the player has a v****a and it is tight, it loosens.
            if (target.hasVagina)
            {
                VaginalLooseness targetLooseness = EnumHelper.Min(VaginalLooseness.LOOSE, target.genitals.maxVaginalLooseness);
                V****a           tightest        = target.genitals.TightestVagina();

                if (tightest.looseness < targetLooseness && Utils.Rand(2) == 0)
                {
                    VaginaData preLoosened = tightest.AsReadOnlyData();


                    tightest.IncreaseLooseness(2);
                    sb.Append(LoosenedTwatText(target, preLoosened));

                    if (++totalChanges >= changeCount)
                    {
                        return(FinalizeTransformation(target, sb, totalChanges));
                    }

                    target.DeltaCreatureStats(lus: 10);
                }
            }
            //Neck restore
            if (target.neck.type != NeckType.HUMANOID && Utils.Rand(4) == 0)
            {
                NeckData oldData = target.neck.AsReadOnlyData();
                target.RestoreNeck();
                sb.Append(RestoredNeckText(target, oldData));

                if (++totalChanges >= changeCount)
                {
                    return(FinalizeTransformation(target, sb, totalChanges));
                }
            }
            //Rear body restore
            if (target.back.type != BackType.SHARK_FIN && Utils.Rand(5) == 0)
            {
                BackData oldData = target.back.AsReadOnlyData();
                target.RestoreBack();
                sb.Append(RestoredBackText(target, oldData));
                if (++totalChanges >= changeCount)
                {
                    return(FinalizeTransformation(target, sb, totalChanges));
                }
            }
            //Ovi perk loss
            if (!isPurified && target.womb.canRemoveOviposition && Utils.Rand(5) == 0)
            {
                target.womb.ClearOviposition();
                sb.Append(ClearOvipositionText(target));

                if (++totalChanges >= changeCount)
                {
                    return(FinalizeTransformation(target, sb, totalChanges));
                }
            }
            //General Appearance (Tail -> Ears -> Paws(fur stripper) -> Face -> Horns
            //Give the player a bovine tail, same as the minotaur
            if (!isPurified && target.tail.type != TailType.COW && Utils.Rand(3) == 0)
            {
                TailData oldData = target.tail.AsReadOnlyData();

                target.UpdateTail(TailType.COW);
                sb.Append(ChangedTailText(target, oldData));

                if (++totalChanges >= changeCount)
                {
                    return(FinalizeTransformation(target, sb, totalChanges));
                }
            }
            //Give the player bovine ears, same as the minotaur
            if (!isPurified && target.ears.type != EarType.COW && Utils.Rand(4) == 0 && target.tail.type == TailType.COW)
            {
                EarData oldEars = target.ears.AsReadOnlyData();
                target.UpdateEars(EarType.COW);

                sb.Append(ChangedEarsText(target, oldEars));

                if (++totalChanges >= changeCount)
                {
                    return(FinalizeTransformation(target, sb, totalChanges));
                }
            }
            //If the player is under 7 feet in height, increase their height, similar to the minotaur
            if (((isEnhanced && target.build.heightInInches < 96) || target.build.heightInInches < 84) && Utils.Rand(2) == 0)
            {
                int temp = Utils.Rand(5) + 3;
                //Slow rate of growth near ceiling
                if (target.build.heightInInches > 74)
                {
                    temp = (int)Math.Floor(temp / 2.0);
                }
                //Never 0
                if (temp == 0)
                {
                    temp = 1;
                }


                byte delta = target.build.IncreaseHeight((byte)temp);

                sb.Append(GrowTaller(target, delta));

                if (++totalChanges >= changeCount)
                {
                    return(FinalizeTransformation(target, sb, totalChanges));
                }
            }
            //Give the player hoofs, if the player already has hoofs STRIP FUR
            if (!isPurified && target.lowerBody.type != LowerBodyType.HOOVED && target.ears.type == EarType.COW)
            {
                if (Utils.Rand(3) == 0)
                {
                    var oldData = target.lowerBody.AsReadOnlyData();
                    target.UpdateLowerBody(LowerBodyType.HOOVED);

                    sb.Append(ChangedLowerBodyText(target, oldData));

                    if (++totalChanges >= changeCount)
                    {
                        return(FinalizeTransformation(target, sb, totalChanges));
                    }
                }
            }
            //If the player's face is non-human, they gain a human face
            if (!isEnhanced && target.lowerBody.type == LowerBodyType.HOOVED && target.face.type != FaceType.HUMAN && Utils.Rand(4) == 0)
            {
                //Remove face before fur!
                var oldData = target.face.AsReadOnlyData();
                target.RestoreFace();
                sb.Append(RestoredFaceText(target, oldData));

                if (++totalChanges >= changeCount)
                {
                    return(FinalizeTransformation(target, sb, totalChanges));
                }
            }
            //isEnhanced get shitty fur
            var targetFur = new FurColor(HairFurColors.BLACK, HairFurColors.WHITE, FurMulticolorPattern.SPOTTED);

            if (isEnhanced && (!target.body.IsFurBodyType() || !target.body.mainEpidermis.fur.Equals(targetFur)))
            {
                var oldData = target.body.AsReadOnlyData();

                if (target.body.type == BodyType.SIMPLE_FUR)
                {
                    target.body.ChangeMainFur(targetFur);
                }
                else
                {
                    target.UpdateBody(BodyType.SIMPLE_FUR, targetFur);
                }

                if (!oldData.IsFurBodyType())
                {
                    sb.Append(ChangedBodyText(target, oldData));
                }
                else
                {
                    sb.Append(ChandedFurToSpots(target, oldData));
                }

                if (++totalChanges >= changeCount)
                {
                    return(FinalizeTransformation(target, sb, totalChanges));
                }
            }
            //if isEnhanced to probova give a shitty cow face
            else if (isEnhanced && target.face.type != FaceType.COW_MINOTAUR)
            {
                var oldData = target.face.AsReadOnlyData();
                target.UpdateFace(FaceType.COW_MINOTAUR);
                sb.Append(ChangedFaceText(target, oldData));

                if (++totalChanges >= changeCount)
                {
                    return(FinalizeTransformation(target, sb, totalChanges));
                }
            }
            //Give the player bovine horns, or increase their size, same as the minotaur
            //New horns or expanding mino horns
            if (!isPurified && Utils.Rand(3) == 0)
            {
                var oldHorns = target.horns.AsReadOnlyData();
                if (target.horns.type != HornType.BOVINE)
                {
                    target.UpdateHorns(HornType.BOVINE);
                    sb.Append(ChangedHornsText(target, oldHorns));

                    if (++totalChanges >= changeCount)
                    {
                        return(FinalizeTransformation(target, sb, totalChanges));
                    }
                }
                else if (target.horns.type == HornType.BOVINE && target.horns.CanStrengthen && target.horns.significantHornSize < 5)
                {
                    target.horns.StrengthenTransform();
                    sb.Append(MadeHornsBigger(target, oldHorns));

                    if (++totalChanges >= changeCount)
                    {
                        return(FinalizeTransformation(target, sb, totalChanges));
                    }
                }
            }

            //Increase the size of the player's hips, if they are not already childbearing or larger
            if (Utils.Rand(2) == 0 && target.hips.size < 15)
            {
                if (isPurified && target.hips.size < 8 || !isPurified)
                {
                    var oldHips = target.hips.AsReadOnlyData();

                    if (target.build.GrowHips((byte)(1 + Utils.Rand(4))) > 0)
                    {
                        sb.Append(WidenedHipsText(target, oldHips));
                        if (++totalChanges >= changeCount)
                        {
                            return(FinalizeTransformation(target, sb, totalChanges));
                        }
                    }
                }
            }
            // Remove gills
            if (Utils.Rand(4) == 0 && target.gills.type != GillType.NONE)
            {
                var oldData = target.gills.AsReadOnlyData();
                target.RestoreGills();

                sb.Append(RestoredGillsText(target, oldData));

                if (++totalChanges >= changeCount)
                {
                    return(FinalizeTransformation(target, sb, totalChanges));
                }
            }

            //Increase the size of the player's ass (less likely then hips), if it is not already somewhat big
            if (Utils.Rand(2) == 0 && target.butt.size < 8 || (!isPurified && target.butt.size < 13))
            {
                var oldButt = target.butt.AsReadOnlyData();
                if (target.butt.GrowButt((byte)(1 + Utils.Rand(2))) > 0)
                {
                    sb.Append(GrewButtText(target, oldButt));
                    if (++totalChanges >= changeCount)
                    {
                        return(FinalizeTransformation(target, sb, totalChanges));
                    }
                }
            }
            //Nipples Turn Back:
            if (target.genitals.hasBlackNipples && Utils.Rand(3) == 0)
            {
                target.genitals.SetBlackNipples(false);
                sb.Append(RemovedBlackNippleText(target));

                if (++totalChanges >= changeCount)
                {
                    return(FinalizeTransformation(target, sb, totalChanges));
                }
            }
            //Debugcunt
            if (target.hasVagina && target.vaginas.Any(x => x.type != VaginaType.defaultValue) && Utils.Rand(3) == 0)
            {
                var oldCollection = target.genitals.allVaginas.AsReadOnlyData();
                target.vaginas.ForEach(x => target.genitals.RestoreVagina(x));
                sb.Append(RestoreAllVaginasText(target, oldCollection));

                if (++totalChanges >= changeCount)
                {
                    return(FinalizeTransformation(target, sb, totalChanges));
                }
            }


            //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes
            //occurred, then return the contents of the stringbuilder.
            return(FinalizeTransformation(target, sb, changeCount - totalChanges));
        }
Exemplo n.º 18
0
        protected internal override string DoTransformation(Creature target, out bool isBadEnd)
        {
            isBadEnd = false;

            int changeCount      = GenerateChangeCount(target, new int[] { 2, 2, 3, 4 });
            int remainingChanges = changeCount;

            StringBuilder sb = new StringBuilder();

#warning fix me
            int ngPlus(int value) => value;

            int currentChanges() => changeCount - remainingChanges;

            //For all of these, any text regarding the transformation should be instead abstracted out as an abstract string function. append the result of this abstract function
            //to the string builder declared above (aka sb.Append(FunctionCall(variables));) string builder is just a fancy way of telling the compiler that you'll be creating a
            //long string, piece by piece, so don't do any crazy optimizations first.

            //the initial text for starting the transformation. feel free to add additional variables to this if needed.
            sb.Append(InitialTransformationText(target));

            //Add any free changes here - these can occur even if the change count is 0. these include things such as change in stats (intelligence, etc)
            //change in height, hips, and/or butt, or other similar stats.

            //this will handle the edge case where the change count starts out as 0.
            if (remainingChanges <= 0)
            {
                return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
            }

            //Any transformation related changes go here. these typically cost 1 change. these can be anything from body parts to gender (which technically also changes body parts,
            //but w/e). You are required to make sure you return as soon as you've applied changeCount changes, but a single line of code can be applied at the end of a change to do
            //this for you.

            //paste this line after any tf is applied, and it will: automatically decrement the remaining changes count. if it becomes 0 or less, apply the total number of changes
            //underwent to the target's change count (if applicable) and then return the StringBuilder content.
            //if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges);

            //clear screen

            //Statistical changes:
            //-Reduces speed down to 50.
            if (target.speed > ngPlus(50) && Utils.Rand(4) == 0)
            {
                target.ChangeSpeed(-1);
            }
            //-Raises toughness to 70
            //(+3 to 40, +2 to 55, +1 to 70)
            if (target.toughness < ngPlus(70) && Utils.Rand(3) == 0)
            {
                //(+3)
                if (target.toughness < ngPlus(40))
                {
                    target.ChangeToughness(3);
                }
                //(+2)
                else if (target.toughness < ngPlus(55))
                {
                    target.ChangeToughness(2);
                }
                //(+1)
                else
                {
                    target.ChangeToughness(1);
                }
            }
            //-Reduces sensitivity.
            if (target.relativeSensitivity > 20 && Utils.Rand(3) == 0)
            {
                target.ChangeSensitivity(-1);
            }
            //Raises libido greatly to 50, then somewhat to 75, then slowly to 100.
            if (target.relativeLibido < 100 && Utils.Rand(3) == 0)
            {
                //+3 lib if less than 50
                if (target.relativeLibido < 50)
                {
                    target.ChangeLibido(1);
                }
                //+2 lib if less than 75
                if (target.relativeLibido < 75)
                {
                    target.ChangeLibido(1);
                }
                //+1 if above 75.
                target.ChangeLibido(1);
            }


            //Sexual Changes:
            //-Lizard dick - first one
            if (target.cocks.Any(x => x.type != CockType.LIZARD) && target.cocks.Count > 0 && ScalingChance(2, currentChanges(), 4))
            {
                //Find the first non-lizzy dick
                C**k firstNonLizard = target.cocks.First(x => x.type != CockType.LIZARD);
                //Actually xform it nau
                target.genitals.UpdateCock(firstNonLizard, CockType.LIZARD);

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }

                target.DeltaCreatureStats(lib: 3, lus: 10);
            }
            //(CHANGE OTHER DICK)
            int lizardCocks = target.genitals.CountCocksOfType(CockType.LIZARD);
            //Requires 1 lizard c**k, multiple cocks
            if (target.hasCock && (lizardCocks != target.cocks.Count || target.cocks.Count == 1) && ScalingChance(2, currentChanges(), 4))
            {
                if (target.cocks.Count > 1)
                {
                    C**k nonLizard = target.cocks.First(x => x.type != CockType.LIZARD);

                    target.genitals.UpdateCock(nonLizard, CockType.LIZARD);

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }

                    target.DeltaCreatureStats(lib: 3, lus: 10);
                }
                else
                {
                    target.genitals.AddCock(CockType.LIZARD, target.cocks[0].length, target.cocks[0].girth);

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }

                    target.DeltaCreatureStats(lib: 3, lus: 10);
                }
            }

            //MOD NOTE: REMOVED. SEE RANT IN SALAMANDER TRANSFORMATIONS

            //--Worms leave if 100% lizard dicks?
            //Require mammals?
            //if (target.genitals.CountCocksOfType(CockType.LIZARD) == target.cocks.Count && target.hasStatusEffect(StatusEffects.Infested))
            //{
            //	target.removeStatusEffect(StatusEffects.Infested);
            //	if (--remainingChanges <= 0)
            //	{
            //		return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges);
            //	}
            //}

            //-Breasts vanish to 0 rating if male
            if (target.genitals.BiggestCupSize() > target.genitals.smallestPossibleMaleCupSize && target.gender == Gender.MALE && ScalingChance(2, currentChanges(), 3))
            {
                //(HUEG)
                foreach (Breasts breast in target.breasts)
                {
                    if (breast.cupSize > CupSize.E_BIG)
                    {
                        breast.ShrinkBreasts(((byte)breast.cupSize).div(2));
                    }
                    else
                    {
                        breast.SetCupSize(target.genitals.smallestPossibleMaleCupSize);
                    }
                }
                //(+2 speed)
                target.IncreaseSpeed(2);
                target.ChangeLibido(2);
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Lactation stoppage.
            if (target.genitals.isLactating && ScalingChance(2, currentChanges(), 4))
            {
                if (target.HasPerk <Feeder>())
                {
                    target.RemovePerk <Feeder>();
                }
                target.genitals.SetLactationTo(LactationStatus.NOT_LACTATING);

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Nipples reduction to 1 per tit.
            if (target.genitals.hasQuadNipples && ScalingChance(2, currentChanges(), 4))
            {
                target.genitals.SetQuadNipples(false);

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Remove extra breast rows
            if (target.breasts.Count > 1 && ScalingChance(2, currentChanges(), 3) && !hyperHappy)
            {
                target.RemoveExtraBreastRows();

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-VAGs
            if (target.hasVagina && target.womb.canObtainOviposition && Species.LIZARD.Score(target) > 3 && ScalingChance(3, currentChanges(), 5))
            {
                target.womb.GrantOviposition();
                sb.Append(GrantOvipositionText(target));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //Physical changes:
            //-Existing horns become draconic, max of 4, max length of 1'
            if (target.horns.type != HornType.DRACONIC && ScalingChance(3, currentChanges(), 5))
            {
                HornData oldData = target.horns.AsReadOnlyData();
                target.UpdateHorns(HornType.DRACONIC);
                sb.Append(UpdateHornsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //Neck restore
            if (target.neck.type != NeckType.HUMANOID && ScalingChance(2, currentChanges(), 4))
            {
                NeckData oldData = target.neck.AsReadOnlyData();
                target.RestoreNeck();
                sb.Append(RestoredNeckText(target, oldData));
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Rear body restore
            if (!target.back.isDefault && ScalingChance(3, currentChanges(), 5))
            {
                BackData oldData = target.back.AsReadOnlyData();
                target.RestoreBack();
                sb.Append(RestoredBackText(target, oldData));
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Hair changes
            if (ScalingChance(2, currentChanges(), 4))
            {
                if (target.eyes.type == EyeType.BASILISK)
                {
                    if (target.corruption > 65 && target.face.IsReptilian() && target.body.type == BodyType.REPTILE && target.hair.type != HairType.BASILISK_SPINES)
                    {
                        HairData oldData = target.hair.AsReadOnlyData();
                        target.UpdateHair(HairType.BASILISK_SPINES);
                        sb.Append(UpdateHairText(target, oldData));

                        if (--remainingChanges <= 0)
                        {
                            return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                        }
                    }
                    else if (target.corruption < 15 && target.gender.HasFlag(Gender.FEMALE) && target.hair.type != HairType.BASILISK_PLUME)
                    {
                        target.hair.ResumeNaturalGrowth();
                        HairData oldData = target.hair.AsReadOnlyData();
                        target.UpdateHair(HairType.BASILISK_PLUME);
                        sb.Append(UpdateHairText(target, oldData));

                        if (--remainingChanges <= 0)
                        {
                            return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                        }
                    }
                }
                else
                {
                    target.hair.StopNaturalGrowth();

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
            }
            //Remove beard!
#warning BEARDS NOT YET IMPLEMENTED
            //Mod note: Nords are so serious about beards. ... Mai'q thinks they wish they had GLORIOUS pubes like Khajiit.

            //if (target.hasBeard() && ScalingChance(2, currentChanges(), 3))
            //{
            //	target.beard.length = 0;
            //	target.beard.style = 0;
            //}
            //Big physical changes:
            //-Legs – Draconic, clawed feet
            if (target.lowerBody.type != LowerBodyType.LIZARD && ScalingChance(3, currentChanges(), 5))
            {
                //Hooves -
                //TAURS -
                //feet types -
                //Else –
                LowerBodyData oldData = target.lowerBody.AsReadOnlyData();
                target.UpdateLowerBody(LowerBodyType.LIZARD);
                sb.Append(UpdateLowerBodyText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            // <mod name="Predator arms" author="Stadler76">
            //Gain predator arms
            //Claw transition
            //MOD OF MOD (LOL): predator arms are a collection of arm types now, not a single type. thus, we can combine the claw and type checks.
            //now, you get the arms (and thus, the claws) if they aren't a predator type and have lizard legs, or switch to lizard arms from any other predator type.
            if ((target.arms.IsPredatorArms() || target.lowerBody.type == LowerBodyType.LIZARD) && target.body.type == BodyType.REPTILE && ScalingChance(2, currentChanges(), 3))
            {
                ArmData oldData = target.arms.AsReadOnlyData();
                target.UpdateArms(ArmType.LIZARD);
                sb.Append(UpdateArmsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            // </mod>

            //-Tail – sinuous lizard tail
            if (target.tail.type != TailType.LIZARD && target.lowerBody.type == LowerBodyType.LIZARD && ScalingChance(3, currentChanges(), 5))
            {
                //No tail
                //Yes tail
                TailData oldData = target.tail.AsReadOnlyData();
                target.UpdateTail(TailType.LIZARD);
                sb.Append(UpdateTailText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Remove odd eyes
            if (ScalingChance(3, currentChanges(), 5) && target.eyes.type != EyeType.HUMAN && !target.eyes.isReptilian)
            {
                EyeData oldData = target.eyes.AsReadOnlyData();
                target.RestoreEyes();
                sb.Append(RestoredEyesText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Ears become smaller nub-like openings?
            if (target.ears.type != EarType.LIZARD && target.tail.type == TailType.LIZARD && target.lowerBody.type == LowerBodyType.LIZARD && ScalingChance(3, currentChanges(), 5))
            {
                EarData oldData = target.ears.AsReadOnlyData();
                target.UpdateEars(EarType.LIZARD);
                sb.Append(UpdateEarsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Scales – color changes to red, green, white, blue, or black. Rarely: purple or silver.
            if (target.body.type != BodyType.REPTILE && target.ears.type == EarType.LIZARD && target.tail.type == TailType.LIZARD && target.lowerBody.type == LowerBodyType.LIZARD &&
                ScalingChance(3, currentChanges(), 5))
            {
                Species.LIZARD.GetRandomSkinTone(out Tones primary, out Tones underbody);

                target.UpdateBody(BodyType.REPTILE, primary, underbody);

                //kGAMECLASS.rathazul.addMixologyXP(20);
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Lizard-like face.
            if (target.face.type != FaceType.LIZARD && target.body.type == BodyType.REPTILE && target.ears.type == EarType.LIZARD && target.tail.type == TailType.LIZARD &&
                target.lowerBody.type == LowerBodyType.LIZARD && ScalingChance(3, currentChanges(), 5))
            {
                FaceData oldData = target.face.AsReadOnlyData();
                target.UpdateFace(FaceType.LIZARD);
                sb.Append(UpdateFaceText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Lizard tongue
            if (target.tongue.type == TongueType.SNAKE && Utils.Rand(10) < 6)
            {
                // Higher (60%) chance to be 'fixed' if old variant
                TongueData oldData = target.tongue.AsReadOnlyData();
                target.UpdateTongue(TongueType.LIZARD);
                sb.Append(UpdateTongueText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            if (target.tongue.type != TongueType.LIZARD && target.tongue.type != TongueType.SNAKE && target.face.IsReptilian() && ScalingChance(2, currentChanges(), 3))
            {
                TongueData oldData = target.tongue.AsReadOnlyData();
                target.UpdateTongue(TongueType.LIZARD);
                sb.Append(UpdateTongueText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Remove Gills
            if (ScalingChance(2, currentChanges(), 4) && !target.gills.isDefault)
            {
                GillData oldData = target.gills.AsReadOnlyData();
                target.RestoreGills();
                sb.Append(RestoredGillsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //<mod name="Reptile eyes" author="Stadler76">
            //-Lizard eyes
            if (target.eyes.type != EyeType.LIZARD && target.face.type == FaceType.LIZARD && target.body.type == BodyType.REPTILE && target.ears.type == EarType.LIZARD &&
                ScalingChance(2, currentChanges(), 4))
            {
                EyeData oldData = target.eyes.AsReadOnlyData();
                target.UpdateEyes(EyeType.LIZARD);
                sb.Append(UpdateEyesText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //</mod>
            //FAILSAFE CHANGE
            if (remainingChanges == changeCount)
            {
                (target as CombatCreature)?.AddHP(50);
                target.ChangeLust(3);
            }


            //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes
            //occurred, then return the contents of the stringbuilder.
            return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
        }
Exemplo n.º 19
0
            protected override string RestoredBackAndWings(Creature target, WingData oldWings, BackData oldBack)
            {
                string missing;

                if (oldBack.type == BackType.SHARK_FIN && !oldWings.isDefault)
                {
                    missing = "shark-like fin and wings are both";
                }
                else if (oldBack.type == BackType.SHARK_FIN)
                {
                    missing = "shark-like fin is";
                }
                else
                {
                    missing = "wings are";
                }

                return(GlobalStrings.NewParagraph() + "A wave of tightness spreads through your back, and it feels as if someone is stabbing a dagger into your spine."
                       + " After a moment the pain passes, though your " + missing + " gone!");
            }
        protected internal override string DoTransformation(Creature target, out bool isBadEnd)
        {
            isBadEnd = false;

            //by default, this is 2 rolls at 50%, so a 25% chance of 0 additional tfs, 50% chance of 1 additional tf, 25% chance of 2 additional tfs.
            //also takes into consideration any perks that increase or decrease tf effectiveness. if you need to roll out your own, feel free to do so.
            int changeCount      = GenerateChangeCount(target, new int[] { 2, 3, 4 });
            int remainingChanges = changeCount;

            StringBuilder sb = new StringBuilder();

            //For all of these, any text regarding the transformation should be instead abstracted out as an abstract string function. append the result of this abstract function
            //to the string builder declared above (aka sb.Append(FunctionCall(variables));) string builder is just a fancy way of telling the compiler that you'll be creating a
            //long string, piece by piece, so don't do any crazy optimizations first.

            //the initial text for starting the transformation. feel free to add additional variables to this if needed.
            sb.Append(InitialTransformationText(target));

            //Add any free changes here - these can occur even if the change count is 0. these include things such as change in stats (intelligence, etc)
            //change in height, hips, and/or butt, or other similar stats.

            //this will handle the edge case where the change count starts out as 0.
            if (remainingChanges <= 0)
            {
                return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
            }

            //Any transformation related changes go here. these typically cost 1 change. these can be anything from body parts to gender (which technically also changes body parts,
            //but w/e). You are required to make sure you return as soon as you've applied changeCount changes, but a single line of code can be applied at the end of a change to do
            //this for you.

            //paste this line after any tf is applied, and it will: automatically decrement the remaining changes count. if it becomes 0 or less, apply the total number of changes
            //underwent to the target's change count (if applicable) and then return the StringBuilder content.
            //if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges);


            //clear screen
            //Statistical changes:
            //-Reduces speed down to 70.
            if (target.relativeSpeed > 70 && Utils.Rand(4) == 0)
            {
                target.ChangeSpeed(-1);
            }
            //-Reduces intelligence down to 60.
            if (target.relativeIntelligence > 60 && Utils.Rand(4) == 0)
            {
                target.ChangeIntelligence(-1);
            }

            //-Raises toughness up to 90.
            //(+3 to 50, +2 to 70, +1 to 90)
            if (target.relativeToughness < 90 && Utils.Rand(3) == 0)
            {
                //(+3)
                if (target.relativeToughness < 50)
                {
                    target.ChangeToughness(3);
                }
                //(+2)
                else if (target.relativeToughness < 70)
                {
                    target.ChangeToughness(2);
                }
                //(+1)
                else
                {
                    target.ChangeToughness(1);
                }
            }
            //-Raises strength to 80.
            if (target.relativeStrength < 80 && Utils.Rand(3) == 0)
            {
                target.ChangeStrength(1);
            }
            //-Raises libido up to 90.
            if (target.relativeLibido < 90 && Utils.Rand(3) == 0)
            {
                target.ChangeLibido(2);
            }
            //Sexual Changes:
            //MOD: lizard dicks get a common rng roll now. The only difference is the text.
            if (target.hasCock && !target.genitals.OnlyHasCocksOfType(CockType.LIZARD) && Utils.Rand(4) == 0)
            {
                C**k nonLizard = target.cocks.First(x => x.type != CockType.LIZARD);
                //Actually xform it nau
                target.genitals.UpdateCock(nonLizard, CockType.LIZARD);
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }

                target.DeltaCreatureStats(lib: 3, lus: 10);
            }

            //-Breasts vanish to 0 rating if male
            if (target.genitals.BiggestCupSize() >= target.genitals.smallestPossibleMaleCupSize && target.gender == Gender.MALE && Utils.Rand(3) == 0)
            {
                //(HUEG)
                //Loop through behind the scenes and adjust all t**s.
                foreach (Breasts breastRow in target.breasts)
                {
                    if (breastRow.cupSize > CupSize.E_BIG)
                    {
                        breastRow.ShrinkBreasts(((byte)breastRow.cupSize).div(2));
                    }
                    else
                    {
                        breastRow.SetCupSize(target.genitals.smallestPossibleMaleCupSize);
                    }
                }
                //(+2 speed)
                //target.IncreaseSpeed(2);
                target.ChangeLibido(2);
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Nipples reduction to 1 per tit.
            if (target.genitals.hasQuadNipples && Utils.Rand(4) == 0)
            {
                target.genitals.SetQuadNipples(false);

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            Breasts smallestTits = target.genitals.SmallestBreast();

            //Increase target's breast size, if they are big DD or smaller
            if (smallestTits.cupSize <= CupSize.DD_BIG && target.gender == Gender.FEMALE && Utils.Rand(4) == 0)
            {
                smallestTits.GrowBreasts();
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Remove extra breast rows
            if (target.breasts.Count > 1 && Utils.Rand(3) == 0 && !hyperHappy)
            {
                target.RemoveExtraBreastRows();

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Neck restore
            if (target.neck.type != NeckType.HUMANOID && Utils.Rand(4) == 0)
            {
                NeckData oldData = target.neck.AsReadOnlyData();
                target.RestoreNeck();
                sb.Append(RestoredNeckText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Rear body restore
            if (!target.back.isDefault && Utils.Rand(5) == 0)
            {
                BackData oldData = target.back.AsReadOnlyData();
                target.RestoreBack();
                sb.Append(RestoredBackText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Ovi perk loss
            if (target.womb.canRemoveOviposition && Utils.Rand(5) == 0)
            {
                target.womb.ClearOviposition();
                sb.Append(ClearOvipositionText(target));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Physical changes:
            //Tail - 1st gain reptilian tail, 2nd unlocks enhanced with fire tail whip attack
            if (target.tail.type != TailType.LIZARD && target.tail.type != TailType.SALAMANDER && Utils.Rand(3) == 0)
            {
                TailData oldData = target.tail.AsReadOnlyData();
                target.UpdateTail(TailType.LIZARD);
                sb.Append(UpdateTailText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            if (target.tail.type == TailType.LIZARD && Utils.Rand(3) == 0)
            {
                TailData oldData = target.tail.AsReadOnlyData();
                target.UpdateTail(TailType.SALAMANDER);
                sb.Append(UpdateTailText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Legs
            if (target.lowerBody.type != LowerBodyType.SALAMANDER && target.tail.type == TailType.SALAMANDER && Utils.Rand(3) == 0)
            {
                LowerBodyData oldData = target.lowerBody.AsReadOnlyData();
                target.UpdateLowerBody(LowerBodyType.SALAMANDER);
                sb.Append(UpdateLowerBodyText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Arms
            if (target.arms.type != ArmType.SALAMANDER && target.lowerBody.type == LowerBodyType.SALAMANDER && Utils.Rand(3) == 0)
            {
                ArmData oldData = target.arms.AsReadOnlyData();
                target.UpdateArms(ArmType.SALAMANDER);
                sb.Append(UpdateArmsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Remove odd eyes
            if (Utils.Rand(4) == 0 && !target.eyes.isDefault)
            {
                EyeData oldData = target.eyes.AsReadOnlyData();
                target.RestoreEyes();
                sb.Append(RestoredEyesText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Human face
            if (target.face.type != FaceType.HUMAN && Utils.Rand(4) == 0)
            {
                FaceData oldData = target.face.AsReadOnlyData();
                target.UpdateFace(FaceType.HUMAN);
                sb.Append(UpdateFaceText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Human ears
            if (target.face.type == FaceType.HUMAN && target.ears.type != EarType.HUMAN && Utils.Rand(4) == 0)
            {
                EarData oldData = target.ears.AsReadOnlyData();
                target.UpdateEars(EarType.HUMAN);
                sb.Append(UpdateEarsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Skin color change
            if (!Species.SALAMANDER.availableTones.Contains(target.body.primarySkin.tone) && Utils.Rand(4) == 0)
            {
                target.body.ChangeMainSkin(Utils.RandomChoice(Species.SALAMANDER.availableTones));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Change skin to normal
            if (target.body.type != BodyType.HUMANOID && target.ears.type == EarType.HUMAN && Utils.Rand(3) == 0)
            {
                BodyData oldData = target.body.AsReadOnlyData();
                target.RestoreBody();
                sb.Append(RestoredBodyText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Removing gills
            if (Utils.Rand(4) == 0 && !target.gills.isDefault)
            {
                GillData oldData = target.gills.AsReadOnlyData();
                target.RestoreGills();
                sb.Append(RestoredGillsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //FAILSAFE CHANGE
            if (remainingChanges == changeCount)
            {
                (target as CombatCreature)?.AddHP(100);
                target.ChangeLust(5);
            }

            //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes
            //occurred, then return the contents of the stringbuilder.
            return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
        }
Exemplo n.º 21
0
        protected internal override string DoTransformation(Creature target, out bool isBadEnd)
        {
            isBadEnd = false;

            //by default, this is 2 rolls at 50%, so a 25% chance of 0 additional tfs, 50% chance of 1 additional tf, 25% chance of 2 additional tfs.
            //also takes into consideration any perks that increase or decrease tf effectiveness. if you need to roll out your own, feel free to do so.
            int changeCount      = GenerateChangeCount(target, new int[] { 2, 2 }, isEnhanced ? 2 : 1);
            int remainingChanges = changeCount;

            StringBuilder sb = new StringBuilder();

            //For all of these, any text regarding the transformation should be instead abstracted out as an abstract string function. append the result of this abstract function
            //to the string builder declared above (aka sb.Append(FunctionCall(variables));) string builder is just a fancy way of telling the compiler that you'll be creating a
            //long string, piece by piece, so don't do any crazy optimizations first.

            //the initial text for starting the transformation. feel free to add additional variables to this if needed.
            sb.Append(InitialTransformationText(target));

            //Add any free changes here - these can occur even if the change count is 0. these include things such as change in stats (intelligence, etc)
            //change in height, hips, and/or butt, or other similar stats.

            //this will handle the edge case where the change count starts out as 0.
            if (remainingChanges <= 0)
            {
                return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
            }

            //Any transformation related changes go here. these typically cost 1 change. these can be anything from body parts to gender (which technically also changes body parts,
            //but w/e). You are required to make sure you return as soon as you've applied changeCount changes, but a single line of code can be applied at the end of a change to do
            //this for you.

            //paste this line after any tf is applied, and it will: automatically decrement the remaining changes count. if it becomes 0 or less, apply the total number of changes
            //underwent to the target's change count (if applicable) and then return the StringBuilder content.
            //if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges);

            //-----------------------
            // SIZE MODIFICATIONS
            //-----------------------
            //Increase thickness
            if (Utils.Rand(3) == 0 && target.build.thickness < 75)
            {
                target.build.ChangeThicknessToward(75, 3);

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Decrease muscle tone
            if (Utils.Rand(3) == 0 && target.gender.HasFlag(Gender.FEMALE) && target.build.muscleTone > 20)
            {
                target.build.ChangeMuscleToneToward(20, 4);

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Increase hip rating
            if (Utils.Rand(3) == 0 && target.gender.HasFlag(Gender.FEMALE) && target.hips.size < 15)
            {
                target.hips.GrowHips();
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Increase ass rating
            if (Utils.Rand(3) == 0 && target.butt.size < 12)
            {
                target.butt.GrowButt();
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Increase ball size if you have balls.
            if (Utils.Rand(3) == 0 && target.balls.count > 0 && target.balls.size < 4)
            {
                target.balls.EnlargeBalls(1);
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Neck restore
            if (target.neck.type != NeckType.HUMANOID && Utils.Rand(4) == 0)
            {
                NeckData oldData = target.neck.AsReadOnlyData();
                target.RestoreNeck();
                sb.Append(RestoredNeckText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Rear body restore
            if (!target.back.isDefault && Utils.Rand(5) == 0)
            {
                BackData oldData = target.back.AsReadOnlyData();
                target.RestoreBack();
                sb.Append(RestoredBackText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Ovi perk loss
            if (target.womb.canRemoveOviposition && Utils.Rand(5) == 0)
            {
                target.womb.ClearOviposition();
                sb.Append(ClearOvipositionText(target));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-----------------------
            // TRANSFORMATIONS
            //-----------------------
            //Gain pig c**k, independent of other pig TFs.
            if (Utils.Rand(4) == 0 && target.hasCock && !target.genitals.OnlyHasCocksOfType(CockType.PIG))
            {
                if (target.cocks.Count == 1)
                {                 //Single c**k
                    target.genitals.UpdateCock(0, CockType.PIG);
                }
                else
                {                 //Multiple cocks
                    target.genitals.UpdateCock(target.cocks.First(x => x.type != CockType.PIG), CockType.PIG);
                }
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Gain pig ears!
            if (Utils.Rand(isEnhanced ? 3 : 4) == 0 && target.ears.type != EarType.PIG)
            {
                EarData oldData = target.ears.AsReadOnlyData();
                target.UpdateEars(EarType.PIG);
                sb.Append(UpdateEarsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Gain pig tail if you already have pig ears!
            if (Utils.Rand(isEnhanced ? 2 : 3) == 0 && target.ears.type == EarType.PIG && target.tail.type != TailType.PIG)
            {
                if (!target.tail.isDefault)                 //If you have non-pig tail.
                {
                }
                else                 //If you don't have a tail.
                {
                    target.UpdateTail(TailType.PIG);
                }

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Gain pig tail even when centaur, needs pig ears.
            if (Utils.Rand(isEnhanced ? 2 : 3) == 0 && target.ears.type == EarType.PIG && target.tail.type != TailType.PIG && target.lowerBody.isQuadruped && (target.lowerBody.type == LowerBodyType.HOOVED || target.lowerBody.type == LowerBodyType.PONY))
            {
                TailData oldData = target.tail.AsReadOnlyData();
                target.UpdateTail(TailType.PIG);
                sb.Append(UpdateTailText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Turn your lower body into pig legs if you have pig ears and tail.
            if (Utils.Rand(isEnhanced ? 3 : 4) == 0 && target.ears.type == EarType.PIG && target.tail.type == TailType.PIG && target.lowerBody.type != LowerBodyType.CLOVEN_HOOVED)
            {
                if (target.lowerBody.isQuadruped)                 //Centaur
                {
                }
                else if (target.lowerBody.type == LowerBodyType.NAGA)                 //Naga
                {
                }
                else                 //Bipedal
                {
                    target.UpdateLowerBody(LowerBodyType.CLOVEN_HOOVED);
                }

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Gain pig face when you have the first three pig TFs.
            if (Utils.Rand(isEnhanced ? 2 : 3) == 0 && target.ears.type == EarType.PIG && target.tail.type == TailType.PIG && target.lowerBody.type == LowerBodyType.CLOVEN_HOOVED && target.face.type != FaceType.PIG)
            {
                FaceData oldData = target.face.AsReadOnlyData();
                target.UpdateFace(FaceType.PIG);
                sb.Append(UpdateFaceText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Gain enhanced face if you have pig face.
            if (Utils.Rand(3) == 0 && target.ears.type == EarType.PIG && target.tail.type == TailType.PIG && target.lowerBody.type == LowerBodyType.CLOVEN_HOOVED && target.face.type == FaceType.PIG &&
                !target.face.isFullMorph)
            {
                target.face.StrengthenFacialMorph();

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Change skin colour
            if (Utils.Rand(isEnhanced ? 3 : 4) == 0)
            {
                //String skinToBeChosen = Utils.RandomChoice(enhanced?["dark brown", "brown", "brown"] : ["pink", "tan", "sable"]);
                //target.body.primarySkin.tone = skinToBeChosen;
                //target.arms.updateClaws(target.arms.claws.type);
                //getGame().rathazul.addMixologyXP(20);
                //if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges);
            }
            if (remainingChanges == changeCount)
            {
            }


            //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes
            //occurred, then return the contents of the stringbuilder.
            return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
        }
Exemplo n.º 22
0
        /// <summary>
        /// 提交验证码
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnOK_Click(object sender, RoutedEventArgs e)
        {
            string[] retArr           = null;
            string[] TemplateCodeList = StringHelper.GetConfigValByKey(Constant.PasscodeRange, false).Replace('[', ' ').Replace(']', ' ').Split('|');
            if (this.passCodeList.Count > 0)
            {
                retArr = new string[passCodeList.Count];
                for (int i = 0; i < passCodeList.Count; i++)
                {
                    retArr[i] = TemplateCodeList[passCodeList[i]];
                }
                string temp = String.Join(",", retArr);
                temp = temp.Replace('{', ' ').Replace('}', ' ');
                string result = Regex.Replace(temp, @"\s", "");

                //提交验证码
                string url = StringHelper.GetConfigValByKey(Constant.CheckCodeUrl, false);
                Dictionary <String, String> parames = new Dictionary <String, String> {
                    { "login_site", "E" },
                    { "rand", "sjrand" },
                    { "answer", result }
                };
                try
                {
                    //TrainServiceClient client = TrainClientSVC.GetTrainSVC().GetClientService();
                    //string resp = client.HttpPostAsync(url, parames).ToString();
                    HttpItem item = new HttpItem()
                    {
                        URL      = url,
                        PostData = parames,
                        Cookie   = TrainCommon.HttpRequest.BeforLoginCookie
                    };
                    string resp = TrainCommon.HttpRequest.HttpPost(item);
                    //反序列化
                    BackData back = JsonConvert.DeserializeObject <BackData>(resp);

                    /*-校验验证码
                     *  - 没携带cookie:           { "result_message":"验证码校验失败,信息为空","result_code":"8" }
                     *  -携带cookie但点错了:      { "result_message":"验证码校验失败","result_code":"5" }
                     *  -携带cookie并且点击正确:  { "result_message":"验证码校验成功","result_code":"4" }
                     *  -停留时间过长:            { "result_message":"验证码已经过期","result_code":"7" }*/
                    if (back != null && back.result_code == "4")
                    {
                        //触发父窗口事件方法
                        ChangeTextEvent?.Invoke(true);

                        this.isPass = true;
                        this._loginWindow.Show();
                        this.DialogResult = true;
                        this.Close();
                    }
                    else
                    {
                        MessageBox.Show("验证失败\r\n" + back.result_message, "信息", MessageBoxButton.OK, MessageBoxImage.Warning);
                        LogHelper.Log(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, back.result_message);
                        LogHelper.Info("验证失败" + back.result_message);
                        LogHelper.Error("验证失败" + back.result_message);
                        RefreshPasscode(sender, e);//验证失败刷新验证码
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("验证失败了。\r\n" + ex.Message, "信息提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    RefreshPasscode(sender, e);//验证失败刷新验证码
                    LogHelper.Log(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message);
                    LogHelper.Error(ex);
                }
            }
            else
            {
                MessageBox.Show("请点击图中验证码", "信息", MessageBoxButton.OK, MessageBoxImage.Exclamation);
            }
        }
        protected internal override string DoTransformation(Creature target, out bool isBadEnd)
        {
            isBadEnd = false;

            //by default, this is 2 rolls at 50%, so a 25% chance of 0 additional tfs, 50% chance of 1 additional tf, 25% chance of 2 additional tfs.
            //also takes into consideration any perks that increase or decrease tf effectiveness. if you need to roll out your own, feel free to do so.
            int changeCount      = GenerateChangeCount(target, new int[] { 2, 3 });
            int remainingChanges = changeCount;

            StringBuilder sb = new StringBuilder();

            //For all of these, any text regarding the transformation should be instead abstracted out as an abstract string function. append the result of this abstract function
            //to the string builder declared above (aka sb.Append(FunctionCall(variables));) string builder is just a fancy way of telling the compiler that you'll be creating a
            //long string, piece by piece, so don't do any crazy optimizations first.

            //the initial text for starting the transformation. feel free to add additional variables to this if needed.
            sb.Append(InitialTransformationText(target));

            //Add any free changes here - these can occur even if the change count is 0. these include things such as change in stats (intelligence, etc)
            //change in height, hips, and/or butt, or other similar stats.

            //this will handle the edge case where the change count starts out as 0.
            if (remainingChanges <= 0)
            {
                return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
            }

            //Any transformation related changes go here. these typically cost 1 change. these can be anything from body parts to gender (which technically also changes body parts,
            //but w/e). You are required to make sure you return as soon as you've applied changeCount changes, but a single line of code can be applied at the end of a change to do
            //this for you.

            //paste this line after any tf is applied, and it will: automatically decrement the remaining changes count. if it becomes 0 or less, apply the total number of changes
            //underwent to the target's change count (if applicable) and then return the StringBuilder content.
            //if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges);

            //possible use effects:
            //- corruption increases by 1 up to low threshold (~20)
            if (Utils.Rand(3) == 0 && target.corruption < 20)
            {
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }

                target.ChangeCorruption(1);
            }

            //- toughess up, sensitivity down
            if (Utils.Rand(3) == 0 && target.relativeToughness < 50)
            {
                target.DeltaCreatureStats(tou: 1, sens: -1);
            }
            //- speed down
            if (Utils.Rand(3) == 0 && target.relativeSpeed > 40)
            {
                target.ChangeSpeed(-1);
            }
            //-always increases lust by a function of sensitivity

            //"The tingling of the tentacle

            //Neck restore
            if (target.neck.type != NeckType.HUMANOID && Utils.Rand(4) == 0)
            {
                NeckData oldData = target.neck.AsReadOnlyData();
                target.RestoreNeck();
                sb.Append(RestoredNeckText(target, oldData));
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Rear body restore
            if (!target.back.isDefault && Utils.Rand(5) == 0)
            {
                BackData oldData = target.back.AsReadOnlyData();
                target.RestoreBack();
                sb.Append(RestoredBackText(target, oldData));
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Ovi perk loss
            if (target.womb.canRemoveOviposition && Utils.Rand(5) == 0)
            {
                target.womb.ClearOviposition();
                sb.Append(ClearOvipositionText(target));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //physical changes:
            //- may randomly remove bee abdomen, if present; always checks and does so when any changes to hair might happen
            if (Utils.Rand(4) == 0 && target.tail.type == TailType.BEE_STINGER)
            {
                TailData oldData = target.tail.AsReadOnlyData();
                target.UpdateTail(TailType.NONE);
                sb.Append(UpdateTailText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-may randomly remove bee wings:
            if (Utils.Rand(4) == 0 && target.wings.type == WingType.BEE_LIKE)
            {
                WingData oldData = target.wings.AsReadOnlyData();
                target.RestoreWings();
                sb.Append(RestoredWingsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-hair morphs to anemone tentacles, retains color, hair shrinks back to med-short('shaggy') and stops growing, lengthening treatments don't work and goblins won't cut it, but more anemone items can lengthen it one level at a time
            if (target.gills.type == GillType.ANEMONE && target.hair.type != HairType.ANEMONE && Utils.Rand(5) == 0)
            {
                HairData oldData = target.hair.AsReadOnlyData();
                target.UpdateHair(HairType.ANEMONE, newStyle: HairStyle.WAVY);
                sb.Append(UpdateHairText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //-feathery gills sprout from chest and drape sensually over nipples (cumulative swimming power boost with fin, if swimming is implemented)
            if (Utils.Rand(5) == 0 && target.gills.type != GillType.ANEMONE && target.body.primarySkin.tone == Tones.BLUE_BLACK)
            {
                GillData oldData = target.gills.AsReadOnlyData();
                target.UpdateGills(GillType.ANEMONE);
                sb.Append(UpdateGillsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //-[aphotic] skin tone (blue-black)
            if (Utils.Rand(5) == 0 && target.body.primarySkin.tone != Tones.BLUE_BLACK)
            {
                target.body.ChangeAllSkin(Tones.BLUE_BLACK);

                //kGAMECLASS.rathazul.addMixologyXP(20);
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-eat more, grow more 'hair':
            if (target.hair.type == HairType.ANEMONE && target.hair.length < 36 && Utils.Rand(2) == 0)
            {
                double temp = 5 + Utils.Rand(3);

                //grow it, and force growth. ignore the natural growth because that's how anemone hair works - it lengthens with tf item.
                target.hair.GrowHair(temp, true);

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes
            //occurred, then return the contents of the stringbuilder.
            return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
        }
Exemplo n.º 24
0
 protected abstract string RestoredBackAndWings(Creature target, WingData oldWings, BackData oldBack);
Exemplo n.º 25
0
        protected internal override string DoTransformation(Creature target, out bool isBadEnd)
        {
            isBadEnd = false;

            //by default, this is 2 rolls at 50%, so a 25% chance of 0 additional tfs, 50% chance of 1 additional tf, 25% chance of 2 additional tfs.
            //also takes into consideration any perks that increase or decrease tf effectiveness. if you need to roll out your own, feel free to do so.
            int changeCount      = GenerateChangeCount(target, new int[] { 2, 2, 3 });
            int remainingChanges = changeCount;

            StringBuilder sb = new StringBuilder();

            //For all of these, any text regarding the transformation should be instead abstracted out as an abstract string function. append the result of this abstract function
            //to the string builder declared above (aka sb.Append(FunctionCall(variables));) string builder is just a fancy way of telling the compiler that you'll be creating a
            //long string, piece by piece, so don't do any crazy optimizations first.

            //the initial text for starting the transformation. feel free to add additional variables to this if needed.
            sb.Append(InitialTransformationText(target));

            //Add any free changes here - these can occur even if the change count is 0. these include things such as change in stats (intelligence, etc)
            //change in height, hips, and/or butt, or other similar stats.

            //this will handle the edge case where the change count starts out as 0.
            if (remainingChanges <= 0)
            {
                return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
            }

            //Any transformation related changes go here. these typically cost 1 change. these can be anything from body parts to gender (which technically also changes body parts,
            //but w/e). You are required to make sure you return as soon as you've applied changeCount changes, but a single line of code can be applied at the end of a change to do
            //this for you.

            //paste this line after any tf is applied, and it will: automatically decrement the remaining changes count. if it becomes 0 or less, apply the total number of changes
            //underwent to the target's change count (if applicable) and then return the StringBuilder content.
            //if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges);


            //Text go!

            //Speed raises up to 75
            if (target.relativeSpeed < 75 && Utils.Rand(3) == 0)
            {
                //low speed
                if (target.relativeSpeed <= 30)
                {
                    target.ChangeSpeed(2);
                }
                //medium speed
                else if (target.relativeSpeed <= 60)
                {
                    target.ChangeSpeed(1);
                }
                //high speed
                else
                {
                    target.ChangeSpeed(.5);
                }
            }
            //Strength raises to 40
            if (target.relativeStrength < 40 && Utils.Rand(3) == 0)
            {
                target.ChangeStrength(1);
            }
            //Strength ALWAYS drops if over 60
            //Does not add to change total
            else if (target.relativeStrength > 60 && Utils.Rand(2) == 0)
            {
                target.ChangeStrength(-2);
            }
            //Toughness drops if over 50
            //Does not add to change total
            if (target.relativeToughness > 50 && Utils.Rand(2) == 0)
            {
                target.ChangeToughness(-2);
            }
            //Intelliloss
            if (Utils.Rand(4) == 0)
            {
                target.ChangeIntelligence(-1);
            }

            //Libido gain
            if (target.relativeLibido < 80 && Utils.Rand(4) == 0)
            {
                target.DeltaCreatureStats(lib: 1, sens: .25);
            }

            //Sexual changes would go here if I wasn't a tard.
            //Heat
            if (Utils.Rand(4) == 0)
            {
                bool intensified = target.HasTimedEffect <Heat>();

                if (target.GoIntoHeat())
                {
                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
            }

            //Shrink the boobalies down to A for men or C for girls.
            if (Utils.Rand(4) == 0 && !hyperHappy)
            {
                CupSize targetSize;
                //female or herm. targeting C cup, but will respect smallest possible cup if it's somehow above a c cup.
                if (target.gender.HasFlag(Gender.FEMALE))
                {
                    targetSize = EnumHelper.Max(CupSize.C, target.genitals.smallestPossibleFemaleCupSize);
                }
                //male or genderless. targeting A cup, but will respect smallest possible cup if somehow above an a cup.
                else
                {
                    targetSize = EnumHelper.Max(CupSize.A, target.genitals.smallestPossibleMaleCupSize);
                }
                //IT IS!
                int rowsShrunk = 0;
                foreach (Breasts row in target.breasts)
                {
                    //If this row is over threshhold
                    if (row.cupSize > targetSize)
                    {
                        //Big change
                        if (row.cupSize > CupSize.EE_BIG)
                        {
                            row.ShrinkBreasts((byte)(2 + Utils.Rand(3)));
                        }
                        //Small change
                        else
                        {
                            row.ShrinkBreasts(1);
                        }
                        rowsShrunk++;
                    }
                }
                //Count that t**s were shrunk
                if (rowsShrunk > 0)
                {
                    remainingChanges--;
                    if (remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
            }
            //Cat dangly-doo.
            if (target.cocks.Count > 0 && target.cocks.Any(x => x.type != CockType.CAT) && (target.ears.type == EarType.CAT || Utils.Rand(3) > 0) &&
                (target.tail.type == TailType.CAT || Utils.Rand(3) > 0) && Utils.Rand(4) == 0)
            {
                C**k nonCat = target.cocks.First(x => x.type != CockType.CAT);

                target.genitals.UpdateCock(nonCat, CockType.CAT);
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Cat penorz shrink
            if (target.genitals.HasAnyCocksOfType(CockType.CAT) && Utils.Rand(3) == 0 && !hyperHappy)
            {
                //loop through and find a cat wang.

                foreach (C**k catCock in target.cocks.Where(x => x.type == CockType.CAT))
                {
                    //lose 33% size until under 10, then lose 2" at a time
                    if (catCock.length > 16)
                    {
                        catCock.SetLength(catCock.length * .66);
                    }
                    else if (catCock.length > 6)
                    {
                        catCock.DecreaseLength(2);
                    }
                    if (catCock.length / 5 < catCock.girth && catCock.girth > 1.25)
                    {
                        catCock.SetGirth(catCock.length / 6);
                    }
                }

                //(big sensitivity boost)
                target.ChangeSensitivity(5);
                //Make note of other dicks changing
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Neck restore
            if (target.neck.type != NeckType.HUMANOID && Utils.Rand(4) == 0)
            {
                NeckData oldData = target.neck.AsReadOnlyData();
                target.RestoreNeck();
                sb.Append(RestoredNeckText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Rear body restore
            if (!target.back.isDefault && Utils.Rand(5) == 0)
            {
                BackData oldData = target.back.AsReadOnlyData();
                target.RestoreBack();
                sb.Append(RestoredBackText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Ovi perk loss
            if (target.womb.canRemoveOviposition && Utils.Rand(5) == 0)
            {
                target.womb.ClearOviposition();
                sb.Append(ClearOvipositionText(target));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Body type changes. Teh rarest of the rare.
            // Catgirl-face -> cat-morph-face
            if (target.face.type == FaceType.CAT && !target.face.isFullMorph && target.tongue.type == TongueType.CAT && target.ears.type == EarType.CAT &&
                target.tail.type == TailType.CAT && target.lowerBody.type == LowerBodyType.CAT && target.arms.type == ArmType.CAT &&
                (target.body.IsFurBodyType() /*|| (target.body.type == BodyType.REPTILE && Species.SPHINX.Score(target) >= 4)*/) && Utils.Rand(5) == 0)
            {
                target.face.StrengthenFacialMorph();
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //DA EARZ
            if (target.ears.type != EarType.CAT && Utils.Rand(5) == 0)
            {
                EarData oldData = target.ears.AsReadOnlyData();
                target.UpdateEars(EarType.CAT);
                sb.Append(UpdateEarsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //DA TAIL (IF ALREADY HAZ URZ)
            if (target.tail.type != TailType.CAT && target.ears.type == EarType.CAT && Utils.Rand(5) == 0)
            {
                TailData oldData = target.tail.AsReadOnlyData();
                target.UpdateTail(TailType.CAT);
                sb.Append(UpdateTailText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Da paws (if already haz ears & tail)
            if (target.tail.type == TailType.CAT && target.ears.type == EarType.CAT && Utils.Rand(5) == 0 && target.lowerBody.type != LowerBodyType.CAT)
            {
                //hoof to cat:
                if (target.lowerBody.type == LowerBodyType.HOOVED)
                {
                }
                //Goo to cat
                else if (target.lowerBody.type == LowerBodyType.GOO)
                {
                }
                //non hoof to cat:
                LowerBodyData oldData = target.lowerBody.AsReadOnlyData();
                target.UpdateLowerBody(LowerBodyType.CAT);
                sb.Append(UpdateLowerBodyText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //TURN INTO A FURRAH! OH SHIT
            if (target.tail.type == TailType.CAT && target.ears.type == EarType.CAT && Utils.Rand(5) == 0 && target.lowerBody.type == LowerBodyType.CAT && !target.body.IsFurBodyType())
            {
                BodyData oldData = target.body.AsReadOnlyData();
                target.UpdateBody(BodyType.UNDERBODY_FUR);
                sb.Append(UpdateBodyText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            // Fix old cat faces without cat-eyes.
            if (target.face.type == FaceType.CAT && target.eyes.type != EyeType.CAT && Utils.Rand(3) == 0)
            {
                EyeData oldData = target.eyes.AsReadOnlyData();
                target.UpdateEyes(EyeType.CAT);
                sb.Append(UpdateEyesText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //CAT-FACE! FULL ON FURRY! RAGE AWAY NEKOZ
            if (target.tail.type == TailType.CAT && target.ears.type == EarType.CAT && target.lowerBody.type == LowerBodyType.CAT && target.face.type != FaceType.CAT && Utils.Rand(5) == 0)
            {
                //Gain cat face, replace old face
                //MOD NOTE: but not a full-morph cat face. just level 1.
                FaceData oldData = target.face.AsReadOnlyData();
                target.UpdateFace(FaceType.CAT);
                sb.Append(UpdateFaceText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            // Cat-tongue
            if (target.face.type == FaceType.CAT && target.tongue.type != TongueType.CAT && Utils.Rand(5) == 0)
            {
                TongueData oldData = target.tongue.AsReadOnlyData();
                target.UpdateTongue(TongueType.CAT);
                sb.Append(UpdateTongueText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Arms
            if (target.arms.type != ArmType.CAT && target.body.IsFurBodyType() && target.tail.type == TailType.CAT && target.lowerBody.type == LowerBodyType.CAT && Utils.Rand(4) == 0)
            {
                ArmData oldData = target.arms.AsReadOnlyData();
                target.UpdateArms(ArmType.CAT);
                sb.Append(UpdateArmsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            // Remove gills
            if (Utils.Rand(4) == 0 && !target.gills.isDefault)
            {
                GillData oldData = target.gills.AsReadOnlyData();
                target.RestoreGills();
                sb.Append(RestoredGillsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //FAILSAFE CHANGE
            if (remainingChanges == changeCount)
            {
                (target as CombatCreature)?.AddHP(50);
                target.ChangeLust(3);
            }

            //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes
            //occurred, then return the contents of the stringbuilder.
            return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
        }
        /** Original Credits:
         * @since March 26, 2018
         * @author Stadler76
         */
        protected internal override string DoTransformation(Creature target, out bool isBadEnd)
        {
            isBadEnd = false;

            //by default, this is 2 rolls at 50%, so a 25% chance of 0 additional tfs, 50% chance of 1 additional tf, 25% chance of 2 additional tfs.
            //also takes into consideration any perks that increase or decrease tf effectiveness. if you need to roll out your own, feel free to do so.
            int changeCount      = GenerateChangeCount(target, new int[] { 2, 2 }, isEnhanced ? 3 : 1);
            int remainingChanges = changeCount;

            StringBuilder sb = new StringBuilder();

            //For all of these, any text regarding the transformation should be instead abstracted out as an abstract string function. append the result of this abstract function
            //to the string builder declared above (aka sb.Append(FunctionCall(variables));) string builder is just a fancy way of telling the compiler that you'll be creating a
            //long string, piece by piece, so don't do any crazy optimizations first.

            //the initial text for starting the transformation. feel free to add additional variables to this if needed.
            sb.Append(InitialTransformationText(target));

            //Add any free changes here - these can occur even if the change count is 0. these include things such as change in stats (intelligencelligence, etc)
            //change in height, hips, and/or butt, or other similar stats.

            //this will handle the edge case where the change count starts out as 0.
            if (remainingChanges <= 0)
            {
                return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
            }

            //Any transformation related changes go here. these typically cost 1 change. these can be anything from body parts to gender (which technically also changes body parts,
            //but w/e). You are required to make sure you return as soon as you've applied changeCount changes, but a single line of code can be applied at the end of a change to do
            //this for you.

            //paste this line after any tf is applied, and it will: automatically decrement the remaining changes count. if it becomes 0 or less, apply the total number of changes
            //underwent to the target's change count (if applicable) and then return the StringBuilder content.
            //if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges);

            //Used as a holding variable for biggest dicks and the like
            //****************
            //General Effects:
            //****************
            //-Int less than 10
            if (target is IExtendedCreature extendedCreature && !extendedCreature.extendedData.resistsTFBadEnds && target.intelligence < 10)
            {
                if (target.intelligence < 8 && Species.KANGAROO.Score(target) >= 5)
                {
                    isBadEnd = true;
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //-Speed to 70
            if (target.relativeSpeed < 70 && Utils.Rand(3) == 0)
            {
                //2 points up if below 40!
                if (target.relativeSpeed < 40)
                {
                    target.ChangeSpeed(1);
                }

                target.ChangeSpeed(1);
            }
            //-Int to 10
            if (target.intelligence > 2 && Utils.Rand(3) == 0)
            {
                //Gain dumb (smart!)
                //gain dumb (30-10 int):

                //gain dumb (10-1 int):
                target.ChangeIntelligence(-1);
            }

            //****************
            //Appearance Effects:
            //****************
            //-Hip widening funtimes
            if (Utils.Rand(4) == 0 && target.hips.size < 40)
            {
                target.hips.GrowHips();
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Restore arms to become human arms again
            if (Utils.Rand(4) == 0)
            {
                ArmData oldData = target.arms.AsReadOnlyData();
                target.RestoreArms();
                sb.Append(RestoredArmsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Remove feathery hair
            if (RemoveFeatheryHair(target))
            {
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Remove odd eyes
            if (Utils.Rand(5) == 0 && !target.eyes.isDefault)
            {
                EyeData oldData = target.eyes.AsReadOnlyData();
                target.RestoreEyes();
                sb.Append(RestoredEyesText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //****************
            //Sexual:
            //****************
            //-Shrink balls down to reasonable size (3?)
            if (target.balls.size >= 4 && Utils.Rand(2) == 0)
            {
                target.balls.ShrinkBalls();
                target.genitals.IncreaseCumMultiplier();

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Shorten clits to reasonable size
            //MOD NOTE: lets do one at a time. i generally do all because that's the easiest way to port it, but f**k it.
            V****a largestClit = target.genitals.LargestVaginaByClitSize();

            if (target.hasVagina && largestClit.c**t.length >= 4 && Utils.Rand(5) == 0)
            {
                largestClit.ShrinkClit(largestClit.c**t.length / 2);

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Find biggest dick!
            C**k biggestCock = target.genitals.LongestCock();

            //-Shrink dicks down to 8\" max.
            if (target.hasCock && biggestCock.length >= 16 && Utils.Rand(5) == 0)
            {
                biggestCock.DecreaseLength(biggestCock.length / 2);
                biggestCock.DecreaseThickness(2 * biggestCock.length / 3);

                if (biggestCock.girth * 6 > biggestCock.length)
                {
                    biggestCock.DecreaseThickness(.4);
                }

                else if (biggestCock.girth * 8 > biggestCock.length)
                {
                    biggestCock.DecreaseThickness(.2);
                }

                if (biggestCock.girth < .5)
                {
                    biggestCock.SetGirth(0.5);
                }

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //C**K TF!
            if (target.cocks.Any(x => x.type != CockType.KANGAROO) && Utils.Rand(isEnhanced ? 2 : 3) == 0)
            {
                C**k notRoo = target.cocks.First(x => x.type != CockType.KANGAROO);
                target.genitals.UpdateCock(notRoo, CockType.KANGAROO);
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Neck restore
            if (target.neck.type != NeckType.HUMANOID && Utils.Rand(4) == 0)
            {
                NeckData oldData = target.neck.AsReadOnlyData();
                target.RestoreNeck();
                sb.Append(RestoredNeckText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Rear body restore
            if (!target.back.isDefault && Utils.Rand(5) == 0)
            {
                BackData oldData = target.back.AsReadOnlyData();
                target.RestoreBack();
                sb.Append(RestoredBackText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Ovi perk loss
            if (target.womb.canRemoveOviposition && Utils.Rand(5) == 0)
            {
                target.womb.ClearOviposition();
                sb.Append(ClearOvipositionText(target));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //****************
            //Big Kanga Morphs
            //type 1 ignores normal restrictions
            //****************
            //-Face (Req: Fur + Feet)
            if (target.face.type != FaceType.KANGAROO && ((target.body.IsFurBodyType() && target.lowerBody.type == LowerBodyType.KANGAROO) || isEnhanced) && Utils.Rand(4) == 0)
            {
                FaceData oldData = target.face.AsReadOnlyData();
                target.UpdateFace(FaceType.KANGAROO);
                sb.Append(UpdateFaceText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Fur (Req: Footsies)
            if (!target.body.IsFurBodyType() && (target.lowerBody.type == LowerBodyType.KANGAROO || isEnhanced) && Utils.Rand(4) == 0)
            {
                BodyData oldData = target.body.AsReadOnlyData();
                target.UpdateBody(BodyType.SIMPLE_FUR, new FurColor(HairFurColors.BROWN));
                sb.Append(UpdateBodyText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Roo footsies (Req: Tail)
            if (target.lowerBody.type != LowerBodyType.KANGAROO && (isEnhanced || target.tail.type == TailType.KANGAROO) && Utils.Rand(4) == 0)
            {
                LowerBodyData oldData = target.lowerBody.AsReadOnlyData();
                target.UpdateLowerBody(LowerBodyType.KANGAROO);
                sb.Append(UpdateLowerBodyText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Roo tail (Req: Ears)
            if (target.tail.type != TailType.KANGAROO && Utils.Rand(4) == 0 && (isEnhanced || target.ears.type == EarType.KANGAROO))
            {
                TailData oldData = target.tail.AsReadOnlyData();
                target.UpdateTail(TailType.KANGAROO);
                sb.Append(UpdateTailText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-Roo ears
            if (target.ears.type != EarType.KANGAROO && Utils.Rand(4) == 0)
            {
                EarData oldData = target.ears.AsReadOnlyData();
                target.UpdateEars(EarType.KANGAROO);
                sb.Append(UpdateEarsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //UBEROOOO
            //kangaroo perk: - any liquid or food intake will accelerate a pregnancy, but it will not progress otherwise
            if (target.womb.canObtainDiapause && Species.KANGAROO.Score(target) > 4 && Utils.Rand(4) == 0 && target.hasVagina)
            {
                target.womb.EnableDiapause();

                //Perk name and description:
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
                //trigger effect: Your body reacts to the influx of nutrition, accelerating your pregnancy. Your belly bulges outward slightly.
            }
            // Remove gills
            if (Utils.Rand(4) == 0 && !target.gills.isDefault)
            {
                target.RestoreGills();
            }
            if (remainingChanges == changeCount)
            {
                (target as CombatCreature)?.RecoverFatigue(40);
            }


            //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes
            //occurred, then return the contents of the stringbuilder.
            return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
        }
Exemplo n.º 27
0
 private void BtnUpload_Click(object sender, EventArgs e)
 {
     FILE = ComboBoxFile.Text; BackData.RunWorkerAsync();
 }
        protected internal override string DoTransformation(Creature target, out bool isBadEnd)
        {
            isBadEnd = false;

            //by default, this is 2 rolls at 50%, so a 25% chance of 0 additional tfs, 50% chance of 1 additional tf, 25% chance of 2 additional tfs.
            //also takes into consideration any perks that increase or decrease tf effectiveness. if you need to roll out your own, feel free to do so.
            int changeCount      = GenerateChangeCount(target, new int[] { 2, 3, 3 });
            int remainingChanges = changeCount;

            StringBuilder sb = new StringBuilder();

            //For all of these, any text regarding the transformation should be instead abstracted out as an abstract string function. append the result of this abstract function
            //to the string builder declared above (aka sb.Append(FunctionCall(variables));) string builder is just a fancy way of telling the compiler that you'll be creating a
            //long string, piece by piece, so don't do any crazy optimizations first.

            //the initial text for starting the transformation. feel free to add additional variables to this if needed.
            sb.Append(InitialTransformationText(target));

            //Add any free changes here - these can occur even if the change count is 0. these include things such as change in stats (intelligence, etc)
            //change in height, hips, and/or butt, or other similar stats.

            //this will handle the edge case where the change count starts out as 0.
            if (remainingChanges <= 0)
            {
                return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
            }

            //Any transformation related changes go here. these typically cost 1 change. these can be anything from body parts to gender (which technically also changes body parts,
            //but w/e). You are required to make sure you return as soon as you've applied changeCount changes, but a single line of code can be applied at the end of a change to do
            //this for you.

            //paste this line after any tf is applied, and it will: automatically decrement the remaining changes count. if it becomes 0 or less, apply the total number of changes
            //underwent to the target's change count (if applicable) and then return the StringBuilder content.
            //if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges);


            //Speed Increase:
            if (target.relativeSpeed < 100 && Utils.Rand(3) == 0)
            {
                target.ChangeSpeed(1);
            }
            //Strength Loss:
            else if (target.relativeStrength > 40 && Utils.Rand(3) == 0)
            {
                target.ChangeStrength(-1);
            }
            //Sensitivity Increase:
            if (target.relativeSensitivity < 70 && target.hasCock && Utils.Rand(3) == 0)
            {
                target.ChangeSensitivity(5);
            }
            //Libido Increase:
            if (target.relativeLibido < 70 && target.hasVagina && Utils.Rand(3) == 0)
            {
                target.ChangeLibido(2);
                if (target.relativeLibido < 30)
                {
                    target.ChangeLibido(2);
                }
            }
            //Body Mass Loss:
            if (target.build.thickness > 40 && Utils.Rand(3) == 0)
            {
                target.build.ChangeThicknessToward(40, 3);
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //Thigh Loss: (towards \"girly\")
            if (target.hips.size >= 10 && Utils.Rand(4) == 0)
            {
                target.hips.ShrinkHips();
                if (target.hips.size > 15)
                {
                    target.hips.ShrinkHips((byte)(2 + Utils.Rand(3)));
                }

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Thigh Gain: (towards \"girly\")
            if (target.hips.size < 6 && Utils.Rand(4) == 0)
            {
                target.hips.GrowHips();
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //Breast Loss: (towards A cup)
            CupSize largestSize = target.genitals.BiggestCupSize();

            CupSize targetCup = EnumHelper.Max(target.genitals.smallestPossibleCupSize, CupSize.A);

            //Mod note: both shrink and gain combined into one check.
            if (largestSize != targetCup && Utils.Rand(4) == 0)
            {
                foreach (Breasts breast in target.breasts)
                {
                    //Mod Note: Generally i prefer the enum value over magic constants, but i have no idea what 70 is in cup land and don't want to look it up.
                    if (breast.cupSize > (CupSize)70)
                    {
                        breast.ShrinkBreasts((byte)(Utils.Rand(3) + 15));
                    }
                    else if (breast.cupSize > (CupSize)50)
                    {
                        breast.ShrinkBreasts((byte)(Utils.Rand(3) + 10));
                    }
                    else if (breast.cupSize > (CupSize)30)
                    {
                        breast.ShrinkBreasts((byte)(Utils.Rand(3) + 7));
                    }
                    else if (breast.cupSize > (CupSize)15)
                    {
                        breast.ShrinkBreasts((byte)(Utils.Rand(3) + 4));
                    }
                    else if (breast.cupSize > targetCup)
                    {
                        breast.ShrinkBreasts((byte)(2 + Utils.Rand(2)));
                    }

                    //Mod note: if we shrunk it below the target cup size or it already was,
                    if (breast.cupSize < targetCup)
                    {
                        breast.SetCupSize(targetCup);
                    }
                }
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Penis Reduction towards 3.5 Inches:
            if (target.genitals.LongestCockLength() >= 3.5 && target.hasCock && Utils.Rand(2) == 0)
            {
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Testicle Reduction:
            if (target.balls.count > 0 && target.hasCock && (target.balls.size > 1 || target.balls.count > 1) && Utils.Rand(4) == 0)
            {
                if (target.balls.size > 20)
                {
                    target.balls.ShrinkBalls(6);
                }
                else if (target.balls.size > 15)
                {
                    target.balls.ShrinkBalls(5);
                }
                else if (target.balls.size > 12)
                {
                    target.balls.ShrinkBalls(4);
                }
                else if (target.balls.size > 10)
                {
                    target.balls.ShrinkBalls(3);
                }
                else if (target.balls.size > 8)
                {
                    target.balls.ShrinkBalls(2);
                }
                else if (target.balls.size > 1)
                {
                    target.balls.ShrinkBalls(1);
                }
                else
                {
                    target.balls.MakeUniBall();
                }

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Anal Wetness Increase:
            if (target.ass.wetness < AnalWetness.SLIME_DROOLING && Utils.Rand(4) == 0)
            {
                //Anal Wetness Increase Final (always loose):
                target.ass.IncreaseWetness();
                //buttChange(30,false,false,false);
                if (target.ass.looseness < AnalLooseness.STRETCHED)
                {
                    target.ass.IncreaseLooseness();
                }

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }

                target.ChangeSensitivity(2);
            }
            //Fertility Decrease:
            if (target.hasVagina && Utils.Rand(4) == 0)
            {
                target.ChangeSensitivity(-2);

                target.fertility.DecreaseFertility((byte)(1 + Utils.Rand(3)));
                if (target.fertility.currentFertility < 4)
                {
                    target.fertility.SetFertility(4);
                }

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Male Effects
            if (target.gender == Gender.MALE)
            {
                //Femininity Increase Final (max femininity allowed increased by +10):
                if (Utils.Rand(4) == 0)
                {
                    if (target.femininity < 70 && target.femininity >= 60)
                    {
                        if (target.femininity.femininityLimitedByGender)
                        {
                            target.femininity.ActivateAndrogyny();
                        }
                        target.femininity.IncreaseFemininity(10);
                        if (target.femininity > 70)
                        {
                            target.femininity.SetFemininity(70);
                        }

                        if (--remainingChanges <= 0)
                        {
                            return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                        }
                    }
                    //Femininity Increase:
                    else
                    {
                        target.femininity.IncreaseFemininity(10);
                        if (--remainingChanges <= 0)
                        {
                            return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                        }
                    }
                }
                //Muscle tone reduction:
                if (target.build.muscleTone > 20 && Utils.Rand(4) == 0)
                {
                    target.build.DecreaseMuscleTone(10);
                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
            }
            //Female Effects
            else if (target.gender == Gender.FEMALE)
            {
                //Masculinity Increase:
                if (target.femininity > 30 && Utils.Rand(4) == 0)
                {
                    target.femininity.IncreaseMasculinity(10);
                    if (target.femininity < 30)
                    {
                        target.femininity.SetFemininity(30);
                        //Masculinity Increase Final (max masculinity allowed increased by +10):

                        if (target.femininity.femininityLimitedByGender)
                        {
                            target.femininity.ActivateAndrogyny();
                        }
                    }

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
                //Muscle tone gain:
                if (target.build.muscleTone < 80 && Utils.Rand(4) == 0)
                {
                    target.build.GainMuscle(10);
                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
            }
            //Neck restore
            if (target.neck.type != NeckType.HUMANOID && Utils.Rand(4) == 0)
            {
                NeckData oldData = target.neck.AsReadOnlyData();
                target.RestoreNeck();
                sb.Append(RestoredNeckText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Rear body restore
            if (!target.back.isDefault && Utils.Rand(5) == 0)
            {
                BackData oldData = target.back.AsReadOnlyData();
                target.RestoreBack();
                sb.Append(RestoredBackText(target, oldData));
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Ovi perk loss
            if (target.womb.canRemoveOviposition && Utils.Rand(5) == 0)
            {
                target.womb.ClearOviposition();
                sb.Append(ClearOvipositionText(target));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Nipples Turn Black:
            if (!target.genitals.hasBlackNipples && Utils.Rand(6) == 0)
            {
                target.genitals.SetBlackNipples(true);

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Remove odd eyes
            if (target.eyes.count != 2 && target.eyes.type != EyeType.SAND_TRAP && Utils.Rand(2) == 0)
            {
                EyeData oldData = target.eyes.AsReadOnlyData();
                target.RestoreEyes();
                sb.Append(RestoredEyesText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //PC Trap Effects
            if (target.eyes.type != EyeType.SAND_TRAP && Utils.Rand(4) == 0)
            {
                //Eyes Turn Black:
                EyeData oldData = target.eyes.AsReadOnlyData();
                target.UpdateEyes(EyeType.SAND_TRAP);
                sb.Append(UpdateEyesText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //V****a Turns Black:
            //has a v****a and any v****a is not a sand trap (aka, not all of the vaginas are sand trap vags)
            if (target.hasVagina && !target.genitals.OnlyHasVaginasOfType(VaginaType.SAND_TRAP) && Utils.Rand(4) == 0)
            {
                //(Wet:
                //(Corruption <50:
                target.DeltaCreatureStats(sens: 2, lus: 10);

                target.vaginas.ForEach(x => target.genitals.UpdateVagina(x, VaginaType.SAND_TRAP));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Dragonfly Wings:
            if (target.wings.type != WingType.DRAGONFLY && Utils.Rand(4) == 0)
            {
                //Wings Fall Out: You feel a sharp pinching sensation in your shoulders and you cringe slightly. Your former dragonfly wings make soft, papery sounds as they fall into the dirt behind you.
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }

                target.UpdateWings(WingType.DRAGONFLY);
            }
            if (remainingChanges == changeCount)
            {
            }


            //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes
            //occurred, then return the contents of the stringbuilder.
            return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
        }
Exemplo n.º 29
0
 protected virtual string RestoredBackText(Creature target, BackData oldData)
 {
     return(target.back.RestoredText(oldData));
 }
Exemplo n.º 30
0
        private void BackData_DoWork(object sender, DoWorkEventArgs e)
        {
            string[] lines = File.ReadAllLines(TextBoxLocal.Text.Replace(@"\", @"\\"), Encoding.Default);

            if (FILE == "CADCOTI")
            {
                int step     = lines.Length / 100;
                int contline = 0;

                foreach (string linha in lines)
                {
                    if (linha.Length == 1264)
                    {
                        string CODEXT = linha.Substring(6, 4) + linha.Substring(12, 8);
                        string Nome   = linha.Substring(20, 30).Trim();
                        string CNPJ   = linha.Substring(60, 14).Trim();
                        string Data   = linha.Substring(1241, 2) + "/" + linha.Substring(1239, 2) + "/" + linha.Substring(1235, 4);

                        if (linha.Substring(58, 1) == "F")
                        {
                            CNPJ = linha.Substring(63, 11).Trim();
                        }

                        //DCTA.ADD(Convert.ToDouble(CODEXT), Nome, CNPJ, Data);
                    }
                    contline++;
                    if (contline % step == 0)
                    {
                        int steps = contline / step;
                        BackData.ReportProgress(steps);
                    }
                }
            }
            else if (FILE == "ARQSDFD0")
            {
                BL_Saldo ObjSaldo = new BL_Saldo();
                ObjSaldo.Deletar();

                int step     = lines.Length / 100;
                int contline = 0;

                foreach (string linha in lines)
                {
                    if (linha.Length == 600)
                    {
                        long     CODCOT       = Convert.ToInt64(linha.Substring(17, 14));
                        long     CODFUND      = Convert.ToInt64(linha.Substring(6, 5));
                        string   TIPOREGISTRO = linha.Substring(48, 2) == "20"? "Simples":"Total";
                        long     CAUTELA      = Convert.ToInt64(linha.Substring(50, 10));
                        decimal  QNTCOTAS     = Convert.ToDecimal(linha.Substring(111, 15)) / 100000;
                        DateTime DATACOTA     = DateTime.ParseExact(linha.Substring(139, 8), "yyyyMMdd", null);
                        decimal  COTA         = Convert.ToDecimal(linha.Substring(147, 15)) / 10000000;

                        ObjSaldo.Inserir(CODCOT, CODFUND, TIPOREGISTRO, CAUTELA, QNTCOTAS, DATACOTA, COTA);
                    }
                    contline++;
                    if (contline % step == 0)
                    {
                        int steps = contline / step;
                        BackData.ReportProgress(steps);
                    }
                }
            }
        }