diff --git a/About/Manifest.xml b/About/Manifest.xml index 443fcd9..485b02d 100644 --- a/About/Manifest.xml +++ b/About/Manifest.xml @@ -1,7 +1,7 @@ RJW Sexperience - 1.0.1.9 + 1.0.1.10 diff --git a/Assemblies/RJWSexperience.dll b/Assemblies/RJWSexperience.dll index b426f41..9a66324 100644 Binary files a/Assemblies/RJWSexperience.dll and b/Assemblies/RJWSexperience.dll differ diff --git a/Languages/ChineseSimplified/Keyed/RJW_Sexperience.xml b/Languages/ChineseSimplified/Keyed/RJW_Sexperience.xml index 889a626..6aff4bc 100644 --- a/Languages/ChineseSimplified/Keyed/RJW_Sexperience.xml +++ b/Languages/ChineseSimplified/Keyed/RJW_Sexperience.xml @@ -21,13 +21,5 @@ 设置平均每年的性交次数 允许奴隶被强奸获得性经验 奴隶被强奸获得性经验 - - - - - - - - \ No newline at end of file diff --git a/Languages/English/Keyed/RJW_Sexperience.xml b/Languages/English/Keyed/RJW_Sexperience.xml index 7b0339f..12cc018 100644 --- a/Languages/English/Keyed/RJW_Sexperience.xml +++ b/Languages/English/Keyed/RJW_Sexperience.xml @@ -12,6 +12,7 @@ not animal capable of sex is required Total gathered cum: + {1} took {0}'s virginity. Enable record randomizer Randomize pawn's sex records. @@ -29,10 +30,10 @@ Slaves will have experience of being raped Lust Limit Set limitation of lust. If absolute value of lust close to or larger than this value, lust will be less likely to change. - - - - + Minimum age can have sex + Set minimum sexable age. This value is not related to RJW's minimum sex age. Only used for generating records. + Virgin ratio + Set probability of virgin regardless of age. diff --git a/RJWSexperience/IdeologyAddon/Ideology/RJW_Patch_Ideo.cs b/RJWSexperience/IdeologyAddon/Ideology/RJW_Patch_Ideo.cs index 2d205c6..6194cdc 100644 --- a/RJWSexperience/IdeologyAddon/Ideology/RJW_Patch_Ideo.cs +++ b/RJWSexperience/IdeologyAddon/Ideology/RJW_Patch_Ideo.cs @@ -129,13 +129,20 @@ namespace RJWSexperience.Ideology } - [HarmonyPatch(typeof(SexUtility), "Aftersex", new Type[] { typeof(Pawn), typeof(Pawn), typeof(bool), typeof(bool), typeof(bool), typeof(xxx.rjwSextype) })] + [HarmonyPatch(typeof(SexUtility), "Aftersex", new Type[] { typeof(SexProps) })] public static class RJW_Patch_Aftersex { - public static void Postfix(Pawn pawn, Pawn partner, bool usedCondom, bool rape, bool isCoreLovin, xxx.rjwSextype sextype) + public static void Postfix(SexProps props) { + Pawn pawn = props.pawn; + Pawn partner = props.partner; + bool usedCondom = props.usedCondom; + bool rape = props.isRape; + bool isCoreLovin = props.isCoreLovin; + xxx.rjwSextype sextype = props.sexType; + //Log.Message("Aftersex " + pawn.Label + ": " + sextype); if (xxx.is_human(pawn)) AfterSexHuman(pawn, partner, usedCondom, rape, isCoreLovin, sextype); else if (xxx.is_human(partner)) AfterSexHuman(partner, pawn, usedCondom, false, isCoreLovin, sextype, true); diff --git a/RJWSexperience/IdeologyAddon/Ideology/Rituals/JobGiver_DrugOrgy.cs b/RJWSexperience/IdeologyAddon/Ideology/Rituals/JobGiver_DrugOrgy.cs index 94e4aff..80aa619 100644 --- a/RJWSexperience/IdeologyAddon/Ideology/Rituals/JobGiver_DrugOrgy.cs +++ b/RJWSexperience/IdeologyAddon/Ideology/Rituals/JobGiver_DrugOrgy.cs @@ -149,7 +149,7 @@ namespace RJWSexperience.Ideology initAction = delegate { //// Trying to add some interactions and social logs - SexUtility.ProcessSex(pawn, Partner, usedCondom: usedCondom, rape: isRape, sextype: sexType); + SexUtility.ProcessSex(Sexprops); }, defaultCompleteMode = ToilCompleteMode.Instant }; @@ -260,7 +260,7 @@ namespace RJWSexperience.Ideology { initAction = delegate { - SexUtility.Aftersex(pawn, xxx.rjwSextype.Masturbation); + SexUtility.Aftersex(Sexprops); if (!SexUtility.ConsiderCleaning(pawn)) return; LocalTargetInfo own_cum = pawn.PositionHeld.GetFirstThing(pawn.Map); diff --git a/RJWSexperience/IdeologyAddon/Ideology/Rituals/JobGiver_GangbangVictim.cs b/RJWSexperience/IdeologyAddon/Ideology/Rituals/JobGiver_GangbangVictim.cs index 3008dc6..03f1fd0 100644 --- a/RJWSexperience/IdeologyAddon/Ideology/Rituals/JobGiver_GangbangVictim.cs +++ b/RJWSexperience/IdeologyAddon/Ideology/Rituals/JobGiver_GangbangVictim.cs @@ -123,7 +123,7 @@ namespace RJWSexperience.Ideology initAction = delegate { // Trying to add some interactions and social logs - SexUtility.ProcessSex(pawn, Partner, usedCondom: usedCondom, rape: isRape, sextype: sexType); + SexUtility.ProcessSex(Sexprops); Partner.records.Increment(xxx.GetRapedAsComfortPawn); }, defaultCompleteMode = ToilCompleteMode.Instant diff --git a/RJWSexperience/RJWSexperience/Configurations.cs b/RJWSexperience/RJWSexperience/Configurations.cs index 1cf08bf..a10122d 100644 --- a/RJWSexperience/RJWSexperience/Configurations.cs +++ b/RJWSexperience/RJWSexperience/Configurations.cs @@ -22,6 +22,8 @@ namespace RJWSexperience public const bool SlavesBeenRapedExpDefault = true; public const bool EnableStatRandomizerDefault = true; public const float LustLimitDefault = 500f/3f; + public const float MinSexablePercentDefault = 0.2f; + public const float VirginRatioDefault = 0.01f; public static float MaxLustDeviation = MaxInitialLustDefault; public static float AvgLust = AvgLustDefault; @@ -31,6 +33,8 @@ namespace RJWSexperience public static bool SlavesBeenRapedExp = SlavesBeenRapedExpDefault; public static bool EnableRecordRandomizer = EnableStatRandomizerDefault; public static float LustLimit = LustLimitDefault; + public static float MinSexablePercent = MinSexablePercentDefault; + public static float VirginRatio = VirginRatioDefault; public static void ResettoDefault() { @@ -42,6 +46,8 @@ namespace RJWSexperience SlavesBeenRapedExp = SlavesBeenRapedExpDefault; EnableRecordRandomizer = EnableStatRandomizerDefault; LustLimit = LustLimitDefault; + MinSexablePercent = MinSexablePercentDefault; + VirginRatio = VirginRatioDefault; } public override void ExposeData() @@ -54,6 +60,8 @@ namespace RJWSexperience Scribe_Values.Look(ref SlavesBeenRapedExp, "SlavesBeenRapedExp", SlavesBeenRapedExp, true); Scribe_Values.Look(ref EnableRecordRandomizer, "EnableRecordRandomizer", EnableRecordRandomizer, true); Scribe_Values.Look(ref LustLimit, "LustLimit", LustLimit, true); + Scribe_Values.Look(ref MinSexablePercent, "MinSexablePercent", MinSexablePercent, true); + Scribe_Values.Look(ref VirginRatio, "VirginRatio", VirginRatio, true); base.ExposeData(); } } @@ -100,7 +108,7 @@ namespace RJWSexperience listmain.CheckboxLabeled(Keyed.Option_1_Label, ref Configurations.EnableRecordRandomizer, Keyed.Option_1_Desc); if (Configurations.EnableRecordRandomizer) { - Listing_Standard section = listmain.BeginSection(24f*9f); + Listing_Standard section = listmain.BeginSection(24f*13f); LabelwithTextfield(section.GetRect(24f), Keyed.Option_3_Label + " " + Configurations.MaxLustDeviation, Keyed.Option_3_Label, ref Configurations.MaxLustDeviation, 0f, 2000f); @@ -128,6 +136,9 @@ namespace RJWSexperience Adjuster = (int)section.Slider(Adjuster, 0, 2000); Configurations.SexPerYear = Adjuster; + SliderOption(section.GetRect(48f), Keyed.Option_9_Label + " " + Configurations.MinSexablePercent*100 + "% " + ThingDefOf.Human.race.lifeExpectancy * Configurations.MinSexablePercent + "years", Keyed.Option_9_Desc, ref Configurations.MinSexablePercent, 0, 1, 1000f); + SliderOption(section.GetRect(48f), Keyed.Option_10_Label + " " + Configurations.VirginRatio*100 + "%" , Keyed.Option_10_Desc, ref Configurations.VirginRatio, 0, 1, 1000f); + section.CheckboxLabeled(Keyed.Option_7_Label, ref Configurations.SlavesBeenRapedExp, Keyed.Option_7_Desc); @@ -143,7 +154,7 @@ namespace RJWSexperience Widgets.EndScrollView(); } - + public void LabelwithTextfield(Rect rect, string label, string tooltip, ref float value, float min, float max) { Rect textfieldRect = new Rect(rect.xMax - 100f, rect.y, 100f, rect.height); @@ -152,8 +163,17 @@ namespace RJWSexperience Widgets.TextFieldNumeric(textfieldRect,ref value, ref valuestr, min, max); Widgets.DrawHighlightIfMouseover(rect); TooltipHandler.TipRegion(rect, tooltip); + } + public void SliderOption(Rect doublerect, string label, string tooltip, ref float value, float min, float max, float division) + { + int Adjuster; + LabelwithTextfield(doublerect.TopHalf(), label, tooltip, ref value, min, max); + Adjuster = (int)(value.Normalization(min,max)*division); + Adjuster = (int)Widgets.HorizontalSlider(doublerect.BottomHalf(), Adjuster, 0, division); + value = (Adjuster / division).Denormalization(min,max); + } } diff --git a/RJWSexperience/RJWSexperience/Keyed.cs b/RJWSexperience/RJWSexperience/Keyed.cs index 943d3bc..530dfb7 100644 --- a/RJWSexperience/RJWSexperience/Keyed.cs +++ b/RJWSexperience/RJWSexperience/Keyed.cs @@ -14,6 +14,7 @@ namespace RJWSexperience public static string LustStatFactor(string value) => "LustStatFactor".Translate(value); public static string SlaveStatFactor(string value) => "SlaveStatFactor".Translate(value); public static string MemeStatFactor(string value) => "MemeStatFactor".Translate(value); + public static string RS_LostVirgin(string pawn, string partner) => "RS_LostVirgin".Translate(pawn,partner); public static readonly string Mod_Title = "RS_Mod_Title".Translate(); public static readonly string SlaveStatFactorDefault = "SlaveStatFactorDefault".Translate(); @@ -23,7 +24,7 @@ namespace RJWSexperience public static readonly string RSNotAnimal = "RSNotAnimal".Translate(); public static readonly string RSShouldCanFuck = "RSShouldCanFuck".Translate(); public static readonly string RSTotalGatheredCum = "RSTotalGatheredCum".Translate(); - + public static readonly string Option_1_Label = "RSOption_1_Label".Translate(); public static readonly string Option_1_Desc = "RSOption_1_Desc".Translate(); diff --git a/RJWSexperience/RJWSexperience/RJW_Patch.cs b/RJWSexperience/RJWSexperience/RJW_Patch.cs index 643fbf6..bd111b0 100644 --- a/RJWSexperience/RJWSexperience/RJW_Patch.cs +++ b/RJWSexperience/RJWSexperience/RJW_Patch.cs @@ -28,6 +28,36 @@ namespace RJWSexperience return Mathf.Exp(-Mathf.Pow(lust / Configurations.LustLimit, 2)); } + /// + /// If the pawn is virgin, return true. + /// + public static bool IsVirgin(this Pawn pawn) + { + if (pawn.records.GetValue(xxx.CountOfSex) == 0) return true; + return false; + } + + /// + /// If pawn is virgin, lose his/her virginity. + /// + //public static void PoptheCherry(this Pawn pawn, Pawn partner, bool violent) + //{ + // if (pawn.IsVirgin()) + // { + // Messages.Message(Keyed.RS_LostVirgin(pawn.LabelShort, partner.LabelShort), MessageTypeDefOf.NeutralEvent, true); + // RemoveVirginTrait(pawn); + // FilthMaker.TryMakeFilth(pawn.Position, pawn.Map, ThingDefOf.Filth_Blood, 1, FilthSourceFlags.Pawn); + // } + //} + // + //public static void RemoveVirginTrait(Pawn pawn) + //{ + // Trait virgin = pawn.story?.traits?.GetTrait(VariousDefOf.Virgin); + // if (virgin != null) + // { + // pawn.story.traits.RemoveTrait(virgin); + // } + //} } @@ -37,13 +67,12 @@ namespace RJWSexperience { public static void Postfix(JobDriver_Sex __instance) { - if (__instance.sexType != xxx.rjwSextype.Masturbation && !(__instance is JobDriver_Masturbate)) + if (__instance.Sexprops.sexType != xxx.rjwSextype.Masturbation && !(__instance is JobDriver_Masturbate)) { if (__instance.isRape) { __instance.pawn?.skills?.Learn(VariousDefOf.SexSkill, 0.05f, true); } - else { __instance.pawn?.skills?.Learn(VariousDefOf.SexSkill, 0.35f, true); } @@ -74,14 +103,15 @@ namespace RJWSexperience { private const float base_sat_per_fuck = 0.4f; - public static void Prefix(Pawn pawn, Pawn partner, xxx.rjwSextype sextype, bool violent, bool pawn_is_raping, ref float satisfaction) + public static void Prefix(Pawn pawn, Pawn partner, SexProps props, bool pawn_is_raping , ref float satisfaction) { - satisfaction *= Mathf.Max(base_sat_per_fuck, partner.GetSexStat()); + satisfaction = Mathf.Max(base_sat_per_fuck, satisfaction * partner.GetSexStat()); } - public static void Postfix(Pawn pawn, Pawn partner, xxx.rjwSextype sextype, bool violent, bool pawn_is_raping, float satisfaction) + public static void Postfix(Pawn pawn, Pawn partner, SexProps props, bool pawn_is_raping, float satisfaction) { float? lust = pawn.records?.GetValue(VariousDefOf.Lust); + xxx.rjwSextype sextype = props.sexType; if (lust != null) { if (sextype != xxx.rjwSextype.Masturbation || partner != null) pawn.records.AddTo(VariousDefOf.Lust, Mathf.Clamp((satisfaction - base_sat_per_fuck) * RJWUtility.LustIncrementFactor(lust ?? 0), -0.5f, 0.5f)); // If the sex is satisfactory, lust grows up. Declines at the opposite. @@ -103,12 +133,16 @@ namespace RJWSexperience } - [HarmonyPatch(typeof(xxx), "TransferNutrition")] + [HarmonyPatch(typeof(SexUtility), "TransferNutrition")] public static class RJW_Patch_TransferNutrition { - public static void Postfix(Pawn pawn, Pawn partner, xxx.rjwSextype sextype) + public static void Postfix(SexProps props) { + Pawn pawn = props.pawn; + Pawn partner = props.partner; + xxx.rjwSextype sextype = props.sexType; Pawn receiver = null; + if (Genital_Helper.has_penis_fertile(pawn)) receiver = partner; else if (Genital_Helper.has_penis_fertile(partner)) receiver = pawn; diff --git a/RJWSexperience/RJWSexperience/Rimworld_Patch.cs b/RJWSexperience/RJWSexperience/Rimworld_Patch.cs index e0b5813..f495a8c 100644 --- a/RJWSexperience/RJWSexperience/Rimworld_Patch.cs +++ b/RJWSexperience/RJWSexperience/Rimworld_Patch.cs @@ -21,7 +21,7 @@ namespace RJWSexperience if (__result != null && !request.Newborn && xxx.is_human(__result)) { float avgsex = -500; - + bool isvirgin = Rand.Chance(Configurations.VirginRatio); int totalsex = 0; float totalbirth = 0; if (__result.story != null) @@ -31,51 +31,55 @@ namespace RJWSexperience else lust = __result.RecordRandomizer(VariousDefOf.Lust, Configurations.AvgLust, Configurations.MaxLustDeviation, float.MinValue); float sexableage = 0; - if (__result.ageTracker.AgeBiologicalYears > RJWSettings.sex_minimum_age) + float minsexage = __result.RaceProps.lifeExpectancy * Configurations.MinSexablePercent; + if (__result.ageTracker.AgeBiologicalYears > minsexage) { - sexableage = __result.ageTracker.AgeBiologicalYearsFloat - RJWSettings.sex_minimum_age; + sexableage = __result.ageTracker.AgeBiologicalYearsFloat - minsexage; avgsex = sexableage * Configurations.SexPerYear * __result.LustFactor(); } - - if (xxx.is_rapist(__result)) - { - if (xxx.is_zoophile(__result)) - { - if (__result.Has(Quirk.ChitinLover)) totalsex += (int)__result.RecordRandomizer(xxx.CountOfRapedInsects, avgsex, Configurations.MaxSexCountDeviation); - else totalsex += (int)__result.RecordRandomizer(xxx.CountOfRapedAnimals, avgsex, Configurations.MaxSexCountDeviation); - } - else totalsex += (int)__result.RecordRandomizer(xxx.CountOfRapedHumanlikes, avgsex, Configurations.MaxSexCountDeviation); - avgsex /= 4; - } - - if (xxx.is_zoophile(__result)) - { - if (__result.Has(Quirk.ChitinLover)) totalsex += (int)__result.RecordRandomizer(xxx.CountOfRapedInsects, avgsex, Configurations.MaxSexCountDeviation); - else totalsex += (int)__result.RecordRandomizer(xxx.CountOfSexWithAnimals, avgsex, Configurations.MaxSexCountDeviation); - avgsex /= 2; - } - else if (xxx.is_necrophiliac(__result)) - { - totalsex += (int)__result.RecordRandomizer(xxx.CountOfSexWithCorpse, avgsex, Configurations.MaxSexCountDeviation); - avgsex /= 2; - } - - if (__result.IsSlave) - { - totalsex += (int)__result.RecordRandomizer(xxx.CountOfBeenRapedByAnimals, Rand.Range(-50,10), Rand.Range(0,10)*sexableage); - totalsex += (int)__result.RecordRandomizer(xxx.CountOfBeenRapedByHumanlikes, 0, Rand.Range(0,100)*sexableage); - } - - - totalsex += (int)__result.RecordRandomizer(xxx.CountOfSexWithHumanlikes, avgsex, Configurations.MaxSexCountDeviation); if (__result.relations != null && __result.gender == Gender.Female) { totalbirth += __result.relations.ChildrenCount; totalsex += (int)totalbirth; __result.records?.AddTo(xxx.CountOfSexWithHumanlikes, totalbirth); __result.records?.SetTo(xxx.CountOfBirthHuman, totalbirth); + if (totalbirth > 0) isvirgin = false; + } + if (!isvirgin) + { + if (xxx.is_rapist(__result)) + { + if (xxx.is_zoophile(__result)) + { + if (__result.Has(Quirk.ChitinLover)) totalsex += (int)__result.RecordRandomizer(xxx.CountOfRapedInsects, avgsex, Configurations.MaxSexCountDeviation); + else totalsex += (int)__result.RecordRandomizer(xxx.CountOfRapedAnimals, avgsex, Configurations.MaxSexCountDeviation); + } + else totalsex += (int)__result.RecordRandomizer(xxx.CountOfRapedHumanlikes, avgsex, Configurations.MaxSexCountDeviation); + avgsex /= 4; + } + + if (xxx.is_zoophile(__result)) + { + if (__result.Has(Quirk.ChitinLover)) totalsex += (int)__result.RecordRandomizer(xxx.CountOfRapedInsects, avgsex, Configurations.MaxSexCountDeviation); + else totalsex += (int)__result.RecordRandomizer(xxx.CountOfSexWithAnimals, avgsex, Configurations.MaxSexCountDeviation); + avgsex /= 2; + } + else if (xxx.is_necrophiliac(__result)) + { + totalsex += (int)__result.RecordRandomizer(xxx.CountOfSexWithCorpse, avgsex, Configurations.MaxSexCountDeviation); + avgsex /= 2; + } + + if (__result.IsSlave) + { + totalsex += (int)__result.RecordRandomizer(xxx.CountOfBeenRapedByAnimals, Rand.Range(-50, 10), Rand.Range(0, 10) * sexableage); + totalsex += (int)__result.RecordRandomizer(xxx.CountOfBeenRapedByHumanlikes, 0, Rand.Range(0, 100) * sexableage); + } + + + totalsex += (int)__result.RecordRandomizer(xxx.CountOfSexWithHumanlikes, avgsex, Configurations.MaxSexCountDeviation); } } __result.records?.SetTo(xxx.CountOfSex, totalsex); diff --git a/RJWSexperience/RJWSexperience/Utility.cs b/RJWSexperience/RJWSexperience/Utility.cs index 0ca6bd6..199e6f3 100644 --- a/RJWSexperience/RJWSexperience/Utility.cs +++ b/RJWSexperience/RJWSexperience/Utility.cs @@ -14,6 +14,23 @@ namespace RJWSexperience { public static System.Random random = new System.Random(Environment.TickCount); + //public static readonly Dictionary sextypeRecords = new Dictionary { + // { xxx.rjwSextype.Vaginal, xxx.CountOfSex }, + // { xxx.rjwSextype.Vaginal, xxx.CountOfSex }, + // { xxx.rjwSextype.Vaginal, xxx.CountOfSex }, + // { xxx.rjwSextype.Vaginal, xxx.CountOfSex }, + // { xxx.rjwSextype.Vaginal, xxx.CountOfSex }, + // { xxx.rjwSextype.Vaginal, xxx.CountOfSex }, + // { xxx.rjwSextype.Vaginal, xxx.CountOfSex }, + // { xxx.rjwSextype.Vaginal, xxx.CountOfSex }, + // { xxx.rjwSextype.Vaginal, xxx.CountOfSex }, + // { xxx.rjwSextype.Vaginal, xxx.CountOfSex }, + // { xxx.rjwSextype.Vaginal, xxx.CountOfSex }, + // { xxx.rjwSextype.Vaginal, xxx.CountOfSex } + // + // + //}; + public static float RandGaussianLike(float min, float max, int iterations = 3) { double res = 0; @@ -135,5 +152,16 @@ namespace RJWSexperience pawn.needs?.mood?.thoughts?.memories?.TryGainMemoryFast(VariousDefOf.AteCum); } + public static float Normalization(this float num, float min, float max) + { + + return (num - min)/(max - min); + } + + public static float Denormalization(this float num, float min, float max) + { + return num * (max - min) + min; + } + } } diff --git a/RJWSexperience/RJWSexperience/VariousDefOf.cs b/RJWSexperience/RJWSexperience/VariousDefOf.cs index 4c2307d..28283e8 100644 --- a/RJWSexperience/RJWSexperience/VariousDefOf.cs +++ b/RJWSexperience/RJWSexperience/VariousDefOf.cs @@ -20,7 +20,8 @@ namespace RJWSexperience public static readonly HediffDef CumTolerance = DefDatabase.GetNamed("CumTolerance"); public static readonly ChemicalDef Cum = DefDatabase.GetNamed("Cum"); public static readonly NeedDef Chemical_Cum = DefDatabase.GetNamed("Chemical_Cum"); - + public static readonly TraitDef Virgin = DefDatabase.GetNamed("Virgin"); + public static float CumneedLevelOffset { get diff --git a/RJWSexperience_Ideology/Assemblies/RJWSexperience.Ideology.dll b/RJWSexperience_Ideology/Assemblies/RJWSexperience.Ideology.dll index dcb9696..fe8bdde 100644 Binary files a/RJWSexperience_Ideology/Assemblies/RJWSexperience.Ideology.dll and b/RJWSexperience_Ideology/Assemblies/RJWSexperience.Ideology.dll differ diff --git a/changelogs.txt b/changelogs.txt index 0224d47..9b26258 100644 --- a/changelogs.txt +++ b/changelogs.txt @@ -1,4 +1,8 @@ +Version Beta 1.0.1.10 + - requires RJW 4.8.0 or later + Version Beta 1.0.1.9 + - not compatible with RJW 4.8.0 or later - removed consciousness and manipulation factors from sex ability stat - fixed rituals get canceled after the victim being incapacitated - does not apply on your save. (you should remove and add rituals again using debug mod)