Healpussy gene and succubus wing retexture

Brought over the healpussy gene from my mod and changed the succubus wings to a lighter version
This commit is contained in:
Shabakur 2022-12-28 10:30:26 +01:00
parent e8f9f94130
commit 0d15873bd2
19 changed files with 557 additions and 1 deletions

View file

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse.Sound;
using Verse;
using RimWorld;
using rjw;
using rjw.Modules.Interactions.Helpers;
using rjw.Modules.Interactions.Enums;
namespace RJW_Genes
{
public class AbilityUtility
{
public static void PussyHeal(SexProps props)
{
if (InteractionHelper.GetWithExtension(props.dictionaryKey).DominantHasFamily(GenitalFamily.Vagina) || InteractionHelper.GetWithExtension(props.dictionaryKey).SubmissiveHasFamily(GenitalFamily.Vagina))
{
Pawn pawn = props.pawn;
Pawn partner = props.partner;
FloatRange tendQualityRange;
tendQualityRange.min = 0.4f;
tendQualityRange.max = 0.8f;
if (GeneUtility.isPussyHealer(pawn))
{
Heal(partner, tendQualityRange);
}
if (GeneUtility.isPussyHealer(partner))
{
Heal(pawn, tendQualityRange);
}
}
}
public static bool Heal(Pawn pawn, FloatRange tendQualityRange)
{
bool any_wound_tended = false;
List<Hediff> hediffs = pawn.health.hediffSet.hediffs;
for (int i = hediffs.Count - 1; i >= 0; i--)
{
if ((hediffs[i] is Hediff_Injury || hediffs[i] is Hediff_MissingPart) && hediffs[i].TendableNow(false))
{
hediffs[i].Tended(tendQualityRange.RandomInRange, tendQualityRange.TrueMax, 1);
any_wound_tended = true;
}
}
return any_wound_tended;
}
}
}

View file

@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using UnityEngine;
using RimWorld;
using rjw;
using rjw.Modules.Interactions.Helpers;
namespace RJW_Genes
{
public class CompAbilityEffect_PussyHeal : CompAbilityEffect
{
private new CompProperties_AbilityPussyHeal Props
{
get
{
return (CompProperties_AbilityPussyHeal)this.props;
}
}
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
{
base.Apply(target, dest);
Pawn pawn = target.Pawn;
if (pawn == null)
{
return;
}
bool any_wound_tended = AbilityUtility.Heal(pawn, this.Props.tendQualityRange);
if (any_wound_tended)
{
MoteMaker.ThrowText(pawn.DrawPos, pawn.Map, "Sex healed wounds", 3.65f);
//pawn.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.Pussy_Healed, pawn, null);
}
//this.AfterSex(any_wound_tended);
//FleckMaker.AttachedOverlay(pawn, FleckDefOf.FlashHollow, Vector3.zero, 1.5f, -1f);
}
public void AfterSex(Pawn pawn, Pawn target)
{
List<Hediff> hediffs = target.health.hediffSet.hediffs;
for (int i = 0; i < hediffs.Count; i++)
{
if ((hediffs[i] is Hediff_Injury || hediffs[i] is Hediff_MissingPart) && hediffs[i].TendableNow(false))
{
//target.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.Pussy_Healed, pawn, null);
break;
}
}
//InteractionHelper.GetWithExtension(dictionaryKey).DominantHasTag("CanBePenetrated")
}
public override bool Valid(LocalTargetInfo target, bool throwMessages = false)
{
Pawn pawn = target.Pawn;
if (pawn != null)
{
//to be replaced with severel checks to make it clear why target is unable to have sex
if (!CasualSex_Helper.CanHaveSex(pawn))
{
if (throwMessages)
{
Messages.Message(pawn.Name + " is unable to have sex", pawn, MessageTypeDefOf.RejectInput, false);
}
return false;
}
else if (pawn.IsAnimal() && !RJWSettings.bestiality_enabled)
{
if (throwMessages)
{
Messages.Message("bestiality is disabled", pawn, MessageTypeDefOf.RejectInput, false);
}
return false;
}
//AbilityUtility.ValidateHasTendableWound(pawn, throwMessages, this.parent);
}
return base.Valid(target, throwMessages);
}
public override bool GizmoDisabled(out string reason)
{
reason = null;
if (!Genital_Helper.has_vagina(this.parent.pawn))
{
reason = this.parent.pawn.Name + " has no vagina to use.";
return true;
}
else if (!RJWSettings.rape_enabled)
{
reason = "Rape is disabled";
return true;
}
return false;
}
}
}

View file

@ -0,0 +1,155 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using RimWorld;
using rjw;
using rjw.Modules.Interactions.Objects;
using rjw.Modules.Interactions.Helpers;
using rjw.Modules.Interactions.Enums;
using rjw.Modules.Interactions.Implementation;
using rjw.Modules.Interactions.Defs.DefFragment;
namespace RJW_Genes
{
public class CompAbility_SexInteractionRequirements : AbilityComp
{
public CompProperties_SexInteractionRequirements Props
{
get
{
return (CompProperties_SexInteractionRequirements)this.props;
}
}
public static List<InteractionDef> GenerateInteractionDefList(Pawn pawn, Pawn pawn2, CompProperties_SexInteractionRequirements sexpropsreq)
{
List<InteractionTag> tags = new List<InteractionTag>();
if (pawn2.IsAnimal())
{
tags.Add(InteractionTag.Animal);
}
else
{
tags = sexpropsreq.tags;
}
InteractionRequirement dominantRequirement = sexpropsreq.dominantRequirement;
InteractionRequirement submissiveRequirement = sexpropsreq.submissiveRequirement;
List<InteractionDef> sexinteractions = SexUtility.SexInterractions;
List<InteractionDef> list = new List<InteractionDef>();
//List<InteractionDef> a = from interaction in sexinteractions
//where InteractionHelper.GetWithExtension(interaction).DominantHasFamily(dominantRequirement.families.)
// select interaction;
//should use where select but dont fully understand that, so I am using this.
foreach (InteractionDef interactionDef in SexUtility.SexInterractions)
{
//Use rjw function to check if the interaction would be valid
if (!LewdInteractionValidatorService.Instance.IsValid(interactionDef, pawn, pawn2))
{
continue;
}
InteractionWithExtension withExtension = InteractionHelper.GetWithExtension(interactionDef);
bool add_interaction = false;
//only add interactions which have a correct tag
foreach (InteractionTag tag in tags)
{
if (withExtension.HasInteractionTag(tag))
{
add_interaction = true;
break;
}
}
//In case of failure go to next interaction
if (!add_interaction)
{
continue;
}
//goes to next interaction if it doesn't have the required genitals
if (dominantRequirement != null)
{
foreach (GenitalFamily genitalFamily in dominantRequirement.families)
{
if (!withExtension.DominantHasFamily(genitalFamily))
{
add_interaction = false;
break;
}
}
if (!add_interaction)
{
continue;
}
foreach (GenitalTag tag in dominantRequirement.tags)
{
if (!withExtension.DominantHasTag(tag))
{
add_interaction = false;
break;
}
}
}
//goes to next interaction if it doesn't have the required genitals
if (submissiveRequirement != null)
{
foreach (GenitalFamily genitalFamily in submissiveRequirement.families)
{
if (!withExtension.SubmissiveHasFamily(genitalFamily))
{
add_interaction = false;
break;
}
}
if (!add_interaction)
{
continue;
}
foreach (GenitalTag tag in submissiveRequirement.tags)
{
if (!withExtension.SubmissiveHasTag(tag))
{
add_interaction = false;
break;
}
}
}
if (add_interaction)
{
list.Add(interactionDef);
}
}
return list;
}
//Generates a valid interaction for the requirements and assigns sexprops based on that
public static SexProps GenerateSexProps(Pawn pawn, Pawn pawn2, CompProperties_SexInteractionRequirements sexpropsreq)
{
List<InteractionDef> interactionlist = GenerateInteractionDefList(pawn, pawn2, sexpropsreq);
if (!interactionlist.Any())
{
return null;
}
InteractionDef dictionaryKey = interactionlist.RandomElement();
bool rape = InteractionHelper.GetWithExtension(dictionaryKey).HasInteractionTag(InteractionTag.Rape);
SexProps sexProps = new SexProps();
sexProps.pawn = pawn;
sexProps.partner = pawn2;
sexProps.sexType = SexUtility.rjwSextypeGet(dictionaryKey);
sexProps.isRape = rape;
sexProps.isRapist = rape;
sexProps.canBeGuilty = false;
sexProps.dictionaryKey = dictionaryKey;
sexProps.rulePack = SexUtility.SexRulePackGet(dictionaryKey);
return sexProps;
}
}
}

View file

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using RimWorld;
namespace RJW_Genes
{
public class CompProperties_AbilityPussyHeal : CompProperties_AbilityEffect
{
public CompProperties_AbilityPussyHeal()
{
this.compClass = typeof(CompAbilityEffect_PussyHeal);
}
public FloatRange tendQualityRange;
}
}

View file

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using RimWorld;
using rjw;
using rjw.Modules.Interactions.Defs.DefFragment;
using rjw.Modules.Interactions.Enums;
namespace RJW_Genes
{
public class CompProperties_SexInteractionRequirements : AbilityCompProperties
{
public CompProperties_SexInteractionRequirements()
{
this.compClass = typeof(CompAbility_SexInteractionRequirements);
}
public List<InteractionTag> tags = new List<InteractionTag>();
public InteractionRequirement dominantRequirement;
public InteractionRequirement submissiveRequirement;
}
}

View file

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using RimWorld;
namespace RJW_Genes
{
public class Interaction_weights
{
public InteractionDef interaction;
public int weight = 1;
}
}

View file

@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;
using Verse.AI;
using rjw;
namespace RJW_Genes
{
public class JobDriver_CastAbilityAfterSex : JobDriver_SexBaseInitiator
{
//Summary//
//Similar to jobdriver rape, but it cast an ability after sex and tries to limit what kind of sexinteractions are allowed.
protected override IEnumerable<Toil> MakeNewToils()
{
base.setup_ticks();
//this.FailOnDespawnedOrNull(TargetIndex.A);
//this.FailOnCannotTouch(TargetIndex.B, PathEndMode.OnCell);
this.FailOnDespawnedNullOrForbidden(this.iTarget);
//this.FailOn(() => !target.health.capacities.CanBeAwake);
JobDef PartnerJob = xxx.gettin_raped;
yield return Toils_Goto.Goto(TargetIndex.A, PathEndMode.OnCell);
yield return new Toil
{
defaultCompleteMode = ToilCompleteMode.Instant,
socialMode = RandomSocialMode.Off,
initAction = delegate ()
{
Job newJob = JobMaker.MakeJob(PartnerJob, this.pawn, this.Partner);
this.Partner.jobs.StartJob(newJob, JobCondition.InterruptForced, null, false, true, null, null, false, false, null, false, true);
}
};
Toil toil = new Toil();
toil.defaultCompleteMode = ToilCompleteMode.Never;
toil.socialMode = RandomSocialMode.Off;
toil.defaultDuration = this.duration;
toil.handlingFacing = true;
toil.FailOn(() => this.Partner.CurJob.def != PartnerJob);
toil.initAction = delegate ()
{
this.Partner.pather.StopDead();
this.Partner.jobs.curDriver.asleep = false;
//Tries to find CompProperties_SexInteractionRequirements and if it finds it it will try and generate sexprops based on the sexpropsrequirements.
foreach (AbilityComp comp in this.job.ability.comps)
{
if (comp.props is CompProperties_SexInteractionRequirements)
{
CompProperties_SexInteractionRequirements sexpropsreq = comp.props as CompProperties_SexInteractionRequirements;
this.Sexprops = CompAbility_SexInteractionRequirements.GenerateSexProps(this.pawn, this.Partner, sexpropsreq);
}
}
this.Start();
this.Sexprops.usedCondom = (CondomUtility.TryUseCondom(this.pawn) || CondomUtility.TryUseCondom(this.Partner));
};
toil.AddPreTickAction(delegate
{
if (this.pawn.IsHashIntervalTick(this.ticks_between_hearts))
{
this.ThrowMetaIconF(this.pawn.Position, this.pawn.Map, FleckDefOf.Heart);
}
this.SexTick(this.pawn, this.Partner, true, true);
SexUtility.reduce_rest(this.Partner, 1f);
SexUtility.reduce_rest(this.pawn, 1f);
if (this.ticks_left <= 0)
{
this.ReadyForNextToil();
}
});
toil.AddFinishAction(delegate
{
this.End();
});
yield return toil;
yield return new Toil
{
initAction = delegate ()
{
SexUtility.ProcessSex(this.Sexprops);
},
defaultCompleteMode = ToilCompleteMode.Instant
};
yield return Toils_Combat.CastVerb(TargetIndex.A, TargetIndex.B, false);
yield break;
}
}
}